[PATCH] linux-user/sh4: Initialize the FPSCR register on signal

Mikulas Patocka <[email protected]> Tue, 4 Aug 2026 10:59:18 +0200 (CEST)
Newsgroups gmane.comp.emulators.qemu
Message-ID <[email protected]>
On the SH4 architecture, the instructions that perform single precision
and double precision floating point operations are encoded in the same
way. The bit PR in the FPSCR register determines if the CPU performs
single or double operation.

According to the ABI, the PR bit must be set at function entry and
function exit.

GCC generates code that flips this bit as needed during function
execution. If we get a signal, we must set the PR bit, so that the signal
handler finds the bit in the expected state. Qemu lacked this logic, so
that if the signal interrupts single-precision floating point
calculation, the PR bit would be incorrectly clear at signal handler
entry. If the signal handler performed some floating-point calculation,
it would get incorrect result.

This patch fixes the bug, by initializing the FPSCR register at signal
entry. Note that we initialize the whole register, because the Linux
kernel initializes the whole register too.

Cc: [email protected]
Signed-off-by: Mikulas Patocka <[email protected]>

---
 linux-user/sh4/signal.c |    4 ++++
 1 file changed, 4 insertions(+)

Index: qemu/linux-user/sh4/signal.c
===================================================================
--- qemu.orig/linux-user/sh4/signal.c	2026-08-02 18:03:09.000000000 +0200
+++ qemu/linux-user/sh4/signal.c	2026-08-04 09:40:21.000000000 +0200
@@ -206,6 +206,8 @@ void setup_frame(int sig, struct target_
         __put_user(set->sig[i + 1], &frame->extramask[i]);
     }
 
+    regs->fpscr = FPSCR_PR;
+
     /* Set up to return from userspace.  If provided, use a stub
        already in userspace.  */
     if (ka->sa_flags & TARGET_SA_RESTORER) {
@@ -258,6 +260,8 @@ void setup_rt_frame(int sig, struct targ
         __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
     }
 
+    regs->fpscr = FPSCR_PR;
+
     /* Set up to return from userspace.  If provided, use a stub
        already in userspace.  */
     if (ka->sa_flags & TARGET_SA_RESTORER) {