[Cfp-interest] functions - fesetexcept implementable on x87?

Jim Thomas jwthomas at cup.hp.com
Mon Aug 2 16:29:19 PDT 2010


We have an outstanding issue, raised by Fred, about whether the 754-2008 
raiseFlags function, which we've named fesetexcept, can be implemented 
for x87(in the absence of SSE) - in particular, whether the function can 
reasonably avoid trapping when exceptions are unmasked. After some 
experiments and discussion with Marius it appears that it cannot. 
raiseFlags can be implemented to set flag bits without immediately 
triggering an unmasked exception, but then a subsequent FP operation 
will trigger one. This is the same behavior as would ensue from a FP 
operation.

I think the Functions spec can just give the 754-2008 definition of this 
function, though there may be an issue for the Alternate Exception 
Handling spec (or x87 implementations of it).

-Jim


[jwthomas at abacus ~]$ cat x.c
#include <stdint.h>

#pragma STDC FENV_ACCESS ON

#define EXCEPTMASK 0x3d

typedef struct {
        unsigned short int __control_word;
        unsigned short int __unused1;
        unsigned short int __status_word;
        unsigned short int __unused2;
        unsigned short int __tags;
        unsigned short int __unused3;
        unsigned int __eip;
        unsigned short int __cs_selector;
        unsigned int __opcode:11;
        unsigned int __unused4:5;
        unsigned int __data_offset;
        unsigned short int __data_selector;
        unsigned short int __unused5;
        unsigned int __mxcsr;
        unsigned short int __decround_mode;
} Fenv_t;

void Fesettrapenable(int excepts) {
        uint16_t cw, trapbits;
        uint32_t mxcsr;
        trapbits = ~excepts & EXCEPTMASK;
        __asm__ volatile ("fnstcw %0\n"
                 "stmxcsr %1" : "=m" (cw), "=m" (mxcsr));
        cw &= ~EXCEPTMASK;
        cw |= trapbits;
        mxcsr &=~ (EXCEPTMASK<<7);
        mxcsr |= trapbits << 7;
        __asm__ volatile ("fldcw %0\n"
                 "ldmxcsr %1" : : "m" (cw), "m" (mxcsr));
}

int Fesetexcept(int excepts) {
        Fenv_t env;
        excepts &= EXCEPTMASK;
        __asm__ volatile ("fnstenv %0" : "=m" (env));
        env.__status_word |= excepts;
        __asm__ volatile ("fldenv %0" : : "m" (env));
        __asm__ volatile ("stmxcsr %0" : "=m" (env.__mxcsr));
        env.__mxcsr |= excepts;
        __asm__ volatile ("ldmxcsr %0" : : "m" (env.__mxcsr));
        return 0;
}

#include <stdio.h>
#include <fenv.h>

int main() {
        //long double x = .1l;
        int excepts;
        Fesettrapenable(FE_ALL_EXCEPT);
        feclearexcept(FE_ALL_EXCEPT);
        Fesetexcept(EXCEPTMASK);
        excepts = fetestexcept(FE_ALL_EXCEPT);
        printf("%.8x\n", excepts);
        //x *= x;
}
[jwthomas at abacus ~]$ gcc -std=c99 x.c -lm -g
[jwthomas at abacus ~]$ a.out
0000003d

If the // commenting is removed, the expected trap occurs after printf:
[jwthomas at abacus ~]$ a.out
0000003d
Floating exception



More information about the Cfp-interest mailing list