Re: catching floating point exception on OS X Intel
Re: catching floating point exception on OS X Intel
- Subject: Re: catching floating point exception on OS X Intel
- From: Jonas Maebe <email@hidden>
- Date: Wed, 9 May 2007 13:51:36 +0200
On 9 mei 2007, at 01:29, Kristoffer Eriksen wrote:
To summarize, I'm using the feraiseexcept() function from fenv.h,
which I had hoped would enable floating point exceptions for the
requested flags.
I figured you'd have to do something like this, but it doesn't work
either:
retval = fegetexceptflag(&flags, FE_INVALID | FE_DIVBYZERO |
FE_OVERFLOW );
flags |= (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
retval = fesetexceptflag(&flags, FE_INVALID | FE_DIVBYZERO |
FE_OVERFLOW );
It's quite annoying that none of the man pages for those functions
available on the Internet contain any example code (and that there
aren't even any man pages for them in Mac OS X)
Anyway, the following does work (based on code from the Free Pascal
runtime library), but with a some caveats:
a) I don't know how to write PIC inline assembler code in gcc (nor
how to address local variables in inline gcc assembler, nor how to
force local variables to be in memory), so this code will not work
inside a dynamic library (because it directly accesses a global
variable from assembler code)
b) do not write GUI programs with fpu exceptions turned on, because
there are parts of CoreGraphics which trigger such exceptions (at
least on ppc)
Float and double are handled using sse by default on Mac OS X, while
long double is handled using the 80x87. This means you need to set
both the sse and 80x87 fpu masks. You can force all code to use the
80x87 by compiling with -mfpmath=387 (not recommended, since slower).
Jonas
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#define FPU_NoMask 0x00
#define FPU_Invalid 0x01
#define FPU_Denormal 0x02
#define FPU_DivisionByZero 0x04
#define FPU_Overflow 0x08
#define FPU_Underflow 0x10
#define FPU_Inexact 0x20
#define FPU_ExceptionMask 0xff
unsigned short fpucw;
unsigned int mxcsr;
int setfpumask(int fpmask) {
int oldmask;
asm volatile ("fstcw _fpucw");
oldmask = fpucw & 0xffc0;
fpucw = fpucw | (fpmask & FPU_ExceptionMask);
asm volatile ("fldcw _fpucw");
asm volatile("fwait");
// the sse masking flags are the same as the 80x87 flags, just
// shifted left 7
asm volatile("stmxcsr _mxcsr");
mxcsr = (mxcsr & 0xffffe07f) | ((fpmask & FPU_ExceptionMask) << 7);
asm volatile("ldmxcsr _mxcsr");
return oldmask;
}
void dosqrtsse() {
double x;
pid_t pid;
pid = getpid();
x = sqrt(-1.0/(double)pid);
printf("sse: %d %f\n",pid,x);
}
void dosqrtx87() {
long double x;
pid_t pid;
pid = getpid();
x = sqrt(-1.0/(long double)pid);
printf("x87: %d %f\n",pid,x);
}
int main(int argc, char *argv[]){
printf("Default mask\n");
dosqrtsse();
dosqrtx87();
// both inexact and invalid need to be masked in this case
printf("Only inexact and invalid exceptions masked\n");
setfpumask(FPU_Inexact|FPU_Invalid);
dosqrtsse();
dosqrtx87();
printf("No exceptions masked\n");
setfpumask(FPU_NoMask);
dosqrtsse();
// not reached
dosqrtx87();
// not reached
exit(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