diff -Naur delve-1.22.0.old/cmd/dlv/dlv_test.go delve-1.22.0/cmd/dlv/dlv_test.go --- delve-1.22.0.old/cmd/dlv/dlv_test.go 2024-06-08 17:27:28.679331240 +0800 +++ delve-1.22.0/cmd/dlv/dlv_test.go 2024-06-08 17:36:06.367331240 +0800 @@ -224,7 +224,7 @@ func getDlvBinInternal(t *testing.T, goflags ...string) string { dlvbin := filepath.Join(t.TempDir(), "dlv.exe") - args := append([]string{"build", "-o", dlvbin}, goflags...) + args := append([]string{"build", "-mod=vendor", "-o", dlvbin}, goflags...) args = append(args, "github.com/go-delve/delve/cmd/dlv") out, err := exec.Command("go", args...).CombinedOutput() @@ -382,7 +382,7 @@ // Checks gen-usage-docs.go tempDir := t.TempDir() - cmd := exec.Command("go", "run", "_scripts/gen-usage-docs.go", tempDir) + cmd := exec.Command("go", "run", "-mod=vendor", "_scripts/gen-usage-docs.go", tempDir) cmd.Dir = projectRoot() err := cmd.Run() assertNoError(err, t, "go run _scripts/gen-usage-docs.go") diff -Naur delve-1.22.0.old/Documentation/backend_test_health.md delve-1.22.0/Documentation/backend_test_health.md --- delve-1.22.0.old/Documentation/backend_test_health.md 2024-06-08 17:27:28.659331240 +0800 +++ delve-1.22.0/Documentation/backend_test_health.md 2024-06-08 17:28:41.227331240 +0800 @@ -29,6 +29,11 @@ * 1 broken in linux ppc64le * linux/ppc64le/native/pie skipped = 3 * 3 broken - pie mode +* loong64 skipped = 8 + * 1 broken + * 3 broken - cgo stacktraces + * 1 broken - global variable symbolication + * 3 not implemented * pie skipped = 2 * 2 upstream issue - https://github.com/golang/go/issues/29322 * ppc64le skipped = 11 diff -Naur delve-1.22.0.old/_fixtures/asmnilptr/main_loong64.s delve-1.22.0/_fixtures/asmnilptr/main_loong64.s --- delve-1.22.0.old/_fixtures/asmnilptr/main_loong64.s 1970-01-01 08:00:00.000000000 +0800 +++ delve-1.22.0/_fixtures/asmnilptr/main_loong64.s 2024-06-08 17:29:39.103331240 +0800 @@ -0,0 +1,7 @@ +#include "textflag.h" + +TEXT ·asmFunc(SB),0,$0-16 + MOVV arg+0(FP), R5 + MOVV (R5), R5 + MOVV R5, ret+8(FP) + RET diff -Naur delve-1.22.0.old/_fixtures/cgostacktest/hello.c delve-1.22.0/_fixtures/cgostacktest/hello.c --- delve-1.22.0.old/_fixtures/cgostacktest/hello.c 2024-06-08 17:27:28.663331240 +0800 +++ delve-1.22.0/_fixtures/cgostacktest/hello.c 2024-06-08 17:30:27.831331240 +0800 @@ -14,6 +14,8 @@ #else #define BREAKPOINT asm("brk 0;") #endif +#elif __loongarch__ +#define BREAKPOINT asm("break 0;") #endif void helloworld_pt2(int x) { diff -Naur delve-1.22.0.old/_fixtures/testvariablescgo/test.c delve-1.22.0/_fixtures/testvariablescgo/test.c --- delve-1.22.0.old/_fixtures/testvariablescgo/test.c 2024-06-08 17:27:28.675331240 +0800 +++ delve-1.22.0/_fixtures/testvariablescgo/test.c 2024-06-08 17:31:43.667331240 +0800 @@ -12,6 +12,8 @@ #else #define BREAKPOINT asm("brk 0;") #endif +#elif __loongarch__ +#define BREAKPOINT asm("break 0;") #endif #define N 100 diff -Naur delve-1.22.0.old/pkg/dwarf/regnum/loong64.go delve-1.22.0/pkg/dwarf/regnum/loong64.go --- delve-1.22.0.old/pkg/dwarf/regnum/loong64.go 1970-01-01 08:00:00.000000000 +0800 +++ delve-1.22.0/pkg/dwarf/regnum/loong64.go 2024-06-08 17:36:40.963331240 +0800 @@ -0,0 +1,87 @@ +package regnum + +import ( + "fmt" +) + +// The mapping between hardware registers and DWARF registers, See +// https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html +// https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html + +const ( + // General-purpose Register + LOONG64_R0 = 0 + LOONG64_LR = 1 // ra: address for subroutine + LOONG64_SP = 3 // sp: stack pointer + LOONG64_R22 = 22 + LOONG64_FP = LOONG64_R22 // fp: frame pointer + LOONG64_R31 = 31 + + // Floating-point Register + LOONG64_F0 = 32 + LOONG64_F31 = 63 + + // Floating condition flag register + LOONG64_FCC0 = 64 + LOONG64_FCC7 = 71 + + LOONG64_FCSR = 72 + + // Extra, not defined in ELF-ABI specification + LOONG64_ERA = 73 + LOONG64_BADV = 74 + + // See golang src/cmd/link/internal/loong64/l.go + LOONG64_PC = LOONG64_ERA // era : exception program counter + + _LOONG64_MaxRegNum = LOONG64_BADV +) + +func LOONG64ToName(num uint64) string { + switch { + case num <= LOONG64_R31: + return fmt.Sprintf("R%d", num) + + case num >= LOONG64_F0 && num <= LOONG64_F31: + return fmt.Sprintf("F%d", num-32) + + case num >= LOONG64_FCC0 && num <= LOONG64_FCC7: + return fmt.Sprintf("FCC%d", num-64) + + case num == LOONG64_FCSR: + return fmt.Sprintf("FCSR") + + case num == LOONG64_ERA: + return fmt.Sprintf("ERA") + + case num == LOONG64_BADV: + return fmt.Sprintf("BADV") + + default: + return fmt.Sprintf("Unknown%d", num) + } +} + +func LOONG64MaxRegNum() uint64 { + return _LOONG64_MaxRegNum +} + +var LOONG64NameToDwarf = func() map[string]int { + r := make(map[string]int) + for i := 0; i <= 31; i++ { + r[fmt.Sprintf("r%d", i)] = LOONG64_R0 + i + } + r[fmt.Sprintf("era")] = LOONG64_ERA + r[fmt.Sprintf("badv")] = LOONG64_BADV + + for i := 0; i <= 31; i++ { + r[fmt.Sprintf("f%d", i)] = LOONG64_F0 + i + } + + for i := 0; i <= 7; i++ { + r[fmt.Sprintf("fcc%d", i)] = LOONG64_FCC0 + i + } + r["fcsr"] = LOONG64_FCSR + + return r +}() diff -Naur delve-1.22.0.old/pkg/gobuild/gobuild.go delve-1.22.0/pkg/gobuild/gobuild.go --- delve-1.22.0.old/pkg/gobuild/gobuild.go 2024-06-08 17:27:28.687331240 +0800 +++ delve-1.22.0/pkg/gobuild/gobuild.go 2024-06-08 17:37:48.659331240 +0800 @@ -80,7 +80,7 @@ args = append(args, "-o", debugname) if isTest { - args = append([]string{"-c"}, args...) + args = append([]string{"-c", "-mod=vendor"}, args...) } args = append(args, "-gcflags", "all=-N -l") if buildflags != "" { diff -Naur delve-1.22.0.old/pkg/proc/bininfo.go delve-1.22.0/pkg/proc/bininfo.go --- delve-1.22.0.old/pkg/proc/bininfo.go 2024-06-08 17:27:28.687331240 +0800 +++ delve-1.22.0/pkg/proc/bininfo.go 2024-06-08 17:43:46.399331240 +0800 @@ -130,6 +130,7 @@ elf.EM_AARCH64: true, elf.EM_386: true, elf.EM_PPC64: true, + elf.EM_LOONGARCH: true, } supportedWindowsArch = map[_PEMachine]bool{ @@ -690,6 +691,8 @@ r.Arch = ARM64Arch(goos) case "ppc64le": r.Arch = PPC64LEArch(goos) + case "loong64": + r.Arch = LOONG64Arch(goos) } return r } @@ -1692,6 +1695,13 @@ case elf.EM_PPC64: _ = getSymbol(image, bi.logger, exe, "runtime.tls_g") + case elf.EM_LOONGARCH: + tlsg := getSymbol(image, bi.logger, exe, "runtime.tls_g") + if tlsg == nil || tls == nil { + bi.gStructOffset = 6 * uint64(bi.Arch.PtrSize()) + return + } + bi.gStructOffset = tlsg.Value + (tls.Vaddr & (tls.Align - 1)) default: // we should never get here panic("architecture not supported") diff -Naur delve-1.22.0.old/pkg/proc/core/linux_core.go delve-1.22.0/pkg/proc/core/linux_core.go --- delve-1.22.0.old/pkg/proc/core/linux_core.go 2024-06-08 17:27:28.687331240 +0800 +++ delve-1.22.0/pkg/proc/core/linux_core.go 2024-06-08 17:50:38.103331240 +0800 @@ -39,6 +39,7 @@ const ( _EM_AARCH64 = 183 _EM_X86_64 = 62 + _EM_LOONGARCH = 258 _ARM_FP_HEADER_START = 512 ) @@ -48,6 +49,7 @@ var currentThread proc.Thread var lastThreadAMD *linuxAMD64Thread var lastThreadARM *linuxARM64Thread + var lastThreadLOONG *linuxLOONG64Thread for _, note := range notes { switch note.Type { case elf.NT_PRSTATUS: @@ -65,12 +67,24 @@ if currentThread == nil { currentThread = p.Threads[int(t.Pid)] } + + } else if machineType == _EM_LOONGARCH { + t := note.Desc.(*linuxPrStatusLOONG64) + lastThreadLOONG = &linuxLOONG64Thread{linutil.LOONG64Registers{Regs: &t.Reg}, t} + p.Threads[int(t.Pid)] = &thread{lastThreadLOONG, 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_LOONGARCH { + if lastThreadLOONG != nil { + lastThreadLOONG.regs.Fpregs = note.Desc.(*linutil.LOONG64PtraceFpRegs).Decode() + } } case _NT_X86_XSTATE: if machineType == _EM_X86_64 { @@ -146,6 +160,8 @@ bi = proc.NewBinaryInfo("linux", "amd64") case _EM_AARCH64: bi = proc.NewBinaryInfo("linux", "arm64") + case _EM_LOONGARCH: + bi = proc.NewBinaryInfo("linux", "loong64") default: return nil, nil, fmt.Errorf("unsupported machine type") } @@ -201,6 +217,21 @@ func (t *linuxARM64Thread) pid() int { return int(t.t.Pid) } +type linuxLOONG64Thread struct { + regs linutil.LOONG64Registers + t *linuxPrStatusLOONG64 +} + +func (t *linuxLOONG64Thread) registers() (proc.Registers, error) { + var r linutil.LOONG64Registers + r.Regs = t.regs.Regs + r.Fpregs = t.regs.Fpregs + return &r, nil +} + +func (t *linuxLOONG64Thread) pid() int { + return int(t.t.Pid) +} // Note is a note from the PT_NOTE prog. // Relevant types: @@ -285,6 +316,8 @@ note.Desc = &linuxPrStatusAMD64{} case _EM_AARCH64: note.Desc = &linuxPrStatusARM64{} + case _EM_LOONGARCH: + note.Desc = &linuxPrStatusLOONG64{} default: return nil, fmt.Errorf("unsupported machine type") } @@ -332,6 +365,15 @@ } note.Desc = fpregs } + + if machineType == _EM_LOONGARCH { + fpregs := &linutil.LOONG64PtraceFpRegs{} + 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 { return nil, fmt.Errorf("aligning after desc: %v", err) @@ -445,6 +487,18 @@ Reg linutil.ARM64PtraceRegs Fpvalid int32 } +// LinuxPrStatusLOONG64 is a copy of the prstatus kernel struct. +type linuxPrStatusLOONG64 struct { + Siginfo linuxSiginfo + Cursig uint16 + _ [2]uint8 + Sigpend uint64 + Sighold uint64 + Pid, Ppid, Pgrp, Sid int32 + Utime, Stime, CUtime, CStime linuxCoreTimeval + Reg linutil.LOONG64PtraceRegs + Fpvalid int32 +} // LinuxSiginfo is a copy of the // siginfo kernel struct. diff -Naur delve-1.22.0.old/pkg/proc/dump.go delve-1.22.0/pkg/proc/dump.go --- delve-1.22.0.old/pkg/proc/dump.go 2024-06-08 17:27:28.687331240 +0800 +++ delve-1.22.0/pkg/proc/dump.go 2024-06-08 17:51:23.899331240 +0800 @@ -138,6 +138,8 @@ fhdr.Machine = elf.EM_AARCH64 case "ppc64le": fhdr.Machine = elf.EM_PPC64 + case "loong64": + fhdr.Machine = elf.EM_LOONGARCH default: panic("not implemented") } diff -Naur delve-1.22.0.old/pkg/proc/linutil/regs_loong64_arch.go delve-1.22.0/pkg/proc/linutil/regs_loong64_arch.go --- delve-1.22.0.old/pkg/proc/linutil/regs_loong64_arch.go 1970-01-01 08:00:00.000000000 +0800 +++ delve-1.22.0/pkg/proc/linutil/regs_loong64_arch.go 2024-06-08 17:52:00.863331240 +0800 @@ -0,0 +1,233 @@ +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" +) + +// Regs is a wrapper for sys.PtraceRegs. +type LOONG64Registers struct { + Regs *LOONG64PtraceRegs // general-purpose registers + iscgo bool + tp_tls uint64 + Fpregs []proc.Register // Formatted floating point registers + Fpregset []byte // holding all floating point register values + loadFpRegs func(*LOONG64Registers) error +} + +func NewLOONG64Registers(regs *LOONG64PtraceRegs, iscgo bool, tp_tls uint64, + loadFpRegs func(*LOONG64Registers) error) *LOONG64Registers { + return &LOONG64Registers{ + Regs: regs, + iscgo: iscgo, + tp_tls: tp_tls, + loadFpRegs: loadFpRegs, + } +} + +// LOONG64PtraceRegs is the struct used by the linux kernel to return the GPR for +// LoongArch64 CPUs. refer to sys/unix/zptrace_linux_loong64.go +type LOONG64PtraceRegs struct { + Regs [32]uint64 + Orig_a0 uint64 + Era uint64 + Badv uint64 + Reserved [10]uint64 +} + +// Slice returns the registers as a list of (name, value) pairs. +func (r *LOONG64Registers) Slice(floatingPoint bool) ([]proc.Register, error) { + var regs64 = []struct { + k string + v uint64 + }{ + {"R0", r.Regs.Regs[0]}, + {"R1", r.Regs.Regs[1]}, + {"R2", r.Regs.Regs[2]}, + {"R3", r.Regs.Regs[3]}, + {"R4", r.Regs.Regs[4]}, + {"R5", r.Regs.Regs[5]}, + {"R6", r.Regs.Regs[6]}, + {"R7", r.Regs.Regs[7]}, + {"R8", r.Regs.Regs[8]}, + {"R9", r.Regs.Regs[9]}, + {"R10", r.Regs.Regs[10]}, + {"R11", r.Regs.Regs[11]}, + {"R12", r.Regs.Regs[12]}, + {"R13", r.Regs.Regs[13]}, + {"R14", r.Regs.Regs[14]}, + {"R15", r.Regs.Regs[15]}, + {"R16", r.Regs.Regs[16]}, + {"R17", r.Regs.Regs[17]}, + {"R18", r.Regs.Regs[18]}, + {"R19", r.Regs.Regs[19]}, + {"R20", r.Regs.Regs[20]}, + {"R21", r.Regs.Regs[21]}, + {"R22", r.Regs.Regs[22]}, + {"R23", r.Regs.Regs[23]}, + {"R24", r.Regs.Regs[24]}, + {"R25", r.Regs.Regs[25]}, + {"R26", r.Regs.Regs[26]}, + {"R27", r.Regs.Regs[27]}, + {"R28", r.Regs.Regs[28]}, + {"R29", r.Regs.Regs[29]}, + {"R30", r.Regs.Regs[30]}, + {"R31", r.Regs.Regs[31]}, + {"ERA", r.Regs.Era}, + {"BADV", r.Regs.Badv}, + } + + 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 *LOONG64Registers) PC() uint64 { + // PC Register + return r.Regs.Era +} + +// SP returns the value of SP register. +func (r *LOONG64Registers) SP() uint64 { + // Stack pointer + return r.Regs.Regs[regnum.LOONG64_SP] +} + +// BP returns the value of FP register +func (r *LOONG64Registers) BP() uint64 { + // unused FP register + return 0 +} + +// TLS returns the address of the thread local storage memory segment. +func (r *LOONG64Registers) TLS() uint64 { + // TODO: calling cgo may overwrite $r22,read it from the kernel + if !r.iscgo { + return 0 + } + + // refer to golang defined REGG: loong64/a.out.go + return r.tp_tls +} + +// GAddr returns the address of the G variable if it is known, 0 and false otherwise. +func (r *LOONG64Registers) GAddr() (uint64, bool) { + // REGG is $r22,store the address of g + return r.Regs.Regs[regnum.LOONG64_R22], !r.iscgo +} + +// LR returns the link register. +func (r *LOONG64Registers) LR() uint64 { + return r.Regs.Regs[regnum.LOONG64_LR] +} + +// Copy returns a copy of these registers that is guaranteed not to change. +func (r *LOONG64Registers) Copy() (proc.Registers, error) { + if r.loadFpRegs != nil { + err := r.loadFpRegs(r) + r.loadFpRegs = nil + if err != nil { + return nil, err + } + } + + var rr LOONG64Registers + rr.Regs = &LOONG64PtraceRegs{} + *(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 *LOONG64Registers) SetReg(regNum uint64, reg *op.DwarfRegister) (fpchanged bool, err error) { + switch regNum { + case regnum.LOONG64_SP: + r.Regs.Regs[regnum.LOONG64_SP] = reg.Uint64Val + return false, nil + + case regnum.LOONG64_PC: + r.Regs.Era = reg.Uint64Val + return false, nil + } + + switch { + case regNum >= regnum.LOONG64_R0 && regNum <= regnum.LOONG64_R31: + r.Regs.Regs[regNum] = reg.Uint64Val + return false, nil + + case regNum >= regnum.LOONG64_F0 && regNum <= regnum.LOONG64_F31: + if r.loadFpRegs != nil { + err := r.loadFpRegs(r) + r.loadFpRegs = nil + if err != nil { + return false, err + } + } + + i := regNum - regnum.LOONG64_F0 + reg.FillBytes() + copy(r.Fpregset[8*i:], reg.Bytes) + return true, nil + + default: + return false, fmt.Errorf("changing register %d not implemented", regNum) + } +} + +// Refer to the definition of struct user_fp_state in the kernel ptrace.h +type LOONG64PtraceFpRegs struct { + Fregs []byte + Fcc uint64 + Fcsr uint32 +} + +const _LOONG64_FPREGSET_LENGTH = (32 * 8) + +func (fpregs *LOONG64PtraceFpRegs) 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) + } + + fccBytes := make([]byte, 8) + binary.LittleEndian.PutUint64(fccBytes, uint64(fpregs.Fcc)) + regs = proc.AppendBytesRegister(regs, "FCC0", fccBytes) + + fcsrBytes := make([]byte, 4) + binary.LittleEndian.PutUint32(fccBytes, uint32(fpregs.Fcsr)) + regs = proc.AppendBytesRegister(regs, "FCSR", fcsrBytes) + + return +} + +func (fpregs *LOONG64PtraceFpRegs) Byte() []byte { + fpregs.Fregs = make([]byte, _LOONG64_FPREGSET_LENGTH) + + return fpregs.Fregs[:] +} diff -Naur delve-1.22.0.old/pkg/proc/loong64_arch.go delve-1.22.0/pkg/proc/loong64_arch.go --- delve-1.22.0.old/pkg/proc/loong64_arch.go 1970-01-01 08:00:00.000000000 +0800 +++ delve-1.22.0/pkg/proc/loong64_arch.go 2024-06-08 17:52:34.151331240 +0800 @@ -0,0 +1,368 @@ +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" + "github.com/go-delve/delve/pkg/goversion" +) + +// Break Instruction : 0x002a0000 +var loong64BreakInstruction = []byte{0x00, 0x00, 0x2a, 0x00} + +// LOONG64Arch returns an initialized LOONG64 struct. +func LOONG64Arch(goos string) *Arch { + return &Arch{ + Name: "loong64", + ptrSize: 8, + maxInstructionLength: 4, + breakpointInstruction: loong64BreakInstruction, + breakInstrMovesPC: false, + derefTLS: false, + prologues: prologuesLOONG64, + fixFrameUnwindContext: loong64FixFrameUnwindContext, + switchStack: loong64SwitchStack, + regSize: loong64RegSize, + RegistersToDwarfRegisters: loong64RegistersToDwarfRegisters, + addrAndStackRegsToDwarfRegisters: loong64AddrAndStackRegsToDwarfRegisters, + DwarfRegisterToString: loong64DwarfRegisterToString, + inhibitStepInto: func(*BinaryInfo, uint64) bool { return false }, + asmDecode: loong64AsmDecode, + usesLR: true, + PCRegNum: regnum.LOONG64_PC, + SPRegNum: regnum.LOONG64_SP, + asmRegisters: loong64AsmRegisters, + RegisterNameToDwarf: nameToDwarfFunc(regnum.LOONG64NameToDwarf), + RegnumToString: regnum.LOONG64ToName, + debugCallMinStackSize: 288, // TODO + maxRegArgBytes: 16*8 + 16*8, // 16 int argument registers plus 16 float argument registers, TODO + } +} + +func loong64FixFrameUnwindContext(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.LOONG64_PC, + Regs: map[uint64]frame.DWRule{ + regnum.LOONG64_PC: { + Rule: frame.RuleOffset, + Offset: int64(-a.PtrSize()), + }, + + regnum.LOONG64_FP: { + Rule: frame.RuleOffset, + Offset: int64(-2 * a.PtrSize()), + }, + + regnum.LOONG64_SP: { + Rule: frame.RuleValOffset, + Offset: 0, + }, + }, + + CFA: frame.DWRule{ + Rule: frame.RuleCFA, + Reg: regnum.LOONG64_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.LOONG64_FP].Rule == frame.RuleUndefined { + fctxt.Regs[regnum.LOONG64_FP] = frame.DWRule{ + Rule: frame.RuleFramePointer, + Reg: regnum.LOONG64_FP, + Offset: 0, + } + } + + if fctxt.Regs[regnum.LOONG64_LR].Rule == frame.RuleUndefined { + fctxt.Regs[regnum.LOONG64_LR] = frame.DWRule{ + Rule: frame.RuleRegister, + Reg: regnum.LOONG64_LR, + Offset: 0, + } + } + + return fctxt +} + +const loong64cgocallSPOffsetSaveSlot = 0x8 +const loong64PrevG0schedSPOffsetSaveSlot = 0x10 + +func loong64SwitchStack(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": + // 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_loong64.s + // + // When a C function 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.top || it.systemstack { + return false + } + + it.loadG0SchedSP() + if it.g0_sched_sp <= 0 { + return false + } + // Entering the system stack. + it.regs.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(it.regs.SP()+loong64PrevG0schedSPOffsetSaveSlot), int64(it.bi.Arch.PtrSize())) + it.top = false + callFrameRegs, ret, retaddr := it.advanceRegs() + frameOnSystemStack := it.newStackframe(ret, retaddr) + it.pc = frameOnSystemStack.Ret + it.regs = callFrameRegs + it.systemstack = true + + return true + + case "runtime.asmcgocall": + if it.top || !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(it.regs.SP()+loong64cgocallSPOffsetSaveSlot), + int64(it.bi.Arch.PtrSize())) + oldsp := it.regs.SP() + it.regs.Reg(it.regs.SPRegNum).Uint64Val = 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 it.regs.SP() == oldsp { + return false + } + + it.top = false + it.systemstack = false + // The return value is stored in the LR register which is saved at 24(SP). + addrret := uint64(int64(it.regs.SP()) + int64(it.bi.Arch.PtrSize()*3)) // TODO + it.frame.Ret, _ = readUintRaw(it.mem, addrret, int64(it.bi.Arch.PtrSize())) + it.pc = it.frame.Ret + + return true + + case "runtime.goexit", "runtime.rt0_go", "runtime.mcall": + // Look for "top of stack" functions. + it.atend = true + return true + + case "crosscall2": + // The offsets get from runtime/cgo/asm_loong64.s:10 + bpoff := uint64(14) + lroff := uint64(15) + if producer := it.bi.Producer(); producer != "" && goversion.ProducerAfterOrEqual(producer, 1, 19) { + // In Go 1.19 (specifically eee6f9f82) the order registers are saved was changed. + bpoff = 22 + lroff = 23 + } + newbp, _ := readUintRaw(it.mem, uint64(it.regs.SP()+8*bpoff), int64(it.bi.Arch.PtrSize())) + newlr, _ := readUintRaw(it.mem, uint64(it.regs.SP()+8*lroff), int64(it.bi.Arch.PtrSize())) + if it.regs.Reg(it.regs.BPRegNum) != nil { + it.regs.Reg(it.regs.BPRegNum).Uint64Val = uint64(newbp) + } else { + reg, _ := it.readRegisterAt(it.regs.BPRegNum, it.regs.SP()+8*bpoff) + it.regs.AddReg(it.regs.BPRegNum, reg) + } + it.regs.Reg(it.regs.LRRegNum).Uint64Val = uint64(newlr) + it.regs.Reg(it.regs.SPRegNum).Uint64Val = uint64(newbp) + it.pc = newlr + 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()+loong64cgocallSPOffsetSaveSlot), + 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_loong64.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()+loong64PrevG0schedSPOffsetSaveSlot), + int64(it.bi.Arch.PtrSize())) + it.systemstack = true + + return false + } + + return false +} + +func loong64RegSize(regnum uint64) int { + // All CPU registers are 64bit + return 8 +} + +func loong64RegistersToDwarfRegisters(staticBase uint64, regs Registers) *op.DwarfRegisters { + dregs := initDwarfRegistersFromSlice(int(regnum.LOONG64MaxRegNum()), regs, regnum.LOONG64NameToDwarf) + dr := op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, regnum.LOONG64_PC, regnum.LOONG64_SP, regnum.LOONG64_FP, regnum.LOONG64_LR) + dr.SetLoadMoreCallback(loadMoreDwarfRegistersFromSliceFunc(dr, regs, regnum.LOONG64NameToDwarf)) + return dr +} + +func loong64AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters { + dregs := make([]*op.DwarfRegister, int(regnum.LOONG64MaxRegNum())) + dregs[regnum.LOONG64_PC] = op.DwarfRegisterFromUint64(pc) + dregs[regnum.LOONG64_SP] = op.DwarfRegisterFromUint64(sp) + dregs[regnum.LOONG64_FP] = op.DwarfRegisterFromUint64(bp) + dregs[regnum.LOONG64_LR] = op.DwarfRegisterFromUint64(lr) + + return *op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, regnum.LOONG64_PC, regnum.LOONG64_SP, regnum.LOONG64_FP, regnum.LOONG64_LR) +} + +func loong64DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) { + name = regnum.LOONG64ToName(uint64(i)) + + if reg == nil { + return name, false, "" + } + + if strings.HasPrefix(name, "FCC") { + return name, true, fmt.Sprintf("%#x", reg.Uint64Val) + } else if strings.HasPrefix(name, "F") { + return name, true, fmt.Sprintf("%#016x", reg.Uint64Val) + } else { + return name, false, fmt.Sprintf("%#016x", reg.Uint64Val) + } +} diff -Naur delve-1.22.0.old/pkg/proc/loong64_disasm.go delve-1.22.0/pkg/proc/loong64_disasm.go --- delve-1.22.0.old/pkg/proc/loong64_disasm.go 1970-01-01 08:00:00.000000000 +0800 +++ delve-1.22.0/pkg/proc/loong64_disasm.go 2024-06-08 17:53:11.283331240 +0800 @@ -0,0 +1,217 @@ +// TODO: disassembler support should be compiled in unconditionally, +// instead of being decided by the build-target architecture, and be +// part of the Arch object instead. + +package proc + +import ( + "fmt" + "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/go-delve/delve/pkg/dwarf/regnum" + "golang.org/x/arch/loong64/loong64asm" +) + +var ( + errType = fmt.Errorf("unknown type") +) + +func loong64AsmDecode(asmInst *AsmInstruction, mem []byte, regs *op.DwarfRegisters, memrw MemoryReadWriter, bi *BinaryInfo) error { + asmInst.Size = 4 + asmInst.Bytes = mem[:asmInst.Size] + + inst, err := loong64asm.Decode(mem) + if err != nil { + asmInst.Inst = (*loong64ArchInst)(nil) + return err + } + + asmInst.Inst = (*loong64ArchInst)(&inst) + asmInst.Kind = OtherInstruction + + switch inst.Op { + case loong64asm.JIRL: + rd, _ := inst.Args[0].(loong64asm.Reg) + rj, _ := inst.Args[1].(loong64asm.Reg) + if rd == loong64asm.R1 { + asmInst.Kind = CallInstruction + } else if rd == loong64asm.R0 && rj == loong64asm.R1 { + asmInst.Kind = RetInstruction + } else { + asmInst.Kind = JmpInstruction + } + + case loong64asm.BL: + asmInst.Kind = CallInstruction + + case loong64asm.BEQZ, + loong64asm.BNEZ, + loong64asm.BCEQZ, + loong64asm.BCNEZ, + loong64asm.B, + loong64asm.BEQ, + loong64asm.BNE, + loong64asm.BLT, + loong64asm.BGE, + loong64asm.BLTU, + loong64asm.BGEU: + asmInst.Kind = JmpInstruction + + case loong64asm.BREAK: + asmInst.Kind = HardBreakInstruction + + default: + asmInst.Kind = OtherInstruction + } + + asmInst.DestLoc = resolveCallArgLOONG64(&inst, asmInst.Loc.PC, asmInst.AtPC, regs, memrw, bi) + + return nil +} + +func resolveCallArgLOONG64(inst *loong64asm.Inst, instAddr uint64, currentGoroutine bool, regs *op.DwarfRegisters, mem MemoryReadWriter, bininfo *BinaryInfo) *Location { + var pc uint64 + var err error + + switch inst.Op { + // Format: op offs26 + // Target: offs26 + case loong64asm.B, loong64asm.BL: + switch arg := inst.Args[0].(type) { + case loong64asm.OffsetSimm: + pc = uint64(int64(instAddr) + int64(arg.Imm)) + default: + return nil + } + + // Format: op rd,rj,offs16 + // Target: offs16 + case loong64asm.BEQ, + loong64asm.BNE, + loong64asm.BLT, + loong64asm.BGE, + loong64asm.BLTU, + loong64asm.BGEU: + + switch arg := inst.Args[2].(type) { + case loong64asm.OffsetSimm: + pc = uint64(int64(instAddr) + int64(arg.Imm)) + default: + return nil + } + + // Format: op rd,rj,offs16 + // Target: rj + offs16 + case loong64asm.JIRL: + if !currentGoroutine || regs == nil { + return nil + } + switch arg1 := inst.Args[1].(type) { + case loong64asm.Reg: + switch arg2 := inst.Args[2].(type) { + case loong64asm.OffsetSimm: + pc, err = bininfo.Arch.getAsmRegister(regs, int(arg1)) + if err != nil { + return nil + } + pc = uint64(int64(pc) + int64(arg2.Imm)) + } + } + + // Format: op rj,offs21 + // Target: offs21 + case loong64asm.BEQZ, + loong64asm.BNEZ, + loong64asm.BCEQZ, + loong64asm.BCNEZ: + + if (!currentGoroutine) || (regs == nil) { + return nil + } + + switch arg := inst.Args[1].(type) { + case loong64asm.OffsetSimm: + pc = uint64(int64(instAddr) + int64(arg.Imm)) + default: + return nil + } + + 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/loong64/obj.go. +var prologuesLOONG64 []opcodeSeq + +func init() { + var tinyStacksplit = opcodeSeq{uint64(loong64asm.ADDI_D)} + var smallStacksplit = opcodeSeq{} + var bigStacksplit = opcodeSeq{uint64(loong64asm.LU12I_W), + uint64(loong64asm.ORI), + uint64(loong64asm.SLTU), + uint64(loong64asm.BNE), + uint64(loong64asm.LU12I_W), + uint64(loong64asm.ORI), + uint64(loong64asm.ADD_D)} + + var unixGetG = opcodeSeq{uint64(loong64asm.LD_D)} + var tailPrologues = opcodeSeq{uint64(loong64asm.SLTU), + uint64(loong64asm.BNE), + uint64(loong64asm.OR), + uint64(loong64asm.BL), + uint64(loong64asm.BEQ)} + + prologuesLOONG64 = 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...) + prologuesLOONG64 = append(prologuesLOONG64, prologue) + } +} + +type loong64ArchInst loong64asm.Inst + +func (inst *loong64ArchInst) Text(flavour AssemblyFlavour, pc uint64, symLookup func(uint64) (string, uint64)) string { + if inst == nil { + return "?" + } + + var text string + + switch flavour { + case GNUFlavour: + text = loong64asm.GNUSyntax(loong64asm.Inst(*inst)) + default: + text = loong64asm.GoSyntax(loong64asm.Inst(*inst), pc, symLookup) + } + + return text +} + +func (inst *loong64ArchInst) OpcodeEquals(op uint64) bool { + if inst == nil { + return false + } + + return uint64(inst.Op) == op +} + +var loong64AsmRegisters = func() map[int]asmRegister { + r := make(map[int]asmRegister) + + for i := loong64asm.R0; i <= loong64asm.R31; i++ { + r[int(i)] = asmRegister{regnum.LOONG64_R0 + uint64(i), 0, 0} + } + + return r +}() diff -Naur delve-1.22.0.old/pkg/proc/native/hwbreak_other.go delve-1.22.0/pkg/proc/native/hwbreak_other.go --- delve-1.22.0.old/pkg/proc/native/hwbreak_other.go 2024-06-08 17:27:28.695331240 +0800 +++ delve-1.22.0/pkg/proc/native/hwbreak_other.go 2024-06-08 17:53:44.007331240 +0800 @@ -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 && loong64) package native diff -Naur delve-1.22.0.old/pkg/proc/native/ptrace_linux_64bit.go delve-1.22.0/pkg/proc/native/ptrace_linux_64bit.go --- delve-1.22.0.old/pkg/proc/native/ptrace_linux_64bit.go 2024-06-08 17:27:28.695331240 +0800 +++ delve-1.22.0/pkg/proc/native/ptrace_linux_64bit.go 2024-06-08 17:54:15.767331240 +0800 @@ -1,4 +1,4 @@ -//go:build (linux && amd64) || (linux && arm64) || (linux && ppc64le) +//go:build (linux && amd64) || (linux && arm64) || (linux && ppc64le) || (linux && loong64) package native diff -Naur delve-1.22.0.old/pkg/proc/native/registers_linux_loong64.go delve-1.22.0/pkg/proc/native/registers_linux_loong64.go --- delve-1.22.0.old/pkg/proc/native/registers_linux_loong64.go 1970-01-01 08:00:00.000000000 +0800 +++ delve-1.22.0/pkg/proc/native/registers_linux_loong64.go 2024-06-08 17:54:46.735331240 +0800 @@ -0,0 +1,158 @@ +//go:build linux && loong64 +// +build linux,loong64 + +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" +) + +const ( + // Refer to the definition of struct user_pt_regs in the kernel file ptrace.h + _LOONG64_GREGS_SIZE = (32 * 8) + 8 + 8 + 8 + (10 * 8) + + // In fact, the total number of bytes is 268(32 fpr * 8 + 1 Fcc * 8 + 1 Fcsr * 4), + // but since the Len defined in sys.Iovec is uint64,the total numbel of bytes must + // be an integral multiple of 8,so add 4 bytes + _LOONG64_FPREGS_SIZE = (32 * 8) + (1 * 8) + (1 * 4) + 4 +) + +func ptraceGetGRegs(pid int, regs *linutil.LOONG64PtraceRegs) (err error) { + iov := sys.Iovec{Base: (*byte)(unsafe.Pointer(regs)), Len: _LOONG64_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.LOONG64PtraceRegs) (err error) { + iov := sys.Iovec{Base: (*byte)(unsafe.Pointer(regs)), Len: _LOONG64_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 +} + +// ptraceGetFpRegset returns floating point registers of +// the specified thread using PTRACE. +func ptraceGetFpRegset(tid int, fpregs *linutil.LOONG64PtraceFpRegs) (err error) { + fprBytes := make([]byte, _LOONG64_FPREGS_SIZE) + iov := sys.Iovec{Base: &fprBytes[0], Len: uint64(_LOONG64_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-16] + fpregs.Fcc = binary.LittleEndian.Uint64(fprBytes[iov.Len-16 : iov.Len-8]) + fpregs.Fcsr = binary.LittleEndian.Uint32(fprBytes[iov.Len-8 : iov.Len-4]) + + return +} + +// SetPC sets PC to the value specified by 'pc'. +func (thread *nativeThread) setPC(pc uint64) error { + ir, err := registers(thread) + if err != nil { + return err + } + + r := ir.(*linutil.LOONG64Registers) + r.Regs.Era = pc + thread.dbp.execPtraceFunc(func() { err = ptraceSetGRegs(thread.ID, r.Regs) }) + + return err +} + +// SetSP sets SP to the value specified by 'sp' +func (thread *nativeThread) setSP(sp uint64) (err error) { + var ir proc.Registers + + ir, err = registers(thread) + if err != nil { + return err + } + + r := ir.(*linutil.LOONG64Registers) + r.Regs.Regs[3] = 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.LOONG64Registers) + 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.LOONG64PtraceRegs + 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.Regs[2] + } + r := linutil.NewLOONG64Registers(®s, thread.dbp.iscgo, tp_tls, + func(r *linutil.LOONG64Registers) error { + var floatLoadError error + r.Fpregs, r.Fpregset, floatLoadError = thread.fpRegisters() + return floatLoadError + }) + + return r, nil +} diff -Naur delve-1.22.0.old/pkg/proc/native/support_sentinel_linux.go delve-1.22.0/pkg/proc/native/support_sentinel_linux.go --- delve-1.22.0.old/pkg/proc/native/support_sentinel_linux.go 2024-06-08 17:27:28.695331240 +0800 +++ delve-1.22.0/pkg/proc/native/support_sentinel_linux.go 2024-06-08 17:55:51.815331240 +0800 @@ -1,4 +1,4 @@ -//go:build linux && !amd64 && !arm64 && !386 && !(ppc64le && exp.linuxppc64le) +//go:build linux && !amd64 && !arm64 && !386 && !(ppc64le && exp.linuxppc64le) && !loong64 // This file is used to detect build on unsupported GOOS/GOARCH combinations. diff -Naur delve-1.22.0.old/pkg/proc/native/threads_linux_loong64.go delve-1.22.0/pkg/proc/native/threads_linux_loong64.go --- delve-1.22.0.old/pkg/proc/native/threads_linux_loong64.go 1970-01-01 08:00:00.000000000 +0800 +++ delve-1.22.0/pkg/proc/native/threads_linux_loong64.go 2024-06-08 17:56:28.115331240 +0800 @@ -0,0 +1,54 @@ +//go:build linux && loong64 +// +build linux,loong64 + +package native + +import ( + "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" +) + +func (thread *nativeThread) fpRegisters() ([]proc.Register, []byte, error) { + var err error + var loong64_fpregs linutil.LOONG64PtraceFpRegs + + thread.dbp.execPtraceFunc(func() { err = ptraceGetFpRegset(thread.ID, &loong64_fpregs) }) + fpregs := loong64_fpregs.Decode() + + if err != nil { + err = fmt.Errorf("could not get floating point registers: %v", err.Error()) + } + + return fpregs, loong64_fpregs.Fregs, err +} + +func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error { + var restoreRegistersErr error + + sr := savedRegs.(*linutil.LOONG64Registers) + 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 +} diff -Naur delve-1.22.0.old/pkg/proc/pe.go delve-1.22.0/pkg/proc/pe.go --- delve-1.22.0.old/pkg/proc/pe.go 2024-06-08 17:27:28.695331240 +0800 +++ delve-1.22.0/pkg/proc/pe.go 2024-06-08 17:58:21.479331240 +0800 @@ -5,58 +5,61 @@ ) const ( - _IMAGE_FILE_MACHINE_UNKNOWN = 0x0 - _IMAGE_FILE_MACHINE_AM33 = 0x1d3 - _IMAGE_FILE_MACHINE_AMD64 = 0x8664 - _IMAGE_FILE_MACHINE_ARM = 0x1c0 - _IMAGE_FILE_MACHINE_ARMNT = 0x1c4 - _IMAGE_FILE_MACHINE_ARM64 = 0xaa64 - _IMAGE_FILE_MACHINE_EBC = 0xebc - _IMAGE_FILE_MACHINE_I386 = 0x14c - _IMAGE_FILE_MACHINE_IA64 = 0x200 - _IMAGE_FILE_MACHINE_M32R = 0x9041 - _IMAGE_FILE_MACHINE_MIPS16 = 0x266 - _IMAGE_FILE_MACHINE_MIPSFPU = 0x366 - _IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466 - _IMAGE_FILE_MACHINE_POWERPC = 0x1f0 - _IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1 - _IMAGE_FILE_MACHINE_R4000 = 0x166 - _IMAGE_FILE_MACHINE_SH3 = 0x1a2 - _IMAGE_FILE_MACHINE_SH3DSP = 0x1a3 - _IMAGE_FILE_MACHINE_SH4 = 0x1a6 - _IMAGE_FILE_MACHINE_SH5 = 0x1a8 - _IMAGE_FILE_MACHINE_THUMB = 0x1c2 - _IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169 + _IMAGE_FILE_MACHINE_UNKNOWN = 0x0 + _IMAGE_FILE_MACHINE_AM33 = 0x1d3 + _IMAGE_FILE_MACHINE_AMD64 = 0x8664 + _IMAGE_FILE_MACHINE_ARM = 0x1c0 + _IMAGE_FILE_MACHINE_ARMNT = 0x1c4 + _IMAGE_FILE_MACHINE_ARM64 = 0xaa64 + _IMAGE_FILE_MACHINE_EBC = 0xebc + _IMAGE_FILE_MACHINE_I386 = 0x14c + _IMAGE_FILE_MACHINE_IA64 = 0x200 + _IMAGE_FILE_MACHINE_LOONGARCH64 = 0x6264 + _IMAGE_FILE_MACHINE_M32R = 0x9041 + _IMAGE_FILE_MACHINE_MIPS16 = 0x266 + _IMAGE_FILE_MACHINE_MIPSFPU = 0x366 + _IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466 + _IMAGE_FILE_MACHINE_POWERPC = 0x1f0 + _IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1 + _IMAGE_FILE_MACHINE_R4000 = 0x166 + _IMAGE_FILE_MACHINE_SH3 = 0x1a2 + _IMAGE_FILE_MACHINE_SH3DSP = 0x1a3 + _IMAGE_FILE_MACHINE_SH4 = 0x1a6 + _IMAGE_FILE_MACHINE_SH5 = 0x1a8 + _IMAGE_FILE_MACHINE_THUMB = 0x1c2 + _IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169 ) type _PEMachine uint16 // PEMachineString map pe machine to name, See $GOROOT/src/debug/pe/pe.go for detail var _PEMachineString = map[_PEMachine]string{ - _IMAGE_FILE_MACHINE_UNKNOWN: "unknown", - _IMAGE_FILE_MACHINE_AM33: "am33", - _IMAGE_FILE_MACHINE_AMD64: "amd64", - _IMAGE_FILE_MACHINE_ARM: "arm", - _IMAGE_FILE_MACHINE_ARMNT: "armnt", - _IMAGE_FILE_MACHINE_ARM64: "arm64", - _IMAGE_FILE_MACHINE_EBC: "ebc", - _IMAGE_FILE_MACHINE_I386: "i386", - _IMAGE_FILE_MACHINE_IA64: "ia64", - _IMAGE_FILE_MACHINE_M32R: "m32r", - _IMAGE_FILE_MACHINE_MIPS16: "mips16", - _IMAGE_FILE_MACHINE_MIPSFPU: "mipsfpu", - _IMAGE_FILE_MACHINE_MIPSFPU16: "mipsfpu16", - _IMAGE_FILE_MACHINE_POWERPC: "powerpc", - _IMAGE_FILE_MACHINE_POWERPCFP: "powerpcfp", - _IMAGE_FILE_MACHINE_R4000: "r4000", - _IMAGE_FILE_MACHINE_SH3: "sh3", - _IMAGE_FILE_MACHINE_SH3DSP: "sh3dsp", - _IMAGE_FILE_MACHINE_SH4: "sh4", - _IMAGE_FILE_MACHINE_SH5: "sh5", - _IMAGE_FILE_MACHINE_THUMB: "thumb", - _IMAGE_FILE_MACHINE_WCEMIPSV2: "wcemipsv2", + _IMAGE_FILE_MACHINE_UNKNOWN: "unknown", + _IMAGE_FILE_MACHINE_AM33: "am33", + _IMAGE_FILE_MACHINE_AMD64: "amd64", + _IMAGE_FILE_MACHINE_ARM: "arm", + _IMAGE_FILE_MACHINE_ARMNT: "armnt", + _IMAGE_FILE_MACHINE_ARM64: "arm64", + _IMAGE_FILE_MACHINE_EBC: "ebc", + _IMAGE_FILE_MACHINE_I386: "i386", + _IMAGE_FILE_MACHINE_IA64: "ia64", + _IMAGE_FILE_MACHINE_LOONGARCH64: "loong64", + _IMAGE_FILE_MACHINE_M32R: "m32r", + _IMAGE_FILE_MACHINE_MIPS16: "mips16", + _IMAGE_FILE_MACHINE_MIPSFPU: "mipsfpu", + _IMAGE_FILE_MACHINE_MIPSFPU16: "mipsfpu16", + _IMAGE_FILE_MACHINE_POWERPC: "powerpc", + _IMAGE_FILE_MACHINE_POWERPCFP: "powerpcfp", + _IMAGE_FILE_MACHINE_R4000: "r4000", + _IMAGE_FILE_MACHINE_SH3: "sh3", + _IMAGE_FILE_MACHINE_SH3DSP: "sh3dsp", + _IMAGE_FILE_MACHINE_SH4: "sh4", + _IMAGE_FILE_MACHINE_SH5: "sh5", + _IMAGE_FILE_MACHINE_THUMB: "thumb", + _IMAGE_FILE_MACHINE_WCEMIPSV2: "wcemipsv2", } + func (m _PEMachine) String() string { str, ok := _PEMachineString[m] if ok { diff -Naur delve-1.22.0.old/pkg/proc/proc_test.go delve-1.22.0/pkg/proc/proc_test.go --- delve-1.22.0.old/pkg/proc/proc_test.go 2024-06-08 17:27:28.699331240 +0800 +++ delve-1.22.0/pkg/proc/proc_test.go 2024-06-08 19:07:41.939331240 +0800 @@ -3350,6 +3350,7 @@ 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", "loong64") if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 21) { skipOn(t, "broken - cgo stacktraces", "windows", "arm64") } @@ -3459,6 +3460,11 @@ t.Skip("cgo stacktraces not supported on i386 for now") } + if runtime.GOARCH == "loong64"{ + t.Skip("cgo stacktraces not supported on loong64 for now") + } + + protest.MustHaveCgo(t) withTestProcess("cgostacktest/", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { @@ -3533,6 +3539,7 @@ func TestIssue1034(t *testing.T) { skipOn(t, "broken - cgo stacktraces", "386") + skipOn(t, "broken - cgo stacktraces", "loong64") protest.MustHaveCgo(t) // The external linker on macOS produces an abbrev for DW_TAG_subprogram @@ -3553,6 +3560,7 @@ func TestIssue1008(t *testing.T) { skipOn(t, "broken - cgo stacktraces", "386") + skipOn(t, "broken - cgo stacktraces", "loong64") protest.MustHaveCgo(t) // The external linker on macOS inserts "end of sequence" extended opcodes @@ -3738,6 +3746,7 @@ 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", "loong64") // 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 @@ -3924,6 +3933,7 @@ func TestInlineStep(t *testing.T) { skipOn(t, "broken", "ppc64le") + if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) { // Versions of go before 1.10 do not have DWARF information for inlined calls t.Skip("inlining not supported") @@ -4085,6 +4095,7 @@ func TestDWZCompression(t *testing.T) { skipOn(t, "broken", "ppc64le") + skipOn(t, "broken - global variable symbolication", "loong64") // If dwz is not available in the system, skip this test if _, err := exec.LookPath("dwz"); err != nil { t.Skip("dwz not installed") @@ -4645,6 +4656,7 @@ skipOn(t, "broken", "386") skipOn(t, "broken - cgo stacktraces", "darwin", "arm64") skipOn(t, "broken", "ppc64le") + skipOn(t, "broken", "loong64") protest.MustHaveCgo(t) // If a panic happens during cgo execution the stacktrace should show the C // function that caused the problem. @@ -5380,6 +5392,7 @@ skipOn(t, "not implemented", "freebsd") skipOn(t, "not implemented", "386") skipOn(t, "not implemented", "ppc64le") + skipOn(t, "not implemented", "loong64") skipOn(t, "see https://github.com/go-delve/delve/issues/2768", "windows") protest.AllowRecording(t) @@ -5441,6 +5454,7 @@ 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", "loong64") protest.AllowRecording(t) withTestProcess("databpcountstest", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { @@ -5715,6 +5729,8 @@ asmfile = "main_386.s" case "ppc64le": asmfile = "main_ppc64le.s" + case "loong64": + asmfile = "main_loong64.s" default: t.Fatalf("assembly file for %s not provided", runtime.GOARCH) } diff -Naur delve-1.22.0.old/pkg/proc/stack.go delve-1.22.0/pkg/proc/stack.go --- delve-1.22.0.old/pkg/proc/stack.go 2024-06-08 17:27:28.699331240 +0800 +++ delve-1.22.0/pkg/proc/stack.go 2024-06-08 19:09:11.039331240 +0800 @@ -282,7 +282,7 @@ 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 == "loong64"{ it.regs.Reg(it.regs.LRRegNum).Uint64Val = it.g.LR } } @@ -521,7 +521,7 @@ } } - 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 == "loong64"{ if ret == 0 && it.regs.Reg(it.regs.LRRegNum) != nil { ret = it.regs.Reg(it.regs.LRRegNum).Uint64Val } diff -Naur delve-1.22.0.old/pkg/proc/test/support.go delve-1.22.0/pkg/proc/test/support.go --- delve-1.22.0.old/pkg/proc/test/support.go 2024-06-08 17:27:28.699331240 +0800 +++ delve-1.22.0/pkg/proc/test/support.go 2024-06-08 19:09:48.479331240 +0800 @@ -310,6 +310,9 @@ if runtime.GOARCH == "386" { t.Skip(fmt.Errorf("%s does not support FunctionCall for now", runtime.GOARCH)) } + if runtime.GOARCH == "loong64" { + 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") diff -Naur delve-1.22.0.old/_scripts/make.go delve-1.22.0/_scripts/make.go --- delve-1.22.0.old/_scripts/make.go 2024-06-08 17:27:28.675331240 +0800 +++ delve-1.22.0/_scripts/make.go 2024-06-08 17:33:46.295331240 +0800 @@ -50,7 +50,10 @@ envflags = append(envflags, "GOOS="+OS) } if len(envflags) > 0 { - executeEnv(envflags, "go", "build", "-ldflags", "-extldflags -static", tagFlags(), buildFlags(), DelveMainPackagePath) + envflags = append(envflags, "-mod=vendor") + } + if len(envflags) > 0 { + executeEnv(envflags, "go", "build", "-mod=vendor", "-ldflags", "-extldflags -static", tagFlags(), buildFlags(), DelveMainPackagePath) } else { execute("go", "build", "-ldflags", "-extldflags -static", tagFlags(), buildFlags(), DelveMainPackagePath) } diff -Naur delve-1.22.0.old/service/dap/server_test.go delve-1.22.0/service/dap/server_test.go --- delve-1.22.0.old/service/dap/server_test.go 2024-06-08 17:27:28.703331240 +0800 +++ delve-1.22.0/service/dap/server_test.go 2024-06-08 19:13:04.111331240 +0800 @@ -2542,7 +2542,7 @@ []onBreakpoint{{ // Stop at line 36 execute: func() { - if runtime.GOARCH == "386" && goversion.VersionAfterOrEqual(runtime.Version(), 1, 18) && !goversion.VersionAfterOrEqual(runtime.Version(), 1, 21) { + if (runtime.GOARCH == "386" && goversion.VersionAfterOrEqual(runtime.Version(), 1, 18) && !goversion.VersionAfterOrEqual(runtime.Version(), 1, 21)) || runtime.GOARCH == "loong64" { client.StepInRequest(1) client.ExpectStepInResponse(t) client.ExpectStoppedEvent(t) @@ -2617,7 +2617,7 @@ []onBreakpoint{{ // Stop at line 36 execute: func() { - if runtime.GOARCH == "386" && goversion.VersionAfterOrEqual(runtime.Version(), 1, 18) && !goversion.VersionAfterOrEqual(runtime.Version(), 1, 21) { + if (runtime.GOARCH == "386" && goversion.VersionAfterOrEqual(runtime.Version(), 1, 18) && !goversion.VersionAfterOrEqual(runtime.Version(), 1, 21)) || runtime.GOARCH == "loong64" { client.StepInRequest(1) client.ExpectStepInResponse(t) client.ExpectStoppedEvent(t) @@ -2717,7 +2717,7 @@ } func isPcReg(reg dap.Variable) bool { - pcRegNames := []string{"rip", "pc", "eip"} + pcRegNames := []string{"rip", "pc", "eip", "era"} for _, name := range pcRegNames { if name == strings.TrimSpace(reg.Name) { return true diff -Naur delve-1.22.0.old/service/debugger/debugger_test.go delve-1.22.0/service/debugger/debugger_test.go --- delve-1.22.0.old/service/debugger/debugger_test.go 2024-06-08 17:27:28.703331240 +0800 +++ delve-1.22.0/service/debugger/debugger_test.go 2024-06-08 19:13:56.767331240 +0800 @@ -49,6 +49,9 @@ if runtime.GOARCH == "ppc64le" && runtime.GOOS == "linux" { t.Setenv("GOARCH", "amd64") } + if runtime.GOARCH == "loong64" && runtime.GOOS == "linux" { + os.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 -Naur delve-1.22.0.old/service/debugger/debugger_unix_test.go delve-1.22.0/service/debugger/debugger_unix_test.go --- delve-1.22.0.old/service/debugger/debugger_unix_test.go 2024-06-08 17:27:28.703331240 +0800 +++ delve-1.22.0/service/debugger/debugger_unix_test.go 2024-06-08 19:14:37.551331240 +0800 @@ -34,6 +34,9 @@ if runtime.GOARCH == "ppc64le" && runtime.GOOS == "linux" { t.Setenv("GOARCH", "amd64") } + if runtime.GOARCH == "loong64" && runtime.GOOS == "linux" { + os.Setenv("GOARCH", "amd64") + } t.Setenv("GOOS", switchOS[runtime.GOOS]) exepath := filepath.Join(buildtestdir, debugname) defer os.Remove(exepath) diff -Naur delve-1.22.0.old/service/test/integration1_test.go delve-1.22.0/service/test/integration1_test.go --- delve-1.22.0.old/service/test/integration1_test.go 2024-06-08 17:27:28.703331240 +0800 +++ delve-1.22.0/service/test/integration1_test.go 2024-06-08 19:16:33.043331240 +0800 @@ -910,7 +910,7 @@ // look for static call to afunction() on line 29 found := false for i := range d3 { - if d3[i].Loc.Line == 29 && (strings.HasPrefix(d3[i].Text, "call") || strings.HasPrefix(d3[i].Text, "CALL")) && d3[i].DestLoc != nil && d3[i].DestLoc.Function != nil && d3[i].DestLoc.Function.Name() == "main.afunction" { + if d3[i].Loc.Line == 29 && (strings.HasPrefix(d3[i].Text, "call") || strings.HasPrefix(d3[i].Text, "CALL") || strings.HasPrefix(d3[i].Text, "bl")) && d3[i].DestLoc != nil && d3[i].DestLoc.Function != nil && d3[i].DestLoc.Function.Name() == "main.afunction" { found = true break } @@ -960,7 +960,7 @@ t.Fatal("Calling StepInstruction() repeatedly did not find the call instruction") } - if strings.HasPrefix(curinstr.Text, "call") || strings.HasPrefix(curinstr.Text, "CALL") { + if strings.HasPrefix(curinstr.Text, "call") || strings.HasPrefix(curinstr.Text, "CALL") || strings.HasPrefix(curinstr.Text, "jirl") || strings.HasPrefix(curinstr.Text, "bl"){ t.Logf("call: %v", curinstr) if curinstr.DestLoc == nil || curinstr.DestLoc.Function == nil { t.Fatalf("Call instruction does not have destination: %v", curinstr) diff -Naur delve-1.22.0.old/service/test/integration2_test.go delve-1.22.0/service/test/integration2_test.go --- delve-1.22.0.old/service/test/integration2_test.go 2024-06-08 17:27:28.703331240 +0800 +++ delve-1.22.0/service/test/integration2_test.go 2024-06-08 19:17:49.975331240 +0800 @@ -1418,7 +1418,7 @@ // look for static call to afunction() on line 29 found := false for i := range d3 { - if d3[i].Loc.Line == 29 && (strings.HasPrefix(d3[i].Text, "call") || strings.HasPrefix(d3[i].Text, "CALL")) && d3[i].DestLoc != nil && d3[i].DestLoc.Function != nil && d3[i].DestLoc.Function.Name() == "main.afunction" { + if d3[i].Loc.Line == 29 && (strings.HasPrefix(d3[i].Text, "bl") || strings.HasPrefix(d3[i].Text, "jirl") || strings.HasPrefix(d3[i].Text, "call") || strings.HasPrefix(d3[i].Text, "CALL")) && d3[i].DestLoc != nil && d3[i].DestLoc.Function != nil && d3[i].DestLoc.Function.Name() == "main.afunction" { found = true break } @@ -1468,7 +1468,7 @@ t.Fatal("Calling StepInstruction() repeatedly did not find the call instruction") } - if strings.HasPrefix(curinstr.Text, "call") || strings.HasPrefix(curinstr.Text, "CALL") { + if strings.HasPrefix(curinstr.Text, "call") || strings.HasPrefix(curinstr.Text, "CALL") || strings.HasPrefix(curinstr.Text, "bl") || strings.HasPrefix(curinstr.Text, "jirl") { t.Logf("call: %v", curinstr) if curinstr.DestLoc == nil || curinstr.DestLoc.Function == nil { t.Fatalf("Call instruction does not have destination: %v", curinstr) diff -Naur delve-1.22.0.old/vendor/golang.org/x/arch/loong64/loong64asm/arg.go delve-1.22.0/vendor/golang.org/x/arch/loong64/loong64asm/arg.go --- delve-1.22.0.old/vendor/golang.org/x/arch/loong64/loong64asm/arg.go 1970-01-01 08:00:00.000000000 +0800 +++ delve-1.22.0/vendor/golang.org/x/arch/loong64/loong64asm/arg.go 2024-06-08 19:28:12.463331240 +0800 @@ -0,0 +1,93 @@ +// Copyright 2023 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 loong64asm + +// Naming for Go decoder arguments: +// +// - arg_fd: a Floating Point operand register fd encoded in the fd[4:0] field +// +// - arg_fj: a Floating Point operand register fj encoded in the fj[9:5] field +// +// - arg_fk: a Floating Point operand register fk encoded in the fk[14:10] field +// +// - arg_fa: a Floating Point operand register fa encoded in the fa[19:15] field +// +// - arg_rd: a general-purpose register rd encoded in the rd[4:0] field +// +// - arg_rj: a general-purpose register rj encoded in the rj[9:5] field +// +// - arg_rk: a general-purpose register rk encoded in the rk[14:10] field +// +// - arg_fcsr_4_0: float control status register encoded in [4:0] field +// +// - arg_cd_2_0: condition flag register encoded in [2:0] field +// +// - arg_sa2_16_15: shift bits constant encoded in [16:15] field +// +// - arg_code_14_0: arg for exception process routine encoded in [14:0] field +// +// - arg_ui5_14_10: 5bits unsigned immediate +// +// - arg_lsbw: For details, please refer to chapter 2.2.3.8 of instruction manual +// +// - arg_msbw: For details, please refer to chapter 2.2.3.9 of instruction manual +// +// - arg_hint_4_0: hint field implied the prefetch type and the data should fetch to cache's level +// 0: load to data cache level 1 +// 8: store to data cache level 1 +// other: no define +// +// - arg_si12_21_10: 12bits signed immediate + +type instArg uint16 + +const ( + _ instArg = iota + //1-5 + arg_fd + arg_fj + arg_fk + arg_fa + arg_rd + //6-10 + arg_rj + arg_rk + arg_op_4_0 + arg_fcsr_4_0 + arg_fcsr_9_5 + //11-15 + arg_csr_23_10 + arg_cd + arg_cj + arg_ca + arg_sa2_16_15 + //16-20 + arg_sa3_17_15 + arg_code_4_0 + arg_code_14_0 + arg_ui5_14_10 + arg_ui6_15_10 + //21-25 + arg_ui12_21_10 + arg_lsbw + arg_msbw + arg_lsbd + arg_msbd + //26-30 + arg_hint_4_0 + arg_hint_14_0 + arg_level_14_0 + arg_level_17_10 + arg_seq_17_10 + //31-35 + arg_si12_21_10 + arg_si14_23_10 + arg_si16_25_10 + arg_si20_24_5 + arg_offset_20_0 + //36~ + arg_offset_25_0 + arg_offset_15_0 +) diff -Naur delve-1.22.0.old/vendor/golang.org/x/arch/loong64/loong64asm/decode.go delve-1.22.0/vendor/golang.org/x/arch/loong64/loong64asm/decode.go --- delve-1.22.0.old/vendor/golang.org/x/arch/loong64/loong64asm/decode.go 1970-01-01 08:00:00.000000000 +0800 +++ delve-1.22.0/vendor/golang.org/x/arch/loong64/loong64asm/decode.go 2024-06-08 19:28:33.979331240 +0800 @@ -0,0 +1,269 @@ +// Copyright 2023 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 loong64asm + +import ( + "encoding/binary" + "fmt" +) + +type instArgs [5]instArg + +// 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 instArgs +} + +var ( + errShort = fmt.Errorf("truncated instruction") + errUnknown = fmt.Errorf("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 Inst, err error) { + if len(src) < 4 { + return Inst{}, errShort + } + + x := binary.LittleEndian.Uint32(src) + +Search: + for i := range instFormats { + f := &instFormats[i] + + 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 { + // Cannot decode argument + continue Search + } + + args[j] = arg + } + + decoderCover[i] = true + inst = Inst{ + Op: f.op, + Args: args, + Enc: x, + } + 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 instArg, x uint32, index int) Arg { + switch aop { + case arg_fd: + return F0 + Reg(x&((1<<5)-1)) + + case arg_fj: + return F0 + Reg((x>>5)&((1<<5)-1)) + + case arg_fk: + return F0 + Reg((x>>10)&((1<<5)-1)) + + case arg_fa: + return F0 + Reg((x>>15)&((1<<5)-1)) + + case arg_rd: + return R0 + Reg(x&((1<<5)-1)) + + case arg_rj: + return R0 + Reg((x>>5)&((1<<5)-1)) + + case arg_rk: + return R0 + Reg((x>>10)&((1<<5)-1)) + + case arg_fcsr_4_0: + return FCSR0 + Fcsr(x&((1<<5)-1)) + + case arg_fcsr_9_5: + return FCSR0 + Fcsr((x>>5)&((1<<5)-1)) + + case arg_cd: + return FCC0 + Fcc(x&((1<<3)-1)) + + case arg_cj: + return FCC0 + Fcc((x>>5)&((1<<3)-1)) + + case arg_ca: + return FCC0 + Fcc((x>>15)&((1<<3)-1)) + + case arg_op_4_0: + tmp := x & ((1 << 5) - 1) + return Uimm{tmp, false} + + case arg_csr_23_10: + tmp := (x >> 10) & ((1 << 14) - 1) + return Uimm{tmp, false} + + case arg_sa2_16_15: + f := &instFormats[index] + tmp := SaSimm((x >> 15) & ((1 << 2) - 1)) + if (f.op == ALSL_D) || (f.op == ALSL_W) || (f.op == ALSL_WU) { + return tmp + 1 + } else { + return tmp + 0 + } + + case arg_sa3_17_15: + return SaSimm((x >> 15) & ((1 << 3) - 1)) + + case arg_code_4_0: + return CodeSimm(x & ((1 << 5) - 1)) + + case arg_code_14_0: + return CodeSimm(x & ((1 << 15) - 1)) + + case arg_ui5_14_10: + tmp := (x >> 10) & ((1 << 5) - 1) + return Uimm{tmp, false} + + case arg_ui6_15_10: + tmp := (x >> 10) & ((1 << 6) - 1) + return Uimm{tmp, false} + + case arg_ui12_21_10: + tmp := ((x >> 10) & ((1 << 12) - 1) & 0xfff) + return Uimm{tmp, false} + + case arg_lsbw: + tmp := (x >> 10) & ((1 << 5) - 1) + return Uimm{tmp, false} + + case arg_msbw: + tmp := (x >> 16) & ((1 << 5) - 1) + return Uimm{tmp, false} + + case arg_lsbd: + tmp := (x >> 10) & ((1 << 6) - 1) + return Uimm{tmp, false} + + case arg_msbd: + tmp := (x >> 16) & ((1 << 6) - 1) + return Uimm{tmp, false} + + case arg_hint_4_0: + tmp := x & ((1 << 5) - 1) + return Uimm{tmp, false} + + case arg_hint_14_0: + tmp := x & ((1 << 15) - 1) + return Uimm{tmp, false} + + case arg_level_14_0: + tmp := x & ((1 << 15) - 1) + return Uimm{tmp, false} + + case arg_level_17_10: + tmp := (x >> 10) & ((1 << 8) - 1) + return Uimm{tmp, false} + + case arg_seq_17_10: + tmp := (x >> 10) & ((1 << 8) - 1) + return Uimm{tmp, false} + + case arg_si12_21_10: + var tmp int16 + + //no int12, so sign-extend a 12-bit signed to 16-bit signed + if (x & 0x200000) == 0x200000 { + tmp = int16(((x >> 10) & ((1 << 12) - 1)) | 0xf000) + } else { + tmp = int16(((x >> 10) & ((1 << 12) - 1)) | 0x0000) + } + return Simm16{tmp, 12} + + case arg_si14_23_10: + var tmp int32 + if (x & 0x800000) == 0x800000 { + tmp = int32((((x >> 10) & ((1 << 14) - 1)) << 2) | 0xffff0000) + } else { + tmp = int32((((x >> 10) & ((1 << 14) - 1)) << 2) | 0x00000000) + } + return Simm32{tmp, 14} + + case arg_si16_25_10: + var tmp int32 + + if (x & 0x2000000) == 0x2000000 { + tmp = int32(((x >> 10) & ((1 << 16) - 1)) | 0xffff0000) + } else { + tmp = int32(((x >> 10) & ((1 << 16) - 1)) | 0x00000000) + } + + return Simm32{tmp, 16} + + case arg_si20_24_5: + var tmp int32 + if (x & 0x1000000) == 0x1000000 { + tmp = int32(((x >> 5) & ((1 << 20) - 1)) | 0xfff00000) + } else { + tmp = int32(((x >> 5) & ((1 << 20) - 1)) | 0x00000000) + } + return Simm32{tmp, 20} + + case arg_offset_20_0: + var tmp int32 + + if (x & 0x10) == 0x10 { + tmp = int32(((((x << 16) | ((x >> 10) & ((1 << 16) - 1))) & ((1 << 21) - 1)) << 2) | 0xff800000) + } else { + tmp = int32((((x << 16) | ((x >> 10) & ((1 << 16) - 1))) & ((1 << 21) - 1)) << 2) + } + + return OffsetSimm{tmp, 21} + + case arg_offset_15_0: + var tmp int32 + if (x & 0x2000000) == 0x2000000 { + tmp = int32((((x >> 10) & ((1 << 16) - 1)) << 2) | 0xfffc0000) + } else { + tmp = int32((((x >> 10) & ((1 << 16) - 1)) << 2) | 0x00000000) + } + + return OffsetSimm{tmp, 16} + + case arg_offset_25_0: + var tmp int32 + + if (x & 0x200) == 0x200 { + tmp = int32(((((x << 16) | ((x >> 10) & ((1 << 16) - 1))) & ((1 << 26) - 1)) << 2) | 0xf0000000) + } else { + tmp = int32(((((x << 16) | ((x >> 10) & ((1 << 16) - 1))) & ((1 << 26) - 1)) << 2) | 0x00000000) + } + + return OffsetSimm{tmp, 26} + default: + return nil + } +} diff -Naur delve-1.22.0.old/vendor/golang.org/x/arch/loong64/loong64asm/gnu.go delve-1.22.0/vendor/golang.org/x/arch/loong64/loong64asm/gnu.go --- delve-1.22.0.old/vendor/golang.org/x/arch/loong64/loong64asm/gnu.go 1970-01-01 08:00:00.000000000 +0800 +++ delve-1.22.0/vendor/golang.org/x/arch/loong64/loong64asm/gnu.go 2024-06-08 19:28:50.963331240 +0800 @@ -0,0 +1,16 @@ +// Copyright 2023 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 loong64asm + +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 Loong64 Reference Manual. See +// https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html +func GNUSyntax(inst Inst) string { + return strings.ToLower(inst.String()) +} diff -Naur delve-1.22.0.old/vendor/golang.org/x/arch/loong64/loong64asm/inst.go delve-1.22.0/vendor/golang.org/x/arch/loong64/loong64asm/inst.go --- delve-1.22.0.old/vendor/golang.org/x/arch/loong64/loong64asm/inst.go 1970-01-01 08:00:00.000000000 +0800 +++ delve-1.22.0/vendor/golang.org/x/arch/loong64/loong64asm/inst.go 2024-06-08 19:29:29.299331240 +0800 @@ -0,0 +1,302 @@ +// Copyright 2023 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 loong64asm + +import ( + "fmt" + "strings" +) + +// An Inst is a single instruction. +type Inst struct { + Op Op // Opcode mnemonic + Enc uint32 // Raw encoding bits. + Args Args // Instruction arguments, in Loong64 manual order. +} + +func (i Inst) String() string { + var op string = i.Op.String() + var args []string + + for _, arg := range i.Args { + if arg == nil { + break + } + args = append(args, arg.String()) + } + + switch i.Op { + case OR: + if i.Args[2].(Reg) == R0 { + op = "move" + args = args[0:2] + } + + case ANDI: + if i.Args[0].(Reg) == R0 && i.Args[1].(Reg) == R0 { + return "nop" + } + + case JIRL: + if i.Args[0].(Reg) == R0 && i.Args[2].(OffsetSimm).Imm == 0 { + return "jr " + args[1] + } + + case BLT: + if i.Args[0].(Reg) == R0 { + op = "bgtz" + args = args[1:] + } else if i.Args[1].(Reg) == R0 { + op = "bltz" + args = append(args[:1], args[2:]...) + } + + case BGE: + if i.Args[0].(Reg) == R0 { + op = "blez" + args = args[1:] + } else if i.Args[1].(Reg) == R0 { + op = "bgez" + args = append(args[:1], args[2:]...) + } + } + + if len(args) == 0 { + return op + } else { + return op + " " + strings.Join(args, ", ") + } +} + +// An Op is an Loong64 opcode. +type Op uint16 + +// NOTE: The actual Op values are defined in tables.go. +// They are chosen to simplify instruction decoding and +// are not a dense packing from 0 to N, although the +// density is high, probably at least 90%. +func (op Op) String() string { + if (op >= Op(len(opstr))) || (opstr[op] == "") { + return fmt.Sprintf("Op(%d)", int(op)) + } + + return opstr[op] +} + +// An Args holds the instruction arguments. +// If an instruction has fewer than 5 arguments, +// the final elements in the array are nil. +type Args [5]Arg + +// An Arg is a single instruction argument +type Arg interface { + String() string +} + +// A Reg is a single register. +// The zero value denotes R0, not the absence of a register. +type Reg uint16 + +const ( + //_ Reg = iota + + // General-purpose register + R0 Reg = iota + R1 + R2 + R3 + R4 + R5 + R6 + R7 + R8 + R9 + R10 + R11 + R12 + R13 + R14 + R15 + R16 + R17 + R18 + R19 + R20 + R21 + R22 + R23 + R24 + R25 + R26 + R27 + R28 + R29 + R30 + R31 + + // 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 == R0: + return "$zero" + + case r == R1: + return "$ra" + + case r == R2: + return "$tp" + + case r == R3: + return "$sp" + + case (r >= R4) && (r <= R11): + return fmt.Sprintf("$a%d", int(r-R4)) + + case (r >= R12) && (r <= R20): + return fmt.Sprintf("$t%d", int(r-R12)) + + case r == R21: + return "$r21" + + case r == R22: + return "$fp" + + case (r >= R23) && (r <= R31): + return fmt.Sprintf("$s%d", int(r-R23)) + + case (r >= F0) && (r <= F7): + return fmt.Sprintf("$fa%d", int(r-F0)) + + case (r >= F8) && (r <= F23): + return fmt.Sprintf("$ft%d", int(r-F8)) + + case (r >= F24) && (r <= F31): + return fmt.Sprintf("$fs%d", int(r-F24)) + + default: + return fmt.Sprintf("Unknown(%d)", int(r)) + } +} + +// float control status register +type Fcsr uint8 + +const ( + //_ Fcsr = iota + FCSR0 Fcsr = iota + FCSR1 + FCSR2 + FCSR3 +) + +func (f Fcsr) String() string { + return fmt.Sprintf("$fcsr%d", uint8(f)) +} + +// float condition flags register +type Fcc uint8 + +const ( + //_ Fcc = iota + FCC0 Fcc = iota + FCC1 + FCC2 + FCC3 + FCC4 + FCC5 + FCC6 + FCC7 +) + +func (f Fcc) String() string { + return fmt.Sprintf("$fcc%d", uint8(f)) +} + +// An Imm is an integer constant. +type Uimm struct { + Imm uint32 + Decimal bool +} + +func (i Uimm) String() string { + if i.Decimal == true { + return fmt.Sprintf("%d", i.Imm) + } else { + return fmt.Sprintf("%#x", i.Imm) + } +} + +type Simm16 struct { + Imm int16 + Width uint8 +} + +func (si Simm16) String() string { + return fmt.Sprintf("%d", int32(si.Imm)) +} + +type Simm32 struct { + Imm int32 + Width uint8 +} + +func (si Simm32) String() string { + return fmt.Sprintf("%d", int32(si.Imm)) +} + +type OffsetSimm struct { + Imm int32 + Width uint8 +} + +func (o OffsetSimm) String() string { + return fmt.Sprintf("%d", int32(o.Imm)) +} + +type SaSimm int16 + +func (s SaSimm) String() string { + return fmt.Sprintf("%#x", int(s)) +} + +type CodeSimm int16 + +func (c CodeSimm) String() string { + return fmt.Sprintf("%#x", int(c)) +} diff -Naur delve-1.22.0.old/vendor/golang.org/x/arch/loong64/loong64asm/plan9x.go delve-1.22.0/vendor/golang.org/x/arch/loong64/loong64asm/plan9x.go --- delve-1.22.0.old/vendor/golang.org/x/arch/loong64/loong64asm/plan9x.go 1970-01-01 08:00:00.000000000 +0800 +++ delve-1.22.0/vendor/golang.org/x/arch/loong64/loong64asm/plan9x.go 2024-06-08 19:30:22.707331240 +0800 @@ -0,0 +1,437 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package loong64asm + +import ( + "fmt" + "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. +func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) string { + if symname == nil { + symname = func(uint64) (string, uint64) { return "", 0 } + } + if inst.Op == 0 && inst.Enc == 0 { + return "WORD $0" + } else if inst.Op == 0 { + return "?" + } + + var args []string + for _, a := range inst.Args { + if a == nil { + break + } + args = append(args, plan9Arg(&inst, pc, symname, a)) + } + + var op string = plan9OpMap[inst.Op] + if op == "" { + op = "Unknown " + inst.Op.String() + } + + switch inst.Op { + case BSTRPICK_D: + msbw, lsbw := inst.Args[2].(Uimm), inst.Args[3].(Uimm) + if msbw.Imm == 15 && lsbw.Imm == 0 { + op = "MOVHU" + } else if msbw.Imm == 31 && lsbw.Imm == 0 { + op = "MOVWU" + } + args = append(args[1:2], args[0:1]...) + + case BCNEZ, BCEQZ: + args = args[1:2] + + case BEQ, BNE: + rj := inst.Args[0].(Reg) + rd := inst.Args[1].(Reg) + if rj == rd && inst.Op == BEQ { + op = "JMP" + args = args[2:] + } else if rj == R0 { + args = args[1:] + } else if rd == R0 { + args = append(args[:1], args[2:]...) + } + + case BEQZ, BNEZ: + if inst.Args[0].(Reg) == R0 && inst.Op == BEQ { + op = "JMP" + args = args[1:] + } + + case BLT, BLTU, BGE, BGEU: + rj := inst.Args[0].(Reg) + rd := inst.Args[1].(Reg) + if rj == rd && (inst.Op == BGE || inst.Op == BGEU) { + op = "JMP" + args = args[2:] + } else if rj == R0 { + switch inst.Op { + case BGE: + op = "BLEZ" + case BLT: + op = "BGTZ" + } + args = args[1:] + } else if rd == R0 { + if !strings.HasSuffix(op, "U") { + op += "Z" + } + args = append(args[:1], args[2:]...) + } + + case JIRL: + rd := inst.Args[0].(Reg) + rj := inst.Args[1].(Reg) + regno := uint16(rj) & 31 + if rd == R0 { + return fmt.Sprintf("JMP (R%d)", regno) + } + return fmt.Sprintf("CALL (R%d)", regno) + + case LD_B, LD_H, LD_W, LD_D, LD_BU, LD_HU, LD_WU, LL_W, LL_D, + ST_B, ST_H, ST_W, ST_D, SC_W, SC_D, FLD_S, FLD_D, FST_S, FST_D: + var off int32 + switch a := inst.Args[2].(type) { + case Simm16: + off = signumConvInt32(int32(a.Imm), a.Width) + case Simm32: + off = signumConvInt32(int32(a.Imm), a.Width) >> 2 + } + Iop := strings.ToUpper(inst.Op.String()) + if strings.HasPrefix(Iop, "L") || strings.HasPrefix(Iop, "FL") { + return fmt.Sprintf("%s %d(%s), %s", op, off, args[1], args[0]) + } + return fmt.Sprintf("%s %s, %d(%s)", op, args[0], off, args[1]) + + case CACOP: + code := inst.Args[0].(CodeSimm) + si12 := inst.Args[2].(Simm16) + off := signumConvInt32(int32(si12.Imm), si12.Width) + return fmt.Sprintf("%s R%d, %d(%s)", op, code, off, args[1]) + + default: + // 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] + } + switch len(args) { + case 0, 1: + if inst.Op != B && inst.Op != BL { + return op + } + + case 3: + switch a0 := inst.Args[0].(type) { + case Reg: + rj := inst.Args[1].(Reg) + if a0 == rj && a0 != R0 { + args = args[0:2] + } + case Fcc: + args = args[0:2] + } + switch inst.Op { + case SUB_W, SUB_D, ADDI_W, ADDI_D, ORI: + rj := inst.Args[1].(Reg) + if rj == R0 { + args = append(args[0:1], args[2:]...) + if inst.Op == SUB_W { + op = "NEGW" + } else if inst.Op == SUB_D { + op = "NEGV" + } else { + op = "MOVW" + } + } + + case ANDI: + ui12 := inst.Args[2].(Uimm) + if ui12.Imm == uint32(0xff) { + op = "MOVBU" + args = args[1:] + } else if ui12.Imm == 0 && inst.Args[0].(Reg) == R0 && inst.Args[1].(Reg) == R0 { + return "NOOP" + } + + case SLL_W, OR: + rk := inst.Args[2].(Reg) + if rk == R0 { + args = args[1:] + if inst.Op == SLL_W { + op = "MOVW" + } else { + op = "MOVV" + } + } + } + } + } + + if args != nil { + op += " " + strings.Join(args, ", ") + } + return op +} + +func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string { + // Reg: gpr[0, 31] and fpr[0, 31] + // Fcsr: fcsr[0, 3] + // Fcc: fcc[0, 7] + // Uimm: unsigned integer constant + // Simm16: si16 + // Simm32: si32 + // OffsetSimm: si32 + switch a := arg.(type) { + case Reg: + regenum := uint16(a) + regno := uint16(a) & 0x1f + // General-purpose register + if regenum >= uint16(R0) && regenum <= uint16(R31) { + return fmt.Sprintf("R%d", regno) + } else { // Float point register + return fmt.Sprintf("F%d", regno) + } + + case Fcsr: + regno := uint8(a) & 0x1f + return fmt.Sprintf("FCSR%d", regno) + + case Fcc: + regno := uint8(a) & 0x1f + return fmt.Sprintf("FCC%d", regno) + + case Uimm: + return fmt.Sprintf("$%d", a.Imm) + + case Simm16: + si16 := signumConvInt32(int32(a.Imm), a.Width) + return fmt.Sprintf("$%d", si16) + + case Simm32: + si32 := signumConvInt32(a.Imm, a.Width) + return fmt.Sprintf("$%d", si32) + + case OffsetSimm: + offs := offsConvInt32(a.Imm, a.Width) + if inst.Op == B || inst.Op == BL { + addr := int64(pc) + int64(a.Imm) + if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base { + return fmt.Sprintf("%s(SB)", s) + } + } + return fmt.Sprintf("%d(PC)", offs>>2) + + case SaSimm: + return fmt.Sprintf("$%d", a) + + case CodeSimm: + return fmt.Sprintf("$%d", a) + + } + return strings.ToUpper(arg.String()) +} + +func signumConvInt32(imm int32, width uint8) int32 { + active := uint32(1<> (width - 1)) & 0x1) == 1 { + signum |= ^active + } + return int32(signum) +} + +func offsConvInt32(imm int32, width uint8) int32 { + relWidth := width + 2 + return signumConvInt32(imm, relWidth) +} + +var plan9OpMap = map[Op]string{ + ADD_W: "ADD", + ADD_D: "ADDV", + SUB_W: "SUB", + SUB_D: "SUBV", + ADDI_W: "ADD", + ADDI_D: "ADDV", + LU12I_W: "LU12IW", + LU32I_D: "LU32ID", + LU52I_D: "LU52ID", + SLT: "SGT", + SLTU: "SGTU", + SLTI: "SGT", + SLTUI: "SGTU", + PCADDU12I: "PCADDU12I", + PCALAU12I: "PCALAU12I", + AND: "AND", + OR: "OR", + NOR: "NOR", + XOR: "XOR", + ANDI: "AND", + ORI: "OR", + XORI: "XOR", + MUL_W: "MUL", + MULH_W: "MULH", + MULH_WU: "MULHU", + MUL_D: "MULV", + MULH_D: "MULHV", + MULH_DU: "MULHVU", + DIV_W: "DIV", + DIV_WU: "DIVU", + DIV_D: "DIVV", + DIV_DU: "DIVVU", + MOD_W: "REM", + MOD_WU: "REMU", + MOD_D: "REMV", + MOD_DU: "REMVU", + SLL_W: "SLL", + SRL_W: "SRL", + SRA_W: "SRA", + ROTR_W: "ROTR", + SLL_D: "SLLV", + SRL_D: "SRLV", + SRA_D: "SRAV", + ROTR_D: "ROTRV", + SLLI_W: "SLL", + SRLI_W: "SRL", + SRAI_W: "SRA", + ROTRI_W: "ROTR", + SLLI_D: "SLLV", + SRLI_D: "SRLV", + SRAI_D: "SRAV", + ROTRI_D: "ROTRV", + EXT_W_B: "", + EXT_W_H: "", + CLO_W: "CLO", + CLZ_W: "CLZ", + BSTRPICK_D: "", + MASKEQZ: "MASKEQZ", + MASKNEZ: "MASKNEZ", + BCNEZ: "BFPT", + BCEQZ: "BFPF", + BEQ: "BEQ", + BNE: "BNE", + BEQZ: "BEQ", + BNEZ: "BNE", + BLT: "BLT", + BLTU: "BLTU", + BGE: "BGE", + BGEU: "BGEU", + B: "JMP", + BL: "CALL", + LD_B: "MOVB", + LD_H: "MOVH", + LD_W: "MOVW", + LD_D: "MOVV", + LD_BU: "MOVBU", + LD_HU: "MOVHU", + LD_WU: "MOVWU", + ST_B: "MOVB", + ST_H: "MOVH", + ST_W: "MOVW", + ST_D: "MOVV", + AMSWAP_W: "AMSWAPW", + AMSWAP_D: "AMSWAPD", + AMADD_W: "AMADDW", + AMADD_D: "AMADDV", + AMAND_W: "AMANDW", + AMAND_D: "AMANDV", + AMOR_W: "AMORW", + AMOR_D: "AMORV", + AMXOR_W: "AMXORW", + AMXOR_D: "AMXORV", + AMMAX_W: "AMMAXW", + AMMAX_D: "AMMAXV", + AMMIN_W: "AMMINW", + AMMIN_D: "AMMINV", + AMMAX_WU: "AMMAXWU", + AMMAX_DU: "AMMAXVU", + AMMIN_WU: "AMMINWU", + AMMIN_DU: "AMMINVU", + AMSWAP_DB_W: "AMSWAPDBW", + AMSWAP_DB_D: "AMSWAPDBV", + AMADD_DB_W: "AMADDDBW", + AMADD_DB_D: "AMADDDBV", + AMAND_DB_W: "AMANDDBW", + AMAND_DB_D: "AMANDDBV", + AMOR_DB_W: "AMORDBW", + AMOR_DB_D: "AMORDBV", + AMXOR_DB_W: "AMXORDBW", + AMXOR_DB_D: "AMXORDBV", + AMMAX_DB_W: "AMMAXDBW", + AMMAX_DB_D: "AMMAXDBV", + AMMIN_DB_W: "AMMINDBW", + AMMIN_DB_D: "AMMINDBV", + AMMAX_DB_WU: "AMMAXDBWU", + AMMAX_DB_DU: "AMMAXDBVU", + AMMIN_DB_WU: "AMMINDBWU", + AMMIN_DB_DU: "AMMINDBVU", + LL_W: "LL", + LL_D: "LLV", + SC_W: "SC", + SC_D: "SCV", + DBAR: "DBAR", + SYSCALL: "SYSCALL", + BREAK: "BREAK", + CACOP: "BREAK", + RDTIMEL_W: "RDTIMELW", + RDTIMEH_W: "RDTIMEHW", + RDTIME_D: "RDTIMED", + FADD_S: "ADDF", + FADD_D: "ADDD", + FSUB_S: "SUBF", + FSUB_D: "SUBD", + FMUL_S: "MULF", + FMUL_D: "MULD", + FDIV_S: "DIVF", + FDIV_D: "DIVD", + FABS_S: "ABSF", + FABS_D: "ABSD", + FNEG_S: "NEGF", + FNEG_D: "NEGD", + FSQRT_S: "SQRTF", + FSQRT_D: "SQRTD", + FCMP_CEQ_S: "CMPEQF", + FCMP_CEQ_D: "CMPEQD", + FCMP_SLE_S: "CMPGEF", + FCMP_SLE_D: "CMPGED", + FCMP_SLT_S: "CMPGTF", + FCMP_SLT_D: "CMPGTD", + FCVT_D_S: "MOVFD", + FCVT_S_D: "MOVDF", + FFINT_S_W: "MOVWF", + FFINT_S_L: "MOVVF", + FFINT_D_W: "MOVWD", + FFINT_D_L: "MOVVD", + FTINT_W_S: "MOVFW", + FTINT_L_S: "MOVFV", + FTINT_W_D: "MOVDW", + FTINT_L_D: "MOVDV", + FTINTRZ_W_S: "TRUNCFW", + FTINTRZ_W_D: "TRUNCDW", + FTINTRZ_L_S: "TRUNCFV", + FTINTRZ_L_D: "TRUNCDV", + FMOV_S: "MOVF", + FMOV_D: "MOVD", + MOVGR2FR_W: "MOVW", + MOVGR2FR_D: "MOVV", + MOVFR2GR_S: "MOVW", + MOVFR2GR_D: "MOVV", + MOVGR2CF: "MOVV", + MOVCF2GR: "MOVV", + FLD_S: "MOVF", + FLD_D: "MOVD", + FST_S: "MOVF", + FST_D: "MOVD", +} diff -Naur delve-1.22.0.old/vendor/golang.org/x/arch/loong64/loong64asm/tables.go delve-1.22.0/vendor/golang.org/x/arch/loong64/loong64asm/tables.go --- delve-1.22.0.old/vendor/golang.org/x/arch/loong64/loong64asm/tables.go 1970-01-01 08:00:00.000000000 +0800 +++ delve-1.22.0/vendor/golang.org/x/arch/loong64/loong64asm/tables.go 2024-06-08 19:31:17.327331240 +0800 @@ -0,0 +1,1514 @@ +// Generated by loong64spec LoongArch-Vol1-EN.pdf +// DO NOT EDIT + +// Copyright 2023 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 loong64asm + +const ( + _ Op = iota + ADDI_D + ADDI_W + ADDU16I_D + ADD_D + ADD_W + ALSL_D + ALSL_W + ALSL_WU + AMADD_D + AMADD_DB_D + AMADD_DB_W + AMADD_W + AMAND_D + AMAND_DB_D + AMAND_DB_W + AMAND_W + AMMAX_D + AMMAX_DB_D + AMMAX_DB_DU + AMMAX_DB_W + AMMAX_DB_WU + AMMAX_DU + AMMAX_W + AMMAX_WU + AMMIN_D + AMMIN_DB_D + AMMIN_DB_DU + AMMIN_DB_W + AMMIN_DB_WU + AMMIN_DU + AMMIN_W + AMMIN_WU + AMOR_D + AMOR_DB_D + AMOR_DB_W + AMOR_W + AMSWAP_D + AMSWAP_DB_D + AMSWAP_DB_W + AMSWAP_W + AMXOR_D + AMXOR_DB_D + AMXOR_DB_W + AMXOR_W + AND + ANDI + ANDN + ASRTGT_D + ASRTLE_D + B + BCEQZ + BCNEZ + BEQ + BEQZ + BGE + BGEU + BITREV_4B + BITREV_8B + BITREV_D + BITREV_W + BL + BLT + BLTU + BNE + BNEZ + BREAK + BSTRINS_D + BSTRINS_W + BSTRPICK_D + BSTRPICK_W + BYTEPICK_D + BYTEPICK_W + CACOP + CLO_D + CLO_W + CLZ_D + CLZ_W + CPUCFG + CRCC_W_B_W + CRCC_W_D_W + CRCC_W_H_W + CRCC_W_W_W + CRC_W_B_W + CRC_W_D_W + CRC_W_H_W + CRC_W_W_W + CSRRD + CSRWR + CSRXCHG + CTO_D + CTO_W + CTZ_D + CTZ_W + DBAR + DBCL + DIV_D + DIV_DU + DIV_W + DIV_WU + ERTN + EXT_W_B + EXT_W_H + FABS_D + FABS_S + FADD_D + FADD_S + FCLASS_D + FCLASS_S + FCMP_CAF_D + FCMP_CAF_S + FCMP_CEQ_D + FCMP_CEQ_S + FCMP_CLE_D + FCMP_CLE_S + FCMP_CLT_D + FCMP_CLT_S + FCMP_CNE_D + FCMP_CNE_S + FCMP_COR_D + FCMP_COR_S + FCMP_CUEQ_D + FCMP_CUEQ_S + FCMP_CULE_D + FCMP_CULE_S + FCMP_CULT_D + FCMP_CULT_S + FCMP_CUNE_D + FCMP_CUNE_S + FCMP_CUN_D + FCMP_CUN_S + FCMP_SAF_D + FCMP_SAF_S + FCMP_SEQ_D + FCMP_SEQ_S + FCMP_SLE_D + FCMP_SLE_S + FCMP_SLT_D + FCMP_SLT_S + FCMP_SNE_D + FCMP_SNE_S + FCMP_SOR_D + FCMP_SOR_S + FCMP_SUEQ_D + FCMP_SUEQ_S + FCMP_SULE_D + FCMP_SULE_S + FCMP_SULT_D + FCMP_SULT_S + FCMP_SUNE_D + FCMP_SUNE_S + FCMP_SUN_D + FCMP_SUN_S + FCOPYSIGN_D + FCOPYSIGN_S + FCVT_D_S + FCVT_S_D + FDIV_D + FDIV_S + FFINT_D_L + FFINT_D_W + FFINT_S_L + FFINT_S_W + FLDGT_D + FLDGT_S + FLDLE_D + FLDLE_S + FLDX_D + FLDX_S + FLD_D + FLD_S + FLOGB_D + FLOGB_S + FMADD_D + FMADD_S + FMAXA_D + FMAXA_S + FMAX_D + FMAX_S + FMINA_D + FMINA_S + FMIN_D + FMIN_S + FMOV_D + FMOV_S + FMSUB_D + FMSUB_S + FMUL_D + FMUL_S + FNEG_D + FNEG_S + FNMADD_D + FNMADD_S + FNMSUB_D + FNMSUB_S + FRECIP_D + FRECIP_S + FRINT_D + FRINT_S + FRSQRT_D + FRSQRT_S + FSCALEB_D + FSCALEB_S + FSEL + FSQRT_D + FSQRT_S + FSTGT_D + FSTGT_S + FSTLE_D + FSTLE_S + FSTX_D + FSTX_S + FST_D + FST_S + FSUB_D + FSUB_S + FTINTRM_L_D + FTINTRM_L_S + FTINTRM_W_D + FTINTRM_W_S + FTINTRNE_L_D + FTINTRNE_L_S + FTINTRNE_W_D + FTINTRNE_W_S + FTINTRP_L_D + FTINTRP_L_S + FTINTRP_W_D + FTINTRP_W_S + FTINTRZ_L_D + FTINTRZ_L_S + FTINTRZ_W_D + FTINTRZ_W_S + FTINT_L_D + FTINT_L_S + FTINT_W_D + FTINT_W_S + IBAR + IDLE + INVTLB + IOCSRRD_B + IOCSRRD_D + IOCSRRD_H + IOCSRRD_W + IOCSRWR_B + IOCSRWR_D + IOCSRWR_H + IOCSRWR_W + JIRL + LDDIR + LDGT_B + LDGT_D + LDGT_H + LDGT_W + LDLE_B + LDLE_D + LDLE_H + LDLE_W + LDPTE + LDPTR_D + LDPTR_W + LDX_B + LDX_BU + LDX_D + LDX_H + LDX_HU + LDX_W + LDX_WU + LD_B + LD_BU + LD_D + LD_H + LD_HU + LD_W + LD_WU + LL_D + LL_W + LU12I_W + LU32I_D + LU52I_D + MASKEQZ + MASKNEZ + MOD_D + MOD_DU + MOD_W + MOD_WU + MOVCF2FR + MOVCF2GR + MOVFCSR2GR + MOVFR2CF + MOVFR2GR_D + MOVFR2GR_S + MOVFRH2GR_S + MOVGR2CF + MOVGR2FCSR + MOVGR2FRH_W + MOVGR2FR_D + MOVGR2FR_W + MULH_D + MULH_DU + MULH_W + MULH_WU + MULW_D_W + MULW_D_WU + MUL_D + MUL_W + NOR + OR + ORI + ORN + PCADDI + PCADDU12I + PCADDU18I + PCALAU12I + PRELD + PRELDX + RDTIMEH_W + RDTIMEL_W + RDTIME_D + REVB_2H + REVB_2W + REVB_4H + REVB_D + REVH_2W + REVH_D + ROTRI_D + ROTRI_W + ROTR_D + ROTR_W + SC_D + SC_W + SLLI_D + SLLI_W + SLL_D + SLL_W + SLT + SLTI + SLTU + SLTUI + SRAI_D + SRAI_W + SRA_D + SRA_W + SRLI_D + SRLI_W + SRL_D + SRL_W + STGT_B + STGT_D + STGT_H + STGT_W + STLE_B + STLE_D + STLE_H + STLE_W + STPTR_D + STPTR_W + STX_B + STX_D + STX_H + STX_W + ST_B + ST_D + ST_H + ST_W + SUB_D + SUB_W + SYSCALL + TLBCLR + TLBFILL + TLBFLUSH + TLBRD + TLBSRCH + TLBWR + XOR + XORI +) + +var opstr = [...]string{ + ADDI_D: "ADDI.D", + ADDI_W: "ADDI.W", + ADDU16I_D: "ADDU16I.D", + ADD_D: "ADD.D", + ADD_W: "ADD.W", + ALSL_D: "ALSL.D", + ALSL_W: "ALSL.W", + ALSL_WU: "ALSL.WU", + AMADD_D: "AMADD.D", + AMADD_DB_D: "AMADD_DB.D", + AMADD_DB_W: "AMADD_DB.W", + AMADD_W: "AMADD.W", + AMAND_D: "AMAND.D", + AMAND_DB_D: "AMAND_DB.D", + AMAND_DB_W: "AMAND_DB.W", + AMAND_W: "AMAND.W", + AMMAX_D: "AMMAX.D", + AMMAX_DB_D: "AMMAX_DB.D", + AMMAX_DB_DU: "AMMAX_DB.DU", + AMMAX_DB_W: "AMMAX_DB.W", + AMMAX_DB_WU: "AMMAX_DB.WU", + AMMAX_DU: "AMMAX.DU", + AMMAX_W: "AMMAX.W", + AMMAX_WU: "AMMAX.WU", + AMMIN_D: "AMMIN.D", + AMMIN_DB_D: "AMMIN_DB.D", + AMMIN_DB_DU: "AMMIN_DB.DU", + AMMIN_DB_W: "AMMIN_DB.W", + AMMIN_DB_WU: "AMMIN_DB.WU", + AMMIN_DU: "AMMIN.DU", + AMMIN_W: "AMMIN.W", + AMMIN_WU: "AMMIN.WU", + AMOR_D: "AMOR.D", + AMOR_DB_D: "AMOR_DB.D", + AMOR_DB_W: "AMOR_DB.W", + AMOR_W: "AMOR.W", + AMSWAP_D: "AMSWAP.D", + AMSWAP_DB_D: "AMSWAP_DB.D", + AMSWAP_DB_W: "AMSWAP_DB.W", + AMSWAP_W: "AMSWAP.W", + AMXOR_D: "AMXOR.D", + AMXOR_DB_D: "AMXOR_DB.D", + AMXOR_DB_W: "AMXOR_DB.W", + AMXOR_W: "AMXOR.W", + AND: "AND", + ANDI: "ANDI", + ANDN: "ANDN", + ASRTGT_D: "ASRTGT.D", + ASRTLE_D: "ASRTLE.D", + B: "B", + BCEQZ: "BCEQZ", + BCNEZ: "BCNEZ", + BEQ: "BEQ", + BEQZ: "BEQZ", + BGE: "BGE", + BGEU: "BGEU", + BITREV_4B: "BITREV.4B", + BITREV_8B: "BITREV.8B", + BITREV_D: "BITREV.D", + BITREV_W: "BITREV.W", + BL: "BL", + BLT: "BLT", + BLTU: "BLTU", + BNE: "BNE", + BNEZ: "BNEZ", + BREAK: "BREAK", + BSTRINS_D: "BSTRINS.D", + BSTRINS_W: "BSTRINS.W", + BSTRPICK_D: "BSTRPICK.D", + BSTRPICK_W: "BSTRPICK.W", + BYTEPICK_D: "BYTEPICK.D", + BYTEPICK_W: "BYTEPICK.W", + CACOP: "CACOP", + CLO_D: "CLO.D", + CLO_W: "CLO.W", + CLZ_D: "CLZ.D", + CLZ_W: "CLZ.W", + CPUCFG: "CPUCFG", + CRCC_W_B_W: "CRCC.W.B.W", + CRCC_W_D_W: "CRCC.W.D.W", + CRCC_W_H_W: "CRCC.W.H.W", + CRCC_W_W_W: "CRCC.W.W.W", + CRC_W_B_W: "CRC.W.B.W", + CRC_W_D_W: "CRC.W.D.W", + CRC_W_H_W: "CRC.W.H.W", + CRC_W_W_W: "CRC.W.W.W", + CSRRD: "CSRRD", + CSRWR: "CSRWR", + CSRXCHG: "CSRXCHG", + CTO_D: "CTO.D", + CTO_W: "CTO.W", + CTZ_D: "CTZ.D", + CTZ_W: "CTZ.W", + DBAR: "DBAR", + DBCL: "DBCL", + DIV_D: "DIV.D", + DIV_DU: "DIV.DU", + DIV_W: "DIV.W", + DIV_WU: "DIV.WU", + ERTN: "ERTN", + EXT_W_B: "EXT.W.B", + EXT_W_H: "EXT.W.H", + FABS_D: "FABS.D", + FABS_S: "FABS.S", + FADD_D: "FADD.D", + FADD_S: "FADD.S", + FCLASS_D: "FCLASS.D", + FCLASS_S: "FCLASS.S", + FCMP_CAF_D: "FCMP.CAF.D", + FCMP_CAF_S: "FCMP.CAF.S", + FCMP_CEQ_D: "FCMP.CEQ.D", + FCMP_CEQ_S: "FCMP.CEQ.S", + FCMP_CLE_D: "FCMP.CLE.D", + FCMP_CLE_S: "FCMP.CLE.S", + FCMP_CLT_D: "FCMP.CLT.D", + FCMP_CLT_S: "FCMP.CLT.S", + FCMP_CNE_D: "FCMP.CNE.D", + FCMP_CNE_S: "FCMP.CNE.S", + FCMP_COR_D: "FCMP.COR.D", + FCMP_COR_S: "FCMP.COR.S", + FCMP_CUEQ_D: "FCMP.CUEQ.D", + FCMP_CUEQ_S: "FCMP.CUEQ.S", + FCMP_CULE_D: "FCMP.CULE.D", + FCMP_CULE_S: "FCMP.CULE.S", + FCMP_CULT_D: "FCMP.CULT.D", + FCMP_CULT_S: "FCMP.CULT.S", + FCMP_CUNE_D: "FCMP.CUNE.D", + FCMP_CUNE_S: "FCMP.CUNE.S", + FCMP_CUN_D: "FCMP.CUN.D", + FCMP_CUN_S: "FCMP.CUN.S", + FCMP_SAF_D: "FCMP.SAF.D", + FCMP_SAF_S: "FCMP.SAF.S", + FCMP_SEQ_D: "FCMP.SEQ.D", + FCMP_SEQ_S: "FCMP.SEQ.S", + FCMP_SLE_D: "FCMP.SLE.D", + FCMP_SLE_S: "FCMP.SLE.S", + FCMP_SLT_D: "FCMP.SLT.D", + FCMP_SLT_S: "FCMP.SLT.S", + FCMP_SNE_D: "FCMP.SNE.D", + FCMP_SNE_S: "FCMP.SNE.S", + FCMP_SOR_D: "FCMP.SOR.D", + FCMP_SOR_S: "FCMP.SOR.S", + FCMP_SUEQ_D: "FCMP.SUEQ.D", + FCMP_SUEQ_S: "FCMP.SUEQ.S", + FCMP_SULE_D: "FCMP.SULE.D", + FCMP_SULE_S: "FCMP.SULE.S", + FCMP_SULT_D: "FCMP.SULT.D", + FCMP_SULT_S: "FCMP.SULT.S", + FCMP_SUNE_D: "FCMP.SUNE.D", + FCMP_SUNE_S: "FCMP.SUNE.S", + FCMP_SUN_D: "FCMP.SUN.D", + FCMP_SUN_S: "FCMP.SUN.S", + FCOPYSIGN_D: "FCOPYSIGN.D", + FCOPYSIGN_S: "FCOPYSIGN.S", + FCVT_D_S: "FCVT.D.S", + FCVT_S_D: "FCVT.S.D", + FDIV_D: "FDIV.D", + FDIV_S: "FDIV.S", + FFINT_D_L: "FFINT.D.L", + FFINT_D_W: "FFINT.D.W", + FFINT_S_L: "FFINT.S.L", + FFINT_S_W: "FFINT.S.W", + FLDGT_D: "FLDGT.D", + FLDGT_S: "FLDGT.S", + FLDLE_D: "FLDLE.D", + FLDLE_S: "FLDLE.S", + FLDX_D: "FLDX.D", + FLDX_S: "FLDX.S", + FLD_D: "FLD.D", + FLD_S: "FLD.S", + FLOGB_D: "FLOGB.D", + FLOGB_S: "FLOGB.S", + FMADD_D: "FMADD.D", + FMADD_S: "FMADD.S", + FMAXA_D: "FMAXA.D", + FMAXA_S: "FMAXA.S", + FMAX_D: "FMAX.D", + FMAX_S: "FMAX.S", + FMINA_D: "FMINA.D", + FMINA_S: "FMINA.S", + FMIN_D: "FMIN.D", + FMIN_S: "FMIN.S", + FMOV_D: "FMOV.D", + FMOV_S: "FMOV.S", + FMSUB_D: "FMSUB.D", + FMSUB_S: "FMSUB.S", + FMUL_D: "FMUL.D", + FMUL_S: "FMUL.S", + FNEG_D: "FNEG.D", + FNEG_S: "FNEG.S", + FNMADD_D: "FNMADD.D", + FNMADD_S: "FNMADD.S", + FNMSUB_D: "FNMSUB.D", + FNMSUB_S: "FNMSUB.S", + FRECIP_D: "FRECIP.D", + FRECIP_S: "FRECIP.S", + FRINT_D: "FRINT.D", + FRINT_S: "FRINT.S", + FRSQRT_D: "FRSQRT.D", + FRSQRT_S: "FRSQRT.S", + FSCALEB_D: "FSCALEB.D", + FSCALEB_S: "FSCALEB.S", + FSEL: "FSEL", + FSQRT_D: "FSQRT.D", + FSQRT_S: "FSQRT.S", + FSTGT_D: "FSTGT.D", + FSTGT_S: "FSTGT.S", + FSTLE_D: "FSTLE.D", + FSTLE_S: "FSTLE.S", + FSTX_D: "FSTX.D", + FSTX_S: "FSTX.S", + FST_D: "FST.D", + FST_S: "FST.S", + FSUB_D: "FSUB.D", + FSUB_S: "FSUB.S", + FTINTRM_L_D: "FTINTRM.L.D", + FTINTRM_L_S: "FTINTRM.L.S", + FTINTRM_W_D: "FTINTRM.W.D", + FTINTRM_W_S: "FTINTRM.W.S", + FTINTRNE_L_D: "FTINTRNE.L.D", + FTINTRNE_L_S: "FTINTRNE.L.S", + FTINTRNE_W_D: "FTINTRNE.W.D", + FTINTRNE_W_S: "FTINTRNE.W.S", + FTINTRP_L_D: "FTINTRP.L.D", + FTINTRP_L_S: "FTINTRP.L.S", + FTINTRP_W_D: "FTINTRP.W.D", + FTINTRP_W_S: "FTINTRP.W.S", + FTINTRZ_L_D: "FTINTRZ.L.D", + FTINTRZ_L_S: "FTINTRZ.L.S", + FTINTRZ_W_D: "FTINTRZ.W.D", + FTINTRZ_W_S: "FTINTRZ.W.S", + FTINT_L_D: "FTINT.L.D", + FTINT_L_S: "FTINT.L.S", + FTINT_W_D: "FTINT.W.D", + FTINT_W_S: "FTINT.W.S", + IBAR: "IBAR", + IDLE: "IDLE", + INVTLB: "INVTLB", + IOCSRRD_B: "IOCSRRD.B", + IOCSRRD_D: "IOCSRRD.D", + IOCSRRD_H: "IOCSRRD.H", + IOCSRRD_W: "IOCSRRD.W", + IOCSRWR_B: "IOCSRWR.B", + IOCSRWR_D: "IOCSRWR.D", + IOCSRWR_H: "IOCSRWR.H", + IOCSRWR_W: "IOCSRWR.W", + JIRL: "JIRL", + LDDIR: "LDDIR", + LDGT_B: "LDGT.B", + LDGT_D: "LDGT.D", + LDGT_H: "LDGT.H", + LDGT_W: "LDGT.W", + LDLE_B: "LDLE.B", + LDLE_D: "LDLE.D", + LDLE_H: "LDLE.H", + LDLE_W: "LDLE.W", + LDPTE: "LDPTE", + LDPTR_D: "LDPTR.D", + LDPTR_W: "LDPTR.W", + LDX_B: "LDX.B", + LDX_BU: "LDX.BU", + LDX_D: "LDX.D", + LDX_H: "LDX.H", + LDX_HU: "LDX.HU", + LDX_W: "LDX.W", + LDX_WU: "LDX.WU", + LD_B: "LD.B", + LD_BU: "LD.BU", + LD_D: "LD.D", + LD_H: "LD.H", + LD_HU: "LD.HU", + LD_W: "LD.W", + LD_WU: "LD.WU", + LL_D: "LL.D", + LL_W: "LL.W", + LU12I_W: "LU12I.W", + LU32I_D: "LU32I.D", + LU52I_D: "LU52I.D", + MASKEQZ: "MASKEQZ", + MASKNEZ: "MASKNEZ", + MOD_D: "MOD.D", + MOD_DU: "MOD.DU", + MOD_W: "MOD.W", + MOD_WU: "MOD.WU", + MOVCF2FR: "MOVCF2FR", + MOVCF2GR: "MOVCF2GR", + MOVFCSR2GR: "MOVFCSR2GR", + MOVFR2CF: "MOVFR2CF", + MOVFR2GR_D: "MOVFR2GR.D", + MOVFR2GR_S: "MOVFR2GR.S", + MOVFRH2GR_S: "MOVFRH2GR.S", + MOVGR2CF: "MOVGR2CF", + MOVGR2FCSR: "MOVGR2FCSR", + MOVGR2FRH_W: "MOVGR2FRH.W", + MOVGR2FR_D: "MOVGR2FR.D", + MOVGR2FR_W: "MOVGR2FR.W", + MULH_D: "MULH.D", + MULH_DU: "MULH.DU", + MULH_W: "MULH.W", + MULH_WU: "MULH.WU", + MULW_D_W: "MULW.D.W", + MULW_D_WU: "MULW.D.WU", + MUL_D: "MUL.D", + MUL_W: "MUL.W", + NOR: "NOR", + OR: "OR", + ORI: "ORI", + ORN: "ORN", + PCADDI: "PCADDI", + PCADDU12I: "PCADDU12I", + PCADDU18I: "PCADDU18I", + PCALAU12I: "PCALAU12I", + PRELD: "PRELD", + PRELDX: "PRELDX", + RDTIMEH_W: "RDTIMEH.W", + RDTIMEL_W: "RDTIMEL.W", + RDTIME_D: "RDTIME.D", + REVB_2H: "REVB.2H", + REVB_2W: "REVB.2W", + REVB_4H: "REVB.4H", + REVB_D: "REVB.D", + REVH_2W: "REVH.2W", + REVH_D: "REVH.D", + ROTRI_D: "ROTRI.D", + ROTRI_W: "ROTRI.W", + ROTR_D: "ROTR.D", + ROTR_W: "ROTR.W", + SC_D: "SC.D", + SC_W: "SC.W", + SLLI_D: "SLLI.D", + SLLI_W: "SLLI.W", + SLL_D: "SLL.D", + SLL_W: "SLL.W", + SLT: "SLT", + SLTI: "SLTI", + SLTU: "SLTU", + SLTUI: "SLTUI", + SRAI_D: "SRAI.D", + SRAI_W: "SRAI.W", + SRA_D: "SRA.D", + SRA_W: "SRA.W", + SRLI_D: "SRLI.D", + SRLI_W: "SRLI.W", + SRL_D: "SRL.D", + SRL_W: "SRL.W", + STGT_B: "STGT.B", + STGT_D: "STGT.D", + STGT_H: "STGT.H", + STGT_W: "STGT.W", + STLE_B: "STLE.B", + STLE_D: "STLE.D", + STLE_H: "STLE.H", + STLE_W: "STLE.W", + STPTR_D: "STPTR.D", + STPTR_W: "STPTR.W", + STX_B: "STX.B", + STX_D: "STX.D", + STX_H: "STX.H", + STX_W: "STX.W", + ST_B: "ST.B", + ST_D: "ST.D", + ST_H: "ST.H", + ST_W: "ST.W", + SUB_D: "SUB.D", + SUB_W: "SUB.W", + SYSCALL: "SYSCALL", + TLBCLR: "TLBCLR", + TLBFILL: "TLBFILL", + TLBFLUSH: "TLBFLUSH", + TLBRD: "TLBRD", + TLBSRCH: "TLBSRCH", + TLBWR: "TLBWR", + XOR: "XOR", + XORI: "XORI", +} + +var instFormats = [...]instFormat{ + // ADDI.D rd, rj, si12 + {mask: 0xffc00000, value: 0x02c00000, op: ADDI_D, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // ADDI.W rd, rj, si12 + {mask: 0xffc00000, value: 0x02800000, op: ADDI_W, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // ADDU16I.D rd, rj, si16 + {mask: 0xfc000000, value: 0x10000000, op: ADDU16I_D, args: instArgs{arg_rd, arg_rj, arg_si16_25_10}}, + // ADD.D rd, rj, rk + {mask: 0xffff8000, value: 0x00108000, op: ADD_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // ADD.W rd, rj, rk + {mask: 0xffff8000, value: 0x00100000, op: ADD_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // ALSL.D rd, rj, rk, sa2 + {mask: 0xfffe0000, value: 0x002c0000, op: ALSL_D, args: instArgs{arg_rd, arg_rj, arg_rk, arg_sa2_16_15}}, + // ALSL.W rd, rj, rk, sa2 + {mask: 0xfffe0000, value: 0x00040000, op: ALSL_W, args: instArgs{arg_rd, arg_rj, arg_rk, arg_sa2_16_15}}, + // ALSL.WU rd, rj, rk, sa2 + {mask: 0xfffe0000, value: 0x00060000, op: ALSL_WU, args: instArgs{arg_rd, arg_rj, arg_rk, arg_sa2_16_15}}, + // AMADD.D rd, rk, rj + {mask: 0xffff8000, value: 0x38618000, op: AMADD_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMADD_DB.D rd, rk, rj + {mask: 0xffff8000, value: 0x386a8000, op: AMADD_DB_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMADD_DB.W rd, rk, rj + {mask: 0xffff8000, value: 0x386a0000, op: AMADD_DB_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMADD.W rd, rk, rj + {mask: 0xffff8000, value: 0x38610000, op: AMADD_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMAND.D rd, rk, rj + {mask: 0xffff8000, value: 0x38628000, op: AMAND_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMAND_DB.D rd, rk, rj + {mask: 0xffff8000, value: 0x386b8000, op: AMAND_DB_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMAND_DB.W rd, rk, rj + {mask: 0xffff8000, value: 0x386b0000, op: AMAND_DB_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMAND.W rd, rk, rj + {mask: 0xffff8000, value: 0x38620000, op: AMAND_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMAX.D rd, rk, rj + {mask: 0xffff8000, value: 0x38658000, op: AMMAX_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMAX_DB.D rd, rk, rj + {mask: 0xffff8000, value: 0x386e8000, op: AMMAX_DB_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMAX_DB.DU rd, rk, rj + {mask: 0xffff8000, value: 0x38708000, op: AMMAX_DB_DU, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMAX_DB.W rd, rk, rj + {mask: 0xffff8000, value: 0x386e0000, op: AMMAX_DB_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMAX_DB.WU rd, rk, rj + {mask: 0xffff8000, value: 0x38700000, op: AMMAX_DB_WU, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMAX.DU rd, rk, rj + {mask: 0xffff8000, value: 0x38678000, op: AMMAX_DU, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMAX.W rd, rk, rj + {mask: 0xffff8000, value: 0x38650000, op: AMMAX_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMAX.WU rd, rk, rj + {mask: 0xffff8000, value: 0x38670000, op: AMMAX_WU, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMIN.D rd, rk, rj + {mask: 0xffff8000, value: 0x38668000, op: AMMIN_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMIN_DB.D rd, rk, rj + {mask: 0xffff8000, value: 0x386f8000, op: AMMIN_DB_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMIN_DB.DU rd, rk, rj + {mask: 0xffff8000, value: 0x38718000, op: AMMIN_DB_DU, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMIN_DB.W rd, rk, rj + {mask: 0xffff8000, value: 0x386f0000, op: AMMIN_DB_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMIN_DB.WU rd, rk, rj + {mask: 0xffff8000, value: 0x38710000, op: AMMIN_DB_WU, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMIN.DU rd, rk, rj + {mask: 0xffff8000, value: 0x38688000, op: AMMIN_DU, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMIN.W rd, rk, rj + {mask: 0xffff8000, value: 0x38660000, op: AMMIN_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMMIN.WU rd, rk, rj + {mask: 0xffff8000, value: 0x38680000, op: AMMIN_WU, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMOR.D rd, rk, rj + {mask: 0xffff8000, value: 0x38638000, op: AMOR_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMOR_DB.D rd, rk, rj + {mask: 0xffff8000, value: 0x386c8000, op: AMOR_DB_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMOR_DB.W rd, rk, rj + {mask: 0xffff8000, value: 0x386c0000, op: AMOR_DB_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMOR.W rd, rk, rj + {mask: 0xffff8000, value: 0x38630000, op: AMOR_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMSWAP.D rd, rk, rj + {mask: 0xffff8000, value: 0x38608000, op: AMSWAP_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMSWAP_DB.D rd, rk, rj + {mask: 0xffff8000, value: 0x38698000, op: AMSWAP_DB_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMSWAP_DB.W rd, rk, rj + {mask: 0xffff8000, value: 0x38690000, op: AMSWAP_DB_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMSWAP.W rd, rk, rj + {mask: 0xffff8000, value: 0x38600000, op: AMSWAP_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMXOR.D rd, rk, rj + {mask: 0xffff8000, value: 0x38648000, op: AMXOR_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMXOR_DB.D rd, rk, rj + {mask: 0xffff8000, value: 0x386d8000, op: AMXOR_DB_D, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMXOR_DB.W rd, rk, rj + {mask: 0xffff8000, value: 0x386d0000, op: AMXOR_DB_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AMXOR.W rd, rk, rj + {mask: 0xffff8000, value: 0x38640000, op: AMXOR_W, args: instArgs{arg_rd, arg_rk, arg_rj}}, + // AND rd, rj, rk + {mask: 0xffff8000, value: 0x00148000, op: AND, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // ANDI rd, rj, ui12 + {mask: 0xffc00000, value: 0x03400000, op: ANDI, args: instArgs{arg_rd, arg_rj, arg_ui12_21_10}}, + // ANDN rd, rj, rk + {mask: 0xffff8000, value: 0x00168000, op: ANDN, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // ASRTGT.D rj, rk + {mask: 0xffff801f, value: 0x00018000, op: ASRTGT_D, args: instArgs{arg_rj, arg_rk}}, + // ASRTLE.D rj, rk + {mask: 0xffff801f, value: 0x00010000, op: ASRTLE_D, args: instArgs{arg_rj, arg_rk}}, + // B offs + {mask: 0xfc000000, value: 0x50000000, op: B, args: instArgs{arg_offset_25_0}}, + // BCEQZ cj, offs + {mask: 0xfc000300, value: 0x48000000, op: BCEQZ, args: instArgs{arg_cj, arg_offset_20_0}}, + // BCNEZ cj, offs + {mask: 0xfc000300, value: 0x48000100, op: BCNEZ, args: instArgs{arg_cj, arg_offset_20_0}}, + // BEQ rj, rd, offs + {mask: 0xfc000000, value: 0x58000000, op: BEQ, args: instArgs{arg_rj, arg_rd, arg_offset_15_0}}, + // BEQZ rj, offs + {mask: 0xfc000000, value: 0x40000000, op: BEQZ, args: instArgs{arg_rj, arg_offset_20_0}}, + // BGE rj, rd, offs + {mask: 0xfc000000, value: 0x64000000, op: BGE, args: instArgs{arg_rj, arg_rd, arg_offset_15_0}}, + // BGEU rj, rd, offs + {mask: 0xfc000000, value: 0x6c000000, op: BGEU, args: instArgs{arg_rj, arg_rd, arg_offset_15_0}}, + // BITREV.4B rd, rj + {mask: 0xfffffc00, value: 0x00004800, op: BITREV_4B, args: instArgs{arg_rd, arg_rj}}, + // BITREV.8B rd, rj + {mask: 0xfffffc00, value: 0x00004c00, op: BITREV_8B, args: instArgs{arg_rd, arg_rj}}, + // BITREV.D rd, rj + {mask: 0xfffffc00, value: 0x00005400, op: BITREV_D, args: instArgs{arg_rd, arg_rj}}, + // BITREV.W rd, rj + {mask: 0xfffffc00, value: 0x00005000, op: BITREV_W, args: instArgs{arg_rd, arg_rj}}, + // BL offs + {mask: 0xfc000000, value: 0x54000000, op: BL, args: instArgs{arg_offset_25_0}}, + // BLT rj, rd, offs + {mask: 0xfc000000, value: 0x60000000, op: BLT, args: instArgs{arg_rj, arg_rd, arg_offset_15_0}}, + // BLTU rj, rd, offs + {mask: 0xfc000000, value: 0x68000000, op: BLTU, args: instArgs{arg_rj, arg_rd, arg_offset_15_0}}, + // BNE rj, rd, offs + {mask: 0xfc000000, value: 0x5c000000, op: BNE, args: instArgs{arg_rj, arg_rd, arg_offset_15_0}}, + // BNEZ rj, offs + {mask: 0xfc000000, value: 0x44000000, op: BNEZ, args: instArgs{arg_rj, arg_offset_20_0}}, + // BREAK code + {mask: 0xffff8000, value: 0x002a0000, op: BREAK, args: instArgs{arg_code_14_0}}, + // BSTRINS.D rd, rj, msbd, lsbd + {mask: 0xffc00000, value: 0x00800000, op: BSTRINS_D, args: instArgs{arg_rd, arg_rj, arg_msbd, arg_lsbd}}, + // BSTRINS.W rd, rj, msbw, lsbw + {mask: 0xffe08000, value: 0x00600000, op: BSTRINS_W, args: instArgs{arg_rd, arg_rj, arg_msbw, arg_lsbw}}, + // BSTRPICK.D rd, rj, msbd, lsbd + {mask: 0xffc00000, value: 0x00c00000, op: BSTRPICK_D, args: instArgs{arg_rd, arg_rj, arg_msbd, arg_lsbd}}, + // BSTRPICK.W rd, rj, msbw, lsbw + {mask: 0xffe08000, value: 0x00608000, op: BSTRPICK_W, args: instArgs{arg_rd, arg_rj, arg_msbw, arg_lsbw}}, + // BYTEPICK.D rd, rj, rk, sa3 + {mask: 0xfffc0000, value: 0x000c0000, op: BYTEPICK_D, args: instArgs{arg_rd, arg_rj, arg_rk, arg_sa3_17_15}}, + // BYTEPICK.W rd, rj, rk, sa2 + {mask: 0xfffe0000, value: 0x00080000, op: BYTEPICK_W, args: instArgs{arg_rd, arg_rj, arg_rk, arg_sa2_16_15}}, + // CACOP code, rj, si12 + {mask: 0xffc00000, value: 0x06000000, op: CACOP, args: instArgs{arg_code_4_0, arg_rj, arg_si12_21_10}}, + // CLO.D rd, rj + {mask: 0xfffffc00, value: 0x00002000, op: CLO_D, args: instArgs{arg_rd, arg_rj}}, + // CLO.W rd, rj + {mask: 0xfffffc00, value: 0x00001000, op: CLO_W, args: instArgs{arg_rd, arg_rj}}, + // CLZ.D rd, rj + {mask: 0xfffffc00, value: 0x00002400, op: CLZ_D, args: instArgs{arg_rd, arg_rj}}, + // CLZ.W rd, rj + {mask: 0xfffffc00, value: 0x00001400, op: CLZ_W, args: instArgs{arg_rd, arg_rj}}, + // CPUCFG rd, rj + {mask: 0xfffffc00, value: 0x00006c00, op: CPUCFG, args: instArgs{arg_rd, arg_rj}}, + // CRCC.W.B.W rd, rj, rk + {mask: 0xffff8000, value: 0x00260000, op: CRCC_W_B_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // CRCC.W.D.W rd, rj, rk + {mask: 0xffff8000, value: 0x00278000, op: CRCC_W_D_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // CRCC.W.H.W rd, rj, rk + {mask: 0xffff8000, value: 0x00268000, op: CRCC_W_H_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // CRCC.W.W.W rd, rj, rk + {mask: 0xffff8000, value: 0x00270000, op: CRCC_W_W_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // CRC.W.B.W rd, rj, rk + {mask: 0xffff8000, value: 0x00240000, op: CRC_W_B_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // CRC.W.D.W rd, rj, rk + {mask: 0xffff8000, value: 0x00258000, op: CRC_W_D_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // CRC.W.H.W rd, rj, rk + {mask: 0xffff8000, value: 0x00248000, op: CRC_W_H_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // CRC.W.W.W rd, rj, rk + {mask: 0xffff8000, value: 0x00250000, op: CRC_W_W_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // CSRRD rd, csr + {mask: 0xff0003e0, value: 0x04000000, op: CSRRD, args: instArgs{arg_rd, arg_csr_23_10}}, + // CSRWR rd, csr + {mask: 0xff0003e0, value: 0x04000020, op: CSRWR, args: instArgs{arg_rd, arg_csr_23_10}}, + // CSRXCHG rd, rj, csr + {mask: 0xff000000, value: 0x04000000, op: CSRXCHG, args: instArgs{arg_rd, arg_rj, arg_csr_23_10}}, + // CTO.D rd, rj + {mask: 0xfffffc00, value: 0x00002800, op: CTO_D, args: instArgs{arg_rd, arg_rj}}, + // CTO.W rd, rj + {mask: 0xfffffc00, value: 0x00001800, op: CTO_W, args: instArgs{arg_rd, arg_rj}}, + // CTZ.D rd, rj + {mask: 0xfffffc00, value: 0x00002c00, op: CTZ_D, args: instArgs{arg_rd, arg_rj}}, + // CTZ.W rd, rj + {mask: 0xfffffc00, value: 0x00001c00, op: CTZ_W, args: instArgs{arg_rd, arg_rj}}, + // DBAR hint + {mask: 0xffff8000, value: 0x38720000, op: DBAR, args: instArgs{arg_hint_14_0}}, + // DBCL code + {mask: 0xffff8000, value: 0x002a8000, op: DBCL, args: instArgs{arg_code_14_0}}, + // DIV.D rd, rj, rk + {mask: 0xffff8000, value: 0x00220000, op: DIV_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // DIV.DU rd, rj, rk + {mask: 0xffff8000, value: 0x00230000, op: DIV_DU, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // DIV.W rd, rj, rk + {mask: 0xffff8000, value: 0x00200000, op: DIV_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // DIV.WU rd, rj, rk + {mask: 0xffff8000, value: 0x00210000, op: DIV_WU, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // ERTN + {mask: 0xffffffff, value: 0x06483800, op: ERTN, args: instArgs{}}, + // EXT.W.B rd, rj + {mask: 0xfffffc00, value: 0x00005c00, op: EXT_W_B, args: instArgs{arg_rd, arg_rj}}, + // EXT.W.H rd, rj + {mask: 0xfffffc00, value: 0x00005800, op: EXT_W_H, args: instArgs{arg_rd, arg_rj}}, + // FABS.D fd, fj + {mask: 0xfffffc00, value: 0x01140800, op: FABS_D, args: instArgs{arg_fd, arg_fj}}, + // FABS.S fd, fj + {mask: 0xfffffc00, value: 0x01140400, op: FABS_S, args: instArgs{arg_fd, arg_fj}}, + // FADD.D fd, fj, fk + {mask: 0xffff8000, value: 0x01010000, op: FADD_D, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FADD.S fd, fj, fk + {mask: 0xffff8000, value: 0x01008000, op: FADD_S, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FCLASS.D fd, fj + {mask: 0xfffffc00, value: 0x01143800, op: FCLASS_D, args: instArgs{arg_fd, arg_fj}}, + // FCLASS.S fd, fj + {mask: 0xfffffc00, value: 0x01143400, op: FCLASS_S, args: instArgs{arg_fd, arg_fj}}, + // FCMP.CAF.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c200000, op: FCMP_CAF_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CAF.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c100000, op: FCMP_CAF_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CEQ.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c220000, op: FCMP_CEQ_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CEQ.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c120000, op: FCMP_CEQ_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CLE.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c230000, op: FCMP_CLE_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CLE.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c130000, op: FCMP_CLE_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CLT.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c210000, op: FCMP_CLT_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CLT.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c110000, op: FCMP_CLT_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CNE.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c280000, op: FCMP_CNE_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CNE.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c180000, op: FCMP_CNE_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.COR.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c2a0000, op: FCMP_COR_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.COR.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c1a0000, op: FCMP_COR_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CUEQ.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c260000, op: FCMP_CUEQ_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CUEQ.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c160000, op: FCMP_CUEQ_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CULE.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c270000, op: FCMP_CULE_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CULE.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c170000, op: FCMP_CULE_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CULT.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c250000, op: FCMP_CULT_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CULT.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c150000, op: FCMP_CULT_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CUNE.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c2c0000, op: FCMP_CUNE_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CUNE.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c1c0000, op: FCMP_CUNE_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CUN.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c240000, op: FCMP_CUN_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.CUN.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c140000, op: FCMP_CUN_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SAF.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c208000, op: FCMP_SAF_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SAF.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c108000, op: FCMP_SAF_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SEQ.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c228000, op: FCMP_SEQ_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SEQ.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c128000, op: FCMP_SEQ_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SLE.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c238000, op: FCMP_SLE_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SLE.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c138000, op: FCMP_SLE_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SLT.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c218000, op: FCMP_SLT_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SLT.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c118000, op: FCMP_SLT_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SNE.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c288000, op: FCMP_SNE_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SNE.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c188000, op: FCMP_SNE_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SOR.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c2a8000, op: FCMP_SOR_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SOR.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c1a8000, op: FCMP_SOR_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SUEQ.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c268000, op: FCMP_SUEQ_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SUEQ.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c168000, op: FCMP_SUEQ_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SULE.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c278000, op: FCMP_SULE_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SULE.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c178000, op: FCMP_SULE_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SULT.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c258000, op: FCMP_SULT_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SULT.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c158000, op: FCMP_SULT_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SUNE.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c2c8000, op: FCMP_SUNE_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SUNE.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c1c8000, op: FCMP_SUNE_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SUN.D cd, fj, fk + {mask: 0xffff8018, value: 0x0c248000, op: FCMP_SUN_D, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCMP.SUN.S cd, fj, fk + {mask: 0xffff8018, value: 0x0c148000, op: FCMP_SUN_S, args: instArgs{arg_cd, arg_fj, arg_fk}}, + // FCOPYSIGN.D fd, fj, fk + {mask: 0xffff8000, value: 0x01130000, op: FCOPYSIGN_D, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FCOPYSIGN.S fd, fj, fk + {mask: 0xffff8000, value: 0x01128000, op: FCOPYSIGN_S, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FCVT.D.S fd, fj + {mask: 0xfffffc00, value: 0x01192400, op: FCVT_D_S, args: instArgs{arg_fd, arg_fj}}, + // FCVT.S.D fd, fj + {mask: 0xfffffc00, value: 0x01191800, op: FCVT_S_D, args: instArgs{arg_fd, arg_fj}}, + // FDIV.D fd, fj, fk + {mask: 0xffff8000, value: 0x01070000, op: FDIV_D, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FDIV.S fd, fj, fk + {mask: 0xffff8000, value: 0x01068000, op: FDIV_S, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FFINT.D.L fd, fj + {mask: 0xfffffc00, value: 0x011d2800, op: FFINT_D_L, args: instArgs{arg_fd, arg_fj}}, + // FFINT.D.W fd, fj + {mask: 0xfffffc00, value: 0x011d2000, op: FFINT_D_W, args: instArgs{arg_fd, arg_fj}}, + // FFINT.S.L fd, fj + {mask: 0xfffffc00, value: 0x011d1800, op: FFINT_S_L, args: instArgs{arg_fd, arg_fj}}, + // FFINT.S.W fd, fj + {mask: 0xfffffc00, value: 0x011d1000, op: FFINT_S_W, args: instArgs{arg_fd, arg_fj}}, + // FLDGT.D fd, rj, rk + {mask: 0xffff8000, value: 0x38748000, op: FLDGT_D, args: instArgs{arg_fd, arg_rj, arg_rk}}, + // FLDGT.S fd, rj, rk + {mask: 0xffff8000, value: 0x38740000, op: FLDGT_S, args: instArgs{arg_fd, arg_rj, arg_rk}}, + // FLDLE.D fd, rj, rk + {mask: 0xffff8000, value: 0x38758000, op: FLDLE_D, args: instArgs{arg_fd, arg_rj, arg_rk}}, + // FLDLE.S fd, rj, rk + {mask: 0xffff8000, value: 0x38750000, op: FLDLE_S, args: instArgs{arg_fd, arg_rj, arg_rk}}, + // FLDX.D fd, rj, rk + {mask: 0xffff8000, value: 0x38340000, op: FLDX_D, args: instArgs{arg_fd, arg_rj, arg_rk}}, + // FLDX.S fd, rj, rk + {mask: 0xffff8000, value: 0x38300000, op: FLDX_S, args: instArgs{arg_fd, arg_rj, arg_rk}}, + // FLD.D fd, rj, si12 + {mask: 0xffc00000, value: 0x2b800000, op: FLD_D, args: instArgs{arg_fd, arg_rj, arg_si12_21_10}}, + // FLD.S fd, rj, si12 + {mask: 0xffc00000, value: 0x2b000000, op: FLD_S, args: instArgs{arg_fd, arg_rj, arg_si12_21_10}}, + // FLOGB.D fd, fj + {mask: 0xfffffc00, value: 0x01142800, op: FLOGB_D, args: instArgs{arg_fd, arg_fj}}, + // FLOGB.S fd, fj + {mask: 0xfffffc00, value: 0x01142400, op: FLOGB_S, args: instArgs{arg_fd, arg_fj}}, + // FMADD.D fd, fj, fk, fa + {mask: 0xfff00000, value: 0x08200000, op: FMADD_D, args: instArgs{arg_fd, arg_fj, arg_fk, arg_fa}}, + // FMADD.S fd, fj, fk, fa + {mask: 0xfff00000, value: 0x08100000, op: FMADD_S, args: instArgs{arg_fd, arg_fj, arg_fk, arg_fa}}, + // FMAXA.D fd, fj, fk + {mask: 0xffff8000, value: 0x010d0000, op: FMAXA_D, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FMAXA.S fd, fj, fk + {mask: 0xffff8000, value: 0x010c8000, op: FMAXA_S, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FMAX.D fd, fj, fk + {mask: 0xffff8000, value: 0x01090000, op: FMAX_D, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FMAX.S fd, fj, fk + {mask: 0xffff8000, value: 0x01088000, op: FMAX_S, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FMINA.D fd, fj, fk + {mask: 0xffff8000, value: 0x010f0000, op: FMINA_D, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FMINA.S fd, fj, fk + {mask: 0xffff8000, value: 0x010e8000, op: FMINA_S, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FMIN.D fd, fj, fk + {mask: 0xffff8000, value: 0x010b0000, op: FMIN_D, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FMIN.S fd, fj, fk + {mask: 0xffff8000, value: 0x010a8000, op: FMIN_S, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FMOV.D fd, fj + {mask: 0xfffffc00, value: 0x01149800, op: FMOV_D, args: instArgs{arg_fd, arg_fj}}, + // FMOV.S fd, fj + {mask: 0xfffffc00, value: 0x01149400, op: FMOV_S, args: instArgs{arg_fd, arg_fj}}, + // FMSUB.D fd, fj, fk, fa + {mask: 0xfff00000, value: 0x08600000, op: FMSUB_D, args: instArgs{arg_fd, arg_fj, arg_fk, arg_fa}}, + // FMSUB.S fd, fj, fk, fa + {mask: 0xfff00000, value: 0x08500000, op: FMSUB_S, args: instArgs{arg_fd, arg_fj, arg_fk, arg_fa}}, + // FMUL.D fd, fj, fk + {mask: 0xffff8000, value: 0x01050000, op: FMUL_D, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FMUL.S fd, fj, fk + {mask: 0xffff8000, value: 0x01048000, op: FMUL_S, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FNEG.D fd, fj + {mask: 0xfffffc00, value: 0x01141800, op: FNEG_D, args: instArgs{arg_fd, arg_fj}}, + // FNEG.S fd, fj + {mask: 0xfffffc00, value: 0x01141400, op: FNEG_S, args: instArgs{arg_fd, arg_fj}}, + // FNMADD.D fd, fj, fk, fa + {mask: 0xfff00000, value: 0x08a00000, op: FNMADD_D, args: instArgs{arg_fd, arg_fj, arg_fk, arg_fa}}, + // FNMADD.S fd, fj, fk, fa + {mask: 0xfff00000, value: 0x08900000, op: FNMADD_S, args: instArgs{arg_fd, arg_fj, arg_fk, arg_fa}}, + // FNMSUB.D fd, fj, fk, fa + {mask: 0xfff00000, value: 0x08e00000, op: FNMSUB_D, args: instArgs{arg_fd, arg_fj, arg_fk, arg_fa}}, + // FNMSUB.S fd, fj, fk, fa + {mask: 0xfff00000, value: 0x08d00000, op: FNMSUB_S, args: instArgs{arg_fd, arg_fj, arg_fk, arg_fa}}, + // FRECIP.D fd, fj + {mask: 0xfffffc00, value: 0x01145800, op: FRECIP_D, args: instArgs{arg_fd, arg_fj}}, + // FRECIP.S fd, fj + {mask: 0xfffffc00, value: 0x01145400, op: FRECIP_S, args: instArgs{arg_fd, arg_fj}}, + // FRINT.D fd, fj + {mask: 0xfffffc00, value: 0x011e4800, op: FRINT_D, args: instArgs{arg_fd, arg_fj}}, + // FRINT.S fd, fj + {mask: 0xfffffc00, value: 0x011e4400, op: FRINT_S, args: instArgs{arg_fd, arg_fj}}, + // FRSQRT.D fd, fj + {mask: 0xfffffc00, value: 0x01146800, op: FRSQRT_D, args: instArgs{arg_fd, arg_fj}}, + // FRSQRT.S fd, fj + {mask: 0xfffffc00, value: 0x01146400, op: FRSQRT_S, args: instArgs{arg_fd, arg_fj}}, + // FSCALEB.D fd, fj, fk + {mask: 0xffff8000, value: 0x01110000, op: FSCALEB_D, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FSCALEB.S fd, fj, fk + {mask: 0xffff8000, value: 0x01108000, op: FSCALEB_S, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FSEL fd, fj, fk, ca + {mask: 0xfffc0000, value: 0x0d000000, op: FSEL, args: instArgs{arg_fd, arg_fj, arg_fk, arg_ca}}, + // FSQRT.D fd, fj + {mask: 0xfffffc00, value: 0x01144800, op: FSQRT_D, args: instArgs{arg_fd, arg_fj}}, + // FSQRT.S fd, fj + {mask: 0xfffffc00, value: 0x01144400, op: FSQRT_S, args: instArgs{arg_fd, arg_fj}}, + // FSTGT.D fd, rj, rk + {mask: 0xffff8000, value: 0x38768000, op: FSTGT_D, args: instArgs{arg_fd, arg_rj, arg_rk}}, + // FSTGT.S fd, rj, rk + {mask: 0xffff8000, value: 0x38760000, op: FSTGT_S, args: instArgs{arg_fd, arg_rj, arg_rk}}, + // FSTLE.D fd, rj, rk + {mask: 0xffff8000, value: 0x38778000, op: FSTLE_D, args: instArgs{arg_fd, arg_rj, arg_rk}}, + // FSTLE.S fd, rj, rk + {mask: 0xffff8000, value: 0x38770000, op: FSTLE_S, args: instArgs{arg_fd, arg_rj, arg_rk}}, + // FSTX.D fd, rj, rk + {mask: 0xffff8000, value: 0x383c0000, op: FSTX_D, args: instArgs{arg_fd, arg_rj, arg_rk}}, + // FSTX.S fd, rj, rk + {mask: 0xffff8000, value: 0x38380000, op: FSTX_S, args: instArgs{arg_fd, arg_rj, arg_rk}}, + // FST.D fd, rj, si12 + {mask: 0xffc00000, value: 0x2bc00000, op: FST_D, args: instArgs{arg_fd, arg_rj, arg_si12_21_10}}, + // FST.S fd, rj, si12 + {mask: 0xffc00000, value: 0x2b400000, op: FST_S, args: instArgs{arg_fd, arg_rj, arg_si12_21_10}}, + // FSUB.D fd, fj, fk + {mask: 0xffff8000, value: 0x01030000, op: FSUB_D, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FSUB.S fd, fj, fk + {mask: 0xffff8000, value: 0x01028000, op: FSUB_S, args: instArgs{arg_fd, arg_fj, arg_fk}}, + // FTINTRM.L.D fd, fj + {mask: 0xfffffc00, value: 0x011a2800, op: FTINTRM_L_D, args: instArgs{arg_fd, arg_fj}}, + // FTINTRM.L.S fd, fj + {mask: 0xfffffc00, value: 0x011a2400, op: FTINTRM_L_S, args: instArgs{arg_fd, arg_fj}}, + // FTINTRM.W.D fd, fj + {mask: 0xfffffc00, value: 0x011a0800, op: FTINTRM_W_D, args: instArgs{arg_fd, arg_fj}}, + // FTINTRM.W.S fd, fj + {mask: 0xfffffc00, value: 0x011a0400, op: FTINTRM_W_S, args: instArgs{arg_fd, arg_fj}}, + // FTINTRNE.L.D fd, fj + {mask: 0xfffffc00, value: 0x011ae800, op: FTINTRNE_L_D, args: instArgs{arg_fd, arg_fj}}, + // FTINTRNE.L.S fd, fj + {mask: 0xfffffc00, value: 0x011ae400, op: FTINTRNE_L_S, args: instArgs{arg_fd, arg_fj}}, + // FTINTRNE.W.D fd, fj + {mask: 0xfffffc00, value: 0x011ac800, op: FTINTRNE_W_D, args: instArgs{arg_fd, arg_fj}}, + // FTINTRNE.W.S fd, fj + {mask: 0xfffffc00, value: 0x011ac400, op: FTINTRNE_W_S, args: instArgs{arg_fd, arg_fj}}, + // FTINTRP.L.D fd, fj + {mask: 0xfffffc00, value: 0x011a6800, op: FTINTRP_L_D, args: instArgs{arg_fd, arg_fj}}, + // FTINTRP.L.S fd, fj + {mask: 0xfffffc00, value: 0x011a6400, op: FTINTRP_L_S, args: instArgs{arg_fd, arg_fj}}, + // FTINTRP.W.D fd, fj + {mask: 0xfffffc00, value: 0x011a4800, op: FTINTRP_W_D, args: instArgs{arg_fd, arg_fj}}, + // FTINTRP.W.S fd, fj + {mask: 0xfffffc00, value: 0x011a4400, op: FTINTRP_W_S, args: instArgs{arg_fd, arg_fj}}, + // FTINTRZ.L.D fd, fj + {mask: 0xfffffc00, value: 0x011aa800, op: FTINTRZ_L_D, args: instArgs{arg_fd, arg_fj}}, + // FTINTRZ.L.S fd, fj + {mask: 0xfffffc00, value: 0x011aa400, op: FTINTRZ_L_S, args: instArgs{arg_fd, arg_fj}}, + // FTINTRZ.W.D fd, fj + {mask: 0xfffffc00, value: 0x011a8800, op: FTINTRZ_W_D, args: instArgs{arg_fd, arg_fj}}, + // FTINTRZ.W.S fd, fj + {mask: 0xfffffc00, value: 0x011a8400, op: FTINTRZ_W_S, args: instArgs{arg_fd, arg_fj}}, + // FTINT.L.D fd, fj + {mask: 0xfffffc00, value: 0x011b2800, op: FTINT_L_D, args: instArgs{arg_fd, arg_fj}}, + // FTINT.L.S fd, fj + {mask: 0xfffffc00, value: 0x011b2400, op: FTINT_L_S, args: instArgs{arg_fd, arg_fj}}, + // FTINT.W.D fd, fj + {mask: 0xfffffc00, value: 0x011b0800, op: FTINT_W_D, args: instArgs{arg_fd, arg_fj}}, + // FTINT.W.S fd, fj + {mask: 0xfffffc00, value: 0x011b0400, op: FTINT_W_S, args: instArgs{arg_fd, arg_fj}}, + // IBAR hint + {mask: 0xffff8000, value: 0x38728000, op: IBAR, args: instArgs{arg_hint_14_0}}, + // IDLE level + {mask: 0xffff8000, value: 0x06488000, op: IDLE, args: instArgs{arg_level_14_0}}, + // INVTLB op, rj, rk + {mask: 0xffff8000, value: 0x06498000, op: INVTLB, args: instArgs{arg_op_4_0, arg_rj, arg_rk}}, + // IOCSRRD.B rd, rj + {mask: 0xfffffc00, value: 0x06480000, op: IOCSRRD_B, args: instArgs{arg_rd, arg_rj}}, + // IOCSRRD.D rd, rj + {mask: 0xfffffc00, value: 0x06480c00, op: IOCSRRD_D, args: instArgs{arg_rd, arg_rj}}, + // IOCSRRD.H rd, rj + {mask: 0xfffffc00, value: 0x06480400, op: IOCSRRD_H, args: instArgs{arg_rd, arg_rj}}, + // IOCSRRD.W rd, rj + {mask: 0xfffffc00, value: 0x06480800, op: IOCSRRD_W, args: instArgs{arg_rd, arg_rj}}, + // IOCSRWR.B rd, rj + {mask: 0xfffffc00, value: 0x06481000, op: IOCSRWR_B, args: instArgs{arg_rd, arg_rj}}, + // IOCSRWR.D rd, rj + {mask: 0xfffffc00, value: 0x06481c00, op: IOCSRWR_D, args: instArgs{arg_rd, arg_rj}}, + // IOCSRWR.H rd, rj + {mask: 0xfffffc00, value: 0x06481400, op: IOCSRWR_H, args: instArgs{arg_rd, arg_rj}}, + // IOCSRWR.W rd, rj + {mask: 0xfffffc00, value: 0x06481800, op: IOCSRWR_W, args: instArgs{arg_rd, arg_rj}}, + // JIRL rd, rj, offs + {mask: 0xfc000000, value: 0x4c000000, op: JIRL, args: instArgs{arg_rd, arg_rj, arg_offset_15_0}}, + // LDDIR rd, rj, level + {mask: 0xfffc0000, value: 0x06400000, op: LDDIR, args: instArgs{arg_rd, arg_rj, arg_level_17_10}}, + // LDGT.B rd, rj, rk + {mask: 0xffff8000, value: 0x38780000, op: LDGT_B, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDGT.D rd, rj, rk + {mask: 0xffff8000, value: 0x38798000, op: LDGT_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDGT.H rd, rj, rk + {mask: 0xffff8000, value: 0x38788000, op: LDGT_H, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDGT.W rd, rj, rk + {mask: 0xffff8000, value: 0x38790000, op: LDGT_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDLE.B rd, rj, rk + {mask: 0xffff8000, value: 0x387a0000, op: LDLE_B, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDLE.D rd, rj, rk + {mask: 0xffff8000, value: 0x387b8000, op: LDLE_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDLE.H rd, rj, rk + {mask: 0xffff8000, value: 0x387a8000, op: LDLE_H, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDLE.W rd, rj, rk + {mask: 0xffff8000, value: 0x387b0000, op: LDLE_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDPTE rj, seq + {mask: 0xfffc001f, value: 0x06440000, op: LDPTE, args: instArgs{arg_rj, arg_seq_17_10}}, + // LDPTR.D rd, rj, si14 + {mask: 0xff000000, value: 0x26000000, op: LDPTR_D, args: instArgs{arg_rd, arg_rj, arg_si14_23_10}}, + // LDPTR.W rd, rj, si14 + {mask: 0xff000000, value: 0x24000000, op: LDPTR_W, args: instArgs{arg_rd, arg_rj, arg_si14_23_10}}, + // LDX.B rd, rj, rk + {mask: 0xffff8000, value: 0x38000000, op: LDX_B, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDX.BU rd, rj, rk + {mask: 0xffff8000, value: 0x38200000, op: LDX_BU, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDX.D rd, rj, rk + {mask: 0xffff8000, value: 0x380c0000, op: LDX_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDX.H rd, rj, rk + {mask: 0xffff8000, value: 0x38040000, op: LDX_H, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDX.HU rd, rj, rk + {mask: 0xffff8000, value: 0x38240000, op: LDX_HU, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDX.W rd, rj, rk + {mask: 0xffff8000, value: 0x38080000, op: LDX_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LDX.WU rd, rj, rk + {mask: 0xffff8000, value: 0x38280000, op: LDX_WU, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // LD.B rd, rj, si12 + {mask: 0xffc00000, value: 0x28000000, op: LD_B, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // LD.BU rd, rj, si12 + {mask: 0xffc00000, value: 0x2a000000, op: LD_BU, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // LD.D rd, rj, si12 + {mask: 0xffc00000, value: 0x28c00000, op: LD_D, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // LD.H rd, rj, si12 + {mask: 0xffc00000, value: 0x28400000, op: LD_H, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // LD.HU rd, rj, si12 + {mask: 0xffc00000, value: 0x2a400000, op: LD_HU, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // LD.W rd, rj, si12 + {mask: 0xffc00000, value: 0x28800000, op: LD_W, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // LD.WU rd, rj, si12 + {mask: 0xffc00000, value: 0x2a800000, op: LD_WU, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // LL.D rd, rj, si14 + {mask: 0xff000000, value: 0x22000000, op: LL_D, args: instArgs{arg_rd, arg_rj, arg_si14_23_10}}, + // LL.W rd, rj, si14 + {mask: 0xff000000, value: 0x20000000, op: LL_W, args: instArgs{arg_rd, arg_rj, arg_si14_23_10}}, + // LU12I.W rd, si20 + {mask: 0xfe000000, value: 0x14000000, op: LU12I_W, args: instArgs{arg_rd, arg_si20_24_5}}, + // LU32I.D rd, si20 + {mask: 0xfe000000, value: 0x16000000, op: LU32I_D, args: instArgs{arg_rd, arg_si20_24_5}}, + // LU52I.D rd, rj, si12 + {mask: 0xffc00000, value: 0x03000000, op: LU52I_D, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // MASKEQZ rd, rj, rk + {mask: 0xffff8000, value: 0x00130000, op: MASKEQZ, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // MASKNEZ rd, rj, rk + {mask: 0xffff8000, value: 0x00138000, op: MASKNEZ, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // MOD.D rd, rj, rk + {mask: 0xffff8000, value: 0x00228000, op: MOD_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // MOD.DU rd, rj, rk + {mask: 0xffff8000, value: 0x00238000, op: MOD_DU, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // MOD.W rd, rj, rk + {mask: 0xffff8000, value: 0x00208000, op: MOD_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // MOD.WU rd, rj, rk + {mask: 0xffff8000, value: 0x00218000, op: MOD_WU, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // MOVCF2FR fd, cj + {mask: 0xffffff00, value: 0x0114d400, op: MOVCF2FR, args: instArgs{arg_fd, arg_cj}}, + // MOVCF2GR rd, cj + {mask: 0xffffff00, value: 0x0114dc00, op: MOVCF2GR, args: instArgs{arg_rd, arg_cj}}, + // MOVFCSR2GR rd, fcsr + {mask: 0xfffffc00, value: 0x0114c800, op: MOVFCSR2GR, args: instArgs{arg_rd, arg_fcsr_9_5}}, + // MOVFR2CF cd, fj + {mask: 0xfffffc18, value: 0x0114d000, op: MOVFR2CF, args: instArgs{arg_cd, arg_fj}}, + // MOVFR2GR.D rd, fj + {mask: 0xfffffc00, value: 0x0114b800, op: MOVFR2GR_D, args: instArgs{arg_rd, arg_fj}}, + // MOVFR2GR.S rd, fj + {mask: 0xfffffc00, value: 0x0114b400, op: MOVFR2GR_S, args: instArgs{arg_rd, arg_fj}}, + // MOVFRH2GR.S rd, fj + {mask: 0xfffffc00, value: 0x0114bc00, op: MOVFRH2GR_S, args: instArgs{arg_rd, arg_fj}}, + // MOVGR2CF cd, rj + {mask: 0xfffffc18, value: 0x0114d800, op: MOVGR2CF, args: instArgs{arg_cd, arg_rj}}, + // MOVGR2FCSR fcsr, rj + {mask: 0xfffffc00, value: 0x0114c000, op: MOVGR2FCSR, args: instArgs{arg_fcsr_4_0, arg_rj}}, + // MOVGR2FRH.W fd, rj + {mask: 0xfffffc00, value: 0x0114ac00, op: MOVGR2FRH_W, args: instArgs{arg_fd, arg_rj}}, + // MOVGR2FR.D fd, rj + {mask: 0xfffffc00, value: 0x0114a800, op: MOVGR2FR_D, args: instArgs{arg_fd, arg_rj}}, + // MOVGR2FR.W fd, rj + {mask: 0xfffffc00, value: 0x0114a400, op: MOVGR2FR_W, args: instArgs{arg_fd, arg_rj}}, + // MULH.D rd, rj, rk + {mask: 0xffff8000, value: 0x001e0000, op: MULH_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // MULH.DU rd, rj, rk + {mask: 0xffff8000, value: 0x001e8000, op: MULH_DU, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // MULH.W rd, rj, rk + {mask: 0xffff8000, value: 0x001c8000, op: MULH_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // MULH.WU rd, rj, rk + {mask: 0xffff8000, value: 0x001d0000, op: MULH_WU, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // MULW.D.W rd, rj, rk + {mask: 0xffff8000, value: 0x001f0000, op: MULW_D_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // MULW.D.WU rd, rj, rk + {mask: 0xffff8000, value: 0x001f8000, op: MULW_D_WU, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // MUL.D rd, rj, rk + {mask: 0xffff8000, value: 0x001d8000, op: MUL_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // MUL.W rd, rj, rk + {mask: 0xffff8000, value: 0x001c0000, op: MUL_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // NOR rd, rj, rk + {mask: 0xffff8000, value: 0x00140000, op: NOR, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // OR rd, rj, rk + {mask: 0xffff8000, value: 0x00150000, op: OR, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // ORI rd, rj, ui12 + {mask: 0xffc00000, value: 0x03800000, op: ORI, args: instArgs{arg_rd, arg_rj, arg_ui12_21_10}}, + // ORN rd, rj, rk + {mask: 0xffff8000, value: 0x00160000, op: ORN, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // PCADDI rd, si20 + {mask: 0xfe000000, value: 0x18000000, op: PCADDI, args: instArgs{arg_rd, arg_si20_24_5}}, + // PCADDU12I rd, si20 + {mask: 0xfe000000, value: 0x1c000000, op: PCADDU12I, args: instArgs{arg_rd, arg_si20_24_5}}, + // PCADDU18I rd, si20 + {mask: 0xfe000000, value: 0x1e000000, op: PCADDU18I, args: instArgs{arg_rd, arg_si20_24_5}}, + // PCALAU12I rd, si20 + {mask: 0xfe000000, value: 0x1a000000, op: PCALAU12I, args: instArgs{arg_rd, arg_si20_24_5}}, + // PRELD hint, rj, si12 + {mask: 0xffc00000, value: 0x2ac00000, op: PRELD, args: instArgs{arg_hint_4_0, arg_rj, arg_si12_21_10}}, + // PRELDX hint, rj, rk + {mask: 0xffff8000, value: 0x382c0000, op: PRELDX, args: instArgs{arg_hint_4_0, arg_rj, arg_rk}}, + // RDTIMEH.W rd, rj + {mask: 0xfffffc00, value: 0x00006400, op: RDTIMEH_W, args: instArgs{arg_rd, arg_rj}}, + // RDTIMEL.W rd, rj + {mask: 0xfffffc00, value: 0x00006000, op: RDTIMEL_W, args: instArgs{arg_rd, arg_rj}}, + // RDTIME.D rd, rj + {mask: 0xfffffc00, value: 0x00006800, op: RDTIME_D, args: instArgs{arg_rd, arg_rj}}, + // REVB.2H rd, rj + {mask: 0xfffffc00, value: 0x00003000, op: REVB_2H, args: instArgs{arg_rd, arg_rj}}, + // REVB.2W rd, rj + {mask: 0xfffffc00, value: 0x00003800, op: REVB_2W, args: instArgs{arg_rd, arg_rj}}, + // REVB.4H rd, rj + {mask: 0xfffffc00, value: 0x00003400, op: REVB_4H, args: instArgs{arg_rd, arg_rj}}, + // REVB.D rd, rj + {mask: 0xfffffc00, value: 0x00003c00, op: REVB_D, args: instArgs{arg_rd, arg_rj}}, + // REVH.2W rd, rj + {mask: 0xfffffc00, value: 0x00004000, op: REVH_2W, args: instArgs{arg_rd, arg_rj}}, + // REVH.D rd, rj + {mask: 0xfffffc00, value: 0x00004400, op: REVH_D, args: instArgs{arg_rd, arg_rj}}, + // ROTRI.D rd, rj, ui6 + {mask: 0xffff0000, value: 0x004d0000, op: ROTRI_D, args: instArgs{arg_rd, arg_rj, arg_ui6_15_10}}, + // ROTRI.W rd, rj, ui5 + {mask: 0xffff8000, value: 0x004c8000, op: ROTRI_W, args: instArgs{arg_rd, arg_rj, arg_ui5_14_10}}, + // ROTR.D rd, rj, rk + {mask: 0xffff8000, value: 0x001b8000, op: ROTR_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // ROTR.W rd, rj, rk + {mask: 0xffff8000, value: 0x001b0000, op: ROTR_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // SC.D rd, rj, si14 + {mask: 0xff000000, value: 0x23000000, op: SC_D, args: instArgs{arg_rd, arg_rj, arg_si14_23_10}}, + // SC.W rd, rj, si14 + {mask: 0xff000000, value: 0x21000000, op: SC_W, args: instArgs{arg_rd, arg_rj, arg_si14_23_10}}, + // SLLI.D rd, rj, ui6 + {mask: 0xffff0000, value: 0x00410000, op: SLLI_D, args: instArgs{arg_rd, arg_rj, arg_ui6_15_10}}, + // SLLI.W rd, rj, ui5 + {mask: 0xffff8000, value: 0x00408000, op: SLLI_W, args: instArgs{arg_rd, arg_rj, arg_ui5_14_10}}, + // SLL.D rd, rj, rk + {mask: 0xffff8000, value: 0x00188000, op: SLL_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // SLL.W rd, rj, rk + {mask: 0xffff8000, value: 0x00170000, op: SLL_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // SLT rd, rj, rk + {mask: 0xffff8000, value: 0x00120000, op: SLT, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // SLTI rd, rj, si12 + {mask: 0xffc00000, value: 0x02000000, op: SLTI, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // SLTU rd, rj, rk + {mask: 0xffff8000, value: 0x00128000, op: SLTU, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // SLTUI rd, rj, si12 + {mask: 0xffc00000, value: 0x02400000, op: SLTUI, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // SRAI.D rd, rj, ui6 + {mask: 0xffff0000, value: 0x00490000, op: SRAI_D, args: instArgs{arg_rd, arg_rj, arg_ui6_15_10}}, + // SRAI.W rd, rj, ui5 + {mask: 0xffff8000, value: 0x00488000, op: SRAI_W, args: instArgs{arg_rd, arg_rj, arg_ui5_14_10}}, + // SRA.D rd, rj, rk + {mask: 0xffff8000, value: 0x00198000, op: SRA_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // SRA.W rd, rj, rk + {mask: 0xffff8000, value: 0x00180000, op: SRA_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // SRLI.D rd, rj, ui6 + {mask: 0xffff0000, value: 0x00450000, op: SRLI_D, args: instArgs{arg_rd, arg_rj, arg_ui6_15_10}}, + // SRLI.W rd, rj, ui5 + {mask: 0xffff8000, value: 0x00448000, op: SRLI_W, args: instArgs{arg_rd, arg_rj, arg_ui5_14_10}}, + // SRL.D rd, rj, rk + {mask: 0xffff8000, value: 0x00190000, op: SRL_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // SRL.W rd, rj, rk + {mask: 0xffff8000, value: 0x00178000, op: SRL_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // STGT.B rd, rj, rk + {mask: 0xffff8000, value: 0x387c0000, op: STGT_B, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // STGT.D rd, rj, rk + {mask: 0xffff8000, value: 0x387d8000, op: STGT_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // STGT.H rd, rj, rk + {mask: 0xffff8000, value: 0x387c8000, op: STGT_H, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // STGT.W rd, rj, rk + {mask: 0xffff8000, value: 0x387d0000, op: STGT_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // STLE.B rd, rj, rk + {mask: 0xffff8000, value: 0x387e0000, op: STLE_B, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // STLE.D rd, rj, rk + {mask: 0xffff8000, value: 0x387f8000, op: STLE_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // STLE.H rd, rj, rk + {mask: 0xffff8000, value: 0x387e8000, op: STLE_H, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // STLE.W rd, rj, rk + {mask: 0xffff8000, value: 0x387f0000, op: STLE_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // STPTR.D rd, rj, si14 + {mask: 0xff000000, value: 0x27000000, op: STPTR_D, args: instArgs{arg_rd, arg_rj, arg_si14_23_10}}, + // STPTR.W rd, rj, si14 + {mask: 0xff000000, value: 0x25000000, op: STPTR_W, args: instArgs{arg_rd, arg_rj, arg_si14_23_10}}, + // STX.B rd, rj, rk + {mask: 0xffff8000, value: 0x38100000, op: STX_B, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // STX.D rd, rj, rk + {mask: 0xffff8000, value: 0x381c0000, op: STX_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // STX.H rd, rj, rk + {mask: 0xffff8000, value: 0x38140000, op: STX_H, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // STX.W rd, rj, rk + {mask: 0xffff8000, value: 0x38180000, op: STX_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // ST.B rd, rj, si12 + {mask: 0xffc00000, value: 0x29000000, op: ST_B, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // ST.D rd, rj, si12 + {mask: 0xffc00000, value: 0x29c00000, op: ST_D, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // ST.H rd, rj, si12 + {mask: 0xffc00000, value: 0x29400000, op: ST_H, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // ST.W rd, rj, si12 + {mask: 0xffc00000, value: 0x29800000, op: ST_W, args: instArgs{arg_rd, arg_rj, arg_si12_21_10}}, + // SUB.D rd, rj, rk + {mask: 0xffff8000, value: 0x00118000, op: SUB_D, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // SUB.W rd, rj, rk + {mask: 0xffff8000, value: 0x00110000, op: SUB_W, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // SYSCALL code + {mask: 0xffff8000, value: 0x002b0000, op: SYSCALL, args: instArgs{arg_code_14_0}}, + // TLBCLR + {mask: 0xffffffff, value: 0x06482000, op: TLBCLR, args: instArgs{}}, + // TLBFILL + {mask: 0xffffffff, value: 0x06483400, op: TLBFILL, args: instArgs{}}, + // TLBFLUSH + {mask: 0xffffffff, value: 0x06482400, op: TLBFLUSH, args: instArgs{}}, + // TLBRD + {mask: 0xffffffff, value: 0x06482c00, op: TLBRD, args: instArgs{}}, + // TLBSRCH + {mask: 0xffffffff, value: 0x06482800, op: TLBSRCH, args: instArgs{}}, + // TLBWR + {mask: 0xffffffff, value: 0x06483000, op: TLBWR, args: instArgs{}}, + // XOR rd, rj, rk + {mask: 0xffff8000, value: 0x00158000, op: XOR, args: instArgs{arg_rd, arg_rj, arg_rk}}, + // XORI rd, rj, ui12 + {mask: 0xffc00000, value: 0x03c00000, op: XORI, args: instArgs{arg_rd, arg_rj, arg_ui12_21_10}}, +}