mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-13 22:40:29 +02:00
Jit: Remove the Jal-to-replacement optimization (really not all that benificial)
This commit is contained in:
1 parent
c22962ee56
commit
9f5be16663
11 files changed
+1
-196
No files matched your search
@@ -1611,7 +1611,7 @@ static const ReplacementTableEntry entries[] = {
|
||||
{ "strncpy", &Replace_strncpy, 0, REPFLAG_DISABLED },
|
||||
{ "strcmp", &Replace_strcmp, 0, REPFLAG_DISABLED },
|
||||
{ "strncmp", &Replace_strncmp, 0, REPFLAG_DISABLED },
|
||||
{ "fabsf", &Replace_fabsf, JITFUNC(Replace_fabsf), REPFLAG_ALLOWINLINE | REPFLAG_DISABLED },
|
||||
{ "fabsf", &Replace_fabsf, JITFUNC(Replace_fabsf), REPFLAG_DISABLED },
|
||||
{ "dl_write_matrix", &Replace_dl_write_matrix, 0, REPFLAG_DISABLED }, // &MIPSComp::Jit::Replace_dl_write_matrix, REPFLAG_DISABLED },
|
||||
{ "dl_write_matrix_2", &Replace_dl_write_matrix, 0, REPFLAG_DISABLED },
|
||||
{ "gta_dl_write_matrix", &Replace_gta_dl_write_matrix, 0, REPFLAG_DISABLED },
|
||||
@@ -1873,35 +1873,3 @@ bool GetReplacedOpAt(u32 address, u32 *op) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CanReplaceJalTo(u32 dest, const ReplacementTableEntry **entry, u32 *funcSize) {
|
||||
MIPSOpcode op(Memory::Read_Opcode_JIT(dest));
|
||||
if (!MIPS_IS_REPLACEMENT(op.encoding))
|
||||
return false;
|
||||
|
||||
// Make sure we don't replace if there are any breakpoints inside.
|
||||
*funcSize = g_symbolMap->GetFunctionSize(dest);
|
||||
if (*funcSize == SymbolMap::INVALID_ADDRESS) {
|
||||
if (g_breakpoints.IsAddressBreakPoint(dest)) {
|
||||
return false;
|
||||
}
|
||||
*funcSize = (u32)sizeof(u32);
|
||||
} else {
|
||||
if (g_breakpoints.RangeContainsBreakPoint(dest, *funcSize)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int index = op.encoding & MIPS_EMUHACK_VALUE_MASK;
|
||||
*entry = GetReplacementFunc(index);
|
||||
if (!*entry) {
|
||||
ERROR_LOG(Log::HLE, "ReplaceJalTo: Invalid replacement op %08x at %08x", op.encoding, dest);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((*entry)->flags & (REPFLAG_HOOKENTER | REPFLAG_HOOKEXIT | REPFLAG_DISABLED | REPFLAG_SLICED)) {
|
||||
// If it's a hook, we can't replace the jal, we have to go inside the func.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -46,7 +46,6 @@
|
||||
typedef int (* ReplaceFunc)();
|
||||
|
||||
enum {
|
||||
REPFLAG_ALLOWINLINE = 0x01,
|
||||
// Used to keep things around but disable them.
|
||||
REPFLAG_DISABLED = 0x02,
|
||||
// Note that this will re-execute in a function that loops at start.
|
||||
@@ -77,7 +76,6 @@ void WriteReplaceInstructions(u32 address, u64 hash, int size);
|
||||
void RestoreReplacedInstruction(u32 address);
|
||||
void RestoreReplacedInstructions(u32 startAddr, u32 endAddr);
|
||||
bool GetReplacedOpAt(u32 address, u32 *op);
|
||||
bool CanReplaceJalTo(u32 dest, const ReplacementTableEntry **entry, u32 *funcSize);
|
||||
|
||||
// For savestates. If you call SaveAndClearReplacements(), you must call RestoreSavedReplacements().
|
||||
std::map<u32, u32> SaveAndClearReplacements();
|
||||
|
||||
@@ -543,9 +543,6 @@ void ArmJit::Comp_Jump(MIPSOpcode op) {
|
||||
break;
|
||||
|
||||
case 3: //jal
|
||||
if (ReplaceJalTo(targetAddr))
|
||||
return;
|
||||
|
||||
gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8);
|
||||
CompileDelaySlot(DELAYSLOT_NICE);
|
||||
if (jo.continueJumps && js.numInstructions < jo.continueMaxInstructions) {
|
||||
|
||||
@@ -481,58 +481,6 @@ void ArmJit::UnlinkBlock(u8 *checkedEntry, u32 originalAddress) {
|
||||
}
|
||||
}
|
||||
|
||||
bool ArmJit::ReplaceJalTo(u32 dest) {
|
||||
const ReplacementTableEntry *entry = nullptr;
|
||||
u32 funcSize = 0;
|
||||
if (!CanReplaceJalTo(dest, &entry, &funcSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Warning - this might be bad if the code at the destination changes...
|
||||
if (entry->flags & REPFLAG_ALLOWINLINE) {
|
||||
// Jackpot! Just do it, no flushing. The code will be entirely inlined.
|
||||
|
||||
// First, compile the delay slot. It's unconditional so no issues.
|
||||
CompileDelaySlot(DELAYSLOT_NICE);
|
||||
// Technically, we should write the unused return address to RA, but meh.
|
||||
MIPSReplaceFunc repl = entry->jitReplaceFunc;
|
||||
int cycles = (this->*repl)();
|
||||
js.downcountAmount += cycles;
|
||||
} else {
|
||||
gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8);
|
||||
CompileDelaySlot(DELAYSLOT_NICE);
|
||||
FlushAll();
|
||||
SaveDowncount();
|
||||
RestoreRoundingMode();
|
||||
|
||||
if (BLInRange((const void *)(entry->replaceFunc))) {
|
||||
BL((const void *)(entry->replaceFunc));
|
||||
} else {
|
||||
MOVI2R(R0, (uintptr_t)entry->replaceFunc);
|
||||
BL(R0);
|
||||
}
|
||||
ApplyRoundingMode();
|
||||
RestoreDowncount();
|
||||
|
||||
WriteDownCountR(R0);
|
||||
}
|
||||
|
||||
js.compilerPC += 4;
|
||||
// No writing exits, keep going!
|
||||
|
||||
if (g_breakpoints.HasMemChecks()) {
|
||||
// We could modify coreState, so we need to write PC and check.
|
||||
// Otherwise, PC may end up on the jal. We add 4 to skip the delay slot.
|
||||
FlushAll();
|
||||
WriteExit(GetCompilerPC() + 4, js.nextExit++);
|
||||
js.compiling = false;
|
||||
}
|
||||
|
||||
// Add a trigger so that if the inlined code changes, we invalidate this block.
|
||||
blocks.CreateProxyBlock(js.blockStart, dest, funcSize / sizeof(u32), GetCodePtr());
|
||||
return true;
|
||||
}
|
||||
|
||||
void ArmJit::Comp_ReplacementFunc(MIPSOpcode op)
|
||||
{
|
||||
// We get here if we execute the first instruction of a replaced function. This means
|
||||
|
||||
@@ -213,8 +213,6 @@ private:
|
||||
void MovFromPC(ArmGen::ARMReg r);
|
||||
void MovToPC(ArmGen::ARMReg r);
|
||||
|
||||
bool ReplaceJalTo(u32 dest);
|
||||
|
||||
void SaveDowncount();
|
||||
void RestoreDowncount();
|
||||
|
||||
|
||||
@@ -558,9 +558,6 @@ void Arm64Jit::Comp_Jump(MIPSOpcode op) {
|
||||
break;
|
||||
|
||||
case 3: //jal
|
||||
if (ReplaceJalTo(targetAddr))
|
||||
return;
|
||||
|
||||
gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8);
|
||||
CompileDelaySlot(DELAYSLOT_NICE);
|
||||
if (jo.continueJumps && js.numInstructions < jo.continueMaxInstructions) {
|
||||
|
||||
@@ -493,52 +493,6 @@ void Arm64Jit::UnlinkBlock(u8 *checkedEntry, u32 originalAddress) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Arm64Jit::ReplaceJalTo(u32 dest) {
|
||||
#if PPSSPP_ARCH(ARM64)
|
||||
const ReplacementTableEntry *entry = nullptr;
|
||||
u32 funcSize = 0;
|
||||
if (!CanReplaceJalTo(dest, &entry, &funcSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Warning - this might be bad if the code at the destination changes...
|
||||
if (entry->flags & REPFLAG_ALLOWINLINE) {
|
||||
// Jackpot! Just do it, no flushing. The code will be entirely inlined.
|
||||
// First, compile the delay slot. It's unconditional so no issues.
|
||||
CompileDelaySlot(DELAYSLOT_NICE);
|
||||
// Technically, we should write the unused return address to RA, but meh.
|
||||
MIPSReplaceFunc repl = entry->jitReplaceFunc;
|
||||
int cycles = (this->*repl)();
|
||||
js.downcountAmount += cycles;
|
||||
} else {
|
||||
gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8);
|
||||
CompileDelaySlot(DELAYSLOT_NICE);
|
||||
FlushAll();
|
||||
SaveStaticRegisters();
|
||||
RestoreRoundingMode();
|
||||
QuickCallFunction(SCRATCH1_64, (const void *)(entry->replaceFunc));
|
||||
ApplyRoundingMode();
|
||||
LoadStaticRegisters();
|
||||
WriteDownCountR(W0); // W0 is the return value from entry->replaceFunc. Neither LoadStaticRegisters nor ApplyRoundingMode can trash it.
|
||||
}
|
||||
|
||||
js.compilerPC += 4;
|
||||
// No writing exits, keep going!
|
||||
|
||||
if (g_breakpoints.HasMemChecks()) {
|
||||
// We could modify coreState, so we need to write PC and check.
|
||||
// Otherwise, PC may end up on the jal. We add 4 to skip the delay slot.
|
||||
FlushAll();
|
||||
WriteExit(GetCompilerPC() + 4, js.nextExit++);
|
||||
js.compiling = false;
|
||||
}
|
||||
|
||||
// Add a trigger so that if the inlined code changes, we invalidate this block.
|
||||
blocks.CreateProxyBlock(js.blockStart, dest, funcSize / sizeof(u32), GetCodePtr());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arm64Jit::Comp_ReplacementFunc(MIPSOpcode op)
|
||||
{
|
||||
// We get here if we execute the first instruction of a replaced function. This means
|
||||
|
||||
@@ -212,8 +212,6 @@ private:
|
||||
void MovFromPC(Arm64Gen::ARM64Reg r);
|
||||
void MovToPC(Arm64Gen::ARM64Reg r);
|
||||
|
||||
bool ReplaceJalTo(u32 dest);
|
||||
|
||||
// Clobbers SCRATCH2.
|
||||
void SaveStaticRegisters();
|
||||
// Clobbers SCRATCH2.
|
||||
|
||||
@@ -601,13 +601,6 @@ void Jit::Comp_Jump(MIPSOpcode op) {
|
||||
break;
|
||||
|
||||
case 3: //jal
|
||||
// Special case for branches to "replace functions":
|
||||
if (ReplaceJalTo(targetAddr))
|
||||
return;
|
||||
|
||||
// Check for small function inlining (future)
|
||||
|
||||
|
||||
// Save return address - might be overwritten by delay slot.
|
||||
gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8);
|
||||
CompileDelaySlot(DELAYSLOT_NICE);
|
||||
|
||||
@@ -538,51 +538,6 @@ void Jit::UnlinkBlock(u8 *checkedEntry, u32 originalAddress) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Jit::ReplaceJalTo(u32 dest) {
|
||||
const ReplacementTableEntry *entry = nullptr;
|
||||
u32 funcSize = 0;
|
||||
if (!CanReplaceJalTo(dest, &entry, &funcSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Warning - this might be bad if the code at the destination changes...
|
||||
if (entry->flags & REPFLAG_ALLOWINLINE) {
|
||||
// Jackpot! Just do it, no flushing. The code will be entirely inlined.
|
||||
|
||||
// First, compile the delay slot. It's unconditional so no issues.
|
||||
CompileDelaySlot(DELAYSLOT_NICE);
|
||||
// Technically, we should write the unused return address to RA, but meh.
|
||||
MIPSReplaceFunc repl = entry->jitReplaceFunc;
|
||||
int cycles = (this->*repl)();
|
||||
js.downcountAmount += cycles;
|
||||
} else {
|
||||
gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8);
|
||||
CompileDelaySlot(DELAYSLOT_NICE);
|
||||
FlushAll();
|
||||
MOV(32, MIPSSTATE_VAR(pc), Imm32(GetCompilerPC()));
|
||||
RestoreRoundingMode();
|
||||
ABI_CallFunction(entry->replaceFunc);
|
||||
SUB(32, MIPSSTATE_VAR(downcount), R(EAX));
|
||||
ApplyRoundingMode();
|
||||
}
|
||||
|
||||
js.compilerPC += 4;
|
||||
// No writing exits, keep going!
|
||||
|
||||
if (g_breakpoints.HasMemChecks()) {
|
||||
// We could modify coreState, so we need to write PC and check.
|
||||
// Otherwise, PC may end up on the jal. We add 4 to skip the delay slot.
|
||||
MOV(32, MIPSSTATE_VAR(pc), Imm32(GetCompilerPC() + 4));
|
||||
js.afterOp |= JitState::AFTER_CORE_STATE;
|
||||
}
|
||||
|
||||
// Add a trigger so that if the inlined code changes, we invalidate this block.
|
||||
blocks.CreateProxyBlock(js.blockStart, dest, funcSize / sizeof(u32), GetCodePtr());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Jit::Comp_ReplacementFunc(MIPSOpcode op) {
|
||||
// We get here if we execute the first instruction of a replaced function. This means
|
||||
// that we do need to return to RA.
|
||||
|
||||
@@ -187,7 +187,6 @@ private:
|
||||
void FlushAll();
|
||||
void FlushPrefixV();
|
||||
void WriteDowncount(int offset = 0);
|
||||
bool ReplaceJalTo(u32 dest);
|
||||
|
||||
u32 GetCompilerPC();
|
||||
// See CompileDelaySlotFlags for flags.
|
||||
|
||||
Reference in new issue
Block a user