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