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