diff --git a/Common/MachineContext.h b/Common/MachineContext.h index 509c0d332a..b704b2e6a2 100644 --- a/Common/MachineContext.h +++ b/Common/MachineContext.h @@ -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 +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 diff --git a/Core/MIPS/LoongArch64/LoongArch64CompALU.cpp b/Core/MIPS/LoongArch64/LoongArch64CompALU.cpp index 4ce4fc2ddf..9ced74ecc3 100644 --- a/Core/MIPS/LoongArch64/LoongArch64CompALU.cpp +++ b/Core/MIPS/LoongArch64/LoongArch64CompALU.cpp @@ -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: diff --git a/Core/MemFault.cpp b/Core/MemFault.cpp index 80ffc9a120..799b7ed104 100644 --- a/Core/MemFault.cpp +++ b/Core/MemFault.cpp @@ -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)) { diff --git a/ext/loongarch-disasm.cpp b/ext/loongarch-disasm.cpp index cb5ada4fc4..0deae02c69 100644 --- a/ext/loongarch-disasm.cpp +++ b/ext/loongarch-disasm.cpp @@ -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; +} diff --git a/ext/loongarch-disasm.h b/ext/loongarch-disasm.h index b339a73a23..2cef32edb7 100644 --- a/ext/loongarch-disasm.h +++ b/ext/loongarch-disasm.h @@ -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