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