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