JIT: completely inline timer reading
Should be a bit faster on games that heavily use the timer.
This commit is contained in:
parent
b583879c2a
commit
2f9e9bf1fc
|
@ -50,13 +50,13 @@ static Event *eventPool = nullptr;
|
|||
int slicelength;
|
||||
static int maxSliceLength = MAX_SLICE_LENGTH;
|
||||
|
||||
static s64 globalTimer;
|
||||
static s64 idledCycles;
|
||||
|
||||
static u32 fakeDecStartValue;
|
||||
static u64 fakeDecStartTicks;
|
||||
static u64 fakeTBStartValue;
|
||||
static u64 fakeTBStartTicks;
|
||||
|
||||
s64 globalTimer;
|
||||
u64 fakeTBStartValue;
|
||||
u64 fakeTBStartTicks;
|
||||
|
||||
static int ev_lost;
|
||||
|
||||
|
|
|
@ -25,6 +25,10 @@ class PointerWrap;
|
|||
namespace CoreTiming
|
||||
{
|
||||
|
||||
extern s64 globalTimer;
|
||||
extern u64 fakeTBStartValue;
|
||||
extern u64 fakeTBStartTicks;
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
|
|
|
@ -173,15 +173,25 @@ void Jit64::mfspr(UGeckoInstruction inst)
|
|||
// typical use of this instruction is to call it three times, e.g. mftbu/mftbl/mftbu/cmpw/bne
|
||||
// to deal with possible timer wraparound. This makes the second two (out of three) completely
|
||||
// redundant for the JIT.
|
||||
u32 registersInUse = CallerSavedRegistersInUse();
|
||||
u32 offset = js.downcountAmount / SystemTimers::TIMER_RATIO;
|
||||
ABI_PushRegistersAndAdjustStack(registersInUse, false);
|
||||
ABI_CallFunction((void *)&SystemTimers::GetFakeTimeBase);
|
||||
ABI_PopRegistersAndAdjustStack(registersInUse, false);
|
||||
gpr.FlushLockX(EDX);
|
||||
|
||||
// An inline implementation of CoreTiming::GetFakeTimeBase, since in timer-heavy games the
|
||||
// cost of calling out to C for this is actually significant.
|
||||
MOV(64, R(RAX), M(&CoreTiming::globalTimer));
|
||||
SUB(64, R(RAX), M(&CoreTiming::fakeTBStartTicks));
|
||||
// a / 12 = (a * 0xAAAAAAAAAAAAAAAB) >> 67
|
||||
MOV(64, R(RDX), Imm64(0xAAAAAAAAAAAAAAABULL));
|
||||
MUL(64, R(RDX));
|
||||
MOV(64, R(RAX), M(&CoreTiming::fakeTBStartValue));
|
||||
SHR(64, R(RDX), Imm8(3));
|
||||
// The timer can change within a long block, so add in any difference
|
||||
if (offset > 0)
|
||||
ADD(64, R(RAX), Imm32(offset));
|
||||
LEA(64, RAX, MComplex(RAX, RDX, SCALE_1, offset));
|
||||
else
|
||||
ADD(64, R(RAX), R(RDX));
|
||||
MOV(64, M(&TL), R(RAX));
|
||||
|
||||
// Two calls of TU/TL next to each other are extremely common in typical usage, so merge them
|
||||
// if we can.
|
||||
u32 nextIndex = (js.next_inst.SPRU << 5) | (js.next_inst.SPRL & 0x1F);
|
||||
|
@ -225,6 +235,7 @@ void Jit64::mfspr(UGeckoInstruction inst)
|
|||
break;
|
||||
}
|
||||
gpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
}
|
||||
|
||||
void Jit64::mtmsr(UGeckoInstruction inst)
|
||||
|
|
Loading…
Reference in New Issue