mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-11 05:29:43 +00:00
Implement PPC decrementer.
This commit is contained in:
parent
71b2e6c1fa
commit
597c077b19
@ -94,7 +94,7 @@ enum SPR : int {
|
||||
DAR = 19,
|
||||
RTCU_S = 20, // supervisor RTCU
|
||||
RTCL_S = 21, // supervisor RTCL
|
||||
DEC = 22,
|
||||
DEC = 22, // decrementer
|
||||
SDR1 = 25,
|
||||
SRR0 = 26,
|
||||
SRR1 = 27,
|
||||
@ -160,8 +160,10 @@ extern uint32_t opcode_value; // used for interpreting opcodes
|
||||
|
||||
extern uint64_t timebase_counter;
|
||||
extern uint64_t tbr_wr_timestamp;
|
||||
extern uint64_t dec_wr_timestamp;
|
||||
extern uint64_t rtc_timestamp;
|
||||
extern uint64_t tbr_wr_value;
|
||||
extern uint32_t dec_wr_value;
|
||||
extern uint32_t tbr_freq_ghz;
|
||||
extern uint32_t rtc_lo, rtc_hi;
|
||||
|
||||
|
@ -71,7 +71,8 @@ uint64_t rtc_timestamp; // stores vCPU virtual time of the last RTC write
|
||||
uint64_t tbr_wr_value; // last value written to the TBR
|
||||
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
|
||||
uint64_t dec_wr_timestamp; // stores vCPU virtual time of the last DEC write
|
||||
uint32_t dec_wr_value; // last value written to the DEC register
|
||||
uint32_t rtc_lo; // MPC601 RTC lower, counts nanoseconds
|
||||
uint32_t rtc_hi; // MPC601 RTC upper, counts seconds
|
||||
|
||||
@ -771,7 +772,7 @@ void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version, uint64_t tb_freq)
|
||||
exec_flags = 0;
|
||||
|
||||
timebase_counter = 0;
|
||||
decr = 0;
|
||||
dec_wr_value = 0;
|
||||
|
||||
/* zero all GPRs as prescribed for MPC601 */
|
||||
/* For later PPC CPUs, GPR content is undefined */
|
||||
|
@ -870,6 +870,35 @@ static inline void calc_rtcl_value()
|
||||
rtc_timestamp = new_ts;
|
||||
}
|
||||
|
||||
static inline uint64_t calc_tbr_value()
|
||||
{
|
||||
uint64_t tbr_inc;
|
||||
uint32_t tbr_inc_lo;
|
||||
uint64_t diff = get_virt_time_ns() - tbr_wr_timestamp;
|
||||
_u32xu64(tbr_freq_ghz, diff, tbr_inc, tbr_inc_lo);
|
||||
return (tbr_wr_value + tbr_inc);
|
||||
}
|
||||
|
||||
static inline uint32_t calc_dec_value() {
|
||||
uint64_t dec_adj;
|
||||
uint32_t dec_adj_lo;
|
||||
uint64_t diff = get_virt_time_ns() - dec_wr_timestamp;
|
||||
_u32xu64(tbr_freq_ghz, diff, dec_adj, dec_adj_lo);
|
||||
return (dec_wr_value - dec_adj);
|
||||
}
|
||||
|
||||
static void update_timebase(uint64_t mask, uint64_t new_val)
|
||||
{
|
||||
uint64_t tbr_value = calc_tbr_value();
|
||||
tbr_wr_value = (tbr_value & mask) | new_val;
|
||||
tbr_wr_timestamp = get_virt_time_ns();
|
||||
}
|
||||
|
||||
static void update_decrementer(uint32_t val) {
|
||||
dec_wr_value = val;
|
||||
dec_wr_timestamp = get_virt_time_ns();
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_mfspr() {
|
||||
uint32_t ref_spr = (((ppc_cur_instruction >> 11) & 31) << 5) | ((ppc_cur_instruction >> 16) & 31);
|
||||
|
||||
@ -888,25 +917,14 @@ void dppc_interpreter::ppc_mfspr() {
|
||||
calc_rtcl_value();
|
||||
ppc_state.spr[SPR::RTCU_U] = rtc_hi;
|
||||
break;
|
||||
case SPR::DEC:
|
||||
ppc_state.spr[SPR::DEC] = calc_dec_value();
|
||||
break;
|
||||
}
|
||||
|
||||
ppc_state.gpr[(ppc_cur_instruction >> 21) & 31] = ppc_state.spr[ref_spr];
|
||||
}
|
||||
|
||||
static inline uint64_t calc_tbr_value()
|
||||
{
|
||||
uint64_t diff = get_virt_time_ns() - tbr_wr_timestamp;
|
||||
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);
|
||||
}
|
||||
|
||||
static void update_timebase(uint64_t mask, uint64_t new_val)
|
||||
{
|
||||
uint64_t tbr_value = calc_tbr_value();
|
||||
tbr_wr_value = (tbr_value & mask) | new_val;
|
||||
tbr_wr_timestamp = get_virt_time_ns();
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_mtspr() {
|
||||
uint32_t ref_spr = (((ppc_cur_instruction >> 11) & 31) << 5) | ((ppc_cur_instruction >> 16) & 31);
|
||||
reg_s = (ppc_cur_instruction >> 21) & 31;
|
||||
@ -936,6 +954,9 @@ void dppc_interpreter::ppc_mtspr() {
|
||||
calc_rtcl_value();
|
||||
rtc_hi = val;
|
||||
break;
|
||||
case SPR::DEC:
|
||||
update_decrementer(val);
|
||||
break;
|
||||
case SPR::TBL_S:
|
||||
update_timebase(0xFFFFFFFF00000000ULL, val);
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user