Floating-point exception handling
Floating-point exception handling
- Subject: Floating-point exception handling
- From: "David N. Williams" <email@hidden>
- Date: Wed, 16 Sep 2009 08:17:17 -0400
- Organization: University of Michigan
I am part of an ad hoc group working on a Forth language
standard for IEEE 754 (2008) floating point, and I'm trying to
do an example implementation of alternate handling for floating-
point exceptions with gcc/Darwin, for one of the C-based Forths.
It's my first attempt at writing a signal handler, but I was
able to get it working pretty well on my PowerPC G4, with the
sample code quoted below as a guide. The sample code is
apparently an update of Listing 7-1 in the 2004 version of
"PowerPC Numerics".
My question is, what's the analogous magic for OS X intel?
AFAIU, there are two issues, enabling nondefault exception
handling, and dealing with state in the handler. The sample
code deals with state only by restoring it when the handler
returns.
I might be able to figure out the intel analog for the ppc
assembly language functions used for enabling, fegetenvd() and
fesetenvd() quoted below; but I wouldn't mind a little hand
holding on that.
I didn't find any documentation on what's going on with state
restoration in myHandler(), and so don't have a clue how to
change that for intel.
Thanks for any suggestions.
-- David
-----------
/*
The following sample code is slightly modified to get it to
compile with gcc version 4.0.1 (Apple Inc. build 5493) under
OS X 10.5.8 and ppc. The original is here:
http://lists.apple.com/archives/unix-porting/2003/May/msg00026.html
See also Listing 7-1 in "PowerPC Numerics", 2004:
http://developer.apple.com/documentation/Performance/Conceptual/Mac_OSX_Numerics/Mac_OSX_Numerics.pdf
-- David N. Williams, 15-Sep-09
*/
#include <stdio.h>
#include <math.h>
#include <fenv.h>
#include <signal.h>
#include <ucontext.h>
#include <mach/thread_status.h>
#include <stdlib.h> // for exit()
#define fegetenvd(x) asm volatile("mffs %0" : "=f" (x));
#define fesetenvd(x) asm volatile("mtfsf 255,%0" : : "f" (x));
enum {
FE_ENABLE_INEXACT = 0x00000008,
FE_ENABLE_DIVBYZERO = 0x00000010,
FE_ENABLE_UNDERFLOW = 0x00000020,
FE_ENABLE_OVERFLOW = 0x00000040,
FE_ENABLE_INVALID = 0x00000080,
FE_ENABLE_ALL_EXCEPT = 0x000000F8
};
typedef union {
struct {
unsigned long hi;
unsigned long lo;
} i;
double d;
} hexdouble;
// void myHandler(int sig, siginfo_t *sip, struct ucontext *scp)
void myHandler(int sig, siginfo_t *sip, ucontext_t *scp)
{
hexdouble t; // superfluous in this example
ppc_float_state_t *fs;
ppc_thread_state_t *ss;
// fs = &scp->uc_mcontext->fs;
fs = &scp->uc_mcontext->__fs;
// ss = &scp->uc_mcontext->ss;
ss = &scp->uc_mcontext->__ss;
fprintf(stdout, "SIGFPE at 0x%x invokes myHandler, fpscr = X\n",
// sip->si_addr, fs->fpscr);
sip->si_addr, fs->__fpscr);
// fs->fpscr &= FE_ENABLE_ALL_EXCEPT;
fs->__fpscr &= FE_ENABLE_ALL_EXCEPT;
// Re-arms interrupts when this state is restored
// ss->srr0 += 4; // Advances the PC when this state is restored
ss->__srr0 += 4; // Advances the PC when this state is restored
// fprintf(stdout, "fpscr = X\n", fs->fpscr);
fprintf(stdout, "fpscr = X\n", fs->__fpscr);
fflush(stdout);
}
// static struct sigaction act = { myHandler, (sigset_t)0, SA_SIGINFO };
static struct sigaction act =
{ (void (*))myHandler, (sigset_t)0, SA_SIGINFO };
int main( int argc, char **argv)
{
float s;
hexdouble t;
fegetenvd(t.d);
t.i.lo |= FE_ENABLE_ALL_EXCEPT;
// Enable hardware trapping for all exceptions
fesetenvd(t.d);
if (sigaction(SIGFPE, &act, (struct sigaction *)0) != 0)
{ // Set handler
perror("Yikes");
exit(-1);
}
fegetenvd(t.d);
s = HUGE_VALF * HUGE_VALF; // Overflow folded out by compiler
s = s / (1.0 + s); // Inf/Inf raises invalid operation
fegetenvd(t.d);
fprintf(stdout, "In main(1), s computed as: %e , fpscr = X\n",
s, t.i.lo); // keep the compiler honest ...
s = HUGE_VALF * HUGE_VALF; // Overflow folded out by compiler
s = s / (2.0 + s); // Inf/Inf raises invalid operation
fegetenvd(t.d);
fprintf(stdout, "In main(2), s computed as: %e , fpscr = X\n",
s, t.i.lo); // keep the compiler honest ...
return 0;
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden