aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2025-05-22 14:48:42 -0400
committerStefan Hajnoczi <stefanha@redhat.com>2025-05-22 14:48:42 -0400
commitbd02070353f84354c03e3d16287e9e80e0875ec1 (patch)
tree83d92e4a154ab57ff1628bcc569159cddf056f73
parentc6e1f60cc73c787317316bb2956f9a95a5daee15 (diff)
parentebd394948de4e868cb8fc5b265a8a18f0935dce1 (diff)
downloadqemu-bd02070353f84354c03e3d16287e9e80e0875ec1.zip
qemu-bd02070353f84354c03e3d16287e9e80e0875ec1.tar.gz
qemu-bd02070353f84354c03e3d16287e9e80e0875ec1.tar.bz2
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>
-rw-r--r--linux-user/hppa/cpu_loop.c12
-rw-r--r--target/hppa/fpu_helper.c20
-rw-r--r--target/hppa/int_helper.c4
3 files changed, 31 insertions, 5 deletions
diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c
index 890e758..9abaad5 100644
--- a/linux-user/hppa/cpu_loop.c
+++ b/linux-user/hppa/cpu_loop.c
@@ -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);
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
index ddd0a34..4535320 100644
--- a/target/hppa/fpu_helper.c
+++ b/target/hppa/fpu_helper.c
@@ -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);
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index 7d48643..191ae19 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -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;