github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/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 extrasize int32 53 instoffset int64 54 pc int64 55 pool struct { 56 start uint32 57 size uint32 58 } 59 } 60 61 const ( 62 funcAlign = 16 63 ) 64 65 const ( 66 REGFROM = 1 67 ) 68 69 type Optab struct { 70 as obj.As 71 a1 uint8 72 a2 uint8 73 a3 uint8 74 a4 uint8 75 type_ int8 76 size int8 77 param int16 78 flag int8 79 scond uint16 80 } 81 82 var oprange [ALAST & obj.AMask][]Optab 83 84 var xcmp [C_NCLASS][C_NCLASS]bool 85 86 const ( 87 S32 = 0 << 31 88 S64 = 1 << 31 89 Sbit = 1 << 29 90 LSL0_32 = 2 << 13 91 LSL0_64 = 3 << 13 92 ) 93 94 func OPDP2(x uint32) uint32 { 95 return 0<<30 | 0<<29 | 0xd6<<21 | x<<10 96 } 97 98 func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 { 99 return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15 100 } 101 102 func OPBcc(x uint32) uint32 { 103 return 0x2A<<25 | 0<<24 | 0<<4 | x&15 104 } 105 106 func OPBLR(x uint32) uint32 { 107 /* x=0, JMP; 1, CALL; 2, RET */ 108 return 0x6B<<25 | 0<<23 | x<<21 | 0x1F<<16 | 0<<10 109 } 110 111 func SYSOP(l uint32, op0 uint32, op1 uint32, crn uint32, crm uint32, op2 uint32, rt uint32) uint32 { 112 return 0x354<<22 | l<<21 | op0<<19 | op1<<16 | crn&15<<12 | crm&15<<8 | op2<<5 | rt 113 } 114 115 func SYSHINT(x uint32) uint32 { 116 return SYSOP(0, 0, 3, 2, 0, x, 0x1F) 117 } 118 119 func LDSTR12U(sz uint32, v uint32, opc uint32) uint32 { 120 return sz<<30 | 7<<27 | v<<26 | 1<<24 | opc<<22 121 } 122 123 func LDSTR9S(sz uint32, v uint32, opc uint32) uint32 { 124 return sz<<30 | 7<<27 | v<<26 | 0<<24 | opc<<22 125 } 126 127 func LD2STR(o uint32) uint32 { 128 return o &^ (3 << 22) 129 } 130 131 func LDSTX(sz uint32, o2 uint32, l uint32, o1 uint32, o0 uint32) uint32 { 132 return sz<<30 | 0x8<<24 | o2<<23 | l<<22 | o1<<21 | o0<<15 133 } 134 135 func FPCMP(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 { 136 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<14 | 8<<10 | op2 137 } 138 139 func FPCCMP(m uint32, s uint32, type_ uint32, op uint32) uint32 { 140 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | 1<<10 | op<<4 141 } 142 143 func FPOP1S(m uint32, s uint32, type_ uint32, op uint32) uint32 { 144 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<15 | 0x10<<10 145 } 146 147 func FPOP2S(m uint32, s uint32, type_ uint32, op uint32) uint32 { 148 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<12 | 2<<10 149 } 150 151 func FPOP3S(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 { 152 return m<<31 | s<<29 | 0x1F<<24 | type_<<22 | op<<21 | op2<<15 153 } 154 155 func FPCVTI(sf uint32, s uint32, type_ uint32, rmode uint32, op uint32) uint32 { 156 return sf<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | rmode<<19 | op<<16 | 0<<10 157 } 158 159 func ADR(p uint32, o uint32, rt uint32) uint32 { 160 return p<<31 | (o&3)<<29 | 0x10<<24 | ((o>>2)&0x7FFFF)<<5 | rt&31 161 } 162 163 func OPBIT(x uint32) uint32 { 164 return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10 165 } 166 167 func MOVCONST(d int64, s int, rt int) uint32 { 168 return uint32(((d>>uint(s*16))&0xFFFF)<<5) | uint32(s)&3<<21 | uint32(rt&31) 169 } 170 171 const ( 172 LFROM = 1 << 0 173 LTO = 1 << 1 174 ) 175 176 var optab = []Optab{ 177 /* struct Optab: 178 OPCODE, from, prog->reg, from3, to, type,size,param,flag,scond */ 179 {obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0}, 180 181 /* arithmetic operations */ 182 {AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 183 {AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, 184 {AADC, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 185 {AADC, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, 186 {ANEG, C_REG, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0}, 187 {ANEG, C_NONE, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0}, 188 {ANGC, C_REG, C_NONE, C_NONE, C_REG, 17, 4, 0, 0, 0}, 189 {ACMP, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0}, 190 {AADD, C_ADDCON, C_RSP, C_NONE, C_RSP, 2, 4, 0, 0, 0}, 191 {AADD, C_ADDCON, C_NONE, C_NONE, C_RSP, 2, 4, 0, 0, 0}, 192 {ACMP, C_ADDCON, C_RSP, C_NONE, C_NONE, 2, 4, 0, 0, 0}, 193 {AADD, C_MOVCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0}, 194 {AADD, C_MOVCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0}, 195 {ACMP, C_MOVCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0}, 196 {AADD, C_BITCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0}, 197 {AADD, C_BITCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0}, 198 {ACMP, C_BITCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0}, 199 {AADD, C_ADDCON2, C_RSP, C_NONE, C_RSP, 48, 8, 0, 0, 0}, 200 {AADD, C_ADDCON2, C_NONE, C_NONE, C_RSP, 48, 8, 0, 0, 0}, 201 {AADD, C_VCON, C_RSP, C_NONE, C_RSP, 13, 8, 0, LFROM, 0}, 202 {AADD, C_VCON, C_NONE, C_NONE, C_RSP, 13, 8, 0, LFROM, 0}, 203 {ACMP, C_VCON, C_REG, C_NONE, C_NONE, 13, 8, 0, LFROM, 0}, 204 {AADD, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0}, 205 {AADD, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, 206 {AMVN, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, 207 {ACMP, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0}, 208 {ANEG, C_SHIFT, C_NONE, C_NONE, C_REG, 26, 4, 0, 0, 0}, 209 {AADD, C_REG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 210 {AADD, C_REG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 211 {ACMP, C_REG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0}, 212 {AADD, C_EXTREG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 213 {AADD, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 214 {AMVN, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 215 {ACMP, C_EXTREG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0}, 216 {AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 217 {AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, 218 {AMUL, C_REG, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0}, 219 {AMUL, C_REG, C_NONE, C_NONE, C_REG, 15, 4, 0, 0, 0}, 220 {AMADD, C_REG, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0}, 221 {AREM, C_REG, C_REG, C_NONE, C_REG, 16, 8, 0, 0, 0}, 222 {AREM, C_REG, C_NONE, C_NONE, C_REG, 16, 8, 0, 0, 0}, 223 {ASDIV, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, 224 {ASDIV, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 225 226 {AFADDS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 227 {AFADDS, C_FREG, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 228 {AFMSUBD, C_FREG, C_FREG, C_FREG, C_FREG, 15, 4, 0, 0, 0}, 229 {AFCMPS, C_FREG, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0}, 230 {AFCMPS, C_FCON, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0}, 231 {AVADDP, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0}, 232 {AVADD, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0}, 233 {AVADD, C_VREG, C_VREG, C_NONE, C_VREG, 89, 4, 0, 0, 0}, 234 {AVADD, C_VREG, C_NONE, C_NONE, C_VREG, 89, 4, 0, 0, 0}, 235 {AVADDV, C_ARNG, C_NONE, C_NONE, C_VREG, 85, 4, 0, 0, 0}, 236 237 /* logical operations */ 238 {AAND, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 239 {AAND, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, 240 {AANDS, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 241 {AANDS, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, 242 {ATST, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0}, 243 {AAND, C_MBCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0}, 244 {AAND, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, 245 {AANDS, C_MBCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0}, 246 {AANDS, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, 247 {ATST, C_MBCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0}, 248 {AAND, C_BITCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0}, 249 {AAND, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, 250 {AANDS, C_BITCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0}, 251 {AANDS, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, 252 {ATST, C_BITCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0}, 253 {AAND, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0}, 254 {AAND, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0}, 255 {AANDS, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0}, 256 {AANDS, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0}, 257 {ATST, C_MOVCON, C_REG, C_NONE, C_NONE, 62, 8, 0, 0, 0}, 258 {AAND, C_VCON, C_REG, C_NONE, C_REG, 28, 8, 0, LFROM, 0}, 259 {AAND, C_VCON, C_NONE, C_NONE, C_REG, 28, 8, 0, LFROM, 0}, 260 {AANDS, C_VCON, C_REG, C_NONE, C_REG, 28, 8, 0, LFROM, 0}, 261 {AANDS, C_VCON, C_NONE, C_NONE, C_REG, 28, 8, 0, LFROM, 0}, 262 {ATST, C_VCON, C_REG, C_NONE, C_NONE, 28, 8, 0, LFROM, 0}, 263 {AAND, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0}, 264 {AAND, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, 265 {AANDS, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0}, 266 {AANDS, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, 267 {ATST, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0}, 268 {AMOVD, C_RSP, C_NONE, C_NONE, C_RSP, 24, 4, 0, 0, 0}, 269 {AMVN, C_REG, C_NONE, C_NONE, C_REG, 24, 4, 0, 0, 0}, 270 {AMOVB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, 271 {AMOVBU, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, 272 {AMOVH, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVHU */ 273 {AMOVW, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVWU */ 274 /* TODO: MVN C_SHIFT */ 275 276 /* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */ 277 {AMOVW, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, 278 {AMOVD, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, 279 {AMOVW, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, 280 {AMOVD, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, 281 {AMOVW, C_LCON, C_NONE, C_NONE, C_REG, 12, 4, 0, LFROM, 0}, 282 {AMOVD, C_VCON, C_NONE, C_NONE, C_REG, 12, 4, 0, LFROM, 0}, 283 284 {AMOVK, C_VCON, C_NONE, C_NONE, C_REG, 33, 4, 0, 0, 0}, 285 {AMOVD, C_AACON, C_NONE, C_NONE, C_REG, 4, 4, REGFROM, 0, 0}, 286 287 /* jump operations */ 288 {AB, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, 289 {ABL, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, 290 {AB, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, 291 {ABL, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0}, 292 {ABL, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0}, 293 {ABL, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, 294 {obj.ARET, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0}, 295 {obj.ARET, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, 296 {ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 7, 4, 0, 0, 0}, 297 {AADRP, C_SBRA, C_NONE, C_NONE, C_REG, 60, 4, 0, 0, 0}, 298 {AADR, C_SBRA, C_NONE, C_NONE, C_REG, 61, 4, 0, 0, 0}, 299 {ACBZ, C_REG, C_NONE, C_NONE, C_SBRA, 39, 4, 0, 0, 0}, 300 {ATBZ, C_VCON, C_REG, C_NONE, C_SBRA, 40, 4, 0, 0, 0}, 301 {AERET, C_NONE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0}, 302 303 {ACLREX, C_NONE, C_NONE, C_NONE, C_VCON, 38, 4, 0, 0, 0}, 304 {ACLREX, C_NONE, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0}, 305 {ABFM, C_VCON, C_REG, C_VCON, C_REG, 42, 4, 0, 0, 0}, 306 {ABFI, C_VCON, C_REG, C_VCON, C_REG, 43, 4, 0, 0, 0}, 307 {AEXTR, C_VCON, C_REG, C_REG, C_REG, 44, 4, 0, 0, 0}, 308 {ASXTB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, 309 {ACLS, C_REG, C_NONE, C_NONE, C_REG, 46, 4, 0, 0, 0}, 310 {ALSL, C_VCON, C_REG, C_NONE, C_REG, 8, 4, 0, 0, 0}, 311 {ALSL, C_VCON, C_NONE, C_NONE, C_REG, 8, 4, 0, 0, 0}, 312 {ALSL, C_REG, C_NONE, C_NONE, C_REG, 9, 4, 0, 0, 0}, 313 {ALSL, C_REG, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0}, 314 {ASVC, C_VCON, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0}, 315 {ASVC, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0}, 316 {ADWORD, C_NONE, C_NONE, C_NONE, C_VCON, 11, 8, 0, 0, 0}, 317 {ADWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 11, 8, 0, 0, 0}, 318 {ADWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 11, 8, 0, 0, 0}, 319 {ADWORD, C_NONE, C_NONE, C_NONE, C_LACON, 11, 8, 0, 0, 0}, 320 {AWORD, C_NONE, C_NONE, C_NONE, C_LCON, 14, 4, 0, 0, 0}, 321 {AWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0}, 322 {AWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0}, 323 {AMOVW, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, 0, 0}, 324 {AMOVD, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, 0, 0}, 325 {AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 326 {AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 327 {AMOVH, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 328 {AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 329 {AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 330 {AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, 331 {AMOVBU, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, 332 {AMOVH, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, 333 {AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, 334 {AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0}, 335 {AMOVD, C_GOTADDR, C_NONE, C_NONE, C_REG, 71, 8, 0, 0, 0}, 336 {AMOVD, C_TLS_LE, C_NONE, C_NONE, C_REG, 69, 4, 0, 0, 0}, 337 {AMOVD, C_TLS_IE, C_NONE, C_NONE, C_REG, 70, 8, 0, 0, 0}, 338 339 {AFMOVS, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 340 {AFMOVS, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0}, 341 {AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 342 {AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0}, 343 {AFMOVS, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0}, 344 {AFMOVS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 345 {AFMOVD, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0}, 346 {AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 347 {AFMOVS, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 348 {AFMOVS, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0}, 349 {AFMOVD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 350 {AFMOVD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0}, 351 {AFCVTZSD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0}, 352 {ASCVTFD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 353 {AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 354 {AVCNT, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, 355 {AVMOV, C_ELEM, C_NONE, C_NONE, C_REG, 73, 4, 0, 0, 0}, 356 {AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0}, 357 {AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0}, 358 {AVMOV, C_REG, C_NONE, C_NONE, C_ARNG, 82, 4, 0, 0, 0}, 359 {AVMOV, C_REG, C_NONE, C_NONE, C_ELEM, 78, 4, 0, 0, 0}, 360 {AVMOV, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0}, 361 {AVDUP, C_ELEM, C_NONE, C_NONE, C_ARNG, 79, 4, 0, 0, 0}, 362 {AVMOVI, C_ADDCON, C_NONE, C_NONE, C_ARNG, 86, 4, 0, 0, 0}, 363 {AVFMLA, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0}, 364 {AVEXT, C_VCON, C_ARNG, C_ARNG, C_ARNG, 94, 4, 0, 0, 0}, 365 {AVTBL, C_ARNG, C_NONE, C_LIST, C_ARNG, 100, 4, 0, 0, 0}, 366 {AVUSHR, C_VCON, C_ARNG, C_NONE, C_ARNG, 95, 4, 0, 0, 0}, 367 {AVZIP1, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0}, 368 369 /* conditional operations */ 370 {ACSEL, C_COND, C_REG, C_REG, C_REG, 18, 4, 0, 0, 0}, 371 {ACINC, C_COND, C_REG, C_NONE, C_REG, 18, 4, 0, 0, 0}, 372 {ACSET, C_COND, C_NONE, C_NONE, C_REG, 18, 4, 0, 0, 0}, 373 {AFCSELD, C_COND, C_FREG, C_FREG, C_FREG, 18, 4, 0, 0, 0}, 374 {ACCMN, C_COND, C_REG, C_REG, C_VCON, 19, 4, 0, 0, 0}, 375 {ACCMN, C_COND, C_REG, C_VCON, C_VCON, 19, 4, 0, 0, 0}, 376 {AFCCMPS, C_COND, C_FREG, C_FREG, C_VCON, 57, 4, 0, 0, 0}, 377 378 /* scaled 12-bit unsigned displacement store */ 379 {AMOVB, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0}, 380 {AMOVB, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0}, 381 {AMOVBU, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0}, 382 {AMOVBU, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0}, 383 {AMOVH, C_REG, C_NONE, C_NONE, C_UAUTO8K, 20, 4, REGSP, 0, 0}, 384 {AMOVH, C_REG, C_NONE, C_NONE, C_UOREG8K, 20, 4, 0, 0, 0}, 385 {AMOVW, C_REG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0}, 386 {AMOVW, C_REG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0}, 387 {AMOVD, C_REG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0}, 388 {AMOVD, C_REG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0}, 389 390 {AFMOVS, C_FREG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0}, 391 {AFMOVS, C_FREG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0}, 392 {AFMOVD, C_FREG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0}, 393 {AFMOVD, C_FREG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0}, 394 395 /* unscaled 9-bit signed displacement store */ 396 {AMOVB, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 397 {AMOVB, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 398 {AMOVBU, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 399 {AMOVBU, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 400 {AMOVH, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 401 {AMOVH, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 402 {AMOVW, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 403 {AMOVW, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 404 {AMOVD, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 405 {AMOVD, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 406 407 {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 408 {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 409 {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 410 {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 411 412 /* scaled 12-bit unsigned displacement load */ 413 {AMOVB, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 414 {AMOVB, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 415 {AMOVBU, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 416 {AMOVBU, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 417 {AMOVH, C_UAUTO8K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 418 {AMOVH, C_UOREG8K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 419 {AMOVW, C_UAUTO16K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 420 {AMOVW, C_UOREG16K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 421 {AMOVD, C_UAUTO32K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 422 {AMOVD, C_UOREG32K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 423 424 {AFMOVS, C_UAUTO16K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 425 {AFMOVS, C_UOREG16K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 426 {AFMOVD, C_UAUTO32K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 427 {AFMOVD, C_UOREG32K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 428 429 /* unscaled 9-bit signed displacement load */ 430 {AMOVB, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 431 {AMOVB, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 432 {AMOVBU, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 433 {AMOVBU, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 434 {AMOVH, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 435 {AMOVH, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 436 {AMOVW, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 437 {AMOVW, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 438 {AMOVD, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 439 {AMOVD, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 440 441 {AFMOVS, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 442 {AFMOVS, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 443 {AFMOVD, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 444 {AFMOVD, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 445 446 /* long displacement store */ 447 {AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 448 {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 449 {AMOVBU, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 450 {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 451 {AMOVH, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 452 {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 453 {AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 454 {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 455 {AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 456 {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 457 458 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 459 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 460 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 461 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 462 463 /* long displacement load */ 464 {AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 465 {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 466 {AMOVBU, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 467 {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 468 {AMOVH, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 469 {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 470 {AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 471 {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 472 {AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 473 {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 474 475 {AFMOVS, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0}, 476 {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0}, 477 {AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0}, 478 {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0}, 479 480 /* load long effective stack address (load int32 offset and add) */ 481 {AMOVD, C_LACON, C_NONE, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0}, 482 483 /* pre/post-indexed load (unscaled, signed 9-bit offset) */ 484 {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 485 {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 486 {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 487 {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 488 {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 489 {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST}, 490 {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST}, 491 492 {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 493 {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 494 {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 495 {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 496 {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 497 {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE}, 498 {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE}, 499 500 /* pre/post-indexed store (unscaled, signed 9-bit offset) */ 501 {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 502 {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 503 {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 504 {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 505 {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 506 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 507 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 508 509 {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 510 {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 511 {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 512 {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 513 {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 514 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 515 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 516 517 /* load with shifted or extended register offset */ 518 {AMOVD, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, 519 {AMOVW, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, 520 {AMOVH, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, 521 {AMOVB, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, 522 {AMOVBU, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0}, 523 {AFMOVS, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0}, 524 {AFMOVD, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0}, 525 526 /* store with extended register offset */ 527 {AMOVD, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, 528 {AMOVW, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, 529 {AMOVH, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, 530 {AMOVB, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, 531 {AFMOVS, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, 532 {AFMOVD, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, 533 534 /* pre/post-indexed/signed-offset load/store register pair 535 (unscaled, signed 10-bit quad-aligned and long offset) */ 536 {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, 537 {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, 538 {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, 539 {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, 540 {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, 541 {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, 542 {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, 543 {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE}, 544 {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST}, 545 {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, 546 {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE}, 547 {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST}, 548 {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0}, 549 {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE}, 550 {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST}, 551 {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, 552 {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, 553 {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, 554 {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, 555 {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, 556 {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, 557 {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0}, 558 {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE}, 559 {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST}, 560 {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0}, 561 {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE}, 562 {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST}, 563 {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0}, 564 {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE}, 565 {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST}, 566 {ALDP, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0}, 567 568 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, 0}, 569 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPRE}, 570 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPOST}, 571 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, 0}, 572 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPRE}, 573 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPOST}, 574 {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0}, 575 {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE}, 576 {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST}, 577 {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0}, 578 {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE}, 579 {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST}, 580 {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0}, 581 {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE}, 582 {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST}, 583 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, 0}, 584 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPRE}, 585 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPOST}, 586 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, 0}, 587 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPRE}, 588 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPOST}, 589 {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0}, 590 {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE}, 591 {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST}, 592 {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0}, 593 {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE}, 594 {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST}, 595 {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0}, 596 {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE}, 597 {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST}, 598 {ASTP, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0}, 599 600 // differ from LDP/STP for C_NSAUTO_4/C_PSAUTO_4/C_NSOREG_4/C_PSOREG_4 601 {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, 602 {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, 603 {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, 604 {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, 605 {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, 606 {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, 607 {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, 608 {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE}, 609 {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST}, 610 {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, 611 {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE}, 612 {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST}, 613 {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0}, 614 {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE}, 615 {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST}, 616 {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, 617 {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, 618 {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, 619 {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0}, 620 {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, 621 {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, 622 {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0}, 623 {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE}, 624 {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST}, 625 {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0}, 626 {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE}, 627 {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST}, 628 {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0}, 629 {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE}, 630 {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST}, 631 {ALDPW, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0}, 632 633 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, 0}, 634 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPRE}, 635 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPOST}, 636 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, 0}, 637 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPRE}, 638 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPOST}, 639 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0}, 640 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE}, 641 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST}, 642 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0}, 643 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE}, 644 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST}, 645 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0}, 646 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE}, 647 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST}, 648 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, 0}, 649 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPRE}, 650 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPOST}, 651 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, 0}, 652 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPRE}, 653 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPOST}, 654 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0}, 655 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE}, 656 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST}, 657 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0}, 658 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE}, 659 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST}, 660 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0}, 661 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE}, 662 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST}, 663 {ASTPW, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0}, 664 665 {ASWPD, C_REG, C_NONE, C_NONE, C_ZOREG, 47, 4, 0, 0, 0}, // RegTo2=C_REG 666 {ASWPD, C_REG, C_NONE, C_NONE, C_ZAUTO, 47, 4, REGSP, 0, 0}, // RegTo2=C_REG 667 {ALDAR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0}, 668 {ALDXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0}, 669 {ALDAXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0}, 670 {ALDXP, C_ZOREG, C_NONE, C_NONE, C_PAIR, 58, 4, 0, 0, 0}, 671 {ASTLR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_NONE 672 {ASTXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG 673 {ASTLXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG 674 {ASTXP, C_PAIR, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, 675 676 /* VLD1/VST1 */ 677 {AVLD1, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0}, 678 {AVLD1, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST}, 679 {AVLD1, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST}, 680 {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST}, 681 {AVLD1, C_ROFF, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST}, 682 {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, 0}, 683 {AVST1, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0}, 684 {AVST1, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST}, 685 {AVST1, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST}, 686 {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, C_XPOST}, 687 {AVST1, C_ELEM, C_NONE, C_NONE, C_ROFF, 96, 4, 0, 0, C_XPOST}, 688 {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, 0}, 689 690 /* special */ 691 {AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0}, 692 {AMRS, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0}, 693 {AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0}, 694 {AMSR, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0}, 695 {AMOVD, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0}, 696 {AMSR, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0}, 697 {APRFM, C_UOREG32K, C_NONE, C_NONE, C_SPR, 91, 4, 0, 0, 0}, 698 {APRFM, C_UOREG32K, C_NONE, C_NONE, C_LCON, 91, 4, 0, 0, 0}, 699 {ADMB, C_VCON, C_NONE, C_NONE, C_NONE, 51, 4, 0, 0, 0}, 700 {AHINT, C_VCON, C_NONE, C_NONE, C_NONE, 52, 4, 0, 0, 0}, 701 {ASYS, C_VCON, C_NONE, C_NONE, C_NONE, 50, 4, 0, 0, 0}, 702 {ASYS, C_VCON, C_REG, C_NONE, C_NONE, 50, 4, 0, 0, 0}, 703 {ASYSL, C_VCON, C_NONE, C_NONE, C_REG, 50, 4, 0, 0, 0}, 704 705 /* encryption instructions */ 706 {AAESD, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0}, // for compatibility with old code 707 {AAESD, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, // recommend using the new one for better readability 708 {ASHA1C, C_VREG, C_REG, C_NONE, C_VREG, 1, 4, 0, 0, 0}, 709 {ASHA1C, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0}, 710 {ASHA1H, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0}, 711 {ASHA1SU0, C_ARNG, C_ARNG, C_NONE, C_ARNG, 1, 4, 0, 0, 0}, 712 {ASHA256H, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0}, 713 {AVREV32, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0}, 714 {AVPMULL, C_ARNG, C_ARNG, C_NONE, C_ARNG, 93, 4, 0, 0, 0}, 715 716 {obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}, 717 {obj.APCDATA, C_VCON, C_NONE, C_NONE, C_VCON, 0, 0, 0, 0, 0}, 718 {obj.AFUNCDATA, C_VCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0, 0, 0}, 719 {obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, 720 {obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL 721 {obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL 722 723 {obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0}, 724 } 725 726 /* 727 * valid pstate field values, and value to use in instruction 728 */ 729 var pstatefield = []struct { 730 reg int16 731 enc uint32 732 }{ 733 {REG_SPSel, 0<<16 | 4<<12 | 5<<5}, 734 {REG_DAIFSet, 3<<16 | 4<<12 | 6<<5}, 735 {REG_DAIFClr, 3<<16 | 4<<12 | 7<<5}, 736 } 737 738 // the System register values, and value to use in instruction 739 var systemreg = []struct { 740 reg int16 741 enc uint32 742 }{ 743 {REG_ELR_EL1, 8<<16 | 4<<12 | 1<<5}, 744 {REG_DCZID_EL0, 3<<19 | 3<<16 | 7<<5}, 745 } 746 747 var prfopfield = []struct { 748 reg int16 749 enc uint32 750 }{ 751 {REG_PLDL1KEEP, 0}, 752 {REG_PLDL1STRM, 1}, 753 {REG_PLDL2KEEP, 2}, 754 {REG_PLDL2STRM, 3}, 755 {REG_PLDL3KEEP, 4}, 756 {REG_PLDL3STRM, 5}, 757 {REG_PLIL1KEEP, 8}, 758 {REG_PLIL1STRM, 9}, 759 {REG_PLIL2KEEP, 10}, 760 {REG_PLIL2STRM, 11}, 761 {REG_PLIL3KEEP, 12}, 762 {REG_PLIL3STRM, 13}, 763 {REG_PSTL1KEEP, 16}, 764 {REG_PSTL1STRM, 17}, 765 {REG_PSTL2KEEP, 18}, 766 {REG_PSTL2STRM, 19}, 767 {REG_PSTL3KEEP, 20}, 768 {REG_PSTL3STRM, 21}, 769 } 770 771 func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { 772 p := cursym.Func.Text 773 if p == nil || p.Link == nil { // handle external functions and ELF section symbols 774 return 775 } 776 777 if oprange[AAND&obj.AMask] == nil { 778 ctxt.Diag("arm64 ops not initialized, call arm64.buildop first") 779 } 780 781 c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset & 0xffffffff), extrasize: int32(p.To.Offset >> 32)} 782 p.To.Offset &= 0xffffffff // extrasize is no longer needed 783 784 bflag := 1 785 pc := int64(0) 786 p.Pc = pc 787 var m int 788 var o *Optab 789 for p = p.Link; p != nil; p = p.Link { 790 if p.As == ADWORD && (pc&7) != 0 { 791 pc += 4 792 } 793 p.Pc = pc 794 o = c.oplook(p) 795 m = int(o.size) 796 if m == 0 { 797 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA { 798 c.ctxt.Diag("zero-width instruction\n%v", p) 799 } 800 continue 801 } 802 803 switch o.flag & (LFROM | LTO) { 804 case LFROM: 805 c.addpool(p, &p.From) 806 807 case LTO: 808 c.addpool(p, &p.To) 809 break 810 } 811 812 if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */ 813 c.checkpool(p, 0) 814 } 815 pc += int64(m) 816 if c.blitrl != nil { 817 c.checkpool(p, 1) 818 } 819 } 820 821 c.cursym.Size = pc 822 823 /* 824 * if any procedure is large enough to 825 * generate a large SBRA branch, then 826 * generate extra passes putting branches 827 * around jmps to fix. this is rare. 828 */ 829 for bflag != 0 { 830 bflag = 0 831 pc = 0 832 for p = c.cursym.Func.Text.Link; p != nil; p = p.Link { 833 if p.As == ADWORD && (pc&7) != 0 { 834 pc += 4 835 } 836 p.Pc = pc 837 o = c.oplook(p) 838 839 /* very large branches */ 840 if (o.type_ == 7 || o.type_ == 39 || o.type_ == 40) && p.Pcond != nil { // 7: BEQ and like, 39: CBZ and like, 40: TBZ and like 841 otxt := p.Pcond.Pc - pc 842 var toofar bool 843 switch o.type_ { 844 case 7, 39: // branch instruction encodes 19 bits 845 toofar = otxt <= -(1<<20)+10 || otxt >= (1<<20)-10 846 case 40: // branch instruction encodes 14 bits 847 toofar = otxt <= -(1<<15)+10 || otxt >= (1<<15)-10 848 } 849 if toofar { 850 q := c.newprog() 851 q.Link = p.Link 852 p.Link = q 853 q.As = AB 854 q.To.Type = obj.TYPE_BRANCH 855 q.Pcond = p.Pcond 856 p.Pcond = q 857 q = c.newprog() 858 q.Link = p.Link 859 p.Link = q 860 q.As = AB 861 q.To.Type = obj.TYPE_BRANCH 862 q.Pcond = q.Link.Link 863 bflag = 1 864 } 865 } 866 m = int(o.size) 867 868 if m == 0 { 869 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA { 870 c.ctxt.Diag("zero-width instruction\n%v", p) 871 } 872 continue 873 } 874 875 pc += int64(m) 876 } 877 } 878 879 pc += -pc & (funcAlign - 1) 880 c.cursym.Size = pc 881 882 /* 883 * lay out the code, emitting code and data relocations. 884 */ 885 c.cursym.Grow(c.cursym.Size) 886 bp := c.cursym.P 887 psz := int32(0) 888 var i int 889 var out [6]uint32 890 for p := c.cursym.Func.Text.Link; p != nil; p = p.Link { 891 c.pc = p.Pc 892 o = c.oplook(p) 893 894 // need to align DWORDs on 8-byte boundary. The ISA doesn't 895 // require it, but the various 64-bit loads we generate assume it. 896 if o.as == ADWORD && psz%8 != 0 { 897 bp[3] = 0 898 bp[2] = bp[3] 899 bp[1] = bp[2] 900 bp[0] = bp[1] 901 bp = bp[4:] 902 psz += 4 903 } 904 905 if int(o.size) > 4*len(out) { 906 log.Fatalf("out array in span7 is too small, need at least %d for %v", o.size/4, p) 907 } 908 c.asmout(p, o, out[:]) 909 for i = 0; i < int(o.size/4); i++ { 910 c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i]) 911 bp = bp[4:] 912 psz += 4 913 } 914 } 915 } 916 917 /* 918 * when the first reference to the literal pool threatens 919 * to go out of range of a 1Mb PC-relative offset 920 * drop the pool now, and branch round it. 921 */ 922 func (c *ctxt7) checkpool(p *obj.Prog, skip int) { 923 if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) { 924 c.flushpool(p, skip) 925 } else if p.Link == nil { 926 c.flushpool(p, 2) 927 } 928 } 929 930 func (c *ctxt7) flushpool(p *obj.Prog, skip int) { 931 if c.blitrl != nil { 932 if skip != 0 { 933 if c.ctxt.Debugvlog && skip == 1 { 934 fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start) 935 } 936 q := c.newprog() 937 q.As = AB 938 q.To.Type = obj.TYPE_BRANCH 939 q.Pcond = p.Link 940 q.Link = c.blitrl 941 q.Pos = p.Pos 942 c.blitrl = q 943 } else if p.Pc+int64(c.pool.size)-int64(c.pool.start) < maxPCDisp { 944 return 945 } 946 947 // The line number for constant pool entries doesn't really matter. 948 // We set it to the line number of the preceding instruction so that 949 // there are no deltas to encode in the pc-line tables. 950 for q := c.blitrl; q != nil; q = q.Link { 951 q.Pos = p.Pos 952 } 953 954 c.elitrl.Link = p.Link 955 p.Link = c.blitrl 956 957 c.blitrl = nil /* BUG: should refer back to values until out-of-range */ 958 c.elitrl = nil 959 c.pool.size = 0 960 c.pool.start = 0 961 } 962 } 963 964 /* 965 * MOVD foo(SB), R is actually 966 * MOVD addr, REGTMP 967 * MOVD REGTMP, R 968 * where addr is the address of the DWORD containing the address of foo. 969 * 970 * TODO: hash 971 */ 972 func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) { 973 cls := c.aclass(a) 974 lit := c.instoffset 975 t := c.newprog() 976 t.As = AWORD 977 sz := 4 978 979 if a.Type == obj.TYPE_CONST { 980 if lit != int64(int32(lit)) && uint64(lit) != uint64(uint32(lit)) { 981 // out of range -0x80000000 ~ 0xffffffff, must store 64-bit 982 t.As = ADWORD 983 sz = 8 984 } // else store 32-bit 985 } else if p.As == AMOVD && a.Type != obj.TYPE_MEM || cls == C_ADDR || cls == C_VCON || lit != int64(int32(lit)) || uint64(lit) != uint64(uint32(lit)) { 986 // conservative: don't know if we want signed or unsigned extension. 987 // in case of ambiguity, store 64-bit 988 t.As = ADWORD 989 sz = 8 990 } 991 992 switch cls { 993 // TODO(aram): remove. 994 default: 995 if a.Name != obj.NAME_EXTERN { 996 fmt.Printf("addpool: %v in %v shouldn't go to default case\n", DRconv(cls), p) 997 } 998 999 t.To.Offset = a.Offset 1000 t.To.Sym = a.Sym 1001 t.To.Type = a.Type 1002 t.To.Name = a.Name 1003 1004 /* This is here because MOV uint12<<12, R is disabled in optab. 1005 Because of this, we need to load the constant from memory. */ 1006 case C_ADDCON: 1007 fallthrough 1008 1009 case C_ZAUTO, 1010 C_PSAUTO, 1011 C_PSAUTO_8, 1012 C_PSAUTO_4, 1013 C_PPAUTO, 1014 C_UAUTO4K_8, 1015 C_UAUTO4K_4, 1016 C_UAUTO4K_2, 1017 C_UAUTO4K, 1018 C_UAUTO8K_8, 1019 C_UAUTO8K_4, 1020 C_UAUTO8K, 1021 C_UAUTO16K_8, 1022 C_UAUTO16K, 1023 C_UAUTO32K, 1024 C_NSAUTO_8, 1025 C_NSAUTO_4, 1026 C_NSAUTO, 1027 C_NPAUTO, 1028 C_NAUTO4K, 1029 C_LAUTO, 1030 C_PPOREG, 1031 C_PSOREG, 1032 C_PSOREG_4, 1033 C_PSOREG_8, 1034 C_UOREG4K_8, 1035 C_UOREG4K_4, 1036 C_UOREG4K_2, 1037 C_UOREG4K, 1038 C_UOREG8K_8, 1039 C_UOREG8K_4, 1040 C_UOREG8K, 1041 C_UOREG16K_8, 1042 C_UOREG16K, 1043 C_UOREG32K, 1044 C_NSOREG_8, 1045 C_NSOREG_4, 1046 C_NSOREG, 1047 C_NPOREG, 1048 C_NOREG4K, 1049 C_LOREG, 1050 C_LACON, 1051 C_ADDCON2, 1052 C_LCON, 1053 C_VCON: 1054 if a.Name == obj.NAME_EXTERN { 1055 fmt.Printf("addpool: %v in %v needs reloc\n", DRconv(cls), p) 1056 } 1057 1058 t.To.Type = obj.TYPE_CONST 1059 t.To.Offset = lit 1060 break 1061 } 1062 1063 for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */ 1064 if q.To == t.To { 1065 p.Pcond = q 1066 return 1067 } 1068 } 1069 1070 q := c.newprog() 1071 *q = *t 1072 q.Pc = int64(c.pool.size) 1073 if c.blitrl == nil { 1074 c.blitrl = q 1075 c.pool.start = uint32(p.Pc) 1076 } else { 1077 c.elitrl.Link = q 1078 } 1079 c.elitrl = q 1080 c.pool.size = -c.pool.size & (funcAlign - 1) 1081 c.pool.size += uint32(sz) 1082 p.Pcond = q 1083 } 1084 1085 func (c *ctxt7) regoff(a *obj.Addr) uint32 { 1086 c.instoffset = 0 1087 c.aclass(a) 1088 return uint32(c.instoffset) 1089 } 1090 1091 func isSTLXRop(op obj.As) bool { 1092 switch op { 1093 case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH, 1094 ASTXR, ASTXRW, ASTXRB, ASTXRH: 1095 return true 1096 } 1097 return false 1098 } 1099 1100 func isSTXPop(op obj.As) bool { 1101 switch op { 1102 case ASTXP, ASTLXP, ASTXPW, ASTLXPW: 1103 return true 1104 } 1105 return false 1106 } 1107 1108 func isANDWop(op obj.As) bool { 1109 switch op { 1110 case AANDW, AORRW, AEORW, AANDSW, ATSTW, 1111 ABICW, AEONW, AORNW, ABICSW: 1112 return true 1113 } 1114 return false 1115 } 1116 1117 func isADDWop(op obj.As) bool { 1118 switch op { 1119 case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW: 1120 return true 1121 } 1122 return false 1123 } 1124 1125 func isRegShiftOrExt(a *obj.Addr) bool { 1126 return (a.Index-obj.RBaseARM64)®_EXT != 0 || (a.Index-obj.RBaseARM64)®_LSL != 0 1127 } 1128 1129 // Maximum PC-relative displacement. 1130 // The actual limit is ±2²⁰, but we are conservative 1131 // to avoid needing to recompute the literal pool flush points 1132 // as span-dependent jumps are enlarged. 1133 const maxPCDisp = 512 * 1024 1134 1135 // ispcdisp reports whether v is a valid PC-relative displacement. 1136 func ispcdisp(v int32) bool { 1137 return -maxPCDisp < v && v < maxPCDisp && v&3 == 0 1138 } 1139 1140 func isaddcon(v int64) bool { 1141 /* uimm12 or uimm24? */ 1142 if v < 0 { 1143 return false 1144 } 1145 if (v & 0xFFF) == 0 { 1146 v >>= 12 1147 } 1148 return v <= 0xFFF 1149 } 1150 1151 // isbitcon returns whether a constant can be encoded into a logical instruction. 1152 // bitcon has a binary form of repetition of a bit sequence of length 2, 4, 8, 16, 32, or 64, 1153 // which itself is a rotate (w.r.t. the length of the unit) of a sequence of ones. 1154 // special cases: 0 and -1 are not bitcon. 1155 // this function needs to run against virtually all the constants, so it needs to be fast. 1156 // for this reason, bitcon testing and bitcon encoding are separate functions. 1157 func isbitcon(x uint64) bool { 1158 if x == 1<<64-1 || x == 0 { 1159 return false 1160 } 1161 // determine the period and sign-extend a unit to 64 bits 1162 switch { 1163 case x != x>>32|x<<32: 1164 // period is 64 1165 // nothing to do 1166 case x != x>>16|x<<48: 1167 // period is 32 1168 x = uint64(int64(int32(x))) 1169 case x != x>>8|x<<56: 1170 // period is 16 1171 x = uint64(int64(int16(x))) 1172 case x != x>>4|x<<60: 1173 // period is 8 1174 x = uint64(int64(int8(x))) 1175 default: 1176 // period is 4 or 2, always true 1177 // 0001, 0010, 0100, 1000 -- 0001 rotate 1178 // 0011, 0110, 1100, 1001 -- 0011 rotate 1179 // 0111, 1011, 1101, 1110 -- 0111 rotate 1180 // 0101, 1010 -- 01 rotate, repeat 1181 return true 1182 } 1183 return sequenceOfOnes(x) || sequenceOfOnes(^x) 1184 } 1185 1186 // sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros 1187 func sequenceOfOnes(x uint64) bool { 1188 y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2 1189 y += x 1190 return (y-1)&y == 0 1191 } 1192 1193 // bitconEncode returns the encoding of a bitcon used in logical instructions 1194 // x is known to be a bitcon 1195 // a bitcon is a sequence of n ones at low bits (i.e. 1<<n-1), right rotated 1196 // by R bits, and repeated with period of 64, 32, 16, 8, 4, or 2. 1197 // it is encoded in logical instructions with 3 bitfields 1198 // N (1 bit) : R (6 bits) : S (6 bits), where 1199 // N=1 -- period=64 1200 // N=0, S=0xxxxx -- period=32 1201 // N=0, S=10xxxx -- period=16 1202 // N=0, S=110xxx -- period=8 1203 // N=0, S=1110xx -- period=4 1204 // N=0, S=11110x -- period=2 1205 // R is the shift amount, low bits of S = n-1 1206 func bitconEncode(x uint64, mode int) uint32 { 1207 var period uint32 1208 // determine the period and sign-extend a unit to 64 bits 1209 switch { 1210 case x != x>>32|x<<32: 1211 period = 64 1212 case x != x>>16|x<<48: 1213 period = 32 1214 x = uint64(int64(int32(x))) 1215 case x != x>>8|x<<56: 1216 period = 16 1217 x = uint64(int64(int16(x))) 1218 case x != x>>4|x<<60: 1219 period = 8 1220 x = uint64(int64(int8(x))) 1221 case x != x>>2|x<<62: 1222 period = 4 1223 x = uint64(int64(x<<60) >> 60) 1224 default: 1225 period = 2 1226 x = uint64(int64(x<<62) >> 62) 1227 } 1228 neg := false 1229 if int64(x) < 0 { 1230 x = ^x 1231 neg = true 1232 } 1233 y := x & -x // lowest set bit of x. 1234 s := log2(y) 1235 n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits 1236 if neg { 1237 // ^x is a sequence of n ones left shifted by s bits 1238 // adjust n, s for x 1239 s = n + s 1240 n = period - n 1241 } 1242 1243 N := uint32(0) 1244 if mode == 64 && period == 64 { 1245 N = 1 1246 } 1247 R := (period - s) & (period - 1) & uint32(mode-1) // shift amount of right rotate 1248 S := (n - 1) | 63&^(period<<1-1) // low bits = #ones - 1, high bits encodes period 1249 return N<<22 | R<<16 | S<<10 1250 } 1251 1252 func log2(x uint64) uint32 { 1253 if x == 0 { 1254 panic("log2 of 0") 1255 } 1256 n := uint32(0) 1257 if x >= 1<<32 { 1258 x >>= 32 1259 n += 32 1260 } 1261 if x >= 1<<16 { 1262 x >>= 16 1263 n += 16 1264 } 1265 if x >= 1<<8 { 1266 x >>= 8 1267 n += 8 1268 } 1269 if x >= 1<<4 { 1270 x >>= 4 1271 n += 4 1272 } 1273 if x >= 1<<2 { 1274 x >>= 2 1275 n += 2 1276 } 1277 if x >= 1<<1 { 1278 x >>= 1 1279 n += 1 1280 } 1281 return n 1282 } 1283 1284 func autoclass(l int64) int { 1285 if l == 0 { 1286 return C_ZAUTO 1287 } 1288 1289 if l < 0 { 1290 if l >= -256 && (l&7) == 0 { 1291 return C_NSAUTO_8 1292 } 1293 if l >= -256 && (l&3) == 0 { 1294 return C_NSAUTO_4 1295 } 1296 if l >= -256 { 1297 return C_NSAUTO 1298 } 1299 if l >= -512 && (l&7) == 0 { 1300 return C_NPAUTO 1301 } 1302 if l >= -4095 { 1303 return C_NAUTO4K 1304 } 1305 return C_LAUTO 1306 } 1307 1308 if l <= 255 { 1309 if (l & 7) == 0 { 1310 return C_PSAUTO_8 1311 } 1312 if (l & 3) == 0 { 1313 return C_PSAUTO_4 1314 } 1315 return C_PSAUTO 1316 } 1317 if l <= 504 && l&7 == 0 { 1318 return C_PPAUTO 1319 } 1320 if l <= 4095 { 1321 if l&7 == 0 { 1322 return C_UAUTO4K_8 1323 } 1324 if l&3 == 0 { 1325 return C_UAUTO4K_4 1326 } 1327 if l&1 == 0 { 1328 return C_UAUTO4K_2 1329 } 1330 return C_UAUTO4K 1331 } 1332 if l <= 8190 { 1333 if l&7 == 0 { 1334 return C_UAUTO8K_8 1335 } 1336 if l&3 == 0 { 1337 return C_UAUTO8K_4 1338 } 1339 if l&1 == 0 { 1340 return C_UAUTO8K 1341 } 1342 } 1343 if l <= 16380 { 1344 if l&7 == 0 { 1345 return C_UAUTO16K_8 1346 } 1347 if l&3 == 0 { 1348 return C_UAUTO16K 1349 } 1350 } 1351 if l <= 32760 && (l&7) == 0 { 1352 return C_UAUTO32K 1353 } 1354 return C_LAUTO 1355 } 1356 1357 func oregclass(l int64) int { 1358 return autoclass(l) - C_ZAUTO + C_ZOREG 1359 } 1360 1361 /* 1362 * given an offset v and a class c (see above) 1363 * return the offset value to use in the instruction, 1364 * scaled if necessary 1365 */ 1366 func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 { 1367 s := 0 1368 if cls >= C_SEXT1 && cls <= C_SEXT16 { 1369 s = cls - C_SEXT1 1370 } else { 1371 switch cls { 1372 case C_UAUTO4K, C_UOREG4K, C_ZOREG: 1373 s = 0 1374 case C_UAUTO8K, C_UOREG8K: 1375 s = 1 1376 case C_UAUTO16K, C_UOREG16K: 1377 s = 2 1378 case C_UAUTO32K, C_UOREG32K: 1379 s = 3 1380 default: 1381 c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p) 1382 } 1383 } 1384 vs := v >> uint(s) 1385 if vs<<uint(s) != v { 1386 c.ctxt.Diag("odd offset: %d\n%v", v, p) 1387 } 1388 return vs 1389 } 1390 1391 /* 1392 * if v contains a single 16-bit value aligned 1393 * on a 16-bit field, and thus suitable for movk/movn, 1394 * return the field index 0 to 3; otherwise return -1 1395 */ 1396 func movcon(v int64) int { 1397 for s := 0; s < 64; s += 16 { 1398 if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 { 1399 return s / 16 1400 } 1401 } 1402 return -1 1403 } 1404 1405 func rclass(r int16) int { 1406 switch { 1407 case REG_R0 <= r && r <= REG_R30: // not 31 1408 return C_REG 1409 case r == REGZERO: 1410 return C_ZCON 1411 case REG_F0 <= r && r <= REG_F31: 1412 return C_FREG 1413 case REG_V0 <= r && r <= REG_V31: 1414 return C_VREG 1415 case COND_EQ <= r && r <= COND_NV: 1416 return C_COND 1417 case r == REGSP: 1418 return C_RSP 1419 case r >= REG_ARNG && r < REG_ELEM: 1420 return C_ARNG 1421 case r >= REG_ELEM && r < REG_ELEM_END: 1422 return C_ELEM 1423 case r >= REG_UXTB && r < REG_SPECIAL: 1424 return C_EXTREG 1425 case r >= REG_SPECIAL: 1426 return C_SPR 1427 } 1428 return C_GOK 1429 } 1430 1431 // con32class reclassifies the constant of 32-bit instruction. Becuase the constant type is 32-bit, 1432 // but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it. 1433 func (c *ctxt7) con32class(a *obj.Addr) int { 1434 v := uint32(a.Offset) 1435 if v == 0 { 1436 return C_ZCON 1437 } 1438 if isaddcon(int64(v)) { 1439 if v <= 0xFFF { 1440 if isbitcon(uint64(v)) { 1441 return C_ABCON0 1442 } 1443 return C_ADDCON0 1444 } 1445 if isbitcon(uint64(v)) { 1446 return C_ABCON 1447 } 1448 return C_ADDCON 1449 } 1450 1451 t := movcon(int64(v)) 1452 if t >= 0 { 1453 if isbitcon(uint64(v)) { 1454 return C_MBCON 1455 } 1456 return C_MOVCON 1457 } 1458 1459 t = movcon(int64(^v)) 1460 if t >= 0 { 1461 if isbitcon(uint64(v)) { 1462 return C_MBCON 1463 } 1464 return C_MOVCON 1465 } 1466 1467 if isbitcon(uint64(v)) { 1468 return C_BITCON 1469 } 1470 1471 if 0 <= v && v <= 0xffffff { 1472 return C_ADDCON2 1473 } 1474 return C_LCON 1475 } 1476 1477 func (c *ctxt7) aclass(a *obj.Addr) int { 1478 switch a.Type { 1479 case obj.TYPE_NONE: 1480 return C_NONE 1481 1482 case obj.TYPE_REG: 1483 return rclass(a.Reg) 1484 1485 case obj.TYPE_REGREG: 1486 return C_PAIR 1487 1488 case obj.TYPE_SHIFT: 1489 return C_SHIFT 1490 1491 case obj.TYPE_REGLIST: 1492 return C_LIST 1493 1494 case obj.TYPE_MEM: 1495 // The base register should be an integer register. 1496 if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) { 1497 break 1498 } 1499 switch a.Name { 1500 case obj.NAME_EXTERN, obj.NAME_STATIC: 1501 if a.Sym == nil { 1502 break 1503 } 1504 c.instoffset = a.Offset 1505 if a.Sym != nil { // use relocation 1506 if a.Sym.Type == objabi.STLSBSS { 1507 if c.ctxt.Flag_shared { 1508 return C_TLS_IE 1509 } else { 1510 return C_TLS_LE 1511 } 1512 } 1513 return C_ADDR 1514 } 1515 return C_LEXT 1516 1517 case obj.NAME_GOTREF: 1518 return C_GOTADDR 1519 1520 case obj.NAME_AUTO: 1521 if a.Reg == REGSP { 1522 // unset base register for better printing, since 1523 // a.Offset is still relative to pseudo-SP. 1524 a.Reg = obj.REG_NONE 1525 } 1526 // The frame top 8 or 16 bytes are for FP 1527 c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize) 1528 return autoclass(c.instoffset) 1529 1530 case obj.NAME_PARAM: 1531 if a.Reg == REGSP { 1532 // unset base register for better printing, since 1533 // a.Offset is still relative to pseudo-FP. 1534 a.Reg = obj.REG_NONE 1535 } 1536 c.instoffset = int64(c.autosize) + a.Offset + 8 1537 return autoclass(c.instoffset) 1538 1539 case obj.NAME_NONE: 1540 if a.Index != 0 { 1541 if a.Offset != 0 { 1542 if isRegShiftOrExt(a) { 1543 // extended or shifted register offset, (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2). 1544 return C_ROFF 1545 } 1546 return C_GOK 1547 } 1548 // register offset, (Rn)(Rm) 1549 return C_ROFF 1550 } 1551 c.instoffset = a.Offset 1552 return oregclass(c.instoffset) 1553 } 1554 return C_GOK 1555 1556 case obj.TYPE_FCONST: 1557 return C_FCON 1558 1559 case obj.TYPE_TEXTSIZE: 1560 return C_TEXTSIZE 1561 1562 case obj.TYPE_CONST, obj.TYPE_ADDR: 1563 switch a.Name { 1564 case obj.NAME_NONE: 1565 c.instoffset = a.Offset 1566 if a.Reg != 0 && a.Reg != REGZERO { 1567 break 1568 } 1569 v := c.instoffset 1570 if v == 0 { 1571 return C_ZCON 1572 } 1573 if isaddcon(v) { 1574 if v <= 0xFFF { 1575 if isbitcon(uint64(v)) { 1576 return C_ABCON0 1577 } 1578 return C_ADDCON0 1579 } 1580 if isbitcon(uint64(v)) { 1581 return C_ABCON 1582 } 1583 if movcon(v) >= 0 { 1584 return C_AMCON 1585 } 1586 if movcon(^v) >= 0 { 1587 return C_AMCON 1588 } 1589 return C_ADDCON 1590 } 1591 1592 t := movcon(v) 1593 if t >= 0 { 1594 if isbitcon(uint64(v)) { 1595 return C_MBCON 1596 } 1597 return C_MOVCON 1598 } 1599 1600 t = movcon(^v) 1601 if t >= 0 { 1602 if isbitcon(uint64(v)) { 1603 return C_MBCON 1604 } 1605 return C_MOVCON 1606 } 1607 1608 if isbitcon(uint64(v)) { 1609 return C_BITCON 1610 } 1611 1612 if 0 <= v && v <= 0xffffff { 1613 return C_ADDCON2 1614 } 1615 1616 if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) { 1617 return C_LCON 1618 } 1619 return C_VCON 1620 1621 case obj.NAME_EXTERN, obj.NAME_STATIC: 1622 if a.Sym == nil { 1623 return C_GOK 1624 } 1625 if a.Sym.Type == objabi.STLSBSS { 1626 c.ctxt.Diag("taking address of TLS variable is not supported") 1627 } 1628 c.instoffset = a.Offset 1629 return C_VCONADDR 1630 1631 case obj.NAME_AUTO: 1632 if a.Reg == REGSP { 1633 // unset base register for better printing, since 1634 // a.Offset is still relative to pseudo-SP. 1635 a.Reg = obj.REG_NONE 1636 } 1637 // The frame top 8 or 16 bytes are for FP 1638 c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize) 1639 1640 case obj.NAME_PARAM: 1641 if a.Reg == REGSP { 1642 // unset base register for better printing, since 1643 // a.Offset is still relative to pseudo-FP. 1644 a.Reg = obj.REG_NONE 1645 } 1646 c.instoffset = int64(c.autosize) + a.Offset + 8 1647 default: 1648 return C_GOK 1649 } 1650 1651 if isaddcon(c.instoffset) { 1652 return C_AACON 1653 } 1654 return C_LACON 1655 1656 case obj.TYPE_BRANCH: 1657 return C_SBRA 1658 } 1659 1660 return C_GOK 1661 } 1662 1663 func oclass(a *obj.Addr) int { 1664 return int(a.Class) - 1 1665 } 1666 1667 func (c *ctxt7) oplook(p *obj.Prog) *Optab { 1668 a1 := int(p.Optab) 1669 if a1 != 0 { 1670 return &optab[a1-1] 1671 } 1672 a1 = int(p.From.Class) 1673 if a1 == 0 { 1674 a0 := c.aclass(&p.From) 1675 // do not break C_ADDCON2 when S bit is set 1676 if (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) && a0 == C_ADDCON2 { 1677 a0 = C_LCON 1678 } 1679 a1 = a0 + 1 1680 p.From.Class = int8(a1) 1681 // more specific classification of 32-bit integers 1682 if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE { 1683 if p.As == AMOVW || isADDWop(p.As) { 1684 ra0 := c.con32class(&p.From) 1685 // do not break C_ADDCON2 when S bit is set 1686 if (p.As == AADDSW || p.As == ASUBSW) && ra0 == C_ADDCON2 { 1687 ra0 = C_LCON 1688 } 1689 a1 = ra0 + 1 1690 p.From.Class = int8(a1) 1691 } 1692 if isANDWop(p.As) { 1693 switch p.As { 1694 case AANDW, AORRW, AEORW, AANDSW, ATSTW: 1695 // For 32-bit logical instruction with constant, 1696 // rewrite the high 32-bit to be a copy of the low 1697 // 32-bit, so that the BITCON test can be shared 1698 // for both 32-bit and 64-bit. 1699 if a0 == C_BITCON { 1700 break 1701 } 1702 fallthrough 1703 default: 1704 a1 = c.con32class(&p.From) + 1 1705 p.From.Class = int8(a1) 1706 } 1707 } 1708 } 1709 } 1710 1711 a1-- 1712 a3 := C_NONE + 1 1713 if p.GetFrom3() != nil { 1714 a3 = int(p.GetFrom3().Class) 1715 if a3 == 0 { 1716 a3 = c.aclass(p.GetFrom3()) + 1 1717 p.GetFrom3().Class = int8(a3) 1718 } 1719 } 1720 1721 a3-- 1722 a4 := int(p.To.Class) 1723 if a4 == 0 { 1724 a4 = c.aclass(&p.To) + 1 1725 p.To.Class = int8(a4) 1726 } 1727 1728 a4-- 1729 a2 := C_NONE 1730 if p.Reg != 0 { 1731 a2 = rclass(p.Reg) 1732 } 1733 1734 if false { 1735 fmt.Printf("oplook %v %d %d %d %d\n", p.As, a1, a2, a3, a4) 1736 fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type) 1737 } 1738 1739 ops := oprange[p.As&obj.AMask] 1740 c1 := &xcmp[a1] 1741 c2 := &xcmp[a2] 1742 c3 := &xcmp[a3] 1743 c4 := &xcmp[a4] 1744 c5 := &xcmp[p.Scond>>5] 1745 for i := range ops { 1746 op := &ops[i] 1747 if (int(op.a2) == a2 || c2[op.a2]) && c5[op.scond>>5] && c1[op.a1] && c3[op.a3] && c4[op.a4] { 1748 p.Optab = uint16(cap(optab) - cap(ops) + i + 1) 1749 return op 1750 } 1751 } 1752 1753 c.ctxt.Diag("illegal combination: %v %v %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4), p.From.Type, p.To.Type) 1754 // Turn illegal instruction into an UNDEF, avoid crashing in asmout 1755 return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0} 1756 } 1757 1758 func cmp(a int, b int) bool { 1759 if a == b { 1760 return true 1761 } 1762 switch a { 1763 case C_RSP: 1764 if b == C_REG { 1765 return true 1766 } 1767 1768 case C_REG: 1769 if b == C_ZCON { 1770 return true 1771 } 1772 1773 case C_ADDCON0: 1774 if b == C_ZCON || b == C_ABCON0 { 1775 return true 1776 } 1777 1778 case C_ADDCON: 1779 if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON { 1780 return true 1781 } 1782 1783 case C_BITCON: 1784 if b == C_ABCON0 || b == C_ABCON || b == C_MBCON { 1785 return true 1786 } 1787 1788 case C_MOVCON: 1789 if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_AMCON { 1790 return true 1791 } 1792 1793 case C_ADDCON2: 1794 if b == C_ZCON || b == C_ADDCON || b == C_ADDCON0 { 1795 return true 1796 } 1797 1798 case C_LCON: 1799 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 || b == C_ADDCON2 || b == C_AMCON { 1800 return true 1801 } 1802 1803 case C_VCON: 1804 return cmp(C_LCON, b) 1805 1806 case C_LACON: 1807 if b == C_AACON { 1808 return true 1809 } 1810 1811 case C_SEXT2: 1812 if b == C_SEXT1 { 1813 return true 1814 } 1815 1816 case C_SEXT4: 1817 if b == C_SEXT1 || b == C_SEXT2 { 1818 return true 1819 } 1820 1821 case C_SEXT8: 1822 if b >= C_SEXT1 && b <= C_SEXT4 { 1823 return true 1824 } 1825 1826 case C_SEXT16: 1827 if b >= C_SEXT1 && b <= C_SEXT8 { 1828 return true 1829 } 1830 1831 case C_LEXT: 1832 if b >= C_SEXT1 && b <= C_SEXT16 { 1833 return true 1834 } 1835 1836 case C_NSAUTO_4: 1837 if b == C_NSAUTO_8 { 1838 return true 1839 } 1840 1841 case C_NSAUTO: 1842 switch b { 1843 case C_NSAUTO_4, C_NSAUTO_8: 1844 return true 1845 } 1846 1847 case C_NPAUTO: 1848 switch b { 1849 case C_NSAUTO_8: 1850 return true 1851 } 1852 1853 case C_NAUTO4K: 1854 switch b { 1855 case C_NSAUTO_8, C_NSAUTO_4, C_NSAUTO, C_NPAUTO: 1856 return true 1857 } 1858 1859 case C_PSAUTO_8: 1860 if b == C_ZAUTO { 1861 return true 1862 } 1863 1864 case C_PSAUTO_4: 1865 switch b { 1866 case C_ZAUTO, C_PSAUTO_8: 1867 return true 1868 } 1869 1870 case C_PSAUTO: 1871 switch b { 1872 case C_ZAUTO, C_PSAUTO_8, C_PSAUTO_4: 1873 return true 1874 } 1875 1876 case C_PPAUTO: 1877 switch b { 1878 case C_ZAUTO, C_PSAUTO_8: 1879 return true 1880 } 1881 1882 case C_UAUTO4K: 1883 switch b { 1884 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, 1885 C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8: 1886 return true 1887 } 1888 1889 case C_UAUTO8K: 1890 switch b { 1891 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, 1892 C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8: 1893 return true 1894 } 1895 1896 case C_UAUTO16K: 1897 switch b { 1898 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, 1899 C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO16K_8: 1900 return true 1901 } 1902 1903 case C_UAUTO32K: 1904 switch b { 1905 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, 1906 C_PPAUTO, C_UAUTO4K_8, C_UAUTO8K_8, C_UAUTO16K_8: 1907 return true 1908 } 1909 1910 case C_LAUTO: 1911 switch b { 1912 case C_ZAUTO, C_NSAUTO, C_NSAUTO_4, C_NSAUTO_8, C_NPAUTO, 1913 C_NAUTO4K, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, 1914 C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, 1915 C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8, 1916 C_UAUTO16K, C_UAUTO16K_8, 1917 C_UAUTO32K: 1918 return true 1919 } 1920 1921 case C_NSOREG_4: 1922 if b == C_NSOREG_8 { 1923 return true 1924 } 1925 1926 case C_NSOREG: 1927 switch b { 1928 case C_NSOREG_4, C_NSOREG_8: 1929 return true 1930 } 1931 1932 case C_NPOREG: 1933 switch b { 1934 case C_NSOREG_8: 1935 return true 1936 } 1937 1938 case C_NOREG4K: 1939 switch b { 1940 case C_NSOREG_8, C_NSOREG_4, C_NSOREG, C_NPOREG: 1941 return true 1942 } 1943 1944 case C_PSOREG_4: 1945 switch b { 1946 case C_ZOREG, C_PSOREG_8: 1947 return true 1948 } 1949 1950 case C_PSOREG: 1951 switch b { 1952 case C_ZOREG, C_PSOREG_8, C_PSOREG_4: 1953 return true 1954 } 1955 1956 case C_PPOREG: 1957 switch b { 1958 case C_ZOREG, C_PSOREG_8: 1959 return true 1960 } 1961 1962 case C_UOREG4K: 1963 switch b { 1964 case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG, 1965 C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8: 1966 return true 1967 } 1968 1969 case C_UOREG8K: 1970 switch b { 1971 case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG, 1972 C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, 1973 C_UOREG8K_4, C_UOREG8K_8: 1974 return true 1975 } 1976 1977 case C_UOREG16K: 1978 switch b { 1979 case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG, 1980 C_PPOREG, C_UOREG4K_4, C_UOREG4K_8, C_UOREG8K_4, 1981 C_UOREG8K_8, C_UOREG16K_8: 1982 return true 1983 } 1984 1985 case C_UOREG32K: 1986 switch b { 1987 case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG, 1988 C_PPOREG, C_UOREG4K_8, C_UOREG8K_8, C_UOREG16K_8: 1989 return true 1990 } 1991 1992 case C_LOREG: 1993 switch b { 1994 case C_ZOREG, C_NSOREG, C_NSOREG_4, C_NSOREG_8, C_NPOREG, 1995 C_NOREG4K, C_PSOREG_4, C_PSOREG_8, C_PSOREG, C_PPOREG, 1996 C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, 1997 C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8, 1998 C_UOREG16K, C_UOREG16K_8, 1999 C_UOREG32K: 2000 return true 2001 } 2002 2003 case C_LBRA: 2004 if b == C_SBRA { 2005 return true 2006 } 2007 } 2008 2009 return false 2010 } 2011 2012 type ocmp []Optab 2013 2014 func (x ocmp) Len() int { 2015 return len(x) 2016 } 2017 2018 func (x ocmp) Swap(i, j int) { 2019 x[i], x[j] = x[j], x[i] 2020 } 2021 2022 func (x ocmp) Less(i, j int) bool { 2023 p1 := &x[i] 2024 p2 := &x[j] 2025 if p1.as != p2.as { 2026 return p1.as < p2.as 2027 } 2028 if p1.a1 != p2.a1 { 2029 return p1.a1 < p2.a1 2030 } 2031 if p1.a2 != p2.a2 { 2032 return p1.a2 < p2.a2 2033 } 2034 if p1.a3 != p2.a3 { 2035 return p1.a3 < p2.a3 2036 } 2037 if p1.a4 != p2.a4 { 2038 return p1.a4 < p2.a4 2039 } 2040 if p1.scond != p2.scond { 2041 return p1.scond < p2.scond 2042 } 2043 return false 2044 } 2045 2046 func oprangeset(a obj.As, t []Optab) { 2047 oprange[a&obj.AMask] = t 2048 } 2049 2050 func buildop(ctxt *obj.Link) { 2051 if oprange[AAND&obj.AMask] != nil { 2052 // Already initialized; stop now. 2053 // This happens in the cmd/asm tests, 2054 // each of which re-initializes the arch. 2055 return 2056 } 2057 2058 var n int 2059 for i := 0; i < C_GOK; i++ { 2060 for n = 0; n < C_GOK; n++ { 2061 if cmp(n, i) { 2062 xcmp[i][n] = true 2063 } 2064 } 2065 } 2066 for n = 0; optab[n].as != obj.AXXX; n++ { 2067 } 2068 sort.Sort(ocmp(optab[:n])) 2069 for i := 0; i < n; i++ { 2070 r := optab[i].as 2071 start := i 2072 for optab[i].as == r { 2073 i++ 2074 } 2075 t := optab[start:i] 2076 i-- 2077 oprangeset(r, t) 2078 switch r { 2079 default: 2080 ctxt.Diag("unknown op in build: %v", r) 2081 ctxt.DiagFlush() 2082 log.Fatalf("bad code") 2083 2084 case AADD: 2085 oprangeset(AADDS, t) 2086 oprangeset(ASUB, t) 2087 oprangeset(ASUBS, t) 2088 oprangeset(AADDW, t) 2089 oprangeset(AADDSW, t) 2090 oprangeset(ASUBW, t) 2091 oprangeset(ASUBSW, t) 2092 2093 case AAND: /* logical immediate, logical shifted register */ 2094 oprangeset(AANDW, t) 2095 oprangeset(AEOR, t) 2096 oprangeset(AEORW, t) 2097 oprangeset(AORR, t) 2098 oprangeset(AORRW, t) 2099 oprangeset(ABIC, t) 2100 oprangeset(ABICW, t) 2101 oprangeset(AEON, t) 2102 oprangeset(AEONW, t) 2103 oprangeset(AORN, t) 2104 oprangeset(AORNW, t) 2105 2106 case AANDS: /* logical immediate, logical shifted register, set flags, cannot target RSP */ 2107 oprangeset(AANDSW, t) 2108 oprangeset(ABICS, t) 2109 oprangeset(ABICSW, t) 2110 2111 case ANEG: 2112 oprangeset(ANEGS, t) 2113 oprangeset(ANEGSW, t) 2114 oprangeset(ANEGW, t) 2115 2116 case AADC: /* rn=Rd */ 2117 oprangeset(AADCW, t) 2118 2119 oprangeset(AADCS, t) 2120 oprangeset(AADCSW, t) 2121 oprangeset(ASBC, t) 2122 oprangeset(ASBCW, t) 2123 oprangeset(ASBCS, t) 2124 oprangeset(ASBCSW, t) 2125 2126 case ANGC: /* rn=REGZERO */ 2127 oprangeset(ANGCW, t) 2128 2129 oprangeset(ANGCS, t) 2130 oprangeset(ANGCSW, t) 2131 2132 case ACMP: 2133 oprangeset(ACMPW, t) 2134 oprangeset(ACMN, t) 2135 oprangeset(ACMNW, t) 2136 2137 case ATST: 2138 oprangeset(ATSTW, t) 2139 2140 /* register/register, and shifted */ 2141 case AMVN: 2142 oprangeset(AMVNW, t) 2143 2144 case AMOVK: 2145 oprangeset(AMOVKW, t) 2146 oprangeset(AMOVN, t) 2147 oprangeset(AMOVNW, t) 2148 oprangeset(AMOVZ, t) 2149 oprangeset(AMOVZW, t) 2150 2151 case ASWPD: 2152 oprangeset(ASWPALD, t) 2153 oprangeset(ASWPB, t) 2154 oprangeset(ASWPH, t) 2155 oprangeset(ASWPW, t) 2156 oprangeset(ASWPALB, t) 2157 oprangeset(ASWPALH, t) 2158 oprangeset(ASWPALW, t) 2159 oprangeset(ALDADDALB, t) 2160 oprangeset(ALDADDALH, t) 2161 oprangeset(ALDADDALW, t) 2162 oprangeset(ALDADDALD, t) 2163 oprangeset(ALDADDB, t) 2164 oprangeset(ALDADDH, t) 2165 oprangeset(ALDADDW, t) 2166 oprangeset(ALDADDD, t) 2167 oprangeset(ALDANDB, t) 2168 oprangeset(ALDANDH, t) 2169 oprangeset(ALDANDW, t) 2170 oprangeset(ALDANDD, t) 2171 oprangeset(ALDEORB, t) 2172 oprangeset(ALDEORH, t) 2173 oprangeset(ALDEORW, t) 2174 oprangeset(ALDEORD, t) 2175 oprangeset(ALDORB, t) 2176 oprangeset(ALDORH, t) 2177 oprangeset(ALDORW, t) 2178 oprangeset(ALDORD, t) 2179 2180 case ABEQ: 2181 oprangeset(ABNE, t) 2182 oprangeset(ABCS, t) 2183 oprangeset(ABHS, t) 2184 oprangeset(ABCC, t) 2185 oprangeset(ABLO, t) 2186 oprangeset(ABMI, t) 2187 oprangeset(ABPL, t) 2188 oprangeset(ABVS, t) 2189 oprangeset(ABVC, t) 2190 oprangeset(ABHI, t) 2191 oprangeset(ABLS, t) 2192 oprangeset(ABGE, t) 2193 oprangeset(ABLT, t) 2194 oprangeset(ABGT, t) 2195 oprangeset(ABLE, t) 2196 2197 case ALSL: 2198 oprangeset(ALSLW, t) 2199 oprangeset(ALSR, t) 2200 oprangeset(ALSRW, t) 2201 oprangeset(AASR, t) 2202 oprangeset(AASRW, t) 2203 oprangeset(AROR, t) 2204 oprangeset(ARORW, t) 2205 2206 case ACLS: 2207 oprangeset(ACLSW, t) 2208 oprangeset(ACLZ, t) 2209 oprangeset(ACLZW, t) 2210 oprangeset(ARBIT, t) 2211 oprangeset(ARBITW, t) 2212 oprangeset(AREV, t) 2213 oprangeset(AREVW, t) 2214 oprangeset(AREV16, t) 2215 oprangeset(AREV16W, t) 2216 oprangeset(AREV32, t) 2217 2218 case ASDIV: 2219 oprangeset(ASDIVW, t) 2220 oprangeset(AUDIV, t) 2221 oprangeset(AUDIVW, t) 2222 oprangeset(ACRC32B, t) 2223 oprangeset(ACRC32CB, t) 2224 oprangeset(ACRC32CH, t) 2225 oprangeset(ACRC32CW, t) 2226 oprangeset(ACRC32CX, t) 2227 oprangeset(ACRC32H, t) 2228 oprangeset(ACRC32W, t) 2229 oprangeset(ACRC32X, t) 2230 2231 case AMADD: 2232 oprangeset(AMADDW, t) 2233 oprangeset(AMSUB, t) 2234 oprangeset(AMSUBW, t) 2235 oprangeset(ASMADDL, t) 2236 oprangeset(ASMSUBL, t) 2237 oprangeset(AUMADDL, t) 2238 oprangeset(AUMSUBL, t) 2239 2240 case AREM: 2241 oprangeset(AREMW, t) 2242 oprangeset(AUREM, t) 2243 oprangeset(AUREMW, t) 2244 2245 case AMUL: 2246 oprangeset(AMULW, t) 2247 oprangeset(AMNEG, t) 2248 oprangeset(AMNEGW, t) 2249 oprangeset(ASMNEGL, t) 2250 oprangeset(ASMULL, t) 2251 oprangeset(ASMULH, t) 2252 oprangeset(AUMNEGL, t) 2253 oprangeset(AUMULH, t) 2254 oprangeset(AUMULL, t) 2255 2256 case AMOVB: 2257 oprangeset(AMOVBU, t) 2258 2259 case AMOVH: 2260 oprangeset(AMOVHU, t) 2261 2262 case AMOVW: 2263 oprangeset(AMOVWU, t) 2264 2265 case ABFM: 2266 oprangeset(ABFMW, t) 2267 oprangeset(ASBFM, t) 2268 oprangeset(ASBFMW, t) 2269 oprangeset(AUBFM, t) 2270 oprangeset(AUBFMW, t) 2271 2272 case ABFI: 2273 oprangeset(ABFIW, t) 2274 oprangeset(ABFXIL, t) 2275 oprangeset(ABFXILW, t) 2276 oprangeset(ASBFIZ, t) 2277 oprangeset(ASBFIZW, t) 2278 oprangeset(ASBFX, t) 2279 oprangeset(ASBFXW, t) 2280 oprangeset(AUBFIZ, t) 2281 oprangeset(AUBFIZW, t) 2282 oprangeset(AUBFX, t) 2283 oprangeset(AUBFXW, t) 2284 2285 case AEXTR: 2286 oprangeset(AEXTRW, t) 2287 2288 case ASXTB: 2289 oprangeset(ASXTBW, t) 2290 oprangeset(ASXTH, t) 2291 oprangeset(ASXTHW, t) 2292 oprangeset(ASXTW, t) 2293 oprangeset(AUXTB, t) 2294 oprangeset(AUXTH, t) 2295 oprangeset(AUXTW, t) 2296 oprangeset(AUXTBW, t) 2297 oprangeset(AUXTHW, t) 2298 2299 case ACCMN: 2300 oprangeset(ACCMNW, t) 2301 oprangeset(ACCMP, t) 2302 oprangeset(ACCMPW, t) 2303 2304 case ACSEL: 2305 oprangeset(ACSELW, t) 2306 oprangeset(ACSINC, t) 2307 oprangeset(ACSINCW, t) 2308 oprangeset(ACSINV, t) 2309 oprangeset(ACSINVW, t) 2310 oprangeset(ACSNEG, t) 2311 oprangeset(ACSNEGW, t) 2312 2313 case ACINC: 2314 // aliases Rm=Rn, !cond 2315 oprangeset(ACINCW, t) 2316 oprangeset(ACINV, t) 2317 oprangeset(ACINVW, t) 2318 oprangeset(ACNEG, t) 2319 oprangeset(ACNEGW, t) 2320 2321 // aliases, Rm=Rn=REGZERO, !cond 2322 case ACSET: 2323 oprangeset(ACSETW, t) 2324 2325 oprangeset(ACSETM, t) 2326 oprangeset(ACSETMW, t) 2327 2328 case AMOVD, 2329 AMOVBU, 2330 AB, 2331 ABL, 2332 AWORD, 2333 ADWORD, 2334 obj.ARET, 2335 obj.ATEXT: 2336 break 2337 2338 case ALDP: 2339 oprangeset(AFLDPD, t) 2340 2341 case ASTP: 2342 oprangeset(AFSTPD, t) 2343 2344 case ASTPW: 2345 oprangeset(AFSTPS, t) 2346 2347 case ALDPW: 2348 oprangeset(ALDPSW, t) 2349 oprangeset(AFLDPS, t) 2350 2351 case AERET: 2352 oprangeset(AWFE, t) 2353 oprangeset(AWFI, t) 2354 oprangeset(AYIELD, t) 2355 oprangeset(ASEV, t) 2356 oprangeset(ASEVL, t) 2357 oprangeset(ADRPS, t) 2358 2359 case ACBZ: 2360 oprangeset(ACBZW, t) 2361 oprangeset(ACBNZ, t) 2362 oprangeset(ACBNZW, t) 2363 2364 case ATBZ: 2365 oprangeset(ATBNZ, t) 2366 2367 case AADR, AADRP: 2368 break 2369 2370 case ACLREX: 2371 break 2372 2373 case ASVC: 2374 oprangeset(AHVC, t) 2375 oprangeset(AHLT, t) 2376 oprangeset(ASMC, t) 2377 oprangeset(ABRK, t) 2378 oprangeset(ADCPS1, t) 2379 oprangeset(ADCPS2, t) 2380 oprangeset(ADCPS3, t) 2381 2382 case AFADDS: 2383 oprangeset(AFADDD, t) 2384 oprangeset(AFSUBS, t) 2385 oprangeset(AFSUBD, t) 2386 oprangeset(AFMULS, t) 2387 oprangeset(AFMULD, t) 2388 oprangeset(AFNMULS, t) 2389 oprangeset(AFNMULD, t) 2390 oprangeset(AFDIVS, t) 2391 oprangeset(AFMAXD, t) 2392 oprangeset(AFMAXS, t) 2393 oprangeset(AFMIND, t) 2394 oprangeset(AFMINS, t) 2395 oprangeset(AFMAXNMD, t) 2396 oprangeset(AFMAXNMS, t) 2397 oprangeset(AFMINNMD, t) 2398 oprangeset(AFMINNMS, t) 2399 oprangeset(AFDIVD, t) 2400 2401 case AFMSUBD: 2402 oprangeset(AFMSUBS, t) 2403 oprangeset(AFMADDS, t) 2404 oprangeset(AFMADDD, t) 2405 oprangeset(AFNMSUBS, t) 2406 oprangeset(AFNMSUBD, t) 2407 oprangeset(AFNMADDS, t) 2408 oprangeset(AFNMADDD, t) 2409 2410 case AFCVTSD: 2411 oprangeset(AFCVTDS, t) 2412 oprangeset(AFABSD, t) 2413 oprangeset(AFABSS, t) 2414 oprangeset(AFNEGD, t) 2415 oprangeset(AFNEGS, t) 2416 oprangeset(AFSQRTD, t) 2417 oprangeset(AFSQRTS, t) 2418 oprangeset(AFRINTNS, t) 2419 oprangeset(AFRINTND, t) 2420 oprangeset(AFRINTPS, t) 2421 oprangeset(AFRINTPD, t) 2422 oprangeset(AFRINTMS, t) 2423 oprangeset(AFRINTMD, t) 2424 oprangeset(AFRINTZS, t) 2425 oprangeset(AFRINTZD, t) 2426 oprangeset(AFRINTAS, t) 2427 oprangeset(AFRINTAD, t) 2428 oprangeset(AFRINTXS, t) 2429 oprangeset(AFRINTXD, t) 2430 oprangeset(AFRINTIS, t) 2431 oprangeset(AFRINTID, t) 2432 oprangeset(AFCVTDH, t) 2433 oprangeset(AFCVTHS, t) 2434 oprangeset(AFCVTHD, t) 2435 oprangeset(AFCVTSH, t) 2436 2437 case AFCMPS: 2438 oprangeset(AFCMPD, t) 2439 oprangeset(AFCMPES, t) 2440 oprangeset(AFCMPED, t) 2441 2442 case AFCCMPS: 2443 oprangeset(AFCCMPD, t) 2444 oprangeset(AFCCMPES, t) 2445 oprangeset(AFCCMPED, t) 2446 2447 case AFCSELD: 2448 oprangeset(AFCSELS, t) 2449 2450 case AFMOVS, AFMOVD: 2451 break 2452 2453 case AFCVTZSD: 2454 oprangeset(AFCVTZSDW, t) 2455 oprangeset(AFCVTZSS, t) 2456 oprangeset(AFCVTZSSW, t) 2457 oprangeset(AFCVTZUD, t) 2458 oprangeset(AFCVTZUDW, t) 2459 oprangeset(AFCVTZUS, t) 2460 oprangeset(AFCVTZUSW, t) 2461 2462 case ASCVTFD: 2463 oprangeset(ASCVTFS, t) 2464 oprangeset(ASCVTFWD, t) 2465 oprangeset(ASCVTFWS, t) 2466 oprangeset(AUCVTFD, t) 2467 oprangeset(AUCVTFS, t) 2468 oprangeset(AUCVTFWD, t) 2469 oprangeset(AUCVTFWS, t) 2470 2471 case ASYS: 2472 oprangeset(AAT, t) 2473 oprangeset(ADC, t) 2474 oprangeset(AIC, t) 2475 oprangeset(ATLBI, t) 2476 2477 case ASYSL, AHINT: 2478 break 2479 2480 case ADMB: 2481 oprangeset(ADSB, t) 2482 oprangeset(AISB, t) 2483 2484 case AMRS, AMSR: 2485 break 2486 2487 case ALDAR: 2488 oprangeset(ALDARW, t) 2489 oprangeset(ALDARB, t) 2490 oprangeset(ALDARH, t) 2491 fallthrough 2492 2493 case ALDXR: 2494 oprangeset(ALDXRB, t) 2495 oprangeset(ALDXRH, t) 2496 oprangeset(ALDXRW, t) 2497 2498 case ALDAXR: 2499 oprangeset(ALDAXRB, t) 2500 oprangeset(ALDAXRH, t) 2501 oprangeset(ALDAXRW, t) 2502 2503 case ALDXP: 2504 oprangeset(ALDXPW, t) 2505 oprangeset(ALDAXP, t) 2506 oprangeset(ALDAXPW, t) 2507 2508 case ASTLR: 2509 oprangeset(ASTLRB, t) 2510 oprangeset(ASTLRH, t) 2511 oprangeset(ASTLRW, t) 2512 2513 case ASTXR: 2514 oprangeset(ASTXRB, t) 2515 oprangeset(ASTXRH, t) 2516 oprangeset(ASTXRW, t) 2517 2518 case ASTLXR: 2519 oprangeset(ASTLXRB, t) 2520 oprangeset(ASTLXRH, t) 2521 oprangeset(ASTLXRW, t) 2522 2523 case ASTXP: 2524 oprangeset(ASTLXP, t) 2525 oprangeset(ASTLXPW, t) 2526 oprangeset(ASTXPW, t) 2527 2528 case AVADDP: 2529 oprangeset(AVAND, t) 2530 oprangeset(AVCMEQ, t) 2531 oprangeset(AVORR, t) 2532 oprangeset(AVEOR, t) 2533 2534 case AVADD: 2535 oprangeset(AVSUB, t) 2536 2537 case AAESD: 2538 oprangeset(AAESE, t) 2539 oprangeset(AAESMC, t) 2540 oprangeset(AAESIMC, t) 2541 oprangeset(ASHA1SU1, t) 2542 oprangeset(ASHA256SU0, t) 2543 2544 case ASHA1C: 2545 oprangeset(ASHA1P, t) 2546 oprangeset(ASHA1M, t) 2547 2548 case ASHA256H: 2549 oprangeset(ASHA256H2, t) 2550 2551 case ASHA1SU0: 2552 oprangeset(ASHA256SU1, t) 2553 2554 case AVADDV: 2555 oprangeset(AVUADDLV, t) 2556 2557 case AVFMLA: 2558 oprangeset(AVFMLS, t) 2559 2560 case AVPMULL: 2561 oprangeset(AVPMULL2, t) 2562 2563 case AVUSHR: 2564 oprangeset(AVSHL, t) 2565 oprangeset(AVSRI, t) 2566 2567 case AVREV32: 2568 oprangeset(AVRBIT, t) 2569 oprangeset(AVREV64, t) 2570 2571 case AVZIP1: 2572 oprangeset(AVZIP2, t) 2573 2574 case ASHA1H, 2575 AVCNT, 2576 AVMOV, 2577 AVLD1, 2578 AVST1, 2579 AVTBL, 2580 AVDUP, 2581 AVMOVI, 2582 APRFM, 2583 AVEXT: 2584 break 2585 2586 case obj.ANOP, 2587 obj.AUNDEF, 2588 obj.AFUNCDATA, 2589 obj.APCDATA, 2590 obj.ADUFFZERO, 2591 obj.ADUFFCOPY: 2592 break 2593 } 2594 } 2595 } 2596 2597 // chipfloat7() checks if the immediate constants available in FMOVS/FMOVD instructions. 2598 // For details of the range of constants available, see 2599 // http://infocenter.arm.com/help/topic/com.arm.doc.dui0473m/dom1359731199385.html. 2600 func (c *ctxt7) chipfloat7(e float64) int { 2601 ei := math.Float64bits(e) 2602 l := uint32(int32(ei)) 2603 h := uint32(int32(ei >> 32)) 2604 2605 if l != 0 || h&0xffff != 0 { 2606 return -1 2607 } 2608 h1 := h & 0x7fc00000 2609 if h1 != 0x40000000 && h1 != 0x3fc00000 { 2610 return -1 2611 } 2612 n := 0 2613 2614 // sign bit (a) 2615 if h&0x80000000 != 0 { 2616 n |= 1 << 7 2617 } 2618 2619 // exp sign bit (b) 2620 if h1 == 0x3fc00000 { 2621 n |= 1 << 6 2622 } 2623 2624 // rest of exp and mantissa (cd-efgh) 2625 n |= int((h >> 16) & 0x3f) 2626 2627 //print("match %.8lux %.8lux %d\n", l, h, n); 2628 return n 2629 } 2630 2631 /* form offset parameter to SYS; special register number */ 2632 func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int { 2633 return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5 2634 } 2635 2636 func SYSARG4(op1 int, Cn int, Cm int, op2 int) int { 2637 return SYSARG5(0, op1, Cn, Cm, op2) 2638 } 2639 2640 // checkUnpredictable checks if the sourse and transfer registers are the same register. 2641 // ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same. 2642 func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) { 2643 if wback && rn != REGSP && (rn == rt1 || rn == rt2) { 2644 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 2645 } 2646 if isload && rt1 == rt2 { 2647 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 2648 } 2649 } 2650 2651 /* checkindex checks if index >= 0 && index <= maxindex */ 2652 func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) { 2653 if index < 0 || index > maxindex { 2654 c.ctxt.Diag("register element index out of range 0 to %d: %v", maxindex, p) 2655 } 2656 } 2657 2658 /* checkoffset checks whether the immediate offset is valid for VLD1.P and VST1.P */ 2659 func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) { 2660 var offset, list, n int64 2661 switch as { 2662 case AVLD1: 2663 offset = p.From.Offset 2664 list = p.To.Offset 2665 case AVST1: 2666 offset = p.To.Offset 2667 list = p.From.Offset 2668 default: 2669 c.ctxt.Diag("invalid operation on op %v", p.As) 2670 } 2671 opcode := (list >> 12) & 15 2672 q := (list >> 30) & 1 2673 if offset == 0 { 2674 return 2675 } 2676 switch opcode { 2677 case 0x7: 2678 n = 1 // one register 2679 case 0xa: 2680 n = 2 // two registers 2681 case 0x6: 2682 n = 3 // three registers 2683 case 0x2: 2684 n = 4 // four registers 2685 default: 2686 c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p) 2687 } 2688 if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) { 2689 c.ctxt.Diag("invalid post-increment offset: %v", p) 2690 } 2691 } 2692 2693 /* checkShiftAmount checks whether the index shift amount is valid */ 2694 /* for load with register offset instructions */ 2695 func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) { 2696 var amount int16 2697 amount = (a.Index >> 5) & 7 2698 switch p.As { 2699 case AMOVB, AMOVBU: 2700 if amount != 0 { 2701 c.ctxt.Diag("invalid index shift amount: %v", p) 2702 } 2703 case AMOVH, AMOVHU: 2704 if amount != 1 && amount != 0 { 2705 c.ctxt.Diag("invalid index shift amount: %v", p) 2706 } 2707 case AMOVW, AMOVWU, AFMOVS: 2708 if amount != 2 && amount != 0 { 2709 c.ctxt.Diag("invalid index shift amount: %v", p) 2710 } 2711 case AMOVD, AFMOVD: 2712 if amount != 3 && amount != 0 { 2713 c.ctxt.Diag("invalid index shift amount: %v", p) 2714 } 2715 default: 2716 panic("invalid operation") 2717 } 2718 } 2719 2720 func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { 2721 o1 := uint32(0) 2722 o2 := uint32(0) 2723 o3 := uint32(0) 2724 o4 := uint32(0) 2725 o5 := uint32(0) 2726 if false { /*debug['P']*/ 2727 fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_) 2728 } 2729 switch o.type_ { 2730 default: 2731 c.ctxt.Diag("%v: unknown asm %d", p, o.type_) 2732 2733 case 0: /* pseudo ops */ 2734 break 2735 2736 case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */ 2737 o1 = c.oprrr(p, p.As) 2738 2739 rf := int(p.From.Reg) 2740 rt := int(p.To.Reg) 2741 r := int(p.Reg) 2742 if p.To.Type == obj.TYPE_NONE { 2743 rt = REGZERO 2744 } 2745 if r == 0 { 2746 r = rt 2747 } 2748 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 2749 2750 case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */ 2751 o1 = c.opirr(p, p.As) 2752 2753 rt := int(p.To.Reg) 2754 if p.To.Type == obj.TYPE_NONE { 2755 if (o1 & Sbit) == 0 { 2756 c.ctxt.Diag("ineffective ZR destination\n%v", p) 2757 } 2758 rt = REGZERO 2759 } 2760 2761 r := int(p.Reg) 2762 if r == 0 { 2763 r = rt 2764 } 2765 v := int32(c.regoff(&p.From)) 2766 o1 = c.oaddi(p, int32(o1), v, r, rt) 2767 2768 case 3: /* op R<<n[,R],R (shifted register) */ 2769 o1 = c.oprrr(p, p.As) 2770 2771 amount := (p.From.Offset >> 10) & 63 2772 is64bit := o1 & (1 << 31) 2773 if is64bit == 0 && amount >= 32 { 2774 c.ctxt.Diag("shift amount out of range 0 to 31: %v", p) 2775 } 2776 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 2777 rt := int(p.To.Reg) 2778 if p.To.Type == obj.TYPE_NONE { 2779 rt = REGZERO 2780 } 2781 r := int(p.Reg) 2782 if p.As == AMVN || p.As == AMVNW { 2783 r = REGZERO 2784 } else if r == 0 { 2785 r = rt 2786 } 2787 o1 |= (uint32(r&31) << 5) | uint32(rt&31) 2788 2789 case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R */ 2790 o1 = c.opirr(p, p.As) 2791 2792 rt := int(p.To.Reg) 2793 r := int(o.param) 2794 if r == 0 { 2795 r = REGZERO 2796 } else if r == REGFROM { 2797 r = int(p.From.Reg) 2798 } 2799 if r == 0 { 2800 r = REGSP 2801 } 2802 v := int32(c.regoff(&p.From)) 2803 if (v & 0xFFF000) != 0 { 2804 v >>= 12 2805 o1 |= 1 << 22 /* shift, by 12 */ 2806 } 2807 2808 o1 |= ((uint32(v) & 0xFFF) << 10) | (uint32(r&31) << 5) | uint32(rt&31) 2809 2810 case 5: /* b s; bl s */ 2811 o1 = c.opbra(p, p.As) 2812 2813 if p.To.Sym == nil { 2814 o1 |= uint32(c.brdist(p, 0, 26, 2)) 2815 break 2816 } 2817 2818 rel := obj.Addrel(c.cursym) 2819 rel.Off = int32(c.pc) 2820 rel.Siz = 4 2821 rel.Sym = p.To.Sym 2822 rel.Add = p.To.Offset 2823 rel.Type = objabi.R_CALLARM64 2824 2825 case 6: /* b ,O(R); bl ,O(R) */ 2826 o1 = c.opbrr(p, p.As) 2827 2828 o1 |= uint32(p.To.Reg&31) << 5 2829 rel := obj.Addrel(c.cursym) 2830 rel.Off = int32(c.pc) 2831 rel.Siz = 0 2832 rel.Type = objabi.R_CALLIND 2833 2834 case 7: /* beq s */ 2835 o1 = c.opbra(p, p.As) 2836 2837 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5) 2838 2839 case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */ 2840 rt := int(p.To.Reg) 2841 2842 rf := int(p.Reg) 2843 if rf == 0 { 2844 rf = rt 2845 } 2846 v := int32(p.From.Offset) 2847 switch p.As { 2848 case AASR: 2849 o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt) 2850 2851 case AASRW: 2852 o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt) 2853 2854 case ALSL: 2855 o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt) 2856 2857 case ALSLW: 2858 o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt) 2859 2860 case ALSR: 2861 o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt) 2862 2863 case ALSRW: 2864 o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt) 2865 2866 case AROR: 2867 o1 = c.opextr(p, AEXTR, v, rf, rf, rt) 2868 2869 case ARORW: 2870 o1 = c.opextr(p, AEXTRW, v, rf, rf, rt) 2871 2872 default: 2873 c.ctxt.Diag("bad shift $con\n%v", p) 2874 break 2875 } 2876 2877 case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */ 2878 o1 = c.oprrr(p, p.As) 2879 2880 r := int(p.Reg) 2881 if r == 0 { 2882 r = int(p.To.Reg) 2883 } 2884 o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31) 2885 2886 case 10: /* brk/hvc/.../svc [$con] */ 2887 o1 = c.opimm(p, p.As) 2888 2889 if p.From.Type != obj.TYPE_NONE { 2890 o1 |= uint32((p.From.Offset & 0xffff) << 5) 2891 } 2892 2893 case 11: /* dword */ 2894 c.aclass(&p.To) 2895 2896 o1 = uint32(c.instoffset) 2897 o2 = uint32(c.instoffset >> 32) 2898 if p.To.Sym != nil { 2899 rel := obj.Addrel(c.cursym) 2900 rel.Off = int32(c.pc) 2901 rel.Siz = 8 2902 rel.Sym = p.To.Sym 2903 rel.Add = p.To.Offset 2904 rel.Type = objabi.R_ADDR 2905 o2 = 0 2906 o1 = o2 2907 } 2908 2909 case 12: /* movT $vcon, reg */ 2910 o1 = c.omovlit(p.As, p, &p.From, int(p.To.Reg)) 2911 2912 case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */ 2913 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 2914 2915 if o1 == 0 { 2916 break 2917 } 2918 rt := int(p.To.Reg) 2919 if p.To.Type == obj.TYPE_NONE { 2920 rt = REGZERO 2921 } 2922 r := int(p.Reg) 2923 if r == 0 { 2924 r = rt 2925 } 2926 if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) { 2927 o2 = c.opxrrr(p, p.As, false) 2928 o2 |= REGTMP & 31 << 16 2929 o2 |= LSL0_64 2930 } else { 2931 o2 = c.oprrr(p, p.As) 2932 o2 |= REGTMP & 31 << 16 /* shift is 0 */ 2933 } 2934 2935 o2 |= uint32(r&31) << 5 2936 o2 |= uint32(rt & 31) 2937 2938 case 14: /* word */ 2939 if c.aclass(&p.To) == C_ADDR { 2940 c.ctxt.Diag("address constant needs DWORD\n%v", p) 2941 } 2942 o1 = uint32(c.instoffset) 2943 if p.To.Sym != nil { 2944 // This case happens with words generated 2945 // in the PC stream as part of the literal pool. 2946 rel := obj.Addrel(c.cursym) 2947 2948 rel.Off = int32(c.pc) 2949 rel.Siz = 4 2950 rel.Sym = p.To.Sym 2951 rel.Add = p.To.Offset 2952 rel.Type = objabi.R_ADDR 2953 o1 = 0 2954 } 2955 2956 case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub/fmadd/fmsub/fnmadd/fnmsub Rm,Ra,Rn,Rd */ 2957 o1 = c.oprrr(p, p.As) 2958 2959 rf := int(p.From.Reg) 2960 rt := int(p.To.Reg) 2961 var r int 2962 var ra int 2963 if p.From3Type() == obj.TYPE_REG { 2964 r = int(p.GetFrom3().Reg) 2965 ra = int(p.Reg) 2966 if ra == 0 { 2967 ra = REGZERO 2968 } 2969 } else { 2970 r = int(p.Reg) 2971 if r == 0 { 2972 r = rt 2973 } 2974 ra = REGZERO 2975 } 2976 2977 o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31) 2978 2979 case 16: /* XremY R[,R],R -> XdivY; XmsubY */ 2980 o1 = c.oprrr(p, p.As) 2981 2982 rf := int(p.From.Reg) 2983 rt := int(p.To.Reg) 2984 r := int(p.Reg) 2985 if r == 0 { 2986 r = rt 2987 } 2988 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31 2989 o2 = c.oprrr(p, AMSUBW) 2990 o2 |= o1 & (1 << 31) /* same size */ 2991 o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31) 2992 2993 case 17: /* op Rm,[Rn],Rd; default Rn=ZR */ 2994 o1 = c.oprrr(p, p.As) 2995 2996 rf := int(p.From.Reg) 2997 rt := int(p.To.Reg) 2998 r := int(p.Reg) 2999 if p.To.Type == obj.TYPE_NONE { 3000 rt = REGZERO 3001 } 3002 if r == 0 { 3003 r = REGZERO 3004 } 3005 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 3006 3007 case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */ 3008 o1 = c.oprrr(p, p.As) 3009 3010 cond := int(p.From.Reg) 3011 if cond < COND_EQ || cond > COND_NV { 3012 c.ctxt.Diag("invalid condition: %v", p) 3013 } else { 3014 cond -= COND_EQ 3015 } 3016 3017 r := int(p.Reg) 3018 var rf int 3019 if r != 0 { 3020 if p.From3Type() == obj.TYPE_NONE { 3021 /* CINC/CINV/CNEG */ 3022 rf = r 3023 cond ^= 1 3024 } else { 3025 rf = int(p.GetFrom3().Reg) /* CSEL */ 3026 } 3027 } else { 3028 /* CSET */ 3029 rf = REGZERO 3030 r = rf 3031 cond ^= 1 3032 } 3033 3034 rt := int(p.To.Reg) 3035 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31) 3036 3037 case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */ 3038 nzcv := int(p.To.Offset) 3039 3040 cond := int(p.From.Reg) 3041 if cond < COND_EQ || cond > COND_NV { 3042 c.ctxt.Diag("invalid condition\n%v", p) 3043 } else { 3044 cond -= COND_EQ 3045 } 3046 var rf int 3047 if p.GetFrom3().Type == obj.TYPE_REG { 3048 o1 = c.oprrr(p, p.As) 3049 rf = int(p.GetFrom3().Reg) /* Rm */ 3050 } else { 3051 o1 = c.opirr(p, p.As) 3052 rf = int(p.GetFrom3().Offset & 0x1F) 3053 } 3054 3055 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv) 3056 3057 case 20: /* movT R,O(R) -> strT */ 3058 v := int32(c.regoff(&p.To)) 3059 sz := int32(1 << uint(movesize(p.As))) 3060 3061 r := int(p.To.Reg) 3062 if r == 0 { 3063 r = int(o.param) 3064 } 3065 if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ 3066 o1 = c.olsr9s(p, int32(c.opstr9(p, p.As)), v, r, int(p.From.Reg)) 3067 } else { 3068 v = int32(c.offsetshift(p, int64(v), int(o.a4))) 3069 o1 = c.olsr12u(p, int32(c.opstr12(p, p.As)), v, r, int(p.From.Reg)) 3070 } 3071 3072 case 21: /* movT O(R),R -> ldrT */ 3073 v := int32(c.regoff(&p.From)) 3074 sz := int32(1 << uint(movesize(p.As))) 3075 3076 r := int(p.From.Reg) 3077 if r == 0 { 3078 r = int(o.param) 3079 } 3080 if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ 3081 o1 = c.olsr9s(p, int32(c.opldr9(p, p.As)), v, r, int(p.To.Reg)) 3082 } else { 3083 v = int32(c.offsetshift(p, int64(v), int(o.a1))) 3084 //print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1); 3085 o1 = c.olsr12u(p, int32(c.opldr12(p, p.As)), v, r, int(p.To.Reg)) 3086 } 3087 3088 case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */ 3089 if p.From.Reg != REGSP && p.From.Reg == p.To.Reg { 3090 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3091 } 3092 3093 v := int32(p.From.Offset) 3094 3095 if v < -256 || v > 255 { 3096 c.ctxt.Diag("offset out of range [-255,254]: %v", p) 3097 } 3098 o1 = c.opldrpp(p, p.As) 3099 if o.scond == C_XPOST { 3100 o1 |= 1 << 10 3101 } else { 3102 o1 |= 3 << 10 3103 } 3104 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31) 3105 3106 case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */ 3107 if p.To.Reg != REGSP && p.From.Reg == p.To.Reg { 3108 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3109 } 3110 3111 v := int32(p.To.Offset) 3112 3113 if v < -256 || v > 255 { 3114 c.ctxt.Diag("offset out of range [-255,254]: %v", p) 3115 } 3116 o1 = LD2STR(c.opldrpp(p, p.As)) 3117 if o.scond == C_XPOST { 3118 o1 |= 1 << 10 3119 } else { 3120 o1 |= 3 << 10 3121 } 3122 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31) 3123 3124 case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */ 3125 rf := int(p.From.Reg) 3126 rt := int(p.To.Reg) 3127 s := rf == REGSP || rt == REGSP 3128 if p.As == AMVN || p.As == AMVNW { 3129 if s { 3130 c.ctxt.Diag("illegal SP reference\n%v", p) 3131 } 3132 o1 = c.oprrr(p, p.As) 3133 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 3134 } else if s { 3135 o1 = c.opirr(p, p.As) 3136 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 3137 } else { 3138 o1 = c.oprrr(p, p.As) 3139 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 3140 } 3141 3142 case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */ 3143 o1 = c.oprrr(p, p.As) 3144 3145 rf := int(p.From.Reg) 3146 if rf == C_NONE { 3147 rf = int(p.To.Reg) 3148 } 3149 rt := int(p.To.Reg) 3150 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 3151 3152 case 26: /* negX Rm<<s, Rd -> subX Rm<<s, ZR, Rd */ 3153 o1 = c.oprrr(p, p.As) 3154 3155 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 3156 rt := int(p.To.Reg) 3157 o1 |= (REGZERO & 31 << 5) | uint32(rt&31) 3158 3159 case 27: /* op Rm<<n[,Rn],Rd (extended register) */ 3160 if (p.From.Reg-obj.RBaseARM64)®_EXT != 0 { 3161 amount := (p.From.Reg >> 5) & 7 3162 if amount > 4 { 3163 c.ctxt.Diag("shift amount out of range 0 to 4: %v", p) 3164 } 3165 o1 = c.opxrrr(p, p.As, true) 3166 o1 |= c.encRegShiftOrExt(&p.From, p.From.Reg) /* includes reg, op, etc */ 3167 } else { 3168 o1 = c.opxrrr(p, p.As, false) 3169 o1 |= uint32(p.From.Reg&31) << 16 3170 } 3171 rt := int(p.To.Reg) 3172 if p.To.Type == obj.TYPE_NONE { 3173 rt = REGZERO 3174 } 3175 r := int(p.Reg) 3176 if r == 0 { 3177 r = rt 3178 } 3179 o1 |= (uint32(r&31) << 5) | uint32(rt&31) 3180 3181 case 28: /* logop $vcon, [R], R (64 bit literal) */ 3182 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 3183 3184 if o1 == 0 { 3185 break 3186 } 3187 rt := int(p.To.Reg) 3188 if p.To.Type == obj.TYPE_NONE { 3189 rt = REGZERO 3190 } 3191 r := int(p.Reg) 3192 if r == 0 { 3193 r = rt 3194 } 3195 o2 = c.oprrr(p, p.As) 3196 o2 |= REGTMP & 31 << 16 /* shift is 0 */ 3197 o2 |= uint32(r&31) << 5 3198 o2 |= uint32(rt & 31) 3199 3200 case 29: /* op Rn, Rd */ 3201 fc := c.aclass(&p.From) 3202 tc := c.aclass(&p.To) 3203 if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZCON || tc == C_REG || tc == C_ZCON) { 3204 // FMOV Rx, Fy or FMOV Fy, Rx 3205 o1 = FPCVTI(0, 0, 0, 0, 6) 3206 if p.As == AFMOVD { 3207 o1 |= 1<<31 | 1<<22 // 64-bit 3208 } 3209 if fc == C_REG || fc == C_ZCON { 3210 o1 |= 1 << 16 // FMOV Rx, Fy 3211 } 3212 } else { 3213 o1 = c.oprrr(p, p.As) 3214 } 3215 o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31) 3216 3217 case 30: /* movT R,L(R) -> strT */ 3218 // if offset L can be split into hi+lo, and both fit into instructions, do 3219 // add $hi, R, Rtmp 3220 // str R, lo(Rtmp) 3221 // otherwise, use constant pool 3222 // mov $L, Rtmp (from constant pool) 3223 // str R, (R+Rtmp) 3224 s := movesize(o.as) 3225 if s < 0 { 3226 c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) 3227 } 3228 3229 r := int(p.To.Reg) 3230 if r == 0 { 3231 r = int(o.param) 3232 } 3233 3234 v := int32(c.regoff(&p.To)) 3235 var hi int32 3236 if v < 0 || (v&((1<<uint(s))-1)) != 0 { 3237 // negative or unaligned offset, use constant pool 3238 goto storeusepool 3239 } 3240 3241 hi = v - (v & (0xFFF << uint(s))) 3242 if hi&0xFFF != 0 { 3243 c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p) 3244 } 3245 if hi&^0xFFF000 != 0 { 3246 // hi doesn't fit into an ADD instruction 3247 goto storeusepool 3248 } 3249 3250 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP) 3251 o2 = c.olsr12u(p, int32(c.opstr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg)) 3252 break 3253 3254 storeusepool: 3255 if r == REGTMP || p.From.Reg == REGTMP { 3256 c.ctxt.Diag("REGTMP used in large offset store: %v", p) 3257 } 3258 o1 = c.omovlit(AMOVD, p, &p.To, REGTMP) 3259 o2 = c.olsxrr(p, int32(c.opstrr(p, p.As, false)), int(p.From.Reg), r, REGTMP) 3260 3261 case 31: /* movT L(R), R -> ldrT */ 3262 // if offset L can be split into hi+lo, and both fit into instructions, do 3263 // add $hi, R, Rtmp 3264 // ldr lo(Rtmp), R 3265 // otherwise, use constant pool 3266 // mov $L, Rtmp (from constant pool) 3267 // ldr (R+Rtmp), R 3268 s := movesize(o.as) 3269 if s < 0 { 3270 c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) 3271 } 3272 3273 r := int(p.From.Reg) 3274 if r == 0 { 3275 r = int(o.param) 3276 } 3277 3278 v := int32(c.regoff(&p.From)) 3279 var hi int32 3280 if v < 0 || (v&((1<<uint(s))-1)) != 0 { 3281 // negative or unaligned offset, use constant pool 3282 goto loadusepool 3283 } 3284 3285 hi = v - (v & (0xFFF << uint(s))) 3286 if (hi & 0xFFF) != 0 { 3287 c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p) 3288 } 3289 if hi&^0xFFF000 != 0 { 3290 // hi doesn't fit into an ADD instruction 3291 goto loadusepool 3292 } 3293 3294 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP) 3295 o2 = c.olsr12u(p, int32(c.opldr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg)) 3296 break 3297 3298 loadusepool: 3299 if r == REGTMP || p.From.Reg == REGTMP { 3300 c.ctxt.Diag("REGTMP used in large offset load: %v", p) 3301 } 3302 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 3303 o2 = c.olsxrr(p, int32(c.opldrr(p, p.As, false)), int(p.To.Reg), r, REGTMP) 3304 3305 case 32: /* mov $con, R -> movz/movn */ 3306 o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg)) 3307 3308 case 33: /* movk $uimm16 << pos */ 3309 o1 = c.opirr(p, p.As) 3310 3311 d := p.From.Offset 3312 s := movcon(d) 3313 if s < 0 || s >= 4 { 3314 c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p) 3315 } 3316 if (o1&S64) == 0 && s >= 2 { 3317 c.ctxt.Diag("illegal bit position\n%v", p) 3318 } 3319 if ((d >> uint(s*16)) >> 16) != 0 { 3320 c.ctxt.Diag("requires uimm16\n%v", p) 3321 } 3322 rt := int(p.To.Reg) 3323 3324 o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31)) 3325 3326 case 34: /* mov $lacon,R */ 3327 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 3328 3329 if o1 == 0 { 3330 break 3331 } 3332 o2 = c.opxrrr(p, AADD, false) 3333 o2 |= REGTMP & 31 << 16 3334 o2 |= LSL0_64 3335 r := int(p.From.Reg) 3336 if r == 0 { 3337 r = int(o.param) 3338 } 3339 o2 |= uint32(r&31) << 5 3340 o2 |= uint32(p.To.Reg & 31) 3341 3342 case 35: /* mov SPR,R -> mrs */ 3343 o1 = c.oprrr(p, AMRS) 3344 3345 v := uint32(0) 3346 for i := 0; i < len(systemreg); i++ { 3347 if systemreg[i].reg == p.From.Reg { 3348 v = systemreg[i].enc 3349 break 3350 } 3351 } 3352 if v == 0 { 3353 c.ctxt.Diag("illegal system register:\n%v", p) 3354 } 3355 if (o1 & (v &^ (3 << 19))) != 0 { 3356 c.ctxt.Diag("MRS register value overlap\n%v", p) 3357 } 3358 3359 o1 |= v 3360 o1 |= uint32(p.To.Reg & 31) 3361 3362 case 36: /* mov R,SPR */ 3363 o1 = c.oprrr(p, AMSR) 3364 3365 v := uint32(0) 3366 for i := 0; i < len(systemreg); i++ { 3367 if systemreg[i].reg == p.To.Reg { 3368 v = systemreg[i].enc 3369 break 3370 } 3371 } 3372 if v == 0 { 3373 c.ctxt.Diag("illegal system register:\n%v", p) 3374 } 3375 if (o1 & (v &^ (3 << 19))) != 0 { 3376 c.ctxt.Diag("MSR register value overlap\n%v", p) 3377 } 3378 3379 o1 |= v 3380 o1 |= uint32(p.From.Reg & 31) 3381 3382 case 37: /* mov $con,PSTATEfield -> MSR [immediate] */ 3383 if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 { 3384 c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p) 3385 } 3386 o1 = c.opirr(p, AMSR) 3387 o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */ 3388 v := uint32(0) 3389 for i := 0; i < len(pstatefield); i++ { 3390 if pstatefield[i].reg == p.To.Reg { 3391 v = pstatefield[i].enc 3392 break 3393 } 3394 } 3395 3396 if v == 0 { 3397 c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p) 3398 } 3399 o1 |= v 3400 3401 case 38: /* clrex [$imm] */ 3402 o1 = c.opimm(p, p.As) 3403 3404 if p.To.Type == obj.TYPE_NONE { 3405 o1 |= 0xF << 8 3406 } else { 3407 o1 |= uint32((p.To.Offset & 0xF) << 8) 3408 } 3409 3410 case 39: /* cbz R, rel */ 3411 o1 = c.opirr(p, p.As) 3412 3413 o1 |= uint32(p.From.Reg & 31) 3414 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5) 3415 3416 case 40: /* tbz */ 3417 o1 = c.opirr(p, p.As) 3418 3419 v := int32(p.From.Offset) 3420 if v < 0 || v > 63 { 3421 c.ctxt.Diag("illegal bit number\n%v", p) 3422 } 3423 o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19) 3424 o1 |= uint32(c.brdist(p, 0, 14, 2) << 5) 3425 o1 |= uint32(p.Reg & 31) 3426 3427 case 41: /* eret, nop, others with no operands */ 3428 o1 = c.op0(p, p.As) 3429 3430 case 42: /* bfm R,r,s,R */ 3431 o1 = c.opbfm(p, p.As, int(p.From.Offset), int(p.GetFrom3().Offset), int(p.Reg), int(p.To.Reg)) 3432 3433 case 43: /* bfm aliases */ 3434 r := int(p.From.Offset) 3435 s := int(p.GetFrom3().Offset) 3436 rf := int(p.Reg) 3437 rt := int(p.To.Reg) 3438 if rf == 0 { 3439 rf = rt 3440 } 3441 switch p.As { 3442 case ABFI: 3443 if r != 0 { 3444 r = 64 - r 3445 } 3446 o1 = c.opbfm(p, ABFM, r, s-1, rf, rt) 3447 3448 case ABFIW: 3449 if r != 0 { 3450 r = 32 - r 3451 } 3452 o1 = c.opbfm(p, ABFMW, r, s-1, rf, rt) 3453 3454 case ABFXIL: 3455 o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt) 3456 3457 case ABFXILW: 3458 o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt) 3459 3460 case ASBFIZ: 3461 if r != 0 { 3462 r = 64 - r 3463 } 3464 o1 = c.opbfm(p, ASBFM, r, s-1, rf, rt) 3465 3466 case ASBFIZW: 3467 if r != 0 { 3468 r = 32 - r 3469 } 3470 o1 = c.opbfm(p, ASBFMW, r, s-1, rf, rt) 3471 3472 case ASBFX: 3473 o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt) 3474 3475 case ASBFXW: 3476 o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt) 3477 3478 case AUBFIZ: 3479 if r != 0 { 3480 r = 64 - r 3481 } 3482 o1 = c.opbfm(p, AUBFM, r, s-1, rf, rt) 3483 3484 case AUBFIZW: 3485 if r != 0 { 3486 r = 32 - r 3487 } 3488 o1 = c.opbfm(p, AUBFMW, r, s-1, rf, rt) 3489 3490 case AUBFX: 3491 o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt) 3492 3493 case AUBFXW: 3494 o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt) 3495 3496 default: 3497 c.ctxt.Diag("bad bfm alias\n%v", p) 3498 break 3499 } 3500 3501 case 44: /* extr $b, Rn, Rm, Rd */ 3502 o1 = c.opextr(p, p.As, int32(p.From.Offset), int(p.GetFrom3().Reg), int(p.Reg), int(p.To.Reg)) 3503 3504 case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */ 3505 rf := int(p.From.Reg) 3506 3507 rt := int(p.To.Reg) 3508 as := p.As 3509 if rf == REGZERO { 3510 as = AMOVWU /* clearer in disassembly */ 3511 } 3512 switch as { 3513 case AMOVB, ASXTB: 3514 o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt) 3515 3516 case AMOVH, ASXTH: 3517 o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt) 3518 3519 case AMOVW, ASXTW: 3520 o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt) 3521 3522 case AMOVBU, AUXTB: 3523 o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt) 3524 3525 case AMOVHU, AUXTH: 3526 o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt) 3527 3528 case AMOVWU: 3529 o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 3530 3531 case AUXTW: 3532 o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt) 3533 3534 case ASXTBW: 3535 o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt) 3536 3537 case ASXTHW: 3538 o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt) 3539 3540 case AUXTBW: 3541 o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt) 3542 3543 case AUXTHW: 3544 o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt) 3545 3546 default: 3547 c.ctxt.Diag("bad sxt %v", as) 3548 break 3549 } 3550 3551 case 46: /* cls */ 3552 o1 = c.opbit(p, p.As) 3553 3554 o1 |= uint32(p.From.Reg&31) << 5 3555 o1 |= uint32(p.To.Reg & 31) 3556 3557 case 47: /* SWPx Rs, (Rb), Rt: Rs -> (Rb) -> Rt */ 3558 rs := p.From.Reg 3559 rt := p.RegTo2 3560 rb := p.To.Reg 3561 switch p.As { 3562 case ASWPD, ASWPALD, ALDADDALD, ALDADDD, ALDANDD, ALDEORD, ALDORD: // 64-bit 3563 o1 = 3 << 30 3564 case ASWPW, ASWPALW, ALDADDALW, ALDADDW, ALDANDW, ALDEORW, ALDORW: // 32-bit 3565 o1 = 2 << 30 3566 case ASWPH, ASWPALH, ALDADDALH, ALDADDH, ALDANDH, ALDEORH, ALDORH: // 16-bit 3567 o1 = 1 << 30 3568 case ASWPB, ASWPALB, ALDADDALB, ALDADDB, ALDANDB, ALDEORB, ALDORB: // 8-bit 3569 o1 = 0 << 30 3570 default: 3571 c.ctxt.Diag("illegal instruction: %v\n", p) 3572 } 3573 switch p.As { 3574 case ASWPD, ASWPW, ASWPH, ASWPB, ASWPALD, ASWPALW, ASWPALH, ASWPALB: 3575 o1 |= 0x20 << 10 3576 case ALDADDALD, ALDADDALW, ALDADDALH, ALDADDALB, ALDADDD, ALDADDW, ALDADDH, ALDADDB: 3577 o1 |= 0x00 << 10 3578 case ALDANDD, ALDANDW, ALDANDH, ALDANDB: 3579 o1 |= 0x04 << 10 3580 case ALDEORD, ALDEORW, ALDEORH, ALDEORB: 3581 o1 |= 0x08 << 10 3582 case ALDORD, ALDORW, ALDORH, ALDORB: 3583 o1 |= 0x0c << 10 3584 } 3585 switch p.As { 3586 case ALDADDALD, ALDADDALW, ALDADDALH, ALDADDALB, ASWPALD, ASWPALW, ASWPALH, ASWPALB: 3587 o1 |= 3 << 22 3588 } 3589 o1 |= 0x1c1<<21 | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31) 3590 3591 case 48: /* ADD $C_ADDCON2, Rm, Rd */ 3592 op := c.opirr(p, p.As) 3593 if op&Sbit != 0 { 3594 c.ctxt.Diag("can not break addition/subtraction when S bit is set", p) 3595 } 3596 rt := int(p.To.Reg) 3597 r := int(p.Reg) 3598 if r == 0 { 3599 r = rt 3600 } 3601 o1 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0x000fff, r, rt) 3602 o2 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0xfff000, rt, rt) 3603 3604 case 50: /* sys/sysl */ 3605 o1 = c.opirr(p, p.As) 3606 3607 if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 { 3608 c.ctxt.Diag("illegal SYS argument\n%v", p) 3609 } 3610 o1 |= uint32(p.From.Offset) 3611 if p.To.Type == obj.TYPE_REG { 3612 o1 |= uint32(p.To.Reg & 31) 3613 } else if p.Reg != 0 { 3614 o1 |= uint32(p.Reg & 31) 3615 } else { 3616 o1 |= 0x1F 3617 } 3618 3619 case 51: /* dmb */ 3620 o1 = c.opirr(p, p.As) 3621 3622 if p.From.Type == obj.TYPE_CONST { 3623 o1 |= uint32((p.From.Offset & 0xF) << 8) 3624 } 3625 3626 case 52: /* hint */ 3627 o1 = c.opirr(p, p.As) 3628 3629 o1 |= uint32((p.From.Offset & 0x7F) << 5) 3630 3631 case 53: /* and/or/eor/bic/tst/... $bitcon, Rn, Rd */ 3632 a := p.As 3633 rt := int(p.To.Reg) 3634 if p.To.Type == obj.TYPE_NONE { 3635 rt = REGZERO 3636 } 3637 r := int(p.Reg) 3638 if r == 0 { 3639 r = rt 3640 } 3641 mode := 64 3642 v := uint64(p.From.Offset) 3643 switch p.As { 3644 case AANDW, AORRW, AEORW, AANDSW, ATSTW: 3645 mode = 32 3646 case ABIC, AORN, AEON, ABICS: 3647 v = ^v 3648 case ABICW, AORNW, AEONW, ABICSW: 3649 v = ^v 3650 mode = 32 3651 } 3652 o1 = c.opirr(p, a) 3653 o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31) 3654 3655 case 54: /* floating point arith */ 3656 o1 = c.oprrr(p, p.As) 3657 rf := int(p.From.Reg) 3658 rt := int(p.To.Reg) 3659 r := int(p.Reg) 3660 if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */ 3661 r = rf 3662 rf = 0 3663 } else if r == 0 { 3664 r = rt 3665 } 3666 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 3667 3668 case 55: /* floating-point constant */ 3669 var rf int 3670 o1 = 0xf<<25 | 1<<21 | 1<<12 3671 rf = c.chipfloat7(p.From.Val.(float64)) 3672 if rf < 0 { 3673 c.ctxt.Diag("invalid floating-point immediate\n%v", p) 3674 } 3675 if p.As == AFMOVD { 3676 o1 |= 1 << 22 3677 } 3678 o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31) 3679 3680 case 56: /* floating point compare */ 3681 o1 = c.oprrr(p, p.As) 3682 3683 var rf int 3684 if p.From.Type == obj.TYPE_FCONST { 3685 o1 |= 8 /* zero */ 3686 rf = 0 3687 } else { 3688 rf = int(p.From.Reg) 3689 } 3690 rt := int(p.Reg) 3691 o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5 3692 3693 case 57: /* floating point conditional compare */ 3694 o1 = c.oprrr(p, p.As) 3695 3696 cond := int(p.From.Reg) 3697 if cond < COND_EQ || cond > COND_NV { 3698 c.ctxt.Diag("invalid condition\n%v", p) 3699 } else { 3700 cond -= COND_EQ 3701 } 3702 3703 nzcv := int(p.To.Offset) 3704 if nzcv&^0xF != 0 { 3705 c.ctxt.Diag("implausible condition\n%v", p) 3706 } 3707 rf := int(p.Reg) 3708 if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 { 3709 c.ctxt.Diag("illegal FCCMP\n%v", p) 3710 break 3711 } 3712 rt := int(p.GetFrom3().Reg) 3713 o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv) 3714 3715 case 58: /* ldar/ldarb/ldarh/ldaxp/ldxp/ldaxr/ldxr */ 3716 o1 = c.opload(p, p.As) 3717 3718 o1 |= 0x1F << 16 3719 o1 |= uint32(p.From.Reg&31) << 5 3720 if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW { 3721 if int(p.To.Reg) == int(p.To.Offset) { 3722 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3723 } 3724 o1 |= uint32(p.To.Offset&31) << 10 3725 } else { 3726 o1 |= 0x1F << 10 3727 } 3728 o1 |= uint32(p.To.Reg & 31) 3729 3730 case 59: /* stxr/stlxr/stxp/stlxp */ 3731 s := p.RegTo2 3732 n := p.To.Reg 3733 t := p.From.Reg 3734 if isSTLXRop(p.As) { 3735 if s == t || (s == n && n != REGSP) { 3736 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3737 } 3738 } else if isSTXPop(p.As) { 3739 t2 := int16(p.From.Offset) 3740 if (s == t || s == t2) || (s == n && n != REGSP) { 3741 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3742 } 3743 } 3744 o1 = c.opstore(p, p.As) 3745 3746 if p.RegTo2 != obj.REG_NONE { 3747 o1 |= uint32(p.RegTo2&31) << 16 3748 } else { 3749 o1 |= 0x1F << 16 3750 } 3751 if isSTXPop(p.As) { 3752 o1 |= uint32(p.From.Offset&31) << 10 3753 } 3754 o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31) 3755 3756 case 60: /* adrp label,r */ 3757 d := c.brdist(p, 12, 21, 0) 3758 3759 o1 = ADR(1, uint32(d), uint32(p.To.Reg)) 3760 3761 case 61: /* adr label, r */ 3762 d := c.brdist(p, 0, 21, 0) 3763 3764 o1 = ADR(0, uint32(d), uint32(p.To.Reg)) 3765 3766 case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */ 3767 if p.Reg == REGTMP { 3768 c.ctxt.Diag("cannot use REGTMP as source: %v\n", p) 3769 } 3770 if isADDWop(p.As) || isANDWop(p.As) { 3771 o1 = c.omovconst(AMOVW, p, &p.From, REGTMP) 3772 } else { 3773 o1 = c.omovconst(AMOVD, p, &p.From, REGTMP) 3774 } 3775 3776 rt := int(p.To.Reg) 3777 if p.To.Type == obj.TYPE_NONE { 3778 rt = REGZERO 3779 } 3780 r := int(p.Reg) 3781 if r == 0 { 3782 r = rt 3783 } 3784 if p.To.Reg == REGSP || r == REGSP { 3785 o2 = c.opxrrr(p, p.As, false) 3786 o2 |= REGTMP & 31 << 16 3787 o2 |= LSL0_64 3788 } else { 3789 o2 = c.oprrr(p, p.As) 3790 o2 |= REGTMP & 31 << 16 /* shift is 0 */ 3791 } 3792 o2 |= uint32(r&31) << 5 3793 o2 |= uint32(rt & 31) 3794 3795 /* reloc ops */ 3796 case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */ 3797 o1 = ADR(1, 0, REGTMP) 3798 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 3799 rel := obj.Addrel(c.cursym) 3800 rel.Off = int32(c.pc) 3801 rel.Siz = 8 3802 rel.Sym = p.To.Sym 3803 rel.Add = p.To.Offset 3804 rel.Type = objabi.R_ADDRARM64 3805 o3 = c.olsr12u(p, int32(c.opstr12(p, p.As)), 0, REGTMP, int(p.From.Reg)) 3806 3807 case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */ 3808 o1 = ADR(1, 0, REGTMP) 3809 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 3810 rel := obj.Addrel(c.cursym) 3811 rel.Off = int32(c.pc) 3812 rel.Siz = 8 3813 rel.Sym = p.From.Sym 3814 rel.Add = p.From.Offset 3815 rel.Type = objabi.R_ADDRARM64 3816 o3 = c.olsr12u(p, int32(c.opldr12(p, p.As)), 0, REGTMP, int(p.To.Reg)) 3817 3818 case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */ 3819 v := int32(c.regoff(&p.From)) 3820 r := int(p.From.Reg) 3821 if r == obj.REG_NONE { 3822 r = int(o.param) 3823 } 3824 if r == obj.REG_NONE { 3825 c.ctxt.Diag("invalid ldp source: %v\n", p) 3826 } 3827 o1 |= c.opldpstp(p, o, v, uint32(r), uint32(p.To.Reg), uint32(p.To.Offset), 1) 3828 3829 case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */ 3830 r := int(p.To.Reg) 3831 if r == obj.REG_NONE { 3832 r = int(o.param) 3833 } 3834 if r == obj.REG_NONE { 3835 c.ctxt.Diag("invalid stp destination: %v\n", p) 3836 } 3837 v := int32(c.regoff(&p.To)) 3838 o1 = c.opldpstp(p, o, v, uint32(r), uint32(p.From.Reg), uint32(p.From.Offset), 0) 3839 3840 case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */ 3841 if p.As == AMOVW { 3842 c.ctxt.Diag("invalid load of 32-bit address: %v", p) 3843 } 3844 o1 = ADR(1, 0, uint32(p.To.Reg)) 3845 o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31) 3846 rel := obj.Addrel(c.cursym) 3847 rel.Off = int32(c.pc) 3848 rel.Siz = 8 3849 rel.Sym = p.From.Sym 3850 rel.Add = p.From.Offset 3851 rel.Type = objabi.R_ADDRARM64 3852 3853 case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */ 3854 o1 = c.opirr(p, AMOVZ) 3855 o1 |= uint32(p.To.Reg & 31) 3856 rel := obj.Addrel(c.cursym) 3857 rel.Off = int32(c.pc) 3858 rel.Siz = 4 3859 rel.Sym = p.From.Sym 3860 rel.Type = objabi.R_ARM64_TLS_LE 3861 if p.From.Offset != 0 { 3862 c.ctxt.Diag("invalid offset on MOVW $tlsvar") 3863 } 3864 3865 case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */ 3866 o1 = ADR(1, 0, REGTMP) 3867 o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg)) 3868 rel := obj.Addrel(c.cursym) 3869 rel.Off = int32(c.pc) 3870 rel.Siz = 8 3871 rel.Sym = p.From.Sym 3872 rel.Add = 0 3873 rel.Type = objabi.R_ARM64_TLS_IE 3874 if p.From.Offset != 0 { 3875 c.ctxt.Diag("invalid offset on MOVW $tlsvar") 3876 } 3877 3878 case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */ 3879 o1 = ADR(1, 0, REGTMP) 3880 o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg)) 3881 rel := obj.Addrel(c.cursym) 3882 rel.Off = int32(c.pc) 3883 rel.Siz = 8 3884 rel.Sym = p.From.Sym 3885 rel.Add = 0 3886 rel.Type = objabi.R_ARM64_GOTPCREL 3887 3888 case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor/vfmla/vfmls Vm.<T>, Vn.<T>, Vd.<T> */ 3889 af := int((p.From.Reg >> 5) & 15) 3890 af3 := int((p.Reg >> 5) & 15) 3891 at := int((p.To.Reg >> 5) & 15) 3892 if af != af3 || af != at { 3893 c.ctxt.Diag("operand mismatch: %v", p) 3894 break 3895 } 3896 o1 = c.oprrr(p, p.As) 3897 rf := int((p.From.Reg) & 31) 3898 rt := int((p.To.Reg) & 31) 3899 r := int((p.Reg) & 31) 3900 3901 Q := 0 3902 size := 0 3903 switch af { 3904 case ARNG_16B: 3905 Q = 1 3906 size = 0 3907 case ARNG_2D: 3908 Q = 1 3909 size = 3 3910 case ARNG_2S: 3911 Q = 0 3912 size = 2 3913 case ARNG_4H: 3914 Q = 0 3915 size = 1 3916 case ARNG_4S: 3917 Q = 1 3918 size = 2 3919 case ARNG_8B: 3920 Q = 0 3921 size = 0 3922 case ARNG_8H: 3923 Q = 1 3924 size = 1 3925 default: 3926 c.ctxt.Diag("invalid arrangement: %v", p) 3927 } 3928 3929 if (p.As == AVORR || p.As == AVAND || p.As == AVEOR) && 3930 (af != ARNG_16B && af != ARNG_8B) { 3931 c.ctxt.Diag("invalid arrangement: %v", p) 3932 } else if (p.As == AVFMLA || p.As == AVFMLS) && 3933 (af != ARNG_2D && af != ARNG_2S && af != ARNG_4S) { 3934 c.ctxt.Diag("invalid arrangement: %v", p) 3935 } else if p.As == AVORR { 3936 size = 2 3937 } else if p.As == AVAND || p.As == AVEOR { 3938 size = 0 3939 } else if p.As == AVFMLA || p.As == AVFMLS { 3940 if af == ARNG_2D { 3941 size = 1 3942 } else { 3943 size = 0 3944 } 3945 } 3946 3947 o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 3948 3949 case 73: /* vmov V.<T>[index], R */ 3950 rf := int(p.From.Reg) 3951 rt := int(p.To.Reg) 3952 imm5 := 0 3953 o1 = 7<<25 | 0xf<<10 3954 index := int(p.From.Index) 3955 switch (p.From.Reg >> 5) & 15 { 3956 case ARNG_B: 3957 c.checkindex(p, index, 15) 3958 imm5 |= 1 3959 imm5 |= index << 1 3960 case ARNG_H: 3961 c.checkindex(p, index, 7) 3962 imm5 |= 2 3963 imm5 |= index << 2 3964 case ARNG_S: 3965 c.checkindex(p, index, 3) 3966 imm5 |= 4 3967 imm5 |= index << 3 3968 case ARNG_D: 3969 c.checkindex(p, index, 1) 3970 imm5 |= 8 3971 imm5 |= index << 4 3972 o1 |= 1 << 30 3973 default: 3974 c.ctxt.Diag("invalid arrangement: %v", p) 3975 } 3976 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 3977 3978 case 74: 3979 // add $O, R, Rtmp or sub $O, R, Rtmp 3980 // ldp (Rtmp), (R1, R2) 3981 r := int(p.From.Reg) 3982 if r == obj.REG_NONE { 3983 r = int(o.param) 3984 } 3985 if r == obj.REG_NONE { 3986 c.ctxt.Diag("invalid ldp source: %v", p) 3987 } 3988 v := int32(c.regoff(&p.From)) 3989 3990 if v > 0 { 3991 if v > 4095 { 3992 c.ctxt.Diag("offset out of range: %v", p) 3993 } 3994 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP) 3995 } 3996 if v < 0 { 3997 if v < -4095 { 3998 c.ctxt.Diag("offset out of range: %v", p) 3999 } 4000 o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP) 4001 } 4002 o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1) 4003 4004 case 75: 4005 // mov $L, Rtmp (from constant pool) 4006 // add Rtmp, R, Rtmp 4007 // ldp (Rtmp), (R1, R2) 4008 r := int(p.From.Reg) 4009 if r == obj.REG_NONE { 4010 r = int(o.param) 4011 } 4012 if r == obj.REG_NONE { 4013 c.ctxt.Diag("invalid ldp source: %v", p) 4014 } 4015 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 4016 o2 = c.opxrrr(p, AADD, false) 4017 o2 |= (REGTMP & 31) << 16 4018 o2 |= uint32(r&31) << 5 4019 o2 |= uint32(REGTMP & 31) 4020 o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1) 4021 4022 case 76: 4023 // add $O, R, Rtmp or sub $O, R, Rtmp 4024 // stp (R1, R2), (Rtmp) 4025 r := int(p.To.Reg) 4026 if r == obj.REG_NONE { 4027 r = int(o.param) 4028 } 4029 if r == obj.REG_NONE { 4030 c.ctxt.Diag("invalid stp destination: %v", p) 4031 } 4032 v := int32(c.regoff(&p.To)) 4033 if v > 0 { 4034 if v > 4095 { 4035 c.ctxt.Diag("offset out of range: %v", p) 4036 } 4037 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP) 4038 } 4039 if v < 0 { 4040 if v < -4095 { 4041 c.ctxt.Diag("offset out of range: %v", p) 4042 } 4043 o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP) 4044 } 4045 o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0) 4046 4047 case 77: 4048 // mov $L, Rtmp (from constant pool) 4049 // add Rtmp, R, Rtmp 4050 // stp (R1, R2), (Rtmp) 4051 r := int(p.To.Reg) 4052 if r == obj.REG_NONE { 4053 r = int(o.param) 4054 } 4055 if r == obj.REG_NONE { 4056 c.ctxt.Diag("invalid stp destination: %v", p) 4057 } 4058 o1 = c.omovlit(AMOVD, p, &p.To, REGTMP) 4059 o2 = c.opxrrr(p, AADD, false) 4060 o2 |= REGTMP & 31 << 16 4061 o2 |= uint32(r&31) << 5 4062 o2 |= uint32(REGTMP & 31) 4063 o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0) 4064 4065 case 78: /* vmov R, V.<T>[index] */ 4066 rf := int(p.From.Reg) 4067 rt := int(p.To.Reg) 4068 imm5 := 0 4069 o1 = 1<<30 | 7<<25 | 7<<10 4070 index := int(p.To.Index) 4071 switch (p.To.Reg >> 5) & 15 { 4072 case ARNG_B: 4073 c.checkindex(p, index, 15) 4074 imm5 |= 1 4075 imm5 |= index << 1 4076 case ARNG_H: 4077 c.checkindex(p, index, 7) 4078 imm5 |= 2 4079 imm5 |= index << 2 4080 case ARNG_S: 4081 c.checkindex(p, index, 3) 4082 imm5 |= 4 4083 imm5 |= index << 3 4084 case ARNG_D: 4085 c.checkindex(p, index, 1) 4086 imm5 |= 8 4087 imm5 |= index << 4 4088 default: 4089 c.ctxt.Diag("invalid arrangement: %v", p) 4090 } 4091 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 4092 4093 case 79: /* vdup Vn.<T>[index], Vd.<T> */ 4094 rf := int(p.From.Reg) 4095 rt := int(p.To.Reg) 4096 o1 = 7<<25 | 1<<10 4097 var imm5, Q int 4098 index := int(p.From.Index) 4099 switch (p.To.Reg >> 5) & 15 { 4100 case ARNG_16B: 4101 c.checkindex(p, index, 15) 4102 Q = 1 4103 imm5 = 1 4104 imm5 |= index << 1 4105 case ARNG_2D: 4106 c.checkindex(p, index, 1) 4107 Q = 1 4108 imm5 = 8 4109 imm5 |= index << 4 4110 case ARNG_2S: 4111 c.checkindex(p, index, 3) 4112 Q = 0 4113 imm5 = 4 4114 imm5 |= index << 3 4115 case ARNG_4H: 4116 c.checkindex(p, index, 7) 4117 Q = 0 4118 imm5 = 2 4119 imm5 |= index << 2 4120 case ARNG_4S: 4121 c.checkindex(p, index, 3) 4122 Q = 1 4123 imm5 = 4 4124 imm5 |= index << 3 4125 case ARNG_8B: 4126 c.checkindex(p, index, 15) 4127 Q = 0 4128 imm5 = 1 4129 imm5 |= index << 1 4130 case ARNG_8H: 4131 c.checkindex(p, index, 7) 4132 Q = 1 4133 imm5 = 2 4134 imm5 |= index << 2 4135 default: 4136 c.ctxt.Diag("invalid arrangement: %v", p) 4137 } 4138 o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16) 4139 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 4140 4141 case 80: /* vmov V.<T>[index], Vn */ 4142 rf := int(p.From.Reg) 4143 rt := int(p.To.Reg) 4144 imm5 := 0 4145 index := int(p.From.Index) 4146 switch p.As { 4147 case AVMOV: 4148 o1 = 1<<30 | 15<<25 | 1<<10 4149 switch (p.From.Reg >> 5) & 15 { 4150 case ARNG_B: 4151 c.checkindex(p, index, 15) 4152 imm5 |= 1 4153 imm5 |= index << 1 4154 case ARNG_H: 4155 c.checkindex(p, index, 7) 4156 imm5 |= 2 4157 imm5 |= index << 2 4158 case ARNG_S: 4159 c.checkindex(p, index, 3) 4160 imm5 |= 4 4161 imm5 |= index << 3 4162 case ARNG_D: 4163 c.checkindex(p, index, 1) 4164 imm5 |= 8 4165 imm5 |= index << 4 4166 default: 4167 c.ctxt.Diag("invalid arrangement: %v", p) 4168 } 4169 default: 4170 c.ctxt.Diag("unsupported op %v", p.As) 4171 } 4172 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 4173 4174 case 81: /* vld1 (Rn), [Vt1.<T>, Vt2.<T>, ...] */ 4175 r := int(p.From.Reg) 4176 o1 = 3<<26 | 1<<22 4177 if o.scond == C_XPOST { 4178 o1 |= 1 << 23 4179 if p.From.Index == 0 { 4180 // immediate offset variant 4181 c.checkoffset(p, p.As) 4182 o1 |= 0x1f << 16 4183 } else { 4184 // register offset variant 4185 if isRegShiftOrExt(&p.From) { 4186 c.ctxt.Diag("invalid extended register op: %v\n", p) 4187 } 4188 o1 |= uint32(p.From.Index&31) << 16 4189 } 4190 } 4191 o1 |= uint32(p.To.Offset) 4192 o1 |= uint32(r&31) << 5 4193 4194 case 82: /* vmov Rn, Vd.<T> */ 4195 rf := int(p.From.Reg) 4196 rt := int(p.To.Reg) 4197 o1 = 7<<25 | 3<<10 4198 var imm5, Q uint32 4199 switch (p.To.Reg >> 5) & 15 { 4200 case ARNG_16B: 4201 Q = 1 4202 imm5 = 1 4203 case ARNG_2D: 4204 Q = 1 4205 imm5 = 8 4206 case ARNG_2S: 4207 Q = 0 4208 imm5 = 4 4209 case ARNG_4H: 4210 Q = 0 4211 imm5 = 2 4212 case ARNG_4S: 4213 Q = 1 4214 imm5 = 4 4215 case ARNG_8B: 4216 Q = 0 4217 imm5 = 1 4218 case ARNG_8H: 4219 Q = 1 4220 imm5 = 2 4221 default: 4222 c.ctxt.Diag("invalid arrangement on VMOV Rn, Vd.<T>: %v\n", p) 4223 } 4224 o1 |= (Q & 1 << 30) | (imm5 & 0x1f << 16) 4225 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 4226 4227 case 83: /* vmov Vn.<T>, Vd.<T> */ 4228 af := int((p.From.Reg >> 5) & 15) 4229 at := int((p.To.Reg >> 5) & 15) 4230 if af != at { 4231 c.ctxt.Diag("invalid arrangement: %v\n", p) 4232 } 4233 o1 = c.oprrr(p, p.As) 4234 rf := int((p.From.Reg) & 31) 4235 rt := int((p.To.Reg) & 31) 4236 4237 var Q, size uint32 4238 switch af { 4239 case ARNG_8B: 4240 Q = 0 4241 size = 0 4242 case ARNG_16B: 4243 Q = 1 4244 size = 0 4245 case ARNG_4H: 4246 Q = 0 4247 size = 1 4248 case ARNG_8H: 4249 Q = 1 4250 size = 1 4251 case ARNG_2S: 4252 Q = 0 4253 size = 2 4254 case ARNG_4S: 4255 Q = 1 4256 size = 2 4257 default: 4258 c.ctxt.Diag("invalid arrangement: %v\n", p) 4259 } 4260 4261 if (p.As == AVMOV || p.As == AVRBIT) && (af != ARNG_16B && af != ARNG_8B) { 4262 c.ctxt.Diag("invalid arrangement: %v", p) 4263 } 4264 4265 if p.As == AVREV32 && (af == ARNG_2S || af == ARNG_4S) { 4266 c.ctxt.Diag("invalid arrangement: %v", p) 4267 } 4268 4269 if p.As == AVMOV { 4270 o1 |= uint32(rf&31) << 16 4271 } 4272 4273 if p.As == AVRBIT { 4274 size = 1 4275 } 4276 4277 o1 |= (Q&1)<<30 | (size&3)<<22 | uint32(rf&31)<<5 | uint32(rt&31) 4278 4279 case 84: /* vst1 [Vt1.<T>, Vt2.<T>, ...], (Rn) */ 4280 r := int(p.To.Reg) 4281 o1 = 3 << 26 4282 if o.scond == C_XPOST { 4283 o1 |= 1 << 23 4284 if p.To.Index == 0 { 4285 // immediate offset variant 4286 c.checkoffset(p, p.As) 4287 o1 |= 0x1f << 16 4288 } else { 4289 // register offset variant 4290 if isRegShiftOrExt(&p.To) { 4291 c.ctxt.Diag("invalid extended register: %v\n", p) 4292 } 4293 o1 |= uint32(p.To.Index&31) << 16 4294 } 4295 } 4296 o1 |= uint32(p.From.Offset) 4297 o1 |= uint32(r&31) << 5 4298 4299 case 85: /* vaddv/vuaddlv Vn.<T>, Vd*/ 4300 af := int((p.From.Reg >> 5) & 15) 4301 o1 = c.oprrr(p, p.As) 4302 rf := int((p.From.Reg) & 31) 4303 rt := int((p.To.Reg) & 31) 4304 Q := 0 4305 size := 0 4306 switch af { 4307 case ARNG_8B: 4308 Q = 0 4309 size = 0 4310 case ARNG_16B: 4311 Q = 1 4312 size = 0 4313 case ARNG_4H: 4314 Q = 0 4315 size = 1 4316 case ARNG_8H: 4317 Q = 1 4318 size = 1 4319 case ARNG_4S: 4320 Q = 1 4321 size = 2 4322 default: 4323 c.ctxt.Diag("invalid arrangement: %v\n", p) 4324 } 4325 o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31) 4326 4327 case 86: /* vmovi $imm8, Vd.<T>*/ 4328 at := int((p.To.Reg >> 5) & 15) 4329 r := int(p.From.Offset) 4330 if r > 255 || r < 0 { 4331 c.ctxt.Diag("immediate constant out of range: %v\n", p) 4332 } 4333 rt := int((p.To.Reg) & 31) 4334 Q := 0 4335 switch at { 4336 case ARNG_8B: 4337 Q = 0 4338 case ARNG_16B: 4339 Q = 1 4340 default: 4341 c.ctxt.Diag("invalid arrangement: %v\n", p) 4342 } 4343 o1 = 0xf<<24 | 0xe<<12 | 1<<10 4344 o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31) 4345 4346 case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */ 4347 o1 = ADR(1, 0, REGTMP) 4348 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 4349 rel := obj.Addrel(c.cursym) 4350 rel.Off = int32(c.pc) 4351 rel.Siz = 8 4352 rel.Sym = p.To.Sym 4353 rel.Add = p.To.Offset 4354 rel.Type = objabi.R_ADDRARM64 4355 o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0) 4356 4357 case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */ 4358 o1 = ADR(1, 0, REGTMP) 4359 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 4360 rel := obj.Addrel(c.cursym) 4361 rel.Off = int32(c.pc) 4362 rel.Siz = 8 4363 rel.Sym = p.From.Sym 4364 rel.Add = p.From.Offset 4365 rel.Type = objabi.R_ADDRARM64 4366 o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1) 4367 4368 case 89: /* vadd/vsub Vm, Vn, Vd */ 4369 switch p.As { 4370 case AVADD: 4371 o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10 4372 4373 case AVSUB: 4374 o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10 4375 4376 default: 4377 c.ctxt.Diag("bad opcode: %v\n", p) 4378 break 4379 } 4380 4381 rf := int(p.From.Reg) 4382 rt := int(p.To.Reg) 4383 r := int(p.Reg) 4384 if r == 0 { 4385 r = rt 4386 } 4387 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 4388 4389 // This is supposed to be something that stops execution. 4390 // It's not supposed to be reached, ever, but if it is, we'd 4391 // like to be able to tell how we got there. Assemble as 4392 // 0xbea71700 which is guaranteed to raise undefined instruction 4393 // exception. 4394 case 90: 4395 o1 = 0xbea71700 4396 4397 case 91: /* prfm imm(Rn), <prfop | $imm5> */ 4398 imm := uint32(p.From.Offset) 4399 r := p.From.Reg 4400 v := uint32(0xff) 4401 if p.To.Type == obj.TYPE_CONST { 4402 v = uint32(p.To.Offset) 4403 if v > 31 { 4404 c.ctxt.Diag("illegal prefetch operation\n%v", p) 4405 } 4406 } else { 4407 for i := 0; i < len(prfopfield); i++ { 4408 if prfopfield[i].reg == p.To.Reg { 4409 v = prfopfield[i].enc 4410 break 4411 } 4412 } 4413 if v == 0xff { 4414 c.ctxt.Diag("illegal prefetch operation:\n%v", p) 4415 } 4416 } 4417 4418 o1 = c.opldrpp(p, p.As) 4419 o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31)) 4420 4421 case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */ 4422 rf := int(p.From.Reg) 4423 rt := int(p.To.Reg) 4424 imm4 := 0 4425 imm5 := 0 4426 o1 = 3<<29 | 7<<25 | 1<<10 4427 index1 := int(p.To.Index) 4428 index2 := int(p.From.Index) 4429 if ((p.To.Reg >> 5) & 15) != ((p.From.Reg >> 5) & 15) { 4430 c.ctxt.Diag("operand mismatch: %v", p) 4431 } 4432 switch (p.To.Reg >> 5) & 15 { 4433 case ARNG_B: 4434 c.checkindex(p, index1, 15) 4435 c.checkindex(p, index2, 15) 4436 imm5 |= 1 4437 imm5 |= index1 << 1 4438 imm4 |= index2 4439 case ARNG_H: 4440 c.checkindex(p, index1, 7) 4441 c.checkindex(p, index2, 7) 4442 imm5 |= 2 4443 imm5 |= index1 << 2 4444 imm4 |= index2 << 1 4445 case ARNG_S: 4446 c.checkindex(p, index1, 3) 4447 c.checkindex(p, index2, 3) 4448 imm5 |= 4 4449 imm5 |= index1 << 3 4450 imm4 |= index2 << 2 4451 case ARNG_D: 4452 c.checkindex(p, index1, 1) 4453 c.checkindex(p, index2, 1) 4454 imm5 |= 8 4455 imm5 |= index1 << 4 4456 imm4 |= index2 << 3 4457 default: 4458 c.ctxt.Diag("invalid arrangement: %v", p) 4459 } 4460 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(imm4&0xf) << 11) | (uint32(rf&31) << 5) | uint32(rt&31) 4461 4462 case 93: /* vpmull{2} Vm.<T>, Vn.<T>, Vd */ 4463 af := int((p.From.Reg >> 5) & 15) 4464 at := int((p.To.Reg >> 5) & 15) 4465 a := int((p.Reg >> 5) & 15) 4466 4467 var Q, size uint32 4468 if p.As == AVPMULL { 4469 Q = 0 4470 } else { 4471 Q = 1 4472 } 4473 4474 var fArng int 4475 switch at { 4476 case ARNG_8H: 4477 if Q == 0 { 4478 fArng = ARNG_8B 4479 } else { 4480 fArng = ARNG_16B 4481 } 4482 size = 0 4483 case ARNG_1Q: 4484 if Q == 0 { 4485 fArng = ARNG_1D 4486 } else { 4487 fArng = ARNG_2D 4488 } 4489 size = 3 4490 default: 4491 c.ctxt.Diag("invalid arrangement on Vd.<T>: %v", p) 4492 } 4493 4494 if af != a || af != fArng { 4495 c.ctxt.Diag("invalid arrangement: %v", p) 4496 } 4497 4498 o1 = c.oprrr(p, p.As) 4499 rf := int((p.From.Reg) & 31) 4500 rt := int((p.To.Reg) & 31) 4501 r := int((p.Reg) & 31) 4502 4503 o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 4504 4505 case 94: /* vext $imm4, Vm.<T>, Vn.<T>, Vd.<T> */ 4506 af := int(((p.GetFrom3().Reg) >> 5) & 15) 4507 at := int((p.To.Reg >> 5) & 15) 4508 a := int((p.Reg >> 5) & 15) 4509 index := int(p.From.Offset) 4510 4511 if af != a || af != at { 4512 c.ctxt.Diag("invalid arrangement: %v", p) 4513 break 4514 } 4515 4516 var Q uint32 4517 var b int 4518 if af == ARNG_8B { 4519 Q = 0 4520 b = 7 4521 } else if af == ARNG_16B { 4522 Q = 1 4523 b = 15 4524 } else { 4525 c.ctxt.Diag("invalid arrangement, should be 8B or 16B: %v", p) 4526 break 4527 } 4528 4529 if index < 0 || index > b { 4530 c.ctxt.Diag("illegal offset: %v", p) 4531 } 4532 4533 o1 = c.opirr(p, p.As) 4534 rf := int((p.GetFrom3().Reg) & 31) 4535 rt := int((p.To.Reg) & 31) 4536 r := int((p.Reg) & 31) 4537 4538 o1 |= ((Q & 1) << 30) | (uint32(r&31) << 16) | (uint32(index&15) << 11) | (uint32(rf&31) << 5) | uint32(rt&31) 4539 4540 case 95: /* vushr $shift, Vn.<T>, Vd.<T> */ 4541 at := int((p.To.Reg >> 5) & 15) 4542 af := int((p.Reg >> 5) & 15) 4543 shift := int(p.From.Offset) 4544 4545 if af != at { 4546 c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p) 4547 } 4548 4549 var Q uint32 4550 var imax, esize int 4551 4552 switch af { 4553 case ARNG_8B, ARNG_4H, ARNG_2S: 4554 Q = 0 4555 case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D: 4556 Q = 1 4557 default: 4558 c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p) 4559 } 4560 4561 switch af { 4562 case ARNG_8B, ARNG_16B: 4563 imax = 15 4564 esize = 8 4565 case ARNG_4H, ARNG_8H: 4566 imax = 31 4567 esize = 16 4568 case ARNG_2S, ARNG_4S: 4569 imax = 63 4570 esize = 32 4571 case ARNG_2D: 4572 imax = 127 4573 esize = 64 4574 } 4575 4576 imm := 0 4577 4578 switch p.As { 4579 case AVUSHR, AVSRI: 4580 imm = esize*2 - shift 4581 if imm < esize || imm > imax { 4582 c.ctxt.Diag("shift out of range: %v", p) 4583 } 4584 case AVSHL: 4585 imm = esize + shift 4586 if imm > imax { 4587 c.ctxt.Diag("shift out of range: %v", p) 4588 } 4589 default: 4590 c.ctxt.Diag("invalid instruction %v\n", p) 4591 } 4592 4593 o1 = c.opirr(p, p.As) 4594 rt := int((p.To.Reg) & 31) 4595 rf := int((p.Reg) & 31) 4596 4597 o1 |= ((Q & 1) << 30) | (uint32(imm&127) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 4598 4599 case 96: /* vst1 Vt1.<T>[index], offset(Rn) */ 4600 af := int((p.From.Reg >> 5) & 15) 4601 rt := int((p.From.Reg) & 31) 4602 rf := int((p.To.Reg) & 31) 4603 r := int(p.To.Index & 31) 4604 index := int(p.From.Index) 4605 offset := int32(c.regoff(&p.To)) 4606 4607 if o.scond == C_XPOST { 4608 if (p.To.Index != 0) && (offset != 0) { 4609 c.ctxt.Diag("invalid offset: %v", p) 4610 } 4611 if p.To.Index == 0 && offset == 0 { 4612 c.ctxt.Diag("invalid offset: %v", p) 4613 } 4614 } 4615 4616 if offset != 0 { 4617 r = 31 4618 } 4619 4620 var Q, S, size int 4621 var opcode uint32 4622 switch af { 4623 case ARNG_B: 4624 c.checkindex(p, index, 15) 4625 if o.scond == C_XPOST && offset != 0 && offset != 1 { 4626 c.ctxt.Diag("invalid offset: %v", p) 4627 } 4628 Q = index >> 3 4629 S = (index >> 2) & 1 4630 size = index & 3 4631 opcode = 0 4632 case ARNG_H: 4633 c.checkindex(p, index, 7) 4634 if o.scond == C_XPOST && offset != 0 && offset != 2 { 4635 c.ctxt.Diag("invalid offset: %v", p) 4636 } 4637 Q = index >> 2 4638 S = (index >> 1) & 1 4639 size = (index & 1) << 1 4640 opcode = 2 4641 case ARNG_S: 4642 c.checkindex(p, index, 3) 4643 if o.scond == C_XPOST && offset != 0 && offset != 4 { 4644 c.ctxt.Diag("invalid offset: %v", p) 4645 } 4646 Q = index >> 1 4647 S = index & 1 4648 size = 0 4649 opcode = 4 4650 case ARNG_D: 4651 c.checkindex(p, index, 1) 4652 if o.scond == C_XPOST && offset != 0 && offset != 8 { 4653 c.ctxt.Diag("invalid offset: %v", p) 4654 } 4655 Q = index 4656 S = 0 4657 size = 1 4658 opcode = 4 4659 default: 4660 c.ctxt.Diag("invalid arrangement: %v", p) 4661 } 4662 4663 if o.scond == C_XPOST { 4664 o1 |= 27 << 23 4665 } else { 4666 o1 |= 26 << 23 4667 } 4668 4669 o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31) 4670 4671 case 97: /* vld1 offset(Rn), vt.<T>[index] */ 4672 at := int((p.To.Reg >> 5) & 15) 4673 rt := int((p.To.Reg) & 31) 4674 rf := int((p.From.Reg) & 31) 4675 r := int(p.From.Index & 31) 4676 index := int(p.To.Index) 4677 offset := int32(c.regoff(&p.From)) 4678 4679 if o.scond == C_XPOST { 4680 if (p.From.Index != 0) && (offset != 0) { 4681 c.ctxt.Diag("invalid offset: %v", p) 4682 } 4683 if p.From.Index == 0 && offset == 0 { 4684 c.ctxt.Diag("invalid offset: %v", p) 4685 } 4686 } 4687 4688 if offset != 0 { 4689 r = 31 4690 } 4691 4692 Q := 0 4693 S := 0 4694 size := 0 4695 var opcode uint32 4696 switch at { 4697 case ARNG_B: 4698 c.checkindex(p, index, 15) 4699 if o.scond == C_XPOST && offset != 0 && offset != 1 { 4700 c.ctxt.Diag("invalid offset: %v", p) 4701 } 4702 Q = index >> 3 4703 S = (index >> 2) & 1 4704 size = index & 3 4705 opcode = 0 4706 case ARNG_H: 4707 c.checkindex(p, index, 7) 4708 if o.scond == C_XPOST && offset != 0 && offset != 2 { 4709 c.ctxt.Diag("invalid offset: %v", p) 4710 } 4711 Q = index >> 2 4712 S = (index >> 1) & 1 4713 size = (index & 1) << 1 4714 opcode = 2 4715 case ARNG_S: 4716 c.checkindex(p, index, 3) 4717 if o.scond == C_XPOST && offset != 0 && offset != 4 { 4718 c.ctxt.Diag("invalid offset: %v", p) 4719 } 4720 Q = index >> 1 4721 S = index & 1 4722 size = 0 4723 opcode = 4 4724 case ARNG_D: 4725 c.checkindex(p, index, 1) 4726 if o.scond == C_XPOST && offset != 0 && offset != 8 { 4727 c.ctxt.Diag("invalid offset: %v", p) 4728 } 4729 Q = index 4730 S = 0 4731 size = 1 4732 opcode = 4 4733 default: 4734 c.ctxt.Diag("invalid arrangement: %v", p) 4735 } 4736 4737 if o.scond == C_XPOST { 4738 o1 |= 110 << 21 4739 } else { 4740 o1 |= 106 << 21 4741 } 4742 4743 o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31) 4744 4745 case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */ 4746 if isRegShiftOrExt(&p.From) { 4747 // extended or shifted offset register. 4748 c.checkShiftAmount(p, &p.From) 4749 4750 o1 = c.opldrr(p, p.As, true) 4751 o1 |= c.encRegShiftOrExt(&p.From, p.From.Index) /* includes reg, op, etc */ 4752 } else { 4753 // (Rn)(Rm), no extension or shift. 4754 o1 = c.opldrr(p, p.As, false) 4755 o1 |= uint32(p.From.Index&31) << 16 4756 } 4757 o1 |= uint32(p.From.Reg&31) << 5 4758 rt := int(p.To.Reg) 4759 o1 |= uint32(rt & 31) 4760 4761 case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */ 4762 if isRegShiftOrExt(&p.To) { 4763 // extended or shifted offset register. 4764 c.checkShiftAmount(p, &p.To) 4765 4766 o1 = c.opstrr(p, p.As, true) 4767 o1 |= c.encRegShiftOrExt(&p.To, p.To.Index) /* includes reg, op, etc */ 4768 } else { 4769 // (Rn)(Rm), no extension or shift. 4770 o1 = c.opstrr(p, p.As, false) 4771 o1 |= uint32(p.To.Index&31) << 16 4772 } 4773 o1 |= uint32(p.To.Reg&31) << 5 4774 rf := int(p.From.Reg) 4775 o1 |= uint32(rf & 31) 4776 4777 case 100: /* VTBL Vn.<T>, [Vt1.<T>, Vt2.<T>, ...], Vd.<T> */ 4778 af := int((p.From.Reg >> 5) & 15) 4779 at := int((p.To.Reg >> 5) & 15) 4780 if af != at { 4781 c.ctxt.Diag("invalid arrangement: %v\n", p) 4782 } 4783 var q, len uint32 4784 switch af { 4785 case ARNG_8B: 4786 q = 0 4787 case ARNG_16B: 4788 q = 1 4789 default: 4790 c.ctxt.Diag("invalid arrangement: %v", p) 4791 } 4792 rf := int(p.From.Reg) 4793 rt := int(p.To.Reg) 4794 offset := int(p.GetFrom3().Offset) 4795 opcode := (offset >> 12) & 15 4796 switch opcode { 4797 case 0x7: 4798 len = 0 // one register 4799 case 0xa: 4800 len = 1 // two register 4801 case 0x6: 4802 len = 2 // three registers 4803 case 0x2: 4804 len = 3 // four registers 4805 default: 4806 c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p) 4807 } 4808 o1 = q<<30 | 0xe<<24 | len<<13 4809 o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31) 4810 4811 } 4812 out[0] = o1 4813 out[1] = o2 4814 out[2] = o3 4815 out[3] = o4 4816 out[4] = o5 4817 } 4818 4819 /* 4820 * basic Rm op Rn -> Rd (using shifted register with 0) 4821 * also op Rn -> Rt 4822 * also Rm*Rn op Ra -> Rd 4823 * also Vm op Vn -> Vd 4824 */ 4825 func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 { 4826 switch a { 4827 case AADC: 4828 return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 4829 4830 case AADCW: 4831 return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 4832 4833 case AADCS: 4834 return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 4835 4836 case AADCSW: 4837 return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 4838 4839 case ANGC, ASBC: 4840 return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 4841 4842 case ANGCS, ASBCS: 4843 return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 4844 4845 case ANGCW, ASBCW: 4846 return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 4847 4848 case ANGCSW, ASBCSW: 4849 return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 4850 4851 case AADD: 4852 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4853 4854 case AADDW: 4855 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4856 4857 case ACMN, AADDS: 4858 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4859 4860 case ACMNW, AADDSW: 4861 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4862 4863 case ASUB: 4864 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4865 4866 case ASUBW: 4867 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4868 4869 case ACMP, ASUBS: 4870 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4871 4872 case ACMPW, ASUBSW: 4873 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 4874 4875 case AAND: 4876 return S64 | 0<<29 | 0xA<<24 4877 4878 case AANDW: 4879 return S32 | 0<<29 | 0xA<<24 4880 4881 case AMOVD, AORR: 4882 return S64 | 1<<29 | 0xA<<24 4883 4884 // case AMOVW: 4885 case AMOVWU, AORRW: 4886 return S32 | 1<<29 | 0xA<<24 4887 4888 case AEOR: 4889 return S64 | 2<<29 | 0xA<<24 4890 4891 case AEORW: 4892 return S32 | 2<<29 | 0xA<<24 4893 4894 case AANDS, ATST: 4895 return S64 | 3<<29 | 0xA<<24 4896 4897 case AANDSW, ATSTW: 4898 return S32 | 3<<29 | 0xA<<24 4899 4900 case ABIC: 4901 return S64 | 0<<29 | 0xA<<24 | 1<<21 4902 4903 case ABICW: 4904 return S32 | 0<<29 | 0xA<<24 | 1<<21 4905 4906 case ABICS: 4907 return S64 | 3<<29 | 0xA<<24 | 1<<21 4908 4909 case ABICSW: 4910 return S32 | 3<<29 | 0xA<<24 | 1<<21 4911 4912 case AEON: 4913 return S64 | 2<<29 | 0xA<<24 | 1<<21 4914 4915 case AEONW: 4916 return S32 | 2<<29 | 0xA<<24 | 1<<21 4917 4918 case AMVN, AORN: 4919 return S64 | 1<<29 | 0xA<<24 | 1<<21 4920 4921 case AMVNW, AORNW: 4922 return S32 | 1<<29 | 0xA<<24 | 1<<21 4923 4924 case AASR: 4925 return S64 | OPDP2(10) /* also ASRV */ 4926 4927 case AASRW: 4928 return S32 | OPDP2(10) 4929 4930 case ALSL: 4931 return S64 | OPDP2(8) 4932 4933 case ALSLW: 4934 return S32 | OPDP2(8) 4935 4936 case ALSR: 4937 return S64 | OPDP2(9) 4938 4939 case ALSRW: 4940 return S32 | OPDP2(9) 4941 4942 case AROR: 4943 return S64 | OPDP2(11) 4944 4945 case ARORW: 4946 return S32 | OPDP2(11) 4947 4948 case ACCMN: 4949 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */ 4950 4951 case ACCMNW: 4952 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 4953 4954 case ACCMP: 4955 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 4956 4957 case ACCMPW: 4958 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 4959 4960 case ACRC32B: 4961 return S32 | OPDP2(16) 4962 4963 case ACRC32H: 4964 return S32 | OPDP2(17) 4965 4966 case ACRC32W: 4967 return S32 | OPDP2(18) 4968 4969 case ACRC32X: 4970 return S64 | OPDP2(19) 4971 4972 case ACRC32CB: 4973 return S32 | OPDP2(20) 4974 4975 case ACRC32CH: 4976 return S32 | OPDP2(21) 4977 4978 case ACRC32CW: 4979 return S32 | OPDP2(22) 4980 4981 case ACRC32CX: 4982 return S64 | OPDP2(23) 4983 4984 case ACSEL: 4985 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 4986 4987 case ACSELW: 4988 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 4989 4990 case ACSET: 4991 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 4992 4993 case ACSETW: 4994 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 4995 4996 case ACSETM: 4997 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 4998 4999 case ACSETMW: 5000 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 5001 5002 case ACINC, ACSINC: 5003 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 5004 5005 case ACINCW, ACSINCW: 5006 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 5007 5008 case ACINV, ACSINV: 5009 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 5010 5011 case ACINVW, ACSINVW: 5012 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 5013 5014 case ACNEG, ACSNEG: 5015 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 5016 5017 case ACNEGW, ACSNEGW: 5018 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 5019 5020 case AMUL, AMADD: 5021 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 5022 5023 case AMULW, AMADDW: 5024 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 5025 5026 case AMNEG, AMSUB: 5027 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 5028 5029 case AMNEGW, AMSUBW: 5030 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 5031 5032 case AMRS: 5033 return SYSOP(1, 2, 0, 0, 0, 0, 0) 5034 5035 case AMSR: 5036 return SYSOP(0, 2, 0, 0, 0, 0, 0) 5037 5038 case ANEG: 5039 return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 5040 5041 case ANEGW: 5042 return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 5043 5044 case ANEGS: 5045 return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 5046 5047 case ANEGSW: 5048 return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 5049 5050 case AREM, ASDIV: 5051 return S64 | OPDP2(3) 5052 5053 case AREMW, ASDIVW: 5054 return S32 | OPDP2(3) 5055 5056 case ASMULL, ASMADDL: 5057 return OPDP3(1, 0, 1, 0) 5058 5059 case ASMNEGL, ASMSUBL: 5060 return OPDP3(1, 0, 1, 1) 5061 5062 case ASMULH: 5063 return OPDP3(1, 0, 2, 0) 5064 5065 case AUMULL, AUMADDL: 5066 return OPDP3(1, 0, 5, 0) 5067 5068 case AUMNEGL, AUMSUBL: 5069 return OPDP3(1, 0, 5, 1) 5070 5071 case AUMULH: 5072 return OPDP3(1, 0, 6, 0) 5073 5074 case AUREM, AUDIV: 5075 return S64 | OPDP2(2) 5076 5077 case AUREMW, AUDIVW: 5078 return S32 | OPDP2(2) 5079 5080 case AAESE: 5081 return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10 5082 5083 case AAESD: 5084 return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10 5085 5086 case AAESMC: 5087 return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10 5088 5089 case AAESIMC: 5090 return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10 5091 5092 case ASHA1C: 5093 return 0x5E<<24 | 0<<12 5094 5095 case ASHA1P: 5096 return 0x5E<<24 | 1<<12 5097 5098 case ASHA1M: 5099 return 0x5E<<24 | 2<<12 5100 5101 case ASHA1SU0: 5102 return 0x5E<<24 | 3<<12 5103 5104 case ASHA256H: 5105 return 0x5E<<24 | 4<<12 5106 5107 case ASHA256H2: 5108 return 0x5E<<24 | 5<<12 5109 5110 case ASHA256SU1: 5111 return 0x5E<<24 | 6<<12 5112 5113 case ASHA1H: 5114 return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10 5115 5116 case ASHA1SU1: 5117 return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10 5118 5119 case ASHA256SU0: 5120 return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10 5121 5122 case AFCVTZSD: 5123 return FPCVTI(1, 0, 1, 3, 0) 5124 5125 case AFCVTZSDW: 5126 return FPCVTI(0, 0, 1, 3, 0) 5127 5128 case AFCVTZSS: 5129 return FPCVTI(1, 0, 0, 3, 0) 5130 5131 case AFCVTZSSW: 5132 return FPCVTI(0, 0, 0, 3, 0) 5133 5134 case AFCVTZUD: 5135 return FPCVTI(1, 0, 1, 3, 1) 5136 5137 case AFCVTZUDW: 5138 return FPCVTI(0, 0, 1, 3, 1) 5139 5140 case AFCVTZUS: 5141 return FPCVTI(1, 0, 0, 3, 1) 5142 5143 case AFCVTZUSW: 5144 return FPCVTI(0, 0, 0, 3, 1) 5145 5146 case ASCVTFD: 5147 return FPCVTI(1, 0, 1, 0, 2) 5148 5149 case ASCVTFS: 5150 return FPCVTI(1, 0, 0, 0, 2) 5151 5152 case ASCVTFWD: 5153 return FPCVTI(0, 0, 1, 0, 2) 5154 5155 case ASCVTFWS: 5156 return FPCVTI(0, 0, 0, 0, 2) 5157 5158 case AUCVTFD: 5159 return FPCVTI(1, 0, 1, 0, 3) 5160 5161 case AUCVTFS: 5162 return FPCVTI(1, 0, 0, 0, 3) 5163 5164 case AUCVTFWD: 5165 return FPCVTI(0, 0, 1, 0, 3) 5166 5167 case AUCVTFWS: 5168 return FPCVTI(0, 0, 0, 0, 3) 5169 5170 case AFADDS: 5171 return FPOP2S(0, 0, 0, 2) 5172 5173 case AFADDD: 5174 return FPOP2S(0, 0, 1, 2) 5175 5176 case AFSUBS: 5177 return FPOP2S(0, 0, 0, 3) 5178 5179 case AFSUBD: 5180 return FPOP2S(0, 0, 1, 3) 5181 5182 case AFMADDD: 5183 return FPOP3S(0, 0, 1, 0, 0) 5184 5185 case AFMADDS: 5186 return FPOP3S(0, 0, 0, 0, 0) 5187 5188 case AFMSUBD: 5189 return FPOP3S(0, 0, 1, 0, 1) 5190 5191 case AFMSUBS: 5192 return FPOP3S(0, 0, 0, 0, 1) 5193 5194 case AFNMADDD: 5195 return FPOP3S(0, 0, 1, 1, 0) 5196 5197 case AFNMADDS: 5198 return FPOP3S(0, 0, 0, 1, 0) 5199 5200 case AFNMSUBD: 5201 return FPOP3S(0, 0, 1, 1, 1) 5202 5203 case AFNMSUBS: 5204 return FPOP3S(0, 0, 0, 1, 1) 5205 5206 case AFMULS: 5207 return FPOP2S(0, 0, 0, 0) 5208 5209 case AFMULD: 5210 return FPOP2S(0, 0, 1, 0) 5211 5212 case AFDIVS: 5213 return FPOP2S(0, 0, 0, 1) 5214 5215 case AFDIVD: 5216 return FPOP2S(0, 0, 1, 1) 5217 5218 case AFMAXS: 5219 return FPOP2S(0, 0, 0, 4) 5220 5221 case AFMINS: 5222 return FPOP2S(0, 0, 0, 5) 5223 5224 case AFMAXD: 5225 return FPOP2S(0, 0, 1, 4) 5226 5227 case AFMIND: 5228 return FPOP2S(0, 0, 1, 5) 5229 5230 case AFMAXNMS: 5231 return FPOP2S(0, 0, 0, 6) 5232 5233 case AFMAXNMD: 5234 return FPOP2S(0, 0, 1, 6) 5235 5236 case AFMINNMS: 5237 return FPOP2S(0, 0, 0, 7) 5238 5239 case AFMINNMD: 5240 return FPOP2S(0, 0, 1, 7) 5241 5242 case AFNMULS: 5243 return FPOP2S(0, 0, 0, 8) 5244 5245 case AFNMULD: 5246 return FPOP2S(0, 0, 1, 8) 5247 5248 case AFCMPS: 5249 return FPCMP(0, 0, 0, 0, 0) 5250 5251 case AFCMPD: 5252 return FPCMP(0, 0, 1, 0, 0) 5253 5254 case AFCMPES: 5255 return FPCMP(0, 0, 0, 0, 16) 5256 5257 case AFCMPED: 5258 return FPCMP(0, 0, 1, 0, 16) 5259 5260 case AFCCMPS: 5261 return FPCCMP(0, 0, 0, 0) 5262 5263 case AFCCMPD: 5264 return FPCCMP(0, 0, 1, 0) 5265 5266 case AFCCMPES: 5267 return FPCCMP(0, 0, 0, 1) 5268 5269 case AFCCMPED: 5270 return FPCCMP(0, 0, 1, 1) 5271 5272 case AFCSELS: 5273 return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10 5274 5275 case AFCSELD: 5276 return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10 5277 5278 case AFMOVS: 5279 return FPOP1S(0, 0, 0, 0) 5280 5281 case AFABSS: 5282 return FPOP1S(0, 0, 0, 1) 5283 5284 case AFNEGS: 5285 return FPOP1S(0, 0, 0, 2) 5286 5287 case AFSQRTS: 5288 return FPOP1S(0, 0, 0, 3) 5289 5290 case AFCVTSD: 5291 return FPOP1S(0, 0, 0, 5) 5292 5293 case AFCVTSH: 5294 return FPOP1S(0, 0, 0, 7) 5295 5296 case AFRINTNS: 5297 return FPOP1S(0, 0, 0, 8) 5298 5299 case AFRINTPS: 5300 return FPOP1S(0, 0, 0, 9) 5301 5302 case AFRINTMS: 5303 return FPOP1S(0, 0, 0, 10) 5304 5305 case AFRINTZS: 5306 return FPOP1S(0, 0, 0, 11) 5307 5308 case AFRINTAS: 5309 return FPOP1S(0, 0, 0, 12) 5310 5311 case AFRINTXS: 5312 return FPOP1S(0, 0, 0, 14) 5313 5314 case AFRINTIS: 5315 return FPOP1S(0, 0, 0, 15) 5316 5317 case AFMOVD: 5318 return FPOP1S(0, 0, 1, 0) 5319 5320 case AFABSD: 5321 return FPOP1S(0, 0, 1, 1) 5322 5323 case AFNEGD: 5324 return FPOP1S(0, 0, 1, 2) 5325 5326 case AFSQRTD: 5327 return FPOP1S(0, 0, 1, 3) 5328 5329 case AFCVTDS: 5330 return FPOP1S(0, 0, 1, 4) 5331 5332 case AFCVTDH: 5333 return FPOP1S(0, 0, 1, 7) 5334 5335 case AFRINTND: 5336 return FPOP1S(0, 0, 1, 8) 5337 5338 case AFRINTPD: 5339 return FPOP1S(0, 0, 1, 9) 5340 5341 case AFRINTMD: 5342 return FPOP1S(0, 0, 1, 10) 5343 5344 case AFRINTZD: 5345 return FPOP1S(0, 0, 1, 11) 5346 5347 case AFRINTAD: 5348 return FPOP1S(0, 0, 1, 12) 5349 5350 case AFRINTXD: 5351 return FPOP1S(0, 0, 1, 14) 5352 5353 case AFRINTID: 5354 return FPOP1S(0, 0, 1, 15) 5355 5356 case AFCVTHS: 5357 return FPOP1S(0, 0, 3, 4) 5358 5359 case AFCVTHD: 5360 return FPOP1S(0, 0, 3, 5) 5361 5362 case AVADD: 5363 return 7<<25 | 1<<21 | 1<<15 | 1<<10 5364 5365 case AVADDP: 5366 return 7<<25 | 1<<21 | 1<<15 | 15<<10 5367 5368 case AVAND: 5369 return 7<<25 | 1<<21 | 7<<10 5370 5371 case AVCMEQ: 5372 return 1<<29 | 0x71<<21 | 0x23<<10 5373 5374 case AVCNT: 5375 return 0xE<<24 | 0x10<<17 | 5<<12 | 2<<10 5376 5377 case AVZIP1: 5378 return 0xE<<24 | 3<<12 | 2<<10 5379 5380 case AVZIP2: 5381 return 0xE<<24 | 1<<14 | 3<<12 | 2<<10 5382 5383 case AVEOR: 5384 return 1<<29 | 0x71<<21 | 7<<10 5385 5386 case AVORR: 5387 return 7<<25 | 5<<21 | 7<<10 5388 5389 case AVREV32: 5390 return 11<<26 | 2<<24 | 1<<21 | 1<<11 5391 5392 case AVREV64: 5393 return 3<<26 | 2<<24 | 1<<21 | 1<<11 5394 5395 case AVMOV: 5396 return 7<<25 | 5<<21 | 7<<10 5397 5398 case AVADDV: 5399 return 7<<25 | 3<<20 | 3<<15 | 7<<11 5400 5401 case AVUADDLV: 5402 return 1<<29 | 7<<25 | 3<<20 | 7<<11 5403 5404 case AVFMLA: 5405 return 7<<25 | 0<<23 | 1<<21 | 3<<14 | 3<<10 5406 5407 case AVFMLS: 5408 return 7<<25 | 1<<23 | 1<<21 | 3<<14 | 3<<10 5409 5410 case AVPMULL, AVPMULL2: 5411 return 0xE<<24 | 1<<21 | 0x38<<10 5412 5413 case AVRBIT: 5414 return 0x2E<<24 | 1<<22 | 0x10<<17 | 5<<12 | 2<<10 5415 } 5416 5417 c.ctxt.Diag("%v: bad rrr %d %v", p, a, a) 5418 return 0 5419 } 5420 5421 /* 5422 * imm -> Rd 5423 * imm op Rn -> Rd 5424 */ 5425 func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 { 5426 switch a { 5427 /* op $addcon, Rn, Rd */ 5428 case AMOVD, AADD: 5429 return S64 | 0<<30 | 0<<29 | 0x11<<24 5430 5431 case ACMN, AADDS: 5432 return S64 | 0<<30 | 1<<29 | 0x11<<24 5433 5434 case AMOVW, AADDW: 5435 return S32 | 0<<30 | 0<<29 | 0x11<<24 5436 5437 case ACMNW, AADDSW: 5438 return S32 | 0<<30 | 1<<29 | 0x11<<24 5439 5440 case ASUB: 5441 return S64 | 1<<30 | 0<<29 | 0x11<<24 5442 5443 case ACMP, ASUBS: 5444 return S64 | 1<<30 | 1<<29 | 0x11<<24 5445 5446 case ASUBW: 5447 return S32 | 1<<30 | 0<<29 | 0x11<<24 5448 5449 case ACMPW, ASUBSW: 5450 return S32 | 1<<30 | 1<<29 | 0x11<<24 5451 5452 /* op $imm(SB), Rd; op label, Rd */ 5453 case AADR: 5454 return 0<<31 | 0x10<<24 5455 5456 case AADRP: 5457 return 1<<31 | 0x10<<24 5458 5459 /* op $bimm, Rn, Rd */ 5460 case AAND, ABIC: 5461 return S64 | 0<<29 | 0x24<<23 5462 5463 case AANDW, ABICW: 5464 return S32 | 0<<29 | 0x24<<23 | 0<<22 5465 5466 case AORR, AORN: 5467 return S64 | 1<<29 | 0x24<<23 5468 5469 case AORRW, AORNW: 5470 return S32 | 1<<29 | 0x24<<23 | 0<<22 5471 5472 case AEOR, AEON: 5473 return S64 | 2<<29 | 0x24<<23 5474 5475 case AEORW, AEONW: 5476 return S32 | 2<<29 | 0x24<<23 | 0<<22 5477 5478 case AANDS, ABICS, ATST: 5479 return S64 | 3<<29 | 0x24<<23 5480 5481 case AANDSW, ABICSW, ATSTW: 5482 return S32 | 3<<29 | 0x24<<23 | 0<<22 5483 5484 case AASR: 5485 return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */ 5486 5487 case AASRW: 5488 return S32 | 0<<29 | 0x26<<23 | 0<<22 5489 5490 /* op $width, $lsb, Rn, Rd */ 5491 case ABFI: 5492 return S64 | 2<<29 | 0x26<<23 | 1<<22 5493 /* alias of BFM */ 5494 5495 case ABFIW: 5496 return S32 | 2<<29 | 0x26<<23 | 0<<22 5497 5498 /* op $imms, $immr, Rn, Rd */ 5499 case ABFM: 5500 return S64 | 1<<29 | 0x26<<23 | 1<<22 5501 5502 case ABFMW: 5503 return S32 | 1<<29 | 0x26<<23 | 0<<22 5504 5505 case ASBFM: 5506 return S64 | 0<<29 | 0x26<<23 | 1<<22 5507 5508 case ASBFMW: 5509 return S32 | 0<<29 | 0x26<<23 | 0<<22 5510 5511 case AUBFM: 5512 return S64 | 2<<29 | 0x26<<23 | 1<<22 5513 5514 case AUBFMW: 5515 return S32 | 2<<29 | 0x26<<23 | 0<<22 5516 5517 case ABFXIL: 5518 return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */ 5519 5520 case ABFXILW: 5521 return S32 | 1<<29 | 0x26<<23 | 0<<22 5522 5523 case AEXTR: 5524 return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21 5525 5526 case AEXTRW: 5527 return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21 5528 5529 case ACBNZ: 5530 return S64 | 0x1A<<25 | 1<<24 5531 5532 case ACBNZW: 5533 return S32 | 0x1A<<25 | 1<<24 5534 5535 case ACBZ: 5536 return S64 | 0x1A<<25 | 0<<24 5537 5538 case ACBZW: 5539 return S32 | 0x1A<<25 | 0<<24 5540 5541 case ACCMN: 5542 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 5543 5544 case ACCMNW: 5545 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 5546 5547 case ACCMP: 5548 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 5549 5550 case ACCMPW: 5551 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 5552 5553 case AMOVK: 5554 return S64 | 3<<29 | 0x25<<23 5555 5556 case AMOVKW: 5557 return S32 | 3<<29 | 0x25<<23 5558 5559 case AMOVN: 5560 return S64 | 0<<29 | 0x25<<23 5561 5562 case AMOVNW: 5563 return S32 | 0<<29 | 0x25<<23 5564 5565 case AMOVZ: 5566 return S64 | 2<<29 | 0x25<<23 5567 5568 case AMOVZW: 5569 return S32 | 2<<29 | 0x25<<23 5570 5571 case AMSR: 5572 return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */ 5573 5574 case AAT, 5575 ADC, 5576 AIC, 5577 ATLBI, 5578 ASYS: 5579 return SYSOP(0, 1, 0, 0, 0, 0, 0) 5580 5581 case ASYSL: 5582 return SYSOP(1, 1, 0, 0, 0, 0, 0) 5583 5584 case ATBZ: 5585 return 0x36 << 24 5586 5587 case ATBNZ: 5588 return 0x37 << 24 5589 5590 case ADSB: 5591 return SYSOP(0, 0, 3, 3, 0, 4, 0x1F) 5592 5593 case ADMB: 5594 return SYSOP(0, 0, 3, 3, 0, 5, 0x1F) 5595 5596 case AISB: 5597 return SYSOP(0, 0, 3, 3, 0, 6, 0x1F) 5598 5599 case AHINT: 5600 return SYSOP(0, 0, 3, 2, 0, 0, 0x1F) 5601 5602 case AVEXT: 5603 return 0x2E<<24 | 0<<23 | 0<<21 | 0<<15 5604 5605 case AVUSHR: 5606 return 0x5E<<23 | 1<<10 5607 5608 case AVSHL: 5609 return 0x1E<<23 | 21<<10 5610 5611 case AVSRI: 5612 return 0x5E<<23 | 17<<10 5613 } 5614 5615 c.ctxt.Diag("%v: bad irr %v", p, a) 5616 return 0 5617 } 5618 5619 func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 { 5620 switch a { 5621 case ACLS: 5622 return S64 | OPBIT(5) 5623 5624 case ACLSW: 5625 return S32 | OPBIT(5) 5626 5627 case ACLZ: 5628 return S64 | OPBIT(4) 5629 5630 case ACLZW: 5631 return S32 | OPBIT(4) 5632 5633 case ARBIT: 5634 return S64 | OPBIT(0) 5635 5636 case ARBITW: 5637 return S32 | OPBIT(0) 5638 5639 case AREV: 5640 return S64 | OPBIT(3) 5641 5642 case AREVW: 5643 return S32 | OPBIT(2) 5644 5645 case AREV16: 5646 return S64 | OPBIT(1) 5647 5648 case AREV16W: 5649 return S32 | OPBIT(1) 5650 5651 case AREV32: 5652 return S64 | OPBIT(2) 5653 5654 default: 5655 c.ctxt.Diag("bad bit op\n%v", p) 5656 return 0 5657 } 5658 } 5659 5660 /* 5661 * add/subtract sign or zero-extended register 5662 */ 5663 func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 { 5664 extension := uint32(0) 5665 if !extend { 5666 switch a { 5667 case AADD, ACMN, AADDS, ASUB, ACMP, ASUBS: 5668 extension = LSL0_64 5669 5670 case AADDW, ACMNW, AADDSW, ASUBW, ACMPW, ASUBSW: 5671 extension = LSL0_32 5672 } 5673 } 5674 5675 switch a { 5676 case AADD: 5677 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5678 5679 case AADDW: 5680 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5681 5682 case ACMN, AADDS: 5683 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5684 5685 case ACMNW, AADDSW: 5686 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5687 5688 case ASUB: 5689 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5690 5691 case ASUBW: 5692 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5693 5694 case ACMP, ASUBS: 5695 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5696 5697 case ACMPW, ASUBSW: 5698 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 5699 } 5700 5701 c.ctxt.Diag("bad opxrrr %v\n%v", a, p) 5702 return 0 5703 } 5704 5705 func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 { 5706 switch a { 5707 case ASVC: 5708 return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */ 5709 5710 case AHVC: 5711 return 0xD4<<24 | 0<<21 | 2 5712 5713 case ASMC: 5714 return 0xD4<<24 | 0<<21 | 3 5715 5716 case ABRK: 5717 return 0xD4<<24 | 1<<21 | 0 5718 5719 case AHLT: 5720 return 0xD4<<24 | 2<<21 | 0 5721 5722 case ADCPS1: 5723 return 0xD4<<24 | 5<<21 | 1 5724 5725 case ADCPS2: 5726 return 0xD4<<24 | 5<<21 | 2 5727 5728 case ADCPS3: 5729 return 0xD4<<24 | 5<<21 | 3 5730 5731 case ACLREX: 5732 return SYSOP(0, 0, 3, 3, 0, 2, 0x1F) 5733 } 5734 5735 c.ctxt.Diag("%v: bad imm %v", p, a) 5736 return 0 5737 } 5738 5739 func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 { 5740 v := int64(0) 5741 t := int64(0) 5742 if p.Pcond != nil { 5743 v = (p.Pcond.Pc >> uint(preshift)) - (c.pc >> uint(preshift)) 5744 if (v & ((1 << uint(shift)) - 1)) != 0 { 5745 c.ctxt.Diag("misaligned label\n%v", p) 5746 } 5747 v >>= uint(shift) 5748 t = int64(1) << uint(flen-1) 5749 if v < -t || v >= t { 5750 c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, p.Pcond) 5751 panic("branch too far") 5752 } 5753 } 5754 5755 return v & ((t << 1) - 1) 5756 } 5757 5758 /* 5759 * pc-relative branches 5760 */ 5761 func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 { 5762 switch a { 5763 case ABEQ: 5764 return OPBcc(0x0) 5765 5766 case ABNE: 5767 return OPBcc(0x1) 5768 5769 case ABCS: 5770 return OPBcc(0x2) 5771 5772 case ABHS: 5773 return OPBcc(0x2) 5774 5775 case ABCC: 5776 return OPBcc(0x3) 5777 5778 case ABLO: 5779 return OPBcc(0x3) 5780 5781 case ABMI: 5782 return OPBcc(0x4) 5783 5784 case ABPL: 5785 return OPBcc(0x5) 5786 5787 case ABVS: 5788 return OPBcc(0x6) 5789 5790 case ABVC: 5791 return OPBcc(0x7) 5792 5793 case ABHI: 5794 return OPBcc(0x8) 5795 5796 case ABLS: 5797 return OPBcc(0x9) 5798 5799 case ABGE: 5800 return OPBcc(0xa) 5801 5802 case ABLT: 5803 return OPBcc(0xb) 5804 5805 case ABGT: 5806 return OPBcc(0xc) 5807 5808 case ABLE: 5809 return OPBcc(0xd) /* imm19<<5 | cond */ 5810 5811 case AB: 5812 return 0<<31 | 5<<26 /* imm26 */ 5813 5814 case obj.ADUFFZERO, obj.ADUFFCOPY, ABL: 5815 return 1<<31 | 5<<26 5816 } 5817 5818 c.ctxt.Diag("%v: bad bra %v", p, a) 5819 return 0 5820 } 5821 5822 func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 { 5823 switch a { 5824 case ABL: 5825 return OPBLR(1) /* BLR */ 5826 5827 case AB: 5828 return OPBLR(0) /* BR */ 5829 5830 case obj.ARET: 5831 return OPBLR(2) /* RET */ 5832 } 5833 5834 c.ctxt.Diag("%v: bad brr %v", p, a) 5835 return 0 5836 } 5837 5838 func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 { 5839 switch a { 5840 case ADRPS: 5841 return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5 5842 5843 case AERET: 5844 return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5 5845 5846 // case ANOP: 5847 // return SYSHINT(0) 5848 5849 case AYIELD: 5850 return SYSHINT(1) 5851 5852 case AWFE: 5853 return SYSHINT(2) 5854 5855 case AWFI: 5856 return SYSHINT(3) 5857 5858 case ASEV: 5859 return SYSHINT(4) 5860 5861 case ASEVL: 5862 return SYSHINT(5) 5863 } 5864 5865 c.ctxt.Diag("%v: bad op0 %v", p, a) 5866 return 0 5867 } 5868 5869 /* 5870 * register offset 5871 */ 5872 func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 { 5873 switch a { 5874 case ALDAR: 5875 return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10 5876 5877 case ALDARW: 5878 return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10 5879 5880 case ALDARB: 5881 return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10 5882 5883 case ALDARH: 5884 return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10 5885 5886 case ALDAXP: 5887 return LDSTX(3, 0, 1, 1, 1) 5888 5889 case ALDAXPW: 5890 return LDSTX(2, 0, 1, 1, 1) 5891 5892 case ALDAXR: 5893 return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10 5894 5895 case ALDAXRW: 5896 return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10 5897 5898 case ALDAXRB: 5899 return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10 5900 5901 case ALDAXRH: 5902 return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10 5903 5904 case ALDXR: 5905 return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10 5906 5907 case ALDXRB: 5908 return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10 5909 5910 case ALDXRH: 5911 return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10 5912 5913 case ALDXRW: 5914 return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10 5915 5916 case ALDXP: 5917 return LDSTX(3, 0, 1, 1, 0) 5918 5919 case ALDXPW: 5920 return LDSTX(2, 0, 1, 1, 0) 5921 5922 case AMOVNP: 5923 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 5924 5925 case AMOVNPW: 5926 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 5927 } 5928 5929 c.ctxt.Diag("bad opload %v\n%v", a, p) 5930 return 0 5931 } 5932 5933 func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 { 5934 switch a { 5935 case ASTLR: 5936 return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10 5937 5938 case ASTLRB: 5939 return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10 5940 5941 case ASTLRH: 5942 return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10 5943 5944 case ASTLP: 5945 return LDSTX(3, 0, 0, 1, 1) 5946 5947 case ASTLPW: 5948 return LDSTX(2, 0, 0, 1, 1) 5949 5950 case ASTLRW: 5951 return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10 5952 5953 case ASTLXP: 5954 return LDSTX(3, 0, 0, 1, 1) 5955 5956 case ASTLXPW: 5957 return LDSTX(2, 0, 0, 1, 1) 5958 5959 case ASTLXR: 5960 return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10 5961 5962 case ASTLXRB: 5963 return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10 5964 5965 case ASTLXRH: 5966 return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10 5967 5968 case ASTLXRW: 5969 return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10 5970 5971 case ASTXR: 5972 return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10 5973 5974 case ASTXRB: 5975 return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10 5976 5977 case ASTXRH: 5978 return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10 5979 5980 case ASTXP: 5981 return LDSTX(3, 0, 0, 1, 0) 5982 5983 case ASTXPW: 5984 return LDSTX(2, 0, 0, 1, 0) 5985 5986 case ASTXRW: 5987 return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10 5988 5989 case AMOVNP: 5990 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 5991 5992 case AMOVNPW: 5993 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 5994 } 5995 5996 c.ctxt.Diag("bad opstore %v\n%v", a, p) 5997 return 0 5998 } 5999 6000 /* 6001 * load/store register (unsigned immediate) C3.3.13 6002 * these produce 64-bit values (when there's an option) 6003 */ 6004 func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 { 6005 if v < 0 || v >= (1<<12) { 6006 c.ctxt.Diag("offset out of range: %d\n%v", v, p) 6007 } 6008 o |= (v & 0xFFF) << 10 6009 o |= int32(b&31) << 5 6010 o |= int32(r & 31) 6011 return uint32(o) 6012 } 6013 6014 func (c *ctxt7) opldr12(p *obj.Prog, a obj.As) uint32 { 6015 switch a { 6016 case AMOVD: 6017 return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */ 6018 6019 case AMOVW: 6020 return LDSTR12U(2, 0, 2) 6021 6022 case AMOVWU: 6023 return LDSTR12U(2, 0, 1) 6024 6025 case AMOVH: 6026 return LDSTR12U(1, 0, 2) 6027 6028 case AMOVHU: 6029 return LDSTR12U(1, 0, 1) 6030 6031 case AMOVB: 6032 return LDSTR12U(0, 0, 2) 6033 6034 case AMOVBU: 6035 return LDSTR12U(0, 0, 1) 6036 6037 case AFMOVS: 6038 return LDSTR12U(2, 1, 1) 6039 6040 case AFMOVD: 6041 return LDSTR12U(3, 1, 1) 6042 } 6043 6044 c.ctxt.Diag("bad opldr12 %v\n%v", a, p) 6045 return 0 6046 } 6047 6048 func (c *ctxt7) opstr12(p *obj.Prog, a obj.As) uint32 { 6049 return LD2STR(c.opldr12(p, a)) 6050 } 6051 6052 /* 6053 * load/store register (unscaled immediate) C3.3.12 6054 */ 6055 func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 { 6056 if v < -256 || v > 255 { 6057 c.ctxt.Diag("offset out of range: %d\n%v", v, p) 6058 } 6059 o |= (v & 0x1FF) << 12 6060 o |= int32(b&31) << 5 6061 o |= int32(r & 31) 6062 return uint32(o) 6063 } 6064 6065 func (c *ctxt7) opldr9(p *obj.Prog, a obj.As) uint32 { 6066 switch a { 6067 case AMOVD: 6068 return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */ 6069 6070 case AMOVW: 6071 return LDSTR9S(2, 0, 2) 6072 6073 case AMOVWU: 6074 return LDSTR9S(2, 0, 1) 6075 6076 case AMOVH: 6077 return LDSTR9S(1, 0, 2) 6078 6079 case AMOVHU: 6080 return LDSTR9S(1, 0, 1) 6081 6082 case AMOVB: 6083 return LDSTR9S(0, 0, 2) 6084 6085 case AMOVBU: 6086 return LDSTR9S(0, 0, 1) 6087 6088 case AFMOVS: 6089 return LDSTR9S(2, 1, 1) 6090 6091 case AFMOVD: 6092 return LDSTR9S(3, 1, 1) 6093 } 6094 6095 c.ctxt.Diag("bad opldr9 %v\n%v", a, p) 6096 return 0 6097 } 6098 6099 func (c *ctxt7) opstr9(p *obj.Prog, a obj.As) uint32 { 6100 return LD2STR(c.opldr9(p, a)) 6101 } 6102 6103 func (c *ctxt7) opldrpp(p *obj.Prog, a obj.As) uint32 { 6104 switch a { 6105 case AMOVD: 6106 return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */ 6107 6108 case AMOVW: 6109 return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 6110 6111 case AMOVWU: 6112 return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 6113 6114 case AMOVH: 6115 return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 6116 6117 case AMOVHU: 6118 return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 6119 6120 case AMOVB: 6121 return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 6122 6123 case AMOVBU: 6124 return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 6125 6126 case AFMOVS: 6127 return 2<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22 6128 6129 case AFMOVD: 6130 return 3<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22 6131 6132 case APRFM: 6133 return 0xf9<<24 | 2<<22 6134 6135 } 6136 6137 c.ctxt.Diag("bad opldr %v\n%v", a, p) 6138 return 0 6139 } 6140 6141 // olsxrr attaches register operands to a load/store opcode supplied in o. 6142 // The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2). 6143 func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 { 6144 o |= int32(r1&31) << 5 6145 o |= int32(r2&31) << 16 6146 o |= int32(r & 31) 6147 return uint32(o) 6148 } 6149 6150 // opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode 6151 // for load instruction with register offset. 6152 // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm). 6153 func (c *ctxt7) opldrr(p *obj.Prog, a obj.As, extension bool) uint32 { 6154 OptionS := uint32(0x1a) 6155 if extension { 6156 OptionS = uint32(0) // option value and S value have been encoded into p.From.Offset. 6157 } 6158 switch a { 6159 case AMOVD: 6160 return OptionS<<10 | 0x3<<21 | 0x1f<<27 6161 case AMOVW: 6162 return OptionS<<10 | 0x5<<21 | 0x17<<27 6163 case AMOVWU: 6164 return OptionS<<10 | 0x3<<21 | 0x17<<27 6165 case AMOVH: 6166 return OptionS<<10 | 0x5<<21 | 0x0f<<27 6167 case AMOVHU: 6168 return OptionS<<10 | 0x3<<21 | 0x0f<<27 6169 case AMOVB: 6170 return OptionS<<10 | 0x5<<21 | 0x07<<27 6171 case AMOVBU: 6172 return OptionS<<10 | 0x3<<21 | 0x07<<27 6173 case AFMOVS: 6174 return OptionS<<10 | 0x3<<21 | 0x17<<27 | 1<<26 6175 case AFMOVD: 6176 return OptionS<<10 | 0x3<<21 | 0x1f<<27 | 1<<26 6177 } 6178 c.ctxt.Diag("bad opldrr %v\n%v", a, p) 6179 return 0 6180 } 6181 6182 // opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode 6183 // for store instruction with register offset. 6184 // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm). 6185 func (c *ctxt7) opstrr(p *obj.Prog, a obj.As, extension bool) uint32 { 6186 OptionS := uint32(0x1a) 6187 if extension { 6188 OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset. 6189 } 6190 switch a { 6191 case AMOVD: 6192 return OptionS<<10 | 0x1<<21 | 0x1f<<27 6193 case AMOVW, AMOVWU: 6194 return OptionS<<10 | 0x1<<21 | 0x17<<27 6195 case AMOVH, AMOVHU: 6196 return OptionS<<10 | 0x1<<21 | 0x0f<<27 6197 case AMOVB, AMOVBU: 6198 return OptionS<<10 | 0x1<<21 | 0x07<<27 6199 case AFMOVS: 6200 return OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26 6201 case AFMOVD: 6202 return OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26 6203 } 6204 c.ctxt.Diag("bad opstrr %v\n%v", a, p) 6205 return 0 6206 } 6207 6208 func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 { 6209 if (v & 0xFFF000) != 0 { 6210 if v&0xFFF != 0 { 6211 c.ctxt.Diag("%v misuses oaddi", p) 6212 } 6213 v >>= 12 6214 o1 |= 1 << 22 6215 } 6216 6217 o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31) 6218 return uint32(o1) 6219 } 6220 6221 /* 6222 * load a literal value into dr 6223 */ 6224 func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 { 6225 var o1 int32 6226 if p.Pcond == nil { /* not in literal pool */ 6227 c.aclass(a) 6228 c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset)) 6229 6230 /* TODO: could be clever, and use general constant builder */ 6231 o1 = int32(c.opirr(p, AADD)) 6232 6233 v := int32(c.instoffset) 6234 if v != 0 && (v&0xFFF) == 0 { 6235 v >>= 12 6236 o1 |= 1 << 22 /* shift, by 12 */ 6237 } 6238 6239 o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31) 6240 } else { 6241 fp, w := 0, 0 6242 switch as { 6243 case AFMOVS: 6244 fp = 1 6245 w = 0 /* 32-bit SIMD/FP */ 6246 6247 case AFMOVD: 6248 fp = 1 6249 w = 1 /* 64-bit SIMD/FP */ 6250 6251 case AMOVD: 6252 if p.Pcond.As == ADWORD { 6253 w = 1 /* 64-bit */ 6254 } else if p.Pcond.To.Offset < 0 { 6255 w = 2 /* 32-bit, sign-extended to 64-bit */ 6256 } else if p.Pcond.To.Offset >= 0 { 6257 w = 0 /* 32-bit, zero-extended to 64-bit */ 6258 } else { 6259 c.ctxt.Diag("invalid operand %v in %v", a, p) 6260 } 6261 6262 case AMOVBU, AMOVHU, AMOVWU: 6263 w = 0 /* 32-bit, zero-extended to 64-bit */ 6264 6265 case AMOVB, AMOVH, AMOVW: 6266 w = 2 /* 32-bit, sign-extended to 64-bit */ 6267 6268 default: 6269 c.ctxt.Diag("invalid operation %v in %v", as, p) 6270 } 6271 6272 v := int32(c.brdist(p, 0, 19, 2)) 6273 o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27) 6274 o1 |= (v & 0x7FFFF) << 5 6275 o1 |= int32(dr & 31) 6276 } 6277 6278 return uint32(o1) 6279 } 6280 6281 // load a constant (MOVCON or BITCON) in a into rt 6282 func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) { 6283 if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 { 6284 // or $bitcon, REGZERO, rt 6285 mode := 64 6286 var as1 obj.As 6287 switch as { 6288 case AMOVW: 6289 as1 = AORRW 6290 mode = 32 6291 case AMOVD: 6292 as1 = AORR 6293 } 6294 o1 = c.opirr(p, as1) 6295 o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31) 6296 return o1 6297 } 6298 6299 if as == AMOVW { 6300 d := uint32(a.Offset) 6301 s := movcon(int64(d)) 6302 if s < 0 || 16*s >= 32 { 6303 d = ^d 6304 s = movcon(int64(d)) 6305 if s < 0 || 16*s >= 32 { 6306 c.ctxt.Diag("impossible 32-bit move wide: %#x\n%v", uint32(a.Offset), p) 6307 } 6308 o1 = c.opirr(p, AMOVNW) 6309 } else { 6310 o1 = c.opirr(p, AMOVZW) 6311 } 6312 o1 |= MOVCONST(int64(d), s, rt) 6313 } 6314 if as == AMOVD { 6315 d := a.Offset 6316 s := movcon(d) 6317 if s < 0 || 16*s >= 64 { 6318 d = ^d 6319 s = movcon(d) 6320 if s < 0 || 16*s >= 64 { 6321 c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p) 6322 } 6323 o1 = c.opirr(p, AMOVN) 6324 } else { 6325 o1 = c.opirr(p, AMOVZ) 6326 } 6327 o1 |= MOVCONST(d, s, rt) 6328 } 6329 6330 return o1 6331 } 6332 6333 func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 { 6334 var b uint32 6335 o := c.opirr(p, a) 6336 if (o & (1 << 31)) == 0 { 6337 b = 32 6338 } else { 6339 b = 64 6340 } 6341 if r < 0 || uint32(r) >= b { 6342 c.ctxt.Diag("illegal bit number\n%v", p) 6343 } 6344 o |= (uint32(r) & 0x3F) << 16 6345 if s < 0 || uint32(s) >= b { 6346 c.ctxt.Diag("illegal bit number\n%v", p) 6347 } 6348 o |= (uint32(s) & 0x3F) << 10 6349 o |= (uint32(rf&31) << 5) | uint32(rt&31) 6350 return o 6351 } 6352 6353 func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 { 6354 var b uint32 6355 o := c.opirr(p, a) 6356 if (o & (1 << 31)) != 0 { 6357 b = 63 6358 } else { 6359 b = 31 6360 } 6361 if v < 0 || uint32(v) > b { 6362 c.ctxt.Diag("illegal bit number\n%v", p) 6363 } 6364 o |= uint32(v) << 10 6365 o |= uint32(rn&31) << 5 6366 o |= uint32(rm&31) << 16 6367 o |= uint32(rt & 31) 6368 return o 6369 } 6370 6371 /* genrate instruction encoding for LDP/LDPW/LDPSW/STP/STPW */ 6372 func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh, ldp uint32) uint32 { 6373 wback := false 6374 if o.scond == C_XPOST || o.scond == C_XPRE { 6375 wback = true 6376 } 6377 switch p.As { 6378 case ALDP, ALDPW, ALDPSW: 6379 c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset)) 6380 case ASTP, ASTPW: 6381 if wback == true { 6382 c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset)) 6383 } 6384 case AFLDPD, AFLDPS: 6385 c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset)) 6386 } 6387 var ret uint32 6388 // check offset 6389 switch p.As { 6390 case AFLDPD, AFSTPD: 6391 if vo < -512 || vo > 504 || vo%8 != 0 { 6392 c.ctxt.Diag("invalid offset %v\n", p) 6393 } 6394 vo /= 8 6395 ret = 1<<30 | 1<<26 6396 case ALDP, ASTP: 6397 if vo < -512 || vo > 504 || vo%8 != 0 { 6398 c.ctxt.Diag("invalid offset %v\n", p) 6399 } 6400 vo /= 8 6401 ret = 2 << 30 6402 case AFLDPS, AFSTPS: 6403 if vo < -256 || vo > 252 || vo%4 != 0 { 6404 c.ctxt.Diag("invalid offset %v\n", p) 6405 } 6406 vo /= 4 6407 ret = 1 << 26 6408 case ALDPW, ASTPW: 6409 if vo < -256 || vo > 252 || vo%4 != 0 { 6410 c.ctxt.Diag("invalid offset %v\n", p) 6411 } 6412 vo /= 4 6413 ret = 0 6414 case ALDPSW: 6415 if vo < -256 || vo > 252 || vo%4 != 0 { 6416 c.ctxt.Diag("invalid offset %v\n", p) 6417 } 6418 vo /= 4 6419 ret = 1 << 30 6420 default: 6421 c.ctxt.Diag("invalid instruction %v\n", p) 6422 } 6423 // check register pair 6424 switch p.As { 6425 case AFLDPD, AFLDPS, AFSTPD, AFSTPS: 6426 if rl < REG_F0 || REG_F31 < rl || rh < REG_F0 || REG_F31 < rh { 6427 c.ctxt.Diag("invalid register pair %v\n", p) 6428 } 6429 case ALDP, ALDPW, ALDPSW: 6430 if rl < REG_R0 || REG_R30 < rl || rh < REG_R0 || REG_R30 < rh { 6431 c.ctxt.Diag("invalid register pair %v\n", p) 6432 } 6433 case ASTP, ASTPW: 6434 if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh { 6435 c.ctxt.Diag("invalid register pair %v\n", p) 6436 } 6437 } 6438 // other conditional flag bits 6439 switch o.scond { 6440 case C_XPOST: 6441 ret |= 1 << 23 6442 case C_XPRE: 6443 ret |= 3 << 23 6444 default: 6445 ret |= 2 << 23 6446 } 6447 ret |= 5<<27 | (ldp&1)<<22 | uint32(vo&0x7f)<<15 | (rh&31)<<10 | (rbase&31)<<5 | (rl & 31) 6448 return ret 6449 } 6450 6451 /* 6452 * size in log2(bytes) 6453 */ 6454 func movesize(a obj.As) int { 6455 switch a { 6456 case AMOVD: 6457 return 3 6458 6459 case AMOVW, AMOVWU: 6460 return 2 6461 6462 case AMOVH, AMOVHU: 6463 return 1 6464 6465 case AMOVB, AMOVBU: 6466 return 0 6467 6468 case AFMOVS: 6469 return 2 6470 6471 case AFMOVD: 6472 return 3 6473 6474 default: 6475 return -1 6476 } 6477 } 6478 6479 // rm is the Rm register value, o is the extension, amount is the left shift value. 6480 func roff(rm int16, o uint32, amount int16) uint32 { 6481 return uint32(rm&31)<<16 | o<<13 | uint32(amount)<<10 6482 } 6483 6484 // encRegShiftOrExt returns the encoding of shifted/extended register, Rx<<n and Rx.UXTW<<n, etc. 6485 func (c *ctxt7) encRegShiftOrExt(a *obj.Addr, r int16) uint32 { 6486 var num, rm int16 6487 num = (r >> 5) & 7 6488 rm = r & 31 6489 switch { 6490 case REG_UXTB <= r && r < REG_UXTH: 6491 return roff(rm, 0, num) 6492 case REG_UXTH <= r && r < REG_UXTW: 6493 return roff(rm, 1, num) 6494 case REG_UXTW <= r && r < REG_UXTX: 6495 if a.Type == obj.TYPE_MEM { 6496 if num == 0 { 6497 return roff(rm, 2, 2) 6498 } else { 6499 return roff(rm, 2, 6) 6500 } 6501 } else { 6502 return roff(rm, 2, num) 6503 } 6504 case REG_UXTX <= r && r < REG_SXTB: 6505 return roff(rm, 3, num) 6506 case REG_SXTB <= r && r < REG_SXTH: 6507 return roff(rm, 4, num) 6508 case REG_SXTH <= r && r < REG_SXTW: 6509 return roff(rm, 5, num) 6510 case REG_SXTW <= r && r < REG_SXTX: 6511 if a.Type == obj.TYPE_MEM { 6512 if num == 0 { 6513 return roff(rm, 6, 2) 6514 } else { 6515 return roff(rm, 6, 6) 6516 } 6517 } else { 6518 return roff(rm, 6, num) 6519 } 6520 case REG_SXTX <= r && r < REG_SPECIAL: 6521 if a.Type == obj.TYPE_MEM { 6522 if num == 0 { 6523 return roff(rm, 7, 2) 6524 } else { 6525 return roff(rm, 7, 6) 6526 } 6527 } else { 6528 return roff(rm, 7, num) 6529 } 6530 case REG_LSL <= r && r < (REG_LSL+1<<8): 6531 return roff(rm, 3, 6) 6532 default: 6533 c.ctxt.Diag("unsupported register extension type.") 6534 } 6535 6536 return 0 6537 }