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://bitbucket.org/plan9-from-bell-labs/9-cc/src/master/ 3// 4// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5// Portions Copyright © 1995-1997 C H Forsyth ([email protected]) 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 ([email protected]) 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 31package arm64 32 33import ( 34 "cmd/internal/obj" 35 "cmd/internal/objabi" 36 "fmt" 37 "log" 38 "math" 39 "sort" 40 "strings" 41) 42 43// ctxt7 holds state while assembling a single function. 44// Each function gets a fresh ctxt7. 45// This allows for multiple functions to be safely concurrently assembled. 46type ctxt7 struct { 47 ctxt *obj.Link 48 newprog obj.ProgAlloc 49 cursym *obj.LSym 50 blitrl *obj.Prog 51 elitrl *obj.Prog 52 autosize int32 53 extrasize int32 54 instoffset int64 55 pc int64 56 pool struct { 57 start uint32 58 size uint32 59 } 60} 61 62const ( 63 funcAlign = 16 64) 65 66const ( 67 REGFROM = 1 68) 69 70type Optab struct { 71 as obj.As 72 a1 uint8 // Prog.From 73 a2 uint8 // 2nd source operand, Prog.Reg or Prog.RestArgs[XXX] 74 a3 uint8 // 3rd source operand, Prog.RestArgs[XXX] 75 a4 uint8 // Prog.To 76 a5 uint8 // 2nd destination operand, Prog.RegTo2 or Prog.RestArgs[XXX] 77 type_ int8 78 size_ int8 // the value of this field is not static, use the size() method to return the value 79 param int16 80 flag int8 81 scond uint8 82} 83 84func IsAtomicInstruction(as obj.As) bool { 85 if _, ok := atomicLDADD[as]; ok { 86 return true 87 } 88 if _, ok := atomicSWP[as]; ok { 89 return true 90 } 91 return false 92} 93 94// known field values of an instruction. 95var atomicLDADD = map[obj.As]uint32{ 96 ALDADDAD: 3<<30 | 0x1c5<<21 | 0x00<<10, 97 ALDADDAW: 2<<30 | 0x1c5<<21 | 0x00<<10, 98 ALDADDAH: 1<<30 | 0x1c5<<21 | 0x00<<10, 99 ALDADDAB: 0<<30 | 0x1c5<<21 | 0x00<<10, 100 ALDADDALD: 3<<30 | 0x1c7<<21 | 0x00<<10, 101 ALDADDALW: 2<<30 | 0x1c7<<21 | 0x00<<10, 102 ALDADDALH: 1<<30 | 0x1c7<<21 | 0x00<<10, 103 ALDADDALB: 0<<30 | 0x1c7<<21 | 0x00<<10, 104 ALDADDD: 3<<30 | 0x1c1<<21 | 0x00<<10, 105 ALDADDW: 2<<30 | 0x1c1<<21 | 0x00<<10, 106 ALDADDH: 1<<30 | 0x1c1<<21 | 0x00<<10, 107 ALDADDB: 0<<30 | 0x1c1<<21 | 0x00<<10, 108 ALDADDLD: 3<<30 | 0x1c3<<21 | 0x00<<10, 109 ALDADDLW: 2<<30 | 0x1c3<<21 | 0x00<<10, 110 ALDADDLH: 1<<30 | 0x1c3<<21 | 0x00<<10, 111 ALDADDLB: 0<<30 | 0x1c3<<21 | 0x00<<10, 112 ALDCLRAD: 3<<30 | 0x1c5<<21 | 0x04<<10, 113 ALDCLRAW: 2<<30 | 0x1c5<<21 | 0x04<<10, 114 ALDCLRAH: 1<<30 | 0x1c5<<21 | 0x04<<10, 115 ALDCLRAB: 0<<30 | 0x1c5<<21 | 0x04<<10, 116 ALDCLRALD: 3<<30 | 0x1c7<<21 | 0x04<<10, 117 ALDCLRALW: 2<<30 | 0x1c7<<21 | 0x04<<10, 118 ALDCLRALH: 1<<30 | 0x1c7<<21 | 0x04<<10, 119 ALDCLRALB: 0<<30 | 0x1c7<<21 | 0x04<<10, 120 ALDCLRD: 3<<30 | 0x1c1<<21 | 0x04<<10, 121 ALDCLRW: 2<<30 | 0x1c1<<21 | 0x04<<10, 122 ALDCLRH: 1<<30 | 0x1c1<<21 | 0x04<<10, 123 ALDCLRB: 0<<30 | 0x1c1<<21 | 0x04<<10, 124 ALDCLRLD: 3<<30 | 0x1c3<<21 | 0x04<<10, 125 ALDCLRLW: 2<<30 | 0x1c3<<21 | 0x04<<10, 126 ALDCLRLH: 1<<30 | 0x1c3<<21 | 0x04<<10, 127 ALDCLRLB: 0<<30 | 0x1c3<<21 | 0x04<<10, 128 ALDEORAD: 3<<30 | 0x1c5<<21 | 0x08<<10, 129 ALDEORAW: 2<<30 | 0x1c5<<21 | 0x08<<10, 130 ALDEORAH: 1<<30 | 0x1c5<<21 | 0x08<<10, 131 ALDEORAB: 0<<30 | 0x1c5<<21 | 0x08<<10, 132 ALDEORALD: 3<<30 | 0x1c7<<21 | 0x08<<10, 133 ALDEORALW: 2<<30 | 0x1c7<<21 | 0x08<<10, 134 ALDEORALH: 1<<30 | 0x1c7<<21 | 0x08<<10, 135 ALDEORALB: 0<<30 | 0x1c7<<21 | 0x08<<10, 136 ALDEORD: 3<<30 | 0x1c1<<21 | 0x08<<10, 137 ALDEORW: 2<<30 | 0x1c1<<21 | 0x08<<10, 138 ALDEORH: 1<<30 | 0x1c1<<21 | 0x08<<10, 139 ALDEORB: 0<<30 | 0x1c1<<21 | 0x08<<10, 140 ALDEORLD: 3<<30 | 0x1c3<<21 | 0x08<<10, 141 ALDEORLW: 2<<30 | 0x1c3<<21 | 0x08<<10, 142 ALDEORLH: 1<<30 | 0x1c3<<21 | 0x08<<10, 143 ALDEORLB: 0<<30 | 0x1c3<<21 | 0x08<<10, 144 ALDORAD: 3<<30 | 0x1c5<<21 | 0x0c<<10, 145 ALDORAW: 2<<30 | 0x1c5<<21 | 0x0c<<10, 146 ALDORAH: 1<<30 | 0x1c5<<21 | 0x0c<<10, 147 ALDORAB: 0<<30 | 0x1c5<<21 | 0x0c<<10, 148 ALDORALD: 3<<30 | 0x1c7<<21 | 0x0c<<10, 149 ALDORALW: 2<<30 | 0x1c7<<21 | 0x0c<<10, 150 ALDORALH: 1<<30 | 0x1c7<<21 | 0x0c<<10, 151 ALDORALB: 0<<30 | 0x1c7<<21 | 0x0c<<10, 152 ALDORD: 3<<30 | 0x1c1<<21 | 0x0c<<10, 153 ALDORW: 2<<30 | 0x1c1<<21 | 0x0c<<10, 154 ALDORH: 1<<30 | 0x1c1<<21 | 0x0c<<10, 155 ALDORB: 0<<30 | 0x1c1<<21 | 0x0c<<10, 156 ALDORLD: 3<<30 | 0x1c3<<21 | 0x0c<<10, 157 ALDORLW: 2<<30 | 0x1c3<<21 | 0x0c<<10, 158 ALDORLH: 1<<30 | 0x1c3<<21 | 0x0c<<10, 159 ALDORLB: 0<<30 | 0x1c3<<21 | 0x0c<<10, 160} 161 162var atomicSWP = map[obj.As]uint32{ 163 ASWPAD: 3<<30 | 0x1c5<<21 | 0x20<<10, 164 ASWPAW: 2<<30 | 0x1c5<<21 | 0x20<<10, 165 ASWPAH: 1<<30 | 0x1c5<<21 | 0x20<<10, 166 ASWPAB: 0<<30 | 0x1c5<<21 | 0x20<<10, 167 ASWPALD: 3<<30 | 0x1c7<<21 | 0x20<<10, 168 ASWPALW: 2<<30 | 0x1c7<<21 | 0x20<<10, 169 ASWPALH: 1<<30 | 0x1c7<<21 | 0x20<<10, 170 ASWPALB: 0<<30 | 0x1c7<<21 | 0x20<<10, 171 ASWPD: 3<<30 | 0x1c1<<21 | 0x20<<10, 172 ASWPW: 2<<30 | 0x1c1<<21 | 0x20<<10, 173 ASWPH: 1<<30 | 0x1c1<<21 | 0x20<<10, 174 ASWPB: 0<<30 | 0x1c1<<21 | 0x20<<10, 175 ASWPLD: 3<<30 | 0x1c3<<21 | 0x20<<10, 176 ASWPLW: 2<<30 | 0x1c3<<21 | 0x20<<10, 177 ASWPLH: 1<<30 | 0x1c3<<21 | 0x20<<10, 178 ASWPLB: 0<<30 | 0x1c3<<21 | 0x20<<10, 179 ACASD: 3<<30 | 0x45<<21 | 0x1f<<10, 180 ACASW: 2<<30 | 0x45<<21 | 0x1f<<10, 181 ACASH: 1<<30 | 0x45<<21 | 0x1f<<10, 182 ACASB: 0<<30 | 0x45<<21 | 0x1f<<10, 183 ACASAD: 3<<30 | 0x47<<21 | 0x1f<<10, 184 ACASAW: 2<<30 | 0x47<<21 | 0x1f<<10, 185 ACASLD: 3<<30 | 0x45<<21 | 0x3f<<10, 186 ACASLW: 2<<30 | 0x45<<21 | 0x3f<<10, 187 ACASALD: 3<<30 | 0x47<<21 | 0x3f<<10, 188 ACASALW: 2<<30 | 0x47<<21 | 0x3f<<10, 189 ACASALH: 1<<30 | 0x47<<21 | 0x3f<<10, 190 ACASALB: 0<<30 | 0x47<<21 | 0x3f<<10, 191} 192var atomicCASP = map[obj.As]uint32{ 193 ACASPD: 1<<30 | 0x41<<21 | 0x1f<<10, 194 ACASPW: 0<<30 | 0x41<<21 | 0x1f<<10, 195} 196 197var oprange [ALAST & obj.AMask][]Optab 198 199var xcmp [C_NCLASS][C_NCLASS]bool 200 201const ( 202 S32 = 0 << 31 203 S64 = 1 << 31 204 Sbit = 1 << 29 205 LSL0_32 = 2 << 13 206 LSL0_64 = 3 << 13 207) 208 209func OPDP2(x uint32) uint32 { 210 return 0<<30 | 0<<29 | 0xd6<<21 | x<<10 211} 212 213func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 { 214 return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15 215} 216 217func OPBcc(x uint32) uint32 { 218 return 0x2A<<25 | 0<<24 | 0<<4 | x&15 219} 220 221func OPBLR(x uint32) uint32 { 222 /* x=0, JMP; 1, CALL; 2, RET */ 223 return 0x6B<<25 | 0<<23 | x<<21 | 0x1F<<16 | 0<<10 224} 225 226func SYSOP(l uint32, op0 uint32, op1 uint32, crn uint32, crm uint32, op2 uint32, rt uint32) uint32 { 227 return 0x354<<22 | l<<21 | op0<<19 | op1<<16 | crn&15<<12 | crm&15<<8 | op2<<5 | rt 228} 229 230func SYSHINT(x uint32) uint32 { 231 return SYSOP(0, 0, 3, 2, 0, x, 0x1F) 232} 233 234func LDSTR(sz uint32, v uint32, opc uint32) uint32 { 235 return sz<<30 | 7<<27 | v<<26 | opc<<22 236} 237 238func LD2STR(o uint32) uint32 { 239 return o &^ (3 << 22) 240} 241 242func LDSTX(sz uint32, o2 uint32, l uint32, o1 uint32, o0 uint32) uint32 { 243 return sz<<30 | 0x8<<24 | o2<<23 | l<<22 | o1<<21 | o0<<15 244} 245 246func FPCMP(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 { 247 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<14 | 8<<10 | op2 248} 249 250func FPCCMP(m uint32, s uint32, type_ uint32, op uint32) uint32 { 251 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | 1<<10 | op<<4 252} 253 254func FPOP1S(m uint32, s uint32, type_ uint32, op uint32) uint32 { 255 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<15 | 0x10<<10 256} 257 258func FPOP2S(m uint32, s uint32, type_ uint32, op uint32) uint32 { 259 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<12 | 2<<10 260} 261 262func FPOP3S(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 { 263 return m<<31 | s<<29 | 0x1F<<24 | type_<<22 | op<<21 | op2<<15 264} 265 266func FPCVTI(sf uint32, s uint32, type_ uint32, rmode uint32, op uint32) uint32 { 267 return sf<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | rmode<<19 | op<<16 | 0<<10 268} 269 270func ADR(p uint32, o uint32, rt uint32) uint32 { 271 return p<<31 | (o&3)<<29 | 0x10<<24 | ((o>>2)&0x7FFFF)<<5 | rt&31 272} 273 274func OPBIT(x uint32) uint32 { 275 return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10 276} 277 278func MOVCONST(d int64, s int, rt int) uint32 { 279 return uint32(((d>>uint(s*16))&0xFFFF)<<5) | uint32(s)&3<<21 | uint32(rt&31) 280} 281 282const ( 283 // Optab.flag 284 LFROM = 1 << iota // p.From uses constant pool 285 LTO // p.To uses constant pool 286 NOTUSETMP // p expands to multiple instructions, but does NOT use REGTMP 287 BRANCH14BITS // branch instruction encodes 14 bits 288 BRANCH19BITS // branch instruction encodes 19 bits 289) 290 291var optab = []Optab{ 292 /* struct Optab: 293 OPCODE, from, prog->reg, from3, to, to2, type,size,param,flag,scond */ 294 {obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, C_NONE, 0, 0, 0, 0, 0}, 295 296 /* arithmetic operations */ 297 {AADD, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0}, 298 {AADD, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0}, 299 {AADC, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0}, 300 {AADC, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0}, 301 {ANEG, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 25, 4, 0, 0, 0}, 302 {ANEG, C_NONE, C_NONE, C_NONE, C_ZREG, C_NONE, 25, 4, 0, 0, 0}, 303 {ANGC, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 17, 4, 0, 0, 0}, 304 {ACMP, C_ZREG, C_ZREG, C_NONE, C_NONE, C_NONE, 1, 4, 0, 0, 0}, 305 {AADD, C_ADDCON, C_RSP, C_NONE, C_RSP, C_NONE, 2, 4, 0, 0, 0}, 306 {AADD, C_ADDCON, C_NONE, C_NONE, C_RSP, C_NONE, 2, 4, 0, 0, 0}, 307 {ACMP, C_ADDCON, C_RSP, C_NONE, C_NONE, C_NONE, 2, 4, 0, 0, 0}, 308 {AADD, C_MOVCON, C_RSP, C_NONE, C_RSP, C_NONE, 62, 8, 0, 0, 0}, 309 {AADD, C_MOVCON, C_NONE, C_NONE, C_RSP, C_NONE, 62, 8, 0, 0, 0}, 310 {ACMP, C_MOVCON, C_RSP, C_NONE, C_NONE, C_NONE, 62, 8, 0, 0, 0}, 311 {AADD, C_BITCON, C_RSP, C_NONE, C_RSP, C_NONE, 62, 8, 0, 0, 0}, 312 {AADD, C_BITCON, C_NONE, C_NONE, C_RSP, C_NONE, 62, 8, 0, 0, 0}, 313 {ACMP, C_BITCON, C_RSP, C_NONE, C_NONE, C_NONE, 62, 8, 0, 0, 0}, 314 {AADD, C_ADDCON2, C_RSP, C_NONE, C_RSP, C_NONE, 48, 8, 0, NOTUSETMP, 0}, 315 {AADD, C_ADDCON2, C_NONE, C_NONE, C_RSP, C_NONE, 48, 8, 0, NOTUSETMP, 0}, 316 {AADD, C_MOVCON2, C_RSP, C_NONE, C_RSP, C_NONE, 13, 12, 0, 0, 0}, 317 {AADD, C_MOVCON2, C_NONE, C_NONE, C_RSP, C_NONE, 13, 12, 0, 0, 0}, 318 {AADD, C_MOVCON3, C_RSP, C_NONE, C_RSP, C_NONE, 13, 16, 0, 0, 0}, 319 {AADD, C_MOVCON3, C_NONE, C_NONE, C_RSP, C_NONE, 13, 16, 0, 0, 0}, 320 {AADD, C_VCON, C_RSP, C_NONE, C_RSP, C_NONE, 13, 20, 0, 0, 0}, 321 {AADD, C_VCON, C_NONE, C_NONE, C_RSP, C_NONE, 13, 20, 0, 0, 0}, 322 {ACMP, C_MOVCON2, C_ZREG, C_NONE, C_NONE, C_NONE, 13, 12, 0, 0, 0}, 323 {ACMP, C_MOVCON3, C_ZREG, C_NONE, C_NONE, C_NONE, 13, 16, 0, 0, 0}, 324 {ACMP, C_VCON, C_ZREG, C_NONE, C_NONE, C_NONE, 13, 20, 0, 0, 0}, 325 {AADD, C_SHIFT, C_ZREG, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0}, 326 {AADD, C_SHIFT, C_NONE, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0}, 327 {AMVN, C_SHIFT, C_NONE, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0}, 328 {ACMP, C_SHIFT, C_ZREG, C_NONE, C_NONE, C_NONE, 3, 4, 0, 0, 0}, 329 {ANEG, C_SHIFT, C_NONE, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0}, 330 {AADD, C_ZREG, C_RSP, C_NONE, C_RSP, C_NONE, 27, 4, 0, 0, 0}, 331 {AADD, C_ZREG, C_NONE, C_NONE, C_RSP, C_NONE, 27, 4, 0, 0, 0}, 332 {ACMP, C_ZREG, C_RSP, C_NONE, C_NONE, C_NONE, 27, 4, 0, 0, 0}, 333 {AADD, C_EXTREG, C_RSP, C_NONE, C_RSP, C_NONE, 27, 4, 0, 0, 0}, 334 {AADD, C_EXTREG, C_NONE, C_NONE, C_RSP, C_NONE, 27, 4, 0, 0, 0}, 335 {ACMP, C_EXTREG, C_RSP, C_NONE, C_NONE, C_NONE, 27, 4, 0, 0, 0}, 336 {AADD, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0}, 337 {AADD, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0}, 338 {AMUL, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 15, 4, 0, 0, 0}, 339 {AMUL, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 15, 4, 0, 0, 0}, 340 {AMADD, C_ZREG, C_ZREG, C_ZREG, C_ZREG, C_NONE, 15, 4, 0, 0, 0}, 341 {AREM, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 16, 8, 0, 0, 0}, 342 {AREM, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 16, 8, 0, 0, 0}, 343 {ASDIV, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0}, 344 {ASDIV, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0}, 345 346 {AFADDS, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 54, 4, 0, 0, 0}, 347 {AFADDS, C_FREG, C_FREG, C_NONE, C_FREG, C_NONE, 54, 4, 0, 0, 0}, 348 {AFMSUBD, C_FREG, C_FREG, C_FREG, C_FREG, C_NONE, 15, 4, 0, 0, 0}, 349 {AFCMPS, C_FREG, C_FREG, C_NONE, C_NONE, C_NONE, 56, 4, 0, 0, 0}, 350 {AFCMPS, C_FCON, C_FREG, C_NONE, C_NONE, C_NONE, 56, 4, 0, 0, 0}, 351 {AVADDP, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 72, 4, 0, 0, 0}, 352 {AVADD, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 72, 4, 0, 0, 0}, 353 {AVADD, C_VREG, C_VREG, C_NONE, C_VREG, C_NONE, 89, 4, 0, 0, 0}, 354 {AVADD, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 89, 4, 0, 0, 0}, 355 {AVADDV, C_ARNG, C_NONE, C_NONE, C_VREG, C_NONE, 85, 4, 0, 0, 0}, 356 357 /* logical operations */ 358 {AAND, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0}, 359 {AAND, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0}, 360 {AANDS, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0}, 361 {AANDS, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0}, 362 {ATST, C_ZREG, C_ZREG, C_NONE, C_NONE, C_NONE, 1, 4, 0, 0, 0}, 363 {AAND, C_MBCON, C_ZREG, C_NONE, C_RSP, C_NONE, 53, 4, 0, 0, 0}, 364 {AAND, C_MBCON, C_NONE, C_NONE, C_RSP, C_NONE, 53, 4, 0, 0, 0}, 365 {AANDS, C_MBCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 53, 4, 0, 0, 0}, 366 {AANDS, C_MBCON, C_NONE, C_NONE, C_ZREG, C_NONE, 53, 4, 0, 0, 0}, 367 {ATST, C_MBCON, C_ZREG, C_NONE, C_NONE, C_NONE, 53, 4, 0, 0, 0}, 368 {AAND, C_BITCON, C_ZREG, C_NONE, C_RSP, C_NONE, 53, 4, 0, 0, 0}, 369 {AAND, C_BITCON, C_NONE, C_NONE, C_RSP, C_NONE, 53, 4, 0, 0, 0}, 370 {AANDS, C_BITCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 53, 4, 0, 0, 0}, 371 {AANDS, C_BITCON, C_NONE, C_NONE, C_ZREG, C_NONE, 53, 4, 0, 0, 0}, 372 {ATST, C_BITCON, C_ZREG, C_NONE, C_NONE, C_NONE, 53, 4, 0, 0, 0}, 373 {AAND, C_MOVCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 62, 8, 0, 0, 0}, 374 {AAND, C_MOVCON, C_NONE, C_NONE, C_ZREG, C_NONE, 62, 8, 0, 0, 0}, 375 {AANDS, C_MOVCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 62, 8, 0, 0, 0}, 376 {AANDS, C_MOVCON, C_NONE, C_NONE, C_ZREG, C_NONE, 62, 8, 0, 0, 0}, 377 {ATST, C_MOVCON, C_ZREG, C_NONE, C_NONE, C_NONE, 62, 8, 0, 0, 0}, 378 {AAND, C_MOVCON2, C_ZREG, C_NONE, C_ZREG, C_NONE, 28, 12, 0, 0, 0}, 379 {AAND, C_MOVCON2, C_NONE, C_NONE, C_ZREG, C_NONE, 28, 12, 0, 0, 0}, 380 {AAND, C_MOVCON3, C_ZREG, C_NONE, C_ZREG, C_NONE, 28, 16, 0, 0, 0}, 381 {AAND, C_MOVCON3, C_NONE, C_NONE, C_ZREG, C_NONE, 28, 16, 0, 0, 0}, 382 {AAND, C_VCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 28, 20, 0, 0, 0}, 383 {AAND, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 28, 20, 0, 0, 0}, 384 {AANDS, C_MOVCON2, C_ZREG, C_NONE, C_ZREG, C_NONE, 28, 12, 0, 0, 0}, 385 {AANDS, C_MOVCON2, C_NONE, C_NONE, C_ZREG, C_NONE, 28, 12, 0, 0, 0}, 386 {AANDS, C_MOVCON3, C_ZREG, C_NONE, C_ZREG, C_NONE, 28, 16, 0, 0, 0}, 387 {AANDS, C_MOVCON3, C_NONE, C_NONE, C_ZREG, C_NONE, 28, 16, 0, 0, 0}, 388 {AANDS, C_VCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 28, 20, 0, 0, 0}, 389 {AANDS, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 28, 20, 0, 0, 0}, 390 {ATST, C_MOVCON2, C_ZREG, C_NONE, C_NONE, C_NONE, 28, 12, 0, 0, 0}, 391 {ATST, C_MOVCON3, C_ZREG, C_NONE, C_NONE, C_NONE, 28, 16, 0, 0, 0}, 392 {ATST, C_VCON, C_ZREG, C_NONE, C_NONE, C_NONE, 28, 20, 0, 0, 0}, 393 {AAND, C_SHIFT, C_ZREG, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0}, 394 {AAND, C_SHIFT, C_NONE, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0}, 395 {AANDS, C_SHIFT, C_ZREG, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0}, 396 {AANDS, C_SHIFT, C_NONE, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0}, 397 {ATST, C_SHIFT, C_ZREG, C_NONE, C_NONE, C_NONE, 3, 4, 0, 0, 0}, 398 {AMOVD, C_RSP, C_NONE, C_NONE, C_RSP, C_NONE, 24, 4, 0, 0, 0}, 399 {AMOVD, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 24, 4, 0, 0, 0}, 400 {AMVN, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 24, 4, 0, 0, 0}, 401 {AMOVB, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 45, 4, 0, 0, 0}, /* also MOVBU */ 402 {AMOVH, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 45, 4, 0, 0, 0}, /* also MOVHU */ 403 {AMOVW, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 45, 4, 0, 0, 0}, /* also MOVWU */ 404 /* TODO: MVN C_SHIFT */ 405 406 /* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */ 407 {AMOVW, C_MBCON, C_NONE, C_NONE, C_ZREG, C_NONE, 32, 4, 0, 0, 0}, 408 {AMOVD, C_MBCON, C_NONE, C_NONE, C_ZREG, C_NONE, 32, 4, 0, 0, 0}, 409 {AMOVW, C_MOVCON, C_NONE, C_NONE, C_ZREG, C_NONE, 32, 4, 0, 0, 0}, 410 {AMOVD, C_MOVCON, C_NONE, C_NONE, C_ZREG, C_NONE, 32, 4, 0, 0, 0}, 411 {AMOVW, C_BITCON, C_NONE, C_NONE, C_RSP, C_NONE, 32, 4, 0, 0, 0}, 412 {AMOVD, C_BITCON, C_NONE, C_NONE, C_RSP, C_NONE, 32, 4, 0, 0, 0}, 413 {AMOVW, C_MOVCON2, C_NONE, C_NONE, C_ZREG, C_NONE, 12, 8, 0, NOTUSETMP, 0}, 414 {AMOVD, C_MOVCON2, C_NONE, C_NONE, C_ZREG, C_NONE, 12, 8, 0, NOTUSETMP, 0}, 415 {AMOVD, C_MOVCON3, C_NONE, C_NONE, C_ZREG, C_NONE, 12, 12, 0, NOTUSETMP, 0}, 416 {AMOVD, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 12, 16, 0, NOTUSETMP, 0}, 417 418 {AMOVK, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 33, 4, 0, 0, 0}, 419 {AMOVD, C_AACON, C_NONE, C_NONE, C_RSP, C_NONE, 4, 4, REGFROM, 0, 0}, 420 {AMOVD, C_AACON2, C_NONE, C_NONE, C_RSP, C_NONE, 4, 8, REGFROM, NOTUSETMP, 0}, 421 422 /* load long effective stack address (load int32 offset and add) */ 423 {AMOVD, C_LACON, C_NONE, C_NONE, C_RSP, C_NONE, 34, 8, REGSP, LFROM, 0}, 424 425 // Load a large constant into a vector register. 426 {AVMOVS, C_ADDR, C_NONE, C_NONE, C_VREG, C_NONE, 65, 12, 0, 0, 0}, 427 {AVMOVD, C_ADDR, C_NONE, C_NONE, C_VREG, C_NONE, 65, 12, 0, 0, 0}, 428 {AVMOVQ, C_ADDR, C_NONE, C_NONE, C_VREG, C_NONE, 65, 12, 0, 0, 0}, 429 430 /* jump operations */ 431 {AB, C_NONE, C_NONE, C_NONE, C_SBRA, C_NONE, 5, 4, 0, 0, 0}, 432 {ABL, C_NONE, C_NONE, C_NONE, C_SBRA, C_NONE, 5, 4, 0, 0, 0}, 433 {AB, C_NONE, C_NONE, C_NONE, C_ZOREG, C_NONE, 6, 4, 0, 0, 0}, 434 {ABL, C_NONE, C_NONE, C_NONE, C_ZREG, C_NONE, 6, 4, 0, 0, 0}, 435 {ABL, C_NONE, C_NONE, C_NONE, C_ZOREG, C_NONE, 6, 4, 0, 0, 0}, 436 {obj.ARET, C_NONE, C_NONE, C_NONE, C_ZREG, C_NONE, 6, 4, 0, 0, 0}, 437 {obj.ARET, C_NONE, C_NONE, C_NONE, C_ZOREG, C_NONE, 6, 4, 0, 0, 0}, 438 {ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, C_NONE, 7, 4, 0, BRANCH19BITS, 0}, 439 {ACBZ, C_ZREG, C_NONE, C_NONE, C_SBRA, C_NONE, 39, 4, 0, BRANCH19BITS, 0}, 440 {ATBZ, C_VCON, C_ZREG, C_NONE, C_SBRA, C_NONE, 40, 4, 0, BRANCH14BITS, 0}, 441 {AERET, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0}, 442 443 // get a PC-relative address 444 {AADRP, C_SBRA, C_NONE, C_NONE, C_ZREG, C_NONE, 60, 4, 0, 0, 0}, 445 {AADR, C_SBRA, C_NONE, C_NONE, C_ZREG, C_NONE, 61, 4, 0, 0, 0}, 446 447 {ACLREX, C_NONE, C_NONE, C_NONE, C_VCON, C_NONE, 38, 4, 0, 0, 0}, 448 {ACLREX, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0}, 449 {ABFM, C_VCON, C_ZREG, C_VCON, C_ZREG, C_NONE, 42, 4, 0, 0, 0}, 450 {ABFI, C_VCON, C_ZREG, C_VCON, C_ZREG, C_NONE, 43, 4, 0, 0, 0}, 451 {AEXTR, C_VCON, C_ZREG, C_ZREG, C_ZREG, C_NONE, 44, 4, 0, 0, 0}, 452 {ASXTB, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 45, 4, 0, 0, 0}, 453 {ACLS, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 46, 4, 0, 0, 0}, 454 {ALSL, C_VCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 8, 4, 0, 0, 0}, 455 {ALSL, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 8, 4, 0, 0, 0}, 456 {ALSL, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 9, 4, 0, 0, 0}, 457 {ALSL, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 9, 4, 0, 0, 0}, 458 {ASVC, C_VCON, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0}, 459 {ASVC, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0}, 460 {ADWORD, C_NONE, C_NONE, C_NONE, C_VCON, C_NONE, 11, 8, 0, NOTUSETMP, 0}, 461 {ADWORD, C_NONE, C_NONE, C_NONE, C_LEXT, C_NONE, 11, 8, 0, NOTUSETMP, 0}, 462 {ADWORD, C_NONE, C_NONE, C_NONE, C_ADDR, C_NONE, 11, 8, 0, NOTUSETMP, 0}, 463 {ADWORD, C_NONE, C_NONE, C_NONE, C_LACON, C_NONE, 11, 8, 0, NOTUSETMP, 0}, 464 {AWORD, C_NONE, C_NONE, C_NONE, C_LCON, C_NONE, 14, 4, 0, 0, 0}, 465 {AWORD, C_NONE, C_NONE, C_NONE, C_LEXT, C_NONE, 14, 4, 0, 0, 0}, 466 {AWORD, C_NONE, C_NONE, C_NONE, C_ADDR, C_NONE, 14, 4, 0, 0, 0}, 467 {AMOVW, C_VCONADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 68, 8, 0, NOTUSETMP, 0}, 468 {AMOVD, C_VCONADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 68, 8, 0, NOTUSETMP, 0}, 469 {AMOVB, C_ZREG, C_NONE, C_NONE, C_ADDR, C_NONE, 64, 12, 0, 0, 0}, 470 {AMOVH, C_ZREG, C_NONE, C_NONE, C_ADDR, C_NONE, 64, 12, 0, 0, 0}, 471 {AMOVW, C_ZREG, C_NONE, C_NONE, C_ADDR, C_NONE, 64, 12, 0, 0, 0}, 472 {AMOVD, C_ZREG, C_NONE, C_NONE, C_ADDR, C_NONE, 64, 12, 0, 0, 0}, 473 {AMOVB, C_ADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 65, 12, 0, 0, 0}, 474 {AMOVH, C_ADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 65, 12, 0, 0, 0}, 475 {AMOVW, C_ADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 65, 12, 0, 0, 0}, 476 {AMOVD, C_ADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 65, 12, 0, 0, 0}, 477 {AMOVD, C_GOTADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 71, 8, 0, 0, 0}, 478 {AMOVD, C_TLS_LE, C_NONE, C_NONE, C_ZREG, C_NONE, 69, 4, 0, 0, 0}, 479 {AMOVD, C_TLS_IE, C_NONE, C_NONE, C_ZREG, C_NONE, 70, 8, 0, 0, 0}, 480 481 {AFMOVS, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 64, 12, 0, 0, 0}, 482 {AFMOVS, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 65, 12, 0, 0, 0}, 483 {AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 64, 12, 0, 0, 0}, 484 {AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 65, 12, 0, 0, 0}, 485 {AFMOVS, C_FCON, C_NONE, C_NONE, C_FREG, C_NONE, 55, 4, 0, 0, 0}, 486 {AFMOVS, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 54, 4, 0, 0, 0}, 487 {AFMOVD, C_FCON, C_NONE, C_NONE, C_FREG, C_NONE, 55, 4, 0, 0, 0}, 488 {AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 54, 4, 0, 0, 0}, 489 {AFMOVS, C_ZREG, C_NONE, C_NONE, C_FREG, C_NONE, 29, 4, 0, 0, 0}, 490 {AFMOVS, C_FREG, C_NONE, C_NONE, C_ZREG, C_NONE, 29, 4, 0, 0, 0}, 491 {AFMOVD, C_ZREG, C_NONE, C_NONE, C_FREG, C_NONE, 29, 4, 0, 0, 0}, 492 {AFMOVD, C_FREG, C_NONE, C_NONE, C_ZREG, C_NONE, 29, 4, 0, 0, 0}, 493 {AFCVTZSD, C_FREG, C_NONE, C_NONE, C_ZREG, C_NONE, 29, 4, 0, 0, 0}, 494 {ASCVTFD, C_ZREG, C_NONE, C_NONE, C_FREG, C_NONE, 29, 4, 0, 0, 0}, 495 {AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 29, 4, 0, 0, 0}, 496 {AVMOV, C_ELEM, C_NONE, C_NONE, C_ZREG, C_NONE, 73, 4, 0, 0, 0}, 497 {AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, C_NONE, 92, 4, 0, 0, 0}, 498 {AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, C_NONE, 80, 4, 0, 0, 0}, 499 {AVMOV, C_ZREG, C_NONE, C_NONE, C_ARNG, C_NONE, 82, 4, 0, 0, 0}, 500 {AVMOV, C_ZREG, C_NONE, C_NONE, C_ELEM, C_NONE, 78, 4, 0, 0, 0}, 501 {AVMOV, C_ARNG, C_NONE, C_NONE, C_ARNG, C_NONE, 83, 4, 0, 0, 0}, 502 {AVDUP, C_ELEM, C_NONE, C_NONE, C_ARNG, C_NONE, 79, 4, 0, 0, 0}, 503 {AVDUP, C_ELEM, C_NONE, C_NONE, C_VREG, C_NONE, 80, 4, 0, 0, 0}, 504 {AVDUP, C_ZREG, C_NONE, C_NONE, C_ARNG, C_NONE, 82, 4, 0, 0, 0}, 505 {AVMOVI, C_ADDCON, C_NONE, C_NONE, C_ARNG, C_NONE, 86, 4, 0, 0, 0}, 506 {AVFMLA, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 72, 4, 0, 0, 0}, 507 {AVEXT, C_VCON, C_ARNG, C_ARNG, C_ARNG, C_NONE, 94, 4, 0, 0, 0}, 508 {AVTBL, C_ARNG, C_NONE, C_LIST, C_ARNG, C_NONE, 100, 4, 0, 0, 0}, 509 {AVUSHR, C_VCON, C_ARNG, C_NONE, C_ARNG, C_NONE, 95, 4, 0, 0, 0}, 510 {AVZIP1, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 72, 4, 0, 0, 0}, 511 {AVUSHLL, C_VCON, C_ARNG, C_NONE, C_ARNG, C_NONE, 102, 4, 0, 0, 0}, 512 {AVUXTL, C_ARNG, C_NONE, C_NONE, C_ARNG, C_NONE, 102, 4, 0, 0, 0}, 513 {AVUADDW, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 105, 4, 0, 0, 0}, 514 515 /* conditional operations */ 516 {ACSEL, C_COND, C_ZREG, C_ZREG, C_ZREG, C_NONE, 18, 4, 0, 0, 0}, 517 {ACINC, C_COND, C_ZREG, C_NONE, C_ZREG, C_NONE, 18, 4, 0, 0, 0}, 518 {ACSET, C_COND, C_NONE, C_NONE, C_ZREG, C_NONE, 18, 4, 0, 0, 0}, 519 {AFCSELD, C_COND, C_FREG, C_FREG, C_FREG, C_NONE, 18, 4, 0, 0, 0}, 520 {ACCMN, C_COND, C_ZREG, C_ZREG, C_VCON, C_NONE, 19, 4, 0, 0, 0}, 521 {ACCMN, C_COND, C_ZREG, C_VCON, C_VCON, C_NONE, 19, 4, 0, 0, 0}, 522 {AFCCMPS, C_COND, C_FREG, C_FREG, C_VCON, C_NONE, 57, 4, 0, 0, 0}, 523 524 /* scaled 12-bit unsigned displacement store */ 525 {AMOVB, C_ZREG, C_NONE, C_NONE, C_UAUTO4K, C_NONE, 20, 4, REGSP, 0, 0}, 526 {AMOVB, C_ZREG, C_NONE, C_NONE, C_UOREG4K, C_NONE, 20, 4, 0, 0, 0}, 527 {AMOVH, C_ZREG, C_NONE, C_NONE, C_UAUTO8K, C_NONE, 20, 4, REGSP, 0, 0}, 528 {AMOVH, C_ZREG, C_NONE, C_NONE, C_UOREG8K, C_NONE, 20, 4, 0, 0, 0}, 529 {AMOVW, C_ZREG, C_NONE, C_NONE, C_UAUTO16K, C_NONE, 20, 4, REGSP, 0, 0}, 530 {AMOVW, C_ZREG, C_NONE, C_NONE, C_UOREG16K, C_NONE, 20, 4, 0, 0, 0}, 531 {AMOVD, C_ZREG, C_NONE, C_NONE, C_UAUTO32K, C_NONE, 20, 4, REGSP, 0, 0}, 532 {AMOVD, C_ZREG, C_NONE, C_NONE, C_UOREG32K, C_NONE, 20, 4, 0, 0, 0}, 533 534 {AFMOVS, C_FREG, C_NONE, C_NONE, C_UAUTO16K, C_NONE, 20, 4, REGSP, 0, 0}, 535 {AFMOVS, C_FREG, C_NONE, C_NONE, C_UOREG16K, C_NONE, 20, 4, 0, 0, 0}, 536 {AFMOVD, C_FREG, C_NONE, C_NONE, C_UAUTO32K, C_NONE, 20, 4, REGSP, 0, 0}, 537 {AFMOVD, C_FREG, C_NONE, C_NONE, C_UOREG32K, C_NONE, 20, 4, 0, 0, 0}, 538 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_UAUTO64K, C_NONE, 20, 4, REGSP, 0, 0}, 539 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_UOREG64K, C_NONE, 20, 4, 0, 0, 0}, 540 541 /* unscaled 9-bit signed displacement store */ 542 {AMOVB, C_ZREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0}, 543 {AMOVB, C_ZREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0}, 544 {AMOVH, C_ZREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0}, 545 {AMOVH, C_ZREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0}, 546 {AMOVW, C_ZREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0}, 547 {AMOVW, C_ZREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0}, 548 {AMOVD, C_ZREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0}, 549 {AMOVD, C_ZREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0}, 550 551 {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0}, 552 {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0}, 553 {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0}, 554 {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0}, 555 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0}, 556 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0}, 557 558 /* scaled 12-bit unsigned displacement load */ 559 {AMOVB, C_UAUTO4K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0}, 560 {AMOVB, C_UOREG4K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0}, 561 {AMOVH, C_UAUTO8K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0}, 562 {AMOVH, C_UOREG8K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0}, 563 {AMOVW, C_UAUTO16K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0}, 564 {AMOVW, C_UOREG16K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0}, 565 {AMOVD, C_UAUTO32K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0}, 566 {AMOVD, C_UOREG32K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0}, 567 568 {AFMOVS, C_UAUTO16K, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, REGSP, 0, 0}, 569 {AFMOVS, C_UOREG16K, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, 0, 0, 0}, 570 {AFMOVD, C_UAUTO32K, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, REGSP, 0, 0}, 571 {AFMOVD, C_UOREG32K, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, 0, 0, 0}, 572 {AFMOVQ, C_UAUTO64K, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, REGSP, 0, 0}, 573 {AFMOVQ, C_UOREG64K, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, 0, 0, 0}, 574 575 /* unscaled 9-bit signed displacement load */ 576 {AMOVB, C_NSAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0}, 577 {AMOVB, C_NSOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0}, 578 {AMOVH, C_NSAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0}, 579 {AMOVH, C_NSOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0}, 580 {AMOVW, C_NSAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0}, 581 {AMOVW, C_NSOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0}, 582 {AMOVD, C_NSAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0}, 583 {AMOVD, C_NSOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0}, 584 585 {AFMOVS, C_NSAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, REGSP, 0, 0}, 586 {AFMOVS, C_NSOREG, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, 0, 0, 0}, 587 {AFMOVD, C_NSAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, REGSP, 0, 0}, 588 {AFMOVD, C_NSOREG, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, 0, 0, 0}, 589 {AFMOVQ, C_NSAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, REGSP, 0, 0}, 590 {AFMOVQ, C_NSOREG, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, 0, 0, 0}, 591 592 /* long displacement store */ 593 {AMOVB, C_ZREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0}, 594 {AMOVB, C_ZREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0}, 595 {AMOVB, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0}, 596 {AMOVB, C_ZREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0}, 597 {AMOVH, C_ZREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0}, 598 {AMOVH, C_ZREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0}, 599 {AMOVH, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0}, 600 {AMOVH, C_ZREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0}, 601 {AMOVW, C_ZREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0}, 602 {AMOVW, C_ZREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0}, 603 {AMOVW, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0}, 604 {AMOVW, C_ZREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0}, 605 {AMOVD, C_ZREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0}, 606 {AMOVD, C_ZREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0}, 607 {AMOVD, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0}, 608 {AMOVD, C_ZREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0}, 609 610 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0}, 611 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0}, 612 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0}, 613 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0}, 614 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0}, 615 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0}, 616 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0}, 617 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0}, 618 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0}, 619 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0}, 620 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0}, 621 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0}, 622 623 /* long displacement load */ 624 {AMOVB, C_LAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, 0, 0}, 625 {AMOVB, C_LAUTOPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, LFROM, 0}, 626 {AMOVB, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, 0, 0}, 627 {AMOVB, C_LOREGPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, LFROM, 0}, 628 {AMOVH, C_LAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, 0, 0}, 629 {AMOVH, C_LAUTOPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, LFROM, 0}, 630 {AMOVH, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, 0, 0}, 631 {AMOVH, C_LOREGPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, LFROM, 0}, 632 {AMOVW, C_LAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, 0, 0}, 633 {AMOVW, C_LAUTOPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, LFROM, 0}, 634 {AMOVW, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, 0, 0}, 635 {AMOVW, C_LOREGPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, LFROM, 0}, 636 {AMOVD, C_LAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, 0, 0}, 637 {AMOVD, C_LAUTOPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, LFROM, 0}, 638 {AMOVD, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, 0, 0}, 639 {AMOVD, C_LOREGPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, LFROM, 0}, 640 641 {AFMOVS, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, REGSP, 0, 0}, 642 {AFMOVS, C_LAUTOPOOL, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, REGSP, LFROM, 0}, 643 {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, 0, 0, 0}, 644 {AFMOVS, C_LOREGPOOL, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, 0, LFROM, 0}, 645 {AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, REGSP, 0, 0}, 646 {AFMOVD, C_LAUTOPOOL, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, REGSP, LFROM, 0}, 647 {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, 0, 0, 0}, 648 {AFMOVD, C_LOREGPOOL, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, 0, LFROM, 0}, 649 {AFMOVQ, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, REGSP, 0, 0}, 650 {AFMOVQ, C_LAUTOPOOL, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, REGSP, LFROM, 0}, 651 {AFMOVQ, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, 0, 0, 0}, 652 {AFMOVQ, C_LOREGPOOL, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, 0, LFROM, 0}, 653 654 /* pre/post-indexed load (unscaled, signed 9-bit offset) */ 655 {AMOVD, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPOST}, 656 {AMOVW, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPOST}, 657 {AMOVH, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPOST}, 658 {AMOVB, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPOST}, 659 {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 22, 4, 0, 0, C_XPOST}, 660 {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 22, 4, 0, 0, C_XPOST}, 661 {AFMOVQ, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 22, 4, 0, 0, C_XPOST}, 662 663 {AMOVD, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPRE}, 664 {AMOVW, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPRE}, 665 {AMOVH, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPRE}, 666 {AMOVB, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPRE}, 667 {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 22, 4, 0, 0, C_XPRE}, 668 {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 22, 4, 0, 0, C_XPRE}, 669 {AFMOVQ, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 22, 4, 0, 0, C_XPRE}, 670 671 /* pre/post-indexed store (unscaled, signed 9-bit offset) */ 672 {AMOVD, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST}, 673 {AMOVW, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST}, 674 {AMOVH, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST}, 675 {AMOVB, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST}, 676 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST}, 677 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST}, 678 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST}, 679 680 {AMOVD, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE}, 681 {AMOVW, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE}, 682 {AMOVH, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE}, 683 {AMOVB, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE}, 684 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE}, 685 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE}, 686 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE}, 687 688 /* load with shifted or extended register offset */ 689 {AMOVD, C_ROFF, C_NONE, C_NONE, C_ZREG, C_NONE, 98, 4, 0, 0, 0}, 690 {AMOVW, C_ROFF, C_NONE, C_NONE, C_ZREG, C_NONE, 98, 4, 0, 0, 0}, 691 {AMOVH, C_ROFF, C_NONE, C_NONE, C_ZREG, C_NONE, 98, 4, 0, 0, 0}, 692 {AMOVB, C_ROFF, C_NONE, C_NONE, C_ZREG, C_NONE, 98, 4, 0, 0, 0}, 693 {AFMOVS, C_ROFF, C_NONE, C_NONE, C_FREG, C_NONE, 98, 4, 0, 0, 0}, 694 {AFMOVD, C_ROFF, C_NONE, C_NONE, C_FREG, C_NONE, 98, 4, 0, 0, 0}, 695 696 /* store with extended register offset */ 697 {AMOVD, C_ZREG, C_NONE, C_NONE, C_ROFF, C_NONE, 99, 4, 0, 0, 0}, 698 {AMOVW, C_ZREG, C_NONE, C_NONE, C_ROFF, C_NONE, 99, 4, 0, 0, 0}, 699 {AMOVH, C_ZREG, C_NONE, C_NONE, C_ROFF, C_NONE, 99, 4, 0, 0, 0}, 700 {AMOVB, C_ZREG, C_NONE, C_NONE, C_ROFF, C_NONE, 99, 4, 0, 0, 0}, 701 {AFMOVS, C_FREG, C_NONE, C_NONE, C_ROFF, C_NONE, 99, 4, 0, 0, 0}, 702 {AFMOVD, C_FREG, C_NONE, C_NONE, C_ROFF, C_NONE, 99, 4, 0, 0, 0}, 703 704 /* pre/post-indexed/signed-offset load/store register pair 705 (unscaled, signed 10-bit quad-aligned and long offset). 706 The pre/post-indexed format only supports OREG cases because 707 the RSP and pseudo registers are not allowed to be modified 708 in this way. */ 709 {AFLDPQ, C_NQAUTO_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, REGSP, 0, 0}, 710 {AFLDPQ, C_PQAUTO_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, REGSP, 0, 0}, 711 {AFLDPQ, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, REGSP, 0, 0}, 712 {AFLDPQ, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, REGSP, 0, 0}, 713 {AFLDPQ, C_LAUTO, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, REGSP, 0, 0}, 714 {AFLDPQ, C_LAUTOPOOL, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, REGSP, LFROM, 0}, 715 {AFLDPQ, C_NQOREG_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, 0}, 716 {AFLDPQ, C_NQOREG_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPRE}, 717 {AFLDPQ, C_NQOREG_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPOST}, 718 {AFLDPQ, C_PQOREG_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, 0}, 719 {AFLDPQ, C_PQOREG_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPRE}, 720 {AFLDPQ, C_PQOREG_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPOST}, 721 {AFLDPQ, C_UOREG4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, 0, 0, 0}, 722 {AFLDPQ, C_NOREG4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, 0, 0, 0}, 723 {AFLDPQ, C_LOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, 0, 0, 0}, 724 {AFLDPQ, C_LOREGPOOL, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, 0, LFROM, 0}, 725 {AFLDPQ, C_ADDR, C_NONE, C_NONE, C_PAIR, C_NONE, 88, 12, 0, 0, 0}, 726 727 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQAUTO_16, C_NONE, 67, 4, REGSP, 0, 0}, 728 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQAUTO_16, C_NONE, 67, 4, REGSP, 0, 0}, 729 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, C_NONE, 76, 8, REGSP, 0, 0}, 730 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, C_NONE, 76, 8, REGSP, 0, 0}, 731 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_LAUTO, C_NONE, 77, 12, REGSP, 0, 0}, 732 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 77, 12, REGSP, LTO, 0}, 733 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQOREG_16, C_NONE, 67, 4, 0, 0, 0}, 734 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQOREG_16, C_NONE, 67, 4, 0, 0, C_XPRE}, 735 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQOREG_16, C_NONE, 67, 4, 0, 0, C_XPOST}, 736 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQOREG_16, C_NONE, 67, 4, 0, 0, 0}, 737 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQOREG_16, C_NONE, 67, 4, 0, 0, C_XPRE}, 738 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQOREG_16, C_NONE, 67, 4, 0, 0, C_XPOST}, 739 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_UOREG4K, C_NONE, 76, 8, 0, 0, 0}, 740 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NOREG4K, C_NONE, 76, 8, 0, 0, 0}, 741 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_LOREG, C_NONE, 77, 12, 0, 0, 0}, 742 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 77, 12, 0, LTO, 0}, 743 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_ADDR, C_NONE, 87, 12, 0, 0, 0}, 744 745 {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, REGSP, 0, 0}, 746 {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, REGSP, 0, 0}, 747 {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, REGSP, 0, 0}, 748 {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, REGSP, 0, 0}, 749 {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, REGSP, 0, 0}, 750 {ALDP, C_LAUTOPOOL, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, REGSP, LFROM, 0}, 751 {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, 0}, 752 {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPRE}, 753 {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPOST}, 754 {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, 0}, 755 {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPRE}, 756 {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPOST}, 757 {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, 0, 0, 0}, 758 {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, 0, 0, 0}, 759 {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, 0, 0, 0}, 760 {ALDP, C_LOREGPOOL, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, 0, LFROM, 0}, 761 {ALDP, C_ADDR, C_NONE, C_NONE, C_PAIR, C_NONE, 88, 12, 0, 0, 0}, 762 763 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, C_NONE, 67, 4, REGSP, 0, 0}, 764 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, C_NONE, 67, 4, REGSP, 0, 0}, 765 {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, C_NONE, 76, 8, REGSP, 0, 0}, 766 {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, C_NONE, 76, 8, REGSP, 0, 0}, 767 {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, C_NONE, 77, 12, REGSP, 0, 0}, 768 {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 77, 12, REGSP, LTO, 0}, 769 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, C_NONE, 67, 4, 0, 0, 0}, 770 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, C_NONE, 67, 4, 0, 0, C_XPRE}, 771 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, C_NONE, 67, 4, 0, 0, C_XPOST}, 772 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, C_NONE, 67, 4, 0, 0, 0}, 773 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, C_NONE, 67, 4, 0, 0, C_XPRE}, 774 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, C_NONE, 67, 4, 0, 0, C_XPOST}, 775 {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, C_NONE, 76, 8, 0, 0, 0}, 776 {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, C_NONE, 76, 8, 0, 0, 0}, 777 {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, C_NONE, 77, 12, 0, 0, 0}, 778 {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 77, 12, 0, LTO, 0}, 779 {ASTP, C_PAIR, C_NONE, C_NONE, C_ADDR, C_NONE, 87, 12, 0, 0, 0}, 780 781 // differ from LDP/STP for C_NSAUTO_4/C_PSAUTO_4/C_NSOREG_4/C_PSOREG_4 782 {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, REGSP, 0, 0}, 783 {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, REGSP, 0, 0}, 784 {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, REGSP, 0, 0}, 785 {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, REGSP, 0, 0}, 786 {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, REGSP, 0, 0}, 787 {ALDPW, C_LAUTOPOOL, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, REGSP, LFROM, 0}, 788 {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, 0}, 789 {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPRE}, 790 {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPOST}, 791 {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, 0}, 792 {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPRE}, 793 {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPOST}, 794 {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, 0, 0, 0}, 795 {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, 0, 0, 0}, 796 {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, 0, 0, 0}, 797 {ALDPW, C_LOREGPOOL, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, 0, LFROM, 0}, 798 {ALDPW, C_ADDR, C_NONE, C_NONE, C_PAIR, C_NONE, 88, 12, 0, 0, 0}, 799 800 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, C_NONE, 67, 4, REGSP, 0, 0}, 801 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, C_NONE, 67, 4, REGSP, 0, 0}, 802 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, C_NONE, 76, 8, REGSP, 0, 0}, 803 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, C_NONE, 76, 8, REGSP, 0, 0}, 804 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, C_NONE, 77, 12, REGSP, 0, 0}, 805 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 77, 12, REGSP, LTO, 0}, 806 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, C_NONE, 67, 4, 0, 0, 0}, 807 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, C_NONE, 67, 4, 0, 0, C_XPRE}, 808 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, C_NONE, 67, 4, 0, 0, C_XPOST}, 809 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, C_NONE, 67, 4, 0, 0, 0}, 810 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, C_NONE, 67, 4, 0, 0, C_XPRE}, 811 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, C_NONE, 67, 4, 0, 0, C_XPOST}, 812 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, C_NONE, 76, 8, 0, 0, 0}, 813 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, C_NONE, 76, 8, 0, 0, 0}, 814 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, C_NONE, 77, 12, 0, 0, 0}, 815 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 77, 12, 0, LTO, 0}, 816 {ASTPW, C_PAIR, C_NONE, C_NONE, C_ADDR, C_NONE, 87, 12, 0, 0, 0}, 817 818 {ASWPD, C_ZREG, C_NONE, C_NONE, C_ZOREG, C_ZREG, 47, 4, 0, 0, 0}, 819 {ASWPD, C_ZREG, C_NONE, C_NONE, C_ZAUTO, C_ZREG, 47, 4, REGSP, 0, 0}, 820 {ACASPD, C_PAIR, C_NONE, C_NONE, C_ZOREG, C_PAIR, 106, 4, 0, 0, 0}, 821 {ACASPD, C_PAIR, C_NONE, C_NONE, C_ZAUTO, C_PAIR, 106, 4, REGSP, 0, 0}, 822 {ALDAR, C_ZOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 58, 4, 0, 0, 0}, 823 {ALDXR, C_ZOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 58, 4, 0, 0, 0}, 824 {ALDAXR, C_ZOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 58, 4, 0, 0, 0}, 825 {ALDXP, C_ZOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 58, 4, 0, 0, 0}, 826 {ASTLR, C_ZREG, C_NONE, C_NONE, C_ZOREG, C_NONE, 59, 4, 0, 0, 0}, 827 {ASTXR, C_ZREG, C_NONE, C_NONE, C_ZOREG, C_ZREG, 59, 4, 0, 0, 0}, 828 {ASTLXR, C_ZREG, C_NONE, C_NONE, C_ZOREG, C_ZREG, 59, 4, 0, 0, 0}, 829 {ASTXP, C_PAIR, C_NONE, C_NONE, C_ZOREG, C_ZREG, 59, 4, 0, 0, 0}, 830 831 /* VLD[1-4]/VST[1-4] */ 832 {AVLD1, C_ZOREG, C_NONE, C_NONE, C_LIST, C_NONE, 81, 4, 0, 0, 0}, 833 {AVLD1, C_LOREG, C_NONE, C_NONE, C_LIST, C_NONE, 81, 4, 0, 0, C_XPOST}, 834 {AVLD1, C_ROFF, C_NONE, C_NONE, C_LIST, C_NONE, 81, 4, 0, 0, C_XPOST}, 835 {AVLD1R, C_ZOREG, C_NONE, C_NONE, C_LIST, C_NONE, 81, 4, 0, 0, 0}, 836 {AVLD1R, C_LOREG, C_NONE, C_NONE, C_LIST, C_NONE, 81, 4, 0, 0, C_XPOST}, 837 {AVLD1R, C_ROFF, C_NONE, C_NONE, C_LIST, C_NONE, 81, 4, 0, 0, C_XPOST}, 838 {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, C_NONE, 97, 4, 0, 0, C_XPOST}, 839 {AVLD1, C_ROFF, C_NONE, C_NONE, C_ELEM, C_NONE, 97, 4, 0, 0, C_XPOST}, 840 {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, C_NONE, 97, 4, 0, 0, 0}, 841 {AVST1, C_LIST, C_NONE, C_NONE, C_ZOREG, C_NONE, 84, 4, 0, 0, 0}, 842 {AVST1, C_LIST, C_NONE, C_NONE, C_LOREG, C_NONE, 84, 4, 0, 0, C_XPOST}, 843 {AVST1, C_LIST, C_NONE, C_NONE, C_ROFF, C_NONE, 84, 4, 0, 0, C_XPOST}, 844 {AVST2, C_LIST, C_NONE, C_NONE, C_ZOREG, C_NONE, 84, 4, 0, 0, 0}, 845 {AVST2, C_LIST, C_NONE, C_NONE, C_LOREG, C_NONE, 84, 4, 0, 0, C_XPOST}, 846 {AVST2, C_LIST, C_NONE, C_NONE, C_ROFF, C_NONE, 84, 4, 0, 0, C_XPOST}, 847 {AVST3, C_LIST, C_NONE, C_NONE, C_ZOREG, C_NONE, 84, 4, 0, 0, 0}, 848 {AVST3, C_LIST, C_NONE, C_NONE, C_LOREG, C_NONE, 84, 4, 0, 0, C_XPOST}, 849 {AVST3, C_LIST, C_NONE, C_NONE, C_ROFF, C_NONE, 84, 4, 0, 0, C_XPOST}, 850 {AVST4, C_LIST, C_NONE, C_NONE, C_ZOREG, C_NONE, 84, 4, 0, 0, 0}, 851 {AVST4, C_LIST, C_NONE, C_NONE, C_LOREG, C_NONE, 84, 4, 0, 0, C_XPOST}, 852 {AVST4, C_LIST, C_NONE, C_NONE, C_ROFF, C_NONE, 84, 4, 0, 0, C_XPOST}, 853 {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, C_NONE, 96, 4, 0, 0, C_XPOST}, 854 {AVST1, C_ELEM, C_NONE, C_NONE, C_ROFF, C_NONE, 96, 4, 0, 0, C_XPOST}, 855 {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, C_NONE, 96, 4, 0, 0, 0}, 856 857 /* special */ 858 {AMOVD, C_SPR, C_NONE, C_NONE, C_ZREG, C_NONE, 35, 4, 0, 0, 0}, 859 {AMRS, C_SPR, C_NONE, C_NONE, C_ZREG, C_NONE, 35, 4, 0, 0, 0}, 860 {AMOVD, C_ZREG, C_NONE, C_NONE, C_SPR, C_NONE, 36, 4, 0, 0, 0}, 861 {AMSR, C_ZREG, C_NONE, C_NONE, C_SPR, C_NONE, 36, 4, 0, 0, 0}, 862 {AMOVD, C_VCON, C_NONE, C_NONE, C_SPR, C_NONE, 37, 4, 0, 0, 0}, 863 {AMSR, C_VCON, C_NONE, C_NONE, C_SPR, C_NONE, 37, 4, 0, 0, 0}, 864 {AMSR, C_VCON, C_NONE, C_NONE, C_SPOP, C_NONE, 37, 4, 0, 0, 0}, 865 {APRFM, C_UOREG32K, C_NONE, C_NONE, C_SPOP, C_NONE, 91, 4, 0, 0, 0}, 866 {APRFM, C_UOREG32K, C_NONE, C_NONE, C_LCON, C_NONE, 91, 4, 0, 0, 0}, 867 {ADMB, C_VCON, C_NONE, C_NONE, C_NONE, C_NONE, 51, 4, 0, 0, 0}, 868 {AHINT, C_VCON, C_NONE, C_NONE, C_NONE, C_NONE, 52, 4, 0, 0, 0}, 869 {ASYS, C_VCON, C_NONE, C_NONE, C_NONE, C_NONE, 50, 4, 0, 0, 0}, 870 {ASYS, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 50, 4, 0, 0, 0}, 871 {ASYSL, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 50, 4, 0, 0, 0}, 872 {ATLBI, C_SPOP, C_NONE, C_NONE, C_NONE, C_NONE, 107, 4, 0, 0, 0}, 873 {ATLBI, C_SPOP, C_NONE, C_NONE, C_ZREG, C_NONE, 107, 4, 0, 0, 0}, 874 875 /* encryption instructions */ 876 {AAESD, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 26, 4, 0, 0, 0}, // for compatibility with old code 877 {AAESD, C_ARNG, C_NONE, C_NONE, C_ARNG, C_NONE, 26, 4, 0, 0, 0}, // recommend using the new one for better readability 878 {ASHA1C, C_VREG, C_VREG, C_NONE, C_VREG, C_NONE, 49, 4, 0, 0, 0}, 879 {ASHA1C, C_ARNG, C_VREG, C_NONE, C_VREG, C_NONE, 49, 4, 0, 0, 0}, 880 {ASHA1SU0, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 63, 4, 0, 0, 0}, 881 {AVREV32, C_ARNG, C_NONE, C_NONE, C_ARNG, C_NONE, 83, 4, 0, 0, 0}, 882 {AVPMULL, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 93, 4, 0, 0, 0}, 883 {AVEOR3, C_ARNG, C_ARNG, C_ARNG, C_ARNG, C_NONE, 103, 4, 0, 0, 0}, 884 {AVXAR, C_VCON, C_ARNG, C_ARNG, C_ARNG, C_NONE, 104, 4, 0, 0, 0}, 885 {obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}, 886 {obj.APCDATA, C_VCON, C_NONE, C_NONE, C_VCON, C_NONE, 0, 0, 0, 0, 0}, 887 {obj.AFUNCDATA, C_VCON, C_NONE, C_NONE, C_ADDR, C_NONE, 0, 0, 0, 0, 0}, 888 {obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, 889 {obj.ANOP, C_LCON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // nop variants, see #40689 890 {obj.ANOP, C_ZREG, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, 891 {obj.ANOP, C_VREG, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, 892 {obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_SBRA, C_NONE, 5, 4, 0, 0, 0}, // same as AB/ABL 893 {obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_SBRA, C_NONE, 5, 4, 0, 0, 0}, // same as AB/ABL 894 {obj.APCALIGN, C_LCON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // align code 895 {obj.APCALIGNMAX, C_LCON, C_NONE, C_NONE, C_LCON, C_NONE, 0, 0, 0, 0, 0}, // align code, conditional 896} 897 898// Valid pstate field values, and value to use in instruction. 899// Doesn't include special registers. 900var pstatefield = []struct { 901 opd SpecialOperand 902 enc uint32 903}{ 904 {SPOP_DAIFSet, 3<<16 | 4<<12 | 6<<5}, 905 {SPOP_DAIFClr, 3<<16 | 4<<12 | 7<<5}, 906} 907 908var prfopfield = map[SpecialOperand]uint32{ 909 SPOP_PLDL1KEEP: 0, 910 SPOP_PLDL1STRM: 1, 911 SPOP_PLDL2KEEP: 2, 912 SPOP_PLDL2STRM: 3, 913 SPOP_PLDL3KEEP: 4, 914 SPOP_PLDL3STRM: 5, 915 SPOP_PLIL1KEEP: 8, 916 SPOP_PLIL1STRM: 9, 917 SPOP_PLIL2KEEP: 10, 918 SPOP_PLIL2STRM: 11, 919 SPOP_PLIL3KEEP: 12, 920 SPOP_PLIL3STRM: 13, 921 SPOP_PSTL1KEEP: 16, 922 SPOP_PSTL1STRM: 17, 923 SPOP_PSTL2KEEP: 18, 924 SPOP_PSTL2STRM: 19, 925 SPOP_PSTL3KEEP: 20, 926 SPOP_PSTL3STRM: 21, 927} 928 929// sysInstFields helps convert SYS alias instructions to SYS instructions. 930// For example, the format of TLBI is: TLBI <tlbi_op>{, <Xt>}. 931// It's equivalent to: SYS #<op1>, C8, <Cm>, #<op2>{, <Xt>}. 932// The field hasOperand2 indicates whether Xt is required. It helps to check 933// some combinations that may be undefined, such as TLBI VMALLE1IS, R0. 934var sysInstFields = map[SpecialOperand]struct { 935 op1 uint8 936 cn uint8 937 cm uint8 938 op2 uint8 939 hasOperand2 bool 940}{ 941 // TLBI 942 SPOP_VMALLE1IS: {0, 8, 3, 0, false}, 943 SPOP_VAE1IS: {0, 8, 3, 1, true}, 944 SPOP_ASIDE1IS: {0, 8, 3, 2, true}, 945 SPOP_VAAE1IS: {0, 8, 3, 3, true}, 946 SPOP_VALE1IS: {0, 8, 3, 5, true}, 947 SPOP_VAALE1IS: {0, 8, 3, 7, true}, 948 SPOP_VMALLE1: {0, 8, 7, 0, false}, 949 SPOP_VAE1: {0, 8, 7, 1, true}, 950 SPOP_ASIDE1: {0, 8, 7, 2, true}, 951 SPOP_VAAE1: {0, 8, 7, 3, true}, 952 SPOP_VALE1: {0, 8, 7, 5, true}, 953 SPOP_VAALE1: {0, 8, 7, 7, true}, 954 SPOP_IPAS2E1IS: {4, 8, 0, 1, true}, 955 SPOP_IPAS2LE1IS: {4, 8, 0, 5, true}, 956 SPOP_ALLE2IS: {4, 8, 3, 0, false}, 957 SPOP_VAE2IS: {4, 8, 3, 1, true}, 958 SPOP_ALLE1IS: {4, 8, 3, 4, false}, 959 SPOP_VALE2IS: {4, 8, 3, 5, true}, 960 SPOP_VMALLS12E1IS: {4, 8, 3, 6, false}, 961 SPOP_IPAS2E1: {4, 8, 4, 1, true}, 962 SPOP_IPAS2LE1: {4, 8, 4, 5, true}, 963 SPOP_ALLE2: {4, 8, 7, 0, false}, 964 SPOP_VAE2: {4, 8, 7, 1, true}, 965 SPOP_ALLE1: {4, 8, 7, 4, false}, 966 SPOP_VALE2: {4, 8, 7, 5, true}, 967 SPOP_VMALLS12E1: {4, 8, 7, 6, false}, 968 SPOP_ALLE3IS: {6, 8, 3, 0, false}, 969 SPOP_VAE3IS: {6, 8, 3, 1, true}, 970 SPOP_VALE3IS: {6, 8, 3, 5, true}, 971 SPOP_ALLE3: {6, 8, 7, 0, false}, 972 SPOP_VAE3: {6, 8, 7, 1, true}, 973 SPOP_VALE3: {6, 8, 7, 5, true}, 974 SPOP_VMALLE1OS: {0, 8, 1, 0, false}, 975 SPOP_VAE1OS: {0, 8, 1, 1, true}, 976 SPOP_ASIDE1OS: {0, 8, 1, 2, true}, 977 SPOP_VAAE1OS: {0, 8, 1, 3, true}, 978 SPOP_VALE1OS: {0, 8, 1, 5, true}, 979 SPOP_VAALE1OS: {0, 8, 1, 7, true}, 980 SPOP_RVAE1IS: {0, 8, 2, 1, true}, 981 SPOP_RVAAE1IS: {0, 8, 2, 3, true}, 982 SPOP_RVALE1IS: {0, 8, 2, 5, true}, 983 SPOP_RVAALE1IS: {0, 8, 2, 7, true}, 984 SPOP_RVAE1OS: {0, 8, 5, 1, true}, 985 SPOP_RVAAE1OS: {0, 8, 5, 3, true}, 986 SPOP_RVALE1OS: {0, 8, 5, 5, true}, 987 SPOP_RVAALE1OS: {0, 8, 5, 7, true}, 988 SPOP_RVAE1: {0, 8, 6, 1, true}, 989 SPOP_RVAAE1: {0, 8, 6, 3, true}, 990 SPOP_RVALE1: {0, 8, 6, 5, true}, 991 SPOP_RVAALE1: {0, 8, 6, 7, true}, 992 SPOP_RIPAS2E1IS: {4, 8, 0, 2, true}, 993 SPOP_RIPAS2LE1IS: {4, 8, 0, 6, true}, 994 SPOP_ALLE2OS: {4, 8, 1, 0, false}, 995 SPOP_VAE2OS: {4, 8, 1, 1, true}, 996 SPOP_ALLE1OS: {4, 8, 1, 4, false}, 997 SPOP_VALE2OS: {4, 8, 1, 5, true}, 998 SPOP_VMALLS12E1OS: {4, 8, 1, 6, false}, 999 SPOP_RVAE2IS: {4, 8, 2, 1, true}, 1000 SPOP_RVALE2IS: {4, 8, 2, 5, true}, 1001 SPOP_IPAS2E1OS: {4, 8, 4, 0, true}, 1002 SPOP_RIPAS2E1: {4, 8, 4, 2, true}, 1003 SPOP_RIPAS2E1OS: {4, 8, 4, 3, true}, 1004 SPOP_IPAS2LE1OS: {4, 8, 4, 4, true}, 1005 SPOP_RIPAS2LE1: {4, 8, 4, 6, true}, 1006 SPOP_RIPAS2LE1OS: {4, 8, 4, 7, true}, 1007 SPOP_RVAE2OS: {4, 8, 5, 1, true}, 1008 SPOP_RVALE2OS: {4, 8, 5, 5, true}, 1009 SPOP_RVAE2: {4, 8, 6, 1, true}, 1010 SPOP_RVALE2: {4, 8, 6, 5, true}, 1011 SPOP_ALLE3OS: {6, 8, 1, 0, false}, 1012 SPOP_VAE3OS: {6, 8, 1, 1, true}, 1013 SPOP_VALE3OS: {6, 8, 1, 5, true}, 1014 SPOP_RVAE3IS: {6, 8, 2, 1, true}, 1015 SPOP_RVALE3IS: {6, 8, 2, 5, true}, 1016 SPOP_RVAE3OS: {6, 8, 5, 1, true}, 1017 SPOP_RVALE3OS: {6, 8, 5, 5, true}, 1018 SPOP_RVAE3: {6, 8, 6, 1, true}, 1019 SPOP_RVALE3: {6, 8, 6, 5, true}, 1020 // DC 1021 SPOP_IVAC: {0, 7, 6, 1, true}, 1022 SPOP_ISW: {0, 7, 6, 2, true}, 1023 SPOP_CSW: {0, 7, 10, 2, true}, 1024 SPOP_CISW: {0, 7, 14, 2, true}, 1025 SPOP_ZVA: {3, 7, 4, 1, true}, 1026 SPOP_CVAC: {3, 7, 10, 1, true}, 1027 SPOP_CVAU: {3, 7, 11, 1, true}, 1028 SPOP_CIVAC: {3, 7, 14, 1, true}, 1029 SPOP_IGVAC: {0, 7, 6, 3, true}, 1030 SPOP_IGSW: {0, 7, 6, 4, true}, 1031 SPOP_IGDVAC: {0, 7, 6, 5, true}, 1032 SPOP_IGDSW: {0, 7, 6, 6, true}, 1033 SPOP_CGSW: {0, 7, 10, 4, true}, 1034 SPOP_CGDSW: {0, 7, 10, 6, true}, 1035 SPOP_CIGSW: {0, 7, 14, 4, true}, 1036 SPOP_CIGDSW: {0, 7, 14, 6, true}, 1037 SPOP_GVA: {3, 7, 4, 3, true}, 1038 SPOP_GZVA: {3, 7, 4, 4, true}, 1039 SPOP_CGVAC: {3, 7, 10, 3, true}, 1040 SPOP_CGDVAC: {3, 7, 10, 5, true}, 1041 SPOP_CGVAP: {3, 7, 12, 3, true}, 1042 SPOP_CGDVAP: {3, 7, 12, 5, true}, 1043 SPOP_CGVADP: {3, 7, 13, 3, true}, 1044 SPOP_CGDVADP: {3, 7, 13, 5, true}, 1045 SPOP_CIGVAC: {3, 7, 14, 3, true}, 1046 SPOP_CIGDVAC: {3, 7, 14, 5, true}, 1047 SPOP_CVAP: {3, 7, 12, 1, true}, 1048 SPOP_CVADP: {3, 7, 13, 1, true}, 1049} 1050 1051// Used for padding NOOP instruction 1052const OP_NOOP = 0xd503201f 1053 1054// pcAlignPadLength returns the number of bytes required to align pc to alignedValue, 1055// reporting an error if alignedValue is not a power of two or is out of range. 1056func pcAlignPadLength(ctxt *obj.Link, pc int64, alignedValue int64) int { 1057 if !((alignedValue&(alignedValue-1) == 0) && 8 <= alignedValue && alignedValue <= 2048) { 1058 ctxt.Diag("alignment value of an instruction must be a power of two and in the range [8, 2048], got %d\n", alignedValue) 1059 } 1060 return int(-pc & (alignedValue - 1)) 1061} 1062 1063// size returns the size of the sequence of machine instructions when p is encoded with o. 1064// Usually it just returns o.size directly, in some cases it checks whether the optimization 1065// conditions are met, and if so returns the size of the optimized instruction sequence. 1066// These optimizations need to be synchronized with the asmout function. 1067func (o *Optab) size(ctxt *obj.Link, p *obj.Prog) int { 1068 // Optimize adrp+add+ld/st to adrp+ld/st(offset). 1069 sz := movesize(p.As) 1070 if sz != -1 { 1071 // Relocations R_AARCH64_LDST{64,32,16,8}_ABS_LO12_NC can only generate 8-byte, 4-byte, 1072 // 2-byte and 1-byte aligned addresses, so the address of load/store must be aligned. 1073 // Also symbols with prefix of "go:string." are Go strings, which will go into 1074 // the symbol table, their addresses are not necessary aligned, rule this out. 1075 align := int64(1 << sz) 1076 if o.a1 == C_ADDR && p.From.Offset%align == 0 && !strings.HasPrefix(p.From.Sym.Name, "go:string.") || 1077 o.a4 == C_ADDR && p.To.Offset%align == 0 && !strings.HasPrefix(p.To.Sym.Name, "go:string.") { 1078 return 8 1079 } 1080 } 1081 return int(o.size_) 1082} 1083 1084func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { 1085 if ctxt.Retpoline { 1086 ctxt.Diag("-spectre=ret not supported on arm64") 1087 ctxt.Retpoline = false // don't keep printing 1088 } 1089 1090 p := cursym.Func().Text 1091 if p == nil || p.Link == nil { // handle external functions and ELF section symbols 1092 return 1093 } 1094 1095 if oprange[AAND&obj.AMask] == nil { 1096 ctxt.Diag("arm64 ops not initialized, call arm64.buildop first") 1097 } 1098 1099 c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset & 0xffffffff), extrasize: int32(p.To.Offset >> 32)} 1100 p.To.Offset &= 0xffffffff // extrasize is no longer needed 1101 1102 bflag := 1 1103 pc := int64(0) 1104 p.Pc = pc 1105 var m int 1106 var o *Optab 1107 for p = p.Link; p != nil; p = p.Link { 1108 p.Pc = pc 1109 o = c.oplook(p) 1110 m = o.size(c.ctxt, p) 1111 if m == 0 { 1112 switch p.As { 1113 case obj.APCALIGN, obj.APCALIGNMAX: 1114 m = obj.AlignmentPadding(int32(pc), p, ctxt, cursym) 1115 break 1116 case obj.ANOP, obj.AFUNCDATA, obj.APCDATA: 1117 continue 1118 default: 1119 c.ctxt.Diag("zero-width instruction\n%v", p) 1120 } 1121 } 1122 pc += int64(m) 1123 1124 if o.flag&LFROM != 0 { 1125 c.addpool(p, &p.From) 1126 } 1127 if o.flag<O != 0 { 1128 c.addpool(p, &p.To) 1129 } 1130 if c.blitrl != nil { 1131 c.checkpool(p) 1132 } 1133 } 1134 1135 c.cursym.Size = pc 1136 1137 /* 1138 * if any procedure is large enough to 1139 * generate a large SBRA branch, then 1140 * generate extra passes putting branches 1141 * around jmps to fix. this is rare. 1142 */ 1143 for bflag != 0 { 1144 bflag = 0 1145 pc = 0 1146 for p = c.cursym.Func().Text.Link; p != nil; p = p.Link { 1147 p.Pc = pc 1148 o = c.oplook(p) 1149 1150 /* very large branches */ 1151 if (o.flag&BRANCH14BITS != 0 || o.flag&BRANCH19BITS != 0) && p.To.Target() != nil { 1152 otxt := p.To.Target().Pc - pc 1153 var toofar bool 1154 if o.flag&BRANCH14BITS != 0 { // branch instruction encodes 14 bits 1155 toofar = otxt <= -(1<<15)+10 || otxt >= (1<<15)-10 1156 } else if o.flag&BRANCH19BITS != 0 { // branch instruction encodes 19 bits 1157 toofar = otxt <= -(1<<20)+10 || otxt >= (1<<20)-10 1158 } 1159 if toofar { 1160 q := c.newprog() 1161 q.Link = p.Link 1162 p.Link = q 1163 q.As = AB 1164 q.To.Type = obj.TYPE_BRANCH 1165 q.To.SetTarget(p.To.Target()) 1166 p.To.SetTarget(q) 1167 q = c.newprog() 1168 q.Link = p.Link 1169 p.Link = q 1170 q.As = AB 1171 q.To.Type = obj.TYPE_BRANCH 1172 q.To.SetTarget(q.Link.Link) 1173 bflag = 1 1174 } 1175 } 1176 m = o.size(c.ctxt, p) 1177 1178 if m == 0 { 1179 switch p.As { 1180 case obj.APCALIGN, obj.APCALIGNMAX: 1181 m = obj.AlignmentPaddingLength(int32(pc), p, ctxt) 1182 break 1183 case obj.ANOP, obj.AFUNCDATA, obj.APCDATA: 1184 continue 1185 default: 1186 c.ctxt.Diag("zero-width instruction\n%v", p) 1187 } 1188 } 1189 1190 pc += int64(m) 1191 } 1192 } 1193 1194 pc += -pc & (funcAlign - 1) 1195 c.cursym.Size = pc 1196 1197 /* 1198 * lay out the code, emitting code and data relocations. 1199 */ 1200 c.cursym.Grow(c.cursym.Size) 1201 bp := c.cursym.P 1202 psz := int32(0) 1203 var i int 1204 var out [6]uint32 1205 for p := c.cursym.Func().Text.Link; p != nil; p = p.Link { 1206 c.pc = p.Pc 1207 o = c.oplook(p) 1208 sz := o.size(c.ctxt, p) 1209 if sz > 4*len(out) { 1210 log.Fatalf("out array in span7 is too small, need at least %d for %v", sz/4, p) 1211 } 1212 if p.As == obj.APCALIGN || p.As == obj.APCALIGNMAX { 1213 v := obj.AlignmentPaddingLength(int32(p.Pc), p, c.ctxt) 1214 for i = 0; i < int(v/4); i++ { 1215 // emit ANOOP instruction by the padding size 1216 c.ctxt.Arch.ByteOrder.PutUint32(bp, OP_NOOP) 1217 bp = bp[4:] 1218 psz += 4 1219 } 1220 } else { 1221 c.asmout(p, o, out[:]) 1222 for i = 0; i < sz/4; i++ { 1223 c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i]) 1224 bp = bp[4:] 1225 psz += 4 1226 } 1227 } 1228 } 1229 1230 // Mark nonpreemptible instruction sequences. 1231 // We use REGTMP as a scratch register during call injection, 1232 // so instruction sequences that use REGTMP are unsafe to 1233 // preempt asynchronously. 1234 obj.MarkUnsafePoints(c.ctxt, c.cursym.Func().Text, c.newprog, c.isUnsafePoint, c.isRestartable) 1235 1236 // Now that we know byte offsets, we can generate jump table entries. 1237 for _, jt := range cursym.Func().JumpTables { 1238 for i, p := range jt.Targets { 1239 // The ith jumptable entry points to the p.Pc'th 1240 // byte in the function symbol s. 1241 // TODO: try using relative PCs. 1242 jt.Sym.WriteAddr(ctxt, int64(i)*8, 8, cursym, p.Pc) 1243 } 1244 } 1245} 1246 1247// isUnsafePoint returns whether p is an unsafe point. 1248func (c *ctxt7) isUnsafePoint(p *obj.Prog) bool { 1249 // If p explicitly uses REGTMP, it's unsafe to preempt, because the 1250 // preemption sequence clobbers REGTMP. 1251 return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP || 1252 p.From.Type == obj.TYPE_REGREG && p.From.Offset == REGTMP || 1253 p.To.Type == obj.TYPE_REGREG && p.To.Offset == REGTMP 1254} 1255 1256// isRestartable returns whether p is a multi-instruction sequence that, 1257// if preempted, can be restarted. 1258func (c *ctxt7) isRestartable(p *obj.Prog) bool { 1259 if c.isUnsafePoint(p) { 1260 return false 1261 } 1262 // If p is a multi-instruction sequence with uses REGTMP inserted by 1263 // the assembler in order to materialize a large constant/offset, we 1264 // can restart p (at the start of the instruction sequence), recompute 1265 // the content of REGTMP, upon async preemption. Currently, all cases 1266 // of assembler-inserted REGTMP fall into this category. 1267 // If p doesn't use REGTMP, it can be simply preempted, so we don't 1268 // mark it. 1269 o := c.oplook(p) 1270 return o.size(c.ctxt, p) > 4 && o.flag&NOTUSETMP == 0 1271} 1272 1273/* 1274 * when the first reference to the literal pool threatens 1275 * to go out of range of a 1Mb PC-relative offset 1276 * drop the pool now. 1277 */ 1278func (c *ctxt7) checkpool(p *obj.Prog) { 1279 // If the pool is going to go out of range or p is the last instruction of the function, 1280 // flush the pool. 1281 if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) || p.Link == nil { 1282 c.flushpool(p) 1283 } 1284} 1285 1286func (c *ctxt7) flushpool(p *obj.Prog) { 1287 // Needs to insert a branch before flushing the pool. 1288 // We don't need the jump if following an unconditional branch. 1289 // TODO: other unconditional operations. 1290 if !(p.As == AB || p.As == obj.ARET || p.As == AERET) { 1291 if c.ctxt.Debugvlog { 1292 fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start) 1293 } 1294 q := c.newprog() 1295 if p.Link == nil { 1296 // If p is the last instruction of the function, insert an UNDEF instruction in case the 1297 // execution fall through to the pool. 1298 q.As = obj.AUNDEF 1299 } else { 1300 // Else insert a branch to the next instruction of p. 1301 q.As = AB 1302 q.To.Type = obj.TYPE_BRANCH 1303 q.To.SetTarget(p.Link) 1304 } 1305 q.Link = c.blitrl 1306 q.Pos = p.Pos 1307 c.blitrl = q 1308 } 1309 1310 // The line number for constant pool entries doesn't really matter. 1311 // We set it to the line number of the preceding instruction so that 1312 // there are no deltas to encode in the pc-line tables. 1313 for q := c.blitrl; q != nil; q = q.Link { 1314 q.Pos = p.Pos 1315 } 1316 1317 c.elitrl.Link = p.Link 1318 p.Link = c.blitrl 1319 1320 c.blitrl = nil /* BUG: should refer back to values until out-of-range */ 1321 c.elitrl = nil 1322 c.pool.size = 0 1323 c.pool.start = 0 1324} 1325 1326/* 1327 * MOVD foo(SB), R is actually 1328 * MOVD addr, REGTMP 1329 * MOVD REGTMP, R 1330 * where addr is the address of the DWORD containing the address of foo. 1331 * 1332 * TODO: hash 1333 */ 1334func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) { 1335 cls := c.aclass(a) 1336 lit := c.instoffset 1337 t := c.newprog() 1338 t.As = AWORD 1339 sz := 4 1340 1341 if a.Type == obj.TYPE_CONST { 1342 if lit != int64(int32(lit)) && uint64(lit) != uint64(uint32(lit)) { 1343 // out of range -0x80000000 ~ 0xffffffff, must store 64-bit. 1344 t.As = ADWORD 1345 sz = 8 1346 } // else store 32-bit 1347 } 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)) { 1348 // conservative: don't know if we want signed or unsigned extension. 1349 // in case of ambiguity, store 64-bit 1350 t.As = ADWORD 1351 sz = 8 1352 } 1353 1354 t.To.Type = obj.TYPE_CONST 1355 t.To.Offset = lit 1356 1357 for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */ 1358 if q.To == t.To { 1359 p.Pool = q 1360 return 1361 } 1362 } 1363 1364 if c.blitrl == nil { 1365 c.blitrl = t 1366 c.pool.start = uint32(p.Pc) 1367 } else { 1368 c.elitrl.Link = t 1369 } 1370 c.elitrl = t 1371 if t.As == ADWORD { 1372 // make DWORD 8-byte aligned, this is not required by ISA, 1373 // just to avoid performance penalties when loading from 1374 // the constant pool across a cache line. 1375 c.pool.size = roundUp(c.pool.size, 8) 1376 } 1377 c.pool.size += uint32(sz) 1378 p.Pool = t 1379} 1380 1381// roundUp rounds up x to "to". 1382func roundUp(x, to uint32) uint32 { 1383 if to == 0 || to&(to-1) != 0 { 1384 log.Fatalf("rounded up to a value that is not a power of 2: %d\n", to) 1385 } 1386 return (x + to - 1) &^ (to - 1) 1387} 1388 1389// splitImm24uScaled splits an immediate into a scaled 12 bit unsigned lo value 1390// and an unscaled shifted 12 bit unsigned hi value. These are typically used 1391// by adding or subtracting the hi value and using the lo value as the offset 1392// for a load or store. 1393func splitImm24uScaled(v int32, shift int) (int32, int32, error) { 1394 if v < 0 { 1395 return 0, 0, fmt.Errorf("%d is not a 24 bit unsigned immediate", v) 1396 } 1397 if v > 0xfff000+0xfff<<shift { 1398 return 0, 0, fmt.Errorf("%d is too large for a scaled 24 bit unsigned immediate", v) 1399 } 1400 if v&((1<<shift)-1) != 0 { 1401 return 0, 0, fmt.Errorf("%d is not a multiple of %d", v, 1<<shift) 1402 } 1403 lo := (v >> shift) & 0xfff 1404 hi := v - (lo << shift) 1405 if hi > 0xfff000 { 1406 hi = 0xfff000 1407 lo = (v - hi) >> shift 1408 } 1409 if hi & ^0xfff000 != 0 { 1410 panic(fmt.Sprintf("bad split for %x with shift %v (%x, %x)", v, shift, hi, lo)) 1411 } 1412 return hi, lo, nil 1413} 1414 1415func (c *ctxt7) regoff(a *obj.Addr) int32 { 1416 c.instoffset = 0 1417 c.aclass(a) 1418 return int32(c.instoffset) 1419} 1420 1421func isSTLXRop(op obj.As) bool { 1422 switch op { 1423 case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH, 1424 ASTXR, ASTXRW, ASTXRB, ASTXRH: 1425 return true 1426 } 1427 return false 1428} 1429 1430func isSTXPop(op obj.As) bool { 1431 switch op { 1432 case ASTXP, ASTLXP, ASTXPW, ASTLXPW: 1433 return true 1434 } 1435 return false 1436} 1437 1438func isANDop(op obj.As) bool { 1439 switch op { 1440 case AAND, AORR, AEOR, AANDS, ATST, 1441 ABIC, AEON, AORN, ABICS: 1442 return true 1443 } 1444 return false 1445} 1446 1447func isANDWop(op obj.As) bool { 1448 switch op { 1449 case AANDW, AORRW, AEORW, AANDSW, ATSTW, 1450 ABICW, AEONW, AORNW, ABICSW: 1451 return true 1452 } 1453 return false 1454} 1455 1456func isADDop(op obj.As) bool { 1457 switch op { 1458 case AADD, AADDS, ASUB, ASUBS, ACMN, ACMP: 1459 return true 1460 } 1461 return false 1462} 1463 1464func isADDWop(op obj.As) bool { 1465 switch op { 1466 case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW: 1467 return true 1468 } 1469 return false 1470} 1471 1472func isADDSop(op obj.As) bool { 1473 switch op { 1474 case AADDS, AADDSW, ASUBS, ASUBSW: 1475 return true 1476 } 1477 return false 1478} 1479 1480func isNEGop(op obj.As) bool { 1481 switch op { 1482 case ANEG, ANEGW, ANEGS, ANEGSW: 1483 return true 1484 } 1485 return false 1486} 1487 1488func isLoadStorePairOp(op obj.As) bool { 1489 switch op { 1490 case AFLDPQ, AFSTPQ, ALDP, ASTP, ALDPW, ASTPW: 1491 return true 1492 } 1493 return false 1494} 1495 1496func isMOVop(op obj.As) bool { 1497 switch op { 1498 case AMOVB, AMOVBU, AMOVH, AMOVHU, AMOVW, AMOVWU, AMOVD, AFMOVS, AFMOVD, AFMOVQ: 1499 return true 1500 } 1501 return false 1502} 1503 1504func isRegShiftOrExt(a *obj.Addr) bool { 1505 return (a.Index-obj.RBaseARM64)®_EXT != 0 || (a.Index-obj.RBaseARM64)®_LSL != 0 1506} 1507 1508// Maximum PC-relative displacement. 1509// The actual limit is ±2²⁰, but we are conservative 1510// to avoid needing to recompute the literal pool flush points 1511// as span-dependent jumps are enlarged. 1512const maxPCDisp = 512 * 1024 1513 1514// ispcdisp reports whether v is a valid PC-relative displacement. 1515func ispcdisp(v int32) bool { 1516 return -maxPCDisp < v && v < maxPCDisp && v&3 == 0 1517} 1518 1519func isaddcon(v int64) bool { 1520 /* uimm12 or uimm24? */ 1521 if v < 0 { 1522 return false 1523 } 1524 if (v & 0xFFF) == 0 { 1525 v >>= 12 1526 } 1527 return v <= 0xFFF 1528} 1529 1530func isaddcon2(v int64) bool { 1531 return 0 <= v && v <= 0xFFFFFF 1532} 1533 1534// isbitcon reports whether a constant can be encoded into a logical instruction. 1535// bitcon has a binary form of repetition of a bit sequence of length 2, 4, 8, 16, 32, or 64, 1536// which itself is a rotate (w.r.t. the length of the unit) of a sequence of ones. 1537// special cases: 0 and -1 are not bitcon. 1538// this function needs to run against virtually all the constants, so it needs to be fast. 1539// for this reason, bitcon testing and bitcon encoding are separate functions. 1540func isbitcon(x uint64) bool { 1541 if x == 1<<64-1 || x == 0 { 1542 return false 1543 } 1544 // determine the period and sign-extend a unit to 64 bits 1545 switch { 1546 case x != x>>32|x<<32: 1547 // period is 64 1548 // nothing to do 1549 case x != x>>16|x<<48: 1550 // period is 32 1551 x = uint64(int64(int32(x))) 1552 case x != x>>8|x<<56: 1553 // period is 16 1554 x = uint64(int64(int16(x))) 1555 case x != x>>4|x<<60: 1556 // period is 8 1557 x = uint64(int64(int8(x))) 1558 default: 1559 // period is 4 or 2, always true 1560 // 0001, 0010, 0100, 1000 -- 0001 rotate 1561 // 0011, 0110, 1100, 1001 -- 0011 rotate 1562 // 0111, 1011, 1101, 1110 -- 0111 rotate 1563 // 0101, 1010 -- 01 rotate, repeat 1564 return true 1565 } 1566 return sequenceOfOnes(x) || sequenceOfOnes(^x) 1567} 1568 1569// sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros. 1570func sequenceOfOnes(x uint64) bool { 1571 y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2 1572 y += x 1573 return (y-1)&y == 0 1574} 1575 1576// bitconEncode returns the encoding of a bitcon used in logical instructions 1577// x is known to be a bitcon 1578// a bitcon is a sequence of n ones at low bits (i.e. 1<<n-1), right rotated 1579// by R bits, and repeated with period of 64, 32, 16, 8, 4, or 2. 1580// it is encoded in logical instructions with 3 bitfields 1581// N (1 bit) : R (6 bits) : S (6 bits), where 1582// N=1 -- period=64 1583// N=0, S=0xxxxx -- period=32 1584// N=0, S=10xxxx -- period=16 1585// N=0, S=110xxx -- period=8 1586// N=0, S=1110xx -- period=4 1587// N=0, S=11110x -- period=2 1588// R is the shift amount, low bits of S = n-1 1589func bitconEncode(x uint64, mode int) uint32 { 1590 if mode == 32 { 1591 x &= 0xffffffff 1592 x = x<<32 | x 1593 } 1594 var period uint32 1595 // determine the period and sign-extend a unit to 64 bits 1596 switch { 1597 case x != x>>32|x<<32: 1598 period = 64 1599 case x != x>>16|x<<48: 1600 period = 32 1601 x = uint64(int64(int32(x))) 1602 case x != x>>8|x<<56: 1603 period = 16 1604 x = uint64(int64(int16(x))) 1605 case x != x>>4|x<<60: 1606 period = 8 1607 x = uint64(int64(int8(x))) 1608 case x != x>>2|x<<62: 1609 period = 4 1610 x = uint64(int64(x<<60) >> 60) 1611 default: 1612 period = 2 1613 x = uint64(int64(x<<62) >> 62) 1614 } 1615 neg := false 1616 if int64(x) < 0 { 1617 x = ^x 1618 neg = true 1619 } 1620 y := x & -x // lowest set bit of x. 1621 s := log2(y) 1622 n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits 1623 if neg { 1624 // ^x is a sequence of n ones left shifted by s bits 1625 // adjust n, s for x 1626 s = n + s 1627 n = period - n 1628 } 1629 1630 N := uint32(0) 1631 if mode == 64 && period == 64 { 1632 N = 1 1633 } 1634 R := (period - s) & (period - 1) & uint32(mode-1) // shift amount of right rotate 1635 S := (n - 1) | 63&^(period<<1-1) // low bits = #ones - 1, high bits encodes period 1636 return N<<22 | R<<16 | S<<10 1637} 1638 1639func log2(x uint64) uint32 { 1640 if x == 0 { 1641 panic("log2 of 0") 1642 } 1643 n := uint32(0) 1644 if x >= 1<<32 { 1645 x >>= 32 1646 n += 32 1647 } 1648 if x >= 1<<16 { 1649 x >>= 16 1650 n += 16 1651 } 1652 if x >= 1<<8 { 1653 x >>= 8 1654 n += 8 1655 } 1656 if x >= 1<<4 { 1657 x >>= 4 1658 n += 4 1659 } 1660 if x >= 1<<2 { 1661 x >>= 2 1662 n += 2 1663 } 1664 if x >= 1<<1 { 1665 x >>= 1 1666 n += 1 1667 } 1668 return n 1669} 1670 1671func autoclass(l int64) int { 1672 if l == 0 { 1673 return C_ZAUTO 1674 } 1675 1676 if l < 0 { 1677 if l >= -256 && (l&15) == 0 { 1678 return C_NSAUTO_16 1679 } 1680 if l >= -256 && (l&7) == 0 { 1681 return C_NSAUTO_8 1682 } 1683 if l >= -256 && (l&3) == 0 { 1684 return C_NSAUTO_4 1685 } 1686 if l >= -256 { 1687 return C_NSAUTO 1688 } 1689 if l >= -512 && (l&15) == 0 { 1690 return C_NPAUTO_16 1691 } 1692 if l >= -512 && (l&7) == 0 { 1693 return C_NPAUTO 1694 } 1695 if l >= -1024 && (l&15) == 0 { 1696 return C_NQAUTO_16 1697 } 1698 if l >= -4095 { 1699 return C_NAUTO4K 1700 } 1701 return C_LAUTO 1702 } 1703 1704 if l <= 255 { 1705 if (l & 15) == 0 { 1706 return C_PSAUTO_16 1707 } 1708 if (l & 7) == 0 { 1709 return C_PSAUTO_8 1710 } 1711 if (l & 3) == 0 { 1712 return C_PSAUTO_4 1713 } 1714 return C_PSAUTO 1715 } 1716 if l <= 504 { 1717 if l&15 == 0 { 1718 return C_PPAUTO_16 1719 } 1720 if l&7 == 0 { 1721 return C_PPAUTO 1722 } 1723 } 1724 if l <= 1008 { 1725 if l&15 == 0 { 1726 return C_PQAUTO_16 1727 } 1728 } 1729 if l <= 4095 { 1730 if l&15 == 0 { 1731 return C_UAUTO4K_16 1732 } 1733 if l&7 == 0 { 1734 return C_UAUTO4K_8 1735 } 1736 if l&3 == 0 { 1737 return C_UAUTO4K_4 1738 } 1739 if l&1 == 0 { 1740 return C_UAUTO4K_2 1741 } 1742 return C_UAUTO4K 1743 } 1744 if l <= 8190 { 1745 if l&15 == 0 { 1746 return C_UAUTO8K_16 1747 } 1748 if l&7 == 0 { 1749 return C_UAUTO8K_8 1750 } 1751 if l&3 == 0 { 1752 return C_UAUTO8K_4 1753 } 1754 if l&1 == 0 { 1755 return C_UAUTO8K 1756 } 1757 } 1758 if l <= 16380 { 1759 if l&15 == 0 { 1760 return C_UAUTO16K_16 1761 } 1762 if l&7 == 0 { 1763 return C_UAUTO16K_8 1764 } 1765 if l&3 == 0 { 1766 return C_UAUTO16K 1767 } 1768 } 1769 if l <= 32760 { 1770 if l&15 == 0 { 1771 return C_UAUTO32K_16 1772 } 1773 if l&7 == 0 { 1774 return C_UAUTO32K 1775 } 1776 } 1777 if l <= 65520 && (l&15) == 0 { 1778 return C_UAUTO64K 1779 } 1780 return C_LAUTO 1781} 1782 1783func oregclass(l int64) int { 1784 return autoclass(l) - C_ZAUTO + C_ZOREG 1785} 1786 1787/* 1788 * given an offset v and a class c (see above) 1789 * return the offset value to use in the instruction, 1790 * scaled if necessary 1791 */ 1792func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 { 1793 s := 0 1794 if cls >= C_SEXT1 && cls <= C_SEXT16 { 1795 s = cls - C_SEXT1 1796 } else { 1797 switch cls { 1798 case C_UAUTO4K, C_UOREG4K, C_ZOREG: 1799 s = 0 1800 case C_UAUTO8K, C_UOREG8K: 1801 s = 1 1802 case C_UAUTO16K, C_UOREG16K: 1803 s = 2 1804 case C_UAUTO32K, C_UOREG32K: 1805 s = 3 1806 case C_UAUTO64K, C_UOREG64K: 1807 s = 4 1808 default: 1809 c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p) 1810 } 1811 } 1812 vs := v >> uint(s) 1813 if vs<<uint(s) != v { 1814 c.ctxt.Diag("odd offset: %d\n%v", v, p) 1815 } 1816 return vs 1817} 1818 1819/* 1820 * if v contains a single 16-bit value aligned 1821 * on a 16-bit field, and thus suitable for movk/movn, 1822 * return the field index 0 to 3; otherwise return -1. 1823 */ 1824func movcon(v int64) int { 1825 for s := 0; s < 64; s += 16 { 1826 if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 { 1827 return s / 16 1828 } 1829 } 1830 return -1 1831} 1832 1833func rclass(r int16) int { 1834 switch { 1835 case REG_R0 <= r && r <= REG_R30: // not 31 1836 return C_REG 1837 case r == REGZERO: 1838 return C_ZREG 1839 case REG_F0 <= r && r <= REG_F31: 1840 return C_FREG 1841 case REG_V0 <= r && r <= REG_V31: 1842 return C_VREG 1843 case r == REGSP: 1844 return C_RSP 1845 case r >= REG_ARNG && r < REG_ELEM: 1846 return C_ARNG 1847 case r >= REG_ELEM && r < REG_ELEM_END: 1848 return C_ELEM 1849 case r >= REG_UXTB && r < REG_SPECIAL, 1850 r >= REG_LSL && r < REG_ARNG: 1851 return C_EXTREG 1852 case r >= REG_SPECIAL: 1853 return C_SPR 1854 } 1855 return C_GOK 1856} 1857 1858// con32class reclassifies the constant of 32-bit instruction. Because the constant type is 32-bit, 1859// but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it. 1860func (c *ctxt7) con32class(a *obj.Addr) int { 1861 v := uint32(a.Offset) 1862 // For 32-bit instruction with constant, rewrite 1863 // the high 32-bit to be a repetition of the low 1864 // 32-bit, so that the BITCON test can be shared 1865 // for both 32-bit and 64-bit. 32-bit ops will 1866 // zero the high 32-bit of the destination register 1867 // anyway. 1868 vbitcon := uint64(v)<<32 | uint64(v) 1869 if v == 0 { 1870 return C_ZCON 1871 } 1872 if isaddcon(int64(v)) { 1873 if v <= 0xFFF { 1874 if isbitcon(vbitcon) { 1875 return C_ABCON0 1876 } 1877 return C_ADDCON0 1878 } 1879 if isbitcon(vbitcon) { 1880 return C_ABCON 1881 } 1882 if movcon(int64(v)) >= 0 { 1883 return C_AMCON 1884 } 1885 if movcon(int64(^v)) >= 0 { 1886 return C_AMCON 1887 } 1888 return C_ADDCON 1889 } 1890 1891 t := movcon(int64(v)) 1892 if t >= 0 { 1893 if isbitcon(vbitcon) { 1894 return C_MBCON 1895 } 1896 return C_MOVCON 1897 } 1898 1899 t = movcon(int64(^v)) 1900 if t >= 0 { 1901 if isbitcon(vbitcon) { 1902 return C_MBCON 1903 } 1904 return C_MOVCON 1905 } 1906 1907 if isbitcon(vbitcon) { 1908 return C_BITCON 1909 } 1910 1911 if 0 <= v && v <= 0xffffff { 1912 return C_ADDCON2 1913 } 1914 return C_LCON 1915} 1916 1917// con64class reclassifies the constant of C_VCON and C_LCON class. 1918func (c *ctxt7) con64class(a *obj.Addr) int { 1919 zeroCount := 0 1920 negCount := 0 1921 for i := uint(0); i < 4; i++ { 1922 immh := uint32(a.Offset >> (i * 16) & 0xffff) 1923 if immh == 0 { 1924 zeroCount++ 1925 } else if immh == 0xffff { 1926 negCount++ 1927 } 1928 } 1929 if zeroCount >= 3 || negCount >= 3 { 1930 return C_MOVCON 1931 } else if zeroCount == 2 || negCount == 2 { 1932 return C_MOVCON2 1933 } else if zeroCount == 1 || negCount == 1 { 1934 return C_MOVCON3 1935 } else { 1936 return C_VCON 1937 } 1938} 1939 1940// loadStoreClass reclassifies a load or store operation based on its offset. 1941func (c *ctxt7) loadStoreClass(p *obj.Prog, lsc int, v int64) int { 1942 // Avoid reclassification of pre/post-indexed loads and stores. 1943 if p.Scond == C_XPRE || p.Scond == C_XPOST { 1944 return lsc 1945 } 1946 if cmp(C_NSAUTO, lsc) || cmp(C_NSOREG, lsc) { 1947 return lsc 1948 } 1949 1950 needsPool := true 1951 if v >= -4095 && v <= 4095 { 1952 needsPool = false 1953 } 1954 1955 switch p.As { 1956 case AMOVB, AMOVBU: 1957 if cmp(C_UAUTO4K, lsc) || cmp(C_UOREG4K, lsc) { 1958 return lsc 1959 } 1960 if v >= 0 && v <= 0xffffff { 1961 needsPool = false 1962 } 1963 case AMOVH, AMOVHU: 1964 if cmp(C_UAUTO8K, lsc) || cmp(C_UOREG8K, lsc) { 1965 return lsc 1966 } 1967 if v >= 0 && v <= 0xfff000+0xfff<<1 && v&1 == 0 { 1968 needsPool = false 1969 } 1970 case AMOVW, AMOVWU, AFMOVS: 1971 if cmp(C_UAUTO16K, lsc) || cmp(C_UOREG16K, lsc) { 1972 return lsc 1973 } 1974 if v >= 0 && v <= 0xfff000+0xfff<<2 && v&3 == 0 { 1975 needsPool = false 1976 } 1977 case AMOVD, AFMOVD: 1978 if cmp(C_UAUTO32K, lsc) || cmp(C_UOREG32K, lsc) { 1979 return lsc 1980 } 1981 if v >= 0 && v <= 0xfff000+0xfff<<3 && v&7 == 0 { 1982 needsPool = false 1983 } 1984 case AFMOVQ: 1985 if cmp(C_UAUTO64K, lsc) || cmp(C_UOREG64K, lsc) { 1986 return lsc 1987 } 1988 if v >= 0 && v <= 0xfff000+0xfff<<4 && v&15 == 0 { 1989 needsPool = false 1990 } 1991 } 1992 if needsPool && cmp(C_LAUTO, lsc) { 1993 return C_LAUTOPOOL 1994 } 1995 if needsPool && cmp(C_LOREG, lsc) { 1996 return C_LOREGPOOL 1997 } 1998 return lsc 1999} 2000 2001// loadStorePairClass reclassifies a load or store pair operation based on its offset. 2002func (c *ctxt7) loadStorePairClass(p *obj.Prog, lsc int, v int64) int { 2003 // Avoid reclassification of pre/post-indexed loads and stores. 2004 if p.Scond == C_XPRE || p.Scond == C_XPOST { 2005 return lsc 2006 } 2007 2008 if cmp(C_NAUTO4K, lsc) || cmp(C_NOREG4K, lsc) { 2009 return lsc 2010 } 2011 if cmp(C_UAUTO4K, lsc) || cmp(C_UOREG4K, lsc) { 2012 return lsc 2013 } 2014 2015 needsPool := true 2016 if v >= 0 && v <= 0xffffff { 2017 needsPool = false 2018 } 2019 if needsPool && cmp(C_LAUTO, lsc) { 2020 return C_LAUTOPOOL 2021 } 2022 if needsPool && cmp(C_LOREG, lsc) { 2023 return C_LOREGPOOL 2024 } 2025 return lsc 2026} 2027 2028func (c *ctxt7) aclass(a *obj.Addr) int { 2029 switch a.Type { 2030 case obj.TYPE_NONE: 2031 return C_NONE 2032 2033 case obj.TYPE_REG: 2034 return rclass(a.Reg) 2035 2036 case obj.TYPE_REGREG: 2037 return C_PAIR 2038 2039 case obj.TYPE_SHIFT: 2040 return C_SHIFT 2041 2042 case obj.TYPE_REGLIST: 2043 return C_LIST 2044 2045 case obj.TYPE_MEM: 2046 // The base register should be an integer register. 2047 if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) { 2048 break 2049 } 2050 switch a.Name { 2051 case obj.NAME_EXTERN, obj.NAME_STATIC: 2052 if a.Sym == nil { 2053 break 2054 } 2055 c.instoffset = a.Offset 2056 if a.Sym != nil { // use relocation 2057 if a.Sym.Type == objabi.STLSBSS { 2058 if c.ctxt.Flag_shared { 2059 return C_TLS_IE 2060 } else { 2061 return C_TLS_LE 2062 } 2063 } 2064 return C_ADDR 2065 } 2066 return C_LEXT 2067 2068 case obj.NAME_GOTREF: 2069 return C_GOTADDR 2070 2071 case obj.NAME_AUTO: 2072 if a.Reg == REGSP { 2073 // unset base register for better printing, since 2074 // a.Offset is still relative to pseudo-SP. 2075 a.Reg = obj.REG_NONE 2076 } 2077 // The frame top 8 or 16 bytes are for FP 2078 c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize) 2079 return autoclass(c.instoffset) 2080 2081 case obj.NAME_PARAM: 2082 if a.Reg == REGSP { 2083 // unset base register for better printing, since 2084 // a.Offset is still relative to pseudo-FP. 2085 a.Reg = obj.REG_NONE 2086 } 2087 c.instoffset = int64(c.autosize) + a.Offset + 8 2088 return autoclass(c.instoffset) 2089 2090 case obj.NAME_NONE: 2091 if a.Index != 0 { 2092 if a.Offset != 0 { 2093 if isRegShiftOrExt(a) { 2094 // extended or shifted register offset, (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2). 2095 return C_ROFF 2096 } 2097 return C_GOK 2098 } 2099 // register offset, (Rn)(Rm) 2100 return C_ROFF 2101 } 2102 c.instoffset = a.Offset 2103 return oregclass(c.instoffset) 2104 } 2105 return C_GOK 2106 2107 case obj.TYPE_FCONST: 2108 return C_FCON 2109 2110 case obj.TYPE_TEXTSIZE: 2111 return C_TEXTSIZE 2112 2113 case obj.TYPE_CONST, obj.TYPE_ADDR: 2114 switch a.Name { 2115 case obj.NAME_NONE: 2116 c.instoffset = a.Offset 2117 if a.Reg != 0 && a.Reg != REGZERO { 2118 break 2119 } 2120 v := c.instoffset 2121 if v == 0 { 2122 return C_ZCON 2123 } 2124 if isaddcon(v) { 2125 if v <= 0xFFF { 2126 if isbitcon(uint64(v)) { 2127 return C_ABCON0 2128 } 2129 return C_ADDCON0 2130 } 2131 if isbitcon(uint64(v)) { 2132 return C_ABCON 2133 } 2134 if movcon(v) >= 0 { 2135 return C_AMCON 2136 } 2137 if movcon(^v) >= 0 { 2138 return C_AMCON 2139 } 2140 return C_ADDCON 2141 } 2142 2143 t := movcon(v) 2144 if t >= 0 { 2145 if isbitcon(uint64(v)) { 2146 return C_MBCON 2147 } 2148 return C_MOVCON 2149 } 2150 2151 t = movcon(^v) 2152 if t >= 0 { 2153 if isbitcon(uint64(v)) { 2154 return C_MBCON 2155 } 2156 return C_MOVCON 2157 } 2158 2159 if isbitcon(uint64(v)) { 2160 return C_BITCON 2161 } 2162 2163 if 0 <= v && v <= 0xffffff { 2164 return C_ADDCON2 2165 } 2166 2167 if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) { 2168 return C_LCON 2169 } 2170 return C_VCON 2171 2172 case obj.NAME_EXTERN, obj.NAME_STATIC: 2173 if a.Sym == nil { 2174 return C_GOK 2175 } 2176 if a.Sym.Type == objabi.STLSBSS { 2177 c.ctxt.Diag("taking address of TLS variable is not supported") 2178 } 2179 c.instoffset = a.Offset 2180 return C_VCONADDR 2181 2182 case obj.NAME_AUTO: 2183 if a.Reg == REGSP { 2184 // unset base register for better printing, since 2185 // a.Offset is still relative to pseudo-SP. 2186 a.Reg = obj.REG_NONE 2187 } 2188 // The frame top 8 or 16 bytes are for FP 2189 c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize) 2190 2191 case obj.NAME_PARAM: 2192 if a.Reg == REGSP { 2193 // unset base register for better printing, since 2194 // a.Offset is still relative to pseudo-FP. 2195 a.Reg = obj.REG_NONE 2196 } 2197 c.instoffset = int64(c.autosize) + a.Offset + 8 2198 default: 2199 return C_GOK 2200 } 2201 cf := c.instoffset 2202 if isaddcon(cf) || isaddcon(-cf) { 2203 return C_AACON 2204 } 2205 if isaddcon2(cf) { 2206 return C_AACON2 2207 } 2208 2209 return C_LACON 2210 2211 case obj.TYPE_BRANCH: 2212 return C_SBRA 2213 2214 case obj.TYPE_SPECIAL: 2215 opd := SpecialOperand(a.Offset) 2216 if SPOP_EQ <= opd && opd <= SPOP_NV { 2217 return C_COND 2218 } 2219 return C_SPOP 2220 } 2221 return C_GOK 2222} 2223 2224func (c *ctxt7) oplook(p *obj.Prog) *Optab { 2225 a1 := int(p.Optab) 2226 if a1 != 0 { 2227 return &optab[a1-1] 2228 } 2229 a1 = int(p.From.Class) 2230 if a1 == 0 { 2231 a1 = c.aclass(&p.From) 2232 // do not break C_ADDCON2 when S bit is set 2233 if (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) && a1 == C_ADDCON2 { 2234 a1 = C_LCON 2235 } 2236 if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE { 2237 if p.As == AMOVW || isADDWop(p.As) || isANDWop(p.As) { 2238 // For 32-bit instruction with constant, we need to 2239 // treat its offset value as 32 bits to classify it. 2240 a1 = c.con32class(&p.From) 2241 // do not break C_ADDCON2 when S bit is set 2242 if (p.As == AADDSW || p.As == ASUBSW) && a1 == C_ADDCON2 { 2243 a1 = C_LCON 2244 } 2245 } 2246 if ((p.As == AMOVD) || isANDop(p.As) || isADDop(p.As)) && (a1 == C_LCON || a1 == C_VCON) { 2247 // more specific classification of 64-bit integers 2248 a1 = c.con64class(&p.From) 2249 } 2250 } 2251 if p.From.Type == obj.TYPE_MEM { 2252 if isMOVop(p.As) && (cmp(C_LAUTO, a1) || cmp(C_LOREG, a1)) { 2253 // More specific classification of large offset loads and stores. 2254 a1 = c.loadStoreClass(p, a1, c.instoffset) 2255 } 2256 if isLoadStorePairOp(p.As) && (cmp(C_LAUTO, a1) || cmp(C_LOREG, a1)) { 2257 // More specific classification of large offset loads and stores. 2258 a1 = c.loadStorePairClass(p, a1, c.instoffset) 2259 } 2260 } 2261 p.From.Class = int8(a1) 2262 } 2263 2264 a2 := C_NONE 2265 if p.Reg != 0 { 2266 a2 = rclass(p.Reg) 2267 } 2268 2269 a3 := C_NONE 2270 if p.GetFrom3() != nil { 2271 a3 = int(p.GetFrom3().Class) 2272 if a3 == 0 { 2273 a3 = c.aclass(p.GetFrom3()) 2274 p.GetFrom3().Class = int8(a3) 2275 } 2276 } 2277 2278 a4 := int(p.To.Class) 2279 if a4 == 0 { 2280 a4 = c.aclass(&p.To) 2281 if p.To.Type == obj.TYPE_MEM { 2282 if isMOVop(p.As) && (cmp(C_LAUTO, a4) || cmp(C_LOREG, a4)) { 2283 // More specific classification of large offset loads and stores. 2284 a4 = c.loadStoreClass(p, a4, c.instoffset) 2285 } 2286 if isLoadStorePairOp(p.As) && (cmp(C_LAUTO, a4) || cmp(C_LOREG, a4)) { 2287 // More specific classification of large offset loads and stores. 2288 a4 = c.loadStorePairClass(p, a4, c.instoffset) 2289 } 2290 } 2291 p.To.Class = int8(a4) 2292 } 2293 2294 a5 := C_NONE 2295 if p.RegTo2 != 0 { 2296 a5 = rclass(p.RegTo2) 2297 } else if p.GetTo2() != nil { 2298 a5 = int(p.GetTo2().Class) 2299 if a5 == 0 { 2300 a5 = c.aclass(p.GetTo2()) 2301 p.GetTo2().Class = int8(a5) 2302 } 2303 } 2304 2305 if false { 2306 fmt.Printf("oplook %v %d %d %d %d %d\n", p.As, a1, a2, a3, a4, a5) 2307 fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type) 2308 } 2309 2310 ops := oprange[p.As&obj.AMask] 2311 c1 := &xcmp[a1] 2312 c2 := &xcmp[a2] 2313 c3 := &xcmp[a3] 2314 c4 := &xcmp[a4] 2315 c5 := &xcmp[a5] 2316 for i := range ops { 2317 op := &ops[i] 2318 if c1[op.a1] && c2[op.a2] && c3[op.a3] && c4[op.a4] && c5[op.a5] && p.Scond == op.scond { 2319 p.Optab = uint16(cap(optab) - cap(ops) + i + 1) 2320 return op 2321 } 2322 } 2323 2324 c.ctxt.Diag("illegal combination: %v %v %v %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4), DRconv(a5), p.From.Type, p.To.Type) 2325 // Turn illegal instruction into an UNDEF, avoid crashing in asmout 2326 return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0} 2327} 2328 2329func cmp(a int, b int) bool { 2330 if a == b { 2331 return true 2332 } 2333 switch a { 2334 case C_RSP: 2335 if b == C_REG { 2336 return true 2337 } 2338 2339 case C_ZREG: 2340 if b == C_REG { 2341 return true 2342 } 2343 2344 case C_ADDCON0: 2345 if b == C_ZCON || b == C_ABCON0 { 2346 return true 2347 } 2348 2349 case C_ADDCON: 2350 if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON { 2351 return true 2352 } 2353 2354 case C_MBCON: 2355 if b == C_ABCON0 { 2356 return true 2357 } 2358 2359 case C_BITCON: 2360 if b == C_ABCON0 || b == C_ABCON || b == C_MBCON { 2361 return true 2362 } 2363 2364 case C_MOVCON: 2365 if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_ABCON0 || b == C_AMCON { 2366 return true 2367 } 2368 2369 case C_ADDCON2: 2370 if b == C_ZCON || b == C_ADDCON || b == C_ADDCON0 { 2371 return true 2372 } 2373 2374 case C_LCON: 2375 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 { 2376 return true 2377 } 2378 2379 case C_MOVCON2: 2380 return cmp(C_LCON, b) 2381 2382 case C_VCON: 2383 return cmp(C_LCON, b) 2384 2385 case C_LACON: 2386 if b == C_AACON || b == C_AACON2 { 2387 return true 2388 } 2389 2390 case C_SEXT2: 2391 if b == C_SEXT1 { 2392 return true 2393 } 2394 2395 case C_SEXT4: 2396 if b == C_SEXT1 || b == C_SEXT2 { 2397 return true 2398 } 2399 2400 case C_SEXT8: 2401 if b >= C_SEXT1 && b <= C_SEXT4 { 2402 return true 2403 } 2404 2405 case C_SEXT16: 2406 if b >= C_SEXT1 && b <= C_SEXT8 { 2407 return true 2408 } 2409 2410 case C_LEXT: 2411 if b >= C_SEXT1 && b <= C_SEXT16 { 2412 return true 2413 } 2414 2415 case C_NSAUTO_8: 2416 if b == C_NSAUTO_16 { 2417 return true 2418 } 2419 2420 case C_NSAUTO_4: 2421 if b == C_NSAUTO_16 || b == C_NSAUTO_8 { 2422 return true 2423 } 2424 2425 case C_NSAUTO: 2426 switch b { 2427 case C_NSAUTO_4, C_NSAUTO_8, C_NSAUTO_16: 2428 return true 2429 } 2430 2431 case C_NPAUTO_16: 2432 switch b { 2433 case C_NSAUTO_16: 2434 return true 2435 } 2436 2437 case C_NPAUTO: 2438 switch b { 2439 case C_NSAUTO_16, C_NSAUTO_8, C_NPAUTO_16: 2440 return true 2441 } 2442 2443 case C_NQAUTO_16: 2444 switch b { 2445 case C_NSAUTO_16, C_NPAUTO_16: 2446 return true 2447 } 2448 2449 case C_NAUTO4K: 2450 switch b { 2451 case C_NSAUTO_16, C_NSAUTO_8, C_NSAUTO_4, C_NSAUTO, C_NPAUTO_16, 2452 C_NPAUTO, C_NQAUTO_16: 2453 return true 2454 } 2455 2456 case C_PSAUTO_16: 2457 if b == C_ZAUTO { 2458 return true 2459 } 2460 2461 case C_PSAUTO_8: 2462 if b == C_ZAUTO || b == C_PSAUTO_16 { 2463 return true 2464 } 2465 2466 case C_PSAUTO_4: 2467 switch b { 2468 case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8: 2469 return true 2470 } 2471 2472 case C_PSAUTO: 2473 switch b { 2474 case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8, C_PSAUTO_4: 2475 return true 2476 } 2477 2478 case C_PPAUTO_16: 2479 switch b { 2480 case C_ZAUTO, C_PSAUTO_16: 2481 return true 2482 } 2483 2484 case C_PPAUTO: 2485 switch b { 2486 case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8, C_PPAUTO_16: 2487 return true 2488 } 2489 2490 case C_PQAUTO_16: 2491 switch b { 2492 case C_ZAUTO, C_PSAUTO_16, C_PPAUTO_16: 2493 return true 2494 } 2495 2496 case C_UAUTO4K: 2497 switch b { 2498 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16, 2499 C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16, 2500 C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16: 2501 return true 2502 } 2503 2504 case C_UAUTO8K: 2505 switch b { 2506 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16, 2507 C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16, 2508 C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16, 2509 C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16: 2510 return true 2511 } 2512 2513 case C_UAUTO16K: 2514 switch b { 2515 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16, 2516 C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16, 2517 C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16, 2518 C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16, 2519 C_UAUTO16K_8, C_UAUTO16K_16: 2520 return true 2521 } 2522 2523 case C_UAUTO32K: 2524 switch b { 2525 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16, 2526 C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16, 2527 C_UAUTO4K_8, C_UAUTO4K_16, 2528 C_UAUTO8K_8, C_UAUTO8K_16, 2529 C_UAUTO16K_8, C_UAUTO16K_16, 2530 C_UAUTO32K_16: 2531 return true 2532 } 2533 2534 case C_UAUTO64K: 2535 switch b { 2536 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16, 2537 C_PPAUTO_16, C_PQAUTO_16, C_UAUTO4K_16, C_UAUTO8K_16, C_UAUTO16K_16, 2538 C_UAUTO32K_16: 2539 return true 2540 } 2541 2542 case C_LAUTO: 2543 switch b { 2544 case C_ZAUTO, C_NSAUTO, C_NSAUTO_4, C_NSAUTO_8, C_NSAUTO_16, C_NPAUTO_16, C_NPAUTO, C_NQAUTO_16, C_NAUTO4K, 2545 C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16, 2546 C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16, 2547 C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16, 2548 C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16, 2549 C_UAUTO16K, C_UAUTO16K_8, C_UAUTO16K_16, 2550 C_UAUTO32K, C_UAUTO32K_16, 2551 C_UAUTO64K: 2552 return true 2553 } 2554 2555 case C_NSOREG_8: 2556 if b == C_NSOREG_16 { 2557 return true 2558 } 2559 2560 case C_NSOREG_4: 2561 if b == C_NSOREG_8 || b == C_NSOREG_16 { 2562 return true 2563 } 2564 2565 case C_NSOREG: 2566 switch b { 2567 case C_NSOREG_4, C_NSOREG_8, C_NSOREG_16: 2568 return true 2569 } 2570 2571 case C_NPOREG_16: 2572 switch b { 2573 case C_NSOREG_16: 2574 return true 2575 } 2576 2577 case C_NPOREG: 2578 switch b { 2579 case C_NSOREG_16, C_NSOREG_8, C_NPOREG_16: 2580 return true 2581 } 2582 2583 case C_NQOREG_16: 2584 switch b { 2585 case C_NSOREG_16, C_NPOREG_16: 2586 return true 2587 } 2588 2589 case C_NOREG4K: 2590 switch b { 2591 case C_NSOREG_16, C_NSOREG_8, C_NSOREG_4, C_NSOREG, C_NPOREG_16, C_NPOREG, C_NQOREG_16: 2592 return true 2593 } 2594 2595 case C_PSOREG_16: 2596 if b == C_ZOREG { 2597 return true 2598 } 2599 2600 case C_PSOREG_8: 2601 if b == C_ZOREG || b == C_PSOREG_16 { 2602 return true 2603 } 2604 2605 case C_PSOREG_4: 2606 switch b { 2607 case C_ZOREG, C_PSOREG_16, C_PSOREG_8: 2608 return true 2609 } 2610 2611 case C_PSOREG: 2612 switch b { 2613 case C_ZOREG, C_PSOREG_16, C_PSOREG_8, C_PSOREG_4: 2614 return true 2615 } 2616 2617 case C_PPOREG_16: 2618 switch b { 2619 case C_ZOREG, C_PSOREG_16: 2620 return true 2621 } 2622 2623 case C_PPOREG: 2624 switch b { 2625 case C_ZOREG, C_PSOREG_16, C_PSOREG_8, C_PPOREG_16: 2626 return true 2627 } 2628 2629 case C_PQOREG_16: 2630 switch b { 2631 case C_ZOREG, C_PSOREG_16, C_PPOREG_16: 2632 return true 2633 } 2634 2635 case C_UOREG4K: 2636 switch b { 2637 case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16, 2638 C_PPOREG, C_PPOREG_16, C_PQOREG_16, 2639 C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16: 2640 return true 2641 } 2642 2643 case C_UOREG8K: 2644 switch b { 2645 case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16, 2646 C_PPOREG, C_PPOREG_16, C_PQOREG_16, 2647 C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16, 2648 C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16: 2649 return true 2650 } 2651 2652 case C_UOREG16K: 2653 switch b { 2654 case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16, 2655 C_PPOREG, C_PPOREG_16, C_PQOREG_16, 2656 C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16, 2657 C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16, 2658 C_UOREG16K_8, C_UOREG16K_16: 2659 return true 2660 } 2661 2662 case C_UOREG32K: 2663 switch b { 2664 case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16, 2665 C_PPOREG, C_PPOREG_16, C_PQOREG_16, 2666 C_UOREG4K_8, C_UOREG4K_16, 2667 C_UOREG8K_8, C_UOREG8K_16, 2668 C_UOREG16K_8, C_UOREG16K_16, 2669 C_UOREG32K_16: 2670 return true 2671 } 2672 2673 case C_UOREG64K: 2674 switch b { 2675 case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16, 2676 C_PPOREG_16, C_PQOREG_16, C_UOREG4K_16, C_UOREG8K_16, C_UOREG16K_16, 2677 C_UOREG32K_16: 2678 return true 2679 } 2680 2681 case C_LOREG: 2682 switch b { 2683 case C_ZOREG, C_NSOREG, C_NSOREG_4, C_NSOREG_8, C_NSOREG_16, C_NPOREG, C_NPOREG_16, C_NQOREG_16, C_NOREG4K, 2684 C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16, 2685 C_PPOREG, C_PPOREG_16, C_PQOREG_16, 2686 C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16, 2687 C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16, 2688 C_UOREG16K, C_UOREG16K_8, C_UOREG16K_16, 2689 C_UOREG32K, C_UOREG32K_16, 2690 C_UOREG64K: 2691 return true 2692 } 2693 2694 case C_LBRA: 2695 if b == C_SBRA { 2696 return true 2697 } 2698 } 2699 2700 return false 2701} 2702 2703type ocmp []Optab 2704 2705func (x ocmp) Len() int { 2706 return len(x) 2707} 2708 2709func (x ocmp) Swap(i, j int) { 2710 x[i], x[j] = x[j], x[i] 2711} 2712 2713func (x ocmp) Less(i, j int) bool { 2714 p1 := &x[i] 2715 p2 := &x[j] 2716 if p1.as != p2.as { 2717 return p1.as < p2.as 2718 } 2719 if p1.a1 != p2.a1 { 2720 return p1.a1 < p2.a1 2721 } 2722 if p1.a2 != p2.a2 { 2723 return p1.a2 < p2.a2 2724 } 2725 if p1.a3 != p2.a3 { 2726 return p1.a3 < p2.a3 2727 } 2728 if p1.a4 != p2.a4 { 2729 return p1.a4 < p2.a4 2730 } 2731 if p1.scond != p2.scond { 2732 return p1.scond < p2.scond 2733 } 2734 return false 2735} 2736 2737func oprangeset(a obj.As, t []Optab) { 2738 oprange[a&obj.AMask] = t 2739} 2740 2741func buildop(ctxt *obj.Link) { 2742 if oprange[AAND&obj.AMask] != nil { 2743 // Already initialized; stop now. 2744 // This happens in the cmd/asm tests, 2745 // each of which re-initializes the arch. 2746 return 2747 } 2748 2749 for i := 0; i < C_GOK; i++ { 2750 for j := 0; j < C_GOK; j++ { 2751 if cmp(j, i) { 2752 xcmp[i][j] = true 2753 } 2754 } 2755 } 2756 2757 sort.Sort(ocmp(optab)) 2758 for i := 0; i < len(optab); i++ { 2759 as, start := optab[i].as, i 2760 for ; i < len(optab)-1; i++ { 2761 if optab[i+1].as != as { 2762 break 2763 } 2764 } 2765 t := optab[start : i+1] 2766 oprangeset(as, t) 2767 switch as { 2768 default: 2769 ctxt.Diag("unknown op in build: %v", as) 2770 ctxt.DiagFlush() 2771 log.Fatalf("bad code") 2772 2773 case AADD: 2774 oprangeset(AADDS, t) 2775 oprangeset(ASUB, t) 2776 oprangeset(ASUBS, t) 2777 oprangeset(AADDW, t) 2778 oprangeset(AADDSW, t) 2779 oprangeset(ASUBW, t) 2780 oprangeset(ASUBSW, t) 2781 2782 case AAND: /* logical immediate, logical shifted register */ 2783 oprangeset(AANDW, t) 2784 oprangeset(AEOR, t) 2785 oprangeset(AEORW, t) 2786 oprangeset(AORR, t) 2787 oprangeset(AORRW, t) 2788 oprangeset(ABIC, t) 2789 oprangeset(ABICW, t) 2790 oprangeset(AEON, t) 2791 oprangeset(AEONW, t) 2792 oprangeset(AORN, t) 2793 oprangeset(AORNW, t) 2794 2795 case AANDS: /* logical immediate, logical shifted register, set flags, cannot target RSP */ 2796 oprangeset(AANDSW, t) 2797 oprangeset(ABICS, t) 2798 oprangeset(ABICSW, t) 2799 2800 case ANEG: 2801 oprangeset(ANEGS, t) 2802 oprangeset(ANEGSW, t) 2803 oprangeset(ANEGW, t) 2804 2805 case AADC: /* rn=Rd */ 2806 oprangeset(AADCW, t) 2807 2808 oprangeset(AADCS, t) 2809 oprangeset(AADCSW, t) 2810 oprangeset(ASBC, t) 2811 oprangeset(ASBCW, t) 2812 oprangeset(ASBCS, t) 2813 oprangeset(ASBCSW, t) 2814 2815 case ANGC: /* rn=REGZERO */ 2816 oprangeset(ANGCW, t) 2817 2818 oprangeset(ANGCS, t) 2819 oprangeset(ANGCSW, t) 2820 2821 case ACMP: 2822 oprangeset(ACMPW, t) 2823 oprangeset(ACMN, t) 2824 oprangeset(ACMNW, t) 2825 2826 case ATST: 2827 oprangeset(ATSTW, t) 2828 2829 /* register/register, and shifted */ 2830 case AMVN: 2831 oprangeset(AMVNW, t) 2832 2833 case AMOVK: 2834 oprangeset(AMOVKW, t) 2835 oprangeset(AMOVN, t) 2836 oprangeset(AMOVNW, t) 2837 oprangeset(AMOVZ, t) 2838 oprangeset(AMOVZW, t) 2839 2840 case ASWPD: 2841 for i := range atomicLDADD { 2842 oprangeset(i, t) 2843 } 2844 for i := range atomicSWP { 2845 if i == ASWPD { 2846 continue 2847 } 2848 oprangeset(i, t) 2849 } 2850 2851 case ACASPD: 2852 oprangeset(ACASPW, t) 2853 case ABEQ: 2854 oprangeset(ABNE, t) 2855 oprangeset(ABCS, t) 2856 oprangeset(ABHS, t) 2857 oprangeset(ABCC, t) 2858 oprangeset(ABLO, t) 2859 oprangeset(ABMI, t) 2860 oprangeset(ABPL, t) 2861 oprangeset(ABVS, t) 2862 oprangeset(ABVC, t) 2863 oprangeset(ABHI, t) 2864 oprangeset(ABLS, t) 2865 oprangeset(ABGE, t) 2866 oprangeset(ABLT, t) 2867 oprangeset(ABGT, t) 2868 oprangeset(ABLE, t) 2869 2870 case ALSL: 2871 oprangeset(ALSLW, t) 2872 oprangeset(ALSR, t) 2873 oprangeset(ALSRW, t) 2874 oprangeset(AASR, t) 2875 oprangeset(AASRW, t) 2876 oprangeset(AROR, t) 2877 oprangeset(ARORW, t) 2878 2879 case ACLS: 2880 oprangeset(ACLSW, t) 2881 oprangeset(ACLZ, t) 2882 oprangeset(ACLZW, t) 2883 oprangeset(ARBIT, t) 2884 oprangeset(ARBITW, t) 2885 oprangeset(AREV, t) 2886 oprangeset(AREVW, t) 2887 oprangeset(AREV16, t) 2888 oprangeset(AREV16W, t) 2889 oprangeset(AREV32, t) 2890 2891 case ASDIV: 2892 oprangeset(ASDIVW, t) 2893 oprangeset(AUDIV, t) 2894 oprangeset(AUDIVW, t) 2895 oprangeset(ACRC32B, t) 2896 oprangeset(ACRC32CB, t) 2897 oprangeset(ACRC32CH, t) 2898 oprangeset(ACRC32CW, t) 2899 oprangeset(ACRC32CX, t) 2900 oprangeset(ACRC32H, t) 2901 oprangeset(ACRC32W, t) 2902 oprangeset(ACRC32X, t) 2903 2904 case AMADD: 2905 oprangeset(AMADDW, t) 2906 oprangeset(AMSUB, t) 2907 oprangeset(AMSUBW, t) 2908 oprangeset(ASMADDL, t) 2909 oprangeset(ASMSUBL, t) 2910 oprangeset(AUMADDL, t) 2911 oprangeset(AUMSUBL, t) 2912 2913 case AREM: 2914 oprangeset(AREMW, t) 2915 oprangeset(AUREM, t) 2916 oprangeset(AUREMW, t) 2917 2918 case AMUL: 2919 oprangeset(AMULW, t) 2920 oprangeset(AMNEG, t) 2921 oprangeset(AMNEGW, t) 2922 oprangeset(ASMNEGL, t) 2923 oprangeset(ASMULL, t) 2924 oprangeset(ASMULH, t) 2925 oprangeset(AUMNEGL, t) 2926 oprangeset(AUMULH, t) 2927 oprangeset(AUMULL, t) 2928 2929 case AMOVB: 2930 oprangeset(AMOVBU, t) 2931 2932 case AMOVH: 2933 oprangeset(AMOVHU, t) 2934 2935 case AMOVW: 2936 oprangeset(AMOVWU, t) 2937 2938 case ABFM: 2939 oprangeset(ABFMW, t) 2940 oprangeset(ASBFM, t) 2941 oprangeset(ASBFMW, t) 2942 oprangeset(AUBFM, t) 2943 oprangeset(AUBFMW, t) 2944 2945 case ABFI: 2946 oprangeset(ABFIW, t) 2947 oprangeset(ABFXIL, t) 2948 oprangeset(ABFXILW, t) 2949 oprangeset(ASBFIZ, t) 2950 oprangeset(ASBFIZW, t) 2951 oprangeset(ASBFX, t) 2952 oprangeset(ASBFXW, t) 2953 oprangeset(AUBFIZ, t) 2954 oprangeset(AUBFIZW, t) 2955 oprangeset(AUBFX, t) 2956 oprangeset(AUBFXW, t) 2957 2958 case AEXTR: 2959 oprangeset(AEXTRW, t) 2960 2961 case ASXTB: 2962 oprangeset(ASXTBW, t) 2963 oprangeset(ASXTH, t) 2964 oprangeset(ASXTHW, t) 2965 oprangeset(ASXTW, t) 2966 oprangeset(AUXTB, t) 2967 oprangeset(AUXTH, t) 2968 oprangeset(AUXTW, t) 2969 oprangeset(AUXTBW, t) 2970 oprangeset(AUXTHW, t) 2971 2972 case ACCMN: 2973 oprangeset(ACCMNW, t) 2974 oprangeset(ACCMP, t) 2975 oprangeset(ACCMPW, t) 2976 2977 case ACSEL: 2978 oprangeset(ACSELW, t) 2979 oprangeset(ACSINC, t) 2980 oprangeset(ACSINCW, t) 2981 oprangeset(ACSINV, t) 2982 oprangeset(ACSINVW, t) 2983 oprangeset(ACSNEG, t) 2984 oprangeset(ACSNEGW, t) 2985 2986 case ACINC: 2987 // aliases Rm=Rn, !cond 2988 oprangeset(ACINCW, t) 2989 oprangeset(ACINV, t) 2990 oprangeset(ACINVW, t) 2991 oprangeset(ACNEG, t) 2992 oprangeset(ACNEGW, t) 2993 2994 // aliases, Rm=Rn=REGZERO, !cond 2995 case ACSET: 2996 oprangeset(ACSETW, t) 2997 2998 oprangeset(ACSETM, t) 2999 oprangeset(ACSETMW, t) 3000 3001 case AMOVD, 3002 AB, 3003 ABL, 3004 AWORD, 3005 ADWORD, 3006 obj.ARET, 3007 obj.ATEXT: 3008 break 3009 3010 case AFLDPQ: 3011 break 3012 case AFSTPQ: 3013 break 3014 case ALDP: 3015 oprangeset(AFLDPD, t) 3016 3017 case ASTP: 3018 oprangeset(AFSTPD, t) 3019 3020 case ASTPW: 3021 oprangeset(AFSTPS, t) 3022 3023 case ALDPW: 3024 oprangeset(ALDPSW, t) 3025 oprangeset(AFLDPS, t) 3026 3027 case AERET: 3028 oprangeset(AWFE, t) 3029 oprangeset(AWFI, t) 3030 oprangeset(AYIELD, t) 3031 oprangeset(ASEV, t) 3032 oprangeset(ASEVL, t) 3033 oprangeset(ANOOP, t) 3034 oprangeset(ADRPS, t) 3035 3036 case ACBZ: 3037 oprangeset(ACBZW, t) 3038 oprangeset(ACBNZ, t) 3039 oprangeset(ACBNZW, t) 3040 3041 case ATBZ: 3042 oprangeset(ATBNZ, t) 3043 3044 case AADR, AADRP: 3045 break 3046 3047 case ACLREX: 3048 break 3049 3050 case ASVC: 3051 oprangeset(AHVC, t) 3052 oprangeset(AHLT, t) 3053 oprangeset(ASMC, t) 3054 oprangeset(ABRK, t) 3055 oprangeset(ADCPS1, t) 3056 oprangeset(ADCPS2, t) 3057 oprangeset(ADCPS3, t) 3058 3059 case AFADDS: 3060 oprangeset(AFADDD, t) 3061 oprangeset(AFSUBS, t) 3062 oprangeset(AFSUBD, t) 3063 oprangeset(AFMULS, t) 3064 oprangeset(AFMULD, t) 3065 oprangeset(AFNMULS, t) 3066 oprangeset(AFNMULD, t) 3067 oprangeset(AFDIVS, t) 3068 oprangeset(AFMAXD, t) 3069 oprangeset(AFMAXS, t) 3070 oprangeset(AFMIND, t) 3071 oprangeset(AFMINS, t) 3072 oprangeset(AFMAXNMD, t) 3073 oprangeset(AFMAXNMS, t) 3074 oprangeset(AFMINNMD, t) 3075 oprangeset(AFMINNMS, t) 3076 oprangeset(AFDIVD, t) 3077 3078 case AFMSUBD: 3079 oprangeset(AFMSUBS, t) 3080 oprangeset(AFMADDS, t) 3081 oprangeset(AFMADDD, t) 3082 oprangeset(AFNMSUBS, t) 3083 oprangeset(AFNMSUBD, t) 3084 oprangeset(AFNMADDS, t) 3085 oprangeset(AFNMADDD, t) 3086 3087 case AFCVTSD: 3088 oprangeset(AFCVTDS, t) 3089 oprangeset(AFABSD, t) 3090 oprangeset(AFABSS, t) 3091 oprangeset(AFNEGD, t) 3092 oprangeset(AFNEGS, t) 3093 oprangeset(AFSQRTD, t) 3094 oprangeset(AFSQRTS, t) 3095 oprangeset(AFRINTNS, t) 3096 oprangeset(AFRINTND, t) 3097 oprangeset(AFRINTPS, t) 3098 oprangeset(AFRINTPD, t) 3099 oprangeset(AFRINTMS, t) 3100 oprangeset(AFRINTMD, t) 3101 oprangeset(AFRINTZS, t) 3102 oprangeset(AFRINTZD, t) 3103 oprangeset(AFRINTAS, t) 3104 oprangeset(AFRINTAD, t) 3105 oprangeset(AFRINTXS, t) 3106 oprangeset(AFRINTXD, t) 3107 oprangeset(AFRINTIS, t) 3108 oprangeset(AFRINTID, t) 3109 oprangeset(AFCVTDH, t) 3110 oprangeset(AFCVTHS, t) 3111 oprangeset(AFCVTHD, t) 3112 oprangeset(AFCVTSH, t) 3113 3114 case AFCMPS: 3115 oprangeset(AFCMPD, t) 3116 oprangeset(AFCMPES, t) 3117 oprangeset(AFCMPED, t) 3118 3119 case AFCCMPS: 3120 oprangeset(AFCCMPD, t) 3121 oprangeset(AFCCMPES, t) 3122 oprangeset(AFCCMPED, t) 3123 3124 case AFCSELD: 3125 oprangeset(AFCSELS, t) 3126 3127 case AFMOVQ, AFMOVD, AFMOVS, 3128 AVMOVQ, AVMOVD, AVMOVS: 3129 break 3130 3131 case AFCVTZSD: 3132 oprangeset(AFCVTZSDW, t) 3133 oprangeset(AFCVTZSS, t) 3134 oprangeset(AFCVTZSSW, t) 3135 oprangeset(AFCVTZUD, t) 3136 oprangeset(AFCVTZUDW, t) 3137 oprangeset(AFCVTZUS, t) 3138 oprangeset(AFCVTZUSW, t) 3139 3140 case ASCVTFD: 3141 oprangeset(ASCVTFS, t) 3142 oprangeset(ASCVTFWD, t) 3143 oprangeset(ASCVTFWS, t) 3144 oprangeset(AUCVTFD, t) 3145 oprangeset(AUCVTFS, t) 3146 oprangeset(AUCVTFWD, t) 3147 oprangeset(AUCVTFWS, t) 3148 3149 case ASYS: 3150 oprangeset(AAT, t) 3151 oprangeset(AIC, t) 3152 3153 case ATLBI: 3154 oprangeset(ADC, t) 3155 3156 case ASYSL, AHINT: 3157 break 3158 3159 case ADMB: 3160 oprangeset(ADSB, t) 3161 oprangeset(AISB, t) 3162 3163 case AMRS, AMSR: 3164 break 3165 3166 case ALDAR: 3167 oprangeset(ALDARW, t) 3168 oprangeset(ALDARB, t) 3169 oprangeset(ALDARH, t) 3170 fallthrough 3171 3172 case ALDXR: 3173 oprangeset(ALDXRB, t) 3174 oprangeset(ALDXRH, t) 3175 oprangeset(ALDXRW, t) 3176 3177 case ALDAXR: 3178 oprangeset(ALDAXRB, t) 3179 oprangeset(ALDAXRH, t) 3180 oprangeset(ALDAXRW, t) 3181 3182 case ALDXP: 3183 oprangeset(ALDXPW, t) 3184 oprangeset(ALDAXP, t) 3185 oprangeset(ALDAXPW, t) 3186 3187 case ASTLR: 3188 oprangeset(ASTLRB, t) 3189 oprangeset(ASTLRH, t) 3190 oprangeset(ASTLRW, t) 3191 3192 case ASTXR: 3193 oprangeset(ASTXRB, t) 3194 oprangeset(ASTXRH, t) 3195 oprangeset(ASTXRW, t) 3196 3197 case ASTLXR: 3198 oprangeset(ASTLXRB, t) 3199 oprangeset(ASTLXRH, t) 3200 oprangeset(ASTLXRW, t) 3201 3202 case ASTXP: 3203 oprangeset(ASTLXP, t) 3204 oprangeset(ASTLXPW, t) 3205 oprangeset(ASTXPW, t) 3206 3207 case AVADDP: 3208 oprangeset(AVAND, t) 3209 oprangeset(AVCMEQ, t) 3210 oprangeset(AVORR, t) 3211 oprangeset(AVEOR, t) 3212 oprangeset(AVBSL, t) 3213 oprangeset(AVBIT, t) 3214 oprangeset(AVCMTST, t) 3215 oprangeset(AVUMAX, t) 3216 oprangeset(AVUMIN, t) 3217 oprangeset(AVUZP1, t) 3218 oprangeset(AVUZP2, t) 3219 oprangeset(AVBIF, t) 3220 3221 case AVADD: 3222 oprangeset(AVSUB, t) 3223 oprangeset(AVRAX1, t) 3224 3225 case AAESD: 3226 oprangeset(AAESE, t) 3227 oprangeset(AAESMC, t) 3228 oprangeset(AAESIMC, t) 3229 oprangeset(ASHA1SU1, t) 3230 oprangeset(ASHA256SU0, t) 3231 oprangeset(ASHA512SU0, t) 3232 oprangeset(ASHA1H, t) 3233 3234 case ASHA1C: 3235 oprangeset(ASHA1P, t) 3236 oprangeset(ASHA1M, t) 3237 oprangeset(ASHA256H, t) 3238 oprangeset(ASHA256H2, t) 3239 oprangeset(ASHA512H, t) 3240 oprangeset(ASHA512H2, t) 3241 3242 case ASHA1SU0: 3243 oprangeset(ASHA256SU1, t) 3244 oprangeset(ASHA512SU1, t) 3245 3246 case AVADDV: 3247 oprangeset(AVUADDLV, t) 3248 3249 case AVFMLA: 3250 oprangeset(AVFMLS, t) 3251 3252 case AVPMULL: 3253 oprangeset(AVPMULL2, t) 3254 3255 case AVUSHR: 3256 oprangeset(AVSHL, t) 3257 oprangeset(AVSRI, t) 3258 oprangeset(AVSLI, t) 3259 oprangeset(AVUSRA, t) 3260 3261 case AVREV32: 3262 oprangeset(AVCNT, t) 3263 oprangeset(AVRBIT, t) 3264 oprangeset(AVREV64, t) 3265 oprangeset(AVREV16, t) 3266 3267 case AVZIP1: 3268 oprangeset(AVZIP2, t) 3269 oprangeset(AVTRN1, t) 3270 oprangeset(AVTRN2, t) 3271 3272 case AVUXTL: 3273 oprangeset(AVUXTL2, t) 3274 3275 case AVUSHLL: 3276 oprangeset(AVUSHLL2, t) 3277 3278 case AVLD1R: 3279 oprangeset(AVLD2, t) 3280 oprangeset(AVLD2R, t) 3281 oprangeset(AVLD3, t) 3282 oprangeset(AVLD3R, t) 3283 oprangeset(AVLD4, t) 3284 oprangeset(AVLD4R, t) 3285 3286 case AVEOR3: 3287 oprangeset(AVBCAX, t) 3288 3289 case AVUADDW: 3290 oprangeset(AVUADDW2, t) 3291 3292 case AVTBL: 3293 oprangeset(AVTBX, t) 3294 3295 case AVCNT, 3296 AVMOV, 3297 AVLD1, 3298 AVST1, 3299 AVST2, 3300 AVST3, 3301 AVST4, 3302 AVDUP, 3303 AVMOVI, 3304 APRFM, 3305 AVEXT, 3306 AVXAR: 3307 break 3308 3309 case obj.ANOP, 3310 obj.AUNDEF, 3311 obj.AFUNCDATA, 3312 obj.APCALIGN, 3313 obj.APCALIGNMAX, 3314 obj.APCDATA, 3315 obj.ADUFFZERO, 3316 obj.ADUFFCOPY: 3317 break 3318 } 3319 } 3320} 3321 3322// chipfloat7() checks if the immediate constants available in FMOVS/FMOVD instructions. 3323// For details of the range of constants available, see 3324// http://infocenter.arm.com/help/topic/com.arm.doc.dui0473m/dom1359731199385.html. 3325func (c *ctxt7) chipfloat7(e float64) int { 3326 ei := math.Float64bits(e) 3327 l := uint32(int32(ei)) 3328 h := uint32(int32(ei >> 32)) 3329 3330 if l != 0 || h&0xffff != 0 { 3331 return -1 3332 } 3333 h1 := h & 0x7fc00000 3334 if h1 != 0x40000000 && h1 != 0x3fc00000 { 3335 return -1 3336 } 3337 n := 0 3338 3339 // sign bit (a) 3340 if h&0x80000000 != 0 { 3341 n |= 1 << 7 3342 } 3343 3344 // exp sign bit (b) 3345 if h1 == 0x3fc00000 { 3346 n |= 1 << 6 3347 } 3348 3349 // rest of exp and mantissa (cd-efgh) 3350 n |= int((h >> 16) & 0x3f) 3351 3352 //print("match %.8lux %.8lux %d\n", l, h, n); 3353 return n 3354} 3355 3356/* form offset parameter to SYS; special register number */ 3357func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int { 3358 return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5 3359} 3360 3361func SYSARG4(op1 int, Cn int, Cm int, op2 int) int { 3362 return SYSARG5(0, op1, Cn, Cm, op2) 3363} 3364 3365// checkUnpredictable checks if the source and transfer registers are the same register. 3366// ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same. 3367func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) { 3368 if wback && rn != REGSP && (rn == rt1 || rn == rt2) { 3369 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3370 } 3371 if isload && rt1 == rt2 { 3372 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3373 } 3374} 3375 3376/* checkindex checks if index >= 0 && index <= maxindex */ 3377func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) { 3378 if index < 0 || index > maxindex { 3379 c.ctxt.Diag("register element index out of range 0 to %d: %v", maxindex, p) 3380 } 3381} 3382 3383/* checkoffset checks whether the immediate offset is valid for VLD[1-4].P and VST[1-4].P */ 3384func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) { 3385 var offset, list, n, expect int64 3386 switch as { 3387 case AVLD1, AVLD2, AVLD3, AVLD4, AVLD1R, AVLD2R, AVLD3R, AVLD4R: 3388 offset = p.From.Offset 3389 list = p.To.Offset 3390 case AVST1, AVST2, AVST3, AVST4: 3391 offset = p.To.Offset 3392 list = p.From.Offset 3393 default: 3394 c.ctxt.Diag("invalid operation on op %v", p.As) 3395 } 3396 opcode := (list >> 12) & 15 3397 q := (list >> 30) & 1 3398 size := (list >> 10) & 3 3399 if offset == 0 { 3400 return 3401 } 3402 switch opcode { 3403 case 0x7: 3404 n = 1 // one register 3405 case 0xa: 3406 n = 2 // two registers 3407 case 0x6: 3408 n = 3 // three registers 3409 case 0x2: 3410 n = 4 // four registers 3411 default: 3412 c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p) 3413 } 3414 3415 switch as { 3416 case AVLD1R, AVLD2R, AVLD3R, AVLD4R: 3417 if offset != n*(1<<uint(size)) { 3418 c.ctxt.Diag("invalid post-increment offset: %v", p) 3419 } 3420 default: 3421 if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) { 3422 c.ctxt.Diag("invalid post-increment offset: %v", p) 3423 } 3424 } 3425 3426 switch as { 3427 case AVLD1, AVST1: 3428 return 3429 case AVLD1R: 3430 expect = 1 3431 case AVLD2, AVST2, AVLD2R: 3432 expect = 2 3433 case AVLD3, AVST3, AVLD3R: 3434 expect = 3 3435 case AVLD4, AVST4, AVLD4R: 3436 expect = 4 3437 } 3438 3439 if expect != n { 3440 c.ctxt.Diag("expected %d registers, got %d: %v.", expect, n, p) 3441 } 3442} 3443 3444/* checkShiftAmount checks whether the index shift amount is valid */ 3445/* for load with register offset instructions */ 3446func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) { 3447 var amount int16 3448 amount = (a.Index >> 5) & 7 3449 switch p.As { 3450 case AMOVB, AMOVBU: 3451 if amount != 0 { 3452 c.ctxt.Diag("invalid index shift amount: %v", p) 3453 } 3454 case AMOVH, AMOVHU: 3455 if amount != 1 && amount != 0 { 3456 c.ctxt.Diag("invalid index shift amount: %v", p) 3457 } 3458 case AMOVW, AMOVWU, AFMOVS: 3459 if amount != 2 && amount != 0 { 3460 c.ctxt.Diag("invalid index shift amount: %v", p) 3461 } 3462 case AMOVD, AFMOVD: 3463 if amount != 3 && amount != 0 { 3464 c.ctxt.Diag("invalid index shift amount: %v", p) 3465 } 3466 default: 3467 panic("invalid operation") 3468 } 3469} 3470 3471func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { 3472 var os [5]uint32 3473 o1 := uint32(0) 3474 o2 := uint32(0) 3475 o3 := uint32(0) 3476 o4 := uint32(0) 3477 o5 := uint32(0) 3478 if false { /*debug['P']*/ 3479 fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_) 3480 } 3481 switch o.type_ { 3482 default: 3483 c.ctxt.Diag("%v: unknown asm %d", p, o.type_) 3484 3485 case 0: /* pseudo ops */ 3486 break 3487 3488 case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */ 3489 o1 = c.oprrr(p, p.As) 3490 3491 rf := int(p.From.Reg) 3492 rt := int(p.To.Reg) 3493 r := int(p.Reg) 3494 if p.To.Type == obj.TYPE_NONE { 3495 rt = REGZERO 3496 } 3497 if r == obj.REG_NONE { 3498 r = rt 3499 } 3500 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 3501 3502 case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */ 3503 if p.To.Reg == REG_RSP && isADDSop(p.As) { 3504 c.ctxt.Diag("illegal destination register: %v\n", p) 3505 } 3506 o1 = c.opirr(p, p.As) 3507 3508 rt, r := p.To.Reg, p.Reg 3509 if p.To.Type == obj.TYPE_NONE { 3510 if (o1 & Sbit) == 0 { 3511 c.ctxt.Diag("ineffective ZR destination\n%v", p) 3512 } 3513 rt = REGZERO 3514 } 3515 if r == obj.REG_NONE { 3516 r = rt 3517 } 3518 v := c.regoff(&p.From) 3519 o1 = c.oaddi(p, p.As, v, rt, r) 3520 3521 case 3: /* op R<<n[,R],R (shifted register) */ 3522 o1 = c.oprrr(p, p.As) 3523 3524 amount := (p.From.Offset >> 10) & 63 3525 is64bit := o1 & (1 << 31) 3526 if is64bit == 0 && amount >= 32 { 3527 c.ctxt.Diag("shift amount out of range 0 to 31: %v", p) 3528 } 3529 shift := (p.From.Offset >> 22) & 3 3530 if (shift > 2 || shift < 0) && (isADDop(p.As) || isADDWop(p.As) || isNEGop(p.As)) { 3531 c.ctxt.Diag("unsupported shift operator: %v", p) 3532 } 3533 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 3534 rt := int(p.To.Reg) 3535 if p.To.Type == obj.TYPE_NONE { 3536 rt = REGZERO 3537 } 3538 r := int(p.Reg) 3539 if p.As == AMVN || p.As == AMVNW || isNEGop(p.As) { 3540 r = REGZERO 3541 } else if r == obj.REG_NONE { 3542 r = rt 3543 } 3544 o1 |= (uint32(r&31) << 5) | uint32(rt&31) 3545 3546 case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R; mov $addcon2, R */ 3547 rt, r := p.To.Reg, o.param 3548 if r == obj.REG_NONE { 3549 r = REGZERO 3550 } else if r == REGFROM { 3551 r = p.From.Reg 3552 } 3553 if r == obj.REG_NONE { 3554 r = REGSP 3555 } 3556 3557 v := c.regoff(&p.From) 3558 a := AADD 3559 if v < 0 { 3560 a = ASUB 3561 v = -v 3562 } 3563 3564 if o.size(c.ctxt, p) == 8 { 3565 // NOTE: this case does not use REGTMP. If it ever does, 3566 // remove the NOTUSETMP flag in optab. 3567 o1 = c.oaddi(p, a, v&0xfff000, rt, r) 3568 o2 = c.oaddi(p, a, v&0x000fff, rt, rt) 3569 break 3570 } 3571 3572 o1 = c.oaddi(p, a, v, rt, r) 3573 3574 case 5: /* b s; bl s */ 3575 o1 = c.opbra(p, p.As) 3576 3577 if p.To.Sym == nil { 3578 o1 |= uint32(c.brdist(p, 0, 26, 2)) 3579 break 3580 } 3581 3582 rel := obj.Addrel(c.cursym) 3583 rel.Off = int32(c.pc) 3584 rel.Siz = 4 3585 rel.Sym = p.To.Sym 3586 rel.Add = p.To.Offset 3587 rel.Type = objabi.R_CALLARM64 3588 3589 case 6: /* b ,O(R); bl ,O(R) */ 3590 o1 = c.opbrr(p, p.As) 3591 o1 |= uint32(p.To.Reg&31) << 5 3592 if p.As == obj.ACALL { 3593 rel := obj.Addrel(c.cursym) 3594 rel.Off = int32(c.pc) 3595 rel.Siz = 0 3596 rel.Type = objabi.R_CALLIND 3597 } 3598 3599 case 7: /* beq s */ 3600 o1 = c.opbra(p, p.As) 3601 3602 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5) 3603 3604 case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */ 3605 rt, rf := p.To.Reg, p.Reg 3606 if rf == obj.REG_NONE { 3607 rf = rt 3608 } 3609 v := p.From.Offset 3610 switch p.As { 3611 case AASR: 3612 o1 = c.opbfm(p, ASBFM, v, 63, rf, rt) 3613 3614 case AASRW: 3615 o1 = c.opbfm(p, ASBFMW, v, 31, rf, rt) 3616 3617 case ALSL: 3618 o1 = c.opbfm(p, AUBFM, (64-v)&63, 63-v, rf, rt) 3619 3620 case ALSLW: 3621 o1 = c.opbfm(p, AUBFMW, (32-v)&31, 31-v, rf, rt) 3622 3623 case ALSR: 3624 o1 = c.opbfm(p, AUBFM, v, 63, rf, rt) 3625 3626 case ALSRW: 3627 o1 = c.opbfm(p, AUBFMW, v, 31, rf, rt) 3628 3629 case AROR: 3630 o1 = c.opextr(p, AEXTR, v, rf, rf, rt) 3631 3632 case ARORW: 3633 o1 = c.opextr(p, AEXTRW, v, rf, rf, rt) 3634 3635 default: 3636 c.ctxt.Diag("bad shift $con\n%v", p) 3637 break 3638 } 3639 3640 case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */ 3641 o1 = c.oprrr(p, p.As) 3642 3643 r := int(p.Reg) 3644 if r == obj.REG_NONE { 3645 r = int(p.To.Reg) 3646 } 3647 o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31) 3648 3649 case 10: /* brk/hvc/.../svc [$con] */ 3650 o1 = c.opimm(p, p.As) 3651 3652 if p.From.Type != obj.TYPE_NONE { 3653 o1 |= uint32((p.From.Offset & 0xffff) << 5) 3654 } 3655 3656 case 11: /* dword */ 3657 c.aclass(&p.To) 3658 3659 o1 = uint32(c.instoffset) 3660 o2 = uint32(c.instoffset >> 32) 3661 if p.To.Sym != nil { 3662 rel := obj.Addrel(c.cursym) 3663 rel.Off = int32(c.pc) 3664 rel.Siz = 8 3665 rel.Sym = p.To.Sym 3666 rel.Add = p.To.Offset 3667 rel.Type = objabi.R_ADDR 3668 o2 = 0 3669 o1 = o2 3670 } 3671 3672 case 12: /* movT $vcon, reg */ 3673 // NOTE: this case does not use REGTMP. If it ever does, 3674 // remove the NOTUSETMP flag in optab. 3675 num := c.omovlconst(p.As, p, &p.From, int(p.To.Reg), os[:]) 3676 if num == 0 { 3677 c.ctxt.Diag("invalid constant: %v", p) 3678 } 3679 o1 = os[0] 3680 o2 = os[1] 3681 o3 = os[2] 3682 o4 = os[3] 3683 3684 case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */ 3685 if p.Reg == REGTMP { 3686 c.ctxt.Diag("cannot use REGTMP as source: %v\n", p) 3687 } 3688 if p.To.Reg == REG_RSP && isADDSop(p.As) { 3689 c.ctxt.Diag("illegal destination register: %v\n", p) 3690 } 3691 o := uint32(0) 3692 num := uint8(0) 3693 cls := int(p.From.Class) 3694 if isADDWop(p.As) { 3695 if !cmp(C_LCON, cls) { 3696 c.ctxt.Diag("illegal combination: %v", p) 3697 } 3698 num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:]) 3699 } else { 3700 num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:]) 3701 } 3702 if num == 0 { 3703 c.ctxt.Diag("invalid constant: %v", p) 3704 } 3705 3706 rt, r, rf := p.To.Reg, p.Reg, int16(REGTMP) 3707 if p.To.Type == obj.TYPE_NONE { 3708 rt = REGZERO 3709 } 3710 if r == obj.REG_NONE { 3711 r = rt 3712 } 3713 if p.To.Type != obj.TYPE_NONE && (rt == REGSP || r == REGSP) { 3714 o = c.opxrrr(p, p.As, rt, r, rf, false) 3715 o |= LSL0_64 3716 } else { 3717 o = c.oprrr(p, p.As) 3718 o |= uint32(rf&31) << 16 /* shift is 0 */ 3719 o |= uint32(r&31) << 5 3720 o |= uint32(rt & 31) 3721 } 3722 3723 os[num] = o 3724 o1 = os[0] 3725 o2 = os[1] 3726 o3 = os[2] 3727 o4 = os[3] 3728 o5 = os[4] 3729 3730 case 14: /* word */ 3731 if c.aclass(&p.To) == C_ADDR { 3732 c.ctxt.Diag("address constant needs DWORD\n%v", p) 3733 } 3734 o1 = uint32(c.instoffset) 3735 if p.To.Sym != nil { 3736 // This case happens with words generated 3737 // in the PC stream as part of the literal pool. 3738 rel := obj.Addrel(c.cursym) 3739 3740 rel.Off = int32(c.pc) 3741 rel.Siz = 4 3742 rel.Sym = p.To.Sym 3743 rel.Add = p.To.Offset 3744 rel.Type = objabi.R_ADDR 3745 o1 = 0 3746 } 3747 3748 case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub/fmadd/fmsub/fnmadd/fnmsub Rm,Ra,Rn,Rd */ 3749 o1 = c.oprrr(p, p.As) 3750 3751 rf := int(p.From.Reg) 3752 rt := int(p.To.Reg) 3753 var r int 3754 var ra int 3755 if p.From3Type() == obj.TYPE_REG { 3756 r = int(p.GetFrom3().Reg) 3757 ra = int(p.Reg) 3758 if ra == obj.REG_NONE { 3759 ra = REGZERO 3760 } 3761 } else { 3762 r = int(p.Reg) 3763 if r == obj.REG_NONE { 3764 r = rt 3765 } 3766 ra = REGZERO 3767 } 3768 3769 o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31) 3770 3771 case 16: /* XremY R[,R],R -> XdivY; XmsubY */ 3772 o1 = c.oprrr(p, p.As) 3773 3774 rf := int(p.From.Reg) 3775 rt := int(p.To.Reg) 3776 r := int(p.Reg) 3777 if r == obj.REG_NONE { 3778 r = rt 3779 } 3780 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31 3781 o2 = c.oprrr(p, AMSUBW) 3782 o2 |= o1 & (1 << 31) /* same size */ 3783 o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31) 3784 3785 case 17: /* op Rm,[Rn],Rd; default Rn=ZR */ 3786 o1 = c.oprrr(p, p.As) 3787 3788 rf := int(p.From.Reg) 3789 rt := int(p.To.Reg) 3790 r := int(p.Reg) 3791 if p.To.Type == obj.TYPE_NONE { 3792 rt = REGZERO 3793 } 3794 if r == obj.REG_NONE { 3795 r = REGZERO 3796 } 3797 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 3798 3799 case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */ 3800 o1 = c.oprrr(p, p.As) 3801 3802 cond := SpecialOperand(p.From.Offset) 3803 if cond < SPOP_EQ || cond > SPOP_NV || (cond == SPOP_AL || cond == SPOP_NV) && p.From3Type() == obj.TYPE_NONE { 3804 c.ctxt.Diag("invalid condition: %v", p) 3805 } else { 3806 cond -= SPOP_EQ 3807 } 3808 3809 r := int(p.Reg) 3810 var rf int = r 3811 if p.From3Type() == obj.TYPE_NONE { 3812 /* CINC/CINV/CNEG or CSET/CSETM*/ 3813 if r == obj.REG_NONE { 3814 /* CSET/CSETM */ 3815 rf = REGZERO 3816 r = rf 3817 } 3818 cond ^= 1 3819 } else { 3820 rf = int(p.GetFrom3().Reg) /* CSEL */ 3821 } 3822 3823 rt := int(p.To.Reg) 3824 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31) 3825 3826 case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */ 3827 nzcv := int(p.To.Offset) 3828 3829 cond := SpecialOperand(p.From.Offset) 3830 if cond < SPOP_EQ || cond > SPOP_NV { 3831 c.ctxt.Diag("invalid condition\n%v", p) 3832 } else { 3833 cond -= SPOP_EQ 3834 } 3835 var rf int 3836 if p.GetFrom3().Type == obj.TYPE_REG { 3837 o1 = c.oprrr(p, p.As) 3838 rf = int(p.GetFrom3().Reg) /* Rm */ 3839 } else { 3840 o1 = c.opirr(p, p.As) 3841 rf = int(p.GetFrom3().Offset & 0x1F) 3842 } 3843 3844 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv) 3845 3846 case 20: /* movT R,O(R) -> strT */ 3847 v := c.regoff(&p.To) 3848 sz := int32(1 << uint(movesize(p.As))) 3849 3850 rt, rf := p.To.Reg, p.From.Reg 3851 if rt == obj.REG_NONE { 3852 rt = o.param 3853 } 3854 if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ 3855 o1 = c.olsr9s(p, c.opstr(p, p.As), v, rt, rf) 3856 } else { 3857 v = int32(c.offsetshift(p, int64(v), int(o.a4))) 3858 o1 = c.olsr12u(p, c.opstr(p, p.As), v, rt, rf) 3859 } 3860 3861 case 21: /* movT O(R),R -> ldrT */ 3862 v := c.regoff(&p.From) 3863 sz := int32(1 << uint(movesize(p.As))) 3864 3865 rt, rf := p.To.Reg, p.From.Reg 3866 if rf == obj.REG_NONE { 3867 rf = o.param 3868 } 3869 if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ 3870 o1 = c.olsr9s(p, c.opldr(p, p.As), v, rf, rt) 3871 } else { 3872 v = int32(c.offsetshift(p, int64(v), int(o.a1))) 3873 o1 = c.olsr12u(p, c.opldr(p, p.As), v, rf, rt) 3874 } 3875 3876 case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */ 3877 if p.From.Reg != REGSP && p.From.Reg == p.To.Reg { 3878 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3879 } 3880 3881 v := int32(p.From.Offset) 3882 3883 if v < -256 || v > 255 { 3884 c.ctxt.Diag("offset out of range [-256,255]: %v", p) 3885 } 3886 o1 = c.opldr(p, p.As) 3887 if o.scond == C_XPOST { 3888 o1 |= 1 << 10 3889 } else { 3890 o1 |= 3 << 10 3891 } 3892 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31) 3893 3894 case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */ 3895 if p.To.Reg != REGSP && p.From.Reg == p.To.Reg { 3896 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 3897 } 3898 3899 v := int32(p.To.Offset) 3900 3901 if v < -256 || v > 255 { 3902 c.ctxt.Diag("offset out of range [-256,255]: %v", p) 3903 } 3904 o1 = c.opstr(p, p.As) 3905 if o.scond == C_XPOST { 3906 o1 |= 1 << 10 3907 } else { 3908 o1 |= 3 << 10 3909 } 3910 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31) 3911 3912 case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */ 3913 rf := int(p.From.Reg) 3914 rt := int(p.To.Reg) 3915 if rf == REGSP || rt == REGSP { 3916 if p.As == AMVN || p.As == AMVNW { 3917 c.ctxt.Diag("illegal SP reference\n%v", p) 3918 } 3919 o1 = c.opirr(p, p.As) 3920 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 3921 } else { 3922 o1 = c.oprrr(p, p.As) 3923 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 3924 } 3925 3926 case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */ 3927 o1 = c.oprrr(p, p.As) 3928 3929 rf := int(p.From.Reg) 3930 if rf == C_NONE { 3931 rf = int(p.To.Reg) 3932 } 3933 rt := int(p.To.Reg) 3934 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 3935 3936 case 26: /* op Vn, Vd; op Vn.<T>, Vd.<T> */ 3937 o1 = c.oprrr(p, p.As) 3938 cf := c.aclass(&p.From) 3939 af := (p.From.Reg >> 5) & 15 3940 at := (p.To.Reg >> 5) & 15 3941 var sz int16 3942 switch p.As { 3943 case AAESD, AAESE, AAESIMC, AAESMC: 3944 sz = ARNG_16B 3945 case ASHA1SU1, ASHA256SU0: 3946 sz = ARNG_4S 3947 case ASHA512SU0: 3948 sz = ARNG_2D 3949 } 3950 3951 if cf == C_ARNG { 3952 if p.As == ASHA1H { 3953 c.ctxt.Diag("invalid operands: %v", p) 3954 } else { 3955 if af != sz || af != at { 3956 c.ctxt.Diag("invalid arrangement: %v", p) 3957 } 3958 } 3959 } 3960 o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31) 3961 3962 case 27: /* op Rm<<n[,Rn],Rd (extended register) */ 3963 if p.To.Reg == REG_RSP && isADDSop(p.As) { 3964 c.ctxt.Diag("illegal destination register: %v\n", p) 3965 } 3966 rt, r, rf := p.To.Reg, p.Reg, p.From.Reg 3967 if p.To.Type == obj.TYPE_NONE { 3968 rt = REGZERO 3969 } 3970 if r == obj.REG_NONE { 3971 r = rt 3972 } 3973 if (p.From.Reg-obj.RBaseARM64)®_EXT != 0 || 3974 (p.From.Reg >= REG_LSL && p.From.Reg < REG_ARNG) { 3975 amount := (p.From.Reg >> 5) & 7 3976 if amount > 4 { 3977 c.ctxt.Diag("shift amount out of range 0 to 4: %v", p) 3978 } 3979 o1 = c.opxrrr(p, p.As, rt, r, obj.REG_NONE, true) 3980 o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Reg) /* includes reg, op, etc */ 3981 } else { 3982 o1 = c.opxrrr(p, p.As, rt, r, rf, false) 3983 } 3984 3985 case 28: /* logop $vcon, [R], R (64 bit literal) */ 3986 if p.Reg == REGTMP { 3987 c.ctxt.Diag("cannot use REGTMP as source: %v\n", p) 3988 } 3989 o := uint32(0) 3990 num := uint8(0) 3991 cls := int(p.From.Class) 3992 if isANDWop(p.As) { 3993 if !cmp(C_LCON, cls) { 3994 c.ctxt.Diag("illegal combination: %v", p) 3995 } 3996 num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:]) 3997 } else { 3998 num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:]) 3999 } 4000 4001 if num == 0 { 4002 c.ctxt.Diag("invalid constant: %v", p) 4003 } 4004 rt := int(p.To.Reg) 4005 if p.To.Type == obj.TYPE_NONE { 4006 rt = REGZERO 4007 } 4008 r := int(p.Reg) 4009 if r == obj.REG_NONE { 4010 r = rt 4011 } 4012 o = c.oprrr(p, p.As) 4013 o |= REGTMP & 31 << 16 /* shift is 0 */ 4014 o |= uint32(r&31) << 5 4015 o |= uint32(rt & 31) 4016 4017 os[num] = o 4018 o1 = os[0] 4019 o2 = os[1] 4020 o3 = os[2] 4021 o4 = os[3] 4022 o5 = os[4] 4023 4024 case 29: /* op Rn, Rd */ 4025 fc := c.aclass(&p.From) 4026 tc := c.aclass(&p.To) 4027 if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZREG || tc == C_REG || tc == C_ZREG) { 4028 // FMOV Rx, Fy or FMOV Fy, Rx 4029 o1 = FPCVTI(0, 0, 0, 0, 6) 4030 if p.As == AFMOVD { 4031 o1 |= 1<<31 | 1<<22 // 64-bit 4032 } 4033 if fc == C_REG || fc == C_ZREG { 4034 o1 |= 1 << 16 // FMOV Rx, Fy 4035 } 4036 } else { 4037 o1 = c.oprrr(p, p.As) 4038 } 4039 o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31) 4040 4041 case 30: /* movT R,L(R) -> strT */ 4042 // If offset L fits in a 12 bit unsigned immediate: 4043 // add $L, R, Rtmp or sub $L, R, Rtmp 4044 // str R, (Rtmp) 4045 // Otherwise, if offset L can be split into hi+lo, and both fit into instructions: 4046 // add $hi, R, Rtmp 4047 // str R, lo(Rtmp) 4048 // Otherwise, use constant pool: 4049 // mov $L, Rtmp (from constant pool) 4050 // str R, (R+Rtmp) 4051 s := movesize(o.as) 4052 if s < 0 { 4053 c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) 4054 } 4055 4056 r := p.To.Reg 4057 if r == obj.REG_NONE { 4058 r = o.param 4059 } 4060 4061 v := c.regoff(&p.To) 4062 if v >= -256 && v <= 256 { 4063 c.ctxt.Diag("%v: bad type for offset %d (should be 9 bit signed immediate store)", p, v) 4064 } 4065 if v >= 0 && v <= 4095 && v&((1<<int32(s))-1) == 0 { 4066 c.ctxt.Diag("%v: bad type for offset %d (should be 12 bit unsigned immediate store)", p, v) 4067 } 4068 4069 // Handle smaller unaligned and negative offsets via addition or subtraction. 4070 if v >= -4095 && v <= 4095 { 4071 o1 = c.oaddi12(p, v, REGTMP, int16(r)) 4072 o2 = c.olsr12u(p, c.opstr(p, p.As), 0, REGTMP, p.From.Reg) 4073 break 4074 } 4075 4076 hi, lo, err := splitImm24uScaled(v, s) 4077 if err != nil { 4078 goto storeusepool 4079 } 4080 if p.Pool != nil { 4081 c.ctxt.Diag("%v: unused constant in pool (%v)\n", p, v) 4082 } 4083 o1 = c.oaddi(p, AADD, hi, REGTMP, r) 4084 o2 = c.olsr12u(p, c.opstr(p, p.As), lo, REGTMP, p.From.Reg) 4085 break 4086 4087 storeusepool: 4088 if p.Pool == nil { 4089 c.ctxt.Diag("%v: constant is not in pool", p) 4090 } 4091 if r == REGTMP || p.From.Reg == REGTMP { 4092 c.ctxt.Diag("REGTMP used in large offset store: %v", p) 4093 } 4094 o1 = c.omovlit(AMOVD, p, &p.To, REGTMP) 4095 o2 = c.olsxrr(p, int32(c.opstrr(p, p.As, false)), int(p.From.Reg), int(r), REGTMP) 4096 4097 case 31: /* movT L(R), R -> ldrT */ 4098 // If offset L fits in a 12 bit unsigned immediate: 4099 // add $L, R, Rtmp or sub $L, R, Rtmp 4100 // ldr R, (Rtmp) 4101 // Otherwise, if offset L can be split into hi+lo, and both fit into instructions: 4102 // add $hi, R, Rtmp 4103 // ldr lo(Rtmp), R 4104 // Otherwise, use constant pool: 4105 // mov $L, Rtmp (from constant pool) 4106 // ldr (R+Rtmp), R 4107 s := movesize(o.as) 4108 if s < 0 { 4109 c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) 4110 } 4111 4112 r := p.From.Reg 4113 if r == obj.REG_NONE { 4114 r = o.param 4115 } 4116 4117 v := c.regoff(&p.From) 4118 if v >= -256 && v <= 256 { 4119 c.ctxt.Diag("%v: bad type for offset %d (should be 9 bit signed immediate load)", p, v) 4120 } 4121 if v >= 0 && v <= 4095 && v&((1<<int32(s))-1) == 0 { 4122 c.ctxt.Diag("%v: bad type for offset %d (should be 12 bit unsigned immediate load)", p, v) 4123 } 4124 4125 // Handle smaller unaligned and negative offsets via addition or subtraction. 4126 if v >= -4095 && v <= 4095 { 4127 o1 = c.oaddi12(p, v, REGTMP, int16(r)) 4128 o2 = c.olsr12u(p, c.opldr(p, p.As), 0, REGTMP, p.To.Reg) 4129 break 4130 } 4131 4132 hi, lo, err := splitImm24uScaled(v, s) 4133 if err != nil { 4134 goto loadusepool 4135 } 4136 if p.Pool != nil { 4137 c.ctxt.Diag("%v: unused constant in pool (%v)\n", p, v) 4138 } 4139 o1 = c.oaddi(p, AADD, hi, REGTMP, r) 4140 o2 = c.olsr12u(p, c.opldr(p, p.As), lo, REGTMP, p.To.Reg) 4141 break 4142 4143 loadusepool: 4144 if p.Pool == nil { 4145 c.ctxt.Diag("%v: constant is not in pool", p) 4146 } 4147 if r == REGTMP || p.From.Reg == REGTMP { 4148 c.ctxt.Diag("REGTMP used in large offset load: %v", p) 4149 } 4150 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 4151 o2 = c.olsxrr(p, int32(c.opldrr(p, p.As, false)), int(p.To.Reg), int(r), REGTMP) 4152 4153 case 32: /* mov $con, R -> movz/movn */ 4154 o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg)) 4155 4156 case 33: /* movk $uimm16 << pos */ 4157 o1 = c.opirr(p, p.As) 4158 4159 d := p.From.Offset 4160 if d == 0 { 4161 c.ctxt.Diag("zero shifts cannot be handled correctly: %v", p) 4162 } 4163 s := movcon(d) 4164 if s < 0 || s >= 4 { 4165 c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p) 4166 } 4167 if (o1&S64) == 0 && s >= 2 { 4168 c.ctxt.Diag("illegal bit position\n%v", p) 4169 } 4170 if ((uint64(d) >> uint(s*16)) >> 16) != 0 { 4171 c.ctxt.Diag("requires uimm16\n%v", p) 4172 } 4173 rt := int(p.To.Reg) 4174 4175 o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31)) 4176 4177 case 34: /* mov $lacon,R */ 4178 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 4179 rt, r, rf := p.To.Reg, p.From.Reg, int16(REGTMP) 4180 if r == obj.REG_NONE { 4181 r = o.param 4182 } 4183 o2 = c.opxrrr(p, AADD, rt, r, rf, false) 4184 o2 |= LSL0_64 4185 4186 case 35: /* mov SPR,R -> mrs */ 4187 o1 = c.oprrr(p, AMRS) 4188 4189 // SysRegEnc function returns the system register encoding and accessFlags. 4190 _, v, accessFlags := SysRegEnc(p.From.Reg) 4191 if v == 0 { 4192 c.ctxt.Diag("illegal system register:\n%v", p) 4193 } 4194 if (o1 & (v &^ (3 << 19))) != 0 { 4195 c.ctxt.Diag("MRS register value overlap\n%v", p) 4196 } 4197 if accessFlags&SR_READ == 0 { 4198 c.ctxt.Diag("system register is not readable: %v", p) 4199 } 4200 4201 o1 |= v 4202 o1 |= uint32(p.To.Reg & 31) 4203 4204 case 36: /* mov R,SPR */ 4205 o1 = c.oprrr(p, AMSR) 4206 4207 // SysRegEnc function returns the system register encoding and accessFlags. 4208 _, v, accessFlags := SysRegEnc(p.To.Reg) 4209 if v == 0 { 4210 c.ctxt.Diag("illegal system register:\n%v", p) 4211 } 4212 if (o1 & (v &^ (3 << 19))) != 0 { 4213 c.ctxt.Diag("MSR register value overlap\n%v", p) 4214 } 4215 if accessFlags&SR_WRITE == 0 { 4216 c.ctxt.Diag("system register is not writable: %v", p) 4217 } 4218 4219 o1 |= v 4220 o1 |= uint32(p.From.Reg & 31) 4221 4222 case 37: /* mov $con,PSTATEfield -> MSR [immediate] */ 4223 if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 { 4224 c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p) 4225 } 4226 o1 = c.opirr(p, AMSR) 4227 o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */ 4228 v := uint32(0) 4229 // PSTATEfield can be special registers and special operands. 4230 if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_SPSel { 4231 v = 0<<16 | 4<<12 | 5<<5 4232 } else if p.To.Type == obj.TYPE_SPECIAL { 4233 opd := SpecialOperand(p.To.Offset) 4234 for _, pf := range pstatefield { 4235 if pf.opd == opd { 4236 v = pf.enc 4237 break 4238 } 4239 } 4240 } 4241 4242 if v == 0 { 4243 c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p) 4244 } 4245 o1 |= v 4246 4247 case 38: /* clrex [$imm] */ 4248 o1 = c.opimm(p, p.As) 4249 4250 if p.To.Type == obj.TYPE_NONE { 4251 o1 |= 0xF << 8 4252 } else { 4253 o1 |= uint32((p.To.Offset & 0xF) << 8) 4254 } 4255 4256 case 39: /* cbz R, rel */ 4257 o1 = c.opirr(p, p.As) 4258 4259 o1 |= uint32(p.From.Reg & 31) 4260 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5) 4261 4262 case 40: /* tbz */ 4263 o1 = c.opirr(p, p.As) 4264 4265 v := int32(p.From.Offset) 4266 if v < 0 || v > 63 { 4267 c.ctxt.Diag("illegal bit number\n%v", p) 4268 } 4269 o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19) 4270 o1 |= uint32(c.brdist(p, 0, 14, 2) << 5) 4271 o1 |= uint32(p.Reg & 31) 4272 4273 case 41: /* eret, nop, others with no operands */ 4274 o1 = c.op0(p, p.As) 4275 4276 case 42: /* bfm R,r,s,R */ 4277 o1 = c.opbfm(p, p.As, p.From.Offset, p.GetFrom3().Offset, p.Reg, p.To.Reg) 4278 4279 case 43: /* bfm aliases */ 4280 rt, rf := p.To.Reg, p.Reg 4281 if rf == obj.REG_NONE { 4282 rf = rt 4283 } 4284 r, s := p.From.Offset, p.GetFrom3().Offset 4285 switch p.As { 4286 case ABFI: 4287 if r != 0 { 4288 r = 64 - r 4289 } 4290 o1 = c.opbfm(p, ABFM, r, s-1, rf, rt) 4291 4292 case ABFIW: 4293 if r != 0 { 4294 r = 32 - r 4295 } 4296 o1 = c.opbfm(p, ABFMW, r, s-1, rf, rt) 4297 4298 case ABFXIL: 4299 o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt) 4300 4301 case ABFXILW: 4302 o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt) 4303 4304 case ASBFIZ: 4305 if r != 0 { 4306 r = 64 - r 4307 } 4308 o1 = c.opbfm(p, ASBFM, r, s-1, rf, rt) 4309 4310 case ASBFIZW: 4311 if r != 0 { 4312 r = 32 - r 4313 } 4314 o1 = c.opbfm(p, ASBFMW, r, s-1, rf, rt) 4315 4316 case ASBFX: 4317 o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt) 4318 4319 case ASBFXW: 4320 o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt) 4321 4322 case AUBFIZ: 4323 if r != 0 { 4324 r = 64 - r 4325 } 4326 o1 = c.opbfm(p, AUBFM, r, s-1, rf, rt) 4327 4328 case AUBFIZW: 4329 if r != 0 { 4330 r = 32 - r 4331 } 4332 o1 = c.opbfm(p, AUBFMW, r, s-1, rf, rt) 4333 4334 case AUBFX: 4335 o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt) 4336 4337 case AUBFXW: 4338 o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt) 4339 4340 default: 4341 c.ctxt.Diag("bad bfm alias\n%v", p) 4342 break 4343 } 4344 4345 case 44: /* extr $b, Rn, Rm, Rd */ 4346 o1 = c.opextr(p, p.As, p.From.Offset, p.GetFrom3().Reg, p.Reg, p.To.Reg) 4347 4348 case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */ 4349 as := p.As 4350 rt, rf := p.To.Reg, p.From.Reg 4351 if rf == REGZERO { 4352 as = AMOVWU /* clearer in disassembly */ 4353 } 4354 switch as { 4355 case AMOVB, ASXTB: 4356 o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt) 4357 4358 case AMOVH, ASXTH: 4359 o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt) 4360 4361 case AMOVW, ASXTW: 4362 o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt) 4363 4364 case AMOVBU, AUXTB: 4365 o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt) 4366 4367 case AMOVHU, AUXTH: 4368 o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt) 4369 4370 case AMOVWU: 4371 o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 4372 4373 case AUXTW: 4374 o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt) 4375 4376 case ASXTBW: 4377 o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt) 4378 4379 case ASXTHW: 4380 o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt) 4381 4382 case AUXTBW: 4383 o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt) 4384 4385 case AUXTHW: 4386 o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt) 4387 4388 default: 4389 c.ctxt.Diag("bad sxt %v", as) 4390 break 4391 } 4392 4393 case 46: /* cls */ 4394 o1 = c.opbit(p, p.As) 4395 4396 o1 |= uint32(p.From.Reg&31) << 5 4397 o1 |= uint32(p.To.Reg & 31) 4398 4399 case 47: // SWPx/LDADDx/LDCLRx/LDEORx/LDORx/CASx Rs, (Rb), Rt 4400 rs := p.From.Reg 4401 rt := p.RegTo2 4402 rb := p.To.Reg 4403 4404 // rt can't be sp. 4405 if rt == REG_RSP { 4406 c.ctxt.Diag("illegal destination register: %v\n", p) 4407 } 4408 4409 o1 = atomicLDADD[p.As] | atomicSWP[p.As] 4410 o1 |= uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31) 4411 4412 case 48: /* ADD $C_ADDCON2, Rm, Rd */ 4413 // NOTE: this case does not use REGTMP. If it ever does, 4414 // remove the NOTUSETMP flag in optab. 4415 op := c.opirr(p, p.As) 4416 if op&Sbit != 0 { 4417 c.ctxt.Diag("can not break addition/subtraction when S bit is set", p) 4418 } 4419 rt, r := p.To.Reg, p.Reg 4420 if r == obj.REG_NONE { 4421 r = rt 4422 } 4423 o1 = c.oaddi(p, p.As, c.regoff(&p.From)&0x000fff, rt, r) 4424 o2 = c.oaddi(p, p.As, c.regoff(&p.From)&0xfff000, rt, rt) 4425 4426 case 49: /* op Vm.<T>, Vn, Vd */ 4427 o1 = c.oprrr(p, p.As) 4428 cf := c.aclass(&p.From) 4429 af := (p.From.Reg >> 5) & 15 4430 sz := ARNG_4S 4431 if p.As == ASHA512H || p.As == ASHA512H2 { 4432 sz = ARNG_2D 4433 } 4434 if cf == C_ARNG && af != int16(sz) { 4435 c.ctxt.Diag("invalid arrangement: %v", p) 4436 } 4437 o1 |= uint32(p.From.Reg&31)<<16 | uint32(p.Reg&31)<<5 | uint32(p.To.Reg&31) 4438 4439 case 50: /* sys/sysl */ 4440 o1 = c.opirr(p, p.As) 4441 4442 if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 { 4443 c.ctxt.Diag("illegal SYS argument\n%v", p) 4444 } 4445 o1 |= uint32(p.From.Offset) 4446 if p.To.Type == obj.TYPE_REG { 4447 o1 |= uint32(p.To.Reg & 31) 4448 } else { 4449 o1 |= 0x1F 4450 } 4451 4452 case 51: /* dmb */ 4453 o1 = c.opirr(p, p.As) 4454 4455 if p.From.Type == obj.TYPE_CONST { 4456 o1 |= uint32((p.From.Offset & 0xF) << 8) 4457 } 4458 4459 case 52: /* hint */ 4460 o1 = c.opirr(p, p.As) 4461 4462 o1 |= uint32((p.From.Offset & 0x7F) << 5) 4463 4464 case 53: /* and/or/eor/bic/tst/... $bitcon, Rn, Rd */ 4465 a := p.As 4466 rt := int(p.To.Reg) 4467 if p.To.Type == obj.TYPE_NONE { 4468 rt = REGZERO 4469 } 4470 r := int(p.Reg) 4471 if r == obj.REG_NONE { 4472 r = rt 4473 } 4474 if r == REG_RSP { 4475 c.ctxt.Diag("illegal source register: %v", p) 4476 break 4477 } 4478 mode := 64 4479 v := uint64(p.From.Offset) 4480 switch p.As { 4481 case AANDW, AORRW, AEORW, AANDSW, ATSTW: 4482 mode = 32 4483 case ABIC, AORN, AEON, ABICS: 4484 v = ^v 4485 case ABICW, AORNW, AEONW, ABICSW: 4486 v = ^v 4487 mode = 32 4488 } 4489 o1 = c.opirr(p, a) 4490 o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31) 4491 4492 case 54: /* floating point arith */ 4493 o1 = c.oprrr(p, p.As) 4494 rf := int(p.From.Reg) 4495 rt := int(p.To.Reg) 4496 r := int(p.Reg) 4497 if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */ 4498 r = rf 4499 rf = 0 4500 } else if r == obj.REG_NONE { 4501 r = rt 4502 } 4503 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 4504 4505 case 55: /* floating-point constant */ 4506 var rf int 4507 o1 = 0xf<<25 | 1<<21 | 1<<12 4508 rf = c.chipfloat7(p.From.Val.(float64)) 4509 if rf < 0 { 4510 c.ctxt.Diag("invalid floating-point immediate\n%v", p) 4511 } 4512 if p.As == AFMOVD { 4513 o1 |= 1 << 22 4514 } 4515 o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31) 4516 4517 case 56: /* floating point compare */ 4518 o1 = c.oprrr(p, p.As) 4519 4520 var rf int 4521 if p.From.Type == obj.TYPE_FCONST { 4522 o1 |= 8 /* zero */ 4523 rf = 0 4524 } else { 4525 rf = int(p.From.Reg) 4526 } 4527 rt := int(p.Reg) 4528 o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5 4529 4530 case 57: /* floating point conditional compare */ 4531 o1 = c.oprrr(p, p.As) 4532 4533 cond := SpecialOperand(p.From.Offset) 4534 if cond < SPOP_EQ || cond > SPOP_NV { 4535 c.ctxt.Diag("invalid condition\n%v", p) 4536 } else { 4537 cond -= SPOP_EQ 4538 } 4539 4540 nzcv := int(p.To.Offset) 4541 if nzcv&^0xF != 0 { 4542 c.ctxt.Diag("implausible condition\n%v", p) 4543 } 4544 rf := int(p.Reg) 4545 if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 { 4546 c.ctxt.Diag("illegal FCCMP\n%v", p) 4547 break 4548 } 4549 rt := int(p.GetFrom3().Reg) 4550 o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv) 4551 4552 case 58: /* ldar/ldarb/ldarh/ldaxp/ldxp/ldaxr/ldxr */ 4553 o1 = c.opload(p, p.As) 4554 4555 o1 |= 0x1F << 16 4556 o1 |= uint32(p.From.Reg&31) << 5 4557 if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW { 4558 if int(p.To.Reg) == int(p.To.Offset) { 4559 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 4560 } 4561 o1 |= uint32(p.To.Offset&31) << 10 4562 } else { 4563 o1 |= 0x1F << 10 4564 } 4565 o1 |= uint32(p.To.Reg & 31) 4566 4567 case 59: /* stxr/stlxr/stxp/stlxp */ 4568 s := p.RegTo2 4569 n := p.To.Reg 4570 t := p.From.Reg 4571 if isSTLXRop(p.As) { 4572 if s == t || (s == n && n != REGSP) { 4573 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 4574 } 4575 } else if isSTXPop(p.As) { 4576 t2 := int16(p.From.Offset) 4577 if (s == t || s == t2) || (s == n && n != REGSP) { 4578 c.ctxt.Diag("constrained unpredictable behavior: %v", p) 4579 } 4580 } 4581 if s == REG_RSP { 4582 c.ctxt.Diag("illegal destination register: %v\n", p) 4583 } 4584 o1 = c.opstore(p, p.As) 4585 4586 if p.RegTo2 != obj.REG_NONE { 4587 o1 |= uint32(p.RegTo2&31) << 16 4588 } else { 4589 o1 |= 0x1F << 16 4590 } 4591 if isSTXPop(p.As) { 4592 o1 |= uint32(p.From.Offset&31) << 10 4593 } 4594 o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31) 4595 4596 case 60: /* adrp label,r */ 4597 d := c.brdist(p, 12, 21, 0) 4598 4599 o1 = ADR(1, uint32(d), uint32(p.To.Reg)) 4600 4601 case 61: /* adr label, r */ 4602 d := c.brdist(p, 0, 21, 0) 4603 4604 o1 = ADR(0, uint32(d), uint32(p.To.Reg)) 4605 4606 case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */ 4607 if p.Reg == REGTMP { 4608 c.ctxt.Diag("cannot use REGTMP as source: %v\n", p) 4609 } 4610 if p.To.Reg == REG_RSP && isADDSop(p.As) { 4611 c.ctxt.Diag("illegal destination register: %v\n", p) 4612 } 4613 lsl0 := LSL0_64 4614 if isADDWop(p.As) || isANDWop(p.As) { 4615 o1 = c.omovconst(AMOVW, p, &p.From, REGTMP) 4616 lsl0 = LSL0_32 4617 } else { 4618 o1 = c.omovconst(AMOVD, p, &p.From, REGTMP) 4619 } 4620 4621 rt, r, rf := p.To.Reg, p.Reg, int16(REGTMP) 4622 if p.To.Type == obj.TYPE_NONE { 4623 rt = REGZERO 4624 } 4625 if r == obj.REG_NONE { 4626 r = rt 4627 } 4628 if rt == REGSP || r == REGSP { 4629 o2 = c.opxrrr(p, p.As, rt, r, rf, false) 4630 o2 |= uint32(lsl0) 4631 } else { 4632 o2 = c.oprrr(p, p.As) 4633 o2 |= uint32(rf&31) << 16 /* shift is 0 */ 4634 o2 |= uint32(r&31) << 5 4635 o2 |= uint32(rt & 31) 4636 } 4637 4638 case 63: /* op Vm.<t>, Vn.<T>, Vd.<T> */ 4639 o1 |= c.oprrr(p, p.As) 4640 af := (p.From.Reg >> 5) & 15 4641 at := (p.To.Reg >> 5) & 15 4642 ar := (p.Reg >> 5) & 15 4643 sz := ARNG_4S 4644 if p.As == ASHA512SU1 { 4645 sz = ARNG_2D 4646 } 4647 if af != at || af != ar || af != int16(sz) { 4648 c.ctxt.Diag("invalid arrangement: %v", p) 4649 } 4650 o1 |= uint32(p.From.Reg&31)<<16 | uint32(p.Reg&31)<<5 | uint32(p.To.Reg&31) 4651 4652 /* reloc ops */ 4653 case 64: /* movT R,addr -> adrp + movT R, (REGTMP) */ 4654 if p.From.Reg == REGTMP { 4655 c.ctxt.Diag("cannot use REGTMP as source: %v\n", p) 4656 } 4657 o1 = ADR(1, 0, REGTMP) 4658 rel := obj.Addrel(c.cursym) 4659 rel.Off = int32(c.pc) 4660 rel.Siz = 8 4661 rel.Sym = p.To.Sym 4662 rel.Add = p.To.Offset 4663 // For unaligned access, fall back to adrp + add + movT R, (REGTMP). 4664 if o.size(c.ctxt, p) != 8 { 4665 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 4666 o3 = c.olsr12u(p, c.opstr(p, p.As), 0, REGTMP, p.From.Reg) 4667 rel.Type = objabi.R_ADDRARM64 4668 break 4669 } 4670 o2 = c.olsr12u(p, c.opstr(p, p.As), 0, REGTMP, p.From.Reg) 4671 rel.Type = c.addrRelocType(p) 4672 4673 case 65: /* movT addr,R -> adrp + movT (REGTMP), R */ 4674 o1 = ADR(1, 0, REGTMP) 4675 rel := obj.Addrel(c.cursym) 4676 rel.Off = int32(c.pc) 4677 rel.Siz = 8 4678 rel.Sym = p.From.Sym 4679 rel.Add = p.From.Offset 4680 // For unaligned access, fall back to adrp + add + movT (REGTMP), R. 4681 if o.size(c.ctxt, p) != 8 { 4682 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 4683 o3 = c.olsr12u(p, c.opldr(p, p.As), 0, REGTMP, p.To.Reg) 4684 rel.Type = objabi.R_ADDRARM64 4685 break 4686 } 4687 o2 = c.olsr12u(p, c.opldr(p, p.As), 0, REGTMP, p.To.Reg) 4688 rel.Type = c.addrRelocType(p) 4689 4690 case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */ 4691 rf, rt1, rt2 := p.From.Reg, p.To.Reg, int16(p.To.Offset) 4692 if rf == obj.REG_NONE { 4693 rf = o.param 4694 } 4695 if rf == obj.REG_NONE { 4696 c.ctxt.Diag("invalid ldp source: %v\n", p) 4697 } 4698 v := c.regoff(&p.From) 4699 o1 = c.opldpstp(p, o, v, rf, rt1, rt2, 1) 4700 4701 case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */ 4702 rt, rf1, rf2 := p.To.Reg, p.From.Reg, int16(p.From.Offset) 4703 if rt == obj.REG_NONE { 4704 rt = o.param 4705 } 4706 if rt == obj.REG_NONE { 4707 c.ctxt.Diag("invalid stp destination: %v\n", p) 4708 } 4709 v := c.regoff(&p.To) 4710 o1 = c.opldpstp(p, o, v, rt, rf1, rf2, 0) 4711 4712 case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */ 4713 // NOTE: this case does not use REGTMP. If it ever does, 4714 // remove the NOTUSETMP flag in optab. 4715 if p.As == AMOVW { 4716 c.ctxt.Diag("invalid load of 32-bit address: %v", p) 4717 } 4718 o1 = ADR(1, 0, uint32(p.To.Reg)) 4719 o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31) 4720 rel := obj.Addrel(c.cursym) 4721 rel.Off = int32(c.pc) 4722 rel.Siz = 8 4723 rel.Sym = p.From.Sym 4724 rel.Add = p.From.Offset 4725 rel.Type = objabi.R_ADDRARM64 4726 4727 case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */ 4728 o1 = c.opirr(p, AMOVZ) 4729 o1 |= uint32(p.To.Reg & 31) 4730 rel := obj.Addrel(c.cursym) 4731 rel.Off = int32(c.pc) 4732 rel.Siz = 4 4733 rel.Sym = p.From.Sym 4734 rel.Type = objabi.R_ARM64_TLS_LE 4735 if p.From.Offset != 0 { 4736 c.ctxt.Diag("invalid offset on MOVW $tlsvar") 4737 } 4738 4739 case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */ 4740 o1 = ADR(1, 0, REGTMP) 4741 o2 = c.olsr12u(p, c.opldr(p, AMOVD), 0, REGTMP, p.To.Reg) 4742 rel := obj.Addrel(c.cursym) 4743 rel.Off = int32(c.pc) 4744 rel.Siz = 8 4745 rel.Sym = p.From.Sym 4746 rel.Add = 0 4747 rel.Type = objabi.R_ARM64_TLS_IE 4748 if p.From.Offset != 0 { 4749 c.ctxt.Diag("invalid offset on MOVW $tlsvar") 4750 } 4751 4752 case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */ 4753 o1 = ADR(1, 0, REGTMP) 4754 o2 = c.olsr12u(p, c.opldr(p, AMOVD), 0, REGTMP, p.To.Reg) 4755 rel := obj.Addrel(c.cursym) 4756 rel.Off = int32(c.pc) 4757 rel.Siz = 8 4758 rel.Sym = p.From.Sym 4759 rel.Add = 0 4760 rel.Type = objabi.R_ARM64_GOTPCREL 4761 4762 case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor/vfmla/vfmls/vbit/vbsl/vcmtst/vsub/vbif/vuzip1/vuzip2/vrax1 Vm.<T>, Vn.<T>, Vd.<T> */ 4763 af := int((p.From.Reg >> 5) & 15) 4764 af3 := int((p.Reg >> 5) & 15) 4765 at := int((p.To.Reg >> 5) & 15) 4766 if af != af3 || af != at { 4767 c.ctxt.Diag("operand mismatch: %v", p) 4768 break 4769 } 4770 o1 = c.oprrr(p, p.As) 4771 rf := int((p.From.Reg) & 31) 4772 rt := int((p.To.Reg) & 31) 4773 r := int((p.Reg) & 31) 4774 4775 Q := 0 4776 size := 0 4777 switch af { 4778 case ARNG_16B: 4779 Q = 1 4780 size = 0 4781 case ARNG_2D: 4782 Q = 1 4783 size = 3 4784 case ARNG_2S: 4785 Q = 0 4786 size = 2 4787 case ARNG_4H: 4788 Q = 0 4789 size = 1 4790 case ARNG_4S: 4791 Q = 1 4792 size = 2 4793 case ARNG_8B: 4794 Q = 0 4795 size = 0 4796 case ARNG_8H: 4797 Q = 1 4798 size = 1 4799 default: 4800 c.ctxt.Diag("invalid arrangement: %v", p) 4801 } 4802 4803 switch p.As { 4804 case AVORR, AVAND, AVEOR, AVBIT, AVBSL, AVBIF: 4805 if af != ARNG_16B && af != ARNG_8B { 4806 c.ctxt.Diag("invalid arrangement: %v", p) 4807 } 4808 case AVFMLA, AVFMLS: 4809 if af != ARNG_2D && af != ARNG_2S && af != ARNG_4S { 4810 c.ctxt.Diag("invalid arrangement: %v", p) 4811 } 4812 case AVUMAX, AVUMIN: 4813 if af == ARNG_2D { 4814 c.ctxt.Diag("invalid arrangement: %v", p) 4815 } 4816 } 4817 switch p.As { 4818 case AVAND, AVEOR: 4819 size = 0 4820 case AVBSL: 4821 size = 1 4822 case AVORR, AVBIT, AVBIF: 4823 size = 2 4824 case AVFMLA, AVFMLS: 4825 if af == ARNG_2D { 4826 size = 1 4827 } else { 4828 size = 0 4829 } 4830 case AVRAX1: 4831 if af != ARNG_2D { 4832 c.ctxt.Diag("invalid arrangement: %v", p) 4833 } 4834 size = 0 4835 Q = 0 4836 } 4837 4838 o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 4839 4840 case 73: /* vmov V.<T>[index], R */ 4841 rf := int(p.From.Reg) 4842 rt := int(p.To.Reg) 4843 imm5 := 0 4844 o1 = 7<<25 | 0xf<<10 4845 index := int(p.From.Index) 4846 switch (p.From.Reg >> 5) & 15 { 4847 case ARNG_B: 4848 c.checkindex(p, index, 15) 4849 imm5 |= 1 4850 imm5 |= index << 1 4851 case ARNG_H: 4852 c.checkindex(p, index, 7) 4853 imm5 |= 2 4854 imm5 |= index << 2 4855 case ARNG_S: 4856 c.checkindex(p, index, 3) 4857 imm5 |= 4 4858 imm5 |= index << 3 4859 case ARNG_D: 4860 c.checkindex(p, index, 1) 4861 imm5 |= 8 4862 imm5 |= index << 4 4863 o1 |= 1 << 30 4864 default: 4865 c.ctxt.Diag("invalid arrangement: %v", p) 4866 } 4867 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 4868 4869 case 74: 4870 // add $O, R, Rtmp or sub $O, R, Rtmp 4871 // ldp (Rtmp), (R1, R2) 4872 rf, rt1, rt2 := p.From.Reg, p.To.Reg, int16(p.To.Offset) 4873 if rf == obj.REG_NONE { 4874 rf = o.param 4875 } 4876 if rf == obj.REG_NONE { 4877 c.ctxt.Diag("invalid ldp source: %v", p) 4878 } 4879 v := c.regoff(&p.From) 4880 o1 = c.oaddi12(p, v, REGTMP, rf) 4881 o2 = c.opldpstp(p, o, 0, REGTMP, rt1, rt2, 1) 4882 4883 case 75: 4884 // If offset L fits in a 24 bit unsigned immediate: 4885 // add $lo, R, Rtmp 4886 // add $hi, Rtmp, Rtmp 4887 // ldr (Rtmp), R 4888 // Otherwise, use constant pool: 4889 // mov $L, Rtmp (from constant pool) 4890 // add Rtmp, R, Rtmp 4891 // ldp (Rtmp), (R1, R2) 4892 rf, rt1, rt2 := p.From.Reg, p.To.Reg, int16(p.To.Offset) 4893 if rf == REGTMP { 4894 c.ctxt.Diag("REGTMP used in large offset load: %v", p) 4895 } 4896 if rf == obj.REG_NONE { 4897 rf = o.param 4898 } 4899 if rf == obj.REG_NONE { 4900 c.ctxt.Diag("invalid ldp source: %v", p) 4901 } 4902 4903 v := c.regoff(&p.From) 4904 if v >= -4095 && v <= 4095 { 4905 c.ctxt.Diag("%v: bad type for offset %d (should be add/sub+ldp)", p, v) 4906 } 4907 4908 hi, lo, err := splitImm24uScaled(v, 0) 4909 if err != nil { 4910 goto loadpairusepool 4911 } 4912 if p.Pool != nil { 4913 c.ctxt.Diag("%v: unused constant in pool (%v)\n", p, v) 4914 } 4915 o1 = c.oaddi(p, AADD, lo, REGTMP, int16(rf)) 4916 o2 = c.oaddi(p, AADD, hi, REGTMP, REGTMP) 4917 o3 = c.opldpstp(p, o, 0, REGTMP, rt1, rt2, 1) 4918 break 4919 4920 loadpairusepool: 4921 if p.Pool == nil { 4922 c.ctxt.Diag("%v: constant is not in pool", p) 4923 } 4924 if rf == REGTMP || p.From.Reg == REGTMP { 4925 c.ctxt.Diag("REGTMP used in large offset load: %v", p) 4926 } 4927 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP) 4928 o2 = c.opxrrr(p, AADD, REGTMP, rf, REGTMP, false) 4929 o3 = c.opldpstp(p, o, 0, REGTMP, rt1, rt2, 1) 4930 4931 case 76: 4932 // add $O, R, Rtmp or sub $O, R, Rtmp 4933 // stp (R1, R2), (Rtmp) 4934 rt, rf1, rf2 := p.To.Reg, p.From.Reg, int16(p.From.Offset) 4935 if rf1 == REGTMP || rf2 == REGTMP { 4936 c.ctxt.Diag("cannot use REGTMP as source: %v", p) 4937 } 4938 if rt == obj.REG_NONE { 4939 rt = o.param 4940 } 4941 if rt == obj.REG_NONE { 4942 c.ctxt.Diag("invalid stp destination: %v", p) 4943 } 4944 v := c.regoff(&p.To) 4945 o1 = c.oaddi12(p, v, REGTMP, rt) 4946 o2 = c.opldpstp(p, o, 0, REGTMP, rf1, rf2, 0) 4947 4948 case 77: 4949 // If offset L fits in a 24 bit unsigned immediate: 4950 // add $lo, R, Rtmp 4951 // add $hi, Rtmp, Rtmp 4952 // stp (R1, R2), (Rtmp) 4953 // Otherwise, use constant pool: 4954 // mov $L, Rtmp (from constant pool) 4955 // add Rtmp, R, Rtmp 4956 // stp (R1, R2), (Rtmp) 4957 rt, rf1, rf2 := p.To.Reg, p.From.Reg, int16(p.From.Offset) 4958 if rt == REGTMP || rf1 == REGTMP || rf2 == REGTMP { 4959 c.ctxt.Diag("REGTMP used in large offset store: %v", p) 4960 } 4961 if rt == obj.REG_NONE { 4962 rt = o.param 4963 } 4964 if rt == obj.REG_NONE { 4965 c.ctxt.Diag("invalid stp destination: %v", p) 4966 } 4967 4968 v := c.regoff(&p.To) 4969 if v >= -4095 && v <= 4095 { 4970 c.ctxt.Diag("%v: bad type for offset %d (should be add/sub+stp)", p, v) 4971 } 4972 4973 hi, lo, err := splitImm24uScaled(v, 0) 4974 if err != nil { 4975 goto storepairusepool 4976 } 4977 if p.Pool != nil { 4978 c.ctxt.Diag("%v: unused constant in pool (%v)\n", p, v) 4979 } 4980 o1 = c.oaddi(p, AADD, lo, REGTMP, int16(rt)) 4981 o2 = c.oaddi(p, AADD, hi, REGTMP, REGTMP) 4982 o3 = c.opldpstp(p, o, 0, REGTMP, rf1, rf2, 0) 4983 break 4984 4985 storepairusepool: 4986 if p.Pool == nil { 4987 c.ctxt.Diag("%v: constant is not in pool", p) 4988 } 4989 if rt == REGTMP || p.From.Reg == REGTMP { 4990 c.ctxt.Diag("REGTMP used in large offset store: %v", p) 4991 } 4992 o1 = c.omovlit(AMOVD, p, &p.To, REGTMP) 4993 o2 = c.opxrrr(p, AADD, REGTMP, rt, REGTMP, false) 4994 o3 = c.opldpstp(p, o, 0, REGTMP, rf1, rf2, 0) 4995 4996 case 78: /* vmov R, V.<T>[index] */ 4997 rf := int(p.From.Reg) 4998 rt := int(p.To.Reg) 4999 imm5 := 0 5000 o1 = 1<<30 | 7<<25 | 7<<10 5001 index := int(p.To.Index) 5002 switch (p.To.Reg >> 5) & 15 { 5003 case ARNG_B: 5004 c.checkindex(p, index, 15) 5005 imm5 |= 1 5006 imm5 |= index << 1 5007 case ARNG_H: 5008 c.checkindex(p, index, 7) 5009 imm5 |= 2 5010 imm5 |= index << 2 5011 case ARNG_S: 5012 c.checkindex(p, index, 3) 5013 imm5 |= 4 5014 imm5 |= index << 3 5015 case ARNG_D: 5016 c.checkindex(p, index, 1) 5017 imm5 |= 8 5018 imm5 |= index << 4 5019 default: 5020 c.ctxt.Diag("invalid arrangement: %v", p) 5021 } 5022 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 5023 5024 case 79: /* vdup Vn.<T>[index], Vd.<T> */ 5025 rf := int(p.From.Reg) 5026 rt := int(p.To.Reg) 5027 o1 = 7<<25 | 1<<10 5028 var imm5, Q int 5029 index := int(p.From.Index) 5030 switch (p.To.Reg >> 5) & 15 { 5031 case ARNG_16B: 5032 c.checkindex(p, index, 15) 5033 Q = 1 5034 imm5 = 1 5035 imm5 |= index << 1 5036 case ARNG_2D: 5037 c.checkindex(p, index, 1) 5038 Q = 1 5039 imm5 = 8 5040 imm5 |= index << 4 5041 case ARNG_2S: 5042 c.checkindex(p, index, 3) 5043 Q = 0 5044 imm5 = 4 5045 imm5 |= index << 3 5046 case ARNG_4H: 5047 c.checkindex(p, index, 7) 5048 Q = 0 5049 imm5 = 2 5050 imm5 |= index << 2 5051 case ARNG_4S: 5052 c.checkindex(p, index, 3) 5053 Q = 1 5054 imm5 = 4 5055 imm5 |= index << 3 5056 case ARNG_8B: 5057 c.checkindex(p, index, 15) 5058 Q = 0 5059 imm5 = 1 5060 imm5 |= index << 1 5061 case ARNG_8H: 5062 c.checkindex(p, index, 7) 5063 Q = 1 5064 imm5 = 2 5065 imm5 |= index << 2 5066 default: 5067 c.ctxt.Diag("invalid arrangement: %v", p) 5068 } 5069 o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16) 5070 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 5071 5072 case 80: /* vmov/vdup V.<T>[index], Vn */ 5073 rf := int(p.From.Reg) 5074 rt := int(p.To.Reg) 5075 imm5 := 0 5076 index := int(p.From.Index) 5077 switch p.As { 5078 case AVMOV, AVDUP: 5079 o1 = 1<<30 | 15<<25 | 1<<10 5080 switch (p.From.Reg >> 5) & 15 { 5081 case ARNG_B: 5082 c.checkindex(p, index, 15) 5083 imm5 |= 1 5084 imm5 |= index << 1 5085 case ARNG_H: 5086 c.checkindex(p, index, 7) 5087 imm5 |= 2 5088 imm5 |= index << 2 5089 case ARNG_S: 5090 c.checkindex(p, index, 3) 5091 imm5 |= 4 5092 imm5 |= index << 3 5093 case ARNG_D: 5094 c.checkindex(p, index, 1) 5095 imm5 |= 8 5096 imm5 |= index << 4 5097 default: 5098 c.ctxt.Diag("invalid arrangement: %v", p) 5099 } 5100 default: 5101 c.ctxt.Diag("unsupported op %v", p.As) 5102 } 5103 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 5104 5105 case 81: /* vld[1-4]|vld[1-4]r (Rn), [Vt1.<T>, Vt2.<T>, ...] */ 5106 c.checkoffset(p, p.As) 5107 r := int(p.From.Reg) 5108 o1 = c.oprrr(p, p.As) 5109 if o.scond == C_XPOST { 5110 o1 |= 1 << 23 5111 if p.From.Index == 0 { 5112 // immediate offset variant 5113 o1 |= 0x1f << 16 5114 } else { 5115 // register offset variant 5116 if isRegShiftOrExt(&p.From) { 5117 c.ctxt.Diag("invalid extended register op: %v\n", p) 5118 } 5119 o1 |= uint32(p.From.Index&0x1f) << 16 5120 } 5121 } 5122 o1 |= uint32(p.To.Offset) 5123 // cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset 5124 // add opcode(bit 12-15) for vld1, mask it off if it's not vld1 5125 o1 = c.maskOpvldvst(p, o1) 5126 o1 |= uint32(r&31) << 5 5127 5128 case 82: /* vmov/vdup Rn, Vd.<T> */ 5129 rf := int(p.From.Reg) 5130 rt := int(p.To.Reg) 5131 o1 = 7<<25 | 3<<10 5132 var imm5, Q uint32 5133 switch (p.To.Reg >> 5) & 15 { 5134 case ARNG_16B: 5135 Q = 1 5136 imm5 = 1 5137 case ARNG_2D: 5138 Q = 1 5139 imm5 = 8 5140 case ARNG_2S: 5141 Q = 0 5142 imm5 = 4 5143 case ARNG_4H: 5144 Q = 0 5145 imm5 = 2 5146 case ARNG_4S: 5147 Q = 1 5148 imm5 = 4 5149 case ARNG_8B: 5150 Q = 0 5151 imm5 = 1 5152 case ARNG_8H: 5153 Q = 1 5154 imm5 = 2 5155 default: 5156 c.ctxt.Diag("invalid arrangement: %v\n", p) 5157 } 5158 o1 |= (Q & 1 << 30) | (imm5 & 0x1f << 16) 5159 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 5160 5161 case 83: /* vmov Vn.<T>, Vd.<T> */ 5162 af := int((p.From.Reg >> 5) & 15) 5163 at := int((p.To.Reg >> 5) & 15) 5164 if af != at { 5165 c.ctxt.Diag("invalid arrangement: %v\n", p) 5166 } 5167 o1 = c.oprrr(p, p.As) 5168 rf := int((p.From.Reg) & 31) 5169 rt := int((p.To.Reg) & 31) 5170 5171 var Q, size uint32 5172 switch af { 5173 case ARNG_8B: 5174 Q = 0 5175 size = 0 5176 case ARNG_16B: 5177 Q = 1 5178 size = 0 5179 case ARNG_4H: 5180 Q = 0 5181 size = 1 5182 case ARNG_8H: 5183 Q = 1 5184 size = 1 5185 case ARNG_2S: 5186 Q = 0 5187 size = 2 5188 case ARNG_4S: 5189 Q = 1 5190 size = 2 5191 default: 5192 c.ctxt.Diag("invalid arrangement: %v\n", p) 5193 } 5194 5195 if (p.As == AVMOV || p.As == AVRBIT || p.As == AVCNT) && (af != ARNG_16B && af != ARNG_8B) { 5196 c.ctxt.Diag("invalid arrangement: %v", p) 5197 } 5198 5199 if p.As == AVREV32 && (af == ARNG_2S || af == ARNG_4S) { 5200 c.ctxt.Diag("invalid arrangement: %v", p) 5201 } 5202 5203 if p.As == AVREV16 && af != ARNG_8B && af != ARNG_16B { 5204 c.ctxt.Diag("invalid arrangement: %v", p) 5205 } 5206 5207 if p.As == AVMOV { 5208 o1 |= uint32(rf&31) << 16 5209 } 5210 5211 if p.As == AVRBIT { 5212 size = 1 5213 } 5214 5215 o1 |= (Q&1)<<30 | (size&3)<<22 | uint32(rf&31)<<5 | uint32(rt&31) 5216 5217 case 84: /* vst[1-4] [Vt1.<T>, Vt2.<T>, ...], (Rn) */ 5218 c.checkoffset(p, p.As) 5219 r := int(p.To.Reg) 5220 o1 = 3 << 26 5221 if o.scond == C_XPOST { 5222 o1 |= 1 << 23 5223 if p.To.Index == 0 { 5224 // immediate offset variant 5225 o1 |= 0x1f << 16 5226 } else { 5227 // register offset variant 5228 if isRegShiftOrExt(&p.To) { 5229 c.ctxt.Diag("invalid extended register: %v\n", p) 5230 } 5231 o1 |= uint32(p.To.Index&31) << 16 5232 } 5233 } 5234 o1 |= uint32(p.From.Offset) 5235 // cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset 5236 // add opcode(bit 12-15) for vst1, mask it off if it's not vst1 5237 o1 = c.maskOpvldvst(p, o1) 5238 o1 |= uint32(r&31) << 5 5239 5240 case 85: /* vaddv/vuaddlv Vn.<T>, Vd*/ 5241 af := int((p.From.Reg >> 5) & 15) 5242 o1 = c.oprrr(p, p.As) 5243 rf := int((p.From.Reg) & 31) 5244 rt := int((p.To.Reg) & 31) 5245 Q := 0 5246 size := 0 5247 switch af { 5248 case ARNG_8B: 5249 Q = 0 5250 size = 0 5251 case ARNG_16B: 5252 Q = 1 5253 size = 0 5254 case ARNG_4H: 5255 Q = 0 5256 size = 1 5257 case ARNG_8H: 5258 Q = 1 5259 size = 1 5260 case ARNG_4S: 5261 Q = 1 5262 size = 2 5263 default: 5264 c.ctxt.Diag("invalid arrangement: %v\n", p) 5265 } 5266 o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31) 5267 5268 case 86: /* vmovi $imm8, Vd.<T>*/ 5269 at := int((p.To.Reg >> 5) & 15) 5270 r := int(p.From.Offset) 5271 if r > 255 || r < 0 { 5272 c.ctxt.Diag("immediate constant out of range: %v\n", p) 5273 } 5274 rt := int((p.To.Reg) & 31) 5275 Q := 0 5276 switch at { 5277 case ARNG_8B: 5278 Q = 0 5279 case ARNG_16B: 5280 Q = 1 5281 default: 5282 c.ctxt.Diag("invalid arrangement: %v\n", p) 5283 } 5284 o1 = 0xf<<24 | 0xe<<12 | 1<<10 5285 o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31) 5286 5287 case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */ 5288 rf1, rf2 := p.From.Reg, int16(p.From.Offset) 5289 if rf1 == REGTMP || rf2 == REGTMP { 5290 c.ctxt.Diag("cannot use REGTMP as source: %v", p) 5291 } 5292 o1 = ADR(1, 0, REGTMP) 5293 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 5294 rel := obj.Addrel(c.cursym) 5295 rel.Off = int32(c.pc) 5296 rel.Siz = 8 5297 rel.Sym = p.To.Sym 5298 rel.Add = p.To.Offset 5299 rel.Type = objabi.R_ADDRARM64 5300 o3 = c.opldpstp(p, o, 0, REGTMP, rf1, rf2, 0) 5301 5302 case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */ 5303 rt1, rt2 := p.To.Reg, int16(p.To.Offset) 5304 o1 = ADR(1, 0, REGTMP) 5305 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 5306 rel := obj.Addrel(c.cursym) 5307 rel.Off = int32(c.pc) 5308 rel.Siz = 8 5309 rel.Sym = p.From.Sym 5310 rel.Add = p.From.Offset 5311 rel.Type = objabi.R_ADDRARM64 5312 o3 = c.opldpstp(p, o, 0, REGTMP, rt1, rt2, 1) 5313 5314 case 89: /* vadd/vsub Vm, Vn, Vd */ 5315 switch p.As { 5316 case AVADD: 5317 o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10 5318 5319 case AVSUB: 5320 o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10 5321 5322 default: 5323 c.ctxt.Diag("bad opcode: %v\n", p) 5324 break 5325 } 5326 5327 rf := int(p.From.Reg) 5328 rt := int(p.To.Reg) 5329 r := int(p.Reg) 5330 if r == obj.REG_NONE { 5331 r = rt 5332 } 5333 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 5334 5335 // This is supposed to be something that stops execution. 5336 // It's not supposed to be reached, ever, but if it is, we'd 5337 // like to be able to tell how we got there. Assemble as 5338 // 0xbea71700 which is guaranteed to raise undefined instruction 5339 // exception. 5340 case 90: 5341 o1 = 0xbea71700 5342 5343 case 91: /* prfm imm(Rn), <prfop | $imm5> */ 5344 imm := uint32(p.From.Offset) 5345 r := p.From.Reg 5346 var v uint32 5347 var ok bool 5348 if p.To.Type == obj.TYPE_CONST { 5349 v = uint32(p.To.Offset) 5350 ok = v <= 31 5351 } else { 5352 v, ok = prfopfield[SpecialOperand(p.To.Offset)] 5353 } 5354 if !ok { 5355 c.ctxt.Diag("illegal prefetch operation:\n%v", p) 5356 } 5357 5358 o1 = c.opirr(p, p.As) 5359 o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31)) 5360 5361 case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */ 5362 rf := int(p.From.Reg) 5363 rt := int(p.To.Reg) 5364 imm4 := 0 5365 imm5 := 0 5366 o1 = 3<<29 | 7<<25 | 1<<10 5367 index1 := int(p.To.Index) 5368 index2 := int(p.From.Index) 5369 if ((p.To.Reg >> 5) & 15) != ((p.From.Reg >> 5) & 15) { 5370 c.ctxt.Diag("operand mismatch: %v", p) 5371 } 5372 switch (p.To.Reg >> 5) & 15 { 5373 case ARNG_B: 5374 c.checkindex(p, index1, 15) 5375 c.checkindex(p, index2, 15) 5376 imm5 |= 1 5377 imm5 |= index1 << 1 5378 imm4 |= index2 5379 case ARNG_H: 5380 c.checkindex(p, index1, 7) 5381 c.checkindex(p, index2, 7) 5382 imm5 |= 2 5383 imm5 |= index1 << 2 5384 imm4 |= index2 << 1 5385 case ARNG_S: 5386 c.checkindex(p, index1, 3) 5387 c.checkindex(p, index2, 3) 5388 imm5 |= 4 5389 imm5 |= index1 << 3 5390 imm4 |= index2 << 2 5391 case ARNG_D: 5392 c.checkindex(p, index1, 1) 5393 c.checkindex(p, index2, 1) 5394 imm5 |= 8 5395 imm5 |= index1 << 4 5396 imm4 |= index2 << 3 5397 default: 5398 c.ctxt.Diag("invalid arrangement: %v", p) 5399 } 5400 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(imm4&0xf) << 11) | (uint32(rf&31) << 5) | uint32(rt&31) 5401 5402 case 93: /* vpmull{2} Vm.<Tb>, Vn.<Tb>, Vd.<Ta> */ 5403 af := uint8((p.From.Reg >> 5) & 15) 5404 at := uint8((p.To.Reg >> 5) & 15) 5405 a := uint8((p.Reg >> 5) & 15) 5406 if af != a { 5407 c.ctxt.Diag("invalid arrangement: %v", p) 5408 } 5409 5410 var Q, size uint32 5411 if p.As == AVPMULL2 { 5412 Q = 1 5413 } 5414 switch pack(Q, at, af) { 5415 case pack(0, ARNG_8H, ARNG_8B), pack(1, ARNG_8H, ARNG_16B): 5416 size = 0 5417 case pack(0, ARNG_1Q, ARNG_1D), pack(1, ARNG_1Q, ARNG_2D): 5418 size = 3 5419 default: 5420 c.ctxt.Diag("operand mismatch: %v\n", p) 5421 } 5422 5423 o1 = c.oprrr(p, p.As) 5424 rf := int((p.From.Reg) & 31) 5425 rt := int((p.To.Reg) & 31) 5426 r := int((p.Reg) & 31) 5427 o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 5428 5429 case 94: /* vext $imm4, Vm.<T>, Vn.<T>, Vd.<T> */ 5430 af := int(((p.GetFrom3().Reg) >> 5) & 15) 5431 at := int((p.To.Reg >> 5) & 15) 5432 a := int((p.Reg >> 5) & 15) 5433 index := int(p.From.Offset) 5434 5435 if af != a || af != at { 5436 c.ctxt.Diag("invalid arrangement: %v", p) 5437 break 5438 } 5439 5440 var Q uint32 5441 var b int 5442 if af == ARNG_8B { 5443 Q = 0 5444 b = 7 5445 } else if af == ARNG_16B { 5446 Q = 1 5447 b = 15 5448 } else { 5449 c.ctxt.Diag("invalid arrangement, should be B8 or B16: %v", p) 5450 break 5451 } 5452 5453 if index < 0 || index > b { 5454 c.ctxt.Diag("illegal offset: %v", p) 5455 } 5456 5457 o1 = c.opirr(p, p.As) 5458 rf := int((p.GetFrom3().Reg) & 31) 5459 rt := int((p.To.Reg) & 31) 5460 r := int((p.Reg) & 31) 5461 5462 o1 |= ((Q & 1) << 30) | (uint32(r&31) << 16) | (uint32(index&15) << 11) | (uint32(rf&31) << 5) | uint32(rt&31) 5463 5464 case 95: /* vushr/vshl/vsri/vsli/vusra $shift, Vn.<T>, Vd.<T> */ 5465 at := int((p.To.Reg >> 5) & 15) 5466 af := int((p.Reg >> 5) & 15) 5467 shift := int(p.From.Offset) 5468 5469 if af != at { 5470 c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p) 5471 } 5472 5473 var Q uint32 5474 var imax, esize int 5475 5476 switch af { 5477 case ARNG_8B, ARNG_4H, ARNG_2S: 5478 Q = 0 5479 case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D: 5480 Q = 1 5481 default: 5482 c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p) 5483 } 5484 5485 switch af { 5486 case ARNG_8B, ARNG_16B: 5487 imax = 15 5488 esize = 8 5489 case ARNG_4H, ARNG_8H: 5490 imax = 31 5491 esize = 16 5492 case ARNG_2S, ARNG_4S: 5493 imax = 63 5494 esize = 32 5495 case ARNG_2D: 5496 imax = 127 5497 esize = 64 5498 } 5499 5500 imm := 0 5501 switch p.As { 5502 case AVUSHR, AVSRI, AVUSRA: 5503 imm = esize*2 - shift 5504 if imm < esize || imm > imax { 5505 c.ctxt.Diag("shift out of range: %v", p) 5506 } 5507 case AVSHL, AVSLI: 5508 imm = esize + shift 5509 if imm > imax { 5510 c.ctxt.Diag("shift out of range: %v", p) 5511 } 5512 default: 5513 c.ctxt.Diag("invalid instruction %v\n", p) 5514 } 5515 5516 o1 = c.opirr(p, p.As) 5517 rt := int((p.To.Reg) & 31) 5518 rf := int((p.Reg) & 31) 5519 5520 o1 |= ((Q & 1) << 30) | (uint32(imm&0x7f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31) 5521 5522 case 96: /* vst1 Vt1.<T>[index], offset(Rn) */ 5523 af := int((p.From.Reg >> 5) & 15) 5524 rt := int((p.From.Reg) & 31) 5525 rf := int((p.To.Reg) & 31) 5526 r := int(p.To.Index & 31) 5527 index := int(p.From.Index) 5528 offset := c.regoff(&p.To) 5529 5530 if o.scond == C_XPOST { 5531 if (p.To.Index != 0) && (offset != 0) { 5532 c.ctxt.Diag("invalid offset: %v", p) 5533 } 5534 if p.To.Index == 0 && offset == 0 { 5535 c.ctxt.Diag("invalid offset: %v", p) 5536 } 5537 } 5538 5539 if offset != 0 { 5540 r = 31 5541 } 5542 5543 var Q, S, size int 5544 var opcode uint32 5545 switch af { 5546 case ARNG_B: 5547 c.checkindex(p, index, 15) 5548 if o.scond == C_XPOST && offset != 0 && offset != 1 { 5549 c.ctxt.Diag("invalid offset: %v", p) 5550 } 5551 Q = index >> 3 5552 S = (index >> 2) & 1 5553 size = index & 3 5554 opcode = 0 5555 case ARNG_H: 5556 c.checkindex(p, index, 7) 5557 if o.scond == C_XPOST && offset != 0 && offset != 2 { 5558 c.ctxt.Diag("invalid offset: %v", p) 5559 } 5560 Q = index >> 2 5561 S = (index >> 1) & 1 5562 size = (index & 1) << 1 5563 opcode = 2 5564 case ARNG_S: 5565 c.checkindex(p, index, 3) 5566 if o.scond == C_XPOST && offset != 0 && offset != 4 { 5567 c.ctxt.Diag("invalid offset: %v", p) 5568 } 5569 Q = index >> 1 5570 S = index & 1 5571 size = 0 5572 opcode = 4 5573 case ARNG_D: 5574 c.checkindex(p, index, 1) 5575 if o.scond == C_XPOST && offset != 0 && offset != 8 { 5576 c.ctxt.Diag("invalid offset: %v", p) 5577 } 5578 Q = index 5579 S = 0 5580 size = 1 5581 opcode = 4 5582 default: 5583 c.ctxt.Diag("invalid arrangement: %v", p) 5584 } 5585 5586 if o.scond == C_XPOST { 5587 o1 |= 27 << 23 5588 } else { 5589 o1 |= 26 << 23 5590 } 5591 5592 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) 5593 5594 case 97: /* vld1 offset(Rn), vt.<T>[index] */ 5595 at := int((p.To.Reg >> 5) & 15) 5596 rt := int((p.To.Reg) & 31) 5597 rf := int((p.From.Reg) & 31) 5598 r := int(p.From.Index & 31) 5599 index := int(p.To.Index) 5600 offset := c.regoff(&p.From) 5601 5602 if o.scond == C_XPOST { 5603 if (p.From.Index != 0) && (offset != 0) { 5604 c.ctxt.Diag("invalid offset: %v", p) 5605 } 5606 if p.From.Index == 0 && offset == 0 { 5607 c.ctxt.Diag("invalid offset: %v", p) 5608 } 5609 } 5610 5611 if offset != 0 { 5612 r = 31 5613 } 5614 5615 Q := 0 5616 S := 0 5617 size := 0 5618 var opcode uint32 5619 switch at { 5620 case ARNG_B: 5621 c.checkindex(p, index, 15) 5622 if o.scond == C_XPOST && offset != 0 && offset != 1 { 5623 c.ctxt.Diag("invalid offset: %v", p) 5624 } 5625 Q = index >> 3 5626 S = (index >> 2) & 1 5627 size = index & 3 5628 opcode = 0 5629 case ARNG_H: 5630 c.checkindex(p, index, 7) 5631 if o.scond == C_XPOST && offset != 0 && offset != 2 { 5632 c.ctxt.Diag("invalid offset: %v", p) 5633 } 5634 Q = index >> 2 5635 S = (index >> 1) & 1 5636 size = (index & 1) << 1 5637 opcode = 2 5638 case ARNG_S: 5639 c.checkindex(p, index, 3) 5640 if o.scond == C_XPOST && offset != 0 && offset != 4 { 5641 c.ctxt.Diag("invalid offset: %v", p) 5642 } 5643 Q = index >> 1 5644 S = index & 1 5645 size = 0 5646 opcode = 4 5647 case ARNG_D: 5648 c.checkindex(p, index, 1) 5649 if o.scond == C_XPOST && offset != 0 && offset != 8 { 5650 c.ctxt.Diag("invalid offset: %v", p) 5651 } 5652 Q = index 5653 S = 0 5654 size = 1 5655 opcode = 4 5656 default: 5657 c.ctxt.Diag("invalid arrangement: %v", p) 5658 } 5659 5660 if o.scond == C_XPOST { 5661 o1 |= 110 << 21 5662 } else { 5663 o1 |= 106 << 21 5664 } 5665 5666 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) 5667 5668 case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */ 5669 if isRegShiftOrExt(&p.From) { 5670 // extended or shifted offset register. 5671 c.checkShiftAmount(p, &p.From) 5672 5673 o1 = c.opldrr(p, p.As, true) 5674 o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Index) /* includes reg, op, etc */ 5675 } else { 5676 // (Rn)(Rm), no extension or shift. 5677 o1 = c.opldrr(p, p.As, false) 5678 o1 |= uint32(p.From.Index&31) << 16 5679 } 5680 o1 |= uint32(p.From.Reg&31) << 5 5681 rt := int(p.To.Reg) 5682 o1 |= uint32(rt & 31) 5683 5684 case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */ 5685 if isRegShiftOrExt(&p.To) { 5686 // extended or shifted offset register. 5687 c.checkShiftAmount(p, &p.To) 5688 5689 o1 = c.opstrr(p, p.As, true) 5690 o1 |= c.encRegShiftOrExt(p, &p.To, p.To.Index) /* includes reg, op, etc */ 5691 } else { 5692 // (Rn)(Rm), no extension or shift. 5693 o1 = c.opstrr(p, p.As, false) 5694 o1 |= uint32(p.To.Index&31) << 16 5695 } 5696 o1 |= uint32(p.To.Reg&31) << 5 5697 rf := int(p.From.Reg) 5698 o1 |= uint32(rf & 31) 5699 5700 case 100: /* VTBL/VTBX Vn.<T>, [Vt1.<T>, Vt2.<T>, ...], Vd.<T> */ 5701 af := int((p.From.Reg >> 5) & 15) 5702 at := int((p.To.Reg >> 5) & 15) 5703 if af != at { 5704 c.ctxt.Diag("invalid arrangement: %v\n", p) 5705 } 5706 var q, len uint32 5707 switch af { 5708 case ARNG_8B: 5709 q = 0 5710 case ARNG_16B: 5711 q = 1 5712 default: 5713 c.ctxt.Diag("invalid arrangement: %v", p) 5714 } 5715 rf := int(p.From.Reg) 5716 rt := int(p.To.Reg) 5717 offset := int(p.GetFrom3().Offset) 5718 opcode := (offset >> 12) & 15 5719 switch opcode { 5720 case 0x7: 5721 len = 0 // one register 5722 case 0xa: 5723 len = 1 // two register 5724 case 0x6: 5725 len = 2 // three registers 5726 case 0x2: 5727 len = 3 // four registers 5728 default: 5729 c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p) 5730 } 5731 var op uint32 5732 switch p.As { 5733 case AVTBL: 5734 op = 0 5735 case AVTBX: 5736 op = 1 5737 } 5738 o1 = q<<30 | 0xe<<24 | len<<13 | op<<12 5739 o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31) 5740 5741 case 102: /* vushll, vushll2, vuxtl, vuxtl2 */ 5742 o1 = c.opirr(p, p.As) 5743 rf := p.Reg 5744 af := uint8((p.Reg >> 5) & 15) 5745 at := uint8((p.To.Reg >> 5) & 15) 5746 shift := int(p.From.Offset) 5747 if p.As == AVUXTL || p.As == AVUXTL2 { 5748 rf = p.From.Reg 5749 af = uint8((p.From.Reg >> 5) & 15) 5750 shift = 0 5751 } 5752 5753 Q := (o1 >> 30) & 1 5754 var immh, width uint8 5755 switch pack(Q, af, at) { 5756 case pack(0, ARNG_8B, ARNG_8H): 5757 immh, width = 1, 8 5758 case pack(1, ARNG_16B, ARNG_8H): 5759 immh, width = 1, 8 5760 case pack(0, ARNG_4H, ARNG_4S): 5761 immh, width = 2, 16 5762 case pack(1, ARNG_8H, ARNG_4S): 5763 immh, width = 2, 16 5764 case pack(0, ARNG_2S, ARNG_2D): 5765 immh, width = 4, 32 5766 case pack(1, ARNG_4S, ARNG_2D): 5767 immh, width = 4, 32 5768 default: 5769 c.ctxt.Diag("operand mismatch: %v\n", p) 5770 } 5771 if !(0 <= shift && shift <= int(width-1)) { 5772 c.ctxt.Diag("shift amount out of range: %v\n", p) 5773 } 5774 o1 |= uint32(immh)<<19 | uint32(shift)<<16 | uint32(rf&31)<<5 | uint32(p.To.Reg&31) 5775 5776 case 103: /* VEOR3/VBCAX Va.B16, Vm.B16, Vn.B16, Vd.B16 */ 5777 ta := (p.From.Reg >> 5) & 15 5778 tm := (p.Reg >> 5) & 15 5779 td := (p.To.Reg >> 5) & 15 5780 tn := ((p.GetFrom3().Reg) >> 5) & 15 5781 5782 if ta != tm || ta != tn || ta != td || ta != ARNG_16B { 5783 c.ctxt.Diag("invalid arrangement: %v", p) 5784 break 5785 } 5786 5787 o1 = c.oprrr(p, p.As) 5788 ra := int(p.From.Reg) 5789 rm := int(p.Reg) 5790 rn := int(p.GetFrom3().Reg) 5791 rd := int(p.To.Reg) 5792 o1 |= uint32(rm&31)<<16 | uint32(ra&31)<<10 | uint32(rn&31)<<5 | uint32(rd)&31 5793 5794 case 104: /* vxar $imm4, Vm.<T>, Vn.<T>, Vd.<T> */ 5795 af := ((p.GetFrom3().Reg) >> 5) & 15 5796 at := (p.To.Reg >> 5) & 15 5797 a := (p.Reg >> 5) & 15 5798 index := int(p.From.Offset) 5799 5800 if af != a || af != at { 5801 c.ctxt.Diag("invalid arrangement: %v", p) 5802 break 5803 } 5804 5805 if af != ARNG_2D { 5806 c.ctxt.Diag("invalid arrangement, should be D2: %v", p) 5807 break 5808 } 5809 5810 if index < 0 || index > 63 { 5811 c.ctxt.Diag("illegal offset: %v", p) 5812 } 5813 5814 o1 = c.opirr(p, p.As) 5815 rf := (p.GetFrom3().Reg) & 31 5816 rt := (p.To.Reg) & 31 5817 r := (p.Reg) & 31 5818 5819 o1 |= (uint32(r&31) << 16) | (uint32(index&63) << 10) | (uint32(rf&31) << 5) | uint32(rt&31) 5820 5821 case 105: /* vuaddw{2} Vm.<Tb>, Vn.<Ta>, Vd.<Ta> */ 5822 af := uint8((p.From.Reg >> 5) & 15) 5823 at := uint8((p.To.Reg >> 5) & 15) 5824 a := uint8((p.Reg >> 5) & 15) 5825 if at != a { 5826 c.ctxt.Diag("invalid arrangement: %v", p) 5827 break 5828 } 5829 5830 var Q, size uint32 5831 if p.As == AVUADDW2 { 5832 Q = 1 5833 } 5834 switch pack(Q, at, af) { 5835 case pack(0, ARNG_8H, ARNG_8B), pack(1, ARNG_8H, ARNG_16B): 5836 size = 0 5837 case pack(0, ARNG_4S, ARNG_4H), pack(1, ARNG_4S, ARNG_8H): 5838 size = 1 5839 case pack(0, ARNG_2D, ARNG_2S), pack(1, ARNG_2D, ARNG_4S): 5840 size = 2 5841 default: 5842 c.ctxt.Diag("operand mismatch: %v\n", p) 5843 } 5844 5845 o1 = c.oprrr(p, p.As) 5846 rf := int((p.From.Reg) & 31) 5847 rt := int((p.To.Reg) & 31) 5848 r := int((p.Reg) & 31) 5849 o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 5850 5851 case 106: // CASPx (Rs, Rs+1), (Rb), (Rt, Rt+1) 5852 rs := p.From.Reg 5853 rt := p.GetTo2().Reg 5854 rb := p.To.Reg 5855 rs1 := int16(p.From.Offset) 5856 rt1 := int16(p.GetTo2().Offset) 5857 5858 enc, ok := atomicCASP[p.As] 5859 if !ok { 5860 c.ctxt.Diag("invalid CASP-like atomic instructions: %v\n", p) 5861 } 5862 // for CASPx-like instructions, Rs<0> != 1 && Rt<0> != 1 5863 switch { 5864 case rs&1 != 0: 5865 c.ctxt.Diag("source register pair must start from even register: %v\n", p) 5866 break 5867 case rt&1 != 0: 5868 c.ctxt.Diag("destination register pair must start from even register: %v\n", p) 5869 break 5870 case rs != rs1-1: 5871 c.ctxt.Diag("source register pair must be contiguous: %v\n", p) 5872 break 5873 case rt != rt1-1: 5874 c.ctxt.Diag("destination register pair must be contiguous: %v\n", p) 5875 break 5876 } 5877 // rt can't be sp. 5878 if rt == REG_RSP { 5879 c.ctxt.Diag("illegal destination register: %v\n", p) 5880 } 5881 o1 |= enc | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31) 5882 5883 case 107: /* tlbi, dc */ 5884 op, ok := sysInstFields[SpecialOperand(p.From.Offset)] 5885 if !ok || (p.As == ATLBI && op.cn != 8) || (p.As == ADC && op.cn != 7) { 5886 c.ctxt.Diag("illegal argument: %v\n", p) 5887 break 5888 } 5889 o1 = c.opirr(p, p.As) 5890 if op.hasOperand2 { 5891 if p.To.Reg == obj.REG_NONE { 5892 c.ctxt.Diag("missing register at operand 2: %v\n", p) 5893 } 5894 o1 |= uint32(p.To.Reg & 0x1F) 5895 } else { 5896 if p.To.Reg != obj.REG_NONE || p.Reg != obj.REG_NONE { 5897 c.ctxt.Diag("extraneous register at operand 2: %v\n", p) 5898 } 5899 o1 |= uint32(0x1F) 5900 } 5901 o1 |= uint32(SYSARG4(int(op.op1), int(op.cn), int(op.cm), int(op.op2))) 5902 } 5903 out[0] = o1 5904 out[1] = o2 5905 out[2] = o3 5906 out[3] = o4 5907 out[4] = o5 5908} 5909 5910func (c *ctxt7) addrRelocType(p *obj.Prog) objabi.RelocType { 5911 switch movesize(p.As) { 5912 case 0: 5913 return objabi.R_ARM64_PCREL_LDST8 5914 case 1: 5915 return objabi.R_ARM64_PCREL_LDST16 5916 case 2: 5917 return objabi.R_ARM64_PCREL_LDST32 5918 case 3: 5919 return objabi.R_ARM64_PCREL_LDST64 5920 default: 5921 c.ctxt.Diag("use R_ADDRARM64 relocation type for: %v\n", p) 5922 } 5923 return -1 5924} 5925 5926/* 5927 * basic Rm op Rn -> Rd (using shifted register with 0) 5928 * also op Rn -> Rt 5929 * also Rm*Rn op Ra -> Rd 5930 * also Vm op Vn -> Vd 5931 */ 5932func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 { 5933 switch a { 5934 case AADC: 5935 return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 5936 5937 case AADCW: 5938 return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 5939 5940 case AADCS: 5941 return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 5942 5943 case AADCSW: 5944 return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 5945 5946 case ANGC, ASBC: 5947 return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 5948 5949 case ANGCS, ASBCS: 5950 return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 5951 5952 case ANGCW, ASBCW: 5953 return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 5954 5955 case ANGCSW, ASBCSW: 5956 return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 5957 5958 case AADD: 5959 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 5960 5961 case AADDW: 5962 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 5963 5964 case ACMN, AADDS: 5965 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 5966 5967 case ACMNW, AADDSW: 5968 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 5969 5970 case ASUB: 5971 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 5972 5973 case ASUBW: 5974 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 5975 5976 case ACMP, ASUBS: 5977 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 5978 5979 case ACMPW, ASUBSW: 5980 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 5981 5982 case AAND: 5983 return S64 | 0<<29 | 0xA<<24 5984 5985 case AANDW: 5986 return S32 | 0<<29 | 0xA<<24 5987 5988 case AMOVD, AORR: 5989 return S64 | 1<<29 | 0xA<<24 5990 5991 // case AMOVW: 5992 case AMOVWU, AORRW: 5993 return S32 | 1<<29 | 0xA<<24 5994 5995 case AEOR: 5996 return S64 | 2<<29 | 0xA<<24 5997 5998 case AEORW: 5999 return S32 | 2<<29 | 0xA<<24 6000 6001 case AANDS, ATST: 6002 return S64 | 3<<29 | 0xA<<24 6003 6004 case AANDSW, ATSTW: 6005 return S32 | 3<<29 | 0xA<<24 6006 6007 case ABIC: 6008 return S64 | 0<<29 | 0xA<<24 | 1<<21 6009 6010 case ABICW: 6011 return S32 | 0<<29 | 0xA<<24 | 1<<21 6012 6013 case ABICS: 6014 return S64 | 3<<29 | 0xA<<24 | 1<<21 6015 6016 case ABICSW: 6017 return S32 | 3<<29 | 0xA<<24 | 1<<21 6018 6019 case AEON: 6020 return S64 | 2<<29 | 0xA<<24 | 1<<21 6021 6022 case AEONW: 6023 return S32 | 2<<29 | 0xA<<24 | 1<<21 6024 6025 case AMVN, AORN: 6026 return S64 | 1<<29 | 0xA<<24 | 1<<21 6027 6028 case AMVNW, AORNW: 6029 return S32 | 1<<29 | 0xA<<24 | 1<<21 6030 6031 case AASR: 6032 return S64 | OPDP2(10) /* also ASRV */ 6033 6034 case AASRW: 6035 return S32 | OPDP2(10) 6036 6037 case ALSL: 6038 return S64 | OPDP2(8) 6039 6040 case ALSLW: 6041 return S32 | OPDP2(8) 6042 6043 case ALSR: 6044 return S64 | OPDP2(9) 6045 6046 case ALSRW: 6047 return S32 | OPDP2(9) 6048 6049 case AROR: 6050 return S64 | OPDP2(11) 6051 6052 case ARORW: 6053 return S32 | OPDP2(11) 6054 6055 case ACCMN: 6056 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */ 6057 6058 case ACCMNW: 6059 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 6060 6061 case ACCMP: 6062 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 6063 6064 case ACCMPW: 6065 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 6066 6067 case ACRC32B: 6068 return S32 | OPDP2(16) 6069 6070 case ACRC32H: 6071 return S32 | OPDP2(17) 6072 6073 case ACRC32W: 6074 return S32 | OPDP2(18) 6075 6076 case ACRC32X: 6077 return S64 | OPDP2(19) 6078 6079 case ACRC32CB: 6080 return S32 | OPDP2(20) 6081 6082 case ACRC32CH: 6083 return S32 | OPDP2(21) 6084 6085 case ACRC32CW: 6086 return S32 | OPDP2(22) 6087 6088 case ACRC32CX: 6089 return S64 | OPDP2(23) 6090 6091 case ACSEL: 6092 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 6093 6094 case ACSELW: 6095 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 6096 6097 case ACSET: 6098 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 6099 6100 case ACSETW: 6101 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 6102 6103 case ACSETM: 6104 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 6105 6106 case ACSETMW: 6107 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 6108 6109 case ACINC, ACSINC: 6110 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 6111 6112 case ACINCW, ACSINCW: 6113 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 6114 6115 case ACINV, ACSINV: 6116 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 6117 6118 case ACINVW, ACSINVW: 6119 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 6120 6121 case ACNEG, ACSNEG: 6122 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 6123 6124 case ACNEGW, ACSNEGW: 6125 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 6126 6127 case AMUL, AMADD: 6128 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 6129 6130 case AMULW, AMADDW: 6131 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 6132 6133 case AMNEG, AMSUB: 6134 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 6135 6136 case AMNEGW, AMSUBW: 6137 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 6138 6139 case AMRS: 6140 return SYSOP(1, 2, 0, 0, 0, 0, 0) 6141 6142 case AMSR: 6143 return SYSOP(0, 2, 0, 0, 0, 0, 0) 6144 6145 case ANEG: 6146 return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 6147 6148 case ANEGW: 6149 return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 6150 6151 case ANEGS: 6152 return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 6153 6154 case ANEGSW: 6155 return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 6156 6157 case AREM, ASDIV: 6158 return S64 | OPDP2(3) 6159 6160 case AREMW, ASDIVW: 6161 return S32 | OPDP2(3) 6162 6163 case ASMULL, ASMADDL: 6164 return OPDP3(1, 0, 1, 0) 6165 6166 case ASMNEGL, ASMSUBL: 6167 return OPDP3(1, 0, 1, 1) 6168 6169 case ASMULH: 6170 return OPDP3(1, 0, 2, 0) 6171 6172 case AUMULL, AUMADDL: 6173 return OPDP3(1, 0, 5, 0) 6174 6175 case AUMNEGL, AUMSUBL: 6176 return OPDP3(1, 0, 5, 1) 6177 6178 case AUMULH: 6179 return OPDP3(1, 0, 6, 0) 6180 6181 case AUREM, AUDIV: 6182 return S64 | OPDP2(2) 6183 6184 case AUREMW, AUDIVW: 6185 return S32 | OPDP2(2) 6186 6187 case AAESE: 6188 return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10 6189 6190 case AAESD: 6191 return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10 6192 6193 case AAESMC: 6194 return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10 6195 6196 case AAESIMC: 6197 return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10 6198 6199 case ASHA1C: 6200 return 0x5E<<24 | 0<<12 6201 6202 case ASHA1P: 6203 return 0x5E<<24 | 1<<12 6204 6205 case ASHA1M: 6206 return 0x5E<<24 | 2<<12 6207 6208 case ASHA1SU0: 6209 return 0x5E<<24 | 3<<12 6210 6211 case ASHA256H: 6212 return 0x5E<<24 | 4<<12 6213 6214 case ASHA256H2: 6215 return 0x5E<<24 | 5<<12 6216 6217 case ASHA256SU1: 6218 return 0x5E<<24 | 6<<12 6219 6220 case ASHA1H: 6221 return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10 6222 6223 case ASHA1SU1: 6224 return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10 6225 6226 case ASHA256SU0: 6227 return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10 6228 6229 case ASHA512H: 6230 return 0xCE<<24 | 3<<21 | 8<<12 6231 6232 case ASHA512H2: 6233 return 0xCE<<24 | 3<<21 | 8<<12 | 4<<8 6234 6235 case ASHA512SU1: 6236 return 0xCE<<24 | 3<<21 | 8<<12 | 8<<8 6237 6238 case ASHA512SU0: 6239 return 0xCE<<24 | 3<<22 | 8<<12 6240 6241 case AFCVTZSD: 6242 return FPCVTI(1, 0, 1, 3, 0) 6243 6244 case AFCVTZSDW: 6245 return FPCVTI(0, 0, 1, 3, 0) 6246 6247 case AFCVTZSS: 6248 return FPCVTI(1, 0, 0, 3, 0) 6249 6250 case AFCVTZSSW: 6251 return FPCVTI(0, 0, 0, 3, 0) 6252 6253 case AFCVTZUD: 6254 return FPCVTI(1, 0, 1, 3, 1) 6255 6256 case AFCVTZUDW: 6257 return FPCVTI(0, 0, 1, 3, 1) 6258 6259 case AFCVTZUS: 6260 return FPCVTI(1, 0, 0, 3, 1) 6261 6262 case AFCVTZUSW: 6263 return FPCVTI(0, 0, 0, 3, 1) 6264 6265 case ASCVTFD: 6266 return FPCVTI(1, 0, 1, 0, 2) 6267 6268 case ASCVTFS: 6269 return FPCVTI(1, 0, 0, 0, 2) 6270 6271 case ASCVTFWD: 6272 return FPCVTI(0, 0, 1, 0, 2) 6273 6274 case ASCVTFWS: 6275 return FPCVTI(0, 0, 0, 0, 2) 6276 6277 case AUCVTFD: 6278 return FPCVTI(1, 0, 1, 0, 3) 6279 6280 case AUCVTFS: 6281 return FPCVTI(1, 0, 0, 0, 3) 6282 6283 case AUCVTFWD: 6284 return FPCVTI(0, 0, 1, 0, 3) 6285 6286 case AUCVTFWS: 6287 return FPCVTI(0, 0, 0, 0, 3) 6288 6289 case AFADDS: 6290 return FPOP2S(0, 0, 0, 2) 6291 6292 case AFADDD: 6293 return FPOP2S(0, 0, 1, 2) 6294 6295 case AFSUBS: 6296 return FPOP2S(0, 0, 0, 3) 6297 6298 case AFSUBD: 6299 return FPOP2S(0, 0, 1, 3) 6300 6301 case AFMADDD: 6302 return FPOP3S(0, 0, 1, 0, 0) 6303 6304 case AFMADDS: 6305 return FPOP3S(0, 0, 0, 0, 0) 6306 6307 case AFMSUBD: 6308 return FPOP3S(0, 0, 1, 0, 1) 6309 6310 case AFMSUBS: 6311 return FPOP3S(0, 0, 0, 0, 1) 6312 6313 case AFNMADDD: 6314 return FPOP3S(0, 0, 1, 1, 0) 6315 6316 case AFNMADDS: 6317 return FPOP3S(0, 0, 0, 1, 0) 6318 6319 case AFNMSUBD: 6320 return FPOP3S(0, 0, 1, 1, 1) 6321 6322 case AFNMSUBS: 6323 return FPOP3S(0, 0, 0, 1, 1) 6324 6325 case AFMULS: 6326 return FPOP2S(0, 0, 0, 0) 6327 6328 case AFMULD: 6329 return FPOP2S(0, 0, 1, 0) 6330 6331 case AFDIVS: 6332 return FPOP2S(0, 0, 0, 1) 6333 6334 case AFDIVD: 6335 return FPOP2S(0, 0, 1, 1) 6336 6337 case AFMAXS: 6338 return FPOP2S(0, 0, 0, 4) 6339 6340 case AFMINS: 6341 return FPOP2S(0, 0, 0, 5) 6342 6343 case AFMAXD: 6344 return FPOP2S(0, 0, 1, 4) 6345 6346 case AFMIND: 6347 return FPOP2S(0, 0, 1, 5) 6348 6349 case AFMAXNMS: 6350 return FPOP2S(0, 0, 0, 6) 6351 6352 case AFMAXNMD: 6353 return FPOP2S(0, 0, 1, 6) 6354 6355 case AFMINNMS: 6356 return FPOP2S(0, 0, 0, 7) 6357 6358 case AFMINNMD: 6359 return FPOP2S(0, 0, 1, 7) 6360 6361 case AFNMULS: 6362 return FPOP2S(0, 0, 0, 8) 6363 6364 case AFNMULD: 6365 return FPOP2S(0, 0, 1, 8) 6366 6367 case AFCMPS: 6368 return FPCMP(0, 0, 0, 0, 0) 6369 6370 case AFCMPD: 6371 return FPCMP(0, 0, 1, 0, 0) 6372 6373 case AFCMPES: 6374 return FPCMP(0, 0, 0, 0, 16) 6375 6376 case AFCMPED: 6377 return FPCMP(0, 0, 1, 0, 16) 6378 6379 case AFCCMPS: 6380 return FPCCMP(0, 0, 0, 0) 6381 6382 case AFCCMPD: 6383 return FPCCMP(0, 0, 1, 0) 6384 6385 case AFCCMPES: 6386 return FPCCMP(0, 0, 0, 1) 6387 6388 case AFCCMPED: 6389 return FPCCMP(0, 0, 1, 1) 6390 6391 case AFCSELS: 6392 return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10 6393 6394 case AFCSELD: 6395 return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10 6396 6397 case AFMOVS: 6398 return FPOP1S(0, 0, 0, 0) 6399 6400 case AFABSS: 6401 return FPOP1S(0, 0, 0, 1) 6402 6403 case AFNEGS: 6404 return FPOP1S(0, 0, 0, 2) 6405 6406 case AFSQRTS: 6407 return FPOP1S(0, 0, 0, 3) 6408 6409 case AFCVTSD: 6410 return FPOP1S(0, 0, 0, 5) 6411 6412 case AFCVTSH: 6413 return FPOP1S(0, 0, 0, 7) 6414 6415 case AFRINTNS: 6416 return FPOP1S(0, 0, 0, 8) 6417 6418 case AFRINTPS: 6419 return FPOP1S(0, 0, 0, 9) 6420 6421 case AFRINTMS: 6422 return FPOP1S(0, 0, 0, 10) 6423 6424 case AFRINTZS: 6425 return FPOP1S(0, 0, 0, 11) 6426 6427 case AFRINTAS: 6428 return FPOP1S(0, 0, 0, 12) 6429 6430 case AFRINTXS: 6431 return FPOP1S(0, 0, 0, 14) 6432 6433 case AFRINTIS: 6434 return FPOP1S(0, 0, 0, 15) 6435 6436 case AFMOVD: 6437 return FPOP1S(0, 0, 1, 0) 6438 6439 case AFABSD: 6440 return FPOP1S(0, 0, 1, 1) 6441 6442 case AFNEGD: 6443 return FPOP1S(0, 0, 1, 2) 6444 6445 case AFSQRTD: 6446 return FPOP1S(0, 0, 1, 3) 6447 6448 case AFCVTDS: 6449 return FPOP1S(0, 0, 1, 4) 6450 6451 case AFCVTDH: 6452 return FPOP1S(0, 0, 1, 7) 6453 6454 case AFRINTND: 6455 return FPOP1S(0, 0, 1, 8) 6456 6457 case AFRINTPD: 6458 return FPOP1S(0, 0, 1, 9) 6459 6460 case AFRINTMD: 6461 return FPOP1S(0, 0, 1, 10) 6462 6463 case AFRINTZD: 6464 return FPOP1S(0, 0, 1, 11) 6465 6466 case AFRINTAD: 6467 return FPOP1S(0, 0, 1, 12) 6468 6469 case AFRINTXD: 6470 return FPOP1S(0, 0, 1, 14) 6471 6472 case AFRINTID: 6473 return FPOP1S(0, 0, 1, 15) 6474 6475 case AFCVTHS: 6476 return FPOP1S(0, 0, 3, 4) 6477 6478 case AFCVTHD: 6479 return FPOP1S(0, 0, 3, 5) 6480 6481 case AVADD: 6482 return 7<<25 | 1<<21 | 1<<15 | 1<<10 6483 6484 case AVSUB: 6485 return 0x17<<25 | 1<<21 | 1<<15 | 1<<10 6486 6487 case AVADDP: 6488 return 7<<25 | 1<<21 | 1<<15 | 15<<10 6489 6490 case AVAND: 6491 return 7<<25 | 1<<21 | 7<<10 6492 6493 case AVBCAX: 6494 return 0xCE<<24 | 1<<21 6495 6496 case AVCMEQ: 6497 return 1<<29 | 0x71<<21 | 0x23<<10 6498 6499 case AVCNT: 6500 return 0xE<<24 | 0x10<<17 | 5<<12 | 2<<10 6501 6502 case AVZIP1: 6503 return 0xE<<24 | 3<<12 | 2<<10 6504 6505 case AVZIP2: 6506 return 0xE<<24 | 1<<14 | 3<<12 | 2<<10 6507 6508 case AVEOR: 6509 return 1<<29 | 0x71<<21 | 7<<10 6510 6511 case AVEOR3: 6512 return 0xCE << 24 6513 6514 case AVORR: 6515 return 7<<25 | 5<<21 | 7<<10 6516 6517 case AVREV16: 6518 return 3<<26 | 2<<24 | 1<<21 | 3<<11 6519 6520 case AVRAX1: 6521 return 0xCE<<24 | 3<<21 | 1<<15 | 3<<10 6522 6523 case AVREV32: 6524 return 11<<26 | 2<<24 | 1<<21 | 1<<11 6525 6526 case AVREV64: 6527 return 3<<26 | 2<<24 | 1<<21 | 1<<11 6528 6529 case AVMOV: 6530 return 7<<25 | 5<<21 | 7<<10 6531 6532 case AVADDV: 6533 return 7<<25 | 3<<20 | 3<<15 | 7<<11 6534 6535 case AVUADDLV: 6536 return 1<<29 | 7<<25 | 3<<20 | 7<<11 6537 6538 case AVFMLA: 6539 return 7<<25 | 0<<23 | 1<<21 | 3<<14 | 3<<10 6540 6541 case AVFMLS: 6542 return 7<<25 | 1<<23 | 1<<21 | 3<<14 | 3<<10 6543 6544 case AVPMULL, AVPMULL2: 6545 return 0xE<<24 | 1<<21 | 0x38<<10 6546 6547 case AVRBIT: 6548 return 0x2E<<24 | 1<<22 | 0x10<<17 | 5<<12 | 2<<10 6549 6550 case AVLD1, AVLD2, AVLD3, AVLD4: 6551 return 3<<26 | 1<<22 6552 6553 case AVLD1R, AVLD3R: 6554 return 0xD<<24 | 1<<22 6555 6556 case AVLD2R, AVLD4R: 6557 return 0xD<<24 | 3<<21 6558 6559 case AVBIF: 6560 return 1<<29 | 7<<25 | 7<<21 | 7<<10 6561 6562 case AVBIT: 6563 return 1<<29 | 0x75<<21 | 7<<10 6564 6565 case AVBSL: 6566 return 1<<29 | 0x73<<21 | 7<<10 6567 6568 case AVCMTST: 6569 return 0xE<<24 | 1<<21 | 0x23<<10 6570 6571 case AVUMAX: 6572 return 1<<29 | 7<<25 | 1<<21 | 0x19<<10 6573 6574 case AVUMIN: 6575 return 1<<29 | 7<<25 | 1<<21 | 0x1b<<10 6576 6577 case AVUZP1: 6578 return 7<<25 | 3<<11 6579 6580 case AVUZP2: 6581 return 7<<25 | 1<<14 | 3<<11 6582 6583 case AVUADDW, AVUADDW2: 6584 return 0x17<<25 | 1<<21 | 1<<12 6585 6586 case AVTRN1: 6587 return 7<<25 | 5<<11 6588 6589 case AVTRN2: 6590 return 7<<25 | 1<<14 | 5<<11 6591 } 6592 6593 c.ctxt.Diag("%v: bad rrr %d %v", p, a, a) 6594 return 0 6595} 6596 6597/* 6598 * imm -> Rd 6599 * imm op Rn -> Rd 6600 */ 6601func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 { 6602 switch a { 6603 /* op $addcon, Rn, Rd */ 6604 case AMOVD, AADD: 6605 return S64 | 0<<30 | 0<<29 | 0x11<<24 6606 6607 case ACMN, AADDS: 6608 return S64 | 0<<30 | 1<<29 | 0x11<<24 6609 6610 case AMOVW, AADDW: 6611 return S32 | 0<<30 | 0<<29 | 0x11<<24 6612 6613 case ACMNW, AADDSW: 6614 return S32 | 0<<30 | 1<<29 | 0x11<<24 6615 6616 case ASUB: 6617 return S64 | 1<<30 | 0<<29 | 0x11<<24 6618 6619 case ACMP, ASUBS: 6620 return S64 | 1<<30 | 1<<29 | 0x11<<24 6621 6622 case ASUBW: 6623 return S32 | 1<<30 | 0<<29 | 0x11<<24 6624 6625 case ACMPW, ASUBSW: 6626 return S32 | 1<<30 | 1<<29 | 0x11<<24 6627 6628 /* op $imm(SB), Rd; op label, Rd */ 6629 case AADR: 6630 return 0<<31 | 0x10<<24 6631 6632 case AADRP: 6633 return 1<<31 | 0x10<<24 6634 6635 /* op $bimm, Rn, Rd */ 6636 case AAND, ABIC: 6637 return S64 | 0<<29 | 0x24<<23 6638 6639 case AANDW, ABICW: 6640 return S32 | 0<<29 | 0x24<<23 | 0<<22 6641 6642 case AORR, AORN: 6643 return S64 | 1<<29 | 0x24<<23 6644 6645 case AORRW, AORNW: 6646 return S32 | 1<<29 | 0x24<<23 | 0<<22 6647 6648 case AEOR, AEON: 6649 return S64 | 2<<29 | 0x24<<23 6650 6651 case AEORW, AEONW: 6652 return S32 | 2<<29 | 0x24<<23 | 0<<22 6653 6654 case AANDS, ABICS, ATST: 6655 return S64 | 3<<29 | 0x24<<23 6656 6657 case AANDSW, ABICSW, ATSTW: 6658 return S32 | 3<<29 | 0x24<<23 | 0<<22 6659 6660 case AASR: 6661 return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */ 6662 6663 case AASRW: 6664 return S32 | 0<<29 | 0x26<<23 | 0<<22 6665 6666 /* op $width, $lsb, Rn, Rd */ 6667 case ABFI: 6668 return S64 | 2<<29 | 0x26<<23 | 1<<22 6669 /* alias of BFM */ 6670 6671 case ABFIW: 6672 return S32 | 2<<29 | 0x26<<23 | 0<<22 6673 6674 /* op $imms, $immr, Rn, Rd */ 6675 case ABFM: 6676 return S64 | 1<<29 | 0x26<<23 | 1<<22 6677 6678 case ABFMW: 6679 return S32 | 1<<29 | 0x26<<23 | 0<<22 6680 6681 case ASBFM: 6682 return S64 | 0<<29 | 0x26<<23 | 1<<22 6683 6684 case ASBFMW: 6685 return S32 | 0<<29 | 0x26<<23 | 0<<22 6686 6687 case AUBFM: 6688 return S64 | 2<<29 | 0x26<<23 | 1<<22 6689 6690 case AUBFMW: 6691 return S32 | 2<<29 | 0x26<<23 | 0<<22 6692 6693 case ABFXIL: 6694 return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */ 6695 6696 case ABFXILW: 6697 return S32 | 1<<29 | 0x26<<23 | 0<<22 6698 6699 case AEXTR: 6700 return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21 6701 6702 case AEXTRW: 6703 return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21 6704 6705 case ACBNZ: 6706 return S64 | 0x1A<<25 | 1<<24 6707 6708 case ACBNZW: 6709 return S32 | 0x1A<<25 | 1<<24 6710 6711 case ACBZ: 6712 return S64 | 0x1A<<25 | 0<<24 6713 6714 case ACBZW: 6715 return S32 | 0x1A<<25 | 0<<24 6716 6717 case ACCMN: 6718 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 6719 6720 case ACCMNW: 6721 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 6722 6723 case ACCMP: 6724 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 6725 6726 case ACCMPW: 6727 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 6728 6729 case AMOVK: 6730 return S64 | 3<<29 | 0x25<<23 6731 6732 case AMOVKW: 6733 return S32 | 3<<29 | 0x25<<23 6734 6735 case AMOVN: 6736 return S64 | 0<<29 | 0x25<<23 6737 6738 case AMOVNW: 6739 return S32 | 0<<29 | 0x25<<23 6740 6741 case AMOVZ: 6742 return S64 | 2<<29 | 0x25<<23 6743 6744 case AMOVZW: 6745 return S32 | 2<<29 | 0x25<<23 6746 6747 case AMSR: 6748 return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */ 6749 6750 case AAT, 6751 ADC, 6752 AIC, 6753 ATLBI, 6754 ASYS: 6755 return SYSOP(0, 1, 0, 0, 0, 0, 0) 6756 6757 case ASYSL: 6758 return SYSOP(1, 1, 0, 0, 0, 0, 0) 6759 6760 case ATBZ: 6761 return 0x36 << 24 6762 6763 case ATBNZ: 6764 return 0x37 << 24 6765 6766 case ADSB: 6767 return SYSOP(0, 0, 3, 3, 0, 4, 0x1F) 6768 6769 case ADMB: 6770 return SYSOP(0, 0, 3, 3, 0, 5, 0x1F) 6771 6772 case AISB: 6773 return SYSOP(0, 0, 3, 3, 0, 6, 0x1F) 6774 6775 case AHINT: 6776 return SYSOP(0, 0, 3, 2, 0, 0, 0x1F) 6777 6778 case AVEXT: 6779 return 0x2E<<24 | 0<<23 | 0<<21 | 0<<15 6780 6781 case AVUSHR: 6782 return 0x5E<<23 | 1<<10 6783 6784 case AVSHL: 6785 return 0x1E<<23 | 21<<10 6786 6787 case AVSRI: 6788 return 0x5E<<23 | 17<<10 6789 6790 case AVSLI: 6791 return 0x5E<<23 | 21<<10 6792 6793 case AVUSHLL, AVUXTL: 6794 return 1<<29 | 15<<24 | 0x29<<10 6795 6796 case AVUSHLL2, AVUXTL2: 6797 return 3<<29 | 15<<24 | 0x29<<10 6798 6799 case AVXAR: 6800 return 0xCE<<24 | 1<<23 6801 6802 case AVUSRA: 6803 return 1<<29 | 15<<24 | 5<<10 6804 6805 case APRFM: 6806 return 0xf9<<24 | 2<<22 6807 } 6808 6809 c.ctxt.Diag("%v: bad irr %v", p, a) 6810 return 0 6811} 6812 6813func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 { 6814 switch a { 6815 case ACLS: 6816 return S64 | OPBIT(5) 6817 6818 case ACLSW: 6819 return S32 | OPBIT(5) 6820 6821 case ACLZ: 6822 return S64 | OPBIT(4) 6823 6824 case ACLZW: 6825 return S32 | OPBIT(4) 6826 6827 case ARBIT: 6828 return S64 | OPBIT(0) 6829 6830 case ARBITW: 6831 return S32 | OPBIT(0) 6832 6833 case AREV: 6834 return S64 | OPBIT(3) 6835 6836 case AREVW: 6837 return S32 | OPBIT(2) 6838 6839 case AREV16: 6840 return S64 | OPBIT(1) 6841 6842 case AREV16W: 6843 return S32 | OPBIT(1) 6844 6845 case AREV32: 6846 return S64 | OPBIT(2) 6847 6848 default: 6849 c.ctxt.Diag("bad bit op\n%v", p) 6850 return 0 6851 } 6852} 6853 6854/* 6855 * add/subtract sign or zero-extended register 6856 */ 6857func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, rd, rn, rm int16, extend bool) uint32 { 6858 extension := uint32(0) 6859 if !extend { 6860 if isADDop(a) { 6861 extension = LSL0_64 6862 } 6863 if isADDWop(a) { 6864 extension = LSL0_32 6865 } 6866 } 6867 6868 var op uint32 6869 6870 switch a { 6871 case AADD: 6872 op = S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 6873 6874 case AADDW: 6875 op = S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 6876 6877 case ACMN, AADDS: 6878 op = S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 6879 6880 case ACMNW, AADDSW: 6881 op = S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 6882 6883 case ASUB: 6884 op = S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 6885 6886 case ASUBW: 6887 op = S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 6888 6889 case ACMP, ASUBS: 6890 op = S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 6891 6892 case ACMPW, ASUBSW: 6893 op = S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension 6894 6895 default: 6896 c.ctxt.Diag("bad opxrrr %v\n%v", a, p) 6897 return 0 6898 } 6899 6900 op |= uint32(rm&0x1f)<<16 | uint32(rn&0x1f)<<5 | uint32(rd&0x1f) 6901 6902 return op 6903} 6904 6905func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 { 6906 switch a { 6907 case ASVC: 6908 return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */ 6909 6910 case AHVC: 6911 return 0xD4<<24 | 0<<21 | 2 6912 6913 case ASMC: 6914 return 0xD4<<24 | 0<<21 | 3 6915 6916 case ABRK: 6917 return 0xD4<<24 | 1<<21 | 0 6918 6919 case AHLT: 6920 return 0xD4<<24 | 2<<21 | 0 6921 6922 case ADCPS1: 6923 return 0xD4<<24 | 5<<21 | 1 6924 6925 case ADCPS2: 6926 return 0xD4<<24 | 5<<21 | 2 6927 6928 case ADCPS3: 6929 return 0xD4<<24 | 5<<21 | 3 6930 6931 case ACLREX: 6932 return SYSOP(0, 0, 3, 3, 0, 2, 0x1F) 6933 } 6934 6935 c.ctxt.Diag("%v: bad imm %v", p, a) 6936 return 0 6937} 6938 6939func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 { 6940 v := int64(0) 6941 t := int64(0) 6942 var q *obj.Prog 6943 if p.To.Type == obj.TYPE_BRANCH { 6944 q = p.To.Target() 6945 } else if p.From.Type == obj.TYPE_BRANCH { // adr, adrp 6946 q = p.From.Target() 6947 } 6948 if q == nil { 6949 // TODO: don't use brdist for this case, as it isn't a branch. 6950 // (Calls from omovlit, and maybe adr/adrp opcodes as well.) 6951 q = p.Pool 6952 } 6953 if q != nil { 6954 v = (q.Pc >> uint(preshift)) - (c.pc >> uint(preshift)) 6955 if (v & ((1 << uint(shift)) - 1)) != 0 { 6956 c.ctxt.Diag("misaligned label\n%v", p) 6957 } 6958 v >>= uint(shift) 6959 t = int64(1) << uint(flen-1) 6960 if v < -t || v >= t { 6961 c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, q) 6962 panic("branch too far") 6963 } 6964 } 6965 6966 return v & ((t << 1) - 1) 6967} 6968 6969/* 6970 * pc-relative branches 6971 */ 6972func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 { 6973 switch a { 6974 case ABEQ: 6975 return OPBcc(0x0) 6976 6977 case ABNE: 6978 return OPBcc(0x1) 6979 6980 case ABCS: 6981 return OPBcc(0x2) 6982 6983 case ABHS: 6984 return OPBcc(0x2) 6985 6986 case ABCC: 6987 return OPBcc(0x3) 6988 6989 case ABLO: 6990 return OPBcc(0x3) 6991 6992 case ABMI: 6993 return OPBcc(0x4) 6994 6995 case ABPL: 6996 return OPBcc(0x5) 6997 6998 case ABVS: 6999 return OPBcc(0x6) 7000 7001 case ABVC: 7002 return OPBcc(0x7) 7003 7004 case ABHI: 7005 return OPBcc(0x8) 7006 7007 case ABLS: 7008 return OPBcc(0x9) 7009 7010 case ABGE: 7011 return OPBcc(0xa) 7012 7013 case ABLT: 7014 return OPBcc(0xb) 7015 7016 case ABGT: 7017 return OPBcc(0xc) 7018 7019 case ABLE: 7020 return OPBcc(0xd) /* imm19<<5 | cond */ 7021 7022 case AB: 7023 return 0<<31 | 5<<26 /* imm26 */ 7024 7025 case obj.ADUFFZERO, obj.ADUFFCOPY, ABL: 7026 return 1<<31 | 5<<26 7027 } 7028 7029 c.ctxt.Diag("%v: bad bra %v", p, a) 7030 return 0 7031} 7032 7033func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 { 7034 switch a { 7035 case ABL: 7036 return OPBLR(1) /* BLR */ 7037 7038 case AB: 7039 return OPBLR(0) /* BR */ 7040 7041 case obj.ARET: 7042 return OPBLR(2) /* RET */ 7043 } 7044 7045 c.ctxt.Diag("%v: bad brr %v", p, a) 7046 return 0 7047} 7048 7049func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 { 7050 switch a { 7051 case ADRPS: 7052 return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5 7053 7054 case AERET: 7055 return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5 7056 7057 case ANOOP: 7058 return SYSHINT(0) 7059 7060 case AYIELD: 7061 return SYSHINT(1) 7062 7063 case AWFE: 7064 return SYSHINT(2) 7065 7066 case AWFI: 7067 return SYSHINT(3) 7068 7069 case ASEV: 7070 return SYSHINT(4) 7071 7072 case ASEVL: 7073 return SYSHINT(5) 7074 } 7075 7076 c.ctxt.Diag("%v: bad op0 %v", p, a) 7077 return 0 7078} 7079 7080/* 7081 * register offset 7082 */ 7083func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 { 7084 switch a { 7085 case ALDAR: 7086 return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10 7087 7088 case ALDARW: 7089 return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10 7090 7091 case ALDARB: 7092 return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10 7093 7094 case ALDARH: 7095 return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10 7096 7097 case ALDAXP: 7098 return LDSTX(3, 0, 1, 1, 1) 7099 7100 case ALDAXPW: 7101 return LDSTX(2, 0, 1, 1, 1) 7102 7103 case ALDAXR: 7104 return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10 7105 7106 case ALDAXRW: 7107 return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10 7108 7109 case ALDAXRB: 7110 return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10 7111 7112 case ALDAXRH: 7113 return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10 7114 7115 case ALDXR: 7116 return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10 7117 7118 case ALDXRB: 7119 return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10 7120 7121 case ALDXRH: 7122 return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10 7123 7124 case ALDXRW: 7125 return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10 7126 7127 case ALDXP: 7128 return LDSTX(3, 0, 1, 1, 0) 7129 7130 case ALDXPW: 7131 return LDSTX(2, 0, 1, 1, 0) 7132 } 7133 7134 c.ctxt.Diag("bad opload %v\n%v", a, p) 7135 return 0 7136} 7137 7138func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 { 7139 switch a { 7140 case ASTLR: 7141 return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10 7142 7143 case ASTLRB: 7144 return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10 7145 7146 case ASTLRH: 7147 return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10 7148 7149 case ASTLRW: 7150 return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10 7151 7152 case ASTLXP: 7153 return LDSTX(3, 0, 0, 1, 1) 7154 7155 case ASTLXPW: 7156 return LDSTX(2, 0, 0, 1, 1) 7157 7158 case ASTLXR: 7159 return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10 7160 7161 case ASTLXRB: 7162 return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10 7163 7164 case ASTLXRH: 7165 return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10 7166 7167 case ASTLXRW: 7168 return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10 7169 7170 case ASTXR: 7171 return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10 7172 7173 case ASTXRB: 7174 return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10 7175 7176 case ASTXRH: 7177 return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10 7178 7179 case ASTXP: 7180 return LDSTX(3, 0, 0, 1, 0) 7181 7182 case ASTXPW: 7183 return LDSTX(2, 0, 0, 1, 0) 7184 7185 case ASTXRW: 7186 return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10 7187 } 7188 7189 c.ctxt.Diag("bad opstore %v\n%v", a, p) 7190 return 0 7191} 7192 7193/* 7194 * load/store register (scaled 12-bit unsigned immediate) C3.3.13 7195 * these produce 64-bit values (when there's an option) 7196 */ 7197func (c *ctxt7) olsr12u(p *obj.Prog, o uint32, v int32, rn, rt int16) uint32 { 7198 if v < 0 || v >= (1<<12) { 7199 c.ctxt.Diag("offset out of range: %d\n%v", v, p) 7200 } 7201 o |= uint32(v&0xFFF) << 10 7202 o |= uint32(rn&31) << 5 7203 o |= uint32(rt & 31) 7204 o |= 1 << 24 7205 return o 7206} 7207 7208/* 7209 * load/store register (unscaled 9-bit signed immediate) C3.3.12 7210 */ 7211func (c *ctxt7) olsr9s(p *obj.Prog, o uint32, v int32, rn, rt int16) uint32 { 7212 if v < -256 || v > 255 { 7213 c.ctxt.Diag("offset out of range: %d\n%v", v, p) 7214 } 7215 o |= uint32((v & 0x1FF) << 12) 7216 o |= uint32(rn&31) << 5 7217 o |= uint32(rt & 31) 7218 return o 7219} 7220 7221// store(immediate) 7222// scaled 12-bit unsigned immediate offset. 7223// unscaled 9-bit signed immediate offset. 7224// pre/post-indexed store. 7225// and the 12-bit and 9-bit are distinguished in olsr12u and oslr9s. 7226func (c *ctxt7) opstr(p *obj.Prog, a obj.As) uint32 { 7227 enc := c.opldr(p, a) 7228 switch p.As { 7229 case AFMOVQ: 7230 enc = enc &^ (1 << 22) 7231 default: 7232 enc = LD2STR(enc) 7233 } 7234 return enc 7235} 7236 7237// load(immediate) 7238// scaled 12-bit unsigned immediate offset. 7239// unscaled 9-bit signed immediate offset. 7240// pre/post-indexed load. 7241// and the 12-bit and 9-bit are distinguished in olsr12u and oslr9s. 7242func (c *ctxt7) opldr(p *obj.Prog, a obj.As) uint32 { 7243 switch a { 7244 case AMOVD: 7245 return LDSTR(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */ 7246 7247 case AMOVW: 7248 return LDSTR(2, 0, 2) 7249 7250 case AMOVWU: 7251 return LDSTR(2, 0, 1) 7252 7253 case AMOVH: 7254 return LDSTR(1, 0, 2) 7255 7256 case AMOVHU: 7257 return LDSTR(1, 0, 1) 7258 7259 case AMOVB: 7260 return LDSTR(0, 0, 2) 7261 7262 case AMOVBU: 7263 return LDSTR(0, 0, 1) 7264 7265 case AFMOVS, AVMOVS: 7266 return LDSTR(2, 1, 1) 7267 7268 case AFMOVD, AVMOVD: 7269 return LDSTR(3, 1, 1) 7270 7271 case AFMOVQ, AVMOVQ: 7272 return LDSTR(0, 1, 3) 7273 } 7274 7275 c.ctxt.Diag("bad opldr %v\n%v", a, p) 7276 return 0 7277} 7278 7279// olsxrr attaches register operands to a load/store opcode supplied in o. 7280// The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2). 7281func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 { 7282 o |= int32(r1&31) << 5 7283 o |= int32(r2&31) << 16 7284 o |= int32(r & 31) 7285 return uint32(o) 7286} 7287 7288// opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode 7289// for load instruction with register offset. 7290// The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm). 7291func (c *ctxt7) opldrr(p *obj.Prog, a obj.As, extension bool) uint32 { 7292 OptionS := uint32(0x1a) 7293 if extension { 7294 OptionS = uint32(0) // option value and S value have been encoded into p.From.Offset. 7295 } 7296 switch a { 7297 case AMOVD: 7298 return OptionS<<10 | 0x3<<21 | 0x1f<<27 7299 case AMOVW: 7300 return OptionS<<10 | 0x5<<21 | 0x17<<27 7301 case AMOVWU: 7302 return OptionS<<10 | 0x3<<21 | 0x17<<27 7303 case AMOVH: 7304 return OptionS<<10 | 0x5<<21 | 0x0f<<27 7305 case AMOVHU: 7306 return OptionS<<10 | 0x3<<21 | 0x0f<<27 7307 case AMOVB: 7308 return OptionS<<10 | 0x5<<21 | 0x07<<27 7309 case AMOVBU: 7310 return OptionS<<10 | 0x3<<21 | 0x07<<27 7311 case AFMOVS: 7312 return OptionS<<10 | 0x3<<21 | 0x17<<27 | 1<<26 7313 case AFMOVD: 7314 return OptionS<<10 | 0x3<<21 | 0x1f<<27 | 1<<26 7315 } 7316 c.ctxt.Diag("bad opldrr %v\n%v", a, p) 7317 return 0 7318} 7319 7320// opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode 7321// for store instruction with register offset. 7322// The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm). 7323func (c *ctxt7) opstrr(p *obj.Prog, a obj.As, extension bool) uint32 { 7324 OptionS := uint32(0x1a) 7325 if extension { 7326 OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset. 7327 } 7328 switch a { 7329 case AMOVD: 7330 return OptionS<<10 | 0x1<<21 | 0x1f<<27 7331 case AMOVW, AMOVWU: 7332 return OptionS<<10 | 0x1<<21 | 0x17<<27 7333 case AMOVH, AMOVHU: 7334 return OptionS<<10 | 0x1<<21 | 0x0f<<27 7335 case AMOVB, AMOVBU: 7336 return OptionS<<10 | 0x1<<21 | 0x07<<27 7337 case AFMOVS: 7338 return OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26 7339 case AFMOVD: 7340 return OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26 7341 } 7342 c.ctxt.Diag("bad opstrr %v\n%v", a, p) 7343 return 0 7344} 7345 7346func (c *ctxt7) oaddi(p *obj.Prog, a obj.As, v int32, rd, rn int16) uint32 { 7347 op := c.opirr(p, a) 7348 7349 if (v & 0xFFF000) != 0 { 7350 if v&0xFFF != 0 { 7351 c.ctxt.Diag("%v misuses oaddi", p) 7352 } 7353 v >>= 12 7354 op |= 1 << 22 7355 } 7356 7357 op |= (uint32(v&0xFFF) << 10) | (uint32(rn&31) << 5) | uint32(rd&31) 7358 7359 return op 7360} 7361 7362func (c *ctxt7) oaddi12(p *obj.Prog, v int32, rd, rn int16) uint32 { 7363 if v < -4095 || v > 4095 { 7364 c.ctxt.Diag("%v is not a 12 bit immediate: %v", v, p) 7365 return 0 7366 } 7367 a := AADD 7368 if v < 0 { 7369 a = ASUB 7370 v = -v 7371 } 7372 return c.oaddi(p, a, v, rd, rn) 7373} 7374 7375/* 7376 * load a literal value into dr 7377 */ 7378func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 { 7379 var o1 int32 7380 if p.Pool == nil { /* not in literal pool */ 7381 c.aclass(a) 7382 c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset)) 7383 7384 /* TODO: could be clever, and use general constant builder */ 7385 o1 = int32(c.opirr(p, AADD)) 7386 7387 v := int32(c.instoffset) 7388 if v != 0 && (v&0xFFF) == 0 { 7389 v >>= 12 7390 o1 |= 1 << 22 /* shift, by 12 */ 7391 } 7392 7393 o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31) 7394 } else { 7395 fp, w := 0, 0 7396 switch as { 7397 case AFMOVS, AVMOVS: 7398 fp = 1 7399 w = 0 /* 32-bit SIMD/FP */ 7400 7401 case AFMOVD, AVMOVD: 7402 fp = 1 7403 w = 1 /* 64-bit SIMD/FP */ 7404 7405 case AVMOVQ: 7406 fp = 1 7407 w = 2 /* 128-bit SIMD/FP */ 7408 7409 case AMOVD: 7410 if p.Pool.As == ADWORD { 7411 w = 1 /* 64-bit */ 7412 } else if p.Pool.To.Offset < 0 { 7413 w = 2 /* 32-bit, sign-extended to 64-bit */ 7414 } else if p.Pool.To.Offset >= 0 { 7415 w = 0 /* 32-bit, zero-extended to 64-bit */ 7416 } else { 7417 c.ctxt.Diag("invalid operand %v in %v", a, p) 7418 } 7419 7420 case AMOVBU, AMOVHU, AMOVWU: 7421 w = 0 /* 32-bit, zero-extended to 64-bit */ 7422 7423 case AMOVB, AMOVH, AMOVW: 7424 w = 2 /* 32-bit, sign-extended to 64-bit */ 7425 7426 default: 7427 c.ctxt.Diag("invalid operation %v in %v", as, p) 7428 } 7429 7430 v := int32(c.brdist(p, 0, 19, 2)) 7431 o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27) 7432 o1 |= (v & 0x7FFFF) << 5 7433 o1 |= int32(dr & 31) 7434 } 7435 7436 return uint32(o1) 7437} 7438 7439// load a constant (MOVCON or BITCON) in a into rt 7440func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) { 7441 if cls := int(a.Class); (cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0) && rt != REGZERO { 7442 // or $bitcon, REGZERO, rt. rt can't be ZR. 7443 mode := 64 7444 var as1 obj.As 7445 switch as { 7446 case AMOVW: 7447 as1 = AORRW 7448 mode = 32 7449 case AMOVD: 7450 as1 = AORR 7451 } 7452 o1 = c.opirr(p, as1) 7453 o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31) 7454 return o1 7455 } 7456 7457 if as == AMOVW { 7458 d := uint32(a.Offset) 7459 s := movcon(int64(d)) 7460 if s < 0 || 16*s >= 32 { 7461 d = ^d 7462 s = movcon(int64(d)) 7463 if s < 0 || 16*s >= 32 { 7464 c.ctxt.Diag("impossible 32-bit move wide: %#x\n%v", uint32(a.Offset), p) 7465 } 7466 o1 = c.opirr(p, AMOVNW) 7467 } else { 7468 o1 = c.opirr(p, AMOVZW) 7469 } 7470 o1 |= MOVCONST(int64(d), s, rt) 7471 } 7472 if as == AMOVD { 7473 d := a.Offset 7474 s := movcon(d) 7475 if s < 0 || 16*s >= 64 { 7476 d = ^d 7477 s = movcon(d) 7478 if s < 0 || 16*s >= 64 { 7479 c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p) 7480 } 7481 o1 = c.opirr(p, AMOVN) 7482 } else { 7483 o1 = c.opirr(p, AMOVZ) 7484 } 7485 o1 |= MOVCONST(d, s, rt) 7486 } 7487 return o1 7488} 7489 7490// load a 32-bit/64-bit large constant (LCON or VCON) in a.Offset into rt 7491// put the instruction sequence in os and return the number of instructions. 7492func (c *ctxt7) omovlconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int, os []uint32) (num uint8) { 7493 switch as { 7494 case AMOVW: 7495 d := uint32(a.Offset) 7496 // use MOVZW and MOVKW to load a constant to rt 7497 os[0] = c.opirr(p, AMOVZW) 7498 os[0] |= MOVCONST(int64(d), 0, rt) 7499 os[1] = c.opirr(p, AMOVKW) 7500 os[1] |= MOVCONST(int64(d), 1, rt) 7501 return 2 7502 7503 case AMOVD: 7504 d := a.Offset 7505 dn := ^d 7506 var immh [4]uint64 7507 var i int 7508 zeroCount := int(0) 7509 negCount := int(0) 7510 for i = 0; i < 4; i++ { 7511 immh[i] = uint64((d >> uint(i*16)) & 0xffff) 7512 if immh[i] == 0 { 7513 zeroCount++ 7514 } else if immh[i] == 0xffff { 7515 negCount++ 7516 } 7517 } 7518 7519 if zeroCount == 4 || negCount == 4 { 7520 c.ctxt.Diag("the immediate should be MOVCON: %v", p) 7521 } 7522 switch { 7523 case zeroCount == 3: 7524 // one MOVZ 7525 for i = 0; i < 4; i++ { 7526 if immh[i] != 0 { 7527 os[0] = c.opirr(p, AMOVZ) 7528 os[0] |= MOVCONST(d, i, rt) 7529 break 7530 } 7531 } 7532 return 1 7533 7534 case negCount == 3: 7535 // one MOVN 7536 for i = 0; i < 4; i++ { 7537 if immh[i] != 0xffff { 7538 os[0] = c.opirr(p, AMOVN) 7539 os[0] |= MOVCONST(dn, i, rt) 7540 break 7541 } 7542 } 7543 return 1 7544 7545 case zeroCount == 2: 7546 // one MOVZ and one MOVK 7547 for i = 0; i < 4; i++ { 7548 if immh[i] != 0 { 7549 os[0] = c.opirr(p, AMOVZ) 7550 os[0] |= MOVCONST(d, i, rt) 7551 i++ 7552 break 7553 } 7554 } 7555 for ; i < 4; i++ { 7556 if immh[i] != 0 { 7557 os[1] = c.opirr(p, AMOVK) 7558 os[1] |= MOVCONST(d, i, rt) 7559 } 7560 } 7561 return 2 7562 7563 case negCount == 2: 7564 // one MOVN and one MOVK 7565 for i = 0; i < 4; i++ { 7566 if immh[i] != 0xffff { 7567 os[0] = c.opirr(p, AMOVN) 7568 os[0] |= MOVCONST(dn, i, rt) 7569 i++ 7570 break 7571 } 7572 } 7573 for ; i < 4; i++ { 7574 if immh[i] != 0xffff { 7575 os[1] = c.opirr(p, AMOVK) 7576 os[1] |= MOVCONST(d, i, rt) 7577 } 7578 } 7579 return 2 7580 7581 case zeroCount == 1: 7582 // one MOVZ and two MOVKs 7583 for i = 0; i < 4; i++ { 7584 if immh[i] != 0 { 7585 os[0] = c.opirr(p, AMOVZ) 7586 os[0] |= MOVCONST(d, i, rt) 7587 i++ 7588 break 7589 } 7590 } 7591 7592 for j := 1; i < 4; i++ { 7593 if immh[i] != 0 { 7594 os[j] = c.opirr(p, AMOVK) 7595 os[j] |= MOVCONST(d, i, rt) 7596 j++ 7597 } 7598 } 7599 return 3 7600 7601 case negCount == 1: 7602 // one MOVN and two MOVKs 7603 for i = 0; i < 4; i++ { 7604 if immh[i] != 0xffff { 7605 os[0] = c.opirr(p, AMOVN) 7606 os[0] |= MOVCONST(dn, i, rt) 7607 i++ 7608 break 7609 } 7610 } 7611 7612 for j := 1; i < 4; i++ { 7613 if immh[i] != 0xffff { 7614 os[j] = c.opirr(p, AMOVK) 7615 os[j] |= MOVCONST(d, i, rt) 7616 j++ 7617 } 7618 } 7619 return 3 7620 7621 default: 7622 // one MOVZ and 3 MOVKs 7623 os[0] = c.opirr(p, AMOVZ) 7624 os[0] |= MOVCONST(d, 0, rt) 7625 for i = 1; i < 4; i++ { 7626 os[i] = c.opirr(p, AMOVK) 7627 os[i] |= MOVCONST(d, i, rt) 7628 } 7629 return 4 7630 } 7631 default: 7632 return 0 7633 } 7634} 7635 7636func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r, s int64, rf, rt int16) uint32 { 7637 var b uint32 7638 o := c.opirr(p, a) 7639 if (o & (1 << 31)) == 0 { 7640 b = 32 7641 } else { 7642 b = 64 7643 } 7644 if r < 0 || uint32(r) >= b { 7645 c.ctxt.Diag("illegal bit number\n%v", p) 7646 } 7647 o |= (uint32(r) & 0x3F) << 16 7648 if s < 0 || uint32(s) >= b { 7649 c.ctxt.Diag("illegal bit number\n%v", p) 7650 } 7651 o |= (uint32(s) & 0x3F) << 10 7652 o |= (uint32(rf&31) << 5) | uint32(rt&31) 7653 return o 7654} 7655 7656func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int64, rn, rm, rt int16) uint32 { 7657 var b uint32 7658 o := c.opirr(p, a) 7659 if (o & (1 << 31)) != 0 { 7660 b = 63 7661 } else { 7662 b = 31 7663 } 7664 if v < 0 || uint32(v) > b { 7665 c.ctxt.Diag("illegal bit number\n%v", p) 7666 } 7667 o |= uint32(v) << 10 7668 o |= uint32(rn&31) << 5 7669 o |= uint32(rm&31) << 16 7670 o |= uint32(rt & 31) 7671 return o 7672} 7673 7674/* generate instruction encoding for ldp and stp series */ 7675func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh int16, ldp uint32) uint32 { 7676 wback := false 7677 if o.scond == C_XPOST || o.scond == C_XPRE { 7678 wback = true 7679 } 7680 switch p.As { 7681 case ALDP, ALDPW, ALDPSW: 7682 c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset)) 7683 case ASTP, ASTPW: 7684 if wback { 7685 c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset)) 7686 } 7687 case AFLDPD, AFLDPQ, AFLDPS: 7688 c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset)) 7689 } 7690 var ret uint32 7691 // check offset 7692 switch p.As { 7693 case AFLDPQ, AFSTPQ: 7694 if vo < -1024 || vo > 1008 || vo%16 != 0 { 7695 c.ctxt.Diag("invalid offset %v\n", p) 7696 } 7697 vo /= 16 7698 ret = 2<<30 | 1<<26 7699 case AFLDPD, AFSTPD: 7700 if vo < -512 || vo > 504 || vo%8 != 0 { 7701 c.ctxt.Diag("invalid offset %v\n", p) 7702 } 7703 vo /= 8 7704 ret = 1<<30 | 1<<26 7705 case AFLDPS, AFSTPS: 7706 if vo < -256 || vo > 252 || vo%4 != 0 { 7707 c.ctxt.Diag("invalid offset %v\n", p) 7708 } 7709 vo /= 4 7710 ret = 1 << 26 7711 case ALDP, ASTP: 7712 if vo < -512 || vo > 504 || vo%8 != 0 { 7713 c.ctxt.Diag("invalid offset %v\n", p) 7714 } 7715 vo /= 8 7716 ret = 2 << 30 7717 case ALDPW, ASTPW: 7718 if vo < -256 || vo > 252 || vo%4 != 0 { 7719 c.ctxt.Diag("invalid offset %v\n", p) 7720 } 7721 vo /= 4 7722 ret = 0 7723 case ALDPSW: 7724 if vo < -256 || vo > 252 || vo%4 != 0 { 7725 c.ctxt.Diag("invalid offset %v\n", p) 7726 } 7727 vo /= 4 7728 ret = 1 << 30 7729 default: 7730 c.ctxt.Diag("invalid instruction %v\n", p) 7731 } 7732 // check register pair 7733 switch p.As { 7734 case AFLDPQ, AFLDPD, AFLDPS, AFSTPQ, AFSTPD, AFSTPS: 7735 if rl < REG_F0 || REG_F31 < rl || rh < REG_F0 || REG_F31 < rh { 7736 c.ctxt.Diag("invalid register pair %v\n", p) 7737 } 7738 case ALDP, ALDPW, ALDPSW: 7739 if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh { 7740 c.ctxt.Diag("invalid register pair %v\n", p) 7741 } 7742 case ASTP, ASTPW: 7743 if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh { 7744 c.ctxt.Diag("invalid register pair %v\n", p) 7745 } 7746 } 7747 // other conditional flag bits 7748 switch o.scond { 7749 case C_XPOST: 7750 ret |= 1 << 23 7751 case C_XPRE: 7752 ret |= 3 << 23 7753 default: 7754 ret |= 2 << 23 7755 } 7756 ret |= 5<<27 | (ldp&1)<<22 | uint32(vo&0x7f)<<15 | uint32(rh&31)<<10 | uint32(rbase&31)<<5 | uint32(rl&31) 7757 return ret 7758} 7759 7760func (c *ctxt7) maskOpvldvst(p *obj.Prog, o1 uint32) uint32 { 7761 if p.As == AVLD1 || p.As == AVST1 { 7762 return o1 7763 } 7764 7765 o1 &^= 0xf000 // mask out "opcode" field (bit 12-15) 7766 switch p.As { 7767 case AVLD1R, AVLD2R: 7768 o1 |= 0xC << 12 7769 case AVLD3R, AVLD4R: 7770 o1 |= 0xE << 12 7771 case AVLD2, AVST2: 7772 o1 |= 8 << 12 7773 case AVLD3, AVST3: 7774 o1 |= 4 << 12 7775 case AVLD4, AVST4: 7776 default: 7777 c.ctxt.Diag("unsupported instruction:%v\n", p.As) 7778 } 7779 return o1 7780} 7781 7782/* 7783 * size in log2(bytes) 7784 */ 7785func movesize(a obj.As) int { 7786 switch a { 7787 case AFMOVQ: 7788 return 4 7789 7790 case AMOVD, AFMOVD: 7791 return 3 7792 7793 case AMOVW, AMOVWU, AFMOVS: 7794 return 2 7795 7796 case AMOVH, AMOVHU: 7797 return 1 7798 7799 case AMOVB, AMOVBU: 7800 return 0 7801 7802 default: 7803 return -1 7804 } 7805} 7806 7807// rm is the Rm register value, o is the extension, amount is the left shift value. 7808func roff(rm int16, o uint32, amount int16) uint32 { 7809 return uint32(rm&31)<<16 | o<<13 | uint32(amount)<<10 7810} 7811 7812// encRegShiftOrExt returns the encoding of shifted/extended register, Rx<<n and Rx.UXTW<<n, etc. 7813func (c *ctxt7) encRegShiftOrExt(p *obj.Prog, a *obj.Addr, r int16) uint32 { 7814 var num, rm int16 7815 num = (r >> 5) & 7 7816 rm = r & 31 7817 switch { 7818 case REG_UXTB <= r && r < REG_UXTH: 7819 return roff(rm, 0, num) 7820 case REG_UXTH <= r && r < REG_UXTW: 7821 return roff(rm, 1, num) 7822 case REG_UXTW <= r && r < REG_UXTX: 7823 if a.Type == obj.TYPE_MEM { 7824 if num == 0 { 7825 // According to the arm64 specification, for instructions MOVB, MOVBU and FMOVB, 7826 // the extension amount must be 0, encoded in "S" as 0 if omitted, or as 1 if present. 7827 // But in Go, we don't distinguish between Rn.UXTW and Rn.UXTW<<0, so we encode it as 7828 // that does not present. This makes no difference to the function of the instruction. 7829 // This is also true for extensions LSL, SXTW and SXTX. 7830 return roff(rm, 2, 2) 7831 } else { 7832 return roff(rm, 2, 6) 7833 } 7834 } else { 7835 return roff(rm, 2, num) 7836 } 7837 case REG_UXTX <= r && r < REG_SXTB: 7838 return roff(rm, 3, num) 7839 case REG_SXTB <= r && r < REG_SXTH: 7840 return roff(rm, 4, num) 7841 case REG_SXTH <= r && r < REG_SXTW: 7842 return roff(rm, 5, num) 7843 case REG_SXTW <= r && r < REG_SXTX: 7844 if a.Type == obj.TYPE_MEM { 7845 if num == 0 { 7846 return roff(rm, 6, 2) 7847 } else { 7848 return roff(rm, 6, 6) 7849 } 7850 } else { 7851 return roff(rm, 6, num) 7852 } 7853 case REG_SXTX <= r && r < REG_SPECIAL: 7854 if a.Type == obj.TYPE_MEM { 7855 if num == 0 { 7856 return roff(rm, 7, 2) 7857 } else { 7858 return roff(rm, 7, 6) 7859 } 7860 } else { 7861 return roff(rm, 7, num) 7862 } 7863 case REG_LSL <= r && r < REG_ARNG: 7864 if a.Type == obj.TYPE_MEM { // (R1)(R2<<1) 7865 if num == 0 { 7866 return roff(rm, 3, 2) 7867 } else { 7868 return roff(rm, 3, 6) 7869 } 7870 } else if isADDWop(p.As) { 7871 return roff(rm, 2, num) 7872 } 7873 return roff(rm, 3, num) 7874 default: 7875 c.ctxt.Diag("unsupported register extension type.") 7876 } 7877 7878 return 0 7879} 7880 7881// pack returns the encoding of the "Q" field and two arrangement specifiers. 7882func pack(q uint32, arngA, arngB uint8) uint32 { 7883 return uint32(q)<<16 | uint32(arngA)<<8 | uint32(arngB) 7884} 7885