This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: I want my FPE!


Dave Korn writes [why Yes, it was indeed a long time ago]:
> > Is there something I need to do to "condition" the Cygwin environment to
> > generate FP exceptions?  I saw the code in winsup/something/or/other to map
> > x86 FP exceptions to SIGFPE but it seems somehow the exceptions aren't being
> > generated in the first place.
> 
>   Very possibly not.  There's probably a bit in the FPUCW you need to set or
> something.  Ah, yes: see winsup/cygwin/crt0.c:
[...good stuff elided for brevity...]
>   You can copy and paste that hunk into your own main() and change the
> constants to anything you like.

I've tried many things but have been unable to get this to work.  STC appended
below but watch for linewraps.  It uses ideas from Cygwin's crt0.c.  Although I
can trap SIGSEGV just fine, SIGFPE remains elusive even though the control word
has zeroed FP exception mask bits.  Also odd is that crt0.c claims to be setting
the control word to 0x033F but it's actually 0x037F as the program starts.

Any further suggestions would be greatly appreciated.
Thanks much,

..mark

#include <setjmp.h>
#include <signal.h>
#include <stdio.h>

//
// The following code is derived from Cygwin's crt0.c
//
#define FPU_RESERVED    0xF0C0
#define FPU_DEFAULT     0x033F

unsigned short
getstatusword()
{
    volatile unsigned short sw = 0xFFFF;

    __asm__ volatile("fnstsw %0" : "=m" (sw) : );
    return sw;
}

unsigned short
getcontrolword()
{
    volatile unsigned short cw = 0xFFFF;

    __asm__ volatile("fnstcw %0" : "=m" (cw) : );
    return cw;
}

void
setcontrolword(unsigned short x)
{
    volatile unsigned short cw = getcontrolword();

    cw &= FPU_RESERVED;
    cw |= x;
    __asm__ volatile("fldcw %0" :: "m" (cw));
}
//
// end of code derived from Cygwin's crt0.c
//

volatile int    step = 0;  // tells which step of demo we're currently in
jmp_buf         trapoline; // location+status for signal handlers to longjmp to

void
segv_handler(int x)
{
    printf("step %d: SIGSEGV handled, continuing\n\n", step++);
    longjmp(trapoline, step);
}

void
fpe_handler(int x)
{
    printf("step %d: SIGFPE handled, continuing\n\n", step++);
    longjmp(trapoline, step);
}

int
main()
{
    unsigned short      cw = 0x0300;     // desired control word setting
    signed int          i  = 0x7FFFFFFF; // number i such that i*i overflows

    printf("--- initial FPU state at start of program execution ---\n");
    printf("initial cw: %04X\n", getcontrolword());
    printf("initial sw: %04X\n", getstatusword());
    putchar('\n');

    printf("--- now updating FPU control word ---\n");
    printf("desired cw: %04X\n", cw);
    setcontrolword(cw);
    printf("updated cw: %04X\n", getcontrolword());
    putchar('\n');

    printf("--- setting up signal handlers for SIGSEGV and SIGFPE ---\n");
    signal(SIGSEGV, segv_handler);
    signal(SIGFPE, fpe_handler);
    putchar('\n');

    printf("--- now executing each step of demo in turn ---\n");
    // each exception that's trapped causes step++, missed exception ->fallthru
    switch(setjmp(trapoline)) {
        case 0: // force a SIGSEGV
            printf("step %d should cause a memory fault\n", step);
            printf("step %d: %X\n", step, *(int *) 42);
            putchar('\n');
            ++step;

        case 1: // force a floating overflow exception
            printf("step %d should cause a floating-point overflow\n", step);
            printf("step %d: %f\n", step, 1E200L * 1E200L);
            printf("step %d: current sw %04X\n", step, getstatusword());
            putchar('\n');
            ++step;

        case 2: // force an integer overflow exception
            printf("step %d should cause an integer overflow\n", step);
            printf("step %d: %d\n", step, i * i);
            printf("step %d: current sw %04X\n", step, getstatusword());
            putchar('\n');
            ++step;

        case 3: // all done
            printf("step %d: all done\n", step);
            printf("step %d: current sw %04X\n", step, getstatusword());
            putchar('\n');
            break;
    }

    printf("--- done with demo steps, now preparing to exit ---\n");
    printf("current cw: %04X\n", getcontrolword());
    return 0;
}


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]