Files
delve/pkg/proc/loong64_disasm.go
yelvens d2f748f1bd *: add support for linux/loong64 to native backend (#3892)
* delve: support linux-loong64 native debug

LoongArch is a new RISC ISA, which is independently designed by Loongson Technology.

LoongArch includes a reduced 32-bit version (LA32R), a standard 32-bit version (LA32S)
and a 64-bit version (LA64), and loong64 is the 64-bit version of LoongArch.

LoongArch documentation: https://github.com/loongson/LoongArch-Documentation.git

* *: mark loong64 port as experimental

---------

Co-authored-by: Huang Qiqi <huangqiqi@loongson.cn>
2025-01-17 09:41:37 -08:00

177 lines
3.7 KiB
Go

package proc
import (
"github.com/go-delve/delve/pkg/dwarf/op"
"github.com/go-delve/delve/pkg/dwarf/regnum"
"golang.org/x/arch/loong64/loong64asm"
)
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}
}
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
}()