mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-10-31 09:14:47 +00:00
Make accessing RTC or TBR not affect the other
Fixed an issue where the following would cause inconsistent results (tb in the left column would sometimes decrement instead of always incrementing): 2 0 do 2 0 do cr tb@ 8 u.r ." ." 8 u.r loop 2 0 do cr 12 spaces rtc@ 8 u.r ." ." 8 u.r loop 2 0 do cr tb@ 8 u.r ." ." 8 u.r space rtc@ 8 u.r ." ." 8 u.r loop loop RTC and TBR could not be used simultaneously because they are both incremented by an amount based on the last time stamp but that time stamp can be changed by accessing either RTC or TBR. The solution is to have a different time stamp for each.
This commit is contained in:
parent
ce925f5e56
commit
01d7d6bac3
@ -159,6 +159,7 @@ extern uint32_t opcode_value; // used for interpreting opcodes
|
||||
|
||||
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 rtc_lo, rtc_hi;
|
||||
|
@ -66,7 +66,8 @@ uint64_t g_icycles;
|
||||
int icnt_factor;
|
||||
|
||||
/* global variables related to the timebase facility */
|
||||
uint64_t tbr_wr_timestamp; // stores vCPU virtual time of the last TBR/RTC write
|
||||
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
|
||||
uint64_t timebase_counter; // internal timebase counter
|
||||
@ -763,6 +764,7 @@ void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version, uint64_t tb_freq)
|
||||
g_icycles = 0;
|
||||
icnt_factor = 4;
|
||||
tbr_wr_timestamp = 0;
|
||||
rtc_timestamp = 0;
|
||||
tbr_wr_value = 0;
|
||||
tbr_freq_hz = tb_freq;
|
||||
|
||||
|
@ -857,13 +857,13 @@ void dppc_interpreter::ppc_mtmsr() {
|
||||
|
||||
static inline uint64_t calc_rtcl_value()
|
||||
{
|
||||
uint64_t diff = get_virt_time_ns() - tbr_wr_timestamp;
|
||||
uint64_t diff = get_virt_time_ns() - rtc_timestamp;
|
||||
uint64_t rtc_inc = diff * tbr_freq_hz / NS_PER_SEC;
|
||||
uint64_t rtc_l = rtc_lo + (rtc_inc << 7);
|
||||
if (rtc_l >= ONE_BILLION_NS) { // check RTCL overflow
|
||||
rtc_hi += rtc_l / ONE_BILLION_NS;
|
||||
rtc_lo = rtc_l % ONE_BILLION_NS;
|
||||
tbr_wr_timestamp = get_virt_time_ns();
|
||||
rtc_timestamp = get_virt_time_ns();
|
||||
rtc_l = rtc_lo;
|
||||
}
|
||||
return rtc_l & 0x3FFFFF80UL;
|
||||
@ -927,11 +927,11 @@ void dppc_interpreter::ppc_mtspr() {
|
||||
switch (ref_spr) {
|
||||
case SPR::RTCL_S:
|
||||
rtc_lo = val & 0x3FFFFF80UL;
|
||||
tbr_wr_timestamp = get_virt_time_ns();
|
||||
rtc_timestamp = get_virt_time_ns();
|
||||
break;
|
||||
case SPR::RTCU_S:
|
||||
rtc_hi = val;
|
||||
tbr_wr_timestamp = get_virt_time_ns();
|
||||
rtc_timestamp = get_virt_time_ns();
|
||||
break;
|
||||
case SPR::TBL_S:
|
||||
update_timebase(0xFFFFFFFF00000000ULL, val);
|
||||
|
Loading…
Reference in New Issue
Block a user