diff options
Diffstat (limited to 'vendor/github.com/twitchyliquid64/golang-asm/asm/arch')
7 files changed, 1606 insertions, 0 deletions
| diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arch.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arch.go new file mode 100644 index 000000000..b8ddbc99d --- /dev/null +++ b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arch.go @@ -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, +	} +} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm.go new file mode 100644 index 000000000..645e98a57 --- /dev/null +++ b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm.go @@ -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 +} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm64.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm64.go new file mode 100644 index 000000000..b0606beb3 --- /dev/null +++ b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arm64.go @@ -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 +} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/mips.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/mips.go new file mode 100644 index 000000000..7af9dbb23 --- /dev/null +++ b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/mips.go @@ -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 +} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/ppc64.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/ppc64.go new file mode 100644 index 000000000..8b2f097d5 --- /dev/null +++ b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/ppc64.go @@ -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 +} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/riscv64.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/riscv64.go new file mode 100644 index 000000000..e4f17536a --- /dev/null +++ b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/riscv64.go @@ -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 +} diff --git a/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/s390x.go b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/s390x.go new file mode 100644 index 000000000..1e33f1e32 --- /dev/null +++ b/vendor/github.com/twitchyliquid64/golang-asm/asm/arch/s390x.go @@ -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 +} | 
