mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
loongarch: Implement excepetion handler and JIT bug fix
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user