SPU LLVM: Subtract Timebase from decrementer

This commit is contained in:
Elad 2025-03-08 18:49:36 +02:00
parent a3d2e93b14
commit 5e4637e15c
3 changed files with 14 additions and 10 deletions

View file

@ -5,6 +5,7 @@
#include "Emu/system_config.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/timers.hpp"
#include "Emu/Cell/lv2/sys_time.h"
#include "Emu/Memory/vm_reservation.h"
#include "Emu/RSX/Core/RSXReservationLock.hpp"
#include "Crypto/sha1.h"
@ -3482,13 +3483,13 @@ public:
#if defined(ARCH_X64)
if (utils::get_tsc_freq() && !(g_cfg.core.spu_loop_detection) && (g_cfg.core.clocks_scale == 100))
{
const auto timebase_offs = m_ir->CreateLoad(get_type<u64>(), m_ir->CreateIntToPtr(m_ir->getInt64(reinterpret_cast<u64>(&g_timebase_offs)), get_type<u64*>()));
const auto timestamp = m_ir->CreateLoad(get_type<u64>(), spu_ptr<u64>(&spu_thread::ch_dec_start_timestamp));
const auto dec_value = m_ir->CreateLoad(get_type<u32>(), spu_ptr<u32>(&spu_thread::ch_dec_value));
const auto tsc = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_rdtsc));
const auto tscx = m_ir->CreateMul(m_ir->CreateUDiv(tsc, m_ir->getInt64(utils::get_tsc_freq())), m_ir->getInt64(80000000));
const auto tscm = m_ir->CreateUDiv(m_ir->CreateMul(m_ir->CreateURem(tsc, m_ir->getInt64(utils::get_tsc_freq())), m_ir->getInt64(80000000)), m_ir->getInt64(utils::get_tsc_freq()));
const auto tsctb = m_ir->CreateAdd(tscx, tscm);
const auto tsctb = m_ir->CreateSub(m_ir->CreateAdd(tscx, tscm), timebase_offs);
const auto frz = m_ir->CreateLoad(get_type<u8>(), spu_ptr<u8>(&spu_thread::is_dec_frozen));
const auto frzev = m_ir->CreateICmpEQ(frz, m_ir->getInt8(0));
@ -4305,10 +4306,11 @@ public:
#if defined(ARCH_X64)
if (utils::get_tsc_freq() && !(g_cfg.core.spu_loop_detection) && (g_cfg.core.clocks_scale == 100))
{
const auto timebase_offs = m_ir->CreateLoad(get_type<u64>(), m_ir->CreateIntToPtr(m_ir->getInt64(reinterpret_cast<u64>(&g_timebase_offs)), get_type<u64*>()));
const auto tsc = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_rdtsc));
const auto tscx = m_ir->CreateMul(m_ir->CreateUDiv(tsc, m_ir->getInt64(utils::get_tsc_freq())), m_ir->getInt64(80000000));
const auto tscm = m_ir->CreateUDiv(m_ir->CreateMul(m_ir->CreateURem(tsc, m_ir->getInt64(utils::get_tsc_freq())), m_ir->getInt64(80000000)), m_ir->getInt64(utils::get_tsc_freq()));
const auto tsctb = m_ir->CreateAdd(tscx, tscm);
const auto tsctb = m_ir->CreateSub(m_ir->CreateAdd(tscx, tscm), timebase_offs);
m_ir->CreateStore(tsctb, spu_ptr<u64>(&spu_thread::ch_dec_start_timestamp));
}
else

View file

@ -9,7 +9,7 @@
#include "util/sysinfo.hpp"
static u64 timebase_offset;
u64 g_timebase_offs{};
static u64 systemtime_offset;
#ifndef __linux__
@ -145,8 +145,8 @@ static constexpr u64 g_timebase_freq = /*79800000*/ 80000000ull; // 80 Mhz
u64 convert_to_timebased_time(u64 time)
{
const u64 result = time * (g_timebase_freq / 1000000ull) * g_cfg.core.clocks_scale / 100u;
ensure(result >= timebase_offset);
return result - timebase_offset;
ensure(result >= g_timebase_offs);
return result - g_timebase_offs;
}
u64 get_timebased_time()
@ -160,7 +160,7 @@ u64 get_timebased_time()
#else
const u64 result = (tsc / freq * g_timebase_freq + tsc % freq * g_timebase_freq / freq) * g_cfg.core.clocks_scale / 100u;
#endif
return result - timebase_offset;
return result - g_timebase_offs;
}
while (true)
@ -183,7 +183,7 @@ u64 get_timebased_time()
const u64 result = (static_cast<u64>(ts.tv_sec) * g_timebase_freq + static_cast<u64>(ts.tv_nsec) * g_timebase_freq / 1000000000ull) * g_cfg.core.clocks_scale / 100u;
#endif
if (result) return result - timebase_offset;
if (result) return result - g_timebase_offs;
}
}
@ -192,7 +192,7 @@ u64 get_timebased_time()
// If none-zero arg is specified it will become the base time (for savestates)
void initialize_timebased_time(u64 timebased_init, bool reset)
{
timebase_offset = 0;
g_timebase_offs = 0;
if (reset)
{
@ -204,7 +204,7 @@ void initialize_timebased_time(u64 timebased_init, bool reset)
const u64 current = get_timebased_time();
timebased_init = current - timebased_init;
timebase_offset = timebased_init;
g_timebase_offs = timebased_init;
systemtime_offset = timebased_init / (g_timebase_freq / 1000000);
}

View file

@ -11,3 +11,5 @@ error_code sys_time_get_current_time(vm::ptr<s64> sec, vm::ptr<s64> nsec);
error_code sys_time_set_current_time(s64 sec, s64 nsec);
u64 sys_time_get_timebase_frequency();
error_code sys_time_get_rtc(vm::ptr<u64> rtc);
extern u64 g_timebase_offs;