arch.go raw

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