CoreTiming: Cleanup naming conventions
This commit is contained in:
parent
da82389347
commit
b88b188819
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
@ -20,8 +21,6 @@
|
|||
#include "VideoCommon/Fifo.h"
|
||||
#include "VideoCommon/VideoBackendBase.h"
|
||||
|
||||
#define MAX_SLICE_LENGTH 20000
|
||||
|
||||
namespace CoreTiming
|
||||
{
|
||||
struct EventType
|
||||
|
@ -30,7 +29,7 @@ struct EventType
|
|||
std::string name;
|
||||
};
|
||||
|
||||
static std::vector<EventType> event_types;
|
||||
static std::vector<EventType> s_event_types;
|
||||
|
||||
struct BaseEvent
|
||||
{
|
||||
|
@ -42,45 +41,45 @@ struct BaseEvent
|
|||
typedef LinkedListItem<BaseEvent> Event;
|
||||
|
||||
// STATE_TO_SAVE
|
||||
static Event* first;
|
||||
static std::mutex tsWriteLock;
|
||||
static Common::FifoQueue<BaseEvent, false> tsQueue;
|
||||
static Event* s_first_event;
|
||||
static std::mutex s_ts_write_lock;
|
||||
static Common::FifoQueue<BaseEvent, false> s_ts_queue;
|
||||
|
||||
// event pools
|
||||
static Event* eventPool = nullptr;
|
||||
static Event* s_event_pool = nullptr;
|
||||
|
||||
static float s_lastOCFactor;
|
||||
float g_lastOCFactor_inverted;
|
||||
int g_slicelength;
|
||||
static int maxslicelength = MAX_SLICE_LENGTH;
|
||||
static float s_last_OC_factor;
|
||||
float g_last_OC_factor_inverted;
|
||||
int g_slice_length;
|
||||
static constexpr int MAX_SLICE_LENGTH = 20000;
|
||||
|
||||
static s64 idledCycles;
|
||||
static u32 fakeDecStartValue;
|
||||
static u64 fakeDecStartTicks;
|
||||
static s64 s_idled_cycles;
|
||||
static u32 s_fake_dec_start_value;
|
||||
static u64 s_fake_dec_start_ticks;
|
||||
|
||||
// Are we in a function that has been called from Advance()
|
||||
static bool globalTimerIsSane;
|
||||
static bool s_is_global_timer_sane;
|
||||
|
||||
s64 g_globalTimer;
|
||||
u64 g_fakeTBStartValue;
|
||||
u64 g_fakeTBStartTicks;
|
||||
s64 g_global_timer;
|
||||
u64 g_fake_TB_start_value;
|
||||
u64 g_fake_TB_start_ticks;
|
||||
|
||||
static int ev_lost;
|
||||
static int s_ev_lost;
|
||||
|
||||
static Event* GetNewEvent()
|
||||
{
|
||||
if (!eventPool)
|
||||
if (!s_event_pool)
|
||||
return new Event;
|
||||
|
||||
Event* ev = eventPool;
|
||||
eventPool = ev->next;
|
||||
Event* ev = s_event_pool;
|
||||
s_event_pool = ev->next;
|
||||
return ev;
|
||||
}
|
||||
|
||||
static void FreeEvent(Event* ev)
|
||||
{
|
||||
ev->next = eventPool;
|
||||
eventPool = ev;
|
||||
ev->next = s_event_pool;
|
||||
s_event_pool = ev;
|
||||
}
|
||||
|
||||
static void EmptyTimedCallback(u64 userdata, s64 cyclesLate)
|
||||
|
@ -96,12 +95,12 @@ static void EmptyTimedCallback(u64 userdata, s64 cyclesLate)
|
|||
// but the effect is largely the same.
|
||||
static int DowncountToCycles(int downcount)
|
||||
{
|
||||
return (int)(downcount * g_lastOCFactor_inverted);
|
||||
return static_cast<int>(downcount * g_last_OC_factor_inverted);
|
||||
}
|
||||
|
||||
static int CyclesToDowncount(int cycles)
|
||||
{
|
||||
return (int)(cycles * s_lastOCFactor);
|
||||
return static_cast<int>(cycles * s_last_OC_factor);
|
||||
}
|
||||
|
||||
int RegisterEvent(const std::string& name, TimedCallback callback)
|
||||
|
@ -112,7 +111,7 @@ int RegisterEvent(const std::string& name, TimedCallback callback)
|
|||
|
||||
// check for existing type with same name.
|
||||
// we want event type names to remain unique so that we can use them for serialization.
|
||||
for (auto& event_type : event_types)
|
||||
for (auto& event_type : s_event_types)
|
||||
{
|
||||
if (name == event_type.name)
|
||||
{
|
||||
|
@ -127,41 +126,41 @@ int RegisterEvent(const std::string& name, TimedCallback callback)
|
|||
}
|
||||
}
|
||||
|
||||
event_types.push_back(type);
|
||||
return (int)event_types.size() - 1;
|
||||
s_event_types.push_back(type);
|
||||
return static_cast<int>(s_event_types.size() - 1);
|
||||
}
|
||||
|
||||
void UnregisterAllEvents()
|
||||
{
|
||||
if (first)
|
||||
if (s_first_event)
|
||||
PanicAlert("Cannot unregister events with events pending");
|
||||
event_types.clear();
|
||||
s_event_types.clear();
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
s_lastOCFactor = SConfig::GetInstance().m_OCEnable ? SConfig::GetInstance().m_OCFactor : 1.0f;
|
||||
g_lastOCFactor_inverted = 1.0f / s_lastOCFactor;
|
||||
PowerPC::ppcState.downcount = CyclesToDowncount(maxslicelength);
|
||||
g_slicelength = maxslicelength;
|
||||
g_globalTimer = 0;
|
||||
idledCycles = 0;
|
||||
globalTimerIsSane = true;
|
||||
s_last_OC_factor = SConfig::GetInstance().m_OCEnable ? SConfig::GetInstance().m_OCFactor : 1.0f;
|
||||
g_last_OC_factor_inverted = 1.0f / s_last_OC_factor;
|
||||
PowerPC::ppcState.downcount = CyclesToDowncount(MAX_SLICE_LENGTH);
|
||||
g_slice_length = MAX_SLICE_LENGTH;
|
||||
g_global_timer = 0;
|
||||
s_idled_cycles = 0;
|
||||
s_is_global_timer_sane = true;
|
||||
|
||||
ev_lost = RegisterEvent("_lost_event", &EmptyTimedCallback);
|
||||
s_ev_lost = RegisterEvent("_lost_event", &EmptyTimedCallback);
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(tsWriteLock);
|
||||
std::lock_guard<std::mutex> lk(s_ts_write_lock);
|
||||
MoveEvents();
|
||||
ClearPendingEvents();
|
||||
UnregisterAllEvents();
|
||||
|
||||
while (eventPool)
|
||||
while (s_event_pool)
|
||||
{
|
||||
Event* ev = eventPool;
|
||||
eventPool = ev->next;
|
||||
Event* ev = s_event_pool;
|
||||
s_event_pool = ev->next;
|
||||
delete ev;
|
||||
}
|
||||
}
|
||||
|
@ -178,15 +177,15 @@ static void EventDoState(PointerWrap& p, BaseEvent* ev)
|
|||
// so, we savestate the event's type's name, and derive ev->type from that when loading.
|
||||
std::string name;
|
||||
if (p.GetMode() != PointerWrap::MODE_READ)
|
||||
name = event_types[ev->type].name;
|
||||
name = s_event_types[ev->type].name;
|
||||
|
||||
p.Do(name);
|
||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||
{
|
||||
bool foundMatch = false;
|
||||
for (unsigned int i = 0; i < event_types.size(); ++i)
|
||||
for (unsigned int i = 0; i < s_event_types.size(); ++i)
|
||||
{
|
||||
if (name == event_types[i].name)
|
||||
if (name == s_event_types[i].name)
|
||||
{
|
||||
ev->type = i;
|
||||
foundMatch = true;
|
||||
|
@ -198,30 +197,29 @@ static void EventDoState(PointerWrap& p, BaseEvent* ev)
|
|||
WARN_LOG(POWERPC,
|
||||
"Lost event from savestate because its type, \"%s\", has not been registered.",
|
||||
name.c_str());
|
||||
ev->type = ev_lost;
|
||||
ev->type = s_ev_lost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoState(PointerWrap& p)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(tsWriteLock);
|
||||
p.Do(g_slicelength);
|
||||
p.Do(g_globalTimer);
|
||||
p.Do(idledCycles);
|
||||
p.Do(fakeDecStartValue);
|
||||
p.Do(fakeDecStartTicks);
|
||||
p.Do(g_fakeTBStartValue);
|
||||
p.Do(g_fakeTBStartTicks);
|
||||
p.Do(s_lastOCFactor);
|
||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||
g_lastOCFactor_inverted = 1.0f / s_lastOCFactor;
|
||||
std::lock_guard<std::mutex> lk(s_ts_write_lock);
|
||||
p.Do(g_slice_length);
|
||||
p.Do(g_global_timer);
|
||||
p.Do(s_idled_cycles);
|
||||
p.Do(s_fake_dec_start_value);
|
||||
p.Do(s_fake_dec_start_ticks);
|
||||
p.Do(g_fake_TB_start_value);
|
||||
p.Do(g_fake_TB_start_ticks);
|
||||
p.Do(s_last_OC_factor);
|
||||
g_last_OC_factor_inverted = 1.0f / s_last_OC_factor;
|
||||
|
||||
p.DoMarker("CoreTimingData");
|
||||
|
||||
MoveEvents();
|
||||
|
||||
p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, EventDoState>(first);
|
||||
p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, EventDoState>(s_first_event);
|
||||
p.DoMarker("CoreTimingEvents");
|
||||
}
|
||||
|
||||
|
@ -229,34 +227,34 @@ void DoState(PointerWrap& p)
|
|||
// it from any other thread, you are doing something evil
|
||||
u64 GetTicks()
|
||||
{
|
||||
u64 ticks = (u64)g_globalTimer;
|
||||
if (!globalTimerIsSane)
|
||||
u64 ticks = static_cast<u64>(g_global_timer);
|
||||
if (!s_is_global_timer_sane)
|
||||
{
|
||||
int downcount = DowncountToCycles(PowerPC::ppcState.downcount);
|
||||
ticks += g_slicelength - downcount;
|
||||
ticks += g_slice_length - downcount;
|
||||
}
|
||||
return ticks;
|
||||
}
|
||||
|
||||
u64 GetIdleTicks()
|
||||
{
|
||||
return (u64)idledCycles;
|
||||
return static_cast<u64>(s_idled_cycles);
|
||||
}
|
||||
|
||||
void ClearPendingEvents()
|
||||
{
|
||||
while (first)
|
||||
while (s_first_event)
|
||||
{
|
||||
Event* e = first->next;
|
||||
FreeEvent(first);
|
||||
first = e;
|
||||
Event* e = s_first_event->next;
|
||||
FreeEvent(s_first_event);
|
||||
s_first_event = e;
|
||||
}
|
||||
}
|
||||
|
||||
static void AddEventToQueue(Event* ne)
|
||||
{
|
||||
Event* prev = nullptr;
|
||||
Event** pNext = &first;
|
||||
Event** pNext = &s_first_event;
|
||||
for (;;)
|
||||
{
|
||||
Event*& next = *pNext;
|
||||
|
@ -293,7 +291,7 @@ void ScheduleEvent(s64 cycles_into_future, int event_type, u64 userdata, FromThr
|
|||
ne->type = event_type;
|
||||
|
||||
// If this event needs to be scheduled before the next advance(), force one early
|
||||
if (!globalTimerIsSane)
|
||||
if (!s_is_global_timer_sane)
|
||||
ForceExceptionCheck(cycles_into_future);
|
||||
|
||||
AddEventToQueue(ne);
|
||||
|
@ -304,31 +302,31 @@ void ScheduleEvent(s64 cycles_into_future, int event_type, u64 userdata, FromThr
|
|||
{
|
||||
ERROR_LOG(POWERPC, "Someone scheduled an off-thread \"%s\" event while netplay or "
|
||||
"movie play/record was active. This is likely to cause a desync.",
|
||||
event_types[event_type].name.c_str());
|
||||
s_event_types[event_type].name.c_str());
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lk(tsWriteLock);
|
||||
std::lock_guard<std::mutex> lk(s_ts_write_lock);
|
||||
Event ne;
|
||||
ne.time = g_globalTimer + cycles_into_future;
|
||||
ne.time = g_global_timer + cycles_into_future;
|
||||
ne.type = event_type;
|
||||
ne.userdata = userdata;
|
||||
tsQueue.Push(ne);
|
||||
s_ts_queue.Push(ne);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveEvent(int event_type)
|
||||
{
|
||||
while (first && first->type == event_type)
|
||||
while (s_first_event && s_first_event->type == event_type)
|
||||
{
|
||||
Event* next = first->next;
|
||||
FreeEvent(first);
|
||||
first = next;
|
||||
Event* next = s_first_event->next;
|
||||
FreeEvent(s_first_event);
|
||||
s_first_event = next;
|
||||
}
|
||||
|
||||
if (!first)
|
||||
if (!s_first_event)
|
||||
return;
|
||||
|
||||
Event* prev = first;
|
||||
Event* prev = s_first_event;
|
||||
Event* ptr = prev->next;
|
||||
while (ptr)
|
||||
{
|
||||
|
@ -354,20 +352,19 @@ void RemoveAllEvents(int event_type)
|
|||
|
||||
void ForceExceptionCheck(s64 cycles)
|
||||
{
|
||||
if (s64(DowncountToCycles(PowerPC::ppcState.downcount)) > cycles)
|
||||
if (DowncountToCycles(PowerPC::ppcState.downcount) > cycles)
|
||||
{
|
||||
// downcount is always (much) smaller than MAX_INT so we can safely cast cycles to an int here.
|
||||
g_slicelength -=
|
||||
(DowncountToCycles(PowerPC::ppcState.downcount) -
|
||||
(int)cycles); // Account for cycles already executed by adjusting the g_slicelength
|
||||
PowerPC::ppcState.downcount = CyclesToDowncount((int)cycles);
|
||||
// Account for cycles already executed by adjusting the g_slice_length
|
||||
g_slice_length -= (DowncountToCycles(PowerPC::ppcState.downcount) - static_cast<int>(cycles));
|
||||
PowerPC::ppcState.downcount = CyclesToDowncount(static_cast<int>(cycles));
|
||||
}
|
||||
}
|
||||
|
||||
void MoveEvents()
|
||||
{
|
||||
BaseEvent sevt;
|
||||
while (tsQueue.Pop(sevt))
|
||||
while (s_ts_queue.Pop(sevt))
|
||||
{
|
||||
Event* evt = GetNewEvent();
|
||||
evt->time = sevt.time;
|
||||
|
@ -381,35 +378,35 @@ void Advance()
|
|||
{
|
||||
MoveEvents();
|
||||
|
||||
int cyclesExecuted = g_slicelength - DowncountToCycles(PowerPC::ppcState.downcount);
|
||||
g_globalTimer += cyclesExecuted;
|
||||
s_lastOCFactor = SConfig::GetInstance().m_OCEnable ? SConfig::GetInstance().m_OCFactor : 1.0f;
|
||||
g_lastOCFactor_inverted = 1.0f / s_lastOCFactor;
|
||||
g_slicelength = maxslicelength;
|
||||
int cyclesExecuted = g_slice_length - DowncountToCycles(PowerPC::ppcState.downcount);
|
||||
g_global_timer += cyclesExecuted;
|
||||
s_last_OC_factor = SConfig::GetInstance().m_OCEnable ? SConfig::GetInstance().m_OCFactor : 1.0f;
|
||||
g_last_OC_factor_inverted = 1.0f / s_last_OC_factor;
|
||||
g_slice_length = MAX_SLICE_LENGTH;
|
||||
|
||||
globalTimerIsSane = true;
|
||||
s_is_global_timer_sane = true;
|
||||
|
||||
while (first && first->time <= g_globalTimer)
|
||||
while (s_first_event && s_first_event->time <= g_global_timer)
|
||||
{
|
||||
// LOG(POWERPC, "[Scheduler] %s (%lld, %lld) ",
|
||||
// event_types[first->type].name ? event_types[first->type].name : "?",
|
||||
// (u64)g_globalTimer, (u64)first->time);
|
||||
Event* evt = first;
|
||||
first = first->next;
|
||||
event_types[evt->type].callback(evt->userdata, (int)(g_globalTimer - evt->time));
|
||||
// s_event_types[s_first_event->type].name ? s_event_types[s_first_event->type].name
|
||||
// : "?",
|
||||
// (u64)g_global_timer, (u64)s_first_event->time);
|
||||
Event* evt = s_first_event;
|
||||
s_first_event = s_first_event->next;
|
||||
s_event_types[evt->type].callback(evt->userdata, g_global_timer - evt->time);
|
||||
FreeEvent(evt);
|
||||
}
|
||||
|
||||
globalTimerIsSane = false;
|
||||
s_is_global_timer_sane = false;
|
||||
|
||||
if (first)
|
||||
if (s_first_event)
|
||||
{
|
||||
g_slicelength = (int)(first->time - g_globalTimer);
|
||||
if (g_slicelength > maxslicelength)
|
||||
g_slicelength = maxslicelength;
|
||||
g_slice_length =
|
||||
static_cast<int>(std::min<s64>(s_first_event->time - g_global_timer, MAX_SLICE_LENGTH));
|
||||
}
|
||||
|
||||
PowerPC::ppcState.downcount = CyclesToDowncount(g_slicelength);
|
||||
PowerPC::ppcState.downcount = CyclesToDowncount(g_slice_length);
|
||||
|
||||
// Check for any external exceptions.
|
||||
// It's important to do this after processing events otherwise any exceptions will be delayed
|
||||
|
@ -420,10 +417,10 @@ void Advance()
|
|||
|
||||
void LogPendingEvents()
|
||||
{
|
||||
Event* ptr = first;
|
||||
Event* ptr = s_first_event;
|
||||
while (ptr)
|
||||
{
|
||||
INFO_LOG(POWERPC, "PENDING: Now: %" PRId64 " Pending: %" PRId64 " Type: %d", g_globalTimer,
|
||||
INFO_LOG(POWERPC, "PENDING: Now: %" PRId64 " Pending: %" PRId64 " Type: %d", g_global_timer,
|
||||
ptr->time, ptr->type);
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
@ -439,22 +436,22 @@ void Idle()
|
|||
Fifo::FlushGpu();
|
||||
}
|
||||
|
||||
idledCycles += DowncountToCycles(PowerPC::ppcState.downcount);
|
||||
s_idled_cycles += DowncountToCycles(PowerPC::ppcState.downcount);
|
||||
PowerPC::ppcState.downcount = 0;
|
||||
}
|
||||
|
||||
std::string GetScheduledEventsSummary()
|
||||
{
|
||||
Event* ptr = first;
|
||||
Event* ptr = s_first_event;
|
||||
std::string text = "Scheduled events\n";
|
||||
text.reserve(1000);
|
||||
while (ptr)
|
||||
{
|
||||
unsigned int t = ptr->type;
|
||||
if (t >= event_types.size())
|
||||
if (t >= s_event_types.size())
|
||||
PanicAlertT("Invalid event type %i", t);
|
||||
|
||||
const std::string& name = event_types[ptr->type].name;
|
||||
const std::string& name = s_event_types[ptr->type].name;
|
||||
|
||||
text += StringFromFormat("%s : %" PRIi64 " %016" PRIx64 "\n", name.c_str(), ptr->time,
|
||||
ptr->userdata);
|
||||
|
@ -465,42 +462,42 @@ std::string GetScheduledEventsSummary()
|
|||
|
||||
u32 GetFakeDecStartValue()
|
||||
{
|
||||
return fakeDecStartValue;
|
||||
return s_fake_dec_start_value;
|
||||
}
|
||||
|
||||
void SetFakeDecStartValue(u32 val)
|
||||
{
|
||||
fakeDecStartValue = val;
|
||||
s_fake_dec_start_value = val;
|
||||
}
|
||||
|
||||
u64 GetFakeDecStartTicks()
|
||||
{
|
||||
return fakeDecStartTicks;
|
||||
return s_fake_dec_start_ticks;
|
||||
}
|
||||
|
||||
void SetFakeDecStartTicks(u64 val)
|
||||
{
|
||||
fakeDecStartTicks = val;
|
||||
s_fake_dec_start_ticks = val;
|
||||
}
|
||||
|
||||
u64 GetFakeTBStartValue()
|
||||
{
|
||||
return g_fakeTBStartValue;
|
||||
return g_fake_TB_start_value;
|
||||
}
|
||||
|
||||
void SetFakeTBStartValue(u64 val)
|
||||
{
|
||||
g_fakeTBStartValue = val;
|
||||
g_fake_TB_start_value = val;
|
||||
}
|
||||
|
||||
u64 GetFakeTBStartTicks()
|
||||
{
|
||||
return g_fakeTBStartTicks;
|
||||
return g_fake_TB_start_ticks;
|
||||
}
|
||||
|
||||
void SetFakeTBStartTicks(u64 val)
|
||||
{
|
||||
g_fakeTBStartTicks = val;
|
||||
g_fake_TB_start_ticks = val;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -25,11 +25,11 @@ class PointerWrap;
|
|||
namespace CoreTiming
|
||||
{
|
||||
// These really shouldn't be global, but jit64 accesses them directly
|
||||
extern s64 g_globalTimer;
|
||||
extern u64 g_fakeTBStartValue;
|
||||
extern u64 g_fakeTBStartTicks;
|
||||
extern int g_slicelength;
|
||||
extern float g_lastOCFactor_inverted;
|
||||
extern s64 g_global_timer;
|
||||
extern u64 g_fake_TB_start_value;
|
||||
extern u64 g_fake_TB_start_ticks;
|
||||
extern int g_slice_length;
|
||||
extern float g_last_OC_factor_inverted;
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
|
|
@ -198,7 +198,7 @@ void Interpreter::SingleStep()
|
|||
{
|
||||
SingleStepInner();
|
||||
|
||||
CoreTiming::g_slicelength = 1;
|
||||
CoreTiming::g_slice_length = 1;
|
||||
PowerPC::ppcState.downcount = 0;
|
||||
CoreTiming::Advance();
|
||||
|
||||
|
|
|
@ -286,13 +286,13 @@ void Jit64::mfspr(UGeckoInstruction inst)
|
|||
// cost of calling out to C for this is actually significant.
|
||||
// Scale downcount by the CPU overclocking factor.
|
||||
CVTSI2SS(XMM0, PPCSTATE(downcount));
|
||||
MULSS(XMM0, M(&CoreTiming::g_lastOCFactor_inverted));
|
||||
MULSS(XMM0, M(&CoreTiming::g_last_OC_factor_inverted));
|
||||
CVTSS2SI(RDX, R(XMM0)); // RDX is downcount scaled by the overclocking factor
|
||||
MOV(32, R(RAX), M(&CoreTiming::g_slicelength));
|
||||
MOV(32, R(RAX), M(&CoreTiming::g_slice_length));
|
||||
SUB(64, R(RAX), R(RDX)); // cycles since the last CoreTiming::Advance() event is (slicelength -
|
||||
// Scaled_downcount)
|
||||
ADD(64, R(RAX), M(&CoreTiming::g_globalTimer));
|
||||
SUB(64, R(RAX), M(&CoreTiming::g_fakeTBStartTicks));
|
||||
ADD(64, R(RAX), M(&CoreTiming::g_global_timer));
|
||||
SUB(64, R(RAX), M(&CoreTiming::g_fake_TB_start_ticks));
|
||||
// It might seem convenient to correct the timer for the block position here for even more
|
||||
// accurate
|
||||
// timing, but as of currently, this can break games. If we end up reading a time *after* the
|
||||
|
@ -308,7 +308,7 @@ void Jit64::mfspr(UGeckoInstruction inst)
|
|||
// a / 12 = (a * 0xAAAAAAAAAAAAAAAB) >> 67
|
||||
MOV(64, R(RDX), Imm64(0xAAAAAAAAAAAAAAABULL));
|
||||
MUL(64, R(RDX));
|
||||
MOV(64, R(RAX), M(&CoreTiming::g_fakeTBStartValue));
|
||||
MOV(64, R(RAX), M(&CoreTiming::g_fake_TB_start_value));
|
||||
SHR(64, R(RDX), Imm8(3));
|
||||
ADD(64, R(RAX), R(RDX));
|
||||
MOV(64, PPCSTATE(spr[SPR_TL]), R(RAX));
|
||||
|
|
|
@ -234,9 +234,9 @@ void JitArm64::mfspr(UGeckoInstruction inst)
|
|||
|
||||
// An inline implementation of CoreTiming::GetFakeTimeBase, since in timer-heavy games the
|
||||
// cost of calling out to C for this is actually significant.
|
||||
MOVI2R(XA, (u64)&CoreTiming::g_globalTimer);
|
||||
MOVI2R(XA, (u64)&CoreTiming::g_global_timer);
|
||||
LDR(INDEX_UNSIGNED, XA, XA, 0);
|
||||
MOVI2R(XB, (u64)&CoreTiming::g_fakeTBStartTicks);
|
||||
MOVI2R(XB, (u64)&CoreTiming::g_fake_TB_start_ticks);
|
||||
LDR(INDEX_UNSIGNED, XB, XB, 0);
|
||||
SUB(XA, XA, XB);
|
||||
|
||||
|
@ -254,7 +254,7 @@ void JitArm64::mfspr(UGeckoInstruction inst)
|
|||
ADD(XB, XB, 1);
|
||||
UMULH(XA, XA, XB);
|
||||
|
||||
MOVI2R(XB, (u64)&CoreTiming::g_fakeTBStartValue);
|
||||
MOVI2R(XB, (u64)&CoreTiming::g_fake_TB_start_value);
|
||||
LDR(INDEX_UNSIGNED, XB, XB, 0);
|
||||
ADD(XA, XB, XA, ArithOption(XA, ST_LSR, 3));
|
||||
STR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(spr[SPR_TL]));
|
||||
|
|
Loading…
Reference in New Issue