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