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;
|
CPUPPCState *env = &cpu->env;
|
||||||
ppc_tb_t *tb_env = env->tb_env;
|
ppc_tb_t *tb_env = env->tb_env;
|
||||||
uint64_t now, next;
|
uint64_t now, next;
|
||||||
bool negative;
|
int64_t signed_value;
|
||||||
|
int64_t signed_decr;
|
||||||
|
|
||||||
/* Truncate value to decr_width and sign extend for simplicity */
|
/* Truncate value to decr_width and sign extend for simplicity */
|
||||||
value &= ((1ULL << nr_bits) - 1);
|
signed_value = sextract64(value, 0, nr_bits);
|
||||||
negative = !!(value & (1ULL << (nr_bits - 1)));
|
signed_decr = sextract64(decr, 0, nr_bits);
|
||||||
if (negative) {
|
|
||||||
value |= (0xFFFFFFFFULL << nr_bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
trace_ppc_decr_store(nr_bits, decr, value);
|
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
|
* On MSB edge based DEC implementations the MSB going from 0 -> 1 triggers
|
||||||
* an edge interrupt, so raise it here too.
|
* an edge interrupt, so raise it here too.
|
||||||
*/
|
*/
|
||||||
if ((value < 3) ||
|
if ((signed_value < 3) ||
|
||||||
((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && negative) ||
|
((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && signed_value < 0) ||
|
||||||
((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && negative
|
((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && signed_value < 0
|
||||||
&& !(decr & (1ULL << (nr_bits - 1))))) {
|
&& signed_decr >= 0)) {
|
||||||
(*raise_excp)(cpu);
|
(*raise_excp)(cpu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* On MSB level based systems a 0 for the MSB stops interrupt delivery */
|
/* 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);
|
(*lower_excp)(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user