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