mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
irjit: Add constructs for validing mem access.
Basically to allow slow/fast memory to work with IR, including for alignment checks.
This commit is contained in:
parent
5f30c88e38
commit
6715f41410
6 changed files with 78 additions and 0 deletions
|
@ -264,6 +264,7 @@ void IRFrontend::DoJit(u32 em_address, std::vector<IRInst> &instructions, u32 &m
|
|||
&OptimizeFPMoves,
|
||||
&PropagateConstants,
|
||||
&PurgeTemps,
|
||||
&ApplyMemoryValidation,
|
||||
// &ReorderLoadStore,
|
||||
// &MergeLoadStore,
|
||||
// &ThreeOpToTwoOp,
|
||||
|
|
|
@ -163,6 +163,11 @@ static const IRMeta irMeta[] = {
|
|||
{ IROp::Breakpoint, "Breakpoint", "", IRFLAG_EXIT },
|
||||
{ IROp::MemoryCheck, "MemoryCheck", "_GC", IRFLAG_EXIT },
|
||||
|
||||
{ IROp::ValidateAddress8, "ValidAddr8", "_GC", IRFLAG_EXIT },
|
||||
{ IROp::ValidateAddress16, "ValidAddr16", "_GC", IRFLAG_EXIT },
|
||||
{ IROp::ValidateAddress32, "ValidAddr32", "_GC", IRFLAG_EXIT },
|
||||
{ IROp::ValidateAddress128, "ValidAddr128", "_GC", IRFLAG_EXIT },
|
||||
|
||||
{ IROp::RestoreRoundingMode, "RestoreRoundingMode", "" },
|
||||
{ IROp::ApplyRoundingMode, "ApplyRoundingMode", "" },
|
||||
{ IROp::UpdateRoundingMode, "UpdateRoundingMode", "" },
|
||||
|
|
|
@ -213,8 +213,15 @@ enum class IROp : u8 {
|
|||
SetPCConst, // hack to make replacement know PC
|
||||
CallReplacement,
|
||||
Break,
|
||||
|
||||
// Debugging breakpoints.
|
||||
Breakpoint,
|
||||
MemoryCheck,
|
||||
|
||||
ValidateAddress8,
|
||||
ValidateAddress16,
|
||||
ValidateAddress32,
|
||||
ValidateAddress128,
|
||||
};
|
||||
|
||||
enum IRComparison {
|
||||
|
|
|
@ -79,6 +79,19 @@ u32 RunMemCheck(u32 pc, u32 addr) {
|
|||
return coreState != CORE_RUNNING ? 1 : 0;
|
||||
}
|
||||
|
||||
template <uint32_t alignment>
|
||||
u32 RunValidateAddress(u32 pc, u32 addr) {
|
||||
if (!Memory::IsValidRange(addr, alignment)) {
|
||||
Core_MemoryException(addr, pc, MemoryExceptionType::UNKNOWN);
|
||||
return coreState != CORE_RUNNING ? 1 : 0;
|
||||
}
|
||||
if (alignment > 1 && (addr & (alignment - 1)) != 0) {
|
||||
Core_MemoryException(addr, pc, MemoryExceptionType::UNKNOWN);
|
||||
return coreState != CORE_RUNNING ? 1 : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We cannot use NEON on ARM32 here until we make it a hard dependency. We can, however, on ARM64.
|
||||
u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) {
|
||||
const IRInst *end = inst + count;
|
||||
|
@ -142,6 +155,31 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) {
|
|||
mips->r[inst->dest] = ReverseBits32(mips->r[inst->src1]);
|
||||
break;
|
||||
|
||||
case IROp::ValidateAddress8:
|
||||
if (RunValidateAddress<1>(mips->pc, mips->r[inst->src1] + inst->constant)) {
|
||||
CoreTiming::ForceCheck();
|
||||
return mips->pc;
|
||||
}
|
||||
break;
|
||||
case IROp::ValidateAddress16:
|
||||
if (RunValidateAddress<2>(mips->pc, mips->r[inst->src1] + inst->constant)) {
|
||||
CoreTiming::ForceCheck();
|
||||
return mips->pc;
|
||||
}
|
||||
break;
|
||||
case IROp::ValidateAddress32:
|
||||
if (RunValidateAddress<4>(mips->pc, mips->r[inst->src1] + inst->constant)) {
|
||||
CoreTiming::ForceCheck();
|
||||
return mips->pc;
|
||||
}
|
||||
break;
|
||||
case IROp::ValidateAddress128:
|
||||
if (RunValidateAddress<16>(mips->pc, mips->r[inst->src1] + inst->constant)) {
|
||||
CoreTiming::ForceCheck();
|
||||
return mips->pc;
|
||||
}
|
||||
break;
|
||||
|
||||
case IROp::Load8:
|
||||
mips->r[inst->dest] = Memory::ReadUnchecked_U8(mips->r[inst->src1] + inst->constant);
|
||||
break;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Common/BitSet.h"
|
||||
#include "Common/Data/Convert/SmallDataConvert.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/MIPS/IR/IRInterpreter.h"
|
||||
#include "Core/MIPS/IR/IRPassSimplify.h"
|
||||
#include "Core/MIPS/IR/IRRegCache.h"
|
||||
|
@ -622,6 +623,18 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts
|
|||
}
|
||||
break;
|
||||
|
||||
case IROp::ValidateAddress8:
|
||||
case IROp::ValidateAddress16:
|
||||
case IROp::ValidateAddress32:
|
||||
case IROp::ValidateAddress128:
|
||||
if (gpr.IsImm(inst.src1)) {
|
||||
out.Write(inst.op, inst.dest, 0, out.AddConstant(gpr.GetImm(inst.src1) + inst.constant));
|
||||
} else {
|
||||
gpr.MapIn(inst.src1);
|
||||
goto doDefault;
|
||||
}
|
||||
break;
|
||||
|
||||
case IROp::Downcount:
|
||||
case IROp::SetPCConst:
|
||||
goto doDefault;
|
||||
|
@ -1428,3 +1441,16 @@ bool MergeLoadStore(const IRWriter &in, IRWriter &out, const IROptions &opts) {
|
|||
}
|
||||
return logBlocks;
|
||||
}
|
||||
|
||||
bool ApplyMemoryValidation(const IRWriter &in, IRWriter &out, const IROptions &opts) {
|
||||
CONDITIONAL_DISABLE;
|
||||
if (g_Config.bFastMemory)
|
||||
DISABLE;
|
||||
|
||||
bool logBlocks = false;
|
||||
for (IRInst inst : in.GetInstructions()) {
|
||||
// TODO
|
||||
out.Write(inst);
|
||||
}
|
||||
return logBlocks;
|
||||
}
|
||||
|
|
|
@ -14,3 +14,4 @@ bool ThreeOpToTwoOp(const IRWriter &in, IRWriter &out, const IROptions &opts);
|
|||
bool OptimizeFPMoves(const IRWriter &in, IRWriter &out, const IROptions &opts);
|
||||
bool ReorderLoadStore(const IRWriter &in, IRWriter &out, const IROptions &opts);
|
||||
bool MergeLoadStore(const IRWriter &in, IRWriter &out, const IROptions &opts);
|
||||
bool ApplyMemoryValidation(const IRWriter &in, IRWriter &out, const IROptions &opts);
|
||||
|
|
Loading…
Add table
Reference in a new issue