Merge pull request #21499 from lrzlin/loong-handler

loongarch: Implement excepetion handler and JIT bug fix
This commit is contained in:
Henrik Rydgård
2026-03-30 11:12:15 -06:00
committed by GitHub
5 changed files with 109 additions and 1 deletions
+11
View File
@@ -182,6 +182,17 @@ typedef mcontext_t SContext;
#define CTX_PC CTX_REG(0)
#define CTX_SP CTX_REG(2)
#elif PPSSPP_ARCH(LOONGARCH64)
#include <ucontext.h>
typedef mcontext_t SContext;
#define MACHINE_CONTEXT_SUPPORTED
#define CTX_REG(x) __gregs[x]
#define CTX_PC __pc
#define CTX_SP CTX_REG(2)
#else
// No context definition for architecture
+2 -1
View File
@@ -242,7 +242,8 @@ void LoongArch64JitBackend::CompIR_Bits(IRInst inst) {
case IROp::BSwap32:
regs_.Map(inst);
REVB_2W(regs_.R(inst.dest), regs_.R(inst.src1));
regs_.MarkGPRDirty(inst.dest, true);
// REVB.2W will also swap the upper 32-bit, so mark normalized32 as false.
regs_.MarkGPRDirty(inst.dest, false);
break;
case IROp::Clz:
+12
View File
@@ -32,6 +32,8 @@
#include "Core/Util/DisArm64.h"
#elif PPSSPP_ARCH(ARM)
#include "ext/disarm.h"
#elif PPSSPP_ARCH(LOONGARCH64)
#include "ext/loongarch-disasm.h"
#endif
#include "Common/Log.h"
@@ -242,6 +244,16 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
}
break;
}
#elif PPSSPP_ARCH(LOONGARCH64)
uint32_t word;
memcpy(&word, codePtr, 4);
// To ignore the access, we need to disassemble the instruction and modify context->CTX_PC
LoongArch64LSInstructionInfo info{};
success = LoongArch64AnalyzeLoadStore((uint64_t)codePtr, word, &info);
if (success)
instructionSize = info.instructionSize;
// It's quite pointless to ignore bad memory access on LoongArch because we could not handle it correctly.
success = false;
#endif
if (MIPSComp::jit && MIPSComp::jit->IsAtDispatchFetch(codePtr)) {
+74
View File
@@ -9927,3 +9927,77 @@ void print_disasm(uint32_t opcode)
sprint_disasm(opcode, msg);
puts(msg);
}
// Currently only support instructions which JIT could generate.
bool LoongArch64AnalyzeLoadStore(uint64_t addr, uint32_t opcode, LoongArch64LSInstructionInfo *info)
{
if (opcode >> 26 == 0b001010) {
switch (opcode >> 24 & 3) {
// ld.b/ld.h/ld.w/ld.d
case 0:
info->isIntegerLoadStore = true;
info->size = 1 << ((opcode >> 22) & 3);
break;
// st.b/st.h/st.w/st.d
case 1:
info->isIntegerLoadStore = true;
info->isMemoryWrite = true;
info->size = 1 << ((opcode >> 22) & 3);
break;
// ld.bu/ld.hu/ld.wu/preld
case 2:
info->isIntegerLoadStore = true;
info->size = 1 << ((opcode >> 22) & 3);
break;
// fld.s/fst.s/fld.d/fld.d
case 3:
info->isFPLoadStore = true;
switch (opcode >> 22 & 3) {
case 0:
info->size = 4;
break;
case 1:
info->isMemoryWrite = true;
info->size = 4;
break;
case 2:
info->size = 8;
break;
case 3:
info->isMemoryWrite = true;
info->size = 8;
break;
}
break;
}
}
if (opcode >> 26 == 0b001011) {
switch (opcode >> 22 & 15) {
// vld
case 0:
info->isFPLoadStore = true;
info->size = 16;
break;
// vst
case 1:
info->isFPLoadStore = true;
info->isMemoryWrite = true;
info->size = 16;
break;
}
}
if (opcode >> 26 == 0b001100) {
if (((opcode >> 20) & 63) == 0b000010) {
// vldrepl.w
info->isFPLoadStore = true;
info->size = 4;
}
}
if (info->isIntegerLoadStore || info->isFPLoadStore)
return true;
else
return false;
}
+10
View File
@@ -2755,6 +2755,14 @@ typedef struct Ins {
struct Ins *next;
} Ins;
struct LoongArch64LSInstructionInfo {
int instructionSize = 4;
bool isIntegerLoadStore;
bool isFPLoadStore;
int size; // 0 = 8-bit, 1 = 16-bit, 2 = 32-bit, 3 = 64-bit
bool isMemoryWrite;
};
uint32_t la_assemble(Ins *ins);
void la_disasm(uint32_t opcode, Ins *ins);
@@ -2774,4 +2782,6 @@ void print_op(LA_OPCODE op);
void print_ins(Ins *ins);
void print_disasm(uint32_t opcode);
bool LoongArch64AnalyzeLoadStore(uint64_t addr, uint32_t opcode, LoongArch64LSInstructionInfo *info);
#endif