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