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