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