github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/engine/wazevo/backend/isa/arm64/reg.go (about) 1 package arm64 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 8 "github.com/wasilibs/wazerox/internal/engine/wazevo/backend/regalloc" 9 ) 10 11 // Arm64-specific registers. 12 // 13 // See https://developer.arm.com/documentation/dui0801/a/Overview-of-AArch64-state/Predeclared-core-register-names-in-AArch64-state 14 15 const ( 16 // General purpose registers. Note that we do not distinguish wn and xn registers 17 // because they are the same from the perspective of register allocator, and 18 // the size can be determined by the type of the instruction. 19 20 x0 = regalloc.RealRegInvalid + 1 + iota 21 x1 22 x2 23 x3 24 x4 25 x5 26 x6 27 x7 28 x8 29 x9 30 x10 31 x11 32 x12 33 x13 34 x14 35 x15 36 x16 37 x17 38 x18 39 x19 40 x20 41 x21 42 x22 43 x23 44 x24 45 x25 46 x26 47 x27 48 x28 49 x29 50 x30 51 52 // Vector registers. Note that we do not distinguish vn and dn, ... registers 53 // because they are the same from the perspective of register allocator, and 54 // the size can be determined by the type of the instruction. 55 56 v0 57 v1 58 v2 59 v3 60 v4 61 v5 62 v6 63 v7 64 v8 65 v9 66 v10 67 v11 68 v12 69 v13 70 v14 71 v15 72 v16 73 v17 74 v18 75 v19 76 v20 77 v21 78 v22 79 v23 80 v24 81 v25 82 v26 83 v27 84 v28 85 v29 86 v30 87 v31 88 89 // Special registers 90 91 xzr 92 sp 93 lr = x30 94 fp = x29 95 tmp = x27 96 ) 97 98 var ( 99 x0VReg = regalloc.FromRealReg(x0, regalloc.RegTypeInt) 100 x1VReg = regalloc.FromRealReg(x1, regalloc.RegTypeInt) 101 x2VReg = regalloc.FromRealReg(x2, regalloc.RegTypeInt) 102 x3VReg = regalloc.FromRealReg(x3, regalloc.RegTypeInt) 103 x4VReg = regalloc.FromRealReg(x4, regalloc.RegTypeInt) 104 x5VReg = regalloc.FromRealReg(x5, regalloc.RegTypeInt) 105 x6VReg = regalloc.FromRealReg(x6, regalloc.RegTypeInt) 106 x7VReg = regalloc.FromRealReg(x7, regalloc.RegTypeInt) 107 x8VReg = regalloc.FromRealReg(x8, regalloc.RegTypeInt) 108 x9VReg = regalloc.FromRealReg(x9, regalloc.RegTypeInt) 109 x10VReg = regalloc.FromRealReg(x10, regalloc.RegTypeInt) 110 x11VReg = regalloc.FromRealReg(x11, regalloc.RegTypeInt) 111 x12VReg = regalloc.FromRealReg(x12, regalloc.RegTypeInt) 112 x13VReg = regalloc.FromRealReg(x13, regalloc.RegTypeInt) 113 x14VReg = regalloc.FromRealReg(x14, regalloc.RegTypeInt) 114 x15VReg = regalloc.FromRealReg(x15, regalloc.RegTypeInt) 115 x16VReg = regalloc.FromRealReg(x16, regalloc.RegTypeInt) 116 x17VReg = regalloc.FromRealReg(x17, regalloc.RegTypeInt) 117 x18VReg = regalloc.FromRealReg(x18, regalloc.RegTypeInt) 118 x19VReg = regalloc.FromRealReg(x19, regalloc.RegTypeInt) 119 x20VReg = regalloc.FromRealReg(x20, regalloc.RegTypeInt) 120 x21VReg = regalloc.FromRealReg(x21, regalloc.RegTypeInt) 121 x22VReg = regalloc.FromRealReg(x22, regalloc.RegTypeInt) 122 x23VReg = regalloc.FromRealReg(x23, regalloc.RegTypeInt) 123 x24VReg = regalloc.FromRealReg(x24, regalloc.RegTypeInt) 124 x25VReg = regalloc.FromRealReg(x25, regalloc.RegTypeInt) 125 x26VReg = regalloc.FromRealReg(x26, regalloc.RegTypeInt) 126 x27VReg = regalloc.FromRealReg(x27, regalloc.RegTypeInt) 127 x28VReg = regalloc.FromRealReg(x28, regalloc.RegTypeInt) 128 x29VReg = regalloc.FromRealReg(x29, regalloc.RegTypeInt) 129 x30VReg = regalloc.FromRealReg(x30, regalloc.RegTypeInt) 130 v0VReg = regalloc.FromRealReg(v0, regalloc.RegTypeFloat) 131 v1VReg = regalloc.FromRealReg(v1, regalloc.RegTypeFloat) 132 v2VReg = regalloc.FromRealReg(v2, regalloc.RegTypeFloat) 133 v3VReg = regalloc.FromRealReg(v3, regalloc.RegTypeFloat) 134 v4VReg = regalloc.FromRealReg(v4, regalloc.RegTypeFloat) 135 v5VReg = regalloc.FromRealReg(v5, regalloc.RegTypeFloat) 136 v6VReg = regalloc.FromRealReg(v6, regalloc.RegTypeFloat) 137 v7VReg = regalloc.FromRealReg(v7, regalloc.RegTypeFloat) 138 v8VReg = regalloc.FromRealReg(v8, regalloc.RegTypeFloat) 139 v9VReg = regalloc.FromRealReg(v9, regalloc.RegTypeFloat) 140 v10VReg = regalloc.FromRealReg(v10, regalloc.RegTypeFloat) 141 v11VReg = regalloc.FromRealReg(v11, regalloc.RegTypeFloat) 142 v12VReg = regalloc.FromRealReg(v12, regalloc.RegTypeFloat) 143 v13VReg = regalloc.FromRealReg(v13, regalloc.RegTypeFloat) 144 v14VReg = regalloc.FromRealReg(v14, regalloc.RegTypeFloat) 145 v15VReg = regalloc.FromRealReg(v15, regalloc.RegTypeFloat) 146 v16VReg = regalloc.FromRealReg(v16, regalloc.RegTypeFloat) 147 v17VReg = regalloc.FromRealReg(v17, regalloc.RegTypeFloat) 148 v18VReg = regalloc.FromRealReg(v18, regalloc.RegTypeFloat) 149 v19VReg = regalloc.FromRealReg(v19, regalloc.RegTypeFloat) 150 v20VReg = regalloc.FromRealReg(v20, regalloc.RegTypeFloat) 151 v21VReg = regalloc.FromRealReg(v21, regalloc.RegTypeFloat) 152 v22VReg = regalloc.FromRealReg(v22, regalloc.RegTypeFloat) 153 v23VReg = regalloc.FromRealReg(v23, regalloc.RegTypeFloat) 154 v24VReg = regalloc.FromRealReg(v24, regalloc.RegTypeFloat) 155 v25VReg = regalloc.FromRealReg(v25, regalloc.RegTypeFloat) 156 v26VReg = regalloc.FromRealReg(v26, regalloc.RegTypeFloat) 157 v27VReg = regalloc.FromRealReg(v27, regalloc.RegTypeFloat) 158 // lr (link register) holds the return address at the function entry. 159 lrVReg = x30VReg 160 // tmpReg is used to perform spill/load on large stack offsets, and load large constants. 161 // Therefore, be cautious to use this register in the middle of the compilation, especially before the register allocation. 162 // This is the same as golang/go, but it's only described in the source code: 163 // https://github.com/golang/go/blob/18e17e2cb12837ea2c8582ecdb0cc780f49a1aac/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go#L59 164 // https://github.com/golang/go/blob/18e17e2cb12837ea2c8582ecdb0cc780f49a1aac/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go#L13-L15 165 tmpRegVReg = regalloc.FromRealReg(tmp, regalloc.RegTypeInt) 166 v28VReg = regalloc.FromRealReg(v28, regalloc.RegTypeFloat) 167 v29VReg = regalloc.FromRealReg(v29, regalloc.RegTypeFloat) 168 v30VReg = regalloc.FromRealReg(v30, regalloc.RegTypeFloat) 169 v31VReg = regalloc.FromRealReg(v31, regalloc.RegTypeFloat) 170 xzrVReg = regalloc.FromRealReg(xzr, regalloc.RegTypeInt) 171 spVReg = regalloc.FromRealReg(sp, regalloc.RegTypeInt) 172 fpVReg = regalloc.FromRealReg(fp, regalloc.RegTypeInt) 173 ) 174 175 var regNames = [...]string{ 176 x0: "x0", 177 x1: "x1", 178 x2: "x2", 179 x3: "x3", 180 x4: "x4", 181 x5: "x5", 182 x6: "x6", 183 x7: "x7", 184 x8: "x8", 185 x9: "x9", 186 x10: "x10", 187 x11: "x11", 188 x12: "x12", 189 x13: "x13", 190 x14: "x14", 191 x15: "x15", 192 x16: "x16", 193 x17: "x17", 194 x18: "x18", 195 x19: "x19", 196 x20: "x20", 197 x21: "x21", 198 x22: "x22", 199 x23: "x23", 200 x24: "x24", 201 x25: "x25", 202 x26: "x26", 203 x27: "x27", 204 x28: "x28", 205 x29: "x29", 206 x30: "x30", 207 xzr: "xzr", 208 sp: "sp", 209 v0: "v0", 210 v1: "v1", 211 v2: "v2", 212 v3: "v3", 213 v4: "v4", 214 v5: "v5", 215 v6: "v6", 216 v7: "v7", 217 v8: "v8", 218 v9: "v9", 219 v10: "v10", 220 v11: "v11", 221 v12: "v12", 222 v13: "v13", 223 v14: "v14", 224 v15: "v15", 225 v16: "v16", 226 v17: "v17", 227 v18: "v18", 228 v19: "v19", 229 v20: "v20", 230 v21: "v21", 231 v22: "v22", 232 v23: "v23", 233 v24: "v24", 234 v25: "v25", 235 v26: "v26", 236 v27: "v27", 237 v28: "v28", 238 v29: "v29", 239 v30: "v30", 240 v31: "v31", 241 } 242 243 func formatVRegSized(r regalloc.VReg, size byte) (ret string) { 244 if r.IsRealReg() { 245 ret = regNames[r.RealReg()] 246 switch ret[0] { 247 case 'x': 248 switch size { 249 case 32: 250 ret = strings.Replace(ret, "x", "w", 1) 251 case 64: 252 default: 253 panic("BUG: invalid register size: " + strconv.Itoa(int(size))) 254 } 255 case 'v': 256 switch size { 257 case 32: 258 ret = strings.Replace(ret, "v", "s", 1) 259 case 64: 260 ret = strings.Replace(ret, "v", "d", 1) 261 case 128: 262 ret = strings.Replace(ret, "v", "q", 1) 263 default: 264 panic("BUG: invalid register size") 265 } 266 } 267 } else { 268 switch r.RegType() { 269 case regalloc.RegTypeInt: 270 switch size { 271 case 32: 272 ret = fmt.Sprintf("w%d?", r.ID()) 273 case 64: 274 ret = fmt.Sprintf("x%d?", r.ID()) 275 default: 276 panic("BUG: invalid register size: " + strconv.Itoa(int(size))) 277 } 278 case regalloc.RegTypeFloat: 279 switch size { 280 case 32: 281 ret = fmt.Sprintf("s%d?", r.ID()) 282 case 64: 283 ret = fmt.Sprintf("d%d?", r.ID()) 284 case 128: 285 ret = fmt.Sprintf("q%d?", r.ID()) 286 default: 287 panic("BUG: invalid register size") 288 } 289 default: 290 panic(fmt.Sprintf("BUG: invalid register type: %d for %s", r.RegType(), r)) 291 } 292 } 293 return 294 } 295 296 func formatVRegWidthVec(r regalloc.VReg, width vecArrangement) (ret string) { 297 var id string 298 wspec := strings.ToLower(width.String()) 299 if r.IsRealReg() { 300 id = regNames[r.RealReg()][1:] 301 } else { 302 id = fmt.Sprintf("%d?", r.ID()) 303 } 304 ret = fmt.Sprintf("%s%s", wspec, id) 305 return 306 } 307 308 func formatVRegVec(r regalloc.VReg, arr vecArrangement, index vecIndex) (ret string) { 309 id := fmt.Sprintf("v%d?", r.ID()) 310 if r.IsRealReg() { 311 id = regNames[r.RealReg()] 312 } 313 ret = fmt.Sprintf("%s.%s", id, strings.ToLower(arr.String())) 314 if index != vecIndexNone { 315 ret += fmt.Sprintf("[%d]", index) 316 } 317 return 318 } 319 320 func regTypeToRegisterSizeInBits(r regalloc.RegType) byte { 321 switch r { 322 case regalloc.RegTypeInt: 323 return 64 324 case regalloc.RegTypeFloat: 325 return 128 326 default: 327 panic("BUG: invalid register type") 328 } 329 } 330 331 var regNumberInEncoding = [...]uint32{ 332 x0: 0, 333 x1: 1, 334 x2: 2, 335 x3: 3, 336 x4: 4, 337 x5: 5, 338 x6: 6, 339 x7: 7, 340 x8: 8, 341 x9: 9, 342 x10: 10, 343 x11: 11, 344 x12: 12, 345 x13: 13, 346 x14: 14, 347 x15: 15, 348 x16: 16, 349 x17: 17, 350 x18: 18, 351 x19: 19, 352 x20: 20, 353 x21: 21, 354 x22: 22, 355 x23: 23, 356 x24: 24, 357 x25: 25, 358 x26: 26, 359 x27: 27, 360 x28: 28, 361 x29: 29, 362 x30: 30, 363 xzr: 31, 364 sp: 31, 365 v0: 0, 366 v1: 1, 367 v2: 2, 368 v3: 3, 369 v4: 4, 370 v5: 5, 371 v6: 6, 372 v7: 7, 373 v8: 8, 374 v9: 9, 375 v10: 10, 376 v11: 11, 377 v12: 12, 378 v13: 13, 379 v14: 14, 380 v15: 15, 381 v16: 16, 382 v17: 17, 383 v18: 18, 384 v19: 19, 385 v20: 20, 386 v21: 21, 387 v22: 22, 388 v23: 23, 389 v24: 24, 390 v25: 25, 391 v26: 26, 392 v27: 27, 393 v28: 28, 394 v29: 29, 395 v30: 30, 396 v31: 31, 397 }