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); }