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