www.delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2009/12/09/01:16:03

X-Recipient: archive-cygwin AT delorie DOT com
X-SWARE-Spam-Status: No, hits=-2.9 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS,SPF_PASS
X-Spam-Check-By: sourceware.org
To: cygwin AT cygwin DOT com
From: Mark Geisert <mark AT maxrnd DOT com>
Subject: Re: I want my FPE!
Date: Wed, 9 Dec 2009 06:15:14 +0000 (UTC)
Lines: 137
Message-ID: <loom.20091209T065622-863@post.gmane.org>
References: <loom DOT 20090917T213422-417 AT post DOT gmane DOT org> <4AB29DDF DOT 301 AT gmail DOT com>
Mime-Version: 1.0
User-Agent: Loom/3.14 (http://gmane.org/)
X-IsSubscribed: yes
Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Id: <cygwin.cygwin.com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com

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

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019