diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index 82e4408c5c..0fc82bb175 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -788,8 +788,8 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp, QEMUTimer *timer, void (*raise_excp)(void *), void (*lower_excp)(PowerPCCPU *), - target_ulong decr, target_ulong value, - int nr_bits) + uint32_t flags, target_ulong decr, + target_ulong value, int nr_bits) { CPUPPCState *env = &cpu->env; ppc_tb_t *tb_env = env->tb_env; @@ -819,15 +819,15 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp, * On MSB edge based DEC implementations the MSB going from 0 -> 1 triggers * an edge interrupt, so raise it here too. */ - if (((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && signed_value < 0) || - ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && signed_value < 0 + if (((flags & PPC_DECR_UNDERFLOW_LEVEL) && signed_value < 0) || + ((flags & PPC_DECR_UNDERFLOW_TRIGGERED) && signed_value < 0 && signed_decr >= 0)) { (*raise_excp)(cpu); return; } /* On MSB level based systems a 0 for the MSB stops interrupt delivery */ - if (signed_value >= 0 && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) { + if (signed_value >= 0 && (flags & PPC_DECR_UNDERFLOW_LEVEL)) { (*lower_excp)(cpu); } @@ -846,8 +846,8 @@ static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, target_ulong decr, ppc_tb_t *tb_env = cpu->env.tb_env; __cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer, - tb_env->decr_timer->cb, &cpu_ppc_decr_lower, decr, - value, nr_bits); + tb_env->decr_timer->cb, &cpu_ppc_decr_lower, + tb_env->flags, decr, value, nr_bits); } void cpu_ppc_store_decr(CPUPPCState *env, target_ulong value) @@ -876,8 +876,10 @@ static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, target_ulong hdecr, ppc_tb_t *tb_env = cpu->env.tb_env; if (tb_env->hdecr_timer != NULL) { + /* HDECR (Book3S 64bit) is edge-based, not level like DECR */ __cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer, tb_env->hdecr_timer->cb, &cpu_ppc_hdecr_lower, + PPC_DECR_UNDERFLOW_TRIGGERED, hdecr, value, nr_bits); } }