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