Date: Mon, 01 Sep 2025 13:15:14 +0000 From: bugzilla-noreply@freebsd.org To: bugs@FreeBSD.org Subject: [Bug 289232] i386 (x87) signal incorrectly reports FPE_FLTRES over FPE_FLTUND when both are present Message-ID: <bug-289232-227@https.bugs.freebsd.org/bugzilla/>
index | next in thread | raw e-mail
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=289232 Bug ID: 289232 Summary: i386 (x87) signal incorrectly reports FPE_FLTRES over FPE_FLTUND when both are present Product: Base System Version: 13.5-RELEASE Hardware: i386 OS: Any Status: New Severity: Affects Many People Priority: --- Component: kern Assignee: bugs@FreeBSD.org Reporter: riverstdr@gmail.com When an x87 floating-point operation underflows, the result is often also inexact; so both the #U and #P flags are set in the x87 status register. IEEE 754 prioritizes FP exception reporting with a hierarchy. When both UNDERFLOW and INEXACT are present, UNDERFLOW should be reported (as UNDERFLOW implies INEXACT.) Unfortunately, the signal handling code appears to prefer INEXACT in this case, so that the 'si_code' handed to the signal handler indicates FPE_FLTRES instead of FPE_FLTUND. This makes detecting underflow in a signal handler impossible when FE_INEXACT is allowed in conjunction with FE_UNDERFLOW. If you set the floating-pt mask with fpeenableexcept() to be feenableexcept(FE_UNDERFLOW | FE_INEXACT); the x87 floating-pt status register reported in the machine context only seems to have #P set (something has cleared out #U). But, if you set it to only feenableexcept(FE_UNDERFLOW), the same operation correctly reports FPE_FLTUND in si_code, and the x87 status register only has #U. I've tried several FreeBSD versions - the problem appears to be a very old one all the back to FreeBSD 4.5 a least. Interestingly, when using SSE floating-point, the FPE_FLTUND is properly reported. Here's an example program - compile this with -m64 (using SSE regs) and the proper FPE_FLTUND is reported, compile it with -m32 (which uses x87 operations) and the incorrect FPE_FLTRES is reported. #include <fenv.h> #include <stdio.h> #include <signal.h> #include <math.h> #include <unistd.h> void sigfpe_handler(int signum, siginfo_t *info, void *context) { ucontext_t *uc = (ucontext_t *)context; int si_code = info->si_code; printf("Caught SIGFPE (Floating-Point Exception)!\n"); printf("Signal info (si_code): %d", info->si_code); if(si_code == FPE_FLTUND) printf(": FPE_FLTUND\n"); else if (si_code == FPE_FLTRES) printf(": FPE_FLTRES\n"); else printf("\n"); /* The FP state pointer is within the machine-specific context */ /* This is the structure containing both x87 and SSE state */ struct _fpstate *fpregs = (struct _fpstate *)uc->uc_mcontext.mc_fpstate; if (fpregs) { // The x87 status word is at the beginning of the _fpstate structure // The fxsave format places the FPU status word (fsw) at offset 2 // // On x86-64, the mc_fpstate points to the FXSAVE area, where the // x87 FPU Status Word is at offset 2. unsigned short x87_status_word = *(unsigned short *)((char *)fpregs + 2); printf("x87 FPU Status Word (FSW): 0x%04x\n", x87_status_word); if(x87_status_word & 0x01) printf(" INVALID OP\n"); if(x87_status_word & 0x02) printf(" DENORMAL OPERAND\n"); if(x87_status_word & 0x04) printf(" ZERO DIVIDE\n"); if(x87_status_word & 0x08) printf(" OVERFLOW\n"); if(x87_status_word & 0x10) printf(" UNDERFLOW\n"); if(x87_status_word & 0x20) printf(" INEXACT\n"); } _exit(1); } int main() { struct sigaction sa; sa.sa_sigaction = sigfpe_handler; sa.sa_flags = SA_SIGINFO; sigaction(SIGFPE, &sa, NULL); // Enable traps for floating-point exceptions // The following code is architecture-specific. // It enables traps for underflow and inexact exceptions. // The underflow trap should have priority over the inexact trap. fedisableexcept(FE_INEXACT); feenableexcept(FE_UNDERFLOW ); feenableexcept(FE_UNDERFLOW | FE_INEXACT); double small_num = 1.0E-300; double large_num = 1.0E+300; // This operation will cause both an underflow and an inexact result. double result = small_num / large_num; printf("Result is: %e\n", result); return 0; } -- You are receiving this mail because: You are the assignee for the bug.home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-289232-227>
