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