diff --git a/core/mathutils.h b/core/mathutils.h
new file mode 100644
index 0000000..fa552be
--- /dev/null
+++ b/core/mathutils.h
@@ -0,0 +1,49 @@
+/*
+DingusPPC - The Experimental PowerPC Macintosh emulator
+Copyright (C) 2018-22 divingkatae and maximum
+ (theweirdo) spatium
+
+(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+#ifndef MATH_UTILS_H
+#define MATH_UTILS_H
+
+inline void _u32xu64(uint32_t a, uint64_t b, uint32_t &hi, uint64_t &lo)
+{
+ uint64_t p0 = (b & 0xffffffff) * a;
+ uint64_t p1 = (b >> 32) * a;
+ lo = p0 + (p1 << 32);
+ hi = (p1 >> 32) + (lo < p0);
+}
+
+inline void _u32xu64(uint32_t a, uint64_t b, uint64_t &hi, uint32_t &lo)
+{
+ uint64_t p0 = (b & 0xffffffff) * a;
+ uint64_t p1 = (b >> 32) * a;
+ lo = p0;
+ hi = (p0 >> 32) + p1;
+}
+
+inline void _u64xu64(uint64_t a, uint64_t b, uint64_t &hi, uint64_t &lo)
+{
+ uint32_t p0h; uint64_t p0l; _u32xu64(b, a, p0h, p0l);
+ uint64_t p1h; uint32_t p1l; _u32xu64(b >> 32, a, p1h, p1l);
+ lo = p0l + ((uint64_t)p1l << 32);
+ hi = p0h + p1h + (lo < p0l);
+}
+
+#endif // MATH_UTILS_H
diff --git a/cpu/ppc/ppcemu.h b/cpu/ppc/ppcemu.h
index 4110a1f..465a1d5 100644
--- a/cpu/ppc/ppcemu.h
+++ b/cpu/ppc/ppcemu.h
@@ -161,7 +161,7 @@ extern uint64_t timebase_counter;
extern uint64_t tbr_wr_timestamp;
extern uint64_t rtc_timestamp;
extern uint64_t tbr_wr_value;
-extern uint64_t tbr_freq_hz;
+extern uint32_t tbr_freq_ghz;
extern uint32_t rtc_lo, rtc_hi;
// Additional steps to prevent overflow?
diff --git a/cpu/ppc/ppcexec.cpp b/cpu/ppc/ppcexec.cpp
index f0b86f3..9236450 100644
--- a/cpu/ppc/ppcexec.cpp
+++ b/cpu/ppc/ppcexec.cpp
@@ -69,7 +69,7 @@ int icnt_factor;
uint64_t tbr_wr_timestamp; // stores vCPU virtual time of the last TBR write
uint64_t rtc_timestamp; // stores vCPU virtual time of the last RTC write
uint64_t tbr_wr_value; // last value written to the TBR
-uint64_t tbr_freq_hz; // TBR/RTC driving frequency in Hz
+uint32_t tbr_freq_ghz; // TBR/RTC driving frequency in GHz expressed as a 32 bit fraction less than 1.0.
uint64_t timebase_counter; // internal timebase counter
uint32_t decr; // current value of PPC DEC register
uint32_t rtc_lo; // MPC601 RTC lower, counts nanoseconds
@@ -766,7 +766,7 @@ void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version, uint64_t tb_freq)
tbr_wr_timestamp = 0;
rtc_timestamp = 0;
tbr_wr_value = 0;
- tbr_freq_hz = tb_freq;
+ tbr_freq_ghz = (tb_freq << 32) / NS_PER_SEC;
exec_flags = 0;
diff --git a/cpu/ppc/ppcopcodes.cpp b/cpu/ppc/ppcopcodes.cpp
index 47b2c1b..e899a75 100644
--- a/cpu/ppc/ppcopcodes.cpp
+++ b/cpu/ppc/ppcopcodes.cpp
@@ -22,6 +22,7 @@ along with this program. If not, see .
// General opcodes for the processor - ppcopcodes.cpp
#include
+#include
#include "ppcemu.h"
#include "ppcmmu.h"
#include
@@ -895,7 +896,7 @@ void dppc_interpreter::ppc_mfspr() {
static inline uint64_t calc_tbr_value()
{
uint64_t diff = get_virt_time_ns() - tbr_wr_timestamp;
- uint64_t tbr_inc = diff * tbr_freq_hz / NS_PER_SEC;
+ uint64_t tbr_inc; uint32_t tbr_inc_lo; _u32xu64(tbr_freq_ghz, diff, tbr_inc, tbr_inc_lo);
return (tbr_wr_value + tbr_inc);
}