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