- Fixed TimeBase and Decrementer registers so that they are updated only when needed
- Fixed RTC for GC homebrews git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6158 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
8d6f98439e
commit
9e17007c90
|
@ -66,7 +66,7 @@ s64 idledCycles;
|
||||||
|
|
||||||
Common::CriticalSection externalEventSection;
|
Common::CriticalSection externalEventSection;
|
||||||
|
|
||||||
void (*advanceCallback)(int cyclesExecuted);
|
void (*advanceCallback)(int cyclesExecuted) = NULL;
|
||||||
|
|
||||||
Event* GetNewEvent()
|
Event* GetNewEvent()
|
||||||
{
|
{
|
||||||
|
|
|
@ -271,13 +271,10 @@ void CEXIIPL::TransferByte(u8& _uByte)
|
||||||
if (m_uPosition == 3)
|
if (m_uPosition == 3)
|
||||||
{
|
{
|
||||||
// Get the time ...
|
// Get the time ...
|
||||||
// Subtract Wii bias
|
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
||||||
u32 GCTime = CEXIIPL::GetGCTime() - cWiiBias;
|
*((u32 *)&m_RTC) = Common::swap32(CEXIIPL::GetGCTime() - cWiiBias); // Subtract Wii bias
|
||||||
u8* pGCTime = (u8*)&GCTime;
|
else
|
||||||
for (int i=0; i<4; i++)
|
*((u32 *)&m_RTC) = Common::swap32(CEXIIPL::GetGCTime());
|
||||||
{
|
|
||||||
m_RTC[i] = pGCTime[i^3];
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MAX_LOGLEVEL >= INFO_LEVEL
|
#if MAX_LOGLEVEL >= INFO_LEVEL
|
||||||
|
|
||||||
|
|
|
@ -81,8 +81,10 @@ namespace SystemTimers
|
||||||
|
|
||||||
u32 CPU_CORE_CLOCK = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
u32 CPU_CORE_CLOCK = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
||||||
|
|
||||||
s64 fakeDec;
|
u32 fakeDecStartValue;
|
||||||
u64 startTimeBaseTicks;
|
u64 fakeDecStartTicks;
|
||||||
|
u64 fakeTBStartValue;
|
||||||
|
u64 fakeTBStartTicks;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Gamecube MHz
|
Gamecube MHz
|
||||||
|
@ -189,9 +191,6 @@ void SICallback(u64 userdata, int cyclesLate)
|
||||||
|
|
||||||
void DecrementerCallback(u64 userdata, int cyclesLate)
|
void DecrementerCallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
// Why is fakeDec too big here?
|
|
||||||
// A: Because it's 64bit (0xffffffffffffffff)...?
|
|
||||||
fakeDec = -1;
|
|
||||||
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
|
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DECREMENTER);
|
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DECREMENTER);
|
||||||
}
|
}
|
||||||
|
@ -199,23 +198,32 @@ void DecrementerCallback(u64 userdata, int cyclesLate)
|
||||||
void DecrementerSet()
|
void DecrementerSet()
|
||||||
{
|
{
|
||||||
u32 decValue = PowerPC::ppcState.spr[SPR_DEC];
|
u32 decValue = PowerPC::ppcState.spr[SPR_DEC];
|
||||||
fakeDec = decValue * TIMER_RATIO;
|
|
||||||
CoreTiming::RemoveEvent(et_Dec);
|
CoreTiming::RemoveEvent(et_Dec);
|
||||||
|
if ((decValue & 0x80000000) == 0)
|
||||||
|
{
|
||||||
|
fakeDecStartTicks = CoreTiming::GetTicks();
|
||||||
|
fakeDecStartValue = decValue;
|
||||||
|
|
||||||
CoreTiming::ScheduleEvent(decValue * TIMER_RATIO, et_Dec);
|
CoreTiming::ScheduleEvent(decValue * TIMER_RATIO, et_Dec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvanceCallback(int cyclesExecuted)
|
|
||||||
{
|
|
||||||
if (PowerPC::GetState() != PowerPC::CPU_RUNNING)
|
|
||||||
return;
|
|
||||||
|
|
||||||
fakeDec -= cyclesExecuted;
|
|
||||||
u64 timebase_ticks = CoreTiming::GetTicks() / TIMER_RATIO;
|
|
||||||
*(u64*)&TL = timebase_ticks + startTimeBaseTicks; //works since we are little endian and TL comes first :)
|
|
||||||
if (fakeDec >= 0)
|
|
||||||
PowerPC::ppcState.spr[SPR_DEC] = (u32)fakeDec / TIMER_RATIO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 GetFakeDecrementer()
|
||||||
|
{
|
||||||
|
return (fakeDecStartValue - (u32)((CoreTiming::GetTicks() - fakeDecStartTicks) / TIMER_RATIO));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeBaseSet()
|
||||||
|
{
|
||||||
|
fakeTBStartTicks = CoreTiming::GetTicks();
|
||||||
|
fakeTBStartValue = *((u64 *)&TL);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 GetFakeTimeBase()
|
||||||
|
{
|
||||||
|
return fakeTBStartValue + ((CoreTiming::GetTicks() - fakeTBStartTicks) / TIMER_RATIO);
|
||||||
|
}
|
||||||
|
|
||||||
// For DC watchdog hack
|
// For DC watchdog hack
|
||||||
void FakeGPWatchdogCallback(u64 userdata, int cyclesLate)
|
void FakeGPWatchdogCallback(u64 userdata, int cyclesLate)
|
||||||
|
@ -273,7 +281,11 @@ void Init()
|
||||||
|
|
||||||
Common::Timer::IncreaseResolution();
|
Common::Timer::IncreaseResolution();
|
||||||
// store and convert localtime at boot to timebase ticks
|
// store and convert localtime at boot to timebase ticks
|
||||||
startTimeBaseTicks = (u64)(CPU_CORE_CLOCK / TIMER_RATIO) * (u64)CEXIIPL::GetGCTime();
|
fakeTBStartValue = (u64)(CPU_CORE_CLOCK / TIMER_RATIO) * (u64)CEXIIPL::GetGCTime();
|
||||||
|
fakeTBStartTicks = CoreTiming::GetTicks();
|
||||||
|
|
||||||
|
fakeDecStartValue = 0xFFFFFFFF;
|
||||||
|
u64 fakeDecStartTicks = CoreTiming::GetTicks();
|
||||||
|
|
||||||
et_Dec = CoreTiming::RegisterEvent("DecCallback", DecrementerCallback);
|
et_Dec = CoreTiming::RegisterEvent("DecCallback", DecrementerCallback);
|
||||||
et_AI = CoreTiming::RegisterEvent("AICallback", AICallback);
|
et_AI = CoreTiming::RegisterEvent("AICallback", AICallback);
|
||||||
|
@ -300,8 +312,6 @@ void Init()
|
||||||
|
|
||||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
||||||
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD, et_IPC_HLE);
|
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD, et_IPC_HLE);
|
||||||
|
|
||||||
CoreTiming::RegisterAdvanceCallback(&AdvanceCallback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
|
|
|
@ -29,6 +29,10 @@ void Shutdown();
|
||||||
|
|
||||||
// Notify timing system that somebody wrote to the decrementer
|
// Notify timing system that somebody wrote to the decrementer
|
||||||
void DecrementerSet();
|
void DecrementerSet();
|
||||||
|
u32 GetFakeDecrementer();
|
||||||
|
|
||||||
|
void TimeBaseSet();
|
||||||
|
u64 GetFakeTimeBase();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -263,9 +263,8 @@ void Interpreter::mtsrin(UGeckoInstruction _inst)
|
||||||
void Interpreter::mftb(UGeckoInstruction _inst)
|
void Interpreter::mftb(UGeckoInstruction _inst)
|
||||||
{
|
{
|
||||||
int iIndex = (_inst.TBR >> 5) | ((_inst.TBR & 0x1F) << 5);
|
int iIndex = (_inst.TBR >> 5) | ((_inst.TBR & 0x1F) << 5);
|
||||||
if (iIndex == SPR_TL) m_GPR[_inst.RD] = TL;
|
_dbg_assert_msg_(POWERPC, (iIndex == SPR_TL) || (iIndex == SPR_TU), "Invalid mftb");
|
||||||
else if (iIndex == SPR_TU) m_GPR[_inst.RD] = TU;
|
mfspr(_inst);
|
||||||
else _dbg_assert_(POWERPC, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -279,9 +278,18 @@ void Interpreter::mfspr(UGeckoInstruction _inst)
|
||||||
|
|
||||||
switch (iIndex)
|
switch (iIndex)
|
||||||
{
|
{
|
||||||
//case SPR_DEC:
|
case SPR_DEC:
|
||||||
// MessageBox(NULL, "Read from DEC", "????", MB_OK);
|
if ((rSPR(iIndex) & 0x80000000) == 0) // We are still decrementing
|
||||||
// break;
|
{
|
||||||
|
rSPR(iIndex) = SystemTimers::GetFakeDecrementer();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPR_TL:
|
||||||
|
case SPR_TU:
|
||||||
|
*((u64 *)&TL) = SystemTimers::GetFakeTimeBase(); //works since we are little endian and TL comes first :)
|
||||||
|
break;
|
||||||
|
|
||||||
case SPR_WPAR:
|
case SPR_WPAR:
|
||||||
{
|
{
|
||||||
// If wpar_empty ever is false, Paper Mario hangs. Strange.
|
// If wpar_empty ever is false, Paper Mario hangs. Strange.
|
||||||
|
@ -318,10 +326,12 @@ void Interpreter::mtspr(UGeckoInstruction _inst)
|
||||||
|
|
||||||
case SPR_TL_W:
|
case SPR_TL_W:
|
||||||
TL = m_GPR[_inst.RD];
|
TL = m_GPR[_inst.RD];
|
||||||
|
SystemTimers::TimeBaseSet();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPR_TU_W:
|
case SPR_TU_W:
|
||||||
TU = m_GPR[_inst.RD];
|
TU = m_GPR[_inst.RD];
|
||||||
|
SystemTimers::TimeBaseSet();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPR_HID0: // HID0
|
case SPR_HID0: // HID0
|
||||||
|
@ -416,10 +426,7 @@ void Interpreter::mtspr(UGeckoInstruction _inst)
|
||||||
PanicAlert("Interesting - Software triggered Decrementer exception");
|
PanicAlert("Interesting - Software triggered Decrementer exception");
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DECREMENTER);
|
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DECREMENTER);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
SystemTimers::DecrementerSet();
|
SystemTimers::DecrementerSet();
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Page table base etc
|
// Page table base etc
|
||||||
|
|
|
@ -90,15 +90,11 @@ void Jit64::mfspr(UGeckoInstruction inst)
|
||||||
switch (iIndex)
|
switch (iIndex)
|
||||||
{
|
{
|
||||||
case SPR_WPAR:
|
case SPR_WPAR:
|
||||||
Default(inst);
|
case SPR_DEC:
|
||||||
return;
|
|
||||||
// case SPR_DEC:
|
|
||||||
//MessageBox(NULL, "Read from DEC", "????", MB_OK);
|
|
||||||
//break;
|
|
||||||
case SPR_TL:
|
case SPR_TL:
|
||||||
case SPR_TU:
|
case SPR_TU:
|
||||||
//CALL((void Jit64::*)&CoreTiming::Advance);
|
Default(inst);
|
||||||
// fall through
|
return;
|
||||||
default:
|
default:
|
||||||
gpr.Lock(d);
|
gpr.Lock(d);
|
||||||
gpr.BindToRegister(d, false);
|
gpr.BindToRegister(d, false);
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "../HW/CPU.h"
|
#include "../HW/CPU.h"
|
||||||
#include "../Core.h"
|
#include "../Core.h"
|
||||||
#include "../CoreTiming.h"
|
#include "../CoreTiming.h"
|
||||||
|
#include "../HW/SystemTimers.h"
|
||||||
|
|
||||||
#include "Interpreter/Interpreter.h"
|
#include "Interpreter/Interpreter.h"
|
||||||
#include "JitCommon/JitBase.h"
|
#include "JitCommon/JitBase.h"
|
||||||
|
@ -73,7 +74,13 @@ void ExpandCR()
|
||||||
|
|
||||||
void DoState(PointerWrap &p)
|
void DoState(PointerWrap &p)
|
||||||
{
|
{
|
||||||
|
rSPR(SPR_DEC) = SystemTimers::GetFakeDecrementer();
|
||||||
|
*((u64 *)&TL) = SystemTimers::GetFakeTimeBase(); //works since we are little endian and TL comes first :)
|
||||||
|
|
||||||
p.Do(ppcState);
|
p.Do(ppcState);
|
||||||
|
|
||||||
|
SystemTimers::DecrementerSet();
|
||||||
|
SystemTimers::TimeBaseSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetRegisters()
|
void ResetRegisters()
|
||||||
|
@ -110,10 +117,12 @@ void ResetRegisters()
|
||||||
|
|
||||||
TL = 0;
|
TL = 0;
|
||||||
TU = 0;
|
TU = 0;
|
||||||
|
SystemTimers::TimeBaseSet();
|
||||||
|
|
||||||
// MSR should be 0x40, but we don't emulate BS1, so it would never be turned off :}
|
// MSR should be 0x40, but we don't emulate BS1, so it would never be turned off :}
|
||||||
ppcState.msr = 0;
|
ppcState.msr = 0;
|
||||||
rDEC = 0xFFFFFFFF;
|
rDEC = 0xFFFFFFFF;
|
||||||
|
SystemTimers::DecrementerSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(int cpu_core)
|
void Init(int cpu_core)
|
||||||
|
|
Loading…
Reference in New Issue