Merge pull request #840 from FioraAeterna/jittimer
JIT: implement timer support in mtspr
This commit is contained in:
commit
fa29b18e3e
|
@ -70,31 +70,6 @@ namespace SystemTimers
|
|||
|
||||
static u32 CPU_CORE_CLOCK = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
||||
|
||||
/*
|
||||
GameCube MHz
|
||||
flipper <-> ARAM bus: 81 (DSP)
|
||||
gekko <-> flipper bus: 162
|
||||
flipper <-> 1T-SRAM bus: 324
|
||||
gekko: 486
|
||||
|
||||
These contain some guesses:
|
||||
Wii MHz
|
||||
hollywood <-> GDDR3 RAM bus: ??? no idea really
|
||||
broadway <-> hollywood bus: 243
|
||||
hollywood <-> 1T-SRAM bus: 486
|
||||
broadway: 729
|
||||
*/
|
||||
// Ratio of TB and Decrementer to clock cycles.
|
||||
// TB clk is 1/4 of BUS clk. And it seems BUS clk is really 1/3 of CPU clk.
|
||||
// So, ratio is 1 / (1/4 * 1/3 = 1/12) = 12.
|
||||
// note: ZWW is ok and faster with TIMER_RATIO=8 though.
|
||||
// !!! POSSIBLE STABLE PERF BOOST HACK THERE !!!
|
||||
|
||||
enum
|
||||
{
|
||||
TIMER_RATIO = 12
|
||||
};
|
||||
|
||||
static int et_Dec;
|
||||
static int et_VI;
|
||||
static int et_SI;
|
||||
|
|
|
@ -9,6 +9,31 @@
|
|||
namespace SystemTimers
|
||||
{
|
||||
|
||||
/*
|
||||
GameCube MHz
|
||||
flipper <-> ARAM bus: 81 (DSP)
|
||||
gekko <-> flipper bus: 162
|
||||
flipper <-> 1T-SRAM bus: 324
|
||||
gekko: 486
|
||||
|
||||
These contain some guesses:
|
||||
Wii MHz
|
||||
hollywood <-> GDDR3 RAM bus: ??? no idea really
|
||||
broadway <-> hollywood bus: 243
|
||||
hollywood <-> 1T-SRAM bus: 486
|
||||
broadway: 729
|
||||
*/
|
||||
// Ratio of TB and Decrementer to clock cycles.
|
||||
// TB clk is 1/4 of BUS clk. And it seems BUS clk is really 1/3 of CPU clk.
|
||||
// So, ratio is 1 / (1/4 * 1/3 = 1/12) = 12.
|
||||
// note: ZWW is ok and faster with TIMER_RATIO=8 though.
|
||||
// !!! POSSIBLE STABLE PERF BOOST HACK THERE !!!
|
||||
|
||||
enum
|
||||
{
|
||||
TIMER_RATIO = 12
|
||||
};
|
||||
|
||||
u32 GetTicksPerSecond();
|
||||
void PreInit();
|
||||
void Init();
|
||||
|
|
|
@ -166,10 +166,53 @@ void Jit64::mfspr(UGeckoInstruction inst)
|
|||
int d = inst.RD;
|
||||
switch (iIndex)
|
||||
{
|
||||
case SPR_WPAR:
|
||||
case SPR_DEC:
|
||||
case SPR_TL:
|
||||
case SPR_TU:
|
||||
{
|
||||
// TODO: we really only need to call GetFakeTimeBase once per JIT block; this matters because
|
||||
// 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);
|
||||
// The timer can change within a long block, so add in any difference
|
||||
if (offset > 0)
|
||||
ADD(64, R(RAX), Imm32(offset));
|
||||
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);
|
||||
// Be careful; the actual opcode is for mftb (371), not mfspr (339)
|
||||
if (js.next_inst.OPCD == 31 && js.next_inst.SUBOP10 == 371 && (nextIndex == SPR_TU || nextIndex == SPR_TL))
|
||||
{
|
||||
int n = js.next_inst.RD;
|
||||
js.downcountAmount++;
|
||||
js.skipnext = true;
|
||||
gpr.Lock(d, n);
|
||||
if (iIndex == SPR_TL)
|
||||
MOV(32, gpr.R(d), R(EAX));
|
||||
if (nextIndex == SPR_TL)
|
||||
MOV(32, gpr.R(n), R(EAX));
|
||||
SHR(64, R(RAX), Imm8(32));
|
||||
if (iIndex == SPR_TU)
|
||||
MOV(32, gpr.R(d), R(EAX));
|
||||
if (nextIndex == SPR_TU)
|
||||
MOV(32, gpr.R(n), R(EAX));
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.Lock(d);
|
||||
if (iIndex == SPR_TU)
|
||||
SHR(64, R(RAX), Imm8(32));
|
||||
MOV(32, gpr.R(d), R(EAX));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPR_WPAR:
|
||||
case SPR_DEC:
|
||||
case SPR_PMC1:
|
||||
case SPR_PMC2:
|
||||
case SPR_PMC3:
|
||||
|
@ -179,9 +222,9 @@ void Jit64::mfspr(UGeckoInstruction inst)
|
|||
gpr.Lock(d);
|
||||
gpr.BindToRegister(d, false);
|
||||
MOV(32, gpr.R(d), M(&PowerPC::ppcState.spr[iIndex]));
|
||||
gpr.UnlockAll();
|
||||
break;
|
||||
}
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
|
||||
void Jit64::mtmsr(UGeckoInstruction inst)
|
||||
|
|
Loading…
Reference in New Issue