github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/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 c.instoffset = int64(c.autosize) + a.Offset 1153 return autoclass(c.instoffset) 1154 1155 case obj.NAME_PARAM: 1156 c.instoffset = int64(c.autosize) + a.Offset + 8 1157 return autoclass(c.instoffset) 1158 1159 case obj.NAME_NONE: 1160 c.instoffset = a.Offset 1161 return oregclass(c.instoffset) 1162 } 1163 return C_GOK 1164 1165 case obj.TYPE_FCONST: 1166 return C_FCON 1167 1168 case obj.TYPE_TEXTSIZE: 1169 return C_TEXTSIZE 1170 1171 case obj.TYPE_CONST, obj.TYPE_ADDR: 1172 switch a.Name { 1173 case obj.NAME_NONE: 1174 c.instoffset = a.Offset 1175 if a.Reg != 0 && a.Reg != REGZERO { 1176 goto aconsize 1177 } 1178 v := c.instoffset 1179 if v == 0 { 1180 return C_ZCON 1181 } 1182 if isaddcon(v) { 1183 if v <= 0xFFF { 1184 if isbitcon(uint64(v)) { 1185 return C_ABCON0 1186 } 1187 return C_ADDCON0 1188 } 1189 if isbitcon(uint64(v)) { 1190 return C_ABCON 1191 } 1192 return C_ADDCON 1193 } 1194 1195 t := movcon(v) 1196 if t >= 0 { 1197 if isbitcon(uint64(v)) { 1198 return C_MBCON 1199 } 1200 return C_MOVCON 1201 } 1202 1203 t = movcon(^v) 1204 if t >= 0 { 1205 if isbitcon(uint64(v)) { 1206 return C_MBCON 1207 } 1208 return C_MOVCON 1209 } 1210 1211 if isbitcon(uint64(v)) { 1212 return C_BITCON 1213 } 1214 1215 if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) { 1216 return C_LCON 1217 } 1218 return C_VCON 1219 1220 case obj.NAME_EXTERN, obj.NAME_STATIC: 1221 if a.Sym == nil { 1222 break 1223 } 1224 if a.Sym.Type == objabi.STLSBSS { 1225 c.ctxt.Diag("taking address of TLS variable is not supported") 1226 } 1227 c.instoffset = a.Offset 1228 return C_VCONADDR 1229 1230 case obj.NAME_AUTO: 1231 c.instoffset = int64(c.autosize) + a.Offset 1232 goto aconsize 1233 1234 case obj.NAME_PARAM: 1235 c.instoffset = int64(c.autosize) + a.Offset + 8 1236 goto aconsize 1237 } 1238 return C_GOK 1239 1240 aconsize: 1241 if isaddcon(c.instoffset) { 1242 return C_AACON 1243 } 1244 return C_LACON 1245 1246 case obj.TYPE_BRANCH: 1247 return C_SBRA 1248 } 1249 1250 return C_GOK 1251 } 1252 1253 func oclass(a *obj.Addr) int { 1254 return int(a.Class) - 1 1255 } 1256 1257 func (c *ctxt7) oplook(p *obj.Prog) *Optab { 1258 a1 := int(p.Optab) 1259 if a1 != 0 { 1260 return &optab[a1-1] 1261 } 1262 a1 = int(p.From.Class) 1263 if a1 == 0 { 1264 a1 = c.aclass(&p.From) + 1 1265 p.From.Class = int8(a1) 1266 } 1267 1268 a1-- 1269 a3 := int(p.To.Class) 1270 if a3 == 0 { 1271 a3 = c.aclass(&p.To) + 1 1272 p.To.Class = int8(a3) 1273 } 1274 1275 a3-- 1276 a2 := C_NONE 1277 if p.Reg != 0 { 1278 a2 = rclass(p.Reg) 1279 } 1280 1281 if false { 1282 fmt.Printf("oplook %v %d %d %d\n", p.As, a1, a2, a3) 1283 fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type) 1284 } 1285 1286 ops := oprange[p.As&obj.AMask] 1287 c1 := &xcmp[a1] 1288 c2 := &xcmp[a2] 1289 c3 := &xcmp[a3] 1290 c4 := &xcmp[p.Scond>>5] 1291 for i := range ops { 1292 op := &ops[i] 1293 if (int(op.a2) == a2 || c2[op.a2]) && c4[op.scond>>5] && c1[op.a1] && c3[op.a3] { 1294 p.Optab = uint16(cap(optab) - cap(ops) + i + 1) 1295 return op 1296 } 1297 } 1298 1299 c.ctxt.Diag("illegal combination %v %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.To.Type) 1300 if ops == nil { 1301 ops = optab 1302 } 1303 return &ops[0] 1304 } 1305 1306 func cmp(a int, b int) bool { 1307 if a == b { 1308 return true 1309 } 1310 switch a { 1311 case C_RSP: 1312 if b == C_REG { 1313 return true 1314 } 1315 1316 case C_REG: 1317 if b == C_ZCON { 1318 return true 1319 } 1320 1321 case C_ADDCON0: 1322 if b == C_ZCON || b == C_ABCON0 { 1323 return true 1324 } 1325 1326 case C_ADDCON: 1327 if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON { 1328 return true 1329 } 1330 1331 case C_BITCON: 1332 if b == C_ABCON0 || b == C_ABCON || b == C_MBCON { 1333 return true 1334 } 1335 1336 case C_MOVCON: 1337 if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 { 1338 return true 1339 } 1340 1341 case C_LCON: 1342 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 { 1343 return true 1344 } 1345 1346 case C_VCON: 1347 return cmp(C_LCON, b) 1348 1349 case C_LACON: 1350 if b == C_AACON { 1351 return true 1352 } 1353 1354 case C_SEXT2: 1355 if b == C_SEXT1 { 1356 return true 1357 } 1358 1359 case C_SEXT4: 1360 if b == C_SEXT1 || b == C_SEXT2 { 1361 return true 1362 } 1363 1364 case C_SEXT8: 1365 if b >= C_SEXT1 && b <= C_SEXT4 { 1366 return true 1367 } 1368 1369 case C_SEXT16: 1370 if b >= C_SEXT1 && b <= C_SEXT8 { 1371 return true 1372 } 1373 1374 case C_LEXT: 1375 if b >= C_SEXT1 && b <= C_SEXT16 { 1376 return true 1377 } 1378 1379 case C_PPAUTO: 1380 if b == C_PSAUTO { 1381 return true 1382 } 1383 1384 case C_UAUTO4K: 1385 switch b { 1386 case C_PSAUTO, C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8: 1387 return true 1388 } 1389 1390 case C_UAUTO8K: 1391 switch b { 1392 case C_PSAUTO, C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8: 1393 return true 1394 } 1395 1396 case C_UAUTO16K: 1397 switch b { 1398 case C_PSAUTO, C_PPAUTO, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO16K_8: 1399 return true 1400 } 1401 1402 case C_UAUTO32K: 1403 switch b { 1404 case C_PSAUTO, C_PPAUTO, C_UAUTO4K_8, C_UAUTO8K_8, C_UAUTO16K_8: 1405 return true 1406 } 1407 1408 case C_NPAUTO: 1409 return cmp(C_NSAUTO, b) 1410 1411 case C_LAUTO: 1412 switch b { 1413 case C_PSAUTO, C_PPAUTO, 1414 C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, 1415 C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8, 1416 C_UAUTO16K, C_UAUTO16K_8, 1417 C_UAUTO32K: 1418 return true 1419 } 1420 return cmp(C_NPAUTO, b) 1421 1422 case C_PSOREG: 1423 if b == C_ZOREG { 1424 return true 1425 } 1426 1427 case C_PPOREG: 1428 if b == C_ZOREG || b == C_PSOREG { 1429 return true 1430 } 1431 1432 case C_UOREG4K: 1433 switch b { 1434 case C_ZOREG, C_PSOREG, C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8: 1435 return true 1436 } 1437 1438 case C_UOREG8K: 1439 switch b { 1440 case C_ZOREG, C_PSOREG, C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG8K_4, C_UOREG8K_8: 1441 return true 1442 } 1443 1444 case C_UOREG16K: 1445 switch b { 1446 case C_ZOREG, C_PSOREG, C_PPOREG, C_UOREG4K_4, C_UOREG4K_8, C_UOREG8K_4, C_UOREG8K_8, C_UOREG16K_8: 1447 return true 1448 } 1449 1450 case C_UOREG32K: 1451 switch b { 1452 case C_ZOREG, C_PSOREG, C_PPOREG, C_UOREG4K_8, C_UOREG8K_8, C_UOREG16K_8: 1453 return true 1454 } 1455 1456 case C_NPOREG: 1457 return cmp(C_NSOREG, b) 1458 1459 case C_LOREG: 1460 switch b { 1461 case C_ZOREG, C_PSOREG, C_PPOREG, 1462 C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, 1463 C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8, 1464 C_UOREG16K, C_UOREG16K_8, 1465 C_UOREG32K: 1466 return true 1467 } 1468 return cmp(C_NPOREG, b) 1469 1470 case C_LBRA: 1471 if b == C_SBRA { 1472 return true 1473 } 1474 } 1475 1476 return false 1477 } 1478 1479 type ocmp []Optab 1480 1481 func (x ocmp) Len() int { 1482 return len(x) 1483 } 1484 1485 func (x ocmp) Swap(i, j int) { 1486 x[i], x[j] = x[j], x[i] 1487 } 1488 1489 func (x ocmp) Less(i, j int) bool { 1490 p1 := &x[i] 1491 p2 := &x[j] 1492 if p1.as != p2.as { 1493 return p1.as < p2.as 1494 } 1495 if p1.a1 != p2.a1 { 1496 return p1.a1 < p2.a1 1497 } 1498 if p1.a2 != p2.a2 { 1499 return p1.a2 < p2.a2 1500 } 1501 if p1.a3 != p2.a3 { 1502 return p1.a3 < p2.a3 1503 } 1504 if p1.scond != p2.scond { 1505 return p1.scond < p2.scond 1506 } 1507 return false 1508 } 1509 1510 func oprangeset(a obj.As, t []Optab) { 1511 oprange[a&obj.AMask] = t 1512 } 1513 1514 func buildop(ctxt *obj.Link) { 1515 if oprange[AAND&obj.AMask] != nil { 1516 // Already initialized; stop now. 1517 // This happens in the cmd/asm tests, 1518 // each of which re-initializes the arch. 1519 return 1520 } 1521 1522 var n int 1523 for i := 0; i < C_GOK; i++ { 1524 for n = 0; n < C_GOK; n++ { 1525 if cmp(n, i) { 1526 xcmp[i][n] = true 1527 } 1528 } 1529 } 1530 for n = 0; optab[n].as != obj.AXXX; n++ { 1531 } 1532 sort.Sort(ocmp(optab[:n])) 1533 for i := 0; i < n; i++ { 1534 r := optab[i].as 1535 start := i 1536 for optab[i].as == r { 1537 i++ 1538 } 1539 t := optab[start:i] 1540 i-- 1541 oprangeset(r, t) 1542 switch r { 1543 default: 1544 ctxt.Diag("unknown op in build: %v", r) 1545 log.Fatalf("bad code") 1546 1547 case AADD: 1548 oprangeset(AADDS, t) 1549 oprangeset(ASUB, t) 1550 oprangeset(ASUBS, t) 1551 oprangeset(AADDW, t) 1552 oprangeset(AADDSW, t) 1553 oprangeset(ASUBW, t) 1554 oprangeset(ASUBSW, t) 1555 1556 case AAND: /* logical immediate, logical shifted register */ 1557 oprangeset(AANDS, t) 1558 1559 oprangeset(AANDSW, t) 1560 oprangeset(AANDW, t) 1561 oprangeset(AEOR, t) 1562 oprangeset(AEORW, t) 1563 oprangeset(AORR, t) 1564 oprangeset(AORRW, t) 1565 1566 case ABIC: /* only logical shifted register */ 1567 oprangeset(ABICS, t) 1568 1569 oprangeset(ABICSW, t) 1570 oprangeset(ABICW, t) 1571 oprangeset(AEON, t) 1572 oprangeset(AEONW, t) 1573 oprangeset(AORN, t) 1574 oprangeset(AORNW, t) 1575 1576 case ANEG: 1577 oprangeset(ANEGS, t) 1578 oprangeset(ANEGSW, t) 1579 oprangeset(ANEGW, t) 1580 1581 case AADC: /* rn=Rd */ 1582 oprangeset(AADCW, t) 1583 1584 oprangeset(AADCS, t) 1585 oprangeset(AADCSW, t) 1586 oprangeset(ASBC, t) 1587 oprangeset(ASBCW, t) 1588 oprangeset(ASBCS, t) 1589 oprangeset(ASBCSW, t) 1590 1591 case ANGC: /* rn=REGZERO */ 1592 oprangeset(ANGCW, t) 1593 1594 oprangeset(ANGCS, t) 1595 oprangeset(ANGCSW, t) 1596 1597 case ACMP: 1598 oprangeset(ACMPW, t) 1599 oprangeset(ACMN, t) 1600 oprangeset(ACMNW, t) 1601 1602 case ATST: 1603 oprangeset(ATSTW, t) 1604 1605 /* register/register, and shifted */ 1606 case AMVN: 1607 oprangeset(AMVNW, t) 1608 1609 case AMOVK: 1610 oprangeset(AMOVKW, t) 1611 oprangeset(AMOVN, t) 1612 oprangeset(AMOVNW, t) 1613 oprangeset(AMOVZ, t) 1614 oprangeset(AMOVZW, t) 1615 1616 case ABEQ: 1617 oprangeset(ABNE, t) 1618 oprangeset(ABCS, t) 1619 oprangeset(ABHS, t) 1620 oprangeset(ABCC, t) 1621 oprangeset(ABLO, t) 1622 oprangeset(ABMI, t) 1623 oprangeset(ABPL, t) 1624 oprangeset(ABVS, t) 1625 oprangeset(ABVC, t) 1626 oprangeset(ABHI, t) 1627 oprangeset(ABLS, t) 1628 oprangeset(ABGE, t) 1629 oprangeset(ABLT, t) 1630 oprangeset(ABGT, t) 1631 oprangeset(ABLE, t) 1632 1633 case ALSL: 1634 oprangeset(ALSLW, t) 1635 oprangeset(ALSR, t) 1636 oprangeset(ALSRW, t) 1637 oprangeset(AASR, t) 1638 oprangeset(AASRW, t) 1639 oprangeset(AROR, t) 1640 oprangeset(ARORW, t) 1641 1642 case ACLS: 1643 oprangeset(ACLSW, t) 1644 oprangeset(ACLZ, t) 1645 oprangeset(ACLZW, t) 1646 oprangeset(ARBIT, t) 1647 oprangeset(ARBITW, t) 1648 oprangeset(AREV, t) 1649 oprangeset(AREVW, t) 1650 oprangeset(AREV16, t) 1651 oprangeset(AREV16W, t) 1652 oprangeset(AREV32, t) 1653 1654 case ASDIV: 1655 oprangeset(ASDIVW, t) 1656 oprangeset(AUDIV, t) 1657 oprangeset(AUDIVW, t) 1658 oprangeset(ACRC32B, t) 1659 oprangeset(ACRC32CB, t) 1660 oprangeset(ACRC32CH, t) 1661 oprangeset(ACRC32CW, t) 1662 oprangeset(ACRC32CX, t) 1663 oprangeset(ACRC32H, t) 1664 oprangeset(ACRC32W, t) 1665 oprangeset(ACRC32X, t) 1666 1667 case AMADD: 1668 oprangeset(AMADDW, t) 1669 oprangeset(AMSUB, t) 1670 oprangeset(AMSUBW, t) 1671 oprangeset(ASMADDL, t) 1672 oprangeset(ASMSUBL, t) 1673 oprangeset(AUMADDL, t) 1674 oprangeset(AUMSUBL, t) 1675 1676 case AREM: 1677 oprangeset(AREMW, t) 1678 oprangeset(AUREM, t) 1679 oprangeset(AUREMW, t) 1680 1681 case AMUL: 1682 oprangeset(AMULW, t) 1683 oprangeset(AMNEG, t) 1684 oprangeset(AMNEGW, t) 1685 oprangeset(ASMNEGL, t) 1686 oprangeset(ASMULL, t) 1687 oprangeset(ASMULH, t) 1688 oprangeset(AUMNEGL, t) 1689 oprangeset(AUMULH, t) 1690 oprangeset(AUMULL, t) 1691 1692 case AMOVB: 1693 oprangeset(AMOVBU, t) 1694 1695 case AMOVH: 1696 oprangeset(AMOVHU, t) 1697 1698 case AMOVW: 1699 oprangeset(AMOVWU, t) 1700 1701 case ABFM: 1702 oprangeset(ABFMW, t) 1703 oprangeset(ASBFM, t) 1704 oprangeset(ASBFMW, t) 1705 oprangeset(AUBFM, t) 1706 oprangeset(AUBFMW, t) 1707 1708 case ABFI: 1709 oprangeset(ABFIW, t) 1710 oprangeset(ABFXIL, t) 1711 oprangeset(ABFXILW, t) 1712 oprangeset(ASBFIZ, t) 1713 oprangeset(ASBFIZW, t) 1714 oprangeset(ASBFX, t) 1715 oprangeset(ASBFXW, t) 1716 oprangeset(AUBFIZ, t) 1717 oprangeset(AUBFIZW, t) 1718 oprangeset(AUBFX, t) 1719 oprangeset(AUBFXW, t) 1720 1721 case AEXTR: 1722 oprangeset(AEXTRW, t) 1723 1724 case ASXTB: 1725 oprangeset(ASXTBW, t) 1726 oprangeset(ASXTH, t) 1727 oprangeset(ASXTHW, t) 1728 oprangeset(ASXTW, t) 1729 oprangeset(AUXTB, t) 1730 oprangeset(AUXTH, t) 1731 oprangeset(AUXTW, t) 1732 oprangeset(AUXTBW, t) 1733 oprangeset(AUXTHW, t) 1734 1735 case ACCMN: 1736 oprangeset(ACCMNW, t) 1737 oprangeset(ACCMP, t) 1738 oprangeset(ACCMPW, t) 1739 1740 case ACSEL: 1741 oprangeset(ACSELW, t) 1742 oprangeset(ACSINC, t) 1743 oprangeset(ACSINCW, t) 1744 oprangeset(ACSINV, t) 1745 oprangeset(ACSINVW, t) 1746 oprangeset(ACSNEG, t) 1747 oprangeset(ACSNEGW, t) 1748 1749 // aliases Rm=Rn, !cond 1750 oprangeset(ACINC, t) 1751 1752 oprangeset(ACINCW, t) 1753 oprangeset(ACINV, t) 1754 oprangeset(ACINVW, t) 1755 oprangeset(ACNEG, t) 1756 oprangeset(ACNEGW, t) 1757 1758 // aliases, Rm=Rn=REGZERO, !cond 1759 case ACSET: 1760 oprangeset(ACSETW, t) 1761 1762 oprangeset(ACSETM, t) 1763 oprangeset(ACSETMW, t) 1764 1765 case AMOVD, 1766 AMOVBU, 1767 AB, 1768 ABL, 1769 AWORD, 1770 ADWORD, 1771 obj.ARET, 1772 obj.ATEXT, 1773 ASTP, 1774 ALDP: 1775 break 1776 1777 case AERET: 1778 oprangeset(AWFE, t) 1779 oprangeset(AWFI, t) 1780 oprangeset(AYIELD, t) 1781 oprangeset(ASEV, t) 1782 oprangeset(ASEVL, t) 1783 oprangeset(ADRPS, t) 1784 1785 case ACBZ: 1786 oprangeset(ACBZW, t) 1787 oprangeset(ACBNZ, t) 1788 oprangeset(ACBNZW, t) 1789 1790 case ATBZ: 1791 oprangeset(ATBNZ, t) 1792 1793 case AADR, AADRP: 1794 break 1795 1796 case ACLREX: 1797 break 1798 1799 case ASVC: 1800 oprangeset(AHLT, t) 1801 oprangeset(AHVC, t) 1802 oprangeset(ASMC, t) 1803 oprangeset(ABRK, t) 1804 oprangeset(ADCPS1, t) 1805 oprangeset(ADCPS2, t) 1806 oprangeset(ADCPS3, t) 1807 1808 case AFADDS: 1809 oprangeset(AFADDD, t) 1810 oprangeset(AFSUBS, t) 1811 oprangeset(AFSUBD, t) 1812 oprangeset(AFMULS, t) 1813 oprangeset(AFMULD, t) 1814 oprangeset(AFNMULS, t) 1815 oprangeset(AFNMULD, t) 1816 oprangeset(AFDIVS, t) 1817 oprangeset(AFMAXD, t) 1818 oprangeset(AFMAXS, t) 1819 oprangeset(AFMIND, t) 1820 oprangeset(AFMINS, t) 1821 oprangeset(AFMAXNMD, t) 1822 oprangeset(AFMAXNMS, t) 1823 oprangeset(AFMINNMD, t) 1824 oprangeset(AFMINNMS, t) 1825 oprangeset(AFDIVD, t) 1826 1827 case AFCVTSD: 1828 oprangeset(AFCVTDS, t) 1829 oprangeset(AFABSD, t) 1830 oprangeset(AFABSS, t) 1831 oprangeset(AFNEGD, t) 1832 oprangeset(AFNEGS, t) 1833 oprangeset(AFSQRTD, t) 1834 oprangeset(AFSQRTS, t) 1835 oprangeset(AFRINTNS, t) 1836 oprangeset(AFRINTND, t) 1837 oprangeset(AFRINTPS, t) 1838 oprangeset(AFRINTPD, t) 1839 oprangeset(AFRINTMS, t) 1840 oprangeset(AFRINTMD, t) 1841 oprangeset(AFRINTZS, t) 1842 oprangeset(AFRINTZD, t) 1843 oprangeset(AFRINTAS, t) 1844 oprangeset(AFRINTAD, t) 1845 oprangeset(AFRINTXS, t) 1846 oprangeset(AFRINTXD, t) 1847 oprangeset(AFRINTIS, t) 1848 oprangeset(AFRINTID, t) 1849 oprangeset(AFCVTDH, t) 1850 oprangeset(AFCVTHS, t) 1851 oprangeset(AFCVTHD, t) 1852 oprangeset(AFCVTSH, t) 1853 1854 case AFCMPS: 1855 oprangeset(AFCMPD, t) 1856 oprangeset(AFCMPES, t) 1857 oprangeset(AFCMPED, t) 1858 1859 case AFCCMPS: 1860 oprangeset(AFCCMPD, t) 1861 oprangeset(AFCCMPES, t) 1862 oprangeset(AFCCMPED, t) 1863 1864 case AFCSELD: 1865 oprangeset(AFCSELS, t) 1866 1867 case AFMOVS, AFMOVD: 1868 break 1869 1870 case AFCVTZSD: 1871 oprangeset(AFCVTZSDW, t) 1872 oprangeset(AFCVTZSS, t) 1873 oprangeset(AFCVTZSSW, t) 1874 oprangeset(AFCVTZUD, t) 1875 oprangeset(AFCVTZUDW, t) 1876 oprangeset(AFCVTZUS, t) 1877 oprangeset(AFCVTZUSW, t) 1878 1879 case ASCVTFD: 1880 oprangeset(ASCVTFS, t) 1881 oprangeset(ASCVTFWD, t) 1882 oprangeset(ASCVTFWS, t) 1883 oprangeset(AUCVTFD, t) 1884 oprangeset(AUCVTFS, t) 1885 oprangeset(AUCVTFWD, t) 1886 oprangeset(AUCVTFWS, t) 1887 1888 case ASYS: 1889 oprangeset(AAT, t) 1890 oprangeset(ADC, t) 1891 oprangeset(AIC, t) 1892 oprangeset(ATLBI, t) 1893 1894 case ASYSL, AHINT: 1895 break 1896 1897 case ADMB: 1898 oprangeset(ADSB, t) 1899 oprangeset(AISB, t) 1900 1901 case AMRS, AMSR: 1902 break 1903 1904 case ALDAR: 1905 oprangeset(ALDARW, t) 1906 fallthrough 1907 1908 case ALDXR: 1909 oprangeset(ALDXRB, t) 1910 oprangeset(ALDXRH, t) 1911 oprangeset(ALDXRW, t) 1912 1913 case ALDAXR: 1914 oprangeset(ALDAXRB, t) 1915 oprangeset(ALDAXRH, t) 1916 oprangeset(ALDAXRW, t) 1917 1918 case ALDXP: 1919 oprangeset(ALDXPW, t) 1920 1921 case ASTLR: 1922 oprangeset(ASTLRW, t) 1923 1924 case ASTXR: 1925 oprangeset(ASTXRB, t) 1926 oprangeset(ASTXRH, t) 1927 oprangeset(ASTXRW, t) 1928 1929 case ASTLXR: 1930 oprangeset(ASTLXRB, t) 1931 oprangeset(ASTLXRH, t) 1932 oprangeset(ASTLXRW, t) 1933 1934 case ASTXP: 1935 oprangeset(ASTXPW, t) 1936 1937 case AAESD: 1938 oprangeset(AAESE, t) 1939 oprangeset(AAESMC, t) 1940 oprangeset(AAESIMC, t) 1941 oprangeset(ASHA1H, t) 1942 oprangeset(ASHA1SU1, t) 1943 oprangeset(ASHA256SU0, t) 1944 1945 case ASHA1C: 1946 oprangeset(ASHA1P, t) 1947 oprangeset(ASHA1M, t) 1948 oprangeset(ASHA1SU0, t) 1949 oprangeset(ASHA256H, t) 1950 oprangeset(ASHA256H2, t) 1951 oprangeset(ASHA256SU1, t) 1952 1953 case obj.ANOP, 1954 obj.AUNDEF, 1955 obj.AFUNCDATA, 1956 obj.APCDATA, 1957 obj.ADUFFZERO, 1958 obj.ADUFFCOPY: 1959 break 1960 } 1961 } 1962 } 1963 1964 func (c *ctxt7) chipfloat7(e float64) int { 1965 ei := math.Float64bits(e) 1966 l := uint32(int32(ei)) 1967 h := uint32(int32(ei >> 32)) 1968 1969 if l != 0 || h&0xffff != 0 { 1970 return -1 1971 } 1972 h1 := h & 0x7fc00000 1973 if h1 != 0x40000000 && h1 != 0x3fc00000 { 1974 return -1 1975 } 1976 n := 0 1977 1978 // sign bit (a) 1979 if h&0x80000000 != 0 { 1980 n |= 1 << 7 1981 } 1982 1983 // exp sign bit (b) 1984 if h1 == 0x3fc00000 { 1985 n |= 1 << 6 1986 } 1987 1988 // rest of exp and mantissa (cd-efgh) 1989 n |= int((h >> 16) & 0x3f) 1990 1991 //print("match %.8lux %.8lux %d\n", l, h, n); 1992 return n 1993 } 1994 1995 /* form offset parameter to SYS; special register number */ 1996 func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int { 1997 return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5 1998 } 1999 2000 func SYSARG4(op1 int, Cn int, Cm int, op2 int) int { 2001 return SYSARG5(0, op1, Cn, Cm, op2) 2002 } 2003 2004 func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { 2005 o1 := uint32(0) 2006 o2 := uint32(0) 2007 o3 := uint32(0) 2008 o4 := uint32(0) 2009 o5 := uint32(0) 2010 if false { /*debug['P']*/ 2011 fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_) 2012 } 2013 switch o.type_ { 2014 default: 2015 c.ctxt.Diag("%v: unknown asm %d", p, o.type_) 2016 2017 case 0: /* pseudo ops */ 2018 break 2019 2020 case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */ 2021 o1 = c.oprrr(p, p.As) 2022 2023 rf := int(p.From.Reg) 2024 rt := int(p.To.Reg) 2025 r := int(p.Reg) 2026 if p.To.Type == obj.TYPE_NONE { 2027 rt = REGZERO 2028 } 2029 if r == 0 { 2030 r = rt 2031 } 2032 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 2033 2034 case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */ 2035 o1 = c.opirr(p, p.As) 2036 2037 rt := int(p.To.Reg) 2038 if p.To.Type == obj.TYPE_NONE { 2039 if (o1 & Sbit) == 0 { 2040 c.ctxt.Diag("ineffective ZR destination\n%v", p) 2041 } 2042 rt = REGZERO 2043 } 2044 2045 r := int(p.Reg) 2046 if r == 0 { 2047 r = rt 2048 } 2049 v := int32(c.regoff(&p.From)) 2050 o1 = c.oaddi(p, int32(o1), v, r, rt) 2051 2052 case 3: /* op R<<n[,R],R (shifted register) */ 2053 o1 = c.oprrr(p, p.As) 2054 2055 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 2056 rt := int(p.To.Reg) 2057 if p.To.Type == obj.TYPE_NONE { 2058 rt = REGZERO 2059 } 2060 r := int(p.Reg) 2061 if p.As == AMVN || p.As == AMVNW { 2062 r = REGZERO 2063 } else if r == 0 { 2064 r = rt 2065 } 2066 o1 |= (uint32(r&31) << 5) | uint32(rt&31) 2067 2068 case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R */ 2069 o1 = c.opirr(p, p.As) 2070 2071 rt := int(p.To.Reg) 2072 r := int(o.param) 2073 if r == 0 { 2074 r = REGZERO 2075 } else if r == REGFROM { 2076 r = int(p.From.Reg) 2077 } 2078 if r == 0 { 2079 r = REGSP 2080 } 2081 v := int32(c.regoff(&p.From)) 2082 if (v & 0xFFF000) != 0 { 2083 v >>= 12 2084 o1 |= 1 << 22 /* shift, by 12 */ 2085 } 2086 2087 o1 |= ((uint32(v) & 0xFFF) << 10) | (uint32(r&31) << 5) | uint32(rt&31) 2088 2089 case 5: /* b s; bl s */ 2090 o1 = c.opbra(p, p.As) 2091 2092 if p.To.Sym == nil { 2093 o1 |= uint32(c.brdist(p, 0, 26, 2)) 2094 break 2095 } 2096 2097 rel := obj.Addrel(c.cursym) 2098 rel.Off = int32(c.pc) 2099 rel.Siz = 4 2100 rel.Sym = p.To.Sym 2101 rel.Add = p.To.Offset 2102 rel.Type = objabi.R_CALLARM64 2103 2104 case 6: /* b ,O(R); bl ,O(R) */ 2105 o1 = c.opbrr(p, p.As) 2106 2107 o1 |= uint32(p.To.Reg&31) << 5 2108 rel := obj.Addrel(c.cursym) 2109 rel.Off = int32(c.pc) 2110 rel.Siz = 0 2111 rel.Type = objabi.R_CALLIND 2112 2113 case 7: /* beq s */ 2114 o1 = c.opbra(p, p.As) 2115 2116 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5) 2117 2118 case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */ 2119 rt := int(p.To.Reg) 2120 2121 rf := int(p.Reg) 2122 if rf == 0 { 2123 rf = rt 2124 } 2125 v := int32(p.From.Offset) 2126 switch p.As { 2127 case AASR: 2128 o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt) 2129 2130 case AASRW: 2131 o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt) 2132 2133 case ALSL: 2134 o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt) 2135 2136 case ALSLW: 2137 o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt) 2138 2139 case ALSR: 2140 o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt) 2141 2142 case ALSRW: 2143 o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt) 2144 2145 case AROR: 2146 o1 = c.opextr(p, AEXTR, v, rf, rf, rt) 2147 2148 case ARORW: 2149 o1 = c.opextr(p, AEXTRW, v, rf, rf, rt) 2150 2151 default: 2152 c.ctxt.Diag("bad shift $con\n%v", p) 2153 break 2154 } 2155 2156 case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */ 2157 o1 = c.oprrr(p, p.As) 2158 2159 r := int(p.Reg) 2160 if r == 0 { 2161 r = int(p.To.Reg) 2162 } 2163 o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31) 2164 2165 case 10: /* brk/hvc/.../svc [$con] */ 2166 o1 = c.opimm(p, p.As) 2167 2168 if p.To.Type != obj.TYPE_NONE { 2169 o1 |= uint32((p.To.Offset & 0xffff) << 5) 2170 } 2171 2172 case 11: /* dword */ 2173 c.aclass(&p.To) 2174 2175 o1 = uint32(c.instoffset) 2176 o2 = uint32(c.instoffset >> 32) 2177 if p.To.Sym != nil { 2178 rel := obj.Addrel(c.cursym) 2179 rel.Off = int32(c.pc) 2180 rel.Siz = 8 2181 rel.Sym = p.To.Sym 2182 rel.Add = p.To.Offset 2183 rel.Type = objabi.R_ADDR 2184 o2 = 0 2185 o1 = o2 2186 } 2187 2188 case 12: /* movT $vcon, reg */ 2189 o1 = c.omovlit(p.As, p, &p.From, int(p.To.Reg)) 2190 2191 case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */ 2192 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 2193 2194 if !(o1 != 0) { 2195 break 2196 } 2197 rt := int(p.To.Reg) 2198 if p.To.Type == obj.TYPE_NONE { 2199 rt = REGZERO 2200 } 2201 r := int(p.Reg) 2202 if r == 0 { 2203 r = rt 2204 } 2205 if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) { 2206 o2 = c.opxrrr(p, p.As) 2207 o2 |= REGTMP & 31 << 16 2208 o2 |= LSL0_64 2209 } else { 2210 o2 = c.oprrr(p, p.As) 2211 o2 |= REGTMP & 31 << 16 /* shift is 0 */ 2212 } 2213 2214 o2 |= uint32(r&31) << 5 2215 o2 |= uint32(rt & 31) 2216 2217 case 14: /* word */ 2218 if c.aclass(&p.To) == C_ADDR { 2219 c.ctxt.Diag("address constant needs DWORD\n%v", p) 2220 } 2221 o1 = uint32(c.instoffset) 2222 if p.To.Sym != nil { 2223 // This case happens with words generated 2224 // in the PC stream as part of the literal pool. 2225 rel := obj.Addrel(c.cursym) 2226 2227 rel.Off = int32(c.pc) 2228 rel.Siz = 4 2229 rel.Sym = p.To.Sym 2230 rel.Add = p.To.Offset 2231 rel.Type = objabi.R_ADDR 2232 o1 = 0 2233 } 2234 2235 case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub Rm,Rn,Ra,Rd */ 2236 o1 = c.oprrr(p, p.As) 2237 2238 rf := int(p.From.Reg) 2239 rt := int(p.To.Reg) 2240 var r int 2241 var ra int 2242 if p.From3Type() == obj.TYPE_REG { 2243 r = int(p.From3.Reg) 2244 ra = int(p.Reg) 2245 if ra == 0 { 2246 ra = REGZERO 2247 } 2248 } else { 2249 r = int(p.Reg) 2250 if r == 0 { 2251 r = rt 2252 } 2253 ra = REGZERO 2254 } 2255 2256 o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31) 2257 2258 case 16: /* XremY R[,R],R -> XdivY; XmsubY */ 2259 o1 = c.oprrr(p, p.As) 2260 2261 rf := int(p.From.Reg) 2262 rt := int(p.To.Reg) 2263 r := int(p.Reg) 2264 if r == 0 { 2265 r = rt 2266 } 2267 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31 2268 o2 = c.oprrr(p, AMSUBW) 2269 o2 |= o1 & (1 << 31) /* same size */ 2270 o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31) 2271 2272 case 17: /* op Rm,[Rn],Rd; default Rn=ZR */ 2273 o1 = c.oprrr(p, p.As) 2274 2275 rf := int(p.From.Reg) 2276 rt := int(p.To.Reg) 2277 r := int(p.Reg) 2278 if p.To.Type == obj.TYPE_NONE { 2279 rt = REGZERO 2280 } 2281 if r == 0 { 2282 r = REGZERO 2283 } 2284 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 2285 2286 case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */ 2287 o1 = c.oprrr(p, p.As) 2288 2289 cond := int(p.From.Reg) 2290 if cond < COND_EQ || cond > COND_NV { 2291 c.ctxt.Diag("invalid condition\n%v", p) 2292 } else { 2293 cond -= COND_EQ 2294 } 2295 2296 r := int(p.Reg) 2297 var rf int 2298 if r != 0 { 2299 if p.From3Type() == obj.TYPE_NONE { 2300 /* CINC/CINV/CNEG */ 2301 rf = r 2302 2303 cond ^= 1 2304 } else { 2305 rf = int(p.From3.Reg) /* CSEL */ 2306 } 2307 } else { 2308 /* CSET */ 2309 if p.From3Type() != obj.TYPE_NONE { 2310 c.ctxt.Diag("invalid combination\n%v", p) 2311 } 2312 rf = REGZERO 2313 r = rf 2314 cond ^= 1 2315 } 2316 2317 rt := int(p.To.Reg) 2318 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31) 2319 2320 case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */ 2321 nzcv := int(p.To.Offset) 2322 2323 cond := int(p.From.Reg) 2324 if cond < COND_EQ || cond > COND_NV { 2325 c.ctxt.Diag("invalid condition\n%v", p) 2326 } else { 2327 cond -= COND_EQ 2328 } 2329 var rf int 2330 if p.From3.Type == obj.TYPE_REG { 2331 o1 = c.oprrr(p, p.As) 2332 rf = int(p.From3.Reg) /* Rm */ 2333 } else { 2334 o1 = c.opirr(p, p.As) 2335 rf = int(p.From3.Offset & 0x1F) 2336 } 2337 2338 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv) 2339 2340 case 20: /* movT R,O(R) -> strT */ 2341 v := int32(c.regoff(&p.To)) 2342 sz := int32(1 << uint(movesize(p.As))) 2343 2344 r := int(p.To.Reg) 2345 if r == 0 { 2346 r = int(o.param) 2347 } 2348 if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ 2349 o1 = c.olsr9s(p, int32(c.opstr9(p, p.As)), v, r, int(p.From.Reg)) 2350 } else { 2351 v = int32(c.offsetshift(p, int64(v), int(o.a3))) 2352 o1 = c.olsr12u(p, int32(c.opstr12(p, p.As)), v, r, int(p.From.Reg)) 2353 } 2354 2355 case 21: /* movT O(R),R -> ldrT */ 2356 v := int32(c.regoff(&p.From)) 2357 sz := int32(1 << uint(movesize(p.As))) 2358 2359 r := int(p.From.Reg) 2360 if r == 0 { 2361 r = int(o.param) 2362 } 2363 if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ 2364 o1 = c.olsr9s(p, int32(c.opldr9(p, p.As)), v, r, int(p.To.Reg)) 2365 } else { 2366 v = int32(c.offsetshift(p, int64(v), int(o.a1))) 2367 //print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1); 2368 o1 = c.olsr12u(p, int32(c.opldr12(p, p.As)), v, r, int(p.To.Reg)) 2369 } 2370 2371 case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */ 2372 v := int32(p.From.Offset) 2373 2374 if v < -256 || v > 255 { 2375 c.ctxt.Diag("offset out of range\n%v", p) 2376 } 2377 o1 = c.opldrpp(p, p.As) 2378 if o.scond == C_XPOST { 2379 o1 |= 1 << 10 2380 } else { 2381 o1 |= 3 << 10 2382 } 2383 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31) 2384 2385 case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */ 2386 v := int32(p.To.Offset) 2387 2388 if v < -256 || v > 255 { 2389 c.ctxt.Diag("offset out of range\n%v", p) 2390 } 2391 o1 = LD2STR(c.opldrpp(p, p.As)) 2392 if o.scond == C_XPOST { 2393 o1 |= 1 << 10 2394 } else { 2395 o1 |= 3 << 10 2396 } 2397 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31) 2398 2399 case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */ 2400 rf := int(p.From.Reg) 2401 rt := int(p.To.Reg) 2402 s := rf == REGSP || rt == REGSP 2403 if p.As == AMVN || p.As == AMVNW { 2404 if s { 2405 c.ctxt.Diag("illegal SP reference\n%v", p) 2406 } 2407 o1 = c.oprrr(p, p.As) 2408 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 2409 } else if s { 2410 o1 = c.opirr(p, p.As) 2411 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 2412 } else { 2413 o1 = c.oprrr(p, p.As) 2414 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 2415 } 2416 2417 case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */ 2418 o1 = c.oprrr(p, p.As) 2419 2420 rf := int(p.From.Reg) 2421 if rf == C_NONE { 2422 rf = int(p.To.Reg) 2423 } 2424 rt := int(p.To.Reg) 2425 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 2426 2427 case 26: /* negX Rm<<s, Rd -> subX Rm<<s, ZR, Rd */ 2428 o1 = c.oprrr(p, p.As) 2429 2430 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 2431 rt := int(p.To.Reg) 2432 o1 |= (REGZERO & 31 << 5) | uint32(rt&31) 2433 2434 case 27: /* op Rm<<n[,Rn],Rd (extended register) */ 2435 o1 = c.opxrrr(p, p.As) 2436 2437 if (p.From.Reg-obj.RBaseARM64)®_EXT != 0 { 2438 c.ctxt.Diag("extended register not implemented\n%v", p) 2439 // o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 2440 } else { 2441 o1 |= uint32(p.From.Reg&31) << 16 2442 } 2443 rt := int(p.To.Reg) 2444 if p.To.Type == obj.TYPE_NONE { 2445 rt = REGZERO 2446 } 2447 r := int(p.Reg) 2448 if r == 0 { 2449 r = rt 2450 } 2451 o1 |= (uint32(r&31) << 5) | uint32(rt&31) 2452 2453 case 28: /* logop $vcon, [R], R (64 bit literal) */ 2454 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 2455 2456 if !(o1 != 0) { 2457 break 2458 } 2459 r := int(p.Reg) 2460 if r == 0 { 2461 r = int(p.To.Reg) 2462 } 2463 o2 = c.oprrr(p, p.As) 2464 o2 |= REGTMP & 31 << 16 /* shift is 0 */ 2465 o2 |= uint32(r&31) << 5 2466 o2 |= uint32(p.To.Reg & 31) 2467 2468 case 29: /* op Rn, Rd */ 2469 fc := c.aclass(&p.From) 2470 tc := c.aclass(&p.To) 2471 if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZCON || tc == C_REG || tc == C_ZCON) { 2472 // FMOV Rx, Fy or FMOV Fy, Rx 2473 o1 = FPCVTI(0, 0, 0, 0, 6) 2474 if p.As == AFMOVD { 2475 o1 |= 1<<31 | 1<<22 // 64-bit 2476 } 2477 if fc == C_REG || fc == C_ZCON { 2478 o1 |= 1 << 16 // FMOV Rx, Fy 2479 } 2480 } else { 2481 o1 = c.oprrr(p, p.As) 2482 } 2483 o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31) 2484 2485 case 30: /* movT R,L(R) -> strT */ 2486 // if offset L can be split into hi+lo, and both fit into instructions, do 2487 // add $hi, R, Rtmp 2488 // str R, lo(Rtmp) 2489 // otherwise, use constant pool 2490 // mov $L, Rtmp (from constant pool) 2491 // str R, (R+Rtmp) 2492 s := movesize(o.as) 2493 if s < 0 { 2494 c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) 2495 } 2496 2497 r := int(p.To.Reg) 2498 if r == 0 { 2499 r = int(o.param) 2500 } 2501 2502 v := int32(c.regoff(&p.To)) 2503 var hi int32 2504 if v < 0 || (v&((1<<uint(s))-1)) != 0 { 2505 // negative or unaligned offset, use constant pool 2506 goto storeusepool 2507 } 2508 2509 hi = v - (v & (0xFFF << uint(s))) 2510 if hi&0xFFF != 0 { 2511 c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p) 2512 } 2513 if hi&^0xFFF000 != 0 { 2514 // hi doesn't fit into an ADD instruction 2515 goto storeusepool 2516 } 2517 2518 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP) 2519 o2 = c.olsr12u(p, int32(c.opstr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg)) 2520 break 2521 2522 storeusepool: 2523 if r == REGTMP || p.From.Reg == REGTMP { 2524 c.ctxt.Diag("REGTMP used in large offset store: %v", p) 2525 } 2526 o1 = c.omovlit(AMOVD, p, &p.To, REGTMP) 2527 o2 = c.olsxrr(p, int32(c.opstrr(p, p.As)), int(p.From.Reg), r, REGTMP) 2528 2529 case 31: /* movT L(R), R -> ldrT */ 2530 // if offset L can be split into hi+lo, and both fit into instructions, do 2531 // add $hi, R, Rtmp 2532 // ldr lo(Rtmp), R 2533 // otherwise, use constant pool 2534 // mov $L, Rtmp (from constant pool) 2535 // ldr (R+Rtmp), R 2536 s := movesize(o.as) 2537 if s < 0 { 2538 c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) 2539 } 2540 2541 r := int(p.From.Reg) 2542 if r == 0 { 2543 r = int(o.param) 2544 } 2545 2546 v := int32(c.regoff(&p.From)) 2547 var hi int32 2548 if v < 0 || (v&((1<<uint(s))-1)) != 0 { 2549 // negative or unaligned offset, use constant pool 2550 goto loadusepool 2551 } 2552 2553 hi = v - (v & (0xFFF << uint(s))) 2554 if (hi & 0xFFF) != 0 { 2555 c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p) 2556 } 2557 if hi&^0xFFF000 != 0 { 2558 // hi doesn't fit into an ADD instruction 2559 goto loadusepool 2560 } 2561 2562 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP) 2563 o2 = c.olsr12u(p, int32(c.opldr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg)) 2564 break 2565 2566 loadusepool: 2567 if r == REGTMP || p.From.Reg == REGTMP { 2568 c.ctxt.Diag("REGTMP used in large offset load: %v", p) 2569 } 2570 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 2571 o2 = c.olsxrr(p, int32(c.opldrr(p, p.As)), int(p.To.Reg), r, REGTMP) 2572 2573 case 32: /* mov $con, R -> movz/movn */ 2574 o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg)) 2575 2576 case 33: /* movk $uimm16 << pos */ 2577 o1 = c.opirr(p, p.As) 2578 2579 d := p.From.Offset 2580 if (d >> 16) != 0 { 2581 c.ctxt.Diag("requires uimm16\n%v", p) 2582 } 2583 s := 0 2584 if p.From3Type() != obj.TYPE_NONE { 2585 if p.From3.Type != obj.TYPE_CONST { 2586 c.ctxt.Diag("missing bit position\n%v", p) 2587 } 2588 s = int(p.From3.Offset / 16) 2589 if (s*16&0xF) != 0 || s >= 4 || (o1&S64) == 0 && s >= 2 { 2590 c.ctxt.Diag("illegal bit position\n%v", p) 2591 } 2592 } 2593 2594 rt := int(p.To.Reg) 2595 o1 |= uint32(((d & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31)) 2596 2597 case 34: /* mov $lacon,R */ 2598 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 2599 2600 if !(o1 != 0) { 2601 break 2602 } 2603 o2 = c.opxrrr(p, AADD) 2604 o2 |= REGTMP & 31 << 16 2605 o2 |= LSL0_64 2606 r := int(p.From.Reg) 2607 if r == 0 { 2608 r = int(o.param) 2609 } 2610 o2 |= uint32(r&31) << 5 2611 o2 |= uint32(p.To.Reg & 31) 2612 2613 case 35: /* mov SPR,R -> mrs */ 2614 o1 = c.oprrr(p, AMRS) 2615 2616 v := int32(p.From.Offset) 2617 if (o1 & uint32(v&^(3<<19))) != 0 { 2618 c.ctxt.Diag("MRS register value overlap\n%v", p) 2619 } 2620 o1 |= uint32(v) 2621 o1 |= uint32(p.To.Reg & 31) 2622 2623 case 36: /* mov R,SPR */ 2624 o1 = c.oprrr(p, AMSR) 2625 2626 v := int32(p.To.Offset) 2627 if (o1 & uint32(v&^(3<<19))) != 0 { 2628 c.ctxt.Diag("MSR register value overlap\n%v", p) 2629 } 2630 o1 |= uint32(v) 2631 o1 |= uint32(p.From.Reg & 31) 2632 2633 case 37: /* mov $con,PSTATEfield -> MSR [immediate] */ 2634 if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 { 2635 c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p) 2636 } 2637 o1 = c.opirr(p, AMSR) 2638 o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */ 2639 v := int32(0) 2640 for i := 0; i < len(pstatefield); i++ { 2641 if int64(pstatefield[i].a) == p.To.Offset { 2642 v = int32(pstatefield[i].b) 2643 break 2644 } 2645 } 2646 2647 if v == 0 { 2648 c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p) 2649 } 2650 o1 |= uint32(v) 2651 2652 case 38: /* clrex [$imm] */ 2653 o1 = c.opimm(p, p.As) 2654 2655 if p.To.Type == obj.TYPE_NONE { 2656 o1 |= 0xF << 8 2657 } else { 2658 o1 |= uint32((p.To.Offset & 0xF) << 8) 2659 } 2660 2661 case 39: /* cbz R, rel */ 2662 o1 = c.opirr(p, p.As) 2663 2664 o1 |= uint32(p.From.Reg & 31) 2665 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5) 2666 2667 case 40: /* tbz */ 2668 o1 = c.opirr(p, p.As) 2669 2670 v := int32(p.From.Offset) 2671 if v < 0 || v > 63 { 2672 c.ctxt.Diag("illegal bit number\n%v", p) 2673 } 2674 o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19) 2675 o1 |= uint32(c.brdist(p, 0, 14, 2) << 5) 2676 o1 |= uint32(p.Reg & 31) 2677 2678 case 41: /* eret, nop, others with no operands */ 2679 o1 = c.op0(p, p.As) 2680 2681 case 42: /* bfm R,r,s,R */ 2682 o1 = c.opbfm(p, p.As, int(p.From.Offset), int(p.From3.Offset), int(p.Reg), int(p.To.Reg)) 2683 2684 case 43: /* bfm aliases */ 2685 r := int(p.From.Offset) 2686 2687 s := int(p.From3.Offset) 2688 rf := int(p.Reg) 2689 rt := int(p.To.Reg) 2690 if rf == 0 { 2691 rf = rt 2692 } 2693 switch p.As { 2694 case ABFI: 2695 o1 = c.opbfm(p, ABFM, 64-r, s-1, rf, rt) 2696 2697 case ABFIW: 2698 o1 = c.opbfm(p, ABFMW, 32-r, s-1, rf, rt) 2699 2700 case ABFXIL: 2701 o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt) 2702 2703 case ABFXILW: 2704 o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt) 2705 2706 case ASBFIZ: 2707 o1 = c.opbfm(p, ASBFM, 64-r, s-1, rf, rt) 2708 2709 case ASBFIZW: 2710 o1 = c.opbfm(p, ASBFMW, 32-r, s-1, rf, rt) 2711 2712 case ASBFX: 2713 o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt) 2714 2715 case ASBFXW: 2716 o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt) 2717 2718 case AUBFIZ: 2719 o1 = c.opbfm(p, AUBFM, 64-r, s-1, rf, rt) 2720 2721 case AUBFIZW: 2722 o1 = c.opbfm(p, AUBFMW, 32-r, s-1, rf, rt) 2723 2724 case AUBFX: 2725 o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt) 2726 2727 case AUBFXW: 2728 o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt) 2729 2730 default: 2731 c.ctxt.Diag("bad bfm alias\n%v", p) 2732 break 2733 } 2734 2735 case 44: /* extr $b, Rn, Rm, Rd */ 2736 o1 = c.opextr(p, p.As, int32(p.From.Offset), int(p.From3.Reg), int(p.Reg), int(p.To.Reg)) 2737 2738 case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */ 2739 rf := int(p.From.Reg) 2740 2741 rt := int(p.To.Reg) 2742 as := p.As 2743 if rf == REGZERO { 2744 as = AMOVWU /* clearer in disassembly */ 2745 } 2746 switch as { 2747 case AMOVB, ASXTB: 2748 o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt) 2749 2750 case AMOVH, ASXTH: 2751 o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt) 2752 2753 case AMOVW, ASXTW: 2754 o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt) 2755 2756 case AMOVBU, AUXTB: 2757 o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt) 2758 2759 case AMOVHU, AUXTH: 2760 o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt) 2761 2762 case AMOVWU: 2763 o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 2764 2765 case AUXTW: 2766 o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt) 2767 2768 case ASXTBW: 2769 o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt) 2770 2771 case ASXTHW: 2772 o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt) 2773 2774 case AUXTBW: 2775 o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt) 2776 2777 case AUXTHW: 2778 o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt) 2779 2780 default: 2781 c.ctxt.Diag("bad sxt %v", as) 2782 break 2783 } 2784 2785 case 46: /* cls */ 2786 o1 = c.opbit(p, p.As) 2787 2788 o1 |= uint32(p.From.Reg&31) << 5 2789 o1 |= uint32(p.To.Reg & 31) 2790 2791 case 50: /* sys/sysl */ 2792 o1 = c.opirr(p, p.As) 2793 2794 if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 { 2795 c.ctxt.Diag("illegal SYS argument\n%v", p) 2796 } 2797 o1 |= uint32(p.From.Offset) 2798 if p.To.Type == obj.TYPE_REG { 2799 o1 |= uint32(p.To.Reg & 31) 2800 } else if p.Reg != 0 { 2801 o1 |= uint32(p.Reg & 31) 2802 } else { 2803 o1 |= 0x1F 2804 } 2805 2806 case 51: /* dmb */ 2807 o1 = c.opirr(p, p.As) 2808 2809 if p.From.Type == obj.TYPE_CONST { 2810 o1 |= uint32((p.From.Offset & 0xF) << 8) 2811 } 2812 2813 case 52: /* hint */ 2814 o1 = c.opirr(p, p.As) 2815 2816 o1 |= uint32((p.From.Offset & 0x7F) << 5) 2817 2818 case 53: /* and/or/eor/bic/... $bitcon, Rn, Rd */ 2819 a := p.As 2820 rt := int(p.To.Reg) 2821 r := int(p.Reg) 2822 if r == 0 { 2823 r = rt 2824 } 2825 mode := 64 2826 v := uint64(p.From.Offset) 2827 switch p.As { 2828 case AANDW, AORRW, AEORW, AANDSW: 2829 mode = 32 2830 case ABIC, AORN, AEON, ABICS: 2831 v = ^v 2832 case ABICW, AORNW, AEONW, ABICSW: 2833 v = ^v 2834 mode = 32 2835 } 2836 o1 = c.opirr(p, a) 2837 o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31) 2838 2839 case 54: /* floating point arith */ 2840 o1 = c.oprrr(p, p.As) 2841 2842 var rf int 2843 if p.From.Type == obj.TYPE_CONST { 2844 rf = c.chipfloat7(p.From.Val.(float64)) 2845 if rf < 0 || true { 2846 c.ctxt.Diag("invalid floating-point immediate\n%v", p) 2847 rf = 0 2848 } 2849 2850 rf |= (1 << 3) 2851 } else { 2852 rf = int(p.From.Reg) 2853 } 2854 rt := int(p.To.Reg) 2855 r := int(p.Reg) 2856 if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */ 2857 r = rf 2858 rf = 0 2859 } else if r == 0 { 2860 r = rt 2861 } 2862 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 2863 2864 case 56: /* floating point compare */ 2865 o1 = c.oprrr(p, p.As) 2866 2867 var rf int 2868 if p.From.Type == obj.TYPE_CONST { 2869 o1 |= 8 /* zero */ 2870 rf = 0 2871 } else { 2872 rf = int(p.From.Reg) 2873 } 2874 rt := int(p.Reg) 2875 o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5 2876 2877 case 57: /* floating point conditional compare */ 2878 o1 = c.oprrr(p, p.As) 2879 2880 cond := int(p.From.Reg) 2881 if cond < COND_EQ || cond > COND_NV { 2882 c.ctxt.Diag("invalid condition\n%v", p) 2883 } else { 2884 cond -= COND_EQ 2885 } 2886 2887 nzcv := int(p.To.Offset) 2888 if nzcv&^0xF != 0 { 2889 c.ctxt.Diag("implausible condition\n%v", p) 2890 } 2891 rf := int(p.Reg) 2892 if p.From3 == nil || p.From3.Reg < REG_F0 || p.From3.Reg > REG_F31 { 2893 c.ctxt.Diag("illegal FCCMP\n%v", p) 2894 break 2895 } 2896 rt := int(p.From3.Reg) 2897 o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv) 2898 2899 case 58: /* ldar/ldxr/ldaxr */ 2900 o1 = c.opload(p, p.As) 2901 2902 o1 |= 0x1F << 16 2903 o1 |= uint32(p.From.Reg) << 5 2904 if p.Reg != 0 { 2905 o1 |= uint32(p.Reg) << 10 2906 } else { 2907 o1 |= 0x1F << 10 2908 } 2909 o1 |= uint32(p.To.Reg & 31) 2910 2911 case 59: /* stxr/stlxr */ 2912 o1 = c.opstore(p, p.As) 2913 2914 if p.RegTo2 != obj.REG_NONE { 2915 o1 |= uint32(p.RegTo2&31) << 16 2916 } else { 2917 o1 |= 0x1F << 16 2918 } 2919 2920 // TODO(aram): add support for STXP 2921 o1 |= uint32(p.To.Reg&31) << 5 2922 2923 o1 |= uint32(p.From.Reg & 31) 2924 2925 case 60: /* adrp label,r */ 2926 d := c.brdist(p, 12, 21, 0) 2927 2928 o1 = ADR(1, uint32(d), uint32(p.To.Reg)) 2929 2930 case 61: /* adr label, r */ 2931 d := c.brdist(p, 0, 21, 0) 2932 2933 o1 = ADR(0, uint32(d), uint32(p.To.Reg)) 2934 2935 case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */ 2936 if p.Reg == REGTMP { 2937 c.ctxt.Diag("cannot use REGTMP as source: %v\n", p) 2938 } 2939 o1 = c.omovconst(AMOVD, p, &p.From, REGTMP) 2940 2941 rt := int(p.To.Reg) 2942 if p.To.Type == obj.TYPE_NONE { 2943 rt = REGZERO 2944 } 2945 r := int(p.Reg) 2946 if r == 0 { 2947 r = rt 2948 } 2949 if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) { 2950 o2 = c.opxrrr(p, p.As) 2951 o2 |= REGTMP & 31 << 16 2952 o2 |= LSL0_64 2953 } else { 2954 o2 = c.oprrr(p, p.As) 2955 o2 |= REGTMP & 31 << 16 /* shift is 0 */ 2956 } 2957 o2 |= uint32(r&31) << 5 2958 o2 |= uint32(rt & 31) 2959 2960 /* reloc ops */ 2961 case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */ 2962 o1 = ADR(1, 0, REGTMP) 2963 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 2964 rel := obj.Addrel(c.cursym) 2965 rel.Off = int32(c.pc) 2966 rel.Siz = 8 2967 rel.Sym = p.To.Sym 2968 rel.Add = p.To.Offset 2969 rel.Type = objabi.R_ADDRARM64 2970 o3 = c.olsr12u(p, int32(c.opstr12(p, p.As)), 0, REGTMP, int(p.From.Reg)) 2971 2972 case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */ 2973 o1 = ADR(1, 0, REGTMP) 2974 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 2975 rel := obj.Addrel(c.cursym) 2976 rel.Off = int32(c.pc) 2977 rel.Siz = 8 2978 rel.Sym = p.From.Sym 2979 rel.Add = p.From.Offset 2980 rel.Type = objabi.R_ADDRARM64 2981 o3 = c.olsr12u(p, int32(c.opldr12(p, p.As)), 0, REGTMP, int(p.To.Reg)) 2982 2983 case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */ 2984 v := int32(p.From.Offset) 2985 2986 if v < -512 || v > 504 { 2987 c.ctxt.Diag("offset out of range\n%v", p) 2988 } 2989 if o.scond == C_XPOST { 2990 o1 |= 1 << 23 2991 } else { 2992 o1 |= 3 << 23 2993 } 2994 o1 |= 1 << 22 2995 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)) 2996 2997 case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */ 2998 v := int32(p.To.Offset) 2999 3000 if v < -512 || v > 504 { 3001 c.ctxt.Diag("offset out of range\n%v", p) 3002 } 3003 if o.scond == C_XPOST { 3004 o1 |= 1 << 23 3005 } else { 3006 o1 |= 3 << 23 3007 } 3008 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)) 3009 3010 case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */ 3011 if p.As == AMOVW { 3012 c.ctxt.Diag("invalid load of 32-bit address: %v", p) 3013 } 3014 o1 = ADR(1, 0, uint32(p.To.Reg)) 3015 o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31) 3016 rel := obj.Addrel(c.cursym) 3017 rel.Off = int32(c.pc) 3018 rel.Siz = 8 3019 rel.Sym = p.From.Sym 3020 rel.Add = p.From.Offset 3021 rel.Type = objabi.R_ADDRARM64 3022 3023 case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */ 3024 o1 = c.opirr(p, AMOVZ) 3025 o1 |= uint32(p.To.Reg & 31) 3026 rel := obj.Addrel(c.cursym) 3027 rel.Off = int32(c.pc) 3028 rel.Siz = 4 3029 rel.Sym = p.From.Sym 3030 rel.Type = objabi.R_ARM64_TLS_LE 3031 if p.From.Offset != 0 { 3032 c.ctxt.Diag("invalid offset on MOVW $tlsvar") 3033 } 3034 3035 case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */ 3036 o1 = ADR(1, 0, REGTMP) 3037 o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg)) 3038 rel := obj.Addrel(c.cursym) 3039 rel.Off = int32(c.pc) 3040 rel.Siz = 8 3041 rel.Sym = p.From.Sym 3042 rel.Add = 0 3043 rel.Type = objabi.R_ARM64_TLS_IE 3044 if p.From.Offset != 0 { 3045 c.ctxt.Diag("invalid offset on MOVW $tlsvar") 3046 } 3047 3048 case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */ 3049 o1 = ADR(1, 0, REGTMP) 3050 o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg)) 3051 rel := obj.Addrel(c.cursym) 3052 rel.Off = int32(c.pc) 3053 rel.Siz = 8 3054 rel.Sym = p.From.Sym 3055 rel.Add = 0 3056 rel.Type = objabi.R_ARM64_GOTPCREL 3057 3058 // This is supposed to be something that stops execution. 3059 // It's not supposed to be reached, ever, but if it is, we'd 3060 // like to be able to tell how we got there. Assemble as 3061 // 0xbea71700 which is guaranteed to raise undefined instruction 3062 // exception. 3063 case 90: 3064 o1 = 0xbea71700 3065 3066 break 3067 } 3068 3069 out[0] = o1 3070 out[1] = o2 3071 out[2] = o3 3072 out[3] = o4 3073 out[4] = o5 3074 return 3075 } 3076 3077 /* 3078 * basic Rm op Rn -> Rd (using shifted register with 0) 3079 * also op Rn -> Rt 3080 * also Rm*Rn op Ra -> Rd 3081 */ 3082 func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 { 3083 switch a { 3084 case AADC: 3085 return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 3086 3087 case AADCW: 3088 return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 3089 3090 case AADCS: 3091 return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 3092 3093 case AADCSW: 3094 return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 3095 3096 case ANGC, ASBC: 3097 return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 3098 3099 case ANGCS, ASBCS: 3100 return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 3101 3102 case ANGCW, ASBCW: 3103 return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 3104 3105 case ANGCSW, ASBCSW: 3106 return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 3107 3108 case AADD: 3109 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3110 3111 case AADDW: 3112 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3113 3114 case ACMN, AADDS: 3115 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3116 3117 case ACMNW, AADDSW: 3118 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3119 3120 case ASUB: 3121 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3122 3123 case ASUBW: 3124 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3125 3126 case ACMP, ASUBS: 3127 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3128 3129 case ACMPW, ASUBSW: 3130 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 3131 3132 case AAND: 3133 return S64 | 0<<29 | 0xA<<24 3134 3135 case AANDW: 3136 return S32 | 0<<29 | 0xA<<24 3137 3138 case AMOVD, AORR: 3139 return S64 | 1<<29 | 0xA<<24 3140 3141 // case AMOVW: 3142 case AMOVWU, AORRW: 3143 return S32 | 1<<29 | 0xA<<24 3144 3145 case AEOR: 3146 return S64 | 2<<29 | 0xA<<24 3147 3148 case AEORW: 3149 return S32 | 2<<29 | 0xA<<24 3150 3151 case AANDS: 3152 return S64 | 3<<29 | 0xA<<24 3153 3154 case AANDSW: 3155 return S32 | 3<<29 | 0xA<<24 3156 3157 case ABIC: 3158 return S64 | 0<<29 | 0xA<<24 | 1<<21 3159 3160 case ABICW: 3161 return S32 | 0<<29 | 0xA<<24 | 1<<21 3162 3163 case ABICS: 3164 return S64 | 3<<29 | 0xA<<24 | 1<<21 3165 3166 case ABICSW: 3167 return S32 | 3<<29 | 0xA<<24 | 1<<21 3168 3169 case AEON: 3170 return S64 | 2<<29 | 0xA<<24 | 1<<21 3171 3172 case AEONW: 3173 return S32 | 2<<29 | 0xA<<24 | 1<<21 3174 3175 case AMVN, AORN: 3176 return S64 | 1<<29 | 0xA<<24 | 1<<21 3177 3178 case AMVNW, AORNW: 3179 return S32 | 1<<29 | 0xA<<24 | 1<<21 3180 3181 case AASR: 3182 return S64 | OPDP2(10) /* also ASRV */ 3183 3184 case AASRW: 3185 return S32 | OPDP2(10) 3186 3187 case ALSL: 3188 return S64 | OPDP2(8) 3189 3190 case ALSLW: 3191 return S32 | OPDP2(8) 3192 3193 case ALSR: 3194 return S64 | OPDP2(9) 3195 3196 case ALSRW: 3197 return S32 | OPDP2(9) 3198 3199 case AROR: 3200 return S64 | OPDP2(11) 3201 3202 case ARORW: 3203 return S32 | OPDP2(11) 3204 3205 case ACCMN: 3206 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */ 3207 3208 case ACCMNW: 3209 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 3210 3211 case ACCMP: 3212 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 3213 3214 case ACCMPW: 3215 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 3216 3217 case ACRC32B: 3218 return S32 | OPDP2(16) 3219 3220 case ACRC32H: 3221 return S32 | OPDP2(17) 3222 3223 case ACRC32W: 3224 return S32 | OPDP2(18) 3225 3226 case ACRC32X: 3227 return S64 | OPDP2(19) 3228 3229 case ACRC32CB: 3230 return S32 | OPDP2(20) 3231 3232 case ACRC32CH: 3233 return S32 | OPDP2(21) 3234 3235 case ACRC32CW: 3236 return S32 | OPDP2(22) 3237 3238 case ACRC32CX: 3239 return S64 | OPDP2(23) 3240 3241 case ACSEL: 3242 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 3243 3244 case ACSELW: 3245 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 3246 3247 case ACSET: 3248 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 3249 3250 case ACSETW: 3251 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 3252 3253 case ACSETM: 3254 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 3255 3256 case ACSETMW: 3257 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 3258 3259 case ACINC, ACSINC: 3260 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 3261 3262 case ACINCW, ACSINCW: 3263 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 3264 3265 case ACINV, ACSINV: 3266 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 3267 3268 case ACINVW, ACSINVW: 3269 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 3270 3271 case ACNEG, ACSNEG: 3272 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 3273 3274 case ACNEGW, ACSNEGW: 3275 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 3276 3277 case AMUL, AMADD: 3278 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 3279 3280 case AMULW, AMADDW: 3281 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 3282 3283 case AMNEG, AMSUB: 3284 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 3285 3286 case AMNEGW, AMSUBW: 3287 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 3288 3289 case AMRS: 3290 return SYSOP(1, 2, 0, 0, 0, 0, 0) 3291 3292 case AMSR: 3293 return SYSOP(0, 2, 0, 0, 0, 0, 0) 3294 3295 case ANEG: 3296 return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 3297 3298 case ANEGW: 3299 return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 3300 3301 case ANEGS: 3302 return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 3303 3304 case ANEGSW: 3305 return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 3306 3307 case AREM, ASDIV: 3308 return S64 | OPDP2(3) 3309 3310 case AREMW, ASDIVW: 3311 return S32 | OPDP2(3) 3312 3313 case ASMULL, ASMADDL: 3314 return OPDP3(1, 0, 1, 0) 3315 3316 case ASMNEGL, ASMSUBL: 3317 return OPDP3(1, 0, 1, 1) 3318 3319 case ASMULH: 3320 return OPDP3(1, 0, 2, 0) 3321 3322 case AUMULL, AUMADDL: 3323 return OPDP3(1, 0, 5, 0) 3324 3325 case AUMNEGL, AUMSUBL: 3326 return OPDP3(1, 0, 5, 1) 3327 3328 case AUMULH: 3329 return OPDP3(1, 0, 6, 0) 3330 3331 case AUREM, AUDIV: 3332 return S64 | OPDP2(2) 3333 3334 case AUREMW, AUDIVW: 3335 return S32 | OPDP2(2) 3336 3337 case AAESE: 3338 return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10 3339 3340 case AAESD: 3341 return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10 3342 3343 case AAESMC: 3344 return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10 3345 3346 case AAESIMC: 3347 return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10 3348 3349 case ASHA1C: 3350 return 0x5E<<24 | 0<<12 3351 3352 case ASHA1P: 3353 return 0x5E<<24 | 1<<12 3354 3355 case ASHA1M: 3356 return 0x5E<<24 | 2<<12 3357 3358 case ASHA1SU0: 3359 return 0x5E<<24 | 3<<12 3360 3361 case ASHA256H: 3362 return 0x5E<<24 | 4<<12 3363 3364 case ASHA256H2: 3365 return 0x5E<<24 | 5<<12 3366 3367 case ASHA256SU1: 3368 return 0x5E<<24 | 6<<12 3369 3370 case ASHA1H: 3371 return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10 3372 3373 case ASHA1SU1: 3374 return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10 3375 3376 case ASHA256SU0: 3377 return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10 3378 3379 case AFCVTZSD: 3380 return FPCVTI(1, 0, 1, 3, 0) 3381 3382 case AFCVTZSDW: 3383 return FPCVTI(0, 0, 1, 3, 0) 3384 3385 case AFCVTZSS: 3386 return FPCVTI(1, 0, 0, 3, 0) 3387 3388 case AFCVTZSSW: 3389 return FPCVTI(0, 0, 0, 3, 0) 3390 3391 case AFCVTZUD: 3392 return FPCVTI(1, 0, 1, 3, 1) 3393 3394 case AFCVTZUDW: 3395 return FPCVTI(0, 0, 1, 3, 1) 3396 3397 case AFCVTZUS: 3398 return FPCVTI(1, 0, 0, 3, 1) 3399 3400 case AFCVTZUSW: 3401 return FPCVTI(0, 0, 0, 3, 1) 3402 3403 case ASCVTFD: 3404 return FPCVTI(1, 0, 1, 0, 2) 3405 3406 case ASCVTFS: 3407 return FPCVTI(1, 0, 0, 0, 2) 3408 3409 case ASCVTFWD: 3410 return FPCVTI(0, 0, 1, 0, 2) 3411 3412 case ASCVTFWS: 3413 return FPCVTI(0, 0, 0, 0, 2) 3414 3415 case AUCVTFD: 3416 return FPCVTI(1, 0, 1, 0, 3) 3417 3418 case AUCVTFS: 3419 return FPCVTI(1, 0, 0, 0, 3) 3420 3421 case AUCVTFWD: 3422 return FPCVTI(0, 0, 1, 0, 3) 3423 3424 case AUCVTFWS: 3425 return FPCVTI(0, 0, 0, 0, 3) 3426 3427 case AFADDS: 3428 return FPOP2S(0, 0, 0, 2) 3429 3430 case AFADDD: 3431 return FPOP2S(0, 0, 1, 2) 3432 3433 case AFSUBS: 3434 return FPOP2S(0, 0, 0, 3) 3435 3436 case AFSUBD: 3437 return FPOP2S(0, 0, 1, 3) 3438 3439 case AFMULS: 3440 return FPOP2S(0, 0, 0, 0) 3441 3442 case AFMULD: 3443 return FPOP2S(0, 0, 1, 0) 3444 3445 case AFDIVS: 3446 return FPOP2S(0, 0, 0, 1) 3447 3448 case AFDIVD: 3449 return FPOP2S(0, 0, 1, 1) 3450 3451 case AFMAXS: 3452 return FPOP2S(0, 0, 0, 4) 3453 3454 case AFMINS: 3455 return FPOP2S(0, 0, 0, 5) 3456 3457 case AFMAXD: 3458 return FPOP2S(0, 0, 1, 4) 3459 3460 case AFMIND: 3461 return FPOP2S(0, 0, 1, 5) 3462 3463 case AFMAXNMS: 3464 return FPOP2S(0, 0, 0, 6) 3465 3466 case AFMAXNMD: 3467 return FPOP2S(0, 0, 1, 6) 3468 3469 case AFMINNMS: 3470 return FPOP2S(0, 0, 0, 7) 3471 3472 case AFMINNMD: 3473 return FPOP2S(0, 0, 1, 7) 3474 3475 case AFNMULS: 3476 return FPOP2S(0, 0, 0, 8) 3477 3478 case AFNMULD: 3479 return FPOP2S(0, 0, 1, 8) 3480 3481 case AFCMPS: 3482 return FPCMP(0, 0, 0, 0, 0) 3483 3484 case AFCMPD: 3485 return FPCMP(0, 0, 1, 0, 0) 3486 3487 case AFCMPES: 3488 return FPCMP(0, 0, 0, 0, 16) 3489 3490 case AFCMPED: 3491 return FPCMP(0, 0, 1, 0, 16) 3492 3493 case AFCCMPS: 3494 return FPCCMP(0, 0, 0, 0) 3495 3496 case AFCCMPD: 3497 return FPCCMP(0, 0, 1, 0) 3498 3499 case AFCCMPES: 3500 return FPCCMP(0, 0, 0, 1) 3501 3502 case AFCCMPED: 3503 return FPCCMP(0, 0, 1, 1) 3504 3505 case AFCSELS: 3506 return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10 3507 3508 case AFCSELD: 3509 return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10 3510 3511 case AFMOVS: 3512 return FPOP1S(0, 0, 0, 0) 3513 3514 case AFABSS: 3515 return FPOP1S(0, 0, 0, 1) 3516 3517 case AFNEGS: 3518 return FPOP1S(0, 0, 0, 2) 3519 3520 case AFSQRTS: 3521 return FPOP1S(0, 0, 0, 3) 3522 3523 case AFCVTSD: 3524 return FPOP1S(0, 0, 0, 5) 3525 3526 case AFCVTSH: 3527 return FPOP1S(0, 0, 0, 7) 3528 3529 case AFRINTNS: 3530 return FPOP1S(0, 0, 0, 8) 3531 3532 case AFRINTPS: 3533 return FPOP1S(0, 0, 0, 9) 3534 3535 case AFRINTMS: 3536 return FPOP1S(0, 0, 0, 10) 3537 3538 case AFRINTZS: 3539 return FPOP1S(0, 0, 0, 11) 3540 3541 case AFRINTAS: 3542 return FPOP1S(0, 0, 0, 12) 3543 3544 case AFRINTXS: 3545 return FPOP1S(0, 0, 0, 14) 3546 3547 case AFRINTIS: 3548 return FPOP1S(0, 0, 0, 15) 3549 3550 case AFMOVD: 3551 return FPOP1S(0, 0, 1, 0) 3552 3553 case AFABSD: 3554 return FPOP1S(0, 0, 1, 1) 3555 3556 case AFNEGD: 3557 return FPOP1S(0, 0, 1, 2) 3558 3559 case AFSQRTD: 3560 return FPOP1S(0, 0, 1, 3) 3561 3562 case AFCVTDS: 3563 return FPOP1S(0, 0, 1, 4) 3564 3565 case AFCVTDH: 3566 return FPOP1S(0, 0, 1, 7) 3567 3568 case AFRINTND: 3569 return FPOP1S(0, 0, 1, 8) 3570 3571 case AFRINTPD: 3572 return FPOP1S(0, 0, 1, 9) 3573 3574 case AFRINTMD: 3575 return FPOP1S(0, 0, 1, 10) 3576 3577 case AFRINTZD: 3578 return FPOP1S(0, 0, 1, 11) 3579 3580 case AFRINTAD: 3581 return FPOP1S(0, 0, 1, 12) 3582 3583 case AFRINTXD: 3584 return FPOP1S(0, 0, 1, 14) 3585 3586 case AFRINTID: 3587 return FPOP1S(0, 0, 1, 15) 3588 3589 case AFCVTHS: 3590 return FPOP1S(0, 0, 3, 4) 3591 3592 case AFCVTHD: 3593 return FPOP1S(0, 0, 3, 5) 3594 } 3595 3596 c.ctxt.Diag("%v: bad rrr %d %v", p, a, a) 3597 return 0 3598 } 3599 3600 /* 3601 * imm -> Rd 3602 * imm op Rn -> Rd 3603 */ 3604 func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 { 3605 switch a { 3606 /* op $addcon, Rn, Rd */ 3607 case AMOVD, AADD: 3608 return S64 | 0<<30 | 0<<29 | 0x11<<24 3609 3610 case ACMN, AADDS: 3611 return S64 | 0<<30 | 1<<29 | 0x11<<24 3612 3613 case AMOVW, AADDW: 3614 return S32 | 0<<30 | 0<<29 | 0x11<<24 3615 3616 case ACMNW, AADDSW: 3617 return S32 | 0<<30 | 1<<29 | 0x11<<24 3618 3619 case ASUB: 3620 return S64 | 1<<30 | 0<<29 | 0x11<<24 3621 3622 case ACMP, ASUBS: 3623 return S64 | 1<<30 | 1<<29 | 0x11<<24 3624 3625 case ASUBW: 3626 return S32 | 1<<30 | 0<<29 | 0x11<<24 3627 3628 case ACMPW, ASUBSW: 3629 return S32 | 1<<30 | 1<<29 | 0x11<<24 3630 3631 /* op $imm(SB), Rd; op label, Rd */ 3632 case AADR: 3633 return 0<<31 | 0x10<<24 3634 3635 case AADRP: 3636 return 1<<31 | 0x10<<24 3637 3638 /* op $bimm, Rn, Rd */ 3639 case AAND, ABIC: 3640 return S64 | 0<<29 | 0x24<<23 3641 3642 case AANDW, ABICW: 3643 return S32 | 0<<29 | 0x24<<23 | 0<<22 3644 3645 case AORR, AORN: 3646 return S64 | 1<<29 | 0x24<<23 3647 3648 case AORRW, AORNW: 3649 return S32 | 1<<29 | 0x24<<23 | 0<<22 3650 3651 case AEOR, AEON: 3652 return S64 | 2<<29 | 0x24<<23 3653 3654 case AEORW, AEONW: 3655 return S32 | 2<<29 | 0x24<<23 | 0<<22 3656 3657 case AANDS, ABICS: 3658 return S64 | 3<<29 | 0x24<<23 3659 3660 case AANDSW, ABICSW: 3661 return S32 | 3<<29 | 0x24<<23 | 0<<22 3662 3663 case AASR: 3664 return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */ 3665 3666 case AASRW: 3667 return S32 | 0<<29 | 0x26<<23 | 0<<22 3668 3669 /* op $width, $lsb, Rn, Rd */ 3670 case ABFI: 3671 return S64 | 2<<29 | 0x26<<23 | 1<<22 3672 /* alias of BFM */ 3673 3674 case ABFIW: 3675 return S32 | 2<<29 | 0x26<<23 | 0<<22 3676 3677 /* op $imms, $immr, Rn, Rd */ 3678 case ABFM: 3679 return S64 | 1<<29 | 0x26<<23 | 1<<22 3680 3681 case ABFMW: 3682 return S32 | 1<<29 | 0x26<<23 | 0<<22 3683 3684 case ASBFM: 3685 return S64 | 0<<29 | 0x26<<23 | 1<<22 3686 3687 case ASBFMW: 3688 return S32 | 0<<29 | 0x26<<23 | 0<<22 3689 3690 case AUBFM: 3691 return S64 | 2<<29 | 0x26<<23 | 1<<22 3692 3693 case AUBFMW: 3694 return S32 | 2<<29 | 0x26<<23 | 0<<22 3695 3696 case ABFXIL: 3697 return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */ 3698 3699 case ABFXILW: 3700 return S32 | 1<<29 | 0x26<<23 | 0<<22 3701 3702 case AEXTR: 3703 return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21 3704 3705 case AEXTRW: 3706 return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21 3707 3708 case ACBNZ: 3709 return S64 | 0x1A<<25 | 1<<24 3710 3711 case ACBNZW: 3712 return S32 | 0x1A<<25 | 1<<24 3713 3714 case ACBZ: 3715 return S64 | 0x1A<<25 | 0<<24 3716 3717 case ACBZW: 3718 return S32 | 0x1A<<25 | 0<<24 3719 3720 case ACCMN: 3721 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 3722 3723 case ACCMNW: 3724 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 3725 3726 case ACCMP: 3727 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 3728 3729 case ACCMPW: 3730 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 3731 3732 case AMOVK: 3733 return S64 | 3<<29 | 0x25<<23 3734 3735 case AMOVKW: 3736 return S32 | 3<<29 | 0x25<<23 3737 3738 case AMOVN: 3739 return S64 | 0<<29 | 0x25<<23 3740 3741 case AMOVNW: 3742 return S32 | 0<<29 | 0x25<<23 3743 3744 case AMOVZ: 3745 return S64 | 2<<29 | 0x25<<23 3746 3747 case AMOVZW: 3748 return S32 | 2<<29 | 0x25<<23 3749 3750 case AMSR: 3751 return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */ 3752 3753 case AAT, 3754 ADC, 3755 AIC, 3756 ATLBI, 3757 ASYS: 3758 return SYSOP(0, 1, 0, 0, 0, 0, 0) 3759 3760 case ASYSL: 3761 return SYSOP(1, 1, 0, 0, 0, 0, 0) 3762 3763 case ATBZ: 3764 return 0x36 << 24 3765 3766 case ATBNZ: 3767 return 0x37 << 24 3768 3769 case ADSB: 3770 return SYSOP(0, 0, 3, 3, 0, 4, 0x1F) 3771 3772 case ADMB: 3773 return SYSOP(0, 0, 3, 3, 0, 5, 0x1F) 3774 3775 case AISB: 3776 return SYSOP(0, 0, 3, 3, 0, 6, 0x1F) 3777 3778 case AHINT: 3779 return SYSOP(0, 0, 3, 2, 0, 0, 0x1F) 3780 } 3781 3782 c.ctxt.Diag("%v: bad irr %v", p, a) 3783 return 0 3784 } 3785 3786 func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 { 3787 switch a { 3788 case ACLS: 3789 return S64 | OPBIT(5) 3790 3791 case ACLSW: 3792 return S32 | OPBIT(5) 3793 3794 case ACLZ: 3795 return S64 | OPBIT(4) 3796 3797 case ACLZW: 3798 return S32 | OPBIT(4) 3799 3800 case ARBIT: 3801 return S64 | OPBIT(0) 3802 3803 case ARBITW: 3804 return S32 | OPBIT(0) 3805 3806 case AREV: 3807 return S64 | OPBIT(3) 3808 3809 case AREVW: 3810 return S32 | OPBIT(2) 3811 3812 case AREV16: 3813 return S64 | OPBIT(1) 3814 3815 case AREV16W: 3816 return S32 | OPBIT(1) 3817 3818 case AREV32: 3819 return S64 | OPBIT(2) 3820 3821 default: 3822 c.ctxt.Diag("bad bit op\n%v", p) 3823 return 0 3824 } 3825 } 3826 3827 /* 3828 * add/subtract extended register 3829 */ 3830 func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As) uint32 { 3831 switch a { 3832 case AADD: 3833 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64 3834 3835 case AADDW: 3836 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32 3837 3838 case ACMN, AADDS: 3839 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64 3840 3841 case ACMNW, AADDSW: 3842 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32 3843 3844 case ASUB: 3845 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64 3846 3847 case ASUBW: 3848 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32 3849 3850 case ACMP, ASUBS: 3851 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64 3852 3853 case ACMPW, ASUBSW: 3854 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32 3855 } 3856 3857 c.ctxt.Diag("bad opxrrr %v\n%v", a, p) 3858 return 0 3859 } 3860 3861 func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 { 3862 switch a { 3863 case ASVC: 3864 return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */ 3865 3866 case AHVC: 3867 return 0xD4<<24 | 0<<21 | 2 3868 3869 case ASMC: 3870 return 0xD4<<24 | 0<<21 | 3 3871 3872 case ABRK: 3873 return 0xD4<<24 | 1<<21 | 0 3874 3875 case AHLT: 3876 return 0xD4<<24 | 2<<21 | 0 3877 3878 case ADCPS1: 3879 return 0xD4<<24 | 5<<21 | 1 3880 3881 case ADCPS2: 3882 return 0xD4<<24 | 5<<21 | 2 3883 3884 case ADCPS3: 3885 return 0xD4<<24 | 5<<21 | 3 3886 3887 case ACLREX: 3888 return SYSOP(0, 0, 3, 3, 0, 2, 0x1F) 3889 } 3890 3891 c.ctxt.Diag("%v: bad imm %v", p, a) 3892 return 0 3893 } 3894 3895 func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 { 3896 v := int64(0) 3897 t := int64(0) 3898 if p.Pcond != nil { 3899 v = (p.Pcond.Pc >> uint(preshift)) - (c.pc >> uint(preshift)) 3900 if (v & ((1 << uint(shift)) - 1)) != 0 { 3901 c.ctxt.Diag("misaligned label\n%v", p) 3902 } 3903 v >>= uint(shift) 3904 t = int64(1) << uint(flen-1) 3905 if v < -t || v >= t { 3906 c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, p.Pcond) 3907 panic("branch too far") 3908 } 3909 } 3910 3911 return v & ((t << 1) - 1) 3912 } 3913 3914 /* 3915 * pc-relative branches 3916 */ 3917 func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 { 3918 switch a { 3919 case ABEQ: 3920 return OPBcc(0x0) 3921 3922 case ABNE: 3923 return OPBcc(0x1) 3924 3925 case ABCS: 3926 return OPBcc(0x2) 3927 3928 case ABHS: 3929 return OPBcc(0x2) 3930 3931 case ABCC: 3932 return OPBcc(0x3) 3933 3934 case ABLO: 3935 return OPBcc(0x3) 3936 3937 case ABMI: 3938 return OPBcc(0x4) 3939 3940 case ABPL: 3941 return OPBcc(0x5) 3942 3943 case ABVS: 3944 return OPBcc(0x6) 3945 3946 case ABVC: 3947 return OPBcc(0x7) 3948 3949 case ABHI: 3950 return OPBcc(0x8) 3951 3952 case ABLS: 3953 return OPBcc(0x9) 3954 3955 case ABGE: 3956 return OPBcc(0xa) 3957 3958 case ABLT: 3959 return OPBcc(0xb) 3960 3961 case ABGT: 3962 return OPBcc(0xc) 3963 3964 case ABLE: 3965 return OPBcc(0xd) /* imm19<<5 | cond */ 3966 3967 case AB: 3968 return 0<<31 | 5<<26 /* imm26 */ 3969 3970 case obj.ADUFFZERO, obj.ADUFFCOPY, ABL: 3971 return 1<<31 | 5<<26 3972 } 3973 3974 c.ctxt.Diag("%v: bad bra %v", p, a) 3975 return 0 3976 } 3977 3978 func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 { 3979 switch a { 3980 case ABL: 3981 return OPBLR(1) /* BLR */ 3982 3983 case AB: 3984 return OPBLR(0) /* BR */ 3985 3986 case obj.ARET: 3987 return OPBLR(2) /* RET */ 3988 } 3989 3990 c.ctxt.Diag("%v: bad brr %v", p, a) 3991 return 0 3992 } 3993 3994 func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 { 3995 switch a { 3996 case ADRPS: 3997 return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5 3998 3999 case AERET: 4000 return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5 4001 4002 // case ANOP: 4003 // return SYSHINT(0) 4004 4005 case AYIELD: 4006 return SYSHINT(1) 4007 4008 case AWFE: 4009 return SYSHINT(2) 4010 4011 case AWFI: 4012 return SYSHINT(3) 4013 4014 case ASEV: 4015 return SYSHINT(4) 4016 4017 case ASEVL: 4018 return SYSHINT(5) 4019 } 4020 4021 c.ctxt.Diag("%v: bad op0 %v", p, a) 4022 return 0 4023 } 4024 4025 /* 4026 * register offset 4027 */ 4028 func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 { 4029 switch a { 4030 case ALDAR: 4031 return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10 4032 4033 case ALDARW: 4034 return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10 4035 4036 case ALDARB: 4037 return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10 4038 4039 case ALDARH: 4040 return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10 4041 4042 case ALDAXP: 4043 return LDSTX(3, 0, 1, 1, 1) 4044 4045 case ALDAXPW: 4046 return LDSTX(2, 0, 1, 1, 1) 4047 4048 case ALDAXR: 4049 return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10 4050 4051 case ALDAXRW: 4052 return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10 4053 4054 case ALDAXRB: 4055 return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10 4056 4057 case ALDAXRH: 4058 return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10 4059 4060 case ALDXR: 4061 return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10 4062 4063 case ALDXRB: 4064 return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10 4065 4066 case ALDXRH: 4067 return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10 4068 4069 case ALDXRW: 4070 return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10 4071 4072 case ALDXP: 4073 return LDSTX(3, 0, 1, 1, 0) 4074 4075 case ALDXPW: 4076 return LDSTX(2, 0, 1, 1, 0) 4077 4078 case AMOVNP: 4079 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 4080 4081 case AMOVNPW: 4082 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 4083 } 4084 4085 c.ctxt.Diag("bad opload %v\n%v", a, p) 4086 return 0 4087 } 4088 4089 func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 { 4090 switch a { 4091 case ASTLR: 4092 return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10 4093 4094 case ASTLRB: 4095 return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10 4096 4097 case ASTLRH: 4098 return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10 4099 4100 case ASTLP: 4101 return LDSTX(3, 0, 0, 1, 1) 4102 4103 case ASTLPW: 4104 return LDSTX(2, 0, 0, 1, 1) 4105 4106 case ASTLRW: 4107 return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10 4108 4109 case ASTLXP: 4110 return LDSTX(2, 0, 0, 1, 1) 4111 4112 case ASTLXPW: 4113 return LDSTX(3, 0, 0, 1, 1) 4114 4115 case ASTLXR: 4116 return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10 4117 4118 case ASTLXRB: 4119 return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10 4120 4121 case ASTLXRH: 4122 return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10 4123 4124 case ASTLXRW: 4125 return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10 4126 4127 case ASTXR: 4128 return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10 4129 4130 case ASTXRB: 4131 return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10 4132 4133 case ASTXRH: 4134 return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10 4135 4136 case ASTXP: 4137 return LDSTX(3, 0, 0, 1, 0) 4138 4139 case ASTXPW: 4140 return LDSTX(2, 0, 0, 1, 0) 4141 4142 case ASTXRW: 4143 return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10 4144 4145 case AMOVNP: 4146 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 4147 4148 case AMOVNPW: 4149 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 4150 } 4151 4152 c.ctxt.Diag("bad opstore %v\n%v", a, p) 4153 return 0 4154 } 4155 4156 /* 4157 * load/store register (unsigned immediate) C3.3.13 4158 * these produce 64-bit values (when there's an option) 4159 */ 4160 func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 { 4161 if v < 0 || v >= (1<<12) { 4162 c.ctxt.Diag("offset out of range: %d\n%v", v, p) 4163 } 4164 o |= (v & 0xFFF) << 10 4165 o |= int32(b&31) << 5 4166 o |= int32(r & 31) 4167 return uint32(o) 4168 } 4169 4170 func (c *ctxt7) opldr12(p *obj.Prog, a obj.As) uint32 { 4171 switch a { 4172 case AMOVD: 4173 return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */ 4174 4175 case AMOVW: 4176 return LDSTR12U(2, 0, 2) 4177 4178 case AMOVWU: 4179 return LDSTR12U(2, 0, 1) 4180 4181 case AMOVH: 4182 return LDSTR12U(1, 0, 2) 4183 4184 case AMOVHU: 4185 return LDSTR12U(1, 0, 1) 4186 4187 case AMOVB: 4188 return LDSTR12U(0, 0, 2) 4189 4190 case AMOVBU: 4191 return LDSTR12U(0, 0, 1) 4192 4193 case AFMOVS: 4194 return LDSTR12U(2, 1, 1) 4195 4196 case AFMOVD: 4197 return LDSTR12U(3, 1, 1) 4198 } 4199 4200 c.ctxt.Diag("bad opldr12 %v\n%v", a, p) 4201 return 0 4202 } 4203 4204 func (c *ctxt7) opstr12(p *obj.Prog, a obj.As) uint32 { 4205 return LD2STR(c.opldr12(p, a)) 4206 } 4207 4208 /* 4209 * load/store register (unscaled immediate) C3.3.12 4210 */ 4211 func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 { 4212 if v < -256 || v > 255 { 4213 c.ctxt.Diag("offset out of range: %d\n%v", v, p) 4214 } 4215 o |= (v & 0x1FF) << 12 4216 o |= int32(b&31) << 5 4217 o |= int32(r & 31) 4218 return uint32(o) 4219 } 4220 4221 func (c *ctxt7) opldr9(p *obj.Prog, a obj.As) uint32 { 4222 switch a { 4223 case AMOVD: 4224 return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */ 4225 4226 case AMOVW: 4227 return LDSTR9S(2, 0, 2) 4228 4229 case AMOVWU: 4230 return LDSTR9S(2, 0, 1) 4231 4232 case AMOVH: 4233 return LDSTR9S(1, 0, 2) 4234 4235 case AMOVHU: 4236 return LDSTR9S(1, 0, 1) 4237 4238 case AMOVB: 4239 return LDSTR9S(0, 0, 2) 4240 4241 case AMOVBU: 4242 return LDSTR9S(0, 0, 1) 4243 4244 case AFMOVS: 4245 return LDSTR9S(2, 1, 1) 4246 4247 case AFMOVD: 4248 return LDSTR9S(3, 1, 1) 4249 } 4250 4251 c.ctxt.Diag("bad opldr9 %v\n%v", a, p) 4252 return 0 4253 } 4254 4255 func (c *ctxt7) opstr9(p *obj.Prog, a obj.As) uint32 { 4256 return LD2STR(c.opldr9(p, a)) 4257 } 4258 4259 func (c *ctxt7) opldrpp(p *obj.Prog, a obj.As) uint32 { 4260 switch a { 4261 case AMOVD: 4262 return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */ 4263 4264 case AMOVW: 4265 return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 4266 4267 case AMOVWU: 4268 return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 4269 4270 case AMOVH: 4271 return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 4272 4273 case AMOVHU: 4274 return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 4275 4276 case AMOVB: 4277 return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 4278 4279 case AMOVBU: 4280 return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 4281 } 4282 4283 c.ctxt.Diag("bad opldr %v\n%v", a, p) 4284 return 0 4285 } 4286 4287 // olsxrr attaches register operands to a load/store opcode supplied in o. 4288 // The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2). 4289 func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 { 4290 o |= int32(r1&31) << 5 4291 o |= int32(r2&31) << 16 4292 o |= int32(r & 31) 4293 return uint32(o) 4294 } 4295 4296 // opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode 4297 // for load instruction with register offset. 4298 func (c *ctxt7) opldrr(p *obj.Prog, a obj.As) uint32 { 4299 switch a { 4300 case AMOVD: 4301 return 0x1a<<10 | 0x3<<21 | 0x1f<<27 4302 case AMOVW: 4303 return 0x1a<<10 | 0x5<<21 | 0x17<<27 4304 case AMOVWU: 4305 return 0x1a<<10 | 0x3<<21 | 0x17<<27 4306 case AMOVH: 4307 return 0x1a<<10 | 0x5<<21 | 0x0f<<27 4308 case AMOVHU: 4309 return 0x1a<<10 | 0x3<<21 | 0x0f<<27 4310 case AMOVB: 4311 return 0x1a<<10 | 0x5<<21 | 0x07<<27 4312 case AMOVBU: 4313 return 0x1a<<10 | 0x3<<21 | 0x07<<27 4314 case AFMOVS: 4315 return 0x1a<<10 | 0x3<<21 | 0x17<<27 | 1<<26 4316 case AFMOVD: 4317 return 0x1a<<10 | 0x3<<21 | 0x1f<<27 | 1<<26 4318 } 4319 c.ctxt.Diag("bad opldrr %v\n%v", a, p) 4320 return 0 4321 } 4322 4323 // opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode 4324 // for store instruction with register offset. 4325 func (c *ctxt7) opstrr(p *obj.Prog, a obj.As) uint32 { 4326 switch a { 4327 case AMOVD: 4328 return 0x1a<<10 | 0x1<<21 | 0x1f<<27 4329 case AMOVW, AMOVWU: 4330 return 0x1a<<10 | 0x1<<21 | 0x17<<27 4331 case AMOVH, AMOVHU: 4332 return 0x1a<<10 | 0x1<<21 | 0x0f<<27 4333 case AMOVB, AMOVBU: 4334 return 0x1a<<10 | 0x1<<21 | 0x07<<27 4335 case AFMOVS: 4336 return 0x1a<<10 | 0x1<<21 | 0x17<<27 | 1<<26 4337 case AFMOVD: 4338 return 0x1a<<10 | 0x1<<21 | 0x1f<<27 | 1<<26 4339 } 4340 c.ctxt.Diag("bad opstrr %v\n%v", a, p) 4341 return 0 4342 } 4343 4344 func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 { 4345 if (v & 0xFFF000) != 0 { 4346 if v&0xFFF != 0 { 4347 c.ctxt.Diag("%v misuses oaddi", p) 4348 } 4349 v >>= 12 4350 o1 |= 1 << 22 4351 } 4352 4353 o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31) 4354 return uint32(o1) 4355 } 4356 4357 /* 4358 * load a a literal value into dr 4359 */ 4360 func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 { 4361 var o1 int32 4362 if p.Pcond == nil { /* not in literal pool */ 4363 c.aclass(a) 4364 c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset)) 4365 4366 /* TODO: could be clever, and use general constant builder */ 4367 o1 = int32(c.opirr(p, AADD)) 4368 4369 v := int32(c.instoffset) 4370 if v != 0 && (v&0xFFF) == 0 { 4371 v >>= 12 4372 o1 |= 1 << 22 /* shift, by 12 */ 4373 } 4374 4375 o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31) 4376 } else { 4377 fp := 0 4378 w := 0 /* default: 32 bit, unsigned */ 4379 switch as { 4380 case AFMOVS: 4381 fp = 1 4382 4383 case AFMOVD: 4384 fp = 1 4385 w = 1 /* 64 bit simd&fp */ 4386 4387 case AMOVD: 4388 if p.Pcond.As == ADWORD { 4389 w = 1 /* 64 bit */ 4390 } else if p.Pcond.To.Offset < 0 { 4391 w = 2 /* sign extend */ 4392 } 4393 4394 case AMOVB, AMOVH, AMOVW: 4395 w = 2 /* 32 bit, sign-extended to 64 */ 4396 break 4397 } 4398 4399 v := int32(c.brdist(p, 0, 19, 2)) 4400 o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27) 4401 o1 |= (v & 0x7FFFF) << 5 4402 o1 |= int32(dr & 31) 4403 } 4404 4405 return uint32(o1) 4406 } 4407 4408 // load a constant (MOVCON or BITCON) in a into rt 4409 func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) { 4410 if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 { 4411 // or $bitcon, REGZERO, rt 4412 mode := 64 4413 var as1 obj.As 4414 switch as { 4415 case AMOVW: 4416 as1 = AORRW 4417 mode = 32 4418 case AMOVD: 4419 as1 = AORR 4420 } 4421 o1 = c.opirr(p, as1) 4422 o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31) 4423 return o1 4424 } 4425 4426 r := 32 4427 if as == AMOVD { 4428 r = 64 4429 } 4430 d := a.Offset 4431 s := movcon(d) 4432 if s < 0 || s >= r { 4433 d = ^d 4434 s = movcon(d) 4435 if s < 0 || s >= r { 4436 c.ctxt.Diag("impossible move wide: %#x\n%v", uint64(a.Offset), p) 4437 } 4438 if as == AMOVD { 4439 o1 = c.opirr(p, AMOVN) 4440 } else { 4441 o1 = c.opirr(p, AMOVNW) 4442 } 4443 } else { 4444 if as == AMOVD { 4445 o1 = c.opirr(p, AMOVZ) 4446 } else { 4447 o1 = c.opirr(p, AMOVZW) 4448 } 4449 } 4450 o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31)) 4451 return o1 4452 } 4453 4454 func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 { 4455 var b uint32 4456 o := c.opirr(p, a) 4457 if (o & (1 << 31)) == 0 { 4458 b = 32 4459 } else { 4460 b = 64 4461 } 4462 if r < 0 || uint32(r) >= b { 4463 c.ctxt.Diag("illegal bit number\n%v", p) 4464 } 4465 o |= (uint32(r) & 0x3F) << 16 4466 if s < 0 || uint32(s) >= b { 4467 c.ctxt.Diag("illegal bit number\n%v", p) 4468 } 4469 o |= (uint32(s) & 0x3F) << 10 4470 o |= (uint32(rf&31) << 5) | uint32(rt&31) 4471 return o 4472 } 4473 4474 func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 { 4475 var b uint32 4476 o := c.opirr(p, a) 4477 if (o & (1 << 31)) != 0 { 4478 b = 63 4479 } else { 4480 b = 31 4481 } 4482 if v < 0 || uint32(v) > b { 4483 c.ctxt.Diag("illegal bit number\n%v", p) 4484 } 4485 o |= uint32(v) << 10 4486 o |= uint32(rn&31) << 5 4487 o |= uint32(rm&31) << 16 4488 o |= uint32(rt & 31) 4489 return o 4490 } 4491 4492 /* 4493 * size in log2(bytes) 4494 */ 4495 func movesize(a obj.As) int { 4496 switch a { 4497 case AMOVD: 4498 return 3 4499 4500 case AMOVW, AMOVWU: 4501 return 2 4502 4503 case AMOVH, AMOVHU: 4504 return 1 4505 4506 case AMOVB, AMOVBU: 4507 return 0 4508 4509 case AFMOVS: 4510 return 2 4511 4512 case AFMOVD: 4513 return 3 4514 4515 default: 4516 return -1 4517 } 4518 }