feat: gasm-devkit 0.1.0 — GAsm lexer, parser, linter, formatter, LSP and amd64 assembler

Assisted-by: Qwen 3.8 Max Preview
This commit is contained in:
2026-07-06 09:49:50 +02:00
commit d5a4a6de45
53 changed files with 13166 additions and 0 deletions
+317
View File
@@ -0,0 +1,317 @@
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
package arch
import "fmt"
func buildAMD64() *Table {
return newTable(AMD64, amd64Registers(), mergedInstrs(amd64Summaries(), commonGeneratedInstrs, amd64GeneratedInstrs, amd64Aliases()))
}
// amd64Aliases are the traditional x86 conditional-jump spellings (plus a few
// instruction aliases) that Go's assembler accepts and maps onto its canonical
// opcodes. They are user-writable but absent from the generated opcode table,
// so they are listed explicitly here.
func amd64Aliases() []string {
return []string{
"JA", "JAE", "JB", "JBE", "JC", "JCC", "JCS", "JE", "JG", "JHI", "JHS",
"JL", "JLO", "JLS", "JMI", "JNA", "JNAE", "JNB", "JNBE", "JNC", "JNG",
"JNGE", "JNL", "JNLE", "JNO", "JNP", "JNS", "JNZ", "JO", "JOC", "JOS",
"JP", "JPC", "JPE", "JPL", "JPO", "JPS", "JS", "JZ",
"MASKMOVDQU", "MOVDQ2Q", "MOVNTDQ", "MOVOA", "PSLLDQ", "PSRLDQ",
"MOVD", "PADDD", "MOVBELL", "MOVBEQQ", "MOVBEWW",
}
}
// amd64Summaries returns the curated documentation/operand-count table keyed by
// upper-case mnemonic. It enriches the complete generated name list; names
// without a curated entry are still recognised, just without a summary.
func amd64Summaries() map[string]Instr { return toMap(amd64Curated()) }
// amd64Registers builds the amd64 register file. Numbered registers are
// generated; the irregularly named ones are listed explicitly.
func amd64Registers() []Register {
var regs []Register
add := func(name string, class RegClass, desc string) {
regs = append(regs, Register{Name: name, Class: class, Desc: desc})
}
// 64-bit general-purpose registers.
for _, n := range []string{"AX", "BX", "CX", "DX", "SI", "DI", "BP", "SP"} {
add(n, GPR, "64-bit general-purpose register")
}
for i := 8; i <= 15; i++ {
add(fmt.Sprintf("R%d", i), GPR, "64-bit general-purpose register")
}
// 8-bit low/high sub-registers.
for _, n := range []string{"AL", "BL", "CL", "DL", "SIL", "DIL", "BPL", "SPL"} {
add(n, GPRSub, "8-bit low sub-register")
}
for _, n := range []string{"AH", "BH", "CH", "DH"} {
add(n, GPRSub, "8-bit high sub-register")
}
// Sized numbered sub-registers.
for i := 8; i <= 15; i++ {
add(fmt.Sprintf("R%dB", i), GPRSub, "8-bit sub-register")
add(fmt.Sprintf("R%dW", i), GPRSub, "16-bit sub-register")
add(fmt.Sprintf("R%dD", i), GPRSub, "32-bit sub-register")
}
// SIMD vector registers: X (SSE), Y (AVX2), Z (AVX-512).
for i := 0; i <= 15; i++ {
add(fmt.Sprintf("X%d", i), Vector, "128-bit SSE/AVX vector register")
add(fmt.Sprintf("Y%d", i), Vector, "256-bit AVX2 vector register")
add(fmt.Sprintf("Z%d", i), Vector, "512-bit AVX-512 vector register")
}
for i := 16; i <= 31; i++ {
add(fmt.Sprintf("Z%d", i), Vector, "512-bit AVX-512 vector register")
}
// AVX-512 mask registers.
for i := 0; i <= 7; i++ {
add(fmt.Sprintf("K%d", i), Mask, "AVX-512 mask register")
}
return regs
}
// i builds an instruction with an unknown/variable operand count.
func i(name, summary string) Instr {
return Instr{Name: name, Summary: summary, MinOps: -1, MaxOps: -1}
}
// ic builds an instruction with an explicit operand-count range.
func ic(name, summary string, min, max int) Instr {
return Instr{Name: name, Summary: summary, MinOps: min, MaxOps: max}
}
// amd64Curated returns the hand-written subset of amd64 instructions that carry
// a summary and/or an explicit operand-count range. The authoritative,
// complete instruction set is amd64GeneratedInstrs (see amd64_gen.go).
func amd64Curated() []Instr {
var t []Instr
// Data movement.
for _, s := range []string{"B", "W", "L", "Q"} {
t = append(t, ic("MOV"+s, "Move "+s+"-width value", 2, 2))
}
for _, m := range []string{
"MOVBLZX", "MOVBQSX", "MOVWLZX", "MOVWQSX", "MOVWLSX", "MOVLQSX", "MOVBLSX", "MOVQL",
} {
t = append(t, ic(m, "Sign/zero-extending move", 2, 2))
}
for _, m := range []string{"MOVO", "MOVOU"} {
t = append(t, ic(m, "Move 16-byte aligned/unaligned vector", 2, 2))
}
for _, s := range []string{"B", "W", "L", "Q"} {
t = append(t, ic("LEA"+s, "Load effective address", 2, 2))
}
for _, s := range []string{"B", "W", "L", "Q"} {
t = append(t, ic("XCHG"+s, "Exchange operands", 2, 2))
}
// Integer arithmetic and logic.
for _, op := range []string{"ADD", "SUB", "AND", "OR", "XOR", "ADC", "SBB"} {
for _, s := range []string{"B", "W", "L", "Q"} {
t = append(t, ic(op+s, op+" integer", 2, 2))
}
}
for _, s := range []string{"B", "W", "L", "Q"} {
t = append(t, ic("INC"+s, "Increment", 1, 1))
t = append(t, ic("DEC"+s, "Decrement", 1, 1))
t = append(t, ic("NEG"+s, "Two's-complement negate", 1, 1))
t = append(t, ic("NOT"+s, "Bitwise complement", 1, 1))
}
for _, s := range []string{"B", "W", "L", "Q"} {
t = append(t, i("IMUL"+s, "Signed multiply"))
t = append(t, ic("IMUL3"+s, "Signed multiply by immediate", 3, 3))
t = append(t, ic("MUL"+s, "Unsigned multiply", 1, 1))
t = append(t, ic("DIV"+s, "Unsigned divide", 1, 1))
t = append(t, ic("IDIV"+s, "Signed divide", 1, 1))
}
// Shifts and rotates.
for _, op := range []string{"SHL", "SHR", "SAR", "SAL", "ROL", "ROR", "RCL", "RCR"} {
for _, s := range []string{"B", "W", "L", "Q"} {
t = append(t, i(op+s, op+" shift/rotate"))
}
}
for _, s := range []string{"W", "L", "Q"} {
t = append(t, i("SHLD"+s, "Double-precision left shift"))
t = append(t, i("SHRD"+s, "Double-precision right shift"))
}
// Compare and test.
for _, s := range []string{"B", "W", "L", "Q"} {
t = append(t, ic("CMP"+s, "Compare (subtract, flags only)", 2, 2))
t = append(t, ic("TEST"+s, "AND, flags only", 2, 2))
}
for _, op := range []string{"BT", "BTS", "BTR", "BTC"} {
for _, s := range []string{"W", "L", "Q"} {
t = append(t, i(op+s, "Bit test"+op[1:]))
}
}
// Control flow.
t = append(t, ic("JMP", "Unconditional jump", 1, 1))
for _, cc := range []string{
"EQ", "NE", "Z", "NZ", "L", "LE", "G", "GE", "LT", "GT", "MI", "PL",
"B", "BE", "A", "AE", "CS", "CC", "HI", "LS", "C", "NC",
"S", "NS", "O", "NO", "P", "NP", "PE", "PO", "OS", "OC",
"CXZ", "ECXZ", "RCXZ",
} {
t = append(t, ic("J"+cc, "Conditional jump", 1, 1))
}
t = append(t, ic("CALL", "Call subroutine", 1, 1))
t = append(t, ic("RET", "Return from subroutine", 0, 0))
t = append(t, ic("RETF", "Far return", 0, 0))
t = append(t, ic("NOP", "No operation", 0, 1))
t = append(t, i("INT", "Software interrupt"))
t = append(t, ic("SYSCALL", "System call", 0, 0))
t = append(t, ic("HLT", "Halt", 0, 0))
t = append(t, ic("UD2", "Undefined instruction (trap)", 0, 0))
// Conditional set and move.
for _, cc := range []string{
"EQ", "NE", "L", "LE", "G", "GE", "LT", "GT", "B", "BE", "A", "AE",
"CS", "CC", "HI", "LS", "S", "NS", "O", "NO", "P", "NP", "MI", "PL",
} {
t = append(t, ic("SET"+cc, "Set byte on condition", 1, 1))
}
for _, s := range []string{"L", "Q", "W"} {
for _, cc := range []string{"EQ", "NE", "LT", "LE", "GT", "GE"} {
t = append(t, ic("CMOV"+s+cc, "Conditional move", 2, 2))
}
}
// Bit scanning and counting.
for _, op := range []string{"LZCNT", "TZCNT", "POPCNT", "BSF", "BSR"} {
for _, s := range []string{"W", "L", "Q"} {
t = append(t, ic(op+s, op+" bit operation", 2, 2))
}
}
for _, s := range []string{"L", "Q"} {
t = append(t, ic("BSWAP"+s, "Byte-swap", 1, 1))
}
for _, m := range []string{"CDQ", "CQO", "CBW", "CWDE", "CDQE"} {
t = append(t, ic(m, "Sign-extend accumulator", 0, 0))
}
for _, m := range []string{"CPUID", "RDTSC", "LFENCE", "SFENCE", "MFENCE", "PAUSE"} {
t = append(t, ic(m, "Serialising/system instruction", 0, 0))
}
// SIMD data movement.
for _, m := range []string{
"VMOVDQU", "VMOVDQA", "VMOVUPS", "VMOVUPD", "VMOVAPS", "VMOVAPD",
"VMOVSD", "VMOVSS", "VMOVQ", "VMOVD",
"VMOVDQU32", "VMOVDQU64", "VMOVDQA32", "VMOVDQA64",
"MOVDQU", "MOVDQA", "MOVUPS", "MOVUPD", "MOVAPS", "MOVAPD", "MOVSD", "MOVSS", "MOVD",
} {
t = append(t, i(m, "SIMD move"))
}
// SIMD integer logic and arithmetic.
for _, m := range []string{
"VPXOR", "VPXORD", "VPXORQ", "VPAND", "VPANDN", "VPANDD", "VPANDND", "VPOR", "VPORD", "VPORQ",
"VPADDB", "VPADDW", "VPADDD", "VPADDQ",
"VPSUBB", "VPSUBW", "VPSUBD", "VPSUBQ",
"VPMULLW", "VPMULLD", "VPMULLQ", "VPMULDQ", "VPMULUDQ", "VPMULHUW", "VPMULHW",
"VPADUSB", "VPADUSW", "VPSUBUSB", "VPSUBUSW",
"VPMINSB", "VPMINSW", "VPMINSD", "VPMAXSB", "VPMAXSW", "VPMAXSD",
"VPABSB", "VPABSW", "VPABSD", "VPABSQ",
"VPSLLW", "VPSLLD", "VPSLLQ", "VPSRLW", "VPSRLD", "VPSRLQ",
"VPSRAW", "VPSRAD", "VPSRAQ", "VPSRAVD", "VPSRAVQ", "VPSLLVD", "VPSLLVQ", "VPSRLVD", "VPSRLVQ",
"VPAVGB", "VPAVGW",
"VPACKSSDW", "VPACKSSWB", "VPACKUSDW", "VPACKUSWB",
} {
t = append(t, i(m, "Packed integer SIMD"))
}
// SIMD comparison.
for _, m := range []string{
"VPCMPEQB", "VPCMPEQW", "VPCMPEQD", "VPCMPEQQ",
"VPCMPGTB", "VPCMPGTW", "VPCMPGTD", "VPCMPGTQ",
"VPCMPB", "VPCMPW", "VPCMPD", "VPCMPQ",
} {
t = append(t, i(m, "Packed compare"))
}
// SIMD unpack, shuffle, permute, broadcast, extract, insert.
for _, m := range []string{
"VPUNPCKLBW", "VPUNPCKLWD", "VPUNPCKLDQ", "VPUNPCKLQDQ",
"VPUNPCKHBW", "VPUNPCKHWD", "VPUNPCKHDQ", "VPUNPCKHQDQ",
"VPSHUFD", "VPSHUFHW", "VPSHUFLW", "VPSHUFB",
"VEXTRACTI128", "VEXTRACTF128", "VEXTRACTI32X4", "VEXTRACTI64X4",
"VEXTRACTF32X4", "VEXTRACTF64X4", "VEXTRACTI32X8", "VEXTRACTI64X2",
"VINSERTI128", "VINSERTF128", "VINSERTI32X4", "VINSERTI64X4", "VINSERTF32X4", "VINSERTF64X4",
"VPERMQ", "VPERMD", "VPERMPS", "VPERM2I128", "VPERM2F128",
"VPBROADCASTD", "VPBROADCASTQ", "VPBROADCASTB", "VPBROADCASTW",
"VBROADCASTSD", "VBROADCASTSS", "VBROADCASTI128", "VBROADCASTI32X4",
"VALIGND", "VALIGNQ", "VPBLENDD", "VPBLENDW", "VBLENDVPD", "VBLENDVPS",
"VSHUFPD", "VSHUFPS",
} {
t = append(t, i(m, "Shuffle / permute / broadcast"))
}
// SIMD sign/zero extension and truncation.
for _, m := range []string{
"VPMOVSXBW", "VPMOVSXBD", "VPMOVSXBQ", "VPMOVSXWD", "VPMOVSXWQ", "VPMOVSXDQ",
"VPMOVZXBW", "VPMOVZXBD", "VPMOVZXBQ", "VPMOVZXWD", "VPMOVZXWQ", "VPMOVZXDQ",
"VPMOVDW", "VPMOVQW", "VPMOVQD", "VPMOVDB", "VPMOVWB", "VPMOVQB",
"VPMOVMSKB", "VMOVMSKPS", "VMOVMSKPD", "VMOVQ2DQ", "VMOVDQ2Q",
} {
t = append(t, i(m, "Packed extend / truncate / mask"))
}
// SIMD floating point.
for _, m := range []string{
"VADDPD", "VADDPS", "VADDSD", "VADDSS",
"VSUBPD", "VSUBPS", "VSUBSD", "VSUBSS",
"VMULPD", "VMULPS", "VMULSD", "VMULSS",
"VDIVPD", "VDIVPS", "VDIVSD", "VDIVSS",
"VMINPD", "VMINPS", "VMINSD", "VMINSS", "VMAXPD", "VMAXPS", "VMAXSD", "VMAXSS",
"VXORPD", "VXORPS", "VANDPD", "VANDPS", "VANDNPD", "VANDNPS", "VORPD", "VORPS",
"VUNPCKHPD", "VUNPCKLPD", "VUNPCKHPS", "VUNPCKLPS",
"VSQRTPD", "VSQRTPS", "VSQRTSD", "VSQRTSS", "VRSQRTPS", "VRCPPS",
"VCMPPD", "VCMPPS", "VCMPSD", "VCMPSS",
} {
t = append(t, i(m, "Packed/scalar floating point"))
}
// FMA.
for _, ord := range []string{"132", "213", "231"} {
for _, sfx := range []string{"PD", "PS", "SD", "SS"} {
t = append(t, i("VFMADD"+ord+sfx, "Fused multiply-add"))
t = append(t, i("VFMSUB"+ord+sfx, "Fused multiply-subtract"))
t = append(t, i("VFNMADD"+ord+sfx, "Fused negated multiply-add"))
t = append(t, i("VFNMSUB"+ord+sfx, "Fused negated multiply-subtract"))
}
}
// SIMD conversion.
for _, m := range []string{
"VCVTDQ2PD", "VCVTDQ2PS", "VCVTPD2DQ", "VCVTPS2DQ", "VCVTPD2PS", "VCVTPS2PD",
"VCVTQQ2PD", "VCVTQQ2PS", "VCVTUQQ2PD", "VCVTUQQ2PS",
"VCVTTPD2DQ", "VCVTTPS2DQ", "VCVTSI2SD", "VCVTSI2SS", "VCVTSD2SI", "VCVTSS2SI",
"VCVTSD2SS", "VCVTSS2SD",
"CVTSL2SD", "CVTSL2SS", "CVTSQ2SD", "CVTSQ2SS", "CVTTSD2SL", "CVTTSD2SQ", "CVTTSS2SL",
} {
t = append(t, i(m, "Numeric conversion"))
}
// SIMD zeroing.
t = append(t, ic("VZEROUPPER", "Zero upper halves of YMM/ZMM", 0, 0))
t = append(t, ic("VZEROALL", "Zero all YMM/ZMM state", 0, 0))
// AVX-512 mask register operations.
for _, s := range []string{"B", "W", "D", "Q"} {
t = append(t, ic("KMOV"+s, "Move mask register", 2, 2))
t = append(t, ic("KTEST"+s, "Test mask registers", 2, 2))
t = append(t, i("KAND"+s, "AND masks"))
t = append(t, i("KOR"+s, "OR masks"))
t = append(t, i("KXOR"+s, "XOR masks"))
t = append(t, i("KNOT"+s, "NOT mask"))
t = append(t, i("KANDN"+s, "AND-NOT masks"))
t = append(t, i("KUNPCK"+s, "Unpack masks"))
}
return t
}
+1609
View File
File diff suppressed because it is too large Load Diff
+275
View File
@@ -0,0 +1,275 @@
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
// Package arch provides architecture-specific metadata for GAsm: the register
// files and instruction tables for amd64 and arm64. The metadata powers
// completion, hover documentation, semantic highlighting and the "unknown
// instruction" lint. It is pure data with no dependency on the parser, so it
// can be consulted from any layer.
package arch
import (
"strings"
)
// Arch identifies a target instruction set.
type Arch string
// Supported architectures.
const (
AMD64 Arch = "amd64"
ARM64 Arch = "arm64"
RISCV Arch = "riscv"
LOONG64 Arch = "loong64"
Unknown Arch = ""
)
// FromFilename guesses the target architecture from a source file name. Go
// assembly files conventionally carry a GOARCH suffix such as "_amd64.s",
// "_arm64.s", "_riscv64.s" or "_loong64.s". It returns Unknown when no suffix
// matches.
func FromFilename(name string) Arch {
lower := strings.ToLower(name)
switch {
case strings.Contains(lower, "_amd64"):
return AMD64
case strings.Contains(lower, "_arm64"):
return ARM64
case strings.Contains(lower, "_riscv64"), strings.Contains(lower, "_riscv"):
return RISCV
case strings.Contains(lower, "_loong64"), strings.Contains(lower, "_loong"):
return LOONG64
default:
return Unknown
}
}
// RegClass classifies a register for highlighting and completion grouping.
type RegClass int
// Register classes.
const (
GPR RegClass = iota // general-purpose integer register
GPRSub // sized sub-register (AL, R8D, …)
Vector // SSE/AVX/AVX-512 vector (X/Y/Z)
Mask // AVX-512 mask register (K)
Float // arm64 floating-point register (F)
VecARM // arm64 SIMD/vector register (V)
Special // architecture-special register
)
// String returns a short label for the class.
func (c RegClass) String() string {
switch c {
case GPR:
return "general-purpose"
case GPRSub:
return "sub-register"
case Vector:
return "vector"
case Mask:
return "mask"
case Float:
return "float"
case VecARM:
return "vector (arm64)"
case Special:
return "special"
default:
return "register"
}
}
// Register describes one architectural register.
type Register struct {
Name string
Class RegClass
Desc string
}
// Instr describes one instruction mnemonic.
type Instr struct {
Name string
Summary string
// MinOps and MaxOps bound the operand count; -1 means "unknown/variable"
// and disables the operand-count lint for that instruction.
MinOps int
MaxOps int
}
// Table is the metadata for one architecture.
type Table struct {
Arch Arch
regs map[string]Register
regList []Register
instrs map[string]Instr
instrList []Instr
}
func newTable(a Arch, regs []Register, instrs []Instr) *Table {
t := &Table{
Arch: a,
regs: make(map[string]Register, len(regs)),
regList: regs,
instrs: make(map[string]Instr, len(instrs)),
instrList: instrs,
}
for _, r := range regs {
t.regs[strings.ToUpper(r.Name)] = r
}
for _, in := range instrs {
t.instrs[strings.ToUpper(in.Name)] = in
}
return t
}
// IsRegister reports whether name is a register of this architecture.
func (t *Table) IsRegister(name string) bool {
_, ok := t.regs[strings.ToUpper(name)]
return ok
}
// Register returns the named register.
func (t *Table) Register(name string) (Register, bool) {
r, ok := t.regs[strings.ToUpper(name)]
return r, ok
}
// Registers returns all registers in definition order.
func (t *Table) Registers() []Register { return t.regList }
// Lookup returns the metadata for a mnemonic (case-insensitive).
func (t *Table) Lookup(mnemonic string) (Instr, bool) {
key := strings.ToUpper(mnemonic)
if in, ok := t.instrs[key]; ok {
return in, true
}
// arm64 load/store instructions take a .P (post-index) or .W (pre-index)
// addressing suffix that the assembler front-end strips; mirror that so the
// base instruction is still recognised.
if t.Arch == ARM64 {
for _, suffix := range []string{".P", ".W"} {
if base, ok := strings.CutSuffix(key, suffix); ok {
if in, found := t.instrs[base]; found {
return in, true
}
}
}
}
return Instr{}, false
}
// Instructions returns all instructions in definition order.
func (t *Table) Instructions() []Instr { return t.instrList }
// pseudoRegs are the Plan 9 pseudo-registers, valid on every architecture.
var pseudoRegs = map[string]string{
"FP": "frame pointer: references function arguments and results",
"SP": "stack pointer: the top of the local stack frame",
"SB": "static base: references global symbols",
"PC": "program counter",
}
// IsPseudoReg reports whether name is a Plan 9 pseudo-register.
func IsPseudoReg(name string) bool {
_, ok := pseudoRegs[strings.ToUpper(name)]
return ok
}
// PseudoRegDesc returns the description of a pseudo-register.
func PseudoRegDesc(name string) (string, bool) {
d, ok := pseudoRegs[strings.ToUpper(name)]
return d, ok
}
var (
amd64Table *Table
arm64Table *Table
riscvTable *Table
loong64Table *Table
)
func init() {
amd64Table = buildAMD64()
arm64Table = buildARM64()
riscvTable = buildRISCV()
loong64Table = buildLOONG64()
}
// ForArch returns the table for a, or the amd64 table for Unknown so that
// callers always get a usable default.
func ForArch(a Arch) *Table {
switch a {
case ARM64:
return arm64Table
case RISCV:
return riscvTable
case LOONG64:
return loong64Table
default:
return amd64Table
}
}
// fixedArity lists the few instructions whose operand count is reliable on
// every architecture; relaxCounts leaves these untouched.
var fixedArity = map[string]bool{
"RET": true, "NOP": true, "JMP": true, "CALL": true, "UNDEF": true,
}
// relaxCounts clears operand-count bounds for every instruction except the
// fixed-arity ones. It is applied to architectures (arm64, riscv64, loong64)
// whose instructions have too many operand forms for a single fixed count to be
// reliable, so the operand-count lint stays silent rather than guess.
func relaxCounts(instrs []Instr) []Instr {
for i := range instrs {
if !fixedArity[strings.ToUpper(instrs[i].Name)] {
instrs[i].MinOps = -1
instrs[i].MaxOps = -1
}
}
return instrs
}
// mergedInstrs combines the common opcode list with an architecture-specific
// list (de-duplicated, common first) and enriches the result with the curated
// summaries map.
func mergedInstrs(summaries map[string]Instr, nameSets ...[]string) []Instr {
seen := make(map[string]bool)
var names []string
for _, set := range nameSets {
for _, n := range set {
if !seen[n] {
seen[n] = true
names = append(names, n)
}
}
}
return buildInstrs(names, summaries)
}
// buildInstrs merges the complete generated instruction name list with a
// curated summaries map (keyed by upper-case mnemonic). Instructions without a
// curated entry get an empty summary and an unknown operand count, which keeps
// the operand-count lint silent for them.
func buildInstrs(names []string, summaries map[string]Instr) []Instr {
out := make([]Instr, 0, len(names))
for _, n := range names {
if in, ok := summaries[strings.ToUpper(n)]; ok {
in.Name = n
out = append(out, in)
} else {
out = append(out, Instr{Name: n, MinOps: -1, MaxOps: -1})
}
}
return out
}
// toMap converts a curated instruction slice into an upper-case-keyed map.
func toMap(list []Instr) map[string]Instr {
m := make(map[string]Instr, len(list))
for _, in := range list {
m[strings.ToUpper(in.Name)] = in
}
return m
}
+161
View File
@@ -0,0 +1,161 @@
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
package arch
import "testing"
func TestFromFilename(t *testing.T) {
cases := map[string]Arch{
"avx2_amd64.s": AMD64,
"foo_arm64.s": ARM64,
"portable.s": Unknown,
"decode_ARM64.S": ARM64,
"kernels_amd64.s": AMD64,
"kernel_riscv64.s": RISCV,
"kernel_loong64.s": LOONG64,
}
for name, want := range cases {
if got := FromFilename(name); got != want {
t.Errorf("FromFilename(%q) = %q, want %q", name, got, want)
}
}
}
func TestAMD64Registers(t *testing.T) {
tab := ForArch(AMD64)
for _, reg := range []string{"AX", "BX", "R15", "AL", "X0", "Y15", "Z31", "K7"} {
if !tab.IsRegister(reg) {
t.Errorf("amd64: %s should be a register", reg)
}
}
for _, not := range []string{"vec1", "R16", "Z32", "K8", "swin_base"} {
if tab.IsRegister(not) {
t.Errorf("amd64: %s should NOT be a register", not)
}
}
if r, ok := tab.Register("Y0"); !ok || r.Class != Vector {
t.Errorf("Y0 class = %+v, want Vector", r)
}
if r, ok := tab.Register("K1"); !ok || r.Class != Mask {
t.Errorf("K1 class = %+v, want Mask", r)
}
}
func TestARM64Registers(t *testing.T) {
tab := ForArch(ARM64)
for _, reg := range []string{"R0", "R30", "SP", "ZR", "F0", "V31"} {
if !tab.IsRegister(reg) {
t.Errorf("arm64: %s should be a register", reg)
}
}
if tab.IsRegister("AX") {
t.Error("arm64: AX must not be a register")
}
}
func TestAMD64Instructions(t *testing.T) {
tab := ForArch(AMD64)
// Every mnemonic used in the go-flac kernels must be known.
used := []string{
"MOVQ", "MOVL", "MOVB", "LEAQ", "ADDQ", "SUBL", "ANDQ", "ORL", "XORL",
"CMPQ", "CMPL", "TESTQ", "IMUL3L", "IMULQ", "INCW", "LZCNTL", "CMOVLGT",
"SETNE", "JMP", "JGE", "JNE", "JLE", "JLT", "JGT", "JZ", "JNZ", "RET",
"VPCMPEQD", "VPSLLD", "VPXOR", "VPSUBD", "VPADDD", "VPADDQ", "VMOVDQU",
"VEXTRACTI128", "VPSHUFD", "VMOVQ", "VMOVMSKPS", "VZEROUPPER", "VPUNPCKLDQ",
"VPUNPCKHDQ", "VPSRAD", "VPOR", "VPMOVSXDQ", "VPMULDQ", "VPCMPGTQ", "VPSRLQ",
"VPANDN", "VPMOVMSKB", "VPBROADCASTD", "VPSHUFB", "VPACKSSDW", "VPERMQ",
"VPERM2I128", "VPMOVZXDQ", "VFMADD231PD", "VCVTDQ2PD", "VMOVUPD", "VMULPD",
"VADDPD", "VADDSD", "VMOVSD", "VMULSD", "CVTSL2SD", "VEXTRACTF128",
"VPMOVSXWD", "MOVWLSX", "MOVBLZX", "MOVLQSX",
// AVX-512.
"VMOVDQU32", "VPXORD", "VALIGND", "VPERMD", "VPMULLD", "VPMOVDW", "VPSRAQ",
"KTESTW", "KMOVW", "VPXORQ", "VPMOVQD", "VEXTRACTF64X4", "VEXTRACTI64X4",
"VPBROADCASTQ", "VPMULLQ", "VPCMPEQD",
}
for _, m := range used {
if _, ok := tab.Lookup(m); !ok {
t.Errorf("amd64: instruction %s is missing from the table", m)
}
}
}
func TestOperandCounts(t *testing.T) {
tab := ForArch(AMD64)
if in, _ := tab.Lookup("RET"); in.MinOps != 0 || in.MaxOps != 0 {
t.Errorf("RET counts = %d/%d, want 0/0", in.MinOps, in.MaxOps)
}
if in, _ := tab.Lookup("JMP"); in.MinOps != 1 || in.MaxOps != 1 {
t.Errorf("JMP counts = %d/%d, want 1/1", in.MinOps, in.MaxOps)
}
if in, _ := tab.Lookup("MOVQ"); in.MinOps != 2 || in.MaxOps != 2 {
t.Errorf("MOVQ counts = %d/%d, want 2/2", in.MinOps, in.MaxOps)
}
if in, _ := tab.Lookup("IMUL3L"); in.MinOps != 3 || in.MaxOps != 3 {
t.Errorf("IMUL3L counts = %d/%d, want 3/3", in.MinOps, in.MaxOps)
}
}
func TestPseudoRegs(t *testing.T) {
for _, p := range []string{"FP", "SP", "SB", "PC"} {
if !IsPseudoReg(p) {
t.Errorf("%s should be a pseudo-register", p)
}
}
if IsPseudoReg("AX") {
t.Error("AX must not be a pseudo-register")
}
}
func TestRISCVRegisters(t *testing.T) {
tab := ForArch(RISCV)
for _, reg := range []string{"X0", "X31", "F0", "F31", "ZERO", "RA", "SP", "A0", "S11", "T6", "FA0"} {
if !tab.IsRegister(reg) {
t.Errorf("riscv: %s should be a register", reg)
}
}
if tab.IsRegister("AX") {
t.Error("riscv: AX must not be a register")
}
}
func TestLOONG64Registers(t *testing.T) {
tab := ForArch(LOONG64)
for _, reg := range []string{"R0", "R31", "F0", "F31", "V0", "V31", "X0", "X31"} {
if !tab.IsRegister(reg) {
t.Errorf("loong64: %s should be a register", reg)
}
}
if tab.IsRegister("AX") {
t.Error("loong64: AX must not be a register")
}
}
func TestRISCVInstructions(t *testing.T) {
tab := ForArch(RISCV)
for _, m := range []string{"ADD", "ADDI", "SUB", "MUL", "DIV", "BEQ", "BNE", "JAL", "JALR", "LW", "SW", "FADDD", "AMOSWAPD"} {
if _, ok := tab.Lookup(m); !ok {
t.Errorf("riscv: instruction %s is missing", m)
}
}
}
func TestLOONG64Instructions(t *testing.T) {
tab := ForArch(LOONG64)
for _, m := range []string{"ADD", "ADDD", "SUBD", "MULD", "BEQ", "BNE", "BGE", "BGEZ", "JIRL", "MOVD", "MOVW"} {
if _, ok := tab.Lookup(m); !ok {
t.Errorf("loong64: instruction %s is missing", m)
}
}
}
// TestGeneratedTableSize sanity-checks that the toolchain-derived tables are
// the full instruction sets, not a partial hand-written subset.
func TestGeneratedTableSize(t *testing.T) {
min := map[Arch]int{AMD64: 1000, ARM64: 400, RISCV: 800, LOONG64: 600}
for a, want := range min {
if n := len(ForArch(a).Instructions()); n < want {
t.Errorf("%s: only %d instructions, want >= %d (generation incomplete?)", a, n, want)
}
}
}
+181
View File
@@ -0,0 +1,181 @@
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
package arch
import "fmt"
func buildARM64() *Table {
return newTable(ARM64, arm64Registers(), relaxCounts(mergedInstrs(arm64Summaries(), commonGeneratedInstrs, arm64GeneratedInstrs, arm64Aliases())))
}
// arm64Aliases are the branch/jump spellings the assembler front-end accepts in
// addition to the generated opcode table (notably the unconditional B and BL).
func arm64Aliases() []string {
return []string{
"B", "BL", "BCS", "BHS", "BCC", "BLO", "BMI", "BPL", "BVS", "BVC",
"BHI", "BLS", "CBZW", "CBNZW", "ADR", "ADRP",
}
}
// arm64Summaries returns the curated documentation/operand-count table keyed by
// upper-case mnemonic; it enriches the complete generated name list.
func arm64Summaries() map[string]Instr { return toMap(arm64Curated()) }
// arm64Registers builds the arm64 (AArch64) register file.
func arm64Registers() []Register {
var regs []Register
add := func(name string, class RegClass, desc string) {
regs = append(regs, Register{Name: name, Class: class, Desc: desc})
}
// General-purpose integer registers R0–R30.
for i := 0; i <= 30; i++ {
add(fmt.Sprintf("R%d", i), GPR, "64-bit general-purpose register")
}
add("ZR", Special, "zero register (reads as 0)")
add("SP", Special, "stack pointer")
add("LR", Special, "link register (alias of R30)")
add("PC", Special, "program counter")
add("RSP", Special, "stack pointer (alias)")
// Floating-point / SIMD registers: F (scalar FP) and V (vector).
for i := 0; i <= 31; i++ {
add(fmt.Sprintf("F%d", i), Float, "floating-point register")
add(fmt.Sprintf("V%d", i), VecARM, "128-bit SIMD/vector register")
}
return regs
}
// arm64Curated returns the hand-written subset of arm64 (AArch64) instructions
// that carry a summary and/or an operand-count range. 32-bit operations carry
// a W suffix. The authoritative, complete set is arm64GeneratedInstrs.
func arm64Curated() []Instr {
var t []Instr
// Data movement (loads and stores are MOVx with a memory operand).
for _, m := range []string{
"MOVB", "MOVBU", "MOVH", "MOVHU", "MOVW", "MOVWU", "MOVD",
"FMOVS", "FMOVD",
} {
t = append(t, ic(m, "Move / load / store", 2, 2))
}
for _, m := range []string{"MOVK", "MOVN", "MOVZ", "MOVKW", "MOVNW", "MOVZW"} {
t = append(t, i(m, "Move wide constant"))
}
for _, m := range []string{"ADR", "ADRP"} {
t = append(t, ic(m, "Address of label/page", 2, 2))
}
// Integer arithmetic and logic (64-bit and W 32-bit forms).
for _, op := range []string{"ADD", "ADDS", "SUB", "SUBS", "AND", "ANDS", "ORR", "ORN", "EOR", "EON", "BIC", "BICS", "ADC", "ADCS", "SBC", "SBCS"} {
t = append(t, i(op, op+" (64-bit)"))
t = append(t, i(op+"W", op+" (32-bit)"))
}
for _, op := range []string{"NEG", "NGC", "MVN"} {
t = append(t, i(op, op+" (64-bit)"))
t = append(t, i(op+"W", op+" (32-bit)"))
}
for _, op := range []string{"MUL", "MNEG", "SMULL", "UMULL", "SMULH", "UMULH", "MADD", "MSUB", "SMADDL", "UMADDL", "SMSUBL", "UMSUBL"} {
t = append(t, i(op, "Multiply / multiply-accumulate"))
}
for _, op := range []string{"UDIV", "SDIV", "UDIVW", "SDIVW"} {
t = append(t, ic(op, "Divide", 3, 3))
}
// Shifts, rotates and bit manipulation.
for _, op := range []string{"LSL", "LSR", "ASR", "ROR"} {
t = append(t, i(op, op+" shift"))
t = append(t, i(op+"W", op+" shift (32-bit)"))
}
for _, op := range []string{"LSLV", "LSRV", "ASRV", "RORV", "LSLVW", "LSRVW", "ASRVW", "RORVW"} {
t = append(t, i(op, "Variable shift"))
}
for _, op := range []string{"RBIT", "REV", "REV16", "REV32", "REV64", "CLZ", "CLS", "RBITW", "REVW", "CLZW", "CLSW"} {
t = append(t, ic(op, "Bit manipulation", 2, 2))
}
for _, op := range []string{"UBFX", "SBFX", "UBFM", "SBFM", "BFXIL", "EXTR"} {
t = append(t, i(op, "Bitfield extract"))
}
// Compare and test.
for _, op := range []string{"CMP", "CMN", "TST"} {
t = append(t, i(op, op+" (64-bit)"))
t = append(t, i(op+"W", op+" (32-bit)"))
}
// Conditional select.
for _, op := range []string{"CSEL", "CSINC", "CSINV", "CSNEG", "CSET", "CSETM", "CINC", "CINV", "CNEG"} {
t = append(t, i(op, "Conditional select"))
t = append(t, i(op+"W", "Conditional select (32-bit)"))
}
for _, op := range []string{"CCMP", "CCMN", "CCMPW", "CCMNW"} {
t = append(t, i(op, "Conditional compare"))
}
// Control flow.
t = append(t, ic("B", "Unconditional branch", 1, 1))
t = append(t, ic("BL", "Branch with link", 1, 1))
for _, cc := range []string{
"EQ", "NE", "CS", "HS", "CC", "LO", "MI", "PL", "VS", "VC",
"HI", "LS", "GE", "LT", "GT", "LE", "AL", "NV",
} {
t = append(t, ic("B"+cc, "Conditional branch", 1, 1))
}
for _, op := range []string{"CBZ", "CBNZ", "TBZ", "TBNZ"} {
t = append(t, i(op, "Compare/test and branch"))
t = append(t, i(op+"W", "Compare/test and branch (32-bit)"))
}
t = append(t, ic("RET", "Return", 0, 1))
t = append(t, ic("BR", "Branch to register", 1, 1))
t = append(t, ic("BLR", "Branch with link to register", 1, 1))
t = append(t, ic("NOP", "No operation", 0, 1))
t = append(t, ic("BRK", "Breakpoint", 0, 1))
for _, op := range []string{"SVC", "HVC", "SMC"} {
t = append(t, i(op, "Exception generation"))
}
for _, op := range []string{"DMB", "DSB", "ISB"} {
t = append(t, i(op, "Barrier"))
}
for _, op := range []string{"MRS", "MSR"} {
t = append(t, ic(op, "System register access", 2, 2))
}
// Atomics (LSE and load-exclusive/store-exclusive).
for _, op := range []string{
"LDAXR", "LDAXRB", "LDAXRH", "LDAXRW", "STXR", "STXRB", "STXRH", "STXRW",
"LDAR", "LDARB", "LDARH", "LDARW", "STLR", "STLRB", "STLRH", "STLRW",
"LDADD", "LDCLR", "LDEOR", "LDSET", "SWP", "CAS", "CASAL", "CASL", "CASAL",
} {
t = append(t, i(op, "Atomic memory operation"))
}
// Floating-point scalar.
for _, op := range []string{
"FADD", "FSUB", "FMUL", "FDIV", "FNEG", "FABS", "FSQRT", "FMIN", "FMAX",
"FMADD", "FMSUB", "FNMADD", "FNMSUB", "FCMP", "FCMPE",
"FCVT", "FCVTZS", "FCVTZU", "FCVTNS", "FCVTNU", "FCVTAS", "FCVTAU",
"SCVTF", "UCVTF", "FRINTM", "FRINTN", "FRINTP", "FRINTZ",
} {
t = append(t, i(op, "Floating-point operation"))
}
t = append(t, i("FMOV", "Floating-point move"))
// NEON / SIMD vector (arrangement carried by the operand suffix).
for _, op := range []string{
"VADD", "VSUB", "VMUL", "VMLA", "VMLS", "VNEG", "VABS", "VMIN", "VMAX",
"VAND", "VORR", "VEOR", "VBIC", "VBIF", "VBSL", "VNOT",
"VDUP", "VMOV", "VMOVI", "VMOVQ",
"VLD1", "VLD2", "VLD3", "VLD4", "VST1", "VST2", "VST3", "VST4",
"VCNT", "VREV16", "VREV32", "VREV64", "VUZP1", "VUZP2", "VZIP1", "VZIP2", "VTRN1", "VTRN2",
"VSHL", "VSHR", "VSSHLL", "VUSHR", "VEXT", "VTBL", "VTBX",
"VADDV", "VUMAXV", "VUMINV", "VSMAXV", "VSMINV",
"VFADD", "VFSUB", "VFMUL", "VFDIV", "VFNEG", "VFABS", "VFMIN", "VFMAX",
"VFMLA", "VFMLS", "VFCVT", "VSCVTF", "VUCVTF", "VFCMEQ", "VFCMGT", "VFCMLT",
"VCMPEQ", "VCMPGT", "VCMPGE", "VSHLL",
} {
t = append(t, i(op, "NEON SIMD vector operation"))
}
return t
}
+547
View File
@@ -0,0 +1,547 @@
// Code generated by gasm-devkit _gen; DO NOT EDIT.
// Source: cmd/internal/obj/arm64/anames.go from the Go toolchain.
package arch
// arm64GeneratedInstrs is the complete set of arm64 mnemonics accepted by
// Go's Plan 9 assembler.
var arm64GeneratedInstrs = []string{
"ADC",
"ADCS",
"ADCSW",
"ADCW",
"ADD",
"ADDS",
"ADDSW",
"ADDW",
"ADR",
"ADRP",
"AESD",
"AESE",
"AESIMC",
"AESMC",
"AND",
"ANDS",
"ANDSW",
"ANDW",
"ASR",
"ASRW",
"AT",
"AUTIA1716",
"AUTIASP",
"AUTIB1716",
"AUTIBSP",
"BCC",
"BCS",
"BEQ",
"BFI",
"BFIW",
"BFM",
"BFMW",
"BFXIL",
"BFXILW",
"BGE",
"BGT",
"BHI",
"BHS",
"BIC",
"BICS",
"BICSW",
"BICW",
"BLE",
"BLO",
"BLS",
"BLT",
"BMI",
"BNE",
"BPL",
"BRK",
"BTI",
"BVC",
"BVS",
"CASAD",
"CASALB",
"CASALD",
"CASALH",
"CASALW",
"CASAW",
"CASB",
"CASD",
"CASH",
"CASLD",
"CASLW",
"CASPD",
"CASPW",
"CASW",
"CBNZ",
"CBNZW",
"CBZ",
"CBZW",
"CCMN",
"CCMNW",
"CCMP",
"CCMPW",
"CINC",
"CINCW",
"CINV",
"CINVW",
"CLREX",
"CLS",
"CLSW",
"CLZ",
"CLZW",
"CMN",
"CMNW",
"CMP",
"CMPW",
"CNEG",
"CNEGW",
"CRC32B",
"CRC32CB",
"CRC32CH",
"CRC32CW",
"CRC32CX",
"CRC32H",
"CRC32W",
"CRC32X",
"CSEL",
"CSELW",
"CSET",
"CSETM",
"CSETMW",
"CSETW",
"CSINC",
"CSINCW",
"CSINV",
"CSINVW",
"CSNEG",
"CSNEGW",
"DC",
"DCPS1",
"DCPS2",
"DCPS3",
"DMB",
"DRPS",
"DSB",
"DWORD",
"EON",
"EONW",
"EOR",
"EORW",
"ERET",
"EXTR",
"EXTRW",
"FABSD",
"FABSS",
"FADDD",
"FADDS",
"FCCMPD",
"FCCMPED",
"FCCMPES",
"FCCMPS",
"FCMPD",
"FCMPED",
"FCMPES",
"FCMPS",
"FCSELD",
"FCSELS",
"FCVTDH",
"FCVTDS",
"FCVTHD",
"FCVTHS",
"FCVTSD",
"FCVTSH",
"FCVTZSD",
"FCVTZSDW",
"FCVTZSS",
"FCVTZSSW",
"FCVTZUD",
"FCVTZUDW",
"FCVTZUS",
"FCVTZUSW",
"FDIVD",
"FDIVS",
"FLDPD",
"FLDPQ",
"FLDPS",
"FMADDD",
"FMADDS",
"FMAXD",
"FMAXNMD",
"FMAXNMS",
"FMAXS",
"FMIND",
"FMINNMD",
"FMINNMS",
"FMINS",
"FMOVD",
"FMOVQ",
"FMOVS",
"FMSUBD",
"FMSUBS",
"FMULD",
"FMULS",
"FNEGD",
"FNEGS",
"FNMADDD",
"FNMADDS",
"FNMSUBD",
"FNMSUBS",
"FNMULD",
"FNMULS",
"FRINTAD",
"FRINTAS",
"FRINTID",
"FRINTIS",
"FRINTMD",
"FRINTMS",
"FRINTND",
"FRINTNS",
"FRINTPD",
"FRINTPS",
"FRINTXD",
"FRINTXS",
"FRINTZD",
"FRINTZS",
"FSQRTD",
"FSQRTS",
"FSTPD",
"FSTPQ",
"FSTPS",
"FSUBD",
"FSUBS",
"HINT",
"HLT",
"HVC",
"IC",
"ISB",
"LDADDAB",
"LDADDAD",
"LDADDAH",
"LDADDALB",
"LDADDALD",
"LDADDALH",
"LDADDALW",
"LDADDAW",
"LDADDB",
"LDADDD",
"LDADDH",
"LDADDLB",
"LDADDLD",
"LDADDLH",
"LDADDLW",
"LDADDW",
"LDAR",
"LDARB",
"LDARH",
"LDARW",
"LDAXP",
"LDAXPW",
"LDAXR",
"LDAXRB",
"LDAXRH",
"LDAXRW",
"LDCLRAB",
"LDCLRAD",
"LDCLRAH",
"LDCLRALB",
"LDCLRALD",
"LDCLRALH",
"LDCLRALW",
"LDCLRAW",
"LDCLRB",
"LDCLRD",
"LDCLRH",
"LDCLRLB",
"LDCLRLD",
"LDCLRLH",
"LDCLRLW",
"LDCLRW",
"LDEORAB",
"LDEORAD",
"LDEORAH",
"LDEORALB",
"LDEORALD",
"LDEORALH",
"LDEORALW",
"LDEORAW",
"LDEORB",
"LDEORD",
"LDEORH",
"LDEORLB",
"LDEORLD",
"LDEORLH",
"LDEORLW",
"LDEORW",
"LDORAB",
"LDORAD",
"LDORAH",
"LDORALB",
"LDORALD",
"LDORALH",
"LDORALW",
"LDORAW",
"LDORB",
"LDORD",
"LDORH",
"LDORLB",
"LDORLD",
"LDORLH",
"LDORLW",
"LDORW",
"LDP",
"LDPSW",
"LDPW",
"LDXP",
"LDXPW",
"LDXR",
"LDXRB",
"LDXRH",
"LDXRW",
"LSL",
"LSLW",
"LSR",
"LSRW",
"MADD",
"MADDW",
"MNEG",
"MNEGW",
"MOVB",
"MOVBU",
"MOVD",
"MOVH",
"MOVHU",
"MOVK",
"MOVKW",
"MOVN",
"MOVNW",
"MOVP",
"MOVPD",
"MOVPQ",
"MOVPS",
"MOVPSW",
"MOVPW",
"MOVW",
"MOVWU",
"MOVZ",
"MOVZW",
"MRS",
"MSR",
"MSUB",
"MSUBW",
"MUL",
"MULW",
"MVN",
"MVNW",
"NEG",
"NEGS",
"NEGSW",
"NEGW",
"NGC",
"NGCS",
"NGCSW",
"NGCW",
"NOOP",
"ORN",
"ORNW",
"ORR",
"ORRW",
"PACIASP",
"PACIBSP",
"PRFM",
"PRFUM",
"RBIT",
"RBITW",
"REM",
"REMW",
"REV",
"REV16",
"REV16W",
"REV32",
"REVW",
"ROR",
"RORW",
"SBC",
"SBCS",
"SBCSW",
"SBCW",
"SBFIZ",
"SBFIZW",
"SBFM",
"SBFMW",
"SBFX",
"SBFXW",
"SCVTFD",
"SCVTFS",
"SCVTFWD",
"SCVTFWS",
"SDIV",
"SDIVW",
"SEV",
"SEVL",
"SHA1C",
"SHA1H",
"SHA1M",
"SHA1P",
"SHA1SU0",
"SHA1SU1",
"SHA256H",
"SHA256H2",
"SHA256SU0",
"SHA256SU1",
"SHA512H",
"SHA512H2",
"SHA512SU0",
"SHA512SU1",
"SMADDL",
"SMC",
"SMNEGL",
"SMSUBL",
"SMULH",
"SMULL",
"STLR",
"STLRB",
"STLRH",
"STLRW",
"STLXP",
"STLXPW",
"STLXR",
"STLXRB",
"STLXRH",
"STLXRW",
"STP",
"STPW",
"STXP",
"STXPW",
"STXR",
"STXRB",
"STXRH",
"STXRW",
"SUB",
"SUBS",
"SUBSW",
"SUBW",
"SVC",
"SWPAB",
"SWPAD",
"SWPAH",
"SWPALB",
"SWPALD",
"SWPALH",
"SWPALW",
"SWPAW",
"SWPB",
"SWPD",
"SWPH",
"SWPLB",
"SWPLD",
"SWPLH",
"SWPLW",
"SWPW",
"SXTB",
"SXTBW",
"SXTH",
"SXTHW",
"SXTW",
"SYS",
"SYSL",
"TBNZ",
"TBZ",
"TLBI",
"TST",
"TSTW",
"UBFIZ",
"UBFIZW",
"UBFM",
"UBFMW",
"UBFX",
"UBFXW",
"UCVTFD",
"UCVTFS",
"UCVTFWD",
"UCVTFWS",
"UDIV",
"UDIVW",
"UMADDL",
"UMNEGL",
"UMSUBL",
"UMULH",
"UMULL",
"UREM",
"UREMW",
"UXTB",
"UXTBW",
"UXTH",
"UXTHW",
"UXTW",
"VADD",
"VADDP",
"VADDV",
"VAND",
"VBCAX",
"VBIF",
"VBIT",
"VBSL",
"VCMEQ",
"VCMTST",
"VCNT",
"VDUP",
"VEOR",
"VEOR3",
"VEXT",
"VFMLA",
"VFMLS",
"VLD1",
"VLD1R",
"VLD2",
"VLD2R",
"VLD3",
"VLD3R",
"VLD4",
"VLD4R",
"VMOV",
"VMOVD",
"VMOVI",
"VMOVQ",
"VMOVS",
"VORR",
"VPMULL",
"VPMULL2",
"VRAX1",
"VRBIT",
"VREV16",
"VREV32",
"VREV64",
"VSHL",
"VSLI",
"VSRI",
"VST1",
"VST2",
"VST3",
"VST4",
"VSUB",
"VTBL",
"VTBX",
"VTRN1",
"VTRN2",
"VUADDLV",
"VUADDW",
"VUADDW2",
"VUMAX",
"VUMIN",
"VUSHLL",
"VUSHLL2",
"VUSHR",
"VUSRA",
"VUXTL",
"VUXTL2",
"VUZP1",
"VUZP2",
"VXAR",
"VZIP1",
"VZIP2",
"WFE",
"WFI",
"WORD",
"YIELD",
}
+23
View File
@@ -0,0 +1,23 @@
// Code generated by gasm-devkit _gen; DO NOT EDIT.
// Source: cmd/internal/obj/util.go from the Go toolchain.
package arch
// commonGeneratedInstrs is the set of opcodes shared by every architecture
// (RET, JMP, NOP, CALL, TEXT, FUNCDATA, PCDATA, …).
var commonGeneratedInstrs = []string{
"CALL",
"DUFFCOPY",
"DUFFZERO",
"END",
"FUNCDATA",
"GETCALLERPC",
"JMP",
"NOP",
"PCALIGN",
"PCALIGNMAX",
"PCDATA",
"RET",
"TEXT",
"UNDEF",
}
+81
View File
@@ -0,0 +1,81 @@
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
package arch
import "fmt"
func buildLOONG64() *Table {
return newTable(LOONG64, loong64Registers(), relaxCounts(mergedInstrs(loong64Summaries(), commonGeneratedInstrs, loong64GeneratedInstrs, loong64Aliases())))
}
// loong64Aliases are branch spellings the assembler front-end accepts in
// addition to the generated opcode table (notably JAL, BFPF and BFPT).
func loong64Aliases() []string {
return []string{"JAL", "BFPF", "BFPT"}
}
func loong64Summaries() map[string]Instr { return toMap(loong64Curated()) }
// loong64Registers builds the LoongArch (loong64) register file: 32 integer
// (R), 32 floating-point (F), and the LSX/LASX SIMD vector registers (V and X).
func loong64Registers() []Register {
var regs []Register
add := func(name string, class RegClass, desc string) {
regs = append(regs, Register{Name: name, Class: class, Desc: desc})
}
for i := 0; i <= 31; i++ {
add(fmt.Sprintf("R%d", i), GPR, "integer register")
}
for i := 0; i <= 31; i++ {
add(fmt.Sprintf("F%d", i), Float, "floating-point register")
}
for i := 0; i <= 31; i++ {
add(fmt.Sprintf("V%d", i), VecARM, "LSX 128-bit vector register")
}
for i := 0; i <= 31; i++ {
add(fmt.Sprintf("X%d", i), VecARM, "LASX 256-bit vector register")
}
return regs
}
// loong64Curated is a hand-written subset of common LoongArch instructions
// carrying summaries. The authoritative, complete set is loong64GeneratedInstrs.
func loong64Curated() []Instr {
return []Instr{
ic("ADD", "Integer add (word)", 3, 3), ic("ADDW", "Add word", 3, 3),
ic("ADDD", "Add doubleword", 3, 3), ic("ADDI", "Add immediate", 3, 3),
ic("SUB", "Subtract (word)", 3, 3), ic("SUBW", "Subtract word", 3, 3),
ic("SUBD", "Subtract doubleword", 3, 3),
ic("AND", "Bitwise AND", 3, 3), ic("ANDI", "AND immediate", 3, 3),
ic("OR", "Bitwise OR", 3, 3), ic("ORI", "OR immediate", 3, 3),
ic("XOR", "Bitwise XOR", 3, 3), ic("XORI", "XOR immediate", 3, 3),
ic("NOR", "Bitwise NOR", 3, 3),
ic("MUL", "Multiply (word)", 3, 3), ic("MULW", "Multiply word", 3, 3),
ic("MULD", "Multiply doubleword", 3, 3),
ic("DIV", "Divide (word)", 3, 3), ic("DIVW", "Divide word", 3, 3),
ic("DIVD", "Divide doubleword", 3, 3),
ic("MOD", "Modulo (word)", 3, 3), ic("MODW", "Modulo word", 3, 3),
ic("MODD", "Modulo doubleword", 3, 3),
ic("SLL", "Shift left logical", 3, 3), ic("SRL", "Shift right logical", 3, 3),
ic("SRA", "Shift right arithmetic", 3, 3), ic("ROTR", "Rotate right", 3, 3),
ic("SLT", "Set if less than", 3, 3), ic("SLTU", "Set if less than unsigned", 3, 3),
ic("SLTI", "Set if less than immediate", 3, 3),
ic("LD", "Load doubleword", 2, 2), ic("LDW", "Load word", 2, 2),
ic("LDH", "Load halfword", 2, 2), ic("LDB", "Load byte", 2, 2),
ic("ST", "Store doubleword", 2, 2), ic("STW", "Store word", 2, 2),
ic("STH", "Store halfword", 2, 2), ic("STB", "Store byte", 2, 2),
ic("BEQ", "Branch if equal", 3, 3), ic("BNE", "Branch if not equal", 3, 3),
ic("BLT", "Branch if less than", 3, 3), ic("BGE", "Branch if greater or equal", 3, 3),
ic("BLTU", "Branch if less than unsigned", 3, 3), ic("BGEU", "Branch if greater or equal unsigned", 3, 3),
ic("B", "Unconditional branch", 1, 1), ic("BL", "Branch with link", 1, 1),
ic("JIRL", "Jump indirect with link", 1, 3),
ic("RET", "Return", 0, 1), ic("NOP", "No operation", 0, 1),
i("SYSCALL", "System call"), i("BREAK", "Breakpoint"), i("DBAR", "Barrier"),
ic("FADDS", "FP add (single)", 3, 3), ic("FADDD", "FP add (double)", 3, 3),
ic("FSUBS", "FP subtract (single)", 3, 3), ic("FSUBD", "FP subtract (double)", 3, 3),
ic("FMULS", "FP multiply (single)", 3, 3), ic("FMULD", "FP multiply (double)", 3, 3),
ic("FDIVS", "FP divide (single)", 3, 3), ic("FDIVD", "FP divide (double)", 3, 3),
ic("MOV", "Move register", 2, 2),
}
}
+808
View File
@@ -0,0 +1,808 @@
// Code generated by gasm-devkit _gen; DO NOT EDIT.
// Source: cmd/internal/obj/loong64/anames.go from the Go toolchain.
package arch
// loong64GeneratedInstrs is the complete set of loong64 mnemonics accepted by
// Go's Plan 9 assembler.
var loong64GeneratedInstrs = []string{
"ABSD",
"ABSF",
"ADD",
"ADDD",
"ADDF",
"ADDV",
"ADDV16",
"ADDVU",
"ADDW",
"ALSLV",
"ALSLW",
"ALSLWU",
"AMADDDBV",
"AMADDDBW",
"AMADDV",
"AMADDW",
"AMANDDBV",
"AMANDDBW",
"AMANDV",
"AMANDW",
"AMCASB",
"AMCASDBB",
"AMCASDBH",
"AMCASDBV",
"AMCASDBW",
"AMCASH",
"AMCASV",
"AMCASW",
"AMMAXDBV",
"AMMAXDBVU",
"AMMAXDBW",
"AMMAXDBWU",
"AMMAXV",
"AMMAXVU",
"AMMAXW",
"AMMAXWU",
"AMMINDBV",
"AMMINDBVU",
"AMMINDBW",
"AMMINDBWU",
"AMMINV",
"AMMINVU",
"AMMINW",
"AMMINWU",
"AMORDBV",
"AMORDBW",
"AMORV",
"AMORW",
"AMSWAPB",
"AMSWAPDBB",
"AMSWAPDBH",
"AMSWAPDBV",
"AMSWAPDBW",
"AMSWAPH",
"AMSWAPV",
"AMSWAPW",
"AMXORDBV",
"AMXORDBW",
"AMXORV",
"AMXORW",
"AND",
"ANDN",
"BEQ",
"BFPF",
"BFPT",
"BGE",
"BGEU",
"BGEZ",
"BGTZ",
"BITREV4B",
"BITREV8B",
"BITREVV",
"BITREVW",
"BLEZ",
"BLT",
"BLTU",
"BLTZ",
"BNE",
"BREAK",
"BSTRINSV",
"BSTRINSW",
"BSTRPICKV",
"BSTRPICKW",
"CLOV",
"CLOW",
"CLZV",
"CLZW",
"CMPEQD",
"CMPEQF",
"CMPGED",
"CMPGEF",
"CMPGTD",
"CMPGTF",
"CPUCFG",
"CRCCWBW",
"CRCCWHW",
"CRCCWVW",
"CRCCWWW",
"CRCWBW",
"CRCWHW",
"CRCWVW",
"CRCWWW",
"CTOV",
"CTOW",
"CTZV",
"CTZW",
"DBAR",
"DIV",
"DIVD",
"DIVF",
"DIVU",
"DIVV",
"DIVVU",
"DIVW",
"DIVWU",
"EXTWB",
"EXTWH",
"FCLASSD",
"FCLASSF",
"FCOPYSGD",
"FCOPYSGF",
"FFINTDV",
"FFINTDW",
"FFINTFV",
"FFINTFW",
"FLOGBD",
"FLOGBF",
"FMADDD",
"FMADDF",
"FMAXAD",
"FMAXAF",
"FMAXD",
"FMAXF",
"FMINAD",
"FMINAF",
"FMIND",
"FMINF",
"FMSUBD",
"FMSUBF",
"FNMADDD",
"FNMADDF",
"FNMSUBD",
"FNMSUBF",
"FSCALEBD",
"FSCALEBF",
"FSEL",
"FTINTRMVD",
"FTINTRMVF",
"FTINTRMWD",
"FTINTRMWF",
"FTINTRNEVD",
"FTINTRNEVF",
"FTINTRNEWD",
"FTINTRNEWF",
"FTINTRPVD",
"FTINTRPVF",
"FTINTRPWD",
"FTINTRPWF",
"FTINTRZVD",
"FTINTRZVF",
"FTINTRZWD",
"FTINTRZWF",
"FTINTVD",
"FTINTVF",
"FTINTWD",
"FTINTWF",
"JIRL",
"LL",
"LLV",
"LU12IW",
"LU32ID",
"LU52ID",
"LUI",
"MASKEQZ",
"MASKNEZ",
"MOVB",
"MOVBU",
"MOVD",
"MOVDF",
"MOVDV",
"MOVDW",
"MOVF",
"MOVFD",
"MOVFV",
"MOVFW",
"MOVH",
"MOVHU",
"MOVV",
"MOVVD",
"MOVVF",
"MOVVP",
"MOVW",
"MOVWD",
"MOVWF",
"MOVWP",
"MOVWU",
"MUL",
"MULD",
"MULF",
"MULH",
"MULHU",
"MULHV",
"MULHVU",
"MULV",
"MULVU",
"MULW",
"MULWVW",
"MULWVWU",
"NEGD",
"NEGF",
"NEGV",
"NEGW",
"NOOP",
"NOR",
"OR",
"ORN",
"PCADDU12I",
"PCALAU12I",
"PRELD",
"PRELDX",
"RDTIMED",
"RDTIMEHW",
"RDTIMELW",
"REM",
"REMU",
"REMV",
"REMVU",
"REMW",
"REMWU",
"REVB2H",
"REVB2W",
"REVB4H",
"REVBV",
"REVH2W",
"REVHV",
"RFE",
"ROTR",
"ROTRV",
"SC",
"SCV",
"SGT",
"SGTU",
"SLL",
"SLLV",
"SQRTD",
"SQRTF",
"SRA",
"SRAV",
"SRL",
"SRLV",
"SUB",
"SUBD",
"SUBF",
"SUBV",
"SUBVU",
"SUBW",
"SYSCALL",
"TEQ",
"TNE",
"TRUNCDV",
"TRUNCDW",
"TRUNCFV",
"TRUNCFW",
"VADDB",
"VADDBU",
"VADDD",
"VADDF",
"VADDH",
"VADDHU",
"VADDQ",
"VADDV",
"VADDVU",
"VADDW",
"VADDWEVHB",
"VADDWEVHBU",
"VADDWEVQV",
"VADDWEVQVU",
"VADDWEVVW",
"VADDWEVVWU",
"VADDWEVWH",
"VADDWEVWHU",
"VADDWODHB",
"VADDWODHBU",
"VADDWODQV",
"VADDWODQVU",
"VADDWODVW",
"VADDWODVWU",
"VADDWODWH",
"VADDWODWHU",
"VADDWU",
"VANDB",
"VANDNV",
"VANDV",
"VBITCLRB",
"VBITCLRH",
"VBITCLRV",
"VBITCLRW",
"VBITREVB",
"VBITREVH",
"VBITREVV",
"VBITREVW",
"VBITSETB",
"VBITSETH",
"VBITSETV",
"VBITSETW",
"VDIVB",
"VDIVBU",
"VDIVD",
"VDIVF",
"VDIVH",
"VDIVHU",
"VDIVV",
"VDIVVU",
"VDIVW",
"VDIVWU",
"VEXTRINSB",
"VEXTRINSH",
"VEXTRINSV",
"VEXTRINSW",
"VFCLASSD",
"VFCLASSF",
"VFRECIPD",
"VFRECIPF",
"VFRINTD",
"VFRINTF",
"VFRINTRMD",
"VFRINTRMF",
"VFRINTRNED",
"VFRINTRNEF",
"VFRINTRPD",
"VFRINTRPF",
"VFRINTRZD",
"VFRINTRZF",
"VFRSQRTD",
"VFRSQRTF",
"VFSQRTD",
"VFSQRTF",
"VILVHB",
"VILVHH",
"VILVHV",
"VILVHW",
"VILVLB",
"VILVLH",
"VILVLV",
"VILVLW",
"VMADDB",
"VMADDH",
"VMADDV",
"VMADDW",
"VMADDWEVHB",
"VMADDWEVHBU",
"VMADDWEVHBUB",
"VMADDWEVQV",
"VMADDWEVQVU",
"VMADDWEVQVUV",
"VMADDWEVVW",
"VMADDWEVVWU",
"VMADDWEVVWUW",
"VMADDWEVWH",
"VMADDWEVWHU",
"VMADDWEVWHUH",
"VMADDWODHB",
"VMADDWODHBU",
"VMADDWODHBUB",
"VMADDWODQV",
"VMADDWODQVU",
"VMADDWODQVUV",
"VMADDWODVW",
"VMADDWODVWU",
"VMADDWODVWUW",
"VMADDWODWH",
"VMADDWODWHU",
"VMADDWODWHUH",
"VMODB",
"VMODBU",
"VMODH",
"VMODHU",
"VMODV",
"VMODVU",
"VMODW",
"VMODWU",
"VMOVQ",
"VMSUBB",
"VMSUBH",
"VMSUBV",
"VMSUBW",
"VMUHB",
"VMUHBU",
"VMUHH",
"VMUHHU",
"VMUHV",
"VMUHVU",
"VMUHW",
"VMUHWU",
"VMULB",
"VMULD",
"VMULF",
"VMULH",
"VMULV",
"VMULW",
"VMULWEVHB",
"VMULWEVHBU",
"VMULWEVHBUB",
"VMULWEVQV",
"VMULWEVQVU",
"VMULWEVQVUV",
"VMULWEVVW",
"VMULWEVVWU",
"VMULWEVVWUW",
"VMULWEVWH",
"VMULWEVWHU",
"VMULWEVWHUH",
"VMULWODHB",
"VMULWODHBU",
"VMULWODHBUB",
"VMULWODQV",
"VMULWODQVU",
"VMULWODQVUV",
"VMULWODVW",
"VMULWODVWU",
"VMULWODVWUW",
"VMULWODWH",
"VMULWODWHU",
"VMULWODWHUH",
"VNEGB",
"VNEGH",
"VNEGV",
"VNEGW",
"VNORB",
"VNORV",
"VORB",
"VORNV",
"VORV",
"VPCNTB",
"VPCNTH",
"VPCNTV",
"VPCNTW",
"VPERMIW",
"VROTRB",
"VROTRH",
"VROTRV",
"VROTRW",
"VSADDB",
"VSADDBU",
"VSADDH",
"VSADDHU",
"VSADDV",
"VSADDVU",
"VSADDW",
"VSADDWU",
"VSEQB",
"VSEQH",
"VSEQV",
"VSEQW",
"VSETALLNEB",
"VSETALLNEH",
"VSETALLNEV",
"VSETALLNEW",
"VSETANYEQB",
"VSETANYEQH",
"VSETANYEQV",
"VSETANYEQW",
"VSETEQV",
"VSETNEV",
"VSHUF4IB",
"VSHUF4IH",
"VSHUF4IV",
"VSHUF4IW",
"VSHUFB",
"VSHUFH",
"VSHUFV",
"VSHUFW",
"VSLLB",
"VSLLH",
"VSLLV",
"VSLLW",
"VSLTB",
"VSLTBU",
"VSLTH",
"VSLTHU",
"VSLTV",
"VSLTVU",
"VSLTW",
"VSLTWU",
"VSRAB",
"VSRAH",
"VSRAV",
"VSRAW",
"VSRLB",
"VSRLH",
"VSRLV",
"VSRLW",
"VSSUBB",
"VSSUBBU",
"VSSUBH",
"VSSUBHU",
"VSSUBV",
"VSSUBVU",
"VSSUBW",
"VSSUBWU",
"VSUBB",
"VSUBBU",
"VSUBD",
"VSUBF",
"VSUBH",
"VSUBHU",
"VSUBQ",
"VSUBV",
"VSUBVU",
"VSUBW",
"VSUBWEVHB",
"VSUBWEVHBU",
"VSUBWEVQV",
"VSUBWEVQVU",
"VSUBWEVVW",
"VSUBWEVVWU",
"VSUBWEVWH",
"VSUBWEVWHU",
"VSUBWODHB",
"VSUBWODHBU",
"VSUBWODQV",
"VSUBWODQVU",
"VSUBWODVW",
"VSUBWODVWU",
"VSUBWODWH",
"VSUBWODWHU",
"VSUBWU",
"VXORB",
"VXORV",
"WORD",
"XOR",
"XVADDB",
"XVADDBU",
"XVADDD",
"XVADDF",
"XVADDH",
"XVADDHU",
"XVADDQ",
"XVADDV",
"XVADDVU",
"XVADDW",
"XVADDWEVHB",
"XVADDWEVHBU",
"XVADDWEVQV",
"XVADDWEVQVU",
"XVADDWEVVW",
"XVADDWEVVWU",
"XVADDWEVWH",
"XVADDWEVWHU",
"XVADDWODHB",
"XVADDWODHBU",
"XVADDWODQV",
"XVADDWODQVU",
"XVADDWODVW",
"XVADDWODVWU",
"XVADDWODWH",
"XVADDWODWHU",
"XVADDWU",
"XVANDB",
"XVANDNV",
"XVANDV",
"XVBITCLRB",
"XVBITCLRH",
"XVBITCLRV",
"XVBITCLRW",
"XVBITREVB",
"XVBITREVH",
"XVBITREVV",
"XVBITREVW",
"XVBITSETB",
"XVBITSETH",
"XVBITSETV",
"XVBITSETW",
"XVDIVB",
"XVDIVBU",
"XVDIVD",
"XVDIVF",
"XVDIVH",
"XVDIVHU",
"XVDIVV",
"XVDIVVU",
"XVDIVW",
"XVDIVWU",
"XVEXTRINSB",
"XVEXTRINSH",
"XVEXTRINSV",
"XVEXTRINSW",
"XVFCLASSD",
"XVFCLASSF",
"XVFRECIPD",
"XVFRECIPF",
"XVFRINTD",
"XVFRINTF",
"XVFRINTRMD",
"XVFRINTRMF",
"XVFRINTRNED",
"XVFRINTRNEF",
"XVFRINTRPD",
"XVFRINTRPF",
"XVFRINTRZD",
"XVFRINTRZF",
"XVFRSQRTD",
"XVFRSQRTF",
"XVFSQRTD",
"XVFSQRTF",
"XVILVHB",
"XVILVHH",
"XVILVHV",
"XVILVHW",
"XVILVLB",
"XVILVLH",
"XVILVLV",
"XVILVLW",
"XVMADDB",
"XVMADDH",
"XVMADDV",
"XVMADDW",
"XVMADDWEVHB",
"XVMADDWEVHBU",
"XVMADDWEVHBUB",
"XVMADDWEVQV",
"XVMADDWEVQVU",
"XVMADDWEVQVUV",
"XVMADDWEVVW",
"XVMADDWEVVWU",
"XVMADDWEVVWUW",
"XVMADDWEVWH",
"XVMADDWEVWHU",
"XVMADDWEVWHUH",
"XVMADDWODHB",
"XVMADDWODHBU",
"XVMADDWODHBUB",
"XVMADDWODQV",
"XVMADDWODQVU",
"XVMADDWODQVUV",
"XVMADDWODVW",
"XVMADDWODVWU",
"XVMADDWODVWUW",
"XVMADDWODWH",
"XVMADDWODWHU",
"XVMADDWODWHUH",
"XVMODB",
"XVMODBU",
"XVMODH",
"XVMODHU",
"XVMODV",
"XVMODVU",
"XVMODW",
"XVMODWU",
"XVMOVQ",
"XVMSUBB",
"XVMSUBH",
"XVMSUBV",
"XVMSUBW",
"XVMUHB",
"XVMUHBU",
"XVMUHH",
"XVMUHHU",
"XVMUHV",
"XVMUHVU",
"XVMUHW",
"XVMUHWU",
"XVMULB",
"XVMULD",
"XVMULF",
"XVMULH",
"XVMULV",
"XVMULW",
"XVMULWEVHB",
"XVMULWEVHBU",
"XVMULWEVHBUB",
"XVMULWEVQV",
"XVMULWEVQVU",
"XVMULWEVQVUV",
"XVMULWEVVW",
"XVMULWEVVWU",
"XVMULWEVVWUW",
"XVMULWEVWH",
"XVMULWEVWHU",
"XVMULWEVWHUH",
"XVMULWODHB",
"XVMULWODHBU",
"XVMULWODHBUB",
"XVMULWODQV",
"XVMULWODQVU",
"XVMULWODQVUV",
"XVMULWODVW",
"XVMULWODVWU",
"XVMULWODVWUW",
"XVMULWODWH",
"XVMULWODWHU",
"XVMULWODWHUH",
"XVNEGB",
"XVNEGH",
"XVNEGV",
"XVNEGW",
"XVNORB",
"XVNORV",
"XVORB",
"XVORNV",
"XVORV",
"XVPCNTB",
"XVPCNTH",
"XVPCNTV",
"XVPCNTW",
"XVPERMIQ",
"XVPERMIV",
"XVPERMIW",
"XVROTRB",
"XVROTRH",
"XVROTRV",
"XVROTRW",
"XVSADDB",
"XVSADDBU",
"XVSADDH",
"XVSADDHU",
"XVSADDV",
"XVSADDVU",
"XVSADDW",
"XVSADDWU",
"XVSEQB",
"XVSEQH",
"XVSEQV",
"XVSEQW",
"XVSETALLNEB",
"XVSETALLNEH",
"XVSETALLNEV",
"XVSETALLNEW",
"XVSETANYEQB",
"XVSETANYEQH",
"XVSETANYEQV",
"XVSETANYEQW",
"XVSETEQV",
"XVSETNEV",
"XVSHUF4IB",
"XVSHUF4IH",
"XVSHUF4IV",
"XVSHUF4IW",
"XVSHUFB",
"XVSHUFH",
"XVSHUFV",
"XVSHUFW",
"XVSLLB",
"XVSLLH",
"XVSLLV",
"XVSLLW",
"XVSLTB",
"XVSLTBU",
"XVSLTH",
"XVSLTHU",
"XVSLTV",
"XVSLTVU",
"XVSLTW",
"XVSLTWU",
"XVSRAB",
"XVSRAH",
"XVSRAV",
"XVSRAW",
"XVSRLB",
"XVSRLH",
"XVSRLV",
"XVSRLW",
"XVSSUBB",
"XVSSUBBU",
"XVSSUBH",
"XVSSUBHU",
"XVSSUBV",
"XVSSUBVU",
"XVSSUBW",
"XVSSUBWU",
"XVSUBB",
"XVSUBBU",
"XVSUBD",
"XVSUBF",
"XVSUBH",
"XVSUBHU",
"XVSUBQ",
"XVSUBV",
"XVSUBVU",
"XVSUBW",
"XVSUBWEVHB",
"XVSUBWEVHBU",
"XVSUBWEVQV",
"XVSUBWEVQVU",
"XVSUBWEVVW",
"XVSUBWEVVWU",
"XVSUBWEVWH",
"XVSUBWEVWHU",
"XVSUBWODHB",
"XVSUBWODHBU",
"XVSUBWODQV",
"XVSUBWODQVU",
"XVSUBWODVW",
"XVSUBWODVWU",
"XVSUBWODWH",
"XVSUBWODWHU",
"XVSUBWU",
"XVXORB",
"XVXORV",
}
+100
View File
@@ -0,0 +1,100 @@
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
package arch
import "fmt"
func buildRISCV() *Table {
return newTable(RISCV, riscvRegisters(), relaxCounts(mergedInstrs(riscvSummaries(), commonGeneratedInstrs, riscvGeneratedInstrs)))
}
func riscvSummaries() map[string]Instr { return toMap(riscvCurated()) }
// riscvRegisters builds the RISC-V register file: the numbered integer (X) and
// floating-point (F) registers plus their standard ABI aliases.
func riscvRegisters() []Register {
var regs []Register
add := func(name string, class RegClass, desc string) {
regs = append(regs, Register{Name: name, Class: class, Desc: desc})
}
for i := 0; i <= 31; i++ {
add(fmt.Sprintf("X%d", i), GPR, "integer register")
}
for i := 0; i <= 31; i++ {
add(fmt.Sprintf("F%d", i), Float, "floating-point register")
}
// Integer ABI aliases.
for _, n := range []string{"ZERO", "RA", "SP", "GP", "TP", "FP", "LR", "TMP"} {
add(n, GPR, "integer ABI alias")
}
for i := 0; i <= 6; i++ {
add(fmt.Sprintf("T%d", i), GPR, "temporary")
}
for i := 0; i <= 11; i++ {
add(fmt.Sprintf("S%d", i), GPR, "saved register")
}
for i := 0; i <= 7; i++ {
add(fmt.Sprintf("A%d", i), GPR, "argument/result register")
}
// Floating-point ABI aliases.
for i := 0; i <= 11; i++ {
add(fmt.Sprintf("FT%d", i), Float, "FP temporary")
}
for i := 0; i <= 11; i++ {
add(fmt.Sprintf("FS%d", i), Float, "FP saved register")
}
for i := 0; i <= 7; i++ {
add(fmt.Sprintf("FA%d", i), Float, "FP argument/result register")
}
return regs
}
// riscvCurated is a hand-written subset of common RISC-V instructions carrying
// summaries. The authoritative, complete set is riscvGeneratedInstrs.
func riscvCurated() []Instr {
return []Instr{
ic("ADD", "Integer add", 3, 3), ic("ADDI", "Add immediate", 3, 3),
ic("ADDIW", "Add immediate (32-bit)", 3, 3), ic("ADDW", "Add (32-bit)", 3, 3),
ic("SUB", "Integer subtract", 3, 3), ic("SUBW", "Subtract (32-bit)", 3, 3),
ic("AND", "Bitwise AND", 3, 3), ic("ANDI", "AND immediate", 3, 3),
ic("OR", "Bitwise OR", 3, 3), ic("ORI", "OR immediate", 3, 3),
ic("XOR", "Bitwise XOR", 3, 3), ic("XORI", "XOR immediate", 3, 3),
ic("SLL", "Shift left logical", 3, 3), ic("SLLI", "Shift left logical immediate", 3, 3),
ic("SRL", "Shift right logical", 3, 3), ic("SRLI", "Shift right logical immediate", 3, 3),
ic("SRA", "Shift right arithmetic", 3, 3), ic("SRAI", "Shift right arithmetic immediate", 3, 3),
ic("SLT", "Set if less than", 3, 3), ic("SLTI", "Set if less than immediate", 3, 3),
ic("SLTU", "Set if less than unsigned", 3, 3), ic("SLTIU", "Set if less than unsigned immediate", 3, 3),
ic("MUL", "Multiply", 3, 3), ic("MULH", "Multiply high", 3, 3),
ic("MULHU", "Multiply high unsigned", 3, 3), ic("MULHSU", "Multiply high signed/unsigned", 3, 3),
ic("DIV", "Divide", 3, 3), ic("DIVU", "Divide unsigned", 3, 3),
ic("REM", "Remainder", 3, 3), ic("REMU", "Remainder unsigned", 3, 3),
ic("MULW", "Multiply (32-bit)", 3, 3), ic("DIVW", "Divide (32-bit)", 3, 3),
ic("LB", "Load byte", 2, 2), ic("LBU", "Load byte unsigned", 2, 2),
ic("LH", "Load halfword", 2, 2), ic("LHU", "Load halfword unsigned", 2, 2),
ic("LW", "Load word", 2, 2), ic("LWU", "Load word unsigned", 2, 2),
ic("LD", "Load doubleword", 2, 2),
ic("SB", "Store byte", 2, 2), ic("SH", "Store halfword", 2, 2),
ic("SW", "Store word", 2, 2), ic("SD", "Store doubleword", 2, 2),
ic("LUI", "Load upper immediate", 2, 2), ic("AUIPC", "Add upper immediate to PC", 2, 2),
ic("BEQ", "Branch if equal", 3, 3), ic("BNE", "Branch if not equal", 3, 3),
ic("BLT", "Branch if less than", 3, 3), ic("BGE", "Branch if greater or equal", 3, 3),
ic("BLTU", "Branch if less than unsigned", 3, 3), ic("BGEU", "Branch if greater or equal unsigned", 3, 3),
ic("JAL", "Jump and link", 1, 2), ic("JALR", "Jump and link register", 1, 3),
i("JMP", "Unconditional jump"), i("CALL", "Call subroutine"),
ic("RET", "Return", 0, 1), i("ECALL", "Environment call"), i("EBREAK", "Breakpoint"),
i("FENCE", "Memory barrier"), i("CSR", "Control/status register access"),
// Floating point.
ic("FADDS", "FP add (single)", 3, 3), ic("FADDD", "FP add (double)", 3, 3),
ic("FSUBS", "FP subtract (single)", 3, 3), ic("FSUBD", "FP subtract (double)", 3, 3),
ic("FMULS", "FP multiply (single)", 3, 3), ic("FMULD", "FP multiply (double)", 3, 3),
ic("FDIVS", "FP divide (single)", 3, 3), ic("FDIVD", "FP divide (double)", 3, 3),
ic("FLW", "FP load word", 2, 2), ic("FLD", "FP load doubleword", 2, 2),
ic("FSW", "FP store word", 2, 2), ic("FSD", "FP store doubleword", 2, 2),
// Atomics.
i("LRW", "Load-reserved word"), i("LRD", "Load-reserved doubleword"),
i("SCW", "Store-conditional word"), i("SCD", "Store-conditional doubleword"),
i("AMOSWAPW", "Atomic swap word"), i("AMOSWAPD", "Atomic swap doubleword"),
i("AMOADDW", "Atomic add word"), i("AMOADDD", "Atomic add doubleword"),
}
}
+970
View File
@@ -0,0 +1,970 @@
// Code generated by gasm-devkit _gen; DO NOT EDIT.
// Source: cmd/internal/obj/riscv/anames.go from the Go toolchain.
package arch
// riscvGeneratedInstrs is the complete set of riscv mnemonics accepted by
// Go's Plan 9 assembler.
var riscvGeneratedInstrs = []string{
"ADD",
"ADDI",
"ADDIW",
"ADDUW",
"ADDW",
"AMOADDD",
"AMOADDW",
"AMOANDD",
"AMOANDW",
"AMOMAXD",
"AMOMAXUD",
"AMOMAXUW",
"AMOMAXW",
"AMOMIND",
"AMOMINUD",
"AMOMINUW",
"AMOMINW",
"AMOORD",
"AMOORW",
"AMOSWAPD",
"AMOSWAPW",
"AMOXORD",
"AMOXORW",
"AND",
"ANDI",
"ANDN",
"AUIPC",
"BCLR",
"BCLRI",
"BEQ",
"BEQZ",
"BEXT",
"BEXTI",
"BGE",
"BGEU",
"BGEZ",
"BGT",
"BGTU",
"BGTZ",
"BINV",
"BINVI",
"BLE",
"BLEU",
"BLEZ",
"BLT",
"BLTU",
"BLTZ",
"BNE",
"BNEZ",
"BSET",
"BSETI",
"CADD",
"CADDI",
"CADDI16SP",
"CADDI4SPN",
"CADDIW",
"CADDW",
"CAND",
"CANDI",
"CBEQZ",
"CBNEZ",
"CEBREAK",
"CFLD",
"CFLDSP",
"CFSD",
"CFSDSP",
"CJ",
"CJALR",
"CJR",
"CLD",
"CLDSP",
"CLI",
"CLUI",
"CLW",
"CLWSP",
"CLZ",
"CLZW",
"CMV",
"CNOP",
"COR",
"CPOP",
"CPOPW",
"CSD",
"CSDSP",
"CSLLI",
"CSRAI",
"CSRLI",
"CSRRC",
"CSRRCI",
"CSRRS",
"CSRRSI",
"CSRRW",
"CSRRWI",
"CSUB",
"CSUBW",
"CSW",
"CSWSP",
"CTZ",
"CTZW",
"CXOR",
"CZEROEQZ",
"CZERONEZ",
"DIV",
"DIVU",
"DIVUW",
"DIVW",
"DRET",
"EBREAK",
"ECALL",
"FABSD",
"FABSS",
"FADDD",
"FADDQ",
"FADDS",
"FCLASSD",
"FCLASSQ",
"FCLASSS",
"FCVTDL",
"FCVTDLU",
"FCVTDQ",
"FCVTDS",
"FCVTDW",
"FCVTDWU",
"FCVTLD",
"FCVTLQ",
"FCVTLS",
"FCVTLUD",
"FCVTLUQ",
"FCVTLUS",
"FCVTQD",
"FCVTQL",
"FCVTQLU",
"FCVTQS",
"FCVTQW",
"FCVTQWU",
"FCVTSD",
"FCVTSL",
"FCVTSLU",
"FCVTSQ",
"FCVTSW",
"FCVTSWU",
"FCVTWD",
"FCVTWQ",
"FCVTWS",
"FCVTWUD",
"FCVTWUQ",
"FCVTWUS",
"FDIVD",
"FDIVQ",
"FDIVS",
"FENCE",
"FEQD",
"FEQQ",
"FEQS",
"FLD",
"FLED",
"FLEQ",
"FLES",
"FLQ",
"FLTD",
"FLTQ",
"FLTS",
"FLW",
"FMADDD",
"FMADDQ",
"FMADDS",
"FMAXD",
"FMAXQ",
"FMAXS",
"FMIND",
"FMINQ",
"FMINS",
"FMSUBD",
"FMSUBQ",
"FMSUBS",
"FMULD",
"FMULQ",
"FMULS",
"FMVDX",
"FMVSX",
"FMVWX",
"FMVXD",
"FMVXS",
"FMVXW",
"FNED",
"FNEGD",
"FNEGS",
"FNES",
"FNMADDD",
"FNMADDQ",
"FNMADDS",
"FNMSUBD",
"FNMSUBQ",
"FNMSUBS",
"FSD",
"FSGNJD",
"FSGNJND",
"FSGNJNQ",
"FSGNJNS",
"FSGNJQ",
"FSGNJS",
"FSGNJXD",
"FSGNJXQ",
"FSGNJXS",
"FSQ",
"FSQRTD",
"FSQRTQ",
"FSQRTS",
"FSUBD",
"FSUBQ",
"FSUBS",
"FSW",
"JAL",
"JALR",
"LB",
"LBU",
"LD",
"LH",
"LHU",
"LRD",
"LRW",
"LUI",
"LW",
"LWU",
"MAX",
"MAXU",
"MIN",
"MINU",
"MOV",
"MOVB",
"MOVBU",
"MOVD",
"MOVF",
"MOVH",
"MOVHU",
"MOVW",
"MOVWU",
"MRET",
"MUL",
"MULH",
"MULHSU",
"MULHU",
"MULW",
"NEG",
"NEGW",
"NOT",
"OR",
"ORCB",
"ORI",
"ORN",
"RDCYCLE",
"RDINSTRET",
"RDTIME",
"REM",
"REMU",
"REMUW",
"REMW",
"REV8",
"ROL",
"ROLW",
"ROR",
"RORI",
"RORIW",
"RORW",
"SB",
"SBREAK",
"SCALL",
"SCD",
"SCW",
"SD",
"SEQZ",
"SEXTB",
"SEXTH",
"SFENCEVMA",
"SH",
"SH1ADD",
"SH1ADDUW",
"SH2ADD",
"SH2ADDUW",
"SH3ADD",
"SH3ADDUW",
"SLL",
"SLLI",
"SLLIUW",
"SLLIW",
"SLLW",
"SLT",
"SLTI",
"SLTIU",
"SLTU",
"SNEZ",
"SRA",
"SRAI",
"SRAIW",
"SRAW",
"SRET",
"SRL",
"SRLI",
"SRLIW",
"SRLW",
"SUB",
"SUBW",
"SW",
"VAADDUVV",
"VAADDUVX",
"VAADDVV",
"VAADDVX",
"VADCVIM",
"VADCVVM",
"VADCVXM",
"VADDVI",
"VADDVV",
"VADDVX",
"VANDVI",
"VANDVV",
"VANDVX",
"VASUBUVV",
"VASUBUVX",
"VASUBVV",
"VASUBVX",
"VCOMPRESSVM",
"VCPOPM",
"VDIVUVV",
"VDIVUVX",
"VDIVVV",
"VDIVVX",
"VFABSV",
"VFADDVF",
"VFADDVV",
"VFCLASSV",
"VFCVTFXUV",
"VFCVTFXV",
"VFCVTRTZXFV",
"VFCVTRTZXUFV",
"VFCVTXFV",
"VFCVTXUFV",
"VFDIVVF",
"VFDIVVV",
"VFIRSTM",
"VFMACCVF",
"VFMACCVV",
"VFMADDVF",
"VFMADDVV",
"VFMAXVF",
"VFMAXVV",
"VFMERGEVFM",
"VFMINVF",
"VFMINVV",
"VFMSACVF",
"VFMSACVV",
"VFMSUBVF",
"VFMSUBVV",
"VFMULVF",
"VFMULVV",
"VFMVFS",
"VFMVSF",
"VFMVVF",
"VFNCVTFFW",
"VFNCVTFXUW",
"VFNCVTFXW",
"VFNCVTRODFFW",
"VFNCVTRTZXFW",
"VFNCVTRTZXUFW",
"VFNCVTXFW",
"VFNCVTXUFW",
"VFNEGV",
"VFNMACCVF",
"VFNMACCVV",
"VFNMADDVF",
"VFNMADDVV",
"VFNMSACVF",
"VFNMSACVV",
"VFNMSUBVF",
"VFNMSUBVV",
"VFRDIVVF",
"VFREC7V",
"VFREDMAXVS",
"VFREDMINVS",
"VFREDOSUMVS",
"VFREDUSUMVS",
"VFRSQRT7V",
"VFRSUBVF",
"VFSGNJNVF",
"VFSGNJNVV",
"VFSGNJVF",
"VFSGNJVV",
"VFSGNJXVF",
"VFSGNJXVV",
"VFSLIDE1DOWNVF",
"VFSLIDE1UPVF",
"VFSQRTV",
"VFSUBVF",
"VFSUBVV",
"VFWADDVF",
"VFWADDVV",
"VFWADDWF",
"VFWADDWV",
"VFWCVTFFV",
"VFWCVTFXUV",
"VFWCVTFXV",
"VFWCVTRTZXFV",
"VFWCVTRTZXUFV",
"VFWCVTXFV",
"VFWCVTXUFV",
"VFWMACCVF",
"VFWMACCVV",
"VFWMSACVF",
"VFWMSACVV",
"VFWMULVF",
"VFWMULVV",
"VFWNMACCVF",
"VFWNMACCVV",
"VFWNMSACVF",
"VFWNMSACVV",
"VFWREDOSUMVS",
"VFWREDUSUMVS",
"VFWSUBVF",
"VFWSUBVV",
"VFWSUBWF",
"VFWSUBWV",
"VIDV",
"VIOTAM",
"VL1RE16V",
"VL1RE32V",
"VL1RE64V",
"VL1RE8V",
"VL1RV",
"VL2RE16V",
"VL2RE32V",
"VL2RE64V",
"VL2RE8V",
"VL2RV",
"VL4RE16V",
"VL4RE32V",
"VL4RE64V",
"VL4RE8V",
"VL4RV",
"VL8RE16V",
"VL8RE32V",
"VL8RE64V",
"VL8RE8V",
"VL8RV",
"VLE16FFV",
"VLE16V",
"VLE32FFV",
"VLE32V",
"VLE64FFV",
"VLE64V",
"VLE8FFV",
"VLE8V",
"VLMV",
"VLOXEI16V",
"VLOXEI32V",
"VLOXEI64V",
"VLOXEI8V",
"VLOXSEG2EI16V",
"VLOXSEG2EI32V",
"VLOXSEG2EI64V",
"VLOXSEG2EI8V",
"VLOXSEG3EI16V",
"VLOXSEG3EI32V",
"VLOXSEG3EI64V",
"VLOXSEG3EI8V",
"VLOXSEG4EI16V",
"VLOXSEG4EI32V",
"VLOXSEG4EI64V",
"VLOXSEG4EI8V",
"VLOXSEG5EI16V",
"VLOXSEG5EI32V",
"VLOXSEG5EI64V",
"VLOXSEG5EI8V",
"VLOXSEG6EI16V",
"VLOXSEG6EI32V",
"VLOXSEG6EI64V",
"VLOXSEG6EI8V",
"VLOXSEG7EI16V",
"VLOXSEG7EI32V",
"VLOXSEG7EI64V",
"VLOXSEG7EI8V",
"VLOXSEG8EI16V",
"VLOXSEG8EI32V",
"VLOXSEG8EI64V",
"VLOXSEG8EI8V",
"VLSE16V",
"VLSE32V",
"VLSE64V",
"VLSE8V",
"VLSEG2E16FFV",
"VLSEG2E16V",
"VLSEG2E32FFV",
"VLSEG2E32V",
"VLSEG2E64FFV",
"VLSEG2E64V",
"VLSEG2E8FFV",
"VLSEG2E8V",
"VLSEG3E16FFV",
"VLSEG3E16V",
"VLSEG3E32FFV",
"VLSEG3E32V",
"VLSEG3E64FFV",
"VLSEG3E64V",
"VLSEG3E8FFV",
"VLSEG3E8V",
"VLSEG4E16FFV",
"VLSEG4E16V",
"VLSEG4E32FFV",
"VLSEG4E32V",
"VLSEG4E64FFV",
"VLSEG4E64V",
"VLSEG4E8FFV",
"VLSEG4E8V",
"VLSEG5E16FFV",
"VLSEG5E16V",
"VLSEG5E32FFV",
"VLSEG5E32V",
"VLSEG5E64FFV",
"VLSEG5E64V",
"VLSEG5E8FFV",
"VLSEG5E8V",
"VLSEG6E16FFV",
"VLSEG6E16V",
"VLSEG6E32FFV",
"VLSEG6E32V",
"VLSEG6E64FFV",
"VLSEG6E64V",
"VLSEG6E8FFV",
"VLSEG6E8V",
"VLSEG7E16FFV",
"VLSEG7E16V",
"VLSEG7E32FFV",
"VLSEG7E32V",
"VLSEG7E64FFV",
"VLSEG7E64V",
"VLSEG7E8FFV",
"VLSEG7E8V",
"VLSEG8E16FFV",
"VLSEG8E16V",
"VLSEG8E32FFV",
"VLSEG8E32V",
"VLSEG8E64FFV",
"VLSEG8E64V",
"VLSEG8E8FFV",
"VLSEG8E8V",
"VLSSEG2E16V",
"VLSSEG2E32V",
"VLSSEG2E64V",
"VLSSEG2E8V",
"VLSSEG3E16V",
"VLSSEG3E32V",
"VLSSEG3E64V",
"VLSSEG3E8V",
"VLSSEG4E16V",
"VLSSEG4E32V",
"VLSSEG4E64V",
"VLSSEG4E8V",
"VLSSEG5E16V",
"VLSSEG5E32V",
"VLSSEG5E64V",
"VLSSEG5E8V",
"VLSSEG6E16V",
"VLSSEG6E32V",
"VLSSEG6E64V",
"VLSSEG6E8V",
"VLSSEG7E16V",
"VLSSEG7E32V",
"VLSSEG7E64V",
"VLSSEG7E8V",
"VLSSEG8E16V",
"VLSSEG8E32V",
"VLSSEG8E64V",
"VLSSEG8E8V",
"VLUXEI16V",
"VLUXEI32V",
"VLUXEI64V",
"VLUXEI8V",
"VLUXSEG2EI16V",
"VLUXSEG2EI32V",
"VLUXSEG2EI64V",
"VLUXSEG2EI8V",
"VLUXSEG3EI16V",
"VLUXSEG3EI32V",
"VLUXSEG3EI64V",
"VLUXSEG3EI8V",
"VLUXSEG4EI16V",
"VLUXSEG4EI32V",
"VLUXSEG4EI64V",
"VLUXSEG4EI8V",
"VLUXSEG5EI16V",
"VLUXSEG5EI32V",
"VLUXSEG5EI64V",
"VLUXSEG5EI8V",
"VLUXSEG6EI16V",
"VLUXSEG6EI32V",
"VLUXSEG6EI64V",
"VLUXSEG6EI8V",
"VLUXSEG7EI16V",
"VLUXSEG7EI32V",
"VLUXSEG7EI64V",
"VLUXSEG7EI8V",
"VLUXSEG8EI16V",
"VLUXSEG8EI32V",
"VLUXSEG8EI64V",
"VLUXSEG8EI8V",
"VMACCVV",
"VMACCVX",
"VMADCVI",
"VMADCVIM",
"VMADCVV",
"VMADCVVM",
"VMADCVX",
"VMADCVXM",
"VMADDVV",
"VMADDVX",
"VMANDMM",
"VMANDNMM",
"VMAXUVV",
"VMAXUVX",
"VMAXVV",
"VMAXVX",
"VMCLRM",
"VMERGEVIM",
"VMERGEVVM",
"VMERGEVXM",
"VMFEQVF",
"VMFEQVV",
"VMFGEVF",
"VMFGEVV",
"VMFGTVF",
"VMFGTVV",
"VMFLEVF",
"VMFLEVV",
"VMFLTVF",
"VMFLTVV",
"VMFNEVF",
"VMFNEVV",
"VMINUVV",
"VMINUVX",
"VMINVV",
"VMINVX",
"VMMVM",
"VMNANDMM",
"VMNORMM",
"VMNOTM",
"VMORMM",
"VMORNMM",
"VMSBCVV",
"VMSBCVVM",
"VMSBCVX",
"VMSBCVXM",
"VMSBFM",
"VMSEQVI",
"VMSEQVV",
"VMSEQVX",
"VMSETM",
"VMSGEUVI",
"VMSGEUVV",
"VMSGEVI",
"VMSGEVV",
"VMSGTUVI",
"VMSGTUVV",
"VMSGTUVX",
"VMSGTVI",
"VMSGTVV",
"VMSGTVX",
"VMSIFM",
"VMSLEUVI",
"VMSLEUVV",
"VMSLEUVX",
"VMSLEVI",
"VMSLEVV",
"VMSLEVX",
"VMSLTUVI",
"VMSLTUVV",
"VMSLTUVX",
"VMSLTVI",
"VMSLTVV",
"VMSLTVX",
"VMSNEVI",
"VMSNEVV",
"VMSNEVX",
"VMSOFM",
"VMULHSUVV",
"VMULHSUVX",
"VMULHUVV",
"VMULHUVX",
"VMULHVV",
"VMULHVX",
"VMULVV",
"VMULVX",
"VMV1RV",
"VMV2RV",
"VMV4RV",
"VMV8RV",
"VMVSX",
"VMVVI",
"VMVVV",
"VMVVX",
"VMVXS",
"VMXNORMM",
"VMXORMM",
"VNCLIPUWI",
"VNCLIPUWV",
"VNCLIPUWX",
"VNCLIPWI",
"VNCLIPWV",
"VNCLIPWX",
"VNCVTXXW",
"VNEGV",
"VNMSACVV",
"VNMSACVX",
"VNMSUBVV",
"VNMSUBVX",
"VNOTV",
"VNSRAWI",
"VNSRAWV",
"VNSRAWX",
"VNSRLWI",
"VNSRLWV",
"VNSRLWX",
"VORVI",
"VORVV",
"VORVX",
"VREDANDVS",
"VREDMAXUVS",
"VREDMAXVS",
"VREDMINUVS",
"VREDMINVS",
"VREDORVS",
"VREDSUMVS",
"VREDXORVS",
"VREMUVV",
"VREMUVX",
"VREMVV",
"VREMVX",
"VRGATHEREI16VV",
"VRGATHERVI",
"VRGATHERVV",
"VRGATHERVX",
"VRSUBVI",
"VRSUBVX",
"VS1RV",
"VS2RV",
"VS4RV",
"VS8RV",
"VSADDUVI",
"VSADDUVV",
"VSADDUVX",
"VSADDVI",
"VSADDVV",
"VSADDVX",
"VSBCVVM",
"VSBCVXM",
"VSE16V",
"VSE32V",
"VSE64V",
"VSE8V",
"VSETIVLI",
"VSETVL",
"VSETVLI",
"VSEXTVF2",
"VSEXTVF4",
"VSEXTVF8",
"VSLIDE1DOWNVX",
"VSLIDE1UPVX",
"VSLIDEDOWNVI",
"VSLIDEDOWNVX",
"VSLIDEUPVI",
"VSLIDEUPVX",
"VSLLVI",
"VSLLVV",
"VSLLVX",
"VSMULVV",
"VSMULVX",
"VSMV",
"VSOXEI16V",
"VSOXEI32V",
"VSOXEI64V",
"VSOXEI8V",
"VSOXSEG2EI16V",
"VSOXSEG2EI32V",
"VSOXSEG2EI64V",
"VSOXSEG2EI8V",
"VSOXSEG3EI16V",
"VSOXSEG3EI32V",
"VSOXSEG3EI64V",
"VSOXSEG3EI8V",
"VSOXSEG4EI16V",
"VSOXSEG4EI32V",
"VSOXSEG4EI64V",
"VSOXSEG4EI8V",
"VSOXSEG5EI16V",
"VSOXSEG5EI32V",
"VSOXSEG5EI64V",
"VSOXSEG5EI8V",
"VSOXSEG6EI16V",
"VSOXSEG6EI32V",
"VSOXSEG6EI64V",
"VSOXSEG6EI8V",
"VSOXSEG7EI16V",
"VSOXSEG7EI32V",
"VSOXSEG7EI64V",
"VSOXSEG7EI8V",
"VSOXSEG8EI16V",
"VSOXSEG8EI32V",
"VSOXSEG8EI64V",
"VSOXSEG8EI8V",
"VSRAVI",
"VSRAVV",
"VSRAVX",
"VSRLVI",
"VSRLVV",
"VSRLVX",
"VSSE16V",
"VSSE32V",
"VSSE64V",
"VSSE8V",
"VSSEG2E16V",
"VSSEG2E32V",
"VSSEG2E64V",
"VSSEG2E8V",
"VSSEG3E16V",
"VSSEG3E32V",
"VSSEG3E64V",
"VSSEG3E8V",
"VSSEG4E16V",
"VSSEG4E32V",
"VSSEG4E64V",
"VSSEG4E8V",
"VSSEG5E16V",
"VSSEG5E32V",
"VSSEG5E64V",
"VSSEG5E8V",
"VSSEG6E16V",
"VSSEG6E32V",
"VSSEG6E64V",
"VSSEG6E8V",
"VSSEG7E16V",
"VSSEG7E32V",
"VSSEG7E64V",
"VSSEG7E8V",
"VSSEG8E16V",
"VSSEG8E32V",
"VSSEG8E64V",
"VSSEG8E8V",
"VSSRAVI",
"VSSRAVV",
"VSSRAVX",
"VSSRLVI",
"VSSRLVV",
"VSSRLVX",
"VSSSEG2E16V",
"VSSSEG2E32V",
"VSSSEG2E64V",
"VSSSEG2E8V",
"VSSSEG3E16V",
"VSSSEG3E32V",
"VSSSEG3E64V",
"VSSSEG3E8V",
"VSSSEG4E16V",
"VSSSEG4E32V",
"VSSSEG4E64V",
"VSSSEG4E8V",
"VSSSEG5E16V",
"VSSSEG5E32V",
"VSSSEG5E64V",
"VSSSEG5E8V",
"VSSSEG6E16V",
"VSSSEG6E32V",
"VSSSEG6E64V",
"VSSSEG6E8V",
"VSSSEG7E16V",
"VSSSEG7E32V",
"VSSSEG7E64V",
"VSSSEG7E8V",
"VSSSEG8E16V",
"VSSSEG8E32V",
"VSSSEG8E64V",
"VSSSEG8E8V",
"VSSUBUVV",
"VSSUBUVX",
"VSSUBVV",
"VSSUBVX",
"VSUBVV",
"VSUBVX",
"VSUXEI16V",
"VSUXEI32V",
"VSUXEI64V",
"VSUXEI8V",
"VSUXSEG2EI16V",
"VSUXSEG2EI32V",
"VSUXSEG2EI64V",
"VSUXSEG2EI8V",
"VSUXSEG3EI16V",
"VSUXSEG3EI32V",
"VSUXSEG3EI64V",
"VSUXSEG3EI8V",
"VSUXSEG4EI16V",
"VSUXSEG4EI32V",
"VSUXSEG4EI64V",
"VSUXSEG4EI8V",
"VSUXSEG5EI16V",
"VSUXSEG5EI32V",
"VSUXSEG5EI64V",
"VSUXSEG5EI8V",
"VSUXSEG6EI16V",
"VSUXSEG6EI32V",
"VSUXSEG6EI64V",
"VSUXSEG6EI8V",
"VSUXSEG7EI16V",
"VSUXSEG7EI32V",
"VSUXSEG7EI64V",
"VSUXSEG7EI8V",
"VSUXSEG8EI16V",
"VSUXSEG8EI32V",
"VSUXSEG8EI64V",
"VSUXSEG8EI8V",
"VWADDUVV",
"VWADDUVX",
"VWADDUWV",
"VWADDUWX",
"VWADDVV",
"VWADDVX",
"VWADDWV",
"VWADDWX",
"VWCVTUXXV",
"VWCVTXXV",
"VWMACCSUVV",
"VWMACCSUVX",
"VWMACCUSVX",
"VWMACCUVV",
"VWMACCUVX",
"VWMACCVV",
"VWMACCVX",
"VWMULSUVV",
"VWMULSUVX",
"VWMULUVV",
"VWMULUVX",
"VWMULVV",
"VWMULVX",
"VWREDSUMUVS",
"VWREDSUMVS",
"VWSUBUVV",
"VWSUBUVX",
"VWSUBUWV",
"VWSUBUWX",
"VWSUBVV",
"VWSUBVX",
"VWSUBWV",
"VWSUBWX",
"VXORVI",
"VXORVV",
"VXORVX",
"VZEXTVF2",
"VZEXTVF4",
"VZEXTVF8",
"WFI",
"WORD",
"XNOR",
"XOR",
"XORI",
"ZEXTH",
}