Skip to content

Commit

Permalink
Merge pull request #1805 from nicolasnoble/64bits-counters
Browse files Browse the repository at this point in the history
Moving cycle counters to 64-bits.
  • Loading branch information
nicolasnoble authored Nov 22, 2024
2 parents 33b7ec3 + fb4eb9e commit 1587118
Show file tree
Hide file tree
Showing 11 changed files with 44 additions and 50 deletions.
6 changes: 3 additions & 3 deletions src/core/DynaRec_aa64/recompiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,9 @@ DynarecCallback DynaRecCPU::recompile(DynarecCallback* callback, uint32_t pc, bo
m_linkedPC = std::nullopt;
}

gen.Ldr(w0, MemOperand(contextPointer, CYCLE_OFFSET)); // Fetch cycle count from memory
gen.Add(w0, w0, count * PCSX::Emulator::BIAS); // Add block cycles
gen.Str(w0, MemOperand(contextPointer, CYCLE_OFFSET)); // Store cycles back to memory
gen.Ldr(x0, MemOperand(contextPointer, CYCLE_OFFSET)); // Fetch cycle count from memory
gen.Add(x0, x0, count * PCSX::Emulator::BIAS); // Add block cycles
gen.Str(x0, MemOperand(contextPointer, CYCLE_OFFSET)); // Store cycles back to memory

// Link block else return to dispatcher
if (m_linkedPC && ENABLE_BLOCK_LINKING && m_linkedPC.value() != startingPC) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/DynaRec_x64/recompiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ DynarecCallback DynaRecCPU::recompile(uint32_t pc, bool fullLoadDelayEmulation,
endProfiling();
}

gen.add(dword[contextPointer + CYCLE_OFFSET], count * PCSX::Emulator::BIAS); // Add block cycles;
gen.add(qword[contextPointer + CYCLE_OFFSET], count * PCSX::Emulator::BIAS); // Add block cycles;
if (m_linkedPC && ENABLE_BLOCK_LINKING && m_linkedPC.value() != startingPC) {
handleLinking();
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/core/DynaRec_x64/symbols.cc
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ void DynaRecCPU::makeSymbols() {
REGISTER_VARIABLE(m_regs.CP2C.r[i], COP2_controlRegs[i], 4);
}

REGISTER_VARIABLE(m_regs.cycle, "m_cycles", 4);
REGISTER_VARIABLE(m_regs.cycle, "m_cycles", 8);
REGISTER_VARIABLE(m_regs.pc, "m_pc", 4);

for (int i = 0; i < 16; i++) { // Register host register cache
Expand Down
4 changes: 3 additions & 1 deletion src/core/cdrom.cc
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,9 @@ class CDRomImpl : public PCSX::CDRom {

if (m_irqRepeated) {
m_irqRepeated = 0;
if (m_eCycle > PCSX::g_emulator->m_cpu->m_regs.cycle) {
auto &regs = PCSX::g_emulator->m_cpu->m_regs;
auto diff = regs.intTargets[PCSX::PSXINT_CDR] - regs.cycle;
if (m_eCycle > diff) {
scheduleCDIRQ(m_eCycle);
goto finish;
}
Expand Down
28 changes: 10 additions & 18 deletions src/core/psxcounters.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ inline void PCSX::Counters::writeCounterInternal(uint32_t index, uint32_t value)
}

inline uint32_t PCSX::Counters::readCounterInternal(uint32_t index) {
uint32_t count;
uint64_t count;

count = PCSX::g_emulator->m_cpu->m_regs.cycle;
count -= m_rcnts[index].cycleStart;
Expand All @@ -71,17 +71,17 @@ inline uint32_t PCSX::Counters::readCounterInternal(uint32_t index) {

void PCSX::Counters::set() {
m_psxNextCounter = PCSX::g_emulator->m_cpu->m_regs.cycle;
uint32_t next = 0x7fffffff;
uint64_t next = 0x7fffffffffffffff;

for (int i = 0; i < CounterQuantity; ++i) {
int32_t countToUpdate = m_rcnts[i].cycle - (m_psxNextCounter - m_rcnts[i].cycleStart);
int64_t countToUpdate = m_rcnts[i].cycle - (m_psxNextCounter - m_rcnts[i].cycleStart);

if (countToUpdate < 0) {
next = 0;
break;
}

if (countToUpdate < (int32_t)next) {
if (countToUpdate < (int64_t)next) {
next = countToUpdate;
}
}
Expand All @@ -90,7 +90,7 @@ void PCSX::Counters::set() {
}

void PCSX::Counters::reset(uint32_t index) {
uint32_t count;
uint64_t count;

if (m_rcnts[index].counterState == CountToTarget) {
if (m_rcnts[index].mode & RcCountToTarget) {
Expand Down Expand Up @@ -138,19 +138,11 @@ void PCSX::Counters::reset(uint32_t index) {
}

void PCSX::Counters::update() {
const uint32_t cycle = PCSX::g_emulator->m_cpu->m_regs.cycle;
const uint64_t cycle = PCSX::g_emulator->m_cpu->m_regs.cycle;

{
uint32_t prev = g_emulator->m_cpu->m_regs.previousCycles;
uint64_t diff;
if (cycle > prev) {
diff = cycle - prev;
} else {
diff = std::numeric_limits<uint32_t>::max();
diff += cycle + 1;
diff -= prev;
diff &= 0xffffffff;
}
uint64_t prev = g_emulator->m_cpu->m_regs.previousCycles;
uint64_t diff = cycle - prev;
diff *= 4410000;
diff /= g_emulator->settings.get<Emulator::SettingScaler>();
diff /= g_emulator->m_psxClockSpeed;
Expand Down Expand Up @@ -297,8 +289,8 @@ uint32_t PCSX::Counters::readCounter(uint32_t index) {
*affected).
*/
static uint32_t clast = 0xffff;
static uint32_t cylast = 0;
uint32_t count1 = count;
static uint64_t cylast = 0;
uint64_t count1 = count;
count /= PCSX::Emulator::BIAS;
verboseLog(4, "[RCNT %i] rcountpe2: %x %x %x (%u)\n", index, count, count1, clast,
(PCSX::g_emulator->m_cpu->m_regs.cycle - cylast));
Expand Down
4 changes: 2 additions & 2 deletions src/core/psxcounters.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Counters {
struct Rcnt {
uint16_t mode, target;
uint32_t rate, irq, counterState, irqState;
uint32_t cycle, cycleStart;
uint64_t cycle, cycleStart;
};

enum {
Expand Down Expand Up @@ -86,7 +86,7 @@ class Counters {

uint32_t m_HSyncTotal[PCSX::Emulator::PSX_TYPE_PAL + 1]; // 2
public:
uint32_t m_psxNextCounter;
uint64_t m_psxNextCounter;
bool m_pollSIO1 = false;
void init();
void update();
Expand Down
14 changes: 7 additions & 7 deletions src/core/r3000a.cc
Original file line number Diff line number Diff line change
Expand Up @@ -350,25 +350,25 @@ void PCSX::R3000Acpu::branchTest() {
}
#endif

const uint32_t cycle = m_regs.cycle;
const uint64_t cycle = m_regs.cycle;

if (cycle >= g_emulator->m_counters->m_psxNextCounter) g_emulator->m_counters->update();

if (m_regs.spuInterrupt.exchange(false)) g_emulator->m_spu->interrupt();

const uint32_t interrupts = m_regs.interrupt;

int32_t lowestDistance = std::numeric_limits<int32_t>::max();
uint32_t lowestTarget = cycle;
uint32_t* targets = m_regs.intTargets;
int32_t lowestDistance = std::numeric_limits<int64_t>::max();
uint64_t lowestTarget = cycle;
uint64_t* targets = m_regs.intTargets;

if ((interrupts != 0) && (((int32_t)(m_regs.lowestTarget - cycle)) <= 0)) {
if ((interrupts != 0) && (m_regs.lowestTarget < cycle)) {
#define checkAndUpdate(irq, act) \
{ \
constexpr uint32_t mask = 1 << irq; \
if ((interrupts & mask) != 0) { \
uint32_t target = targets[irq]; \
int32_t dist = target - cycle; \
uint64_t target = targets[irq]; \
int64_t dist = target - cycle; \
if (dist > 0) { \
if (lowestDistance > dist) { \
lowestDistance = dist; \
Expand Down
16 changes: 8 additions & 8 deletions src/core/r3000a.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,12 @@ struct psxRegisters {
psxCP2Ctrl CP2C; // COP2 control registers
uint32_t pc; // Program counter
uint32_t code; // The current instruction
uint32_t cycle;
uint32_t previousCycles;
uint64_t cycle;
uint64_t previousCycles;
uint32_t interrupt;
std::atomic<bool> spuInterrupt;
uint32_t intTargets[32];
uint32_t lowestTarget;
uint64_t intTargets[32];
uint64_t lowestTarget;
uint8_t iCacheAddr[0x1000];
uint8_t iCacheCode[0x1000];
};
Expand Down Expand Up @@ -317,12 +317,12 @@ class R3000Acpu {

void scheduleInterrupt(unsigned interrupt, uint32_t eCycle) {
PSXIRQ_LOG("Scheduling interrupt %08x at %08x\n", interrupt, eCycle);
const uint32_t cycle = m_regs.cycle;
uint32_t target = uint32_t(cycle + eCycle * m_interruptScales[interrupt]);
const uint64_t cycle = m_regs.cycle;
uint64_t target = uint64_t(cycle + eCycle * m_interruptScales[interrupt]);
m_regs.interrupt |= (1 << interrupt);
m_regs.intTargets[interrupt] = target;
int32_t lowest = m_regs.lowestTarget - cycle;
int32_t maybeNewLowest = target - cycle;
int64_t lowest = m_regs.lowestTarget - cycle;
int64_t maybeNewLowest = target - cycle;
if (maybeNewLowest < lowest) m_regs.lowestTarget = target;
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/sio.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ class SIO {

bool isReceiveIRQReady();
bool isTransmitReady();
static inline void scheduleInterrupt(uint32_t eCycle) {
static inline void scheduleInterrupt(uint64_t eCycle) {
g_emulator->m_cpu->scheduleInterrupt(PSXINT_SIO, eCycle);
#if 0
// Breaks Twisted Metal 2 intro
Expand Down
6 changes: 3 additions & 3 deletions src/core/sstate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,8 @@ std::string PCSX::SaveStates::save() {
SaveState state = constructSaveState();
SaveStateWrapper wrapper(state);

state.get<SaveStateInfoField>().get<VersionString>().value = "PCSX-Redux SaveState v3";
state.get<SaveStateInfoField>().get<Version>().value = 3;
state.get<SaveStateInfoField>().get<VersionString>().value = "PCSX-Redux SaveState v4";
state.get<SaveStateInfoField>().get<Version>().value = 4;

g_emulator->m_gpu->serialize(&wrapper);
g_emulator->m_spu->save(state.get<SPUField>());
Expand Down Expand Up @@ -288,7 +288,7 @@ bool PCSX::SaveStates::load(std::string_view data) {
return false;
}

if (state.get<SaveStateInfoField>().get<Version>().value != 3) {
if (state.get<SaveStateInfoField>().get<Version>().value != 4) {
return false;
}

Expand Down
10 changes: 5 additions & 5 deletions src/core/sstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ typedef Protobuf::RepeatedFieldRef<Protobuf::UInt32, 32, TYPESTRING("cp2d"), 3>
typedef Protobuf::RepeatedFieldRef<Protobuf::UInt32, 32, TYPESTRING("cp2c"), 4> CP2C;
typedef Protobuf::FieldRef<Protobuf::UInt32, TYPESTRING("pc"), 5> PC;
typedef Protobuf::FieldRef<Protobuf::UInt32, TYPESTRING("code"), 6> Code;
typedef Protobuf::FieldRef<Protobuf::UInt32, TYPESTRING("cycle"), 7> Cycle;
typedef Protobuf::FieldRef<Protobuf::UInt64, TYPESTRING("cycle"), 7> Cycle;
typedef Protobuf::FieldRef<Protobuf::UInt32, TYPESTRING("interrupt"), 8> Interrupt;
// skip id 9
typedef Protobuf::FieldPtr<Protobuf::FixedBytes<0x1000>, TYPESTRING("icache_addr"), 10> ICacheAddr;
Expand All @@ -75,7 +75,7 @@ typedef Protobuf::Message<TYPESTRING("DelaySlotInfo"), DelaySlotIndex, DelaySlot
typedef Protobuf::MessageField<DelaySlotInfo, TYPESTRING("delay_slot_info_1"), 14> DelaySlotInfo1;
typedef Protobuf::MessageField<DelaySlotInfo, TYPESTRING("delay_slot_info_2"), 15> DelaySlotInfo2;
typedef Protobuf::FieldRef<Protobuf::UInt32, TYPESTRING("current_delayed_load"), 16> CurrentDelayedLoad;
typedef Protobuf::RepeatedFieldRef<Protobuf::UInt32, 32, TYPESTRING("interrupt_targets"), 17> IntTargetsField;
typedef Protobuf::RepeatedFieldRef<Protobuf::UInt64, 32, TYPESTRING("interrupt_targets"), 17> IntTargetsField;
typedef Protobuf::FieldRef<Protobuf::Bool, TYPESTRING("in_isr"), 18> InISR;
typedef Protobuf::Message<TYPESTRING("Registers"), GPR, CP0, CP2D, CP2C, PC, Code, Cycle, Interrupt, ICacheAddr,
ICacheCode, NextIsDelaySlot, DelaySlotInfo1, DelaySlotInfo2, CurrentDelayedLoad,
Expand Down Expand Up @@ -255,15 +255,15 @@ typedef Protobuf::Field<Protobuf::UInt32, TYPESTRING("rate"), 3> RcntRate;
typedef Protobuf::Field<Protobuf::UInt32, TYPESTRING("irq"), 4> RcntIRQ;
typedef Protobuf::Field<Protobuf::UInt32, TYPESTRING("counter_state"), 5> RcntCounterState;
typedef Protobuf::Field<Protobuf::UInt32, TYPESTRING("irq_state"), 6> RcntIRQState;
typedef Protobuf::Field<Protobuf::UInt32, TYPESTRING("cycle"), 7> RcntCycle;
typedef Protobuf::Field<Protobuf::UInt32, TYPESTRING("cycle_start"), 8> RcntCycleStart;
typedef Protobuf::Field<Protobuf::UInt64, TYPESTRING("cycle"), 7> RcntCycle;
typedef Protobuf::Field<Protobuf::UInt64, TYPESTRING("cycle_start"), 8> RcntCycleStart;
typedef Protobuf::Message<TYPESTRING("Rcnt"), RcntMode, RcntTarget, RcntRate, RcntIRQ, RcntCounterState, RcntIRQState,
RcntCycle, RcntCycleStart>
Rcnt;
typedef Protobuf::RepeatedField<Rcnt, 4, TYPESTRING("rcnts"), 1> Rcnts;
typedef Protobuf::Field<Protobuf::UInt32, TYPESTRING("hsync_count"), 2> HSyncCount;
typedef Protobuf::Field<Protobuf::Int32, TYPESTRING("spu_sync_countdown"), 3> SPUSyncCountdown;
typedef Protobuf::Field<Protobuf::UInt32, TYPESTRING("psx_next_counter"), 4> PSXNextCounter;
typedef Protobuf::Field<Protobuf::UInt64, TYPESTRING("psx_next_counter"), 4> PSXNextCounter;
typedef Protobuf::Message<TYPESTRING("Counters"), Rcnts, HSyncCount, SPUSyncCountdown, PSXNextCounter> Counters;
typedef Protobuf::MessageField<Counters, TYPESTRING("counters"), 10> CountersField;

Expand Down

0 comments on commit 1587118

Please sign in to comment.