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