[chore] Update gin to v1.9.0 (#1553)

This commit is contained in:
Daenney
2023-02-25 13:12:40 +01:00
committed by GitHub
parent 689a10fe17
commit ecdc8379fa
347 changed files with 166814 additions and 3671 deletions

View File

@ -0,0 +1,716 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package arch defines architecture-specific information and support functions.
package arch
import (
"github.com/twitchyliquid64/golang-asm/obj"
"github.com/twitchyliquid64/golang-asm/obj/arm"
"github.com/twitchyliquid64/golang-asm/obj/arm64"
"github.com/twitchyliquid64/golang-asm/obj/mips"
"github.com/twitchyliquid64/golang-asm/obj/ppc64"
"github.com/twitchyliquid64/golang-asm/obj/riscv"
"github.com/twitchyliquid64/golang-asm/obj/s390x"
"github.com/twitchyliquid64/golang-asm/obj/wasm"
"github.com/twitchyliquid64/golang-asm/obj/x86"
"fmt"
"strings"
)
// Pseudo-registers whose names are the constant name without the leading R.
const (
RFP = -(iota + 1)
RSB
RSP
RPC
)
// Arch wraps the link architecture object with more architecture-specific information.
type Arch struct {
*obj.LinkArch
// Map of instruction names to enumeration.
Instructions map[string]obj.As
// Map of register names to enumeration.
Register map[string]int16
// Table of register prefix names. These are things like R for R(0) and SPR for SPR(268).
RegisterPrefix map[string]bool
// RegisterNumber converts R(10) into arm.REG_R10.
RegisterNumber func(string, int16) (int16, bool)
// Instruction is a jump.
IsJump func(word string) bool
}
// nilRegisterNumber is the register number function for architectures
// that do not accept the R(N) notation. It always returns failure.
func nilRegisterNumber(name string, n int16) (int16, bool) {
return 0, false
}
// Set configures the architecture specified by GOARCH and returns its representation.
// It returns nil if GOARCH is not recognized.
func Set(GOARCH string) *Arch {
switch GOARCH {
case "386":
return archX86(&x86.Link386)
case "amd64":
return archX86(&x86.Linkamd64)
case "arm":
return archArm()
case "arm64":
return archArm64()
case "mips":
return archMips(&mips.Linkmips)
case "mipsle":
return archMips(&mips.Linkmipsle)
case "mips64":
return archMips64(&mips.Linkmips64)
case "mips64le":
return archMips64(&mips.Linkmips64le)
case "ppc64":
return archPPC64(&ppc64.Linkppc64)
case "ppc64le":
return archPPC64(&ppc64.Linkppc64le)
case "riscv64":
return archRISCV64()
case "s390x":
return archS390x()
case "wasm":
return archWasm()
}
return nil
}
func jumpX86(word string) bool {
return word[0] == 'J' || word == "CALL" || strings.HasPrefix(word, "LOOP") || word == "XBEGIN"
}
func jumpRISCV(word string) bool {
switch word {
case "BEQ", "BEQZ", "BGE", "BGEU", "BGEZ", "BGT", "BGTU", "BGTZ", "BLE", "BLEU", "BLEZ",
"BLT", "BLTU", "BLTZ", "BNE", "BNEZ", "CALL", "JAL", "JALR", "JMP":
return true
}
return false
}
func jumpWasm(word string) bool {
return word == "JMP" || word == "CALL" || word == "Call" || word == "Br" || word == "BrIf"
}
func archX86(linkArch *obj.LinkArch) *Arch {
register := make(map[string]int16)
// Create maps for easy lookup of instruction names etc.
for i, s := range x86.Register {
register[s] = int16(i + x86.REG_AL)
}
// Pseudo-registers.
register["SB"] = RSB
register["FP"] = RFP
register["PC"] = RPC
// Register prefix not used on this architecture.
instructions := make(map[string]obj.As)
for i, s := range obj.Anames {
instructions[s] = obj.As(i)
}
for i, s := range x86.Anames {
if obj.As(i) >= obj.A_ARCHSPECIFIC {
instructions[s] = obj.As(i) + obj.ABaseAMD64
}
}
// Annoying aliases.
instructions["JA"] = x86.AJHI /* alternate */
instructions["JAE"] = x86.AJCC /* alternate */
instructions["JB"] = x86.AJCS /* alternate */
instructions["JBE"] = x86.AJLS /* alternate */
instructions["JC"] = x86.AJCS /* alternate */
instructions["JCC"] = x86.AJCC /* carry clear (CF = 0) */
instructions["JCS"] = x86.AJCS /* carry set (CF = 1) */
instructions["JE"] = x86.AJEQ /* alternate */
instructions["JEQ"] = x86.AJEQ /* equal (ZF = 1) */
instructions["JG"] = x86.AJGT /* alternate */
instructions["JGE"] = x86.AJGE /* greater than or equal (signed) (SF = OF) */
instructions["JGT"] = x86.AJGT /* greater than (signed) (ZF = 0 && SF = OF) */
instructions["JHI"] = x86.AJHI /* higher (unsigned) (CF = 0 && ZF = 0) */
instructions["JHS"] = x86.AJCC /* alternate */
instructions["JL"] = x86.AJLT /* alternate */
instructions["JLE"] = x86.AJLE /* less than or equal (signed) (ZF = 1 || SF != OF) */
instructions["JLO"] = x86.AJCS /* alternate */
instructions["JLS"] = x86.AJLS /* lower or same (unsigned) (CF = 1 || ZF = 1) */
instructions["JLT"] = x86.AJLT /* less than (signed) (SF != OF) */
instructions["JMI"] = x86.AJMI /* negative (minus) (SF = 1) */
instructions["JNA"] = x86.AJLS /* alternate */
instructions["JNAE"] = x86.AJCS /* alternate */
instructions["JNB"] = x86.AJCC /* alternate */
instructions["JNBE"] = x86.AJHI /* alternate */
instructions["JNC"] = x86.AJCC /* alternate */
instructions["JNE"] = x86.AJNE /* not equal (ZF = 0) */
instructions["JNG"] = x86.AJLE /* alternate */
instructions["JNGE"] = x86.AJLT /* alternate */
instructions["JNL"] = x86.AJGE /* alternate */
instructions["JNLE"] = x86.AJGT /* alternate */
instructions["JNO"] = x86.AJOC /* alternate */
instructions["JNP"] = x86.AJPC /* alternate */
instructions["JNS"] = x86.AJPL /* alternate */
instructions["JNZ"] = x86.AJNE /* alternate */
instructions["JO"] = x86.AJOS /* alternate */
instructions["JOC"] = x86.AJOC /* overflow clear (OF = 0) */
instructions["JOS"] = x86.AJOS /* overflow set (OF = 1) */
instructions["JP"] = x86.AJPS /* alternate */
instructions["JPC"] = x86.AJPC /* parity clear (PF = 0) */
instructions["JPE"] = x86.AJPS /* alternate */
instructions["JPL"] = x86.AJPL /* non-negative (plus) (SF = 0) */
instructions["JPO"] = x86.AJPC /* alternate */
instructions["JPS"] = x86.AJPS /* parity set (PF = 1) */
instructions["JS"] = x86.AJMI /* alternate */
instructions["JZ"] = x86.AJEQ /* alternate */
instructions["MASKMOVDQU"] = x86.AMASKMOVOU
instructions["MOVD"] = x86.AMOVQ
instructions["MOVDQ2Q"] = x86.AMOVQ
instructions["MOVNTDQ"] = x86.AMOVNTO
instructions["MOVOA"] = x86.AMOVO
instructions["PSLLDQ"] = x86.APSLLO
instructions["PSRLDQ"] = x86.APSRLO
instructions["PADDD"] = x86.APADDL
return &Arch{
LinkArch: linkArch,
Instructions: instructions,
Register: register,
RegisterPrefix: nil,
RegisterNumber: nilRegisterNumber,
IsJump: jumpX86,
}
}
func archArm() *Arch {
register := make(map[string]int16)
// Create maps for easy lookup of instruction names etc.
// Note that there is no list of names as there is for x86.
for i := arm.REG_R0; i < arm.REG_SPSR; i++ {
register[obj.Rconv(i)] = int16(i)
}
// Avoid unintentionally clobbering g using R10.
delete(register, "R10")
register["g"] = arm.REG_R10
for i := 0; i < 16; i++ {
register[fmt.Sprintf("C%d", i)] = int16(i)
}
// Pseudo-registers.
register["SB"] = RSB
register["FP"] = RFP
register["PC"] = RPC
register["SP"] = RSP
registerPrefix := map[string]bool{
"F": true,
"R": true,
}
// special operands for DMB/DSB instructions
register["MB_SY"] = arm.REG_MB_SY
register["MB_ST"] = arm.REG_MB_ST
register["MB_ISH"] = arm.REG_MB_ISH
register["MB_ISHST"] = arm.REG_MB_ISHST
register["MB_NSH"] = arm.REG_MB_NSH
register["MB_NSHST"] = arm.REG_MB_NSHST
register["MB_OSH"] = arm.REG_MB_OSH
register["MB_OSHST"] = arm.REG_MB_OSHST
instructions := make(map[string]obj.As)
for i, s := range obj.Anames {
instructions[s] = obj.As(i)
}
for i, s := range arm.Anames {
if obj.As(i) >= obj.A_ARCHSPECIFIC {
instructions[s] = obj.As(i) + obj.ABaseARM
}
}
// Annoying aliases.
instructions["B"] = obj.AJMP
instructions["BL"] = obj.ACALL
// MCR differs from MRC by the way fields of the word are encoded.
// (Details in arm.go). Here we add the instruction so parse will find
// it, but give it an opcode number known only to us.
instructions["MCR"] = aMCR
return &Arch{
LinkArch: &arm.Linkarm,
Instructions: instructions,
Register: register,
RegisterPrefix: registerPrefix,
RegisterNumber: armRegisterNumber,
IsJump: jumpArm,
}
}
func archArm64() *Arch {
register := make(map[string]int16)
// Create maps for easy lookup of instruction names etc.
// Note that there is no list of names as there is for 386 and amd64.
register[obj.Rconv(arm64.REGSP)] = int16(arm64.REGSP)
for i := arm64.REG_R0; i <= arm64.REG_R31; i++ {
register[obj.Rconv(i)] = int16(i)
}
// Rename R18 to R18_PLATFORM to avoid accidental use.
register["R18_PLATFORM"] = register["R18"]
delete(register, "R18")
for i := arm64.REG_F0; i <= arm64.REG_F31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := arm64.REG_V0; i <= arm64.REG_V31; i++ {
register[obj.Rconv(i)] = int16(i)
}
// System registers.
for i := 0; i < len(arm64.SystemReg); i++ {
register[arm64.SystemReg[i].Name] = arm64.SystemReg[i].Reg
}
register["LR"] = arm64.REGLINK
register["DAIFSet"] = arm64.REG_DAIFSet
register["DAIFClr"] = arm64.REG_DAIFClr
register["PLDL1KEEP"] = arm64.REG_PLDL1KEEP
register["PLDL1STRM"] = arm64.REG_PLDL1STRM
register["PLDL2KEEP"] = arm64.REG_PLDL2KEEP
register["PLDL2STRM"] = arm64.REG_PLDL2STRM
register["PLDL3KEEP"] = arm64.REG_PLDL3KEEP
register["PLDL3STRM"] = arm64.REG_PLDL3STRM
register["PLIL1KEEP"] = arm64.REG_PLIL1KEEP
register["PLIL1STRM"] = arm64.REG_PLIL1STRM
register["PLIL2KEEP"] = arm64.REG_PLIL2KEEP
register["PLIL2STRM"] = arm64.REG_PLIL2STRM
register["PLIL3KEEP"] = arm64.REG_PLIL3KEEP
register["PLIL3STRM"] = arm64.REG_PLIL3STRM
register["PSTL1KEEP"] = arm64.REG_PSTL1KEEP
register["PSTL1STRM"] = arm64.REG_PSTL1STRM
register["PSTL2KEEP"] = arm64.REG_PSTL2KEEP
register["PSTL2STRM"] = arm64.REG_PSTL2STRM
register["PSTL3KEEP"] = arm64.REG_PSTL3KEEP
register["PSTL3STRM"] = arm64.REG_PSTL3STRM
// Conditional operators, like EQ, NE, etc.
register["EQ"] = arm64.COND_EQ
register["NE"] = arm64.COND_NE
register["HS"] = arm64.COND_HS
register["CS"] = arm64.COND_HS
register["LO"] = arm64.COND_LO
register["CC"] = arm64.COND_LO
register["MI"] = arm64.COND_MI
register["PL"] = arm64.COND_PL
register["VS"] = arm64.COND_VS
register["VC"] = arm64.COND_VC
register["HI"] = arm64.COND_HI
register["LS"] = arm64.COND_LS
register["GE"] = arm64.COND_GE
register["LT"] = arm64.COND_LT
register["GT"] = arm64.COND_GT
register["LE"] = arm64.COND_LE
register["AL"] = arm64.COND_AL
register["NV"] = arm64.COND_NV
// Pseudo-registers.
register["SB"] = RSB
register["FP"] = RFP
register["PC"] = RPC
register["SP"] = RSP
// Avoid unintentionally clobbering g using R28.
delete(register, "R28")
register["g"] = arm64.REG_R28
registerPrefix := map[string]bool{
"F": true,
"R": true,
"V": true,
}
instructions := make(map[string]obj.As)
for i, s := range obj.Anames {
instructions[s] = obj.As(i)
}
for i, s := range arm64.Anames {
if obj.As(i) >= obj.A_ARCHSPECIFIC {
instructions[s] = obj.As(i) + obj.ABaseARM64
}
}
// Annoying aliases.
instructions["B"] = arm64.AB
instructions["BL"] = arm64.ABL
return &Arch{
LinkArch: &arm64.Linkarm64,
Instructions: instructions,
Register: register,
RegisterPrefix: registerPrefix,
RegisterNumber: arm64RegisterNumber,
IsJump: jumpArm64,
}
}
func archPPC64(linkArch *obj.LinkArch) *Arch {
register := make(map[string]int16)
// Create maps for easy lookup of instruction names etc.
// Note that there is no list of names as there is for x86.
for i := ppc64.REG_R0; i <= ppc64.REG_R31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := ppc64.REG_V0; i <= ppc64.REG_V31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := ppc64.REG_VS0; i <= ppc64.REG_VS63; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := ppc64.REG_CR0; i <= ppc64.REG_CR7; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ {
register[obj.Rconv(i)] = int16(i)
}
register["CR"] = ppc64.REG_CR
register["XER"] = ppc64.REG_XER
register["LR"] = ppc64.REG_LR
register["CTR"] = ppc64.REG_CTR
register["FPSCR"] = ppc64.REG_FPSCR
register["MSR"] = ppc64.REG_MSR
// Pseudo-registers.
register["SB"] = RSB
register["FP"] = RFP
register["PC"] = RPC
// Avoid unintentionally clobbering g using R30.
delete(register, "R30")
register["g"] = ppc64.REG_R30
registerPrefix := map[string]bool{
"CR": true,
"F": true,
"R": true,
"SPR": true,
}
instructions := make(map[string]obj.As)
for i, s := range obj.Anames {
instructions[s] = obj.As(i)
}
for i, s := range ppc64.Anames {
if obj.As(i) >= obj.A_ARCHSPECIFIC {
instructions[s] = obj.As(i) + obj.ABasePPC64
}
}
// Annoying aliases.
instructions["BR"] = ppc64.ABR
instructions["BL"] = ppc64.ABL
return &Arch{
LinkArch: linkArch,
Instructions: instructions,
Register: register,
RegisterPrefix: registerPrefix,
RegisterNumber: ppc64RegisterNumber,
IsJump: jumpPPC64,
}
}
func archMips(linkArch *obj.LinkArch) *Arch {
register := make(map[string]int16)
// Create maps for easy lookup of instruction names etc.
// Note that there is no list of names as there is for x86.
for i := mips.REG_R0; i <= mips.REG_R31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := mips.REG_F0; i <= mips.REG_F31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := mips.REG_M0; i <= mips.REG_M31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
register[obj.Rconv(i)] = int16(i)
}
register["HI"] = mips.REG_HI
register["LO"] = mips.REG_LO
// Pseudo-registers.
register["SB"] = RSB
register["FP"] = RFP
register["PC"] = RPC
// Avoid unintentionally clobbering g using R30.
delete(register, "R30")
register["g"] = mips.REG_R30
registerPrefix := map[string]bool{
"F": true,
"FCR": true,
"M": true,
"R": true,
}
instructions := make(map[string]obj.As)
for i, s := range obj.Anames {
instructions[s] = obj.As(i)
}
for i, s := range mips.Anames {
if obj.As(i) >= obj.A_ARCHSPECIFIC {
instructions[s] = obj.As(i) + obj.ABaseMIPS
}
}
// Annoying alias.
instructions["JAL"] = mips.AJAL
return &Arch{
LinkArch: linkArch,
Instructions: instructions,
Register: register,
RegisterPrefix: registerPrefix,
RegisterNumber: mipsRegisterNumber,
IsJump: jumpMIPS,
}
}
func archMips64(linkArch *obj.LinkArch) *Arch {
register := make(map[string]int16)
// Create maps for easy lookup of instruction names etc.
// Note that there is no list of names as there is for x86.
for i := mips.REG_R0; i <= mips.REG_R31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := mips.REG_F0; i <= mips.REG_F31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := mips.REG_M0; i <= mips.REG_M31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := mips.REG_W0; i <= mips.REG_W31; i++ {
register[obj.Rconv(i)] = int16(i)
}
register["HI"] = mips.REG_HI
register["LO"] = mips.REG_LO
// Pseudo-registers.
register["SB"] = RSB
register["FP"] = RFP
register["PC"] = RPC
// Avoid unintentionally clobbering g using R30.
delete(register, "R30")
register["g"] = mips.REG_R30
// Avoid unintentionally clobbering RSB using R28.
delete(register, "R28")
register["RSB"] = mips.REG_R28
registerPrefix := map[string]bool{
"F": true,
"FCR": true,
"M": true,
"R": true,
"W": true,
}
instructions := make(map[string]obj.As)
for i, s := range obj.Anames {
instructions[s] = obj.As(i)
}
for i, s := range mips.Anames {
if obj.As(i) >= obj.A_ARCHSPECIFIC {
instructions[s] = obj.As(i) + obj.ABaseMIPS
}
}
// Annoying alias.
instructions["JAL"] = mips.AJAL
return &Arch{
LinkArch: linkArch,
Instructions: instructions,
Register: register,
RegisterPrefix: registerPrefix,
RegisterNumber: mipsRegisterNumber,
IsJump: jumpMIPS,
}
}
func archRISCV64() *Arch {
register := make(map[string]int16)
// Standard register names.
for i := riscv.REG_X0; i <= riscv.REG_X31; i++ {
name := fmt.Sprintf("X%d", i-riscv.REG_X0)
register[name] = int16(i)
}
for i := riscv.REG_F0; i <= riscv.REG_F31; i++ {
name := fmt.Sprintf("F%d", i-riscv.REG_F0)
register[name] = int16(i)
}
// General registers with ABI names.
register["ZERO"] = riscv.REG_ZERO
register["RA"] = riscv.REG_RA
register["SP"] = riscv.REG_SP
register["GP"] = riscv.REG_GP
register["TP"] = riscv.REG_TP
register["T0"] = riscv.REG_T0
register["T1"] = riscv.REG_T1
register["T2"] = riscv.REG_T2
register["S0"] = riscv.REG_S0
register["S1"] = riscv.REG_S1
register["A0"] = riscv.REG_A0
register["A1"] = riscv.REG_A1
register["A2"] = riscv.REG_A2
register["A3"] = riscv.REG_A3
register["A4"] = riscv.REG_A4
register["A5"] = riscv.REG_A5
register["A6"] = riscv.REG_A6
register["A7"] = riscv.REG_A7
register["S2"] = riscv.REG_S2
register["S3"] = riscv.REG_S3
register["S4"] = riscv.REG_S4
register["S5"] = riscv.REG_S5
register["S6"] = riscv.REG_S6
register["S7"] = riscv.REG_S7
register["S8"] = riscv.REG_S8
register["S9"] = riscv.REG_S9
register["S10"] = riscv.REG_S10
register["S11"] = riscv.REG_S11
register["T3"] = riscv.REG_T3
register["T4"] = riscv.REG_T4
register["T5"] = riscv.REG_T5
register["T6"] = riscv.REG_T6
// Go runtime register names.
register["g"] = riscv.REG_G
register["CTXT"] = riscv.REG_CTXT
register["TMP"] = riscv.REG_TMP
// ABI names for floating point register.
register["FT0"] = riscv.REG_FT0
register["FT1"] = riscv.REG_FT1
register["FT2"] = riscv.REG_FT2
register["FT3"] = riscv.REG_FT3
register["FT4"] = riscv.REG_FT4
register["FT5"] = riscv.REG_FT5
register["FT6"] = riscv.REG_FT6
register["FT7"] = riscv.REG_FT7
register["FS0"] = riscv.REG_FS0
register["FS1"] = riscv.REG_FS1
register["FA0"] = riscv.REG_FA0
register["FA1"] = riscv.REG_FA1
register["FA2"] = riscv.REG_FA2
register["FA3"] = riscv.REG_FA3
register["FA4"] = riscv.REG_FA4
register["FA5"] = riscv.REG_FA5
register["FA6"] = riscv.REG_FA6
register["FA7"] = riscv.REG_FA7
register["FS2"] = riscv.REG_FS2
register["FS3"] = riscv.REG_FS3
register["FS4"] = riscv.REG_FS4
register["FS5"] = riscv.REG_FS5
register["FS6"] = riscv.REG_FS6
register["FS7"] = riscv.REG_FS7
register["FS8"] = riscv.REG_FS8
register["FS9"] = riscv.REG_FS9
register["FS10"] = riscv.REG_FS10
register["FS11"] = riscv.REG_FS11
register["FT8"] = riscv.REG_FT8
register["FT9"] = riscv.REG_FT9
register["FT10"] = riscv.REG_FT10
register["FT11"] = riscv.REG_FT11
// Pseudo-registers.
register["SB"] = RSB
register["FP"] = RFP
register["PC"] = RPC
instructions := make(map[string]obj.As)
for i, s := range obj.Anames {
instructions[s] = obj.As(i)
}
for i, s := range riscv.Anames {
if obj.As(i) >= obj.A_ARCHSPECIFIC {
instructions[s] = obj.As(i) + obj.ABaseRISCV
}
}
return &Arch{
LinkArch: &riscv.LinkRISCV64,
Instructions: instructions,
Register: register,
RegisterPrefix: nil,
RegisterNumber: nilRegisterNumber,
IsJump: jumpRISCV,
}
}
func archS390x() *Arch {
register := make(map[string]int16)
// Create maps for easy lookup of instruction names etc.
// Note that there is no list of names as there is for x86.
for i := s390x.REG_R0; i <= s390x.REG_R15; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := s390x.REG_F0; i <= s390x.REG_F15; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := s390x.REG_V0; i <= s390x.REG_V31; i++ {
register[obj.Rconv(i)] = int16(i)
}
for i := s390x.REG_AR0; i <= s390x.REG_AR15; i++ {
register[obj.Rconv(i)] = int16(i)
}
register["LR"] = s390x.REG_LR
// Pseudo-registers.
register["SB"] = RSB
register["FP"] = RFP
register["PC"] = RPC
// Avoid unintentionally clobbering g using R13.
delete(register, "R13")
register["g"] = s390x.REG_R13
registerPrefix := map[string]bool{
"AR": true,
"F": true,
"R": true,
}
instructions := make(map[string]obj.As)
for i, s := range obj.Anames {
instructions[s] = obj.As(i)
}
for i, s := range s390x.Anames {
if obj.As(i) >= obj.A_ARCHSPECIFIC {
instructions[s] = obj.As(i) + obj.ABaseS390X
}
}
// Annoying aliases.
instructions["BR"] = s390x.ABR
instructions["BL"] = s390x.ABL
return &Arch{
LinkArch: &s390x.Links390x,
Instructions: instructions,
Register: register,
RegisterPrefix: registerPrefix,
RegisterNumber: s390xRegisterNumber,
IsJump: jumpS390x,
}
}
func archWasm() *Arch {
instructions := make(map[string]obj.As)
for i, s := range obj.Anames {
instructions[s] = obj.As(i)
}
for i, s := range wasm.Anames {
if obj.As(i) >= obj.A_ARCHSPECIFIC {
instructions[s] = obj.As(i) + obj.ABaseWasm
}
}
return &Arch{
LinkArch: &wasm.Linkwasm,
Instructions: instructions,
Register: wasm.Register,
RegisterPrefix: nil,
RegisterNumber: nilRegisterNumber,
IsJump: jumpWasm,
}
}

View File

@ -0,0 +1,257 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file encapsulates some of the odd characteristics of the ARM
// instruction set, to minimize its interaction with the core of the
// assembler.
package arch
import (
"strings"
"github.com/twitchyliquid64/golang-asm/obj"
"github.com/twitchyliquid64/golang-asm/obj/arm"
)
var armLS = map[string]uint8{
"U": arm.C_UBIT,
"S": arm.C_SBIT,
"W": arm.C_WBIT,
"P": arm.C_PBIT,
"PW": arm.C_WBIT | arm.C_PBIT,
"WP": arm.C_WBIT | arm.C_PBIT,
}
var armSCOND = map[string]uint8{
"EQ": arm.C_SCOND_EQ,
"NE": arm.C_SCOND_NE,
"CS": arm.C_SCOND_HS,
"HS": arm.C_SCOND_HS,
"CC": arm.C_SCOND_LO,
"LO": arm.C_SCOND_LO,
"MI": arm.C_SCOND_MI,
"PL": arm.C_SCOND_PL,
"VS": arm.C_SCOND_VS,
"VC": arm.C_SCOND_VC,
"HI": arm.C_SCOND_HI,
"LS": arm.C_SCOND_LS,
"GE": arm.C_SCOND_GE,
"LT": arm.C_SCOND_LT,
"GT": arm.C_SCOND_GT,
"LE": arm.C_SCOND_LE,
"AL": arm.C_SCOND_NONE,
"U": arm.C_UBIT,
"S": arm.C_SBIT,
"W": arm.C_WBIT,
"P": arm.C_PBIT,
"PW": arm.C_WBIT | arm.C_PBIT,
"WP": arm.C_WBIT | arm.C_PBIT,
"F": arm.C_FBIT,
"IBW": arm.C_WBIT | arm.C_PBIT | arm.C_UBIT,
"IAW": arm.C_WBIT | arm.C_UBIT,
"DBW": arm.C_WBIT | arm.C_PBIT,
"DAW": arm.C_WBIT,
"IB": arm.C_PBIT | arm.C_UBIT,
"IA": arm.C_UBIT,
"DB": arm.C_PBIT,
"DA": 0,
}
var armJump = map[string]bool{
"B": true,
"BL": true,
"BX": true,
"BEQ": true,
"BNE": true,
"BCS": true,
"BHS": true,
"BCC": true,
"BLO": true,
"BMI": true,
"BPL": true,
"BVS": true,
"BVC": true,
"BHI": true,
"BLS": true,
"BGE": true,
"BLT": true,
"BGT": true,
"BLE": true,
"CALL": true,
"JMP": true,
}
func jumpArm(word string) bool {
return armJump[word]
}
// IsARMCMP reports whether the op (as defined by an arm.A* constant) is
// one of the comparison instructions that require special handling.
func IsARMCMP(op obj.As) bool {
switch op {
case arm.ACMN, arm.ACMP, arm.ATEQ, arm.ATST:
return true
}
return false
}
// IsARMSTREX reports whether the op (as defined by an arm.A* constant) is
// one of the STREX-like instructions that require special handling.
func IsARMSTREX(op obj.As) bool {
switch op {
case arm.ASTREX, arm.ASTREXD, arm.ASWPW, arm.ASWPBU:
return true
}
return false
}
// MCR is not defined by the obj/arm; instead we define it privately here.
// It is encoded as an MRC with a bit inside the instruction word,
// passed to arch.ARMMRCOffset.
const aMCR = arm.ALAST + 1
// IsARMMRC reports whether the op (as defined by an arm.A* constant) is
// MRC or MCR
func IsARMMRC(op obj.As) bool {
switch op {
case arm.AMRC, aMCR: // Note: aMCR is defined in this package.
return true
}
return false
}
// IsARMBFX reports whether the op (as defined by an arm.A* constant) is one the
// BFX-like instructions which are in the form of "op $width, $LSB, (Reg,) Reg".
func IsARMBFX(op obj.As) bool {
switch op {
case arm.ABFX, arm.ABFXU, arm.ABFC, arm.ABFI:
return true
}
return false
}
// IsARMFloatCmp reports whether the op is a floating comparison instruction.
func IsARMFloatCmp(op obj.As) bool {
switch op {
case arm.ACMPF, arm.ACMPD:
return true
}
return false
}
// ARMMRCOffset implements the peculiar encoding of the MRC and MCR instructions.
// The difference between MRC and MCR is represented by a bit high in the word, not
// in the usual way by the opcode itself. Asm must use AMRC for both instructions, so
// we return the opcode for MRC so that asm doesn't need to import obj/arm.
func ARMMRCOffset(op obj.As, cond string, x0, x1, x2, x3, x4, x5 int64) (offset int64, op0 obj.As, ok bool) {
op1 := int64(0)
if op == arm.AMRC {
op1 = 1
}
bits, ok := ParseARMCondition(cond)
if !ok {
return
}
offset = (0xe << 24) | // opcode
(op1 << 20) | // MCR/MRC
((int64(bits) ^ arm.C_SCOND_XOR) << 28) | // scond
((x0 & 15) << 8) | //coprocessor number
((x1 & 7) << 21) | // coprocessor operation
((x2 & 15) << 12) | // ARM register
((x3 & 15) << 16) | // Crn
((x4 & 15) << 0) | // Crm
((x5 & 7) << 5) | // coprocessor information
(1 << 4) /* must be set */
return offset, arm.AMRC, true
}
// IsARMMULA reports whether the op (as defined by an arm.A* constant) is
// MULA, MULS, MMULA, MMULS, MULABB, MULAWB or MULAWT, the 4-operand instructions.
func IsARMMULA(op obj.As) bool {
switch op {
case arm.AMULA, arm.AMULS, arm.AMMULA, arm.AMMULS, arm.AMULABB, arm.AMULAWB, arm.AMULAWT:
return true
}
return false
}
var bcode = []obj.As{
arm.ABEQ,
arm.ABNE,
arm.ABCS,
arm.ABCC,
arm.ABMI,
arm.ABPL,
arm.ABVS,
arm.ABVC,
arm.ABHI,
arm.ABLS,
arm.ABGE,
arm.ABLT,
arm.ABGT,
arm.ABLE,
arm.AB,
obj.ANOP,
}
// ARMConditionCodes handles the special condition code situation for the ARM.
// It returns a boolean to indicate success; failure means cond was unrecognized.
func ARMConditionCodes(prog *obj.Prog, cond string) bool {
if cond == "" {
return true
}
bits, ok := ParseARMCondition(cond)
if !ok {
return false
}
/* hack to make B.NE etc. work: turn it into the corresponding conditional */
if prog.As == arm.AB {
prog.As = bcode[(bits^arm.C_SCOND_XOR)&0xf]
bits = (bits &^ 0xf) | arm.C_SCOND_NONE
}
prog.Scond = bits
return true
}
// ParseARMCondition parses the conditions attached to an ARM instruction.
// The input is a single string consisting of period-separated condition
// codes, such as ".P.W". An initial period is ignored.
func ParseARMCondition(cond string) (uint8, bool) {
return parseARMCondition(cond, armLS, armSCOND)
}
func parseARMCondition(cond string, ls, scond map[string]uint8) (uint8, bool) {
cond = strings.TrimPrefix(cond, ".")
if cond == "" {
return arm.C_SCOND_NONE, true
}
names := strings.Split(cond, ".")
bits := uint8(0)
for _, name := range names {
if b, present := ls[name]; present {
bits |= b
continue
}
if b, present := scond[name]; present {
bits = (bits &^ arm.C_SCOND) | b
continue
}
return 0, false
}
return bits, true
}
func armRegisterNumber(name string, n int16) (int16, bool) {
if n < 0 || 15 < n {
return 0, false
}
switch name {
case "R":
return arm.REG_R0 + n, true
case "F":
return arm.REG_F0 + n, true
}
return 0, false
}

View File

@ -0,0 +1,350 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file encapsulates some of the odd characteristics of the ARM64
// instruction set, to minimize its interaction with the core of the
// assembler.
package arch
import (
"github.com/twitchyliquid64/golang-asm/obj"
"github.com/twitchyliquid64/golang-asm/obj/arm64"
"errors"
)
var arm64LS = map[string]uint8{
"P": arm64.C_XPOST,
"W": arm64.C_XPRE,
}
var arm64Jump = map[string]bool{
"B": true,
"BL": true,
"BEQ": true,
"BNE": true,
"BCS": true,
"BHS": true,
"BCC": true,
"BLO": true,
"BMI": true,
"BPL": true,
"BVS": true,
"BVC": true,
"BHI": true,
"BLS": true,
"BGE": true,
"BLT": true,
"BGT": true,
"BLE": true,
"CALL": true,
"CBZ": true,
"CBZW": true,
"CBNZ": true,
"CBNZW": true,
"JMP": true,
"TBNZ": true,
"TBZ": true,
}
func jumpArm64(word string) bool {
return arm64Jump[word]
}
// IsARM64CMP reports whether the op (as defined by an arm.A* constant) is
// one of the comparison instructions that require special handling.
func IsARM64CMP(op obj.As) bool {
switch op {
case arm64.ACMN, arm64.ACMP, arm64.ATST,
arm64.ACMNW, arm64.ACMPW, arm64.ATSTW,
arm64.AFCMPS, arm64.AFCMPD,
arm64.AFCMPES, arm64.AFCMPED:
return true
}
return false
}
// IsARM64STLXR reports whether the op (as defined by an arm64.A*
// constant) is one of the STLXR-like instructions that require special
// handling.
func IsARM64STLXR(op obj.As) bool {
switch op {
case arm64.ASTLXRB, arm64.ASTLXRH, arm64.ASTLXRW, arm64.ASTLXR,
arm64.ASTXRB, arm64.ASTXRH, arm64.ASTXRW, arm64.ASTXR,
arm64.ASTXP, arm64.ASTXPW, arm64.ASTLXP, arm64.ASTLXPW:
return true
}
// atomic instructions
if arm64.IsAtomicInstruction(op) {
return true
}
return false
}
// ARM64Suffix handles the special suffix for the ARM64.
// It returns a boolean to indicate success; failure means
// cond was unrecognized.
func ARM64Suffix(prog *obj.Prog, cond string) bool {
if cond == "" {
return true
}
bits, ok := parseARM64Suffix(cond)
if !ok {
return false
}
prog.Scond = bits
return true
}
// parseARM64Suffix parses the suffix attached to an ARM64 instruction.
// The input is a single string consisting of period-separated condition
// codes, such as ".P.W". An initial period is ignored.
func parseARM64Suffix(cond string) (uint8, bool) {
if cond == "" {
return 0, true
}
return parseARMCondition(cond, arm64LS, nil)
}
func arm64RegisterNumber(name string, n int16) (int16, bool) {
switch name {
case "F":
if 0 <= n && n <= 31 {
return arm64.REG_F0 + n, true
}
case "R":
if 0 <= n && n <= 30 { // not 31
return arm64.REG_R0 + n, true
}
case "V":
if 0 <= n && n <= 31 {
return arm64.REG_V0 + n, true
}
}
return 0, false
}
// IsARM64TBL reports whether the op (as defined by an arm64.A*
// constant) is one of the table lookup instructions that require special
// handling.
func IsARM64TBL(op obj.As) bool {
return op == arm64.AVTBL
}
// ARM64RegisterExtension parses an ARM64 register with extension or arrangement.
func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
Rnum := (reg & 31) + int16(num<<5)
if isAmount {
if num < 0 || num > 7 {
return errors.New("index shift amount is out of range")
}
}
switch ext {
case "UXTB":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode")
}
a.Reg = arm64.REG_UXTB + Rnum
case "UXTH":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode")
}
a.Reg = arm64.REG_UXTH + Rnum
case "UXTW":
if !isAmount {
return errors.New("invalid register extension")
}
// effective address of memory is a base register value and an offset register value.
if a.Type == obj.TYPE_MEM {
a.Index = arm64.REG_UXTW + Rnum
} else {
a.Reg = arm64.REG_UXTW + Rnum
}
case "UXTX":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode")
}
a.Reg = arm64.REG_UXTX + Rnum
case "SXTB":
if !isAmount {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_SXTB + Rnum
case "SXTH":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode")
}
a.Reg = arm64.REG_SXTH + Rnum
case "SXTW":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
a.Index = arm64.REG_SXTW + Rnum
} else {
a.Reg = arm64.REG_SXTW + Rnum
}
case "SXTX":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM {
a.Index = arm64.REG_SXTX + Rnum
} else {
a.Reg = arm64.REG_SXTX + Rnum
}
case "LSL":
if !isAmount {
return errors.New("invalid register extension")
}
a.Index = arm64.REG_LSL + Rnum
case "B8":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_8B & 15) << 5)
case "B16":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_16B & 15) << 5)
case "H4":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_4H & 15) << 5)
case "H8":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_8H & 15) << 5)
case "S2":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_2S & 15) << 5)
case "S4":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_4S & 15) << 5)
case "D1":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_1D & 15) << 5)
case "D2":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_2D & 15) << 5)
case "Q1":
if isIndex {
return errors.New("invalid register extension")
}
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_1Q & 15) << 5)
case "B":
if !isIndex {
return nil
}
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_B & 15) << 5)
a.Index = num
case "H":
if !isIndex {
return nil
}
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_H & 15) << 5)
a.Index = num
case "S":
if !isIndex {
return nil
}
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_S & 15) << 5)
a.Index = num
case "D":
if !isIndex {
return nil
}
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_D & 15) << 5)
a.Index = num
default:
return errors.New("unsupported register extension type: " + ext)
}
return nil
}
// ARM64RegisterArrangement parses an ARM64 vector register arrangement.
func ARM64RegisterArrangement(reg int16, name, arng string) (int64, error) {
var curQ, curSize uint16
if name[0] != 'V' {
return 0, errors.New("expect V0 through V31; found: " + name)
}
if reg < 0 {
return 0, errors.New("invalid register number: " + name)
}
switch arng {
case "B8":
curSize = 0
curQ = 0
case "B16":
curSize = 0
curQ = 1
case "H4":
curSize = 1
curQ = 0
case "H8":
curSize = 1
curQ = 1
case "S2":
curSize = 2
curQ = 0
case "S4":
curSize = 2
curQ = 1
case "D1":
curSize = 3
curQ = 0
case "D2":
curSize = 3
curQ = 1
default:
return 0, errors.New("invalid arrangement in ARM64 register list")
}
return (int64(curQ) & 1 << 30) | (int64(curSize&3) << 10), nil
}
// ARM64RegisterListOffset generates offset encoding according to AArch64 specification.
func ARM64RegisterListOffset(firstReg, regCnt int, arrangement int64) (int64, error) {
offset := int64(firstReg)
switch regCnt {
case 1:
offset |= 0x7 << 12
case 2:
offset |= 0xa << 12
case 3:
offset |= 0x6 << 12
case 4:
offset |= 0x2 << 12
default:
return 0, errors.New("invalid register numbers in ARM64 register list")
}
offset |= arrangement
// arm64 uses the 60th bit to differentiate from other archs
// For more details, refer to: obj/arm64/list7.go
offset |= 1 << 60
return offset, nil
}

View File

@ -0,0 +1,72 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file encapsulates some of the odd characteristics of the
// MIPS (MIPS64) instruction set, to minimize its interaction
// with the core of the assembler.
package arch
import (
"github.com/twitchyliquid64/golang-asm/obj"
"github.com/twitchyliquid64/golang-asm/obj/mips"
)
func jumpMIPS(word string) bool {
switch word {
case "BEQ", "BFPF", "BFPT", "BGEZ", "BGEZAL", "BGTZ", "BLEZ", "BLTZ", "BLTZAL", "BNE", "JMP", "JAL", "CALL":
return true
}
return false
}
// IsMIPSCMP reports whether the op (as defined by an mips.A* constant) is
// one of the CMP instructions that require special handling.
func IsMIPSCMP(op obj.As) bool {
switch op {
case mips.ACMPEQF, mips.ACMPEQD, mips.ACMPGEF, mips.ACMPGED,
mips.ACMPGTF, mips.ACMPGTD:
return true
}
return false
}
// IsMIPSMUL reports whether the op (as defined by an mips.A* constant) is
// one of the MUL/DIV/REM/MADD/MSUB instructions that require special handling.
func IsMIPSMUL(op obj.As) bool {
switch op {
case mips.AMUL, mips.AMULU, mips.AMULV, mips.AMULVU,
mips.ADIV, mips.ADIVU, mips.ADIVV, mips.ADIVVU,
mips.AREM, mips.AREMU, mips.AREMV, mips.AREMVU,
mips.AMADD, mips.AMSUB:
return true
}
return false
}
func mipsRegisterNumber(name string, n int16) (int16, bool) {
switch name {
case "F":
if 0 <= n && n <= 31 {
return mips.REG_F0 + n, true
}
case "FCR":
if 0 <= n && n <= 31 {
return mips.REG_FCR0 + n, true
}
case "M":
if 0 <= n && n <= 31 {
return mips.REG_M0 + n, true
}
case "R":
if 0 <= n && n <= 31 {
return mips.REG_R0 + n, true
}
case "W":
if 0 <= n && n <= 31 {
return mips.REG_W0 + n, true
}
}
return 0, false
}

View File

@ -0,0 +1,102 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file encapsulates some of the odd characteristics of the
// 64-bit PowerPC (PPC64) instruction set, to minimize its interaction
// with the core of the assembler.
package arch
import (
"github.com/twitchyliquid64/golang-asm/obj"
"github.com/twitchyliquid64/golang-asm/obj/ppc64"
)
func jumpPPC64(word string) bool {
switch word {
case "BC", "BCL", "BEQ", "BGE", "BGT", "BL", "BLE", "BLT", "BNE", "BR", "BVC", "BVS", "CALL", "JMP":
return true
}
return false
}
// IsPPC64RLD reports whether the op (as defined by an ppc64.A* constant) is
// one of the RLD-like instructions that require special handling.
// The FMADD-like instructions behave similarly.
func IsPPC64RLD(op obj.As) bool {
switch op {
case ppc64.ARLDC, ppc64.ARLDCCC, ppc64.ARLDCL, ppc64.ARLDCLCC,
ppc64.ARLDCR, ppc64.ARLDCRCC, ppc64.ARLDMI, ppc64.ARLDMICC,
ppc64.ARLWMI, ppc64.ARLWMICC, ppc64.ARLWNM, ppc64.ARLWNMCC:
return true
case ppc64.AFMADD, ppc64.AFMADDCC, ppc64.AFMADDS, ppc64.AFMADDSCC,
ppc64.AFMSUB, ppc64.AFMSUBCC, ppc64.AFMSUBS, ppc64.AFMSUBSCC,
ppc64.AFNMADD, ppc64.AFNMADDCC, ppc64.AFNMADDS, ppc64.AFNMADDSCC,
ppc64.AFNMSUB, ppc64.AFNMSUBCC, ppc64.AFNMSUBS, ppc64.AFNMSUBSCC:
return true
}
return false
}
func IsPPC64ISEL(op obj.As) bool {
return op == ppc64.AISEL
}
// IsPPC64CMP reports whether the op (as defined by an ppc64.A* constant) is
// one of the CMP instructions that require special handling.
func IsPPC64CMP(op obj.As) bool {
switch op {
case ppc64.ACMP, ppc64.ACMPU, ppc64.ACMPW, ppc64.ACMPWU, ppc64.AFCMPU:
return true
}
return false
}
// IsPPC64NEG reports whether the op (as defined by an ppc64.A* constant) is
// one of the NEG-like instructions that require special handling.
func IsPPC64NEG(op obj.As) bool {
switch op {
case ppc64.AADDMECC, ppc64.AADDMEVCC, ppc64.AADDMEV, ppc64.AADDME,
ppc64.AADDZECC, ppc64.AADDZEVCC, ppc64.AADDZEV, ppc64.AADDZE,
ppc64.ACNTLZDCC, ppc64.ACNTLZD, ppc64.ACNTLZWCC, ppc64.ACNTLZW,
ppc64.AEXTSBCC, ppc64.AEXTSB, ppc64.AEXTSHCC, ppc64.AEXTSH,
ppc64.AEXTSWCC, ppc64.AEXTSW, ppc64.ANEGCC, ppc64.ANEGVCC,
ppc64.ANEGV, ppc64.ANEG, ppc64.ASLBMFEE, ppc64.ASLBMFEV,
ppc64.ASLBMTE, ppc64.ASUBMECC, ppc64.ASUBMEVCC, ppc64.ASUBMEV,
ppc64.ASUBME, ppc64.ASUBZECC, ppc64.ASUBZEVCC, ppc64.ASUBZEV,
ppc64.ASUBZE:
return true
}
return false
}
func ppc64RegisterNumber(name string, n int16) (int16, bool) {
switch name {
case "CR":
if 0 <= n && n <= 7 {
return ppc64.REG_CR0 + n, true
}
case "VS":
if 0 <= n && n <= 63 {
return ppc64.REG_VS0 + n, true
}
case "V":
if 0 <= n && n <= 31 {
return ppc64.REG_V0 + n, true
}
case "F":
if 0 <= n && n <= 31 {
return ppc64.REG_F0 + n, true
}
case "R":
if 0 <= n && n <= 31 {
return ppc64.REG_R0 + n, true
}
case "SPR":
if 0 <= n && n <= 1024 {
return ppc64.REG_SPR0 + n, true
}
}
return 0, false
}

View File

@ -0,0 +1,28 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file encapsulates some of the odd characteristics of the RISCV64
// instruction set, to minimize its interaction with the core of the
// assembler.
package arch
import (
"github.com/twitchyliquid64/golang-asm/obj"
"github.com/twitchyliquid64/golang-asm/obj/riscv"
)
// IsRISCV64AMO reports whether the op (as defined by a riscv.A*
// constant) is one of the AMO instructions that requires special
// handling.
func IsRISCV64AMO(op obj.As) bool {
switch op {
case riscv.ASCW, riscv.ASCD, riscv.AAMOSWAPW, riscv.AAMOSWAPD, riscv.AAMOADDW, riscv.AAMOADDD,
riscv.AAMOANDW, riscv.AAMOANDD, riscv.AAMOORW, riscv.AAMOORD, riscv.AAMOXORW, riscv.AAMOXORD,
riscv.AAMOMINW, riscv.AAMOMIND, riscv.AAMOMINUW, riscv.AAMOMINUD,
riscv.AAMOMAXW, riscv.AAMOMAXD, riscv.AAMOMAXUW, riscv.AAMOMAXUD:
return true
}
return false
}

View File

@ -0,0 +1,81 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file encapsulates some of the odd characteristics of the
// s390x instruction set, to minimize its interaction
// with the core of the assembler.
package arch
import (
"github.com/twitchyliquid64/golang-asm/obj/s390x"
)
func jumpS390x(word string) bool {
switch word {
case "BRC",
"BC",
"BCL",
"BEQ",
"BGE",
"BGT",
"BL",
"BLE",
"BLEU",
"BLT",
"BLTU",
"BNE",
"BR",
"BVC",
"BVS",
"BRCT",
"BRCTG",
"CMPBEQ",
"CMPBGE",
"CMPBGT",
"CMPBLE",
"CMPBLT",
"CMPBNE",
"CMPUBEQ",
"CMPUBGE",
"CMPUBGT",
"CMPUBLE",
"CMPUBLT",
"CMPUBNE",
"CRJ",
"CGRJ",
"CLRJ",
"CLGRJ",
"CIJ",
"CGIJ",
"CLIJ",
"CLGIJ",
"CALL",
"JMP":
return true
}
return false
}
func s390xRegisterNumber(name string, n int16) (int16, bool) {
switch name {
case "AR":
if 0 <= n && n <= 15 {
return s390x.REG_AR0 + n, true
}
case "F":
if 0 <= n && n <= 15 {
return s390x.REG_F0 + n, true
}
case "R":
if 0 <= n && n <= 15 {
return s390x.REG_R0 + n, true
}
case "V":
if 0 <= n && n <= 31 {
return s390x.REG_V0 + n, true
}
}
return 0, false
}