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