github.com/zxy12/go_duplicate_1_12@v0.0.0-20200217043740-b1636fc0368b/src/cmd/internal/obj/arm64/asm7.go (about) 1 // cmd/7l/asm.c, cmd/7l/asmout.c, cmd/7l/optab.c, cmd/7l/span.c, cmd/ld/sub.c, cmd/ld/mod.c, from Vita Nuova. 2 // https://code.google.com/p/ken-cc/source/browse/ 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 package arm64 32 33 import ( 34 "cmd/internal/obj" 35 "cmd/internal/objabi" 36 "fmt" 37 "log" 38 "math" 39 "sort" 40 ) 41 42 // ctxt7 holds state while assembling a single function. 43 // Each function gets a fresh ctxt7. 44 // This allows for multiple functions to be safely concurrently assembled. 45 type ctxt7 struct { 46 ctxt *obj.Link 47 newprog obj.ProgAlloc 48 cursym *obj.LSym 49 blitrl *obj.Prog 50 elitrl *obj.Prog 51 autosize int32 52 extrasize int32 53 instoffset int64 54 pc int64 55 pool struct { 56 start uint32 57 size uint32 58 } 59 } 60 61 const ( 62 funcAlign = 16 63 ) 64 65 const ( 66 REGFROM = 1 67 ) 68 69 type Optab struct { 70 as obj.As 71 a1 uint8 72 a2 uint8 73 a3 uint8 74 a4 uint8 75 type_ int8 76 size int8 77 param int16 78 flag int8 79 scond uint16 80 } 81 82 var oprange [ALAST & obj.AMask][]Optab 83 84 var xcmp [C_NCLASS][C_NCLASS]bool 85 86 const ( 87 S32 = 0 << 31 88 S64 = 1 << 31 89 Sbit = 1 << 29 90 LSL0_32 = 2 << 13 91 LSL0_64 = 3 << 13 92 ) 93 94 func OPDP2(x uint32) uint32 { 95 return 0<<30 | 0<<29 | 0xd6<<21 | x<<10 96 } 97 98 func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 { 99 return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15 100 } 101 102 func OPBcc(x uint32) uint32 { 103 return 0x2A<<25 | 0<<24 | 0<<4 | x&15 104 } 105 106 func OPBLR(x uint32) uint32 { 107 /* x=0, JMP; 1, CALL; 2, RET */ 108 return 0x6B<<25 | 0<<23 | x<<21 | 0x1F<<16 | 0<<10 109 } 110 111 func SYSOP(l uint32, op0 uint32, op1 uint32, crn uint32, crm uint32, op2 uint32, rt uint32) uint32 { 112 return 0x354<<22 | l<<21 | op0<<19 | op1<<16 | crn&15<<12 | crm&15<<8 | op2<<5 | rt 113 } 114 115 func SYSHINT(x uint32) uint32 { 116 return SYSOP(0, 0, 3, 2, 0, x, 0x1F) 117 } 118 119 func LDSTR12U(sz uint32, v uint32, opc uint32) uint32 { 120 return sz<<30 | 7<<27 | v<<26 | 1<<24 | opc<<22 121 } 122 123 func LDSTR9S(sz uint32, v uint32, opc uint32) uint32 { 124 return sz<<30 | 7<<27 | v<<26 | 0<<24 | opc<<22 125 } 126 127 func LD2STR(o uint32) uint32 { 128 return o &^ (3 << 22) 129 } 130 131 func LDSTX(sz uint32, o2 uint32, l uint32, o1 uint32, o0 uint32) uint32 { 132 return sz<<30 | 0x8<<24 | o2<<23 | l<<22 | o1<<21 | o0<<15 133 } 134 135 func FPCMP(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 { 136 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<14 | 8<<10 | op2 137 } 138 139 func FPCCMP(m uint32, s uint32, type_ uint32, op uint32) uint32 { 140 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | 1<<10 | op<<4 141 } 142 143 func FPOP1S(m uint32, s uint32, type_ uint32, op uint32) uint32 { 144 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<15 | 0x10<<10 145 } 146 147 func FPOP2S(m uint32, s uint32, type_ uint32, op uint32) uint32 { 148 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<12 | 2<<10 149 } 150 151 func FPOP3S(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 { 152 return m<<31 | s<<29 | 0x1F<<24 | type_<<22 | op<<21 | op2<<15 153 } 154 155 func FPCVTI(sf uint32, s uint32, type_ uint32, rmode uint32, op uint32) uint32 { 156 return sf<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | rmode<<19 | op<<16 | 0<<10 157 } 158 159 func ADR(p uint32, o uint32, rt uint32) uint32 { 160 return p<<31 | (o&3)<<29 | 0x10<<24 | ((o>>2)&0x7FFFF)<<5 | rt&31 161 } 162 163 func OPBIT(x uint32) uint32 { 164 return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10 165 } 166 167 func MOVCONST(d int64, s int, rt int) uint32 { 168 return uint32(((d>>uint(s*16))&0xFFFF)<<5) | uint32(s)&3<<21 | uint32(rt&31) 169 } 170 171 const ( 172 LFROM = 1 << 0 173 LTO = 1 << 1 174 ) 175 176 var optab = []Optab{ 177 /* struct Optab: 178 OPCODE, from, prog->reg, from3, to, type,size,param,flag,scond */ 179 {obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0}, 180 181 /* arithmetic operations */ 182 {AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 183 {AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, 184 {AADC, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 185 {AADC, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, 186 {ANEG, C_REG, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0}, 187 {ANEG, C_NONE, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0}, 188 {ANGC, C_REG, C_NONE, C_NONE, C_REG, 17, 4, 0, 0, 0}, 189 {ACMP, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0}, 190 {AADD, C_ADDCON, C_RSP, C_NONE, C_RSP, 2, 4, 0, 0, 0}, 191 {AADD, C_ADDCON, C_NONE, C_NONE, C_RSP, 2, 4, 0, 0, 0}, 192 {ACMP, C_ADDCON, C_RSP, C_NONE, C_NONE, 2, 4, 0, 0, 0}, 193 {AADD, C_MOVCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0}, 194 {AADD, C_MOVCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0}, 195 {ACMP, C_MOVCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0}, 196 {AADD, C_BITCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0}, 197 {AADD, C_BITCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0}, 198 {ACMP, C_BITCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0}, 199 {AADD, C_ADDCON2, C_RSP, C_NONE, C_RSP, 48, 8, 0, 0, 0}, 200 {AADD, C_ADDCON2, C_NONE, C_NONE, C_RSP, 48, 8, 0, 0, 0}, 201 {AADD, C_MOVCON2, C_RSP, C_NONE, C_RSP, 13, 12, 0, 0, 0}, 202 {AADD, C_MOVCON2, C_NONE, C_NONE, C_RSP, 13, 12, 0, 0, 0}, 203 {AADD, C_MOVCON3, C_RSP, C_NONE, C_RSP, 13, 16, 0, 0, 0}, 204 {AADD, C_MOVCON3, C_NONE, C_NONE, C_RSP, 13, 16, 0, 0, 0}, 205 {AADD, C_VCON, C_RSP, C_NONE, C_RSP, 13, 20, 0, 0, 0}, 206 {AADD, C_VCON, C_NONE, C_NONE, C_RSP, 13, 20, 0, 0, 0}, 207 {ACMP, C_MOVCON2, C_REG, C_NONE, C_NONE, 13, 12, 0, 0, 0}, 208 {ACMP, C_MOVCON3, C_REG, C_NONE, C_NONE, 13, 16, 0, 0, 0}, 209 {ACMP, C_VCON, C_REG, C_NONE, C_NONE, 13, 20, 0, 0, 0}, 210 {AADD, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0}, 211 {AADD, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, 212 {AMVN, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, 213 {ACMP, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0}, 214 {ANEG, C_SHIFT, C_NONE, C_NONE, C_REG, 26, 4, 0, 0, 0}, 215 {AADD, C_REG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 216 {AADD, C_REG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 217 {ACMP, C_REG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0}, 218 {AADD, C_EXTREG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 219 {AADD, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 220 {AMVN, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 221 {ACMP, C_EXTREG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0}, 222 {AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 223 {AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, 224 {AMUL, C_REG, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0}, 225 {AMUL, C_REG, C_NONE, C_NONE, C_REG, 15, 4, 0, 0, 0}, 226 {AMADD, C_REG, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0}, 227 {AREM, C_REG, C_REG, C_NONE, C_REG, 16, 8, 0, 0, 0}, 228 {AREM, C_REG, C_NONE, C_NONE, C_REG, 16, 8, 0, 0, 0}, 229 {ASDIV, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, 230 {ASDIV, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 231 232 {AFADDS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 233 {AFADDS, C_FREG, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 234 {AFMSUBD, C_FREG, C_FREG, C_FREG, C_FREG, 15, 4, 0, 0, 0}, 235 {AFCMPS, C_FREG, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0}, 236 {AFCMPS, C_FCON, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0}, 237 {AVADDP, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0}, 238 {AVADD, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0}, 239 {AVADD, C_VREG, C_VREG, C_NONE, C_VREG, 89, 4, 0, 0, 0}, 240 {AVADD, C_VREG, C_NONE, C_NONE, C_VREG, 89, 4, 0, 0, 0}, 241 {AVADDV, C_ARNG, C_NONE, C_NONE, C_VREG, 85, 4, 0, 0, 0}, 242 243 /* logical operations */ 244 {AAND, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 245 {AAND, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, 246 {AANDS, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 247 {AANDS, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, 248 {ATST, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0}, 249 {AAND, C_MBCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0}, 250 {AAND, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, 251 {AANDS, C_MBCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0}, 252 {AANDS, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, 253 {ATST, C_MBCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0}, 254 {AAND, C_BITCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0}, 255 {AAND, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, 256 {AANDS, C_BITCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0}, 257 {AANDS, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, 258 {ATST, C_BITCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0}, 259 {AAND, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0}, 260 {AAND, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0}, 261 {AANDS, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0}, 262 {AANDS, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0}, 263 {ATST, C_MOVCON, C_REG, C_NONE, C_NONE, 62, 8, 0, 0, 0}, 264 {AAND, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0}, 265 {AAND, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0}, 266 {AAND, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0}, 267 {AAND, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0}, 268 {AAND, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0}, 269 {AAND, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0}, 270 {AANDS, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0}, 271 {AANDS, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0}, 272 {AANDS, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0}, 273 {AANDS, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0}, 274 {AANDS, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0}, 275 {AANDS, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0}, 276 {ATST, C_MOVCON2, C_REG, C_NONE, C_NONE, 28, 12, 0, 0, 0}, 277 {ATST, C_MOVCON3, C_REG, C_NONE, C_NONE, 28, 16, 0, 0, 0}, 278 {ATST, C_VCON, C_REG, C_NONE, C_NONE, 28, 20, 0, 0, 0}, 279 {AAND, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0}, 280 {AAND, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, 281 {AANDS, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0}, 282 {AANDS, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, 283 {ATST, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0}, 284 {AMOVD, C_RSP, C_NONE, C_NONE, C_RSP, 24, 4, 0, 0, 0}, 285 {AMVN, C_REG, C_NONE, C_NONE, C_REG, 24, 4, 0, 0, 0}, 286 {AMOVB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, 287 {AMOVBU, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, 288 {AMOVH, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVHU */ 289 {AMOVW, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVWU */ 290 /* TODO: MVN C_SHIFT */ 291 292 /* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */ 293 {AMOVW, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, 294 {AMOVD, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, 295 {AMOVW, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, 296 {AMOVD, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, 297 {AMOVW, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, 0, 0}, 298 {AMOVD, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, 0, 0}, 299 {AMOVD, C_MOVCON3, C_NONE, C_NONE, C_REG, 12, 12, 0, 0, 0}, 300 {AMOVD, C_VCON, C_NONE, C_NONE, C_REG, 12, 16, 0, 0, 0}, 301 302 {AMOVK, C_VCON, C_NONE, C_NONE, C_REG, 33, 4, 0, 0, 0}, 303 {AMOVD, C_AACON, C_NONE, C_NONE, C_REG, 4, 4, REGFROM, 0, 0}, 304 305 /* jump operations */ 306 {AB, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, 307 {ABL, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, 308 {AB, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, 309 {ABL, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0}, 310 {ABL, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0}, 311 {ABL, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, 312 {obj.ARET, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0}, 313 {obj.ARET, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, 314 {ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 7, 4, 0, 0, 0}, 315 {AADRP, C_SBRA, C_NONE, C_NONE, C_REG, 60, 4, 0, 0, 0}, 316 {AADR, C_SBRA, C_NONE, C_NONE, C_REG, 61, 4, 0, 0, 0}, 317 {ACBZ, C_REG, C_NONE, C_NONE, C_SBRA, 39, 4, 0, 0, 0}, 318 {ATBZ, C_VCON, C_REG, C_NONE, C_SBRA, 40, 4, 0, 0, 0}, 319 {AERET, C_NONE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0}, 320 321 {ACLREX, C_NONE, C_NONE, C_NONE, C_VCON, 38, 4, 0, 0, 0}, 322 {ACLREX, C_NONE, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0}, 323 {ABFM, C_VCON, C_REG, C_VCON, C_REG, 42, 4, 0, 0, 0}, 324 {ABFI, C_VCON, C_REG, C_VCON, C_REG, 43, 4, 0, 0, 0}, 325 {AEXTR, C_VCON, C_REG, C_REG, C_REG, 44, 4, 0, 0, 0}, 326 {ASXTB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, 327 {ACLS, C_REG, C_NONE, C_NONE, C_REG, 46, 4, 0, 0, 0}, 328 {ALSL, C_VCON, C_REG, C_NONE, C_REG, 8, 4, 0, 0, 0}, 329 {ALSL, C_VCON, C_NONE, C_NONE, C_REG, 8, 4, 0, 0, 0}, 330 {ALSL, C_REG, C_NONE, C_NONE, C_REG, 9, 4, 0, 0, 0}, 331 {ALSL, C_REG, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0}, 332 {ASVC, C_VCON, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0}, 333 {ASVC, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0}, 334 {ADWORD, C_NONE, C_NONE, C_NONE, C_VCON, 11, 8, 0, 0, 0}, 335 {ADWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 11, 8, 0, 0, 0}, 336 {ADWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 11, 8, 0, 0, 0}, 337 {ADWORD, C_NONE, C_NONE, C_NONE, C_LACON, 11, 8, 0, 0, 0}, 338 {AWORD, C_NONE, C_NONE, C_NONE, C_LCON, 14, 4, 0, 0, 0}, 339 {AWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0}, 340 {AWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0}, 341 {AMOVW, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, 0, 0}, 342 {AMOVD, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, 0, 0}, 343 {AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 344 {AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 345 {AMOVH, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 346 {AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 347 {AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 348 {AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, 349 {AMOVBU, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, 350 {AMOVH, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, 351 {AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, 352 {AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, 353 {AMOVD, C_GOTADDR, C_NONE, C_NONE, C_REG, 71, 8, 0, 0, 0}, 354 {AMOVD, C_TLS_LE, C_NONE, C_NONE, C_REG, 69, 4, 0, 0, 0}, 355 {AMOVD, C_TLS_IE, C_NONE, C_NONE, C_REG, 70, 8, 0, 0, 0}, 356 357 {AFMOVS, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 358 {AFMOVS, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0}, 359 {AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 360 {AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0}, 361 {AFMOVS, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0}, 362 {AFMOVS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 363 {AFMOVD, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0}, 364 {AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 365 {AFMOVS, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 366 {AFMOVS, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0}, 367 {AFMOVD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 368 {AFMOVD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0}, 369 {AFCVTZSD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0}, 370 {ASCVTFD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 371 {AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 372 {AVCNT, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, 373 {AVMOV, C_ELEM, C_NONE, C_NONE, C_REG, 73, 4, 0, 0, 0}, 374 {AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0}, 375 {AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0}, 376 {AVMOV, C_REG, C_NONE, C_NONE, C_ARNG, 82, 4, 0, 0, 0}, 377 {AVMOV, C_REG, C_NONE, C_NONE, C_ELEM, 78, 4, 0, 0, 0}, 378 {AVMOV, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0}, 379 {AVDUP, C_ELEM, C_NONE, C_NONE, C_ARNG, 79, 4, 0, 0, 0}, 380 {AVMOVI, C_ADDCON, C_NONE, C_NONE, C_ARNG, 86, 4, 0, 0, 0}, 381 {AVFMLA, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0}, 382 {AVEXT, C_VCON, C_ARNG, C_ARNG, C_ARNG, 94, 4, 0, 0, 0}, 383 {AVTBL, C_ARNG, C_NONE, C_LIST, C_ARNG, 100, 4, 0, 0, 0}, 384 {AVUSHR, C_VCON, C_ARNG, C_NONE, C_ARNG, 95, 4, 0, 0, 0}, 385 {AVZIP1, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0}, 386 387 /* conditional operations */ 388 {ACSEL, C_COND, C_REG, C_REG, C_REG, 18, 4, 0, 0, 0}, 389 {ACINC, C_COND, C_REG, C_NONE, C_REG, 18, 4, 0, 0, 0}, 390 {ACSET, C_COND, C_NONE, C_NONE, C_REG, 18, 4, 0, 0, 0}, 391 {AFCSELD, C_COND, C_FREG, C_FREG, C_FREG, 18, 4, 0, 0, 0}, 392 {ACCMN, C_COND, C_REG, C_REG, C_VCON, 19, 4, 0, 0, 0}, 393 {ACCMN, C_COND, C_REG, C_VCON, C_VCON, 19, 4, 0, 0, 0}, 394 {AFCCMPS, C_COND, C_FREG, C_FREG, C_VCON, 57, 4, 0, 0, 0}, 395 396 /* scaled 12-bit unsigned displacement store */ 397 {AMOVB, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0}, 398 {AMOVB, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0}, 399 {AMOVBU, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0}, 400 {AMOVBU, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0}, 401 {AMOVH, C_REG, C_NONE, C_NONE, C_UAUTO8K, 20, 4, REGSP, 0, 0}, 402 {AMOVH, C_REG, C_NONE, C_NONE, C_UOREG8K, 20, 4, 0, 0, 0}, 403 {AMOVW, C_REG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0}, 404 {AMOVW, C_REG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0}, 405 {AMOVD, C_REG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0}, 406 {AMOVD, C_REG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0}, 407 408 {AFMOVS, C_FREG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0}, 409 {AFMOVS, C_FREG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0}, 410 {AFMOVD, C_FREG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0}, 411 {AFMOVD, C_FREG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0}, 412 413 /* unscaled 9-bit signed displacement store */ 414 {AMOVB, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 415 {AMOVB, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 416 {AMOVBU, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 417 {AMOVBU, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 418 {AMOVH, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 419 {AMOVH, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 420 {AMOVW, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 421 {AMOVW, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 422 {AMOVD, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 423 {AMOVD, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 424 425 {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 426 {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 427 {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 428 {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 429 430 /* scaled 12-bit unsigned displacement load */ 431 {AMOVB, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 432 {AMOVB, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, 433 {AMOVBU, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 434 {AMOVBU, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, 435 {AMOVH, C_UAUTO8K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 436 {AMOVH, C_UOREG8K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, 437 {AMOVW, C_UAUTO16K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 438 {AMOVW, C_UOREG16K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, 439 {AMOVD, C_UAUTO32K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 440 {AMOVD, C_UOREG32K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, 441 442 {AFMOVS, C_UAUTO16K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 443 {AFMOVS, C_UOREG16K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 444 {AFMOVD, C_UAUTO32K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 445 {AFMOVD, C_UOREG32K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 446 447 /* unscaled 9-bit signed displacement load */ 448 {AMOVB, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 449 {AMOVB, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, 450 {AMOVBU, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 451 {AMOVBU, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, 452 {AMOVH, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 453 {AMOVH, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, 454 {AMOVW, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 455 {AMOVW, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, 456 {AMOVD, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 457 {AMOVD, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0}, 458 459 {AFMOVS, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 460 {AFMOVS, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 461 {AFMOVD, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 462 {AFMOVD, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 463 464 /* long displacement store */ 465 {AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 466 {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 467 {AMOVBU, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 468 {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 469 {AMOVH, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 470 {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 471 {AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 472 {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 473 {AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 474 {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 475 476 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 477 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 478 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 479 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 480 481 /* long displacement load */ 482 {AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 483 {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 484 {AMOVBU, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 485 {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 486 {AMOVH, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 487 {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 488 {AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 489 {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 490 {AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 491 {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 492 493 {AFMOVS, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0}, 494 {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0}, 495 {AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0}, 496 {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0}, 497 498 /* load long effective stack address (load int32 offset and add) */ 499 {AMOVD, C_LACON, C_NONE, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0}, 500 501 /* pre/post-indexed load (unscaled, signed 9-bit offset) */ 502 {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 503 {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 504 {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 505 {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 506 {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 507 {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST}, 508 {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST}, 509 510 {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 511 {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 512 {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 513 {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 514 {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 515 {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE}, 516 {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE}, 517 518 /* pre/post-indexed store (unscaled, signed 9-bit offset) */ 519 {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 520 {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 521 {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 522 {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 523 {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 524 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 525 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 526 527 {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 528 {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 529 {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 530 {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 531 {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 532 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 533 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 534 535 /* load with shifted or extended register offset */ 536 {AMOVD, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, 537 {AMOVW, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, 538 {AMOVH, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, 539 {AMOVB, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, 540 {AMOVBU, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, 541 {AFMOVS, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0}, 542 {AFMOVD, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0}, 543 544 /* store with extended register offset */ 545 {AMOVD, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, 546 {AMOVW, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, 547 {AMOVH, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, 548 {AMOVB, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, 549 {AFMOVS, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, 550 {AFMOVD, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, 551 552 /* pre/post-indexed/signed-offset load/store register pair 553 (unscaled, signed 10-bit quad-aligned and long offset) */ 554 {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, 555 {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, 556 {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, 557 {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, 558 {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, 559 {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, 560 {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, 561 {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE}, 562 {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST}, 563 {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, 564 {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE}, 565 {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST}, 566 {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0}, 567 {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE}, 568 {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST}, 569 {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, 570 {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, 571 {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, 572 {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, 573 {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, 574 {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, 575 {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0}, 576 {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE}, 577 {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST}, 578 {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0}, 579 {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE}, 580 {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST}, 581 {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0}, 582 {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE}, 583 {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST}, 584 {ALDP, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0}, 585 586 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, 0}, 587 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPRE}, 588 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPOST}, 589 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, 0}, 590 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPRE}, 591 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPOST}, 592 {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0}, 593 {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE}, 594 {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST}, 595 {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0}, 596 {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE}, 597 {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST}, 598 {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0}, 599 {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE}, 600 {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST}, 601 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, 0}, 602 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPRE}, 603 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPOST}, 604 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, 0}, 605 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPRE}, 606 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPOST}, 607 {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0}, 608 {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE}, 609 {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST}, 610 {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0}, 611 {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE}, 612 {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST}, 613 {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0}, 614 {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE}, 615 {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST}, 616 {ASTP, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0}, 617 618 // differ from LDP/STP for C_NSAUTO_4/C_PSAUTO_4/C_NSOREG_4/C_PSOREG_4 619 {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, 620 {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, 621 {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, 622 {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, 623 {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, 624 {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, 625 {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, 626 {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE}, 627 {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST}, 628 {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, 629 {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE}, 630 {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST}, 631 {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0}, 632 {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE}, 633 {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST}, 634 {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, 635 {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, 636 {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, 637 {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, 638 {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, 639 {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, 640 {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0}, 641 {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE}, 642 {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST}, 643 {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0}, 644 {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE}, 645 {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST}, 646 {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0}, 647 {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE}, 648 {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST}, 649 {ALDPW, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0}, 650 651 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, 0}, 652 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPRE}, 653 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPOST}, 654 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, 0}, 655 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPRE}, 656 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPOST}, 657 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0}, 658 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE}, 659 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST}, 660 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0}, 661 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE}, 662 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST}, 663 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0}, 664 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE}, 665 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST}, 666 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, 0}, 667 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPRE}, 668 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPOST}, 669 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, 0}, 670 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPRE}, 671 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPOST}, 672 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0}, 673 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE}, 674 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST}, 675 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0}, 676 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE}, 677 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST}, 678 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0}, 679 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE}, 680 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST}, 681 {ASTPW, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0}, 682 683 {ASWPD, C_REG, C_NONE, C_NONE, C_ZOREG, 47, 4, 0, 0, 0}, // RegTo2=C_REG 684 {ASWPD, C_REG, C_NONE, C_NONE, C_ZAUTO, 47, 4, REGSP, 0, 0}, // RegTo2=C_REG 685 {ALDAR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0}, 686 {ALDXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0}, 687 {ALDAXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0}, 688 {ALDXP, C_ZOREG, C_NONE, C_NONE, C_PAIR, 58, 4, 0, 0, 0}, 689 {ASTLR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_NONE 690 {ASTXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG 691 {ASTLXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG 692 {ASTXP, C_PAIR, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, 693 694 /* VLD1/VST1 */ 695 {AVLD1, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0}, 696 {AVLD1, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST}, 697 {AVLD1, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST}, 698 {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST}, 699 {AVLD1, C_ROFF, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST}, 700 {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, 0}, 701 {AVST1, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0}, 702 {AVST1, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST}, 703 {AVST1, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST}, 704 {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, C_XPOST}, 705 {AVST1, C_ELEM, C_NONE, C_NONE, C_ROFF, 96, 4, 0, 0, C_XPOST}, 706 {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, 0}, 707 708 /* special */ 709 {AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0}, 710 {AMRS, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0}, 711 {AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0}, 712 {AMSR, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0}, 713 {AMOVD, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0}, 714 {AMSR, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0}, 715 {APRFM, C_UOREG32K, C_NONE, C_NONE, C_SPR, 91, 4, 0, 0, 0}, 716 {APRFM, C_UOREG32K, C_NONE, C_NONE, C_LCON, 91, 4, 0, 0, 0}, 717 {ADMB, C_VCON, C_NONE, C_NONE, C_NONE, 51, 4, 0, 0, 0}, 718 {AHINT, C_VCON, C_NONE, C_NONE, C_NONE, 52, 4, 0, 0, 0}, 719 {ASYS, C_VCON, C_NONE, C_NONE, C_NONE, 50, 4, 0, 0, 0}, 720 {ASYS, C_VCON, C_REG, C_NONE, C_NONE, 50, 4, 0, 0, 0}, 721 {ASYSL, C_VCON, C_NONE, C_NONE, C_REG, 50, 4, 0, 0, 0}, 722 723 /* encryption instructions */ 724 {AAESD, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0}, // for compatibility with old code 725 {AAESD, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, // recommend using the new one for better readability 726 {ASHA1C, C_VREG, C_REG, C_NONE, C_VREG, 1, 4, 0, 0, 0}, 727 {ASHA1C, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0}, 728 {ASHA1H, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0}, 729 {ASHA1SU0, C_ARNG, C_ARNG, C_NONE, C_ARNG, 1, 4, 0, 0, 0}, 730 {ASHA256H, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0}, 731 {AVREV32, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0}, 732 {AVPMULL, C_ARNG, C_ARNG, C_NONE, C_ARNG, 93, 4, 0, 0, 0}, 733 734 {obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}, 735 {obj.APCDATA, C_VCON, C_NONE, C_NONE, C_VCON, 0, 0, 0, 0, 0}, 736 {obj.AFUNCDATA, C_VCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0, 0, 0}, 737 {obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, 738 {obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL 739 {obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL 740 741 {obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0}, 742 } 743 744 /* 745 * valid pstate field values, and value to use in instruction 746 */ 747 var pstatefield = []struct { 748 reg int16 749 enc uint32 750 }{ 751 {REG_SPSel, 0<<16 | 4<<12 | 5<<5}, 752 {REG_DAIFSet, 3<<16 | 4<<12 | 6<<5}, 753 {REG_DAIFClr, 3<<16 | 4<<12 | 7<<5}, 754 } 755 756 // the System register values, and value to use in instruction 757 var systemreg = []struct { 758 reg int16 759 enc uint32 760 }{ 761 {REG_ELR_EL1, 8<<16 | 4<<12 | 1<<5}, 762 {REG_DCZID_EL0, 3<<19 | 3<<16 | 7<<5}, 763 } 764 765 var prfopfield = []struct { 766 reg int16 767 enc uint32 768 }{ 769 {REG_PLDL1KEEP, 0}, 770 {REG_PLDL1STRM, 1}, 771 {REG_PLDL2KEEP, 2}, 772 {REG_PLDL2STRM, 3}, 773 {REG_PLDL3KEEP, 4}, 774 {REG_PLDL3STRM, 5}, 775 {REG_PLIL1KEEP, 8}, 776 {REG_PLIL1STRM, 9}, 777 {REG_PLIL2KEEP, 10}, 778 {REG_PLIL2STRM, 11}, 779 {REG_PLIL3KEEP, 12}, 780 {REG_PLIL3STRM, 13}, 781 {REG_PSTL1KEEP, 16}, 782 {REG_PSTL1STRM, 17}, 783 {REG_PSTL2KEEP, 18}, 784 {REG_PSTL2STRM, 19}, 785 {REG_PSTL3KEEP, 20}, 786 {REG_PSTL3STRM, 21}, 787 } 788 789 func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { 790 p := cursym.Func.Text 791 if p == nil || p.Link == nil { // handle external functions and ELF section symbols 792 return 793 } 794 795 if oprange[AAND&obj.AMask] == nil { 796 ctxt.Diag("arm64 ops not initialized, call arm64.buildop first") 797 } 798 799 c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset & 0xffffffff), extrasize: int32(p.To.Offset >> 32)} 800 p.To.Offset &= 0xffffffff // extrasize is no longer needed 801 802 bflag := 1 803 pc := int64(0) 804 p.Pc = pc 805 var m int 806 var o *Optab 807 for p = p.Link; p != nil; p = p.Link { 808 if p.As == ADWORD && (pc&7) != 0 { 809 pc += 4 810 } 811 p.Pc = pc 812 o = c.oplook(p) 813 m = int(o.size) 814 if m == 0 { 815 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA { 816 c.ctxt.Diag("zero-width instruction\n%v", p) 817 } 818 continue 819 } 820 821 switch o.flag & (LFROM | LTO) { 822 case LFROM: 823 c.addpool(p, &p.From) 824 825 case LTO: 826 c.addpool(p, &p.To) 827 break 828 } 829 830 if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */ 831 c.checkpool(p, 0) 832 } 833 pc += int64(m) 834 if c.blitrl != nil { 835 c.checkpool(p, 1) 836 } 837 } 838 839 c.cursym.Size = pc 840 841 /* 842 * if any procedure is large enough to 843 * generate a large SBRA branch, then 844 * generate extra passes putting branches 845 * around jmps to fix. this is rare. 846 */ 847 for bflag != 0 { 848 bflag = 0 849 pc = 0 850 for p = c.cursym.Func.Text.Link; p != nil; p = p.Link { 851 if p.As == ADWORD && (pc&7) != 0 { 852 pc += 4 853 } 854 p.Pc = pc 855 o = c.oplook(p) 856 857 /* very large branches */ 858 if (o.type_ == 7 || o.type_ == 39 || o.type_ == 40) && p.Pcond != nil { // 7: BEQ and like, 39: CBZ and like, 40: TBZ and like 859 otxt := p.Pcond.Pc - pc 860 var toofar bool 861 switch o.type_ { 862 case 7, 39: // branch instruction encodes 19 bits 863 toofar = otxt <= -(1<<20)+10 || otxt >= (1<<20)-10 864 case 40: // branch instruction encodes 14 bits 865 toofar = otxt <= -(1<<15)+10 || otxt >= (1<<15)-10 866 } 867 if toofar { 868 q := c.newprog() 869 q.Link = p.Link 870 p.Link = q 871 q.As = AB 872 q.To.Type = obj.TYPE_BRANCH 873 q.Pcond = p.Pcond 874 p.Pcond = q 875 q = c.newprog() 876 q.Link = p.Link 877 p.Link = q 878 q.As = AB 879 q.To.Type = obj.TYPE_BRANCH 880 q.Pcond = q.Link.Link 881 bflag = 1 882 } 883 } 884 m = int(o.size) 885 886 if m == 0 { 887 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA { 888 c.ctxt.Diag("zero-width instruction\n%v", p) 889 } 890 continue 891 } 892 893 pc += int64(m) 894 } 895 } 896 897 pc += -pc & (funcAlign - 1) 898 c.cursym.Size = pc 899 900 /* 901 * lay out the code, emitting code and data relocations. 902 */ 903 c.cursym.Grow(c.cursym.Size) 904 bp := c.cursym.P 905 psz := int32(0) 906 var i int 907 var out [6]uint32 908 for p := c.cursym.Func.Text.Link; p != nil; p = p.Link { 909 c.pc = p.Pc 910 o = c.oplook(p) 911 912 // need to align DWORDs on 8-byte boundary. The ISA doesn't 913 // require it, but the various 64-bit loads we generate assume it. 914 if o.as == ADWORD && psz%8 != 0 { 915 bp[3] = 0 916 bp[2] = bp[3] 917 bp[1] = bp[2] 918 bp[0] = bp[1] 919 bp = bp[4:] 920 psz += 4 921 } 922 923 if int(o.size) > 4*len(out) { 924 log.Fatalf("out array in span7 is too small, need at least %d for %v", o.size/4, p) 925 } 926 c.asmout(p, o, out[:]) 927 for i = 0; i < int(o.size/4); i++ { 928 c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i]) 929 bp = bp[4:] 930 psz += 4 931 } 932 } 933 } 934 935 /* 936 * when the first reference to the literal pool threatens 937 * to go out of range of a 1Mb PC-relative offset 938 * drop the pool now, and branch round it. 939 */ 940 func (c *ctxt7) checkpool(p *obj.Prog, skip int) { 941 if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) { 942 c.flushpool(p, skip) 943 } else if p.Link == nil { 944 c.flushpool(p, 2) 945 } 946 } 947 948 func (c *ctxt7) flushpool(p *obj.Prog, skip int) { 949 if c.blitrl != nil { 950 if skip != 0 { 951 if c.ctxt.Debugvlog && skip == 1 { 952 fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start) 953 } 954 q := c.newprog() 955 q.As = AB 956 q.To.Type = obj.TYPE_BRANCH 957 q.Pcond = p.Link 958 q.Link = c.blitrl 959 q.Pos = p.Pos 960 c.blitrl = q 961 } else if p.Pc+int64(c.pool.size)-int64(c.pool.start) < maxPCDisp { 962 return 963 } 964 965 // The line number for constant pool entries doesn't really matter. 966 // We set it to the line number of the preceding instruction so that 967 // there are no deltas to encode in the pc-line tables. 968 for q := c.blitrl; q != nil; q = q.Link { 969 q.Pos = p.Pos 970 } 971 972 c.elitrl.Link = p.Link 973 p.Link = c.blitrl 974 975 c.blitrl = nil /* BUG: should refer back to values until out-of-range */ 976 c.elitrl = nil 977 c.pool.size = 0 978 c.pool.start = 0 979 } 980 } 981 982 /* 983 * MOVD foo(SB), R is actually 984 * MOVD addr, REGTMP 985 * MOVD REGTMP, R 986 * where addr is the address of the DWORD containing the address of foo. 987 * 988 * TODO: hash 989 */ 990 func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) { 991 cls := c.aclass(a) 992 lit := c.instoffset 993 t := c.newprog() 994 t.As = AWORD 995 sz := 4 996 997 if a.Type == obj.TYPE_CONST { 998 if lit != int64(int32(lit)) && uint64(lit) != uint64(uint32(lit)) { 999 // out of range -0x80000000 ~ 0xffffffff, must store 64-bit 1000 t.As = ADWORD 1001 sz = 8 1002 } // else store 32-bit 1003 } else if p.As == AMOVD && a.Type != obj.TYPE_MEM || cls == C_ADDR || cls == C_VCON || lit != int64(int32(lit)) || uint64(lit) != uint64(uint32(lit)) { 1004 // conservative: don't know if we want signed or unsigned extension. 1005 // in case of ambiguity, store 64-bit 1006 t.As = ADWORD 1007 sz = 8 1008 } 1009 1010 switch cls { 1011 // TODO(aram): remove. 1012 default: 1013 if a.Name != obj.NAME_EXTERN { 1014 fmt.Printf("addpool: %v in %v shouldn't go to default case\n", DRconv(cls), p) 1015 } 1016 1017 t.To.Offset = a.Offset 1018 t.To.Sym = a.Sym 1019 t.To.Type = a.Type 1020 t.To.Name = a.Name 1021 1022 /* This is here because MOV uint12<<12, R is disabled in optab. 1023 Because of this, we need to load the constant from memory. */ 1024 case C_ADDCON: 1025 fallthrough 1026 1027 case C_ZAUTO, 1028 C_PSAUTO, 1029 C_PSAUTO_8, 1030 C_PSAUTO_4, 1031 C_PPAUTO, 1032 C_UAUTO4K_8, 1033 C_UAUTO4K_4, 1034 C_UAUTO4K_2, 1035 C_UAUTO4K, 1036 C_UAUTO8K_8, 1037 C_UAUTO8K_4, 1038 C_UAUTO8K, 1039 C_UAUTO16K_8, 1040 C_UAUTO16K, 1041 C_UAUTO32K, 1042 C_NSAUTO_8, 1043 C_NSAUTO_4, 1044 C_NSAUTO, 1045 C_NPAUTO, 1046 C_NAUTO4K, 1047 C_LAUTO, 1048 C_PPOREG, 1049 C_PSOREG, 1050 C_PSOREG_4, 1051 C_PSOREG_8, 1052 C_UOREG4K_8, 1053 C_UOREG4K_4, 1054 C_UOREG4K_2, 1055 C_UOREG4K, 1056 C_UOREG8K_8, 1057 C_UOREG8K_4, 1058 C_UOREG8K, 1059 C_UOREG16K_8, 1060 C_UOREG16K, 1061 C_UOREG32K, 1062 C_NSOREG_8, 1063 C_NSOREG_4, 1064 C_NSOREG, 1065 C_NPOREG, 1066 C_NOREG4K, 1067 C_LOREG, 1068 C_LACON, 1069 C_ADDCON2, 1070 C_LCON, 1071 C_VCON: 1072 if a.Name == obj.NAME_EXTERN { 1073 fmt.Printf("addpool: %v in %v needs reloc\n", DRconv(cls), p) 1074 } 1075 1076 t.To.Type = obj.TYPE_CONST 1077 t.To.Offset = lit 1078 break 1079 } 1080 1081 for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */ 1082 if q.To == t.To { 1083 p.Pcond = q 1084 return 1085 } 1086 } 1087 1088 q := c.newprog() 1089 *q = *t 1090 q.Pc = int64(c.pool.size) 1091 if c.blitrl == nil { 1092 c.blitrl = q 1093 c.pool.start = uint32(p.Pc) 1094 } else { 1095 c.elitrl.Link = q 1096 } 1097 c.elitrl = q 1098 c.pool.size = -c.pool.size & (funcAlign - 1) 1099 c.pool.size += uint32(sz) 1100 p.Pcond = q 1101 } 1102 1103 func (c *ctxt7) regoff(a *obj.Addr) uint32 { 1104 c.instoffset = 0 1105 c.aclass(a) 1106 return uint32(c.instoffset) 1107 } 1108 1109 func isSTLXRop(op obj.As) bool { 1110 switch op { 1111 case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH, 1112 ASTXR, ASTXRW, ASTXRB, ASTXRH: 1113 return true 1114 } 1115 return false 1116 } 1117 1118 func isSTXPop(op obj.As) bool { 1119 switch op { 1120 case ASTXP, ASTLXP, ASTXPW, ASTLXPW: 1121 return true 1122 } 1123 return false 1124 } 1125 1126 func isANDop(op obj.As) bool { 1127 switch op { 1128 case AAND, AORR, AEOR, AANDS, ATST, 1129 ABIC, AEON, AORN, ABICS: 1130 return true 1131 } 1132 return false 1133 } 1134 1135 func isANDWop(op obj.As) bool { 1136 switch op { 1137 case AANDW, AORRW, AEORW, AANDSW, ATSTW, 1138 ABICW, AEONW, AORNW, ABICSW: 1139 return true 1140 } 1141 return false 1142 } 1143 1144 func isADDop(op obj.As) bool { 1145 switch op { 1146 case AADD, AADDS, ASUB, ASUBS, ACMN, ACMP: 1147 return true 1148 } 1149 return false 1150 } 1151 1152 func isADDWop(op obj.As) bool { 1153 switch op { 1154 case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW: 1155 return true 1156 } 1157 return false 1158 } 1159 1160 func isRegShiftOrExt(a *obj.Addr) bool { 1161 return (a.Index-obj.RBaseARM64)®_EXT != 0 || (a.Index-obj.RBaseARM64)®_LSL != 0 1162 } 1163 1164 // Maximum PC-relative displacement. 1165 // The actual limit is ±2²⁰, but we are conservative 1166 // to avoid needing to recompute the literal pool flush points 1167 // as span-dependent jumps are enlarged. 1168 const maxPCDisp = 512 * 1024 1169 1170 // ispcdisp reports whether v is a valid PC-relative displacement. 1171 func ispcdisp(v int32) bool { 1172 return -maxPCDisp < v && v < maxPCDisp && v&3 == 0 1173 } 1174 1175 func isaddcon(v int64) bool { 1176 /* uimm12 or uimm24? */ 1177 if v < 0 { 1178 return false 1179 } 1180 if (v & 0xFFF) == 0 { 1181 v >>= 12 1182 } 1183 return v <= 0xFFF 1184 } 1185 1186 // isbitcon reports whether a constant can be encoded into a logical instruction. 1187 // bitcon has a binary form of repetition of a bit sequence of length 2, 4, 8, 16, 32, or 64, 1188 // which itself is a rotate (w.r.t. the length of the unit) of a sequence of ones. 1189 // special cases: 0 and -1 are not bitcon. 1190 // this function needs to run against virtually all the constants, so it needs to be fast. 1191 // for this reason, bitcon testing and bitcon encoding are separate functions. 1192 func isbitcon(x uint64) bool { 1193 if x == 1<<64-1 || x == 0 { 1194 return false 1195 } 1196 // determine the period and sign-extend a unit to 64 bits 1197 switch { 1198 case x != x>>32|x<<32: 1199 // period is 64 1200 // nothing to do 1201 case x != x>>16|x<<48: 1202 // period is 32 1203 x = uint64(int64(int32(x))) 1204 case x != x>>8|x<<56: 1205 // period is 16 1206 x = uint64(int64(int16(x))) 1207 case x != x>>4|x<<60: 1208 // period is 8 1209 x = uint64(int64(int8(x))) 1210 default: 1211 // period is 4 or 2, always true 1212 // 0001, 0010, 0100, 1000 -- 0001 rotate 1213 // 0011, 0110, 1100, 1001 -- 0011 rotate 1214 // 0111, 1011, 1101, 1110 -- 0111 rotate 1215 // 0101, 1010 -- 01 rotate, repeat 1216 return true 1217 } 1218 return sequenceOfOnes(x) || sequenceOfOnes(^x) 1219 } 1220 1221 // sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros 1222 func sequenceOfOnes(x uint64) bool { 1223 y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2 1224 y += x 1225 return (y-1)&y == 0 1226 } 1227 1228 // bitconEncode returns the encoding of a bitcon used in logical instructions 1229 // x is known to be a bitcon 1230 // a bitcon is a sequence of n ones at low bits (i.e. 1<<n-1), right rotated 1231 // by R bits, and repeated with period of 64, 32, 16, 8, 4, or 2. 1232 // it is encoded in logical instructions with 3 bitfields 1233 // N (1 bit) : R (6 bits) : S (6 bits), where 1234 // N=1 -- period=64 1235 // N=0, S=0xxxxx -- period=32 1236 // N=0, S=10xxxx -- period=16 1237 // N=0, S=110xxx -- period=8 1238 // N=0, S=1110xx -- period=4 1239 // N=0, S=11110x -- period=2 1240 // R is the shift amount, low bits of S = n-1 1241 func bitconEncode(x uint64, mode int) uint32 { 1242 var period uint32 1243 // determine the period and sign-extend a unit to 64 bits 1244 switch { 1245 case x != x>>32|x<<32: 1246 period = 64 1247 case x != x>>16|x<<48: 1248 period = 32 1249 x = uint64(int64(int32(x))) 1250 case x != x>>8|x<<56: 1251 period = 16 1252 x = uint64(int64(int16(x))) 1253 case x != x>>4|x<<60: 1254 period = 8 1255 x = uint64(int64(int8(x))) 1256 case x != x>>2|x<<62: 1257 period = 4 1258 x = uint64(int64(x<<60) >> 60) 1259 default: 1260 period = 2 1261 x = uint64(int64(x<<62) >> 62) 1262 } 1263 neg := false 1264 if int64(x) < 0 { 1265 x = ^x 1266 neg = true 1267 } 1268 y := x & -x // lowest set bit of x. 1269 s := log2(y) 1270 n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits 1271 if neg { 1272 // ^x is a sequence of n ones left shifted by s bits 1273 // adjust n, s for x 1274 s = n + s 1275 n = period - n 1276 } 1277 1278 N := uint32(0) 1279 if mode == 64 && period == 64 { 1280 N = 1 1281 } 1282 R := (period - s) & (period - 1) & uint32(mode-1) // shift amount of right rotate 1283 S := (n - 1) | 63&^(period<<1-1) // low bits = #ones - 1, high bits encodes period 1284 return N<<22 | R<<16 | S<<10 1285 } 1286 1287 func log2(x uint64) uint32 { 1288 if x == 0 { 1289 panic("log2 of 0") 1290 } 1291 n := uint32(0) 1292 if x >= 1<<32 { 1293 x >>= 32 1294 n += 32 1295 } 1296 if x >= 1<<16 { 1297 x >>= 16 1298 n += 16 1299 } 1300 if x >= 1<<8 { 1301 x >>= 8 1302 n += 8 1303 } 1304 if x >= 1<<4 { 1305 x >>= 4 1306 n += 4 1307 } 1308 if x >= 1<<2 { 1309 x >>= 2 1310 n += 2 1311 } 1312 if x >= 1<<1 { 1313 x >>= 1 1314 n += 1 1315 } 1316 return n 1317 } 1318 1319 func autoclass(l int64) int { 1320 if l == 0 { 1321 return C_ZAUTO 1322 } 1323 1324 if l < 0 { 1325 if l >= -256 && (l&7) == 0 { 1326 return C_NSAUTO_8 1327 } 1328 if l >= -256 && (l&3) == 0 { 1329 return C_NSAUTO_4 1330 } 1331 if l >= -256 { 1332 return C_NSAUTO 1333 } 1334 if l >= -512 && (l&7) == 0 { 1335 return C_NPAUTO 1336 } 1337 if l >= -4095 { 1338 return C_NAUTO4K 1339 } 1340 return C_LAUTO 1341 } 1342 1343 if l <= 255 { 1344 if (l & 7) == 0 { 1345 return C_PSAUTO_8 1346 } 1347 if (l & 3) == 0 { 1348 return C_PSAUTO_4 1349 } 1350 return C_PSAUTO 1351 } 1352 if l <= 504 && l&7 == 0 { 1353 return C_PPAUTO 1354 } 1355 if l <= 4095 { 1356 if l&7 == 0 { 1357 return C_UAUTO4K_8 1358 } 1359 if l&3 == 0 { 1360 return C_UAUTO4K_4 1361 } 1362 if l&1 == 0 { 1363 return C_UAUTO4K_2 1364 } 1365 return C_UAUTO4K 1366 } 1367 if l <= 8190 { 1368 if l&7 == 0 { 1369 return C_UAUTO8K_8 1370 } 1371 if l&3 == 0 { 1372 return C_UAUTO8K_4 1373 } 1374 if l&1 == 0 { 1375 return C_UAUTO8K 1376 } 1377 } 1378 if l <= 16380 { 1379 if l&7 == 0 { 1380 return C_UAUTO16K_8 1381 } 1382 if l&3 == 0 { 1383 return C_UAUTO16K 1384 } 1385 } 1386 if l <= 32760 && (l&7) == 0 { 1387 return C_UAUTO32K 1388 } 1389 return C_LAUTO 1390 } 1391 1392 func oregclass(l int64) int { 1393 return autoclass(l) - C_ZAUTO + C_ZOREG 1394 } 1395 1396 /* 1397 * given an offset v and a class c (see above) 1398 * return the offset value to use in the instruction, 1399 * scaled if necessary 1400 */ 1401 func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 { 1402 s := 0 1403 if cls >= C_SEXT1 && cls <= C_SEXT16 { 1404 s = cls - C_SEXT1 1405 } else { 1406 switch cls { 1407 case C_UAUTO4K, C_UOREG4K, C_ZOREG: 1408 s = 0 1409 case C_UAUTO8K, C_UOREG8K: 1410 s = 1 1411 case C_UAUTO16K, C_UOREG16K: 1412 s = 2 1413 case C_UAUTO32K, C_UOREG32K: 1414 s = 3 1415 default: 1416 c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p) 1417 } 1418 } 1419 vs := v >> uint(s) 1420 if vs<<uint(s) != v { 1421 c.ctxt.Diag("odd offset: %d\n%v", v, p) 1422 } 1423 return vs 1424 } 1425 1426 /* 1427 * if v contains a single 16-bit value aligned 1428 * on a 16-bit field, and thus suitable for movk/movn, 1429 * return the field index 0 to 3; otherwise return -1 1430 */ 1431 func movcon(v int64) int { 1432 for s := 0; s < 64; s += 16 { 1433 if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 { 1434 return s / 16 1435 } 1436 } 1437 return -1 1438 } 1439 1440 func rclass(r int16) int { 1441 switch { 1442 case REG_R0 <= r && r <= REG_R30: // not 31 1443 return C_REG 1444 case r == REGZERO: 1445 return C_ZCON 1446 case REG_F0 <= r && r <= REG_F31: 1447 return C_FREG 1448 case REG_V0 <= r && r <= REG_V31: 1449 return C_VREG 1450 case COND_EQ <= r && r <= COND_NV: 1451 return C_COND 1452 case r == REGSP: 1453 return C_RSP 1454 case r >= REG_ARNG && r < REG_ELEM: 1455 return C_ARNG 1456 case r >= REG_ELEM && r < REG_ELEM_END: 1457 return C_ELEM 1458 case r >= REG_UXTB && r < REG_SPECIAL: 1459 return C_EXTREG 1460 case r >= REG_SPECIAL: 1461 return C_SPR 1462 } 1463 return C_GOK 1464 } 1465 1466 // con32class reclassifies the constant of 32-bit instruction. Becuase the constant type is 32-bit, 1467 // but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it. 1468 func (c *ctxt7) con32class(a *obj.Addr) int { 1469 v := uint32(a.Offset) 1470 if v == 0 { 1471 return C_ZCON 1472 } 1473 if isaddcon(int64(v)) { 1474 if v <= 0xFFF { 1475 if isbitcon(uint64(v)) { 1476 return C_ABCON0 1477 } 1478 return C_ADDCON0 1479 } 1480 if isbitcon(uint64(v)) { 1481 return C_ABCON 1482 } 1483 if movcon(int64(v)) >= 0 { 1484 return C_AMCON 1485 } 1486 if movcon(int64(^v)) >= 0 { 1487 return C_AMCON 1488 } 1489 return C_ADDCON 1490 } 1491 1492 t := movcon(int64(v)) 1493 if t >= 0 { 1494 if isbitcon(uint64(v)) { 1495 return C_MBCON 1496 } 1497 return C_MOVCON 1498 } 1499 1500 t = movcon(int64(^v)) 1501 if t >= 0 { 1502 if isbitcon(uint64(v)) { 1503 return C_MBCON 1504 } 1505 return C_MOVCON 1506 } 1507 1508 if isbitcon(uint64(v)) { 1509 return C_BITCON 1510 } 1511 1512 if 0 <= v && v <= 0xffffff { 1513 return C_ADDCON2 1514 } 1515 return C_LCON 1516 } 1517 1518 // con64class reclassifies the constant of C_VCON and C_LCON class. 1519 func (c *ctxt7) con64class(a *obj.Addr) int { 1520 zeroCount := 0 1521 negCount := 0 1522 for i := uint(0); i < 4; i++ { 1523 immh := uint32(a.Offset >> (i * 16) & 0xffff) 1524 if immh == 0 { 1525 zeroCount++ 1526 } else if immh == 0xffff { 1527 negCount++ 1528 } 1529 } 1530 if zeroCount >= 3 || negCount >= 3 { 1531 return C_MOVCON 1532 } else if zeroCount == 2 || negCount == 2 { 1533 return C_MOVCON2 1534 } else if zeroCount == 1 || negCount == 1 { 1535 return C_MOVCON3 1536 } else { 1537 return C_VCON 1538 } 1539 } 1540 1541 func (c *ctxt7) aclass(a *obj.Addr) int { 1542 switch a.Type { 1543 case obj.TYPE_NONE: 1544 return C_NONE 1545 1546 case obj.TYPE_REG: 1547 return rclass(a.Reg) 1548 1549 case obj.TYPE_REGREG: 1550 return C_PAIR 1551 1552 case obj.TYPE_SHIFT: 1553 return C_SHIFT 1554 1555 case obj.TYPE_REGLIST: 1556 return C_LIST 1557 1558 case obj.TYPE_MEM: 1559 // The base register should be an integer register. 1560 if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) { 1561 break 1562 } 1563 switch a.Name { 1564 case obj.NAME_EXTERN, obj.NAME_STATIC: 1565 if a.Sym == nil { 1566 break 1567 } 1568 c.instoffset = a.Offset 1569 if a.Sym != nil { // use relocation 1570 if a.Sym.Type == objabi.STLSBSS { 1571 if c.ctxt.Flag_shared { 1572 return C_TLS_IE 1573 } else { 1574 return C_TLS_LE 1575 } 1576 } 1577 return C_ADDR 1578 } 1579 return C_LEXT 1580 1581 case obj.NAME_GOTREF: 1582 return C_GOTADDR 1583 1584 case obj.NAME_AUTO: 1585 if a.Reg == REGSP { 1586 // unset base register for better printing, since 1587 // a.Offset is still relative to pseudo-SP. 1588 a.Reg = obj.REG_NONE 1589 } 1590 // The frame top 8 or 16 bytes are for FP 1591 c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize) 1592 return autoclass(c.instoffset) 1593 1594 case obj.NAME_PARAM: 1595 if a.Reg == REGSP { 1596 // unset base register for better printing, since 1597 // a.Offset is still relative to pseudo-FP. 1598 a.Reg = obj.REG_NONE 1599 } 1600 c.instoffset = int64(c.autosize) + a.Offset + 8 1601 return autoclass(c.instoffset) 1602 1603 case obj.NAME_NONE: 1604 if a.Index != 0 { 1605 if a.Offset != 0 { 1606 if isRegShiftOrExt(a) { 1607 // extended or shifted register offset, (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2). 1608 return C_ROFF 1609 } 1610 return C_GOK 1611 } 1612 // register offset, (Rn)(Rm) 1613 return C_ROFF 1614 } 1615 c.instoffset = a.Offset 1616 return oregclass(c.instoffset) 1617 } 1618 return C_GOK 1619 1620 case obj.TYPE_FCONST: 1621 return C_FCON 1622 1623 case obj.TYPE_TEXTSIZE: 1624 return C_TEXTSIZE 1625 1626 case obj.TYPE_CONST, obj.TYPE_ADDR: 1627 switch a.Name { 1628 case obj.NAME_NONE: 1629 c.instoffset = a.Offset 1630 if a.Reg != 0 && a.Reg != REGZERO { 1631 break 1632 } 1633 v := c.instoffset 1634 if v == 0 { 1635 return C_ZCON 1636 } 1637 if isaddcon(v) { 1638 if v <= 0xFFF { 1639 if isbitcon(uint64(v)) { 1640 return C_ABCON0 1641 } 1642 return C_ADDCON0 1643 } 1644 if isbitcon(uint64(v)) { 1645 return C_ABCON 1646 } 1647 if movcon(v) >= 0 { 1648 return C_AMCON 1649 } 1650 if movcon(^v) >= 0 { 1651 return C_AMCON 1652 } 1653 return C_ADDCON 1654 } 1655 1656 t := movcon(v) 1657 if t >= 0 { 1658 if isbitcon(uint64(v)) { 1659 return C_MBCON 1660 } 1661 return C_MOVCON 1662 } 1663 1664 t = movcon(^v) 1665 if t >= 0 { 1666 if isbitcon(uint64(v)) { 1667 return C_MBCON 1668 } 1669 return C_MOVCON 1670 } 1671 1672 if isbitcon(uint64(v)) { 1673 return C_BITCON 1674 } 1675 1676 if 0 <= v && v <= 0xffffff { 1677 return C_ADDCON2 1678 } 1679 1680 if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) { 1681 return C_LCON 1682 } 1683 return C_VCON 1684 1685 case obj.NAME_EXTERN, obj.NAME_STATIC: 1686 if a.Sym == nil { 1687 return C_GOK 1688 } 1689 if a.Sym.Type == objabi.STLSBSS { 1690 c.ctxt.Diag("taking address of TLS variable is not supported") 1691 } 1692 c.instoffset = a.Offset 1693 return C_VCONADDR 1694 1695 case obj.NAME_AUTO: 1696 if a.Reg == REGSP { 1697 // unset base register for better printing, since 1698 // a.Offset is still relative to pseudo-SP. 1699 a.Reg = obj.REG_NONE 1700 } 1701 // The frame top 8 or 16 bytes are for FP 1702 c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize) 1703 1704 case obj.NAME_PARAM: 1705 if a.Reg == REGSP { 1706 // unset base register for better printing, since 1707 // a.Offset is still relative to pseudo-FP. 1708 a.Reg = obj.REG_NONE 1709 } 1710 c.instoffset = int64(c.autosize) + a.Offset + 8 1711 default: 1712 return C_GOK 1713 } 1714 1715 if isaddcon(c.instoffset) { 1716 return C_AACON 1717 } 1718 return C_LACON 1719 1720 case obj.TYPE_BRANCH: 1721 return C_SBRA 1722 } 1723 1724 return C_GOK 1725 } 1726 1727 func oclass(a *obj.Addr) int { 1728 return int(a.Class) - 1 1729 } 1730 1731 func (c *ctxt7) oplook(p *obj.Prog) *Optab { 1732 a1 := int(p.Optab) 1733 if a1 != 0 { 1734 return &optab[a1-1] 1735 } 1736 a1 = int(p.From.Class) 1737 if a1 == 0 { 1738 a0 := c.aclass(&p.From) 1739 // do not break C_ADDCON2 when S bit is set 1740 if (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) && a0 == C_ADDCON2 { 1741 a0 = C_LCON 1742 } 1743 a1 = a0 + 1 1744 p.From.Class = int8(a1) 1745 // more specific classification of 32-bit integers 1746 if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE { 1747 if p.As == AMOVW || isADDWop(p.As) { 1748 ra0 := c.con32class(&p.From) 1749 // do not break C_ADDCON2 when S bit is set 1750 if (p.As == AADDSW || p.As == ASUBSW) && ra0 == C_ADDCON2 { 1751 ra0 = C_LCON 1752 } 1753 a1 = ra0 + 1 1754 p.From.Class = int8(a1) 1755 } 1756 if isANDWop(p.As) && a0 != C_BITCON { 1757 // For 32-bit logical instruction with constant, 1758 // the BITCON test is special in that it looks at 1759 // the 64-bit which has the high 32-bit as a copy 1760 // of the low 32-bit. We have handled that and 1761 // don't pass it to con32class. 1762 a1 = c.con32class(&p.From) + 1 1763 p.From.Class = int8(a1) 1764 } 1765 if ((p.As == AMOVD) || isANDop(p.As) || isADDop(p.As)) && (a0 == C_LCON || a0 == C_VCON) { 1766 a1 = c.con64class(&p.From) + 1 1767 p.From.Class = int8(a1) 1768 } 1769 } 1770 } 1771 1772 a1-- 1773 a3 := C_NONE + 1 1774 if p.GetFrom3() != nil { 1775 a3 = int(p.GetFrom3().Class) 1776 if a3 == 0 { 1777 a3 = c.aclass(p.GetFrom3()) + 1 1778 p.GetFrom3().Class = int8(a3) 1779 } 1780 } 1781 1782 a3-- 1783 a4 := int(p.To.Class) 1784 if a4 == 0 { 1785 a4 = c.aclass(&p.To) + 1 1786 p.To.Class = int8(a4) 1787 } 1788 1789 a4-- 1790 a2 := C_NONE 1791 if p.Reg != 0 { 1792 a2 = rclass(p.Reg) 1793 } 1794 1795 if false { 1796 fmt.Printf("oplook %v %d %d %d %d\n", p.As, a1, a2, a3, a4) 1797 fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type) 1798 } 1799 1800 ops := oprange[p.As&obj.AMask] 1801 c1 := &xcmp[a1] 1802 c2 := &xcmp[a2] 1803 c3 := &xcmp[a3] 1804 c4 := &xcmp[a4] 1805 c5 := &xcmp[p.Scond>>5] 1806 for i := range ops { 1807 op := &ops[i] 1808 if (int(op.a2) == a2 || c2[op.a2]) && c5[op.scond>>5] && c1[op.a1] && c3[op.a3] && c4[op.a4] { 1809 p.Optab = uint16(cap(optab) - cap(ops) + i + 1) 1810 return op 1811 } 1812 } 1813 1814 c.ctxt.Diag("illegal combination: %v %v %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4), p.From.Type, p.To.Type) 1815 // Turn illegal instruction into an UNDEF, avoid crashing in asmout 1816 return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0} 1817 } 1818 1819 func cmp(a int, b int) bool { 1820 if a == b { 1821 return true 1822 } 1823 switch a { 1824 case C_RSP: 1825 if b == C_REG { 1826 return true 1827 } 1828 1829 case C_REG: 1830 if b == C_ZCON { 1831 return true 1832 } 1833 1834 case C_ADDCON0: 1835 if b == C_ZCON || b == C_ABCON0 { 1836 return true 1837 } 1838 1839 case C_ADDCON: 1840 if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON { 1841 return true 1842 } 1843 1844 case C_BITCON: 1845 if b == C_ABCON0 || b == C_ABCON || b == C_MBCON { 1846 return true 1847 } 1848 1849 case C_MOVCON: 1850 if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_AMCON { 1851 return true 1852 } 1853 1854 case C_ADDCON2: 1855 if b == C_ZCON || b == C_ADDCON || b == C_ADDCON0 { 1856 return true 1857 } 1858 1859 case C_LCON: 1860 if b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_ABCON0 || b == C_MBCON || b == C_MOVCON || b == C_ADDCON2 || b == C_AMCON { 1861 return true 1862 } 1863 1864 case C_MOVCON2: 1865 return cmp(C_LCON, b) 1866 1867 case C_VCON: 1868 return cmp(C_LCON, b) 1869 1870 case C_LACON: 1871 if b == C_AACON { 1872 return true 1873 } 1874 1875 case C_SEXT2: 1876 if b == C_SEXT1 { 1877 return true 1878 } 1879 1880 case C_SEXT4: 1881 if b == C_SEXT1 || b == C_SEXT2 { 1882 return true 1883 } 1884 1885 case C_SEXT8: 1886 if b >= C_SEXT1 && b <= C_SEXT4 { 1887 return true 1888 } 1889 1890 case C_SEXT16: 1891 if b >= C_SEXT1 && b <= C_SEXT8 { 1892 return true 1893 } 1894 1895 case C_LEXT: 1896 if b >= C_SEXT1 && b <= C_SEXT16 { 1897 return true 1898 } 1899 1900 case C_NSAUTO_4: 1901 if b == C_NSAUTO_8 { 1902 return true 1903 } 1904 1905 case C_NSAUTO: 1906 switch b { 1907 case C_NSAUTO_4, C_NSAUTO_8: 1908 return true 1909 } 1910 1911 case C_NPAUTO: 1912 switch b { 1913 case C_NSAUTO_8: 1914 return true 1915 } 1916 1917 case C_NAUTO4K: 1918 switch b { 1919 case C_NSAUTO_8, C_NSAUTO_4, C_NSAUTO, C_NPAUTO: 1920 return true 1921 } 1922 1923 case C_PSAUTO_8: 1924 if b == C_ZAUTO { 1925 return true 1926 } 1927 1928 case C_PSAUTO_4: 1929 switch b { 1930 case C_ZAUTO, C_PSAUTO_8: 1931 return true 1932 } 1933 1934 case C_PSAUTO: 1935 switch b { 1936 case C_ZAUTO, C_PSAUTO_8, C_PSAUTO_4: 1937 return true 1938 } 1939 1940 case C_PPAUTO: 1941 switch b { 1942 case C_ZAUTO, C_PSAUTO_8: 1943 return true 1944 } 1945 1946 case C_UAUTO4K: 1947 switch b { 1948 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, 1949 C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8: 1950 return true 1951 } 1952 1953 case C_UAUTO8K: 1954 switch b { 1955 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, 1956 C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8: 1957 return true 1958 } 1959 1960 case C_UAUTO16K: 1961 switch b { 1962 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, 1963 C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO16K_8: 1964 return true 1965 } 1966 1967 case C_UAUTO32K: 1968 switch b { 1969 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, 1970 C_PPAUTO, C_UAUTO4K_8, C_UAUTO8K_8, C_UAUTO16K_8: 1971 return true 1972 } 1973 1974 case C_LAUTO: 1975 switch b { 1976 case C_ZAUTO, C_NSAUTO, C_NSAUTO_4, C_NSAUTO_8, C_NPAUTO, 1977 C_NAUTO4K, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, 1978 C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, 1979 C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8, 1980 C_UAUTO16K, C_UAUTO16K_8, 1981 C_UAUTO32K: 1982 return true 1983 } 1984 1985 case C_NSOREG_4: 1986 if b == C_NSOREG_8 { 1987 return true 1988 } 1989 1990 case C_NSOREG: 1991 switch b { 1992 case C_NSOREG_4, C_NSOREG_8: 1993 return true 1994 } 1995 1996 case C_NPOREG: 1997 switch b { 1998 case C_NSOREG_8: 1999 return true 2000 } 2001 2002 case C_NOREG4K: 2003 switch b { 2004 case C_NSOREG_8, C_NSOREG_4, C_NSOREG, C_NPOREG: 2005 return true 2006 } 2007 2008 case C_PSOREG_4: 2009 switch b { 2010 case C_ZOREG, C_PSOREG_8: 2011 return true 2012 } 2013 2014 case C_PSOREG: 2015 switch b { 2016 case C_ZOREG, C_PSOREG_8, C_PSOREG_4: 2017 return true 2018 } 2019 2020 case C_PPOREG: 2021 switch b { 2022 case C_ZOREG, C_PSOREG_8: 2023 return true 2024 } 2025 2026 case C_UOREG4K: 2027 switch b { 2028 case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG, 2029 C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8: 2030 return true 2031 } 2032 2033 case C_UOREG8K: 2034 switch b { 2035 case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG, 2036 C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, 2037 C_UOREG8K_4, C_UOREG8K_8: 2038 return true 2039 } 2040 2041 case C_UOREG16K: 2042 switch b { 2043 case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG, 2044 C_PPOREG, C_UOREG4K_4, C_UOREG4K_8, C_UOREG8K_4, 2045 C_UOREG8K_8, C_UOREG16K_8: 2046 return true 2047 } 2048 2049 case C_UOREG32K: 2050 switch b { 2051 case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG, 2052 C_PPOREG, C_UOREG4K_8, C_UOREG8K_8, C_UOREG16K_8: 2053 return true 2054 } 2055 2056 case C_LOREG: 2057 switch b { 2058 case C_ZOREG, C_NSOREG, C_NSOREG_4, C_NSOREG_8, C_NPOREG, 2059 C_NOREG4K, C_PSOREG_4, C_PSOREG_8, C_PSOREG, C_PPOREG, 2060 C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, 2061 C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8, 2062 C_UOREG16K, C_UOREG16K_8, 2063 C_UOREG32K: 2064 return true 2065 } 2066 2067 case C_LBRA: 2068 if b == C_SBRA { 2069 return true 2070 } 2071 } 2072 2073 return false 2074 } 2075 2076 type ocmp []Optab 2077 2078 func (x ocmp) Len() int { 2079 return len(x) 2080 } 2081 2082 func (x ocmp) Swap(i, j int) { 2083 x[i], x[j] = x[j], x[i] 2084 } 2085 2086 func (x ocmp) Less(i, j int) bool { 2087 p1 := &x[i] 2088 p2 := &x[j] 2089 if p1.as != p2.as { 2090 return p1.as < p2.as 2091 } 2092 if p1.a1 != p2.a1 { 2093 return p1.a1 < p2.a1 2094 } 2095 if p1.a2 != p2.a2 { 2096 return p1.a2 < p2.a2 2097 } 2098 if p1.a3 != p2.a3 { 2099 return p1.a3 < p2.a3 2100 } 2101 if p1.a4 != p2.a4 { 2102 return p1.a4 < p2.a4 2103 } 2104 if p1.scond != p2.scond { 2105 return p1.scond < p2.scond 2106 } 2107 return false 2108 } 2109 2110 func oprangeset(a obj.As, t []Optab) { 2111 oprange[a&obj.AMask] = t 2112 } 2113 2114 func buildop(ctxt *obj.Link) { 2115 if oprange[AAND&obj.AMask] != nil { 2116 // Already initialized; stop now. 2117 // This happens in the cmd/asm tests, 2118 // each of which re-initializes the arch. 2119 return 2120 } 2121 2122 var n int 2123 for i := 0; i < C_GOK; i++ { 2124 for n = 0; n < C_GOK; n++ { 2125 if cmp(n, i) { 2126 xcmp[i][n] = true 2127 } 2128 } 2129 } 2130 for n = 0; optab[n].as != obj.AXXX; n++ { 2131 } 2132 sort.Sort(ocmp(optab[:n])) 2133 for i := 0; i < n; i++ { 2134 r := optab[i].as 2135 start := i 2136 for optab[i].as == r { 2137 i++ 2138 } 2139 t := optab[start:i] 2140 i-- 2141 oprangeset(r, t) 2142 switch r { 2143 default: 2144 ctxt.Diag("unknown op in build: %v", r) 2145 ctxt.DiagFlush() 2146 log.Fatalf("bad code") 2147 2148 case AADD: 2149 oprangeset(AADDS, t) 2150 oprangeset(ASUB, t) 2151 oprangeset(ASUBS, t) 2152 oprangeset(AADDW, t) 2153 oprangeset(AADDSW, t) 2154 oprangeset(ASUBW, t) 2155 oprangeset(ASUBSW, t) 2156 2157 case AAND: /* logical immediate, logical shifted register */ 2158 oprangeset(AANDW, t) 2159 oprangeset(AEOR, t) 2160 oprangeset(AEORW, t) 2161 oprangeset(AORR, t) 2162 oprangeset(AORRW, t) 2163 oprangeset(ABIC, t) 2164 oprangeset(ABICW, t) 2165 oprangeset(AEON, t) 2166 oprangeset(AEONW, t) 2167 oprangeset(AORN, t) 2168 oprangeset(AORNW, t) 2169 2170 case AANDS: /* logical immediate, logical shifted register, set flags, cannot target RSP */ 2171 oprangeset(AANDSW, t) 2172 oprangeset(ABICS, t) 2173 oprangeset(ABICSW, t) 2174 2175 case ANEG: 2176 oprangeset(ANEGS, t) 2177 oprangeset(ANEGSW, t) 2178 oprangeset(ANEGW, t) 2179 2180 case AADC: /* rn=Rd */ 2181 oprangeset(AADCW, t) 2182 2183 oprangeset(AADCS, t) 2184 oprangeset(AADCSW, t) 2185 oprangeset(ASBC, t) 2186 oprangeset(ASBCW, t) 2187 oprangeset(ASBCS, t) 2188 oprangeset(ASBCSW, t) 2189 2190 case ANGC: /* rn=REGZERO */ 2191 oprangeset(ANGCW, t) 2192 2193 oprangeset(ANGCS, t) 2194 oprangeset(ANGCSW, t) 2195 2196 case ACMP: 2197 oprangeset(ACMPW, t) 2198 oprangeset(ACMN, t) 2199 oprangeset(ACMNW, t) 2200 2201 case ATST: 2202 oprangeset(ATSTW, t) 2203 2204 /* register/register, and shifted */ 2205 case AMVN: 2206 oprangeset(AMVNW, t) 2207 2208 case AMOVK: 2209 oprangeset(AMOVKW, t) 2210 oprangeset(AMOVN, t) 2211 oprangeset(AMOVNW, t) 2212 oprangeset(AMOVZ, t) 2213 oprangeset(AMOVZW, t) 2214 2215 case ASWPD: 2216 oprangeset(ASWPALD, t) 2217 oprangeset(ASWPB, t) 2218 oprangeset(ASWPH, t) 2219 oprangeset(ASWPW, t) 2220 oprangeset(ASWPALB, t) 2221 oprangeset(ASWPALH, t) 2222 oprangeset(ASWPALW, t) 2223 oprangeset(ALDADDALB, t) 2224 oprangeset(ALDADDALH, t) 2225 oprangeset(ALDADDALW, t) 2226 oprangeset(ALDADDALD, t) 2227 oprangeset(ALDADDB, t) 2228 oprangeset(ALDADDH, t) 2229 oprangeset(ALDADDW, t) 2230 oprangeset(ALDADDD, t) 2231 oprangeset(ALDANDB, t) 2232 oprangeset(ALDANDH, t) 2233 oprangeset(ALDANDW, t) 2234 oprangeset(ALDANDD, t) 2235 oprangeset(ALDEORB, t) 2236 oprangeset(ALDEORH, t) 2237 oprangeset(ALDEORW, t) 2238 oprangeset(ALDEORD, t) 2239 oprangeset(ALDORB, t) 2240 oprangeset(ALDORH, t) 2241 oprangeset(ALDORW, t) 2242 oprangeset(ALDORD, t) 2243 2244 case ABEQ: 2245 oprangeset(ABNE, t) 2246 oprangeset(ABCS, t) 2247 oprangeset(ABHS, t) 2248 oprangeset(ABCC, t) 2249 oprangeset(ABLO, t) 2250 oprangeset(ABMI, t) 2251 oprangeset(ABPL, t) 2252 oprangeset(ABVS, t) 2253 oprangeset(ABVC, t) 2254 oprangeset(ABHI, t) 2255 oprangeset(ABLS, t) 2256 oprangeset(ABGE, t) 2257 oprangeset(ABLT, t) 2258 oprangeset(ABGT, t) 2259 oprangeset(ABLE, t) 2260 2261 case ALSL: 2262 oprangeset(ALSLW, t) 2263 oprangeset(ALSR, t) 2264 oprangeset(ALSRW, t) 2265 oprangeset(AASR, t) 2266 oprangeset(AASRW, t) 2267 oprangeset(AROR, t) 2268 oprangeset(ARORW, t) 2269 2270 case ACLS: 2271 oprangeset(ACLSW, t) 2272 oprangeset(ACLZ, t) 2273 oprangeset(ACLZW, t) 2274 oprangeset(ARBIT, t) 2275 oprangeset(ARBITW, t) 2276 oprangeset(AREV, t) 2277 oprangeset(AREVW, t) 2278 oprangeset(AREV16, t) 2279 oprangeset(AREV16W, t) 2280 oprangeset(AREV32, t) 2281 2282 case ASDIV: 2283 oprangeset(ASDIVW, t) 2284 oprangeset(AUDIV, t) 2285 oprangeset(AUDIVW, t) 2286 oprangeset(ACRC32B, t) 2287 oprangeset(ACRC32CB, t) 2288 oprangeset(ACRC32CH, t) 2289 oprangeset(ACRC32CW, t) 2290 oprangeset(ACRC32CX, t) 2291 oprangeset(ACRC32H, t) 2292 oprangeset(ACRC32W, t) 2293 oprangeset(ACRC32X, t) 2294 2295 case AMADD: 2296 oprangeset(AMADDW, t) 2297 oprangeset(AMSUB, t) 2298 oprangeset(AMSUBW, t) 2299 oprangeset(ASMADDL, t) 2300 oprangeset(ASMSUBL, t) 2301 oprangeset(AUMADDL, t) 2302 oprangeset(AUMSUBL, t) 2303 2304 case AREM: 2305 oprangeset(AREMW, t) 2306 oprangeset(AUREM, t) 2307 oprangeset(AUREMW, t) 2308 2309 case AMUL: 2310 oprangeset(AMULW, t) 2311 oprangeset(AMNEG, t) 2312 oprangeset(AMNEGW, t) 2313 oprangeset(ASMNEGL, t) 2314 oprangeset(ASMULL, t) 2315 oprangeset(ASMULH, t) 2316 oprangeset(AUMNEGL, t) 2317 oprangeset(AUMULH, t) 2318 oprangeset(AUMULL, t) 2319 2320 case AMOVB: 2321 oprangeset(AMOVBU, t) 2322 2323 case AMOVH: 2324 oprangeset(AMOVHU, t) 2325 2326 case AMOVW: 2327 oprangeset(AMOVWU, t) 2328 2329 case ABFM: 2330 oprangeset(ABFMW, t) 2331 oprangeset(ASBFM, t) 2332 oprangeset(ASBFMW, t) 2333 oprangeset(AUBFM, t) 2334 oprangeset(AUBFMW, t) 2335 2336 case ABFI: 2337 oprangeset(ABFIW, t) 2338 oprangeset(ABFXIL, t) 2339 oprangeset(ABFXILW, t) 2340 oprangeset(ASBFIZ, t) 2341 oprangeset(ASBFIZW, t) 2342 oprangeset(ASBFX, t) 2343 oprangeset(ASBFXW, t) 2344 oprangeset(AUBFIZ, t) 2345 oprangeset(AUBFIZW, t) 2346 oprangeset(AUBFX, t) 2347 oprangeset(AUBFXW, t) 2348 2349 case AEXTR: 2350 oprangeset(AEXTRW, t) 2351 2352 case ASXTB: 2353 oprangeset(ASXTBW, t) 2354 oprangeset(ASXTH, t) 2355 oprangeset(ASXTHW, t) 2356 oprangeset(ASXTW, t) 2357 oprangeset(AUXTB, t) 2358 oprangeset(AUXTH, t) 2359 oprangeset(AUXTW, t) 2360 oprangeset(AUXTBW, t) 2361 oprangeset(AUXTHW, t) 2362 2363 case ACCMN: 2364 oprangeset(ACCMNW, t) 2365 oprangeset(ACCMP, t) 2366 oprangeset(ACCMPW, t) 2367 2368 case ACSEL: 2369 oprangeset(ACSELW, t) 2370 oprangeset(ACSINC, t) 2371 oprangeset(ACSINCW, t) 2372 oprangeset(ACSINV, t) 2373 oprangeset(ACSINVW, t) 2374 oprangeset(ACSNEG, t) 2375 oprangeset(ACSNEGW, t) 2376 2377 case ACINC: 2378 // aliases Rm=Rn, !cond 2379 oprangeset(ACINCW, t) 2380 oprangeset(ACINV, t) 2381 oprangeset(ACINVW, t) 2382 oprangeset(ACNEG, t) 2383 oprangeset(ACNEGW, t) 2384 2385 // aliases, Rm=Rn=REGZERO, !cond 2386 case ACSET: 2387 oprangeset(ACSETW, t) 2388 2389 oprangeset(ACSETM, t) 2390 oprangeset(ACSETMW, t) 2391 2392 case AMOVD, 2393 AMOVBU, 2394 AB, 2395 ABL, 2396 AWORD, 2397 ADWORD, 2398 obj.ARET, 2399 obj.ATEXT: 2400 break 2401 2402 case ALDP: 2403 oprangeset(AFLDPD, t) 2404 2405 case ASTP: 2406 oprangeset(AFSTPD, t) 2407 2408 case ASTPW: 2409 oprangeset(AFSTPS, t) 2410 2411 case ALDPW: 2412 oprangeset(ALDPSW, t) 2413 oprangeset(AFLDPS, t) 2414 2415 case AERET: 2416 oprangeset(AWFE, t) 2417 oprangeset(AWFI, t) 2418 oprangeset(AYIELD, t) 2419 oprangeset(ASEV, t) 2420 oprangeset(ASEVL, t) 2421 oprangeset(ADRPS, t) 2422 2423 case ACBZ: 2424 oprangeset(ACBZW, t) 2425 oprangeset(ACBNZ, t) 2426 oprangeset(ACBNZW, t) 2427 2428 case ATBZ: 2429 oprangeset(ATBNZ, t) 2430 2431 case AADR, AADRP: 2432 break 2433 2434 case ACLREX: 2435 break 2436 2437 case ASVC: 2438 oprangeset(AHVC, t) 2439 oprangeset(AHLT, t) 2440 oprangeset(ASMC, t) 2441 oprangeset(ABRK, t) 2442 oprangeset(ADCPS1, t) 2443 oprangeset(ADCPS2, t) 2444 oprangeset(ADCPS3, t) 2445 2446 case AFADDS: 2447 oprangeset(AFADDD, t) 2448 oprangeset(AFSUBS, t) 2449 oprangeset(AFSUBD, t) 2450 oprangeset(AFMULS, t) 2451 oprangeset(AFMULD, t) 2452 oprangeset(AFNMULS, t) 2453 oprangeset(AFNMULD, t) 2454 oprangeset(AFDIVS, t) 2455 oprangeset(AFMAXD, t) 2456 oprangeset(AFMAXS, t) 2457 oprangeset(AFMIND, t) 2458 oprangeset(AFMINS, t) 2459 oprangeset(AFMAXNMD, t) 2460 oprangeset(AFMAXNMS, t) 2461 oprangeset(AFMINNMD, t) 2462 oprangeset(AFMINNMS, t) 2463 oprangeset(AFDIVD, t) 2464 2465 case AFMSUBD: 2466 oprangeset(AFMSUBS, t) 2467 oprangeset(AFMADDS, t) 2468 oprangeset(AFMADDD, t) 2469 oprangeset(AFNMSUBS, t) 2470 oprangeset(AFNMSUBD, t) 2471 oprangeset(AFNMADDS, t) 2472 oprangeset(AFNMADDD, t) 2473 2474 case AFCVTSD: 2475 oprangeset(AFCVTDS, t) 2476 oprangeset(AFABSD, t) 2477 oprangeset(AFABSS, t) 2478 oprangeset(AFNEGD, t) 2479 oprangeset(AFNEGS, t) 2480 oprangeset(AFSQRTD, t) 2481 oprangeset(AFSQRTS, t) 2482 oprangeset(AFRINTNS, t) 2483 oprangeset(AFRINTND, t) 2484 oprangeset(AFRINTPS, t) 2485 oprangeset(AFRINTPD, t) 2486 oprangeset(AFRINTMS, t) 2487 oprangeset(AFRINTMD, t) 2488 oprangeset(AFRINTZS, t) 2489 oprangeset(AFRINTZD, t) 2490 oprangeset(AFRINTAS, t) 2491 oprangeset(AFRINTAD, t) 2492 oprangeset(AFRINTXS, t) 2493 oprangeset(AFRINTXD, t) 2494 oprangeset(AFRINTIS, t) 2495 oprangeset(AFRINTID, t) 2496 oprangeset(AFCVTDH, t) 2497 oprangeset(AFCVTHS, t) 2498 oprangeset(AFCVTHD, t) 2499 oprangeset(AFCVTSH, t) 2500 2501 case AFCMPS: 2502 oprangeset(AFCMPD, t) 2503 oprangeset(AFCMPES, t) 2504 oprangeset(AFCMPED, t) 2505 2506 case AFCCMPS: 2507 oprangeset(AFCCMPD, t) 2508 oprangeset(AFCCMPES, t) 2509 oprangeset(AFCCMPED, t) 2510 2511 case AFCSELD: 2512 oprangeset(AFCSELS, t) 2513 2514 case AFMOVS, AFMOVD: 2515 break 2516 2517 case AFCVTZSD: 2518 oprangeset(AFCVTZSDW, t) 2519 oprangeset(AFCVTZSS, t) 2520 oprangeset(AFCVTZSSW, t) 2521 oprangeset(AFCVTZUD, t) 2522 oprangeset(AFCVTZUDW, t) 2523 oprangeset(AFCVTZUS, t) 2524 oprangeset(AFCVTZUSW, t) 2525 2526 case ASCVTFD: 2527 oprangeset(ASCVTFS, t) 2528 oprangeset(ASCVTFWD, t) 2529 oprangeset(ASCVTFWS, t) 2530 oprangeset(AUCVTFD, t) 2531 oprangeset(AUCVTFS, t) 2532 oprangeset(AUCVTFWD, t) 2533 oprangeset(AUCVTFWS, t) 2534 2535 case ASYS: 2536 oprangeset(AAT, t) 2537 oprangeset(ADC, t) 2538 oprangeset(AIC, t) 2539 oprangeset(ATLBI, t) 2540 2541 case ASYSL, AHINT: 2542 break 2543 2544 case ADMB: 2545 oprangeset(ADSB, t) 2546 oprangeset(AISB, t) 2547 2548 case AMRS, AMSR: 2549 break 2550 2551 case ALDAR: 2552 oprangeset(ALDARW, t) 2553 oprangeset(ALDARB, t) 2554 oprangeset(ALDARH, t) 2555 fallthrough 2556 2557 case ALDXR: 2558 oprangeset(ALDXRB, t) 2559 oprangeset(ALDXRH, t) 2560 oprangeset(ALDXRW, t) 2561 2562 case ALDAXR: 2563 oprangeset(ALDAXRB, t) 2564 oprangeset(ALDAXRH, t) 2565 oprangeset(ALDAXRW, t) 2566 2567 case ALDXP: 2568 oprangeset(ALDXPW, t) 2569 oprangeset(ALDAXP, t) 2570 oprangeset(ALDAXPW, t) 2571 2572 case ASTLR: 2573 oprangeset(ASTLRB, t) 2574 oprangeset(ASTLRH, t) 2575 oprangeset(ASTLRW, t) 2576 2577 case ASTXR: 2578 oprangeset(ASTXRB, t) 2579 oprangeset(ASTXRH, t) 2580 oprangeset(ASTXRW, t) 2581 2582 case ASTLXR: 2583 oprangeset(ASTLXRB, t) 2584 oprangeset(ASTLXRH, t) 2585 oprangeset(ASTLXRW, t) 2586 2587 case ASTXP: 2588 oprangeset(ASTLXP, t) 2589 oprangeset(ASTLXPW, t) 2590 oprangeset(ASTXPW, t) 2591 2592 case AVADDP: 2593 oprangeset(AVAND, t) 2594 oprangeset(AVCMEQ, t) 2595 oprangeset(AVORR, t) 2596 oprangeset(AVEOR, t) 2597 2598 case AVADD: 2599 oprangeset(AVSUB, t) 2600 2601 case AAESD: 2602 oprangeset(AAESE, t) 2603 oprangeset(AAESMC, t) 2604 oprangeset(AAESIMC, t) 2605 oprangeset(ASHA1SU1, t) 2606 oprangeset(ASHA256SU0, t) 2607 2608 case ASHA1C: 2609 oprangeset(ASHA1P, t) 2610 oprangeset(ASHA1M, t) 2611 2612 case ASHA256H: 2613 oprangeset(ASHA256H2, t) 2614 2615 case ASHA1SU0: 2616 oprangeset(ASHA256SU1, t) 2617 2618 case AVADDV: 2619 oprangeset(AVUADDLV, t) 2620 2621 case AVFMLA: 2622 oprangeset(AVFMLS, t) 2623 2624 case AVPMULL: 2625 oprangeset(AVPMULL2, t) 2626 2627 case AVUSHR: 2628 oprangeset(AVSHL, t) 2629 oprangeset(AVSRI, t) 2630 2631 case AVREV32: 2632 oprangeset(AVRBIT, t) 2633 oprangeset(AVREV64, t) 2634 2635 case AVZIP1: 2636 oprangeset(AVZIP2, t) 2637 2638 case ASHA1H, 2639 AVCNT, 2640 AVMOV, 2641 AVLD1, 2642 AVST1, 2643 AVTBL, 2644 AVDUP, 2645 AVMOVI, 2646 APRFM, 2647 AVEXT: 2648 break 2649 2650 case obj.ANOP, 2651 obj.AUNDEF, 2652 obj.AFUNCDATA, 2653 obj.APCDATA, 2654 obj.ADUFFZERO, 2655 obj.ADUFFCOPY: 2656 break 2657 } 2658 } 2659 } 2660 2661 // chipfloat7() checks if the immediate constants available in FMOVS/FMOVD instructions. 2662 // For details of the range of constants available, see 2663 // http://infocenter.arm.com/help/topic/com.arm.doc.dui0473m/dom1359731199385.html. 2664 func (c *ctxt7) chipfloat7(e float64) int { 2665 ei := math.Float64bits(e) 2666 l := uint32(int32(ei)) 2667 h := uint32(int32(ei >> 32)) 2668 2669 if l != 0 || h&0xffff != 0 { 2670 return -1 2671 } 2672 h1 := h & 0x7fc00000 2673 if h1 != 0x40000000 && h1 != 0x3fc00000 { 2674 return -1 2675 } 2676 n := 0 2677 2678 // sign bit (a) 2679 if h&0x80000000 != 0 { 2680 n |= 1 << 7 2681 } 2682 2683 // exp sign bit (b) 2684 if h1 == 0x3fc00000 { 2685 n |= 1 << 6 2686 } 2687 2688 // rest of exp and mantissa (cd-efgh) 2689 n |= int((h >> 16) & 0x3f) 2690 2691 //print("match %.8lux %.8lux %d\n", l, h, n); 2692 return n 2693 } 2694 2695 /* form offset parameter to SYS; special register number */ 2696 func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int { 2697 return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5 2698 } 2699 2700 func SYSARG4(op1 int, Cn int, Cm int, op2 int) int { 2701 return SYSARG5(0, op1, Cn, Cm, op2) 2702 } 2703 2704 // checkUnpredictable checks if the sourse and transfer registers are the same register. 2705 // ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same. 2706 func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) { 2707 if wback && rn != REGSP && (rn == rt1 || rn == rt2) { 2708 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 2709 } 2710 if isload && rt1 == rt2 { 2711 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 2712 } 2713 } 2714 2715 /* checkindex checks if index >= 0 && index <= maxindex */ 2716 func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) { 2717 if index < 0 || index > maxindex { 2718 c.ctxt.Diag("register element index out of range 0 to %d: %v", maxindex, p) 2719 } 2720 } 2721 2722 /* checkoffset checks whether the immediate offset is valid for VLD1.P and VST1.P */ 2723 func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) { 2724 var offset, list, n int64 2725 switch as { 2726 case AVLD1: 2727 offset = p.From.Offset 2728 list = p.To.Offset 2729 case AVST1: 2730 offset = p.To.Offset 2731 list = p.From.Offset 2732 default: 2733 c.ctxt.Diag("invalid operation on op %v", p.As) 2734 } 2735 opcode := (list >> 12) & 15 2736 q := (list >> 30) & 1 2737 if offset == 0 { 2738 return 2739 } 2740 switch opcode { 2741 case 0x7: 2742 n = 1 // one register 2743 case 0xa: 2744 n = 2 // two registers 2745 case 0x6: 2746 n = 3 // three registers 2747 case 0x2: 2748 n = 4 // four registers 2749 default: 2750 c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p) 2751 } 2752 if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) { 2753 c.ctxt.Diag("invalid post-increment offset: %v", p) 2754 } 2755 } 2756 2757 /* checkShiftAmount checks whether the index shift amount is valid */ 2758 /* for load with register offset instructions */ 2759 func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) { 2760 var amount int16 2761 amount = (a.Index >> 5) & 7 2762 switch p.As { 2763 case AMOVB, AMOVBU: 2764 if amount != 0 { 2765 c.ctxt.Diag("invalid index shift amount: %v", p) 2766 } 2767 case AMOVH, AMOVHU: 2768 if amount != 1 && amount != 0 { 2769 c.ctxt.Diag("invalid index shift amount: %v", p) 2770 } 2771 case AMOVW, AMOVWU, AFMOVS: 2772 if amount != 2 && amount != 0 { 2773 c.ctxt.Diag("invalid index shift amount: %v", p) 2774 } 2775 case AMOVD, AFMOVD: 2776 if amount != 3 && amount != 0 { 2777 c.ctxt.Diag("invalid index shift amount: %v", p) 2778 } 2779 default: 2780 panic("invalid operation") 2781 } 2782 } 2783 2784 func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { 2785 var os [5]uint32 2786 o1 := uint32(0) 2787 o2 := uint32(0) 2788 o3 := uint32(0) 2789 o4 := uint32(0) 2790 o5 := uint32(0) 2791 if false { /*debug['P']*/ 2792 fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_) 2793 } 2794 switch o.type_ { 2795 default: 2796 c.ctxt.Diag("%v: unknown asm %d", p, o.type_) 2797 2798 case 0: /* pseudo ops */ 2799 break 2800 2801 case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */ 2802 o1 = c.oprrr(p, p.As) 2803 2804 rf := int(p.From.Reg) 2805 rt := int(p.To.Reg) 2806 r := int(p.Reg) 2807 if p.To.Type == obj.TYPE_NONE { 2808 rt = REGZERO 2809 } 2810 if r == 0 { 2811 r = rt 2812 } 2813 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 2814 2815 case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */ 2816 o1 = c.opirr(p, p.As) 2817 2818 rt := int(p.To.Reg) 2819 if p.To.Type == obj.TYPE_NONE { 2820 if (o1 & Sbit) == 0 { 2821 c.ctxt.Diag("ineffective ZR destination\n%v", p) 2822 } 2823 rt = REGZERO 2824 } 2825 2826 r := int(p.Reg) 2827 if r == 0 { 2828 r = rt 2829 } 2830 v := int32(c.regoff(&p.From)) 2831 o1 = c.oaddi(p, int32(o1), v, r, rt) 2832 2833 case 3: /* op R<<n[,R],R (shifted register) */ 2834 o1 = c.oprrr(p, p.As) 2835 2836 amount := (p.From.Offset >> 10) & 63 2837 is64bit := o1 & (1 << 31) 2838 if is64bit == 0 && amount >= 32 { 2839 c.ctxt.Diag("shift amount out of range 0 to 31: %v", p) 2840 } 2841 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 2842 rt := int(p.To.Reg) 2843 if p.To.Type == obj.TYPE_NONE { 2844 rt = REGZERO 2845 } 2846 r := int(p.Reg) 2847 if p.As == AMVN || p.As == AMVNW { 2848 r = REGZERO 2849 } else if r == 0 { 2850 r = rt 2851 } 2852 o1 |= (uint32(r&31) << 5) | uint32(rt&31) 2853 2854 case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R */ 2855 o1 = c.opirr(p, p.As) 2856 2857 rt := int(p.To.Reg) 2858 r := int(o.param) 2859 if r == 0 { 2860 r = REGZERO 2861 } else if r == REGFROM { 2862 r = int(p.From.Reg) 2863 } 2864 if r == 0 { 2865 r = REGSP 2866 } 2867 v := int32(c.regoff(&p.From)) 2868 if (v & 0xFFF000) != 0 { 2869 v >>= 12 2870 o1 |= 1 << 22 /* shift, by 12 */ 2871 } 2872 2873 o1 |= ((uint32(v) & 0xFFF) << 10) | (uint32(r&31) << 5) | uint32(rt&31) 2874 2875 case 5: /* b s; bl s */ 2876 o1 = c.opbra(p, p.As) 2877 2878 if p.To.Sym == nil { 2879 o1 |= uint32(c.brdist(p, 0, 26, 2)) 2880 break 2881 } 2882 2883 rel := obj.Addrel(c.cursym) 2884 rel.Off = int32(c.pc) 2885 rel.Siz = 4 2886 rel.Sym = p.To.Sym 2887 rel.Add = p.To.Offset 2888 rel.Type = objabi.R_CALLARM64 2889 2890 case 6: /* b ,O(R); bl ,O(R) */ 2891 o1 = c.opbrr(p, p.As) 2892 2893 o1 |= uint32(p.To.Reg&31) << 5 2894 rel := obj.Addrel(c.cursym) 2895 rel.Off = int32(c.pc) 2896 rel.Siz = 0 2897 rel.Type = objabi.R_CALLIND 2898 2899 case 7: /* beq s */ 2900 o1 = c.opbra(p, p.As) 2901 2902 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5) 2903 2904 case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */ 2905 rt := int(p.To.Reg) 2906 2907 rf := int(p.Reg) 2908 if rf == 0 { 2909 rf = rt 2910 } 2911 v := int32(p.From.Offset) 2912 switch p.As { 2913 case AASR: 2914 o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt) 2915 2916 case AASRW: 2917 o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt) 2918 2919 case ALSL: 2920 o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt) 2921 2922 case ALSLW: 2923 o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt) 2924 2925 case ALSR: 2926 o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt) 2927 2928 case ALSRW: 2929 o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt) 2930 2931 case AROR: 2932 o1 = c.opextr(p, AEXTR, v, rf, rf, rt) 2933 2934 case ARORW: 2935 o1 = c.opextr(p, AEXTRW, v, rf, rf, rt) 2936 2937 default: 2938 c.ctxt.Diag("bad shift $con\n%v", p) 2939 break 2940 } 2941 2942 case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */ 2943 o1 = c.oprrr(p, p.As) 2944 2945 r := int(p.Reg) 2946 if r == 0 { 2947 r = int(p.To.Reg) 2948 } 2949 o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31) 2950 2951 case 10: /* brk/hvc/.../svc [$con] */ 2952 o1 = c.opimm(p, p.As) 2953 2954 if p.From.Type != obj.TYPE_NONE { 2955 o1 |= uint32((p.From.Offset & 0xffff) << 5) 2956 } 2957 2958 case 11: /* dword */ 2959 c.aclass(&p.To) 2960 2961 o1 = uint32(c.instoffset) 2962 o2 = uint32(c.instoffset >> 32) 2963 if p.To.Sym != nil { 2964 rel := obj.Addrel(c.cursym) 2965 rel.Off = int32(c.pc) 2966 rel.Siz = 8 2967 rel.Sym = p.To.Sym 2968 rel.Add = p.To.Offset 2969 rel.Type = objabi.R_ADDR 2970 o2 = 0 2971 o1 = o2 2972 } 2973 2974 case 12: /* movT $vcon, reg */ 2975 num := c.omovlconst(p.As, p, &p.From, int(p.To.Reg), os[:]) 2976 if num == 0 { 2977 c.ctxt.Diag("invalid constant: %v", p) 2978 } 2979 o1 = os[0] 2980 o2 = os[1] 2981 o3 = os[2] 2982 o4 = os[3] 2983 2984 case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */ 2985 o := uint32(0) 2986 num := uint8(0) 2987 cls := oclass(&p.From) 2988 if isADDWop(p.As) { 2989 if !cmp(C_LCON, cls) { 2990 c.ctxt.Diag("illegal combination: %v", p) 2991 } 2992 num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:]) 2993 } else { 2994 num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:]) 2995 } 2996 if num == 0 { 2997 c.ctxt.Diag("invalid constant: %v", p) 2998 } 2999 rt := int(p.To.Reg) 3000 if p.To.Type == obj.TYPE_NONE { 3001 rt = REGZERO 3002 } 3003 r := int(p.Reg) 3004 if r == 0 { 3005 r = rt 3006 } 3007 if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) { 3008 o = c.opxrrr(p, p.As, false) 3009 o |= REGTMP & 31 << 16 3010 o |= LSL0_64 3011 } else { 3012 o = c.oprrr(p, p.As) 3013 o |= REGTMP & 31 << 16 /* shift is 0 */ 3014 } 3015 3016 o |= uint32(r&31) << 5 3017 o |= uint32(rt & 31) 3018 3019 os[num] = o 3020 o1 = os[0] 3021 o2 = os[1] 3022 o3 = os[2] 3023 o4 = os[3] 3024 o5 = os[4] 3025 3026 case 14: /* word */ 3027 if c.aclass(&p.To) == C_ADDR { 3028 c.ctxt.Diag("address constant needs DWORD\n%v", p) 3029 } 3030 o1 = uint32(c.instoffset) 3031 if p.To.Sym != nil { 3032 // This case happens with words generated 3033 // in the PC stream as part of the literal pool. 3034 rel := obj.Addrel(c.cursym) 3035 3036 rel.Off = int32(c.pc) 3037 rel.Siz = 4 3038 rel.Sym = p.To.Sym 3039 rel.Add = p.To.Offset 3040 rel.Type = objabi.R_ADDR 3041 o1 = 0 3042 } 3043 3044 case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub/fmadd/fmsub/fnmadd/fnmsub Rm,Ra,Rn,Rd */ 3045 o1 = c.oprrr(p, p.As) 3046 3047 rf := int(p.From.Reg) 3048 rt := int(p.To.Reg) 3049 var r int 3050 var ra int 3051 if p.From3Type() == obj.TYPE_REG { 3052 r = int(p.GetFrom3().Reg) 3053 ra = int(p.Reg) 3054 if ra == 0 { 3055 ra = REGZERO 3056 } 3057 } else { 3058 r = int(p.Reg) 3059 if r == 0 { 3060 r = rt 3061 } 3062 ra = REGZERO 3063 } 3064 3065 o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31) 3066 3067 case 16: /* XremY R[,R],R -> XdivY; XmsubY */ 3068 o1 = c.oprrr(p, p.As) 3069 3070 rf := int(p.From.Reg) 3071 rt := int(p.To.Reg) 3072 r := int(p.Reg) 3073 if r == 0 { 3074 r = rt 3075 } 3076 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31 3077 o2 = c.oprrr(p, AMSUBW) 3078 o2 |= o1 & (1 << 31) /* same size */ 3079 o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31) 3080 3081 case 17: /* op Rm,[Rn],Rd; default Rn=ZR */ 3082 o1 = c.oprrr(p, p.As) 3083 3084 rf := int(p.From.Reg) 3085 rt := int(p.To.Reg) 3086 r := int(p.Reg) 3087 if p.To.Type == obj.TYPE_NONE { 3088 rt = REGZERO 3089 } 3090 if r == 0 { 3091 r = REGZERO 3092 } 3093 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 3094 3095 case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */ 3096 o1 = c.oprrr(p, p.As) 3097 3098 cond := int(p.From.Reg) 3099 if cond < COND_EQ || cond > COND_NV { 3100 c.ctxt.Diag("invalid condition: %v", p) 3101 } else { 3102 cond -= COND_EQ 3103 } 3104 3105 r := int(p.Reg) 3106 var rf int 3107 if r != 0 { 3108 if p.From3Type() == obj.TYPE_NONE { 3109 /* CINC/CINV/CNEG */ 3110 rf = r 3111 cond ^= 1 3112 } else { 3113 rf = int(p.GetFrom3().Reg) /* CSEL */ 3114 } 3115 } else { 3116 /* CSET */ 3117 rf = REGZERO 3118 r = rf 3119 cond ^= 1 3120 } 3121 3122 rt := int(p.To.Reg) 3123 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31) 3124 3125 case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */ 3126 nzcv := int(p.To.Offset) 3127 3128 cond := int(p.From.Reg) 3129 if cond < COND_EQ || cond > COND_NV { 3130 c.ctxt.Diag("invalid condition\n%v", p) 3131 } else { 3132 cond -= COND_EQ 3133 } 3134 var rf int 3135 if p.GetFrom3().Type == obj.TYPE_REG { 3136 o1 = c.oprrr(p, p.As) 3137 rf = int(p.GetFrom3().Reg) /* Rm */ 3138 } else { 3139 o1 = c.opirr(p, p.As) 3140 rf = int(p.GetFrom3().Offset & 0x1F) 3141 } 3142 3143 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv) 3144 3145 case 20: /* movT R,O(R) -> strT */ 3146 v := int32(c.regoff(&p.To)) 3147 sz := int32(1 << uint(movesize(p.As))) 3148 3149 r := int(p.To.Reg) 3150 if r == 0 { 3151 r = int(o.param) 3152 } 3153 if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ 3154 o1 = c.olsr9s(p, int32(c.opstr9(p, p.As)), v, r, int(p.From.Reg)) 3155 } else { 3156 v = int32(c.offsetshift(p, int64(v), int(o.a4))) 3157 o1 = c.olsr12u(p, int32(c.opstr12(p, p.As)), v, r, int(p.From.Reg)) 3158 } 3159 3160 case 21: /* movT O(R),R -> ldrT */ 3161 v := int32(c.regoff(&p.From)) 3162 sz := int32(1 << uint(movesize(p.As))) 3163 3164 r := int(p.From.Reg) 3165 if r == 0 { 3166 r = int(o.param) 3167 } 3168 if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ 3169 o1 = c.olsr9s(p, int32(c.opldr9(p, p.As)), v, r, int(p.To.Reg)) 3170 } else { 3171 v = int32(c.offsetshift(p, int64(v), int(o.a1))) 3172 //print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1); 3173 o1 = c.olsr12u(p, int32(c.opldr12(p, p.As)), v, r, int(p.To.Reg)) 3174 } 3175 3176 case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */ 3177 if p.From.Reg != REGSP && p.From.Reg == p.To.Reg { 3178 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3179 } 3180 3181 v := int32(p.From.Offset) 3182 3183 if v < -256 || v > 255 { 3184 c.ctxt.Diag("offset out of range [-255,254]: %v", p) 3185 } 3186 o1 = c.opldrpp(p, p.As) 3187 if o.scond == C_XPOST { 3188 o1 |= 1 << 10 3189 } else { 3190 o1 |= 3 << 10 3191 } 3192 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31) 3193 3194 case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */ 3195 if p.To.Reg != REGSP && p.From.Reg == p.To.Reg { 3196 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3197 } 3198 3199 v := int32(p.To.Offset) 3200 3201 if v < -256 || v > 255 { 3202 c.ctxt.Diag("offset out of range [-255,254]: %v", p) 3203 } 3204 o1 = LD2STR(c.opldrpp(p, p.As)) 3205 if o.scond == C_XPOST { 3206 o1 |= 1 << 10 3207 } else { 3208 o1 |= 3 << 10 3209 } 3210 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31) 3211 3212 case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */ 3213 rf := int(p.From.Reg) 3214 rt := int(p.To.Reg) 3215 s := rf == REGSP || rt == REGSP 3216 if p.As == AMVN || p.As == AMVNW { 3217 if s { 3218 c.ctxt.Diag("illegal SP reference\n%v", p) 3219 } 3220 o1 = c.oprrr(p, p.As) 3221 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 3222 } else if s { 3223 o1 = c.opirr(p, p.As) 3224 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 3225 } else { 3226 o1 = c.oprrr(p, p.As) 3227 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 3228 } 3229 3230 case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */ 3231 o1 = c.oprrr(p, p.As) 3232 3233 rf := int(p.From.Reg) 3234 if rf == C_NONE { 3235 rf = int(p.To.Reg) 3236 } 3237 rt := int(p.To.Reg) 3238 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 3239 3240 case 26: /* negX Rm<<s, Rd -> subX Rm<<s, ZR, Rd */ 3241 o1 = c.oprrr(p, p.As) 3242 3243 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 3244 rt := int(p.To.Reg) 3245 o1 |= (REGZERO & 31 << 5) | uint32(rt&31) 3246 3247 case 27: /* op Rm<<n[,Rn],Rd (extended register) */ 3248 if (p.From.Reg-obj.RBaseARM64)®_EXT != 0 { 3249 amount := (p.From.Reg >> 5) & 7 3250 if amount > 4 { 3251 c.ctxt.Diag("shift amount out of range 0 to 4: %v", p) 3252 } 3253 o1 = c.opxrrr(p, p.As, true) 3254 o1 |= c.encRegShiftOrExt(&p.From, p.From.Reg) /* includes reg, op, etc */ 3255 } else { 3256 o1 = c.opxrrr(p, p.As, false) 3257 o1 |= uint32(p.From.Reg&31) << 16 3258 } 3259 rt := int(p.To.Reg) 3260 if p.To.Type == obj.TYPE_NONE { 3261 rt = REGZERO 3262 } 3263 r := int(p.Reg) 3264 if r == 0 { 3265 r = rt 3266 } 3267 o1 |= (uint32(r&31) << 5) | uint32(rt&31) 3268 3269 case 28: /* logop $vcon, [R], R (64 bit literal) */ 3270 o := uint32(0) 3271 num := uint8(0) 3272 cls := oclass(&p.From) 3273 if isANDWop(p.As) { 3274 if !cmp(C_LCON, cls) { 3275 c.ctxt.Diag("illegal combination: %v", p) 3276 } 3277 num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:]) 3278 } else { 3279 num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:]) 3280 } 3281 3282 if num == 0 { 3283 c.ctxt.Diag("invalid constant: %v", p) 3284 } 3285 rt := int(p.To.Reg) 3286 if p.To.Type == obj.TYPE_NONE { 3287 rt = REGZERO 3288 } 3289 r := int(p.Reg) 3290 if r == 0 { 3291 r = rt 3292 } 3293 o = c.oprrr(p, p.As) 3294 o |= REGTMP & 31 << 16 /* shift is 0 */ 3295 o |= uint32(r&31) << 5 3296 o |= uint32(rt & 31) 3297 3298 os[num] = o 3299 o1 = os[0] 3300 o2 = os[1] 3301 o3 = os[2] 3302 o4 = os[3] 3303 o5 = os[4] 3304 3305 case 29: /* op Rn, Rd */ 3306 fc := c.aclass(&p.From) 3307 tc := c.aclass(&p.To) 3308 if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZCON || tc == C_REG || tc == C_ZCON) { 3309 // FMOV Rx, Fy or FMOV Fy, Rx 3310 o1 = FPCVTI(0, 0, 0, 0, 6) 3311 if p.As == AFMOVD { 3312 o1 |= 1<<31 | 1<<22 // 64-bit 3313 } 3314 if fc == C_REG || fc == C_ZCON { 3315 o1 |= 1 << 16 // FMOV Rx, Fy 3316 } 3317 } else { 3318 o1 = c.oprrr(p, p.As) 3319 } 3320 o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31) 3321 3322 case 30: /* movT R,L(R) -> strT */ 3323 // if offset L can be split into hi+lo, and both fit into instructions, do 3324 // add $hi, R, Rtmp 3325 // str R, lo(Rtmp) 3326 // otherwise, use constant pool 3327 // mov $L, Rtmp (from constant pool) 3328 // str R, (R+Rtmp) 3329 s := movesize(o.as) 3330 if s < 0 { 3331 c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) 3332 } 3333 3334 r := int(p.To.Reg) 3335 if r == 0 { 3336 r = int(o.param) 3337 } 3338 3339 v := int32(c.regoff(&p.To)) 3340 var hi int32 3341 if v < 0 || (v&((1<<uint(s))-1)) != 0 { 3342 // negative or unaligned offset, use constant pool 3343 goto storeusepool 3344 } 3345 3346 hi = v - (v & (0xFFF << uint(s))) 3347 if hi&0xFFF != 0 { 3348 c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p) 3349 } 3350 if hi&^0xFFF000 != 0 { 3351 // hi doesn't fit into an ADD instruction 3352 goto storeusepool 3353 } 3354 3355 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP) 3356 o2 = c.olsr12u(p, int32(c.opstr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg)) 3357 break 3358 3359 storeusepool: 3360 if r == REGTMP || p.From.Reg == REGTMP { 3361 c.ctxt.Diag("REGTMP used in large offset store: %v", p) 3362 } 3363 o1 = c.omovlit(AMOVD, p, &p.To, REGTMP) 3364 o2 = c.olsxrr(p, int32(c.opstrr(p, p.As, false)), int(p.From.Reg), r, REGTMP) 3365 3366 case 31: /* movT L(R), R -> ldrT */ 3367 // if offset L can be split into hi+lo, and both fit into instructions, do 3368 // add $hi, R, Rtmp 3369 // ldr lo(Rtmp), R 3370 // otherwise, use constant pool 3371 // mov $L, Rtmp (from constant pool) 3372 // ldr (R+Rtmp), R 3373 s := movesize(o.as) 3374 if s < 0 { 3375 c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) 3376 } 3377 3378 r := int(p.From.Reg) 3379 if r == 0 { 3380 r = int(o.param) 3381 } 3382 3383 v := int32(c.regoff(&p.From)) 3384 var hi int32 3385 if v < 0 || (v&((1<<uint(s))-1)) != 0 { 3386 // negative or unaligned offset, use constant pool 3387 goto loadusepool 3388 } 3389 3390 hi = v - (v & (0xFFF << uint(s))) 3391 if (hi & 0xFFF) != 0 { 3392 c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p) 3393 } 3394 if hi&^0xFFF000 != 0 { 3395 // hi doesn't fit into an ADD instruction 3396 goto loadusepool 3397 } 3398 3399 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP) 3400 o2 = c.olsr12u(p, int32(c.opldr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg)) 3401 break 3402 3403 loadusepool: 3404 if r == REGTMP || p.From.Reg == REGTMP { 3405 c.ctxt.Diag("REGTMP used in large offset load: %v", p) 3406 } 3407 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 3408 o2 = c.olsxrr(p, int32(c.opldrr(p, p.As, false)), int(p.To.Reg), r, REGTMP) 3409 3410 case 32: /* mov $con, R -> movz/movn */ 3411 o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg)) 3412 3413 case 33: /* movk $uimm16 << pos */ 3414 o1 = c.opirr(p, p.As) 3415 3416 d := p.From.Offset 3417 s := movcon(d) 3418 if s < 0 || s >= 4 { 3419 c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p) 3420 } 3421 if (o1&S64) == 0 && s >= 2 { 3422 c.ctxt.Diag("illegal bit position\n%v", p) 3423 } 3424 if ((d >> uint(s*16)) >> 16) != 0 { 3425 c.ctxt.Diag("requires uimm16\n%v", p) 3426 } 3427 rt := int(p.To.Reg) 3428 3429 o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31)) 3430 3431 case 34: /* mov $lacon,R */ 3432 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 3433 3434 if o1 == 0 { 3435 break 3436 } 3437 o2 = c.opxrrr(p, AADD, false) 3438 o2 |= REGTMP & 31 << 16 3439 o2 |= LSL0_64 3440 r := int(p.From.Reg) 3441 if r == 0 { 3442 r = int(o.param) 3443 } 3444 o2 |= uint32(r&31) << 5 3445 o2 |= uint32(p.To.Reg & 31) 3446 3447 case 35: /* mov SPR,R -> mrs */ 3448 o1 = c.oprrr(p, AMRS) 3449 3450 v := uint32(0) 3451 for i := 0; i < len(systemreg); i++ { 3452 if systemreg[i].reg == p.From.Reg { 3453 v = systemreg[i].enc 3454 break 3455 } 3456 } 3457 if v == 0 { 3458 c.ctxt.Diag("illegal system register:\n%v", p) 3459 } 3460 if (o1 & (v &^ (3 << 19))) != 0 { 3461 c.ctxt.Diag("MRS register value overlap\n%v", p) 3462 } 3463 3464 o1 |= v 3465 o1 |= uint32(p.To.Reg & 31) 3466 3467 case 36: /* mov R,SPR */ 3468 o1 = c.oprrr(p, AMSR) 3469 3470 v := uint32(0) 3471 for i := 0; i < len(systemreg); i++ { 3472 if systemreg[i].reg == p.To.Reg { 3473 v = systemreg[i].enc 3474 break 3475 } 3476 } 3477 if v == 0 { 3478 c.ctxt.Diag("illegal system register:\n%v", p) 3479 } 3480 if (o1 & (v &^ (3 << 19))) != 0 { 3481 c.ctxt.Diag("MSR register value overlap\n%v", p) 3482 } 3483 3484 o1 |= v 3485 o1 |= uint32(p.From.Reg & 31) 3486 3487 case 37: /* mov $con,PSTATEfield -> MSR [immediate] */ 3488 if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 { 3489 c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p) 3490 } 3491 o1 = c.opirr(p, AMSR) 3492 o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */ 3493 v := uint32(0) 3494 for i := 0; i < len(pstatefield); i++ { 3495 if pstatefield[i].reg == p.To.Reg { 3496 v = pstatefield[i].enc 3497 break 3498 } 3499 } 3500 3501 if v == 0 { 3502 c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p) 3503 } 3504 o1 |= v 3505 3506 case 38: /* clrex [$imm] */ 3507 o1 = c.opimm(p, p.As) 3508 3509 if p.To.Type == obj.TYPE_NONE { 3510 o1 |= 0xF << 8 3511 } else { 3512 o1 |= uint32((p.To.Offset & 0xF) << 8) 3513 } 3514 3515 case 39: /* cbz R, rel */ 3516 o1 = c.opirr(p, p.As) 3517 3518 o1 |= uint32(p.From.Reg & 31) 3519 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5) 3520 3521 case 40: /* tbz */ 3522 o1 = c.opirr(p, p.As) 3523 3524 v := int32(p.From.Offset) 3525 if v < 0 || v > 63 { 3526 c.ctxt.Diag("illegal bit number\n%v", p) 3527 } 3528 o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19) 3529 o1 |= uint32(c.brdist(p, 0, 14, 2) << 5) 3530 o1 |= uint32(p.Reg & 31) 3531 3532 case 41: /* eret, nop, others with no operands */ 3533 o1 = c.op0(p, p.As) 3534 3535 case 42: /* bfm R,r,s,R */ 3536 o1 = c.opbfm(p, p.As, int(p.From.Offset), int(p.GetFrom3().Offset), int(p.Reg), int(p.To.Reg)) 3537 3538 case 43: /* bfm aliases */ 3539 r := int(p.From.Offset) 3540 s := int(p.GetFrom3().Offset) 3541 rf := int(p.Reg) 3542 rt := int(p.To.Reg) 3543 if rf == 0 { 3544 rf = rt 3545 } 3546 switch p.As { 3547 case ABFI: 3548 if r != 0 { 3549 r = 64 - r 3550 } 3551 o1 = c.opbfm(p, ABFM, r, s-1, rf, rt) 3552 3553 case ABFIW: 3554 if r != 0 { 3555 r = 32 - r 3556 } 3557 o1 = c.opbfm(p, ABFMW, r, s-1, rf, rt) 3558 3559 case ABFXIL: 3560 o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt) 3561 3562 case ABFXILW: 3563 o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt) 3564 3565 case ASBFIZ: 3566 if r != 0 { 3567 r = 64 - r 3568 } 3569 o1 = c.opbfm(p, ASBFM, r, s-1, rf, rt) 3570 3571 case ASBFIZW: 3572 if r != 0 { 3573 r = 32 - r 3574 } 3575 o1 = c.opbfm(p, ASBFMW, r, s-1, rf, rt) 3576 3577 case ASBFX: 3578 o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt) 3579 3580 case ASBFXW: 3581 o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt) 3582 3583 case AUBFIZ: 3584 if r != 0 { 3585 r = 64 - r 3586 } 3587 o1 = c.opbfm(p, AUBFM, r, s-1, rf, rt) 3588 3589 case AUBFIZW: 3590 if r != 0 { 3591 r = 32 - r 3592 } 3593 o1 = c.opbfm(p, AUBFMW, r, s-1, rf, rt) 3594 3595 case AUBFX: 3596 o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt) 3597 3598 case AUBFXW: 3599 o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt) 3600 3601 default: 3602 c.ctxt.Diag("bad bfm alias\n%v", p) 3603 break 3604 } 3605 3606 case 44: /* extr $b, Rn, Rm, Rd */ 3607 o1 = c.opextr(p, p.As, int32(p.From.Offset), int(p.GetFrom3().Reg), int(p.Reg), int(p.To.Reg)) 3608 3609 case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */ 3610 rf := int(p.From.Reg) 3611 3612 rt := int(p.To.Reg) 3613 as := p.As 3614 if rf == REGZERO { 3615 as = AMOVWU /* clearer in disassembly */ 3616 } 3617 switch as { 3618 case AMOVB, ASXTB: 3619 o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt) 3620 3621 case AMOVH, ASXTH: 3622 o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt) 3623 3624 case AMOVW, ASXTW: 3625 o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt) 3626 3627 case AMOVBU, AUXTB: 3628 o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt) 3629 3630 case AMOVHU, AUXTH: 3631 o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt) 3632 3633 case AMOVWU: 3634 o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 3635 3636 case AUXTW: 3637 o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt) 3638 3639 case ASXTBW: 3640 o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt) 3641 3642 case ASXTHW: 3643 o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt) 3644 3645 case AUXTBW: 3646 o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt) 3647 3648 case AUXTHW: 3649 o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt) 3650 3651 default: 3652 c.ctxt.Diag("bad sxt %v", as) 3653 break 3654 } 3655 3656 case 46: /* cls */ 3657 o1 = c.opbit(p, p.As) 3658 3659 o1 |= uint32(p.From.Reg&31) << 5 3660 o1 |= uint32(p.To.Reg & 31) 3661 3662 case 47: /* SWPx Rs, (Rb), Rt: Rs -> (Rb) -> Rt */ 3663 rs := p.From.Reg 3664 rt := p.RegTo2 3665 rb := p.To.Reg 3666 switch p.As { 3667 case ASWPD, ASWPALD, ALDADDALD, ALDADDD, ALDANDD, ALDEORD, ALDORD: // 64-bit 3668 o1 = 3 << 30 3669 case ASWPW, ASWPALW, ALDADDALW, ALDADDW, ALDANDW, ALDEORW, ALDORW: // 32-bit 3670 o1 = 2 << 30 3671 case ASWPH, ASWPALH, ALDADDALH, ALDADDH, ALDANDH, ALDEORH, ALDORH: // 16-bit 3672 o1 = 1 << 30 3673 case ASWPB, ASWPALB, ALDADDALB, ALDADDB, ALDANDB, ALDEORB, ALDORB: // 8-bit 3674 o1 = 0 << 30 3675 default: 3676 c.ctxt.Diag("illegal instruction: %v\n", p) 3677 } 3678 switch p.As { 3679 case ASWPD, ASWPW, ASWPH, ASWPB, ASWPALD, ASWPALW, ASWPALH, ASWPALB: 3680 o1 |= 0x20 << 10 3681 case ALDADDALD, ALDADDALW, ALDADDALH, ALDADDALB, ALDADDD, ALDADDW, ALDADDH, ALDADDB: 3682 o1 |= 0x00 << 10 3683 case ALDANDD, ALDANDW, ALDANDH, ALDANDB: 3684 o1 |= 0x04 << 10 3685 case ALDEORD, ALDEORW, ALDEORH, ALDEORB: 3686 o1 |= 0x08 << 10 3687 case ALDORD, ALDORW, ALDORH, ALDORB: 3688 o1 |= 0x0c << 10 3689 } 3690 switch p.As { 3691 case ALDADDALD, ALDADDALW, ALDADDALH, ALDADDALB, ASWPALD, ASWPALW, ASWPALH, ASWPALB: 3692 o1 |= 3 << 22 3693 } 3694 o1 |= 0x1c1<<21 | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31) 3695 3696 case 48: /* ADD $C_ADDCON2, Rm, Rd */ 3697 op := c.opirr(p, p.As) 3698 if op&Sbit != 0 { 3699 c.ctxt.Diag("can not break addition/subtraction when S bit is set", p) 3700 } 3701 rt := int(p.To.Reg) 3702 r := int(p.Reg) 3703 if r == 0 { 3704 r = rt 3705 } 3706 o1 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0x000fff, r, rt) 3707 o2 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0xfff000, rt, rt) 3708 3709 case 50: /* sys/sysl */ 3710 o1 = c.opirr(p, p.As) 3711 3712 if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 { 3713 c.ctxt.Diag("illegal SYS argument\n%v", p) 3714 } 3715 o1 |= uint32(p.From.Offset) 3716 if p.To.Type == obj.TYPE_REG { 3717 o1 |= uint32(p.To.Reg & 31) 3718 } else if p.Reg != 0 { 3719 o1 |= uint32(p.Reg & 31) 3720 } else { 3721 o1 |= 0x1F 3722 } 3723 3724 case 51: /* dmb */ 3725 o1 = c.opirr(p, p.As) 3726 3727 if p.From.Type == obj.TYPE_CONST { 3728 o1 |= uint32((p.From.Offset & 0xF) << 8) 3729 } 3730 3731 case 52: /* hint */ 3732 o1 = c.opirr(p, p.As) 3733 3734 o1 |= uint32((p.From.Offset & 0x7F) << 5) 3735 3736 case 53: /* and/or/eor/bic/tst/... $bitcon, Rn, Rd */ 3737 a := p.As 3738 rt := int(p.To.Reg) 3739 if p.To.Type == obj.TYPE_NONE { 3740 rt = REGZERO 3741 } 3742 r := int(p.Reg) 3743 if r == 0 { 3744 r = rt 3745 } 3746 mode := 64 3747 v := uint64(p.From.Offset) 3748 switch p.As { 3749 case AANDW, AORRW, AEORW, AANDSW, ATSTW: 3750 mode = 32 3751 case ABIC, AORN, AEON, ABICS: 3752 v = ^v 3753 case ABICW, AORNW, AEONW, ABICSW: 3754 v = ^v 3755 mode = 32 3756 } 3757 o1 = c.opirr(p, a) 3758 o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31) 3759 3760 case 54: /* floating point arith */ 3761 o1 = c.oprrr(p, p.As) 3762 rf := int(p.From.Reg) 3763 rt := int(p.To.Reg) 3764 r := int(p.Reg) 3765 if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */ 3766 r = rf 3767 rf = 0 3768 } else if r == 0 { 3769 r = rt 3770 } 3771 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 3772 3773 case 55: /* floating-point constant */ 3774 var rf int 3775 o1 = 0xf<<25 | 1<<21 | 1<<12 3776 rf = c.chipfloat7(p.From.Val.(float64)) 3777 if rf < 0 { 3778 c.ctxt.Diag("invalid floating-point immediate\n%v", p) 3779 } 3780 if p.As == AFMOVD { 3781 o1 |= 1 << 22 3782 } 3783 o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31) 3784 3785 case 56: /* floating point compare */ 3786 o1 = c.oprrr(p, p.As) 3787 3788 var rf int 3789 if p.From.Type == obj.TYPE_FCONST { 3790 o1 |= 8 /* zero */ 3791 rf = 0 3792 } else { 3793 rf = int(p.From.Reg) 3794 } 3795 rt := int(p.Reg) 3796 o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5 3797 3798 case 57: /* floating point conditional compare */ 3799 o1 = c.oprrr(p, p.As) 3800 3801 cond := int(p.From.Reg) 3802 if cond < COND_EQ || cond > COND_NV { 3803 c.ctxt.Diag("invalid condition\n%v", p) 3804 } else { 3805 cond -= COND_EQ 3806 } 3807 3808 nzcv := int(p.To.Offset) 3809 if nzcv&^0xF != 0 { 3810 c.ctxt.Diag("implausible condition\n%v", p) 3811 } 3812 rf := int(p.Reg) 3813 if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 { 3814 c.ctxt.Diag("illegal FCCMP\n%v", p) 3815 break 3816 } 3817 rt := int(p.GetFrom3().Reg) 3818 o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv) 3819 3820 case 58: /* ldar/ldarb/ldarh/ldaxp/ldxp/ldaxr/ldxr */ 3821 o1 = c.opload(p, p.As) 3822 3823 o1 |= 0x1F << 16 3824 o1 |= uint32(p.From.Reg&31) << 5 3825 if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW { 3826 if int(p.To.Reg) == int(p.To.Offset) { 3827 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3828 } 3829 o1 |= uint32(p.To.Offset&31) << 10 3830 } else { 3831 o1 |= 0x1F << 10 3832 } 3833 o1 |= uint32(p.To.Reg & 31) 3834 3835 case 59: /* stxr/stlxr/stxp/stlxp */ 3836 s := p.RegTo2 3837 n := p.To.Reg 3838 t := p.From.Reg 3839 if isSTLXRop(p.As) { 3840 if s == t || (s == n && n != REGSP) { 3841 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3842 } 3843 } else if isSTXPop(p.As) { 3844 t2 := int16(p.From.Offset) 3845 if (s == t || s == t2) || (s == n && n != REGSP) { 3846 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3847 } 3848 } 3849 o1 = c.opstore(p, p.As) 3850 3851 if p.RegTo2 != obj.REG_NONE { 3852 o1 |= uint32(p.RegTo2&31) << 16 3853 } else { 3854 o1 |= 0x1F << 16 3855 } 3856 if isSTXPop(p.As) { 3857 o1 |= uint32(p.From.Offset&31) << 10 3858 } 3859 o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31) 3860 3861 case 60: /* adrp label,r */ 3862 d := c.brdist(p, 12, 21, 0) 3863 3864 o1 = ADR(1, uint32(d), uint32(p.To.Reg)) 3865 3866 case 61: /* adr label, r */ 3867 d := c.brdist(p, 0, 21, 0) 3868 3869 o1 = ADR(0, uint32(d), uint32(p.To.Reg)) 3870 3871 case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */ 3872 if p.Reg == REGTMP { 3873 c.ctxt.Diag("cannot use REGTMP as source: %v\n", p) 3874 } 3875 if isADDWop(p.As) || isANDWop(p.As) { 3876 o1 = c.omovconst(AMOVW, p, &p.From, REGTMP) 3877 } else { 3878 o1 = c.omovconst(AMOVD, p, &p.From, REGTMP) 3879 } 3880 3881 rt := int(p.To.Reg) 3882 if p.To.Type == obj.TYPE_NONE { 3883 rt = REGZERO 3884 } 3885 r := int(p.Reg) 3886 if r == 0 { 3887 r = rt 3888 } 3889 if p.To.Reg == REGSP || r == REGSP { 3890 o2 = c.opxrrr(p, p.As, false) 3891 o2 |= REGTMP & 31 << 16 3892 o2 |= LSL0_64 3893 } else { 3894 o2 = c.oprrr(p, p.As) 3895 o2 |= REGTMP & 31 << 16 /* shift is 0 */ 3896 } 3897 o2 |= uint32(r&31) << 5 3898 o2 |= uint32(rt & 31) 3899 3900 /* reloc ops */ 3901 case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */ 3902 o1 = ADR(1, 0, REGTMP) 3903 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 3904 rel := obj.Addrel(c.cursym) 3905 rel.Off = int32(c.pc) 3906 rel.Siz = 8 3907 rel.Sym = p.To.Sym 3908 rel.Add = p.To.Offset 3909 rel.Type = objabi.R_ADDRARM64 3910 o3 = c.olsr12u(p, int32(c.opstr12(p, p.As)), 0, REGTMP, int(p.From.Reg)) 3911 3912 case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */ 3913 o1 = ADR(1, 0, REGTMP) 3914 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 3915 rel := obj.Addrel(c.cursym) 3916 rel.Off = int32(c.pc) 3917 rel.Siz = 8 3918 rel.Sym = p.From.Sym 3919 rel.Add = p.From.Offset 3920 rel.Type = objabi.R_ADDRARM64 3921 o3 = c.olsr12u(p, int32(c.opldr12(p, p.As)), 0, REGTMP, int(p.To.Reg)) 3922 3923 case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */ 3924 v := int32(c.regoff(&p.From)) 3925 r := int(p.From.Reg) 3926 if r == obj.REG_NONE { 3927 r = int(o.param) 3928 } 3929 if r == obj.REG_NONE { 3930 c.ctxt.Diag("invalid ldp source: %v\n", p) 3931 } 3932 o1 |= c.opldpstp(p, o, v, uint32(r), uint32(p.To.Reg), uint32(p.To.Offset), 1) 3933 3934 case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */ 3935 r := int(p.To.Reg) 3936 if r == obj.REG_NONE { 3937 r = int(o.param) 3938 } 3939 if r == obj.REG_NONE { 3940 c.ctxt.Diag("invalid stp destination: %v\n", p) 3941 } 3942 v := int32(c.regoff(&p.To)) 3943 o1 = c.opldpstp(p, o, v, uint32(r), uint32(p.From.Reg), uint32(p.From.Offset), 0) 3944 3945 case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */ 3946 if p.As == AMOVW { 3947 c.ctxt.Diag("invalid load of 32-bit address: %v", p) 3948 } 3949 o1 = ADR(1, 0, uint32(p.To.Reg)) 3950 o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31) 3951 rel := obj.Addrel(c.cursym) 3952 rel.Off = int32(c.pc) 3953 rel.Siz = 8 3954 rel.Sym = p.From.Sym 3955 rel.Add = p.From.Offset 3956 rel.Type = objabi.R_ADDRARM64 3957 3958 case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */ 3959 o1 = c.opirr(p, AMOVZ) 3960 o1 |= uint32(p.To.Reg & 31) 3961 rel := obj.Addrel(c.cursym) 3962 rel.Off = int32(c.pc) 3963 rel.Siz = 4 3964 rel.Sym = p.From.Sym 3965 rel.Type = objabi.R_ARM64_TLS_LE 3966 if p.From.Offset != 0 { 3967 c.ctxt.Diag("invalid offset on MOVW $tlsvar") 3968 } 3969 3970 case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */ 3971 o1 = ADR(1, 0, REGTMP) 3972 o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg)) 3973 rel := obj.Addrel(c.cursym) 3974 rel.Off = int32(c.pc) 3975 rel.Siz = 8 3976 rel.Sym = p.From.Sym 3977 rel.Add = 0 3978 rel.Type = objabi.R_ARM64_TLS_IE 3979 if p.From.Offset != 0 { 3980 c.ctxt.Diag("invalid offset on MOVW $tlsvar") 3981 } 3982 3983 case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */ 3984 o1 = ADR(1, 0, REGTMP) 3985 o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg)) 3986 rel := obj.Addrel(c.cursym) 3987 rel.Off = int32(c.pc) 3988 rel.Siz = 8 3989 rel.Sym = p.From.Sym 3990 rel.Add = 0 3991 rel.Type = objabi.R_ARM64_GOTPCREL 3992 3993 case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor/vfmla/vfmls Vm.<T>, Vn.<T>, Vd.<T> */ 3994 af := int((p.From.Reg >> 5) & 15) 3995 af3 := int((p.Reg >> 5) & 15) 3996 at := int((p.To.Reg >> 5) & 15) 3997 if af != af3 || af != at { 3998 c.ctxt.Diag("operand mismatch: %v", p) 3999 break 4000 } 4001 o1 = c.oprrr(p, p.As) 4002 rf := int((p.From.Reg) & 31) 4003 rt := int((p.To.Reg) & 31) 4004 r := int((p.Reg) & 31) 4005 4006 Q := 0 4007 size := 0 4008 switch af { 4009 case ARNG_16B: 4010 Q = 1 4011 size = 0 4012 case ARNG_2D: 4013 Q = 1 4014 size = 3 4015 case ARNG_2S: 4016 Q = 0 4017 size = 2 4018 case ARNG_4H: 4019 Q = 0 4020 size = 1 4021 case ARNG_4S: 4022 Q = 1 4023 size = 2 4024 case ARNG_8B: 4025 Q = 0 4026 size = 0 4027 case ARNG_8H: 4028 Q = 1 4029 size = 1 4030 default: 4031 c.ctxt.Diag("invalid arrangement: %v", p) 4032 } 4033 4034 if (p.As == AVORR || p.As == AVAND || p.As == AVEOR) && 4035 (af != ARNG_16B && af != ARNG_8B) { 4036 c.ctxt.Diag("invalid arrangement: %v", p) 4037 } else if (p.As == AVFMLA || p.As == AVFMLS) && 4038 (af != ARNG_2D && af != ARNG_2S && af != ARNG_4S) { 4039 c.ctxt.Diag("invalid arrangement: %v", p) 4040 } else if p.As == AVORR { 4041 size = 2 4042 } else if p.As == AVAND || p.As == AVEOR { 4043 size = 0 4044 } else if p.As == AVFMLA || p.As == AVFMLS { 4045 if af == ARNG_2D { 4046 size = 1 4047 } else { 4048 size = 0 4049 } 4050 } 4051 4052 o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 4053 4054 case 73: /* vmov V.<T>[index], R */ 4055 rf := int(p.From.Reg) 4056 rt := int(p.To.Reg) 4057 imm5 := 0 4058 o1 = 7<<25 | 0xf<<10 4059 index := int(p.From.Index) 4060 switch (p.From.Reg >> 5) & 15 { 4061 case ARNG_B: 4062 c.checkindex(p, index, 15) 4063 imm5 |= 1 4064 imm5 |= index << 1 4065 case ARNG_H: 4066 c.checkindex(p, index, 7) 4067 imm5 |= 2 4068 imm5 |= index << 2 4069 case ARNG_S: 4070 c.checkindex(p, index, 3) 4071 imm5 |= 4 4072 imm5 |= index << 3 4073 case ARNG_D: 4074 c.checkindex(p, index, 1) 4075 imm5 |= 8 4076 imm5 |= index << 4 4077 o1 |= 1 << 30 4078 default: 4079 c.ctxt.Diag("invalid arrangement: %v", p) 4080 } 4081 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 4082 4083 case 74: 4084 // add $O, R, Rtmp or sub $O, R, Rtmp 4085 // ldp (Rtmp), (R1, R2) 4086 r := int(p.From.Reg) 4087 if r == obj.REG_NONE { 4088 r = int(o.param) 4089 } 4090 if r == obj.REG_NONE { 4091 c.ctxt.Diag("invalid ldp source: %v", p) 4092 } 4093 v := int32(c.regoff(&p.From)) 4094 4095 if v > 0 { 4096 if v > 4095 { 4097 c.ctxt.Diag("offset out of range: %v", p) 4098 } 4099 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP) 4100 } 4101 if v < 0 { 4102 if v < -4095 { 4103 c.ctxt.Diag("offset out of range: %v", p) 4104 } 4105 o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP) 4106 } 4107 o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1) 4108 4109 case 75: 4110 // mov $L, Rtmp (from constant pool) 4111 // add Rtmp, R, Rtmp 4112 // ldp (Rtmp), (R1, R2) 4113 r := int(p.From.Reg) 4114 if r == obj.REG_NONE { 4115 r = int(o.param) 4116 } 4117 if r == obj.REG_NONE { 4118 c.ctxt.Diag("invalid ldp source: %v", p) 4119 } 4120 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 4121 o2 = c.opxrrr(p, AADD, false) 4122 o2 |= (REGTMP & 31) << 16 4123 o2 |= uint32(r&31) << 5 4124 o2 |= uint32(REGTMP & 31) 4125 o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1) 4126 4127 case 76: 4128 // add $O, R, Rtmp or sub $O, R, Rtmp 4129 // stp (R1, R2), (Rtmp) 4130 r := int(p.To.Reg) 4131 if r == obj.REG_NONE { 4132 r = int(o.param) 4133 } 4134 if r == obj.REG_NONE { 4135 c.ctxt.Diag("invalid stp destination: %v", p) 4136 } 4137 v := int32(c.regoff(&p.To)) 4138 if v > 0 { 4139 if v > 4095 { 4140 c.ctxt.Diag("offset out of range: %v", p) 4141 } 4142 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP) 4143 } 4144 if v < 0 { 4145 if v < -4095 { 4146 c.ctxt.Diag("offset out of range: %v", p) 4147 } 4148 o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP) 4149 } 4150 o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0) 4151 4152 case 77: 4153 // mov $L, Rtmp (from constant pool) 4154 // add Rtmp, R, Rtmp 4155 // stp (R1, R2), (Rtmp) 4156 r := int(p.To.Reg) 4157 if r == obj.REG_NONE { 4158 r = int(o.param) 4159 } 4160 if r == obj.REG_NONE { 4161 c.ctxt.Diag("invalid stp destination: %v", p) 4162 } 4163 o1 = c.omovlit(AMOVD, p, &p.To, REGTMP) 4164 o2 = c.opxrrr(p, AADD, false) 4165 o2 |= REGTMP & 31 << 16 4166 o2 |= uint32(r&31) << 5 4167 o2 |= uint32(REGTMP & 31) 4168 o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0) 4169 4170 case 78: /* vmov R, V.<T>[index] */ 4171 rf := int(p.From.Reg) 4172 rt := int(p.To.Reg) 4173 imm5 := 0 4174 o1 = 1<<30 | 7<<25 | 7<<10 4175 index := int(p.To.Index) 4176 switch (p.To.Reg >> 5) & 15 { 4177 case ARNG_B: 4178 c.checkindex(p, index, 15) 4179 imm5 |= 1 4180 imm5 |= index << 1 4181 case ARNG_H: 4182 c.checkindex(p, index, 7) 4183 imm5 |= 2 4184 imm5 |= index << 2 4185 case ARNG_S: 4186 c.checkindex(p, index, 3) 4187 imm5 |= 4 4188 imm5 |= index << 3 4189 case ARNG_D: 4190 c.checkindex(p, index, 1) 4191 imm5 |= 8 4192 imm5 |= index << 4 4193 default: 4194 c.ctxt.Diag("invalid arrangement: %v", p) 4195 } 4196 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 4197 4198 case 79: /* vdup Vn.<T>[index], Vd.<T> */ 4199 rf := int(p.From.Reg) 4200 rt := int(p.To.Reg) 4201 o1 = 7<<25 | 1<<10 4202 var imm5, Q int 4203 index := int(p.From.Index) 4204 switch (p.To.Reg >> 5) & 15 { 4205 case ARNG_16B: 4206 c.checkindex(p, index, 15) 4207 Q = 1 4208 imm5 = 1 4209 imm5 |= index << 1 4210 case ARNG_2D: 4211 c.checkindex(p, index, 1) 4212 Q = 1 4213 imm5 = 8 4214 imm5 |= index << 4 4215 case ARNG_2S: 4216 c.checkindex(p, index, 3) 4217 Q = 0 4218 imm5 = 4 4219 imm5 |= index << 3 4220 case ARNG_4H: 4221 c.checkindex(p, index, 7) 4222 Q = 0 4223 imm5 = 2 4224 imm5 |= index << 2 4225 case ARNG_4S: 4226 c.checkindex(p, index, 3) 4227 Q = 1 4228 imm5 = 4 4229 imm5 |= index << 3 4230 case ARNG_8B: 4231 c.checkindex(p, index, 15) 4232 Q = 0 4233 imm5 = 1 4234 imm5 |= index << 1 4235 case ARNG_8H: 4236 c.checkindex(p, index, 7) 4237 Q = 1 4238 imm5 = 2 4239 imm5 |= index << 2 4240 default: 4241 c.ctxt.Diag("invalid arrangement: %v", p) 4242 } 4243 o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16) 4244 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 4245 4246 case 80: /* vmov V.<T>[index], Vn */ 4247 rf := int(p.From.Reg) 4248 rt := int(p.To.Reg) 4249 imm5 := 0 4250 index := int(p.From.Index) 4251 switch p.As { 4252 case AVMOV: 4253 o1 = 1<<30 | 15<<25 | 1<<10 4254 switch (p.From.Reg >> 5) & 15 { 4255 case ARNG_B: 4256 c.checkindex(p, index, 15) 4257 imm5 |= 1 4258 imm5 |= index << 1 4259 case ARNG_H: 4260 c.checkindex(p, index, 7) 4261 imm5 |= 2 4262 imm5 |= index << 2 4263 case ARNG_S: 4264 c.checkindex(p, index, 3) 4265 imm5 |= 4 4266 imm5 |= index << 3 4267 case ARNG_D: 4268 c.checkindex(p, index, 1) 4269 imm5 |= 8 4270 imm5 |= index << 4 4271 default: 4272 c.ctxt.Diag("invalid arrangement: %v", p) 4273 } 4274 default: 4275 c.ctxt.Diag("unsupported op %v", p.As) 4276 } 4277 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 4278 4279 case 81: /* vld1 (Rn), [Vt1.<T>, Vt2.<T>, ...] */ 4280 r := int(p.From.Reg) 4281 o1 = 3<<26 | 1<<22 4282 if o.scond == C_XPOST { 4283 o1 |= 1 << 23 4284 if p.From.Index == 0 { 4285 // immediate offset variant 4286 c.checkoffset(p, p.As) 4287 o1 |= 0x1f << 16 4288 } else { 4289 // register offset variant 4290 if isRegShiftOrExt(&p.From) { 4291 c.ctxt.Diag("invalid extended register op: %v\n", p) 4292 } 4293 o1 |= uint32(p.From.Index&31) << 16 4294 } 4295 } 4296 o1 |= uint32(p.To.Offset) 4297 o1 |= uint32(r&31) << 5 4298 4299 case 82: /* vmov Rn, Vd.<T> */ 4300 rf := int(p.From.Reg) 4301 rt := int(p.To.Reg) 4302 o1 = 7<<25 | 3<<10 4303 var imm5, Q uint32 4304 switch (p.To.Reg >> 5) & 15 { 4305 case ARNG_16B: 4306 Q = 1 4307 imm5 = 1 4308 case ARNG_2D: 4309 Q = 1 4310 imm5 = 8 4311 case ARNG_2S: 4312 Q = 0 4313 imm5 = 4 4314 case ARNG_4H: 4315 Q = 0 4316 imm5 = 2 4317 case ARNG_4S: 4318 Q = 1 4319 imm5 = 4 4320 case ARNG_8B: 4321 Q = 0 4322 imm5 = 1 4323 case ARNG_8H: 4324 Q = 1 4325 imm5 = 2 4326 default: 4327 c.ctxt.Diag("invalid arrangement on VMOV Rn, Vd.<T>: %v\n", p) 4328 } 4329 o1 |= (Q & 1 << 30) | (imm5 & 0x1f << 16) 4330 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 4331 4332 case 83: /* vmov Vn.<T>, Vd.<T> */ 4333 af := int((p.From.Reg >> 5) & 15) 4334 at := int((p.To.Reg >> 5) & 15) 4335 if af != at { 4336 c.ctxt.Diag("invalid arrangement: %v\n", p) 4337 } 4338 o1 = c.oprrr(p, p.As) 4339 rf := int((p.From.Reg) & 31) 4340 rt := int((p.To.Reg) & 31) 4341 4342 var Q, size uint32 4343 switch af { 4344 case ARNG_8B: 4345 Q = 0 4346 size = 0 4347 case ARNG_16B: 4348 Q = 1 4349 size = 0 4350 case ARNG_4H: 4351 Q = 0 4352 size = 1 4353 case ARNG_8H: 4354 Q = 1 4355 size = 1 4356 case ARNG_2S: 4357 Q = 0 4358 size = 2 4359 case ARNG_4S: 4360 Q = 1 4361 size = 2 4362 default: 4363 c.ctxt.Diag("invalid arrangement: %v\n", p) 4364 } 4365 4366 if (p.As == AVMOV || p.As == AVRBIT) && (af != ARNG_16B && af != ARNG_8B) { 4367 c.ctxt.Diag("invalid arrangement: %v", p) 4368 } 4369 4370 if p.As == AVREV32 && (af == ARNG_2S || af == ARNG_4S) { 4371 c.ctxt.Diag("invalid arrangement: %v", p) 4372 } 4373 4374 if p.As == AVMOV { 4375 o1 |= uint32(rf&31) << 16 4376 } 4377 4378 if p.As == AVRBIT { 4379 size = 1 4380 } 4381 4382 o1 |= (Q&1)<<30 | (size&3)<<22 | uint32(rf&31)<<5 | uint32(rt&31) 4383 4384 case 84: /* vst1 [Vt1.<T>, Vt2.<T>, ...], (Rn) */ 4385 r := int(p.To.Reg) 4386 o1 = 3 << 26 4387 if o.scond == C_XPOST { 4388 o1 |= 1 << 23 4389 if p.To.Index == 0 { 4390 // immediate offset variant 4391 c.checkoffset(p, p.As) 4392 o1 |= 0x1f << 16 4393 } else { 4394 // register offset variant 4395 if isRegShiftOrExt(&p.To) { 4396 c.ctxt.Diag("invalid extended register: %v\n", p) 4397 } 4398 o1 |= uint32(p.To.Index&31) << 16 4399 } 4400 } 4401 o1 |= uint32(p.From.Offset) 4402 o1 |= uint32(r&31) << 5 4403 4404 case 85: /* vaddv/vuaddlv Vn.<T>, Vd*/ 4405 af := int((p.From.Reg >> 5) & 15) 4406 o1 = c.oprrr(p, p.As) 4407 rf := int((p.From.Reg) & 31) 4408 rt := int((p.To.Reg) & 31) 4409 Q := 0 4410 size := 0 4411 switch af { 4412 case ARNG_8B: 4413 Q = 0 4414 size = 0 4415 case ARNG_16B: 4416 Q = 1 4417 size = 0 4418 case ARNG_4H: 4419 Q = 0 4420 size = 1 4421 case ARNG_8H: 4422 Q = 1 4423 size = 1 4424 case ARNG_4S: 4425 Q = 1 4426 size = 2 4427 default: 4428 c.ctxt.Diag("invalid arrangement: %v\n", p) 4429 } 4430 o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31) 4431 4432 case 86: /* vmovi $imm8, Vd.<T>*/ 4433 at := int((p.To.Reg >> 5) & 15) 4434 r := int(p.From.Offset) 4435 if r > 255 || r < 0 { 4436 c.ctxt.Diag("immediate constant out of range: %v\n", p) 4437 } 4438 rt := int((p.To.Reg) & 31) 4439 Q := 0 4440 switch at { 4441 case ARNG_8B: 4442 Q = 0 4443 case ARNG_16B: 4444 Q = 1 4445 default: 4446 c.ctxt.Diag("invalid arrangement: %v\n", p) 4447 } 4448 o1 = 0xf<<24 | 0xe<<12 | 1<<10 4449 o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31) 4450 4451 case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */ 4452 o1 = ADR(1, 0, REGTMP) 4453 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 4454 rel := obj.Addrel(c.cursym) 4455 rel.Off = int32(c.pc) 4456 rel.Siz = 8 4457 rel.Sym = p.To.Sym 4458 rel.Add = p.To.Offset 4459 rel.Type = objabi.R_ADDRARM64 4460 o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0) 4461 4462 case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */ 4463 o1 = ADR(1, 0, REGTMP) 4464 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 4465 rel := obj.Addrel(c.cursym) 4466 rel.Off = int32(c.pc) 4467 rel.Siz = 8 4468 rel.Sym = p.From.Sym 4469 rel.Add = p.From.Offset 4470 rel.Type = objabi.R_ADDRARM64 4471 o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1) 4472 4473 case 89: /* vadd/vsub Vm, Vn, Vd */ 4474 switch p.As { 4475 case AVADD: 4476 o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10 4477 4478 case AVSUB: 4479 o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10 4480 4481 default: 4482 c.ctxt.Diag("bad opcode: %v\n", p) 4483 break 4484 } 4485 4486 rf := int(p.From.Reg) 4487 rt := int(p.To.Reg) 4488 r := int(p.Reg) 4489 if r == 0 { 4490 r = rt 4491 } 4492 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 4493 4494 // This is supposed to be something that stops execution. 4495 // It's not supposed to be reached, ever, but if it is, we'd 4496 // like to be able to tell how we got there. Assemble as 4497 // 0xbea71700 which is guaranteed to raise undefined instruction 4498 // exception. 4499 case 90: 4500 o1 = 0xbea71700 4501 4502 case 91: /* prfm imm(Rn), <prfop | $imm5> */ 4503 imm := uint32(p.From.Offset) 4504 r := p.From.Reg 4505 v := uint32(0xff) 4506 if p.To.Type == obj.TYPE_CONST { 4507 v = uint32(p.To.Offset) 4508 if v > 31 { 4509 c.ctxt.Diag("illegal prefetch operation\n%v", p) 4510 } 4511 } else { 4512 for i := 0; i < len(prfopfield); i++ { 4513 if prfopfield[i].reg == p.To.Reg { 4514 v = prfopfield[i].enc 4515 break 4516 } 4517 } 4518 if v == 0xff { 4519 c.ctxt.Diag("illegal prefetch operation:\n%v", p) 4520 } 4521 } 4522 4523 o1 = c.opldrpp(p, p.As) 4524 o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31)) 4525 4526 case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */ 4527 rf := int(p.From.Reg) 4528 rt := int(p.To.Reg) 4529 imm4 := 0 4530 imm5 := 0 4531 o1 = 3<<29 | 7<<25 | 1<<10 4532 index1 := int(p.To.Index) 4533 index2 := int(p.From.Index) 4534 if ((p.To.Reg >> 5) & 15) != ((p.From.Reg >> 5) & 15) { 4535 c.ctxt.Diag("operand mismatch: %v", p) 4536 } 4537 switch (p.To.Reg >> 5) & 15 { 4538 case ARNG_B: 4539 c.checkindex(p, index1, 15) 4540 c.checkindex(p, index2, 15) 4541 imm5 |= 1 4542 imm5 |= index1 << 1 4543 imm4 |= index2 4544 case ARNG_H: 4545 c.checkindex(p, index1, 7) 4546 c.checkindex(p, index2, 7) 4547 imm5 |= 2 4548 imm5 |= index1 << 2 4549 imm4 |= index2 << 1 4550 case ARNG_S: 4551 c.checkindex(p, index1, 3) 4552 c.checkindex(p, index2, 3) 4553 imm5 |= 4 4554 imm5 |= index1 << 3 4555 imm4 |= index2 << 2 4556 case ARNG_D: 4557 c.checkindex(p, index1, 1) 4558 c.checkindex(p, index2, 1) 4559 imm5 |= 8 4560 imm5 |= index1 << 4 4561 imm4 |= index2 << 3 4562 default: 4563 c.ctxt.Diag("invalid arrangement: %v", p) 4564 } 4565 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(imm4&0xf) << 11) | (uint32(rf&31) << 5) | uint32(rt&31) 4566 4567 case 93: /* vpmull{2} Vm.<T>, Vn.<T>, Vd */ 4568 af := int((p.From.Reg >> 5) & 15) 4569 at := int((p.To.Reg >> 5) & 15) 4570 a := int((p.Reg >> 5) & 15) 4571 4572 var Q, size uint32 4573 if p.As == AVPMULL { 4574 Q = 0 4575 } else { 4576 Q = 1 4577 } 4578 4579 var fArng int 4580 switch at { 4581 case ARNG_8H: 4582 if Q == 0 { 4583 fArng = ARNG_8B 4584 } else { 4585 fArng = ARNG_16B 4586 } 4587 size = 0 4588 case ARNG_1Q: 4589 if Q == 0 { 4590 fArng = ARNG_1D 4591 } else { 4592 fArng = ARNG_2D 4593 } 4594 size = 3 4595 default: 4596 c.ctxt.Diag("invalid arrangement on Vd.<T>: %v", p) 4597 } 4598 4599 if af != a || af != fArng { 4600 c.ctxt.Diag("invalid arrangement: %v", p) 4601 } 4602 4603 o1 = c.oprrr(p, p.As) 4604 rf := int((p.From.Reg) & 31) 4605 rt := int((p.To.Reg) & 31) 4606 r := int((p.Reg) & 31) 4607 4608 o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 4609 4610 case 94: /* vext $imm4, Vm.<T>, Vn.<T>, Vd.<T> */ 4611 af := int(((p.GetFrom3().Reg) >> 5) & 15) 4612 at := int((p.To.Reg >> 5) & 15) 4613 a := int((p.Reg >> 5) & 15) 4614 index := int(p.From.Offset) 4615 4616 if af != a || af != at { 4617 c.ctxt.Diag("invalid arrangement: %v", p) 4618 break 4619 } 4620 4621 var Q uint32 4622 var b int 4623 if af == ARNG_8B { 4624 Q = 0 4625 b = 7 4626 } else if af == ARNG_16B { 4627 Q = 1 4628 b = 15 4629 } else { 4630 c.ctxt.Diag("invalid arrangement, should be 8B or 16B: %v", p) 4631 break 4632 } 4633 4634 if index < 0 || index > b { 4635 c.ctxt.Diag("illegal offset: %v", p) 4636 } 4637 4638 o1 = c.opirr(p, p.As) 4639 rf := int((p.GetFrom3().Reg) & 31) 4640 rt := int((p.To.Reg) & 31) 4641 r := int((p.Reg) & 31) 4642 4643 o1 |= ((Q & 1) << 30) | (uint32(r&31) << 16) | (uint32(index&15) << 11) | (uint32(rf&31) << 5) | uint32(rt&31) 4644 4645 case 95: /* vushr $shift, Vn.<T>, Vd.<T> */ 4646 at := int((p.To.Reg >> 5) & 15) 4647 af := int((p.Reg >> 5) & 15) 4648 shift := int(p.From.Offset) 4649 4650 if af != at { 4651 c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p) 4652 } 4653 4654 var Q uint32 4655 var imax, esize int 4656 4657 switch af { 4658 case ARNG_8B, ARNG_4H, ARNG_2S: 4659 Q = 0 4660 case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D: 4661 Q = 1 4662 default: 4663 c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p) 4664 } 4665 4666 switch af { 4667 case ARNG_8B, ARNG_16B: 4668 imax = 15 4669 esize = 8 4670 case ARNG_4H, ARNG_8H: 4671 imax = 31 4672 esize = 16 4673 case ARNG_2S, ARNG_4S: 4674 imax = 63 4675 esize = 32 4676 case ARNG_2D: 4677 imax = 127 4678 esize = 64 4679 } 4680 4681 imm := 0 4682 4683 switch p.As { 4684 case AVUSHR, AVSRI: 4685 imm = esize*2 - shift 4686 if imm < esize || imm > imax { 4687 c.ctxt.Diag("shift out of range: %v", p) 4688 } 4689 case AVSHL: 4690 imm = esize + shift 4691 if imm > imax { 4692 c.ctxt.Diag("shift out of range: %v", p) 4693 } 4694 default: 4695 c.ctxt.Diag("invalid instruction %v\n", p) 4696 } 4697 4698 o1 = c.opirr(p, p.As) 4699 rt := int((p.To.Reg) & 31) 4700 rf := int((p.Reg) & 31) 4701 4702 o1 |= ((Q & 1) << 30) | (uint32(imm&127) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 4703 4704 case 96: /* vst1 Vt1.<T>[index], offset(Rn) */ 4705 af := int((p.From.Reg >> 5) & 15) 4706 rt := int((p.From.Reg) & 31) 4707 rf := int((p.To.Reg) & 31) 4708 r := int(p.To.Index & 31) 4709 index := int(p.From.Index) 4710 offset := int32(c.regoff(&p.To)) 4711 4712 if o.scond == C_XPOST { 4713 if (p.To.Index != 0) && (offset != 0) { 4714 c.ctxt.Diag("invalid offset: %v", p) 4715 } 4716 if p.To.Index == 0 && offset == 0 { 4717 c.ctxt.Diag("invalid offset: %v", p) 4718 } 4719 } 4720 4721 if offset != 0 { 4722 r = 31 4723 } 4724 4725 var Q, S, size int 4726 var opcode uint32 4727 switch af { 4728 case ARNG_B: 4729 c.checkindex(p, index, 15) 4730 if o.scond == C_XPOST && offset != 0 && offset != 1 { 4731 c.ctxt.Diag("invalid offset: %v", p) 4732 } 4733 Q = index >> 3 4734 S = (index >> 2) & 1 4735 size = index & 3 4736 opcode = 0 4737 case ARNG_H: 4738 c.checkindex(p, index, 7) 4739 if o.scond == C_XPOST && offset != 0 && offset != 2 { 4740 c.ctxt.Diag("invalid offset: %v", p) 4741 } 4742 Q = index >> 2 4743 S = (index >> 1) & 1 4744 size = (index & 1) << 1 4745 opcode = 2 4746 case ARNG_S: 4747 c.checkindex(p, index, 3) 4748 if o.scond == C_XPOST && offset != 0 && offset != 4 { 4749 c.ctxt.Diag("invalid offset: %v", p) 4750 } 4751 Q = index >> 1 4752 S = index & 1 4753 size = 0 4754 opcode = 4 4755 case ARNG_D: 4756 c.checkindex(p, index, 1) 4757 if o.scond == C_XPOST && offset != 0 && offset != 8 { 4758 c.ctxt.Diag("invalid offset: %v", p) 4759 } 4760 Q = index 4761 S = 0 4762 size = 1 4763 opcode = 4 4764 default: 4765 c.ctxt.Diag("invalid arrangement: %v", p) 4766 } 4767 4768 if o.scond == C_XPOST { 4769 o1 |= 27 << 23 4770 } else { 4771 o1 |= 26 << 23 4772 } 4773 4774 o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31) 4775 4776 case 97: /* vld1 offset(Rn), vt.<T>[index] */ 4777 at := int((p.To.Reg >> 5) & 15) 4778 rt := int((p.To.Reg) & 31) 4779 rf := int((p.From.Reg) & 31) 4780 r := int(p.From.Index & 31) 4781 index := int(p.To.Index) 4782 offset := int32(c.regoff(&p.From)) 4783 4784 if o.scond == C_XPOST { 4785 if (p.From.Index != 0) && (offset != 0) { 4786 c.ctxt.Diag("invalid offset: %v", p) 4787 } 4788 if p.From.Index == 0 && offset == 0 { 4789 c.ctxt.Diag("invalid offset: %v", p) 4790 } 4791 } 4792 4793 if offset != 0 { 4794 r = 31 4795 } 4796 4797 Q := 0 4798 S := 0 4799 size := 0 4800 var opcode uint32 4801 switch at { 4802 case ARNG_B: 4803 c.checkindex(p, index, 15) 4804 if o.scond == C_XPOST && offset != 0 && offset != 1 { 4805 c.ctxt.Diag("invalid offset: %v", p) 4806 } 4807 Q = index >> 3 4808 S = (index >> 2) & 1 4809 size = index & 3 4810 opcode = 0 4811 case ARNG_H: 4812 c.checkindex(p, index, 7) 4813 if o.scond == C_XPOST && offset != 0 && offset != 2 { 4814 c.ctxt.Diag("invalid offset: %v", p) 4815 } 4816 Q = index >> 2 4817 S = (index >> 1) & 1 4818 size = (index & 1) << 1 4819 opcode = 2 4820 case ARNG_S: 4821 c.checkindex(p, index, 3) 4822 if o.scond == C_XPOST && offset != 0 && offset != 4 { 4823 c.ctxt.Diag("invalid offset: %v", p) 4824 } 4825 Q = index >> 1 4826 S = index & 1 4827 size = 0 4828 opcode = 4 4829 case ARNG_D: 4830 c.checkindex(p, index, 1) 4831 if o.scond == C_XPOST && offset != 0 && offset != 8 { 4832 c.ctxt.Diag("invalid offset: %v", p) 4833 } 4834 Q = index 4835 S = 0 4836 size = 1 4837 opcode = 4 4838 default: 4839 c.ctxt.Diag("invalid arrangement: %v", p) 4840 } 4841 4842 if o.scond == C_XPOST { 4843 o1 |= 110 << 21 4844 } else { 4845 o1 |= 106 << 21 4846 } 4847 4848 o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31) 4849 4850 case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */ 4851 if isRegShiftOrExt(&p.From) { 4852 // extended or shifted offset register. 4853 c.checkShiftAmount(p, &p.From) 4854 4855 o1 = c.opldrr(p, p.As, true) 4856 o1 |= c.encRegShiftOrExt(&p.From, p.From.Index) /* includes reg, op, etc */ 4857 } else { 4858 // (Rn)(Rm), no extension or shift. 4859 o1 = c.opldrr(p, p.As, false) 4860 o1 |= uint32(p.From.Index&31) << 16 4861 } 4862 o1 |= uint32(p.From.Reg&31) << 5 4863 rt := int(p.To.Reg) 4864 o1 |= uint32(rt & 31) 4865 4866 case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */ 4867 if isRegShiftOrExt(&p.To) { 4868 // extended or shifted offset register. 4869 c.checkShiftAmount(p, &p.To) 4870 4871 o1 = c.opstrr(p, p.As, true) 4872 o1 |= c.encRegShiftOrExt(&p.To, p.To.Index) /* includes reg, op, etc */ 4873 } else { 4874 // (Rn)(Rm), no extension or shift. 4875 o1 = c.opstrr(p, p.As, false) 4876 o1 |= uint32(p.To.Index&31) << 16 4877 } 4878 o1 |= uint32(p.To.Reg&31) << 5 4879 rf := int(p.From.Reg) 4880 o1 |= uint32(rf & 31) 4881 4882 case 100: /* VTBL Vn.<T>, [Vt1.<T>, Vt2.<T>, ...], Vd.<T> */ 4883 af := int((p.From.Reg >> 5) & 15) 4884 at := int((p.To.Reg >> 5) & 15) 4885 if af != at { 4886 c.ctxt.Diag("invalid arrangement: %v\n", p) 4887 } 4888 var q, len uint32 4889 switch af { 4890 case ARNG_8B: 4891 q = 0 4892 case ARNG_16B: 4893 q = 1 4894 default: 4895 c.ctxt.Diag("invalid arrangement: %v", p) 4896 } 4897 rf := int(p.From.Reg) 4898 rt := int(p.To.Reg) 4899 offset := int(p.GetFrom3().Offset) 4900 opcode := (offset >> 12) & 15 4901 switch opcode { 4902 case 0x7: 4903 len = 0 // one register 4904 case 0xa: 4905 len = 1 // two register 4906 case 0x6: 4907 len = 2 // three registers 4908 case 0x2: 4909 len = 3 // four registers 4910 default: 4911 c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p) 4912 } 4913 o1 = q<<30 | 0xe<<24 | len<<13 4914 o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31) 4915 4916 } 4917 out[0] = o1 4918 out[1] = o2 4919 out[2] = o3 4920 out[3] = o4 4921 out[4] = o5 4922 } 4923 4924 /* 4925 * basic Rm op Rn -> Rd (using shifted register with 0) 4926 * also op Rn -> Rt 4927 * also Rm*Rn op Ra -> Rd 4928 * also Vm op Vn -> Vd 4929 */ 4930 func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 { 4931 switch a { 4932 case AADC: 4933 return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 4934 4935 case AADCW: 4936 return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 4937 4938 case AADCS: 4939 return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 4940 4941 case AADCSW: 4942 return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 4943 4944 case ANGC, ASBC: 4945 return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 4946 4947 case ANGCS, ASBCS: 4948 return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 4949 4950 case ANGCW, ASBCW: 4951 return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 4952 4953 case ANGCSW, ASBCSW: 4954 return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 4955 4956 case AADD: 4957 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4958 4959 case AADDW: 4960 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4961 4962 case ACMN, AADDS: 4963 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4964 4965 case ACMNW, AADDSW: 4966 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4967 4968 case ASUB: 4969 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4970 4971 case ASUBW: 4972 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4973 4974 case ACMP, ASUBS: 4975 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4976 4977 case ACMPW, ASUBSW: 4978 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4979 4980 case AAND: 4981 return S64 | 0<<29 | 0xA<<24 4982 4983 case AANDW: 4984 return S32 | 0<<29 | 0xA<<24 4985 4986 case AMOVD, AORR: 4987 return S64 | 1<<29 | 0xA<<24 4988 4989 // case AMOVW: 4990 case AMOVWU, AORRW: 4991 return S32 | 1<<29 | 0xA<<24 4992 4993 case AEOR: 4994 return S64 | 2<<29 | 0xA<<24 4995 4996 case AEORW: 4997 return S32 | 2<<29 | 0xA<<24 4998 4999 case AANDS, ATST: 5000 return S64 | 3<<29 | 0xA<<24 5001 5002 case AANDSW, ATSTW: 5003 return S32 | 3<<29 | 0xA<<24 5004 5005 case ABIC: 5006 return S64 | 0<<29 | 0xA<<24 | 1<<21 5007 5008 case ABICW: 5009 return S32 | 0<<29 | 0xA<<24 | 1<<21 5010 5011 case ABICS: 5012 return S64 | 3<<29 | 0xA<<24 | 1<<21 5013 5014 case ABICSW: 5015 return S32 | 3<<29 | 0xA<<24 | 1<<21 5016 5017 case AEON: 5018 return S64 | 2<<29 | 0xA<<24 | 1<<21 5019 5020 case AEONW: 5021 return S32 | 2<<29 | 0xA<<24 | 1<<21 5022 5023 case AMVN, AORN: 5024 return S64 | 1<<29 | 0xA<<24 | 1<<21 5025 5026 case AMVNW, AORNW: 5027 return S32 | 1<<29 | 0xA<<24 | 1<<21 5028 5029 case AASR: 5030 return S64 | OPDP2(10) /* also ASRV */ 5031 5032 case AASRW: 5033 return S32 | OPDP2(10) 5034 5035 case ALSL: 5036 return S64 | OPDP2(8) 5037 5038 case ALSLW: 5039 return S32 | OPDP2(8) 5040 5041 case ALSR: 5042 return S64 | OPDP2(9) 5043 5044 case ALSRW: 5045 return S32 | OPDP2(9) 5046 5047 case AROR: 5048 return S64 | OPDP2(11) 5049 5050 case ARORW: 5051 return S32 | OPDP2(11) 5052 5053 case ACCMN: 5054 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */ 5055 5056 case ACCMNW: 5057 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 5058 5059 case ACCMP: 5060 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 5061 5062 case ACCMPW: 5063 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 5064 5065 case ACRC32B: 5066 return S32 | OPDP2(16) 5067 5068 case ACRC32H: 5069 return S32 | OPDP2(17) 5070 5071 case ACRC32W: 5072 return S32 | OPDP2(18) 5073 5074 case ACRC32X: 5075 return S64 | OPDP2(19) 5076 5077 case ACRC32CB: 5078 return S32 | OPDP2(20) 5079 5080 case ACRC32CH: 5081 return S32 | OPDP2(21) 5082 5083 case ACRC32CW: 5084 return S32 | OPDP2(22) 5085 5086 case ACRC32CX: 5087 return S64 | OPDP2(23) 5088 5089 case ACSEL: 5090 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 5091 5092 case ACSELW: 5093 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 5094 5095 case ACSET: 5096 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 5097 5098 case ACSETW: 5099 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 5100 5101 case ACSETM: 5102 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 5103 5104 case ACSETMW: 5105 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 5106 5107 case ACINC, ACSINC: 5108 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 5109 5110 case ACINCW, ACSINCW: 5111 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 5112 5113 case ACINV, ACSINV: 5114 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 5115 5116 case ACINVW, ACSINVW: 5117 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 5118 5119 case ACNEG, ACSNEG: 5120 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 5121 5122 case ACNEGW, ACSNEGW: 5123 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 5124 5125 case AMUL, AMADD: 5126 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 5127 5128 case AMULW, AMADDW: 5129 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 5130 5131 case AMNEG, AMSUB: 5132 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 5133 5134 case AMNEGW, AMSUBW: 5135 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 5136 5137 case AMRS: 5138 return SYSOP(1, 2, 0, 0, 0, 0, 0) 5139 5140 case AMSR: 5141 return SYSOP(0, 2, 0, 0, 0, 0, 0) 5142 5143 case ANEG: 5144 return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 5145 5146 case ANEGW: 5147 return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 5148 5149 case ANEGS: 5150 return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 5151 5152 case ANEGSW: 5153 return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 5154 5155 case AREM, ASDIV: 5156 return S64 | OPDP2(3) 5157 5158 case AREMW, ASDIVW: 5159 return S32 | OPDP2(3) 5160 5161 case ASMULL, ASMADDL: 5162 return OPDP3(1, 0, 1, 0) 5163 5164 case ASMNEGL, ASMSUBL: 5165 return OPDP3(1, 0, 1, 1) 5166 5167 case ASMULH: 5168 return OPDP3(1, 0, 2, 0) 5169 5170 case AUMULL, AUMADDL: 5171 return OPDP3(1, 0, 5, 0) 5172 5173 case AUMNEGL, AUMSUBL: 5174 return OPDP3(1, 0, 5, 1) 5175 5176 case AUMULH: 5177 return OPDP3(1, 0, 6, 0) 5178 5179 case AUREM, AUDIV: 5180 return S64 | OPDP2(2) 5181 5182 case AUREMW, AUDIVW: 5183 return S32 | OPDP2(2) 5184 5185 case AAESE: 5186 return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10 5187 5188 case AAESD: 5189 return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10 5190 5191 case AAESMC: 5192 return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10 5193 5194 case AAESIMC: 5195 return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10 5196 5197 case ASHA1C: 5198 return 0x5E<<24 | 0<<12 5199 5200 case ASHA1P: 5201 return 0x5E<<24 | 1<<12 5202 5203 case ASHA1M: 5204 return 0x5E<<24 | 2<<12 5205 5206 case ASHA1SU0: 5207 return 0x5E<<24 | 3<<12 5208 5209 case ASHA256H: 5210 return 0x5E<<24 | 4<<12 5211 5212 case ASHA256H2: 5213 return 0x5E<<24 | 5<<12 5214 5215 case ASHA256SU1: 5216 return 0x5E<<24 | 6<<12 5217 5218 case ASHA1H: 5219 return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10 5220 5221 case ASHA1SU1: 5222 return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10 5223 5224 case ASHA256SU0: 5225 return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10 5226 5227 case AFCVTZSD: 5228 return FPCVTI(1, 0, 1, 3, 0) 5229 5230 case AFCVTZSDW: 5231 return FPCVTI(0, 0, 1, 3, 0) 5232 5233 case AFCVTZSS: 5234 return FPCVTI(1, 0, 0, 3, 0) 5235 5236 case AFCVTZSSW: 5237 return FPCVTI(0, 0, 0, 3, 0) 5238 5239 case AFCVTZUD: 5240 return FPCVTI(1, 0, 1, 3, 1) 5241 5242 case AFCVTZUDW: 5243 return FPCVTI(0, 0, 1, 3, 1) 5244 5245 case AFCVTZUS: 5246 return FPCVTI(1, 0, 0, 3, 1) 5247 5248 case AFCVTZUSW: 5249 return FPCVTI(0, 0, 0, 3, 1) 5250 5251 case ASCVTFD: 5252 return FPCVTI(1, 0, 1, 0, 2) 5253 5254 case ASCVTFS: 5255 return FPCVTI(1, 0, 0, 0, 2) 5256 5257 case ASCVTFWD: 5258 return FPCVTI(0, 0, 1, 0, 2) 5259 5260 case ASCVTFWS: 5261 return FPCVTI(0, 0, 0, 0, 2) 5262 5263 case AUCVTFD: 5264 return FPCVTI(1, 0, 1, 0, 3) 5265 5266 case AUCVTFS: 5267 return FPCVTI(1, 0, 0, 0, 3) 5268 5269 case AUCVTFWD: 5270 return FPCVTI(0, 0, 1, 0, 3) 5271 5272 case AUCVTFWS: 5273 return FPCVTI(0, 0, 0, 0, 3) 5274 5275 case AFADDS: 5276 return FPOP2S(0, 0, 0, 2) 5277 5278 case AFADDD: 5279 return FPOP2S(0, 0, 1, 2) 5280 5281 case AFSUBS: 5282 return FPOP2S(0, 0, 0, 3) 5283 5284 case AFSUBD: 5285 return FPOP2S(0, 0, 1, 3) 5286 5287 case AFMADDD: 5288 return FPOP3S(0, 0, 1, 0, 0) 5289 5290 case AFMADDS: 5291 return FPOP3S(0, 0, 0, 0, 0) 5292 5293 case AFMSUBD: 5294 return FPOP3S(0, 0, 1, 0, 1) 5295 5296 case AFMSUBS: 5297 return FPOP3S(0, 0, 0, 0, 1) 5298 5299 case AFNMADDD: 5300 return FPOP3S(0, 0, 1, 1, 0) 5301 5302 case AFNMADDS: 5303 return FPOP3S(0, 0, 0, 1, 0) 5304 5305 case AFNMSUBD: 5306 return FPOP3S(0, 0, 1, 1, 1) 5307 5308 case AFNMSUBS: 5309 return FPOP3S(0, 0, 0, 1, 1) 5310 5311 case AFMULS: 5312 return FPOP2S(0, 0, 0, 0) 5313 5314 case AFMULD: 5315 return FPOP2S(0, 0, 1, 0) 5316 5317 case AFDIVS: 5318 return FPOP2S(0, 0, 0, 1) 5319 5320 case AFDIVD: 5321 return FPOP2S(0, 0, 1, 1) 5322 5323 case AFMAXS: 5324 return FPOP2S(0, 0, 0, 4) 5325 5326 case AFMINS: 5327 return FPOP2S(0, 0, 0, 5) 5328 5329 case AFMAXD: 5330 return FPOP2S(0, 0, 1, 4) 5331 5332 case AFMIND: 5333 return FPOP2S(0, 0, 1, 5) 5334 5335 case AFMAXNMS: 5336 return FPOP2S(0, 0, 0, 6) 5337 5338 case AFMAXNMD: 5339 return FPOP2S(0, 0, 1, 6) 5340 5341 case AFMINNMS: 5342 return FPOP2S(0, 0, 0, 7) 5343 5344 case AFMINNMD: 5345 return FPOP2S(0, 0, 1, 7) 5346 5347 case AFNMULS: 5348 return FPOP2S(0, 0, 0, 8) 5349 5350 case AFNMULD: 5351 return FPOP2S(0, 0, 1, 8) 5352 5353 case AFCMPS: 5354 return FPCMP(0, 0, 0, 0, 0) 5355 5356 case AFCMPD: 5357 return FPCMP(0, 0, 1, 0, 0) 5358 5359 case AFCMPES: 5360 return FPCMP(0, 0, 0, 0, 16) 5361 5362 case AFCMPED: 5363 return FPCMP(0, 0, 1, 0, 16) 5364 5365 case AFCCMPS: 5366 return FPCCMP(0, 0, 0, 0) 5367 5368 case AFCCMPD: 5369 return FPCCMP(0, 0, 1, 0) 5370 5371 case AFCCMPES: 5372 return FPCCMP(0, 0, 0, 1) 5373 5374 case AFCCMPED: 5375 return FPCCMP(0, 0, 1, 1) 5376 5377 case AFCSELS: 5378 return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10 5379 5380 case AFCSELD: 5381 return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10 5382 5383 case AFMOVS: 5384 return FPOP1S(0, 0, 0, 0) 5385 5386 case AFABSS: 5387 return FPOP1S(0, 0, 0, 1) 5388 5389 case AFNEGS: 5390 return FPOP1S(0, 0, 0, 2) 5391 5392 case AFSQRTS: 5393 return FPOP1S(0, 0, 0, 3) 5394 5395 case AFCVTSD: 5396 return FPOP1S(0, 0, 0, 5) 5397 5398 case AFCVTSH: 5399 return FPOP1S(0, 0, 0, 7) 5400 5401 case AFRINTNS: 5402 return FPOP1S(0, 0, 0, 8) 5403 5404 case AFRINTPS: 5405 return FPOP1S(0, 0, 0, 9) 5406 5407 case AFRINTMS: 5408 return FPOP1S(0, 0, 0, 10) 5409 5410 case AFRINTZS: 5411 return FPOP1S(0, 0, 0, 11) 5412 5413 case AFRINTAS: 5414 return FPOP1S(0, 0, 0, 12) 5415 5416 case AFRINTXS: 5417 return FPOP1S(0, 0, 0, 14) 5418 5419 case AFRINTIS: 5420 return FPOP1S(0, 0, 0, 15) 5421 5422 case AFMOVD: 5423 return FPOP1S(0, 0, 1, 0) 5424 5425 case AFABSD: 5426 return FPOP1S(0, 0, 1, 1) 5427 5428 case AFNEGD: 5429 return FPOP1S(0, 0, 1, 2) 5430 5431 case AFSQRTD: 5432 return FPOP1S(0, 0, 1, 3) 5433 5434 case AFCVTDS: 5435 return FPOP1S(0, 0, 1, 4) 5436 5437 case AFCVTDH: 5438 return FPOP1S(0, 0, 1, 7) 5439 5440 case AFRINTND: 5441 return FPOP1S(0, 0, 1, 8) 5442 5443 case AFRINTPD: 5444 return FPOP1S(0, 0, 1, 9) 5445 5446 case AFRINTMD: 5447 return FPOP1S(0, 0, 1, 10) 5448 5449 case AFRINTZD: 5450 return FPOP1S(0, 0, 1, 11) 5451 5452 case AFRINTAD: 5453 return FPOP1S(0, 0, 1, 12) 5454 5455 case AFRINTXD: 5456 return FPOP1S(0, 0, 1, 14) 5457 5458 case AFRINTID: 5459 return FPOP1S(0, 0, 1, 15) 5460 5461 case AFCVTHS: 5462 return FPOP1S(0, 0, 3, 4) 5463 5464 case AFCVTHD: 5465 return FPOP1S(0, 0, 3, 5) 5466 5467 case AVADD: 5468 return 7<<25 | 1<<21 | 1<<15 | 1<<10 5469 5470 case AVADDP: 5471 return 7<<25 | 1<<21 | 1<<15 | 15<<10 5472 5473 case AVAND: 5474 return 7<<25 | 1<<21 | 7<<10 5475 5476 case AVCMEQ: 5477 return 1<<29 | 0x71<<21 | 0x23<<10 5478 5479 case AVCNT: 5480 return 0xE<<24 | 0x10<<17 | 5<<12 | 2<<10 5481 5482 case AVZIP1: 5483 return 0xE<<24 | 3<<12 | 2<<10 5484 5485 case AVZIP2: 5486 return 0xE<<24 | 1<<14 | 3<<12 | 2<<10 5487 5488 case AVEOR: 5489 return 1<<29 | 0x71<<21 | 7<<10 5490 5491 case AVORR: 5492 return 7<<25 | 5<<21 | 7<<10 5493 5494 case AVREV32: 5495 return 11<<26 | 2<<24 | 1<<21 | 1<<11 5496 5497 case AVREV64: 5498 return 3<<26 | 2<<24 | 1<<21 | 1<<11 5499 5500 case AVMOV: 5501 return 7<<25 | 5<<21 | 7<<10 5502 5503 case AVADDV: 5504 return 7<<25 | 3<<20 | 3<<15 | 7<<11 5505 5506 case AVUADDLV: 5507 return 1<<29 | 7<<25 | 3<<20 | 7<<11 5508 5509 case AVFMLA: 5510 return 7<<25 | 0<<23 | 1<<21 | 3<<14 | 3<<10 5511 5512 case AVFMLS: 5513 return 7<<25 | 1<<23 | 1<<21 | 3<<14 | 3<<10 5514 5515 case AVPMULL, AVPMULL2: 5516 return 0xE<<24 | 1<<21 | 0x38<<10 5517 5518 case AVRBIT: 5519 return 0x2E<<24 | 1<<22 | 0x10<<17 | 5<<12 | 2<<10 5520 } 5521 5522 c.ctxt.Diag("%v: bad rrr %d %v", p, a, a) 5523 return 0 5524 } 5525 5526 /* 5527 * imm -> Rd 5528 * imm op Rn -> Rd 5529 */ 5530 func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 { 5531 switch a { 5532 /* op $addcon, Rn, Rd */ 5533 case AMOVD, AADD: 5534 return S64 | 0<<30 | 0<<29 | 0x11<<24 5535 5536 case ACMN, AADDS: 5537 return S64 | 0<<30 | 1<<29 | 0x11<<24 5538 5539 case AMOVW, AADDW: 5540 return S32 | 0<<30 | 0<<29 | 0x11<<24 5541 5542 case ACMNW, AADDSW: 5543 return S32 | 0<<30 | 1<<29 | 0x11<<24 5544 5545 case ASUB: 5546 return S64 | 1<<30 | 0<<29 | 0x11<<24 5547 5548 case ACMP, ASUBS: 5549 return S64 | 1<<30 | 1<<29 | 0x11<<24 5550 5551 case ASUBW: 5552 return S32 | 1<<30 | 0<<29 | 0x11<<24 5553 5554 case ACMPW, ASUBSW: 5555 return S32 | 1<<30 | 1<<29 | 0x11<<24 5556 5557 /* op $imm(SB), Rd; op label, Rd */ 5558 case AADR: 5559 return 0<<31 | 0x10<<24 5560 5561 case AADRP: 5562 return 1<<31 | 0x10<<24 5563 5564 /* op $bimm, Rn, Rd */ 5565 case AAND, ABIC: 5566 return S64 | 0<<29 | 0x24<<23 5567 5568 case AANDW, ABICW: 5569 return S32 | 0<<29 | 0x24<<23 | 0<<22 5570 5571 case AORR, AORN: 5572 return S64 | 1<<29 | 0x24<<23 5573 5574 case AORRW, AORNW: 5575 return S32 | 1<<29 | 0x24<<23 | 0<<22 5576 5577 case AEOR, AEON: 5578 return S64 | 2<<29 | 0x24<<23 5579 5580 case AEORW, AEONW: 5581 return S32 | 2<<29 | 0x24<<23 | 0<<22 5582 5583 case AANDS, ABICS, ATST: 5584 return S64 | 3<<29 | 0x24<<23 5585 5586 case AANDSW, ABICSW, ATSTW: 5587 return S32 | 3<<29 | 0x24<<23 | 0<<22 5588 5589 case AASR: 5590 return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */ 5591 5592 case AASRW: 5593 return S32 | 0<<29 | 0x26<<23 | 0<<22 5594 5595 /* op $width, $lsb, Rn, Rd */ 5596 case ABFI: 5597 return S64 | 2<<29 | 0x26<<23 | 1<<22 5598 /* alias of BFM */ 5599 5600 case ABFIW: 5601 return S32 | 2<<29 | 0x26<<23 | 0<<22 5602 5603 /* op $imms, $immr, Rn, Rd */ 5604 case ABFM: 5605 return S64 | 1<<29 | 0x26<<23 | 1<<22 5606 5607 case ABFMW: 5608 return S32 | 1<<29 | 0x26<<23 | 0<<22 5609 5610 case ASBFM: 5611 return S64 | 0<<29 | 0x26<<23 | 1<<22 5612 5613 case ASBFMW: 5614 return S32 | 0<<29 | 0x26<<23 | 0<<22 5615 5616 case AUBFM: 5617 return S64 | 2<<29 | 0x26<<23 | 1<<22 5618 5619 case AUBFMW: 5620 return S32 | 2<<29 | 0x26<<23 | 0<<22 5621 5622 case ABFXIL: 5623 return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */ 5624 5625 case ABFXILW: 5626 return S32 | 1<<29 | 0x26<<23 | 0<<22 5627 5628 case AEXTR: 5629 return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21 5630 5631 case AEXTRW: 5632 return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21 5633 5634 case ACBNZ: 5635 return S64 | 0x1A<<25 | 1<<24 5636 5637 case ACBNZW: 5638 return S32 | 0x1A<<25 | 1<<24 5639 5640 case ACBZ: 5641 return S64 | 0x1A<<25 | 0<<24 5642 5643 case ACBZW: 5644 return S32 | 0x1A<<25 | 0<<24 5645 5646 case ACCMN: 5647 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 5648 5649 case ACCMNW: 5650 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 5651 5652 case ACCMP: 5653 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 5654 5655 case ACCMPW: 5656 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 5657 5658 case AMOVK: 5659 return S64 | 3<<29 | 0x25<<23 5660 5661 case AMOVKW: 5662 return S32 | 3<<29 | 0x25<<23 5663 5664 case AMOVN: 5665 return S64 | 0<<29 | 0x25<<23 5666 5667 case AMOVNW: 5668 return S32 | 0<<29 | 0x25<<23 5669 5670 case AMOVZ: 5671 return S64 | 2<<29 | 0x25<<23 5672 5673 case AMOVZW: 5674 return S32 | 2<<29 | 0x25<<23 5675 5676 case AMSR: 5677 return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */ 5678 5679 case AAT, 5680 ADC, 5681 AIC, 5682 ATLBI, 5683 ASYS: 5684 return SYSOP(0, 1, 0, 0, 0, 0, 0) 5685 5686 case ASYSL: 5687 return SYSOP(1, 1, 0, 0, 0, 0, 0) 5688 5689 case ATBZ: 5690 return 0x36 << 24 5691 5692 case ATBNZ: 5693 return 0x37 << 24 5694 5695 case ADSB: 5696 return SYSOP(0, 0, 3, 3, 0, 4, 0x1F) 5697 5698 case ADMB: 5699 return SYSOP(0, 0, 3, 3, 0, 5, 0x1F) 5700 5701 case AISB: 5702 return SYSOP(0, 0, 3, 3, 0, 6, 0x1F) 5703 5704 case AHINT: 5705 return SYSOP(0, 0, 3, 2, 0, 0, 0x1F) 5706 5707 case AVEXT: 5708 return 0x2E<<24 | 0<<23 | 0<<21 | 0<<15 5709 5710 case AVUSHR: 5711 return 0x5E<<23 | 1<<10 5712 5713 case AVSHL: 5714 return 0x1E<<23 | 21<<10 5715 5716 case AVSRI: 5717 return 0x5E<<23 | 17<<10 5718 } 5719 5720 c.ctxt.Diag("%v: bad irr %v", p, a) 5721 return 0 5722 } 5723 5724 func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 { 5725 switch a { 5726 case ACLS: 5727 return S64 | OPBIT(5) 5728 5729 case ACLSW: 5730 return S32 | OPBIT(5) 5731 5732 case ACLZ: 5733 return S64 | OPBIT(4) 5734 5735 case ACLZW: 5736 return S32 | OPBIT(4) 5737 5738 case ARBIT: 5739 return S64 | OPBIT(0) 5740 5741 case ARBITW: 5742 return S32 | OPBIT(0) 5743 5744 case AREV: 5745 return S64 | OPBIT(3) 5746 5747 case AREVW: 5748 return S32 | OPBIT(2) 5749 5750 case AREV16: 5751 return S64 | OPBIT(1) 5752 5753 case AREV16W: 5754 return S32 | OPBIT(1) 5755 5756 case AREV32: 5757 return S64 | OPBIT(2) 5758 5759 default: 5760 c.ctxt.Diag("bad bit op\n%v", p) 5761 return 0 5762 } 5763 } 5764 5765 /* 5766 * add/subtract sign or zero-extended register 5767 */ 5768 func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 { 5769 extension := uint32(0) 5770 if !extend { 5771 switch a { 5772 case AADD, ACMN, AADDS, ASUB, ACMP, ASUBS: 5773 extension = LSL0_64 5774 5775 case AADDW, ACMNW, AADDSW, ASUBW, ACMPW, ASUBSW: 5776 extension = LSL0_32 5777 } 5778 } 5779 5780 switch a { 5781 case AADD: 5782 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5783 5784 case AADDW: 5785 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5786 5787 case ACMN, AADDS: 5788 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5789 5790 case ACMNW, AADDSW: 5791 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5792 5793 case ASUB: 5794 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5795 5796 case ASUBW: 5797 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5798 5799 case ACMP, ASUBS: 5800 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5801 5802 case ACMPW, ASUBSW: 5803 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5804 } 5805 5806 c.ctxt.Diag("bad opxrrr %v\n%v", a, p) 5807 return 0 5808 } 5809 5810 func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 { 5811 switch a { 5812 case ASVC: 5813 return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */ 5814 5815 case AHVC: 5816 return 0xD4<<24 | 0<<21 | 2 5817 5818 case ASMC: 5819 return 0xD4<<24 | 0<<21 | 3 5820 5821 case ABRK: 5822 return 0xD4<<24 | 1<<21 | 0 5823 5824 case AHLT: 5825 return 0xD4<<24 | 2<<21 | 0 5826 5827 case ADCPS1: 5828 return 0xD4<<24 | 5<<21 | 1 5829 5830 case ADCPS2: 5831 return 0xD4<<24 | 5<<21 | 2 5832 5833 case ADCPS3: 5834 return 0xD4<<24 | 5<<21 | 3 5835 5836 case ACLREX: 5837 return SYSOP(0, 0, 3, 3, 0, 2, 0x1F) 5838 } 5839 5840 c.ctxt.Diag("%v: bad imm %v", p, a) 5841 return 0 5842 } 5843 5844 func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 { 5845 v := int64(0) 5846 t := int64(0) 5847 if p.Pcond != nil { 5848 v = (p.Pcond.Pc >> uint(preshift)) - (c.pc >> uint(preshift)) 5849 if (v & ((1 << uint(shift)) - 1)) != 0 { 5850 c.ctxt.Diag("misaligned label\n%v", p) 5851 } 5852 v >>= uint(shift) 5853 t = int64(1) << uint(flen-1) 5854 if v < -t || v >= t { 5855 c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, p.Pcond) 5856 panic("branch too far") 5857 } 5858 } 5859 5860 return v & ((t << 1) - 1) 5861 } 5862 5863 /* 5864 * pc-relative branches 5865 */ 5866 func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 { 5867 switch a { 5868 case ABEQ: 5869 return OPBcc(0x0) 5870 5871 case ABNE: 5872 return OPBcc(0x1) 5873 5874 case ABCS: 5875 return OPBcc(0x2) 5876 5877 case ABHS: 5878 return OPBcc(0x2) 5879 5880 case ABCC: 5881 return OPBcc(0x3) 5882 5883 case ABLO: 5884 return OPBcc(0x3) 5885 5886 case ABMI: 5887 return OPBcc(0x4) 5888 5889 case ABPL: 5890 return OPBcc(0x5) 5891 5892 case ABVS: 5893 return OPBcc(0x6) 5894 5895 case ABVC: 5896 return OPBcc(0x7) 5897 5898 case ABHI: 5899 return OPBcc(0x8) 5900 5901 case ABLS: 5902 return OPBcc(0x9) 5903 5904 case ABGE: 5905 return OPBcc(0xa) 5906 5907 case ABLT: 5908 return OPBcc(0xb) 5909 5910 case ABGT: 5911 return OPBcc(0xc) 5912 5913 case ABLE: 5914 return OPBcc(0xd) /* imm19<<5 | cond */ 5915 5916 case AB: 5917 return 0<<31 | 5<<26 /* imm26 */ 5918 5919 case obj.ADUFFZERO, obj.ADUFFCOPY, ABL: 5920 return 1<<31 | 5<<26 5921 } 5922 5923 c.ctxt.Diag("%v: bad bra %v", p, a) 5924 return 0 5925 } 5926 5927 func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 { 5928 switch a { 5929 case ABL: 5930 return OPBLR(1) /* BLR */ 5931 5932 case AB: 5933 return OPBLR(0) /* BR */ 5934 5935 case obj.ARET: 5936 return OPBLR(2) /* RET */ 5937 } 5938 5939 c.ctxt.Diag("%v: bad brr %v", p, a) 5940 return 0 5941 } 5942 5943 func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 { 5944 switch a { 5945 case ADRPS: 5946 return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5 5947 5948 case AERET: 5949 return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5 5950 5951 // case ANOP: 5952 // return SYSHINT(0) 5953 5954 case AYIELD: 5955 return SYSHINT(1) 5956 5957 case AWFE: 5958 return SYSHINT(2) 5959 5960 case AWFI: 5961 return SYSHINT(3) 5962 5963 case ASEV: 5964 return SYSHINT(4) 5965 5966 case ASEVL: 5967 return SYSHINT(5) 5968 } 5969 5970 c.ctxt.Diag("%v: bad op0 %v", p, a) 5971 return 0 5972 } 5973 5974 /* 5975 * register offset 5976 */ 5977 func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 { 5978 switch a { 5979 case ALDAR: 5980 return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10 5981 5982 case ALDARW: 5983 return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10 5984 5985 case ALDARB: 5986 return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10 5987 5988 case ALDARH: 5989 return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10 5990 5991 case ALDAXP: 5992 return LDSTX(3, 0, 1, 1, 1) 5993 5994 case ALDAXPW: 5995 return LDSTX(2, 0, 1, 1, 1) 5996 5997 case ALDAXR: 5998 return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10 5999 6000 case ALDAXRW: 6001 return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10 6002 6003 case ALDAXRB: 6004 return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10 6005 6006 case ALDAXRH: 6007 return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10 6008 6009 case ALDXR: 6010 return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10 6011 6012 case ALDXRB: 6013 return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10 6014 6015 case ALDXRH: 6016 return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10 6017 6018 case ALDXRW: 6019 return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10 6020 6021 case ALDXP: 6022 return LDSTX(3, 0, 1, 1, 0) 6023 6024 case ALDXPW: 6025 return LDSTX(2, 0, 1, 1, 0) 6026 6027 case AMOVNP: 6028 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 6029 6030 case AMOVNPW: 6031 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 6032 } 6033 6034 c.ctxt.Diag("bad opload %v\n%v", a, p) 6035 return 0 6036 } 6037 6038 func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 { 6039 switch a { 6040 case ASTLR: 6041 return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10 6042 6043 case ASTLRB: 6044 return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10 6045 6046 case ASTLRH: 6047 return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10 6048 6049 case ASTLP: 6050 return LDSTX(3, 0, 0, 1, 1) 6051 6052 case ASTLPW: 6053 return LDSTX(2, 0, 0, 1, 1) 6054 6055 case ASTLRW: 6056 return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10 6057 6058 case ASTLXP: 6059 return LDSTX(3, 0, 0, 1, 1) 6060 6061 case ASTLXPW: 6062 return LDSTX(2, 0, 0, 1, 1) 6063 6064 case ASTLXR: 6065 return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10 6066 6067 case ASTLXRB: 6068 return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10 6069 6070 case ASTLXRH: 6071 return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10 6072 6073 case ASTLXRW: 6074 return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10 6075 6076 case ASTXR: 6077 return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10 6078 6079 case ASTXRB: 6080 return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10 6081 6082 case ASTXRH: 6083 return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10 6084 6085 case ASTXP: 6086 return LDSTX(3, 0, 0, 1, 0) 6087 6088 case ASTXPW: 6089 return LDSTX(2, 0, 0, 1, 0) 6090 6091 case ASTXRW: 6092 return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10 6093 6094 case AMOVNP: 6095 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 6096 6097 case AMOVNPW: 6098 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 6099 } 6100 6101 c.ctxt.Diag("bad opstore %v\n%v", a, p) 6102 return 0 6103 } 6104 6105 /* 6106 * load/store register (unsigned immediate) C3.3.13 6107 * these produce 64-bit values (when there's an option) 6108 */ 6109 func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 { 6110 if v < 0 || v >= (1<<12) { 6111 c.ctxt.Diag("offset out of range: %d\n%v", v, p) 6112 } 6113 o |= (v & 0xFFF) << 10 6114 o |= int32(b&31) << 5 6115 o |= int32(r & 31) 6116 return uint32(o) 6117 } 6118 6119 func (c *ctxt7) opldr12(p *obj.Prog, a obj.As) uint32 { 6120 switch a { 6121 case AMOVD: 6122 return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */ 6123 6124 case AMOVW: 6125 return LDSTR12U(2, 0, 2) 6126 6127 case AMOVWU: 6128 return LDSTR12U(2, 0, 1) 6129 6130 case AMOVH: 6131 return LDSTR12U(1, 0, 2) 6132 6133 case AMOVHU: 6134 return LDSTR12U(1, 0, 1) 6135 6136 case AMOVB: 6137 return LDSTR12U(0, 0, 2) 6138 6139 case AMOVBU: 6140 return LDSTR12U(0, 0, 1) 6141 6142 case AFMOVS: 6143 return LDSTR12U(2, 1, 1) 6144 6145 case AFMOVD: 6146 return LDSTR12U(3, 1, 1) 6147 } 6148 6149 c.ctxt.Diag("bad opldr12 %v\n%v", a, p) 6150 return 0 6151 } 6152 6153 func (c *ctxt7) opstr12(p *obj.Prog, a obj.As) uint32 { 6154 return LD2STR(c.opldr12(p, a)) 6155 } 6156 6157 /* 6158 * load/store register (unscaled immediate) C3.3.12 6159 */ 6160 func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 { 6161 if v < -256 || v > 255 { 6162 c.ctxt.Diag("offset out of range: %d\n%v", v, p) 6163 } 6164 o |= (v & 0x1FF) << 12 6165 o |= int32(b&31) << 5 6166 o |= int32(r & 31) 6167 return uint32(o) 6168 } 6169 6170 func (c *ctxt7) opldr9(p *obj.Prog, a obj.As) uint32 { 6171 switch a { 6172 case AMOVD: 6173 return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */ 6174 6175 case AMOVW: 6176 return LDSTR9S(2, 0, 2) 6177 6178 case AMOVWU: 6179 return LDSTR9S(2, 0, 1) 6180 6181 case AMOVH: 6182 return LDSTR9S(1, 0, 2) 6183 6184 case AMOVHU: 6185 return LDSTR9S(1, 0, 1) 6186 6187 case AMOVB: 6188 return LDSTR9S(0, 0, 2) 6189 6190 case AMOVBU: 6191 return LDSTR9S(0, 0, 1) 6192 6193 case AFMOVS: 6194 return LDSTR9S(2, 1, 1) 6195 6196 case AFMOVD: 6197 return LDSTR9S(3, 1, 1) 6198 } 6199 6200 c.ctxt.Diag("bad opldr9 %v\n%v", a, p) 6201 return 0 6202 } 6203 6204 func (c *ctxt7) opstr9(p *obj.Prog, a obj.As) uint32 { 6205 return LD2STR(c.opldr9(p, a)) 6206 } 6207 6208 func (c *ctxt7) opldrpp(p *obj.Prog, a obj.As) uint32 { 6209 switch a { 6210 case AMOVD: 6211 return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */ 6212 6213 case AMOVW: 6214 return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 6215 6216 case AMOVWU: 6217 return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 6218 6219 case AMOVH: 6220 return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 6221 6222 case AMOVHU: 6223 return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 6224 6225 case AMOVB: 6226 return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 6227 6228 case AMOVBU: 6229 return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 6230 6231 case AFMOVS: 6232 return 2<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22 6233 6234 case AFMOVD: 6235 return 3<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22 6236 6237 case APRFM: 6238 return 0xf9<<24 | 2<<22 6239 6240 } 6241 6242 c.ctxt.Diag("bad opldr %v\n%v", a, p) 6243 return 0 6244 } 6245 6246 // olsxrr attaches register operands to a load/store opcode supplied in o. 6247 // The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2). 6248 func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 { 6249 o |= int32(r1&31) << 5 6250 o |= int32(r2&31) << 16 6251 o |= int32(r & 31) 6252 return uint32(o) 6253 } 6254 6255 // opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode 6256 // for load instruction with register offset. 6257 // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm). 6258 func (c *ctxt7) opldrr(p *obj.Prog, a obj.As, extension bool) uint32 { 6259 OptionS := uint32(0x1a) 6260 if extension { 6261 OptionS = uint32(0) // option value and S value have been encoded into p.From.Offset. 6262 } 6263 switch a { 6264 case AMOVD: 6265 return OptionS<<10 | 0x3<<21 | 0x1f<<27 6266 case AMOVW: 6267 return OptionS<<10 | 0x5<<21 | 0x17<<27 6268 case AMOVWU: 6269 return OptionS<<10 | 0x3<<21 | 0x17<<27 6270 case AMOVH: 6271 return OptionS<<10 | 0x5<<21 | 0x0f<<27 6272 case AMOVHU: 6273 return OptionS<<10 | 0x3<<21 | 0x0f<<27 6274 case AMOVB: 6275 return OptionS<<10 | 0x5<<21 | 0x07<<27 6276 case AMOVBU: 6277 return OptionS<<10 | 0x3<<21 | 0x07<<27 6278 case AFMOVS: 6279 return OptionS<<10 | 0x3<<21 | 0x17<<27 | 1<<26 6280 case AFMOVD: 6281 return OptionS<<10 | 0x3<<21 | 0x1f<<27 | 1<<26 6282 } 6283 c.ctxt.Diag("bad opldrr %v\n%v", a, p) 6284 return 0 6285 } 6286 6287 // opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode 6288 // for store instruction with register offset. 6289 // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm). 6290 func (c *ctxt7) opstrr(p *obj.Prog, a obj.As, extension bool) uint32 { 6291 OptionS := uint32(0x1a) 6292 if extension { 6293 OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset. 6294 } 6295 switch a { 6296 case AMOVD: 6297 return OptionS<<10 | 0x1<<21 | 0x1f<<27 6298 case AMOVW, AMOVWU: 6299 return OptionS<<10 | 0x1<<21 | 0x17<<27 6300 case AMOVH, AMOVHU: 6301 return OptionS<<10 | 0x1<<21 | 0x0f<<27 6302 case AMOVB, AMOVBU: 6303 return OptionS<<10 | 0x1<<21 | 0x07<<27 6304 case AFMOVS: 6305 return OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26 6306 case AFMOVD: 6307 return OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26 6308 } 6309 c.ctxt.Diag("bad opstrr %v\n%v", a, p) 6310 return 0 6311 } 6312 6313 func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 { 6314 if (v & 0xFFF000) != 0 { 6315 if v&0xFFF != 0 { 6316 c.ctxt.Diag("%v misuses oaddi", p) 6317 } 6318 v >>= 12 6319 o1 |= 1 << 22 6320 } 6321 6322 o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31) 6323 return uint32(o1) 6324 } 6325 6326 /* 6327 * load a literal value into dr 6328 */ 6329 func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 { 6330 var o1 int32 6331 if p.Pcond == nil { /* not in literal pool */ 6332 c.aclass(a) 6333 c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset)) 6334 6335 /* TODO: could be clever, and use general constant builder */ 6336 o1 = int32(c.opirr(p, AADD)) 6337 6338 v := int32(c.instoffset) 6339 if v != 0 && (v&0xFFF) == 0 { 6340 v >>= 12 6341 o1 |= 1 << 22 /* shift, by 12 */ 6342 } 6343 6344 o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31) 6345 } else { 6346 fp, w := 0, 0 6347 switch as { 6348 case AFMOVS: 6349 fp = 1 6350 w = 0 /* 32-bit SIMD/FP */ 6351 6352 case AFMOVD: 6353 fp = 1 6354 w = 1 /* 64-bit SIMD/FP */ 6355 6356 case AMOVD: 6357 if p.Pcond.As == ADWORD { 6358 w = 1 /* 64-bit */ 6359 } else if p.Pcond.To.Offset < 0 { 6360 w = 2 /* 32-bit, sign-extended to 64-bit */ 6361 } else if p.Pcond.To.Offset >= 0 { 6362 w = 0 /* 32-bit, zero-extended to 64-bit */ 6363 } else { 6364 c.ctxt.Diag("invalid operand %v in %v", a, p) 6365 } 6366 6367 case AMOVBU, AMOVHU, AMOVWU: 6368 w = 0 /* 32-bit, zero-extended to 64-bit */ 6369 6370 case AMOVB, AMOVH, AMOVW: 6371 w = 2 /* 32-bit, sign-extended to 64-bit */ 6372 6373 default: 6374 c.ctxt.Diag("invalid operation %v in %v", as, p) 6375 } 6376 6377 v := int32(c.brdist(p, 0, 19, 2)) 6378 o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27) 6379 o1 |= (v & 0x7FFFF) << 5 6380 o1 |= int32(dr & 31) 6381 } 6382 6383 return uint32(o1) 6384 } 6385 6386 // load a constant (MOVCON or BITCON) in a into rt 6387 func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) { 6388 if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 { 6389 // or $bitcon, REGZERO, rt 6390 mode := 64 6391 var as1 obj.As 6392 switch as { 6393 case AMOVW: 6394 as1 = AORRW 6395 mode = 32 6396 case AMOVD: 6397 as1 = AORR 6398 } 6399 o1 = c.opirr(p, as1) 6400 o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31) 6401 return o1 6402 } 6403 6404 if as == AMOVW { 6405 d := uint32(a.Offset) 6406 s := movcon(int64(d)) 6407 if s < 0 || 16*s >= 32 { 6408 d = ^d 6409 s = movcon(int64(d)) 6410 if s < 0 || 16*s >= 32 { 6411 c.ctxt.Diag("impossible 32-bit move wide: %#x\n%v", uint32(a.Offset), p) 6412 } 6413 o1 = c.opirr(p, AMOVNW) 6414 } else { 6415 o1 = c.opirr(p, AMOVZW) 6416 } 6417 o1 |= MOVCONST(int64(d), s, rt) 6418 } 6419 if as == AMOVD { 6420 d := a.Offset 6421 s := movcon(d) 6422 if s < 0 || 16*s >= 64 { 6423 d = ^d 6424 s = movcon(d) 6425 if s < 0 || 16*s >= 64 { 6426 c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p) 6427 } 6428 o1 = c.opirr(p, AMOVN) 6429 } else { 6430 o1 = c.opirr(p, AMOVZ) 6431 } 6432 o1 |= MOVCONST(d, s, rt) 6433 } 6434 return o1 6435 } 6436 6437 // load a 32-bit/64-bit large constant (LCON or VCON) in a.Offset into rt 6438 // put the instruction sequence in os and return the number of instructions. 6439 func (c *ctxt7) omovlconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int, os []uint32) (num uint8) { 6440 switch as { 6441 case AMOVW: 6442 d := uint32(a.Offset) 6443 // use MOVZW and MOVKW to load a constant to rt 6444 os[0] = c.opirr(p, AMOVZW) 6445 os[0] |= MOVCONST(int64(d), 0, rt) 6446 os[1] = c.opirr(p, AMOVKW) 6447 os[1] |= MOVCONST(int64(d), 1, rt) 6448 return 2 6449 6450 case AMOVD: 6451 d := a.Offset 6452 dn := ^d 6453 var immh [4]uint64 6454 var i int 6455 zeroCount := int(0) 6456 negCount := int(0) 6457 for i = 0; i < 4; i++ { 6458 immh[i] = uint64((d >> uint(i*16)) & 0xffff) 6459 if immh[i] == 0 { 6460 zeroCount++ 6461 } else if immh[i] == 0xffff { 6462 negCount++ 6463 } 6464 } 6465 6466 if zeroCount == 4 || negCount == 4 { 6467 c.ctxt.Diag("the immediate should be MOVCON: %v", p) 6468 } 6469 switch { 6470 case zeroCount == 3: 6471 // one MOVZ 6472 for i = 0; i < 4; i++ { 6473 if immh[i] != 0 { 6474 os[0] = c.opirr(p, AMOVZ) 6475 os[0] |= MOVCONST(d, i, rt) 6476 break 6477 } 6478 } 6479 return 1 6480 6481 case negCount == 3: 6482 // one MOVN 6483 for i = 0; i < 4; i++ { 6484 if immh[i] != 0xffff { 6485 os[0] = c.opirr(p, AMOVN) 6486 os[0] |= MOVCONST(dn, i, rt) 6487 break 6488 } 6489 } 6490 return 1 6491 6492 case zeroCount == 2: 6493 // one MOVZ and one MOVK 6494 for i = 0; i < 4; i++ { 6495 if immh[i] != 0 { 6496 os[0] = c.opirr(p, AMOVZ) 6497 os[0] |= MOVCONST(d, i, rt) 6498 i++ 6499 break 6500 } 6501 } 6502 for ; i < 4; i++ { 6503 if immh[i] != 0 { 6504 os[1] = c.opirr(p, AMOVK) 6505 os[1] |= MOVCONST(d, i, rt) 6506 } 6507 } 6508 return 2 6509 6510 case negCount == 2: 6511 // one MOVN and one MOVK 6512 for i = 0; i < 4; i++ { 6513 if immh[i] != 0xffff { 6514 os[0] = c.opirr(p, AMOVN) 6515 os[0] |= MOVCONST(dn, i, rt) 6516 i++ 6517 break 6518 } 6519 } 6520 for ; i < 4; i++ { 6521 if immh[i] != 0xffff { 6522 os[1] = c.opirr(p, AMOVK) 6523 os[1] |= MOVCONST(d, i, rt) 6524 } 6525 } 6526 return 2 6527 6528 case zeroCount == 1: 6529 // one MOVZ and two MOVKs 6530 for i = 0; i < 4; i++ { 6531 if immh[i] != 0 { 6532 os[0] = c.opirr(p, AMOVZ) 6533 os[0] |= MOVCONST(d, i, rt) 6534 i++ 6535 break 6536 } 6537 } 6538 6539 for j := 1; i < 4; i++ { 6540 if immh[i] != 0 { 6541 os[j] = c.opirr(p, AMOVK) 6542 os[j] |= MOVCONST(d, i, rt) 6543 j++ 6544 } 6545 } 6546 return 3 6547 6548 case negCount == 1: 6549 // one MOVN and two MOVKs 6550 for i = 0; i < 4; i++ { 6551 if immh[i] != 0xffff { 6552 os[0] = c.opirr(p, AMOVN) 6553 os[0] |= MOVCONST(dn, i, rt) 6554 i++ 6555 break 6556 } 6557 } 6558 6559 for j := 1; i < 4; i++ { 6560 if immh[i] != 0xffff { 6561 os[j] = c.opirr(p, AMOVK) 6562 os[j] |= MOVCONST(d, i, rt) 6563 j++ 6564 } 6565 } 6566 return 3 6567 6568 default: 6569 // one MOVZ and 3 MOVKs 6570 os[0] = c.opirr(p, AMOVZ) 6571 os[0] |= MOVCONST(d, 0, rt) 6572 for i = 1; i < 4; i++ { 6573 os[i] = c.opirr(p, AMOVK) 6574 os[i] |= MOVCONST(d, i, rt) 6575 } 6576 return 4 6577 } 6578 default: 6579 return 0 6580 } 6581 } 6582 6583 func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 { 6584 var b uint32 6585 o := c.opirr(p, a) 6586 if (o & (1 << 31)) == 0 { 6587 b = 32 6588 } else { 6589 b = 64 6590 } 6591 if r < 0 || uint32(r) >= b { 6592 c.ctxt.Diag("illegal bit number\n%v", p) 6593 } 6594 o |= (uint32(r) & 0x3F) << 16 6595 if s < 0 || uint32(s) >= b { 6596 c.ctxt.Diag("illegal bit number\n%v", p) 6597 } 6598 o |= (uint32(s) & 0x3F) << 10 6599 o |= (uint32(rf&31) << 5) | uint32(rt&31) 6600 return o 6601 } 6602 6603 func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 { 6604 var b uint32 6605 o := c.opirr(p, a) 6606 if (o & (1 << 31)) != 0 { 6607 b = 63 6608 } else { 6609 b = 31 6610 } 6611 if v < 0 || uint32(v) > b { 6612 c.ctxt.Diag("illegal bit number\n%v", p) 6613 } 6614 o |= uint32(v) << 10 6615 o |= uint32(rn&31) << 5 6616 o |= uint32(rm&31) << 16 6617 o |= uint32(rt & 31) 6618 return o 6619 } 6620 6621 /* genrate instruction encoding for LDP/LDPW/LDPSW/STP/STPW */ 6622 func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh, ldp uint32) uint32 { 6623 wback := false 6624 if o.scond == C_XPOST || o.scond == C_XPRE { 6625 wback = true 6626 } 6627 switch p.As { 6628 case ALDP, ALDPW, ALDPSW: 6629 c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset)) 6630 case ASTP, ASTPW: 6631 if wback == true { 6632 c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset)) 6633 } 6634 case AFLDPD, AFLDPS: 6635 c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset)) 6636 } 6637 var ret uint32 6638 // check offset 6639 switch p.As { 6640 case AFLDPD, AFSTPD: 6641 if vo < -512 || vo > 504 || vo%8 != 0 { 6642 c.ctxt.Diag("invalid offset %v\n", p) 6643 } 6644 vo /= 8 6645 ret = 1<<30 | 1<<26 6646 case ALDP, ASTP: 6647 if vo < -512 || vo > 504 || vo%8 != 0 { 6648 c.ctxt.Diag("invalid offset %v\n", p) 6649 } 6650 vo /= 8 6651 ret = 2 << 30 6652 case AFLDPS, AFSTPS: 6653 if vo < -256 || vo > 252 || vo%4 != 0 { 6654 c.ctxt.Diag("invalid offset %v\n", p) 6655 } 6656 vo /= 4 6657 ret = 1 << 26 6658 case ALDPW, ASTPW: 6659 if vo < -256 || vo > 252 || vo%4 != 0 { 6660 c.ctxt.Diag("invalid offset %v\n", p) 6661 } 6662 vo /= 4 6663 ret = 0 6664 case ALDPSW: 6665 if vo < -256 || vo > 252 || vo%4 != 0 { 6666 c.ctxt.Diag("invalid offset %v\n", p) 6667 } 6668 vo /= 4 6669 ret = 1 << 30 6670 default: 6671 c.ctxt.Diag("invalid instruction %v\n", p) 6672 } 6673 // check register pair 6674 switch p.As { 6675 case AFLDPD, AFLDPS, AFSTPD, AFSTPS: 6676 if rl < REG_F0 || REG_F31 < rl || rh < REG_F0 || REG_F31 < rh { 6677 c.ctxt.Diag("invalid register pair %v\n", p) 6678 } 6679 case ALDP, ALDPW, ALDPSW: 6680 if rl < REG_R0 || REG_R30 < rl || rh < REG_R0 || REG_R30 < rh { 6681 c.ctxt.Diag("invalid register pair %v\n", p) 6682 } 6683 case ASTP, ASTPW: 6684 if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh { 6685 c.ctxt.Diag("invalid register pair %v\n", p) 6686 } 6687 } 6688 // other conditional flag bits 6689 switch o.scond { 6690 case C_XPOST: 6691 ret |= 1 << 23 6692 case C_XPRE: 6693 ret |= 3 << 23 6694 default: 6695 ret |= 2 << 23 6696 } 6697 ret |= 5<<27 | (ldp&1)<<22 | uint32(vo&0x7f)<<15 | (rh&31)<<10 | (rbase&31)<<5 | (rl & 31) 6698 return ret 6699 } 6700 6701 /* 6702 * size in log2(bytes) 6703 */ 6704 func movesize(a obj.As) int { 6705 switch a { 6706 case AMOVD: 6707 return 3 6708 6709 case AMOVW, AMOVWU: 6710 return 2 6711 6712 case AMOVH, AMOVHU: 6713 return 1 6714 6715 case AMOVB, AMOVBU: 6716 return 0 6717 6718 case AFMOVS: 6719 return 2 6720 6721 case AFMOVD: 6722 return 3 6723 6724 default: 6725 return -1 6726 } 6727 } 6728 6729 // rm is the Rm register value, o is the extension, amount is the left shift value. 6730 func roff(rm int16, o uint32, amount int16) uint32 { 6731 return uint32(rm&31)<<16 | o<<13 | uint32(amount)<<10 6732 } 6733 6734 // encRegShiftOrExt returns the encoding of shifted/extended register, Rx<<n and Rx.UXTW<<n, etc. 6735 func (c *ctxt7) encRegShiftOrExt(a *obj.Addr, r int16) uint32 { 6736 var num, rm int16 6737 num = (r >> 5) & 7 6738 rm = r & 31 6739 switch { 6740 case REG_UXTB <= r && r < REG_UXTH: 6741 return roff(rm, 0, num) 6742 case REG_UXTH <= r && r < REG_UXTW: 6743 return roff(rm, 1, num) 6744 case REG_UXTW <= r && r < REG_UXTX: 6745 if a.Type == obj.TYPE_MEM { 6746 if num == 0 { 6747 return roff(rm, 2, 2) 6748 } else { 6749 return roff(rm, 2, 6) 6750 } 6751 } else { 6752 return roff(rm, 2, num) 6753 } 6754 case REG_UXTX <= r && r < REG_SXTB: 6755 return roff(rm, 3, num) 6756 case REG_SXTB <= r && r < REG_SXTH: 6757 return roff(rm, 4, num) 6758 case REG_SXTH <= r && r < REG_SXTW: 6759 return roff(rm, 5, num) 6760 case REG_SXTW <= r && r < REG_SXTX: 6761 if a.Type == obj.TYPE_MEM { 6762 if num == 0 { 6763 return roff(rm, 6, 2) 6764 } else { 6765 return roff(rm, 6, 6) 6766 } 6767 } else { 6768 return roff(rm, 6, num) 6769 } 6770 case REG_SXTX <= r && r < REG_SPECIAL: 6771 if a.Type == obj.TYPE_MEM { 6772 if num == 0 { 6773 return roff(rm, 7, 2) 6774 } else { 6775 return roff(rm, 7, 6) 6776 } 6777 } else { 6778 return roff(rm, 7, num) 6779 } 6780 case REG_LSL <= r && r < (REG_LSL+1<<8): 6781 return roff(rm, 3, 6) 6782 default: 6783 c.ctxt.Diag("unsupported register extension type.") 6784 } 6785 6786 return 0 6787 }