gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

arch.go (21186B)


      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 }