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