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