diff options
-rw-r--r-- | src/fenv/fegetexceptflag.c | 7 | ||||
-rw-r--r-- | src/fenv/feholdexcept.c | 7 | ||||
-rw-r--r-- | src/fenv/fenv.c | 38 | ||||
-rw-r--r-- | src/fenv/fesetexceptflag.c | 8 | ||||
-rw-r--r-- | src/fenv/feupdateenv.c | 9 | ||||
-rw-r--r-- | src/fenv/i386/fenv.s | 75 |
6 files changed, 144 insertions, 0 deletions
diff --git a/src/fenv/fegetexceptflag.c b/src/fenv/fegetexceptflag.c new file mode 100644 index 00000000..bab0b44f --- /dev/null +++ b/src/fenv/fegetexceptflag.c @@ -0,0 +1,7 @@ +#include <fenv.h> + +int fegetexceptflag(fexcept_t *fp, int mask) +{ + *fp = fetestexcept(mask); + return 0; +} diff --git a/src/fenv/feholdexcept.c b/src/fenv/feholdexcept.c new file mode 100644 index 00000000..4c6da239 --- /dev/null +++ b/src/fenv/feholdexcept.c @@ -0,0 +1,7 @@ +#include <fenv.h> + +int feholdexcept(fenv_t *envp) +{ + fegetenv(envp); + return 0; +} diff --git a/src/fenv/fenv.c b/src/fenv/fenv.c new file mode 100644 index 00000000..f77599bc --- /dev/null +++ b/src/fenv/fenv.c @@ -0,0 +1,38 @@ +#include <fenv.h> + +/* Dummy functions for archs lacking fenv implementation */ + +int feclearexcept(int mask) +{ + return 0; +} + +int feraiseexcept(int mask) +{ + return 0; +} + +int fetestexcept(int mask) +{ + return 0; +} + +int fegetround(void) +{ + return 0; +} + +int fesetround(int r) +{ + return 0; +} + +int fegetenv(fenv_t *envp) +{ + return 0; +} + +int fesetenv(const fenv_t *envp) +{ + return 0; +} diff --git a/src/fenv/fesetexceptflag.c b/src/fenv/fesetexceptflag.c new file mode 100644 index 00000000..af5f102d --- /dev/null +++ b/src/fenv/fesetexceptflag.c @@ -0,0 +1,8 @@ +#include <fenv.h> + +int fesetexceptflag(const fexcept_t *fp, int mask) +{ + feclearexcept(~*fp & mask); + feraiseexcept(*fp & mask); + return 0; +} diff --git a/src/fenv/feupdateenv.c b/src/fenv/feupdateenv.c new file mode 100644 index 00000000..50cef8e5 --- /dev/null +++ b/src/fenv/feupdateenv.c @@ -0,0 +1,9 @@ +#include <fenv.h> + +int feupdateenv(const fenv_t *envp) +{ + int ex = fetestexcept(FE_ALL_EXCEPT); + fesetenv(envp); + feraiseexcept(ex); + return 0; +} diff --git a/src/fenv/i386/fenv.s b/src/fenv/i386/fenv.s new file mode 100644 index 00000000..72d2ed7d --- /dev/null +++ b/src/fenv/i386/fenv.s @@ -0,0 +1,75 @@ +2: not %ecx + sub $32,%esp + fnstenv (%esp) + and %ecx,4(%esp) + or %edx,4(%esp) + fldenv (%esp) + add $32,%esp + ret + +.global feclearexcept +feclearexcept: + xor %eax,%eax + mov 4(%esp),%ecx + xor %edx,%edx + test %ecx,%ecx + jnz 2b + ret + +.global feraiseexcept +feraiseexcept: + xor %eax,%eax + mov 4(%esp),%edx + xor %ecx,%ecx + test %edx,%edx + jnz 2b + ret + +.global fesetround +fesetround: + xor %eax,%eax + mov $0xc00,%ecx + mov 4(%esp),%edx + jmp 2b + +.global fegetround +fegetround: + sub $28,%esp + fnstenv (%esp) + mov 4(%esp),%eax + add $28,%esp + and $0xc,%ah + ret + +.global fegetenv +fegetenv: + mov 4(%esp),%ecx + xor %eax,%eax + fnstenv (%ecx) + ret + +.global fesetenv +fesetenv: + mov 4(%esp),%ecx + xor %eax,%eax + test %ecx,%ecx + jz 1f + fldenv (%ecx) + ret +1: push %eax + push %eax + push %eax + push %eax + push %eax + push %eax + pushl $0x37f + fldenv (%esp) + add $28,%esp + ret + +.global fetestexcept +fetestexcept: + mov 4(%esp),%ecx + fnstsw %ax + and %ecx,%eax + ret |