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