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