github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/asm/arch/arch.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package arch defines architecture-specific information and support functions. 6 package arch 7 8 import ( 9 "fmt" 10 "strings" 11 12 "github.com/go-asm/go/cmd/obj" 13 "github.com/go-asm/go/cmd/obj/arm" 14 "github.com/go-asm/go/cmd/obj/arm64" 15 "github.com/go-asm/go/cmd/obj/loong64" 16 "github.com/go-asm/go/cmd/obj/mips" 17 "github.com/go-asm/go/cmd/obj/ppc64" 18 "github.com/go-asm/go/cmd/obj/riscv" 19 "github.com/go-asm/go/cmd/obj/s390x" 20 "github.com/go-asm/go/cmd/obj/wasm" 21 "github.com/go-asm/go/cmd/obj/x86" 22 ) 23 24 // Pseudo-registers whose names are the constant name without the leading R. 25 const ( 26 RFP = -(iota + 1) 27 RSB 28 RSP 29 RPC 30 ) 31 32 // Arch wraps the link architecture object with more architecture-specific information. 33 type Arch struct { 34 *obj.LinkArch 35 // Map of instruction names to enumeration. 36 Instructions map[string]obj.As 37 // Map of register names to enumeration. 38 Register map[string]int16 39 // Table of register prefix names. These are things like R for R(0) and SPR for SPR(268). 40 RegisterPrefix map[string]bool 41 // RegisterNumber converts R(10) into arm.REG_R10. 42 RegisterNumber func(string, int16) (int16, bool) 43 // Instruction is a jump. 44 IsJump func(word string) bool 45 } 46 47 // nilRegisterNumber is the register number function for architectures 48 // that do not accept the R(N) notation. It always returns failure. 49 func nilRegisterNumber(name string, n int16) (int16, bool) { 50 return 0, false 51 } 52 53 // Set configures the architecture specified by GOARCH and returns its representation. 54 // It returns nil if GOARCH is not recognized. 55 func Set(GOARCH string, shared bool) *Arch { 56 switch GOARCH { 57 case "386": 58 return archX86(&x86.Link386) 59 case "amd64": 60 return archX86(&x86.Linkamd64) 61 case "arm": 62 return archArm() 63 case "arm64": 64 return archArm64() 65 case "loong64": 66 return archLoong64(&loong64.Linkloong64) 67 case "mips": 68 return archMips(&mips.Linkmips) 69 case "mipsle": 70 return archMips(&mips.Linkmipsle) 71 case "mips64": 72 return archMips64(&mips.Linkmips64) 73 case "mips64le": 74 return archMips64(&mips.Linkmips64le) 75 case "ppc64": 76 return archPPC64(&ppc64.Linkppc64) 77 case "ppc64le": 78 return archPPC64(&ppc64.Linkppc64le) 79 case "riscv64": 80 return archRISCV64(shared) 81 case "s390x": 82 return archS390x() 83 case "wasm": 84 return archWasm() 85 } 86 return nil 87 } 88 89 func jumpX86(word string) bool { 90 return word[0] == 'J' || word == "CALL" || strings.HasPrefix(word, "LOOP") || word == "XBEGIN" 91 } 92 93 func jumpRISCV(word string) bool { 94 switch word { 95 case "BEQ", "BEQZ", "BGE", "BGEU", "BGEZ", "BGT", "BGTU", "BGTZ", "BLE", "BLEU", "BLEZ", 96 "BLT", "BLTU", "BLTZ", "BNE", "BNEZ", "CALL", "JAL", "JALR", "JMP": 97 return true 98 } 99 return false 100 } 101 102 func jumpWasm(word string) bool { 103 return word == "JMP" || word == "CALL" || word == "Call" || word == "Br" || word == "BrIf" 104 } 105 106 func archX86(linkArch *obj.LinkArch) *Arch { 107 register := make(map[string]int16) 108 // Create maps for easy lookup of instruction names etc. 109 for i, s := range x86.Register { 110 register[s] = int16(i + x86.REG_AL) 111 } 112 // Pseudo-registers. 113 register["SB"] = RSB 114 register["FP"] = RFP 115 register["PC"] = RPC 116 if linkArch == &x86.Linkamd64 { 117 // Alias g to R14 118 register["g"] = x86.REGG 119 } 120 // Register prefix not used on this architecture. 121 122 instructions := make(map[string]obj.As) 123 for i, s := range obj.Anames { 124 instructions[s] = obj.As(i) 125 } 126 for i, s := range x86.Anames { 127 if obj.As(i) >= obj.A_ARCHSPECIFIC { 128 instructions[s] = obj.As(i) + obj.ABaseAMD64 129 } 130 } 131 // Annoying aliases. 132 instructions["JA"] = x86.AJHI /* alternate */ 133 instructions["JAE"] = x86.AJCC /* alternate */ 134 instructions["JB"] = x86.AJCS /* alternate */ 135 instructions["JBE"] = x86.AJLS /* alternate */ 136 instructions["JC"] = x86.AJCS /* alternate */ 137 instructions["JCC"] = x86.AJCC /* carry clear (CF = 0) */ 138 instructions["JCS"] = x86.AJCS /* carry set (CF = 1) */ 139 instructions["JE"] = x86.AJEQ /* alternate */ 140 instructions["JEQ"] = x86.AJEQ /* equal (ZF = 1) */ 141 instructions["JG"] = x86.AJGT /* alternate */ 142 instructions["JGE"] = x86.AJGE /* greater than or equal (signed) (SF = OF) */ 143 instructions["JGT"] = x86.AJGT /* greater than (signed) (ZF = 0 && SF = OF) */ 144 instructions["JHI"] = x86.AJHI /* higher (unsigned) (CF = 0 && ZF = 0) */ 145 instructions["JHS"] = x86.AJCC /* alternate */ 146 instructions["JL"] = x86.AJLT /* alternate */ 147 instructions["JLE"] = x86.AJLE /* less than or equal (signed) (ZF = 1 || SF != OF) */ 148 instructions["JLO"] = x86.AJCS /* alternate */ 149 instructions["JLS"] = x86.AJLS /* lower or same (unsigned) (CF = 1 || ZF = 1) */ 150 instructions["JLT"] = x86.AJLT /* less than (signed) (SF != OF) */ 151 instructions["JMI"] = x86.AJMI /* negative (minus) (SF = 1) */ 152 instructions["JNA"] = x86.AJLS /* alternate */ 153 instructions["JNAE"] = x86.AJCS /* alternate */ 154 instructions["JNB"] = x86.AJCC /* alternate */ 155 instructions["JNBE"] = x86.AJHI /* alternate */ 156 instructions["JNC"] = x86.AJCC /* alternate */ 157 instructions["JNE"] = x86.AJNE /* not equal (ZF = 0) */ 158 instructions["JNG"] = x86.AJLE /* alternate */ 159 instructions["JNGE"] = x86.AJLT /* alternate */ 160 instructions["JNL"] = x86.AJGE /* alternate */ 161 instructions["JNLE"] = x86.AJGT /* alternate */ 162 instructions["JNO"] = x86.AJOC /* alternate */ 163 instructions["JNP"] = x86.AJPC /* alternate */ 164 instructions["JNS"] = x86.AJPL /* alternate */ 165 instructions["JNZ"] = x86.AJNE /* alternate */ 166 instructions["JO"] = x86.AJOS /* alternate */ 167 instructions["JOC"] = x86.AJOC /* overflow clear (OF = 0) */ 168 instructions["JOS"] = x86.AJOS /* overflow set (OF = 1) */ 169 instructions["JP"] = x86.AJPS /* alternate */ 170 instructions["JPC"] = x86.AJPC /* parity clear (PF = 0) */ 171 instructions["JPE"] = x86.AJPS /* alternate */ 172 instructions["JPL"] = x86.AJPL /* non-negative (plus) (SF = 0) */ 173 instructions["JPO"] = x86.AJPC /* alternate */ 174 instructions["JPS"] = x86.AJPS /* parity set (PF = 1) */ 175 instructions["JS"] = x86.AJMI /* alternate */ 176 instructions["JZ"] = x86.AJEQ /* alternate */ 177 instructions["MASKMOVDQU"] = x86.AMASKMOVOU 178 instructions["MOVD"] = x86.AMOVQ 179 instructions["MOVDQ2Q"] = x86.AMOVQ 180 instructions["MOVNTDQ"] = x86.AMOVNTO 181 instructions["MOVOA"] = x86.AMOVO 182 instructions["PSLLDQ"] = x86.APSLLO 183 instructions["PSRLDQ"] = x86.APSRLO 184 instructions["PADDD"] = x86.APADDL 185 // Spellings originally used in CL 97235. 186 instructions["MOVBELL"] = x86.AMOVBEL 187 instructions["MOVBEQQ"] = x86.AMOVBEQ 188 instructions["MOVBEWW"] = x86.AMOVBEW 189 190 return &Arch{ 191 LinkArch: linkArch, 192 Instructions: instructions, 193 Register: register, 194 RegisterPrefix: nil, 195 RegisterNumber: nilRegisterNumber, 196 IsJump: jumpX86, 197 } 198 } 199 200 func archArm() *Arch { 201 register := make(map[string]int16) 202 // Create maps for easy lookup of instruction names etc. 203 // Note that there is no list of names as there is for x86. 204 for i := arm.REG_R0; i < arm.REG_SPSR; i++ { 205 register[obj.Rconv(i)] = int16(i) 206 } 207 // Avoid unintentionally clobbering g using R10. 208 delete(register, "R10") 209 register["g"] = arm.REG_R10 210 for i := 0; i < 16; i++ { 211 register[fmt.Sprintf("C%d", i)] = int16(i) 212 } 213 214 // Pseudo-registers. 215 register["SB"] = RSB 216 register["FP"] = RFP 217 register["PC"] = RPC 218 register["SP"] = RSP 219 registerPrefix := map[string]bool{ 220 "F": true, 221 "R": true, 222 } 223 224 // special operands for DMB/DSB instructions 225 register["MB_SY"] = arm.REG_MB_SY 226 register["MB_ST"] = arm.REG_MB_ST 227 register["MB_ISH"] = arm.REG_MB_ISH 228 register["MB_ISHST"] = arm.REG_MB_ISHST 229 register["MB_NSH"] = arm.REG_MB_NSH 230 register["MB_NSHST"] = arm.REG_MB_NSHST 231 register["MB_OSH"] = arm.REG_MB_OSH 232 register["MB_OSHST"] = arm.REG_MB_OSHST 233 234 instructions := make(map[string]obj.As) 235 for i, s := range obj.Anames { 236 instructions[s] = obj.As(i) 237 } 238 for i, s := range arm.Anames { 239 if obj.As(i) >= obj.A_ARCHSPECIFIC { 240 instructions[s] = obj.As(i) + obj.ABaseARM 241 } 242 } 243 // Annoying aliases. 244 instructions["B"] = obj.AJMP 245 instructions["BL"] = obj.ACALL 246 // MCR differs from MRC by the way fields of the word are encoded. 247 // (Details in arm.go). Here we add the instruction so parse will find 248 // it, but give it an opcode number known only to us. 249 instructions["MCR"] = aMCR 250 251 return &Arch{ 252 LinkArch: &arm.Linkarm, 253 Instructions: instructions, 254 Register: register, 255 RegisterPrefix: registerPrefix, 256 RegisterNumber: armRegisterNumber, 257 IsJump: jumpArm, 258 } 259 } 260 261 func archArm64() *Arch { 262 register := make(map[string]int16) 263 // Create maps for easy lookup of instruction names etc. 264 // Note that there is no list of names as there is for 386 and amd64. 265 register[obj.Rconv(arm64.REGSP)] = int16(arm64.REGSP) 266 for i := arm64.REG_R0; i <= arm64.REG_R31; i++ { 267 register[obj.Rconv(i)] = int16(i) 268 } 269 // Rename R18 to R18_PLATFORM to avoid accidental use. 270 register["R18_PLATFORM"] = register["R18"] 271 delete(register, "R18") 272 for i := arm64.REG_F0; i <= arm64.REG_F31; i++ { 273 register[obj.Rconv(i)] = int16(i) 274 } 275 for i := arm64.REG_V0; i <= arm64.REG_V31; i++ { 276 register[obj.Rconv(i)] = int16(i) 277 } 278 279 // System registers. 280 for i := 0; i < len(arm64.SystemReg); i++ { 281 register[arm64.SystemReg[i].Name] = arm64.SystemReg[i].Reg 282 } 283 284 register["LR"] = arm64.REGLINK 285 286 // Pseudo-registers. 287 register["SB"] = RSB 288 register["FP"] = RFP 289 register["PC"] = RPC 290 register["SP"] = RSP 291 // Avoid unintentionally clobbering g using R28. 292 delete(register, "R28") 293 register["g"] = arm64.REG_R28 294 registerPrefix := map[string]bool{ 295 "F": true, 296 "R": true, 297 "V": true, 298 } 299 300 instructions := make(map[string]obj.As) 301 for i, s := range obj.Anames { 302 instructions[s] = obj.As(i) 303 } 304 for i, s := range arm64.Anames { 305 if obj.As(i) >= obj.A_ARCHSPECIFIC { 306 instructions[s] = obj.As(i) + obj.ABaseARM64 307 } 308 } 309 // Annoying aliases. 310 instructions["B"] = arm64.AB 311 instructions["BL"] = arm64.ABL 312 313 return &Arch{ 314 LinkArch: &arm64.Linkarm64, 315 Instructions: instructions, 316 Register: register, 317 RegisterPrefix: registerPrefix, 318 RegisterNumber: arm64RegisterNumber, 319 IsJump: jumpArm64, 320 } 321 322 } 323 324 func archPPC64(linkArch *obj.LinkArch) *Arch { 325 register := make(map[string]int16) 326 // Create maps for easy lookup of instruction names etc. 327 // Note that there is no list of names as there is for x86. 328 for i := ppc64.REG_R0; i <= ppc64.REG_R31; i++ { 329 register[obj.Rconv(i)] = int16(i) 330 } 331 for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ { 332 register[obj.Rconv(i)] = int16(i) 333 } 334 for i := ppc64.REG_V0; i <= ppc64.REG_V31; i++ { 335 register[obj.Rconv(i)] = int16(i) 336 } 337 for i := ppc64.REG_VS0; i <= ppc64.REG_VS63; i++ { 338 register[obj.Rconv(i)] = int16(i) 339 } 340 for i := ppc64.REG_A0; i <= ppc64.REG_A7; i++ { 341 register[obj.Rconv(i)] = int16(i) 342 } 343 for i := ppc64.REG_CR0; i <= ppc64.REG_CR7; i++ { 344 register[obj.Rconv(i)] = int16(i) 345 } 346 for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ { 347 register[obj.Rconv(i)] = int16(i) 348 } 349 for i := ppc64.REG_CR0LT; i <= ppc64.REG_CR7SO; i++ { 350 register[obj.Rconv(i)] = int16(i) 351 } 352 register["CR"] = ppc64.REG_CR 353 register["XER"] = ppc64.REG_XER 354 register["LR"] = ppc64.REG_LR 355 register["CTR"] = ppc64.REG_CTR 356 register["FPSCR"] = ppc64.REG_FPSCR 357 register["MSR"] = ppc64.REG_MSR 358 // Pseudo-registers. 359 register["SB"] = RSB 360 register["FP"] = RFP 361 register["PC"] = RPC 362 // Avoid unintentionally clobbering g using R30. 363 delete(register, "R30") 364 register["g"] = ppc64.REG_R30 365 registerPrefix := map[string]bool{ 366 "CR": true, 367 "F": true, 368 "R": true, 369 "SPR": true, 370 } 371 372 instructions := make(map[string]obj.As) 373 for i, s := range obj.Anames { 374 instructions[s] = obj.As(i) 375 } 376 for i, s := range ppc64.Anames { 377 if obj.As(i) >= obj.A_ARCHSPECIFIC { 378 instructions[s] = obj.As(i) + obj.ABasePPC64 379 } 380 } 381 // The opcodes generated by x/arch's ppc64map are listed in 382 // a separate slice, add them too. 383 for i, s := range ppc64.GenAnames { 384 instructions[s] = obj.As(i) + ppc64.AFIRSTGEN 385 } 386 // Annoying aliases. 387 instructions["BR"] = ppc64.ABR 388 instructions["BL"] = ppc64.ABL 389 390 return &Arch{ 391 LinkArch: linkArch, 392 Instructions: instructions, 393 Register: register, 394 RegisterPrefix: registerPrefix, 395 RegisterNumber: ppc64RegisterNumber, 396 IsJump: jumpPPC64, 397 } 398 } 399 400 func archMips(linkArch *obj.LinkArch) *Arch { 401 register := make(map[string]int16) 402 // Create maps for easy lookup of instruction names etc. 403 // Note that there is no list of names as there is for x86. 404 for i := mips.REG_R0; i <= mips.REG_R31; i++ { 405 register[obj.Rconv(i)] = int16(i) 406 } 407 408 for i := mips.REG_F0; i <= mips.REG_F31; i++ { 409 register[obj.Rconv(i)] = int16(i) 410 } 411 for i := mips.REG_M0; i <= mips.REG_M31; i++ { 412 register[obj.Rconv(i)] = int16(i) 413 } 414 for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ { 415 register[obj.Rconv(i)] = int16(i) 416 } 417 register["HI"] = mips.REG_HI 418 register["LO"] = mips.REG_LO 419 // Pseudo-registers. 420 register["SB"] = RSB 421 register["FP"] = RFP 422 register["PC"] = RPC 423 // Avoid unintentionally clobbering g using R30. 424 delete(register, "R30") 425 register["g"] = mips.REG_R30 426 427 registerPrefix := map[string]bool{ 428 "F": true, 429 "FCR": true, 430 "M": true, 431 "R": true, 432 } 433 434 instructions := make(map[string]obj.As) 435 for i, s := range obj.Anames { 436 instructions[s] = obj.As(i) 437 } 438 for i, s := range mips.Anames { 439 if obj.As(i) >= obj.A_ARCHSPECIFIC { 440 instructions[s] = obj.As(i) + obj.ABaseMIPS 441 } 442 } 443 // Annoying alias. 444 instructions["JAL"] = mips.AJAL 445 446 return &Arch{ 447 LinkArch: linkArch, 448 Instructions: instructions, 449 Register: register, 450 RegisterPrefix: registerPrefix, 451 RegisterNumber: mipsRegisterNumber, 452 IsJump: jumpMIPS, 453 } 454 } 455 456 func archMips64(linkArch *obj.LinkArch) *Arch { 457 register := make(map[string]int16) 458 // Create maps for easy lookup of instruction names etc. 459 // Note that there is no list of names as there is for x86. 460 for i := mips.REG_R0; i <= mips.REG_R31; i++ { 461 register[obj.Rconv(i)] = int16(i) 462 } 463 for i := mips.REG_F0; i <= mips.REG_F31; i++ { 464 register[obj.Rconv(i)] = int16(i) 465 } 466 for i := mips.REG_M0; i <= mips.REG_M31; i++ { 467 register[obj.Rconv(i)] = int16(i) 468 } 469 for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ { 470 register[obj.Rconv(i)] = int16(i) 471 } 472 for i := mips.REG_W0; i <= mips.REG_W31; i++ { 473 register[obj.Rconv(i)] = int16(i) 474 } 475 register["HI"] = mips.REG_HI 476 register["LO"] = mips.REG_LO 477 // Pseudo-registers. 478 register["SB"] = RSB 479 register["FP"] = RFP 480 register["PC"] = RPC 481 // Avoid unintentionally clobbering g using R30. 482 delete(register, "R30") 483 register["g"] = mips.REG_R30 484 // Avoid unintentionally clobbering RSB using R28. 485 delete(register, "R28") 486 register["RSB"] = mips.REG_R28 487 registerPrefix := map[string]bool{ 488 "F": true, 489 "FCR": true, 490 "M": true, 491 "R": true, 492 "W": true, 493 } 494 495 instructions := make(map[string]obj.As) 496 for i, s := range obj.Anames { 497 instructions[s] = obj.As(i) 498 } 499 for i, s := range mips.Anames { 500 if obj.As(i) >= obj.A_ARCHSPECIFIC { 501 instructions[s] = obj.As(i) + obj.ABaseMIPS 502 } 503 } 504 // Annoying alias. 505 instructions["JAL"] = mips.AJAL 506 507 return &Arch{ 508 LinkArch: linkArch, 509 Instructions: instructions, 510 Register: register, 511 RegisterPrefix: registerPrefix, 512 RegisterNumber: mipsRegisterNumber, 513 IsJump: jumpMIPS, 514 } 515 } 516 517 func archLoong64(linkArch *obj.LinkArch) *Arch { 518 register := make(map[string]int16) 519 // Create maps for easy lookup of instruction names etc. 520 // Note that there is no list of names as there is for x86. 521 for i := loong64.REG_R0; i <= loong64.REG_R31; i++ { 522 register[obj.Rconv(i)] = int16(i) 523 } 524 for i := loong64.REG_F0; i <= loong64.REG_F31; i++ { 525 register[obj.Rconv(i)] = int16(i) 526 } 527 for i := loong64.REG_FCSR0; i <= loong64.REG_FCSR31; i++ { 528 register[obj.Rconv(i)] = int16(i) 529 } 530 for i := loong64.REG_FCC0; i <= loong64.REG_FCC31; i++ { 531 register[obj.Rconv(i)] = int16(i) 532 } 533 // Pseudo-registers. 534 register["SB"] = RSB 535 register["FP"] = RFP 536 register["PC"] = RPC 537 // Avoid unintentionally clobbering g using R22. 538 delete(register, "R22") 539 register["g"] = loong64.REG_R22 540 registerPrefix := map[string]bool{ 541 "F": true, 542 "FCSR": true, 543 "FCC": true, 544 "R": true, 545 } 546 547 instructions := make(map[string]obj.As) 548 for i, s := range obj.Anames { 549 instructions[s] = obj.As(i) 550 } 551 for i, s := range loong64.Anames { 552 if obj.As(i) >= obj.A_ARCHSPECIFIC { 553 instructions[s] = obj.As(i) + obj.ABaseLoong64 554 } 555 } 556 // Annoying alias. 557 instructions["JAL"] = loong64.AJAL 558 559 return &Arch{ 560 LinkArch: linkArch, 561 Instructions: instructions, 562 Register: register, 563 RegisterPrefix: registerPrefix, 564 RegisterNumber: loong64RegisterNumber, 565 IsJump: jumpLoong64, 566 } 567 } 568 569 func archRISCV64(shared bool) *Arch { 570 register := make(map[string]int16) 571 572 // Standard register names. 573 for i := riscv.REG_X0; i <= riscv.REG_X31; i++ { 574 // Disallow X3 in shared mode, as this will likely be used as the 575 // GP register, which could result in problems in non-Go code, 576 // including signal handlers. 577 if shared && i == riscv.REG_GP { 578 continue 579 } 580 if i == riscv.REG_TP || i == riscv.REG_G { 581 continue 582 } 583 name := fmt.Sprintf("X%d", i-riscv.REG_X0) 584 register[name] = int16(i) 585 } 586 for i := riscv.REG_F0; i <= riscv.REG_F31; i++ { 587 name := fmt.Sprintf("F%d", i-riscv.REG_F0) 588 register[name] = int16(i) 589 } 590 591 // General registers with ABI names. 592 register["ZERO"] = riscv.REG_ZERO 593 register["RA"] = riscv.REG_RA 594 register["SP"] = riscv.REG_SP 595 register["GP"] = riscv.REG_GP 596 register["TP"] = riscv.REG_TP 597 register["T0"] = riscv.REG_T0 598 register["T1"] = riscv.REG_T1 599 register["T2"] = riscv.REG_T2 600 register["S0"] = riscv.REG_S0 601 register["S1"] = riscv.REG_S1 602 register["A0"] = riscv.REG_A0 603 register["A1"] = riscv.REG_A1 604 register["A2"] = riscv.REG_A2 605 register["A3"] = riscv.REG_A3 606 register["A4"] = riscv.REG_A4 607 register["A5"] = riscv.REG_A5 608 register["A6"] = riscv.REG_A6 609 register["A7"] = riscv.REG_A7 610 register["S2"] = riscv.REG_S2 611 register["S3"] = riscv.REG_S3 612 register["S4"] = riscv.REG_S4 613 register["S5"] = riscv.REG_S5 614 register["S6"] = riscv.REG_S6 615 register["S7"] = riscv.REG_S7 616 register["S8"] = riscv.REG_S8 617 register["S9"] = riscv.REG_S9 618 register["S10"] = riscv.REG_S10 619 // Skip S11 as it is the g register. 620 register["T3"] = riscv.REG_T3 621 register["T4"] = riscv.REG_T4 622 register["T5"] = riscv.REG_T5 623 register["T6"] = riscv.REG_T6 624 625 // Go runtime register names. 626 register["g"] = riscv.REG_G 627 register["CTXT"] = riscv.REG_CTXT 628 register["TMP"] = riscv.REG_TMP 629 630 // ABI names for floating point register. 631 register["FT0"] = riscv.REG_FT0 632 register["FT1"] = riscv.REG_FT1 633 register["FT2"] = riscv.REG_FT2 634 register["FT3"] = riscv.REG_FT3 635 register["FT4"] = riscv.REG_FT4 636 register["FT5"] = riscv.REG_FT5 637 register["FT6"] = riscv.REG_FT6 638 register["FT7"] = riscv.REG_FT7 639 register["FS0"] = riscv.REG_FS0 640 register["FS1"] = riscv.REG_FS1 641 register["FA0"] = riscv.REG_FA0 642 register["FA1"] = riscv.REG_FA1 643 register["FA2"] = riscv.REG_FA2 644 register["FA3"] = riscv.REG_FA3 645 register["FA4"] = riscv.REG_FA4 646 register["FA5"] = riscv.REG_FA5 647 register["FA6"] = riscv.REG_FA6 648 register["FA7"] = riscv.REG_FA7 649 register["FS2"] = riscv.REG_FS2 650 register["FS3"] = riscv.REG_FS3 651 register["FS4"] = riscv.REG_FS4 652 register["FS5"] = riscv.REG_FS5 653 register["FS6"] = riscv.REG_FS6 654 register["FS7"] = riscv.REG_FS7 655 register["FS8"] = riscv.REG_FS8 656 register["FS9"] = riscv.REG_FS9 657 register["FS10"] = riscv.REG_FS10 658 register["FS11"] = riscv.REG_FS11 659 register["FT8"] = riscv.REG_FT8 660 register["FT9"] = riscv.REG_FT9 661 register["FT10"] = riscv.REG_FT10 662 register["FT11"] = riscv.REG_FT11 663 664 // Pseudo-registers. 665 register["SB"] = RSB 666 register["FP"] = RFP 667 register["PC"] = RPC 668 669 instructions := make(map[string]obj.As) 670 for i, s := range obj.Anames { 671 instructions[s] = obj.As(i) 672 } 673 for i, s := range riscv.Anames { 674 if obj.As(i) >= obj.A_ARCHSPECIFIC { 675 instructions[s] = obj.As(i) + obj.ABaseRISCV 676 } 677 } 678 679 return &Arch{ 680 LinkArch: &riscv.LinkRISCV64, 681 Instructions: instructions, 682 Register: register, 683 RegisterPrefix: nil, 684 RegisterNumber: nilRegisterNumber, 685 IsJump: jumpRISCV, 686 } 687 } 688 689 func archS390x() *Arch { 690 register := make(map[string]int16) 691 // Create maps for easy lookup of instruction names etc. 692 // Note that there is no list of names as there is for x86. 693 for i := s390x.REG_R0; i <= s390x.REG_R15; i++ { 694 register[obj.Rconv(i)] = int16(i) 695 } 696 for i := s390x.REG_F0; i <= s390x.REG_F15; i++ { 697 register[obj.Rconv(i)] = int16(i) 698 } 699 for i := s390x.REG_V0; i <= s390x.REG_V31; i++ { 700 register[obj.Rconv(i)] = int16(i) 701 } 702 for i := s390x.REG_AR0; i <= s390x.REG_AR15; i++ { 703 register[obj.Rconv(i)] = int16(i) 704 } 705 register["LR"] = s390x.REG_LR 706 // Pseudo-registers. 707 register["SB"] = RSB 708 register["FP"] = RFP 709 register["PC"] = RPC 710 // Avoid unintentionally clobbering g using R13. 711 delete(register, "R13") 712 register["g"] = s390x.REG_R13 713 registerPrefix := map[string]bool{ 714 "AR": true, 715 "F": true, 716 "R": true, 717 } 718 719 instructions := make(map[string]obj.As) 720 for i, s := range obj.Anames { 721 instructions[s] = obj.As(i) 722 } 723 for i, s := range s390x.Anames { 724 if obj.As(i) >= obj.A_ARCHSPECIFIC { 725 instructions[s] = obj.As(i) + obj.ABaseS390X 726 } 727 } 728 // Annoying aliases. 729 instructions["BR"] = s390x.ABR 730 instructions["BL"] = s390x.ABL 731 732 return &Arch{ 733 LinkArch: &s390x.Links390x, 734 Instructions: instructions, 735 Register: register, 736 RegisterPrefix: registerPrefix, 737 RegisterNumber: s390xRegisterNumber, 738 IsJump: jumpS390x, 739 } 740 } 741 742 func archWasm() *Arch { 743 instructions := make(map[string]obj.As) 744 for i, s := range obj.Anames { 745 instructions[s] = obj.As(i) 746 } 747 for i, s := range wasm.Anames { 748 if obj.As(i) >= obj.A_ARCHSPECIFIC { 749 instructions[s] = obj.As(i) + obj.ABaseWasm 750 } 751 } 752 753 return &Arch{ 754 LinkArch: &wasm.Linkwasm, 755 Instructions: instructions, 756 Register: wasm.Register, 757 RegisterPrefix: nil, 758 RegisterNumber: nilRegisterNumber, 759 IsJump: jumpWasm, 760 } 761 }