Merge tag 'hppa-fpe-fixup-pull-request' of https://github.com/hdeller/qemu-hppa into staging

HPPA floating point exception handling fixes

Fixes and improvements in the floating point exception
handling in the hppa system and user emulation.

# -----BEGIN PGP SIGNATURE-----
#
# iHUEABYKAB0WIQS86RI+GtKfB8BJu973ErUQojoPXwUCaC7b/QAKCRD3ErUQojoP
# X8IPAQCZGjG3+iwJJuJkL6dSu7WKWgidX16zIxeRYQl+FXTpkAD9FBQ/nDP+EAFN
# 5hQTeiixyj3xIsZHPeHwfzhWiBUwQAo=
# =Q3zi
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 22 May 2025 04:10:37 EDT
# gpg:                using EDDSA key BCE9123E1AD29F07C049BBDEF712B510A23A0F5F
# gpg: Good signature from "Helge Deller <deller@gmx.de>" [unknown]
# gpg:                 aka "Helge Deller <deller@kernel.org>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 4544 8228 2CD9 10DB EF3D  25F8 3E5F 3D04 A7A2 4603
#      Subkey fingerprint: BCE9 123E 1AD2 9F07 C049  BBDE F712 B510 A23A 0F5F

* tag 'hppa-fpe-fixup-pull-request' of https://github.com/hdeller/qemu-hppa:
  target/hppa: Fix FPE exceptions
  linux-user/hppa: Send proper si_code on SIGFPE exception
  target/hppa: Copy instruction code into fr1 on FPU assist fault

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi
2025-05-22 14:48:42 -04:00
3 changed files with 31 additions and 5 deletions
+10 -2
View File
@@ -112,7 +112,7 @@ static abi_ulong hppa_lws(CPUHPPAState *env)
void cpu_loop(CPUHPPAState *env)
{
CPUState *cs = env_cpu(env);
abi_ulong ret;
abi_ulong ret, si_code = 0;
int trapnr;
while (1) {
@@ -169,7 +169,15 @@ void cpu_loop(CPUHPPAState *env)
force_sig_fault(TARGET_SIGFPE, TARGET_FPE_CONDTRAP, env->iaoq_f);
break;
case EXCP_ASSIST:
force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f);
#define set_si_code(mask, val) \
if (env->fr[0] & mask) { si_code = val; }
set_si_code(R_FPSR_FLG_I_MASK, TARGET_FPE_FLTRES);
set_si_code(R_FPSR_FLG_U_MASK, TARGET_FPE_FLTUND);
set_si_code(R_FPSR_FLG_O_MASK, TARGET_FPE_FLTOVF);
set_si_code(R_FPSR_FLG_Z_MASK, TARGET_FPE_FLTDIV);
set_si_code(R_FPSR_FLG_V_MASK, TARGET_FPE_FLTINV);
#undef set_si_code
force_sig_fault(TARGET_SIGFPE, si_code, env->iaoq_f);
break;
case EXCP_BREAK:
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f);
+17 -3
View File
@@ -94,7 +94,8 @@ static void update_fr0_op(CPUHPPAState *env, uintptr_t ra)
{
uint32_t soft_exp = get_float_exception_flags(&env->fp_status);
uint32_t hard_exp = 0;
uint32_t shadow = env->fr0_shadow;
uint32_t shadow = env->fr0_shadow & 0x3ffffff;
uint32_t fr1 = 0;
if (likely(soft_exp == 0)) {
env->fr[0] = (uint64_t)shadow << 32;
@@ -107,9 +108,22 @@ static void update_fr0_op(CPUHPPAState *env, uintptr_t ra)
hard_exp |= CONVERT_BIT(soft_exp, float_flag_overflow, R_FPSR_ENA_O_MASK);
hard_exp |= CONVERT_BIT(soft_exp, float_flag_divbyzero, R_FPSR_ENA_Z_MASK);
hard_exp |= CONVERT_BIT(soft_exp, float_flag_invalid, R_FPSR_ENA_V_MASK);
shadow |= hard_exp << (R_FPSR_FLAGS_SHIFT - R_FPSR_ENABLES_SHIFT);
if (hard_exp & shadow) {
shadow = FIELD_DP32(shadow, FPSR, T, 1);
/* fill exception register #1, which is lower 32-bits of fr[0] */
#if !defined(CONFIG_USER_ONLY)
if (hard_exp & (R_FPSR_ENA_O_MASK | R_FPSR_ENA_U_MASK)) {
/* over- and underflow both set overflow flag only */
fr1 = FIELD_DP32(fr1, FPSR, C, 1);
fr1 = FIELD_DP32(fr1, FPSR, FLG_O, 1);
} else
#endif
{
fr1 |= hard_exp << (R_FPSR_FLAGS_SHIFT - R_FPSR_ENABLES_SHIFT);
}
}
env->fr0_shadow = shadow;
env->fr[0] = (uint64_t)shadow << 32;
env->fr[0] = (uint64_t)shadow << 32 | fr1;
if (hard_exp & shadow) {
hppa_dynamic_excp(env, EXCP_ASSIST, ra);
+4
View File
@@ -177,6 +177,10 @@ void hppa_cpu_do_interrupt(CPUState *cs)
}
}
env->cr[CR_IIR] = ldl_phys(cs->as, paddr);
if (i == EXCP_ASSIST) {
/* stuff insn code into bits of FP exception register #1 */
env->fr[0] |= (env->cr[CR_IIR] & 0x03ffffff);
}
}
break;