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