target/ppc: Fix 64-bit decrementer
The current way the mask is built can overflow with a 64-bit decrementer.
Use sextract64() to extract the signed values and remove the logic to
handle negative values which has become useless.
Cc: Luis Fernando Fujita Pires <luis.pires@eldorado.org.br>
Fixes: a8dafa5251
("target/ppc: Implement large decrementer support for TCG")
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Message-Id: <20210920061203.989563-5-clg@kaod.org>
Reviewed-by: Luis Pires <luis.pires@eldorado.org.br>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
af96d2e692
commit
4d9b8ef9b5
20
hw/ppc/ppc.c
20
hw/ppc/ppc.c
@ -821,14 +821,12 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
|
||||
CPUPPCState *env = &cpu->env;
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
uint64_t now, next;
|
||||
bool negative;
|
||||
int64_t signed_value;
|
||||
int64_t signed_decr;
|
||||
|
||||
/* Truncate value to decr_width and sign extend for simplicity */
|
||||
value &= ((1ULL << nr_bits) - 1);
|
||||
negative = !!(value & (1ULL << (nr_bits - 1)));
|
||||
if (negative) {
|
||||
value |= (0xFFFFFFFFULL << nr_bits);
|
||||
}
|
||||
signed_value = sextract64(value, 0, nr_bits);
|
||||
signed_decr = sextract64(decr, 0, nr_bits);
|
||||
|
||||
trace_ppc_decr_store(nr_bits, decr, value);
|
||||
|
||||
@ -850,16 +848,16 @@ 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 ((value < 3) ||
|
||||
((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && negative) ||
|
||||
((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && negative
|
||||
&& !(decr & (1ULL << (nr_bits - 1))))) {
|
||||
if ((signed_value < 3) ||
|
||||
((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && signed_value < 0) ||
|
||||
((tb_env->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 (!negative && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) {
|
||||
if (signed_value >= 0 && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) {
|
||||
(*lower_excp)(cpu);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user