From c330f5a288ba2b5dc6b1910b212929bf1d7aefc3 Mon Sep 17 00:00:00 2001 From: Lin Runze Date: Thu, 12 Sep 2024 03:55:43 +0800 Subject: [PATCH] delve: add linux-riscv64 support --- Documentation/backend_test_health.md | 7 + _fixtures/asmnilptr/main_riscv64.s | 7 + _fixtures/cgostacktest/hello.c | 2 + _fixtures/testvariablescgo/test.c | 4 +- _scripts/make.go | 2 +- go.mod | 2 +- pkg/dwarf/regnum/riscv64.go | 92 + pkg/proc/bininfo.go | 6 + pkg/proc/core/linux_core.go | 54 + pkg/proc/dump.go | 2 + pkg/proc/linutil/regs_riscv64_arch.go | 386 +++++ pkg/proc/native/hwbreak_other.go | 2 +- pkg/proc/native/proc.go | 2 +- pkg/proc/native/ptrace_linux_64bit.go | 2 +- pkg/proc/native/registers_linux_riscv64.go | 144 ++ pkg/proc/native/support_sentinel_linux.go | 2 +- .../threads_hardware_singlestep_linux.go | 45 + pkg/proc/native/threads_linux.go | 39 - pkg/proc/native/threads_linux_riscv64.go | 294 ++++ pkg/proc/pe.go | 1 + pkg/proc/proc_test.go | 10 + pkg/proc/riscv64_arch.go | 286 ++++ pkg/proc/riscv64_disasm.go | 189 +++ pkg/proc/stack.go | 4 +- pkg/proc/target_exec.go | 5 +- pkg/proc/test/support.go | 5 +- service/debugger/debugger_test.go | 3 + service/debugger/debugger_unix_test.go | 3 + .../x/arch/riscv64/riscv64asm/arg.go | 116 ++ .../x/arch/riscv64/riscv64asm/csr_string.go | 577 +++++++ .../x/arch/riscv64/riscv64asm/decode.go | 550 ++++++ .../x/arch/riscv64/riscv64asm/gnu.go | 328 ++++ .../x/arch/riscv64/riscv64asm/inst.go | 495 ++++++ .../x/arch/riscv64/riscv64asm/plan9x.go | 377 +++++ .../x/arch/riscv64/riscv64asm/tables.go | 1474 +++++++++++++++++ vendor/modules.txt | 3 +- 36 files changed, 5469 insertions(+), 51 deletions(-) create mode 100644 _fixtures/asmnilptr/main_riscv64.s create mode 100644 pkg/dwarf/regnum/riscv64.go create mode 100644 pkg/proc/linutil/regs_riscv64_arch.go create mode 100644 pkg/proc/native/registers_linux_riscv64.go create mode 100644 pkg/proc/native/threads_hardware_singlestep_linux.go create mode 100644 pkg/proc/native/threads_linux_riscv64.go create mode 100644 pkg/proc/riscv64_arch.go create mode 100644 pkg/proc/riscv64_disasm.go create mode 100644 vendor/golang.org/x/arch/riscv64/riscv64asm/arg.go create mode 100644 vendor/golang.org/x/arch/riscv64/riscv64asm/csr_string.go create mode 100644 vendor/golang.org/x/arch/riscv64/riscv64asm/decode.go create mode 100644 vendor/golang.org/x/arch/riscv64/riscv64asm/gnu.go create mode 100644 vendor/golang.org/x/arch/riscv64/riscv64asm/inst.go create mode 100644 vendor/golang.org/x/arch/riscv64/riscv64asm/plan9x.go create mode 100644 vendor/golang.org/x/arch/riscv64/riscv64asm/tables.go diff --git a/Documentation/backend_test_health.md b/Documentation/backend_test_health.md index ec4e9f01de..0e18269759 100644 --- a/Documentation/backend_test_health.md +++ b/Documentation/backend_test_health.md @@ -29,12 +29,19 @@ Tests skipped by each supported backend: * 1 broken in linux ppc64le * linux/ppc64le/native/pie skipped = 3 * 3 broken - pie mode +* linux/riscv64 skipped = 2 + * 1 broken - cgo stacktraces + * 1 not working on linux/riscv64 * pie skipped = 2 * 2 upstream issue - https://github.com/golang/go/issues/29322 * ppc64le skipped = 12 * 6 broken * 1 broken - global variable symbolication * 5 not implemented +* riscv64 skipped = 6 + * 2 broken + * 1 broken - global variable symbolication + * 3 not implemented * windows skipped = 7 * 1 broken * 2 not working on windows diff --git a/_fixtures/asmnilptr/main_riscv64.s b/_fixtures/asmnilptr/main_riscv64.s new file mode 100644 index 0000000000..49faf4ab10 --- /dev/null +++ b/_fixtures/asmnilptr/main_riscv64.s @@ -0,0 +1,7 @@ +#include "textflag.h" + +TEXT ·asmFunc(SB),0,$0-16 + MOV arg+0(FP), R5 + MOV (R5), R5 + MOV R5, ret+8(FP) + RET \ No newline at end of file diff --git a/_fixtures/cgostacktest/hello.c b/_fixtures/cgostacktest/hello.c index b779bf96aa..366cf459e5 100644 --- a/_fixtures/cgostacktest/hello.c +++ b/_fixtures/cgostacktest/hello.c @@ -14,6 +14,8 @@ #else #define BREAKPOINT asm("brk 0;") #endif +#elif __riscv +#define BREAKPOINT asm("ebreak;") #endif void helloworld_pt2(int x) { diff --git a/_fixtures/testvariablescgo/test.c b/_fixtures/testvariablescgo/test.c index fdcae84f93..77617f4f1d 100644 --- a/_fixtures/testvariablescgo/test.c +++ b/_fixtures/testvariablescgo/test.c @@ -12,6 +12,8 @@ #else #define BREAKPOINT asm("brk 0;") #endif +#elif __riscv +#define BREAKPOINT asm("ebreak;") #endif #define N 100 @@ -37,6 +39,6 @@ void testfn(void) { strcpy(s, s0); BREAKPOINT; - + printf("%s %s %p %p\n", s, longstring, v, v_align_check); } diff --git a/_scripts/make.go b/_scripts/make.go index 2a7442faf6..4f4af65ec1 100644 --- a/_scripts/make.go +++ b/_scripts/make.go @@ -112,7 +112,7 @@ This option can only be specified if testset is basic or a single package.`) test.PersistentFlags().StringVarP(&TestBuildMode, "test-build-mode", "m", "", `Runs tests compiling with the specified build mode, one of either: normal normal buildmode (default) pie PIE buildmode - + This option can only be specified if testset is basic or a single package.`) test.PersistentFlags().BoolVarP(&TestIncludePIE, "pie", "", true, "Standard testing should include PIE") diff --git a/go.mod b/go.mod index d6e12811d6..651892e979 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 go.starlark.net v0.0.0-20231101134539-556fd59b42f6 - golang.org/x/arch v0.6.0 + golang.org/x/arch v0.10.1-0.20240910142527-7874f23b9c06 golang.org/x/sys v0.17.0 golang.org/x/tools v0.14.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/pkg/dwarf/regnum/riscv64.go b/pkg/dwarf/regnum/riscv64.go new file mode 100644 index 0000000000..0ff7953996 --- /dev/null +++ b/pkg/dwarf/regnum/riscv64.go @@ -0,0 +1,92 @@ +package regnum + +import "fmt" + +// The mapping between hardware registers and DWARF registers, See +// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-dwarf.adoc + +const ( + // Integer Registers + RISCV64_X0 = 0 + // Link Register + RISCV64_LR = 1 + // Stack Pointer + RISCV64_SP = 2 + RISCV64_GP = 3 + RISCV64_TP = 4 + RISCV64_T0 = 5 + RISCV64_T1 = 6 + RISCV64_T2 = 7 + RISCV64_S0 = 8 + // Frame Pointer + RISCV64_FP = RISCV64_S0 + RISCV64_S1 = 9 + RISCV64_A0 = 10 + RISCV64_A1 = 11 + RISCV64_A2 = 12 + RISCV64_A3 = 13 + RISCV64_A4 = 14 + RISCV64_A5 = 15 + RISCV64_A6 = 16 + RISCV64_A7 = 17 + RISCV64_S2 = 18 + RISCV64_S3 = 19 + RISCV64_S4 = 20 + RISCV64_S5 = 21 + RISCV64_S6 = 22 + RISCV64_S7 = 23 + RISCV64_S8 = 24 + RISCV64_S9 = 25 + RISCV64_S10 = 26 + // G Register + RISCV64_S11 = 27 + RISCV64_T3 = 28 + RISCV64_T4 = 29 + RISCV64_T5 = 30 + RISCV64_T6 = 31 + + RISCV64_X31 = RISCV64_T6 + + // Floating-point Registers + RISCV64_F0 = 32 + RISCV64_F31 = 63 + + // Not defined in DWARF specification + RISCV64_PC = 65 + + _RISC64_MaxRegNum = RISCV64_PC +) + +func RISCV64ToName(num uint64) string { + switch { + case num <= RISCV64_X31: + return fmt.Sprintf("X%d", num) + + case num >= RISCV64_F0 && num <= RISCV64_F31: + return fmt.Sprintf("F%d", num) + + case num == RISCV64_PC: + return fmt.Sprintf("PC") + + default: + return fmt.Sprintf("Unknown%d", num) + } +} + +func RISCV64MaxRegNum() uint64 { + return _RISC64_MaxRegNum +} + +var RISCV64NameToDwarf = func() map[string]int { + r := make(map[string]int) + for i := 0; i <= 31; i++ { + r[fmt.Sprintf("x%d", i)] = RISCV64_X0 + i + } + r[fmt.Sprintf("pc")] = RISCV64_PC + + for i := 0; i <= 31; i++ { + r[fmt.Sprintf("f%d", i)] = RISCV64_F0 + i + } + + return r +}() diff --git a/pkg/proc/bininfo.go b/pkg/proc/bininfo.go index d861bd59b5..c540055ec8 100644 --- a/pkg/proc/bininfo.go +++ b/pkg/proc/bininfo.go @@ -126,6 +126,7 @@ var ( elf.EM_AARCH64: true, elf.EM_386: true, elf.EM_PPC64: true, + elf.EM_RISCV: true, } supportedWindowsArch = map[_PEMachine]bool{ @@ -802,6 +803,8 @@ func NewBinaryInfo(goos, goarch string) *BinaryInfo { r.Arch = ARM64Arch(goos) case "ppc64le": r.Arch = PPC64LEArch(goos) + case "riscv64": + r.Arch = RISCV64Arch(goos) } return r } @@ -1803,6 +1806,9 @@ func (bi *BinaryInfo) setGStructOffsetElf(image *Image, exe *elf.File, wg *sync. case elf.EM_PPC64: _ = getSymbol(image, bi.logger, exe, "runtime.tls_g") + case elf.EM_RISCV: + _ = getSymbol(image, bi.logger, exe, "runtime.tls_g") + default: // we should never get here panic("architecture not supported") diff --git a/pkg/proc/core/linux_core.go b/pkg/proc/core/linux_core.go index beab0d1da6..704216ce48 100644 --- a/pkg/proc/core/linux_core.go +++ b/pkg/proc/core/linux_core.go @@ -40,6 +40,7 @@ const _NT_FPREGSET elf.NType = 0x2 const ( _EM_AARCH64 = 183 _EM_X86_64 = 62 + _EM_RISCV = 243 _ARM_FP_HEADER_START = 512 ) @@ -49,6 +50,8 @@ func linuxThreadsFromNotes(p *process, notes []*note, machineType elf.Machine) p var currentThread proc.Thread var lastThreadAMD *linuxAMD64Thread var lastThreadARM *linuxARM64Thread + var lastThreadRISCV *linuxRISCV64Thread + for _, note := range notes { switch note.Type { case elf.NT_PRSTATUS: @@ -66,12 +69,23 @@ func linuxThreadsFromNotes(p *process, notes []*note, machineType elf.Machine) p if currentThread == nil { currentThread = p.Threads[int(t.Pid)] } + } else if machineType == _EM_RISCV { + t := note.Desc.(*linuxPrStatusRISCV64) + lastThreadRISCV = &linuxRISCV64Thread{linutil.RISCV64Registers{Regs: &t.Reg}, t} + p.Threads[int(t.Pid)] = &thread{lastThreadRISCV, p, proc.CommonThread{}} + if currentThread == nil { + currentThread = p.Threads[int(t.Pid)] + } } case _NT_FPREGSET: if machineType == _EM_AARCH64 { if lastThreadARM != nil { lastThreadARM.regs.Fpregs = note.Desc.(*linutil.ARM64PtraceFpRegs).Decode() } + } else if machineType == _EM_RISCV { + if lastThreadRISCV != nil { + lastThreadRISCV.regs.Fpregs = note.Desc.(*linutil.RISCV64PtraceFpRegs).Decode() + } } case _NT_X86_XSTATE: if machineType == _EM_X86_64 { @@ -147,6 +161,8 @@ func readLinuxOrPlatformIndependentCore(corePath, exePath string) (*process, pro bi = proc.NewBinaryInfo("linux", "amd64") case _EM_AARCH64: bi = proc.NewBinaryInfo("linux", "arm64") + case _EM_RISCV: + bi = proc.NewBinaryInfo("linux", "riscv64") default: return nil, nil, errors.New("unsupported machine type") } @@ -181,6 +197,11 @@ type linuxARM64Thread struct { t *linuxPrStatusARM64 } +type linuxRISCV64Thread struct { + regs linutil.RISCV64Registers + t *linuxPrStatusRISCV64 +} + func (t *linuxAMD64Thread) registers() (proc.Registers, error) { var r linutil.AMD64Registers r.Regs = t.regs.Regs @@ -195,6 +216,13 @@ func (t *linuxARM64Thread) registers() (proc.Registers, error) { return &r, nil } +func (t *linuxRISCV64Thread) registers() (proc.Registers, error) { + var r linutil.RISCV64Registers + r.Regs = t.regs.Regs + r.Fpregs = t.regs.Fpregs + return &r, nil +} + func (t *linuxAMD64Thread) pid() int { return int(t.t.Pid) } @@ -203,6 +231,10 @@ func (t *linuxARM64Thread) pid() int { return int(t.t.Pid) } +func (t *linuxRISCV64Thread) pid() int { + return int(t.t.Pid) +} + // Note is a note from the PT_NOTE prog. // Relevant types: // - NT_FILE: File mapping information, e.g. program text mappings. Desc is a LinuxNTFile. @@ -286,6 +318,8 @@ func readNote(r io.ReadSeeker, machineType elf.Machine) (*note, error) { note.Desc = &linuxPrStatusAMD64{} case _EM_AARCH64: note.Desc = &linuxPrStatusARM64{} + case _EM_RISCV: + note.Desc = &linuxPrStatusRISCV64{} default: return nil, errors.New("unsupported machine type") } @@ -332,6 +366,13 @@ func readNote(r io.ReadSeeker, machineType elf.Machine) (*note, error) { return nil, err } note.Desc = fpregs + } else if machineType == _EM_RISCV { + fpregs := &linutil.RISCV64PtraceFpRegs{} + rdr := bytes.NewReader(desc) + if err := binary.Read(rdr, binary.LittleEndian, fpregs.Byte()); err != nil { + return nil, err + } + note.Desc = fpregs } } if err := skipPadding(r, 4); err != nil { @@ -446,6 +487,19 @@ type linuxPrStatusARM64 struct { Fpvalid int32 } +// LinuxPrStatusRISCV64 is a copy of the prstatus kernel struct. +type linuxPrStatusRISCV64 struct { + Siginfo linuxSiginfo + Cursig uint16 + _ [2]uint8 + Sigpend uint64 + Sighold uint64 + Pid, Ppid, Pgrp, Sid int32 + Utime, Stime, CUtime, CStime linuxCoreTimeval + Reg linutil.RISCV64PtraceRegs + Fpvalid int32 +} + // LinuxSiginfo is a copy of the // siginfo kernel struct. type linuxSiginfo struct { diff --git a/pkg/proc/dump.go b/pkg/proc/dump.go index bb10d300bd..d8cf1851b7 100644 --- a/pkg/proc/dump.go +++ b/pkg/proc/dump.go @@ -138,6 +138,8 @@ func (t *Target) Dump(out elfwriter.WriteCloserSeeker, flags DumpFlags, state *D fhdr.Machine = elf.EM_AARCH64 case "ppc64le": fhdr.Machine = elf.EM_PPC64 + case "riscv64": + fhdr.Machine = elf.EM_RISCV default: panic("not implemented") } diff --git a/pkg/proc/linutil/regs_riscv64_arch.go b/pkg/proc/linutil/regs_riscv64_arch.go new file mode 100644 index 0000000000..726bd67bfb --- /dev/null +++ b/pkg/proc/linutil/regs_riscv64_arch.go @@ -0,0 +1,386 @@ +package linutil + +import ( + "encoding/binary" + "fmt" + + "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/dwarf/regnum" + "github.com/go-delve/delve/pkg/proc" + "golang.org/x/arch/riscv64/riscv64asm" +) + +// RISCV64Registers implements the proc.Registers interface. +type RISCV64Registers struct { + Regs *RISCV64PtraceRegs // general-purpose registers & pc + iscgo bool + tp_tls uint64 + Fpregs []proc.Register // Formatted floating-point registers + Fpregset []byte // holding all floating-point register values + loadFpRegs func(*RISCV64Registers) error +} + +func NewRISCV64Registers(regs *RISCV64PtraceRegs, iscgo bool, tp_tls uint64, + loadFpRegs func(*RISCV64Registers) error) *RISCV64Registers { + return &RISCV64Registers{ + Regs: regs, + iscgo: iscgo, + tp_tls: tp_tls, + loadFpRegs: loadFpRegs, + } +} + +// RISCV64PtraceRegs is the struct used by the linux kernel to return the +// general purpose registers for RISC-V CPUs. +type RISCV64PtraceRegs struct { + Pc uint64 + Ra uint64 + Sp uint64 + Gp uint64 + Tp uint64 + T0 uint64 + T1 uint64 + T2 uint64 + S0 uint64 + S1 uint64 + A0 uint64 + A1 uint64 + A2 uint64 + A3 uint64 + A4 uint64 + A5 uint64 + A6 uint64 + A7 uint64 + S2 uint64 + S3 uint64 + S4 uint64 + S5 uint64 + S6 uint64 + S7 uint64 + S8 uint64 + S9 uint64 + S10 uint64 + S11 uint64 + T3 uint64 + T4 uint64 + T5 uint64 + T6 uint64 +} + +// Slice returns the registers as a list of (name, value) pairs. +func (r *RISCV64Registers) Slice(floatingPoint bool) ([]proc.Register, error) { + var regs64 = []struct { + k string + v uint64 + }{ + {"X1", r.Regs.Ra}, + {"X2", r.Regs.Sp}, + {"X3", r.Regs.Gp}, + {"X4", r.Regs.Tp}, + {"X5", r.Regs.T0}, + {"X6", r.Regs.T1}, + {"X7", r.Regs.T2}, + {"X8", r.Regs.S0}, + {"X9", r.Regs.S1}, + {"X10", r.Regs.A0}, + {"X11", r.Regs.A1}, + {"X12", r.Regs.A2}, + {"X13", r.Regs.A3}, + {"X14", r.Regs.A4}, + {"X15", r.Regs.A5}, + {"X16", r.Regs.A6}, + {"X17", r.Regs.A7}, + {"X18", r.Regs.S2}, + {"X19", r.Regs.S3}, + {"X20", r.Regs.S4}, + {"X21", r.Regs.S5}, + {"X22", r.Regs.S6}, + {"X23", r.Regs.S7}, + {"X24", r.Regs.S8}, + {"X25", r.Regs.S9}, + {"X26", r.Regs.S10}, + {"X27", r.Regs.S11}, + {"X28", r.Regs.T3}, + {"X29", r.Regs.T4}, + {"X30", r.Regs.T5}, + {"X31", r.Regs.T6}, + {"PC", r.Regs.Pc}, + } + + out := make([]proc.Register, 0, (len(regs64) + len(r.Fpregs))) + for _, reg := range regs64 { + out = proc.AppendUint64Register(out, reg.k, reg.v) + } + + var floatLoadError error + if floatingPoint { + if r.loadFpRegs != nil { + floatLoadError = r.loadFpRegs(r) + r.loadFpRegs = nil + } + + out = append(out, r.Fpregs...) + } + + return out, floatLoadError +} + +// PC returns the value of PC register. +func (r *RISCV64Registers) PC() uint64 { + // PC Register + return r.Regs.Pc +} + +// SP returns the value of SP register. +func (r *RISCV64Registers) SP() uint64 { + // Stack pointer + return r.Regs.Sp +} + +// BP returns the value of FP register +func (r *RISCV64Registers) BP() uint64 { + // unused FP register + return 0 +} + +// TLS returns the address of the thread local storage memory segment. +func (r *RISCV64Registers) TLS() uint64 { + // TODO: calling cgo may overwrite $x27, read it from the kernel + if !r.iscgo { + return 0 + } + + return r.tp_tls +} + +// GAddr returns the address of the G variable if it is known, 0 and false otherwise. +func (r *RISCV64Registers) GAddr() (uint64, bool) { + // Defined in $GOROOT/cmd/internal/obj/riscv/cpu.go. + return r.Regs.S11, !r.iscgo +} + +// LR returns the link register. +func (r *RISCV64Registers) LR() uint64 { + return r.Regs.Ra +} + +// Copy returns a copy of these registers that is guaranteed not to change. +func (r *RISCV64Registers) Copy() (proc.Registers, error) { + if r.loadFpRegs != nil { + err := r.loadFpRegs(r) + r.loadFpRegs = nil + if err != nil { + return nil, err + } + } + + var rr RISCV64Registers + rr.Regs = &RISCV64PtraceRegs{} + *(rr.Regs) = *(r.Regs) + if r.Fpregs != nil { + rr.Fpregs = make([]proc.Register, len(r.Fpregs)) + copy(rr.Fpregs, r.Fpregs) + } + + if r.Fpregset != nil { + rr.Fpregset = make([]byte, len(r.Fpregset)) + copy(rr.Fpregset, r.Fpregset) + } + + return &rr, nil +} + +func (r *RISCV64Registers) GetReg(regNum uint64) (uint64, error) { + reg := riscv64asm.Reg(regNum) + + if reg <= riscv64asm.X31 { + switch regNum { + case regnum.RISCV64_LR: + return uint64(r.Regs.Ra), nil + case regnum.RISCV64_SP: + return uint64(r.Regs.Sp), nil + case regnum.RISCV64_GP: + return uint64(r.Regs.Gp), nil + case regnum.RISCV64_TP: + return uint64(r.Regs.Tp), nil + case regnum.RISCV64_T0: + return uint64(r.Regs.T0), nil + case regnum.RISCV64_T1: + return uint64(r.Regs.T1), nil + case regnum.RISCV64_T2: + return uint64(r.Regs.T2), nil + case regnum.RISCV64_S0: + return uint64(r.Regs.S0), nil + case regnum.RISCV64_S1: + return uint64(r.Regs.S1), nil + case regnum.RISCV64_A0: + return uint64(r.Regs.A0), nil + case regnum.RISCV64_A1: + return uint64(r.Regs.A1), nil + case regnum.RISCV64_A2: + return uint64(r.Regs.A2), nil + case regnum.RISCV64_A3: + return uint64(r.Regs.A3), nil + case regnum.RISCV64_A4: + return uint64(r.Regs.A4), nil + case regnum.RISCV64_A5: + return uint64(r.Regs.A5), nil + case regnum.RISCV64_A6: + return uint64(r.Regs.A6), nil + case regnum.RISCV64_A7: + return uint64(r.Regs.A7), nil + case regnum.RISCV64_S2: + return uint64(r.Regs.S2), nil + case regnum.RISCV64_S3: + return uint64(r.Regs.S3), nil + case regnum.RISCV64_S4: + return uint64(r.Regs.S4), nil + case regnum.RISCV64_S5: + return uint64(r.Regs.S5), nil + case regnum.RISCV64_S6: + return uint64(r.Regs.S6), nil + case regnum.RISCV64_S7: + return uint64(r.Regs.S7), nil + case regnum.RISCV64_S8: + return uint64(r.Regs.S8), nil + case regnum.RISCV64_S9: + return uint64(r.Regs.S9), nil + case regnum.RISCV64_S10: + return uint64(r.Regs.S10), nil + case regnum.RISCV64_S11: + return uint64(r.Regs.S11), nil + case regnum.RISCV64_T3: + return uint64(r.Regs.T3), nil + case regnum.RISCV64_T4: + return uint64(r.Regs.T4), nil + case regnum.RISCV64_T5: + return uint64(r.Regs.T5), nil + case regnum.RISCV64_T6: + return uint64(r.Regs.T6), nil + } + } + + return 0, proc.ErrUnknownRegister +} + +func (r *RISCV64Registers) SetReg(regNum uint64, reg *op.DwarfRegister) (fpchanged bool, err error) { + var p *uint64 + switch regNum { + case regnum.RISCV64_LR: + p = &r.Regs.Ra + case regnum.RISCV64_SP: + p = &r.Regs.Sp + case regnum.RISCV64_GP: + p = &r.Regs.Gp + case regnum.RISCV64_TP: + p = &r.Regs.Tp + case regnum.RISCV64_T0: + p = &r.Regs.T0 + case regnum.RISCV64_T1: + p = &r.Regs.T1 + case regnum.RISCV64_T2: + p = &r.Regs.T2 + case regnum.RISCV64_S0: + p = &r.Regs.S0 + case regnum.RISCV64_S1: + p = &r.Regs.S1 + case regnum.RISCV64_A0: + p = &r.Regs.A0 + case regnum.RISCV64_A1: + p = &r.Regs.A1 + case regnum.RISCV64_A2: + p = &r.Regs.A2 + case regnum.RISCV64_A3: + p = &r.Regs.A3 + case regnum.RISCV64_A4: + p = &r.Regs.A4 + case regnum.RISCV64_A5: + p = &r.Regs.A5 + case regnum.RISCV64_A6: + p = &r.Regs.A6 + case regnum.RISCV64_A7: + p = &r.Regs.A7 + case regnum.RISCV64_S2: + p = &r.Regs.S2 + case regnum.RISCV64_S3: + p = &r.Regs.S3 + case regnum.RISCV64_S4: + p = &r.Regs.S4 + case regnum.RISCV64_S5: + p = &r.Regs.S5 + case regnum.RISCV64_S6: + p = &r.Regs.S6 + case regnum.RISCV64_S7: + p = &r.Regs.S7 + case regnum.RISCV64_S8: + p = &r.Regs.S8 + case regnum.RISCV64_S9: + p = &r.Regs.S9 + case regnum.RISCV64_S10: + p = &r.Regs.S10 + case regnum.RISCV64_S11: + p = &r.Regs.S11 + case regnum.RISCV64_T3: + p = &r.Regs.T3 + case regnum.RISCV64_T4: + p = &r.Regs.T4 + case regnum.RISCV64_T5: + p = &r.Regs.T5 + case regnum.RISCV64_T6: + p = &r.Regs.T6 + case regnum.RISCV64_PC: + p = &r.Regs.Pc + } + + if p != nil { + *p = reg.Uint64Val + return false, nil + } + + switch { + case regNum >= regnum.RISCV64_F0 && regNum <= regnum.RISCV64_F31: + if r.loadFpRegs != nil { + err := r.loadFpRegs(r) + r.loadFpRegs = nil + if err != nil { + return false, err + } + } + + i := regNum - regnum.RISCV64_F0 + reg.FillBytes() + copy(r.Fpregset[8*i:], reg.Bytes) + return true, nil + + default: + return false, fmt.Errorf("changing register %d not implemented", regNum) + } +} + +// RISCV64PtraceFpRegs is refer to the definition of struct __riscv_d_ext_state in the kernel ptrace.h +type RISCV64PtraceFpRegs struct { + Fregs []byte + Fcsr uint32 +} + +const _RISCV64_FPREGSET_LENGTH = (32 * 8) + +func (fpregs *RISCV64PtraceFpRegs) Decode() (regs []proc.Register) { + for i := 0; i < len(fpregs.Fregs); i += 8 { + name := fmt.Sprintf("F%d", (i / 8)) + value := fpregs.Fregs[i : i+8] + regs = proc.AppendBytesRegister(regs, name, value) + } + + fcsrBytes := make([]byte, 4) + binary.LittleEndian.PutUint32(fcsrBytes, uint32(fpregs.Fcsr)) + regs = proc.AppendBytesRegister(regs, "FCSR", fcsrBytes) + + return +} + +func (fpregs *RISCV64PtraceFpRegs) Byte() []byte { + fpregs.Fregs = make([]byte, _RISCV64_FPREGSET_LENGTH) + + return fpregs.Fregs[:] +} diff --git a/pkg/proc/native/hwbreak_other.go b/pkg/proc/native/hwbreak_other.go index e65bf5b847..924534fa14 100644 --- a/pkg/proc/native/hwbreak_other.go +++ b/pkg/proc/native/hwbreak_other.go @@ -1,4 +1,4 @@ -//go:build (linux && 386) || (darwin && arm64) || (windows && arm64) || (linux && ppc64le) +//go:build (linux && 386) || (darwin && arm64) || (windows && arm64) || (linux && ppc64le) || (linux && riscv64) package native diff --git a/pkg/proc/native/proc.go b/pkg/proc/native/proc.go index e209d9f81e..715e5686d6 100644 --- a/pkg/proc/native/proc.go +++ b/pkg/proc/native/proc.go @@ -382,7 +382,7 @@ func (dbp *nativeProcess) initialize(path string, debugInfoDirs []string) (*proc if err != nil { return nil, err } - if dbp.bi.Arch.Name == "arm64" || dbp.bi.Arch.Name == "ppc64le" { + if dbp.bi.Arch.Name == "arm64" || dbp.bi.Arch.Name == "ppc64le" || dbp.bi.Arch.Name == "riscv64" { dbp.iscgo = tgt.IsCgo() } return grp, nil diff --git a/pkg/proc/native/ptrace_linux_64bit.go b/pkg/proc/native/ptrace_linux_64bit.go index 01a1170484..78124fa26b 100644 --- a/pkg/proc/native/ptrace_linux_64bit.go +++ b/pkg/proc/native/ptrace_linux_64bit.go @@ -1,4 +1,4 @@ -//go:build (linux && amd64) || (linux && arm64) || (linux && ppc64le) +//go:build (linux && amd64) || (linux && arm64) || (linux && ppc64le) || (linux && riscv64) package native diff --git a/pkg/proc/native/registers_linux_riscv64.go b/pkg/proc/native/registers_linux_riscv64.go new file mode 100644 index 0000000000..d1796b3bc2 --- /dev/null +++ b/pkg/proc/native/registers_linux_riscv64.go @@ -0,0 +1,144 @@ +package native + +import ( + "debug/elf" + "encoding/binary" + "syscall" + "unsafe" + + sys "golang.org/x/sys/unix" + + "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc/linutil" +) + +// Defined in asm/ptrace.h +const ( + _RISCV64_GREGS_SIZE = 32 * 8 + _RISCV64_FPREGS_SIZE = (32 * 8) + 4 + 4 // Add 4 bytes to align with 8 due to sys.Iovec uses uint64 as len +) + +func ptraceGetGRegs(pid int, regs *linutil.RISCV64PtraceRegs) (err error) { + iov := sys.Iovec{Base: (*byte)(unsafe.Pointer(regs)), Len: _RISCV64_GREGS_SIZE} + + _, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETREGSET, uintptr(pid), + uintptr(elf.NT_PRSTATUS), uintptr(unsafe.Pointer(&iov)), 0, 0) + if err == syscall.Errno(0) { + err = nil + } + + return +} + +func ptraceSetGRegs(pid int, regs *linutil.RISCV64PtraceRegs) (err error) { + iov := sys.Iovec{Base: (*byte)(unsafe.Pointer(regs)), Len: _RISCV64_GREGS_SIZE} + + _, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETREGSET, uintptr(pid), uintptr(elf.NT_PRSTATUS), uintptr(unsafe.Pointer(&iov)), 0, 0) + if err == syscall.Errno(0) { + err = nil + } + + return +} + +func ptraceGetFpRegset(tid int, fpregs *linutil.RISCV64PtraceFpRegs) (err error) { + fprBytes := make([]byte, _RISCV64_FPREGS_SIZE) + iov := sys.Iovec{Base: &fprBytes[0], Len: uint64(_RISCV64_FPREGS_SIZE)} + + _, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETREGSET, uintptr(tid), uintptr(elf.NT_FPREGSET), uintptr(unsafe.Pointer(&iov)), 0, 0) + if err != syscall.Errno(0) { + if err == syscall.ENODEV { + err = nil + } + return + } else { + err = nil + } + + fpregs.Fregs = fprBytes[:iov.Len-8] + fpregs.Fcsr = binary.LittleEndian.Uint32(fprBytes[iov.Len-8 : iov.Len-4]) + + return +} + +func (thread *nativeThread) setPC(pc uint64) error { + ir, err := registers(thread) + if err != nil { + return err + } + + r := ir.(*linutil.RISCV64Registers) + r.Regs.Pc = pc + thread.dbp.execPtraceFunc(func() { err = ptraceSetGRegs(thread.ID, r.Regs) }) + + return err +} + +func (thread *nativeThread) setSP(sp uint64) (err error) { + var ir proc.Registers + + ir, err = registers(thread) + if err != nil { + return err + } + + r := ir.(*linutil.RISCV64Registers) + r.Regs.Sp = sp + thread.dbp.execPtraceFunc(func() { err = ptraceSetGRegs(thread.ID, r.Regs) }) + + return nil +} + +func (thread *nativeThread) SetReg(regNum uint64, reg *op.DwarfRegister) error { + ir, err := registers(thread) + if err != nil { + return err + } + r := ir.(*linutil.RISCV64Registers) + fpchanged, err := r.SetReg(regNum, reg) + if err != nil { + return err + } + + thread.dbp.execPtraceFunc(func() { + err = ptraceSetGRegs(thread.ID, r.Regs) + if err != syscall.Errno(0) && err != nil { + return + } + if fpchanged && r.Fpregset != nil { + iov := sys.Iovec{Base: &r.Fpregset[0], Len: uint64(len(r.Fpregset))} + _, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETREGSET, uintptr(thread.ID), uintptr(elf.NT_FPREGSET), uintptr(unsafe.Pointer(&iov)), 0, 0) + } + }) + if err == syscall.Errno(0) { + err = nil + } + + return err +} + +func registers(thread *nativeThread) (proc.Registers, error) { + var ( + regs linutil.RISCV64PtraceRegs + err error + ) + + thread.dbp.execPtraceFunc(func() { err = ptraceGetGRegs(thread.ID, ®s) }) + if err != nil { + return nil, err + } + + var tp_tls uint64 + if thread.dbp.iscgo { + tp_tls = regs.Tp + } + r := linutil.NewRISCV64Registers(®s, thread.dbp.iscgo, tp_tls, + func(r *linutil.RISCV64Registers) error { + var floatLoadError error + r.Fpregs, r.Fpregset, floatLoadError = thread.fpRegisters() + return floatLoadError + }) + + return r, nil +} diff --git a/pkg/proc/native/support_sentinel_linux.go b/pkg/proc/native/support_sentinel_linux.go index afb7c0a6f9..c1149d7d4a 100644 --- a/pkg/proc/native/support_sentinel_linux.go +++ b/pkg/proc/native/support_sentinel_linux.go @@ -1,4 +1,4 @@ -//go:build linux && !amd64 && !arm64 && !386 && !(ppc64le && exp.linuxppc64le) +//go:build linux && !amd64 && !arm64 && !386 && !(ppc64le && exp.linuxppc64le) && !riscv64 // This file is used to detect build on unsupported GOOS/GOARCH combinations. diff --git a/pkg/proc/native/threads_hardware_singlestep_linux.go b/pkg/proc/native/threads_hardware_singlestep_linux.go new file mode 100644 index 0000000000..7741786620 --- /dev/null +++ b/pkg/proc/native/threads_hardware_singlestep_linux.go @@ -0,0 +1,45 @@ +//go:build !riscv64 + +package native + +import ( + "github.com/go-delve/delve/pkg/proc" + sys "golang.org/x/sys/unix" +) + +func (procgrp *processGroup) singleStep(t *nativeThread) (err error) { + sig := 0 + for { + t.dbp.execPtraceFunc(func() { err = ptraceSingleStep(t.ID, sig) }) + sig = 0 + if err != nil { + return err + } + wpid, status, err := t.dbp.waitFast(t.ID) + if err != nil { + return err + } + if (status == nil || status.Exited()) && wpid == t.dbp.pid { + t.dbp.postExit() + rs := 0 + if status != nil { + rs = status.ExitStatus() + } + return proc.ErrProcessExited{Pid: t.dbp.pid, Status: rs} + } + if wpid == t.ID { + switch s := status.StopSignal(); s { + case sys.SIGTRAP: + return nil + case sys.SIGSTOP: + // delayed SIGSTOP, ignore it + case sys.SIGILL, sys.SIGBUS, sys.SIGFPE, sys.SIGSEGV, sys.SIGSTKFLT: + // propagate signals that can have been caused by the current instruction + sig = int(s) + default: + // delay propagation of all other signals + t.os.delayedSignal = int(s) + } + } + } +} diff --git a/pkg/proc/native/threads_linux.go b/pkg/proc/native/threads_linux.go index 9cf1e3a893..e6fac3f240 100644 --- a/pkg/proc/native/threads_linux.go +++ b/pkg/proc/native/threads_linux.go @@ -4,8 +4,6 @@ import ( "fmt" sys "golang.org/x/sys/unix" - - "github.com/go-delve/delve/pkg/proc" ) type waitStatus sys.WaitStatus @@ -50,43 +48,6 @@ func (t *nativeThread) resumeWithSig(sig int) (err error) { return } -func (procgrp *processGroup) singleStep(t *nativeThread) (err error) { - sig := 0 - for { - t.dbp.execPtraceFunc(func() { err = ptraceSingleStep(t.ID, sig) }) - sig = 0 - if err != nil { - return err - } - wpid, status, err := t.dbp.waitFast(t.ID) - if err != nil { - return err - } - if (status == nil || status.Exited()) && wpid == t.dbp.pid { - t.dbp.postExit() - rs := 0 - if status != nil { - rs = status.ExitStatus() - } - return proc.ErrProcessExited{Pid: t.dbp.pid, Status: rs} - } - if wpid == t.ID { - switch s := status.StopSignal(); s { - case sys.SIGTRAP: - return nil - case sys.SIGSTOP: - // delayed SIGSTOP, ignore it - case sys.SIGILL, sys.SIGBUS, sys.SIGFPE, sys.SIGSEGV, sys.SIGSTKFLT: - // propagate signals that can have been caused by the current instruction - sig = int(s) - default: - // delay propagation of all other signals - t.os.delayedSignal = int(s) - } - } - } -} - func (t *nativeThread) WriteMemory(addr uint64, data []byte) (written int, err error) { if ok, err := t.dbp.Valid(); !ok { return 0, err diff --git a/pkg/proc/native/threads_linux_riscv64.go b/pkg/proc/native/threads_linux_riscv64.go new file mode 100644 index 0000000000..1a1b34fb7a --- /dev/null +++ b/pkg/proc/native/threads_linux_riscv64.go @@ -0,0 +1,294 @@ +package native + +import ( + "bytes" + "debug/elf" + "fmt" + "syscall" + "unsafe" + + sys "golang.org/x/sys/unix" + + "github.com/go-delve/delve/pkg/proc" + "github.com/go-delve/delve/pkg/proc/linutil" + "golang.org/x/arch/riscv64/riscv64asm" +) + +func (thread *nativeThread) fpRegisters() ([]proc.Register, []byte, error) { + var err error + var riscv64_fpregs linutil.RISCV64PtraceFpRegs + + thread.dbp.execPtraceFunc(func() { err = ptraceGetFpRegset(thread.ID, &riscv64_fpregs) }) + fpregs := riscv64_fpregs.Decode() + + if err != nil { + err = fmt.Errorf("could not get floating point registers: %v", err.Error()) + } + + return fpregs, riscv64_fpregs.Fregs, err +} + +func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error { + var restoreRegistersErr error + + sr := savedRegs.(*linutil.RISCV64Registers) + t.dbp.execPtraceFunc(func() { + restoreRegistersErr = ptraceSetGRegs(t.ID, sr.Regs) + if restoreRegistersErr != syscall.Errno(0) { + return + } + + if sr.Fpregset != nil { + iov := sys.Iovec{Base: &sr.Fpregset[0], Len: uint64(len(sr.Fpregset))} + _, _, restoreRegistersErr = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETREGSET, uintptr(t.ID), uintptr(elf.NT_FPREGSET), uintptr(unsafe.Pointer(&iov)), 0, 0) + } + }) + + if restoreRegistersErr == syscall.Errno(0) { + restoreRegistersErr = nil + } + + return restoreRegistersErr +} + +// resolvePC is used to resolve next PC for current instruction. +func (t *nativeThread) resolvePC(savedRegs proc.Registers) ([]uint64, error) { + regs := savedRegs.(*linutil.RISCV64Registers) + nextInstLen := t.BinInfo().Arch.MaxInstructionLength() + nextInstBytes := make([]byte, nextInstLen) + var err error + + t.dbp.execPtraceFunc(func() { + _, err = sys.PtracePeekData(t.ID, uintptr(regs.PC()), nextInstBytes) + }) + if err != nil { + return nil, err + } + + nextPCs := []uint64{regs.PC() + uint64(nextInstLen)} + if bytes.Equal(nextInstBytes, t.BinInfo().Arch.AltBreakpointInstruction()) { + return nextPCs, nil + } else if bytes.Equal(nextInstBytes, t.BinInfo().Arch.BreakpointInstruction()) { + nextInstLen = 2 + nextPCs = []uint64{regs.PC() + uint64(nextInstLen)} + return nextPCs, nil + } + + nextInst, err := riscv64asm.Decode(nextInstBytes) + if err != nil { + return nil, err + } + + if nextInst.Len == 2 { + nextInstBytes = nextInstBytes[:2] + nextInstLen = 2 + nextPCs = []uint64{regs.PC() + uint64(nextInstLen)} + } + + switch nextInst.Op { + case riscv64asm.BEQ, riscv64asm.BNE, riscv64asm.BLT, riscv64asm.BGE, riscv64asm.BLTU, riscv64asm.BGEU: + rs1, _ := nextInst.Args[0].(riscv64asm.Reg) + rs2, _ := nextInst.Args[1].(riscv64asm.Reg) + bimm12, _ := nextInst.Args[2].(riscv64asm.Simm) + src1u, _ := regs.GetReg(uint64(rs1)) + src2u, _ := regs.GetReg(uint64(rs2)) + src1, src2 := int64(src1u), int64(src2u) + + switch nextInst.Op { + case riscv64asm.BEQ: + if src1 == src2 && int(bimm12.Imm) != nextInstLen { + nextPCs = append(nextPCs, regs.PC()+uint64(bimm12.Imm)) + } + case riscv64asm.BNE: + if src1 != src2 && int(bimm12.Imm) != nextInstLen { + nextPCs = append(nextPCs, regs.PC()+uint64(bimm12.Imm)) + } + case riscv64asm.BLT: + if src1 < src2 && int(bimm12.Imm) != nextInstLen { + nextPCs = append(nextPCs, regs.PC()+uint64(bimm12.Imm)) + } + case riscv64asm.BGE: + if src1 >= src2 && int(bimm12.Imm) != nextInstLen { + nextPCs = append(nextPCs, regs.PC()+uint64(bimm12.Imm)) + } + case riscv64asm.BLTU: + if src1u < src2u && int(bimm12.Imm) != nextInstLen { + nextPCs = append(nextPCs, regs.PC()+uint64(bimm12.Imm)) + } + case riscv64asm.BGEU: + if src1u >= src2u && int(bimm12.Imm) != nextInstLen { + nextPCs = append(nextPCs, regs.PC()+uint64(bimm12.Imm)) + } + } + + case riscv64asm.JAL: + jimm, _ := nextInst.Args[1].(riscv64asm.Simm) + if int(jimm.Imm) != nextInstLen { + nextPCs = append(nextPCs, regs.PC()+uint64(jimm.Imm)) + } + + case riscv64asm.JALR: + rd, _ := nextInst.Args[0].(riscv64asm.Reg) + rs1_mem := nextInst.Args[1].(riscv64asm.RegOffset) + rs1, ofs := rs1_mem.OfsReg, rs1_mem.Ofs + src1, _ := regs.GetReg(uint64(rs1)) + if rd == riscv64asm.X0 && rs1 == riscv64asm.X1 { + nextPCs = []uint64{(src1 + uint64(ofs.Imm)) & (^uint64(0x1))} + } + if (src1+uint64(ofs.Imm))&(^uint64(0x1)) != nextPCs[0] { + nextPCs = append(nextPCs, (src1+uint64(ofs.Imm))&(^uint64(0x1))) + } + + // We can't put a breakpoint in the middle of a lr/sc atomic sequence, so look for the end of the sequence and put the breakpoint there. + // RISC-V Go only use lr.w/d.aq, see comments at the beginning of $GOROOT/src/runtime/internal/atomic/atomic_riscv64.s + case riscv64asm.LR_D_AQ, riscv64asm.LR_W_AQ: + // Currently, RISC-V Go only use this kind of lr/sc sequence, so only check this pattern. + // defined in $GOROOT/src/cmd/compile/internal/riscv64/ssa.go: + // LR (Rarg0), Rtmp + // BNE Rtmp, Rarg1, 3(PC) + // SC Rarg2, (Rarg0), Rtmp + // BNE Rtmp, ZERO, -3(PC) + curPC := regs.PC() + uint64(nextInstLen) + t.dbp.execPtraceFunc(func() { + _, err = sys.PtracePeekData(t.ID, uintptr(curPC), nextInstBytes) + }) + if err != nil { + return nil, err + } + nextInst, err = riscv64asm.Decode(nextInstBytes) + if err != nil { + return nil, err + } + if nextInst.Len == 2 { + nextInstBytes = nextInstBytes[:2] + } + if nextInst.Op != riscv64asm.BNE { + break + } + + curPC += uint64(nextInstLen) + t.dbp.execPtraceFunc(func() { + _, err = sys.PtracePeekData(t.ID, uintptr(curPC), nextInstBytes) + }) + if err != nil { + return nil, err + } + nextInst, err = riscv64asm.Decode(nextInstBytes) + if err != nil { + return nil, err + } + if nextInst.Len == 2 { + nextInstBytes = nextInstBytes[:2] + } + if nextInst.Op != riscv64asm.SC_D_RL && nextInst.Op != riscv64asm.SC_W_RL { + break + } + + curPC += uint64(nextInstLen) + t.dbp.execPtraceFunc(func() { + _, err = sys.PtracePeekData(t.ID, uintptr(regs.PC()+uint64(curPC)), nextInstBytes) + }) + if err != nil { + return nil, err + } + nextInst, err = riscv64asm.Decode(nextInstBytes) + if err != nil { + return nil, err + } + if nextInst.Len == 2 { + nextInstBytes = nextInstBytes[:2] + } + if nextInst.Op != riscv64asm.BNE { + break + } + nextPCs = []uint64{curPC} + } + + return nextPCs, nil +} + +// RISC-V doesn't have ptrace singlestep support, so use breakpoint to emulate it. +func (procgrp *processGroup) singleStep(t *nativeThread) (err error) { + regs, err := t.Registers() + if err != nil { + return err + } + nextPCs, err := t.resolvePC(regs) + if err != nil { + return err + } + originalDataSet := make(map[uintptr][]byte) + + // Do in batch, first set breakpoint, then continue. + t.dbp.execPtraceFunc(func() { + breakpointInstr := t.BinInfo().Arch.BreakpointInstruction() + readWriteMem := func(i int, addr uintptr, instr []byte) error { + originalData := make([]byte, len(breakpointInstr)) + _, err = sys.PtracePeekData(t.ID, addr, originalData) + if err != nil { + return err + } + _, err = sys.PtracePokeData(t.ID, addr, instr) + if err != nil { + return err + } + // Everything is ok, store originalData + originalDataSet[addr] = originalData + return nil + } + for i, nextPC := range nextPCs { + err = readWriteMem(i, uintptr(nextPC), breakpointInstr) + if err != nil { + return + } + } + }) + // Make sure we restore before return. + defer func() { + t.dbp.execPtraceFunc(func() { + for addr, originalData := range originalDataSet { + if originalData != nil { + _, err = sys.PtracePokeData(t.ID, addr, originalData) + } + } + }) + }() + if err != nil { + return err + } + for { + sig := 0 + t.dbp.execPtraceFunc(func() { err = ptraceCont(t.ID, sig) }) + if err != nil { + return err + } + // To be able to catch process exit, we can only use wait instead of waitFast. + wpid, status, err := t.dbp.wait(t.ID, 0) + if err != nil { + return err + } + if (status == nil || status.Exited()) && wpid == t.dbp.pid { + t.dbp.postExit() + rs := 0 + if status != nil { + rs = status.ExitStatus() + } + return proc.ErrProcessExited{Pid: t.dbp.pid, Status: rs} + } + if wpid == t.ID { + sig = 0 + switch s := status.StopSignal(); s { + case sys.SIGTRAP: + return nil + case sys.SIGSTOP: + // delayed SIGSTOP, ignore it + case sys.SIGILL, sys.SIGBUS, sys.SIGFPE, sys.SIGSEGV, sys.SIGSTKFLT: + // propagate signals that can have been caused by the current instruction + sig = int(s) + default: + // delay propagation of all other signals + t.os.delayedSignal = int(s) + } + } + } +} diff --git a/pkg/proc/pe.go b/pkg/proc/pe.go index 6295f8f89a..5cf55a9e57 100644 --- a/pkg/proc/pe.go +++ b/pkg/proc/pe.go @@ -21,6 +21,7 @@ const ( _IMAGE_FILE_MACHINE_POWERPC = 0x1f0 _IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1 _IMAGE_FILE_MACHINE_R4000 = 0x166 + _IMAGE_FILE_MACHINE_RISCV64 = 0x5064 _IMAGE_FILE_MACHINE_SH3 = 0x1a2 _IMAGE_FILE_MACHINE_SH3DSP = 0x1a3 _IMAGE_FILE_MACHINE_SH4 = 0x1a6 diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index d86bf67f19..6fe5bc2d1c 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -2814,6 +2814,7 @@ func TestDebugStripped2(t *testing.T) { skipOn(t, "not working on freebsd", "freebsd") skipOn(t, "not working on linux/386", "linux", "386") skipOn(t, "not working on linux/ppc64le when -gcflags=-N -l is passed", "linux", "ppc64le") + skipOn(t, "not working on linux/riscv64", "linux", "riscv64") ver, _ := goversion.Parse(runtime.Version()) if ver.IsDevel() { t.Skip("not supported") @@ -2961,6 +2962,7 @@ func TestCgoStacktrace(t *testing.T) { skipOn(t, "broken - cgo stacktraces", "386") skipOn(t, "broken - cgo stacktraces", "windows", "arm64") skipOn(t, "broken - cgo stacktraces", "linux", "ppc64le") + skipOn(t, "broken - cgo stacktraces", "linux", "riscv64") if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 21) { skipOn(t, "broken - cgo stacktraces", "windows", "arm64") } @@ -3349,6 +3351,7 @@ func TestHaltKeepsSteppingBreakpoints(t *testing.T) { func TestDisassembleGlobalVars(t *testing.T) { skipOn(t, "broken - global variable symbolication", "arm64") // On ARM64 symLookup can't look up variables due to how they are loaded, see issue #1778 skipOn(t, "broken - global variable symbolication", "ppc64le") // See comment on ARM64 above. + skipOn(t, "broken - global variable symbolication", "riscv64") // On 386 linux when pie, the generated code use __x86.get_pc_thunk to ensure position-independent. // Locate global variable by // `CALL __x86.get_pc_thunk.ax(SB) 0xb0f7f @@ -3640,6 +3643,7 @@ func TestIssue951(t *testing.T) { func TestDWZCompression(t *testing.T) { skipOn(t, "broken", "ppc64le") + skipOn(t, "broken", "riscv64") // If dwz is not available in the system, skip this test if _, err := exec.LookPath("dwz"); err != nil { t.Skip("dwz not installed") @@ -4202,6 +4206,7 @@ func TestCgoStacktrace2(t *testing.T) { skipOn(t, "broken", "386") skipOn(t, "broken - cgo stacktraces", "darwin", "arm64") skipOn(t, "broken", "ppc64le") + skipOn(t, "broken", "riscv64") protest.MustHaveCgo(t) // If a panic happens during cgo execution the stacktrace should show the C // function that caused the problem. @@ -4745,6 +4750,7 @@ func TestWatchpointsBasic(t *testing.T) { skipOn(t, "not implemented", "freebsd") skipOn(t, "not implemented", "386") skipOn(t, "not implemented", "ppc64le") + skipOn(t, "not implemented", "riscv64") skipOn(t, "see https://github.com/go-delve/delve/issues/2768", "windows") protest.AllowRecording(t) @@ -4801,6 +4807,7 @@ func TestWatchpointCounts(t *testing.T) { skipOn(t, "not implemented", "386") skipOn(t, "see https://github.com/go-delve/delve/issues/2768", "windows") skipOn(t, "not implemented", "ppc64le") + skipOn(t, "not implemented", "riscv64") if _, isTeamCityTest := os.LookupEnv("TEAMCITY_VERSION"); isTeamCityTest { skipOn(t, "CI is running a version of macOS that is too old (11.2)", "darwin", "arm64") } @@ -4919,6 +4926,7 @@ func TestWatchpointStack(t *testing.T) { skipOn(t, "not implemented", "freebsd") skipOn(t, "not implemented", "386") skipOn(t, "not implemented", "ppc64le") + skipOn(t, "not implemented", "riscv64") skipOn(t, "see https://github.com/go-delve/delve/issues/2768", "windows") if _, isTeamCityTest := os.LookupEnv("TEAMCITY_VERSION"); isTeamCityTest { skipOn(t, "CI is running a version of macOS that is too old (11.2)", "darwin", "arm64") @@ -5077,6 +5085,8 @@ func TestNilPtrDerefInBreakInstr(t *testing.T) { asmfile = "main_386.s" case "ppc64le": asmfile = "main_ppc64le.s" + case "riscv64": + asmfile = "main_riscv64.s" default: t.Fatalf("assembly file for %s not provided", runtime.GOARCH) } diff --git a/pkg/proc/riscv64_arch.go b/pkg/proc/riscv64_arch.go new file mode 100644 index 0000000000..71d9b5655e --- /dev/null +++ b/pkg/proc/riscv64_arch.go @@ -0,0 +1,286 @@ +package proc + +import ( + "encoding/binary" + "fmt" + "strings" + + "github.com/go-delve/delve/pkg/dwarf/frame" + "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/dwarf/regnum" +) + +// ebreak instruction: 0x00100073 +var riscv64BreakInstruction = []byte{0x73, 0x00, 0x10, 0x00} + +// c.ebreak instruction: 0x9002 +var riscv64CompressedBreakInstruction = []byte{0x02, 0x90} + +// RISCV64Arch returns an initialized RISCV64 struct. +func RISCV64Arch(goos string) *Arch { + return &Arch{ + Name: "riscv64", + ptrSize: 8, + maxInstructionLength: 4, + breakpointInstruction: riscv64CompressedBreakInstruction, + altBreakpointInstruction: riscv64BreakInstruction, + breakInstrMovesPC: false, + derefTLS: false, + prologues: prologuesRISCV64, + fixFrameUnwindContext: riscv64FixFrameUnwindContext, + switchStack: riscv64SwitchStack, + regSize: riscv64RegSize, + RegistersToDwarfRegisters: riscv64RegistersToDwarfRegisters, + addrAndStackRegsToDwarfRegisters: riscv64AddrAndStackRegsToDwarfRegisters, + DwarfRegisterToString: riscv64DwarfRegisterToString, + inhibitStepInto: func(*BinaryInfo, uint64) bool { return false }, + asmDecode: riscv64AsmDecode, + usesLR: true, + PCRegNum: regnum.RISCV64_PC, + SPRegNum: regnum.RISCV64_SP, + asmRegisters: riscv64AsmRegisters, + RegisterNameToDwarf: nameToDwarfFunc(regnum.RISCV64NameToDwarf), + RegnumToString: regnum.RISCV64ToName, + debugCallMinStackSize: 288, // TODO + maxRegArgBytes: 16*8 + 16*8, // 16 int argument registers plus 16 float argument registers + } +} + +func riscv64FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi *BinaryInfo) *frame.FrameContext { + a := bi.Arch + + if a.sigreturnfn == nil { + a.sigreturnfn = bi.lookupOneFunc("runtime.sigreturn") + } + + if (fctxt == nil) || ((a.sigreturnfn != nil) && (pc >= a.sigreturnfn.Entry) && (pc < a.sigreturnfn.End)) { + // When there's no frame descriptor entry use BP (the frame pointer) instead + // - return register is [bp + a.PtrSize()] (i.e. [cfa-a.PtrSize()]) + // - cfa is bp + a.PtrSize()*2 + // - bp is [bp] (i.e. [cfa-a.PtrSize()*2]) + // - sp is cfa + + // When the signal handler runs it will move the execution to the signal + // handling stack (installed using the sigaltstack system call). + // This isn't a proper stack switch: the pointer to g in TLS will still + // refer to whatever g was executing on that thread before the signal was + // received. + // Since go did not execute a stack switch the previous value of sp, pc + // and bp is not saved inside g.sched, as it normally would. + // The only way to recover is to either read sp/pc from the signal context + // parameter (the ucontext_t* parameter) or to unconditionally follow the + // frame pointer when we get to runtime.sigreturn (which is what we do + // here). + + return &frame.FrameContext{ + RetAddrReg: regnum.RISCV64_PC, + Regs: map[uint64]frame.DWRule{ + regnum.RISCV64_PC: { + Rule: frame.RuleOffset, + Offset: int64(-a.PtrSize()), + }, + + regnum.RISCV64_FP: { + Rule: frame.RuleOffset, + Offset: int64(-2 * a.PtrSize()), + }, + + regnum.RISCV64_SP: { + Rule: frame.RuleValOffset, + Offset: 0, + }, + }, + + CFA: frame.DWRule{ + Rule: frame.RuleCFA, + Reg: regnum.RISCV64_FP, + Offset: int64(2 * a.PtrSize()), + }, + } + } + + if a.crosscall2fn == nil { + a.crosscall2fn = bi.lookupOneFunc("crosscall2") + } + + if a.crosscall2fn != nil && pc >= a.crosscall2fn.Entry && pc < a.crosscall2fn.End { + rule := fctxt.CFA + + if rule.Offset == crosscall2SPOffsetBad { + rule.Offset += crosscall2SPOffset + } + fctxt.CFA = rule + } + + // We assume that FP is the frame pointer and we want to keep it updated, + // so that we can use it to unwind the stack even when we encounter frames + // without descriptor entries. + // If there isn't a rule already we emit one. + if fctxt.Regs[regnum.RISCV64_FP].Rule == frame.RuleUndefined { + fctxt.Regs[regnum.RISCV64_FP] = frame.DWRule{ + Rule: frame.RuleFramePointer, + Reg: regnum.RISCV64_FP, + Offset: 0, + } + } + + if fctxt.Regs[regnum.RISCV64_LR].Rule == frame.RuleUndefined { + fctxt.Regs[regnum.RISCV64_LR] = frame.DWRule{ + Rule: frame.RuleRegister, + Reg: regnum.RISCV64_LR, + Offset: 0, + } + } + + return fctxt +} + +const riscv64cgocallSPOffsetSaveSlot = 0x8 +const riscv64prevG0schedSPOffsetSaveSlot = 0x10 + +func riscv64SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool { + if it.frame.Current.Fn == nil { + if it.systemstack && it.g != nil && it.top { + it.switchToGoroutineStack() + return true + } + return false + } + switch it.frame.Current.Fn.Name { + case "runtime.cgocallback_gofunc", "runtime.cgocallback", "runtime.asmcgocall", "crosscall2": + // cgostacktrace is broken on riscv64, so do nothing here. + + case "runtime.goexit", "runtime.rt0_go", "runtime.mcall": + // Look for "top of stack" functions. + it.atend = true + return true + + case "runtime.mstart": + // Calls to runtime.systemstack will switch to the systemstack then: + // 1. alter the goroutine stack so that it looks like systemstack_switch + // was called + // 2. alter the system stack so that it looks like the bottom-most frame + // belongs to runtime.mstart + // If we find a runtime.mstart frame on the system stack of a goroutine + // parked on runtime.systemstack_switch we assume runtime.systemstack was + // called and continue tracing from the parked position. + + if it.top || !it.systemstack || it.g == nil { + return false + } + if fn := it.bi.PCToFunc(it.g.PC); fn == nil || fn.Name != "runtime.systemstack_switch" { + return false + } + + it.switchToGoroutineStack() + return true + default: + if it.systemstack && it.top && it.g != nil && strings.HasPrefix(it.frame.Current.Fn.Name, "runtime.") && it.frame.Current.Fn.Name != "runtime.throw" && it.frame.Current.Fn.Name != "runtime.fatalthrow" { + // The runtime switches to the system stack in multiple places. + // This usually happens through a call to runtime.systemstack but there + // are functions that switch to the system stack manually (for example + // runtime.morestack). + // Since we are only interested in printing the system stack for cgo + // calls we switch directly to the goroutine stack if we detect that the + // function at the top of the stack is a runtime function. + it.switchToGoroutineStack() + return true + } + } + + fn := it.bi.PCToFunc(it.frame.Ret) + if fn == nil { + return false + } + + switch fn.Name { + case "runtime.asmcgocall": + if !it.systemstack { + return false + } + + // This function is called by a goroutine to execute a C function and + // switches from the goroutine stack to the system stack. + // Since we are unwinding the stack from callee to caller we have to switch + // from the system stack to the goroutine stack. + off, _ := readIntRaw(it.mem, uint64(callFrameRegs.SP()+riscv64cgocallSPOffsetSaveSlot), int64(it.bi.Arch.PtrSize())) + oldsp := callFrameRegs.SP() + newsp := uint64(int64(it.stackhi) - off) + + // runtime.asmcgocall can also be called from inside the system stack, + // in that case no stack switch actually happens + if newsp == oldsp { + return false + } + + it.systemstack = false + callFrameRegs.Reg(callFrameRegs.SPRegNum).Uint64Val = uint64(int64(newsp)) + + return false + + case "runtime.cgocallback_gofunc": + // For a detailed description of how this works read the long comment at + // the start of $GOROOT/src/runtime/cgocall.go and the source code of + // runtime.cgocallback_gofunc in $GOROOT/src/runtime/asm_riscv64.s + // + // When a C functions calls back into go it will eventually call into + // runtime.cgocallback_gofunc which is the function that does the stack + // switch from the system stack back into the goroutine stack + // Since we are going backwards on the stack here we see the transition + // as goroutine stack -> system stack. + if it.systemstack { + return false + } + + it.loadG0SchedSP() + if it.g0_sched_sp <= 0 { + return false + } + + // entering the system stack + callFrameRegs.Reg(callFrameRegs.SPRegNum).Uint64Val = it.g0_sched_sp + + // reads the previous value of g0.sched.sp that runtime.cgocallback_gofunc saved on the stack + it.g0_sched_sp, _ = readUintRaw(it.mem, uint64(callFrameRegs.SP()+riscv64prevG0schedSPOffsetSaveSlot), int64(it.bi.Arch.PtrSize())) + it.systemstack = true + return false + } + + return false +} + +func riscv64RegSize(regnum uint64) int { + // All CPU registers are 64bit + return 8 +} + +func riscv64RegistersToDwarfRegisters(staticBase uint64, regs Registers) *op.DwarfRegisters { + dregs := initDwarfRegistersFromSlice(int(regnum.RISCV64MaxRegNum()), regs, regnum.RISCV64NameToDwarf) + dr := op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, regnum.RISCV64_PC, regnum.RISCV64_SP, regnum.RISCV64_FP, regnum.RISCV64_LR) + dr.SetLoadMoreCallback(loadMoreDwarfRegistersFromSliceFunc(dr, regs, regnum.RISCV64NameToDwarf)) + return dr +} + +func riscv64AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters { + dregs := make([]*op.DwarfRegister, int(regnum.RISCV64_PC+1)) + dregs[regnum.RISCV64_PC] = op.DwarfRegisterFromUint64(pc) + dregs[regnum.RISCV64_SP] = op.DwarfRegisterFromUint64(sp) + dregs[regnum.RISCV64_FP] = op.DwarfRegisterFromUint64(bp) + dregs[regnum.RISCV64_LR] = op.DwarfRegisterFromUint64(lr) + + return *op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, regnum.RISCV64_PC, regnum.RISCV64_SP, regnum.RISCV64_FP, regnum.RISCV64_LR) +} + +func riscv64DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) { + name = regnum.RISCV64ToName(uint64(i)) + + if reg == nil { + return name, false, "" + } + + if strings.HasPrefix(name, "F") { + return name, true, fmt.Sprintf("%#016x", reg.Uint64Val) + } else { + return name, false, fmt.Sprintf("%#016x", reg.Uint64Val) + } +} diff --git a/pkg/proc/riscv64_disasm.go b/pkg/proc/riscv64_disasm.go new file mode 100644 index 0000000000..03f4d5be65 --- /dev/null +++ b/pkg/proc/riscv64_disasm.go @@ -0,0 +1,189 @@ +package proc + +import ( + "fmt" + + "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/dwarf/regnum" + "golang.org/x/arch/riscv64/riscv64asm" +) + +var ( + errType = fmt.Errorf("unknown type") +) + +func riscv64AsmDecode(asmInst *AsmInstruction, mem []byte, regs *op.DwarfRegisters, memrw MemoryReadWriter, bi *BinaryInfo) error { + inst, err := riscv64asm.Decode(mem) + if err != nil { + asmInst.Inst = (*riscv64ArchInst)(nil) + return err + } + + asmInst.Size = inst.Len + asmInst.Bytes = mem[:asmInst.Size] + asmInst.Inst = (*riscv64ArchInst)(&inst) + asmInst.Kind = OtherInstruction + + switch inst.Op { + case riscv64asm.JALR: + rd, _ := inst.Args[0].(riscv64asm.Reg) + rs1 := inst.Args[1].(riscv64asm.RegOffset).OfsReg + if rd == riscv64asm.X1 { + asmInst.Kind = CallInstruction + } else if rd == riscv64asm.X0 && rs1 == riscv64asm.X1 { + asmInst.Kind = RetInstruction + } else { + asmInst.Kind = JmpInstruction + } + + case riscv64asm.JAL: + rd, _ := inst.Args[0].(riscv64asm.Reg) + if rd == riscv64asm.X1 { + asmInst.Kind = CallInstruction + } else { + asmInst.Kind = JmpInstruction + } + + case riscv64asm.BEQ, + riscv64asm.BNE, + riscv64asm.BLT, + riscv64asm.BGE, + riscv64asm.BLTU, + riscv64asm.BGEU: + asmInst.Kind = JmpInstruction + + case riscv64asm.EBREAK: + asmInst.Kind = HardBreakInstruction + + default: + asmInst.Kind = OtherInstruction + } + + asmInst.DestLoc = resolveCallArgRISCV64(&inst, asmInst.Loc.PC, asmInst.AtPC, regs, memrw, bi) + + return nil +} + +func resolveCallArgRISCV64(inst *riscv64asm.Inst, instAddr uint64, currentGoroutine bool, regs *op.DwarfRegisters, mem MemoryReadWriter, bininfo *BinaryInfo) *Location { + var pc uint64 + var err error + + switch inst.Op { + // Format: op rs1, rs2, bimm12 + // Target: bimm12 + case riscv64asm.BEQ, + riscv64asm.BNE, + riscv64asm.BLT, + riscv64asm.BGE, + riscv64asm.BLTU, + riscv64asm.BGEU: + + switch arg := inst.Args[2].(type) { + case riscv64asm.Simm: + pc = uint64(int64(instAddr) + int64(arg.Imm)) + default: + return nil + } + + // Format: op rd, jimm20 + // Target: simm20 + case riscv64asm.JAL: + switch arg := inst.Args[1].(type) { + case riscv64asm.Simm: + pc = uint64(int64(instAddr) + int64(arg.Imm)) + default: + return nil + } + + // Format: op rd, rs1, imm12 + // Target: rj + offs16 + case riscv64asm.JALR: + if !currentGoroutine || regs == nil { + return nil + } + switch arg := inst.Args[1].(type) { + case riscv64asm.RegOffset: + pc, err = bininfo.Arch.getAsmRegister(regs, int(arg.OfsReg)) + if err != nil { + return nil + } + pc = uint64(int64(pc) + int64(arg.Ofs.Imm)) + } + + default: + return nil + } + + file, line, fn := bininfo.PCToLine(pc) + if fn == nil { + return &Location{PC: pc} + } + + return &Location{PC: pc, File: file, Line: line, Fn: fn} +} + +// Possible stacksplit prologues are inserted by stacksplit in +// $GOROOT/src/cmd/internal/obj/riscv/obj.go. +var prologuesRISCV64 []opcodeSeq + +func init() { + var tinyStacksplit = opcodeSeq{uint64(riscv64asm.ADDI)} + var smallStacksplit = opcodeSeq{} + var bigStacksplit = opcodeSeq{uint64(riscv64asm.LUI), + uint64(riscv64asm.ADDIW), + uint64(riscv64asm.BLTU), + uint64(riscv64asm.LUI), + uint64(riscv64asm.ADDIW), + uint64(riscv64asm.ADD)} + + var unixGetG = opcodeSeq{uint64(riscv64asm.LD)} + var tailPrologues = opcodeSeq{uint64(riscv64asm.BLTU), + uint64(riscv64asm.JAL), + uint64(riscv64asm.JAL)} + + prologuesRISCV64 = make([]opcodeSeq, 0, 3) + for _, stacksplit := range []opcodeSeq{tinyStacksplit, smallStacksplit, bigStacksplit} { + prologue := make(opcodeSeq, 0, len(unixGetG)+len(stacksplit)+len(tailPrologues)) + prologue = append(prologue, unixGetG...) + prologue = append(prologue, stacksplit...) + prologue = append(prologue, tailPrologues...) + prologuesRISCV64 = append(prologuesRISCV64, prologue) + } +} + +type riscv64ArchInst riscv64asm.Inst + +func (inst *riscv64ArchInst) Text(flavour AssemblyFlavour, pc uint64, symLookup func(uint64) (string, uint64)) string { + if inst == nil { + return "?" + } + + var text string + + switch flavour { + case GNUFlavour: + text = riscv64asm.GNUSyntax(riscv64asm.Inst(*inst)) + default: + text = riscv64asm.GoSyntax(riscv64asm.Inst(*inst), pc, symLookup, nil) + } + + return text +} + +func (inst *riscv64ArchInst) OpcodeEquals(op uint64) bool { + if inst == nil { + return false + } + + return uint64(inst.Op) == op +} + +var riscv64AsmRegisters = func() map[int]asmRegister { + r := make(map[int]asmRegister) + + for i := riscv64asm.X0; i <= riscv64asm.X31; i++ { + r[int(i)] = asmRegister{regnum.RISCV64_X0 + uint64(i), 0, 0} + } + + return r +}() diff --git a/pkg/proc/stack.go b/pkg/proc/stack.go index c34f44fa32..6af48bd64d 100644 --- a/pkg/proc/stack.go +++ b/pkg/proc/stack.go @@ -299,7 +299,7 @@ func (it *stackIterator) switchToGoroutineStack() { it.pc = it.g.PC it.regs.Reg(it.regs.SPRegNum).Uint64Val = it.g.SP it.regs.AddReg(it.regs.BPRegNum, op.DwarfRegisterFromUint64(it.g.BP)) - if it.bi.Arch.Name == "arm64" || it.bi.Arch.Name == "ppc64le" { + if it.bi.Arch.Name == "arm64" || it.bi.Arch.Name == "ppc64le" || it.bi.Arch.Name == "riscv64" { it.regs.Reg(it.regs.LRRegNum).Uint64Val = it.g.LR } } @@ -564,7 +564,7 @@ func (it *stackIterator) advanceRegs() (callFrameRegs op.DwarfRegisters, ret uin } } - if it.bi.Arch.Name == "arm64" || it.bi.Arch.Name == "ppc64le" { + if it.bi.Arch.Name == "arm64" || it.bi.Arch.Name == "ppc64le" || it.bi.Arch.Name == "riscv64" { if ret == 0 && it.regs.Reg(it.regs.LRRegNum) != nil { ret = it.regs.Reg(it.regs.LRRegNum).Uint64Val } diff --git a/pkg/proc/target_exec.go b/pkg/proc/target_exec.go index 4cc02266e7..7f2f1b1a7c 100644 --- a/pkg/proc/target_exec.go +++ b/pkg/proc/target_exec.go @@ -9,6 +9,7 @@ import ( "go/constant" "go/token" "path/filepath" + "runtime" "strings" "golang.org/x/arch/ppc64/ppc64asm" @@ -1674,7 +1675,9 @@ func (t *Target) handleHardcodedBreakpoints(grp *TargetGroup, trapthread Thread, stepOverBreak(thread, loc.PC) // In linux-arm64, PtraceSingleStep seems cannot step over BRK instruction // (linux-arm64 feature or kernel bug maybe). - if !arch.BreakInstrMovesPC() { + // RISC-V use ebreak as hardcoded breakpoint in Go, however we use c.ebreak + // in delve to support breakpoints in cgo. + if !arch.BreakInstrMovesPC() && runtime.GOARCH != "riscv64" { setPC(thread, loc.PC+uint64(arch.BreakpointSize())) } // Single-step current thread until we exit runtime.breakpoint and diff --git a/pkg/proc/test/support.go b/pkg/proc/test/support.go index f1d2ae64a5..59da6ddc1b 100644 --- a/pkg/proc/test/support.go +++ b/pkg/proc/test/support.go @@ -310,6 +310,9 @@ func MustSupportFunctionCalls(t *testing.T, testBackend string) { if runtime.GOARCH == "386" { t.Skip(fmt.Errorf("%s does not support FunctionCall for now", runtime.GOARCH)) } + if runtime.GOARCH == "riscv64" { + t.Skip(fmt.Errorf("%s does not support FunctionCall for now", runtime.GOARCH)) + } if runtime.GOARCH == "arm64" { if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 19) || runtime.GOOS == "windows" { t.Skip("this version of Go does not support function calls") @@ -382,7 +385,7 @@ func RegabiSupported() bool { // Tracks regabiSupported variable in ParseGOEXPERIMENT internal/buildcfg/exp.go switch { case goversion.VersionAfterOrEqual(runtime.Version(), 1, 18): - return runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "ppc64" + return runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "riscv64" case goversion.VersionAfterOrEqual(runtime.Version(), 1, 17): return runtime.GOARCH == "amd64" && (runtime.GOOS == "android" || runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows") default: diff --git a/service/debugger/debugger_test.go b/service/debugger/debugger_test.go index c493ff9804..a85ca6b19b 100644 --- a/service/debugger/debugger_test.go +++ b/service/debugger/debugger_test.go @@ -49,6 +49,9 @@ func TestDebugger_LaunchInvalidFormat(t *testing.T) { if runtime.GOARCH == "ppc64le" && runtime.GOOS == "linux" { t.Setenv("GOARCH", "amd64") } + if runtime.GOARCH == "riscv64" && runtime.GOOS == "linux" { + t.Setenv("GOARCH", "amd64") + } t.Setenv("GOOS", switchOS[runtime.GOOS]) exepath := filepath.Join(buildtestdir, debugname) if err := gobuild.GoBuild(debugname, []string{buildtestdir}, fmt.Sprintf("-o %s", exepath)); err != nil { diff --git a/service/debugger/debugger_unix_test.go b/service/debugger/debugger_unix_test.go index df31e160d8..5fcb579afa 100644 --- a/service/debugger/debugger_unix_test.go +++ b/service/debugger/debugger_unix_test.go @@ -34,6 +34,9 @@ func TestDebugger_LaunchNoExecutablePerm(t *testing.T) { if runtime.GOARCH == "ppc64le" && runtime.GOOS == "linux" { t.Setenv("GOARCH", "amd64") } + if runtime.GOARCH == "riscv64" && runtime.GOOS == "linux" { + t.Setenv("GOARCH", "amd64") + } t.Setenv("GOOS", switchOS[runtime.GOOS]) exepath := filepath.Join(buildtestdir, debugname) defer os.Remove(exepath) diff --git a/vendor/golang.org/x/arch/riscv64/riscv64asm/arg.go b/vendor/golang.org/x/arch/riscv64/riscv64asm/arg.go new file mode 100644 index 0000000000..7898c27366 --- /dev/null +++ b/vendor/golang.org/x/arch/riscv64/riscv64asm/arg.go @@ -0,0 +1,116 @@ +// Copyright 2024 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 riscv64asm + +// Naming for Go decoder arguments: +// +// - arg_rd: a general purpose register rd encoded in rd[11:7] field +// +// - arg_rs1: a general purpose register rs1 encoded in rs1[19:15] field +// +// - arg_rs2: a general purpose register rs2 encoded in rs2[24:20] field +// +// - arg_rs3: a general purpose register rs3 encoded in rs3[31:27] field +// +// - arg_fd: a floating point register rd encoded in rd[11:7] field +// +// - arg_fs1: a floating point register rs1 encoded in rs1[19:15] field +// +// - arg_fs2: a floating point register rs2 encoded in rs2[24:20] field +// +// - arg_fs3: a floating point register rs3 encoded in rs3[31:27] field +// +// - arg_csr: a control status register encoded in csr[31:20] field +// +// - arg_rs1_mem: source register with offset in load commands +// +// - arg_rs1_store: source register with offset in store commands +// +// - arg_rs1_amo: source register with offset in atomic commands +// +// - arg_pred: predecessor memory ordering information encoded in pred[27:24] field +// For details, please refer to chapter 2.7 of ISA manual volume 1 +// +// - arg_succ: successor memory ordering information encoded in succ[23:20] field +// For details, please refer to chapter 2.7 of ISA manual volume 1 +// +// - arg_zimm: a unsigned immediate encoded in zimm[19:15] field +// +// - arg_imm12: an I-type immediate encoded in imm12[31:20] field +// +// - arg_simm12: a S-type immediate encoded in simm12[31:25|11:7] field +// +// - arg_bimm12: a B-type immediate encoded in bimm12[31:25|11:7] field +// +// - arg_imm20: an U-type immediate encoded in imm20[31:12] field +// +// - arg_jimm20: a J-type immediate encoded in jimm20[31:12] field +// +// - arg_shamt5: a shift amount encoded in shamt5[24:20] field +// +// - arg_shamt6: a shift amount encoded in shamt6[25:20] field +// + +type argType uint16 + +const ( + _ argType = iota + arg_rd + arg_rs1 + arg_rs2 + arg_rs3 + arg_fd + arg_fs1 + arg_fs2 + arg_fs3 + arg_csr + + arg_rs1_amo + arg_rs1_mem + arg_rs1_store + + arg_pred + arg_succ + + arg_zimm + arg_imm12 + arg_simm12 + arg_bimm12 + arg_imm20 + arg_jimm20 + arg_shamt5 + arg_shamt6 + + // RISC-V Compressed Extension Args + arg_rd_p + arg_fd_p + arg_rs1_p + arg_rd_rs1_p + arg_fs2_p + arg_rs2_p + arg_rd_n0 + arg_rs1_n0 + arg_rd_rs1_n0 + arg_c_rs1_n0 + arg_c_rs2_n0 + arg_c_fs2 + arg_c_rs2 + arg_rd_n2 + + arg_c_imm6 + arg_c_nzimm6 + arg_c_nzuimm6 + arg_c_uimm7 + arg_c_uimm8 + arg_c_uimm8sp_s + arg_c_uimm8sp + arg_c_uimm9sp_s + arg_c_uimm9sp + arg_c_bimm9 + arg_c_nzimm10 + arg_c_nzuimm10 + arg_c_imm12 + arg_c_nzimm18 +) diff --git a/vendor/golang.org/x/arch/riscv64/riscv64asm/csr_string.go b/vendor/golang.org/x/arch/riscv64/riscv64asm/csr_string.go new file mode 100644 index 0000000000..addf91aa5b --- /dev/null +++ b/vendor/golang.org/x/arch/riscv64/riscv64asm/csr_string.go @@ -0,0 +1,577 @@ +// Code generated by "stringer -type=CSR"; DO NOT EDIT. + +package riscv64asm + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[USTATUS-0] + _ = x[FFLAGS-1] + _ = x[FRM-2] + _ = x[FCSR-3] + _ = x[UIE-4] + _ = x[UTVEC-5] + _ = x[UTVT-7] + _ = x[VSTART-8] + _ = x[VXSAT-9] + _ = x[VXRM-10] + _ = x[VCSR-15] + _ = x[USCRATCH-64] + _ = x[UEPC-65] + _ = x[UCAUSE-66] + _ = x[UTVAL-67] + _ = x[UIP-68] + _ = x[UNXTI-69] + _ = x[UINTSTATUS-70] + _ = x[USCRATCHCSW-72] + _ = x[USCRATCHCSWL-73] + _ = x[SSTATUS-256] + _ = x[SEDELEG-258] + _ = x[SIDELEG-259] + _ = x[SIE-260] + _ = x[STVEC-261] + _ = x[SCOUNTEREN-262] + _ = x[STVT-263] + _ = x[SSCRATCH-320] + _ = x[SEPC-321] + _ = x[SCAUSE-322] + _ = x[STVAL-323] + _ = x[SIP-324] + _ = x[SNXTI-325] + _ = x[SINTSTATUS-326] + _ = x[SSCRATCHCSW-328] + _ = x[SSCRATCHCSWL-329] + _ = x[SATP-384] + _ = x[VSSTATUS-512] + _ = x[VSIE-516] + _ = x[VSTVEC-517] + _ = x[VSSCRATCH-576] + _ = x[VSEPC-577] + _ = x[VSCAUSE-578] + _ = x[VSTVAL-579] + _ = x[VSIP-580] + _ = x[VSATP-640] + _ = x[MSTATUS-768] + _ = x[MISA-769] + _ = x[MEDELEG-770] + _ = x[MIDELEG-771] + _ = x[MIE-772] + _ = x[MTVEC-773] + _ = x[MCOUNTEREN-774] + _ = x[MTVT-775] + _ = x[MSTATUSH-784] + _ = x[MCOUNTINHIBIT-800] + _ = x[MHPMEVENT3-803] + _ = x[MHPMEVENT4-804] + _ = x[MHPMEVENT5-805] + _ = x[MHPMEVENT6-806] + _ = x[MHPMEVENT7-807] + _ = x[MHPMEVENT8-808] + _ = x[MHPMEVENT9-809] + _ = x[MHPMEVENT10-810] + _ = x[MHPMEVENT11-811] + _ = x[MHPMEVENT12-812] + _ = x[MHPMEVENT13-813] + _ = x[MHPMEVENT14-814] + _ = x[MHPMEVENT15-815] + _ = x[MHPMEVENT16-816] + _ = x[MHPMEVENT17-817] + _ = x[MHPMEVENT18-818] + _ = x[MHPMEVENT19-819] + _ = x[MHPMEVENT20-820] + _ = x[MHPMEVENT21-821] + _ = x[MHPMEVENT22-822] + _ = x[MHPMEVENT23-823] + _ = x[MHPMEVENT24-824] + _ = x[MHPMEVENT25-825] + _ = x[MHPMEVENT26-826] + _ = x[MHPMEVENT27-827] + _ = x[MHPMEVENT28-828] + _ = x[MHPMEVENT29-829] + _ = x[MHPMEVENT30-830] + _ = x[MHPMEVENT31-831] + _ = x[MSCRATCH-832] + _ = x[MEPC-833] + _ = x[MCAUSE-834] + _ = x[MTVAL-835] + _ = x[MIP-836] + _ = x[MNXTI-837] + _ = x[MINTSTATUS-838] + _ = x[MSCRATCHCSW-840] + _ = x[MSCRATCHCSWL-841] + _ = x[MTINST-842] + _ = x[MTVAL2-843] + _ = x[PMPCFG0-928] + _ = x[PMPCFG1-929] + _ = x[PMPCFG2-930] + _ = x[PMPCFG3-931] + _ = x[PMPADDR0-944] + _ = x[PMPADDR1-945] + _ = x[PMPADDR2-946] + _ = x[PMPADDR3-947] + _ = x[PMPADDR4-948] + _ = x[PMPADDR5-949] + _ = x[PMPADDR6-950] + _ = x[PMPADDR7-951] + _ = x[PMPADDR8-952] + _ = x[PMPADDR9-953] + _ = x[PMPADDR10-954] + _ = x[PMPADDR11-955] + _ = x[PMPADDR12-956] + _ = x[PMPADDR13-957] + _ = x[PMPADDR14-958] + _ = x[PMPADDR15-959] + _ = x[HSTATUS-1536] + _ = x[HEDELEG-1538] + _ = x[HIDELEG-1539] + _ = x[HIE-1540] + _ = x[HTIMEDELTA-1541] + _ = x[HCOUNTEREN-1542] + _ = x[HGEIE-1543] + _ = x[HTIMEDELTAH-1557] + _ = x[HTVAL-1603] + _ = x[HIP-1604] + _ = x[HVIP-1605] + _ = x[HTINST-1610] + _ = x[HGATP-1664] + _ = x[TSELECT-1952] + _ = x[TDATA1-1953] + _ = x[TDATA2-1954] + _ = x[TDATA3-1955] + _ = x[TINFO-1956] + _ = x[TCONTROL-1957] + _ = x[MCONTEXT-1960] + _ = x[MNOISE-1961] + _ = x[SCONTEXT-1962] + _ = x[DCSR-1968] + _ = x[DPC-1969] + _ = x[DSCRATCH0-1970] + _ = x[DSCRATCH1-1971] + _ = x[MCYCLE-2816] + _ = x[MINSTRET-2818] + _ = x[MHPMCOUNTER3-2819] + _ = x[MHPMCOUNTER4-2820] + _ = x[MHPMCOUNTER5-2821] + _ = x[MHPMCOUNTER6-2822] + _ = x[MHPMCOUNTER7-2823] + _ = x[MHPMCOUNTER8-2824] + _ = x[MHPMCOUNTER9-2825] + _ = x[MHPMCOUNTER10-2826] + _ = x[MHPMCOUNTER11-2827] + _ = x[MHPMCOUNTER12-2828] + _ = x[MHPMCOUNTER13-2829] + _ = x[MHPMCOUNTER14-2830] + _ = x[MHPMCOUNTER15-2831] + _ = x[MHPMCOUNTER16-2832] + _ = x[MHPMCOUNTER17-2833] + _ = x[MHPMCOUNTER18-2834] + _ = x[MHPMCOUNTER19-2835] + _ = x[MHPMCOUNTER20-2836] + _ = x[MHPMCOUNTER21-2837] + _ = x[MHPMCOUNTER22-2838] + _ = x[MHPMCOUNTER23-2839] + _ = x[MHPMCOUNTER24-2840] + _ = x[MHPMCOUNTER25-2841] + _ = x[MHPMCOUNTER26-2842] + _ = x[MHPMCOUNTER27-2843] + _ = x[MHPMCOUNTER28-2844] + _ = x[MHPMCOUNTER29-2845] + _ = x[MHPMCOUNTER30-2846] + _ = x[MHPMCOUNTER31-2847] + _ = x[MCYCLEH-2944] + _ = x[MINSTRETH-2946] + _ = x[MHPMCOUNTER3H-2947] + _ = x[MHPMCOUNTER4H-2948] + _ = x[MHPMCOUNTER5H-2949] + _ = x[MHPMCOUNTER6H-2950] + _ = x[MHPMCOUNTER7H-2951] + _ = x[MHPMCOUNTER8H-2952] + _ = x[MHPMCOUNTER9H-2953] + _ = x[MHPMCOUNTER10H-2954] + _ = x[MHPMCOUNTER11H-2955] + _ = x[MHPMCOUNTER12H-2956] + _ = x[MHPMCOUNTER13H-2957] + _ = x[MHPMCOUNTER14H-2958] + _ = x[MHPMCOUNTER15H-2959] + _ = x[MHPMCOUNTER16H-2960] + _ = x[MHPMCOUNTER17H-2961] + _ = x[MHPMCOUNTER18H-2962] + _ = x[MHPMCOUNTER19H-2963] + _ = x[MHPMCOUNTER20H-2964] + _ = x[MHPMCOUNTER21H-2965] + _ = x[MHPMCOUNTER22H-2966] + _ = x[MHPMCOUNTER23H-2967] + _ = x[MHPMCOUNTER24H-2968] + _ = x[MHPMCOUNTER25H-2969] + _ = x[MHPMCOUNTER26H-2970] + _ = x[MHPMCOUNTER27H-2971] + _ = x[MHPMCOUNTER28H-2972] + _ = x[MHPMCOUNTER29H-2973] + _ = x[MHPMCOUNTER30H-2974] + _ = x[MHPMCOUNTER31H-2975] + _ = x[CYCLE-3072] + _ = x[TIME-3073] + _ = x[INSTRET-3074] + _ = x[HPMCOUNTER3-3075] + _ = x[HPMCOUNTER4-3076] + _ = x[HPMCOUNTER5-3077] + _ = x[HPMCOUNTER6-3078] + _ = x[HPMCOUNTER7-3079] + _ = x[HPMCOUNTER8-3080] + _ = x[HPMCOUNTER9-3081] + _ = x[HPMCOUNTER10-3082] + _ = x[HPMCOUNTER11-3083] + _ = x[HPMCOUNTER12-3084] + _ = x[HPMCOUNTER13-3085] + _ = x[HPMCOUNTER14-3086] + _ = x[HPMCOUNTER15-3087] + _ = x[HPMCOUNTER16-3088] + _ = x[HPMCOUNTER17-3089] + _ = x[HPMCOUNTER18-3090] + _ = x[HPMCOUNTER19-3091] + _ = x[HPMCOUNTER20-3092] + _ = x[HPMCOUNTER21-3093] + _ = x[HPMCOUNTER22-3094] + _ = x[HPMCOUNTER23-3095] + _ = x[HPMCOUNTER24-3096] + _ = x[HPMCOUNTER25-3097] + _ = x[HPMCOUNTER26-3098] + _ = x[HPMCOUNTER27-3099] + _ = x[HPMCOUNTER28-3100] + _ = x[HPMCOUNTER29-3101] + _ = x[HPMCOUNTER30-3102] + _ = x[HPMCOUNTER31-3103] + _ = x[VL-3104] + _ = x[VTYPE-3105] + _ = x[VLENB-3106] + _ = x[CYCLEH-3200] + _ = x[TIMEH-3201] + _ = x[INSTRETH-3202] + _ = x[HPMCOUNTER3H-3203] + _ = x[HPMCOUNTER4H-3204] + _ = x[HPMCOUNTER5H-3205] + _ = x[HPMCOUNTER6H-3206] + _ = x[HPMCOUNTER7H-3207] + _ = x[HPMCOUNTER8H-3208] + _ = x[HPMCOUNTER9H-3209] + _ = x[HPMCOUNTER10H-3210] + _ = x[HPMCOUNTER11H-3211] + _ = x[HPMCOUNTER12H-3212] + _ = x[HPMCOUNTER13H-3213] + _ = x[HPMCOUNTER14H-3214] + _ = x[HPMCOUNTER15H-3215] + _ = x[HPMCOUNTER16H-3216] + _ = x[HPMCOUNTER17H-3217] + _ = x[HPMCOUNTER18H-3218] + _ = x[HPMCOUNTER19H-3219] + _ = x[HPMCOUNTER20H-3220] + _ = x[HPMCOUNTER21H-3221] + _ = x[HPMCOUNTER22H-3222] + _ = x[HPMCOUNTER23H-3223] + _ = x[HPMCOUNTER24H-3224] + _ = x[HPMCOUNTER25H-3225] + _ = x[HPMCOUNTER26H-3226] + _ = x[HPMCOUNTER27H-3227] + _ = x[HPMCOUNTER28H-3228] + _ = x[HPMCOUNTER29H-3229] + _ = x[HPMCOUNTER30H-3230] + _ = x[HPMCOUNTER31H-3231] + _ = x[HGEIP-3602] + _ = x[MVENDORID-3857] + _ = x[MARCHID-3858] + _ = x[MIMPID-3859] + _ = x[MHARTID-3860] + _ = x[MENTROPY-3861] +} + +const _CSR_name = "USTATUSFFLAGSFRMFCSRUIEUTVECUTVTVSTARTVXSATVXRMVCSRUSCRATCHUEPCUCAUSEUTVALUIPUNXTIUINTSTATUSUSCRATCHCSWUSCRATCHCSWLSSTATUSSEDELEGSIDELEGSIESTVECSCOUNTERENSTVTSSCRATCHSEPCSCAUSESTVALSIPSNXTISINTSTATUSSSCRATCHCSWSSCRATCHCSWLSATPVSSTATUSVSIEVSTVECVSSCRATCHVSEPCVSCAUSEVSTVALVSIPVSATPMSTATUSMISAMEDELEGMIDELEGMIEMTVECMCOUNTERENMTVTMSTATUSHMCOUNTINHIBITMHPMEVENT3MHPMEVENT4MHPMEVENT5MHPMEVENT6MHPMEVENT7MHPMEVENT8MHPMEVENT9MHPMEVENT10MHPMEVENT11MHPMEVENT12MHPMEVENT13MHPMEVENT14MHPMEVENT15MHPMEVENT16MHPMEVENT17MHPMEVENT18MHPMEVENT19MHPMEVENT20MHPMEVENT21MHPMEVENT22MHPMEVENT23MHPMEVENT24MHPMEVENT25MHPMEVENT26MHPMEVENT27MHPMEVENT28MHPMEVENT29MHPMEVENT30MHPMEVENT31MSCRATCHMEPCMCAUSEMTVALMIPMNXTIMINTSTATUSMSCRATCHCSWMSCRATCHCSWLMTINSTMTVAL2PMPCFG0PMPCFG1PMPCFG2PMPCFG3PMPADDR0PMPADDR1PMPADDR2PMPADDR3PMPADDR4PMPADDR5PMPADDR6PMPADDR7PMPADDR8PMPADDR9PMPADDR10PMPADDR11PMPADDR12PMPADDR13PMPADDR14PMPADDR15HSTATUSHEDELEGHIDELEGHIEHTIMEDELTAHCOUNTERENHGEIEHTIMEDELTAHHTVALHIPHVIPHTINSTHGATPTSELECTTDATA1TDATA2TDATA3TINFOTCONTROLMCONTEXTMNOISESCONTEXTDCSRDPCDSCRATCH0DSCRATCH1MCYCLEMINSTRETMHPMCOUNTER3MHPMCOUNTER4MHPMCOUNTER5MHPMCOUNTER6MHPMCOUNTER7MHPMCOUNTER8MHPMCOUNTER9MHPMCOUNTER10MHPMCOUNTER11MHPMCOUNTER12MHPMCOUNTER13MHPMCOUNTER14MHPMCOUNTER15MHPMCOUNTER16MHPMCOUNTER17MHPMCOUNTER18MHPMCOUNTER19MHPMCOUNTER20MHPMCOUNTER21MHPMCOUNTER22MHPMCOUNTER23MHPMCOUNTER24MHPMCOUNTER25MHPMCOUNTER26MHPMCOUNTER27MHPMCOUNTER28MHPMCOUNTER29MHPMCOUNTER30MHPMCOUNTER31MCYCLEHMINSTRETHMHPMCOUNTER3HMHPMCOUNTER4HMHPMCOUNTER5HMHPMCOUNTER6HMHPMCOUNTER7HMHPMCOUNTER8HMHPMCOUNTER9HMHPMCOUNTER10HMHPMCOUNTER11HMHPMCOUNTER12HMHPMCOUNTER13HMHPMCOUNTER14HMHPMCOUNTER15HMHPMCOUNTER16HMHPMCOUNTER17HMHPMCOUNTER18HMHPMCOUNTER19HMHPMCOUNTER20HMHPMCOUNTER21HMHPMCOUNTER22HMHPMCOUNTER23HMHPMCOUNTER24HMHPMCOUNTER25HMHPMCOUNTER26HMHPMCOUNTER27HMHPMCOUNTER28HMHPMCOUNTER29HMHPMCOUNTER30HMHPMCOUNTER31HCYCLETIMEINSTRETHPMCOUNTER3HPMCOUNTER4HPMCOUNTER5HPMCOUNTER6HPMCOUNTER7HPMCOUNTER8HPMCOUNTER9HPMCOUNTER10HPMCOUNTER11HPMCOUNTER12HPMCOUNTER13HPMCOUNTER14HPMCOUNTER15HPMCOUNTER16HPMCOUNTER17HPMCOUNTER18HPMCOUNTER19HPMCOUNTER20HPMCOUNTER21HPMCOUNTER22HPMCOUNTER23HPMCOUNTER24HPMCOUNTER25HPMCOUNTER26HPMCOUNTER27HPMCOUNTER28HPMCOUNTER29HPMCOUNTER30HPMCOUNTER31VLVTYPEVLENBCYCLEHTIMEHINSTRETHHPMCOUNTER3HHPMCOUNTER4HHPMCOUNTER5HHPMCOUNTER6HHPMCOUNTER7HHPMCOUNTER8HHPMCOUNTER9HHPMCOUNTER10HHPMCOUNTER11HHPMCOUNTER12HHPMCOUNTER13HHPMCOUNTER14HHPMCOUNTER15HHPMCOUNTER16HHPMCOUNTER17HHPMCOUNTER18HHPMCOUNTER19HHPMCOUNTER20HHPMCOUNTER21HHPMCOUNTER22HHPMCOUNTER23HHPMCOUNTER24HHPMCOUNTER25HHPMCOUNTER26HHPMCOUNTER27HHPMCOUNTER28HHPMCOUNTER29HHPMCOUNTER30HHPMCOUNTER31HHGEIPMVENDORIDMARCHIDMIMPIDMHARTIDMENTROPY" + +var _CSR_map = map[CSR]string{ + 0: _CSR_name[0:7], + 1: _CSR_name[7:13], + 2: _CSR_name[13:16], + 3: _CSR_name[16:20], + 4: _CSR_name[20:23], + 5: _CSR_name[23:28], + 7: _CSR_name[28:32], + 8: _CSR_name[32:38], + 9: _CSR_name[38:43], + 10: _CSR_name[43:47], + 15: _CSR_name[47:51], + 64: _CSR_name[51:59], + 65: _CSR_name[59:63], + 66: _CSR_name[63:69], + 67: _CSR_name[69:74], + 68: _CSR_name[74:77], + 69: _CSR_name[77:82], + 70: _CSR_name[82:92], + 72: _CSR_name[92:103], + 73: _CSR_name[103:115], + 256: _CSR_name[115:122], + 258: _CSR_name[122:129], + 259: _CSR_name[129:136], + 260: _CSR_name[136:139], + 261: _CSR_name[139:144], + 262: _CSR_name[144:154], + 263: _CSR_name[154:158], + 320: _CSR_name[158:166], + 321: _CSR_name[166:170], + 322: _CSR_name[170:176], + 323: _CSR_name[176:181], + 324: _CSR_name[181:184], + 325: _CSR_name[184:189], + 326: _CSR_name[189:199], + 328: _CSR_name[199:210], + 329: _CSR_name[210:222], + 384: _CSR_name[222:226], + 512: _CSR_name[226:234], + 516: _CSR_name[234:238], + 517: _CSR_name[238:244], + 576: _CSR_name[244:253], + 577: _CSR_name[253:258], + 578: _CSR_name[258:265], + 579: _CSR_name[265:271], + 580: _CSR_name[271:275], + 640: _CSR_name[275:280], + 768: _CSR_name[280:287], + 769: _CSR_name[287:291], + 770: _CSR_name[291:298], + 771: _CSR_name[298:305], + 772: _CSR_name[305:308], + 773: _CSR_name[308:313], + 774: _CSR_name[313:323], + 775: _CSR_name[323:327], + 784: _CSR_name[327:335], + 800: _CSR_name[335:348], + 803: _CSR_name[348:358], + 804: _CSR_name[358:368], + 805: _CSR_name[368:378], + 806: _CSR_name[378:388], + 807: _CSR_name[388:398], + 808: _CSR_name[398:408], + 809: _CSR_name[408:418], + 810: _CSR_name[418:429], + 811: _CSR_name[429:440], + 812: _CSR_name[440:451], + 813: _CSR_name[451:462], + 814: _CSR_name[462:473], + 815: _CSR_name[473:484], + 816: _CSR_name[484:495], + 817: _CSR_name[495:506], + 818: _CSR_name[506:517], + 819: _CSR_name[517:528], + 820: _CSR_name[528:539], + 821: _CSR_name[539:550], + 822: _CSR_name[550:561], + 823: _CSR_name[561:572], + 824: _CSR_name[572:583], + 825: _CSR_name[583:594], + 826: _CSR_name[594:605], + 827: _CSR_name[605:616], + 828: _CSR_name[616:627], + 829: _CSR_name[627:638], + 830: _CSR_name[638:649], + 831: _CSR_name[649:660], + 832: _CSR_name[660:668], + 833: _CSR_name[668:672], + 834: _CSR_name[672:678], + 835: _CSR_name[678:683], + 836: _CSR_name[683:686], + 837: _CSR_name[686:691], + 838: _CSR_name[691:701], + 840: _CSR_name[701:712], + 841: _CSR_name[712:724], + 842: _CSR_name[724:730], + 843: _CSR_name[730:736], + 928: _CSR_name[736:743], + 929: _CSR_name[743:750], + 930: _CSR_name[750:757], + 931: _CSR_name[757:764], + 944: _CSR_name[764:772], + 945: _CSR_name[772:780], + 946: _CSR_name[780:788], + 947: _CSR_name[788:796], + 948: _CSR_name[796:804], + 949: _CSR_name[804:812], + 950: _CSR_name[812:820], + 951: _CSR_name[820:828], + 952: _CSR_name[828:836], + 953: _CSR_name[836:844], + 954: _CSR_name[844:853], + 955: _CSR_name[853:862], + 956: _CSR_name[862:871], + 957: _CSR_name[871:880], + 958: _CSR_name[880:889], + 959: _CSR_name[889:898], + 1536: _CSR_name[898:905], + 1538: _CSR_name[905:912], + 1539: _CSR_name[912:919], + 1540: _CSR_name[919:922], + 1541: _CSR_name[922:932], + 1542: _CSR_name[932:942], + 1543: _CSR_name[942:947], + 1557: _CSR_name[947:958], + 1603: _CSR_name[958:963], + 1604: _CSR_name[963:966], + 1605: _CSR_name[966:970], + 1610: _CSR_name[970:976], + 1664: _CSR_name[976:981], + 1952: _CSR_name[981:988], + 1953: _CSR_name[988:994], + 1954: _CSR_name[994:1000], + 1955: _CSR_name[1000:1006], + 1956: _CSR_name[1006:1011], + 1957: _CSR_name[1011:1019], + 1960: _CSR_name[1019:1027], + 1961: _CSR_name[1027:1033], + 1962: _CSR_name[1033:1041], + 1968: _CSR_name[1041:1045], + 1969: _CSR_name[1045:1048], + 1970: _CSR_name[1048:1057], + 1971: _CSR_name[1057:1066], + 2816: _CSR_name[1066:1072], + 2818: _CSR_name[1072:1080], + 2819: _CSR_name[1080:1092], + 2820: _CSR_name[1092:1104], + 2821: _CSR_name[1104:1116], + 2822: _CSR_name[1116:1128], + 2823: _CSR_name[1128:1140], + 2824: _CSR_name[1140:1152], + 2825: _CSR_name[1152:1164], + 2826: _CSR_name[1164:1177], + 2827: _CSR_name[1177:1190], + 2828: _CSR_name[1190:1203], + 2829: _CSR_name[1203:1216], + 2830: _CSR_name[1216:1229], + 2831: _CSR_name[1229:1242], + 2832: _CSR_name[1242:1255], + 2833: _CSR_name[1255:1268], + 2834: _CSR_name[1268:1281], + 2835: _CSR_name[1281:1294], + 2836: _CSR_name[1294:1307], + 2837: _CSR_name[1307:1320], + 2838: _CSR_name[1320:1333], + 2839: _CSR_name[1333:1346], + 2840: _CSR_name[1346:1359], + 2841: _CSR_name[1359:1372], + 2842: _CSR_name[1372:1385], + 2843: _CSR_name[1385:1398], + 2844: _CSR_name[1398:1411], + 2845: _CSR_name[1411:1424], + 2846: _CSR_name[1424:1437], + 2847: _CSR_name[1437:1450], + 2944: _CSR_name[1450:1457], + 2946: _CSR_name[1457:1466], + 2947: _CSR_name[1466:1479], + 2948: _CSR_name[1479:1492], + 2949: _CSR_name[1492:1505], + 2950: _CSR_name[1505:1518], + 2951: _CSR_name[1518:1531], + 2952: _CSR_name[1531:1544], + 2953: _CSR_name[1544:1557], + 2954: _CSR_name[1557:1571], + 2955: _CSR_name[1571:1585], + 2956: _CSR_name[1585:1599], + 2957: _CSR_name[1599:1613], + 2958: _CSR_name[1613:1627], + 2959: _CSR_name[1627:1641], + 2960: _CSR_name[1641:1655], + 2961: _CSR_name[1655:1669], + 2962: _CSR_name[1669:1683], + 2963: _CSR_name[1683:1697], + 2964: _CSR_name[1697:1711], + 2965: _CSR_name[1711:1725], + 2966: _CSR_name[1725:1739], + 2967: _CSR_name[1739:1753], + 2968: _CSR_name[1753:1767], + 2969: _CSR_name[1767:1781], + 2970: _CSR_name[1781:1795], + 2971: _CSR_name[1795:1809], + 2972: _CSR_name[1809:1823], + 2973: _CSR_name[1823:1837], + 2974: _CSR_name[1837:1851], + 2975: _CSR_name[1851:1865], + 3072: _CSR_name[1865:1870], + 3073: _CSR_name[1870:1874], + 3074: _CSR_name[1874:1881], + 3075: _CSR_name[1881:1892], + 3076: _CSR_name[1892:1903], + 3077: _CSR_name[1903:1914], + 3078: _CSR_name[1914:1925], + 3079: _CSR_name[1925:1936], + 3080: _CSR_name[1936:1947], + 3081: _CSR_name[1947:1958], + 3082: _CSR_name[1958:1970], + 3083: _CSR_name[1970:1982], + 3084: _CSR_name[1982:1994], + 3085: _CSR_name[1994:2006], + 3086: _CSR_name[2006:2018], + 3087: _CSR_name[2018:2030], + 3088: _CSR_name[2030:2042], + 3089: _CSR_name[2042:2054], + 3090: _CSR_name[2054:2066], + 3091: _CSR_name[2066:2078], + 3092: _CSR_name[2078:2090], + 3093: _CSR_name[2090:2102], + 3094: _CSR_name[2102:2114], + 3095: _CSR_name[2114:2126], + 3096: _CSR_name[2126:2138], + 3097: _CSR_name[2138:2150], + 3098: _CSR_name[2150:2162], + 3099: _CSR_name[2162:2174], + 3100: _CSR_name[2174:2186], + 3101: _CSR_name[2186:2198], + 3102: _CSR_name[2198:2210], + 3103: _CSR_name[2210:2222], + 3104: _CSR_name[2222:2224], + 3105: _CSR_name[2224:2229], + 3106: _CSR_name[2229:2234], + 3200: _CSR_name[2234:2240], + 3201: _CSR_name[2240:2245], + 3202: _CSR_name[2245:2253], + 3203: _CSR_name[2253:2265], + 3204: _CSR_name[2265:2277], + 3205: _CSR_name[2277:2289], + 3206: _CSR_name[2289:2301], + 3207: _CSR_name[2301:2313], + 3208: _CSR_name[2313:2325], + 3209: _CSR_name[2325:2337], + 3210: _CSR_name[2337:2350], + 3211: _CSR_name[2350:2363], + 3212: _CSR_name[2363:2376], + 3213: _CSR_name[2376:2389], + 3214: _CSR_name[2389:2402], + 3215: _CSR_name[2402:2415], + 3216: _CSR_name[2415:2428], + 3217: _CSR_name[2428:2441], + 3218: _CSR_name[2441:2454], + 3219: _CSR_name[2454:2467], + 3220: _CSR_name[2467:2480], + 3221: _CSR_name[2480:2493], + 3222: _CSR_name[2493:2506], + 3223: _CSR_name[2506:2519], + 3224: _CSR_name[2519:2532], + 3225: _CSR_name[2532:2545], + 3226: _CSR_name[2545:2558], + 3227: _CSR_name[2558:2571], + 3228: _CSR_name[2571:2584], + 3229: _CSR_name[2584:2597], + 3230: _CSR_name[2597:2610], + 3231: _CSR_name[2610:2623], + 3602: _CSR_name[2623:2628], + 3857: _CSR_name[2628:2637], + 3858: _CSR_name[2637:2644], + 3859: _CSR_name[2644:2650], + 3860: _CSR_name[2650:2657], + 3861: _CSR_name[2657:2665], +} + +func (i CSR) String() string { + if str, ok := _CSR_map[i]; ok { + return str + } + return "CSR(" + strconv.FormatInt(int64(i), 10) + ")" +} diff --git a/vendor/golang.org/x/arch/riscv64/riscv64asm/decode.go b/vendor/golang.org/x/arch/riscv64/riscv64asm/decode.go new file mode 100644 index 0000000000..d78fef9e39 --- /dev/null +++ b/vendor/golang.org/x/arch/riscv64/riscv64asm/decode.go @@ -0,0 +1,550 @@ +// Copyright 2024 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 riscv64asm + +import ( + "encoding/binary" + "errors" +) + +type argTypeList [6]argType + +// An instFormat describes the format of an instruction encoding. +type instFormat struct { + mask uint32 + value uint32 + op Op + // args describe how to decode the instruction arguments. + // args is stored as a fixed-size array. + // if there are fewer than len(args) arguments, args[i] == 0 marks + // the end of the argument list. + args argTypeList +} + +var ( + errShort = errors.New("truncated instruction") + errUnknown = errors.New("unknown instruction") +) + +var decoderCover []bool + +func init() { + decoderCover = make([]bool, len(instFormats)) +} + +// Decode decodes the 4 bytes in src as a single instruction. +func Decode(src []byte) (Inst, error) { + length := len(src) + if length < 2 { + return Inst{}, errShort + } + + var x uint32 + // Non-RVC instructions always starts with 0x11 + // So check whether src[0] & 3 == 3 + if src[0]&3 == 3 { + if length < 4 { + return Inst{}, errShort + } + length = 4 + x = binary.LittleEndian.Uint32(src) + } else { + length = 2 + x = uint32(binary.LittleEndian.Uint16(src)) + } + +Search: + for i, f := range instFormats { + if (x & f.mask) != f.value { + continue + } + + // Decode args. + var args Args + for j, aop := range f.args { + if aop == 0 { + break + } + arg := decodeArg(aop, x, i) + if arg == nil && f.op != C_NOP { + // Cannot decode argument. + continue Search + } + args[j] = arg + } + + if length == 2 { + args = convertCompressedIns(&f, args) + } + + decoderCover[i] = true + inst := Inst{ + Op: f.op, + Args: args, + Enc: x, + Len: length, + } + return inst, nil + } + return Inst{}, errUnknown +} + +// decodeArg decodes the arg described by aop from the instruction bits x. +// It returns nil if x cannot be decoded according to aop. +func decodeArg(aop argType, x uint32, index int) Arg { + switch aop { + case arg_rd: + return X0 + Reg((x>>7)&((1<<5)-1)) + + case arg_rs1: + return X0 + Reg((x>>15)&((1<<5)-1)) + + case arg_rs2: + return X0 + Reg((x>>20)&((1<<5)-1)) + + case arg_rs3: + return X0 + Reg((x>>27)&((1<<5)-1)) + + case arg_fd: + return F0 + Reg((x>>7)&((1<<5)-1)) + + case arg_fs1: + return F0 + Reg((x>>15)&((1<<5)-1)) + + case arg_fs2: + return F0 + Reg((x>>20)&((1<<5)-1)) + + case arg_fs3: + return F0 + Reg((x>>27)&((1<<5)-1)) + + case arg_rs1_amo: + return AmoReg{X0 + Reg((x>>15)&((1<<5)-1))} + + case arg_rs1_mem: + imm := x >> 20 + // Sign-extend + if imm>>uint32(12-1) == 1 { + imm |= 0xfffff << 12 + } + return RegOffset{X0 + Reg((x>>15)&((1<<5)-1)), Simm{int32(imm), true, 12}} + + case arg_rs1_store: + imm := (x<<20)>>27 | (x>>25)<<5 + // Sign-extend + if imm>>uint32(12-1) == 1 { + imm |= 0xfffff << 12 + } + return RegOffset{X0 + Reg((x>>15)&((1<<5)-1)), Simm{int32(imm), true, 12}} + + case arg_pred: + imm := x << 4 >> 28 + return MemOrder(uint8(imm)) + + case arg_succ: + imm := x << 8 >> 28 + return MemOrder(uint8(imm)) + + case arg_csr: + imm := x >> 20 + return CSR(imm) + + case arg_zimm: + imm := x << 12 >> 27 + return Uimm{imm, true} + + case arg_shamt5: + imm := x << 7 >> 27 + return Uimm{imm, false} + + case arg_shamt6: + imm := x << 6 >> 26 + return Uimm{imm, false} + + case arg_imm12: + imm := x >> 20 + // Sign-extend + if imm>>uint32(12-1) == 1 { + imm |= 0xfffff << 12 + } + return Simm{int32(imm), true, 12} + + case arg_imm20: + imm := x >> 12 + return Uimm{imm, false} + + case arg_jimm20: + imm := (x>>31)<<20 | (x<<1)>>22<<1 | (x<<11)>>31<<11 | (x<<12)>>24<<12 + // Sign-extend + if imm>>uint32(21-1) == 1 { + imm |= 0x7ff << 21 + } + return Simm{int32(imm), true, 21} + + case arg_simm12: + imm := (x<<20)>>27 | (x>>25)<<5 + // Sign-extend + if imm>>uint32(12-1) == 1 { + imm |= 0xfffff << 12 + } + return Simm{int32(imm), true, 12} + + case arg_bimm12: + imm := (x<<20)>>28<<1 | (x<<1)>>26<<5 | (x<<24)>>31<<11 | (x>>31)<<12 + // Sign-extend + if imm>>uint32(13-1) == 1 { + imm |= 0x7ffff << 13 + } + return Simm{int32(imm), true, 13} + + case arg_rd_p, arg_rs2_p: + return X8 + Reg((x>>2)&((1<<3)-1)) + + case arg_fd_p, arg_fs2_p: + return F8 + Reg((x>>2)&((1<<3)-1)) + + case arg_rs1_p, arg_rd_rs1_p: + return X8 + Reg((x>>7)&((1<<3)-1)) + + case arg_rd_n0, arg_rs1_n0, arg_rd_rs1_n0, arg_c_rs1_n0: + if X0+Reg((x>>7)&((1<<5)-1)) == X0 { + return nil + } + return X0 + Reg((x>>7)&((1<<5)-1)) + + case arg_c_rs2_n0: + if X0+Reg((x>>2)&((1<<5)-1)) == X0 { + return nil + } + return X0 + Reg((x>>2)&((1<<5)-1)) + + case arg_c_fs2: + return F0 + Reg((x>>2)&((1<<5)-1)) + + case arg_c_rs2: + return X0 + Reg((x>>2)&((1<<5)-1)) + + case arg_rd_n2: + if X0+Reg((x>>7)&((1<<5)-1)) == X0 || X0+Reg((x>>7)&((1<<5)-1)) == X2 { + return nil + } + return X0 + Reg((x>>7)&((1<<5)-1)) + + case arg_c_imm6: + imm := (x<<25)>>27 | (x<<19)>>31<<5 + // Sign-extend + if imm>>uint32(6-1) == 1 { + imm |= 0x3ffffff << 6 + } + return Simm{int32(imm), true, 6} + + case arg_c_nzimm6: + imm := (x<<25)>>27 | (x<<19)>>31<<5 + // Sign-extend + if imm>>uint32(6-1) == 1 { + imm |= 0x3ffffff << 6 + } + if int32(imm) == 0 { + return nil + } + return Simm{int32(imm), true, 6} + + case arg_c_nzuimm6: + imm := (x<<25)>>27 | (x<<19)>>31<<5 + if int32(imm) == 0 { + return nil + } + return Uimm{imm, false} + + case arg_c_uimm7: + imm := (x<<26)>>31<<6 | (x<<25)>>31<<2 | (x<<19)>>29<<3 + return Uimm{imm, false} + + case arg_c_uimm8: + imm := (x<<25)>>30<<6 | (x<<19)>>29<<3 + return Uimm{imm, false} + + case arg_c_uimm8sp_s: + imm := (x<<23)>>30<<6 | (x<<19)>>28<<2 + return Uimm{imm, false} + + case arg_c_uimm8sp: + imm := (x<<25)>>29<<2 | (x<<19)>>31<<5 | (x<<28)>>30<<6 + return Uimm{imm, false} + + case arg_c_uimm9sp_s: + imm := (x<<22)>>29<<6 | (x<<19)>>29<<3 + return Uimm{imm, false} + + case arg_c_uimm9sp: + imm := (x<<25)>>30<<3 | (x<<19)>>31<<5 | (x<<27)>>29<<6 + return Uimm{imm, false} + + case arg_c_bimm9: + imm := (x<<29)>>31<<5 | (x<<27)>>30<<1 | (x<<25)>>30<<6 | (x<<19)>>31<<8 | (x<<20)>>30<<3 + // Sign-extend + if imm>>uint32(9-1) == 1 { + imm |= 0x7fffff << 9 + } + return Simm{int32(imm), true, 9} + + case arg_c_nzimm10: + imm := (x<<29)>>31<<5 | (x<<27)>>30<<7 | (x<<26)>>31<<6 | (x<<25)>>31<<4 | (x<<19)>>31<<9 + // Sign-extend + if imm>>uint32(10-1) == 1 { + imm |= 0x3fffff << 10 + } + if int32(imm) == 0 { + return nil + } + return Simm{int32(imm), true, 10} + + case arg_c_nzuimm10: + imm := (x<<26)>>31<<3 | (x<<25)>>31<<2 | (x<<21)>>28<<6 | (x<<19)>>30<<4 + if int32(imm) == 0 { + return nil + } + return Uimm{imm, false} + + case arg_c_imm12: + imm := (x<<29)>>31<<5 | (x<<26)>>28<<1 | (x<<25)>>31<<7 | (x<<24)>>31<<6 | (x<<23)>>31<<10 | (x<<21)>>30<<8 | (x<<20)>>31<<4 | (x<<19)>>31<<11 + // Sign-extend + if imm>>uint32(12-1) == 1 { + imm |= 0xfffff << 12 + } + return Simm{int32(imm), true, 12} + + case arg_c_nzimm18: + imm := (x<<25)>>27<<12 | (x<<19)>>31<<17 + // Sign-extend + if imm>>uint32(18-1) == 1 { + imm |= 0x3fff << 18 + } + if int32(imm) == 0 { + return nil + } + return Simm{int32(imm), true, 18} + + default: + return nil + } +} + +// convertCompressedIns rewrites the RVC Instruction to regular Instructions +func convertCompressedIns(f *instFormat, args Args) Args { + var newargs Args + switch f.op { + case C_ADDI4SPN: + f.op = ADDI + newargs[0] = args[0] + newargs[1] = Reg(X2) + newargs[2] = Simm{int32(args[1].(Uimm).Imm), true, 12} + + case C_LW: + f.op = LW + newargs[0] = args[0] + newargs[1] = RegOffset{args[1].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}} + + case C_SW: + f.op = SW + newargs[0] = args[1] + newargs[1] = RegOffset{args[0].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}} + + case C_NOP: + f.op = ADDI + newargs[0] = X0 + newargs[1] = X0 + newargs[2] = Simm{0, true, 12} + + case C_ADDI: + f.op = ADDI + newargs[0] = args[0] + newargs[1] = args[0] + newargs[2] = Simm{args[1].(Simm).Imm, true, 12} + + case C_LI: + f.op = ADDI + newargs[0] = args[0] + newargs[1] = Reg(X0) + newargs[2] = Simm{args[1].(Simm).Imm, true, 12} + + case C_ADDI16SP: + f.op = ADDI + newargs[0] = Reg(X2) + newargs[1] = Reg(X2) + newargs[2] = Simm{args[0].(Simm).Imm, true, 12} + + case C_LUI: + f.op = LUI + newargs[0] = args[0] + newargs[1] = Uimm{uint32(args[1].(Simm).Imm >> 12), false} + + case C_ANDI: + f.op = ANDI + newargs[0] = args[0] + newargs[1] = args[0] + newargs[2] = Simm{args[1].(Simm).Imm, true, 12} + + case C_SUB: + f.op = SUB + newargs[0] = args[0] + newargs[1] = args[0] + newargs[2] = args[1] + + case C_XOR: + f.op = XOR + newargs[0] = args[0] + newargs[1] = args[0] + newargs[2] = args[1] + + case C_OR: + f.op = OR + newargs[0] = args[0] + newargs[1] = args[0] + newargs[2] = args[1] + + case C_AND: + f.op = AND + newargs[0] = args[0] + newargs[1] = args[0] + newargs[2] = args[1] + + case C_J: + f.op = JAL + newargs[0] = Reg(X0) + newargs[1] = Simm{args[0].(Simm).Imm, true, 21} + + case C_BEQZ: + f.op = BEQ + newargs[0] = args[0] + newargs[1] = Reg(X0) + newargs[2] = Simm{args[1].(Simm).Imm, true, 13} + + case C_BNEZ: + f.op = BNE + newargs[0] = args[0] + newargs[1] = Reg(X0) + newargs[2] = Simm{args[1].(Simm).Imm, true, 13} + + case C_LWSP: + f.op = LW + newargs[0] = args[0] + newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}} + + case C_JR: + f.op = JALR + newargs[0] = Reg(X0) + newargs[1] = RegOffset{args[0].(Reg), Simm{0, true, 12}} + + case C_MV: + f.op = ADD + newargs[0] = args[0] + newargs[1] = Reg(X0) + newargs[2] = args[1] + + case C_EBREAK: + f.op = EBREAK + + case C_JALR: + f.op = JALR + newargs[0] = Reg(X1) + newargs[1] = RegOffset{args[0].(Reg), Simm{0, true, 12}} + + case C_ADD: + f.op = ADD + newargs[0] = args[0] + newargs[1] = args[0] + newargs[2] = args[1] + + case C_SWSP: + f.op = SW + newargs[0] = args[0] + newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}} + + // riscv64 compressed instructions + case C_LD: + f.op = LD + newargs[0] = args[0] + newargs[1] = RegOffset{args[1].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}} + + case C_SD: + f.op = SD + newargs[0] = args[1] + newargs[1] = RegOffset{args[0].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}} + + case C_ADDIW: + f.op = ADDIW + newargs[0] = args[0] + newargs[1] = args[0] + newargs[2] = Simm{args[1].(Simm).Imm, true, 12} + + case C_SRLI: + f.op = SRLI + newargs[0] = args[0] + newargs[1] = args[0] + newargs[2] = args[1] + + case C_SRAI: + f.op = SRAI + newargs[0] = args[0] + newargs[1] = args[0] + newargs[2] = args[1] + + case C_SUBW: + f.op = SUBW + newargs[0] = args[0] + newargs[1] = args[0] + newargs[2] = args[1] + + case C_ADDW: + f.op = ADDW + newargs[0] = args[0] + newargs[1] = args[0] + newargs[2] = args[1] + + case C_SLLI: + f.op = SLLI + newargs[0] = args[0] + newargs[1] = args[0] + newargs[2] = args[1] + + case C_LDSP: + f.op = LD + newargs[0] = args[0] + newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}} + + case C_SDSP: + f.op = SD + newargs[0] = args[0] + newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}} + + // riscv double precision floating point compressed instructions + case C_FLD: + f.op = FLD + newargs[0] = args[0] + newargs[1] = RegOffset{args[1].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}} + + case C_FSD: + f.op = FSD + newargs[0] = args[1] + newargs[1] = RegOffset{args[0].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}} + + case C_FLDSP: + f.op = FLD + newargs[0] = args[0] + newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}} + + case C_FSDSP: + f.op = FSD + newargs[0] = args[0] + newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}} + + case C_UNIMP: + f.op = CSRRW + newargs[0] = Reg(X0) + newargs[1] = CSR(CYCLE) + newargs[2] = Reg(X0) + } + return newargs +} diff --git a/vendor/golang.org/x/arch/riscv64/riscv64asm/gnu.go b/vendor/golang.org/x/arch/riscv64/riscv64asm/gnu.go new file mode 100644 index 0000000000..d6b3dc040e --- /dev/null +++ b/vendor/golang.org/x/arch/riscv64/riscv64asm/gnu.go @@ -0,0 +1,328 @@ +// Copyright 2024 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 riscv64asm + +import ( + "strings" +) + +// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils. +// This form typically matches the syntax defined in the RISC-V Instruction Set Manual. See +// https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf +func GNUSyntax(inst Inst) string { + op := strings.ToLower(inst.Op.String()) + var args []string + for _, a := range inst.Args { + if a == nil { + break + } + args = append(args, strings.ToLower(a.String())) + } + + switch inst.Op { + case ADDI, ADDIW, ANDI, ORI, SLLI, SLLIW, SRAI, SRAIW, SRLI, SRLIW, XORI: + if inst.Op == ADDI { + if inst.Args[1].(Reg) == X0 && inst.Args[0].(Reg) != X0 { + op = "li" + args[1] = args[2] + args = args[:len(args)-1] + break + } + + if inst.Args[2].(Simm).Imm == 0 { + if inst.Args[0].(Reg) == X0 && inst.Args[1].(Reg) == X0 { + op = "nop" + args = nil + } else { + op = "mv" + args = args[:len(args)-1] + } + } + } + + if inst.Op == ADDIW && inst.Args[2].(Simm).Imm == 0 { + op = "sext.w" + args = args[:len(args)-1] + } + + if inst.Op == XORI && inst.Args[2].(Simm).String() == "-1" { + op = "not" + args = args[:len(args)-1] + } + + case ADD: + if inst.Args[1].(Reg) == X0 { + op = "mv" + args[1] = args[2] + args = args[:len(args)-1] + } + + case BEQ: + if inst.Args[1].(Reg) == X0 { + op = "beqz" + args[1] = args[2] + args = args[:len(args)-1] + } + + case BGE: + if inst.Args[1].(Reg) == X0 { + op = "bgez" + args[1] = args[2] + args = args[:len(args)-1] + } else if inst.Args[0].(Reg) == X0 { + op = "blez" + args[0], args[1] = args[1], args[2] + args = args[:len(args)-1] + } + + case BLT: + if inst.Args[1].(Reg) == X0 { + op = "bltz" + args[1] = args[2] + args = args[:len(args)-1] + } else if inst.Args[0].(Reg) == X0 { + op = "bgtz" + args[0], args[1] = args[1], args[2] + args = args[:len(args)-1] + } + + case BNE: + if inst.Args[1].(Reg) == X0 { + op = "bnez" + args[1] = args[2] + args = args[:len(args)-1] + } + + case CSRRC: + if inst.Args[0].(Reg) == X0 { + op = "csrc" + args[0], args[1] = args[1], args[2] + args = args[:len(args)-1] + } + + case CSRRCI: + if inst.Args[0].(Reg) == X0 { + op = "csrci" + args[0], args[1] = args[1], args[2] + args = args[:len(args)-1] + } + + case CSRRS: + if inst.Args[2].(Reg) == X0 { + switch inst.Args[1].(CSR) { + case FCSR: + op = "frcsr" + args = args[:len(args)-2] + + case FFLAGS: + op = "frflags" + args = args[:len(args)-2] + + case FRM: + op = "frrm" + args = args[:len(args)-2] + + // rdcycleh, rdinstreth and rdtimeh are RV-32 only instructions. + // So not included there. + case CYCLE: + op = "rdcycle" + args = args[:len(args)-2] + + case INSTRET: + op = "rdinstret" + args = args[:len(args)-2] + + case TIME: + op = "rdtime" + args = args[:len(args)-2] + + default: + op = "csrr" + args = args[:len(args)-1] + } + } else if inst.Args[0].(Reg) == X0 { + op = "csrs" + args[0], args[1] = args[1], args[2] + args = args[:len(args)-1] + } + + case CSRRSI: + if inst.Args[0].(Reg) == X0 { + op = "csrsi" + args[0], args[1] = args[1], args[2] + args = args[:len(args)-1] + } + + case CSRRW: + switch inst.Args[1].(CSR) { + case FCSR: + op = "fscsr" + if inst.Args[0].(Reg) == X0 { + args[0] = args[2] + args = args[:len(args)-2] + } else { + args[1] = args[2] + args = args[:len(args)-1] + } + + case FFLAGS: + op = "fsflags" + if inst.Args[0].(Reg) == X0 { + args[0] = args[2] + args = args[:len(args)-2] + } else { + args[1] = args[2] + args = args[:len(args)-1] + } + + case FRM: + op = "fsrm" + if inst.Args[0].(Reg) == X0 { + args[0] = args[2] + args = args[:len(args)-2] + } else { + args[1] = args[2] + args = args[:len(args)-1] + } + + case CYCLE: + if inst.Args[0].(Reg) == X0 && inst.Args[2].(Reg) == X0 { + op = "unimp" + args = nil + } + + default: + if inst.Args[0].(Reg) == X0 { + op = "csrw" + args[0], args[1] = args[1], args[2] + args = args[:len(args)-1] + } + } + + case CSRRWI: + if inst.Args[0].(Reg) == X0 { + op = "csrwi" + args[0], args[1] = args[1], args[2] + args = args[:len(args)-1] + } + + // When both pred and succ equals to iorw, the GNU objdump will omit them. + case FENCE: + if inst.Args[0].(MemOrder).String() == "iorw" && + inst.Args[1].(MemOrder).String() == "iorw" { + args = nil + } + + case FSGNJX_D: + if inst.Args[1].(Reg) == inst.Args[2].(Reg) { + op = "fabs.d" + args = args[:len(args)-1] + } + + case FSGNJX_S: + if inst.Args[1].(Reg) == inst.Args[2].(Reg) { + op = "fabs.s" + args = args[:len(args)-1] + } + + case FSGNJ_D: + if inst.Args[1].(Reg) == inst.Args[2].(Reg) { + op = "fmv.d" + args = args[:len(args)-1] + } + + case FSGNJ_S: + if inst.Args[1].(Reg) == inst.Args[2].(Reg) { + op = "fmv.s" + args = args[:len(args)-1] + } + + case FSGNJN_D: + if inst.Args[1].(Reg) == inst.Args[2].(Reg) { + op = "fneg.d" + args = args[:len(args)-1] + } + + case FSGNJN_S: + if inst.Args[1].(Reg) == inst.Args[2].(Reg) { + op = "fneg.s" + args = args[:len(args)-1] + } + + case JAL: + if inst.Args[0].(Reg) == X0 { + op = "j" + args[0] = args[1] + args = args[:len(args)-1] + } else if inst.Args[0].(Reg) == X1 { + op = "jal" + args[0] = args[1] + args = args[:len(args)-1] + } + + case JALR: + if inst.Args[0].(Reg) == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 { + args[0] = inst.Args[1].(RegOffset).OfsReg.String() + args = args[:len(args)-1] + } + + if inst.Args[0].(Reg) == X0 { + if inst.Args[1].(RegOffset).OfsReg == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 { + op = "ret" + args = nil + } else if inst.Args[1].(RegOffset).Ofs.Imm == 0 { + op = "jr" + args[0] = inst.Args[1].(RegOffset).OfsReg.String() + args = args[:len(args)-1] + } else { + op = "jr" + args[0] = inst.Args[1].(RegOffset).String() + args = args[:len(args)-1] + } + } + + case SLTIU: + if inst.Args[2].(Simm).String() == "1" { + op = "seqz" + args = args[:len(args)-1] + } + + case SLT: + if inst.Args[1].(Reg) == X0 { + op = "sgtz" + args[1] = args[2] + args = args[:len(args)-1] + } else if inst.Args[2].(Reg) == X0 { + op = "sltz" + args = args[:len(args)-1] + } + + case SLTU: + if inst.Args[1].(Reg) == X0 { + op = "snez" + args[1] = args[2] + args = args[:len(args)-1] + } + + case SUB: + if inst.Args[1].(Reg) == X0 { + op = "neg" + args[1] = args[2] + args = args[:len(args)-1] + } + + case SUBW: + if inst.Args[1].(Reg) == X0 { + op = "negw" + args[1] = args[2] + args = args[:len(args)-1] + } + } + + if args != nil { + op += " " + strings.Join(args, ",") + } + return op +} diff --git a/vendor/golang.org/x/arch/riscv64/riscv64asm/inst.go b/vendor/golang.org/x/arch/riscv64/riscv64asm/inst.go new file mode 100644 index 0000000000..3c13567cb0 --- /dev/null +++ b/vendor/golang.org/x/arch/riscv64/riscv64asm/inst.go @@ -0,0 +1,495 @@ +// Copyright 2024 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 riscv64asm + +import ( + "fmt" + "strings" +) + +// An Op is a RISC-V opcode. +type Op uint16 + +// NOTE: The actual Op values are defined in tables.go. +func (op Op) String() string { + if op >= Op(len(opstr)) || opstr[op] == "" { + return fmt.Sprintf("Op(%d)", op) + } + + return opstr[op] +} + +// An Arg is a single instruction argument. +type Arg interface { + String() string +} + +// An Args holds the instruction arguments. +// If an instruction has fewer than 6 arguments, +// the final elements in the array are nil. +type Args [6]Arg + +// An Inst is a single instruction. +type Inst struct { + Op Op // Opcode mnemonic. + Enc uint32 // Raw encoding bits. + Args Args // Instruction arguments, in RISC-V mamual order. + Len int // Length of encoded instruction in bytes +} + +func (i Inst) String() string { + var args []string + for _, arg := range i.Args { + if arg == nil { + break + } + args = append(args, arg.String()) + } + + if len(args) == 0 { + return i.Op.String() + } + return i.Op.String() + " " + strings.Join(args, ",") +} + +// A Reg is a single register. +// The zero value denotes X0, not the absence of a register. +type Reg uint16 + +const ( + // General-purpose register + X0 Reg = iota + X1 + X2 + X3 + X4 + X5 + X6 + X7 + X8 + X9 + X10 + X11 + X12 + X13 + X14 + X15 + X16 + X17 + X18 + X19 + X20 + X21 + X22 + X23 + X24 + X25 + X26 + X27 + X28 + X29 + X30 + X31 + + //Float point register + F0 + F1 + F2 + F3 + F4 + F5 + F6 + F7 + F8 + F9 + F10 + F11 + F12 + F13 + F14 + F15 + F16 + F17 + F18 + F19 + F20 + F21 + F22 + F23 + F24 + F25 + F26 + F27 + F28 + F29 + F30 + F31 +) + +func (r Reg) String() string { + switch { + case r >= X0 && r <= X31: + return fmt.Sprintf("x%d", r) + + case r >= F0 && r <= F31: + return fmt.Sprintf("f%d", r-F0) + + default: + return fmt.Sprintf("Unknown(%d)", r) + } +} + +// A CSR is a single control and status register. +// Use stringer to generate CSR match table. +// +//go:generate stringer -type=CSR +type CSR uint16 + +const ( + // Control status register + USTATUS CSR = 0x0000 + FFLAGS CSR = 0x0001 + FRM CSR = 0x0002 + FCSR CSR = 0x0003 + UIE CSR = 0x0004 + UTVEC CSR = 0x0005 + UTVT CSR = 0x0007 + VSTART CSR = 0x0008 + VXSAT CSR = 0x0009 + VXRM CSR = 0x000a + VCSR CSR = 0x000f + USCRATCH CSR = 0x0040 + UEPC CSR = 0x0041 + UCAUSE CSR = 0x0042 + UTVAL CSR = 0x0043 + UIP CSR = 0x0044 + UNXTI CSR = 0x0045 + UINTSTATUS CSR = 0x0046 + USCRATCHCSW CSR = 0x0048 + USCRATCHCSWL CSR = 0x0049 + SSTATUS CSR = 0x0100 + SEDELEG CSR = 0x0102 + SIDELEG CSR = 0x0103 + SIE CSR = 0x0104 + STVEC CSR = 0x0105 + SCOUNTEREN CSR = 0x0106 + STVT CSR = 0x0107 + SSCRATCH CSR = 0x0140 + SEPC CSR = 0x0141 + SCAUSE CSR = 0x0142 + STVAL CSR = 0x0143 + SIP CSR = 0x0144 + SNXTI CSR = 0x0145 + SINTSTATUS CSR = 0x0146 + SSCRATCHCSW CSR = 0x0148 + SSCRATCHCSWL CSR = 0x0149 + SATP CSR = 0x0180 + VSSTATUS CSR = 0x0200 + VSIE CSR = 0x0204 + VSTVEC CSR = 0x0205 + VSSCRATCH CSR = 0x0240 + VSEPC CSR = 0x0241 + VSCAUSE CSR = 0x0242 + VSTVAL CSR = 0x0243 + VSIP CSR = 0x0244 + VSATP CSR = 0x0280 + MSTATUS CSR = 0x0300 + MISA CSR = 0x0301 + MEDELEG CSR = 0x0302 + MIDELEG CSR = 0x0303 + MIE CSR = 0x0304 + MTVEC CSR = 0x0305 + MCOUNTEREN CSR = 0x0306 + MTVT CSR = 0x0307 + MSTATUSH CSR = 0x0310 + MCOUNTINHIBIT CSR = 0x0320 + MHPMEVENT3 CSR = 0x0323 + MHPMEVENT4 CSR = 0x0324 + MHPMEVENT5 CSR = 0x0325 + MHPMEVENT6 CSR = 0x0326 + MHPMEVENT7 CSR = 0x0327 + MHPMEVENT8 CSR = 0x0328 + MHPMEVENT9 CSR = 0x0329 + MHPMEVENT10 CSR = 0x032a + MHPMEVENT11 CSR = 0x032b + MHPMEVENT12 CSR = 0x032c + MHPMEVENT13 CSR = 0x032d + MHPMEVENT14 CSR = 0x032e + MHPMEVENT15 CSR = 0x032f + MHPMEVENT16 CSR = 0x0330 + MHPMEVENT17 CSR = 0x0331 + MHPMEVENT18 CSR = 0x0332 + MHPMEVENT19 CSR = 0x0333 + MHPMEVENT20 CSR = 0x0334 + MHPMEVENT21 CSR = 0x0335 + MHPMEVENT22 CSR = 0x0336 + MHPMEVENT23 CSR = 0x0337 + MHPMEVENT24 CSR = 0x0338 + MHPMEVENT25 CSR = 0x0339 + MHPMEVENT26 CSR = 0x033a + MHPMEVENT27 CSR = 0x033b + MHPMEVENT28 CSR = 0x033c + MHPMEVENT29 CSR = 0x033d + MHPMEVENT30 CSR = 0x033e + MHPMEVENT31 CSR = 0x033f + MSCRATCH CSR = 0x0340 + MEPC CSR = 0x0341 + MCAUSE CSR = 0x0342 + MTVAL CSR = 0x0343 + MIP CSR = 0x0344 + MNXTI CSR = 0x0345 + MINTSTATUS CSR = 0x0346 + MSCRATCHCSW CSR = 0x0348 + MSCRATCHCSWL CSR = 0x0349 + MTINST CSR = 0x034a + MTVAL2 CSR = 0x034b + PMPCFG0 CSR = 0x03a0 + PMPCFG1 CSR = 0x03a1 + PMPCFG2 CSR = 0x03a2 + PMPCFG3 CSR = 0x03a3 + PMPADDR0 CSR = 0x03b0 + PMPADDR1 CSR = 0x03b1 + PMPADDR2 CSR = 0x03b2 + PMPADDR3 CSR = 0x03b3 + PMPADDR4 CSR = 0x03b4 + PMPADDR5 CSR = 0x03b5 + PMPADDR6 CSR = 0x03b6 + PMPADDR7 CSR = 0x03b7 + PMPADDR8 CSR = 0x03b8 + PMPADDR9 CSR = 0x03b9 + PMPADDR10 CSR = 0x03ba + PMPADDR11 CSR = 0x03bb + PMPADDR12 CSR = 0x03bc + PMPADDR13 CSR = 0x03bd + PMPADDR14 CSR = 0x03be + PMPADDR15 CSR = 0x03bf + HSTATUS CSR = 0x0600 + HEDELEG CSR = 0x0602 + HIDELEG CSR = 0x0603 + HIE CSR = 0x0604 + HTIMEDELTA CSR = 0x0605 + HCOUNTEREN CSR = 0x0606 + HGEIE CSR = 0x0607 + HTIMEDELTAH CSR = 0x0615 + HTVAL CSR = 0x0643 + HIP CSR = 0x0644 + HVIP CSR = 0x0645 + HTINST CSR = 0x064a + HGATP CSR = 0x0680 + TSELECT CSR = 0x07a0 + TDATA1 CSR = 0x07a1 + TDATA2 CSR = 0x07a2 + TDATA3 CSR = 0x07a3 + TINFO CSR = 0x07a4 + TCONTROL CSR = 0x07a5 + MCONTEXT CSR = 0x07a8 + MNOISE CSR = 0x07a9 + SCONTEXT CSR = 0x07aa + DCSR CSR = 0x07b0 + DPC CSR = 0x07b1 + DSCRATCH0 CSR = 0x07b2 + DSCRATCH1 CSR = 0x07b3 + MCYCLE CSR = 0x0b00 + MINSTRET CSR = 0x0b02 + MHPMCOUNTER3 CSR = 0x0b03 + MHPMCOUNTER4 CSR = 0x0b04 + MHPMCOUNTER5 CSR = 0x0b05 + MHPMCOUNTER6 CSR = 0x0b06 + MHPMCOUNTER7 CSR = 0x0b07 + MHPMCOUNTER8 CSR = 0x0b08 + MHPMCOUNTER9 CSR = 0x0b09 + MHPMCOUNTER10 CSR = 0x0b0a + MHPMCOUNTER11 CSR = 0x0b0b + MHPMCOUNTER12 CSR = 0x0b0c + MHPMCOUNTER13 CSR = 0x0b0d + MHPMCOUNTER14 CSR = 0x0b0e + MHPMCOUNTER15 CSR = 0x0b0f + MHPMCOUNTER16 CSR = 0x0b10 + MHPMCOUNTER17 CSR = 0x0b11 + MHPMCOUNTER18 CSR = 0x0b12 + MHPMCOUNTER19 CSR = 0x0b13 + MHPMCOUNTER20 CSR = 0x0b14 + MHPMCOUNTER21 CSR = 0x0b15 + MHPMCOUNTER22 CSR = 0x0b16 + MHPMCOUNTER23 CSR = 0x0b17 + MHPMCOUNTER24 CSR = 0x0b18 + MHPMCOUNTER25 CSR = 0x0b19 + MHPMCOUNTER26 CSR = 0x0b1a + MHPMCOUNTER27 CSR = 0x0b1b + MHPMCOUNTER28 CSR = 0x0b1c + MHPMCOUNTER29 CSR = 0x0b1d + MHPMCOUNTER30 CSR = 0x0b1e + MHPMCOUNTER31 CSR = 0x0b1f + MCYCLEH CSR = 0x0b80 + MINSTRETH CSR = 0x0b82 + MHPMCOUNTER3H CSR = 0x0b83 + MHPMCOUNTER4H CSR = 0x0b84 + MHPMCOUNTER5H CSR = 0x0b85 + MHPMCOUNTER6H CSR = 0x0b86 + MHPMCOUNTER7H CSR = 0x0b87 + MHPMCOUNTER8H CSR = 0x0b88 + MHPMCOUNTER9H CSR = 0x0b89 + MHPMCOUNTER10H CSR = 0x0b8a + MHPMCOUNTER11H CSR = 0x0b8b + MHPMCOUNTER12H CSR = 0x0b8c + MHPMCOUNTER13H CSR = 0x0b8d + MHPMCOUNTER14H CSR = 0x0b8e + MHPMCOUNTER15H CSR = 0x0b8f + MHPMCOUNTER16H CSR = 0x0b90 + MHPMCOUNTER17H CSR = 0x0b91 + MHPMCOUNTER18H CSR = 0x0b92 + MHPMCOUNTER19H CSR = 0x0b93 + MHPMCOUNTER20H CSR = 0x0b94 + MHPMCOUNTER21H CSR = 0x0b95 + MHPMCOUNTER22H CSR = 0x0b96 + MHPMCOUNTER23H CSR = 0x0b97 + MHPMCOUNTER24H CSR = 0x0b98 + MHPMCOUNTER25H CSR = 0x0b99 + MHPMCOUNTER26H CSR = 0x0b9a + MHPMCOUNTER27H CSR = 0x0b9b + MHPMCOUNTER28H CSR = 0x0b9c + MHPMCOUNTER29H CSR = 0x0b9d + MHPMCOUNTER30H CSR = 0x0b9e + MHPMCOUNTER31H CSR = 0x0b9f + CYCLE CSR = 0x0c00 + TIME CSR = 0x0c01 + INSTRET CSR = 0x0c02 + HPMCOUNTER3 CSR = 0x0c03 + HPMCOUNTER4 CSR = 0x0c04 + HPMCOUNTER5 CSR = 0x0c05 + HPMCOUNTER6 CSR = 0x0c06 + HPMCOUNTER7 CSR = 0x0c07 + HPMCOUNTER8 CSR = 0x0c08 + HPMCOUNTER9 CSR = 0x0c09 + HPMCOUNTER10 CSR = 0x0c0a + HPMCOUNTER11 CSR = 0x0c0b + HPMCOUNTER12 CSR = 0x0c0c + HPMCOUNTER13 CSR = 0x0c0d + HPMCOUNTER14 CSR = 0x0c0e + HPMCOUNTER15 CSR = 0x0c0f + HPMCOUNTER16 CSR = 0x0c10 + HPMCOUNTER17 CSR = 0x0c11 + HPMCOUNTER18 CSR = 0x0c12 + HPMCOUNTER19 CSR = 0x0c13 + HPMCOUNTER20 CSR = 0x0c14 + HPMCOUNTER21 CSR = 0x0c15 + HPMCOUNTER22 CSR = 0x0c16 + HPMCOUNTER23 CSR = 0x0c17 + HPMCOUNTER24 CSR = 0x0c18 + HPMCOUNTER25 CSR = 0x0c19 + HPMCOUNTER26 CSR = 0x0c1a + HPMCOUNTER27 CSR = 0x0c1b + HPMCOUNTER28 CSR = 0x0c1c + HPMCOUNTER29 CSR = 0x0c1d + HPMCOUNTER30 CSR = 0x0c1e + HPMCOUNTER31 CSR = 0x0c1f + VL CSR = 0x0c20 + VTYPE CSR = 0x0c21 + VLENB CSR = 0x0c22 + CYCLEH CSR = 0x0c80 + TIMEH CSR = 0x0c81 + INSTRETH CSR = 0x0c82 + HPMCOUNTER3H CSR = 0x0c83 + HPMCOUNTER4H CSR = 0x0c84 + HPMCOUNTER5H CSR = 0x0c85 + HPMCOUNTER6H CSR = 0x0c86 + HPMCOUNTER7H CSR = 0x0c87 + HPMCOUNTER8H CSR = 0x0c88 + HPMCOUNTER9H CSR = 0x0c89 + HPMCOUNTER10H CSR = 0x0c8a + HPMCOUNTER11H CSR = 0x0c8b + HPMCOUNTER12H CSR = 0x0c8c + HPMCOUNTER13H CSR = 0x0c8d + HPMCOUNTER14H CSR = 0x0c8e + HPMCOUNTER15H CSR = 0x0c8f + HPMCOUNTER16H CSR = 0x0c90 + HPMCOUNTER17H CSR = 0x0c91 + HPMCOUNTER18H CSR = 0x0c92 + HPMCOUNTER19H CSR = 0x0c93 + HPMCOUNTER20H CSR = 0x0c94 + HPMCOUNTER21H CSR = 0x0c95 + HPMCOUNTER22H CSR = 0x0c96 + HPMCOUNTER23H CSR = 0x0c97 + HPMCOUNTER24H CSR = 0x0c98 + HPMCOUNTER25H CSR = 0x0c99 + HPMCOUNTER26H CSR = 0x0c9a + HPMCOUNTER27H CSR = 0x0c9b + HPMCOUNTER28H CSR = 0x0c9c + HPMCOUNTER29H CSR = 0x0c9d + HPMCOUNTER30H CSR = 0x0c9e + HPMCOUNTER31H CSR = 0x0c9f + HGEIP CSR = 0x0e12 + MVENDORID CSR = 0x0f11 + MARCHID CSR = 0x0f12 + MIMPID CSR = 0x0f13 + MHARTID CSR = 0x0f14 + MENTROPY CSR = 0x0f15 +) + +// An Uimm is an unsigned immediate number +type Uimm struct { + Imm uint32 // 32-bit unsigned integer + Decimal bool // Print format of the immediate, either decimal or hexadecimal +} + +func (ui Uimm) String() string { + if ui.Decimal { + return fmt.Sprintf("%d", ui.Imm) + } + return fmt.Sprintf("%#x", ui.Imm) +} + +// A Simm is a signed immediate number +type Simm struct { + Imm int32 // 32-bit signed integer + Decimal bool // Print format of the immediate, either decimal or hexadecimal + Width uint8 // Actual width of the Simm +} + +func (si Simm) String() string { + if si.Decimal { + return fmt.Sprintf("%d", si.Imm) + } + return fmt.Sprintf("%#x", si.Imm) +} + +// An AmoReg is an atomic address register used in AMO instructions +type AmoReg struct { + reg Reg // Avoid promoted String method +} + +func (amoReg AmoReg) String() string { + return fmt.Sprintf("(%s)", amoReg.reg) +} + +// A RegOffset is a register with offset value +type RegOffset struct { + OfsReg Reg + Ofs Simm +} + +func (regofs RegOffset) String() string { + return fmt.Sprintf("%s(%s)", regofs.Ofs, regofs.OfsReg) +} + +// A MemOrder is a memory order hint in fence instruction +type MemOrder uint8 + +func (memOrder MemOrder) String() string { + var str string + if memOrder<<7>>7 == 1 { + str += "i" + } + if memOrder>>1<<7>>7 == 1 { + str += "o" + } + if memOrder>>2<<7>>7 == 1 { + str += "r" + } + if memOrder>>3<<7>>7 == 1 { + str += "w" + } + return str +} diff --git a/vendor/golang.org/x/arch/riscv64/riscv64asm/plan9x.go b/vendor/golang.org/x/arch/riscv64/riscv64asm/plan9x.go new file mode 100644 index 0000000000..367122d940 --- /dev/null +++ b/vendor/golang.org/x/arch/riscv64/riscv64asm/plan9x.go @@ -0,0 +1,377 @@ +// Copyright 2024 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 riscv64asm + +import ( + "fmt" + "io" + "strconv" + "strings" +) + +// GoSyntax returns the Go assembler syntax for the instruction. +// The syntax was originally defined by Plan 9. +// The pc is the program counter of the instruction, used for +// expanding PC-relative addresses into absolute ones. +// The symname function queries the symbol table for the program +// being disassembled. Given a target address it returns the name +// and base address of the symbol containing the target, if any; +// otherwise it returns "", 0. +// The reader text should read from the text segment using text addresses +// as offsets; it is used to display pc-relative loads as constant loads. +func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64), text io.ReaderAt) string { + if symname == nil { + symname = func(uint64) (string, uint64) { return "", 0 } + } + + var args []string + for _, a := range inst.Args { + if a == nil { + break + } + args = append(args, plan9Arg(&inst, pc, symname, a)) + } + + op := inst.Op.String() + + switch inst.Op { + + case AMOADD_D, AMOADD_D_AQ, AMOADD_D_RL, AMOADD_D_AQRL, AMOADD_W, AMOADD_W_AQ, + AMOADD_W_RL, AMOADD_W_AQRL, AMOAND_D, AMOAND_D_AQ, AMOAND_D_RL, AMOAND_D_AQRL, + AMOAND_W, AMOAND_W_AQ, AMOAND_W_RL, AMOAND_W_AQRL, AMOMAXU_D, AMOMAXU_D_AQ, + AMOMAXU_D_RL, AMOMAXU_D_AQRL, AMOMAXU_W, AMOMAXU_W_AQ, AMOMAXU_W_RL, AMOMAXU_W_AQRL, + AMOMAX_D, AMOMAX_D_AQ, AMOMAX_D_RL, AMOMAX_D_AQRL, AMOMAX_W, AMOMAX_W_AQ, AMOMAX_W_RL, + AMOMAX_W_AQRL, AMOMINU_D, AMOMINU_D_AQ, AMOMINU_D_RL, AMOMINU_D_AQRL, AMOMINU_W, + AMOMINU_W_AQ, AMOMINU_W_RL, AMOMINU_W_AQRL, AMOMIN_D, AMOMIN_D_AQ, AMOMIN_D_RL, + AMOMIN_D_AQRL, AMOMIN_W, AMOMIN_W_AQ, AMOMIN_W_RL, AMOMIN_W_AQRL, AMOOR_D, AMOOR_D_AQ, + AMOOR_D_RL, AMOOR_D_AQRL, AMOOR_W, AMOOR_W_AQ, AMOOR_W_RL, AMOOR_W_AQRL, AMOSWAP_D, + AMOSWAP_D_AQ, AMOSWAP_D_RL, AMOSWAP_D_AQRL, AMOSWAP_W, AMOSWAP_W_AQ, AMOSWAP_W_RL, + AMOSWAP_W_AQRL, AMOXOR_D, AMOXOR_D_AQ, AMOXOR_D_RL, AMOXOR_D_AQRL, AMOXOR_W, + AMOXOR_W_AQ, AMOXOR_W_RL, AMOXOR_W_AQRL, SC_D, SC_D_AQ, SC_D_RL, SC_D_AQRL, + SC_W, SC_W_AQ, SC_W_RL, SC_W_AQRL: + // Atomic instructions have special operand order. + args[2], args[1] = args[1], args[2] + + case ADDI: + if inst.Args[2].(Simm).Imm == 0 { + op = "MOV" + args = args[:len(args)-1] + } + + case ADDIW: + if inst.Args[2].(Simm).Imm == 0 { + op = "MOVW" + args = args[:len(args)-1] + } + + case ANDI: + if inst.Args[2].(Simm).Imm == 255 { + op = "MOVBU" + args = args[:len(args)-1] + } + + case BEQ: + if inst.Args[1].(Reg) == X0 { + op = "BEQZ" + args[1] = args[2] + args = args[:len(args)-1] + } + for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 { + args[i], args[j] = args[j], args[i] + } + + case BGE: + if inst.Args[1].(Reg) == X0 { + op = "BGEZ" + args[1] = args[2] + args = args[:len(args)-1] + } + for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 { + args[i], args[j] = args[j], args[i] + } + + case BLT: + if inst.Args[1].(Reg) == X0 { + op = "BLTZ" + args[1] = args[2] + args = args[:len(args)-1] + } + for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 { + args[i], args[j] = args[j], args[i] + } + + case BNE: + if inst.Args[1].(Reg) == X0 { + op = "BNEZ" + args[1] = args[2] + args = args[:len(args)-1] + } + for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 { + args[i], args[j] = args[j], args[i] + } + + case BLTU, BGEU: + for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 { + args[i], args[j] = args[j], args[i] + } + + case CSRRW: + switch inst.Args[1].(CSR) { + case FCSR: + op = "FSCSR" + args[1] = args[2] + args = args[:len(args)-1] + case FFLAGS: + op = "FSFLAGS" + args[1] = args[2] + args = args[:len(args)-1] + case FRM: + op = "FSRM" + args[1] = args[2] + args = args[:len(args)-1] + case CYCLE: + if inst.Args[0].(Reg) == X0 && inst.Args[2].(Reg) == X0 { + op = "UNIMP" + args = nil + } + } + + case CSRRS: + if inst.Args[2].(Reg) == X0 { + switch inst.Args[1].(CSR) { + case FCSR: + op = "FRCSR" + args = args[:len(args)-2] + case FFLAGS: + op = "FRFLAGS" + args = args[:len(args)-2] + case FRM: + op = "FRRM" + args = args[:len(args)-2] + case CYCLE: + op = "RDCYCLE" + args = args[:len(args)-2] + case CYCLEH: + op = "RDCYCLEH" + args = args[:len(args)-2] + case INSTRET: + op = "RDINSTRET" + args = args[:len(args)-2] + case INSTRETH: + op = "RDINSTRETH" + args = args[:len(args)-2] + case TIME: + op = "RDTIME" + args = args[:len(args)-2] + case TIMEH: + op = "RDTIMEH" + args = args[:len(args)-2] + } + } + + // Fence instruction in plan9 doesn't have any operands. + case FENCE: + args = nil + + case FMADD_D, FMADD_H, FMADD_Q, FMADD_S, FMSUB_D, FMSUB_H, + FMSUB_Q, FMSUB_S, FNMADD_D, FNMADD_H, FNMADD_Q, FNMADD_S, + FNMSUB_D, FNMSUB_H, FNMSUB_Q, FNMSUB_S: + args[1], args[3] = args[3], args[1] + + case FSGNJ_S: + if inst.Args[2] == inst.Args[1] { + op = "MOVF" + args = args[:len(args)-1] + } + + case FSGNJ_D: + if inst.Args[2] == inst.Args[1] { + op = "MOVD" + args = args[:len(args)-1] + } + + case FSGNJX_S: + if inst.Args[2] == inst.Args[1] { + op = "FABSS" + args = args[:len(args)-1] + } + + case FSGNJX_D: + if inst.Args[2] == inst.Args[1] { + op = "FABSD" + args = args[:len(args)-1] + } + + case FSGNJN_S: + if inst.Args[2] == inst.Args[1] { + op = "FNEGS" + args = args[:len(args)-1] + } + + case FSGNJN_D: + if inst.Args[2] == inst.Args[1] { + op = "FNESD" + args = args[:len(args)-1] + } + + case LD, SD: + op = "MOV" + if inst.Op == SD { + args[0], args[1] = args[1], args[0] + } + + case LB, SB: + op = "MOVB" + if inst.Op == SB { + args[0], args[1] = args[1], args[0] + } + + case LH, SH: + op = "MOVH" + if inst.Op == SH { + args[0], args[1] = args[1], args[0] + } + + case LW, SW: + op = "MOVW" + if inst.Op == SW { + args[0], args[1] = args[1], args[0] + } + + case LBU: + op = "MOVBU" + + case LHU: + op = "MOVHU" + + case LWU: + op = "MOVWU" + + case FLW, FSW: + op = "MOVF" + if inst.Op == FLW { + args[0], args[1] = args[1], args[0] + } + + case FLD, FSD: + op = "MOVD" + if inst.Op == FLD { + args[0], args[1] = args[1], args[0] + } + + case SUB: + if inst.Args[1].(Reg) == X0 { + op = "NEG" + args[1] = args[2] + args = args[:len(args)-1] + } + + case XORI: + if inst.Args[2].(Simm).String() == "-1" { + op = "NOT" + args = args[:len(args)-1] + } + + case SLTIU: + if inst.Args[2].(Simm).Imm == 1 { + op = "SEQZ" + args = args[:len(args)-1] + } + + case SLTU: + if inst.Args[1].(Reg) == X0 { + op = "SNEZ" + args[1] = args[2] + args = args[:len(args)-1] + } + + case JAL: + if inst.Args[0].(Reg) == X0 { + op = "JMP" + args[0] = args[1] + args = args[:len(args)-1] + } else if inst.Args[0].(Reg) == X1 { + op = "CALL" + args[0] = args[1] + args = args[:len(args)-1] + } else { + args[0], args[1] = args[1], args[0] + } + + case JALR: + if inst.Args[0].(Reg) == X0 { + if inst.Args[1].(RegOffset).OfsReg == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 { + op = "RET" + args = nil + break + } + op = "JMP" + args[0] = args[1] + args = args[:len(args)-1] + } else if inst.Args[0].(Reg) == X1 { + op = "CALL" + args[0] = args[1] + args = args[:len(args)-1] + } else { + args[0], args[1] = args[1], args[0] + } + } + + // Reverse args, placing dest last. + for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 { + args[i], args[j] = args[j], args[i] + } + + // Change to plan9 opcode format + // Atomic instructions do not have reorder suffix, so remove them + op = strings.Replace(op, ".AQRL", "", -1) + op = strings.Replace(op, ".AQ", "", -1) + op = strings.Replace(op, ".RL", "", -1) + op = strings.Replace(op, ".", "", -1) + + if args != nil { + op += " " + strings.Join(args, ", ") + } + + return op +} + +func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string { + switch a := arg.(type) { + case Uimm: + return fmt.Sprintf("$%d", uint32(a.Imm)) + + case Simm: + imm, _ := strconv.Atoi(a.String()) + if a.Width == 13 || a.Width == 21 { + addr := int64(pc) + int64(imm) + if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base { + return fmt.Sprintf("%s(SB)", s) + } + return fmt.Sprintf("%d(PC)", imm/4) + } + return fmt.Sprintf("$%d", int32(imm)) + + case Reg: + if a <= 31 { + return fmt.Sprintf("X%d", a) + } else { + return fmt.Sprintf("F%d", a-32) + } + + case RegOffset: + if a.Ofs.Imm == 0 { + return fmt.Sprintf("(X%d)", a.OfsReg) + } else { + return fmt.Sprintf("%s(X%d)", a.Ofs.String(), a.OfsReg) + } + + case AmoReg: + return fmt.Sprintf("(X%d)", a.reg) + + default: + return strings.ToUpper(arg.String()) + } +} diff --git a/vendor/golang.org/x/arch/riscv64/riscv64asm/tables.go b/vendor/golang.org/x/arch/riscv64/riscv64asm/tables.go new file mode 100644 index 0000000000..3e5db415e7 --- /dev/null +++ b/vendor/golang.org/x/arch/riscv64/riscv64asm/tables.go @@ -0,0 +1,1474 @@ +// Code generated by riscv64spec riscv-opcodes +// DO NOT EDIT + +// Copyright 2024 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 riscv64asm + +const ( + _ Op = iota + ADD + ADDI + ADDIW + ADDW + ADD_UW + AMOADD_D + AMOADD_D_AQ + AMOADD_D_AQRL + AMOADD_D_RL + AMOADD_W + AMOADD_W_AQ + AMOADD_W_AQRL + AMOADD_W_RL + AMOAND_D + AMOAND_D_AQ + AMOAND_D_AQRL + AMOAND_D_RL + AMOAND_W + AMOAND_W_AQ + AMOAND_W_AQRL + AMOAND_W_RL + AMOMAXU_D + AMOMAXU_D_AQ + AMOMAXU_D_AQRL + AMOMAXU_D_RL + AMOMAXU_W + AMOMAXU_W_AQ + AMOMAXU_W_AQRL + AMOMAXU_W_RL + AMOMAX_D + AMOMAX_D_AQ + AMOMAX_D_AQRL + AMOMAX_D_RL + AMOMAX_W + AMOMAX_W_AQ + AMOMAX_W_AQRL + AMOMAX_W_RL + AMOMINU_D + AMOMINU_D_AQ + AMOMINU_D_AQRL + AMOMINU_D_RL + AMOMINU_W + AMOMINU_W_AQ + AMOMINU_W_AQRL + AMOMINU_W_RL + AMOMIN_D + AMOMIN_D_AQ + AMOMIN_D_AQRL + AMOMIN_D_RL + AMOMIN_W + AMOMIN_W_AQ + AMOMIN_W_AQRL + AMOMIN_W_RL + AMOOR_D + AMOOR_D_AQ + AMOOR_D_AQRL + AMOOR_D_RL + AMOOR_W + AMOOR_W_AQ + AMOOR_W_AQRL + AMOOR_W_RL + AMOSWAP_D + AMOSWAP_D_AQ + AMOSWAP_D_AQRL + AMOSWAP_D_RL + AMOSWAP_W + AMOSWAP_W_AQ + AMOSWAP_W_AQRL + AMOSWAP_W_RL + AMOXOR_D + AMOXOR_D_AQ + AMOXOR_D_AQRL + AMOXOR_D_RL + AMOXOR_W + AMOXOR_W_AQ + AMOXOR_W_AQRL + AMOXOR_W_RL + AND + ANDI + ANDN + AUIPC + BCLR + BCLRI + BEQ + BEXT + BEXTI + BGE + BGEU + BINV + BINVI + BLT + BLTU + BNE + BSET + BSETI + CLZ + CLZW + CPOP + CPOPW + CSRRC + CSRRCI + CSRRS + CSRRSI + CSRRW + CSRRWI + CTZ + CTZW + C_ADD + C_ADDI + C_ADDI16SP + C_ADDI4SPN + C_ADDIW + C_ADDW + C_AND + C_ANDI + C_BEQZ + C_BNEZ + C_EBREAK + C_FLD + C_FLDSP + C_FSD + C_FSDSP + C_J + C_JALR + C_JR + C_LD + C_LDSP + C_LI + C_LUI + C_LW + C_LWSP + C_MV + C_NOP + C_OR + C_SD + C_SDSP + C_SLLI + C_SRAI + C_SRLI + C_SUB + C_SUBW + C_SW + C_SWSP + C_UNIMP + C_XOR + DIV + DIVU + DIVUW + DIVW + EBREAK + ECALL + FADD_D + FADD_H + FADD_Q + FADD_S + FCLASS_D + FCLASS_H + FCLASS_Q + FCLASS_S + FCVT_D_L + FCVT_D_LU + FCVT_D_Q + FCVT_D_S + FCVT_D_W + FCVT_D_WU + FCVT_H_L + FCVT_H_LU + FCVT_H_S + FCVT_H_W + FCVT_H_WU + FCVT_LU_D + FCVT_LU_H + FCVT_LU_Q + FCVT_LU_S + FCVT_L_D + FCVT_L_H + FCVT_L_Q + FCVT_L_S + FCVT_Q_D + FCVT_Q_L + FCVT_Q_LU + FCVT_Q_S + FCVT_Q_W + FCVT_Q_WU + FCVT_S_D + FCVT_S_H + FCVT_S_L + FCVT_S_LU + FCVT_S_Q + FCVT_S_W + FCVT_S_WU + FCVT_WU_D + FCVT_WU_H + FCVT_WU_Q + FCVT_WU_S + FCVT_W_D + FCVT_W_H + FCVT_W_Q + FCVT_W_S + FDIV_D + FDIV_H + FDIV_Q + FDIV_S + FENCE + FENCE_I + FEQ_D + FEQ_H + FEQ_Q + FEQ_S + FLD + FLE_D + FLE_H + FLE_Q + FLE_S + FLH + FLQ + FLT_D + FLT_H + FLT_Q + FLT_S + FLW + FMADD_D + FMADD_H + FMADD_Q + FMADD_S + FMAX_D + FMAX_H + FMAX_Q + FMAX_S + FMIN_D + FMIN_H + FMIN_Q + FMIN_S + FMSUB_D + FMSUB_H + FMSUB_Q + FMSUB_S + FMUL_D + FMUL_H + FMUL_Q + FMUL_S + FMV_D_X + FMV_H_X + FMV_W_X + FMV_X_D + FMV_X_H + FMV_X_W + FNMADD_D + FNMADD_H + FNMADD_Q + FNMADD_S + FNMSUB_D + FNMSUB_H + FNMSUB_Q + FNMSUB_S + FSD + FSGNJN_D + FSGNJN_H + FSGNJN_Q + FSGNJN_S + FSGNJX_D + FSGNJX_H + FSGNJX_Q + FSGNJX_S + FSGNJ_D + FSGNJ_H + FSGNJ_Q + FSGNJ_S + FSH + FSQ + FSQRT_D + FSQRT_H + FSQRT_Q + FSQRT_S + FSUB_D + FSUB_H + FSUB_Q + FSUB_S + FSW + JAL + JALR + LB + LBU + LD + LH + LHU + LR_D + LR_D_AQ + LR_D_AQRL + LR_D_RL + LR_W + LR_W_AQ + LR_W_AQRL + LR_W_RL + LUI + LW + LWU + MAX + MAXU + MIN + MINU + MUL + MULH + MULHSU + MULHU + MULW + OR + ORC_B + ORI + ORN + REM + REMU + REMUW + REMW + REV8 + ROL + ROLW + ROR + RORI + RORIW + RORW + SB + SC_D + SC_D_AQ + SC_D_AQRL + SC_D_RL + SC_W + SC_W_AQ + SC_W_AQRL + SC_W_RL + SD + SEXT_B + SEXT_H + SH + SH1ADD + SH1ADD_UW + SH2ADD + SH2ADD_UW + SH3ADD + SH3ADD_UW + SLL + SLLI + SLLIW + SLLI_UW + SLLW + SLT + SLTI + SLTIU + SLTU + SRA + SRAI + SRAIW + SRAW + SRL + SRLI + SRLIW + SRLW + SUB + SUBW + SW + XNOR + XOR + XORI + ZEXT_H +) + +var opstr = [...]string{ + ADD: "ADD", + ADDI: "ADDI", + ADDIW: "ADDIW", + ADDW: "ADDW", + ADD_UW: "ADD.UW", + AMOADD_D: "AMOADD.D", + AMOADD_D_AQ: "AMOADD.D.AQ", + AMOADD_D_AQRL: "AMOADD.D.AQRL", + AMOADD_D_RL: "AMOADD.D.RL", + AMOADD_W: "AMOADD.W", + AMOADD_W_AQ: "AMOADD.W.AQ", + AMOADD_W_AQRL: "AMOADD.W.AQRL", + AMOADD_W_RL: "AMOADD.W.RL", + AMOAND_D: "AMOAND.D", + AMOAND_D_AQ: "AMOAND.D.AQ", + AMOAND_D_AQRL: "AMOAND.D.AQRL", + AMOAND_D_RL: "AMOAND.D.RL", + AMOAND_W: "AMOAND.W", + AMOAND_W_AQ: "AMOAND.W.AQ", + AMOAND_W_AQRL: "AMOAND.W.AQRL", + AMOAND_W_RL: "AMOAND.W.RL", + AMOMAXU_D: "AMOMAXU.D", + AMOMAXU_D_AQ: "AMOMAXU.D.AQ", + AMOMAXU_D_AQRL: "AMOMAXU.D.AQRL", + AMOMAXU_D_RL: "AMOMAXU.D.RL", + AMOMAXU_W: "AMOMAXU.W", + AMOMAXU_W_AQ: "AMOMAXU.W.AQ", + AMOMAXU_W_AQRL: "AMOMAXU.W.AQRL", + AMOMAXU_W_RL: "AMOMAXU.W.RL", + AMOMAX_D: "AMOMAX.D", + AMOMAX_D_AQ: "AMOMAX.D.AQ", + AMOMAX_D_AQRL: "AMOMAX.D.AQRL", + AMOMAX_D_RL: "AMOMAX.D.RL", + AMOMAX_W: "AMOMAX.W", + AMOMAX_W_AQ: "AMOMAX.W.AQ", + AMOMAX_W_AQRL: "AMOMAX.W.AQRL", + AMOMAX_W_RL: "AMOMAX.W.RL", + AMOMINU_D: "AMOMINU.D", + AMOMINU_D_AQ: "AMOMINU.D.AQ", + AMOMINU_D_AQRL: "AMOMINU.D.AQRL", + AMOMINU_D_RL: "AMOMINU.D.RL", + AMOMINU_W: "AMOMINU.W", + AMOMINU_W_AQ: "AMOMINU.W.AQ", + AMOMINU_W_AQRL: "AMOMINU.W.AQRL", + AMOMINU_W_RL: "AMOMINU.W.RL", + AMOMIN_D: "AMOMIN.D", + AMOMIN_D_AQ: "AMOMIN.D.AQ", + AMOMIN_D_AQRL: "AMOMIN.D.AQRL", + AMOMIN_D_RL: "AMOMIN.D.RL", + AMOMIN_W: "AMOMIN.W", + AMOMIN_W_AQ: "AMOMIN.W.AQ", + AMOMIN_W_AQRL: "AMOMIN.W.AQRL", + AMOMIN_W_RL: "AMOMIN.W.RL", + AMOOR_D: "AMOOR.D", + AMOOR_D_AQ: "AMOOR.D.AQ", + AMOOR_D_AQRL: "AMOOR.D.AQRL", + AMOOR_D_RL: "AMOOR.D.RL", + AMOOR_W: "AMOOR.W", + AMOOR_W_AQ: "AMOOR.W.AQ", + AMOOR_W_AQRL: "AMOOR.W.AQRL", + AMOOR_W_RL: "AMOOR.W.RL", + AMOSWAP_D: "AMOSWAP.D", + AMOSWAP_D_AQ: "AMOSWAP.D.AQ", + AMOSWAP_D_AQRL: "AMOSWAP.D.AQRL", + AMOSWAP_D_RL: "AMOSWAP.D.RL", + AMOSWAP_W: "AMOSWAP.W", + AMOSWAP_W_AQ: "AMOSWAP.W.AQ", + AMOSWAP_W_AQRL: "AMOSWAP.W.AQRL", + AMOSWAP_W_RL: "AMOSWAP.W.RL", + AMOXOR_D: "AMOXOR.D", + AMOXOR_D_AQ: "AMOXOR.D.AQ", + AMOXOR_D_AQRL: "AMOXOR.D.AQRL", + AMOXOR_D_RL: "AMOXOR.D.RL", + AMOXOR_W: "AMOXOR.W", + AMOXOR_W_AQ: "AMOXOR.W.AQ", + AMOXOR_W_AQRL: "AMOXOR.W.AQRL", + AMOXOR_W_RL: "AMOXOR.W.RL", + AND: "AND", + ANDI: "ANDI", + ANDN: "ANDN", + AUIPC: "AUIPC", + BCLR: "BCLR", + BCLRI: "BCLRI", + BEQ: "BEQ", + BEXT: "BEXT", + BEXTI: "BEXTI", + BGE: "BGE", + BGEU: "BGEU", + BINV: "BINV", + BINVI: "BINVI", + BLT: "BLT", + BLTU: "BLTU", + BNE: "BNE", + BSET: "BSET", + BSETI: "BSETI", + CLZ: "CLZ", + CLZW: "CLZW", + CPOP: "CPOP", + CPOPW: "CPOPW", + CSRRC: "CSRRC", + CSRRCI: "CSRRCI", + CSRRS: "CSRRS", + CSRRSI: "CSRRSI", + CSRRW: "CSRRW", + CSRRWI: "CSRRWI", + CTZ: "CTZ", + CTZW: "CTZW", + C_ADD: "C.ADD", + C_ADDI: "C.ADDI", + C_ADDI16SP: "C.ADDI16SP", + C_ADDI4SPN: "C.ADDI4SPN", + C_ADDIW: "C.ADDIW", + C_ADDW: "C.ADDW", + C_AND: "C.AND", + C_ANDI: "C.ANDI", + C_BEQZ: "C.BEQZ", + C_BNEZ: "C.BNEZ", + C_EBREAK: "C.EBREAK", + C_FLD: "C.FLD", + C_FLDSP: "C.FLDSP", + C_FSD: "C.FSD", + C_FSDSP: "C.FSDSP", + C_J: "C.J", + C_JALR: "C.JALR", + C_JR: "C.JR", + C_LD: "C.LD", + C_LDSP: "C.LDSP", + C_LI: "C.LI", + C_LUI: "C.LUI", + C_LW: "C.LW", + C_LWSP: "C.LWSP", + C_MV: "C.MV", + C_NOP: "C.NOP", + C_OR: "C.OR", + C_SD: "C.SD", + C_SDSP: "C.SDSP", + C_SLLI: "C.SLLI", + C_SRAI: "C.SRAI", + C_SRLI: "C.SRLI", + C_SUB: "C.SUB", + C_SUBW: "C.SUBW", + C_SW: "C.SW", + C_SWSP: "C.SWSP", + C_UNIMP: "C.UNIMP", + C_XOR: "C.XOR", + DIV: "DIV", + DIVU: "DIVU", + DIVUW: "DIVUW", + DIVW: "DIVW", + EBREAK: "EBREAK", + ECALL: "ECALL", + FADD_D: "FADD.D", + FADD_H: "FADD.H", + FADD_Q: "FADD.Q", + FADD_S: "FADD.S", + FCLASS_D: "FCLASS.D", + FCLASS_H: "FCLASS.H", + FCLASS_Q: "FCLASS.Q", + FCLASS_S: "FCLASS.S", + FCVT_D_L: "FCVT.D.L", + FCVT_D_LU: "FCVT.D.LU", + FCVT_D_Q: "FCVT.D.Q", + FCVT_D_S: "FCVT.D.S", + FCVT_D_W: "FCVT.D.W", + FCVT_D_WU: "FCVT.D.WU", + FCVT_H_L: "FCVT.H.L", + FCVT_H_LU: "FCVT.H.LU", + FCVT_H_S: "FCVT.H.S", + FCVT_H_W: "FCVT.H.W", + FCVT_H_WU: "FCVT.H.WU", + FCVT_LU_D: "FCVT.LU.D", + FCVT_LU_H: "FCVT.LU.H", + FCVT_LU_Q: "FCVT.LU.Q", + FCVT_LU_S: "FCVT.LU.S", + FCVT_L_D: "FCVT.L.D", + FCVT_L_H: "FCVT.L.H", + FCVT_L_Q: "FCVT.L.Q", + FCVT_L_S: "FCVT.L.S", + FCVT_Q_D: "FCVT.Q.D", + FCVT_Q_L: "FCVT.Q.L", + FCVT_Q_LU: "FCVT.Q.LU", + FCVT_Q_S: "FCVT.Q.S", + FCVT_Q_W: "FCVT.Q.W", + FCVT_Q_WU: "FCVT.Q.WU", + FCVT_S_D: "FCVT.S.D", + FCVT_S_H: "FCVT.S.H", + FCVT_S_L: "FCVT.S.L", + FCVT_S_LU: "FCVT.S.LU", + FCVT_S_Q: "FCVT.S.Q", + FCVT_S_W: "FCVT.S.W", + FCVT_S_WU: "FCVT.S.WU", + FCVT_WU_D: "FCVT.WU.D", + FCVT_WU_H: "FCVT.WU.H", + FCVT_WU_Q: "FCVT.WU.Q", + FCVT_WU_S: "FCVT.WU.S", + FCVT_W_D: "FCVT.W.D", + FCVT_W_H: "FCVT.W.H", + FCVT_W_Q: "FCVT.W.Q", + FCVT_W_S: "FCVT.W.S", + FDIV_D: "FDIV.D", + FDIV_H: "FDIV.H", + FDIV_Q: "FDIV.Q", + FDIV_S: "FDIV.S", + FENCE: "FENCE", + FENCE_I: "FENCE.I", + FEQ_D: "FEQ.D", + FEQ_H: "FEQ.H", + FEQ_Q: "FEQ.Q", + FEQ_S: "FEQ.S", + FLD: "FLD", + FLE_D: "FLE.D", + FLE_H: "FLE.H", + FLE_Q: "FLE.Q", + FLE_S: "FLE.S", + FLH: "FLH", + FLQ: "FLQ", + FLT_D: "FLT.D", + FLT_H: "FLT.H", + FLT_Q: "FLT.Q", + FLT_S: "FLT.S", + FLW: "FLW", + FMADD_D: "FMADD.D", + FMADD_H: "FMADD.H", + FMADD_Q: "FMADD.Q", + FMADD_S: "FMADD.S", + FMAX_D: "FMAX.D", + FMAX_H: "FMAX.H", + FMAX_Q: "FMAX.Q", + FMAX_S: "FMAX.S", + FMIN_D: "FMIN.D", + FMIN_H: "FMIN.H", + FMIN_Q: "FMIN.Q", + FMIN_S: "FMIN.S", + FMSUB_D: "FMSUB.D", + FMSUB_H: "FMSUB.H", + FMSUB_Q: "FMSUB.Q", + FMSUB_S: "FMSUB.S", + FMUL_D: "FMUL.D", + FMUL_H: "FMUL.H", + FMUL_Q: "FMUL.Q", + FMUL_S: "FMUL.S", + FMV_D_X: "FMV.D.X", + FMV_H_X: "FMV.H.X", + FMV_W_X: "FMV.W.X", + FMV_X_D: "FMV.X.D", + FMV_X_H: "FMV.X.H", + FMV_X_W: "FMV.X.W", + FNMADD_D: "FNMADD.D", + FNMADD_H: "FNMADD.H", + FNMADD_Q: "FNMADD.Q", + FNMADD_S: "FNMADD.S", + FNMSUB_D: "FNMSUB.D", + FNMSUB_H: "FNMSUB.H", + FNMSUB_Q: "FNMSUB.Q", + FNMSUB_S: "FNMSUB.S", + FSD: "FSD", + FSGNJN_D: "FSGNJN.D", + FSGNJN_H: "FSGNJN.H", + FSGNJN_Q: "FSGNJN.Q", + FSGNJN_S: "FSGNJN.S", + FSGNJX_D: "FSGNJX.D", + FSGNJX_H: "FSGNJX.H", + FSGNJX_Q: "FSGNJX.Q", + FSGNJX_S: "FSGNJX.S", + FSGNJ_D: "FSGNJ.D", + FSGNJ_H: "FSGNJ.H", + FSGNJ_Q: "FSGNJ.Q", + FSGNJ_S: "FSGNJ.S", + FSH: "FSH", + FSQ: "FSQ", + FSQRT_D: "FSQRT.D", + FSQRT_H: "FSQRT.H", + FSQRT_Q: "FSQRT.Q", + FSQRT_S: "FSQRT.S", + FSUB_D: "FSUB.D", + FSUB_H: "FSUB.H", + FSUB_Q: "FSUB.Q", + FSUB_S: "FSUB.S", + FSW: "FSW", + JAL: "JAL", + JALR: "JALR", + LB: "LB", + LBU: "LBU", + LD: "LD", + LH: "LH", + LHU: "LHU", + LR_D: "LR.D", + LR_D_AQ: "LR.D.AQ", + LR_D_AQRL: "LR.D.AQRL", + LR_D_RL: "LR.D.RL", + LR_W: "LR.W", + LR_W_AQ: "LR.W.AQ", + LR_W_AQRL: "LR.W.AQRL", + LR_W_RL: "LR.W.RL", + LUI: "LUI", + LW: "LW", + LWU: "LWU", + MAX: "MAX", + MAXU: "MAXU", + MIN: "MIN", + MINU: "MINU", + MUL: "MUL", + MULH: "MULH", + MULHSU: "MULHSU", + MULHU: "MULHU", + MULW: "MULW", + OR: "OR", + ORC_B: "ORC.B", + ORI: "ORI", + ORN: "ORN", + REM: "REM", + REMU: "REMU", + REMUW: "REMUW", + REMW: "REMW", + REV8: "REV8", + ROL: "ROL", + ROLW: "ROLW", + ROR: "ROR", + RORI: "RORI", + RORIW: "RORIW", + RORW: "RORW", + SB: "SB", + SC_D: "SC.D", + SC_D_AQ: "SC.D.AQ", + SC_D_AQRL: "SC.D.AQRL", + SC_D_RL: "SC.D.RL", + SC_W: "SC.W", + SC_W_AQ: "SC.W.AQ", + SC_W_AQRL: "SC.W.AQRL", + SC_W_RL: "SC.W.RL", + SD: "SD", + SEXT_B: "SEXT.B", + SEXT_H: "SEXT.H", + SH: "SH", + SH1ADD: "SH1ADD", + SH1ADD_UW: "SH1ADD.UW", + SH2ADD: "SH2ADD", + SH2ADD_UW: "SH2ADD.UW", + SH3ADD: "SH3ADD", + SH3ADD_UW: "SH3ADD.UW", + SLL: "SLL", + SLLI: "SLLI", + SLLIW: "SLLIW", + SLLI_UW: "SLLI.UW", + SLLW: "SLLW", + SLT: "SLT", + SLTI: "SLTI", + SLTIU: "SLTIU", + SLTU: "SLTU", + SRA: "SRA", + SRAI: "SRAI", + SRAIW: "SRAIW", + SRAW: "SRAW", + SRL: "SRL", + SRLI: "SRLI", + SRLIW: "SRLIW", + SRLW: "SRLW", + SUB: "SUB", + SUBW: "SUBW", + SW: "SW", + XNOR: "XNOR", + XOR: "XOR", + XORI: "XORI", + ZEXT_H: "ZEXT.H", +} + +var instFormats = [...]instFormat{ + // ADD rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x00000033, op: ADD, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // ADDI rd, rs1, imm12 + {mask: 0x0000707f, value: 0x00000013, op: ADDI, args: argTypeList{arg_rd, arg_rs1, arg_imm12}}, + // ADDIW rd, rs1, imm12 + {mask: 0x0000707f, value: 0x0000001b, op: ADDIW, args: argTypeList{arg_rd, arg_rs1, arg_imm12}}, + // ADDW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x0000003b, op: ADDW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // ADD.UW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x0800003b, op: ADD_UW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // AMOADD.D rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0000302f, op: AMOADD_D, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOADD.D.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0400302f, op: AMOADD_D_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOADD.D.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0600302f, op: AMOADD_D_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOADD.D.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0200302f, op: AMOADD_D_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOADD.W rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0000202f, op: AMOADD_W, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOADD.W.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0400202f, op: AMOADD_W_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOADD.W.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0600202f, op: AMOADD_W_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOADD.W.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0200202f, op: AMOADD_W_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOAND.D rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x6000302f, op: AMOAND_D, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOAND.D.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x6400302f, op: AMOAND_D_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOAND.D.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x6600302f, op: AMOAND_D_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOAND.D.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x6200302f, op: AMOAND_D_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOAND.W rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x6000202f, op: AMOAND_W, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOAND.W.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x6400202f, op: AMOAND_W_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOAND.W.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x6600202f, op: AMOAND_W_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOAND.W.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x6200202f, op: AMOAND_W_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAXU.D rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xe000302f, op: AMOMAXU_D, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAXU.D.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xe400302f, op: AMOMAXU_D_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAXU.D.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xe600302f, op: AMOMAXU_D_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAXU.D.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xe200302f, op: AMOMAXU_D_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAXU.W rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xe000202f, op: AMOMAXU_W, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAXU.W.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xe400202f, op: AMOMAXU_W_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAXU.W.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xe600202f, op: AMOMAXU_W_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAXU.W.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xe200202f, op: AMOMAXU_W_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAX.D rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xa000302f, op: AMOMAX_D, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAX.D.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xa400302f, op: AMOMAX_D_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAX.D.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xa600302f, op: AMOMAX_D_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAX.D.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xa200302f, op: AMOMAX_D_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAX.W rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xa000202f, op: AMOMAX_W, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAX.W.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xa400202f, op: AMOMAX_W_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAX.W.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xa600202f, op: AMOMAX_W_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMAX.W.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xa200202f, op: AMOMAX_W_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMINU.D rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xc000302f, op: AMOMINU_D, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMINU.D.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xc400302f, op: AMOMINU_D_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMINU.D.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xc600302f, op: AMOMINU_D_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMINU.D.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xc200302f, op: AMOMINU_D_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMINU.W rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xc000202f, op: AMOMINU_W, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMINU.W.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xc400202f, op: AMOMINU_W_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMINU.W.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xc600202f, op: AMOMINU_W_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMINU.W.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0xc200202f, op: AMOMINU_W_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMIN.D rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x8000302f, op: AMOMIN_D, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMIN.D.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x8400302f, op: AMOMIN_D_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMIN.D.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x8600302f, op: AMOMIN_D_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMIN.D.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x8200302f, op: AMOMIN_D_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMIN.W rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x8000202f, op: AMOMIN_W, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMIN.W.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x8400202f, op: AMOMIN_W_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMIN.W.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x8600202f, op: AMOMIN_W_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOMIN.W.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x8200202f, op: AMOMIN_W_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOOR.D rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x4000302f, op: AMOOR_D, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOOR.D.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x4400302f, op: AMOOR_D_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOOR.D.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x4600302f, op: AMOOR_D_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOOR.D.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x4200302f, op: AMOOR_D_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOOR.W rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x4000202f, op: AMOOR_W, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOOR.W.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x4400202f, op: AMOOR_W_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOOR.W.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x4600202f, op: AMOOR_W_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOOR.W.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x4200202f, op: AMOOR_W_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOSWAP.D rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0800302f, op: AMOSWAP_D, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOSWAP.D.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0c00302f, op: AMOSWAP_D_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOSWAP.D.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0e00302f, op: AMOSWAP_D_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOSWAP.D.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0a00302f, op: AMOSWAP_D_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOSWAP.W rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0800202f, op: AMOSWAP_W, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOSWAP.W.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0c00202f, op: AMOSWAP_W_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOSWAP.W.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0e00202f, op: AMOSWAP_W_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOSWAP.W.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x0a00202f, op: AMOSWAP_W_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOXOR.D rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x2000302f, op: AMOXOR_D, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOXOR.D.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x2400302f, op: AMOXOR_D_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOXOR.D.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x2600302f, op: AMOXOR_D_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOXOR.D.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x2200302f, op: AMOXOR_D_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOXOR.W rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x2000202f, op: AMOXOR_W, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOXOR.W.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x2400202f, op: AMOXOR_W_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOXOR.W.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x2600202f, op: AMOXOR_W_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AMOXOR.W.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x2200202f, op: AMOXOR_W_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // AND rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x00007033, op: AND, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // ANDI rd, rs1, imm12 + {mask: 0x0000707f, value: 0x00007013, op: ANDI, args: argTypeList{arg_rd, arg_rs1, arg_imm12}}, + // ANDN rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x40007033, op: ANDN, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // AUIPC rd, imm20 + {mask: 0x0000007f, value: 0x00000017, op: AUIPC, args: argTypeList{arg_rd, arg_imm20}}, + // BCLR rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x48001033, op: BCLR, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // BCLRI rd, rs1, shamt6 + {mask: 0xfc00707f, value: 0x48001013, op: BCLRI, args: argTypeList{arg_rd, arg_rs1, arg_shamt6}}, + // BEQ rs1, rs2, bimm12 + {mask: 0x0000707f, value: 0x00000063, op: BEQ, args: argTypeList{arg_rs1, arg_rs2, arg_bimm12}}, + // BEXT rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x48005033, op: BEXT, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // BEXTI rd, rs1, shamt6 + {mask: 0xfc00707f, value: 0x48005013, op: BEXTI, args: argTypeList{arg_rd, arg_rs1, arg_shamt6}}, + // BGE rs1, rs2, bimm12 + {mask: 0x0000707f, value: 0x00005063, op: BGE, args: argTypeList{arg_rs1, arg_rs2, arg_bimm12}}, + // BGEU rs1, rs2, bimm12 + {mask: 0x0000707f, value: 0x00007063, op: BGEU, args: argTypeList{arg_rs1, arg_rs2, arg_bimm12}}, + // BINV rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x68001033, op: BINV, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // BINVI rd, rs1, shamt6 + {mask: 0xfc00707f, value: 0x68001013, op: BINVI, args: argTypeList{arg_rd, arg_rs1, arg_shamt6}}, + // BLT rs1, rs2, bimm12 + {mask: 0x0000707f, value: 0x00004063, op: BLT, args: argTypeList{arg_rs1, arg_rs2, arg_bimm12}}, + // BLTU rs1, rs2, bimm12 + {mask: 0x0000707f, value: 0x00006063, op: BLTU, args: argTypeList{arg_rs1, arg_rs2, arg_bimm12}}, + // BNE rs1, rs2, bimm12 + {mask: 0x0000707f, value: 0x00001063, op: BNE, args: argTypeList{arg_rs1, arg_rs2, arg_bimm12}}, + // BSET rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x28001033, op: BSET, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // BSETI rd, rs1, shamt6 + {mask: 0xfc00707f, value: 0x28001013, op: BSETI, args: argTypeList{arg_rd, arg_rs1, arg_shamt6}}, + // CLZ rd, rs1 + {mask: 0xfff0707f, value: 0x60001013, op: CLZ, args: argTypeList{arg_rd, arg_rs1}}, + // CLZW rd, rs1 + {mask: 0xfff0707f, value: 0x6000101b, op: CLZW, args: argTypeList{arg_rd, arg_rs1}}, + // CPOP rd, rs1 + {mask: 0xfff0707f, value: 0x60201013, op: CPOP, args: argTypeList{arg_rd, arg_rs1}}, + // CPOPW rd, rs1 + {mask: 0xfff0707f, value: 0x6020101b, op: CPOPW, args: argTypeList{arg_rd, arg_rs1}}, + // CSRRC rd, csr, rs1 + {mask: 0x0000707f, value: 0x00003073, op: CSRRC, args: argTypeList{arg_rd, arg_csr, arg_rs1}}, + // CSRRCI rd, csr, zimm + {mask: 0x0000707f, value: 0x00007073, op: CSRRCI, args: argTypeList{arg_rd, arg_csr, arg_zimm}}, + // CSRRS rd, csr, rs1 + {mask: 0x0000707f, value: 0x00002073, op: CSRRS, args: argTypeList{arg_rd, arg_csr, arg_rs1}}, + // CSRRSI rd, csr, zimm + {mask: 0x0000707f, value: 0x00006073, op: CSRRSI, args: argTypeList{arg_rd, arg_csr, arg_zimm}}, + // CSRRW rd, csr, rs1 + {mask: 0x0000707f, value: 0x00001073, op: CSRRW, args: argTypeList{arg_rd, arg_csr, arg_rs1}}, + // CSRRWI rd, csr, zimm + {mask: 0x0000707f, value: 0x00005073, op: CSRRWI, args: argTypeList{arg_rd, arg_csr, arg_zimm}}, + // CTZ rd, rs1 + {mask: 0xfff0707f, value: 0x60101013, op: CTZ, args: argTypeList{arg_rd, arg_rs1}}, + // CTZW rd, rs1 + {mask: 0xfff0707f, value: 0x6010101b, op: CTZW, args: argTypeList{arg_rd, arg_rs1}}, + // C.ADD rd_rs1_n0, c_rs2_n0 + {mask: 0x0000f003, value: 0x00009002, op: C_ADD, args: argTypeList{arg_rd_rs1_n0, arg_c_rs2_n0}}, + // C.ADDI rd_rs1_n0, c_nzimm6 + {mask: 0x0000e003, value: 0x00000001, op: C_ADDI, args: argTypeList{arg_rd_rs1_n0, arg_c_nzimm6}}, + // C.ADDI16SP c_nzimm10 + {mask: 0x0000ef83, value: 0x00006101, op: C_ADDI16SP, args: argTypeList{arg_c_nzimm10}}, + // C.ADDI4SPN rd_p, c_nzuimm10 + {mask: 0x0000e003, value: 0x00000000, op: C_ADDI4SPN, args: argTypeList{arg_rd_p, arg_c_nzuimm10}}, + // C.ADDIW rd_rs1_n0, c_imm6 + {mask: 0x0000e003, value: 0x00002001, op: C_ADDIW, args: argTypeList{arg_rd_rs1_n0, arg_c_imm6}}, + // C.ADDW rd_rs1_p, rs2_p + {mask: 0x0000fc63, value: 0x00009c21, op: C_ADDW, args: argTypeList{arg_rd_rs1_p, arg_rs2_p}}, + // C.AND rd_rs1_p, rs2_p + {mask: 0x0000fc63, value: 0x00008c61, op: C_AND, args: argTypeList{arg_rd_rs1_p, arg_rs2_p}}, + // C.ANDI rd_rs1_p, c_imm6 + {mask: 0x0000ec03, value: 0x00008801, op: C_ANDI, args: argTypeList{arg_rd_rs1_p, arg_c_imm6}}, + // C.BEQZ rs1_p, c_bimm9 + {mask: 0x0000e003, value: 0x0000c001, op: C_BEQZ, args: argTypeList{arg_rs1_p, arg_c_bimm9}}, + // C.BNEZ rs1_p, c_bimm9 + {mask: 0x0000e003, value: 0x0000e001, op: C_BNEZ, args: argTypeList{arg_rs1_p, arg_c_bimm9}}, + // C.EBREAK + {mask: 0x0000ffff, value: 0x00009002, op: C_EBREAK, args: argTypeList{}}, + // C.FLD fd_p, rs1_p, c_uimm8 + {mask: 0x0000e003, value: 0x00002000, op: C_FLD, args: argTypeList{arg_fd_p, arg_rs1_p, arg_c_uimm8}}, + // C.FLDSP fd, c_uimm9sp + {mask: 0x0000e003, value: 0x00002002, op: C_FLDSP, args: argTypeList{arg_fd, arg_c_uimm9sp}}, + // C.FSD rs1_p, fs2_p, c_uimm8 + {mask: 0x0000e003, value: 0x0000a000, op: C_FSD, args: argTypeList{arg_rs1_p, arg_fs2_p, arg_c_uimm8}}, + // C.FSDSP c_fs2, c_uimm9sp_s + {mask: 0x0000e003, value: 0x0000a002, op: C_FSDSP, args: argTypeList{arg_c_fs2, arg_c_uimm9sp_s}}, + // C.J c_imm12 + {mask: 0x0000e003, value: 0x0000a001, op: C_J, args: argTypeList{arg_c_imm12}}, + // C.JALR c_rs1_n0 + {mask: 0x0000f07f, value: 0x00009002, op: C_JALR, args: argTypeList{arg_c_rs1_n0}}, + // C.JR rs1_n0 + {mask: 0x0000f07f, value: 0x00008002, op: C_JR, args: argTypeList{arg_rs1_n0}}, + // C.LD rd_p, rs1_p, c_uimm8 + {mask: 0x0000e003, value: 0x00006000, op: C_LD, args: argTypeList{arg_rd_p, arg_rs1_p, arg_c_uimm8}}, + // C.LDSP rd_n0, c_uimm9sp + {mask: 0x0000e003, value: 0x00006002, op: C_LDSP, args: argTypeList{arg_rd_n0, arg_c_uimm9sp}}, + // C.LI rd_n0, c_imm6 + {mask: 0x0000e003, value: 0x00004001, op: C_LI, args: argTypeList{arg_rd_n0, arg_c_imm6}}, + // C.LUI rd_n2, c_nzimm18 + {mask: 0x0000e003, value: 0x00006001, op: C_LUI, args: argTypeList{arg_rd_n2, arg_c_nzimm18}}, + // C.LW rd_p, rs1_p, c_uimm7 + {mask: 0x0000e003, value: 0x00004000, op: C_LW, args: argTypeList{arg_rd_p, arg_rs1_p, arg_c_uimm7}}, + // C.LWSP rd_n0, c_uimm8sp + {mask: 0x0000e003, value: 0x00004002, op: C_LWSP, args: argTypeList{arg_rd_n0, arg_c_uimm8sp}}, + // C.MV rd_n0, c_rs2_n0 + {mask: 0x0000f003, value: 0x00008002, op: C_MV, args: argTypeList{arg_rd_n0, arg_c_rs2_n0}}, + // C.NOP c_nzimm6 + {mask: 0x0000ef83, value: 0x00000001, op: C_NOP, args: argTypeList{arg_c_nzimm6}}, + // C.OR rd_rs1_p, rs2_p + {mask: 0x0000fc63, value: 0x00008c41, op: C_OR, args: argTypeList{arg_rd_rs1_p, arg_rs2_p}}, + // C.SD rs1_p, rs2_p, c_uimm8 + {mask: 0x0000e003, value: 0x0000e000, op: C_SD, args: argTypeList{arg_rs1_p, arg_rs2_p, arg_c_uimm8}}, + // C.SDSP c_rs2, c_uimm9sp_s + {mask: 0x0000e003, value: 0x0000e002, op: C_SDSP, args: argTypeList{arg_c_rs2, arg_c_uimm9sp_s}}, + // C.SLLI rd_rs1_n0, c_nzuimm6 + {mask: 0x0000e003, value: 0x00000002, op: C_SLLI, args: argTypeList{arg_rd_rs1_n0, arg_c_nzuimm6}}, + // C.SRAI rd_rs1_p, c_nzuimm6 + {mask: 0x0000ec03, value: 0x00008401, op: C_SRAI, args: argTypeList{arg_rd_rs1_p, arg_c_nzuimm6}}, + // C.SRLI rd_rs1_p, c_nzuimm6 + {mask: 0x0000ec03, value: 0x00008001, op: C_SRLI, args: argTypeList{arg_rd_rs1_p, arg_c_nzuimm6}}, + // C.SUB rd_rs1_p, rs2_p + {mask: 0x0000fc63, value: 0x00008c01, op: C_SUB, args: argTypeList{arg_rd_rs1_p, arg_rs2_p}}, + // C.SUBW rd_rs1_p, rs2_p + {mask: 0x0000fc63, value: 0x00009c01, op: C_SUBW, args: argTypeList{arg_rd_rs1_p, arg_rs2_p}}, + // C.SW rs1_p, rs2_p, c_uimm7 + {mask: 0x0000e003, value: 0x0000c000, op: C_SW, args: argTypeList{arg_rs1_p, arg_rs2_p, arg_c_uimm7}}, + // C.SWSP c_rs2, c_uimm8sp_s + {mask: 0x0000e003, value: 0x0000c002, op: C_SWSP, args: argTypeList{arg_c_rs2, arg_c_uimm8sp_s}}, + // C.UNIMP + {mask: 0x0000ffff, value: 0x00000000, op: C_UNIMP, args: argTypeList{}}, + // C.XOR rd_rs1_p, rs2_p + {mask: 0x0000fc63, value: 0x00008c21, op: C_XOR, args: argTypeList{arg_rd_rs1_p, arg_rs2_p}}, + // DIV rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x02004033, op: DIV, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // DIVU rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x02005033, op: DIVU, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // DIVUW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x0200503b, op: DIVUW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // DIVW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x0200403b, op: DIVW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // EBREAK + {mask: 0xffffffff, value: 0x00100073, op: EBREAK, args: argTypeList{}}, + // ECALL + {mask: 0xffffffff, value: 0x00000073, op: ECALL, args: argTypeList{}}, + // FADD.D fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x02000053, op: FADD_D, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FADD.H fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x04000053, op: FADD_H, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FADD.Q fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x06000053, op: FADD_Q, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FADD.S fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x00000053, op: FADD_S, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FCLASS.D rd, fs1 + {mask: 0xfff0707f, value: 0xe2001053, op: FCLASS_D, args: argTypeList{arg_rd, arg_fs1}}, + // FCLASS.H rd, fs1 + {mask: 0xfff0707f, value: 0xe4001053, op: FCLASS_H, args: argTypeList{arg_rd, arg_fs1}}, + // FCLASS.Q rd, fs1 + {mask: 0xfff0707f, value: 0xe6001053, op: FCLASS_Q, args: argTypeList{arg_rd, arg_fs1}}, + // FCLASS.S rd, fs1 + {mask: 0xfff0707f, value: 0xe0001053, op: FCLASS_S, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.D.L fd, rs1 + {mask: 0xfff0007f, value: 0xd2200053, op: FCVT_D_L, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.D.LU fd, rs1 + {mask: 0xfff0007f, value: 0xd2300053, op: FCVT_D_LU, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.D.Q fd, fs1 + {mask: 0xfff0007f, value: 0x42300053, op: FCVT_D_Q, args: argTypeList{arg_fd, arg_fs1}}, + // FCVT.D.S fd, fs1 + {mask: 0xfff0007f, value: 0x42000053, op: FCVT_D_S, args: argTypeList{arg_fd, arg_fs1}}, + // FCVT.D.W fd, rs1 + {mask: 0xfff0007f, value: 0xd2000053, op: FCVT_D_W, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.D.WU fd, rs1 + {mask: 0xfff0007f, value: 0xd2100053, op: FCVT_D_WU, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.H.L fd, rs1 + {mask: 0xfff0007f, value: 0xd4200053, op: FCVT_H_L, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.H.LU fd, rs1 + {mask: 0xfff0007f, value: 0xd4300053, op: FCVT_H_LU, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.H.S fd, fs1 + {mask: 0xfff0007f, value: 0x44000053, op: FCVT_H_S, args: argTypeList{arg_fd, arg_fs1}}, + // FCVT.H.W fd, rs1 + {mask: 0xfff0007f, value: 0xd4000053, op: FCVT_H_W, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.H.WU fd, rs1 + {mask: 0xfff0007f, value: 0xd4100053, op: FCVT_H_WU, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.LU.D rd, fs1 + {mask: 0xfff0007f, value: 0xc2300053, op: FCVT_LU_D, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.LU.H rd, fs1 + {mask: 0xfff0007f, value: 0xc4300053, op: FCVT_LU_H, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.LU.Q rd, fs1 + {mask: 0xfff0007f, value: 0xc6300053, op: FCVT_LU_Q, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.LU.S rd, fs1 + {mask: 0xfff0007f, value: 0xc0300053, op: FCVT_LU_S, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.L.D rd, fs1 + {mask: 0xfff0007f, value: 0xc2200053, op: FCVT_L_D, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.L.H rd, fs1 + {mask: 0xfff0007f, value: 0xc4200053, op: FCVT_L_H, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.L.Q rd, fs1 + {mask: 0xfff0007f, value: 0xc6200053, op: FCVT_L_Q, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.L.S rd, fs1 + {mask: 0xfff0007f, value: 0xc0200053, op: FCVT_L_S, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.Q.D fd, fs1 + {mask: 0xfff0007f, value: 0x46100053, op: FCVT_Q_D, args: argTypeList{arg_fd, arg_fs1}}, + // FCVT.Q.L fd, rs1 + {mask: 0xfff0007f, value: 0xd6200053, op: FCVT_Q_L, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.Q.LU fd, rs1 + {mask: 0xfff0007f, value: 0xd6300053, op: FCVT_Q_LU, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.Q.S fd, fs1 + {mask: 0xfff0007f, value: 0x46000053, op: FCVT_Q_S, args: argTypeList{arg_fd, arg_fs1}}, + // FCVT.Q.W fd, rs1 + {mask: 0xfff0007f, value: 0xd6000053, op: FCVT_Q_W, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.Q.WU fd, rs1 + {mask: 0xfff0007f, value: 0xd6100053, op: FCVT_Q_WU, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.S.D fd, fs1 + {mask: 0xfff0007f, value: 0x40100053, op: FCVT_S_D, args: argTypeList{arg_fd, arg_fs1}}, + // FCVT.S.H fd, fs1 + {mask: 0xfff0007f, value: 0x40200053, op: FCVT_S_H, args: argTypeList{arg_fd, arg_fs1}}, + // FCVT.S.L fd, rs1 + {mask: 0xfff0007f, value: 0xd0200053, op: FCVT_S_L, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.S.LU fd, rs1 + {mask: 0xfff0007f, value: 0xd0300053, op: FCVT_S_LU, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.S.Q fd, fs1 + {mask: 0xfff0007f, value: 0x40300053, op: FCVT_S_Q, args: argTypeList{arg_fd, arg_fs1}}, + // FCVT.S.W fd, rs1 + {mask: 0xfff0007f, value: 0xd0000053, op: FCVT_S_W, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.S.WU fd, rs1 + {mask: 0xfff0007f, value: 0xd0100053, op: FCVT_S_WU, args: argTypeList{arg_fd, arg_rs1}}, + // FCVT.WU.D rd, fs1 + {mask: 0xfff0007f, value: 0xc2100053, op: FCVT_WU_D, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.WU.H rd, fs1 + {mask: 0xfff0007f, value: 0xc4100053, op: FCVT_WU_H, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.WU.Q rd, fs1 + {mask: 0xfff0007f, value: 0xc6100053, op: FCVT_WU_Q, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.WU.S rd, fs1 + {mask: 0xfff0007f, value: 0xc0100053, op: FCVT_WU_S, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.W.D rd, fs1 + {mask: 0xfff0007f, value: 0xc2000053, op: FCVT_W_D, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.W.H rd, fs1 + {mask: 0xfff0007f, value: 0xc4000053, op: FCVT_W_H, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.W.Q rd, fs1 + {mask: 0xfff0007f, value: 0xc6000053, op: FCVT_W_Q, args: argTypeList{arg_rd, arg_fs1}}, + // FCVT.W.S rd, fs1 + {mask: 0xfff0007f, value: 0xc0000053, op: FCVT_W_S, args: argTypeList{arg_rd, arg_fs1}}, + // FDIV.D fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x1a000053, op: FDIV_D, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FDIV.H fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x1c000053, op: FDIV_H, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FDIV.Q fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x1e000053, op: FDIV_Q, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FDIV.S fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x18000053, op: FDIV_S, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FENCE pred, succ + {mask: 0x0000707f, value: 0x0000000f, op: FENCE, args: argTypeList{arg_pred, arg_succ}}, + // FENCE.I + {mask: 0x0000707f, value: 0x0000100f, op: FENCE_I, args: argTypeList{}}, + // FEQ.D rd, fs1, fs2 + {mask: 0xfe00707f, value: 0xa2002053, op: FEQ_D, args: argTypeList{arg_rd, arg_fs1, arg_fs2}}, + // FEQ.H rd, fs1, fs2 + {mask: 0xfe00707f, value: 0xa4002053, op: FEQ_H, args: argTypeList{arg_rd, arg_fs1, arg_fs2}}, + // FEQ.Q rd, fs1, fs2 + {mask: 0xfe00707f, value: 0xa6002053, op: FEQ_Q, args: argTypeList{arg_rd, arg_fs1, arg_fs2}}, + // FEQ.S rd, fs1, fs2 + {mask: 0xfe00707f, value: 0xa0002053, op: FEQ_S, args: argTypeList{arg_rd, arg_fs1, arg_fs2}}, + // FLD fd, rs1_mem + {mask: 0x0000707f, value: 0x00003007, op: FLD, args: argTypeList{arg_fd, arg_rs1_mem}}, + // FLE.D rd, fs1, fs2 + {mask: 0xfe00707f, value: 0xa2000053, op: FLE_D, args: argTypeList{arg_rd, arg_fs1, arg_fs2}}, + // FLE.H rd, fs1, fs2 + {mask: 0xfe00707f, value: 0xa4000053, op: FLE_H, args: argTypeList{arg_rd, arg_fs1, arg_fs2}}, + // FLE.Q rd, fs1, fs2 + {mask: 0xfe00707f, value: 0xa6000053, op: FLE_Q, args: argTypeList{arg_rd, arg_fs1, arg_fs2}}, + // FLE.S rd, fs1, fs2 + {mask: 0xfe00707f, value: 0xa0000053, op: FLE_S, args: argTypeList{arg_rd, arg_fs1, arg_fs2}}, + // FLH fd, rs1_mem + {mask: 0x0000707f, value: 0x00001007, op: FLH, args: argTypeList{arg_fd, arg_rs1_mem}}, + // FLQ fd, rs1_mem + {mask: 0x0000707f, value: 0x00004007, op: FLQ, args: argTypeList{arg_fd, arg_rs1_mem}}, + // FLT.D rd, fs1, fs2 + {mask: 0xfe00707f, value: 0xa2001053, op: FLT_D, args: argTypeList{arg_rd, arg_fs1, arg_fs2}}, + // FLT.H rd, fs1, fs2 + {mask: 0xfe00707f, value: 0xa4001053, op: FLT_H, args: argTypeList{arg_rd, arg_fs1, arg_fs2}}, + // FLT.Q rd, fs1, fs2 + {mask: 0xfe00707f, value: 0xa6001053, op: FLT_Q, args: argTypeList{arg_rd, arg_fs1, arg_fs2}}, + // FLT.S rd, fs1, fs2 + {mask: 0xfe00707f, value: 0xa0001053, op: FLT_S, args: argTypeList{arg_rd, arg_fs1, arg_fs2}}, + // FLW fd, rs1_mem + {mask: 0x0000707f, value: 0x00002007, op: FLW, args: argTypeList{arg_fd, arg_rs1_mem}}, + // FMADD.D fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x02000043, op: FMADD_D, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FMADD.H fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x04000043, op: FMADD_H, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FMADD.Q fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x06000043, op: FMADD_Q, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FMADD.S fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x00000043, op: FMADD_S, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FMAX.D fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x2a001053, op: FMAX_D, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FMAX.H fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x2c001053, op: FMAX_H, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FMAX.Q fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x2e001053, op: FMAX_Q, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FMAX.S fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x28001053, op: FMAX_S, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FMIN.D fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x2a000053, op: FMIN_D, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FMIN.H fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x2c000053, op: FMIN_H, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FMIN.Q fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x2e000053, op: FMIN_Q, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FMIN.S fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x28000053, op: FMIN_S, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FMSUB.D fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x02000047, op: FMSUB_D, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FMSUB.H fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x04000047, op: FMSUB_H, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FMSUB.Q fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x06000047, op: FMSUB_Q, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FMSUB.S fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x00000047, op: FMSUB_S, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FMUL.D fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x12000053, op: FMUL_D, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FMUL.H fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x14000053, op: FMUL_H, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FMUL.Q fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x16000053, op: FMUL_Q, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FMUL.S fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x10000053, op: FMUL_S, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FMV.D.X fd, rs1 + {mask: 0xfff0707f, value: 0xf2000053, op: FMV_D_X, args: argTypeList{arg_fd, arg_rs1}}, + // FMV.H.X fd, rs1 + {mask: 0xfff0707f, value: 0xf4000053, op: FMV_H_X, args: argTypeList{arg_fd, arg_rs1}}, + // FMV.W.X fd, rs1 + {mask: 0xfff0707f, value: 0xf0000053, op: FMV_W_X, args: argTypeList{arg_fd, arg_rs1}}, + // FMV.X.D rd, fs1 + {mask: 0xfff0707f, value: 0xe2000053, op: FMV_X_D, args: argTypeList{arg_rd, arg_fs1}}, + // FMV.X.H rd, fs1 + {mask: 0xfff0707f, value: 0xe4000053, op: FMV_X_H, args: argTypeList{arg_rd, arg_fs1}}, + // FMV.X.W rd, fs1 + {mask: 0xfff0707f, value: 0xe0000053, op: FMV_X_W, args: argTypeList{arg_rd, arg_fs1}}, + // FNMADD.D fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x0200004f, op: FNMADD_D, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FNMADD.H fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x0400004f, op: FNMADD_H, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FNMADD.Q fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x0600004f, op: FNMADD_Q, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FNMADD.S fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x0000004f, op: FNMADD_S, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FNMSUB.D fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x0200004b, op: FNMSUB_D, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FNMSUB.H fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x0400004b, op: FNMSUB_H, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FNMSUB.Q fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x0600004b, op: FNMSUB_Q, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FNMSUB.S fd, fs1, fs2, fs3 + {mask: 0x0600007f, value: 0x0000004b, op: FNMSUB_S, args: argTypeList{arg_fd, arg_fs1, arg_fs2, arg_fs3}}, + // FSD fs2, rs1_store + {mask: 0x0000707f, value: 0x00003027, op: FSD, args: argTypeList{arg_fs2, arg_rs1_store}}, + // FSGNJN.D fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x22001053, op: FSGNJN_D, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSGNJN.H fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x24001053, op: FSGNJN_H, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSGNJN.Q fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x26001053, op: FSGNJN_Q, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSGNJN.S fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x20001053, op: FSGNJN_S, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSGNJX.D fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x22002053, op: FSGNJX_D, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSGNJX.H fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x24002053, op: FSGNJX_H, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSGNJX.Q fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x26002053, op: FSGNJX_Q, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSGNJX.S fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x20002053, op: FSGNJX_S, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSGNJ.D fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x22000053, op: FSGNJ_D, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSGNJ.H fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x24000053, op: FSGNJ_H, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSGNJ.Q fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x26000053, op: FSGNJ_Q, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSGNJ.S fd, fs1, fs2 + {mask: 0xfe00707f, value: 0x20000053, op: FSGNJ_S, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSH fs2, rs1_store + {mask: 0x0000707f, value: 0x00001027, op: FSH, args: argTypeList{arg_fs2, arg_rs1_store}}, + // FSQ fs2, rs1_store + {mask: 0x0000707f, value: 0x00004027, op: FSQ, args: argTypeList{arg_fs2, arg_rs1_store}}, + // FSQRT.D fd, fs1 + {mask: 0xfff0007f, value: 0x5a000053, op: FSQRT_D, args: argTypeList{arg_fd, arg_fs1}}, + // FSQRT.H fd, fs1 + {mask: 0xfff0007f, value: 0x5c000053, op: FSQRT_H, args: argTypeList{arg_fd, arg_fs1}}, + // FSQRT.Q fd, fs1 + {mask: 0xfff0007f, value: 0x5e000053, op: FSQRT_Q, args: argTypeList{arg_fd, arg_fs1}}, + // FSQRT.S fd, fs1 + {mask: 0xfff0007f, value: 0x58000053, op: FSQRT_S, args: argTypeList{arg_fd, arg_fs1}}, + // FSUB.D fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x0a000053, op: FSUB_D, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSUB.H fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x0c000053, op: FSUB_H, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSUB.Q fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x0e000053, op: FSUB_Q, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSUB.S fd, fs1, fs2 + {mask: 0xfe00007f, value: 0x08000053, op: FSUB_S, args: argTypeList{arg_fd, arg_fs1, arg_fs2}}, + // FSW fs2, rs1_store + {mask: 0x0000707f, value: 0x00002027, op: FSW, args: argTypeList{arg_fs2, arg_rs1_store}}, + // JAL rd, jimm20 + {mask: 0x0000007f, value: 0x0000006f, op: JAL, args: argTypeList{arg_rd, arg_jimm20}}, + // JALR rd, rs1_mem + {mask: 0x0000707f, value: 0x00000067, op: JALR, args: argTypeList{arg_rd, arg_rs1_mem}}, + // LB rd, rs1_mem + {mask: 0x0000707f, value: 0x00000003, op: LB, args: argTypeList{arg_rd, arg_rs1_mem}}, + // LBU rd, rs1_mem + {mask: 0x0000707f, value: 0x00004003, op: LBU, args: argTypeList{arg_rd, arg_rs1_mem}}, + // LD rd, rs1_mem + {mask: 0x0000707f, value: 0x00003003, op: LD, args: argTypeList{arg_rd, arg_rs1_mem}}, + // LH rd, rs1_mem + {mask: 0x0000707f, value: 0x00001003, op: LH, args: argTypeList{arg_rd, arg_rs1_mem}}, + // LHU rd, rs1_mem + {mask: 0x0000707f, value: 0x00005003, op: LHU, args: argTypeList{arg_rd, arg_rs1_mem}}, + // LR.D rd, rs1_amo + {mask: 0xfff0707f, value: 0x1000302f, op: LR_D, args: argTypeList{arg_rd, arg_rs1_amo}}, + // LR.D.AQ rd, rs1_amo + {mask: 0xfff0707f, value: 0x1400302f, op: LR_D_AQ, args: argTypeList{arg_rd, arg_rs1_amo}}, + // LR.D.AQRL rd, rs1_amo + {mask: 0xfff0707f, value: 0x1600302f, op: LR_D_AQRL, args: argTypeList{arg_rd, arg_rs1_amo}}, + // LR.D.RL rd, rs1_amo + {mask: 0xfff0707f, value: 0x1200302f, op: LR_D_RL, args: argTypeList{arg_rd, arg_rs1_amo}}, + // LR.W rd, rs1_amo + {mask: 0xfff0707f, value: 0x1000202f, op: LR_W, args: argTypeList{arg_rd, arg_rs1_amo}}, + // LR.W.AQ rd, rs1_amo + {mask: 0xfff0707f, value: 0x1400202f, op: LR_W_AQ, args: argTypeList{arg_rd, arg_rs1_amo}}, + // LR.W.AQRL rd, rs1_amo + {mask: 0xfff0707f, value: 0x1600202f, op: LR_W_AQRL, args: argTypeList{arg_rd, arg_rs1_amo}}, + // LR.W.RL rd, rs1_amo + {mask: 0xfff0707f, value: 0x1200202f, op: LR_W_RL, args: argTypeList{arg_rd, arg_rs1_amo}}, + // LUI rd, imm20 + {mask: 0x0000007f, value: 0x00000037, op: LUI, args: argTypeList{arg_rd, arg_imm20}}, + // LW rd, rs1_mem + {mask: 0x0000707f, value: 0x00002003, op: LW, args: argTypeList{arg_rd, arg_rs1_mem}}, + // LWU rd, rs1_mem + {mask: 0x0000707f, value: 0x00006003, op: LWU, args: argTypeList{arg_rd, arg_rs1_mem}}, + // MAX rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x0a006033, op: MAX, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // MAXU rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x0a007033, op: MAXU, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // MIN rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x0a004033, op: MIN, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // MINU rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x0a005033, op: MINU, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // MUL rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x02000033, op: MUL, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // MULH rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x02001033, op: MULH, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // MULHSU rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x02002033, op: MULHSU, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // MULHU rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x02003033, op: MULHU, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // MULW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x0200003b, op: MULW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // OR rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x00006033, op: OR, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // ORC.B rd, rs1 + {mask: 0xfff0707f, value: 0x28705013, op: ORC_B, args: argTypeList{arg_rd, arg_rs1}}, + // ORI rd, rs1, imm12 + {mask: 0x0000707f, value: 0x00006013, op: ORI, args: argTypeList{arg_rd, arg_rs1, arg_imm12}}, + // ORN rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x40006033, op: ORN, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // REM rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x02006033, op: REM, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // REMU rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x02007033, op: REMU, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // REMUW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x0200703b, op: REMUW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // REMW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x0200603b, op: REMW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // REV8 rd, rs1 + {mask: 0xfff0707f, value: 0x6b805013, op: REV8, args: argTypeList{arg_rd, arg_rs1}}, + // ROL rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x60001033, op: ROL, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // ROLW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x6000103b, op: ROLW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // ROR rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x60005033, op: ROR, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // RORI rd, rs1, shamt6 + {mask: 0xfc00707f, value: 0x60005013, op: RORI, args: argTypeList{arg_rd, arg_rs1, arg_shamt6}}, + // RORIW rd, rs1, shamt5 + {mask: 0xfe00707f, value: 0x6000501b, op: RORIW, args: argTypeList{arg_rd, arg_rs1, arg_shamt5}}, + // RORW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x6000503b, op: RORW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SB rs2, rs1_store + {mask: 0x0000707f, value: 0x00000023, op: SB, args: argTypeList{arg_rs2, arg_rs1_store}}, + // SC.D rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x1800302f, op: SC_D, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // SC.D.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x1c00302f, op: SC_D_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // SC.D.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x1e00302f, op: SC_D_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // SC.D.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x1a00302f, op: SC_D_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // SC.W rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x1800202f, op: SC_W, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // SC.W.AQ rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x1c00202f, op: SC_W_AQ, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // SC.W.AQRL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x1e00202f, op: SC_W_AQRL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // SC.W.RL rd, rs2, rs1_amo + {mask: 0xfe00707f, value: 0x1a00202f, op: SC_W_RL, args: argTypeList{arg_rd, arg_rs2, arg_rs1_amo}}, + // SD rs2, rs1_store + {mask: 0x0000707f, value: 0x00003023, op: SD, args: argTypeList{arg_rs2, arg_rs1_store}}, + // SEXT.B rd, rs1 + {mask: 0xfff0707f, value: 0x60401013, op: SEXT_B, args: argTypeList{arg_rd, arg_rs1}}, + // SEXT.H rd, rs1 + {mask: 0xfff0707f, value: 0x60501013, op: SEXT_H, args: argTypeList{arg_rd, arg_rs1}}, + // SH rs2, rs1_store + {mask: 0x0000707f, value: 0x00001023, op: SH, args: argTypeList{arg_rs2, arg_rs1_store}}, + // SH1ADD rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x20002033, op: SH1ADD, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SH1ADD.UW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x2000203b, op: SH1ADD_UW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SH2ADD rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x20004033, op: SH2ADD, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SH2ADD.UW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x2000403b, op: SH2ADD_UW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SH3ADD rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x20006033, op: SH3ADD, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SH3ADD.UW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x2000603b, op: SH3ADD_UW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SLL rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x00001033, op: SLL, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SLLI rd, rs1, shamt6 + {mask: 0xfc00707f, value: 0x00001013, op: SLLI, args: argTypeList{arg_rd, arg_rs1, arg_shamt6}}, + // SLLIW rd, rs1, shamt5 + {mask: 0xfe00707f, value: 0x0000101b, op: SLLIW, args: argTypeList{arg_rd, arg_rs1, arg_shamt5}}, + // SLLI.UW rd, rs1, shamt6 + {mask: 0xfc00707f, value: 0x0800101b, op: SLLI_UW, args: argTypeList{arg_rd, arg_rs1, arg_shamt6}}, + // SLLW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x0000103b, op: SLLW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SLT rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x00002033, op: SLT, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SLTI rd, rs1, imm12 + {mask: 0x0000707f, value: 0x00002013, op: SLTI, args: argTypeList{arg_rd, arg_rs1, arg_imm12}}, + // SLTIU rd, rs1, imm12 + {mask: 0x0000707f, value: 0x00003013, op: SLTIU, args: argTypeList{arg_rd, arg_rs1, arg_imm12}}, + // SLTU rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x00003033, op: SLTU, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SRA rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x40005033, op: SRA, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SRAI rd, rs1, shamt6 + {mask: 0xfc00707f, value: 0x40005013, op: SRAI, args: argTypeList{arg_rd, arg_rs1, arg_shamt6}}, + // SRAIW rd, rs1, shamt5 + {mask: 0xfe00707f, value: 0x4000501b, op: SRAIW, args: argTypeList{arg_rd, arg_rs1, arg_shamt5}}, + // SRAW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x4000503b, op: SRAW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SRL rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x00005033, op: SRL, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SRLI rd, rs1, shamt6 + {mask: 0xfc00707f, value: 0x00005013, op: SRLI, args: argTypeList{arg_rd, arg_rs1, arg_shamt6}}, + // SRLIW rd, rs1, shamt5 + {mask: 0xfe00707f, value: 0x0000501b, op: SRLIW, args: argTypeList{arg_rd, arg_rs1, arg_shamt5}}, + // SRLW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x0000503b, op: SRLW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SUB rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x40000033, op: SUB, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SUBW rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x4000003b, op: SUBW, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // SW rs2, rs1_store + {mask: 0x0000707f, value: 0x00002023, op: SW, args: argTypeList{arg_rs2, arg_rs1_store}}, + // XNOR rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x40004033, op: XNOR, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // XOR rd, rs1, rs2 + {mask: 0xfe00707f, value: 0x00004033, op: XOR, args: argTypeList{arg_rd, arg_rs1, arg_rs2}}, + // XORI rd, rs1, imm12 + {mask: 0x0000707f, value: 0x00004013, op: XORI, args: argTypeList{arg_rd, arg_rs1, arg_imm12}}, + // ZEXT.H rd, rs1 + {mask: 0xfff0707f, value: 0x0800403b, op: ZEXT_H, args: argTypeList{arg_rd, arg_rs1}}, +} diff --git a/vendor/modules.txt b/vendor/modules.txt index ab61a00bdf..b5785d71af 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -72,10 +72,11 @@ go.starlark.net/resolve go.starlark.net/starlark go.starlark.net/starlarkstruct go.starlark.net/syntax -# golang.org/x/arch v0.6.0 +# golang.org/x/arch v0.10.1-0.20240910142527-7874f23b9c06 ## explicit; go 1.18 golang.org/x/arch/arm64/arm64asm golang.org/x/arch/ppc64/ppc64asm +golang.org/x/arch/riscv64/riscv64asm golang.org/x/arch/x86/x86asm # golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 ## explicit; go 1.18