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