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