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