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