Skip to content

Commit

Permalink
Moving cycle counters to 64-bits.
Browse files Browse the repository at this point in the history
They'll no longer roll over, simplifying a lot of things.
  • Loading branch information
nicolasnoble committed Nov 20, 2024
1 parent 33b7ec3 commit c82fbc4
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 38 deletions.
26 changes: 9 additions & 17 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 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;

Check notice on line 145 in src/core/psxcounters.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Complex Method

PCSX::Counters::update decreases in cyclomatic complexity from 12 to 11, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
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
8 changes: 4 additions & 4 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
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 c82fbc4

Please sign in to comment.