mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
ARMJIT Experiment: Keep downcount in a register. Needs benchmarking.
This commit is contained in:
parent
fe090e8d95
commit
76a937f489
6 changed files with 76 additions and 23 deletions
|
@ -116,12 +116,14 @@ void Jit::GenerateFixedCode()
|
||||||
MOVI2R(R11, (u32)Memory::base);
|
MOVI2R(R11, (u32)Memory::base);
|
||||||
MOVI2R(R10, (u32)mips_);
|
MOVI2R(R10, (u32)mips_);
|
||||||
MOVI2R(R9, (u32)GetBasePtr());
|
MOVI2R(R9, (u32)GetBasePtr());
|
||||||
|
RestoreDowncount();
|
||||||
MovFromPC(R0);
|
MovFromPC(R0);
|
||||||
outerLoopPCInR0 = GetCodePtr();
|
outerLoopPCInR0 = GetCodePtr();
|
||||||
MovToPC(R0);
|
MovToPC(R0);
|
||||||
outerLoop = GetCodePtr();
|
outerLoop = GetCodePtr();
|
||||||
|
SaveDowncount();
|
||||||
QuickCallFunction(R0, (void *)&CoreTiming::Advance);
|
QuickCallFunction(R0, (void *)&CoreTiming::Advance);
|
||||||
|
RestoreDowncount();
|
||||||
FixupBranch skipToRealDispatch = B(); //skip the sync and compare first time
|
FixupBranch skipToRealDispatch = B(); //skip the sync and compare first time
|
||||||
|
|
||||||
dispatcherCheckCoreState = GetCodePtr();
|
dispatcherCheckCoreState = GetCodePtr();
|
||||||
|
@ -174,7 +176,9 @@ void Jit::GenerateFixedCode()
|
||||||
SetCC(CC_AL);
|
SetCC(CC_AL);
|
||||||
|
|
||||||
//Ok, no block, let's jit
|
//Ok, no block, let's jit
|
||||||
|
SaveDowncount();
|
||||||
QuickCallFunction(R2, (void *)&JitAt);
|
QuickCallFunction(R2, (void *)&JitAt);
|
||||||
|
RestoreDowncount();
|
||||||
|
|
||||||
B(dispatcherNoCheck); // no point in special casing this
|
B(dispatcherNoCheck); // no point in special casing this
|
||||||
|
|
||||||
|
@ -187,8 +191,8 @@ void Jit::GenerateFixedCode()
|
||||||
B_CC(CC_EQ, outerLoop);
|
B_CC(CC_EQ, outerLoop);
|
||||||
|
|
||||||
SetJumpTarget(badCoreState);
|
SetJumpTarget(badCoreState);
|
||||||
|
|
||||||
breakpointBailout = GetCodePtr();
|
breakpointBailout = GetCodePtr();
|
||||||
|
SaveDowncount();
|
||||||
|
|
||||||
ADD(_SP, _SP, 4);
|
ADD(_SP, _SP, 4);
|
||||||
|
|
||||||
|
|
|
@ -414,7 +414,9 @@ void Jit::Comp_Syscall(u32 op)
|
||||||
js.downcountAmount = -offset;
|
js.downcountAmount = -offset;
|
||||||
|
|
||||||
MOVI2R(R0, op);
|
MOVI2R(R0, op);
|
||||||
|
SaveDowncount();
|
||||||
QuickCallFunction(R1, (void *)&CallSyscall);
|
QuickCallFunction(R1, (void *)&CallSyscall);
|
||||||
|
RestoreDowncount();
|
||||||
|
|
||||||
WriteSyscallExit();
|
WriteSyscallExit();
|
||||||
js.compiling = false;
|
js.compiling = false;
|
||||||
|
|
|
@ -56,7 +56,7 @@ void DisassembleArm(const u8 *data, int size) {
|
||||||
namespace MIPSComp
|
namespace MIPSComp
|
||||||
{
|
{
|
||||||
|
|
||||||
Jit::Jit(MIPSState *mips) : blocks(mips, this), gpr(mips), fpr(mips), mips_(mips)
|
Jit::Jit(MIPSState *mips) : blocks(mips, this), gpr(mips, &jo), fpr(mips), mips_(mips)
|
||||||
{
|
{
|
||||||
blocks.Init();
|
blocks.Init();
|
||||||
gpr.SetEmitter(this);
|
gpr.SetEmitter(this);
|
||||||
|
@ -286,10 +286,12 @@ void Jit::Comp_Generic(u32 op)
|
||||||
MIPSInterpretFunc func = MIPSGetInterpretFunc(op);
|
MIPSInterpretFunc func = MIPSGetInterpretFunc(op);
|
||||||
if (func)
|
if (func)
|
||||||
{
|
{
|
||||||
|
SaveDowncount();
|
||||||
MOVI2R(R0, js.compilerPC);
|
MOVI2R(R0, js.compilerPC);
|
||||||
MovToPC(R0);
|
MovToPC(R0);
|
||||||
MOVI2R(R0, op);
|
MOVI2R(R0, op);
|
||||||
QuickCallFunction(R1, (void *)func);
|
QuickCallFunction(R1, (void *)func);
|
||||||
|
RestoreDowncount();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Might have eaten prefixes, hard to tell...
|
// Might have eaten prefixes, hard to tell...
|
||||||
|
@ -305,21 +307,45 @@ void Jit::MovToPC(ARMReg r) {
|
||||||
STR(r, CTXREG, offsetof(MIPSState, pc));
|
STR(r, CTXREG, offsetof(MIPSState, pc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Jit::SaveDowncount() {
|
||||||
|
if (jo.downcountInRegister)
|
||||||
|
STR(R7, CTXREG, offsetof(MIPSState, downcount));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit::RestoreDowncount() {
|
||||||
|
if (jo.downcountInRegister)
|
||||||
|
LDR(R7, CTXREG, offsetof(MIPSState, downcount));
|
||||||
|
}
|
||||||
|
|
||||||
void Jit::WriteDownCount(int offset)
|
void Jit::WriteDownCount(int offset)
|
||||||
{
|
{
|
||||||
int theDowncount = js.downcountAmount + offset;
|
if (jo.downcountInRegister) {
|
||||||
LDR(R1, CTXREG, offsetof(MIPSState, downcount));
|
int theDowncount = js.downcountAmount + offset;
|
||||||
Operand2 op2;
|
Operand2 op2;
|
||||||
if (TryMakeOperand2(theDowncount, op2)) // We can enlarge this if we used rotations
|
if (TryMakeOperand2(theDowncount, op2)) // We can enlarge this if we used rotations
|
||||||
{
|
{
|
||||||
SUBS(R1, R1, op2);
|
SUBS(R7, R7, op2);
|
||||||
STR(R1, CTXREG, offsetof(MIPSState, downcount));
|
} else {
|
||||||
|
// Should be fine to use R2 here, flushed the regcache anyway.
|
||||||
|
// If js.downcountAmount can be expressed as an Imm8, we don't need this anyway.
|
||||||
|
MOVI2R(R2, theDowncount);
|
||||||
|
SUBS(R7, R7, R2);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Should be fine to use R2 here, flushed the regcache anyway.
|
int theDowncount = js.downcountAmount + offset;
|
||||||
// If js.downcountAmount can be expressed as an Imm8, we don't need this anyway.
|
LDR(R1, CTXREG, offsetof(MIPSState, downcount));
|
||||||
MOVI2R(R2, theDowncount);
|
Operand2 op2;
|
||||||
SUBS(R1, R1, R2);
|
if (TryMakeOperand2(theDowncount, op2)) // We can enlarge this if we used rotations
|
||||||
STR(R1, CTXREG, offsetof(MIPSState, downcount));
|
{
|
||||||
|
SUBS(R1, R1, op2);
|
||||||
|
STR(R1, CTXREG, offsetof(MIPSState, downcount));
|
||||||
|
} else {
|
||||||
|
// Should be fine to use R2 here, flushed the regcache anyway.
|
||||||
|
// If js.downcountAmount can be expressed as an Imm8, we don't need this anyway.
|
||||||
|
MOVI2R(R2, theDowncount);
|
||||||
|
SUBS(R1, R1, R2);
|
||||||
|
STR(R1, CTXREG, offsetof(MIPSState, downcount));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,11 @@ struct ArmJitOptions
|
||||||
ArmJitOptions()
|
ArmJitOptions()
|
||||||
{
|
{
|
||||||
enableBlocklink = true;
|
enableBlocklink = true;
|
||||||
|
downcountInRegister = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool enableBlocklink;
|
bool enableBlocklink;
|
||||||
|
bool downcountInRegister;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ArmJitState
|
struct ArmJitState
|
||||||
|
@ -230,6 +232,9 @@ private:
|
||||||
void MovFromPC(ARMReg r);
|
void MovFromPC(ARMReg r);
|
||||||
void MovToPC(ARMReg r);
|
void MovToPC(ARMReg r);
|
||||||
|
|
||||||
|
void SaveDowncount();
|
||||||
|
void RestoreDowncount();
|
||||||
|
|
||||||
void WriteExit(u32 destination, int exit_num);
|
void WriteExit(u32 destination, int exit_num);
|
||||||
void WriteExitDestInR(ARMReg Reg);
|
void WriteExitDestInR(ARMReg Reg);
|
||||||
void WriteSyscallExit();
|
void WriteSyscallExit();
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "ArmRegCache.h"
|
#include "ArmRegCache.h"
|
||||||
#include "ArmEmitter.h"
|
#include "ArmEmitter.h"
|
||||||
|
#include "ArmJit.h"
|
||||||
|
|
||||||
#if defined(MAEMO)
|
#if defined(MAEMO)
|
||||||
#include "stddef.h"
|
#include "stddef.h"
|
||||||
|
@ -24,7 +25,7 @@
|
||||||
|
|
||||||
using namespace ArmGen;
|
using namespace ArmGen;
|
||||||
|
|
||||||
ArmRegCache::ArmRegCache(MIPSState *mips) : mips_(mips) {
|
ArmRegCache::ArmRegCache(MIPSState *mips, MIPSComp::ArmJitOptions *options) : mips_(mips), options_(options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArmRegCache::Init(ARMXEmitter *emitter) {
|
void ArmRegCache::Init(ARMXEmitter *emitter) {
|
||||||
|
@ -44,18 +45,26 @@ void ArmRegCache::Start(MIPSAnalyst::AnalysisResults &stats) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const ARMReg *GetMIPSAllocationOrder(int &count) {
|
const ARMReg *ArmRegCache::GetMIPSAllocationOrder(int &count) {
|
||||||
// Note that R0 is reserved as scratch for now.
|
// Note that R0 is reserved as scratch for now.
|
||||||
// R1 could be used as it's only used for scratch outside "regalloc space" now.
|
// R1 could be used as it's only used for scratch outside "regalloc space" now.
|
||||||
// R12 is also potentially usable.
|
// R12 is also potentially usable.
|
||||||
// R4-R7 are registers we could use for static allocation or downcount.
|
// R4-R7 are registers we could use for static allocation or downcount.
|
||||||
// R8 is used to preserve flags in nasty branches.
|
// R8 is used to preserve flags in nasty branches.
|
||||||
// R9 and upwards are reserved for jit basics.
|
// R9 and upwards are reserved for jit basics.
|
||||||
static const ARMReg allocationOrder[] = {
|
if (options_->downcountInRegister) {
|
||||||
R2, R3, R4, R5, R6, R7, R12,
|
static const ARMReg allocationOrder[] = {
|
||||||
};
|
R2, R3, R4, R5, R6, R12,
|
||||||
count = sizeof(allocationOrder) / sizeof(const int);
|
};
|
||||||
return allocationOrder;
|
count = sizeof(allocationOrder) / sizeof(const int);
|
||||||
|
return allocationOrder;
|
||||||
|
} else {
|
||||||
|
static const ARMReg allocationOrder2[] = {
|
||||||
|
R2, R3, R4, R5, R6, R7, R12,
|
||||||
|
};
|
||||||
|
count = sizeof(allocationOrder2) / sizeof(const int);
|
||||||
|
return allocationOrder2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Somewhat smarter spilling - currently simply spills the first available, should do
|
// TODO: Somewhat smarter spilling - currently simply spills the first available, should do
|
||||||
|
|
|
@ -68,10 +68,14 @@ enum {
|
||||||
MAP_NOINIT = 2,
|
MAP_NOINIT = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace MIPSComp {
|
||||||
|
struct ArmJitOptions;
|
||||||
|
}
|
||||||
|
|
||||||
class ArmRegCache
|
class ArmRegCache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ArmRegCache(MIPSState *mips);
|
ArmRegCache(MIPSState *mips, MIPSComp::ArmJitOptions *options);
|
||||||
~ArmRegCache() {}
|
~ArmRegCache() {}
|
||||||
|
|
||||||
void Init(ARMXEmitter *emitter);
|
void Init(ARMXEmitter *emitter);
|
||||||
|
@ -107,7 +111,10 @@ public:
|
||||||
int GetMipsRegOffset(MIPSReg r);
|
int GetMipsRegOffset(MIPSReg r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const ARMReg *GetMIPSAllocationOrder(int &count);
|
||||||
|
|
||||||
MIPSState *mips_;
|
MIPSState *mips_;
|
||||||
|
MIPSComp::ArmJitOptions *options_;
|
||||||
ARMXEmitter *emit;
|
ARMXEmitter *emit;
|
||||||
u32 compilerPC_;
|
u32 compilerPC_;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue