github.com/jonasi/go@v0.0.0-20150930005915-e78e654c1de0/src/cmd/internal/obj/arm64/asm7.go (about) 1 // cmd/7l/asm.c, cmd/7l/asmout.c, cmd/7l/optab.c, cmd/7l/span.c, cmd/ld/sub.c, cmd/ld/mod.c, from Vita Nuova. 2 // https://code.google.com/p/ken-cc/source/browse/ 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 package arm64 32 33 import ( 34 "cmd/internal/obj" 35 "fmt" 36 "log" 37 "math" 38 "sort" 39 ) 40 41 const ( 42 FuncAlign = 16 43 ) 44 45 const ( 46 REGFROM = 1 47 ) 48 49 type Optab struct { 50 as uint16 51 a1 uint8 52 a2 uint8 53 a3 uint8 54 type_ int8 55 size int8 56 param int16 57 flag int8 58 scond uint16 59 } 60 61 type Oprange struct { 62 start []Optab 63 stop []Optab 64 } 65 66 var oprange [ALAST]Oprange 67 68 var xcmp [C_NCLASS][C_NCLASS]uint8 69 70 const ( 71 S32 = 0 << 31 72 S64 = 1 << 31 73 Sbit = 1 << 29 74 LSL0_32 = 2 << 13 75 LSL0_64 = 3 << 13 76 ) 77 78 func OPDP2(x uint32) uint32 { 79 return 0<<30 | 0<<29 | 0xd6<<21 | x<<10 80 } 81 82 func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 { 83 return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15 84 } 85 86 func OPBcc(x uint32) uint32 { 87 return 0x2A<<25 | 0<<24 | 0<<4 | x&15 88 } 89 90 func OPBLR(x uint32) uint32 { 91 /* x=0, JMP; 1, CALL; 2, RET */ 92 return 0x6B<<25 | 0<<23 | x<<21 | 0x1F<<16 | 0<<10 93 } 94 95 func SYSOP(l uint32, op0 uint32, op1 uint32, crn uint32, crm uint32, op2 uint32, rt uint32) uint32 { 96 return 0x354<<22 | l<<21 | op0<<19 | op1<<16 | crn&15<<12 | crm&15<<8 | op2<<5 | rt 97 } 98 99 func SYSHINT(x uint32) uint32 { 100 return SYSOP(0, 0, 3, 2, 0, x, 0x1F) 101 } 102 103 func LDSTR12U(sz uint32, v uint32, opc uint32) uint32 { 104 return sz<<30 | 7<<27 | v<<26 | 1<<24 | opc<<22 105 } 106 107 func LDSTR9S(sz uint32, v uint32, opc uint32) uint32 { 108 return sz<<30 | 7<<27 | v<<26 | 0<<24 | opc<<22 109 } 110 111 func LD2STR(o uint32) uint32 { 112 return o &^ (3 << 22) 113 } 114 115 func LDSTX(sz uint32, o2 uint32, l uint32, o1 uint32, o0 uint32) uint32 { 116 return sz<<30 | 0x8<<24 | o2<<23 | l<<22 | o1<<21 | o0<<15 117 } 118 119 func FPCMP(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 { 120 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<14 | 8<<10 | op2 121 } 122 123 func FPCCMP(m uint32, s uint32, type_ uint32, op uint32) uint32 { 124 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | 1<<10 | op<<4 125 } 126 127 func FPOP1S(m uint32, s uint32, type_ uint32, op uint32) uint32 { 128 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<15 | 0x10<<10 129 } 130 131 func FPOP2S(m uint32, s uint32, type_ uint32, op uint32) uint32 { 132 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<12 | 2<<10 133 } 134 135 func FPCVTI(sf uint32, s uint32, type_ uint32, rmode uint32, op uint32) uint32 { 136 return sf<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | rmode<<19 | op<<16 | 0<<10 137 } 138 139 func ADR(p uint32, o uint32, rt uint32) uint32 { 140 return p<<31 | (o&3)<<29 | 0x10<<24 | ((o>>2)&0x7FFFF)<<5 | rt&31 141 } 142 143 func OPBIT(x uint32) uint32 { 144 return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10 145 } 146 147 const ( 148 LFROM = 1 << 0 149 LTO = 1 << 1 150 ) 151 152 var optab = []Optab{ 153 /* struct Optab: 154 OPCODE, from, prog->reg, to, type,size,param,flag,scond */ 155 {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0}, 156 157 /* arithmetic operations */ 158 {AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 159 {AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 160 {AADC, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 161 {AADC, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 162 {ANEG, C_REG, C_NONE, C_REG, 25, 4, 0, 0, 0}, 163 {ANGC, C_REG, C_NONE, C_REG, 17, 4, 0, 0, 0}, 164 {ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0}, 165 {AADD, C_ADDCON, C_RSP, C_RSP, 2, 4, 0, 0, 0}, 166 {AADD, C_ADDCON, C_NONE, C_RSP, 2, 4, 0, 0, 0}, 167 {ACMP, C_ADDCON, C_RSP, C_NONE, 2, 4, 0, 0, 0}, 168 // TODO: these don't work properly. 169 // {AADD, C_MBCON, C_RSP, C_RSP, 2, 4, 0, 0, 0}, 170 // {AADD, C_MBCON, C_NONE, C_RSP, 2, 4, 0, 0, 0}, 171 // {ACMP, C_MBCON, C_RSP, C_NONE, 2, 4, 0, 0, 0}, 172 {AADD, C_VCON, C_RSP, C_RSP, 13, 8, 0, LFROM, 0}, 173 {AADD, C_VCON, C_NONE, C_RSP, 13, 8, 0, LFROM, 0}, 174 {ACMP, C_VCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0}, 175 {AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0}, 176 {AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0}, 177 {AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0}, 178 {ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0}, 179 {ANEG, C_SHIFT, C_NONE, C_REG, 26, 4, 0, 0, 0}, 180 {AADD, C_REG, C_RSP, C_RSP, 27, 4, 0, 0, 0}, 181 {AADD, C_REG, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 182 {ACMP, C_REG, C_RSP, C_NONE, 27, 4, 0, 0, 0}, 183 {AADD, C_EXTREG, C_RSP, C_RSP, 27, 4, 0, 0, 0}, 184 {AADD, C_EXTREG, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 185 {AMVN, C_EXTREG, C_NONE, C_RSP, 27, 4, 0, 0, 0}, 186 {ACMP, C_EXTREG, C_RSP, C_NONE, 27, 4, 0, 0, 0}, 187 {AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 188 {AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 189 190 /* logical operations */ 191 {AAND, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 192 {AAND, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 193 {ABIC, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 194 {ABIC, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 195 // TODO: these don't work properly. 196 // {AAND, C_BITCON, C_REG, C_REG, 53, 4, 0, 0, 0}, 197 // {AAND, C_BITCON, C_NONE, C_REG, 53, 4, 0, 0, 0}, 198 // {ABIC, C_BITCON, C_REG, C_REG, 53, 4, 0, 0, 0}, 199 // {ABIC, C_BITCON, C_NONE, C_REG, 53, 4, 0, 0, 0}, 200 {AAND, C_VCON, C_REG, C_REG, 28, 8, 0, LFROM, 0}, 201 {AAND, C_VCON, C_NONE, C_REG, 28, 8, 0, LFROM, 0}, 202 {ABIC, C_VCON, C_REG, C_REG, 28, 8, 0, LFROM, 0}, 203 {ABIC, C_VCON, C_NONE, C_REG, 28, 8, 0, LFROM, 0}, 204 {AAND, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0}, 205 {AAND, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0}, 206 {ABIC, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0}, 207 {ABIC, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0}, 208 {AMOVD, C_RSP, C_NONE, C_RSP, 24, 4, 0, 0, 0}, 209 {AMVN, C_REG, C_NONE, C_REG, 24, 4, 0, 0, 0}, 210 {AMOVB, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0}, 211 {AMOVBU, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0}, 212 {AMOVH, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVHU */ 213 {AMOVW, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVWU */ 214 /* TODO: MVN C_SHIFT */ 215 216 /* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */ 217 {AMOVW, C_MOVCON, C_NONE, C_REG, 32, 4, 0, 0, 0}, 218 {AMOVD, C_MOVCON, C_NONE, C_REG, 32, 4, 0, 0, 0}, 219 220 // TODO: these don't work properly. 221 // { AMOVW, C_ADDCON, C_NONE, C_REG, 2, 4, 0 , 0}, 222 // { AMOVD, C_ADDCON, C_NONE, C_REG, 2, 4, 0 , 0}, 223 // { AMOVW, C_BITCON, C_NONE, C_REG, 53, 4, 0 , 0}, 224 // { AMOVD, C_BITCON, C_NONE, C_REG, 53, 4, 0 , 0}, 225 226 {AMOVK, C_VCON, C_NONE, C_REG, 33, 4, 0, 0, 0}, 227 {AMOVD, C_AACON, C_NONE, C_REG, 4, 4, REGFROM, 0, 0}, 228 {ASDIV, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 229 {ASDIV, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 230 {AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, 231 {ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, 232 {AB, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, 233 {ABL, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0}, 234 {ABL, C_REG, C_NONE, C_REG, 6, 4, 0, 0, 0}, 235 {ABL, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, 236 {obj.ARET, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0}, 237 {obj.ARET, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0}, 238 {AADRP, C_SBRA, C_NONE, C_REG, 60, 4, 0, 0, 0}, 239 {AADR, C_SBRA, C_NONE, C_REG, 61, 4, 0, 0, 0}, 240 {ABFM, C_VCON, C_REG, C_REG, 42, 4, 0, 0, 0}, 241 {ABFI, C_VCON, C_REG, C_REG, 43, 4, 0, 0, 0}, 242 {AEXTR, C_VCON, C_REG, C_REG, 44, 4, 0, 0, 0}, 243 {ASXTB, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0}, 244 {ACLS, C_REG, C_NONE, C_REG, 46, 4, 0, 0, 0}, 245 {ABEQ, C_NONE, C_NONE, C_SBRA, 7, 4, 0, 0, 0}, 246 {ALSL, C_VCON, C_REG, C_REG, 8, 4, 0, 0, 0}, 247 {ALSL, C_VCON, C_NONE, C_REG, 8, 4, 0, 0, 0}, 248 {ALSL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0}, 249 {ALSL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0}, 250 {ASVC, C_NONE, C_NONE, C_VCON, 10, 4, 0, 0, 0}, 251 {ASVC, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0}, 252 {ADWORD, C_NONE, C_NONE, C_VCON, 11, 8, 0, 0, 0}, 253 {ADWORD, C_NONE, C_NONE, C_LEXT, 11, 8, 0, 0, 0}, 254 {ADWORD, C_NONE, C_NONE, C_ADDR, 11, 8, 0, 0, 0}, 255 {ADWORD, C_NONE, C_NONE, C_LACON, 11, 8, 0, 0, 0}, 256 {AWORD, C_NONE, C_NONE, C_LCON, 14, 4, 0, 0, 0}, 257 {AWORD, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0}, 258 {AWORD, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0}, 259 {AMOVW, C_VCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0}, 260 {AMOVW, C_VCONADDR, C_NONE, C_REG, 68, 8, 0, 0, 0}, 261 {AMOVD, C_VCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0}, 262 {AMOVD, C_VCONADDR, C_NONE, C_REG, 68, 8, 0, 0, 0}, 263 {AMOVB, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 264 {AMOVBU, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 265 {AMOVH, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 266 {AMOVW, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 267 {AMOVD, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 268 {AMOVB, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0}, 269 {AMOVBU, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0}, 270 {AMOVH, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0}, 271 {AMOVW, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0}, 272 {AMOVD, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0}, 273 {AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0}, 274 {AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0}, 275 {AMADD, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0}, 276 {AREM, C_REG, C_REG, C_REG, 16, 8, 0, 0, 0}, 277 {AREM, C_REG, C_NONE, C_REG, 16, 8, 0, 0, 0}, 278 {ACSEL, C_COND, C_REG, C_REG, 18, 4, 0, 0, 0}, /* from3 optional */ 279 {ACSET, C_COND, C_NONE, C_REG, 18, 4, 0, 0, 0}, 280 {ACCMN, C_COND, C_REG, C_VCON, 19, 4, 0, 0, 0}, /* from3 either C_REG or C_VCON */ 281 282 /* scaled 12-bit unsigned displacement store */ 283 {AMOVB, C_REG, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0}, 284 {AMOVB, C_REG, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0}, 285 {AMOVBU, C_REG, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0}, 286 {AMOVBU, C_REG, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0}, 287 288 {AMOVH, C_REG, C_NONE, C_UAUTO8K, 20, 4, REGSP, 0, 0}, 289 {AMOVH, C_REG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0}, 290 {AMOVH, C_REG, C_NONE, C_UOREG8K, 20, 4, 0, 0, 0}, 291 292 {AMOVW, C_REG, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0}, 293 {AMOVW, C_REG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0}, 294 {AMOVW, C_REG, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0}, 295 296 /* unscaled 9-bit signed displacement store */ 297 {AMOVB, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 298 {AMOVB, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 299 {AMOVBU, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 300 {AMOVBU, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 301 302 {AMOVH, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 303 {AMOVH, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 304 {AMOVW, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 305 {AMOVW, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 306 307 {AMOVD, C_REG, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0}, 308 {AMOVD, C_REG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0}, 309 {AMOVD, C_REG, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0}, 310 {AMOVD, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 311 {AMOVD, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 312 313 /* short displacement load */ 314 {AMOVB, C_UAUTO4K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 315 {AMOVB, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 316 {AMOVB, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0}, 317 {AMOVB, C_UOREG4K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 318 {AMOVB, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 319 320 {AMOVBU, C_UAUTO4K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 321 {AMOVBU, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 322 {AMOVBU, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0}, 323 {AMOVBU, C_UOREG4K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 324 {AMOVBU, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 325 326 {AMOVH, C_UAUTO8K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 327 {AMOVH, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 328 {AMOVH, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0}, 329 {AMOVH, C_UOREG8K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 330 {AMOVH, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 331 332 {AMOVW, C_UAUTO16K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 333 {AMOVW, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 334 {AMOVW, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0}, 335 {AMOVW, C_UOREG16K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 336 {AMOVW, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 337 338 {AMOVD, C_UAUTO32K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 339 {AMOVD, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 340 {AMOVD, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0}, 341 {AMOVD, C_UOREG32K, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 342 {AMOVD, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 343 344 /* long displacement store */ 345 {AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, 0, 0}, 346 {AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, 0, 0}, 347 {AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, 0, 0}, 348 {AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, 0, 0}, 349 {AMOVH, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, 0, 0}, 350 {AMOVH, C_REG, C_NONE, C_LOREG, 30, 8, 0, 0, 0}, 351 {AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, 0, 0}, 352 {AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, 0, 0}, 353 {AMOVD, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, 0, 0}, 354 {AMOVD, C_REG, C_NONE, C_LOREG, 30, 8, 0, 0, 0}, 355 356 /* long displacement load */ 357 {AMOVB, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, 0, 0}, 358 {AMOVB, C_LOREG, C_NONE, C_REG, 31, 8, 0, 0, 0}, 359 {AMOVB, C_LOREG, C_NONE, C_REG, 31, 8, 0, 0, 0}, 360 {AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, 0, 0}, 361 {AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, 0, 0}, 362 {AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, 0, 0}, 363 {AMOVH, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, 0, 0}, 364 {AMOVH, C_LOREG, C_NONE, C_REG, 31, 8, 0, 0, 0}, 365 {AMOVH, C_LOREG, C_NONE, C_REG, 31, 8, 0, 0, 0}, 366 {AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, 0, 0}, 367 {AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, 0, 0}, 368 {AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, 0, 0}, 369 {AMOVD, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, 0, 0}, 370 {AMOVD, C_LOREG, C_NONE, C_REG, 31, 8, 0, 0, 0}, 371 {AMOVD, C_LOREG, C_NONE, C_REG, 31, 8, 0, 0, 0}, 372 373 /* load long effective stack address (load int32 offset and add) */ 374 {AMOVD, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0}, 375 376 /* pre/post-indexed load (unscaled, signed 9-bit offset) */ 377 {AMOVD, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 378 {AMOVW, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 379 {AMOVH, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 380 {AMOVB, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 381 {AMOVBU, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST}, 382 {AFMOVS, C_LOREG, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST}, 383 {AFMOVD, C_LOREG, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST}, 384 {AMOVD, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 385 {AMOVW, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 386 {AMOVH, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 387 {AMOVB, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 388 {AMOVBU, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE}, 389 {AFMOVS, C_LOREG, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE}, 390 {AFMOVD, C_LOREG, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE}, 391 392 /* pre/post-indexed store (unscaled, signed 9-bit offset) */ 393 {AMOVD, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 394 {AMOVW, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 395 {AMOVH, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 396 {AMOVB, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 397 {AMOVBU, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 398 {AFMOVS, C_FREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 399 {AFMOVD, C_FREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST}, 400 {AMOVD, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 401 {AMOVW, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 402 {AMOVH, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 403 {AMOVB, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 404 {AMOVBU, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 405 {AFMOVS, C_FREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 406 {AFMOVD, C_FREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE}, 407 408 /* pre/post-indexed load/store register pair 409 (unscaled, signed 10-bit quad-aligned offset) */ 410 {ALDP, C_LOREG, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE}, 411 {ALDP, C_LOREG, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST}, 412 {ASTP, C_PAIR, C_NONE, C_LOREG, 67, 4, 0, 0, C_XPRE}, 413 {ASTP, C_PAIR, C_NONE, C_LOREG, 67, 4, 0, 0, C_XPOST}, 414 415 /* special */ 416 {AMOVD, C_SPR, C_NONE, C_REG, 35, 4, 0, 0, 0}, 417 {AMRS, C_SPR, C_NONE, C_REG, 35, 4, 0, 0, 0}, 418 {AMOVD, C_REG, C_NONE, C_SPR, 36, 4, 0, 0, 0}, 419 {AMSR, C_REG, C_NONE, C_SPR, 36, 4, 0, 0, 0}, 420 {AMOVD, C_VCON, C_NONE, C_SPR, 37, 4, 0, 0, 0}, 421 {AMSR, C_VCON, C_NONE, C_SPR, 37, 4, 0, 0, 0}, 422 {AERET, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0}, 423 {AFMOVS, C_FREG, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0}, 424 {AFMOVS, C_FREG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 425 {AFMOVS, C_FREG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0}, 426 {AFMOVS, C_FREG, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0}, 427 {AFMOVS, C_FREG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 428 {AFMOVD, C_FREG, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0}, 429 {AFMOVD, C_FREG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0}, 430 {AFMOVD, C_FREG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0}, 431 {AFMOVD, C_FREG, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0}, 432 {AFMOVD, C_FREG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0}, 433 {AFMOVS, C_UAUTO16K, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 434 {AFMOVS, C_NSAUTO, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 435 {AFMOVS, C_ZOREG, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 436 {AFMOVS, C_UOREG16K, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 437 {AFMOVS, C_NSOREG, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 438 {AFMOVD, C_UAUTO32K, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 439 {AFMOVD, C_NSAUTO, C_NONE, C_FREG, 21, 4, REGSP, 0, 0}, 440 {AFMOVD, C_ZOREG, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 441 {AFMOVD, C_UOREG32K, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 442 {AFMOVD, C_NSOREG, C_NONE, C_FREG, 21, 4, 0, 0, 0}, 443 {AFMOVS, C_FREG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 444 {AFMOVS, C_FREG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 445 {AFMOVD, C_FREG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 446 {AFMOVD, C_FREG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 447 {AFMOVS, C_LAUTO, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0}, 448 {AFMOVS, C_LOREG, C_NONE, C_FREG, 31, 8, 0, LFROM, 0}, 449 {AFMOVD, C_LAUTO, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0}, 450 {AFMOVD, C_LOREG, C_NONE, C_FREG, 31, 8, 0, LFROM, 0}, 451 {AFMOVS, C_FREG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 452 {AFMOVS, C_ADDR, C_NONE, C_FREG, 65, 12, 0, 0, 0}, 453 {AFMOVD, C_FREG, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, 454 {AFMOVD, C_ADDR, C_NONE, C_FREG, 65, 12, 0, 0, 0}, 455 {AFADDS, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 456 {AFADDS, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0}, 457 {AFADDS, C_FCON, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 458 {AFADDS, C_FCON, C_FREG, C_FREG, 54, 4, 0, 0, 0}, 459 {AFMOVS, C_FCON, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 460 {AFMOVS, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 461 {AFMOVD, C_FCON, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 462 {AFMOVD, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 463 {AFCVTZSD, C_FREG, C_NONE, C_REG, 29, 4, 0, 0, 0}, 464 {ASCVTFD, C_REG, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 465 {AFCMPS, C_FREG, C_FREG, C_NONE, 56, 4, 0, 0, 0}, 466 {AFCMPS, C_FCON, C_FREG, C_NONE, 56, 4, 0, 0, 0}, 467 {AFCCMPS, C_COND, C_REG, C_VCON, 57, 4, 0, 0, 0}, 468 {AFCSELD, C_COND, C_REG, C_FREG, 18, 4, 0, 0, 0}, 469 {AFCVTSD, C_FREG, C_NONE, C_FREG, 29, 4, 0, 0, 0}, 470 {ACLREX, C_NONE, C_NONE, C_VCON, 38, 4, 0, 0, 0}, 471 {ACLREX, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0}, 472 {ACBZ, C_REG, C_NONE, C_SBRA, 39, 4, 0, 0, 0}, 473 {ATBZ, C_VCON, C_REG, C_SBRA, 40, 4, 0, 0, 0}, 474 {ASYS, C_VCON, C_NONE, C_NONE, 50, 4, 0, 0, 0}, 475 {ASYS, C_VCON, C_REG, C_NONE, 50, 4, 0, 0, 0}, 476 {ASYSL, C_VCON, C_NONE, C_REG, 50, 4, 0, 0, 0}, 477 {ADMB, C_VCON, C_NONE, C_NONE, 51, 4, 0, 0, 0}, 478 {AHINT, C_VCON, C_NONE, C_NONE, 52, 4, 0, 0, 0}, 479 {ALDAR, C_ZOREG, C_NONE, C_REG, 58, 4, 0, 0, 0}, 480 {ALDXR, C_ZOREG, C_NONE, C_REG, 58, 4, 0, 0, 0}, 481 {ALDAXR, C_ZOREG, C_NONE, C_REG, 58, 4, 0, 0, 0}, 482 {ALDXP, C_ZOREG, C_REG, C_REG, 58, 4, 0, 0, 0}, 483 {ASTLR, C_REG, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // to3=C_NONE 484 {ASTXR, C_REG, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // to3=C_REG 485 {ASTLXR, C_REG, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // to3=C_REG 486 487 // { ASTXP, C_REG, C_NONE, C_ZOREG, 59, 4, 0 , 0}, // TODO(aram): 488 489 {AAESD, C_VREG, C_NONE, C_VREG, 29, 4, 0, 0, 0}, 490 {ASHA1C, C_VREG, C_REG, C_VREG, 1, 4, 0, 0, 0}, 491 492 {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}, 493 {obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, 0, 0, 0, 0, 0}, 494 {obj.APCDATA, C_VCON, C_NONE, C_VCON, 0, 0, 0, 0, 0}, 495 {obj.AFUNCDATA, C_VCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0}, 496 {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, 497 {obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL 498 {obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL 499 500 {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0}, 501 } 502 503 /* 504 * valid pstate field values, and value to use in instruction 505 */ 506 var pstatefield = []struct { 507 a uint32 508 b uint32 509 }{ 510 {REG_SPSel, 0<<16 | 4<<12 | 5<<5}, 511 {REG_DAIFSet, 3<<16 | 4<<12 | 6<<5}, 512 {REG_DAIFClr, 3<<16 | 4<<12 | 7<<5}, 513 } 514 515 var pool struct { 516 start uint32 517 size uint32 518 } 519 520 func prasm(p *obj.Prog) { 521 fmt.Printf("%v\n", p) 522 } 523 524 func span7(ctxt *obj.Link, cursym *obj.LSym) { 525 p := cursym.Text 526 if p == nil || p.Link == nil { // handle external functions and ELF section symbols 527 return 528 } 529 ctxt.Cursym = cursym 530 ctxt.Autosize = int32(p.To.Offset&0xffffffff) + 8 531 532 if oprange[AAND].start == nil { 533 buildop(ctxt) 534 } 535 536 bflag := 0 537 c := int32(0) 538 p.Pc = int64(c) 539 var m int 540 var o *Optab 541 for p = p.Link; p != nil; p = p.Link { 542 ctxt.Curp = p 543 if p.As == ADWORD && (c&7) != 0 { 544 c += 4 545 } 546 p.Pc = int64(c) 547 o = oplook(ctxt, p) 548 m = int(o.size) 549 if m == 0 { 550 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA { 551 ctxt.Diag("zero-width instruction\n%v", p) 552 } 553 continue 554 } 555 556 switch o.flag & (LFROM | LTO) { 557 case LFROM: 558 addpool(ctxt, p, &p.From) 559 560 case LTO: 561 addpool(ctxt, p, &p.To) 562 break 563 } 564 565 if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */ 566 checkpool(ctxt, p, 0) 567 } 568 c += int32(m) 569 if ctxt.Blitrl != nil { 570 checkpool(ctxt, p, 1) 571 } 572 } 573 574 cursym.Size = int64(c) 575 576 /* 577 * if any procedure is large enough to 578 * generate a large SBRA branch, then 579 * generate extra passes putting branches 580 * around jmps to fix. this is rare. 581 */ 582 for bflag != 0 { 583 bflag = 0 584 c = 0 585 for p = cursym.Text; p != nil; p = p.Link { 586 if p.As == ADWORD && (c&7) != 0 { 587 c += 4 588 } 589 p.Pc = int64(c) 590 o = oplook(ctxt, p) 591 592 /* very large branches 593 if(o->type == 6 && p->cond) { 594 otxt = p->cond->pc - c; 595 if(otxt < 0) 596 otxt = -otxt; 597 if(otxt >= (1L<<17) - 10) { 598 q = ctxt->arch->prg(); 599 q->link = p->link; 600 p->link = q; 601 q->as = AB; 602 q->to.type = obj.TYPE_BRANCH; 603 q->cond = p->cond; 604 p->cond = q; 605 q = ctxt->arch->prg(); 606 q->link = p->link; 607 p->link = q; 608 q->as = AB; 609 q->to.type = obj.TYPE_BRANCH; 610 q->cond = q->link->link; 611 bflag = 1; 612 } 613 } 614 */ 615 m = int(o.size) 616 617 if m == 0 { 618 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA { 619 ctxt.Diag("zero-width instruction\n%v", p) 620 } 621 continue 622 } 623 624 c += int32(m) 625 } 626 } 627 628 c += -c & (FuncAlign - 1) 629 cursym.Size = int64(c) 630 631 /* 632 * lay out the code, emitting code and data relocations. 633 */ 634 if ctxt.Tlsg == nil { 635 ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0) 636 } 637 obj.Symgrow(ctxt, cursym, cursym.Size) 638 bp := cursym.P 639 psz := int32(0) 640 var i int 641 var out [6]uint32 642 for p := cursym.Text.Link; p != nil; p = p.Link { 643 ctxt.Pc = p.Pc 644 ctxt.Curp = p 645 o = oplook(ctxt, p) 646 647 // need to align DWORDs on 8-byte boundary. The ISA doesn't 648 // require it, but the various 64-bit loads we generate assume it. 649 if o.as == ADWORD && psz%8 != 0 { 650 bp[3] = 0 651 bp[2] = bp[3] 652 bp[1] = bp[2] 653 bp[0] = bp[1] 654 bp = bp[4:] 655 psz += 4 656 } 657 658 if int(o.size) > 4*len(out) { 659 log.Fatalf("out array in span7 is too small, need at least %d for %v", o.size/4, p) 660 } 661 asmout(ctxt, p, o, out[:]) 662 for i = 0; i < int(o.size/4); i++ { 663 ctxt.Arch.ByteOrder.PutUint32(bp, out[i]) 664 bp = bp[4:] 665 psz += 4 666 } 667 } 668 } 669 670 /* 671 * when the first reference to the literal pool threatens 672 * to go out of range of a 1Mb PC-relative offset 673 * drop the pool now, and branch round it. 674 */ 675 func checkpool(ctxt *obj.Link, p *obj.Prog, skip int) { 676 if pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(pool.size)-int64(pool.start)+8)) { 677 flushpool(ctxt, p, skip) 678 } else if p.Link == nil { 679 flushpool(ctxt, p, 2) 680 } 681 } 682 683 func flushpool(ctxt *obj.Link, p *obj.Prog, skip int) { 684 if ctxt.Blitrl != nil { 685 if skip != 0 { 686 if ctxt.Debugvlog != 0 && skip == 1 { 687 fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), pool.size, pool.start) 688 } 689 q := ctxt.NewProg() 690 q.As = AB 691 q.To.Type = obj.TYPE_BRANCH 692 q.Pcond = p.Link 693 q.Link = ctxt.Blitrl 694 q.Lineno = p.Lineno 695 ctxt.Blitrl = q 696 } else if p.Pc+int64(pool.size)-int64(pool.start) < 1024*1024 { 697 return 698 } 699 700 // The line number for constant pool entries doesn't really matter. 701 // We set it to the line number of the preceding instruction so that 702 // there are no deltas to encode in the pc-line tables. 703 for q := ctxt.Blitrl; q != nil; q = q.Link { 704 q.Lineno = p.Lineno 705 } 706 707 ctxt.Elitrl.Link = p.Link 708 p.Link = ctxt.Blitrl 709 710 ctxt.Blitrl = nil /* BUG: should refer back to values until out-of-range */ 711 ctxt.Elitrl = nil 712 pool.size = 0 713 pool.start = 0 714 } 715 } 716 717 /* 718 * TODO: hash 719 */ 720 func addpool(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) { 721 c := aclass(ctxt, a) 722 t := *ctxt.NewProg() 723 t.As = AWORD 724 sz := 4 725 726 // MOVW foo(SB), R is actually 727 // MOV addr, REGTEMP 728 // MOVW REGTEMP, R 729 // where addr is the address of the DWORD containing the address of foo. 730 if p.As == AMOVD || c == C_ADDR || c == C_VCON { 731 t.As = ADWORD 732 sz = 8 733 } 734 735 switch c { 736 // TODO(aram): remove. 737 default: 738 if a.Name != obj.NAME_EXTERN { 739 fmt.Printf("addpool: %v in %v shouldn't go to default case\n", DRconv(c), p) 740 } 741 742 t.To.Offset = a.Offset 743 t.To.Sym = a.Sym 744 t.To.Type = a.Type 745 t.To.Name = a.Name 746 747 /* This is here to work around a bug where we generate negative 748 operands that match C_MOVCON, but we use them with 749 instructions that only accept unsigned immediates. This 750 will cause oplook to return a variant of the instruction 751 that loads the negative constant from memory, rather than 752 using the immediate form. Because of that load, we get here, 753 so we need to know what to do with C_MOVCON. 754 755 The correct fix is to use the "negation" instruction variant, 756 e.g. CMN $1, R instead of CMP $-1, R, or SUB $1, R instead 757 of ADD $-1, R. */ 758 case C_MOVCON, 759 760 /* This is here because MOV uint12<<12, R is disabled in optab. 761 Because of this, we need to load the constant from memory. */ 762 C_ADDCON, 763 764 /* These are here because they are disabled in optab. 765 Because of this, we need to load the constant from memory. */ 766 C_BITCON, 767 C_ABCON, 768 C_MBCON, 769 C_PSAUTO, 770 C_PPAUTO, 771 C_UAUTO4K, 772 C_UAUTO8K, 773 C_UAUTO16K, 774 C_UAUTO32K, 775 C_UAUTO64K, 776 C_NSAUTO, 777 C_NPAUTO, 778 C_LAUTO, 779 C_PPOREG, 780 C_PSOREG, 781 C_UOREG4K, 782 C_UOREG8K, 783 C_UOREG16K, 784 C_UOREG32K, 785 C_UOREG64K, 786 C_NSOREG, 787 C_NPOREG, 788 C_LOREG, 789 C_LACON, 790 C_LCON, 791 C_VCON: 792 if a.Name == obj.NAME_EXTERN { 793 fmt.Printf("addpool: %v in %v needs reloc\n", DRconv(c), p) 794 } 795 796 t.To.Type = obj.TYPE_CONST 797 t.To.Offset = ctxt.Instoffset 798 break 799 } 800 801 for q := ctxt.Blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */ 802 if q.To == t.To { 803 p.Pcond = q 804 return 805 } 806 } 807 808 q := ctxt.NewProg() 809 *q = t 810 q.Pc = int64(pool.size) 811 if ctxt.Blitrl == nil { 812 ctxt.Blitrl = q 813 pool.start = uint32(p.Pc) 814 } else { 815 ctxt.Elitrl.Link = q 816 } 817 ctxt.Elitrl = q 818 pool.size = -pool.size & (FuncAlign - 1) 819 pool.size += uint32(sz) 820 p.Pcond = q 821 } 822 823 func regoff(ctxt *obj.Link, a *obj.Addr) uint32 { 824 ctxt.Instoffset = 0 825 aclass(ctxt, a) 826 return uint32(ctxt.Instoffset) 827 } 828 829 func ispcdisp(v int32) bool { 830 /* pc-relative addressing will reach? */ 831 return v >= -0xfffff && v <= 0xfffff && (v&3) == 0 832 } 833 834 func isaddcon(v int64) bool { 835 /* uimm12 or uimm24? */ 836 if v < 0 { 837 return false 838 } 839 if (v & 0xFFF) == 0 { 840 v >>= 12 841 } 842 return v <= 0xFFF 843 } 844 845 func isbitcon(v uint64) bool { 846 /* fancy bimm32 or bimm64? */ 847 // TODO(aram): 848 return false 849 // return findmask(v) != nil || (v>>32) == 0 && findmask(v|(v<<32)) != nil 850 } 851 852 func autoclass(l int64) int { 853 if l < 0 { 854 if l >= -256 { 855 return C_NSAUTO 856 } 857 if l >= -512 && (l&7) == 0 { 858 return C_NPAUTO 859 } 860 return C_LAUTO 861 } 862 863 if l <= 255 { 864 return C_PSAUTO 865 } 866 if l <= 504 && (l&7) == 0 { 867 return C_PPAUTO 868 } 869 if l <= 4095 { 870 return C_UAUTO4K 871 } 872 if l <= 8190 && (l&1) == 0 { 873 return C_UAUTO8K 874 } 875 if l <= 16380 && (l&3) == 0 { 876 return C_UAUTO16K 877 } 878 if l <= 32760 && (l&7) == 0 { 879 return C_UAUTO32K 880 } 881 if l <= 65520 && (l&0xF) == 0 { 882 return C_UAUTO64K 883 } 884 return C_LAUTO 885 } 886 887 func oregclass(l int64) int { 888 if l == 0 { 889 return C_ZOREG 890 } 891 return autoclass(l) - C_NPAUTO + C_NPOREG 892 } 893 894 /* 895 * given an offset v and a class c (see above) 896 * return the offset value to use in the instruction, 897 * scaled if necessary 898 */ 899 func offsetshift(ctxt *obj.Link, v int64, c int) int64 { 900 s := 0 901 if c >= C_SEXT1 && c <= C_SEXT16 { 902 s = c - C_SEXT1 903 } else if c >= C_UAUTO4K && c <= C_UAUTO64K { 904 s = c - C_UAUTO4K 905 } else if c >= C_UOREG4K && c <= C_UOREG64K { 906 s = c - C_UOREG4K 907 } 908 vs := v >> uint(s) 909 if vs<<uint(s) != v { 910 ctxt.Diag("odd offset: %d\n%v", v, ctxt.Curp) 911 } 912 return vs 913 } 914 915 /* 916 * if v contains a single 16-bit value aligned 917 * on a 16-bit field, and thus suitable for movk/movn, 918 * return the field index 0 to 3; otherwise return -1 919 */ 920 func movcon(v int64) int { 921 for s := 0; s < 64; s += 16 { 922 if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 { 923 return s / 16 924 } 925 } 926 return -1 927 } 928 929 func rclass(r int16) int { 930 switch { 931 case REG_R0 <= r && r <= REG_R30: // not 31 932 return C_REG 933 case r == REGZERO: 934 return C_ZCON 935 case REG_F0 <= r && r <= REG_F31: 936 return C_FREG 937 case REG_V0 <= r && r <= REG_V31: 938 return C_VREG 939 case COND_EQ <= r && r <= COND_NV: 940 return C_COND 941 case r == REGSP: 942 return C_RSP 943 case r®_EXT != 0: 944 return C_EXTREG 945 case r >= REG_SPECIAL: 946 return C_SPR 947 } 948 return C_GOK 949 } 950 951 func aclass(ctxt *obj.Link, a *obj.Addr) int { 952 switch a.Type { 953 case obj.TYPE_NONE: 954 return C_NONE 955 956 case obj.TYPE_REG: 957 return rclass(a.Reg) 958 959 case obj.TYPE_REGREG: 960 return C_PAIR 961 962 case obj.TYPE_SHIFT: 963 return C_SHIFT 964 965 case obj.TYPE_MEM: 966 switch a.Name { 967 case obj.NAME_EXTERN, 968 obj.NAME_STATIC: 969 if a.Sym == nil { 970 break 971 } 972 ctxt.Instoffset = a.Offset 973 if a.Sym != nil { // use relocation 974 return C_ADDR 975 } 976 return C_LEXT 977 978 case obj.NAME_AUTO: 979 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset 980 return autoclass(ctxt.Instoffset) 981 982 case obj.NAME_PARAM: 983 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8 984 return autoclass(ctxt.Instoffset) 985 986 case obj.TYPE_NONE: 987 ctxt.Instoffset = a.Offset 988 return oregclass(ctxt.Instoffset) 989 } 990 return C_GOK 991 992 case obj.TYPE_FCONST: 993 return C_FCON 994 995 case obj.TYPE_TEXTSIZE: 996 return C_TEXTSIZE 997 998 case obj.TYPE_CONST, 999 obj.TYPE_ADDR: 1000 switch a.Name { 1001 case obj.TYPE_NONE: 1002 ctxt.Instoffset = a.Offset 1003 if a.Reg != 0 && a.Reg != REGZERO { 1004 goto aconsize 1005 } 1006 v := ctxt.Instoffset 1007 if v == 0 { 1008 return C_ZCON 1009 } 1010 if isaddcon(v) { 1011 if v <= 0xFFF { 1012 return C_ADDCON0 1013 } 1014 if isbitcon(uint64(v)) { 1015 return C_ABCON 1016 } 1017 return C_ADDCON 1018 } 1019 1020 t := movcon(v) 1021 if t >= 0 { 1022 if isbitcon(uint64(v)) { 1023 return C_MBCON 1024 } 1025 return C_MOVCON 1026 } 1027 1028 t = movcon(^v) 1029 if t >= 0 { 1030 if isbitcon(uint64(v)) { 1031 return C_MBCON 1032 } 1033 return C_MOVCON 1034 } 1035 1036 if isbitcon(uint64(v)) { 1037 return C_BITCON 1038 } 1039 1040 if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) { 1041 return C_LCON 1042 } 1043 return C_VCON 1044 1045 case obj.NAME_EXTERN, 1046 obj.NAME_STATIC: 1047 s := a.Sym 1048 if s == nil { 1049 break 1050 } 1051 ctxt.Instoffset = a.Offset 1052 return C_VCONADDR 1053 1054 case obj.NAME_AUTO: 1055 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset 1056 goto aconsize 1057 1058 case obj.NAME_PARAM: 1059 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8 1060 goto aconsize 1061 } 1062 return C_GOK 1063 1064 aconsize: 1065 if isaddcon(ctxt.Instoffset) { 1066 return C_AACON 1067 } 1068 return C_LACON 1069 1070 case obj.TYPE_BRANCH: 1071 return C_SBRA 1072 } 1073 1074 return C_GOK 1075 } 1076 1077 func oplook(ctxt *obj.Link, p *obj.Prog) *Optab { 1078 a1 := int(p.Optab) 1079 if a1 != 0 { 1080 return &optab[a1-1:][0] 1081 } 1082 a1 = int(p.From.Class) 1083 if a1 == 0 { 1084 a1 = aclass(ctxt, &p.From) + 1 1085 p.From.Class = int8(a1) 1086 } 1087 1088 a1-- 1089 a3 := int(p.To.Class) 1090 if a3 == 0 { 1091 a3 = aclass(ctxt, &p.To) + 1 1092 p.To.Class = int8(a3) 1093 } 1094 1095 a3-- 1096 a2 := C_NONE 1097 if p.Reg != 0 { 1098 a2 = rclass(p.Reg) 1099 } 1100 r := int(p.As) 1101 o := oprange[r].start 1102 if o == nil { 1103 o = oprange[r].stop /* just generate an error */ 1104 } 1105 1106 if false { 1107 fmt.Printf("oplook %v %d %d %d\n", obj.Aconv(int(p.As)), a1, a2, a3) 1108 fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type) 1109 } 1110 1111 e := oprange[r].stop 1112 c1 := xcmp[a1][:] 1113 c2 := xcmp[a2][:] 1114 c3 := xcmp[a3][:] 1115 c4 := xcmp[p.Scond>>5][:] 1116 for ; -cap(o) < -cap(e); o = o[1:] { 1117 if int(o[0].a2) == a2 || c2[o[0].a2] != 0 { 1118 if c4[o[0].scond>>5] != 0 { 1119 if c1[o[0].a1] != 0 { 1120 if c3[o[0].a3] != 0 { 1121 p.Optab = uint16((-cap(o) + cap(optab)) + 1) 1122 return &o[0] 1123 } 1124 } 1125 } 1126 } 1127 } 1128 1129 ctxt.Diag("illegal combination %v %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.To.Type) 1130 prasm(p) 1131 if o == nil { 1132 o = optab 1133 } 1134 return &o[0] 1135 } 1136 1137 func cmp(a int, b int) bool { 1138 if a == b { 1139 return true 1140 } 1141 switch a { 1142 case C_RSP: 1143 if b == C_REG { 1144 return true 1145 } 1146 1147 case C_REG: 1148 if b == C_ZCON { 1149 return true 1150 } 1151 1152 case C_ADDCON0: 1153 if b == C_ZCON { 1154 return true 1155 } 1156 1157 case C_ADDCON: 1158 if b == C_ZCON || b == C_ADDCON0 || b == C_ABCON { 1159 return true 1160 } 1161 1162 case C_BITCON: 1163 if b == C_ABCON || b == C_MBCON { 1164 return true 1165 } 1166 1167 case C_MOVCON: 1168 if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 { 1169 return true 1170 } 1171 1172 case C_LCON: 1173 if b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_MBCON || b == C_MOVCON { 1174 return true 1175 } 1176 1177 case C_VCON: 1178 return cmp(C_LCON, b) 1179 1180 case C_LACON: 1181 if b == C_AACON { 1182 return true 1183 } 1184 1185 case C_SEXT2: 1186 if b == C_SEXT1 { 1187 return true 1188 } 1189 1190 case C_SEXT4: 1191 if b == C_SEXT1 || b == C_SEXT2 { 1192 return true 1193 } 1194 1195 case C_SEXT8: 1196 if b >= C_SEXT1 && b <= C_SEXT4 { 1197 return true 1198 } 1199 1200 case C_SEXT16: 1201 if b >= C_SEXT1 && b <= C_SEXT8 { 1202 return true 1203 } 1204 1205 case C_LEXT: 1206 if b >= C_SEXT1 && b <= C_SEXT16 { 1207 return true 1208 } 1209 1210 case C_PPAUTO: 1211 if b == C_PSAUTO { 1212 return true 1213 } 1214 1215 case C_UAUTO4K: 1216 if b == C_PSAUTO || b == C_PPAUTO { 1217 return true 1218 } 1219 1220 case C_UAUTO8K: 1221 return cmp(C_UAUTO4K, b) 1222 1223 case C_UAUTO16K: 1224 return cmp(C_UAUTO8K, b) 1225 1226 case C_UAUTO32K: 1227 return cmp(C_UAUTO16K, b) 1228 1229 case C_UAUTO64K: 1230 return cmp(C_UAUTO32K, b) 1231 1232 case C_NPAUTO: 1233 return cmp(C_NSAUTO, b) 1234 1235 case C_LAUTO: 1236 return cmp(C_NPAUTO, b) || cmp(C_UAUTO64K, b) 1237 1238 case C_PSOREG: 1239 if b == C_ZOREG { 1240 return true 1241 } 1242 1243 case C_PPOREG: 1244 if b == C_ZOREG || b == C_PSOREG { 1245 return true 1246 } 1247 1248 case C_UOREG4K: 1249 if b == C_ZOREG || b == C_PSAUTO || b == C_PSOREG || b == C_PPAUTO || b == C_PPOREG { 1250 return true 1251 } 1252 1253 case C_UOREG8K: 1254 return cmp(C_UOREG4K, b) 1255 1256 case C_UOREG16K: 1257 return cmp(C_UOREG8K, b) 1258 1259 case C_UOREG32K: 1260 return cmp(C_UOREG16K, b) 1261 1262 case C_UOREG64K: 1263 return cmp(C_UOREG32K, b) 1264 1265 case C_NPOREG: 1266 return cmp(C_NSOREG, b) 1267 1268 case C_LOREG: 1269 return cmp(C_NPOREG, b) || cmp(C_UOREG64K, b) 1270 1271 case C_LBRA: 1272 if b == C_SBRA { 1273 return true 1274 } 1275 } 1276 1277 return false 1278 } 1279 1280 type ocmp []Optab 1281 1282 func (x ocmp) Len() int { 1283 return len(x) 1284 } 1285 1286 func (x ocmp) Swap(i, j int) { 1287 x[i], x[j] = x[j], x[i] 1288 } 1289 1290 func (x ocmp) Less(i, j int) bool { 1291 p1 := &x[i] 1292 p2 := &x[j] 1293 n := int(p1.as) - int(p2.as) 1294 if n != 0 { 1295 return n < 0 1296 } 1297 n = int(p1.a1) - int(p2.a1) 1298 if n != 0 { 1299 return n < 0 1300 } 1301 n = int(p1.a2) - int(p2.a2) 1302 if n != 0 { 1303 return n < 0 1304 } 1305 n = int(p1.a3) - int(p2.a3) 1306 if n != 0 { 1307 return n < 0 1308 } 1309 n = int(p1.scond) - int(p2.scond) 1310 if n != 0 { 1311 return n < 0 1312 } 1313 return false 1314 } 1315 1316 func buildop(ctxt *obj.Link) { 1317 var n int 1318 for i := 0; i < C_GOK; i++ { 1319 for n = 0; n < C_GOK; n++ { 1320 if cmp(n, i) { 1321 xcmp[i][n] = 1 1322 } 1323 } 1324 } 1325 for n = 0; optab[n].as != obj.AXXX; n++ { 1326 } 1327 sort.Sort(ocmp(optab[:n])) 1328 var r int 1329 var t Oprange 1330 for i := 0; i < n; i++ { 1331 r = int(optab[i].as) 1332 oprange[r].start = optab[i:] 1333 for int(optab[i].as) == r { 1334 i++ 1335 } 1336 oprange[r].stop = optab[i:] 1337 i-- 1338 t = oprange[r] 1339 switch r { 1340 default: 1341 ctxt.Diag("unknown op in build: %v", obj.Aconv(r)) 1342 log.Fatalf("bad code") 1343 1344 case AADD: 1345 oprange[AADDS] = t 1346 oprange[ASUB] = t 1347 oprange[ASUBS] = t 1348 oprange[AADDW] = t 1349 oprange[AADDSW] = t 1350 oprange[ASUBW] = t 1351 oprange[ASUBSW] = t 1352 1353 case AAND: /* logical immediate, logical shifted register */ 1354 oprange[AANDS] = t 1355 1356 oprange[AANDSW] = t 1357 oprange[AANDW] = t 1358 oprange[AEOR] = t 1359 oprange[AEORW] = t 1360 oprange[AORR] = t 1361 oprange[AORRW] = t 1362 1363 case ABIC: /* only logical shifted register */ 1364 oprange[ABICS] = t 1365 1366 oprange[ABICSW] = t 1367 oprange[ABICW] = t 1368 oprange[AEON] = t 1369 oprange[AEONW] = t 1370 oprange[AORN] = t 1371 oprange[AORNW] = t 1372 1373 case ANEG: 1374 oprange[ANEGS] = t 1375 oprange[ANEGSW] = t 1376 oprange[ANEGW] = t 1377 1378 case AADC: /* rn=Rd */ 1379 oprange[AADCW] = t 1380 1381 oprange[AADCS] = t 1382 oprange[AADCSW] = t 1383 oprange[ASBC] = t 1384 oprange[ASBCW] = t 1385 oprange[ASBCS] = t 1386 oprange[ASBCSW] = t 1387 1388 case ANGC: /* rn=REGZERO */ 1389 oprange[ANGCW] = t 1390 1391 oprange[ANGCS] = t 1392 oprange[ANGCSW] = t 1393 1394 case ACMP: 1395 oprange[ACMPW] = t 1396 oprange[ACMN] = t 1397 oprange[ACMNW] = t 1398 1399 case ATST: 1400 oprange[ATSTW] = t 1401 1402 /* register/register, and shifted */ 1403 case AMVN: 1404 oprange[AMVNW] = t 1405 1406 case AMOVK: 1407 oprange[AMOVKW] = t 1408 oprange[AMOVN] = t 1409 oprange[AMOVNW] = t 1410 oprange[AMOVZ] = t 1411 oprange[AMOVZW] = t 1412 1413 case ABEQ: 1414 oprange[ABNE] = t 1415 oprange[ABCS] = t 1416 oprange[ABHS] = t 1417 oprange[ABCC] = t 1418 oprange[ABLO] = t 1419 oprange[ABMI] = t 1420 oprange[ABPL] = t 1421 oprange[ABVS] = t 1422 oprange[ABVC] = t 1423 oprange[ABHI] = t 1424 oprange[ABLS] = t 1425 oprange[ABGE] = t 1426 oprange[ABLT] = t 1427 oprange[ABGT] = t 1428 oprange[ABLE] = t 1429 1430 case ALSL: 1431 oprange[ALSLW] = t 1432 oprange[ALSR] = t 1433 oprange[ALSRW] = t 1434 oprange[AASR] = t 1435 oprange[AASRW] = t 1436 oprange[AROR] = t 1437 oprange[ARORW] = t 1438 1439 case ACLS: 1440 oprange[ACLSW] = t 1441 oprange[ACLZ] = t 1442 oprange[ACLZW] = t 1443 oprange[ARBIT] = t 1444 oprange[ARBITW] = t 1445 oprange[AREV] = t 1446 oprange[AREVW] = t 1447 oprange[AREV16] = t 1448 oprange[AREV16W] = t 1449 oprange[AREV32] = t 1450 1451 case ASDIV: 1452 oprange[ASDIVW] = t 1453 oprange[AUDIV] = t 1454 oprange[AUDIVW] = t 1455 oprange[ACRC32B] = t 1456 oprange[ACRC32CB] = t 1457 oprange[ACRC32CH] = t 1458 oprange[ACRC32CW] = t 1459 oprange[ACRC32CX] = t 1460 oprange[ACRC32H] = t 1461 oprange[ACRC32W] = t 1462 oprange[ACRC32X] = t 1463 1464 case AMADD: 1465 oprange[AMADDW] = t 1466 oprange[AMSUB] = t 1467 oprange[AMSUBW] = t 1468 oprange[ASMADDL] = t 1469 oprange[ASMSUBL] = t 1470 oprange[AUMADDL] = t 1471 oprange[AUMSUBL] = t 1472 1473 case AREM: 1474 oprange[AREMW] = t 1475 oprange[AUREM] = t 1476 oprange[AUREMW] = t 1477 1478 case AMUL: 1479 oprange[AMULW] = t 1480 oprange[AMNEG] = t 1481 oprange[AMNEGW] = t 1482 oprange[ASMNEGL] = t 1483 oprange[ASMULL] = t 1484 oprange[ASMULH] = t 1485 oprange[AUMNEGL] = t 1486 oprange[AUMULH] = t 1487 oprange[AUMULL] = t 1488 1489 case AMOVB: 1490 oprange[AMOVBU] = t 1491 1492 case AMOVH: 1493 oprange[AMOVHU] = t 1494 1495 case AMOVW: 1496 oprange[AMOVWU] = t 1497 1498 case ABFM: 1499 oprange[ABFMW] = t 1500 oprange[ASBFM] = t 1501 oprange[ASBFMW] = t 1502 oprange[AUBFM] = t 1503 oprange[AUBFMW] = t 1504 1505 case ABFI: 1506 oprange[ABFIW] = t 1507 oprange[ABFXIL] = t 1508 oprange[ABFXILW] = t 1509 oprange[ASBFIZ] = t 1510 oprange[ASBFIZW] = t 1511 oprange[ASBFX] = t 1512 oprange[ASBFXW] = t 1513 oprange[AUBFIZ] = t 1514 oprange[AUBFIZW] = t 1515 oprange[AUBFX] = t 1516 oprange[AUBFXW] = t 1517 1518 case AEXTR: 1519 oprange[AEXTRW] = t 1520 1521 case ASXTB: 1522 oprange[ASXTBW] = t 1523 oprange[ASXTH] = t 1524 oprange[ASXTHW] = t 1525 oprange[ASXTW] = t 1526 oprange[AUXTB] = t 1527 oprange[AUXTH] = t 1528 oprange[AUXTW] = t 1529 oprange[AUXTBW] = t 1530 oprange[AUXTHW] = t 1531 1532 case ACCMN: 1533 oprange[ACCMNW] = t 1534 oprange[ACCMP] = t 1535 oprange[ACCMPW] = t 1536 1537 case ACSEL: 1538 oprange[ACSELW] = t 1539 oprange[ACSINC] = t 1540 oprange[ACSINCW] = t 1541 oprange[ACSINV] = t 1542 oprange[ACSINVW] = t 1543 oprange[ACSNEG] = t 1544 oprange[ACSNEGW] = t 1545 1546 // aliases Rm=Rn, !cond 1547 oprange[ACINC] = t 1548 1549 oprange[ACINCW] = t 1550 oprange[ACINV] = t 1551 oprange[ACINVW] = t 1552 oprange[ACNEG] = t 1553 oprange[ACNEGW] = t 1554 1555 // aliases, Rm=Rn=REGZERO, !cond 1556 case ACSET: 1557 oprange[ACSETW] = t 1558 1559 oprange[ACSETM] = t 1560 oprange[ACSETMW] = t 1561 1562 case AMOVD, 1563 AMOVBU, 1564 AB, 1565 ABL, 1566 AWORD, 1567 ADWORD, 1568 obj.ARET, 1569 obj.ATEXT, 1570 ASTP, 1571 ALDP: 1572 break 1573 1574 case AERET: 1575 oprange[AWFE] = t 1576 oprange[AWFI] = t 1577 oprange[AYIELD] = t 1578 oprange[ASEV] = t 1579 oprange[ASEVL] = t 1580 oprange[ADRPS] = t 1581 1582 case ACBZ: 1583 oprange[ACBZW] = t 1584 oprange[ACBNZ] = t 1585 oprange[ACBNZW] = t 1586 1587 case ATBZ: 1588 oprange[ATBNZ] = t 1589 1590 case AADR, AADRP: 1591 break 1592 1593 case ACLREX: 1594 break 1595 1596 case ASVC: 1597 oprange[AHLT] = t 1598 oprange[AHVC] = t 1599 oprange[ASMC] = t 1600 oprange[ABRK] = t 1601 oprange[ADCPS1] = t 1602 oprange[ADCPS2] = t 1603 oprange[ADCPS3] = t 1604 1605 case AFADDS: 1606 oprange[AFADDD] = t 1607 oprange[AFSUBS] = t 1608 oprange[AFSUBD] = t 1609 oprange[AFMULS] = t 1610 oprange[AFMULD] = t 1611 oprange[AFNMULS] = t 1612 oprange[AFNMULD] = t 1613 oprange[AFDIVS] = t 1614 oprange[AFMAXD] = t 1615 oprange[AFMAXS] = t 1616 oprange[AFMIND] = t 1617 oprange[AFMINS] = t 1618 oprange[AFMAXNMD] = t 1619 oprange[AFMAXNMS] = t 1620 oprange[AFMINNMD] = t 1621 oprange[AFMINNMS] = t 1622 oprange[AFDIVD] = t 1623 1624 case AFCVTSD: 1625 oprange[AFCVTDS] = t 1626 oprange[AFABSD] = t 1627 oprange[AFABSS] = t 1628 oprange[AFNEGD] = t 1629 oprange[AFNEGS] = t 1630 oprange[AFSQRTD] = t 1631 oprange[AFSQRTS] = t 1632 oprange[AFRINTNS] = t 1633 oprange[AFRINTND] = t 1634 oprange[AFRINTPS] = t 1635 oprange[AFRINTPD] = t 1636 oprange[AFRINTMS] = t 1637 oprange[AFRINTMD] = t 1638 oprange[AFRINTZS] = t 1639 oprange[AFRINTZD] = t 1640 oprange[AFRINTAS] = t 1641 oprange[AFRINTAD] = t 1642 oprange[AFRINTXS] = t 1643 oprange[AFRINTXD] = t 1644 oprange[AFRINTIS] = t 1645 oprange[AFRINTID] = t 1646 oprange[AFCVTDH] = t 1647 oprange[AFCVTHS] = t 1648 oprange[AFCVTHD] = t 1649 oprange[AFCVTSH] = t 1650 1651 case AFCMPS: 1652 oprange[AFCMPD] = t 1653 oprange[AFCMPES] = t 1654 oprange[AFCMPED] = t 1655 1656 case AFCCMPS: 1657 oprange[AFCCMPD] = t 1658 oprange[AFCCMPES] = t 1659 oprange[AFCCMPED] = t 1660 1661 case AFCSELD: 1662 oprange[AFCSELS] = t 1663 1664 case AFMOVS, AFMOVD: 1665 break 1666 1667 case AFCVTZSD: 1668 oprange[AFCVTZSDW] = t 1669 oprange[AFCVTZSS] = t 1670 oprange[AFCVTZSSW] = t 1671 oprange[AFCVTZUD] = t 1672 oprange[AFCVTZUDW] = t 1673 oprange[AFCVTZUS] = t 1674 oprange[AFCVTZUSW] = t 1675 1676 case ASCVTFD: 1677 oprange[ASCVTFS] = t 1678 oprange[ASCVTFWD] = t 1679 oprange[ASCVTFWS] = t 1680 oprange[AUCVTFD] = t 1681 oprange[AUCVTFS] = t 1682 oprange[AUCVTFWD] = t 1683 oprange[AUCVTFWS] = t 1684 1685 case ASYS: 1686 oprange[AAT] = t 1687 oprange[ADC] = t 1688 oprange[AIC] = t 1689 oprange[ATLBI] = t 1690 1691 case ASYSL, AHINT: 1692 break 1693 1694 case ADMB: 1695 oprange[ADSB] = t 1696 oprange[AISB] = t 1697 1698 case AMRS, AMSR: 1699 break 1700 1701 case ALDAR: 1702 oprange[ALDARW] = t 1703 fallthrough 1704 1705 case ALDXR: 1706 oprange[ALDXRB] = t 1707 oprange[ALDXRH] = t 1708 oprange[ALDXRW] = t 1709 1710 case ALDAXR: 1711 oprange[ALDAXRW] = t 1712 1713 case ALDXP: 1714 oprange[ALDXPW] = t 1715 1716 case ASTLR: 1717 oprange[ASTLRW] = t 1718 1719 case ASTXR: 1720 oprange[ASTXRB] = t 1721 oprange[ASTXRH] = t 1722 oprange[ASTXRW] = t 1723 1724 case ASTLXR: 1725 oprange[ASTLXRW] = t 1726 1727 case ASTXP: 1728 oprange[ASTXPW] = t 1729 1730 case AAESD: 1731 oprange[AAESE] = t 1732 oprange[AAESMC] = t 1733 oprange[AAESIMC] = t 1734 oprange[ASHA1H] = t 1735 oprange[ASHA1SU1] = t 1736 oprange[ASHA256SU0] = t 1737 1738 case ASHA1C: 1739 oprange[ASHA1P] = t 1740 oprange[ASHA1M] = t 1741 oprange[ASHA1SU0] = t 1742 oprange[ASHA256H] = t 1743 oprange[ASHA256H2] = t 1744 oprange[ASHA256SU1] = t 1745 1746 case obj.ANOP, 1747 obj.AUNDEF, 1748 obj.AUSEFIELD, 1749 obj.AFUNCDATA, 1750 obj.APCDATA, 1751 obj.ADUFFZERO, 1752 obj.ADUFFCOPY: 1753 break 1754 } 1755 } 1756 } 1757 1758 func chipfloat7(ctxt *obj.Link, e float64) int { 1759 ei := math.Float64bits(e) 1760 l := uint32(int32(ei)) 1761 h := uint32(int32(ei >> 32)) 1762 1763 if l != 0 || h&0xffff != 0 { 1764 return -1 1765 } 1766 h1 := h & 0x7fc00000 1767 if h1 != 0x40000000 && h1 != 0x3fc00000 { 1768 return -1 1769 } 1770 n := 0 1771 1772 // sign bit (a) 1773 if h&0x80000000 != 0 { 1774 n |= 1 << 7 1775 } 1776 1777 // exp sign bit (b) 1778 if h1 == 0x3fc00000 { 1779 n |= 1 << 6 1780 } 1781 1782 // rest of exp and mantissa (cd-efgh) 1783 n |= int((h >> 16) & 0x3f) 1784 1785 //print("match %.8lux %.8lux %d\n", l, h, n); 1786 return n 1787 } 1788 1789 /* form offset parameter to SYS; special register number */ 1790 func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int { 1791 return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5 1792 } 1793 1794 func SYSARG4(op1 int, Cn int, Cm int, op2 int) int { 1795 return SYSARG5(0, op1, Cn, Cm, op2) 1796 } 1797 1798 func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { 1799 o1 := uint32(0) 1800 o2 := uint32(0) 1801 o3 := uint32(0) 1802 o4 := uint32(0) 1803 o5 := uint32(0) 1804 if false { /*debug['P']*/ 1805 fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_) 1806 } 1807 switch o.type_ { 1808 default: 1809 ctxt.Diag("unknown asm %d", o.type_) 1810 prasm(p) 1811 1812 case 0: /* pseudo ops */ 1813 break 1814 1815 case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */ 1816 o1 = oprrr(ctxt, int(p.As)) 1817 1818 rf := int(p.From.Reg) 1819 rt := int(p.To.Reg) 1820 r := int(p.Reg) 1821 if p.To.Type == obj.TYPE_NONE { 1822 rt = REGZERO 1823 } 1824 if r == 0 { 1825 r = rt 1826 } 1827 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 1828 1829 case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */ 1830 o1 = opirr(ctxt, int(p.As)) 1831 1832 rt := int(p.To.Reg) 1833 if p.To.Type == obj.TYPE_NONE { 1834 if (o1 & Sbit) == 0 { 1835 ctxt.Diag("ineffective ZR destination\n%v", p) 1836 } 1837 rt = REGZERO 1838 } 1839 1840 r := int(p.Reg) 1841 if r == 0 { 1842 r = rt 1843 } 1844 v := int32(regoff(ctxt, &p.From)) 1845 o1 = oaddi(ctxt, int32(o1), v, r, rt) 1846 1847 case 3: /* op R<<n[,R],R (shifted register) */ 1848 o1 = oprrr(ctxt, int(p.As)) 1849 1850 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 1851 rt := int(p.To.Reg) 1852 if p.To.Type == obj.TYPE_NONE { 1853 rt = REGZERO 1854 } 1855 r := int(p.Reg) 1856 if p.As == AMVN || p.As == AMVNW { 1857 r = REGZERO 1858 } else if r == 0 { 1859 r = rt 1860 } 1861 o1 |= (uint32(r&31) << 5) | uint32(rt&31) 1862 1863 case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R */ 1864 o1 = opirr(ctxt, int(p.As)) 1865 1866 rt := int(p.To.Reg) 1867 r := int(o.param) 1868 if r == 0 { 1869 r = REGZERO 1870 } else if r == REGFROM { 1871 r = int(p.From.Reg) 1872 } 1873 if r == 0 { 1874 r = REGSP 1875 } 1876 v := int32(regoff(ctxt, &p.From)) 1877 if (v & 0xFFF000) != 0 { 1878 v >>= 12 1879 o1 |= 1 << 22 /* shift, by 12 */ 1880 } 1881 1882 o1 |= ((uint32(v) & 0xFFF) << 10) | (uint32(r&31) << 5) | uint32(rt&31) 1883 1884 case 5: /* b s; bl s */ 1885 o1 = opbra(ctxt, int(p.As)) 1886 1887 if p.To.Sym == nil { 1888 o1 |= uint32(brdist(ctxt, p, 0, 26, 2)) 1889 break 1890 } 1891 1892 rel := obj.Addrel(ctxt.Cursym) 1893 rel.Off = int32(ctxt.Pc) 1894 rel.Siz = 4 1895 rel.Sym = p.To.Sym 1896 rel.Add = p.To.Offset 1897 rel.Type = obj.R_CALLARM64 1898 1899 case 6: /* b ,O(R); bl ,O(R) */ 1900 o1 = opbrr(ctxt, int(p.As)) 1901 1902 o1 |= uint32(p.To.Reg&31) << 5 1903 rel := obj.Addrel(ctxt.Cursym) 1904 rel.Off = int32(ctxt.Pc) 1905 rel.Siz = 0 1906 rel.Type = obj.R_CALLIND 1907 1908 case 7: /* beq s */ 1909 o1 = opbra(ctxt, int(p.As)) 1910 1911 o1 |= uint32(brdist(ctxt, p, 0, 19, 2) << 5) 1912 1913 case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */ 1914 rt := int(p.To.Reg) 1915 1916 rf := int(p.Reg) 1917 if rf == 0 { 1918 rf = rt 1919 } 1920 v := int32(p.From.Offset) 1921 switch p.As { 1922 case AASR: 1923 o1 = opbfm(ctxt, ASBFM, int(v), 63, rf, rt) 1924 1925 case AASRW: 1926 o1 = opbfm(ctxt, ASBFMW, int(v), 31, rf, rt) 1927 1928 case ALSL: 1929 o1 = opbfm(ctxt, AUBFM, int((64-v)&63), int(63-v), rf, rt) 1930 1931 case ALSLW: 1932 o1 = opbfm(ctxt, AUBFMW, int((32-v)&31), int(31-v), rf, rt) 1933 1934 case ALSR: 1935 o1 = opbfm(ctxt, AUBFM, int(v), 63, rf, rt) 1936 1937 case ALSRW: 1938 o1 = opbfm(ctxt, AUBFMW, int(v), 31, rf, rt) 1939 1940 case AROR: 1941 o1 = opextr(ctxt, AEXTR, v, rf, rf, rt) 1942 1943 case ARORW: 1944 o1 = opextr(ctxt, AEXTRW, v, rf, rf, rt) 1945 1946 default: 1947 ctxt.Diag("bad shift $con\n%v", ctxt.Curp) 1948 break 1949 } 1950 1951 case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */ 1952 o1 = oprrr(ctxt, int(p.As)) 1953 1954 r := int(p.Reg) 1955 if r == 0 { 1956 r = int(p.To.Reg) 1957 } 1958 o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31) 1959 1960 case 10: /* brk/hvc/.../svc [$con] */ 1961 o1 = opimm(ctxt, int(p.As)) 1962 1963 if p.To.Type != obj.TYPE_NONE { 1964 o1 |= uint32((p.To.Offset & 0xffff) << 5) 1965 } 1966 1967 case 11: /* dword */ 1968 aclass(ctxt, &p.To) 1969 1970 o1 = uint32(ctxt.Instoffset) 1971 o2 = uint32(ctxt.Instoffset >> 32) 1972 if p.To.Sym != nil { 1973 rel := obj.Addrel(ctxt.Cursym) 1974 rel.Off = int32(ctxt.Pc) 1975 rel.Siz = 8 1976 rel.Sym = p.To.Sym 1977 rel.Add = p.To.Offset 1978 rel.Type = obj.R_ADDR 1979 o2 = 0 1980 o1 = o2 1981 } 1982 1983 case 12: /* movT $vcon, reg */ 1984 o1 = omovlit(ctxt, int(p.As), p, &p.From, int(p.To.Reg)) 1985 1986 case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */ 1987 o1 = omovlit(ctxt, AMOVD, p, &p.From, REGTMP) 1988 1989 if !(o1 != 0) { 1990 break 1991 } 1992 rt := int(p.To.Reg) 1993 if p.To.Type == obj.TYPE_NONE { 1994 rt = REGZERO 1995 } 1996 r := int(p.Reg) 1997 if r == 0 { 1998 r = rt 1999 } 2000 if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) { 2001 o2 = opxrrr(ctxt, int(p.As)) 2002 o2 |= REGTMP & 31 << 16 2003 o2 |= LSL0_64 2004 } else { 2005 o2 = oprrr(ctxt, int(p.As)) 2006 o2 |= REGTMP & 31 << 16 /* shift is 0 */ 2007 } 2008 2009 o2 |= uint32(r&31) << 5 2010 o2 |= uint32(rt & 31) 2011 2012 case 14: /* word */ 2013 if aclass(ctxt, &p.To) == C_ADDR { 2014 ctxt.Diag("address constant needs DWORD\n%v", p) 2015 } 2016 o1 = uint32(ctxt.Instoffset) 2017 if p.To.Sym != nil { 2018 // This case happens with words generated 2019 // in the PC stream as part of the literal pool. 2020 rel := obj.Addrel(ctxt.Cursym) 2021 2022 rel.Off = int32(ctxt.Pc) 2023 rel.Siz = 4 2024 rel.Sym = p.To.Sym 2025 rel.Add = p.To.Offset 2026 rel.Type = obj.R_ADDR 2027 o1 = 0 2028 } 2029 2030 case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub Rm,Rn,Ra,Rd */ 2031 o1 = oprrr(ctxt, int(p.As)) 2032 2033 rf := int(p.From.Reg) 2034 rt := int(p.To.Reg) 2035 var r int 2036 var ra int 2037 if p.From3Type() == obj.TYPE_REG { 2038 r = int(p.From3.Reg) 2039 ra = int(p.Reg) 2040 if ra == 0 { 2041 ra = REGZERO 2042 } 2043 } else { 2044 r = int(p.Reg) 2045 if r == 0 { 2046 r = rt 2047 } 2048 ra = REGZERO 2049 } 2050 2051 o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31) 2052 2053 case 16: /* XremY R[,R],R -> XdivY; XmsubY */ 2054 o1 = oprrr(ctxt, int(p.As)) 2055 2056 rf := int(p.From.Reg) 2057 rt := int(p.To.Reg) 2058 r := int(p.Reg) 2059 if r == 0 { 2060 r = rt 2061 } 2062 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31 2063 o2 = oprrr(ctxt, AMSUBW) 2064 o2 |= o1 & (1 << 31) /* same size */ 2065 o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31) 2066 2067 case 17: /* op Rm,[Rn],Rd; default Rn=ZR */ 2068 o1 = oprrr(ctxt, int(p.As)) 2069 2070 rf := int(p.From.Reg) 2071 rt := int(p.To.Reg) 2072 r := int(p.Reg) 2073 if p.To.Type == obj.TYPE_NONE { 2074 rt = REGZERO 2075 } 2076 if r == 0 { 2077 r = REGZERO 2078 } 2079 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 2080 2081 case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */ 2082 o1 = oprrr(ctxt, int(p.As)) 2083 2084 cond := int(p.From.Reg) 2085 r := int(p.Reg) 2086 var rf int 2087 if r != 0 { 2088 if p.From3Type() == obj.TYPE_NONE { 2089 /* CINC/CINV/CNEG */ 2090 rf = r 2091 2092 cond ^= 1 2093 } else { 2094 rf = int(p.From3.Reg) /* CSEL */ 2095 } 2096 } else { 2097 /* CSET */ 2098 if p.From3Type() != obj.TYPE_NONE { 2099 ctxt.Diag("invalid combination\n%v", p) 2100 } 2101 rf = REGZERO 2102 r = rf 2103 cond ^= 1 2104 } 2105 2106 rt := int(p.To.Reg) 2107 o1 |= (uint32(rf&31) << 16) | (uint32(cond&31) << 12) | (uint32(r&31) << 5) | uint32(rt&31) 2108 2109 case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */ 2110 nzcv := int(p.To.Offset) 2111 2112 cond := int(p.From.Reg) 2113 var rf int 2114 if p.From3.Type == obj.TYPE_REG { 2115 o1 = oprrr(ctxt, int(p.As)) 2116 rf = int(p.From3.Reg) /* Rm */ 2117 } else { 2118 o1 = opirr(ctxt, int(p.As)) 2119 rf = int(p.From3.Offset & 0x1F) 2120 } 2121 2122 o1 |= (uint32(rf&31) << 16) | (uint32(cond) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv) 2123 2124 case 20: /* movT R,O(R) -> strT */ 2125 v := int32(regoff(ctxt, &p.To)) 2126 2127 r := int(p.To.Reg) 2128 if r == 0 { 2129 r = int(o.param) 2130 } 2131 if v < 0 { /* unscaled 9-bit signed */ 2132 o1 = olsr9s(ctxt, int32(opstr9(ctxt, int(p.As))), v, r, int(p.From.Reg)) 2133 } else { 2134 v = int32(offsetshift(ctxt, int64(v), int(o.a3))) 2135 o1 = olsr12u(ctxt, int32(opstr12(ctxt, int(p.As))), v, r, int(p.From.Reg)) 2136 } 2137 2138 case 21: /* movT O(R),R -> ldrT */ 2139 v := int32(regoff(ctxt, &p.From)) 2140 2141 r := int(p.From.Reg) 2142 if r == 0 { 2143 r = int(o.param) 2144 } 2145 if v < 0 { /* unscaled 9-bit signed */ 2146 o1 = olsr9s(ctxt, int32(opldr9(ctxt, int(p.As))), v, r, int(p.To.Reg)) 2147 } else { 2148 v = int32(offsetshift(ctxt, int64(v), int(o.a1))) 2149 2150 //print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1); 2151 o1 = olsr12u(ctxt, int32(opldr12(ctxt, int(p.As))), v, r, int(p.To.Reg)) 2152 } 2153 2154 case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */ 2155 v := int32(p.From.Offset) 2156 2157 if v < -256 || v > 255 { 2158 ctxt.Diag("offset out of range\n%v", p) 2159 } 2160 o1 = opldrpp(ctxt, int(p.As)) 2161 if o.scond == C_XPOST { 2162 o1 |= 1 << 10 2163 } else { 2164 o1 |= 3 << 10 2165 } 2166 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31) 2167 2168 case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */ 2169 v := int32(p.To.Offset) 2170 2171 if v < -256 || v > 255 { 2172 ctxt.Diag("offset out of range\n%v", p) 2173 } 2174 o1 = LD2STR(opldrpp(ctxt, int(p.As))) 2175 if o.scond == C_XPOST { 2176 o1 |= 1 << 10 2177 } else { 2178 o1 |= 3 << 10 2179 } 2180 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31) 2181 2182 case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */ 2183 rf := int(p.From.Reg) 2184 rt := int(p.To.Reg) 2185 s := rf == REGSP || rt == REGSP 2186 if p.As == AMVN || p.As == AMVNW { 2187 if s { 2188 ctxt.Diag("illegal SP reference\n%v", p) 2189 } 2190 o1 = oprrr(ctxt, int(p.As)) 2191 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 2192 } else if s { 2193 o1 = opirr(ctxt, int(p.As)) 2194 o1 |= (uint32(rf&31) << 5) | uint32(rt&31) 2195 } else { 2196 o1 = oprrr(ctxt, int(p.As)) 2197 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 2198 } 2199 2200 case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */ 2201 o1 = oprrr(ctxt, int(p.As)) 2202 2203 rf := int(p.From.Reg) 2204 rt := int(p.To.Reg) 2205 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 2206 2207 case 26: /* negX Rm<<s, Rd -> subX Rm<<s, ZR, Rd */ 2208 o1 = oprrr(ctxt, int(p.As)) 2209 2210 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 2211 rt := int(p.To.Reg) 2212 o1 |= (REGZERO & 31 << 5) | uint32(rt&31) 2213 2214 case 27: /* op Rm<<n[,Rn],Rd (extended register) */ 2215 o1 = opxrrr(ctxt, int(p.As)) 2216 2217 if (p.From.Reg-obj.RBaseARM64)®_EXT != 0 { 2218 ctxt.Diag("extended register not implemented\n%v", p) 2219 // o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ 2220 } else { 2221 o1 |= uint32(p.From.Reg&31) << 16 2222 } 2223 rt := int(p.To.Reg) 2224 if p.To.Type == obj.TYPE_NONE { 2225 rt = REGZERO 2226 } 2227 r := int(p.Reg) 2228 if r == 0 { 2229 r = rt 2230 } 2231 o1 |= (uint32(r&31) << 5) | uint32(rt&31) 2232 2233 case 28: /* logop $vcon, [R], R (64 bit literal) */ 2234 o1 = omovlit(ctxt, AMOVD, p, &p.From, REGTMP) 2235 2236 if !(o1 != 0) { 2237 break 2238 } 2239 r := int(p.Reg) 2240 if r == 0 { 2241 r = int(p.To.Reg) 2242 } 2243 o2 = oprrr(ctxt, int(p.As)) 2244 o2 |= REGTMP & 31 << 16 /* shift is 0 */ 2245 o2 |= uint32(r&31) << 5 2246 o2 |= uint32(p.To.Reg & 31) 2247 2248 case 29: /* op Rn, Rd */ 2249 o1 = oprrr(ctxt, int(p.As)) 2250 2251 o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31) 2252 2253 case 30: /* movT R,L(R) -> strT */ 2254 s := movesize(int(o.as)) 2255 2256 if s < 0 { 2257 ctxt.Diag("unexpected long move, op %v tab %v\n%v", obj.Aconv(int(p.As)), obj.Aconv(int(o.as)), p) 2258 } 2259 v := int32(regoff(ctxt, &p.To)) 2260 if v < 0 { 2261 ctxt.Diag("negative large offset\n%v", p) 2262 } 2263 if (v & ((1 << uint(s)) - 1)) != 0 { 2264 ctxt.Diag("misaligned offset\n%v", p) 2265 } 2266 hi := v - (v & (0xFFF << uint(s))) 2267 if (hi & 0xFFF) != 0 { 2268 ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p) 2269 } 2270 2271 //fprint(2, "v=%ld (%#lux) s=%d hi=%ld (%#lux) v'=%ld (%#lux)\n", v, v, s, hi, hi, ((v-hi)>>s)&0xFFF, ((v-hi)>>s)&0xFFF); 2272 r := int(p.To.Reg) 2273 2274 if r == 0 { 2275 r = int(o.param) 2276 } 2277 o1 = oaddi(ctxt, int32(opirr(ctxt, AADD)), hi, r, REGTMP) 2278 o2 = olsr12u(ctxt, int32(opstr12(ctxt, int(p.As))), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg)) 2279 2280 case 31: /* movT L(R), R -> ldrT */ 2281 s := movesize(int(o.as)) 2282 2283 if s < 0 { 2284 ctxt.Diag("unexpected long move, op %v tab %v\n%v", obj.Aconv(int(p.As)), obj.Aconv(int(o.as)), p) 2285 } 2286 v := int32(regoff(ctxt, &p.From)) 2287 if v < 0 { 2288 ctxt.Diag("negative large offset\n%v", p) 2289 } 2290 if (v & ((1 << uint(s)) - 1)) != 0 { 2291 ctxt.Diag("misaligned offset\n%v", p) 2292 } 2293 hi := v - (v & (0xFFF << uint(s))) 2294 if (hi & 0xFFF) != 0 { 2295 ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p) 2296 } 2297 2298 //fprint(2, "v=%ld (%#lux) s=%d hi=%ld (%#lux) v'=%ld (%#lux)\n", v, v, s, hi, hi, ((v-hi)>>s)&0xFFF, ((v-hi)>>s)&0xFFF); 2299 r := int(p.From.Reg) 2300 2301 if r == 0 { 2302 r = int(o.param) 2303 } 2304 o1 = oaddi(ctxt, int32(opirr(ctxt, AADD)), hi, r, REGTMP) 2305 o2 = olsr12u(ctxt, int32(opldr12(ctxt, int(p.As))), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg)) 2306 2307 case 32: /* mov $con, R -> movz/movn */ 2308 r := 32 2309 2310 if p.As == AMOVD { 2311 r = 64 2312 } 2313 d := p.From.Offset 2314 s := movcon(d) 2315 if s < 0 || s >= r { 2316 d = ^d 2317 s = movcon(d) 2318 if s < 0 || s >= r { 2319 ctxt.Diag("impossible move wide: %#x\n%v", uint64(p.From.Offset), p) 2320 } 2321 if p.As == AMOVD { 2322 o1 = opirr(ctxt, AMOVN) 2323 } else { 2324 o1 = opirr(ctxt, AMOVNW) 2325 } 2326 } else { 2327 if p.As == AMOVD { 2328 o1 = opirr(ctxt, AMOVZ) 2329 } else { 2330 o1 = opirr(ctxt, AMOVZW) 2331 } 2332 } 2333 2334 rt := int(p.To.Reg) 2335 o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31)) 2336 2337 case 33: /* movk $uimm16 << pos */ 2338 o1 = opirr(ctxt, int(p.As)) 2339 2340 d := p.From.Offset 2341 if (d >> 16) != 0 { 2342 ctxt.Diag("requires uimm16\n%v", p) 2343 } 2344 s := 0 2345 if p.From3Type() != obj.TYPE_NONE { 2346 if p.From3.Type != obj.TYPE_CONST { 2347 ctxt.Diag("missing bit position\n%v", p) 2348 } 2349 s = int(p.From3.Offset / 16) 2350 if (s*16&0xF) != 0 || s >= 4 || (o1&S64) == 0 && s >= 2 { 2351 ctxt.Diag("illegal bit position\n%v", p) 2352 } 2353 } 2354 2355 rt := int(p.To.Reg) 2356 o1 |= uint32(((d & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31)) 2357 2358 case 34: /* mov $lacon,R */ 2359 o1 = omovlit(ctxt, AMOVD, p, &p.From, REGTMP) 2360 2361 if !(o1 != 0) { 2362 break 2363 } 2364 o2 = opxrrr(ctxt, AADD) 2365 o2 |= REGTMP & 31 << 16 2366 o2 |= LSL0_64 2367 r := int(p.From.Reg) 2368 if r == 0 { 2369 r = int(o.param) 2370 } 2371 o2 |= uint32(r&31) << 5 2372 o2 |= uint32(p.To.Reg & 31) 2373 2374 case 35: /* mov SPR,R -> mrs */ 2375 o1 = oprrr(ctxt, AMRS) 2376 2377 v := int32(p.From.Offset) 2378 if (o1 & uint32(v&^(3<<19))) != 0 { 2379 ctxt.Diag("MRS register value overlap\n%v", p) 2380 } 2381 o1 |= uint32(v) 2382 o1 |= uint32(p.To.Reg & 31) 2383 2384 case 36: /* mov R,SPR */ 2385 o1 = oprrr(ctxt, AMSR) 2386 2387 v := int32(p.To.Offset) 2388 if (o1 & uint32(v&^(3<<19))) != 0 { 2389 ctxt.Diag("MSR register value overlap\n%v", p) 2390 } 2391 o1 |= uint32(v) 2392 o1 |= uint32(p.From.Reg & 31) 2393 2394 case 37: /* mov $con,PSTATEfield -> MSR [immediate] */ 2395 if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 { 2396 ctxt.Diag("illegal immediate for PSTATE field\n%v", p) 2397 } 2398 o1 = opirr(ctxt, AMSR) 2399 o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */ 2400 v := int32(0) 2401 for i := 0; i < len(pstatefield); i++ { 2402 if int64(pstatefield[i].a) == p.To.Offset { 2403 v = int32(pstatefield[i].b) 2404 break 2405 } 2406 } 2407 2408 if v == 0 { 2409 ctxt.Diag("illegal PSTATE field for immediate move\n%v", p) 2410 } 2411 o1 |= uint32(v) 2412 2413 case 38: /* clrex [$imm] */ 2414 o1 = opimm(ctxt, int(p.As)) 2415 2416 if p.To.Type == obj.TYPE_NONE { 2417 o1 |= 0xF << 8 2418 } else { 2419 o1 |= uint32((p.To.Offset & 0xF) << 8) 2420 } 2421 2422 case 39: /* cbz R, rel */ 2423 o1 = opirr(ctxt, int(p.As)) 2424 2425 o1 |= uint32(p.From.Reg & 31) 2426 o1 |= uint32(brdist(ctxt, p, 0, 19, 2) << 5) 2427 2428 case 40: /* tbz */ 2429 o1 = opirr(ctxt, int(p.As)) 2430 2431 v := int32(p.From.Offset) 2432 if v < 0 || v > 63 { 2433 ctxt.Diag("illegal bit number\n%v", p) 2434 } 2435 o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19) 2436 o1 |= uint32(brdist(ctxt, p, 0, 14, 2) << 5) 2437 o1 |= uint32(p.Reg) 2438 2439 case 41: /* eret, nop, others with no operands */ 2440 o1 = op0(ctxt, int(p.As)) 2441 2442 case 42: /* bfm R,r,s,R */ 2443 o1 = opbfm(ctxt, int(p.As), int(p.From.Offset), int(p.From3.Offset), int(p.Reg), int(p.To.Reg)) 2444 2445 case 43: /* bfm aliases */ 2446 r := int(p.From.Offset) 2447 2448 s := int(p.From3.Offset) 2449 rf := int(p.Reg) 2450 rt := int(p.To.Reg) 2451 if rf == 0 { 2452 rf = rt 2453 } 2454 switch p.As { 2455 case ABFI: 2456 o1 = opbfm(ctxt, ABFM, 64-r, s-1, rf, rt) 2457 2458 case ABFIW: 2459 o1 = opbfm(ctxt, ABFMW, 32-r, s-1, rf, rt) 2460 2461 case ABFXIL: 2462 o1 = opbfm(ctxt, ABFM, r, r+s-1, rf, rt) 2463 2464 case ABFXILW: 2465 o1 = opbfm(ctxt, ABFMW, r, r+s-1, rf, rt) 2466 2467 case ASBFIZ: 2468 o1 = opbfm(ctxt, ASBFM, 64-r, s-1, rf, rt) 2469 2470 case ASBFIZW: 2471 o1 = opbfm(ctxt, ASBFMW, 32-r, s-1, rf, rt) 2472 2473 case ASBFX: 2474 o1 = opbfm(ctxt, ASBFM, r, r+s-1, rf, rt) 2475 2476 case ASBFXW: 2477 o1 = opbfm(ctxt, ASBFMW, r, r+s-1, rf, rt) 2478 2479 case AUBFIZ: 2480 o1 = opbfm(ctxt, AUBFM, 64-r, s-1, rf, rt) 2481 2482 case AUBFIZW: 2483 o1 = opbfm(ctxt, AUBFMW, 32-r, s-1, rf, rt) 2484 2485 case AUBFX: 2486 o1 = opbfm(ctxt, AUBFM, r, r+s-1, rf, rt) 2487 2488 case AUBFXW: 2489 o1 = opbfm(ctxt, AUBFMW, r, r+s-1, rf, rt) 2490 2491 default: 2492 ctxt.Diag("bad bfm alias\n%v", ctxt.Curp) 2493 break 2494 } 2495 2496 case 44: /* extr $b, Rn, Rm, Rd */ 2497 o1 = opextr(ctxt, int(p.As), int32(p.From.Offset), int(p.From3.Reg), int(p.Reg), int(p.To.Reg)) 2498 2499 case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */ 2500 rf := int(p.From.Reg) 2501 2502 rt := int(p.To.Reg) 2503 as := int(p.As) 2504 if rf == REGZERO { 2505 as = AMOVWU /* clearer in disassembly */ 2506 } 2507 switch as { 2508 case AMOVB, ASXTB: 2509 o1 = opbfm(ctxt, ASBFM, 0, 7, rf, rt) 2510 2511 case AMOVH, ASXTH: 2512 o1 = opbfm(ctxt, ASBFM, 0, 15, rf, rt) 2513 2514 case AMOVW, ASXTW: 2515 o1 = opbfm(ctxt, ASBFM, 0, 31, rf, rt) 2516 2517 case AMOVBU, AUXTB: 2518 o1 = opbfm(ctxt, AUBFM, 0, 7, rf, rt) 2519 2520 case AMOVHU, AUXTH: 2521 o1 = opbfm(ctxt, AUBFM, 0, 15, rf, rt) 2522 2523 case AMOVWU: 2524 o1 = oprrr(ctxt, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) 2525 2526 case AUXTW: 2527 o1 = opbfm(ctxt, AUBFM, 0, 31, rf, rt) 2528 2529 case ASXTBW: 2530 o1 = opbfm(ctxt, ASBFMW, 0, 7, rf, rt) 2531 2532 case ASXTHW: 2533 o1 = opbfm(ctxt, ASBFMW, 0, 15, rf, rt) 2534 2535 case AUXTBW: 2536 o1 = opbfm(ctxt, AUBFMW, 0, 7, rf, rt) 2537 2538 case AUXTHW: 2539 o1 = opbfm(ctxt, AUBFMW, 0, 15, rf, rt) 2540 2541 default: 2542 ctxt.Diag("bad sxt %v", obj.Aconv(as)) 2543 break 2544 } 2545 2546 case 46: /* cls */ 2547 o1 = opbit(ctxt, int(p.As)) 2548 2549 o1 |= uint32(p.From.Reg&31) << 5 2550 o1 |= uint32(p.To.Reg & 31) 2551 2552 case 47: /* movT R,V(R) -> strT (huge offset) */ 2553 o1 = omovlit(ctxt, AMOVW, p, &p.To, REGTMP) 2554 2555 if !(o1 != 0) { 2556 break 2557 } 2558 r := int(p.To.Reg) 2559 if r == 0 { 2560 r = int(o.param) 2561 } 2562 o2 = olsxrr(ctxt, int(p.As), REGTMP, r, int(p.From.Reg)) 2563 2564 case 48: /* movT V(R), R -> ldrT (huge offset) */ 2565 o1 = omovlit(ctxt, AMOVW, p, &p.From, REGTMP) 2566 2567 if !(o1 != 0) { 2568 break 2569 } 2570 r := int(p.From.Reg) 2571 if r == 0 { 2572 r = int(o.param) 2573 } 2574 o2 = olsxrr(ctxt, int(p.As), REGTMP, r, int(p.To.Reg)) 2575 2576 case 50: /* sys/sysl */ 2577 o1 = opirr(ctxt, int(p.As)) 2578 2579 if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 { 2580 ctxt.Diag("illegal SYS argument\n%v", p) 2581 } 2582 o1 |= uint32(p.From.Offset) 2583 if p.To.Type == obj.TYPE_REG { 2584 o1 |= uint32(p.To.Reg & 31) 2585 } else if p.Reg != 0 { 2586 o1 |= uint32(p.Reg & 31) 2587 } else { 2588 o1 |= 0x1F 2589 } 2590 2591 case 51: /* dmb */ 2592 o1 = opirr(ctxt, int(p.As)) 2593 2594 if p.From.Type == obj.TYPE_CONST { 2595 o1 |= uint32((p.From.Offset & 0xF) << 8) 2596 } 2597 2598 case 52: /* hint */ 2599 o1 = opirr(ctxt, int(p.As)) 2600 2601 o1 |= uint32((p.From.Offset & 0x7F) << 5) 2602 2603 case 53: /* and/or/eor/bic/... $bimmN, Rn, Rd -> op (N,r,s), Rn, Rd */ 2604 ctxt.Diag("bitmask immediate not implemented\n%v", p) 2605 2606 case 54: /* floating point arith */ 2607 o1 = oprrr(ctxt, int(p.As)) 2608 2609 var rf int 2610 if p.From.Type == obj.TYPE_CONST { 2611 rf = chipfloat7(ctxt, p.From.Val.(float64)) 2612 if rf < 0 || true { 2613 ctxt.Diag("invalid floating-point immediate\n%v", p) 2614 rf = 0 2615 } 2616 2617 rf |= (1 << 3) 2618 } else { 2619 rf = int(p.From.Reg) 2620 } 2621 rt := int(p.To.Reg) 2622 r := int(p.Reg) 2623 if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */ 2624 r = rf 2625 rf = 0 2626 } else if r == 0 { 2627 r = rt 2628 } 2629 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) 2630 2631 case 56: /* floating point compare */ 2632 o1 = oprrr(ctxt, int(p.As)) 2633 2634 var rf int 2635 if p.From.Type == obj.TYPE_CONST { 2636 o1 |= 8 /* zero */ 2637 rf = 0 2638 } else { 2639 rf = int(p.From.Reg) 2640 } 2641 rt := int(p.Reg) 2642 o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5 2643 2644 case 57: /* floating point conditional compare */ 2645 o1 = oprrr(ctxt, int(p.As)) 2646 2647 cond := int(p.From.Reg) 2648 nzcv := int(p.To.Offset) 2649 if nzcv&^0xF != 0 { 2650 ctxt.Diag("implausible condition\n%v", p) 2651 } 2652 rf := int(p.Reg) 2653 if p.From3 == nil || p.From3.Reg < REG_F0 || p.From3.Reg > REG_F31 { 2654 ctxt.Diag("illegal FCCMP\n%v", p) 2655 break 2656 } 2657 rt := int(p.From3.Reg) 2658 o1 |= uint32(rf&31)<<16 | uint32(cond)<<12 | uint32(rt&31)<<5 | uint32(nzcv) 2659 2660 case 58: /* ldar/ldxr/ldaxr */ 2661 o1 = opload(ctxt, int(p.As)) 2662 2663 o1 |= 0x1F << 16 2664 o1 |= uint32(p.From.Reg) << 5 2665 if p.Reg != 0 { 2666 o1 |= uint32(p.Reg) << 10 2667 } else { 2668 o1 |= 0x1F << 10 2669 } 2670 o1 |= uint32(p.To.Reg & 31) 2671 2672 case 59: /* stxr/stlxr */ 2673 o1 = opstore(ctxt, int(p.As)) 2674 2675 if p.RegTo2 != obj.REG_NONE { 2676 o1 |= uint32(p.RegTo2&31) << 16 2677 } else { 2678 o1 |= 0x1F << 16 2679 } 2680 2681 // TODO(aram): add support for STXP 2682 o1 |= uint32(p.To.Reg&31) << 5 2683 2684 o1 |= uint32(p.From.Reg & 31) 2685 2686 case 60: /* adrp label,r */ 2687 d := brdist(ctxt, p, 12, 21, 0) 2688 2689 o1 = ADR(1, uint32(d), uint32(p.To.Reg)) 2690 2691 case 61: /* adr label, r */ 2692 d := brdist(ctxt, p, 0, 21, 0) 2693 2694 o1 = ADR(0, uint32(d), uint32(p.To.Reg)) 2695 2696 /* reloc ops */ 2697 case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */ 2698 o1 = ADR(1, 0, REGTMP) 2699 o2 = opirr(ctxt, AADD) | REGTMP&31<<5 | REGTMP&31 2700 rel := obj.Addrel(ctxt.Cursym) 2701 rel.Off = int32(ctxt.Pc) 2702 rel.Siz = 8 2703 rel.Sym = p.To.Sym 2704 rel.Add = p.To.Offset 2705 rel.Type = obj.R_ADDRARM64 2706 o3 = olsr12u(ctxt, int32(opstr12(ctxt, int(p.As))), 0, REGTMP, int(p.From.Reg)) 2707 2708 case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */ 2709 o1 = ADR(1, 0, REGTMP) 2710 o2 = opirr(ctxt, AADD) | REGTMP&31<<5 | REGTMP&31 2711 rel := obj.Addrel(ctxt.Cursym) 2712 rel.Off = int32(ctxt.Pc) 2713 rel.Siz = 8 2714 rel.Sym = p.From.Sym 2715 rel.Add = p.From.Offset 2716 rel.Type = obj.R_ADDRARM64 2717 o3 = olsr12u(ctxt, int32(opldr12(ctxt, int(p.As))), 0, REGTMP, int(p.To.Reg)) 2718 2719 case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */ 2720 v := int32(p.From.Offset) 2721 2722 if v < -512 || v > 504 { 2723 ctxt.Diag("offset out of range\n%v", p) 2724 } 2725 if o.scond == C_XPOST { 2726 o1 |= 1 << 23 2727 } else { 2728 o1 |= 3 << 23 2729 } 2730 o1 |= 1 << 22 2731 o1 |= uint32(int64(2<<30|5<<27|((uint32(v)/8)&0x7f)<<15) | p.To.Offset<<10 | int64(uint32(p.From.Reg&31)<<5) | int64(p.To.Reg&31)) 2732 2733 case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */ 2734 v := int32(p.To.Offset) 2735 2736 if v < -512 || v > 504 { 2737 ctxt.Diag("offset out of range\n%v", p) 2738 } 2739 if o.scond == C_XPOST { 2740 o1 |= 1 << 23 2741 } else { 2742 o1 |= 3 << 23 2743 } 2744 o1 |= uint32(int64(2<<30|5<<27|((uint32(v)/8)&0x7f)<<15) | p.From.Offset<<10 | int64(uint32(p.To.Reg&31)<<5) | int64(p.From.Reg&31)) 2745 2746 case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */ 2747 if p.As == AMOVW { 2748 ctxt.Diag("invalid load of 32-bit address: %v", p) 2749 } 2750 o1 = ADR(1, 0, uint32(p.To.Reg)) 2751 o2 = opirr(ctxt, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31) 2752 rel := obj.Addrel(ctxt.Cursym) 2753 rel.Off = int32(ctxt.Pc) 2754 rel.Siz = 8 2755 rel.Sym = p.From.Sym 2756 rel.Add = p.From.Offset 2757 rel.Type = obj.R_ADDRARM64 2758 2759 // This is supposed to be something that stops execution. 2760 // It's not supposed to be reached, ever, but if it is, we'd 2761 // like to be able to tell how we got there. Assemble as 2762 // 0xbea71700 which is guaranteed to raise undefined instruction 2763 // exception. 2764 case 90: 2765 o1 = 0xbea71700 2766 2767 break 2768 } 2769 2770 out[0] = o1 2771 out[1] = o2 2772 out[2] = o3 2773 out[3] = o4 2774 out[4] = o5 2775 return 2776 } 2777 2778 /* 2779 * basic Rm op Rn -> Rd (using shifted register with 0) 2780 * also op Rn -> Rt 2781 * also Rm*Rn op Ra -> Rd 2782 */ 2783 func oprrr(ctxt *obj.Link, a int) uint32 { 2784 switch a { 2785 case AADC: 2786 return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 2787 2788 case AADCW: 2789 return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 2790 2791 case AADCS: 2792 return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 2793 2794 case AADCSW: 2795 return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10 2796 2797 case ANGC, ASBC: 2798 return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 2799 2800 case ANGCS, ASBCS: 2801 return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 2802 2803 case ANGCW, ASBCW: 2804 return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10 2805 2806 case ANGCSW, ASBCSW: 2807 return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10 2808 2809 case AADD: 2810 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 2811 2812 case AADDW: 2813 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 2814 2815 case ACMN, AADDS: 2816 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 2817 2818 case ACMNW, AADDSW: 2819 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 2820 2821 case ASUB: 2822 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 2823 2824 case ASUBW: 2825 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 2826 2827 case ACMP, ASUBS: 2828 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 2829 2830 case ACMPW, ASUBSW: 2831 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10 2832 2833 case AAND: 2834 return S64 | 0<<29 | 0xA<<24 2835 2836 case AANDW: 2837 return S32 | 0<<29 | 0xA<<24 2838 2839 case AMOVD, AORR: 2840 return S64 | 1<<29 | 0xA<<24 2841 2842 // case AMOVW: 2843 case AMOVWU, AORRW: 2844 return S32 | 1<<29 | 0xA<<24 2845 2846 case AEOR: 2847 return S64 | 2<<29 | 0xA<<24 2848 2849 case AEORW: 2850 return S32 | 2<<29 | 0xA<<24 2851 2852 case AANDS: 2853 return S64 | 3<<29 | 0xA<<24 2854 2855 case AANDSW: 2856 return S32 | 3<<29 | 0xA<<24 2857 2858 case ABIC: 2859 return S64 | 0<<29 | 0xA<<24 | 1<<21 2860 2861 case ABICW: 2862 return S32 | 0<<29 | 0xA<<24 | 1<<21 2863 2864 case ABICS: 2865 return S64 | 3<<29 | 0xA<<24 | 1<<21 2866 2867 case ABICSW: 2868 return S32 | 3<<29 | 0xA<<24 | 1<<21 2869 2870 case AEON: 2871 return S64 | 2<<29 | 0xA<<24 | 1<<21 2872 2873 case AEONW: 2874 return S32 | 2<<29 | 0xA<<24 | 1<<21 2875 2876 case AMVN, AORN: 2877 return S64 | 1<<29 | 0xA<<24 | 1<<21 2878 2879 case AMVNW, AORNW: 2880 return S32 | 1<<29 | 0xA<<24 | 1<<21 2881 2882 case AASR: 2883 return S64 | OPDP2(10) /* also ASRV */ 2884 2885 case AASRW: 2886 return S32 | OPDP2(10) 2887 2888 case ALSL: 2889 return S64 | OPDP2(8) 2890 2891 case ALSLW: 2892 return S32 | OPDP2(8) 2893 2894 case ALSR: 2895 return S64 | OPDP2(9) 2896 2897 case ALSRW: 2898 return S32 | OPDP2(9) 2899 2900 case AROR: 2901 return S64 | OPDP2(11) 2902 2903 case ARORW: 2904 return S32 | OPDP2(11) 2905 2906 case ACCMN: 2907 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */ 2908 2909 case ACCMNW: 2910 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 2911 2912 case ACCMP: 2913 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 2914 2915 case ACCMPW: 2916 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 2917 2918 case ACRC32B: 2919 return S32 | OPDP2(16) 2920 2921 case ACRC32H: 2922 return S32 | OPDP2(17) 2923 2924 case ACRC32W: 2925 return S32 | OPDP2(18) 2926 2927 case ACRC32X: 2928 return S64 | OPDP2(19) 2929 2930 case ACRC32CB: 2931 return S32 | OPDP2(20) 2932 2933 case ACRC32CH: 2934 return S32 | OPDP2(21) 2935 2936 case ACRC32CW: 2937 return S32 | OPDP2(22) 2938 2939 case ACRC32CX: 2940 return S64 | OPDP2(23) 2941 2942 case ACSEL: 2943 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 2944 2945 case ACSELW: 2946 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 2947 2948 case ACSET: 2949 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 2950 2951 case ACSETW: 2952 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 2953 2954 case ACSETM: 2955 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 2956 2957 case ACSETMW: 2958 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 2959 2960 case ACINC, ACSINC: 2961 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 2962 2963 case ACINCW, ACSINCW: 2964 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 2965 2966 case ACINV, ACSINV: 2967 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 2968 2969 case ACINVW, ACSINVW: 2970 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10 2971 2972 case ACNEG, ACSNEG: 2973 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 2974 2975 case ACNEGW, ACSNEGW: 2976 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10 2977 2978 case AMUL, AMADD: 2979 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 2980 2981 case AMULW, AMADDW: 2982 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15 2983 2984 case AMNEG, AMSUB: 2985 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 2986 2987 case AMNEGW, AMSUBW: 2988 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15 2989 2990 case AMRS: 2991 return SYSOP(1, 2, 0, 0, 0, 0, 0) 2992 2993 case AMSR: 2994 return SYSOP(0, 2, 0, 0, 0, 0, 0) 2995 2996 case ANEG: 2997 return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 2998 2999 case ANEGW: 3000 return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21 3001 3002 case ANEGS: 3003 return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 3004 3005 case ANEGSW: 3006 return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21 3007 3008 case AREM, ASDIV: 3009 return S64 | OPDP2(3) 3010 3011 case AREMW, ASDIVW: 3012 return S32 | OPDP2(3) 3013 3014 case ASMULL, ASMADDL: 3015 return OPDP3(1, 0, 1, 0) 3016 3017 case ASMNEGL, ASMSUBL: 3018 return OPDP3(1, 0, 1, 1) 3019 3020 case ASMULH: 3021 return OPDP3(1, 0, 2, 0) 3022 3023 case AUMULL, AUMADDL: 3024 return OPDP3(1, 0, 5, 0) 3025 3026 case AUMNEGL, AUMSUBL: 3027 return OPDP3(1, 0, 5, 1) 3028 3029 case AUMULH: 3030 return OPDP3(1, 0, 6, 0) 3031 3032 case AUREM, AUDIV: 3033 return S64 | OPDP2(2) 3034 3035 case AUREMW, AUDIVW: 3036 return S32 | OPDP2(2) 3037 3038 case AAESE: 3039 return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10 3040 3041 case AAESD: 3042 return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10 3043 3044 case AAESMC: 3045 return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10 3046 3047 case AAESIMC: 3048 return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10 3049 3050 case ASHA1C: 3051 return 0x5E<<24 | 0<<12 3052 3053 case ASHA1P: 3054 return 0x5E<<24 | 1<<12 3055 3056 case ASHA1M: 3057 return 0x5E<<24 | 2<<12 3058 3059 case ASHA1SU0: 3060 return 0x5E<<24 | 3<<12 3061 3062 case ASHA256H: 3063 return 0x5E<<24 | 4<<12 3064 3065 case ASHA256H2: 3066 return 0x5E<<24 | 5<<12 3067 3068 case ASHA256SU1: 3069 return 0x5E<<24 | 6<<12 3070 3071 case ASHA1H: 3072 return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10 3073 3074 case ASHA1SU1: 3075 return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10 3076 3077 case ASHA256SU0: 3078 return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10 3079 3080 case AFCVTZSD: 3081 return FPCVTI(1, 0, 1, 3, 0) 3082 3083 case AFCVTZSDW: 3084 return FPCVTI(0, 0, 1, 3, 0) 3085 3086 case AFCVTZSS: 3087 return FPCVTI(1, 0, 0, 3, 0) 3088 3089 case AFCVTZSSW: 3090 return FPCVTI(0, 0, 0, 3, 0) 3091 3092 case AFCVTZUD: 3093 return FPCVTI(1, 0, 1, 3, 1) 3094 3095 case AFCVTZUDW: 3096 return FPCVTI(0, 0, 1, 3, 1) 3097 3098 case AFCVTZUS: 3099 return FPCVTI(1, 0, 0, 3, 1) 3100 3101 case AFCVTZUSW: 3102 return FPCVTI(0, 0, 0, 3, 1) 3103 3104 case ASCVTFD: 3105 return FPCVTI(1, 0, 1, 0, 2) 3106 3107 case ASCVTFS: 3108 return FPCVTI(1, 0, 0, 0, 2) 3109 3110 case ASCVTFWD: 3111 return FPCVTI(0, 0, 1, 0, 2) 3112 3113 case ASCVTFWS: 3114 return FPCVTI(0, 0, 0, 0, 2) 3115 3116 case AUCVTFD: 3117 return FPCVTI(1, 0, 1, 0, 3) 3118 3119 case AUCVTFS: 3120 return FPCVTI(1, 0, 0, 0, 3) 3121 3122 case AUCVTFWD: 3123 return FPCVTI(0, 0, 1, 0, 3) 3124 3125 case AUCVTFWS: 3126 return FPCVTI(0, 0, 0, 0, 3) 3127 3128 case AFADDS: 3129 return FPOP2S(0, 0, 0, 2) 3130 3131 case AFADDD: 3132 return FPOP2S(0, 0, 1, 2) 3133 3134 case AFSUBS: 3135 return FPOP2S(0, 0, 0, 3) 3136 3137 case AFSUBD: 3138 return FPOP2S(0, 0, 1, 3) 3139 3140 case AFMULS: 3141 return FPOP2S(0, 0, 0, 0) 3142 3143 case AFMULD: 3144 return FPOP2S(0, 0, 1, 0) 3145 3146 case AFDIVS: 3147 return FPOP2S(0, 0, 0, 1) 3148 3149 case AFDIVD: 3150 return FPOP2S(0, 0, 1, 1) 3151 3152 case AFMAXS: 3153 return FPOP2S(0, 0, 0, 4) 3154 3155 case AFMINS: 3156 return FPOP2S(0, 0, 0, 5) 3157 3158 case AFMAXD: 3159 return FPOP2S(0, 0, 1, 4) 3160 3161 case AFMIND: 3162 return FPOP2S(0, 0, 1, 5) 3163 3164 case AFMAXNMS: 3165 return FPOP2S(0, 0, 0, 6) 3166 3167 case AFMAXNMD: 3168 return FPOP2S(0, 0, 1, 6) 3169 3170 case AFMINNMS: 3171 return FPOP2S(0, 0, 0, 7) 3172 3173 case AFMINNMD: 3174 return FPOP2S(0, 0, 1, 7) 3175 3176 case AFNMULS: 3177 return FPOP2S(0, 0, 0, 8) 3178 3179 case AFNMULD: 3180 return FPOP2S(0, 0, 1, 8) 3181 3182 case AFCMPS: 3183 return FPCMP(0, 0, 0, 0, 0) 3184 3185 case AFCMPD: 3186 return FPCMP(0, 0, 1, 0, 0) 3187 3188 case AFCMPES: 3189 return FPCMP(0, 0, 0, 0, 16) 3190 3191 case AFCMPED: 3192 return FPCMP(0, 0, 1, 0, 16) 3193 3194 case AFCCMPS: 3195 return FPCCMP(0, 0, 0, 0) 3196 3197 case AFCCMPD: 3198 return FPCCMP(0, 0, 1, 0) 3199 3200 case AFCCMPES: 3201 return FPCCMP(0, 0, 0, 1) 3202 3203 case AFCCMPED: 3204 return FPCCMP(0, 0, 1, 1) 3205 3206 case AFCSELS: 3207 return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10 3208 3209 case AFCSELD: 3210 return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10 3211 3212 case AFMOVS: 3213 return FPOP1S(0, 0, 0, 0) 3214 3215 case AFABSS: 3216 return FPOP1S(0, 0, 0, 1) 3217 3218 case AFNEGS: 3219 return FPOP1S(0, 0, 0, 2) 3220 3221 case AFSQRTS: 3222 return FPOP1S(0, 0, 0, 3) 3223 3224 case AFCVTSD: 3225 return FPOP1S(0, 0, 0, 5) 3226 3227 case AFCVTSH: 3228 return FPOP1S(0, 0, 0, 7) 3229 3230 case AFRINTNS: 3231 return FPOP1S(0, 0, 0, 8) 3232 3233 case AFRINTPS: 3234 return FPOP1S(0, 0, 0, 9) 3235 3236 case AFRINTMS: 3237 return FPOP1S(0, 0, 0, 10) 3238 3239 case AFRINTZS: 3240 return FPOP1S(0, 0, 0, 11) 3241 3242 case AFRINTAS: 3243 return FPOP1S(0, 0, 0, 12) 3244 3245 case AFRINTXS: 3246 return FPOP1S(0, 0, 0, 14) 3247 3248 case AFRINTIS: 3249 return FPOP1S(0, 0, 0, 15) 3250 3251 case AFMOVD: 3252 return FPOP1S(0, 0, 1, 0) 3253 3254 case AFABSD: 3255 return FPOP1S(0, 0, 1, 1) 3256 3257 case AFNEGD: 3258 return FPOP1S(0, 0, 1, 2) 3259 3260 case AFSQRTD: 3261 return FPOP1S(0, 0, 1, 3) 3262 3263 case AFCVTDS: 3264 return FPOP1S(0, 0, 1, 4) 3265 3266 case AFCVTDH: 3267 return FPOP1S(0, 0, 1, 7) 3268 3269 case AFRINTND: 3270 return FPOP1S(0, 0, 1, 8) 3271 3272 case AFRINTPD: 3273 return FPOP1S(0, 0, 1, 9) 3274 3275 case AFRINTMD: 3276 return FPOP1S(0, 0, 1, 10) 3277 3278 case AFRINTZD: 3279 return FPOP1S(0, 0, 1, 11) 3280 3281 case AFRINTAD: 3282 return FPOP1S(0, 0, 1, 12) 3283 3284 case AFRINTXD: 3285 return FPOP1S(0, 0, 1, 14) 3286 3287 case AFRINTID: 3288 return FPOP1S(0, 0, 1, 15) 3289 3290 case AFCVTHS: 3291 return FPOP1S(0, 0, 3, 4) 3292 3293 case AFCVTHD: 3294 return FPOP1S(0, 0, 3, 5) 3295 } 3296 3297 ctxt.Diag("bad rrr %d %v", a, obj.Aconv(a)) 3298 prasm(ctxt.Curp) 3299 return 0 3300 } 3301 3302 /* 3303 * imm -> Rd 3304 * imm op Rn -> Rd 3305 */ 3306 func opirr(ctxt *obj.Link, a int) uint32 { 3307 switch a { 3308 /* op $addcon, Rn, Rd */ 3309 case AMOVD, AADD: 3310 return S64 | 0<<30 | 0<<29 | 0x11<<24 3311 3312 case ACMN, AADDS: 3313 return S64 | 0<<30 | 1<<29 | 0x11<<24 3314 3315 case AMOVW, AADDW: 3316 return S32 | 0<<30 | 0<<29 | 0x11<<24 3317 3318 case ACMNW, AADDSW: 3319 return S32 | 0<<30 | 1<<29 | 0x11<<24 3320 3321 case ASUB: 3322 return S64 | 1<<30 | 0<<29 | 0x11<<24 3323 3324 case ACMP, ASUBS: 3325 return S64 | 1<<30 | 1<<29 | 0x11<<24 3326 3327 case ASUBW: 3328 return S32 | 1<<30 | 0<<29 | 0x11<<24 3329 3330 case ACMPW, ASUBSW: 3331 return S32 | 1<<30 | 1<<29 | 0x11<<24 3332 3333 /* op $imm(SB), Rd; op label, Rd */ 3334 case AADR: 3335 return 0<<31 | 0x10<<24 3336 3337 case AADRP: 3338 return 1<<31 | 0x10<<24 3339 3340 /* op $bimm, Rn, Rd */ 3341 case AAND: 3342 return S64 | 0<<29 | 0x24<<23 3343 3344 case AANDW: 3345 return S32 | 0<<29 | 0x24<<23 | 0<<22 3346 3347 case AORR: 3348 return S64 | 1<<29 | 0x24<<23 3349 3350 case AORRW: 3351 return S32 | 1<<29 | 0x24<<23 | 0<<22 3352 3353 case AEOR: 3354 return S64 | 2<<29 | 0x24<<23 3355 3356 case AEORW: 3357 return S32 | 2<<29 | 0x24<<23 | 0<<22 3358 3359 case AANDS: 3360 return S64 | 3<<29 | 0x24<<23 3361 3362 case AANDSW: 3363 return S32 | 3<<29 | 0x24<<23 | 0<<22 3364 3365 case AASR: 3366 return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */ 3367 3368 case AASRW: 3369 return S32 | 0<<29 | 0x26<<23 | 0<<22 3370 3371 /* op $width, $lsb, Rn, Rd */ 3372 case ABFI: 3373 return S64 | 2<<29 | 0x26<<23 | 1<<22 3374 /* alias of BFM */ 3375 3376 case ABFIW: 3377 return S32 | 2<<29 | 0x26<<23 | 0<<22 3378 3379 /* op $imms, $immr, Rn, Rd */ 3380 case ABFM: 3381 return S64 | 1<<29 | 0x26<<23 | 1<<22 3382 3383 case ABFMW: 3384 return S32 | 1<<29 | 0x26<<23 | 0<<22 3385 3386 case ASBFM: 3387 return S64 | 0<<29 | 0x26<<23 | 1<<22 3388 3389 case ASBFMW: 3390 return S32 | 0<<29 | 0x26<<23 | 0<<22 3391 3392 case AUBFM: 3393 return S64 | 2<<29 | 0x26<<23 | 1<<22 3394 3395 case AUBFMW: 3396 return S32 | 2<<29 | 0x26<<23 | 0<<22 3397 3398 case ABFXIL: 3399 return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */ 3400 3401 case ABFXILW: 3402 return S32 | 1<<29 | 0x26<<23 | 0<<22 3403 3404 case AEXTR: 3405 return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21 3406 3407 case AEXTRW: 3408 return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21 3409 3410 case ACBNZ: 3411 return S64 | 0x1A<<25 | 1<<24 3412 3413 case ACBNZW: 3414 return S32 | 0x1A<<25 | 1<<24 3415 3416 case ACBZ: 3417 return S64 | 0x1A<<25 | 0<<24 3418 3419 case ACBZW: 3420 return S32 | 0x1A<<25 | 0<<24 3421 3422 case ACCMN: 3423 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 3424 3425 case ACCMNW: 3426 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 3427 3428 case ACCMP: 3429 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */ 3430 3431 case ACCMPW: 3432 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 3433 3434 case AMOVK: 3435 return S64 | 3<<29 | 0x25<<23 3436 3437 case AMOVKW: 3438 return S32 | 3<<29 | 0x25<<23 3439 3440 case AMOVN: 3441 return S64 | 0<<29 | 0x25<<23 3442 3443 case AMOVNW: 3444 return S32 | 0<<29 | 0x25<<23 3445 3446 case AMOVZ: 3447 return S64 | 2<<29 | 0x25<<23 3448 3449 case AMOVZW: 3450 return S32 | 2<<29 | 0x25<<23 3451 3452 case AMSR: 3453 return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */ 3454 3455 case AAT, 3456 ADC, 3457 AIC, 3458 ATLBI, 3459 ASYS: 3460 return SYSOP(0, 1, 0, 0, 0, 0, 0) 3461 3462 case ASYSL: 3463 return SYSOP(1, 1, 0, 0, 0, 0, 0) 3464 3465 case ATBZ: 3466 return 0x36 << 24 3467 3468 case ATBNZ: 3469 return 0x37 << 24 3470 3471 case ADSB: 3472 return SYSOP(0, 0, 3, 3, 0, 4, 0x1F) 3473 3474 case ADMB: 3475 return SYSOP(0, 0, 3, 3, 0, 5, 0x1F) 3476 3477 case AISB: 3478 return SYSOP(0, 0, 3, 3, 0, 6, 0x1F) 3479 3480 case AHINT: 3481 return SYSOP(0, 0, 3, 2, 0, 0, 0x1F) 3482 } 3483 3484 ctxt.Diag("bad irr %v", obj.Aconv(a)) 3485 prasm(ctxt.Curp) 3486 return 0 3487 } 3488 3489 func opbit(ctxt *obj.Link, a int) uint32 { 3490 switch a { 3491 case ACLS: 3492 return S64 | OPBIT(5) 3493 3494 case ACLSW: 3495 return S32 | OPBIT(5) 3496 3497 case ACLZ: 3498 return S64 | OPBIT(4) 3499 3500 case ACLZW: 3501 return S32 | OPBIT(4) 3502 3503 case ARBIT: 3504 return S64 | OPBIT(0) 3505 3506 case ARBITW: 3507 return S32 | OPBIT(0) 3508 3509 case AREV: 3510 return S64 | OPBIT(3) 3511 3512 case AREVW: 3513 return S32 | OPBIT(2) 3514 3515 case AREV16: 3516 return S64 | OPBIT(1) 3517 3518 case AREV16W: 3519 return S32 | OPBIT(1) 3520 3521 case AREV32: 3522 return S64 | OPBIT(2) 3523 3524 default: 3525 ctxt.Diag("bad bit op\n%v", ctxt.Curp) 3526 return 0 3527 } 3528 } 3529 3530 /* 3531 * add/subtract extended register 3532 */ 3533 func opxrrr(ctxt *obj.Link, a int) uint32 { 3534 switch a { 3535 case AADD: 3536 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64 3537 3538 case AADDW: 3539 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32 3540 3541 case ACMN, AADDS: 3542 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64 3543 3544 case ACMNW, AADDSW: 3545 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32 3546 3547 case ASUB: 3548 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64 3549 3550 case ASUBW: 3551 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32 3552 3553 case ACMP, ASUBS: 3554 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64 3555 3556 case ACMPW, ASUBSW: 3557 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32 3558 } 3559 3560 ctxt.Diag("bad opxrrr %v\n%v", obj.Aconv(a), ctxt.Curp) 3561 return 0 3562 } 3563 3564 func opimm(ctxt *obj.Link, a int) uint32 { 3565 switch a { 3566 case ASVC: 3567 return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */ 3568 3569 case AHVC: 3570 return 0xD4<<24 | 0<<21 | 2 3571 3572 case ASMC: 3573 return 0xD4<<24 | 0<<21 | 3 3574 3575 case ABRK: 3576 return 0xD4<<24 | 1<<21 | 0 3577 3578 case AHLT: 3579 return 0xD4<<24 | 2<<21 | 0 3580 3581 case ADCPS1: 3582 return 0xD4<<24 | 5<<21 | 1 3583 3584 case ADCPS2: 3585 return 0xD4<<24 | 5<<21 | 2 3586 3587 case ADCPS3: 3588 return 0xD4<<24 | 5<<21 | 3 3589 3590 case ACLREX: 3591 return SYSOP(0, 0, 3, 3, 0, 2, 0x1F) 3592 } 3593 3594 ctxt.Diag("bad imm %v", obj.Aconv(a)) 3595 prasm(ctxt.Curp) 3596 return 0 3597 } 3598 3599 func brdist(ctxt *obj.Link, p *obj.Prog, preshift int, flen int, shift int) int64 { 3600 v := int64(0) 3601 t := int64(0) 3602 if p.Pcond != nil { 3603 v = (p.Pcond.Pc >> uint(preshift)) - (ctxt.Pc >> uint(preshift)) 3604 if (v & ((1 << uint(shift)) - 1)) != 0 { 3605 ctxt.Diag("misaligned label\n%v", p) 3606 } 3607 v >>= uint(shift) 3608 t = int64(1) << uint(flen-1) 3609 if v < -t || v >= t { 3610 ctxt.Diag("branch too far\n%v", p) 3611 } 3612 } 3613 3614 return v & ((t << 1) - 1) 3615 } 3616 3617 /* 3618 * pc-relative branches 3619 */ 3620 func opbra(ctxt *obj.Link, a int) uint32 { 3621 switch a { 3622 case ABEQ: 3623 return OPBcc(0x0) 3624 3625 case ABNE: 3626 return OPBcc(0x1) 3627 3628 case ABCS: 3629 return OPBcc(0x2) 3630 3631 case ABHS: 3632 return OPBcc(0x2) 3633 3634 case ABCC: 3635 return OPBcc(0x3) 3636 3637 case ABLO: 3638 return OPBcc(0x3) 3639 3640 case ABMI: 3641 return OPBcc(0x4) 3642 3643 case ABPL: 3644 return OPBcc(0x5) 3645 3646 case ABVS: 3647 return OPBcc(0x6) 3648 3649 case ABVC: 3650 return OPBcc(0x7) 3651 3652 case ABHI: 3653 return OPBcc(0x8) 3654 3655 case ABLS: 3656 return OPBcc(0x9) 3657 3658 case ABGE: 3659 return OPBcc(0xa) 3660 3661 case ABLT: 3662 return OPBcc(0xb) 3663 3664 case ABGT: 3665 return OPBcc(0xc) 3666 3667 case ABLE: 3668 return OPBcc(0xd) /* imm19<<5 | cond */ 3669 3670 case AB: 3671 return 0<<31 | 5<<26 /* imm26 */ 3672 3673 case obj.ADUFFZERO, 3674 ABL: 3675 return 1<<31 | 5<<26 3676 } 3677 3678 ctxt.Diag("bad bra %v", obj.Aconv(a)) 3679 prasm(ctxt.Curp) 3680 return 0 3681 } 3682 3683 func opbrr(ctxt *obj.Link, a int) uint32 { 3684 switch a { 3685 case ABL: 3686 return OPBLR(1) /* BLR */ 3687 3688 case AB: 3689 return OPBLR(0) /* BR */ 3690 3691 case obj.ARET: 3692 return OPBLR(2) /* RET */ 3693 } 3694 3695 ctxt.Diag("bad brr %v", obj.Aconv(a)) 3696 prasm(ctxt.Curp) 3697 return 0 3698 } 3699 3700 func op0(ctxt *obj.Link, a int) uint32 { 3701 switch a { 3702 case ADRPS: 3703 return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5 3704 3705 case AERET: 3706 return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5 3707 3708 // case ANOP: 3709 // return SYSHINT(0) 3710 3711 case AYIELD: 3712 return SYSHINT(1) 3713 3714 case AWFE: 3715 return SYSHINT(2) 3716 3717 case AWFI: 3718 return SYSHINT(3) 3719 3720 case ASEV: 3721 return SYSHINT(4) 3722 3723 case ASEVL: 3724 return SYSHINT(5) 3725 } 3726 3727 ctxt.Diag("bad op0 %v", obj.Aconv(a)) 3728 prasm(ctxt.Curp) 3729 return 0 3730 } 3731 3732 /* 3733 * register offset 3734 */ 3735 func opload(ctxt *obj.Link, a int) uint32 { 3736 switch a { 3737 case ALDAR: 3738 return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10 3739 3740 case ALDARW: 3741 return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10 3742 3743 case ALDARB: 3744 return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10 3745 3746 case ALDARH: 3747 return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10 3748 3749 case ALDAXP: 3750 return LDSTX(3, 0, 1, 1, 1) 3751 3752 case ALDAXPW: 3753 return LDSTX(2, 0, 1, 1, 1) 3754 3755 case ALDAXR: 3756 return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10 3757 3758 case ALDAXRW: 3759 return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10 3760 3761 case ALDAXRB: 3762 return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10 3763 3764 case ALDAXRH: 3765 return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10 3766 3767 case ALDXR: 3768 return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10 3769 3770 case ALDXRB: 3771 return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10 3772 3773 case ALDXRH: 3774 return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10 3775 3776 case ALDXRW: 3777 return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10 3778 3779 case ALDXP: 3780 return LDSTX(3, 0, 1, 1, 0) 3781 3782 case ALDXPW: 3783 return LDSTX(2, 0, 1, 1, 0) 3784 3785 case AMOVNP: 3786 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 3787 3788 case AMOVNPW: 3789 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 3790 } 3791 3792 ctxt.Diag("bad opload %v\n%v", obj.Aconv(a), ctxt.Curp) 3793 return 0 3794 } 3795 3796 func opstore(ctxt *obj.Link, a int) uint32 { 3797 switch a { 3798 case ASTLR: 3799 return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10 3800 3801 case ASTLRB: 3802 return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10 3803 3804 case ASTLRH: 3805 return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10 3806 3807 case ASTLP: 3808 return LDSTX(3, 0, 0, 1, 1) 3809 3810 case ASTLPW: 3811 return LDSTX(2, 0, 0, 1, 1) 3812 3813 case ASTLRW: 3814 return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10 3815 3816 case ASTLXP: 3817 return LDSTX(2, 0, 0, 1, 1) 3818 3819 case ASTLXPW: 3820 return LDSTX(3, 0, 0, 1, 1) 3821 3822 case ASTLXR: 3823 return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10 3824 3825 case ASTLXRB: 3826 return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10 3827 3828 case ASTLXRH: 3829 return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10 3830 3831 case ASTLXRW: 3832 return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10 3833 3834 case ASTXR: 3835 return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10 3836 3837 case ASTXRB: 3838 return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10 3839 3840 case ASTXRH: 3841 return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10 3842 3843 case ASTXP: 3844 return LDSTX(3, 0, 0, 1, 0) 3845 3846 case ASTXPW: 3847 return LDSTX(2, 0, 0, 1, 0) 3848 3849 case ASTXRW: 3850 return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10 3851 3852 case AMOVNP: 3853 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 3854 3855 case AMOVNPW: 3856 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 3857 } 3858 3859 ctxt.Diag("bad opstore %v\n%v", obj.Aconv(a), ctxt.Curp) 3860 return 0 3861 } 3862 3863 /* 3864 * load/store register (unsigned immediate) C3.3.13 3865 * these produce 64-bit values (when there's an option) 3866 */ 3867 func olsr12u(ctxt *obj.Link, o int32, v int32, b int, r int) uint32 { 3868 if v < 0 || v >= (1<<12) { 3869 ctxt.Diag("offset out of range: %d\n%v", v, ctxt.Curp) 3870 } 3871 o |= (v & 0xFFF) << 10 3872 o |= int32(b&31) << 5 3873 o |= int32(r & 31) 3874 return uint32(o) 3875 } 3876 3877 func opldr12(ctxt *obj.Link, a int) uint32 { 3878 switch a { 3879 case AMOVD: 3880 return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */ 3881 3882 case AMOVW: 3883 return LDSTR12U(2, 0, 2) 3884 3885 case AMOVWU: 3886 return LDSTR12U(2, 0, 1) 3887 3888 case AMOVH: 3889 return LDSTR12U(1, 0, 2) 3890 3891 case AMOVHU: 3892 return LDSTR12U(1, 0, 1) 3893 3894 case AMOVB: 3895 return LDSTR12U(0, 0, 2) 3896 3897 case AMOVBU: 3898 return LDSTR12U(0, 0, 1) 3899 3900 case AFMOVS: 3901 return LDSTR12U(2, 1, 1) 3902 3903 case AFMOVD: 3904 return LDSTR12U(3, 1, 1) 3905 } 3906 3907 ctxt.Diag("bad opldr12 %v\n%v", obj.Aconv(a), ctxt.Curp) 3908 return 0 3909 } 3910 3911 func opstr12(ctxt *obj.Link, a int) uint32 { 3912 return LD2STR(opldr12(ctxt, a)) 3913 } 3914 3915 /* 3916 * load/store register (unscaled immediate) C3.3.12 3917 */ 3918 func olsr9s(ctxt *obj.Link, o int32, v int32, b int, r int) uint32 { 3919 if v < -256 || v > 255 { 3920 ctxt.Diag("offset out of range: %d\n%v", v, ctxt.Curp) 3921 } 3922 o |= (v & 0x1FF) << 12 3923 o |= int32(b&31) << 5 3924 o |= int32(r & 31) 3925 return uint32(o) 3926 } 3927 3928 func opldr9(ctxt *obj.Link, a int) uint32 { 3929 switch a { 3930 case AMOVD: 3931 return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */ 3932 3933 case AMOVW: 3934 return LDSTR9S(2, 0, 2) 3935 3936 case AMOVWU: 3937 return LDSTR9S(2, 0, 1) 3938 3939 case AMOVH: 3940 return LDSTR9S(1, 0, 2) 3941 3942 case AMOVHU: 3943 return LDSTR9S(1, 0, 1) 3944 3945 case AMOVB: 3946 return LDSTR9S(0, 0, 2) 3947 3948 case AMOVBU: 3949 return LDSTR9S(0, 0, 1) 3950 3951 case AFMOVS: 3952 return LDSTR9S(2, 1, 1) 3953 3954 case AFMOVD: 3955 return LDSTR9S(3, 1, 1) 3956 } 3957 3958 ctxt.Diag("bad opldr9 %v\n%v", obj.Aconv(a), ctxt.Curp) 3959 return 0 3960 } 3961 3962 func opstr9(ctxt *obj.Link, a int) uint32 { 3963 return LD2STR(opldr9(ctxt, a)) 3964 } 3965 3966 func opldrpp(ctxt *obj.Link, a int) uint32 { 3967 switch a { 3968 case AMOVD: 3969 return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */ 3970 3971 case AMOVW: 3972 return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 3973 3974 case AMOVWU: 3975 return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 3976 3977 case AMOVH: 3978 return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 3979 3980 case AMOVHU: 3981 return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 3982 3983 case AMOVB: 3984 return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 3985 3986 case AMOVBU: 3987 return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 3988 } 3989 3990 ctxt.Diag("bad opldr %v\n%v", obj.Aconv(a), ctxt.Curp) 3991 return 0 3992 } 3993 3994 /* 3995 * load/store register (extended register) 3996 */ 3997 func olsxrr(ctxt *obj.Link, as int, rt int, r1 int, r2 int) uint32 { 3998 ctxt.Diag("need load/store extended register\n%v", ctxt.Curp) 3999 return 0xffffffff 4000 } 4001 4002 func oaddi(ctxt *obj.Link, o1 int32, v int32, r int, rt int) uint32 { 4003 if (v & 0xFFF000) != 0 { 4004 if v&0xFFF != 0 { 4005 ctxt.Diag("%v misuses oaddi", ctxt.Curp) 4006 } 4007 v >>= 12 4008 o1 |= 1 << 22 4009 } 4010 4011 o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31) 4012 return uint32(o1) 4013 } 4014 4015 /* 4016 * load a a literal value into dr 4017 */ 4018 func omovlit(ctxt *obj.Link, as int, p *obj.Prog, a *obj.Addr, dr int) uint32 { 4019 var o1 int32 4020 if p.Pcond == nil { /* not in literal pool */ 4021 aclass(ctxt, a) 4022 fmt.Fprintf(ctxt.Bso, "omovlit add %d (%#x)\n", ctxt.Instoffset, uint64(ctxt.Instoffset)) 4023 4024 /* TODO: could be clever, and use general constant builder */ 4025 o1 = int32(opirr(ctxt, AADD)) 4026 4027 v := int32(ctxt.Instoffset) 4028 if v != 0 && (v&0xFFF) == 0 { 4029 v >>= 12 4030 o1 |= 1 << 22 /* shift, by 12 */ 4031 } 4032 4033 o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31) 4034 } else { 4035 fp := 0 4036 w := 0 /* default: 32 bit, unsigned */ 4037 switch as { 4038 case AFMOVS: 4039 fp = 1 4040 4041 case AFMOVD: 4042 fp = 1 4043 w = 1 /* 64 bit simd&fp */ 4044 4045 case AMOVD: 4046 if p.Pcond.As == ADWORD { 4047 w = 1 /* 64 bit */ 4048 } else if p.Pcond.To.Offset < 0 { 4049 w = 2 /* sign extend */ 4050 } 4051 4052 case AMOVB, AMOVH, AMOVW: 4053 w = 2 /* 32 bit, sign-extended to 64 */ 4054 break 4055 } 4056 4057 v := int32(brdist(ctxt, p, 0, 19, 2)) 4058 o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27) 4059 o1 |= (v & 0x7FFFF) << 5 4060 o1 |= int32(dr & 31) 4061 } 4062 4063 return uint32(o1) 4064 } 4065 4066 func opbfm(ctxt *obj.Link, a int, r int, s int, rf int, rt int) uint32 { 4067 var c uint32 4068 o := opirr(ctxt, a) 4069 if (o & (1 << 31)) == 0 { 4070 c = 32 4071 } else { 4072 c = 64 4073 } 4074 if r < 0 || uint32(r) >= c { 4075 ctxt.Diag("illegal bit number\n%v", ctxt.Curp) 4076 } 4077 o |= (uint32(r) & 0x3F) << 16 4078 if s < 0 || uint32(s) >= c { 4079 ctxt.Diag("illegal bit number\n%v", ctxt.Curp) 4080 } 4081 o |= (uint32(s) & 0x3F) << 10 4082 o |= (uint32(rf&31) << 5) | uint32(rt&31) 4083 return o 4084 } 4085 4086 func opextr(ctxt *obj.Link, a int, v int32, rn int, rm int, rt int) uint32 { 4087 var c uint32 4088 o := opirr(ctxt, a) 4089 if (o & (1 << 31)) != 0 { 4090 c = 63 4091 } else { 4092 c = 31 4093 } 4094 if v < 0 || uint32(v) > c { 4095 ctxt.Diag("illegal bit number\n%v", ctxt.Curp) 4096 } 4097 o |= uint32(v) << 10 4098 o |= uint32(rn&31) << 5 4099 o |= uint32(rm&31) << 16 4100 o |= uint32(rt & 31) 4101 return o 4102 } 4103 4104 /* 4105 * size in log2(bytes) 4106 */ 4107 func movesize(a int) int { 4108 switch a { 4109 case AMOVD: 4110 return 3 4111 4112 case AMOVW, AMOVWU: 4113 return 2 4114 4115 case AMOVH, AMOVHU: 4116 return 1 4117 4118 case AMOVB, AMOVBU: 4119 return 0 4120 4121 case AFMOVS: 4122 return 2 4123 4124 case AFMOVD: 4125 return 3 4126 4127 default: 4128 return -1 4129 } 4130 }