github.com/dara-project/godist@v0.0.0-20200823115410-e0c80c8f0c78/src/cmd/internal/obj/arm64/asm7.go (about) 1 // cmd/7l/asm.c, cmd/7l/asmout.c, cmd/7l/optab.c, cmd/7l/span.c, cmd/ld/sub.c, cmd/ld/mod.c, from Vita Nuova. 2 // https://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 instoffset int64 53 pc int64 54 pool struct { 55 start uint32 56 size uint32 57 } 58 } 59 60 const ( 61 funcAlign = 16 62 ) 63 64 const ( 65 REGFROM = 1 66 ) 67 68 type Optab struct { 69 as obj.As 70 a1 uint8 71 a2 uint8 72 a3 uint8 73 type_ int8 74 size int8 75 param int16 76 flag int8 77 scond uint16 78 } 79 80 var oprange [ALAST & obj.AMask][]Optab 81 82 var xcmp [C_NCLASS][C_NCLASS]bool 83 84 const ( 85 S32 = 0 << 31 86 S64 = 1 << 31 87 Sbit = 1 << 29 88 LSL0_32 = 2 << 13 89 LSL0_64 = 3 << 13 90 ) 91 92 func OPDP2(x uint32) uint32 { 93 return 0<<30 | 0<<29 | 0xd6<<21 | x<<10 94 } 95 96 func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 { 97 return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15 98 } 99 100 func OPBcc(x uint32) uint32 { 101 return 0x2A<<25 | 0<<24 | 0<<4 | x&15 102 } 103 104 func OPBLR(x uint32) uint32 { 105 /* x=0, JMP; 1, CALL; 2, RET */ 106 return 0x6B<<25 | 0<<23 | x<<21 | 0x1F<<16 | 0<<10 107 } 108 109 func SYSOP(l uint32, op0 uint32, op1 uint32, crn uint32, crm uint32, op2 uint32, rt uint32) uint32 { 110 return 0x354<<22 | l<<21 | op0<<19 | op1<<16 | crn&15<<12 | crm&15<<8 | op2<<5 | rt 111 } 112 113 func SYSHINT(x uint32) uint32 { 114 return SYSOP(0, 0, 3, 2, 0, x, 0x1F) 115 } 116 117 func LDSTR12U(sz uint32, v uint32, opc uint32) uint32 { 118 return sz<<30 | 7<<27 | v<<26 | 1<<24 | opc<<22 119 } 120 121 func LDSTR9S(sz uint32, v uint32, opc uint32) uint32 { 122 return sz<<30 | 7<<27 | v<<26 | 0<<24 | opc<<22 123 } 124 125 func LD2STR(o uint32) uint32 { 126 return o &^ (3 << 22) 127 } 128 129 func LDSTX(sz uint32, o2 uint32, l uint32, o1 uint32, o0 uint32) uint32 { 130 return sz<<30 | 0x8<<24 | o2<<23 | l<<22 | o1<<21 | o0<<15 131 } 132 133 func FPCMP(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 { 134 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<14 | 8<<10 | op2 135 } 136 137 func FPCCMP(m uint32, s uint32, type_ uint32, op uint32) uint32 { 138 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | 1<<10 | op<<4 139 } 140 141 func FPOP1S(m uint32, s uint32, type_ uint32, op uint32) uint32 { 142 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<15 | 0x10<<10 143 } 144 145 func FPOP2S(m uint32, s uint32, type_ uint32, op uint32) uint32 { 146 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<12 | 2<<10 147 } 148 149 func FPCVTI(sf uint32, s uint32, type_ uint32, rmode uint32, op uint32) uint32 { 150 return sf<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | rmode<<19 | op<<16 | 0<<10 151 } 152 153 func ADR(p uint32, o uint32, rt uint32) uint32 { 154 return p<<31 | (o&3)<<29 | 0x10<<24 | ((o>>2)&0x7FFFF)<<5 | rt&31 155 } 156 157 func OPBIT(x uint32) uint32 { 158 return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10 159 } 160 161 const ( 162 LFROM = 1 << 0 163 LTO = 1 << 1 164 ) 165 166 var optab = []Optab{ 167 /* struct Optab: 168 OPCODE, from, prog->reg, to, type,size,param,flag,scond */ 169 {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0}, 170 171 /* arithmetic operations */ 172 {AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 173 {AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 174 {AADC, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 175 {AADC, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 176 {ANEG, C_REG, C_NONE, C_REG, 25, 4, 0, 0, 0}, 177 {ANEG, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0}, 178 {ANGC, C_REG, C_NONE, C_REG, 17, 4, 0, 0, 0}, 179 {ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0}, 180 {AADD, C_ADDCON, C_RSP, C_RSP, 2, 4, 0, 0, 0}, 181 {AADD, C_ADDCON, C_NONE, C_RSP, 2, 4, 0, 0, 0}, 182 {ACMP, C_ADDCON, C_RSP, C_NONE, 2, 4, 0, 0, 0}, 183 {AADD, C_MOVCON, C_RSP, C_RSP, 62, 8, 0, 0, 0}, 184 {AADD, C_MOVCON, C_NONE, C_RSP, 62, 8, 0, 0, 0}, 185 {ACMP, C_MOVCON, C_RSP, C_NONE, 62, 8, 0, 0, 0}, 186 {AADD, C_BITCON, C_RSP, C_RSP, 62, 8, 0, 0, 0}, 187 {AADD, C_BITCON, C_NONE, C_RSP, 62, 8, 0, 0, 0}, 188 {ACMP, C_BITCON, C_RSP, C_NONE, 62, 8, 0, 0, 0}, 189 {AADD, C_VCON, C_RSP, C_RSP, 13, 8, 0, LFROM, 0}, 190 {AADD, C_VCON, C_NONE, C_RSP, 13, 8, 0, LFROM, 0}, 191 {ACMP, C_VCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0}, 192 {AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0}, 193 {AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0}, 194 {AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0}, 195 {ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0}, 196 {ANEG, C_SHIFT, C_NONE, C_REG, 26, 4, 0, 0, 0}, 197 {AADD, C_REG, C_RSP, C_RSP, 27, 4, 0, 0, 0}, 198 {AADD, C_REG, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 199 {ACMP, C_REG, C_RSP, C_NONE, 27, 4, 0, 0, 0}, 200 {AADD, C_EXTREG, C_RSP, C_RSP, 27, 4, 0, 0, 0}, 201 {AADD, C_EXTREG, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 202 {AMVN, C_EXTREG, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 203 {ACMP, C_EXTREG, C_RSP, C_NONE, 27, 4, 0, 0, 0}, 204 {AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 205 {AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 206 207 /* logical operations */ 208 {AAND, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 209 {AAND, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 210 {ABIC, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 211 {ABIC, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 212 {AAND, C_MBCON, C_REG, C_REG, 53, 4, 0, 0, 0}, 213 {AAND, C_MBCON, C_NONE, C_REG, 53, 4, 0, 0, 0}, 214 {ABIC, C_MBCON, C_REG, C_REG, 53, 4, 0, 0, 0}, 215 {ABIC, C_MBCON, C_NONE, C_REG, 53, 4, 0, 0, 0}, 216 {AAND, C_BITCON, C_REG, C_REG, 53, 4, 0, 0, 0}, 217 {AAND, C_BITCON, C_NONE, C_REG, 53, 4, 0, 0, 0}, 218 {ABIC, C_BITCON, C_REG, C_REG, 53, 4, 0, 0, 0}, 219 {ABIC, C_BITCON, C_NONE, C_REG, 53, 4, 0, 0, 0}, 220 {AAND, C_MOVCON, C_REG, C_REG, 62, 8, 0, 0, 0}, 221 {AAND, C_MOVCON, C_NONE, C_REG, 62, 8, 0, 0, 0}, 222 {ABIC, C_MOVCON, C_REG, C_REG, 62, 8, 0, 0, 0}, 223 {ABIC, C_MOVCON, C_NONE, C_REG, 62, 8, 0, 0, 0}, 224 {AAND, C_VCON, C_REG, C_REG, 28, 8, 0, LFROM, 0}, 225 {AAND, C_VCON, C_NONE, C_REG, 28, 8, 0, LFROM, 0}, 226 {ABIC, C_VCON, C_REG, C_REG, 28, 8, 0, LFROM, 0}, 227 {ABIC, C_VCON, C_NONE, C_REG, 28, 8, 0, LFROM, 0}, 228 {AAND, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0}, 229 {AAND, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0}, 230 {ABIC, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0}, 231 {ABIC, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0}, 232 {AMOVD, C_RSP, C_NONE, C_RSP, 24, 4, 0, 0, 0}, 233 {AMVN, C_REG, C_NONE, C_REG, 24, 4, 0, 0, 0}, 234 {AMOVB, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0}, 235 {AMOVBU, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0}, 236 {AMOVH, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVHU */ 237 {AMOVW, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVWU */ 238 /* TODO: MVN C_SHIFT */ 239 240 /* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */ 241 {AMOVW, C_MOVCON, C_NONE, C_REG, 32, 4, 0, 0, 0}, 242 {AMOVD, C_MOVCON, C_NONE, C_REG, 32, 4, 0, 0, 0}, 243 244 // TODO: these don't work properly. 245 // { AMOVW, C_ADDCON, C_NONE, C_REG, 2, 4, 0 , 0}, 246 // { AMOVD, C_ADDCON, C_NONE, C_REG, 2, 4, 0 , 0}, 247 {AMOVW, C_BITCON, C_NONE, C_REG, 32, 4, 0, 0, 0}, 248 {AMOVD, C_BITCON, C_NONE, C_REG, 32, 4, 0, 0, 0}, 249 250 {AMOVK, C_VCON, C_NONE, C_REG, 33, 4, 0, 0, 0}, 251 {AMOVD, C_AACON, C_NONE, C_REG, 4, 4, REGFROM, 0, 0}, 252 {ASDIV, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 253 {ASDIV, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 254 {AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, 255 {ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, 256 {AB, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, 257 {ABL, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0}, 258 {ABL, C_REG, C_NONE, C_REG, 6, 4, 0, 0, 0}, 259 {ABL, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, 260 {obj.ARET, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0}, 261 {obj.ARET, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, 262 {AADRP, C_SBRA, C_NONE, C_REG, 60, 4, 0, 0, 0}, 263 {AADR, C_SBRA, C_NONE, C_REG, 61, 4, 0, 0, 0}, 264 {ABFM, C_VCON, C_REG, C_REG, 42, 4, 0, 0, 0}, 265 {ABFI, C_VCON, C_REG, C_REG, 43, 4, 0, 0, 0}, 266 {AEXTR, C_VCON, C_REG, C_REG, 44, 4, 0, 0, 0}, 267 {ASXTB, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0}, 268 {ACLS, C_REG, C_NONE, C_REG, 46, 4, 0, 0, 0}, 269 {ABEQ, C_NONE, C_NONE, C_SBRA, 7, 4, 0, 0, 0}, 270 {ALSL, C_VCON, C_REG, C_REG, 8, 4, 0, 0, 0}, 271 {ALSL, C_VCON, C_NONE, C_REG, 8, 4, 0, 0, 0}, 272 {ALSL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0}, 273 {ALSL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0}, 274 {ASVC, C_VCON, C_NONE, C_NONE, 10, 4, 0, 0, 0}, 275 {ASVC, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0}, 276 {ADWORD, C_NONE, C_NONE, C_VCON, 11, 8, 0, 0, 0}, 277 {ADWORD, C_NONE, C_NONE, C_LEXT, 11, 8, 0, 0, 0}, 278 {ADWORD, C_NONE, C_NONE, C_ADDR, 11, 8, 0, 0, 0}, 279 {ADWORD, C_NONE, C_NONE, C_LACON, 11, 8, 0, 0, 0}, 280 {AWORD, C_NONE, C_NONE, C_LCON, 14, 4, 0, 0, 0}, 281 {AWORD, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0}, 282 {AWORD, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0}, 283 {AMOVW, C_VCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0}, 284 {AMOVW, C_VCONADDR, C_NONE, C_REG, 68, 8, 0, 0, 0}, 285 {AMOVD, C_VCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0}, 286 {AMOVD, C_VCONADDR, C_NONE, C_REG, 68, 8, 0, 0, 0}, 287 {AMOVB, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 288 {AMOVBU, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 289 {AMOVH, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 290 {AMOVW, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 291 {AMOVD, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 292 {AMOVB, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0}, 293 {AMOVBU, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0}, 294 {AMOVH, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0}, 295 {AMOVW, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0}, 296 {AMOVD, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0}, 297 {AMOVD, C_GOTADDR, C_NONE, C_REG, 71, 8, 0, 0, 0}, 298 {AMOVD, C_TLS_LE, C_NONE, C_REG, 69, 4, 0, 0, 0}, 299 {AMOVD, C_TLS_IE, C_NONE, C_REG, 70, 8, 0, 0, 0}, 300 {AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0}, 301 {AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0}, 302 {AMADD, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0}, 303 {AREM, C_REG, C_REG, C_REG, 16, 8, 0, 0, 0}, 304 {AREM, C_REG, C_NONE, C_REG, 16, 8, 0, 0, 0}, 305 {ACSEL, C_COND, C_REG, C_REG, 18, 4, 0, 0, 0}, /* from3 optional */ 306 {ACSET, C_COND, C_NONE, C_REG, 18, 4, 0, 0, 0}, 307 {ACCMN, C_COND, C_REG, C_VCON, 19, 4, 0, 0, 0}, /* from3 either C_REG or C_VCON */ 308 309 /* scaled 12-bit unsigned displacement store */ 310 {AMOVB, C_REG, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0}, 311 {AMOVB, C_REG, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0}, 312 {AMOVBU, C_REG, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0}, 313 {AMOVBU, C_REG, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0}, 314 315 {AMOVH, C_REG, C_NONE, C_UAUTO8K, 20, 4, REGSP, 0, 0}, 316 {AMOVH, C_REG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0}, 317 {AMOVH, C_REG, C_NONE, C_UOREG8K, 20, 4, 0, 0, 0}, 318 319 {AMOVW, C_REG, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0}, 320 {AMOVW, C_REG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0}, 321 {AMOVW, C_REG, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0}, 322 323 {AVMOVS, C_VREG, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0}, 324 {AVMOVS, C_VREG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0}, 325 {AVMOVS, C_VREG, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0}, 326 327 /* unscaled 9-bit signed displacement store */ 328 {AMOVB, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 329 {AMOVB, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 330 {AMOVBU, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 331 {AMOVBU, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 332 333 {AMOVH, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 334 {AMOVH, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 335 {AMOVW, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 336 {AMOVW, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 337 338 {AMOVD, C_REG, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0}, 339 {AMOVD, C_REG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0}, 340 {AMOVD, C_REG, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0}, 341 {AMOVD, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 342 {AMOVD, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 343 344 /* short displacement load */ 345 {AMOVB, C_UAUTO4K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 346 {AMOVB, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 347 {AMOVB, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0}, 348 {AMOVB, C_UOREG4K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 349 {AMOVB, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 350 351 {AMOVBU, C_UAUTO4K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 352 {AMOVBU, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 353 {AMOVBU, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0}, 354 {AMOVBU, C_UOREG4K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 355 {AMOVBU, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 356 357 {AMOVH, C_UAUTO8K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 358 {AMOVH, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 359 {AMOVH, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0}, 360 {AMOVH, C_UOREG8K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 361 {AMOVH, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 362 363 {AMOVW, C_UAUTO16K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 364 {AMOVW, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 365 {AMOVW, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0}, 366 {AMOVW, C_UOREG16K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 367 {AMOVW, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 368 369 {AMOVD, C_UAUTO32K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 370 {AMOVD, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 371 {AMOVD, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0}, 372 {AMOVD, C_UOREG32K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 373 {AMOVD, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 374 375 {AVMOVS, C_UAUTO16K, C_NONE, C_VREG, 21, 4, REGSP, 0, 0}, 376 {AVMOVS, C_ZOREG, C_NONE, C_VREG, 21, 4, 0, 0, 0}, 377 {AVMOVS, C_UOREG16K, C_NONE, C_VREG, 21, 4, 0, 0, 0}, 378 379 /* long displacement store */ 380 {AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 381 {AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 382 {AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 383 {AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 384 {AMOVH, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 385 {AMOVH, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 386 {AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 387 {AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 388 {AMOVD, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 389 {AMOVD, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 390 391 /* long displacement load */ 392 {AMOVB, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 393 {AMOVB, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 394 {AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 395 {AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 396 {AMOVH, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 397 {AMOVH, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 398 {AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 399 {AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 400 {AMOVD, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 401 {AMOVD, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 402 403 /* load long effective stack address (load int32 offset and add) */ 404 {AMOVD, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0}, 405 406 /* pre/post-indexed load (unscaled, signed 9-bit offset) */ 407 {AMOVD, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 408 {AMOVW, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 409 {AMOVH, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 410 {AMOVB, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 411 {AMOVBU, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 412 {AFMOVS, C_LOREG, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST}, 413 {AFMOVD, C_LOREG, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST}, 414 {AVMOVS, C_LOREG, C_NONE, C_VREG, 22, 4, 0, 0, C_XPOST}, 415 {AMOVD, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 416 {AMOVW, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 417 {AMOVH, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 418 {AMOVB, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 419 {AMOVBU, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 420 {AFMOVS, C_LOREG, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE}, 421 {AFMOVD, C_LOREG, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE}, 422 {AVMOVS, C_LOREG, C_NONE, C_VREG, 22, 4, 0, 0, C_XPRE}, 423 424 /* pre/post-indexed store (unscaled, signed 9-bit offset) */ 425 {AMOVD, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 426 {AMOVW, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 427 {AMOVH, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 428 {AMOVB, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 429 {AMOVBU, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 430 {AFMOVS, C_FREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 431 {AFMOVD, C_FREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 432 {AVMOVS, C_VREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 433 {AMOVD, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 434 {AMOVW, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 435 {AMOVH, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 436 {AMOVB, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 437 {AMOVBU, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 438 {AFMOVS, C_FREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 439 {AFMOVD, C_FREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 440 {AVMOVS, C_VREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 441 442 /* pre/post-indexed/signed-offset load/store register pair 443 (unscaled, signed 10-bit quad-aligned and long offset) */ 444 {ALDP, C_NPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, 445 {ALDP, C_NPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, 446 {ALDP, C_NPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, 447 {ALDP, C_PPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, 448 {ALDP, C_PPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, 449 {ALDP, C_PPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, 450 {ALDP, C_UAUTO4K, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, 451 {ALDP, C_UAUTO4K, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE}, 452 {ALDP, C_UAUTO4K, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST}, 453 {ALDP, C_LAUTO, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0}, 454 {ALDP, C_LAUTO, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE}, 455 {ALDP, C_LAUTO, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST}, 456 {ALDP, C_NPOREG, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, 457 {ALDP, C_NPOREG, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, 458 {ALDP, C_NPOREG, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, 459 {ALDP, C_PPOREG, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, 460 {ALDP, C_PPOREG, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, 461 {ALDP, C_PPOREG, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, 462 {ALDP, C_UOREG4K, C_NONE, C_PAIR, 74, 8, 0, 0, 0}, 463 {ALDP, C_UOREG4K, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE}, 464 {ALDP, C_UOREG4K, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST}, 465 {ALDP, C_LOREG, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0}, 466 {ALDP, C_LOREG, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE}, 467 {ALDP, C_LOREG, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST}, 468 {ALDP, C_ADDR, C_NONE, C_PAIR, 88, 12, 0, 0, 0}, 469 470 {ASTP, C_PAIR, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, 0}, 471 {ASTP, C_PAIR, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPRE}, 472 {ASTP, C_PAIR, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPOST}, 473 {ASTP, C_PAIR, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, 0}, 474 {ASTP, C_PAIR, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPRE}, 475 {ASTP, C_PAIR, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPOST}, 476 {ASTP, C_PAIR, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0}, 477 {ASTP, C_PAIR, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE}, 478 {ASTP, C_PAIR, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST}, 479 {ASTP, C_PAIR, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0}, 480 {ASTP, C_PAIR, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE}, 481 {ASTP, C_PAIR, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST}, 482 {ASTP, C_PAIR, C_NONE, C_NPOREG, 67, 4, 0, 0, 0}, 483 {ASTP, C_PAIR, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPRE}, 484 {ASTP, C_PAIR, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPOST}, 485 {ASTP, C_PAIR, C_NONE, C_PPOREG, 67, 4, 0, 0, 0}, 486 {ASTP, C_PAIR, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPRE}, 487 {ASTP, C_PAIR, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPOST}, 488 {ASTP, C_PAIR, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0}, 489 {ASTP, C_PAIR, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE}, 490 {ASTP, C_PAIR, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST}, 491 {ASTP, C_PAIR, C_NONE, C_LOREG, 77, 12, 0, LTO, 0}, 492 {ASTP, C_PAIR, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE}, 493 {ASTP, C_PAIR, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST}, 494 {ASTP, C_PAIR, C_NONE, C_ADDR, 87, 12, 0, 0, 0}, 495 496 /* special */ 497 {AMOVD, C_SPR, C_NONE, C_REG, 35, 4, 0, 0, 0}, 498 {AMRS, C_SPR, C_NONE, C_REG, 35, 4, 0, 0, 0}, 499 {AMOVD, C_REG, C_NONE, C_SPR, 36, 4, 0, 0, 0}, 500 {AMSR, C_REG, C_NONE, C_SPR, 36, 4, 0, 0, 0}, 501 {AMOVD, C_VCON, C_NONE, C_SPR, 37, 4, 0, 0, 0}, 502 {AMSR, C_VCON, C_NONE, C_SPR, 37, 4, 0, 0, 0}, 503 {AERET, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0}, 504 {AFMOVS, C_FREG, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0}, 505 {AFMOVS, C_FREG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 506 {AFMOVS, C_FREG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0}, 507 {AFMOVS, C_FREG, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0}, 508 {AFMOVS, C_FREG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 509 {AFMOVD, C_FREG, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0}, 510 {AFMOVD, C_FREG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 511 {AFMOVD, C_FREG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0}, 512 {AFMOVD, C_FREG, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0}, 513 {AFMOVD, C_FREG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 514 {AFMOVS, C_UAUTO16K, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 515 {AFMOVS, C_NSAUTO, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 516 {AFMOVS, C_ZOREG, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 517 {AFMOVS, C_UOREG16K, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 518 {AFMOVS, C_NSOREG, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 519 {AFMOVD, C_UAUTO32K, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 520 {AFMOVD, C_NSAUTO, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 521 {AFMOVD, C_ZOREG, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 522 {AFMOVD, C_UOREG32K, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 523 {AFMOVD, C_NSOREG, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 524 {AFMOVS, C_FREG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 525 {AFMOVS, C_FREG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 526 {AFMOVD, C_FREG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 527 {AFMOVD, C_FREG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 528 {AFMOVS, C_LAUTO, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0}, 529 {AFMOVS, C_LOREG, C_NONE, C_FREG, 31, 8, 0, LFROM, 0}, 530 {AFMOVD, C_LAUTO, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0}, 531 {AFMOVD, C_LOREG, C_NONE, C_FREG, 31, 8, 0, LFROM, 0}, 532 {AFMOVS, C_FREG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 533 {AFMOVS, C_ADDR, C_NONE, C_FREG, 65, 12, 0, 0, 0}, 534 {AFMOVD, C_FREG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 535 {AFMOVD, C_ADDR, C_NONE, C_FREG, 65, 12, 0, 0, 0}, 536 {AFADDS, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 537 {AFADDS, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0}, 538 {AFADDS, C_FCON, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 539 {AFADDS, C_FCON, C_FREG, C_FREG, 54, 4, 0, 0, 0}, 540 {AFMOVS, C_FCON, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 541 {AFMOVS, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 542 {AFMOVD, C_FCON, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 543 {AFMOVD, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 544 {AFCVTZSD, C_FREG, C_NONE, C_REG, 29, 4, 0, 0, 0}, 545 {ASCVTFD, C_REG, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 546 {AFMOVS, C_REG, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 547 {AFMOVS, C_FREG, C_NONE, C_REG, 29, 4, 0, 0, 0}, 548 {AFMOVD, C_REG, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 549 {AFMOVD, C_FREG, C_NONE, C_REG, 29, 4, 0, 0, 0}, 550 {AFCMPS, C_FREG, C_FREG, C_NONE, 56, 4, 0, 0, 0}, 551 {AFCMPS, C_FCON, C_FREG, C_NONE, 56, 4, 0, 0, 0}, 552 {AFCCMPS, C_COND, C_FREG, C_VCON, 57, 4, 0, 0, 0}, 553 {AFCSELD, C_COND, C_FREG, C_FREG, 18, 4, 0, 0, 0}, 554 {AFCVTSD, C_FREG, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 555 {ACLREX, C_NONE, C_NONE, C_VCON, 38, 4, 0, 0, 0}, 556 {ACLREX, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0}, 557 {ACBZ, C_REG, C_NONE, C_SBRA, 39, 4, 0, 0, 0}, 558 {ATBZ, C_VCON, C_REG, C_SBRA, 40, 4, 0, 0, 0}, 559 {ASYS, C_VCON, C_NONE, C_NONE, 50, 4, 0, 0, 0}, 560 {ASYS, C_VCON, C_REG, C_NONE, 50, 4, 0, 0, 0}, 561 {ASYSL, C_VCON, C_NONE, C_REG, 50, 4, 0, 0, 0}, 562 {ADMB, C_VCON, C_NONE, C_NONE, 51, 4, 0, 0, 0}, 563 {AHINT, C_VCON, C_NONE, C_NONE, 52, 4, 0, 0, 0}, 564 {ALDAR, C_ZOREG, C_NONE, C_REG, 58, 4, 0, 0, 0}, 565 {ALDXR, C_ZOREG, C_NONE, C_REG, 58, 4, 0, 0, 0}, 566 {ALDAXR, C_ZOREG, C_NONE, C_REG, 58, 4, 0, 0, 0}, 567 {ALDXP, C_ZOREG, C_REG, C_REG, 58, 4, 0, 0, 0}, 568 {ASTLR, C_REG, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // to3=C_NONE 569 {ASTXR, C_REG, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // to3=C_REG 570 {ASTLXR, C_REG, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // to3=C_REG 571 572 // { ASTXP, C_REG, C_NONE, C_ZOREG, 59, 4, 0 , 0}, // TODO(aram): 573 574 {AAESD, C_VREG, C_NONE, C_VREG, 29, 4, 0, 0, 0}, // for compatibility with old code 575 {AAESD, C_ARNG, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, // recommend using the new one for better readability 576 {ASHA1C, C_VREG, C_REG, C_VREG, 1, 4, 0, 0, 0}, 577 {ASHA1C, C_ARNG, C_VREG, C_VREG, 1, 4, 0, 0, 0}, 578 {ASHA1H, C_VREG, C_NONE, C_VREG, 29, 4, 0, 0, 0}, 579 {ASHA1SU0, C_ARNG, C_ARNG, C_ARNG, 1, 4, 0, 0, 0}, 580 {ASHA256H, C_ARNG, C_VREG, C_VREG, 1, 4, 0, 0, 0}, 581 {AVADDP, C_ARNG, C_ARNG, C_ARNG, 72, 4, 0, 0, 0}, 582 {AVADD, C_ARNG, C_ARNG, C_ARNG, 72, 4, 0, 0, 0}, 583 {AVADD, C_VREG, C_VREG, C_VREG, 89, 4, 0, 0, 0}, 584 {AVADD, C_VREG, C_NONE, C_VREG, 89, 4, 0, 0, 0}, 585 {AVLD1, C_ZOREG, C_NONE, C_LIST, 81, 4, 0, 0, 0}, 586 {AVLD1, C_LOREG, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST}, 587 {AVLD1, C_ROFF, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST}, 588 {AVMOV, C_ELEM, C_NONE, C_REG, 73, 4, 0, 0, 0}, 589 {AVMOV, C_REG, C_NONE, C_ARNG, 82, 4, 0, 0, 0}, 590 {AVMOV, C_ARNG, C_NONE, C_ARNG, 83, 4, 0, 0, 0}, 591 {AVMOV, C_REG, C_NONE, C_ELEM, 78, 4, 0, 0, 0}, 592 {AVMOV, C_ELEM, C_NONE, C_VREG, 80, 4, 0, 0, 0}, 593 {AVREV32, C_ARNG, C_NONE, C_ARNG, 83, 4, 0, 0, 0}, 594 {AVST1, C_LIST, C_NONE, C_ZOREG, 84, 4, 0, 0, 0}, 595 {AVST1, C_LIST, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST}, 596 {AVST1, C_LIST, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST}, 597 {AVDUP, C_ELEM, C_NONE, C_ARNG, 79, 4, 0, 0, 0}, 598 {AVADDV, C_ARNG, C_NONE, C_VREG, 85, 4, 0, 0, 0}, 599 {AVMOVI, C_ADDCON, C_NONE, C_ARNG, 86, 4, 0, 0, 0}, 600 601 {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}, 602 {obj.APCDATA, C_VCON, C_NONE, C_VCON, 0, 0, 0, 0, 0}, 603 {obj.AFUNCDATA, C_VCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0}, 604 {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, 605 {obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL 606 {obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL 607 608 {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0}, 609 } 610 611 /* 612 * valid pstate field values, and value to use in instruction 613 */ 614 var pstatefield = []struct { 615 reg int16 616 enc uint32 617 }{ 618 {REG_SPSel, 0<<16 | 4<<12 | 5<<5}, 619 {REG_DAIFSet, 3<<16 | 4<<12 | 6<<5}, 620 {REG_DAIFClr, 3<<16 | 4<<12 | 7<<5}, 621 } 622 623 // the System register values, and value to use in instruction 624 var systemreg = []struct { 625 reg int16 626 enc uint32 627 }{ 628 {REG_ELR_EL1, 8<<16 | 4<<12 | 1<<5}, 629 } 630 631 func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { 632 p := cursym.Func.Text 633 if p == nil || p.Link == nil { // handle external functions and ELF section symbols 634 return 635 } 636 637 if oprange[AAND&obj.AMask] == nil { 638 ctxt.Diag("arm64 ops not initialized, call arm64.buildop first") 639 } 640 641 c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset&0xffffffff) + 8} 642 643 bflag := 1 644 pc := int64(0) 645 p.Pc = pc 646 var m int 647 var o *Optab 648 for p = p.Link; p != nil; p = p.Link { 649 if p.As == ADWORD && (pc&7) != 0 { 650 pc += 4 651 } 652 p.Pc = pc 653 o = c.oplook(p) 654 m = int(o.size) 655 if m == 0 { 656 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA { 657 c.ctxt.Diag("zero-width instruction\n%v", p) 658 } 659 continue 660 } 661 662 switch o.flag & (LFROM | LTO) { 663 case LFROM: 664 c.addpool(p, &p.From) 665 666 case LTO: 667 c.addpool(p, &p.To) 668 break 669 } 670 671 if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */ 672 c.checkpool(p, 0) 673 } 674 pc += int64(m) 675 if c.blitrl != nil { 676 c.checkpool(p, 1) 677 } 678 } 679 680 c.cursym.Size = pc 681 682 /* 683 * if any procedure is large enough to 684 * generate a large SBRA branch, then 685 * generate extra passes putting branches 686 * around jmps to fix. this is rare. 687 */ 688 for bflag != 0 { 689 bflag = 0 690 pc = 0 691 for p = c.cursym.Func.Text.Link; p != nil; p = p.Link { 692 if p.As == ADWORD && (pc&7) != 0 { 693 pc += 4 694 } 695 p.Pc = pc 696 o = c.oplook(p) 697 698 /* very large branches */ 699 if (o.type_ == 7 || o.type_ == 39) && p.Pcond != nil { // 7: BEQ and like, 39: CBZ and like 700 otxt := p.Pcond.Pc - pc 701 if otxt <= -(1<<18)+10 || otxt >= (1<<18)-10 { 702 q := c.newprog() 703 q.Link = p.Link 704 p.Link = q 705 q.As = AB 706 q.To.Type = obj.TYPE_BRANCH 707 q.Pcond = p.Pcond 708 p.Pcond = q 709 q = c.newprog() 710 q.Link = p.Link 711 p.Link = q 712 q.As = AB 713 q.To.Type = obj.TYPE_BRANCH 714 q.Pcond = q.Link.Link 715 bflag = 1 716 } 717 } 718 m = int(o.size) 719 720 if m == 0 { 721 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA { 722 c.ctxt.Diag("zero-width instruction\n%v", p) 723 } 724 continue 725 } 726 727 pc += int64(m) 728 } 729 } 730 731 pc += -pc & (funcAlign - 1) 732 c.cursym.Size = pc 733 734 /* 735 * lay out the code, emitting code and data relocations. 736 */ 737 c.cursym.Grow(c.cursym.Size) 738 bp := c.cursym.P 739 psz := int32(0) 740 var i int 741 var out [6]uint32 742 for p := c.cursym.Func.Text.Link; p != nil; p = p.Link { 743 c.pc = p.Pc 744 o = c.oplook(p) 745 746 // need to align DWORDs on 8-byte boundary. The ISA doesn't 747 // require it, but the various 64-bit loads we generate assume it. 748 if o.as == ADWORD && psz%8 != 0 { 749 bp[3] = 0 750 bp[2] = bp[3] 751 bp[1] = bp[2] 752 bp[0] = bp[1] 753 bp = bp[4:] 754 psz += 4 755 } 756 757 if int(o.size) > 4*len(out) { 758 log.Fatalf("out array in span7 is too small, need at least %d for %v", o.size/4, p) 759 } 760 c.asmout(p, o, out[:]) 761 for i = 0; i < int(o.size/4); i++ { 762 c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i]) 763 bp = bp[4:] 764 psz += 4 765 } 766 } 767 } 768 769 /* 770 * when the first reference to the literal pool threatens 771 * to go out of range of a 1Mb PC-relative offset 772 * drop the pool now, and branch round it. 773 */ 774 func (c *ctxt7) checkpool(p *obj.Prog, skip int) { 775 if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) { 776 c.flushpool(p, skip) 777 } else if p.Link == nil { 778 c.flushpool(p, 2) 779 } 780 } 781 782 func (c *ctxt7) flushpool(p *obj.Prog, skip int) { 783 if c.blitrl != nil { 784 if skip != 0 { 785 if c.ctxt.Debugvlog && skip == 1 { 786 fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start) 787 } 788 q := c.newprog() 789 q.As = AB 790 q.To.Type = obj.TYPE_BRANCH 791 q.Pcond = p.Link 792 q.Link = c.blitrl 793 q.Pos = p.Pos 794 c.blitrl = q 795 } else if p.Pc+int64(c.pool.size)-int64(c.pool.start) < maxPCDisp { 796 return 797 } 798 799 // The line number for constant pool entries doesn't really matter. 800 // We set it to the line number of the preceding instruction so that 801 // there are no deltas to encode in the pc-line tables. 802 for q := c.blitrl; q != nil; q = q.Link { 803 q.Pos = p.Pos 804 } 805 806 c.elitrl.Link = p.Link 807 p.Link = c.blitrl 808 809 c.blitrl = nil /* BUG: should refer back to values until out-of-range */ 810 c.elitrl = nil 811 c.pool.size = 0 812 c.pool.start = 0 813 } 814 } 815 816 /* 817 * TODO: hash 818 */ 819 func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) { 820 cls := c.aclass(a) 821 lit := c.instoffset 822 t := c.newprog() 823 t.As = AWORD 824 sz := 4 825 826 // MOVD foo(SB), R is actually 827 // MOVD addr, REGTMP 828 // MOVD REGTMP, R 829 // where addr is the address of the DWORD containing the address of foo. 830 if p.As == AMOVD && a.Type != obj.TYPE_MEM || cls == C_ADDR || cls == C_VCON || int64(lit) != int64(int32(lit)) || uint64(lit) != uint64(uint32(lit)) { 831 // conservative: don't know if we want signed or unsigned extension. 832 // in case of ambiguity, store 64-bit 833 t.As = ADWORD 834 sz = 8 835 } 836 837 switch cls { 838 // TODO(aram): remove. 839 default: 840 if a.Name != obj.NAME_EXTERN { 841 fmt.Printf("addpool: %v in %v shouldn't go to default case\n", DRconv(cls), p) 842 } 843 844 t.To.Offset = a.Offset 845 t.To.Sym = a.Sym 846 t.To.Type = a.Type 847 t.To.Name = a.Name 848 849 /* This is here because MOV uint12<<12, R is disabled in optab. 850 Because of this, we need to load the constant from memory. */ 851 case C_ADDCON: 852 fallthrough 853 854 case C_PSAUTO, 855 C_PSAUTO_8, 856 C_PPAUTO, 857 C_UAUTO4K_8, 858 C_UAUTO4K_4, 859 C_UAUTO4K_2, 860 C_UAUTO4K, 861 C_UAUTO8K_8, 862 C_UAUTO8K_4, 863 C_UAUTO8K, 864 C_UAUTO16K_8, 865 C_UAUTO16K, 866 C_UAUTO32K, 867 C_NSAUTO, 868 C_NPAUTO, 869 C_LAUTO, 870 C_PPOREG, 871 C_PSOREG, 872 C_PSOREG_8, 873 C_UOREG4K_8, 874 C_UOREG4K_4, 875 C_UOREG4K_2, 876 C_UOREG4K, 877 C_UOREG8K_8, 878 C_UOREG8K_4, 879 C_UOREG8K, 880 C_UOREG16K_8, 881 C_UOREG16K, 882 C_UOREG32K, 883 C_NSOREG, 884 C_NPOREG, 885 C_LOREG, 886 C_LACON, 887 C_LCON, 888 C_VCON: 889 if a.Name == obj.NAME_EXTERN { 890 fmt.Printf("addpool: %v in %v needs reloc\n", DRconv(cls), p) 891 } 892 893 t.To.Type = obj.TYPE_CONST 894 t.To.Offset = lit 895 break 896 } 897 898 for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */ 899 if q.To == t.To { 900 p.Pcond = q 901 return 902 } 903 } 904 905 q := c.newprog() 906 *q = *t 907 q.Pc = int64(c.pool.size) 908 if c.blitrl == nil { 909 c.blitrl = q 910 c.pool.start = uint32(p.Pc) 911 } else { 912 c.elitrl.Link = q 913 } 914 c.elitrl = q 915 c.pool.size = -c.pool.size & (funcAlign - 1) 916 c.pool.size += uint32(sz) 917 p.Pcond = q 918 } 919 920 func (c *ctxt7) regoff(a *obj.Addr) uint32 { 921 c.instoffset = 0 922 c.aclass(a) 923 return uint32(c.instoffset) 924 } 925 926 // Maximum PC-relative displacement. 927 // The actual limit is ±2²⁰, but we are conservative 928 // to avoid needing to recompute the literal pool flush points 929 // as span-dependent jumps are enlarged. 930 const maxPCDisp = 512 * 1024 931 932 // ispcdisp reports whether v is a valid PC-relative displacement. 933 func ispcdisp(v int32) bool { 934 return -maxPCDisp < v && v < maxPCDisp && v&3 == 0 935 } 936 937 func isaddcon(v int64) bool { 938 /* uimm12 or uimm24? */ 939 if v < 0 { 940 return false 941 } 942 if (v & 0xFFF) == 0 { 943 v >>= 12 944 } 945 return v <= 0xFFF 946 } 947 948 // isbitcon returns whether a constant can be encoded into a logical instruction. 949 // bitcon has a binary form of repetition of a bit sequence of length 2, 4, 8, 16, 32, or 64, 950 // which itself is a rotate (w.r.t. the length of the unit) of a sequence of ones. 951 // special cases: 0 and -1 are not bitcon. 952 // this function needs to run against virtually all the constants, so it needs to be fast. 953 // for this reason, bitcon testing and bitcon encoding are separate functions. 954 func isbitcon(x uint64) bool { 955 if x == 1<<64-1 || x == 0 { 956 return false 957 } 958 // determine the period and sign-extend a unit to 64 bits 959 switch { 960 case x != x>>32|x<<32: 961 // period is 64 962 // nothing to do 963 case x != x>>16|x<<48: 964 // period is 32 965 x = uint64(int64(int32(x))) 966 case x != x>>8|x<<56: 967 // period is 16 968 x = uint64(int64(int16(x))) 969 case x != x>>4|x<<60: 970 // period is 8 971 x = uint64(int64(int8(x))) 972 default: 973 // period is 4 or 2, always true 974 // 0001, 0010, 0100, 1000 -- 0001 rotate 975 // 0011, 0110, 1100, 1001 -- 0011 rotate 976 // 0111, 1011, 1101, 1110 -- 0111 rotate 977 // 0101, 1010 -- 01 rotate, repeat 978 return true 979 } 980 return sequenceOfOnes(x) || sequenceOfOnes(^x) 981 } 982 983 // sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros 984 func sequenceOfOnes(x uint64) bool { 985 y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2 986 y += x 987 return (y-1)&y == 0 988 } 989 990 // bitconEncode returns the encoding of a bitcon used in logical instructions 991 // x is known to be a bitcon 992 // a bitcon is a sequence of n ones at low bits (i.e. 1<<n-1), right rotated 993 // by R bits, and repeated with period of 64, 32, 16, 8, 4, or 2. 994 // it is encoded in logical instructions with 3 bitfields 995 // N (1 bit) : R (6 bits) : S (6 bits), where 996 // N=1 -- period=64 997 // N=0, S=0xxxxx -- period=32 998 // N=0, S=10xxxx -- period=16 999 // N=0, S=110xxx -- period=8 1000 // N=0, S=1110xx -- period=4 1001 // N=0, S=11110x -- period=2 1002 // R is the shift amount, low bits of S = n-1 1003 func bitconEncode(x uint64, mode int) uint32 { 1004 var period uint32 1005 // determine the period and sign-extend a unit to 64 bits 1006 switch { 1007 case x != x>>32|x<<32: 1008 period = 64 1009 case x != x>>16|x<<48: 1010 period = 32 1011 x = uint64(int64(int32(x))) 1012 case x != x>>8|x<<56: 1013 period = 16 1014 x = uint64(int64(int16(x))) 1015 case x != x>>4|x<<60: 1016 period = 8 1017 x = uint64(int64(int8(x))) 1018 case x != x>>2|x<<62: 1019 period = 4 1020 x = uint64(int64(x<<60) >> 60) 1021 default: 1022 period = 2 1023 x = uint64(int64(x<<62) >> 62) 1024 } 1025 neg := false 1026 if int64(x) < 0 { 1027 x = ^x 1028 neg = true 1029 } 1030 y := x & -x // lowest set bit of x. 1031 s := log2(y) 1032 n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits 1033 if neg { 1034 // ^x is a sequence of n ones left shifted by s bits 1035 // adjust n, s for x 1036 s = n + s 1037 n = period - n 1038 } 1039 1040 N := uint32(0) 1041 if mode == 64 && period == 64 { 1042 N = 1 1043 } 1044 R := (period - s) & (period - 1) & uint32(mode-1) // shift amount of right rotate 1045 S := (n - 1) | 63&^(period<<1-1) // low bits = #ones - 1, high bits encodes period 1046 return N<<22 | R<<16 | S<<10 1047 } 1048 1049 func log2(x uint64) uint32 { 1050 if x == 0 { 1051 panic("log2 of 0") 1052 } 1053 n := uint32(0) 1054 if x >= 1<<32 { 1055 x >>= 32 1056 n += 32 1057 } 1058 if x >= 1<<16 { 1059 x >>= 16 1060 n += 16 1061 } 1062 if x >= 1<<8 { 1063 x >>= 8 1064 n += 8 1065 } 1066 if x >= 1<<4 { 1067 x >>= 4 1068 n += 4 1069 } 1070 if x >= 1<<2 { 1071 x >>= 2 1072 n += 2 1073 } 1074 if x >= 1<<1 { 1075 x >>= 1 1076 n += 1 1077 } 1078 return n 1079 } 1080 1081 func autoclass(l int64) int { 1082 if l < 0 { 1083 if l >= -256 { 1084 return C_NSAUTO 1085 } 1086 if l >= -512 && (l&7) == 0 { 1087 return C_NPAUTO 1088 } 1089 return C_LAUTO 1090 } 1091 1092 if l <= 255 { 1093 if (l & 7) == 0 { 1094 return C_PSAUTO_8 1095 } 1096 return C_PSAUTO 1097 } 1098 if l <= 504 && l&7 == 0 { 1099 return C_PPAUTO 1100 } 1101 if l <= 4095 { 1102 if l&7 == 0 { 1103 return C_UAUTO4K_8 1104 } 1105 if l&3 == 0 { 1106 return C_UAUTO4K_4 1107 } 1108 if l&1 == 0 { 1109 return C_UAUTO4K_2 1110 } 1111 return C_UAUTO4K 1112 } 1113 if l <= 8190 { 1114 if l&7 == 0 { 1115 return C_UAUTO8K_8 1116 } 1117 if l&3 == 0 { 1118 return C_UAUTO8K_4 1119 } 1120 if l&1 == 0 { 1121 return C_UAUTO8K 1122 } 1123 } 1124 if l <= 16380 { 1125 if l&7 == 0 { 1126 return C_UAUTO16K_8 1127 } 1128 if l&3 == 0 { 1129 return C_UAUTO16K 1130 } 1131 } 1132 if l <= 32760 && (l&7) == 0 { 1133 return C_UAUTO32K 1134 } 1135 return C_LAUTO 1136 } 1137 1138 func oregclass(l int64) int { 1139 if l == 0 { 1140 return C_ZOREG 1141 } 1142 return autoclass(l) - C_NPAUTO + C_NPOREG 1143 } 1144 1145 /* 1146 * given an offset v and a class c (see above) 1147 * return the offset value to use in the instruction, 1148 * scaled if necessary 1149 */ 1150 func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 { 1151 s := 0 1152 if cls >= C_SEXT1 && cls <= C_SEXT16 { 1153 s = cls - C_SEXT1 1154 } else { 1155 switch cls { 1156 case C_UAUTO4K, C_UOREG4K, C_ZOREG: 1157 s = 0 1158 case C_UAUTO8K, C_UOREG8K: 1159 s = 1 1160 case C_UAUTO16K, C_UOREG16K: 1161 s = 2 1162 case C_UAUTO32K, C_UOREG32K: 1163 s = 3 1164 default: 1165 c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p) 1166 } 1167 } 1168 vs := v >> uint(s) 1169 if vs<<uint(s) != v { 1170 c.ctxt.Diag("odd offset: %d\n%v", v, p) 1171 } 1172 return vs 1173 } 1174 1175 /* 1176 * if v contains a single 16-bit value aligned 1177 * on a 16-bit field, and thus suitable for movk/movn, 1178 * return the field index 0 to 3; otherwise return -1 1179 */ 1180 func movcon(v int64) int { 1181 for s := 0; s < 64; s += 16 { 1182 if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 { 1183 return s / 16 1184 } 1185 } 1186 return -1 1187 } 1188 1189 func rclass(r int16) int { 1190 switch { 1191 case REG_R0 <= r && r <= REG_R30: // not 31 1192 return C_REG 1193 case r == REGZERO: 1194 return C_ZCON 1195 case REG_F0 <= r && r <= REG_F31: 1196 return C_FREG 1197 case REG_V0 <= r && r <= REG_V31: 1198 return C_VREG 1199 case COND_EQ <= r && r <= COND_NV: 1200 return C_COND 1201 case r == REGSP: 1202 return C_RSP 1203 case r >= REG_ARNG && r < REG_ELEM: 1204 return C_ARNG 1205 case r >= REG_ELEM && r < REG_ELEM_END: 1206 return C_ELEM 1207 case r >= REG_UXTB && r < REG_SPECIAL: 1208 return C_EXTREG 1209 case r >= REG_SPECIAL: 1210 return C_SPR 1211 } 1212 return C_GOK 1213 } 1214 1215 func (c *ctxt7) aclass(a *obj.Addr) int { 1216 switch a.Type { 1217 case obj.TYPE_NONE: 1218 return C_NONE 1219 1220 case obj.TYPE_REG: 1221 return rclass(a.Reg) 1222 1223 case obj.TYPE_REGREG: 1224 return C_PAIR 1225 1226 case obj.TYPE_SHIFT: 1227 return C_SHIFT 1228 1229 case obj.TYPE_REGLIST: 1230 return C_LIST 1231 1232 case obj.TYPE_MEM: 1233 switch a.Name { 1234 case obj.NAME_EXTERN, obj.NAME_STATIC: 1235 if a.Sym == nil { 1236 break 1237 } 1238 c.instoffset = a.Offset 1239 if a.Sym != nil { // use relocation 1240 if a.Sym.Type == objabi.STLSBSS { 1241 if c.ctxt.Flag_shared { 1242 return C_TLS_IE 1243 } else { 1244 return C_TLS_LE 1245 } 1246 } 1247 return C_ADDR 1248 } 1249 return C_LEXT 1250 1251 case obj.NAME_GOTREF: 1252 return C_GOTADDR 1253 1254 case obj.NAME_AUTO: 1255 if a.Reg == REGSP { 1256 // unset base register for better printing, since 1257 // a.Offset is still relative to pseudo-SP. 1258 a.Reg = obj.REG_NONE 1259 } 1260 c.instoffset = int64(c.autosize) + a.Offset 1261 return autoclass(c.instoffset) 1262 1263 case obj.NAME_PARAM: 1264 if a.Reg == REGSP { 1265 // unset base register for better printing, since 1266 // a.Offset is still relative to pseudo-FP. 1267 a.Reg = obj.REG_NONE 1268 } 1269 c.instoffset = int64(c.autosize) + a.Offset + 8 1270 return autoclass(c.instoffset) 1271 1272 case obj.NAME_NONE: 1273 if a.Index != 0 { 1274 if a.Offset != 0 { 1275 return C_GOK 1276 } 1277 return C_ROFF 1278 } 1279 c.instoffset = a.Offset 1280 return oregclass(c.instoffset) 1281 } 1282 return C_GOK 1283 1284 case obj.TYPE_FCONST: 1285 return C_FCON 1286 1287 case obj.TYPE_TEXTSIZE: 1288 return C_TEXTSIZE 1289 1290 case obj.TYPE_CONST, obj.TYPE_ADDR: 1291 switch a.Name { 1292 case obj.NAME_NONE: 1293 c.instoffset = a.Offset 1294 if a.Reg != 0 && a.Reg != REGZERO { 1295 goto aconsize 1296 } 1297 v := c.instoffset 1298 if v == 0 { 1299 return C_ZCON 1300 } 1301 if isaddcon(v) { 1302 if v <= 0xFFF { 1303 if isbitcon(uint64(v)) { 1304 return C_ABCON0 1305 } 1306 return C_ADDCON0 1307 } 1308 if isbitcon(uint64(v)) { 1309 return C_ABCON 1310 } 1311 return C_ADDCON 1312 } 1313 1314 t := movcon(v) 1315 if t >= 0 { 1316 if isbitcon(uint64(v)) { 1317 return C_MBCON 1318 } 1319 return C_MOVCON 1320 } 1321 1322 t = movcon(^v) 1323 if t >= 0 { 1324 if isbitcon(uint64(v)) { 1325 return C_MBCON 1326 } 1327 return C_MOVCON 1328 } 1329 1330 if isbitcon(uint64(v)) { 1331 return C_BITCON 1332 } 1333 1334 if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) { 1335 return C_LCON 1336 } 1337 return C_VCON 1338 1339 case obj.NAME_EXTERN, obj.NAME_STATIC: 1340 if a.Sym == nil { 1341 break 1342 } 1343 if a.Sym.Type == objabi.STLSBSS { 1344 c.ctxt.Diag("taking address of TLS variable is not supported") 1345 } 1346 c.instoffset = a.Offset 1347 return C_VCONADDR 1348 1349 case obj.NAME_AUTO: 1350 if a.Reg == REGSP { 1351 // unset base register for better printing, since 1352 // a.Offset is still relative to pseudo-SP. 1353 a.Reg = obj.REG_NONE 1354 } 1355 c.instoffset = int64(c.autosize) + a.Offset 1356 goto aconsize 1357 1358 case obj.NAME_PARAM: 1359 if a.Reg == REGSP { 1360 // unset base register for better printing, since 1361 // a.Offset is still relative to pseudo-FP. 1362 a.Reg = obj.REG_NONE 1363 } 1364 c.instoffset = int64(c.autosize) + a.Offset + 8 1365 goto aconsize 1366 } 1367 return C_GOK 1368 1369 aconsize: 1370 if isaddcon(c.instoffset) { 1371 return C_AACON 1372 } 1373 return C_LACON 1374 1375 case obj.TYPE_BRANCH: 1376 return C_SBRA 1377 } 1378 1379 return C_GOK 1380 } 1381 1382 func oclass(a *obj.Addr) int { 1383 return int(a.Class) - 1 1384 } 1385 1386 func (c *ctxt7) oplook(p *obj.Prog) *Optab { 1387 a1 := int(p.Optab) 1388 if a1 != 0 { 1389 return &optab[a1-1] 1390 } 1391 a1 = int(p.From.Class) 1392 if a1 == 0 { 1393 a1 = c.aclass(&p.From) + 1 1394 p.From.Class = int8(a1) 1395 } 1396 1397 a1-- 1398 a3 := int(p.To.Class) 1399 if a3 == 0 { 1400 a3 = c.aclass(&p.To) + 1 1401 p.To.Class = int8(a3) 1402 } 1403 1404 a3-- 1405 a2 := C_NONE 1406 if p.Reg != 0 { 1407 a2 = rclass(p.Reg) 1408 } 1409 1410 if false { 1411 fmt.Printf("oplook %v %d %d %d\n", p.As, a1, a2, a3) 1412 fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type) 1413 } 1414 1415 ops := oprange[p.As&obj.AMask] 1416 c1 := &xcmp[a1] 1417 c2 := &xcmp[a2] 1418 c3 := &xcmp[a3] 1419 c4 := &xcmp[p.Scond>>5] 1420 for i := range ops { 1421 op := &ops[i] 1422 if (int(op.a2) == a2 || c2[op.a2]) && c4[op.scond>>5] && c1[op.a1] && c3[op.a3] { 1423 p.Optab = uint16(cap(optab) - cap(ops) + i + 1) 1424 return op 1425 } 1426 } 1427 1428 c.ctxt.Diag("illegal combination: %v %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.To.Type) 1429 if ops == nil { 1430 ops = optab 1431 } 1432 return &ops[0] 1433 } 1434 1435 func cmp(a int, b int) bool { 1436 if a == b { 1437 return true 1438 } 1439 switch a { 1440 case C_RSP: 1441 if b == C_REG { 1442 return true 1443 } 1444 1445 case C_REG: 1446 if b == C_ZCON { 1447 return true 1448 } 1449 1450 case C_ADDCON0: 1451 if b == C_ZCON || b == C_ABCON0 { 1452 return true 1453 } 1454 1455 case C_ADDCON: 1456 if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON { 1457 return true 1458 } 1459 1460 case C_BITCON: 1461 if b == C_ABCON0 || b == C_ABCON || b == C_MBCON { 1462 return true 1463 } 1464 1465 case C_MOVCON: 1466 if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 { 1467 return true 1468 } 1469 1470 case C_LCON: 1471 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 { 1472 return true 1473 } 1474 1475 case C_VCON: 1476 return cmp(C_LCON, b) 1477 1478 case C_LACON: 1479 if b == C_AACON { 1480 return true 1481 } 1482 1483 case C_SEXT2: 1484 if b == C_SEXT1 { 1485 return true 1486 } 1487 1488 case C_SEXT4: 1489 if b == C_SEXT1 || b == C_SEXT2 { 1490 return true 1491 } 1492 1493 case C_SEXT8: 1494 if b >= C_SEXT1 && b <= C_SEXT4 { 1495 return true 1496 } 1497 1498 case C_SEXT16: 1499 if b >= C_SEXT1 && b <= C_SEXT8 { 1500 return true 1501 } 1502 1503 case C_LEXT: 1504 if b >= C_SEXT1 && b <= C_SEXT16 { 1505 return true 1506 } 1507 1508 case C_PSAUTO: 1509 if b == C_PSAUTO_8 { 1510 return true 1511 } 1512 1513 case C_PPAUTO: 1514 if b == C_PSAUTO_8 { 1515 return true 1516 } 1517 1518 case C_UAUTO4K: 1519 switch b { 1520 case C_PSAUTO, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8: 1521 return true 1522 } 1523 1524 case C_UAUTO8K: 1525 switch b { 1526 case C_PSAUTO, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8: 1527 return true 1528 } 1529 1530 case C_UAUTO16K: 1531 switch b { 1532 case C_PSAUTO, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO16K_8: 1533 return true 1534 } 1535 1536 case C_UAUTO32K: 1537 switch b { 1538 case C_PSAUTO, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_8, C_UAUTO8K_8, C_UAUTO16K_8: 1539 return true 1540 } 1541 1542 case C_NPAUTO: 1543 return cmp(C_NSAUTO, b) 1544 1545 case C_LAUTO: 1546 switch b { 1547 case C_PSAUTO, C_PSAUTO_8, C_PPAUTO, 1548 C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, 1549 C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8, 1550 C_UAUTO16K, C_UAUTO16K_8, 1551 C_UAUTO32K: 1552 return true 1553 } 1554 return cmp(C_NPAUTO, b) 1555 1556 case C_PSOREG: 1557 if b == C_ZOREG || b == C_PSOREG_8 { 1558 return true 1559 } 1560 1561 case C_PPOREG: 1562 switch b { 1563 case C_ZOREG, C_PSOREG_8: 1564 return true 1565 } 1566 1567 case C_UOREG4K: 1568 switch b { 1569 case C_ZOREG, C_PSOREG_8, C_PSOREG, C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8: 1570 return true 1571 } 1572 1573 case C_UOREG8K: 1574 switch b { 1575 case C_ZOREG, C_PSOREG_8, C_PSOREG, C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG8K_4, C_UOREG8K_8: 1576 return true 1577 } 1578 1579 case C_UOREG16K: 1580 switch b { 1581 case C_ZOREG, C_PSOREG_8, C_PSOREG, C_PPOREG, C_UOREG4K_4, C_UOREG4K_8, C_UOREG8K_4, C_UOREG8K_8, C_UOREG16K_8: 1582 return true 1583 } 1584 1585 case C_UOREG32K: 1586 switch b { 1587 case C_ZOREG, C_PSOREG_8, C_PSOREG, C_PPOREG, C_UOREG4K_8, C_UOREG8K_8, C_UOREG16K_8: 1588 return true 1589 } 1590 1591 case C_NPOREG: 1592 return cmp(C_NSOREG, b) 1593 1594 case C_LOREG: 1595 switch b { 1596 case C_ZOREG, C_PSOREG_8, C_PSOREG, C_PPOREG, 1597 C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, 1598 C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8, 1599 C_UOREG16K, C_UOREG16K_8, 1600 C_UOREG32K: 1601 return true 1602 } 1603 return cmp(C_NPOREG, b) 1604 1605 case C_LBRA: 1606 if b == C_SBRA { 1607 return true 1608 } 1609 } 1610 1611 return false 1612 } 1613 1614 type ocmp []Optab 1615 1616 func (x ocmp) Len() int { 1617 return len(x) 1618 } 1619 1620 func (x ocmp) Swap(i, j int) { 1621 x[i], x[j] = x[j], x[i] 1622 } 1623 1624 func (x ocmp) Less(i, j int) bool { 1625 p1 := &x[i] 1626 p2 := &x[j] 1627 if p1.as != p2.as { 1628 return p1.as < p2.as 1629 } 1630 if p1.a1 != p2.a1 { 1631 return p1.a1 < p2.a1 1632 } 1633 if p1.a2 != p2.a2 { 1634 return p1.a2 < p2.a2 1635 } 1636 if p1.a3 != p2.a3 { 1637 return p1.a3 < p2.a3 1638 } 1639 if p1.scond != p2.scond { 1640 return p1.scond < p2.scond 1641 } 1642 return false 1643 } 1644 1645 func oprangeset(a obj.As, t []Optab) { 1646 oprange[a&obj.AMask] = t 1647 } 1648 1649 func buildop(ctxt *obj.Link) { 1650 if oprange[AAND&obj.AMask] != nil { 1651 // Already initialized; stop now. 1652 // This happens in the cmd/asm tests, 1653 // each of which re-initializes the arch. 1654 return 1655 } 1656 1657 var n int 1658 for i := 0; i < C_GOK; i++ { 1659 for n = 0; n < C_GOK; n++ { 1660 if cmp(n, i) { 1661 xcmp[i][n] = true 1662 } 1663 } 1664 } 1665 for n = 0; optab[n].as != obj.AXXX; n++ { 1666 } 1667 sort.Sort(ocmp(optab[:n])) 1668 for i := 0; i < n; i++ { 1669 r := optab[i].as 1670 start := i 1671 for optab[i].as == r { 1672 i++ 1673 } 1674 t := optab[start:i] 1675 i-- 1676 oprangeset(r, t) 1677 switch r { 1678 default: 1679 ctxt.Diag("unknown op in build: %v", r) 1680 ctxt.DiagFlush() 1681 log.Fatalf("bad code") 1682 1683 case AADD: 1684 oprangeset(AADDS, t) 1685 oprangeset(ASUB, t) 1686 oprangeset(ASUBS, t) 1687 oprangeset(AADDW, t) 1688 oprangeset(AADDSW, t) 1689 oprangeset(ASUBW, t) 1690 oprangeset(ASUBSW, t) 1691 1692 case AAND: /* logical immediate, logical shifted register */ 1693 oprangeset(AANDS, t) 1694 1695 oprangeset(AANDSW, t) 1696 oprangeset(AANDW, t) 1697 oprangeset(AEOR, t) 1698 oprangeset(AEORW, t) 1699 oprangeset(AORR, t) 1700 oprangeset(AORRW, t) 1701 1702 case ABIC: /* only logical shifted register */ 1703 oprangeset(ABICS, t) 1704 1705 oprangeset(ABICSW, t) 1706 oprangeset(ABICW, t) 1707 oprangeset(AEON, t) 1708 oprangeset(AEONW, t) 1709 oprangeset(AORN, t) 1710 oprangeset(AORNW, t) 1711 1712 case ANEG: 1713 oprangeset(ANEGS, t) 1714 oprangeset(ANEGSW, t) 1715 oprangeset(ANEGW, t) 1716 1717 case AADC: /* rn=Rd */ 1718 oprangeset(AADCW, t) 1719 1720 oprangeset(AADCS, t) 1721 oprangeset(AADCSW, t) 1722 oprangeset(ASBC, t) 1723 oprangeset(ASBCW, t) 1724 oprangeset(ASBCS, t) 1725 oprangeset(ASBCSW, t) 1726 1727 case ANGC: /* rn=REGZERO */ 1728 oprangeset(ANGCW, t) 1729 1730 oprangeset(ANGCS, t) 1731 oprangeset(ANGCSW, t) 1732 1733 case ACMP: 1734 oprangeset(ACMPW, t) 1735 oprangeset(ACMN, t) 1736 oprangeset(ACMNW, t) 1737 1738 case ATST: 1739 oprangeset(ATSTW, t) 1740 1741 /* register/register, and shifted */ 1742 case AMVN: 1743 oprangeset(AMVNW, t) 1744 1745 case AMOVK: 1746 oprangeset(AMOVKW, t) 1747 oprangeset(AMOVN, t) 1748 oprangeset(AMOVNW, t) 1749 oprangeset(AMOVZ, t) 1750 oprangeset(AMOVZW, t) 1751 1752 case ABEQ: 1753 oprangeset(ABNE, t) 1754 oprangeset(ABCS, t) 1755 oprangeset(ABHS, t) 1756 oprangeset(ABCC, t) 1757 oprangeset(ABLO, t) 1758 oprangeset(ABMI, t) 1759 oprangeset(ABPL, t) 1760 oprangeset(ABVS, t) 1761 oprangeset(ABVC, t) 1762 oprangeset(ABHI, t) 1763 oprangeset(ABLS, t) 1764 oprangeset(ABGE, t) 1765 oprangeset(ABLT, t) 1766 oprangeset(ABGT, t) 1767 oprangeset(ABLE, t) 1768 1769 case ALSL: 1770 oprangeset(ALSLW, t) 1771 oprangeset(ALSR, t) 1772 oprangeset(ALSRW, t) 1773 oprangeset(AASR, t) 1774 oprangeset(AASRW, t) 1775 oprangeset(AROR, t) 1776 oprangeset(ARORW, t) 1777 1778 case ACLS: 1779 oprangeset(ACLSW, t) 1780 oprangeset(ACLZ, t) 1781 oprangeset(ACLZW, t) 1782 oprangeset(ARBIT, t) 1783 oprangeset(ARBITW, t) 1784 oprangeset(AREV, t) 1785 oprangeset(AREVW, t) 1786 oprangeset(AREV16, t) 1787 oprangeset(AREV16W, t) 1788 oprangeset(AREV32, t) 1789 1790 case ASDIV: 1791 oprangeset(ASDIVW, t) 1792 oprangeset(AUDIV, t) 1793 oprangeset(AUDIVW, t) 1794 oprangeset(ACRC32B, t) 1795 oprangeset(ACRC32CB, t) 1796 oprangeset(ACRC32CH, t) 1797 oprangeset(ACRC32CW, t) 1798 oprangeset(ACRC32CX, t) 1799 oprangeset(ACRC32H, t) 1800 oprangeset(ACRC32W, t) 1801 oprangeset(ACRC32X, t) 1802 1803 case AMADD: 1804 oprangeset(AMADDW, t) 1805 oprangeset(AMSUB, t) 1806 oprangeset(AMSUBW, t) 1807 oprangeset(ASMADDL, t) 1808 oprangeset(ASMSUBL, t) 1809 oprangeset(AUMADDL, t) 1810 oprangeset(AUMSUBL, t) 1811 1812 case AREM: 1813 oprangeset(AREMW, t) 1814 oprangeset(AUREM, t) 1815 oprangeset(AUREMW, t) 1816 1817 case AMUL: 1818 oprangeset(AMULW, t) 1819 oprangeset(AMNEG, t) 1820 oprangeset(AMNEGW, t) 1821 oprangeset(ASMNEGL, t) 1822 oprangeset(ASMULL, t) 1823 oprangeset(ASMULH, t) 1824 oprangeset(AUMNEGL, t) 1825 oprangeset(AUMULH, t) 1826 oprangeset(AUMULL, t) 1827 1828 case AMOVB: 1829 oprangeset(AMOVBU, t) 1830 1831 case AMOVH: 1832 oprangeset(AMOVHU, t) 1833 1834 case AMOVW: 1835 oprangeset(AMOVWU, t) 1836 1837 case ABFM: 1838 oprangeset(ABFMW, t) 1839 oprangeset(ASBFM, t) 1840 oprangeset(ASBFMW, t) 1841 oprangeset(AUBFM, t) 1842 oprangeset(AUBFMW, t) 1843 1844 case ABFI: 1845 oprangeset(ABFIW, t) 1846 oprangeset(ABFXIL, t) 1847 oprangeset(ABFXILW, t) 1848 oprangeset(ASBFIZ, t) 1849 oprangeset(ASBFIZW, t) 1850 oprangeset(ASBFX, t) 1851 oprangeset(ASBFXW, t) 1852 oprangeset(AUBFIZ, t) 1853 oprangeset(AUBFIZW, t) 1854 oprangeset(AUBFX, t) 1855 oprangeset(AUBFXW, t) 1856 1857 case AEXTR: 1858 oprangeset(AEXTRW, t) 1859 1860 case ASXTB: 1861 oprangeset(ASXTBW, t) 1862 oprangeset(ASXTH, t) 1863 oprangeset(ASXTHW, t) 1864 oprangeset(ASXTW, t) 1865 oprangeset(AUXTB, t) 1866 oprangeset(AUXTH, t) 1867 oprangeset(AUXTW, t) 1868 oprangeset(AUXTBW, t) 1869 oprangeset(AUXTHW, t) 1870 1871 case ACCMN: 1872 oprangeset(ACCMNW, t) 1873 oprangeset(ACCMP, t) 1874 oprangeset(ACCMPW, t) 1875 1876 case ACSEL: 1877 oprangeset(ACSELW, t) 1878 oprangeset(ACSINC, t) 1879 oprangeset(ACSINCW, t) 1880 oprangeset(ACSINV, t) 1881 oprangeset(ACSINVW, t) 1882 oprangeset(ACSNEG, t) 1883 oprangeset(ACSNEGW, t) 1884 1885 // aliases Rm=Rn, !cond 1886 oprangeset(ACINC, t) 1887 1888 oprangeset(ACINCW, t) 1889 oprangeset(ACINV, t) 1890 oprangeset(ACINVW, t) 1891 oprangeset(ACNEG, t) 1892 oprangeset(ACNEGW, t) 1893 1894 // aliases, Rm=Rn=REGZERO, !cond 1895 case ACSET: 1896 oprangeset(ACSETW, t) 1897 1898 oprangeset(ACSETM, t) 1899 oprangeset(ACSETMW, t) 1900 1901 case AMOVD, 1902 AMOVBU, 1903 AB, 1904 ABL, 1905 AWORD, 1906 ADWORD, 1907 obj.ARET, 1908 obj.ATEXT, 1909 ASTP, 1910 ALDP: 1911 break 1912 1913 case AERET: 1914 oprangeset(AWFE, t) 1915 oprangeset(AWFI, t) 1916 oprangeset(AYIELD, t) 1917 oprangeset(ASEV, t) 1918 oprangeset(ASEVL, t) 1919 oprangeset(ADRPS, t) 1920 1921 case ACBZ: 1922 oprangeset(ACBZW, t) 1923 oprangeset(ACBNZ, t) 1924 oprangeset(ACBNZW, t) 1925 1926 case ATBZ: 1927 oprangeset(ATBNZ, t) 1928 1929 case AADR, AADRP: 1930 break 1931 1932 case ACLREX: 1933 break 1934 1935 case ASVC: 1936 oprangeset(AHVC, t) 1937 oprangeset(AHLT, t) 1938 oprangeset(ASMC, t) 1939 oprangeset(ABRK, t) 1940 oprangeset(ADCPS1, t) 1941 oprangeset(ADCPS2, t) 1942 oprangeset(ADCPS3, t) 1943 1944 case AFADDS: 1945 oprangeset(AFADDD, t) 1946 oprangeset(AFSUBS, t) 1947 oprangeset(AFSUBD, t) 1948 oprangeset(AFMULS, t) 1949 oprangeset(AFMULD, t) 1950 oprangeset(AFNMULS, t) 1951 oprangeset(AFNMULD, t) 1952 oprangeset(AFDIVS, t) 1953 oprangeset(AFMAXD, t) 1954 oprangeset(AFMAXS, t) 1955 oprangeset(AFMIND, t) 1956 oprangeset(AFMINS, t) 1957 oprangeset(AFMAXNMD, t) 1958 oprangeset(AFMAXNMS, t) 1959 oprangeset(AFMINNMD, t) 1960 oprangeset(AFMINNMS, t) 1961 oprangeset(AFDIVD, t) 1962 1963 case AFCVTSD: 1964 oprangeset(AFCVTDS, t) 1965 oprangeset(AFABSD, t) 1966 oprangeset(AFABSS, t) 1967 oprangeset(AFNEGD, t) 1968 oprangeset(AFNEGS, t) 1969 oprangeset(AFSQRTD, t) 1970 oprangeset(AFSQRTS, t) 1971 oprangeset(AFRINTNS, t) 1972 oprangeset(AFRINTND, t) 1973 oprangeset(AFRINTPS, t) 1974 oprangeset(AFRINTPD, t) 1975 oprangeset(AFRINTMS, t) 1976 oprangeset(AFRINTMD, t) 1977 oprangeset(AFRINTZS, t) 1978 oprangeset(AFRINTZD, t) 1979 oprangeset(AFRINTAS, t) 1980 oprangeset(AFRINTAD, t) 1981 oprangeset(AFRINTXS, t) 1982 oprangeset(AFRINTXD, t) 1983 oprangeset(AFRINTIS, t) 1984 oprangeset(AFRINTID, t) 1985 oprangeset(AFCVTDH, t) 1986 oprangeset(AFCVTHS, t) 1987 oprangeset(AFCVTHD, t) 1988 oprangeset(AFCVTSH, t) 1989 1990 case AFCMPS: 1991 oprangeset(AFCMPD, t) 1992 oprangeset(AFCMPES, t) 1993 oprangeset(AFCMPED, t) 1994 1995 case AFCCMPS: 1996 oprangeset(AFCCMPD, t) 1997 oprangeset(AFCCMPES, t) 1998 oprangeset(AFCCMPED, t) 1999 2000 case AFCSELD: 2001 oprangeset(AFCSELS, t) 2002 2003 case AFMOVS, AFMOVD: 2004 break 2005 2006 case AFCVTZSD: 2007 oprangeset(AFCVTZSDW, t) 2008 oprangeset(AFCVTZSS, t) 2009 oprangeset(AFCVTZSSW, t) 2010 oprangeset(AFCVTZUD, t) 2011 oprangeset(AFCVTZUDW, t) 2012 oprangeset(AFCVTZUS, t) 2013 oprangeset(AFCVTZUSW, t) 2014 2015 case ASCVTFD: 2016 oprangeset(ASCVTFS, t) 2017 oprangeset(ASCVTFWD, t) 2018 oprangeset(ASCVTFWS, t) 2019 oprangeset(AUCVTFD, t) 2020 oprangeset(AUCVTFS, t) 2021 oprangeset(AUCVTFWD, t) 2022 oprangeset(AUCVTFWS, t) 2023 2024 case ASYS: 2025 oprangeset(AAT, t) 2026 oprangeset(ADC, t) 2027 oprangeset(AIC, t) 2028 oprangeset(ATLBI, t) 2029 2030 case ASYSL, AHINT: 2031 break 2032 2033 case ADMB: 2034 oprangeset(ADSB, t) 2035 oprangeset(AISB, t) 2036 2037 case AMRS, AMSR: 2038 break 2039 2040 case ALDAR: 2041 oprangeset(ALDARW, t) 2042 fallthrough 2043 2044 case ALDXR: 2045 oprangeset(ALDXRB, t) 2046 oprangeset(ALDXRH, t) 2047 oprangeset(ALDXRW, t) 2048 2049 case ALDAXR: 2050 oprangeset(ALDAXRB, t) 2051 oprangeset(ALDAXRH, t) 2052 oprangeset(ALDAXRW, t) 2053 2054 case ALDXP: 2055 oprangeset(ALDXPW, t) 2056 2057 case ASTLR: 2058 oprangeset(ASTLRW, t) 2059 2060 case ASTXR: 2061 oprangeset(ASTXRB, t) 2062 oprangeset(ASTXRH, t) 2063 oprangeset(ASTXRW, t) 2064 2065 case ASTLXR: 2066 oprangeset(ASTLXRB, t) 2067 oprangeset(ASTLXRH, t) 2068 oprangeset(ASTLXRW, t) 2069 2070 case ASTXP: 2071 oprangeset(ASTXPW, t) 2072 2073 case AVADDP: 2074 oprangeset(AVAND, t) 2075 oprangeset(AVCMEQ, t) 2076 oprangeset(AVORR, t) 2077 oprangeset(AVEOR, t) 2078 2079 case AVADD: 2080 oprangeset(AVSUB, t) 2081 2082 case AAESD: 2083 oprangeset(AAESE, t) 2084 oprangeset(AAESMC, t) 2085 oprangeset(AAESIMC, t) 2086 oprangeset(ASHA1SU1, t) 2087 oprangeset(ASHA256SU0, t) 2088 2089 case ASHA1C: 2090 oprangeset(ASHA1P, t) 2091 oprangeset(ASHA1M, t) 2092 2093 case ASHA256H: 2094 oprangeset(ASHA256H2, t) 2095 2096 case ASHA1SU0: 2097 oprangeset(ASHA256SU1, t) 2098 2099 case AVADDV: 2100 oprangeset(AVUADDLV, t) 2101 2102 case ASHA1H, 2103 AVMOV, 2104 AVLD1, 2105 AVREV32, 2106 AVST1, 2107 AVDUP, 2108 AVMOVS, 2109 AVMOVI: 2110 break 2111 2112 case obj.ANOP, 2113 obj.AUNDEF, 2114 obj.AFUNCDATA, 2115 obj.APCDATA, 2116 obj.ADUFFZERO, 2117 obj.ADUFFCOPY: 2118 break 2119 } 2120 } 2121 } 2122 2123 func (c *ctxt7) chipfloat7(e float64) int { 2124 ei := math.Float64bits(e) 2125 l := uint32(int32(ei)) 2126 h := uint32(int32(ei >> 32)) 2127 2128 if l != 0 || h&0xffff != 0 { 2129 return -1 2130 } 2131 h1 := h & 0x7fc00000 2132 if h1 != 0x40000000 && h1 != 0x3fc00000 { 2133 return -1 2134 } 2135 n := 0 2136 2137 // sign bit (a) 2138 if h&0x80000000 != 0 { 2139 n |= 1 << 7 2140 } 2141 2142 // exp sign bit (b) 2143 if h1 == 0x3fc00000 { 2144 n |= 1 << 6 2145 } 2146 2147 // rest of exp and mantissa (cd-efgh) 2148 n |= int((h >> 16) & 0x3f) 2149 2150 //print("match %.8lux %.8lux %d\n", l, h, n); 2151 return n 2152 } 2153 2154 /* form offset parameter to SYS; special register number */ 2155 func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int { 2156 return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5 2157 } 2158 2159 func SYSARG4(op1 int, Cn int, Cm int, op2 int) int { 2160 return SYSARG5(0, op1, Cn, Cm, op2) 2161 } 2162 2163 func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { 2164 o1 := uint32(0) 2165 o2 := uint32(0) 2166 o3 := uint32(0) 2167 o4 := uint32(0) 2168 o5 := uint32(0) 2169 if false { /*debug['P']*/ 2170 fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_) 2171 } 2172 switch o.type_ { 2173 default: 2174 c.ctxt.Diag("%v: unknown asm %d", p, o.type_) 2175 2176 case 0: /* pseudo ops */ 2177 break 2178 2179 case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */ 2180 o1 = c.oprrr(p, p.As) 2181 2182 rf := int(p.From.Reg) 2183 rt := int(p.To.Reg) 2184 r := int(p.Reg) 2185 if p.To.Type == obj.TYPE_NONE { 2186 rt = REGZERO 2187 } 2188 if r == 0 { 2189 r = rt 2190 } 2191 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 2192 2193 case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */ 2194 o1 = c.opirr(p, p.As) 2195 2196 rt := int(p.To.Reg) 2197 if p.To.Type == obj.TYPE_NONE { 2198 if (o1 & Sbit) == 0 { 2199 c.ctxt.Diag("ineffective ZR destination\n%v", p) 2200 } 2201 rt = REGZERO 2202 } 2203 2204 r := int(p.Reg) 2205 if r == 0 { 2206 r = rt 2207 } 2208 v := int32(c.regoff(&p.From)) 2209 o1 = c.oaddi(p, int32(o1), v, r, rt) 2210 2211 case 3: /* op R<<n[,R],R (shifted register) */ 2212 o1 = c.oprrr(p, p.As) 2213 2214 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 2215 rt := int(p.To.Reg) 2216 if p.To.Type == obj.TYPE_NONE { 2217 rt = REGZERO 2218 } 2219 r := int(p.Reg) 2220 if p.As == AMVN || p.As == AMVNW { 2221 r = REGZERO 2222 } else if r == 0 { 2223 r = rt 2224 } 2225 o1 |= (uint32(r&31) << 5) | uint32(rt&31) 2226 2227 case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R */ 2228 o1 = c.opirr(p, p.As) 2229 2230 rt := int(p.To.Reg) 2231 r := int(o.param) 2232 if r == 0 { 2233 r = REGZERO 2234 } else if r == REGFROM { 2235 r = int(p.From.Reg) 2236 } 2237 if r == 0 { 2238 r = REGSP 2239 } 2240 v := int32(c.regoff(&p.From)) 2241 if (v & 0xFFF000) != 0 { 2242 v >>= 12 2243 o1 |= 1 << 22 /* shift, by 12 */ 2244 } 2245 2246 o1 |= ((uint32(v) & 0xFFF) << 10) | (uint32(r&31) << 5) | uint32(rt&31) 2247 2248 case 5: /* b s; bl s */ 2249 o1 = c.opbra(p, p.As) 2250 2251 if p.To.Sym == nil { 2252 o1 |= uint32(c.brdist(p, 0, 26, 2)) 2253 break 2254 } 2255 2256 rel := obj.Addrel(c.cursym) 2257 rel.Off = int32(c.pc) 2258 rel.Siz = 4 2259 rel.Sym = p.To.Sym 2260 rel.Add = p.To.Offset 2261 rel.Type = objabi.R_CALLARM64 2262 2263 case 6: /* b ,O(R); bl ,O(R) */ 2264 o1 = c.opbrr(p, p.As) 2265 2266 o1 |= uint32(p.To.Reg&31) << 5 2267 rel := obj.Addrel(c.cursym) 2268 rel.Off = int32(c.pc) 2269 rel.Siz = 0 2270 rel.Type = objabi.R_CALLIND 2271 2272 case 7: /* beq s */ 2273 o1 = c.opbra(p, p.As) 2274 2275 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5) 2276 2277 case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */ 2278 rt := int(p.To.Reg) 2279 2280 rf := int(p.Reg) 2281 if rf == 0 { 2282 rf = rt 2283 } 2284 v := int32(p.From.Offset) 2285 switch p.As { 2286 case AASR: 2287 o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt) 2288 2289 case AASRW: 2290 o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt) 2291 2292 case ALSL: 2293 o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt) 2294 2295 case ALSLW: 2296 o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt) 2297 2298 case ALSR: 2299 o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt) 2300 2301 case ALSRW: 2302 o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt) 2303 2304 case AROR: 2305 o1 = c.opextr(p, AEXTR, v, rf, rf, rt) 2306 2307 case ARORW: 2308 o1 = c.opextr(p, AEXTRW, v, rf, rf, rt) 2309 2310 default: 2311 c.ctxt.Diag("bad shift $con\n%v", p) 2312 break 2313 } 2314 2315 case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */ 2316 o1 = c.oprrr(p, p.As) 2317 2318 r := int(p.Reg) 2319 if r == 0 { 2320 r = int(p.To.Reg) 2321 } 2322 o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31) 2323 2324 case 10: /* brk/hvc/.../svc [$con] */ 2325 o1 = c.opimm(p, p.As) 2326 2327 if p.From.Type != obj.TYPE_NONE { 2328 o1 |= uint32((p.From.Offset & 0xffff) << 5) 2329 } 2330 2331 case 11: /* dword */ 2332 c.aclass(&p.To) 2333 2334 o1 = uint32(c.instoffset) 2335 o2 = uint32(c.instoffset >> 32) 2336 if p.To.Sym != nil { 2337 rel := obj.Addrel(c.cursym) 2338 rel.Off = int32(c.pc) 2339 rel.Siz = 8 2340 rel.Sym = p.To.Sym 2341 rel.Add = p.To.Offset 2342 rel.Type = objabi.R_ADDR 2343 o2 = 0 2344 o1 = o2 2345 } 2346 2347 case 12: /* movT $vcon, reg */ 2348 o1 = c.omovlit(p.As, p, &p.From, int(p.To.Reg)) 2349 2350 case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */ 2351 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 2352 2353 if !(o1 != 0) { 2354 break 2355 } 2356 rt := int(p.To.Reg) 2357 if p.To.Type == obj.TYPE_NONE { 2358 rt = REGZERO 2359 } 2360 r := int(p.Reg) 2361 if r == 0 { 2362 r = rt 2363 } 2364 if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) { 2365 o2 = c.opxrrr(p, p.As, false) 2366 o2 |= REGTMP & 31 << 16 2367 o2 |= LSL0_64 2368 } else { 2369 o2 = c.oprrr(p, p.As) 2370 o2 |= REGTMP & 31 << 16 /* shift is 0 */ 2371 } 2372 2373 o2 |= uint32(r&31) << 5 2374 o2 |= uint32(rt & 31) 2375 2376 case 14: /* word */ 2377 if c.aclass(&p.To) == C_ADDR { 2378 c.ctxt.Diag("address constant needs DWORD\n%v", p) 2379 } 2380 o1 = uint32(c.instoffset) 2381 if p.To.Sym != nil { 2382 // This case happens with words generated 2383 // in the PC stream as part of the literal pool. 2384 rel := obj.Addrel(c.cursym) 2385 2386 rel.Off = int32(c.pc) 2387 rel.Siz = 4 2388 rel.Sym = p.To.Sym 2389 rel.Add = p.To.Offset 2390 rel.Type = objabi.R_ADDR 2391 o1 = 0 2392 } 2393 2394 case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub Rm,Ra,Rn,Rd */ 2395 o1 = c.oprrr(p, p.As) 2396 2397 rf := int(p.From.Reg) 2398 rt := int(p.To.Reg) 2399 var r int 2400 var ra int 2401 if p.From3Type() == obj.TYPE_REG { 2402 r = int(p.GetFrom3().Reg) 2403 ra = int(p.Reg) 2404 if ra == 0 { 2405 ra = REGZERO 2406 } 2407 } else { 2408 r = int(p.Reg) 2409 if r == 0 { 2410 r = rt 2411 } 2412 ra = REGZERO 2413 } 2414 2415 o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31) 2416 2417 case 16: /* XremY R[,R],R -> XdivY; XmsubY */ 2418 o1 = c.oprrr(p, p.As) 2419 2420 rf := int(p.From.Reg) 2421 rt := int(p.To.Reg) 2422 r := int(p.Reg) 2423 if r == 0 { 2424 r = rt 2425 } 2426 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31 2427 o2 = c.oprrr(p, AMSUBW) 2428 o2 |= o1 & (1 << 31) /* same size */ 2429 o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31) 2430 2431 case 17: /* op Rm,[Rn],Rd; default Rn=ZR */ 2432 o1 = c.oprrr(p, p.As) 2433 2434 rf := int(p.From.Reg) 2435 rt := int(p.To.Reg) 2436 r := int(p.Reg) 2437 if p.To.Type == obj.TYPE_NONE { 2438 rt = REGZERO 2439 } 2440 if r == 0 { 2441 r = REGZERO 2442 } 2443 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 2444 2445 case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */ 2446 o1 = c.oprrr(p, p.As) 2447 2448 cond := int(p.From.Reg) 2449 if cond < COND_EQ || cond > COND_NV { 2450 c.ctxt.Diag("invalid condition\n%v", p) 2451 } else { 2452 cond -= COND_EQ 2453 } 2454 2455 r := int(p.Reg) 2456 var rf int 2457 if r != 0 { 2458 if p.From3Type() == obj.TYPE_NONE { 2459 /* CINC/CINV/CNEG */ 2460 rf = r 2461 2462 cond ^= 1 2463 } else { 2464 rf = int(p.GetFrom3().Reg) /* CSEL */ 2465 } 2466 } else { 2467 /* CSET */ 2468 if p.From3Type() != obj.TYPE_NONE { 2469 c.ctxt.Diag("invalid combination\n%v", p) 2470 } 2471 rf = REGZERO 2472 r = rf 2473 cond ^= 1 2474 } 2475 2476 rt := int(p.To.Reg) 2477 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31) 2478 2479 case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */ 2480 nzcv := int(p.To.Offset) 2481 2482 cond := int(p.From.Reg) 2483 if cond < COND_EQ || cond > COND_NV { 2484 c.ctxt.Diag("invalid condition\n%v", p) 2485 } else { 2486 cond -= COND_EQ 2487 } 2488 var rf int 2489 if p.GetFrom3().Type == obj.TYPE_REG { 2490 o1 = c.oprrr(p, p.As) 2491 rf = int(p.GetFrom3().Reg) /* Rm */ 2492 } else { 2493 o1 = c.opirr(p, p.As) 2494 rf = int(p.GetFrom3().Offset & 0x1F) 2495 } 2496 2497 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv) 2498 2499 case 20: /* movT R,O(R) -> strT */ 2500 v := int32(c.regoff(&p.To)) 2501 sz := int32(1 << uint(movesize(p.As))) 2502 2503 r := int(p.To.Reg) 2504 if r == 0 { 2505 r = int(o.param) 2506 } 2507 if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ 2508 o1 = c.olsr9s(p, int32(c.opstr9(p, p.As)), v, r, int(p.From.Reg)) 2509 } else { 2510 v = int32(c.offsetshift(p, int64(v), int(o.a3))) 2511 o1 = c.olsr12u(p, int32(c.opstr12(p, p.As)), v, r, int(p.From.Reg)) 2512 } 2513 2514 case 21: /* movT O(R),R -> ldrT */ 2515 v := int32(c.regoff(&p.From)) 2516 sz := int32(1 << uint(movesize(p.As))) 2517 2518 r := int(p.From.Reg) 2519 if r == 0 { 2520 r = int(o.param) 2521 } 2522 if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ 2523 o1 = c.olsr9s(p, int32(c.opldr9(p, p.As)), v, r, int(p.To.Reg)) 2524 } else { 2525 v = int32(c.offsetshift(p, int64(v), int(o.a1))) 2526 //print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1); 2527 o1 = c.olsr12u(p, int32(c.opldr12(p, p.As)), v, r, int(p.To.Reg)) 2528 } 2529 2530 case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */ 2531 v := int32(p.From.Offset) 2532 2533 if v < -256 || v > 255 { 2534 c.ctxt.Diag("offset out of range [-255,254]: %v", p) 2535 } 2536 o1 = c.opldrpp(p, p.As) 2537 if o.scond == C_XPOST { 2538 o1 |= 1 << 10 2539 } else { 2540 o1 |= 3 << 10 2541 } 2542 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31) 2543 2544 case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */ 2545 v := int32(p.To.Offset) 2546 2547 if v < -256 || v > 255 { 2548 c.ctxt.Diag("offset out of range [-255,254]: %v", p) 2549 } 2550 o1 = LD2STR(c.opldrpp(p, p.As)) 2551 if o.scond == C_XPOST { 2552 o1 |= 1 << 10 2553 } else { 2554 o1 |= 3 << 10 2555 } 2556 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31) 2557 2558 case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */ 2559 rf := int(p.From.Reg) 2560 rt := int(p.To.Reg) 2561 s := rf == REGSP || rt == REGSP 2562 if p.As == AMVN || p.As == AMVNW { 2563 if s { 2564 c.ctxt.Diag("illegal SP reference\n%v", p) 2565 } 2566 o1 = c.oprrr(p, p.As) 2567 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 2568 } else if s { 2569 o1 = c.opirr(p, p.As) 2570 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 2571 } else { 2572 o1 = c.oprrr(p, p.As) 2573 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 2574 } 2575 2576 case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */ 2577 o1 = c.oprrr(p, p.As) 2578 2579 rf := int(p.From.Reg) 2580 if rf == C_NONE { 2581 rf = int(p.To.Reg) 2582 } 2583 rt := int(p.To.Reg) 2584 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 2585 2586 case 26: /* negX Rm<<s, Rd -> subX Rm<<s, ZR, Rd */ 2587 o1 = c.oprrr(p, p.As) 2588 2589 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 2590 rt := int(p.To.Reg) 2591 o1 |= (REGZERO & 31 << 5) | uint32(rt&31) 2592 2593 case 27: /* op Rm<<n[,Rn],Rd (extended register) */ 2594 2595 if (p.From.Reg-obj.RBaseARM64)®_EXT != 0 { 2596 amount := (p.From.Reg >> 5) & 7 2597 if amount > 4 { 2598 c.ctxt.Diag("shift amount out of range 0 to 4: %v", p) 2599 } 2600 o1 = c.opxrrr(p, p.As, true) 2601 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 2602 } else { 2603 o1 = c.opxrrr(p, p.As, false) 2604 o1 |= uint32(p.From.Reg&31) << 16 2605 } 2606 rt := int(p.To.Reg) 2607 if p.To.Type == obj.TYPE_NONE { 2608 rt = REGZERO 2609 } 2610 r := int(p.Reg) 2611 if r == 0 { 2612 r = rt 2613 } 2614 o1 |= (uint32(r&31) << 5) | uint32(rt&31) 2615 2616 case 28: /* logop $vcon, [R], R (64 bit literal) */ 2617 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 2618 2619 if !(o1 != 0) { 2620 break 2621 } 2622 r := int(p.Reg) 2623 if r == 0 { 2624 r = int(p.To.Reg) 2625 } 2626 o2 = c.oprrr(p, p.As) 2627 o2 |= REGTMP & 31 << 16 /* shift is 0 */ 2628 o2 |= uint32(r&31) << 5 2629 o2 |= uint32(p.To.Reg & 31) 2630 2631 case 29: /* op Rn, Rd */ 2632 fc := c.aclass(&p.From) 2633 tc := c.aclass(&p.To) 2634 if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZCON || tc == C_REG || tc == C_ZCON) { 2635 // FMOV Rx, Fy or FMOV Fy, Rx 2636 o1 = FPCVTI(0, 0, 0, 0, 6) 2637 if p.As == AFMOVD { 2638 o1 |= 1<<31 | 1<<22 // 64-bit 2639 } 2640 if fc == C_REG || fc == C_ZCON { 2641 o1 |= 1 << 16 // FMOV Rx, Fy 2642 } 2643 } else { 2644 o1 = c.oprrr(p, p.As) 2645 } 2646 o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31) 2647 2648 case 30: /* movT R,L(R) -> strT */ 2649 // if offset L can be split into hi+lo, and both fit into instructions, do 2650 // add $hi, R, Rtmp 2651 // str R, lo(Rtmp) 2652 // otherwise, use constant pool 2653 // mov $L, Rtmp (from constant pool) 2654 // str R, (R+Rtmp) 2655 s := movesize(o.as) 2656 if s < 0 { 2657 c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) 2658 } 2659 2660 r := int(p.To.Reg) 2661 if r == 0 { 2662 r = int(o.param) 2663 } 2664 2665 v := int32(c.regoff(&p.To)) 2666 var hi int32 2667 if v < 0 || (v&((1<<uint(s))-1)) != 0 { 2668 // negative or unaligned offset, use constant pool 2669 goto storeusepool 2670 } 2671 2672 hi = v - (v & (0xFFF << uint(s))) 2673 if hi&0xFFF != 0 { 2674 c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p) 2675 } 2676 if hi&^0xFFF000 != 0 { 2677 // hi doesn't fit into an ADD instruction 2678 goto storeusepool 2679 } 2680 2681 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP) 2682 o2 = c.olsr12u(p, int32(c.opstr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg)) 2683 break 2684 2685 storeusepool: 2686 if r == REGTMP || p.From.Reg == REGTMP { 2687 c.ctxt.Diag("REGTMP used in large offset store: %v", p) 2688 } 2689 o1 = c.omovlit(AMOVD, p, &p.To, REGTMP) 2690 o2 = c.olsxrr(p, int32(c.opstrr(p, p.As)), int(p.From.Reg), r, REGTMP) 2691 2692 case 31: /* movT L(R), R -> ldrT */ 2693 // if offset L can be split into hi+lo, and both fit into instructions, do 2694 // add $hi, R, Rtmp 2695 // ldr lo(Rtmp), R 2696 // otherwise, use constant pool 2697 // mov $L, Rtmp (from constant pool) 2698 // ldr (R+Rtmp), R 2699 s := movesize(o.as) 2700 if s < 0 { 2701 c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) 2702 } 2703 2704 r := int(p.From.Reg) 2705 if r == 0 { 2706 r = int(o.param) 2707 } 2708 2709 v := int32(c.regoff(&p.From)) 2710 var hi int32 2711 if v < 0 || (v&((1<<uint(s))-1)) != 0 { 2712 // negative or unaligned offset, use constant pool 2713 goto loadusepool 2714 } 2715 2716 hi = v - (v & (0xFFF << uint(s))) 2717 if (hi & 0xFFF) != 0 { 2718 c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p) 2719 } 2720 if hi&^0xFFF000 != 0 { 2721 // hi doesn't fit into an ADD instruction 2722 goto loadusepool 2723 } 2724 2725 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP) 2726 o2 = c.olsr12u(p, int32(c.opldr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg)) 2727 break 2728 2729 loadusepool: 2730 if r == REGTMP || p.From.Reg == REGTMP { 2731 c.ctxt.Diag("REGTMP used in large offset load: %v", p) 2732 } 2733 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 2734 o2 = c.olsxrr(p, int32(c.opldrr(p, p.As)), int(p.To.Reg), r, REGTMP) 2735 2736 case 32: /* mov $con, R -> movz/movn */ 2737 o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg)) 2738 2739 case 33: /* movk $uimm16 << pos */ 2740 o1 = c.opirr(p, p.As) 2741 2742 d := p.From.Offset 2743 s := movcon(d) 2744 if s < 0 || s >= 4 { 2745 c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p) 2746 } 2747 if (o1&S64) == 0 && s >= 2 { 2748 c.ctxt.Diag("illegal bit position\n%v", p) 2749 } 2750 if ((d >> uint(s*16)) >> 16) != 0 { 2751 c.ctxt.Diag("requires uimm16\n%v", p) 2752 } 2753 rt := int(p.To.Reg) 2754 2755 o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31)) 2756 2757 case 34: /* mov $lacon,R */ 2758 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 2759 2760 if !(o1 != 0) { 2761 break 2762 } 2763 o2 = c.opxrrr(p, AADD, false) 2764 o2 |= REGTMP & 31 << 16 2765 o2 |= LSL0_64 2766 r := int(p.From.Reg) 2767 if r == 0 { 2768 r = int(o.param) 2769 } 2770 o2 |= uint32(r&31) << 5 2771 o2 |= uint32(p.To.Reg & 31) 2772 2773 case 35: /* mov SPR,R -> mrs */ 2774 o1 = c.oprrr(p, AMRS) 2775 2776 v := uint32(0) 2777 for i := 0; i < len(systemreg); i++ { 2778 if systemreg[i].reg == p.From.Reg { 2779 v = systemreg[i].enc 2780 break 2781 } 2782 } 2783 if v == 0 { 2784 c.ctxt.Diag("illegal system register:\n%v", p) 2785 } 2786 if (o1 & uint32(v&^(3<<19))) != 0 { 2787 c.ctxt.Diag("MRS register value overlap\n%v", p) 2788 } 2789 2790 o1 |= v 2791 o1 |= uint32(p.To.Reg & 31) 2792 2793 case 36: /* mov R,SPR */ 2794 o1 = c.oprrr(p, AMSR) 2795 2796 v := uint32(0) 2797 for i := 0; i < len(systemreg); i++ { 2798 if systemreg[i].reg == p.To.Reg { 2799 v = systemreg[i].enc 2800 break 2801 } 2802 } 2803 if v == 0 { 2804 c.ctxt.Diag("illegal system register:\n%v", p) 2805 } 2806 if (o1 & uint32(v&^(3<<19))) != 0 { 2807 c.ctxt.Diag("MSR register value overlap\n%v", p) 2808 } 2809 2810 o1 |= v 2811 o1 |= uint32(p.From.Reg & 31) 2812 2813 case 37: /* mov $con,PSTATEfield -> MSR [immediate] */ 2814 if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 { 2815 c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p) 2816 } 2817 o1 = c.opirr(p, AMSR) 2818 o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */ 2819 v := uint32(0) 2820 for i := 0; i < len(pstatefield); i++ { 2821 if pstatefield[i].reg == p.To.Reg { 2822 v = pstatefield[i].enc 2823 break 2824 } 2825 } 2826 2827 if v == 0 { 2828 c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p) 2829 } 2830 o1 |= v 2831 2832 case 38: /* clrex [$imm] */ 2833 o1 = c.opimm(p, p.As) 2834 2835 if p.To.Type == obj.TYPE_NONE { 2836 o1 |= 0xF << 8 2837 } else { 2838 o1 |= uint32((p.To.Offset & 0xF) << 8) 2839 } 2840 2841 case 39: /* cbz R, rel */ 2842 o1 = c.opirr(p, p.As) 2843 2844 o1 |= uint32(p.From.Reg & 31) 2845 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5) 2846 2847 case 40: /* tbz */ 2848 o1 = c.opirr(p, p.As) 2849 2850 v := int32(p.From.Offset) 2851 if v < 0 || v > 63 { 2852 c.ctxt.Diag("illegal bit number\n%v", p) 2853 } 2854 o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19) 2855 o1 |= uint32(c.brdist(p, 0, 14, 2) << 5) 2856 o1 |= uint32(p.Reg & 31) 2857 2858 case 41: /* eret, nop, others with no operands */ 2859 o1 = c.op0(p, p.As) 2860 2861 case 42: /* bfm R,r,s,R */ 2862 o1 = c.opbfm(p, p.As, int(p.From.Offset), int(p.GetFrom3().Offset), int(p.Reg), int(p.To.Reg)) 2863 2864 case 43: /* bfm aliases */ 2865 r := int(p.From.Offset) 2866 2867 s := int(p.GetFrom3().Offset) 2868 rf := int(p.Reg) 2869 rt := int(p.To.Reg) 2870 if rf == 0 { 2871 rf = rt 2872 } 2873 switch p.As { 2874 case ABFI: 2875 o1 = c.opbfm(p, ABFM, 64-r, s-1, rf, rt) 2876 2877 case ABFIW: 2878 o1 = c.opbfm(p, ABFMW, 32-r, s-1, rf, rt) 2879 2880 case ABFXIL: 2881 o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt) 2882 2883 case ABFXILW: 2884 o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt) 2885 2886 case ASBFIZ: 2887 o1 = c.opbfm(p, ASBFM, 64-r, s-1, rf, rt) 2888 2889 case ASBFIZW: 2890 o1 = c.opbfm(p, ASBFMW, 32-r, s-1, rf, rt) 2891 2892 case ASBFX: 2893 o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt) 2894 2895 case ASBFXW: 2896 o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt) 2897 2898 case AUBFIZ: 2899 o1 = c.opbfm(p, AUBFM, 64-r, s-1, rf, rt) 2900 2901 case AUBFIZW: 2902 o1 = c.opbfm(p, AUBFMW, 32-r, s-1, rf, rt) 2903 2904 case AUBFX: 2905 o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt) 2906 2907 case AUBFXW: 2908 o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt) 2909 2910 default: 2911 c.ctxt.Diag("bad bfm alias\n%v", p) 2912 break 2913 } 2914 2915 case 44: /* extr $b, Rn, Rm, Rd */ 2916 o1 = c.opextr(p, p.As, int32(p.From.Offset), int(p.GetFrom3().Reg), int(p.Reg), int(p.To.Reg)) 2917 2918 case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */ 2919 rf := int(p.From.Reg) 2920 2921 rt := int(p.To.Reg) 2922 as := p.As 2923 if rf == REGZERO { 2924 as = AMOVWU /* clearer in disassembly */ 2925 } 2926 switch as { 2927 case AMOVB, ASXTB: 2928 o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt) 2929 2930 case AMOVH, ASXTH: 2931 o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt) 2932 2933 case AMOVW, ASXTW: 2934 o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt) 2935 2936 case AMOVBU, AUXTB: 2937 o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt) 2938 2939 case AMOVHU, AUXTH: 2940 o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt) 2941 2942 case AMOVWU: 2943 o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 2944 2945 case AUXTW: 2946 o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt) 2947 2948 case ASXTBW: 2949 o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt) 2950 2951 case ASXTHW: 2952 o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt) 2953 2954 case AUXTBW: 2955 o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt) 2956 2957 case AUXTHW: 2958 o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt) 2959 2960 default: 2961 c.ctxt.Diag("bad sxt %v", as) 2962 break 2963 } 2964 2965 case 46: /* cls */ 2966 o1 = c.opbit(p, p.As) 2967 2968 o1 |= uint32(p.From.Reg&31) << 5 2969 o1 |= uint32(p.To.Reg & 31) 2970 2971 case 50: /* sys/sysl */ 2972 o1 = c.opirr(p, p.As) 2973 2974 if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 { 2975 c.ctxt.Diag("illegal SYS argument\n%v", p) 2976 } 2977 o1 |= uint32(p.From.Offset) 2978 if p.To.Type == obj.TYPE_REG { 2979 o1 |= uint32(p.To.Reg & 31) 2980 } else if p.Reg != 0 { 2981 o1 |= uint32(p.Reg & 31) 2982 } else { 2983 o1 |= 0x1F 2984 } 2985 2986 case 51: /* dmb */ 2987 o1 = c.opirr(p, p.As) 2988 2989 if p.From.Type == obj.TYPE_CONST { 2990 o1 |= uint32((p.From.Offset & 0xF) << 8) 2991 } 2992 2993 case 52: /* hint */ 2994 o1 = c.opirr(p, p.As) 2995 2996 o1 |= uint32((p.From.Offset & 0x7F) << 5) 2997 2998 case 53: /* and/or/eor/bic/... $bitcon, Rn, Rd */ 2999 a := p.As 3000 rt := int(p.To.Reg) 3001 r := int(p.Reg) 3002 if r == 0 { 3003 r = rt 3004 } 3005 mode := 64 3006 v := uint64(p.From.Offset) 3007 switch p.As { 3008 case AANDW, AORRW, AEORW, AANDSW: 3009 mode = 32 3010 case ABIC, AORN, AEON, ABICS: 3011 v = ^v 3012 case ABICW, AORNW, AEONW, ABICSW: 3013 v = ^v 3014 mode = 32 3015 } 3016 o1 = c.opirr(p, a) 3017 o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31) 3018 3019 case 54: /* floating point arith */ 3020 o1 = c.oprrr(p, p.As) 3021 3022 var rf int 3023 if p.From.Type == obj.TYPE_CONST { 3024 rf = c.chipfloat7(p.From.Val.(float64)) 3025 if rf < 0 || true { 3026 c.ctxt.Diag("invalid floating-point immediate\n%v", p) 3027 rf = 0 3028 } 3029 3030 rf |= (1 << 3) 3031 } else { 3032 rf = int(p.From.Reg) 3033 } 3034 rt := int(p.To.Reg) 3035 r := int(p.Reg) 3036 if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */ 3037 r = rf 3038 rf = 0 3039 } else if r == 0 { 3040 r = rt 3041 } 3042 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 3043 3044 case 56: /* floating point compare */ 3045 o1 = c.oprrr(p, p.As) 3046 3047 var rf int 3048 if p.From.Type == obj.TYPE_FCONST { 3049 o1 |= 8 /* zero */ 3050 rf = 0 3051 } else { 3052 rf = int(p.From.Reg) 3053 } 3054 rt := int(p.Reg) 3055 o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5 3056 3057 case 57: /* floating point conditional compare */ 3058 o1 = c.oprrr(p, p.As) 3059 3060 cond := int(p.From.Reg) 3061 if cond < COND_EQ || cond > COND_NV { 3062 c.ctxt.Diag("invalid condition\n%v", p) 3063 } else { 3064 cond -= COND_EQ 3065 } 3066 3067 nzcv := int(p.To.Offset) 3068 if nzcv&^0xF != 0 { 3069 c.ctxt.Diag("implausible condition\n%v", p) 3070 } 3071 rf := int(p.Reg) 3072 if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 { 3073 c.ctxt.Diag("illegal FCCMP\n%v", p) 3074 break 3075 } 3076 rt := int(p.GetFrom3().Reg) 3077 o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv) 3078 3079 case 58: /* ldar/ldxr/ldaxr */ 3080 o1 = c.opload(p, p.As) 3081 3082 o1 |= 0x1F << 16 3083 o1 |= uint32(p.From.Reg&31) << 5 3084 if p.Reg != 0 { 3085 o1 |= uint32(p.Reg&31) << 10 3086 } else { 3087 o1 |= 0x1F << 10 3088 } 3089 o1 |= uint32(p.To.Reg & 31) 3090 3091 case 59: /* stxr/stlxr */ 3092 o1 = c.opstore(p, p.As) 3093 3094 if p.RegTo2 != obj.REG_NONE { 3095 o1 |= uint32(p.RegTo2&31) << 16 3096 } else { 3097 o1 |= 0x1F << 16 3098 } 3099 3100 // TODO(aram): add support for STXP 3101 o1 |= uint32(p.To.Reg&31) << 5 3102 3103 o1 |= uint32(p.From.Reg & 31) 3104 3105 case 60: /* adrp label,r */ 3106 d := c.brdist(p, 12, 21, 0) 3107 3108 o1 = ADR(1, uint32(d), uint32(p.To.Reg)) 3109 3110 case 61: /* adr label, r */ 3111 d := c.brdist(p, 0, 21, 0) 3112 3113 o1 = ADR(0, uint32(d), uint32(p.To.Reg)) 3114 3115 case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */ 3116 if p.Reg == REGTMP { 3117 c.ctxt.Diag("cannot use REGTMP as source: %v\n", p) 3118 } 3119 o1 = c.omovconst(AMOVD, p, &p.From, REGTMP) 3120 3121 rt := int(p.To.Reg) 3122 if p.To.Type == obj.TYPE_NONE { 3123 rt = REGZERO 3124 } 3125 r := int(p.Reg) 3126 if r == 0 { 3127 r = rt 3128 } 3129 if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) { 3130 o2 = c.opxrrr(p, p.As, false) 3131 o2 |= REGTMP & 31 << 16 3132 o2 |= LSL0_64 3133 } else { 3134 o2 = c.oprrr(p, p.As) 3135 o2 |= REGTMP & 31 << 16 /* shift is 0 */ 3136 } 3137 o2 |= uint32(r&31) << 5 3138 o2 |= uint32(rt & 31) 3139 3140 /* reloc ops */ 3141 case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */ 3142 o1 = ADR(1, 0, REGTMP) 3143 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 3144 rel := obj.Addrel(c.cursym) 3145 rel.Off = int32(c.pc) 3146 rel.Siz = 8 3147 rel.Sym = p.To.Sym 3148 rel.Add = p.To.Offset 3149 rel.Type = objabi.R_ADDRARM64 3150 o3 = c.olsr12u(p, int32(c.opstr12(p, p.As)), 0, REGTMP, int(p.From.Reg)) 3151 3152 case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */ 3153 o1 = ADR(1, 0, REGTMP) 3154 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 3155 rel := obj.Addrel(c.cursym) 3156 rel.Off = int32(c.pc) 3157 rel.Siz = 8 3158 rel.Sym = p.From.Sym 3159 rel.Add = p.From.Offset 3160 rel.Type = objabi.R_ADDRARM64 3161 o3 = c.olsr12u(p, int32(c.opldr12(p, p.As)), 0, REGTMP, int(p.To.Reg)) 3162 3163 case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */ 3164 v := int32(c.regoff(&p.From)) 3165 r := int(p.From.Reg) 3166 if r == obj.REG_NONE { 3167 r = int(o.param) 3168 } 3169 if r == obj.REG_NONE { 3170 c.ctxt.Diag("invalid ldp source: %v\n", p) 3171 } 3172 3173 if v < -512 || v > 504 || v%8 != 0 { 3174 c.ctxt.Diag("invalid offset %v\n", p) 3175 } 3176 if o.scond == C_XPOST { 3177 o1 |= 1 << 23 3178 } else if o.scond == C_XPRE { 3179 o1 |= 3 << 23 3180 } else { 3181 o1 |= 2 << 23 3182 } 3183 o1 |= 1 << 22 3184 o1 |= uint32(int64(2<<30|5<<27|((uint32(v)/8)&0x7f)<<15) | (p.To.Offset&31)<<10 | int64(uint32(r&31)<<5) | int64(p.To.Reg&31)) 3185 3186 case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */ 3187 r := int(p.To.Reg) 3188 if r == obj.REG_NONE { 3189 r = int(o.param) 3190 } 3191 if r == obj.REG_NONE { 3192 c.ctxt.Diag("invalid stp destination: %v\n", p) 3193 } 3194 3195 v := int32(c.regoff(&p.To)) 3196 if v < -512 || v > 504 || v%8 != 0 { 3197 c.ctxt.Diag("invalid offset %v\n", p) 3198 } 3199 3200 if o.scond == C_XPOST { 3201 o1 |= 1 << 23 3202 } else if o.scond == C_XPRE { 3203 o1 |= 3 << 23 3204 } else { 3205 o1 |= 2 << 23 3206 } 3207 o1 |= uint32(int64(2<<30|5<<27|((uint32(v)/8)&0x7f)<<15) | (p.From.Offset&31)<<10 | int64(uint32(r&31)<<5) | int64(p.From.Reg&31)) 3208 3209 case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */ 3210 if p.As == AMOVW { 3211 c.ctxt.Diag("invalid load of 32-bit address: %v", p) 3212 } 3213 o1 = ADR(1, 0, uint32(p.To.Reg)) 3214 o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31) 3215 rel := obj.Addrel(c.cursym) 3216 rel.Off = int32(c.pc) 3217 rel.Siz = 8 3218 rel.Sym = p.From.Sym 3219 rel.Add = p.From.Offset 3220 rel.Type = objabi.R_ADDRARM64 3221 3222 case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */ 3223 o1 = c.opirr(p, AMOVZ) 3224 o1 |= uint32(p.To.Reg & 31) 3225 rel := obj.Addrel(c.cursym) 3226 rel.Off = int32(c.pc) 3227 rel.Siz = 4 3228 rel.Sym = p.From.Sym 3229 rel.Type = objabi.R_ARM64_TLS_LE 3230 if p.From.Offset != 0 { 3231 c.ctxt.Diag("invalid offset on MOVW $tlsvar") 3232 } 3233 3234 case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */ 3235 o1 = ADR(1, 0, REGTMP) 3236 o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg)) 3237 rel := obj.Addrel(c.cursym) 3238 rel.Off = int32(c.pc) 3239 rel.Siz = 8 3240 rel.Sym = p.From.Sym 3241 rel.Add = 0 3242 rel.Type = objabi.R_ARM64_TLS_IE 3243 if p.From.Offset != 0 { 3244 c.ctxt.Diag("invalid offset on MOVW $tlsvar") 3245 } 3246 3247 case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */ 3248 o1 = ADR(1, 0, REGTMP) 3249 o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg)) 3250 rel := obj.Addrel(c.cursym) 3251 rel.Off = int32(c.pc) 3252 rel.Siz = 8 3253 rel.Sym = p.From.Sym 3254 rel.Add = 0 3255 rel.Type = objabi.R_ARM64_GOTPCREL 3256 3257 case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor Vm.<T>, Vn.<T>, Vd.<T> */ 3258 af := int((p.From.Reg >> 5) & 15) 3259 af3 := int((p.Reg >> 5) & 15) 3260 at := int((p.To.Reg >> 5) & 15) 3261 if af != af3 || af != at { 3262 c.ctxt.Diag("invalid arrangement: %v\n", p) 3263 } 3264 o1 = c.oprrr(p, p.As) 3265 rf := int((p.From.Reg) & 31) 3266 rt := int((p.To.Reg) & 31) 3267 r := int((p.Reg) & 31) 3268 3269 Q := 0 3270 size := 0 3271 switch af { 3272 case ARNG_16B: 3273 Q = 1 3274 size = 0 3275 case ARNG_2D: 3276 Q = 1 3277 size = 3 3278 case ARNG_2S: 3279 Q = 0 3280 size = 2 3281 case ARNG_4H: 3282 Q = 0 3283 size = 1 3284 case ARNG_4S: 3285 Q = 1 3286 size = 2 3287 case ARNG_8B: 3288 Q = 0 3289 size = 0 3290 case ARNG_8H: 3291 Q = 1 3292 size = 1 3293 default: 3294 c.ctxt.Diag("invalid arrangement: %v\n", p) 3295 } 3296 3297 if (p.As == AVORR || p.As == AVAND || p.As == AVEOR) && 3298 (af != ARNG_16B && af != ARNG_8B) { 3299 c.ctxt.Diag("invalid arrangement on op %v", p.As) 3300 } else if p.As == AVORR { 3301 size = 2 3302 } else if p.As == AVAND || p.As == AVEOR { 3303 size = 0 3304 } 3305 3306 o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 3307 3308 case 73: /* vmov V.<T>[index], R */ 3309 rf := int(p.From.Reg) 3310 rt := int(p.To.Reg) 3311 imm5 := 0 3312 o1 = 7<<25 | 0xf<<10 3313 switch (p.From.Reg >> 5) & 15 { 3314 case ARNG_B: 3315 imm5 |= 1 3316 imm5 |= int(p.From.Index) << 1 3317 case ARNG_H: 3318 imm5 |= 2 3319 imm5 |= int(p.From.Index) << 2 3320 case ARNG_S: 3321 imm5 |= 4 3322 imm5 |= int(p.From.Index) << 3 3323 case ARNG_D: 3324 imm5 |= 8 3325 imm5 |= int(p.From.Index) << 4 3326 o1 |= 1 << 30 3327 default: 3328 c.ctxt.Diag("invalid arrangement on op V.<T>[index], R: %v\n", p) 3329 } 3330 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 3331 3332 case 74: 3333 // add $O, R, Rtmp 3334 // ldp (Rtmp), (R1, R2) 3335 r := int(p.From.Reg) 3336 if r == obj.REG_NONE { 3337 r = int(o.param) 3338 } 3339 if r == obj.REG_NONE { 3340 c.ctxt.Diag("invalid ldp source: %v\n", p) 3341 } 3342 3343 v := int32(c.regoff(&p.From)) 3344 if v < 0 || v > 4095 { 3345 c.ctxt.Diag("offset out of range%v\n", p) 3346 } 3347 3348 if o.scond == C_XPOST { 3349 o2 |= 1 << 23 3350 } else if o.scond == C_XPRE { 3351 o2 |= 3 << 23 3352 } else { 3353 o2 |= 2 << 23 3354 } 3355 3356 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP) 3357 o2 |= 1 << 22 3358 o2 |= uint32(int64(2<<30|5<<27) | (p.To.Offset&31)<<10 | int64(uint32(REGTMP&31)<<5) | int64(p.To.Reg&31)) 3359 3360 case 75: 3361 // mov $L, Rtmp (from constant pool) 3362 // add Rtmp, R, Rtmp 3363 // ldp (Rtmp), (R1, R2) 3364 r := int(p.From.Reg) 3365 if r == obj.REG_NONE { 3366 r = int(o.param) 3367 } 3368 if r == obj.REG_NONE { 3369 c.ctxt.Diag("invalid ldp source: %v\n", p) 3370 } 3371 3372 if o.scond == C_XPOST { 3373 o3 |= 1 << 23 3374 } else if o.scond == C_XPRE { 3375 o3 |= 3 << 23 3376 } else { 3377 o3 |= 2 << 23 3378 } 3379 3380 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 3381 o2 = c.opxrrr(p, AADD, false) 3382 o2 |= (REGTMP & 31) << 16 3383 o2 |= uint32(r&31) << 5 3384 o2 |= uint32(REGTMP & 31) 3385 o3 |= 1 << 22 3386 o3 |= uint32(int64(2<<30|5<<27) | (p.To.Offset&31)<<10 | int64(uint32(REGTMP&31)<<5) | int64(p.To.Reg&31)) 3387 3388 case 76: 3389 // add $O, R, Rtmp 3390 // stp (R1, R2), (Rtmp) 3391 r := int(p.To.Reg) 3392 if r == obj.REG_NONE { 3393 r = int(o.param) 3394 } 3395 if r == obj.REG_NONE { 3396 c.ctxt.Diag("invalid stp destination: %v\n", p) 3397 } 3398 3399 v := int32(c.regoff(&p.To)) 3400 if v < 0 || v > 4095 { 3401 c.ctxt.Diag("offset out of range%v\n", p) 3402 } 3403 if o.scond == C_XPOST { 3404 o2 |= 1 << 23 3405 } else if o.scond == C_XPRE { 3406 o2 |= 3 << 23 3407 } else { 3408 o2 |= 2 << 23 3409 } 3410 3411 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP) 3412 o2 |= uint32(int64(2<<30|5<<27) | (p.From.Offset&31)<<10 | int64(uint32(REGTMP&31)<<5) | int64(p.From.Reg&31)) 3413 3414 case 77: 3415 // mov $L, Rtmp (from constant pool) 3416 // add Rtmp, R, Rtmp 3417 // stp (R1, R2), (Rtmp) 3418 r := int(p.To.Reg) 3419 if r == obj.REG_NONE { 3420 r = int(o.param) 3421 } 3422 if r == obj.REG_NONE { 3423 c.ctxt.Diag("invalid stp destination: %v\n", p) 3424 } 3425 3426 if o.scond == C_XPOST { 3427 o3 |= 1 << 23 3428 } else if o.scond == C_XPRE { 3429 o3 |= 3 << 23 3430 } else { 3431 o3 |= 2 << 23 3432 } 3433 o1 = c.omovlit(AMOVD, p, &p.To, REGTMP) 3434 o2 = c.opxrrr(p, AADD, false) 3435 o2 |= REGTMP & 31 << 16 3436 o2 |= uint32(r&31) << 5 3437 o2 |= uint32(REGTMP & 31) 3438 o3 |= uint32(int64(2<<30|5<<27) | (p.From.Offset&31)<<10 | int64(uint32(REGTMP&31)<<5) | int64(p.From.Reg&31)) 3439 3440 case 78: /* vmov R, V.<T>[index] */ 3441 rf := int(p.From.Reg) 3442 rt := int(p.To.Reg) 3443 imm5 := 0 3444 o1 = 1<<30 | 7<<25 | 7<<10 3445 switch (p.To.Reg >> 5) & 15 { 3446 case ARNG_B: 3447 imm5 |= 1 3448 imm5 |= int(p.From.Index) << 1 3449 case ARNG_H: 3450 imm5 |= 2 3451 imm5 |= int(p.From.Index) << 2 3452 case ARNG_S: 3453 imm5 |= 4 3454 imm5 |= int(p.From.Index) << 3 3455 case ARNG_D: 3456 imm5 |= 8 3457 imm5 |= int(p.From.Index) << 4 3458 default: 3459 c.ctxt.Diag("invalid arrangement on op R, V.<T>[index]: %v\n", p) 3460 } 3461 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 3462 3463 case 79: /* vdup Vn.<T>[index], Vd.<T> */ 3464 rf := int(p.From.Reg) 3465 rt := int(p.To.Reg) 3466 o1 = 7<<25 | 1<<10 3467 var imm5, Q uint32 3468 switch (p.To.Reg >> 5) & 15 { 3469 case ARNG_16B: 3470 Q = 1 3471 imm5 = 1 3472 imm5 |= uint32(p.From.Index) << 1 3473 case ARNG_2D: 3474 Q = 1 3475 imm5 = 8 3476 imm5 |= uint32(p.From.Index) << 4 3477 case ARNG_2S: 3478 Q = 0 3479 imm5 = 4 3480 imm5 |= uint32(p.From.Index) << 3 3481 case ARNG_4H: 3482 Q = 0 3483 imm5 = 2 3484 imm5 |= uint32(p.From.Index) << 2 3485 case ARNG_4S: 3486 Q = 1 3487 imm5 = 4 3488 imm5 |= uint32(p.From.Index) << 3 3489 case ARNG_8B: 3490 Q = 0 3491 imm5 = 1 3492 imm5 |= uint32(p.From.Index) << 1 3493 case ARNG_8H: 3494 Q = 1 3495 imm5 = 2 3496 imm5 |= uint32(p.From.Index) << 2 3497 default: 3498 c.ctxt.Diag("invalid arrangement on VDUP Vn.<T>[index], Vd.<T>: %v\n", p) 3499 } 3500 o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16) 3501 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 3502 3503 case 80: /* vmov V.<T>[index], Vn */ 3504 rf := int(p.From.Reg) 3505 rt := int(p.To.Reg) 3506 imm5 := 0 3507 switch p.As { 3508 case AVMOV: 3509 o1 = 1<<30 | 15<<25 | 1<<10 3510 switch (p.From.Reg >> 5) & 15 { 3511 case ARNG_B: 3512 imm5 |= 1 3513 imm5 |= int(p.From.Index) << 1 3514 case ARNG_H: 3515 imm5 |= 2 3516 imm5 |= int(p.From.Index) << 2 3517 case ARNG_S: 3518 imm5 |= 4 3519 imm5 |= int(p.From.Index) << 3 3520 case ARNG_D: 3521 imm5 |= 8 3522 imm5 |= int(p.From.Index) << 4 3523 default: 3524 c.ctxt.Diag("invalid arrangement on op V.<T>[index], Vn: %v\n", p) 3525 } 3526 default: 3527 c.ctxt.Diag("unsupported op %v", p.As) 3528 } 3529 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 3530 3531 case 81: /* vld1 (Rn), [Vt1.<T>, Vt2.<T>, ...] */ 3532 r := int(p.From.Reg) 3533 o1 = 3<<26 | 1<<22 3534 if o.scond == C_XPOST { 3535 o1 |= 1 << 23 3536 if p.From.Index == 0 { 3537 // immediate offset variant 3538 o1 |= 0x1f << 16 3539 } else { 3540 // register offset variant 3541 o1 |= uint32(p.From.Index&31) << 16 3542 } 3543 } 3544 o1 |= uint32(p.To.Offset) 3545 o1 |= uint32(r&31) << 5 3546 3547 case 82: /* vmov Rn, Vd.<T> */ 3548 rf := int(p.From.Reg) 3549 rt := int(p.To.Reg) 3550 o1 = 7<<25 | 3<<10 3551 var imm5, Q uint32 3552 switch (p.To.Reg >> 5) & 15 { 3553 case ARNG_16B: 3554 Q = 1 3555 imm5 = 1 3556 case ARNG_2D: 3557 Q = 1 3558 imm5 = 8 3559 case ARNG_2S: 3560 Q = 0 3561 imm5 = 4 3562 case ARNG_4H: 3563 Q = 0 3564 imm5 = 2 3565 case ARNG_4S: 3566 Q = 1 3567 imm5 = 4 3568 case ARNG_8B: 3569 Q = 0 3570 imm5 = 1 3571 case ARNG_8H: 3572 Q = 1 3573 imm5 = 2 3574 default: 3575 c.ctxt.Diag("invalid arrangement on VMOV Rn, Vd.<T>: %v\n", p) 3576 } 3577 o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16) 3578 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 3579 3580 case 83: /* vmov Vn.<T>, Vd.<T> */ 3581 af := int((p.From.Reg >> 5) & 15) 3582 at := int((p.To.Reg >> 5) & 15) 3583 if af != at { 3584 c.ctxt.Diag("invalid arrangement: %v\n", p) 3585 } 3586 o1 = c.oprrr(p, p.As) 3587 rf := int((p.From.Reg) & 31) 3588 rt := int((p.To.Reg) & 31) 3589 3590 Q := 0 3591 size := 0 3592 switch af { 3593 case ARNG_8B: 3594 Q = 0 3595 size = 0 3596 case ARNG_16B: 3597 Q = 1 3598 size = 0 3599 case ARNG_4H: 3600 Q = 0 3601 size = 1 3602 case ARNG_8H: 3603 Q = 1 3604 size = 1 3605 default: 3606 c.ctxt.Diag("invalid arrangement: %v\n", p) 3607 } 3608 3609 if (p.As == AVMOV) && (af != ARNG_16B && af != ARNG_8B) { 3610 c.ctxt.Diag("invalid arrangement on op %v", p.As) 3611 } 3612 3613 if p.As == AVMOV { 3614 o1 |= uint32(rf&31) << 16 3615 } 3616 3617 o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31) 3618 3619 case 84: /* vst1 [Vt1.<T>, Vt2.<T>, ...], (Rn) */ 3620 r := int(p.To.Reg) 3621 o1 = 3 << 26 3622 if o.scond == C_XPOST { 3623 o1 |= 1 << 23 3624 if p.To.Index == 0 { 3625 // immediate offset variant 3626 o1 |= 0x1f << 16 3627 } else { 3628 // register offset variant 3629 o1 |= uint32(p.To.Index&31) << 16 3630 } 3631 } 3632 o1 |= uint32(p.From.Offset) 3633 o1 |= uint32(r&31) << 5 3634 3635 case 85: /* vaddv/vuaddlv Vn.<T>, Vd*/ 3636 af := int((p.From.Reg >> 5) & 15) 3637 o1 = c.oprrr(p, p.As) 3638 rf := int((p.From.Reg) & 31) 3639 rt := int((p.To.Reg) & 31) 3640 Q := 0 3641 size := 0 3642 switch af { 3643 case ARNG_8B: 3644 Q = 0 3645 size = 0 3646 case ARNG_16B: 3647 Q = 1 3648 size = 0 3649 case ARNG_4H: 3650 Q = 0 3651 size = 1 3652 case ARNG_8H: 3653 Q = 1 3654 size = 1 3655 case ARNG_4S: 3656 Q = 1 3657 size = 2 3658 default: 3659 c.ctxt.Diag("invalid arrangement: %v\n", p) 3660 } 3661 o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31) 3662 3663 case 86: /* vmovi $imm8, Vd.<T>*/ 3664 at := int((p.To.Reg >> 5) & 15) 3665 r := int(p.From.Offset) 3666 if r > 255 || r < 0 { 3667 c.ctxt.Diag("immediate constant out of range: %v\n", p) 3668 } 3669 rt := int((p.To.Reg) & 31) 3670 Q := 0 3671 switch at { 3672 case ARNG_8B: 3673 Q = 0 3674 case ARNG_16B: 3675 Q = 1 3676 default: 3677 c.ctxt.Diag("invalid arrangement: %v\n", p) 3678 } 3679 o1 = 0xf<<24 | 0xe<<12 | 1<<10 3680 o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31) 3681 3682 case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */ 3683 o1 = ADR(1, 0, REGTMP) 3684 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 3685 rel := obj.Addrel(c.cursym) 3686 rel.Off = int32(c.pc) 3687 rel.Siz = 8 3688 rel.Sym = p.To.Sym 3689 rel.Add = p.To.Offset 3690 rel.Type = objabi.R_ADDRARM64 3691 o3 |= 2<<30 | 5<<27 | 2<<23 | uint32(p.From.Offset&31)<<10 | (REGTMP&31)<<5 | uint32(p.From.Reg&31) 3692 3693 case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */ 3694 o1 = ADR(1, 0, REGTMP) 3695 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 3696 rel := obj.Addrel(c.cursym) 3697 rel.Off = int32(c.pc) 3698 rel.Siz = 8 3699 rel.Sym = p.From.Sym 3700 rel.Add = p.From.Offset 3701 rel.Type = objabi.R_ADDRARM64 3702 o3 |= 2<<30 | 5<<27 | 2<<23 | 1<<22 | uint32(p.To.Offset&31)<<10 | (REGTMP&31)<<5 | uint32(p.To.Reg&31) 3703 3704 case 89: /* vadd/vsub Vm, Vn, Vd */ 3705 switch p.As { 3706 case AVADD: 3707 o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10 3708 3709 case AVSUB: 3710 o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10 3711 3712 default: 3713 c.ctxt.Diag("bad opcode: %v\n", p) 3714 break 3715 } 3716 3717 rf := int(p.From.Reg) 3718 rt := int(p.To.Reg) 3719 r := int(p.Reg) 3720 if r == 0 { 3721 r = rt 3722 } 3723 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 3724 3725 // This is supposed to be something that stops execution. 3726 // It's not supposed to be reached, ever, but if it is, we'd 3727 // like to be able to tell how we got there. Assemble as 3728 // 0xbea71700 which is guaranteed to raise undefined instruction 3729 // exception. 3730 case 90: 3731 o1 = 0xbea71700 3732 3733 break 3734 } 3735 3736 out[0] = o1 3737 out[1] = o2 3738 out[2] = o3 3739 out[3] = o4 3740 out[4] = o5 3741 return 3742 } 3743 3744 /* 3745 * basic Rm op Rn -> Rd (using shifted register with 0) 3746 * also op Rn -> Rt 3747 * also Rm*Rn op Ra -> Rd 3748 * also Vm op Vn -> Vd 3749 */ 3750 func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 { 3751 switch a { 3752 case AADC: 3753 return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 3754 3755 case AADCW: 3756 return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 3757 3758 case AADCS: 3759 return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 3760 3761 case AADCSW: 3762 return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 3763 3764 case ANGC, ASBC: 3765 return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 3766 3767 case ANGCS, ASBCS: 3768 return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 3769 3770 case ANGCW, ASBCW: 3771 return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 3772 3773 case ANGCSW, ASBCSW: 3774 return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 3775 3776 case AADD: 3777 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3778 3779 case AADDW: 3780 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3781 3782 case ACMN, AADDS: 3783 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3784 3785 case ACMNW, AADDSW: 3786 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3787 3788 case ASUB: 3789 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3790 3791 case ASUBW: 3792 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3793 3794 case ACMP, ASUBS: 3795 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3796 3797 case ACMPW, ASUBSW: 3798 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3799 3800 case AAND: 3801 return S64 | 0<<29 | 0xA<<24 3802 3803 case AANDW: 3804 return S32 | 0<<29 | 0xA<<24 3805 3806 case AMOVD, AORR: 3807 return S64 | 1<<29 | 0xA<<24 3808 3809 // case AMOVW: 3810 case AMOVWU, AORRW: 3811 return S32 | 1<<29 | 0xA<<24 3812 3813 case AEOR: 3814 return S64 | 2<<29 | 0xA<<24 3815 3816 case AEORW: 3817 return S32 | 2<<29 | 0xA<<24 3818 3819 case AANDS: 3820 return S64 | 3<<29 | 0xA<<24 3821 3822 case AANDSW: 3823 return S32 | 3<<29 | 0xA<<24 3824 3825 case ABIC: 3826 return S64 | 0<<29 | 0xA<<24 | 1<<21 3827 3828 case ABICW: 3829 return S32 | 0<<29 | 0xA<<24 | 1<<21 3830 3831 case ABICS: 3832 return S64 | 3<<29 | 0xA<<24 | 1<<21 3833 3834 case ABICSW: 3835 return S32 | 3<<29 | 0xA<<24 | 1<<21 3836 3837 case AEON: 3838 return S64 | 2<<29 | 0xA<<24 | 1<<21 3839 3840 case AEONW: 3841 return S32 | 2<<29 | 0xA<<24 | 1<<21 3842 3843 case AMVN, AORN: 3844 return S64 | 1<<29 | 0xA<<24 | 1<<21 3845 3846 case AMVNW, AORNW: 3847 return S32 | 1<<29 | 0xA<<24 | 1<<21 3848 3849 case AASR: 3850 return S64 | OPDP2(10) /* also ASRV */ 3851 3852 case AASRW: 3853 return S32 | OPDP2(10) 3854 3855 case ALSL: 3856 return S64 | OPDP2(8) 3857 3858 case ALSLW: 3859 return S32 | OPDP2(8) 3860 3861 case ALSR: 3862 return S64 | OPDP2(9) 3863 3864 case ALSRW: 3865 return S32 | OPDP2(9) 3866 3867 case AROR: 3868 return S64 | OPDP2(11) 3869 3870 case ARORW: 3871 return S32 | OPDP2(11) 3872 3873 case ACCMN: 3874 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */ 3875 3876 case ACCMNW: 3877 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 3878 3879 case ACCMP: 3880 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 3881 3882 case ACCMPW: 3883 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 3884 3885 case ACRC32B: 3886 return S32 | OPDP2(16) 3887 3888 case ACRC32H: 3889 return S32 | OPDP2(17) 3890 3891 case ACRC32W: 3892 return S32 | OPDP2(18) 3893 3894 case ACRC32X: 3895 return S64 | OPDP2(19) 3896 3897 case ACRC32CB: 3898 return S32 | OPDP2(20) 3899 3900 case ACRC32CH: 3901 return S32 | OPDP2(21) 3902 3903 case ACRC32CW: 3904 return S32 | OPDP2(22) 3905 3906 case ACRC32CX: 3907 return S64 | OPDP2(23) 3908 3909 case ACSEL: 3910 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 3911 3912 case ACSELW: 3913 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 3914 3915 case ACSET: 3916 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 3917 3918 case ACSETW: 3919 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 3920 3921 case ACSETM: 3922 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 3923 3924 case ACSETMW: 3925 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 3926 3927 case ACINC, ACSINC: 3928 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 3929 3930 case ACINCW, ACSINCW: 3931 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 3932 3933 case ACINV, ACSINV: 3934 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 3935 3936 case ACINVW, ACSINVW: 3937 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 3938 3939 case ACNEG, ACSNEG: 3940 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 3941 3942 case ACNEGW, ACSNEGW: 3943 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 3944 3945 case AMUL, AMADD: 3946 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 3947 3948 case AMULW, AMADDW: 3949 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 3950 3951 case AMNEG, AMSUB: 3952 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 3953 3954 case AMNEGW, AMSUBW: 3955 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 3956 3957 case AMRS: 3958 return SYSOP(1, 2, 0, 0, 0, 0, 0) 3959 3960 case AMSR: 3961 return SYSOP(0, 2, 0, 0, 0, 0, 0) 3962 3963 case ANEG: 3964 return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 3965 3966 case ANEGW: 3967 return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 3968 3969 case ANEGS: 3970 return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 3971 3972 case ANEGSW: 3973 return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 3974 3975 case AREM, ASDIV: 3976 return S64 | OPDP2(3) 3977 3978 case AREMW, ASDIVW: 3979 return S32 | OPDP2(3) 3980 3981 case ASMULL, ASMADDL: 3982 return OPDP3(1, 0, 1, 0) 3983 3984 case ASMNEGL, ASMSUBL: 3985 return OPDP3(1, 0, 1, 1) 3986 3987 case ASMULH: 3988 return OPDP3(1, 0, 2, 0) 3989 3990 case AUMULL, AUMADDL: 3991 return OPDP3(1, 0, 5, 0) 3992 3993 case AUMNEGL, AUMSUBL: 3994 return OPDP3(1, 0, 5, 1) 3995 3996 case AUMULH: 3997 return OPDP3(1, 0, 6, 0) 3998 3999 case AUREM, AUDIV: 4000 return S64 | OPDP2(2) 4001 4002 case AUREMW, AUDIVW: 4003 return S32 | OPDP2(2) 4004 4005 case AAESE: 4006 return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10 4007 4008 case AAESD: 4009 return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10 4010 4011 case AAESMC: 4012 return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10 4013 4014 case AAESIMC: 4015 return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10 4016 4017 case ASHA1C: 4018 return 0x5E<<24 | 0<<12 4019 4020 case ASHA1P: 4021 return 0x5E<<24 | 1<<12 4022 4023 case ASHA1M: 4024 return 0x5E<<24 | 2<<12 4025 4026 case ASHA1SU0: 4027 return 0x5E<<24 | 3<<12 4028 4029 case ASHA256H: 4030 return 0x5E<<24 | 4<<12 4031 4032 case ASHA256H2: 4033 return 0x5E<<24 | 5<<12 4034 4035 case ASHA256SU1: 4036 return 0x5E<<24 | 6<<12 4037 4038 case ASHA1H: 4039 return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10 4040 4041 case ASHA1SU1: 4042 return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10 4043 4044 case ASHA256SU0: 4045 return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10 4046 4047 case AFCVTZSD: 4048 return FPCVTI(1, 0, 1, 3, 0) 4049 4050 case AFCVTZSDW: 4051 return FPCVTI(0, 0, 1, 3, 0) 4052 4053 case AFCVTZSS: 4054 return FPCVTI(1, 0, 0, 3, 0) 4055 4056 case AFCVTZSSW: 4057 return FPCVTI(0, 0, 0, 3, 0) 4058 4059 case AFCVTZUD: 4060 return FPCVTI(1, 0, 1, 3, 1) 4061 4062 case AFCVTZUDW: 4063 return FPCVTI(0, 0, 1, 3, 1) 4064 4065 case AFCVTZUS: 4066 return FPCVTI(1, 0, 0, 3, 1) 4067 4068 case AFCVTZUSW: 4069 return FPCVTI(0, 0, 0, 3, 1) 4070 4071 case ASCVTFD: 4072 return FPCVTI(1, 0, 1, 0, 2) 4073 4074 case ASCVTFS: 4075 return FPCVTI(1, 0, 0, 0, 2) 4076 4077 case ASCVTFWD: 4078 return FPCVTI(0, 0, 1, 0, 2) 4079 4080 case ASCVTFWS: 4081 return FPCVTI(0, 0, 0, 0, 2) 4082 4083 case AUCVTFD: 4084 return FPCVTI(1, 0, 1, 0, 3) 4085 4086 case AUCVTFS: 4087 return FPCVTI(1, 0, 0, 0, 3) 4088 4089 case AUCVTFWD: 4090 return FPCVTI(0, 0, 1, 0, 3) 4091 4092 case AUCVTFWS: 4093 return FPCVTI(0, 0, 0, 0, 3) 4094 4095 case AFADDS: 4096 return FPOP2S(0, 0, 0, 2) 4097 4098 case AFADDD: 4099 return FPOP2S(0, 0, 1, 2) 4100 4101 case AFSUBS: 4102 return FPOP2S(0, 0, 0, 3) 4103 4104 case AFSUBD: 4105 return FPOP2S(0, 0, 1, 3) 4106 4107 case AFMULS: 4108 return FPOP2S(0, 0, 0, 0) 4109 4110 case AFMULD: 4111 return FPOP2S(0, 0, 1, 0) 4112 4113 case AFDIVS: 4114 return FPOP2S(0, 0, 0, 1) 4115 4116 case AFDIVD: 4117 return FPOP2S(0, 0, 1, 1) 4118 4119 case AFMAXS: 4120 return FPOP2S(0, 0, 0, 4) 4121 4122 case AFMINS: 4123 return FPOP2S(0, 0, 0, 5) 4124 4125 case AFMAXD: 4126 return FPOP2S(0, 0, 1, 4) 4127 4128 case AFMIND: 4129 return FPOP2S(0, 0, 1, 5) 4130 4131 case AFMAXNMS: 4132 return FPOP2S(0, 0, 0, 6) 4133 4134 case AFMAXNMD: 4135 return FPOP2S(0, 0, 1, 6) 4136 4137 case AFMINNMS: 4138 return FPOP2S(0, 0, 0, 7) 4139 4140 case AFMINNMD: 4141 return FPOP2S(0, 0, 1, 7) 4142 4143 case AFNMULS: 4144 return FPOP2S(0, 0, 0, 8) 4145 4146 case AFNMULD: 4147 return FPOP2S(0, 0, 1, 8) 4148 4149 case AFCMPS: 4150 return FPCMP(0, 0, 0, 0, 0) 4151 4152 case AFCMPD: 4153 return FPCMP(0, 0, 1, 0, 0) 4154 4155 case AFCMPES: 4156 return FPCMP(0, 0, 0, 0, 16) 4157 4158 case AFCMPED: 4159 return FPCMP(0, 0, 1, 0, 16) 4160 4161 case AFCCMPS: 4162 return FPCCMP(0, 0, 0, 0) 4163 4164 case AFCCMPD: 4165 return FPCCMP(0, 0, 1, 0) 4166 4167 case AFCCMPES: 4168 return FPCCMP(0, 0, 0, 1) 4169 4170 case AFCCMPED: 4171 return FPCCMP(0, 0, 1, 1) 4172 4173 case AFCSELS: 4174 return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10 4175 4176 case AFCSELD: 4177 return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10 4178 4179 case AFMOVS: 4180 return FPOP1S(0, 0, 0, 0) 4181 4182 case AFABSS: 4183 return FPOP1S(0, 0, 0, 1) 4184 4185 case AFNEGS: 4186 return FPOP1S(0, 0, 0, 2) 4187 4188 case AFSQRTS: 4189 return FPOP1S(0, 0, 0, 3) 4190 4191 case AFCVTSD: 4192 return FPOP1S(0, 0, 0, 5) 4193 4194 case AFCVTSH: 4195 return FPOP1S(0, 0, 0, 7) 4196 4197 case AFRINTNS: 4198 return FPOP1S(0, 0, 0, 8) 4199 4200 case AFRINTPS: 4201 return FPOP1S(0, 0, 0, 9) 4202 4203 case AFRINTMS: 4204 return FPOP1S(0, 0, 0, 10) 4205 4206 case AFRINTZS: 4207 return FPOP1S(0, 0, 0, 11) 4208 4209 case AFRINTAS: 4210 return FPOP1S(0, 0, 0, 12) 4211 4212 case AFRINTXS: 4213 return FPOP1S(0, 0, 0, 14) 4214 4215 case AFRINTIS: 4216 return FPOP1S(0, 0, 0, 15) 4217 4218 case AFMOVD: 4219 return FPOP1S(0, 0, 1, 0) 4220 4221 case AFABSD: 4222 return FPOP1S(0, 0, 1, 1) 4223 4224 case AFNEGD: 4225 return FPOP1S(0, 0, 1, 2) 4226 4227 case AFSQRTD: 4228 return FPOP1S(0, 0, 1, 3) 4229 4230 case AFCVTDS: 4231 return FPOP1S(0, 0, 1, 4) 4232 4233 case AFCVTDH: 4234 return FPOP1S(0, 0, 1, 7) 4235 4236 case AFRINTND: 4237 return FPOP1S(0, 0, 1, 8) 4238 4239 case AFRINTPD: 4240 return FPOP1S(0, 0, 1, 9) 4241 4242 case AFRINTMD: 4243 return FPOP1S(0, 0, 1, 10) 4244 4245 case AFRINTZD: 4246 return FPOP1S(0, 0, 1, 11) 4247 4248 case AFRINTAD: 4249 return FPOP1S(0, 0, 1, 12) 4250 4251 case AFRINTXD: 4252 return FPOP1S(0, 0, 1, 14) 4253 4254 case AFRINTID: 4255 return FPOP1S(0, 0, 1, 15) 4256 4257 case AFCVTHS: 4258 return FPOP1S(0, 0, 3, 4) 4259 4260 case AFCVTHD: 4261 return FPOP1S(0, 0, 3, 5) 4262 4263 case AVADD: 4264 return 7<<25 | 1<<21 | 1<<15 | 1<<10 4265 4266 case AVADDP: 4267 return 7<<25 | 1<<21 | 1<<15 | 15<<10 4268 4269 case AVAND: 4270 return 7<<25 | 1<<21 | 7<<10 4271 4272 case AVCMEQ: 4273 return 1<<29 | 0x71<<21 | 0x23<<10 4274 4275 case AVEOR: 4276 return 1<<29 | 0x71<<21 | 7<<10 4277 4278 case AVORR: 4279 return 7<<25 | 5<<21 | 7<<10 4280 4281 case AVREV32: 4282 return 11<<26 | 2<<24 | 1<<21 | 1<<11 4283 4284 case AVMOV: 4285 return 7<<25 | 5<<21 | 7<<10 4286 4287 case AVADDV: 4288 return 7<<25 | 3<<20 | 3<<15 | 7<<11 4289 4290 case AVUADDLV: 4291 return 1<<29 | 7<<25 | 3<<20 | 7<<11 4292 } 4293 4294 c.ctxt.Diag("%v: bad rrr %d %v", p, a, a) 4295 return 0 4296 } 4297 4298 /* 4299 * imm -> Rd 4300 * imm op Rn -> Rd 4301 */ 4302 func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 { 4303 switch a { 4304 /* op $addcon, Rn, Rd */ 4305 case AMOVD, AADD: 4306 return S64 | 0<<30 | 0<<29 | 0x11<<24 4307 4308 case ACMN, AADDS: 4309 return S64 | 0<<30 | 1<<29 | 0x11<<24 4310 4311 case AMOVW, AADDW: 4312 return S32 | 0<<30 | 0<<29 | 0x11<<24 4313 4314 case ACMNW, AADDSW: 4315 return S32 | 0<<30 | 1<<29 | 0x11<<24 4316 4317 case ASUB: 4318 return S64 | 1<<30 | 0<<29 | 0x11<<24 4319 4320 case ACMP, ASUBS: 4321 return S64 | 1<<30 | 1<<29 | 0x11<<24 4322 4323 case ASUBW: 4324 return S32 | 1<<30 | 0<<29 | 0x11<<24 4325 4326 case ACMPW, ASUBSW: 4327 return S32 | 1<<30 | 1<<29 | 0x11<<24 4328 4329 /* op $imm(SB), Rd; op label, Rd */ 4330 case AADR: 4331 return 0<<31 | 0x10<<24 4332 4333 case AADRP: 4334 return 1<<31 | 0x10<<24 4335 4336 /* op $bimm, Rn, Rd */ 4337 case AAND, ABIC: 4338 return S64 | 0<<29 | 0x24<<23 4339 4340 case AANDW, ABICW: 4341 return S32 | 0<<29 | 0x24<<23 | 0<<22 4342 4343 case AORR, AORN: 4344 return S64 | 1<<29 | 0x24<<23 4345 4346 case AORRW, AORNW: 4347 return S32 | 1<<29 | 0x24<<23 | 0<<22 4348 4349 case AEOR, AEON: 4350 return S64 | 2<<29 | 0x24<<23 4351 4352 case AEORW, AEONW: 4353 return S32 | 2<<29 | 0x24<<23 | 0<<22 4354 4355 case AANDS, ABICS: 4356 return S64 | 3<<29 | 0x24<<23 4357 4358 case AANDSW, ABICSW: 4359 return S32 | 3<<29 | 0x24<<23 | 0<<22 4360 4361 case AASR: 4362 return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */ 4363 4364 case AASRW: 4365 return S32 | 0<<29 | 0x26<<23 | 0<<22 4366 4367 /* op $width, $lsb, Rn, Rd */ 4368 case ABFI: 4369 return S64 | 2<<29 | 0x26<<23 | 1<<22 4370 /* alias of BFM */ 4371 4372 case ABFIW: 4373 return S32 | 2<<29 | 0x26<<23 | 0<<22 4374 4375 /* op $imms, $immr, Rn, Rd */ 4376 case ABFM: 4377 return S64 | 1<<29 | 0x26<<23 | 1<<22 4378 4379 case ABFMW: 4380 return S32 | 1<<29 | 0x26<<23 | 0<<22 4381 4382 case ASBFM: 4383 return S64 | 0<<29 | 0x26<<23 | 1<<22 4384 4385 case ASBFMW: 4386 return S32 | 0<<29 | 0x26<<23 | 0<<22 4387 4388 case AUBFM: 4389 return S64 | 2<<29 | 0x26<<23 | 1<<22 4390 4391 case AUBFMW: 4392 return S32 | 2<<29 | 0x26<<23 | 0<<22 4393 4394 case ABFXIL: 4395 return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */ 4396 4397 case ABFXILW: 4398 return S32 | 1<<29 | 0x26<<23 | 0<<22 4399 4400 case AEXTR: 4401 return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21 4402 4403 case AEXTRW: 4404 return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21 4405 4406 case ACBNZ: 4407 return S64 | 0x1A<<25 | 1<<24 4408 4409 case ACBNZW: 4410 return S32 | 0x1A<<25 | 1<<24 4411 4412 case ACBZ: 4413 return S64 | 0x1A<<25 | 0<<24 4414 4415 case ACBZW: 4416 return S32 | 0x1A<<25 | 0<<24 4417 4418 case ACCMN: 4419 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 4420 4421 case ACCMNW: 4422 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 4423 4424 case ACCMP: 4425 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 4426 4427 case ACCMPW: 4428 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 4429 4430 case AMOVK: 4431 return S64 | 3<<29 | 0x25<<23 4432 4433 case AMOVKW: 4434 return S32 | 3<<29 | 0x25<<23 4435 4436 case AMOVN: 4437 return S64 | 0<<29 | 0x25<<23 4438 4439 case AMOVNW: 4440 return S32 | 0<<29 | 0x25<<23 4441 4442 case AMOVZ: 4443 return S64 | 2<<29 | 0x25<<23 4444 4445 case AMOVZW: 4446 return S32 | 2<<29 | 0x25<<23 4447 4448 case AMSR: 4449 return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */ 4450 4451 case AAT, 4452 ADC, 4453 AIC, 4454 ATLBI, 4455 ASYS: 4456 return SYSOP(0, 1, 0, 0, 0, 0, 0) 4457 4458 case ASYSL: 4459 return SYSOP(1, 1, 0, 0, 0, 0, 0) 4460 4461 case ATBZ: 4462 return 0x36 << 24 4463 4464 case ATBNZ: 4465 return 0x37 << 24 4466 4467 case ADSB: 4468 return SYSOP(0, 0, 3, 3, 0, 4, 0x1F) 4469 4470 case ADMB: 4471 return SYSOP(0, 0, 3, 3, 0, 5, 0x1F) 4472 4473 case AISB: 4474 return SYSOP(0, 0, 3, 3, 0, 6, 0x1F) 4475 4476 case AHINT: 4477 return SYSOP(0, 0, 3, 2, 0, 0, 0x1F) 4478 } 4479 4480 c.ctxt.Diag("%v: bad irr %v", p, a) 4481 return 0 4482 } 4483 4484 func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 { 4485 switch a { 4486 case ACLS: 4487 return S64 | OPBIT(5) 4488 4489 case ACLSW: 4490 return S32 | OPBIT(5) 4491 4492 case ACLZ: 4493 return S64 | OPBIT(4) 4494 4495 case ACLZW: 4496 return S32 | OPBIT(4) 4497 4498 case ARBIT: 4499 return S64 | OPBIT(0) 4500 4501 case ARBITW: 4502 return S32 | OPBIT(0) 4503 4504 case AREV: 4505 return S64 | OPBIT(3) 4506 4507 case AREVW: 4508 return S32 | OPBIT(2) 4509 4510 case AREV16: 4511 return S64 | OPBIT(1) 4512 4513 case AREV16W: 4514 return S32 | OPBIT(1) 4515 4516 case AREV32: 4517 return S64 | OPBIT(2) 4518 4519 default: 4520 c.ctxt.Diag("bad bit op\n%v", p) 4521 return 0 4522 } 4523 } 4524 4525 /* 4526 * add/subtract sign or zero-extended register 4527 */ 4528 func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 { 4529 extension := uint32(0) 4530 if !extend { 4531 switch a { 4532 case AADD, ACMN, AADDS, ASUB, ACMP, ASUBS: 4533 extension = LSL0_64 4534 4535 case AADDW, ACMNW, AADDSW, ASUBW, ACMPW, ASUBSW: 4536 extension = LSL0_32 4537 } 4538 } 4539 4540 switch a { 4541 case AADD: 4542 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 4543 4544 case AADDW: 4545 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 4546 4547 case ACMN, AADDS: 4548 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 4549 4550 case ACMNW, AADDSW: 4551 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 4552 4553 case ASUB: 4554 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 4555 4556 case ASUBW: 4557 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 4558 4559 case ACMP, ASUBS: 4560 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 4561 4562 case ACMPW, ASUBSW: 4563 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 4564 } 4565 4566 c.ctxt.Diag("bad opxrrr %v\n%v", a, p) 4567 return 0 4568 } 4569 4570 func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 { 4571 switch a { 4572 case ASVC: 4573 return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */ 4574 4575 case AHVC: 4576 return 0xD4<<24 | 0<<21 | 2 4577 4578 case ASMC: 4579 return 0xD4<<24 | 0<<21 | 3 4580 4581 case ABRK: 4582 return 0xD4<<24 | 1<<21 | 0 4583 4584 case AHLT: 4585 return 0xD4<<24 | 2<<21 | 0 4586 4587 case ADCPS1: 4588 return 0xD4<<24 | 5<<21 | 1 4589 4590 case ADCPS2: 4591 return 0xD4<<24 | 5<<21 | 2 4592 4593 case ADCPS3: 4594 return 0xD4<<24 | 5<<21 | 3 4595 4596 case ACLREX: 4597 return SYSOP(0, 0, 3, 3, 0, 2, 0x1F) 4598 } 4599 4600 c.ctxt.Diag("%v: bad imm %v", p, a) 4601 return 0 4602 } 4603 4604 func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 { 4605 v := int64(0) 4606 t := int64(0) 4607 if p.Pcond != nil { 4608 v = (p.Pcond.Pc >> uint(preshift)) - (c.pc >> uint(preshift)) 4609 if (v & ((1 << uint(shift)) - 1)) != 0 { 4610 c.ctxt.Diag("misaligned label\n%v", p) 4611 } 4612 v >>= uint(shift) 4613 t = int64(1) << uint(flen-1) 4614 if v < -t || v >= t { 4615 c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, p.Pcond) 4616 panic("branch too far") 4617 } 4618 } 4619 4620 return v & ((t << 1) - 1) 4621 } 4622 4623 /* 4624 * pc-relative branches 4625 */ 4626 func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 { 4627 switch a { 4628 case ABEQ: 4629 return OPBcc(0x0) 4630 4631 case ABNE: 4632 return OPBcc(0x1) 4633 4634 case ABCS: 4635 return OPBcc(0x2) 4636 4637 case ABHS: 4638 return OPBcc(0x2) 4639 4640 case ABCC: 4641 return OPBcc(0x3) 4642 4643 case ABLO: 4644 return OPBcc(0x3) 4645 4646 case ABMI: 4647 return OPBcc(0x4) 4648 4649 case ABPL: 4650 return OPBcc(0x5) 4651 4652 case ABVS: 4653 return OPBcc(0x6) 4654 4655 case ABVC: 4656 return OPBcc(0x7) 4657 4658 case ABHI: 4659 return OPBcc(0x8) 4660 4661 case ABLS: 4662 return OPBcc(0x9) 4663 4664 case ABGE: 4665 return OPBcc(0xa) 4666 4667 case ABLT: 4668 return OPBcc(0xb) 4669 4670 case ABGT: 4671 return OPBcc(0xc) 4672 4673 case ABLE: 4674 return OPBcc(0xd) /* imm19<<5 | cond */ 4675 4676 case AB: 4677 return 0<<31 | 5<<26 /* imm26 */ 4678 4679 case obj.ADUFFZERO, obj.ADUFFCOPY, ABL: 4680 return 1<<31 | 5<<26 4681 } 4682 4683 c.ctxt.Diag("%v: bad bra %v", p, a) 4684 return 0 4685 } 4686 4687 func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 { 4688 switch a { 4689 case ABL: 4690 return OPBLR(1) /* BLR */ 4691 4692 case AB: 4693 return OPBLR(0) /* BR */ 4694 4695 case obj.ARET: 4696 return OPBLR(2) /* RET */ 4697 } 4698 4699 c.ctxt.Diag("%v: bad brr %v", p, a) 4700 return 0 4701 } 4702 4703 func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 { 4704 switch a { 4705 case ADRPS: 4706 return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5 4707 4708 case AERET: 4709 return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5 4710 4711 // case ANOP: 4712 // return SYSHINT(0) 4713 4714 case AYIELD: 4715 return SYSHINT(1) 4716 4717 case AWFE: 4718 return SYSHINT(2) 4719 4720 case AWFI: 4721 return SYSHINT(3) 4722 4723 case ASEV: 4724 return SYSHINT(4) 4725 4726 case ASEVL: 4727 return SYSHINT(5) 4728 } 4729 4730 c.ctxt.Diag("%v: bad op0 %v", p, a) 4731 return 0 4732 } 4733 4734 /* 4735 * register offset 4736 */ 4737 func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 { 4738 switch a { 4739 case ALDAR: 4740 return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10 4741 4742 case ALDARW: 4743 return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10 4744 4745 case ALDARB: 4746 return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10 4747 4748 case ALDARH: 4749 return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10 4750 4751 case ALDAXP: 4752 return LDSTX(3, 0, 1, 1, 1) 4753 4754 case ALDAXPW: 4755 return LDSTX(2, 0, 1, 1, 1) 4756 4757 case ALDAXR: 4758 return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10 4759 4760 case ALDAXRW: 4761 return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10 4762 4763 case ALDAXRB: 4764 return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10 4765 4766 case ALDAXRH: 4767 return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10 4768 4769 case ALDXR: 4770 return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10 4771 4772 case ALDXRB: 4773 return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10 4774 4775 case ALDXRH: 4776 return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10 4777 4778 case ALDXRW: 4779 return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10 4780 4781 case ALDXP: 4782 return LDSTX(3, 0, 1, 1, 0) 4783 4784 case ALDXPW: 4785 return LDSTX(2, 0, 1, 1, 0) 4786 4787 case AMOVNP: 4788 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 4789 4790 case AMOVNPW: 4791 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 4792 } 4793 4794 c.ctxt.Diag("bad opload %v\n%v", a, p) 4795 return 0 4796 } 4797 4798 func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 { 4799 switch a { 4800 case ASTLR: 4801 return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10 4802 4803 case ASTLRB: 4804 return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10 4805 4806 case ASTLRH: 4807 return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10 4808 4809 case ASTLP: 4810 return LDSTX(3, 0, 0, 1, 1) 4811 4812 case ASTLPW: 4813 return LDSTX(2, 0, 0, 1, 1) 4814 4815 case ASTLRW: 4816 return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10 4817 4818 case ASTLXP: 4819 return LDSTX(2, 0, 0, 1, 1) 4820 4821 case ASTLXPW: 4822 return LDSTX(3, 0, 0, 1, 1) 4823 4824 case ASTLXR: 4825 return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10 4826 4827 case ASTLXRB: 4828 return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10 4829 4830 case ASTLXRH: 4831 return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10 4832 4833 case ASTLXRW: 4834 return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10 4835 4836 case ASTXR: 4837 return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10 4838 4839 case ASTXRB: 4840 return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10 4841 4842 case ASTXRH: 4843 return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10 4844 4845 case ASTXP: 4846 return LDSTX(3, 0, 0, 1, 0) 4847 4848 case ASTXPW: 4849 return LDSTX(2, 0, 0, 1, 0) 4850 4851 case ASTXRW: 4852 return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10 4853 4854 case AMOVNP: 4855 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 4856 4857 case AMOVNPW: 4858 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 4859 } 4860 4861 c.ctxt.Diag("bad opstore %v\n%v", a, p) 4862 return 0 4863 } 4864 4865 /* 4866 * load/store register (unsigned immediate) C3.3.13 4867 * these produce 64-bit values (when there's an option) 4868 */ 4869 func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 { 4870 if v < 0 || v >= (1<<12) { 4871 c.ctxt.Diag("offset out of range: %d\n%v", v, p) 4872 } 4873 o |= (v & 0xFFF) << 10 4874 o |= int32(b&31) << 5 4875 o |= int32(r & 31) 4876 return uint32(o) 4877 } 4878 4879 func (c *ctxt7) opldr12(p *obj.Prog, a obj.As) uint32 { 4880 switch a { 4881 case AMOVD: 4882 return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */ 4883 4884 case AMOVW: 4885 return LDSTR12U(2, 0, 2) 4886 4887 case AMOVWU: 4888 return LDSTR12U(2, 0, 1) 4889 4890 case AMOVH: 4891 return LDSTR12U(1, 0, 2) 4892 4893 case AMOVHU: 4894 return LDSTR12U(1, 0, 1) 4895 4896 case AMOVB: 4897 return LDSTR12U(0, 0, 2) 4898 4899 case AMOVBU: 4900 return LDSTR12U(0, 0, 1) 4901 4902 case AFMOVS: 4903 return LDSTR12U(2, 1, 1) 4904 4905 case AFMOVD: 4906 return LDSTR12U(3, 1, 1) 4907 4908 case AVMOVS: 4909 return LDSTR12U(2, 1, 1) 4910 } 4911 4912 c.ctxt.Diag("bad opldr12 %v\n%v", a, p) 4913 return 0 4914 } 4915 4916 func (c *ctxt7) opstr12(p *obj.Prog, a obj.As) uint32 { 4917 return LD2STR(c.opldr12(p, a)) 4918 } 4919 4920 /* 4921 * load/store register (unscaled immediate) C3.3.12 4922 */ 4923 func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 { 4924 if v < -256 || v > 255 { 4925 c.ctxt.Diag("offset out of range: %d\n%v", v, p) 4926 } 4927 o |= (v & 0x1FF) << 12 4928 o |= int32(b&31) << 5 4929 o |= int32(r & 31) 4930 return uint32(o) 4931 } 4932 4933 func (c *ctxt7) opldr9(p *obj.Prog, a obj.As) uint32 { 4934 switch a { 4935 case AMOVD: 4936 return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */ 4937 4938 case AMOVW: 4939 return LDSTR9S(2, 0, 2) 4940 4941 case AMOVWU: 4942 return LDSTR9S(2, 0, 1) 4943 4944 case AMOVH: 4945 return LDSTR9S(1, 0, 2) 4946 4947 case AMOVHU: 4948 return LDSTR9S(1, 0, 1) 4949 4950 case AMOVB: 4951 return LDSTR9S(0, 0, 2) 4952 4953 case AMOVBU: 4954 return LDSTR9S(0, 0, 1) 4955 4956 case AFMOVS: 4957 return LDSTR9S(2, 1, 1) 4958 4959 case AFMOVD: 4960 return LDSTR9S(3, 1, 1) 4961 } 4962 4963 c.ctxt.Diag("bad opldr9 %v\n%v", a, p) 4964 return 0 4965 } 4966 4967 func (c *ctxt7) opstr9(p *obj.Prog, a obj.As) uint32 { 4968 return LD2STR(c.opldr9(p, a)) 4969 } 4970 4971 func (c *ctxt7) opldrpp(p *obj.Prog, a obj.As) uint32 { 4972 switch a { 4973 case AMOVD: 4974 return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */ 4975 4976 case AMOVW: 4977 return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 4978 4979 case AMOVWU: 4980 return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 4981 4982 case AMOVH: 4983 return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 4984 4985 case AMOVHU: 4986 return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 4987 4988 case AMOVB: 4989 return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 4990 4991 case AMOVBU: 4992 return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 4993 4994 case AVMOVS: 4995 return 2<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22 4996 } 4997 4998 c.ctxt.Diag("bad opldr %v\n%v", a, p) 4999 return 0 5000 } 5001 5002 // olsxrr attaches register operands to a load/store opcode supplied in o. 5003 // The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2). 5004 func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 { 5005 o |= int32(r1&31) << 5 5006 o |= int32(r2&31) << 16 5007 o |= int32(r & 31) 5008 return uint32(o) 5009 } 5010 5011 // opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode 5012 // for load instruction with register offset. 5013 func (c *ctxt7) opldrr(p *obj.Prog, a obj.As) uint32 { 5014 switch a { 5015 case AMOVD: 5016 return 0x1a<<10 | 0x3<<21 | 0x1f<<27 5017 case AMOVW: 5018 return 0x1a<<10 | 0x5<<21 | 0x17<<27 5019 case AMOVWU: 5020 return 0x1a<<10 | 0x3<<21 | 0x17<<27 5021 case AMOVH: 5022 return 0x1a<<10 | 0x5<<21 | 0x0f<<27 5023 case AMOVHU: 5024 return 0x1a<<10 | 0x3<<21 | 0x0f<<27 5025 case AMOVB: 5026 return 0x1a<<10 | 0x5<<21 | 0x07<<27 5027 case AMOVBU: 5028 return 0x1a<<10 | 0x3<<21 | 0x07<<27 5029 case AFMOVS: 5030 return 0x1a<<10 | 0x3<<21 | 0x17<<27 | 1<<26 5031 case AFMOVD: 5032 return 0x1a<<10 | 0x3<<21 | 0x1f<<27 | 1<<26 5033 } 5034 c.ctxt.Diag("bad opldrr %v\n%v", a, p) 5035 return 0 5036 } 5037 5038 // opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode 5039 // for store instruction with register offset. 5040 func (c *ctxt7) opstrr(p *obj.Prog, a obj.As) uint32 { 5041 switch a { 5042 case AMOVD: 5043 return 0x1a<<10 | 0x1<<21 | 0x1f<<27 5044 case AMOVW, AMOVWU: 5045 return 0x1a<<10 | 0x1<<21 | 0x17<<27 5046 case AMOVH, AMOVHU: 5047 return 0x1a<<10 | 0x1<<21 | 0x0f<<27 5048 case AMOVB, AMOVBU: 5049 return 0x1a<<10 | 0x1<<21 | 0x07<<27 5050 case AFMOVS: 5051 return 0x1a<<10 | 0x1<<21 | 0x17<<27 | 1<<26 5052 case AFMOVD: 5053 return 0x1a<<10 | 0x1<<21 | 0x1f<<27 | 1<<26 5054 } 5055 c.ctxt.Diag("bad opstrr %v\n%v", a, p) 5056 return 0 5057 } 5058 5059 func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 { 5060 if (v & 0xFFF000) != 0 { 5061 if v&0xFFF != 0 { 5062 c.ctxt.Diag("%v misuses oaddi", p) 5063 } 5064 v >>= 12 5065 o1 |= 1 << 22 5066 } 5067 5068 o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31) 5069 return uint32(o1) 5070 } 5071 5072 /* 5073 * load a a literal value into dr 5074 */ 5075 func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 { 5076 var o1 int32 5077 if p.Pcond == nil { /* not in literal pool */ 5078 c.aclass(a) 5079 c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset)) 5080 5081 /* TODO: could be clever, and use general constant builder */ 5082 o1 = int32(c.opirr(p, AADD)) 5083 5084 v := int32(c.instoffset) 5085 if v != 0 && (v&0xFFF) == 0 { 5086 v >>= 12 5087 o1 |= 1 << 22 /* shift, by 12 */ 5088 } 5089 5090 o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31) 5091 } else { 5092 fp := 0 5093 w := 0 /* default: 32 bit, unsigned */ 5094 switch as { 5095 case AFMOVS: 5096 fp = 1 5097 5098 case AFMOVD: 5099 fp = 1 5100 w = 1 /* 64 bit simd&fp */ 5101 5102 case AMOVD: 5103 if p.Pcond.As == ADWORD { 5104 w = 1 /* 64 bit */ 5105 } else if p.Pcond.To.Offset < 0 { 5106 w = 2 /* sign extend */ 5107 } 5108 5109 case AMOVB, AMOVH, AMOVW: 5110 w = 2 /* 32 bit, sign-extended to 64 */ 5111 break 5112 } 5113 5114 v := int32(c.brdist(p, 0, 19, 2)) 5115 o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27) 5116 o1 |= (v & 0x7FFFF) << 5 5117 o1 |= int32(dr & 31) 5118 } 5119 5120 return uint32(o1) 5121 } 5122 5123 // load a constant (MOVCON or BITCON) in a into rt 5124 func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) { 5125 if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 { 5126 // or $bitcon, REGZERO, rt 5127 mode := 64 5128 var as1 obj.As 5129 switch as { 5130 case AMOVW: 5131 as1 = AORRW 5132 mode = 32 5133 case AMOVD: 5134 as1 = AORR 5135 } 5136 o1 = c.opirr(p, as1) 5137 o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31) 5138 return o1 5139 } 5140 5141 r := 32 5142 if as == AMOVD { 5143 r = 64 5144 } 5145 d := a.Offset 5146 s := movcon(d) 5147 if s < 0 || s >= r { 5148 d = ^d 5149 s = movcon(d) 5150 if s < 0 || s >= r { 5151 c.ctxt.Diag("impossible move wide: %#x\n%v", uint64(a.Offset), p) 5152 } 5153 if as == AMOVD { 5154 o1 = c.opirr(p, AMOVN) 5155 } else { 5156 o1 = c.opirr(p, AMOVNW) 5157 } 5158 } else { 5159 if as == AMOVD { 5160 o1 = c.opirr(p, AMOVZ) 5161 } else { 5162 o1 = c.opirr(p, AMOVZW) 5163 } 5164 } 5165 o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31)) 5166 return o1 5167 } 5168 5169 func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 { 5170 var b uint32 5171 o := c.opirr(p, a) 5172 if (o & (1 << 31)) == 0 { 5173 b = 32 5174 } else { 5175 b = 64 5176 } 5177 if r < 0 || uint32(r) >= b { 5178 c.ctxt.Diag("illegal bit number\n%v", p) 5179 } 5180 o |= (uint32(r) & 0x3F) << 16 5181 if s < 0 || uint32(s) >= b { 5182 c.ctxt.Diag("illegal bit number\n%v", p) 5183 } 5184 o |= (uint32(s) & 0x3F) << 10 5185 o |= (uint32(rf&31) << 5) | uint32(rt&31) 5186 return o 5187 } 5188 5189 func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 { 5190 var b uint32 5191 o := c.opirr(p, a) 5192 if (o & (1 << 31)) != 0 { 5193 b = 63 5194 } else { 5195 b = 31 5196 } 5197 if v < 0 || uint32(v) > b { 5198 c.ctxt.Diag("illegal bit number\n%v", p) 5199 } 5200 o |= uint32(v) << 10 5201 o |= uint32(rn&31) << 5 5202 o |= uint32(rm&31) << 16 5203 o |= uint32(rt & 31) 5204 return o 5205 } 5206 5207 /* 5208 * size in log2(bytes) 5209 */ 5210 func movesize(a obj.As) int { 5211 switch a { 5212 case AMOVD: 5213 return 3 5214 5215 case AMOVW, AMOVWU, AVMOVS: 5216 return 2 5217 5218 case AMOVH, AMOVHU: 5219 return 1 5220 5221 case AMOVB, AMOVBU: 5222 return 0 5223 5224 case AFMOVS: 5225 return 2 5226 5227 case AFMOVD: 5228 return 3 5229 5230 default: 5231 return -1 5232 } 5233 }