diff options
| author | Stefan Hajnoczi <stefanha@redhat.com> | 2025-05-22 14:48:42 -0400 |
|---|---|---|
| committer | Stefan Hajnoczi <stefanha@redhat.com> | 2025-05-22 14:48:42 -0400 |
| commit | bd02070353f84354c03e3d16287e9e80e0875ec1 (patch) | |
| tree | 83d92e4a154ab57ff1628bcc569159cddf056f73 | |
| parent | c6e1f60cc73c787317316bb2956f9a95a5daee15 (diff) | |
| parent | ebd394948de4e868cb8fc5b265a8a18f0935dce1 (diff) | |
| download | focaccia-qemu-bd02070353f84354c03e3d16287e9e80e0875ec1.tar.gz focaccia-qemu-bd02070353f84354c03e3d16287e9e80e0875ec1.zip | |
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.c | 12 | ||||
| -rw-r--r-- | target/hppa/fpu_helper.c | 20 | ||||
| -rw-r--r-- | target/hppa/int_helper.c | 4 |
3 files changed, 31 insertions, 5 deletions
diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c index 890e758cd1..9abaad5ef8 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 ddd0a343d6..45353202fa 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 7d48643bb6..191ae19404 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; |