Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanny Smith <dannysmith@users.sourceforge.net>2006-07-03 14:32:58 +0400
committerDanny Smith <dannysmith@users.sourceforge.net>2006-07-03 14:32:58 +0400
commitf34428eb356a001928e1786d51cbfe216ebeef83 (patch)
treed6319e46a0cc4bdaae18f49f4a4ad821677f895e /winsup/mingw/mingwex
parent69d5f3329f4869d6d0e20f610926934fc0044dce (diff)
Support SSE float environment in fenv.h functions.
* cpu_features.c: New file. * cpu_features.h: New file. * crt1.c: Include "cpu_features.h". (__mingw_CRTStartup): Call cpu_features_init(). * Makefile.in (MING_OBJS): Add cpu_features.c. (SRCDIST_FILES): Add cpu_features.c, cpu_features.h. * include/fenv,h ( fenv_t;): Append __mxcsr field. (__MXCSR_EXCEPT_FLAG_SHIFT): New define. (__MXCSR_EXCEPT_MASK_SHIFT): New define. (__MXCSR_ROUND_FLAG_SHIFT): New define. * mingwex/feclearexcept.c: Include "cpu_features.h". Handle SSE environment. * mingwex/fegetenv.c: Likewise. * mingwex/feholdexcept.c: Likewise. * mingwex/fesetenv.c: Likewise. * mingwex/fesetexceptflag.c: Likewise. * mingwex/fesetround.c: Likewise. * mingwex/fetestexcept.c: Likewise. * mingwex/feupdateenv.c: Likewise. * mingwex/fegetround.c: Add comment.
Diffstat (limited to 'winsup/mingw/mingwex')
-rw-r--r--winsup/mingw/mingwex/feclearexcept.c11
-rw-r--r--winsup/mingw/mingwex/fegetenv.c6
-rw-r--r--winsup/mingw/mingwex/fegetround.c5
-rw-r--r--winsup/mingw/mingwex/feholdexcept.c14
-rw-r--r--winsup/mingw/mingwex/fesetenv.c18
-rw-r--r--winsup/mingw/mingwex/fesetexceptflag.c11
-rw-r--r--winsup/mingw/mingwex/fesetround.c11
-rw-r--r--winsup/mingw/mingwex/fetestexcept.c20
-rw-r--r--winsup/mingw/mingwex/feupdateenv.c14
9 files changed, 99 insertions, 11 deletions
diff --git a/winsup/mingw/mingwex/feclearexcept.c b/winsup/mingw/mingwex/feclearexcept.c
index 8c943893b..a68884f41 100644
--- a/winsup/mingw/mingwex/feclearexcept.c
+++ b/winsup/mingw/mingwex/feclearexcept.c
@@ -1,4 +1,5 @@
#include <fenv.h>
+#include "cpu_features.h"
/* 7.6.2.1
The feclearexcept function clears the supported exceptions
@@ -7,9 +8,17 @@
int feclearexcept (int excepts)
{
fenv_t _env;
+ excepts &= FE_ALL_EXCEPT;
__asm__ volatile ("fnstenv %0;" : "=m" (_env)); /* get the env */
- _env.__status_word &= ~(excepts & FE_ALL_EXCEPT); /* clear the except */
+ _env.__status_word &= ~excepts; /* clear the except */
__asm__ volatile ("fldenv %0;" :: "m" (_env)); /*set the env */
+ if (__HAS_SSE)
+ {
+ unsigned _csr;
+ __asm__ volatile("stmxcsr %0" : "=m" (_csr)); /* get the register */
+ _csr &= ~excepts; /* clear the except */
+ __asm__ volatile("ldmxcsr %0" : : "m" (_csr)); /* set the register */
+ }
return 0;
}
diff --git a/winsup/mingw/mingwex/fegetenv.c b/winsup/mingw/mingwex/fegetenv.c
index 930105673..0c5d591e7 100644
--- a/winsup/mingw/mingwex/fegetenv.c
+++ b/winsup/mingw/mingwex/fegetenv.c
@@ -1,4 +1,5 @@
#include <fenv.h>
+#include "cpu_features.h"
/* 7.6.4.1
The fegetenv function stores the current floating-point environment
@@ -10,5 +11,10 @@ int fegetenv (fenv_t * envp)
/* fnstenv sets control word to non-stop for all exceptions, so we
need to reload our env to restore the original mask. */
__asm__ ("fldenv %0" : : "m" (*envp));
+
+ /* And the SSE environment. */
+ if (__HAS_SSE)
+ __asm__ ("stmxcsr %0" : "=m" (envp->__mxcsr));
+
return 0;
}
diff --git a/winsup/mingw/mingwex/fegetround.c b/winsup/mingw/mingwex/fegetround.c
index 076b1068c..01d42849f 100644
--- a/winsup/mingw/mingwex/fegetround.c
+++ b/winsup/mingw/mingwex/fegetround.c
@@ -1,4 +1,5 @@
#include <fenv.h>
+#include "cpu_features.h"
/* 7.6.3.1
The fegetround function returns the value of the rounding direction
@@ -9,6 +10,10 @@ fegetround (void)
{
unsigned short _cw;
__asm__ ("fnstcw %0;" : "=m" (_cw));
+
+ /* If the MXCSR flag is different, there is no way to indicate, so just
+ report the FPU flag. */
return _cw
& (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO);
+
}
diff --git a/winsup/mingw/mingwex/feholdexcept.c b/winsup/mingw/mingwex/feholdexcept.c
index 8d4a3f67b..66912d85d 100644
--- a/winsup/mingw/mingwex/feholdexcept.c
+++ b/winsup/mingw/mingwex/feholdexcept.c
@@ -1,4 +1,5 @@
#include <fenv.h>
+#include "cpu_features.h"
/* 7.6.4.2
The feholdexcept function saves the current floating-point
@@ -12,5 +13,18 @@ int feholdexcept (fenv_t * envp)
/* fnstenv sets control word to non-stop for all exceptions, so all we
need to do is clear the exception flags. */
__asm__ ("fnclex");
+
+ if (__HAS_SSE)
+ {
+ unsigned int _csr;
+ /* Save the SSE MXCSR register. */
+ __asm__ ("stmxcsr %0" : "=m" (envp->__mxcsr));
+ /* Clear the exception flags. */
+ _csr = envp->__mxcsr & ~FE_ALL_EXCEPT;
+ /* Set exception mask to non-stop */
+ _csr |= (FE_ALL_EXCEPT << __MXCSR_EXCEPT_MASK_SHIFT) /*= 0x1f80 */;
+ __asm__ volatile ("ldmxcsr %0" : : "m" (_csr));
+ }
+
return 0;
}
diff --git a/winsup/mingw/mingwex/fesetenv.c b/winsup/mingw/mingwex/fesetenv.c
index 3d7b5604a..105a0af10 100644
--- a/winsup/mingw/mingwex/fesetenv.c
+++ b/winsup/mingw/mingwex/fesetenv.c
@@ -1,5 +1,6 @@
#include <fenv.h>
#include <float.h>
+#include "cpu_features.h"
/* 7.6.4.3
The fesetenv function establishes the floating-point environment
@@ -15,6 +16,11 @@ extern void (*_imp___fpreset)( void ) ;
int fesetenv (const fenv_t * envp)
{
+ /* Default mxcsr status is to mask all exceptions. All other bits
+ are zero. */
+
+ unsigned int _csr = FE_ALL_EXCEPT << __MXCSR_EXCEPT_MASK_SHIFT /*= 0x1f80 */;
+
if (envp == FE_PC64_ENV)
/*
* fninit initializes the control register to 0x37f,
@@ -37,7 +43,15 @@ int fesetenv (const fenv_t * envp)
_fpreset();
else
- __asm__ ("fldenv %0;" : : "m" (*envp));
-
+ {
+ __asm__ ("fldenv %0;" : : "m" (*envp));
+ /* Setting the reserved high order bits of MXCSR causes a segfault */
+ _csr = envp ->__mxcsr & 0xffff;
+ }
+
+ /* Set MXCSR */
+ if (__HAS_SSE)
+ __asm__ volatile ("ldmxcsr %0" : : "m" (_csr));
+
return 0;
}
diff --git a/winsup/mingw/mingwex/fesetexceptflag.c b/winsup/mingw/mingwex/fesetexceptflag.c
index 7f4b8e562..876174b69 100644
--- a/winsup/mingw/mingwex/fesetexceptflag.c
+++ b/winsup/mingw/mingwex/fesetexceptflag.c
@@ -1,4 +1,5 @@
#include <fenv.h>
+#include "cpu_features.h"
/* 7.6.2.4
The fesetexceptflag function sets the complete status for those
@@ -18,5 +19,15 @@ int fesetexceptflag (const fexcept_t * flagp, int excepts)
_env.__status_word &= ~excepts;
_env.__status_word |= (*flagp & excepts);
__asm__ volatile ("fldenv %0;" : : "m" (_env));
+
+ if (__HAS_SSE)
+ {
+ unsigned int _csr;
+ __asm__ __volatile__("stmxcsr %0" : "=m" (_csr));
+ _csr &= ~excepts;
+ _csr |= *flagp & excepts;
+ __asm__ volatile ("ldmxcsr %0" : : "m" (_csr));
+ }
+
return 0;
}
diff --git a/winsup/mingw/mingwex/fesetround.c b/winsup/mingw/mingwex/fesetround.c
index a8cef86a4..e90dbb4e7 100644
--- a/winsup/mingw/mingwex/fesetround.c
+++ b/winsup/mingw/mingwex/fesetround.c
@@ -1,4 +1,6 @@
#include <fenv.h>
+#include "cpu_features.h"
+
/* 7.6.3.2
The fesetround function establishes the rounding direction
represented by its argument round. If the argument is not equal
@@ -15,5 +17,14 @@ int fesetround (int mode)
_cw &= ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO);
_cw |= mode;
__asm__ volatile ("fldcw %0;" : : "m" (_cw));
+
+ if (__HAS_SSE)
+ {
+ __asm__ volatile ("stmxcsr %0" : "=m" (_cw));
+ _cw &= ~ 0x6000;
+ _cw |= (mode << __MXCSR_ROUND_FLAG_SHIFT);
+ __asm__ volatile ("ldmxcsr %0" : : "m" (_cw));
+ }
+
return 0;
}
diff --git a/winsup/mingw/mingwex/fetestexcept.c b/winsup/mingw/mingwex/fetestexcept.c
index 6934ed925..062d585eb 100644
--- a/winsup/mingw/mingwex/fetestexcept.c
+++ b/winsup/mingw/mingwex/fetestexcept.c
@@ -1,4 +1,5 @@
-#include <fenv.h>
+#include <fenv.h>
+#include "cpu_features.h"
/* 7.6.2.5
The fetestexcept function determines which of a specified subset of
the exception flags are currently set. The excepts argument
@@ -9,7 +10,18 @@
int fetestexcept (int excepts)
{
- unsigned short _sw;
- __asm__ ("fnstsw %%ax" : "=a" (_sw));
- return _sw & excepts & FE_ALL_EXCEPT;
+
+ unsigned int _res;
+ __asm__ ("fnstsw %%ax" : "=a" (_res));
+
+
+ /* If SSE supported, return the union of the FPU and SSE flags. */
+ if (__HAS_SSE)
+ {
+ unsigned int _csr;
+ __asm__ volatile("stmxcsr %0" : "=m" (_csr));
+ _res |= _csr;
+ }
+
+ return (_res & excepts & FE_ALL_EXCEPT);
}
diff --git a/winsup/mingw/mingwex/feupdateenv.c b/winsup/mingw/mingwex/feupdateenv.c
index f414837f5..e37566b02 100644
--- a/winsup/mingw/mingwex/feupdateenv.c
+++ b/winsup/mingw/mingwex/feupdateenv.c
@@ -1,4 +1,5 @@
#include <fenv.h>
+#include "cpu_features.h"
/* 7.6.4.4
The feupdateenv function saves the currently raised exceptions in
@@ -8,13 +9,18 @@
set by a call to feholdexcept or fegetenv, or equal the macro
FE_DFL_ENV or an implementation-defined environment macro. */
-/* FIXME: this works but surely there must be a better way. */
int feupdateenv (const fenv_t * envp)
{
- unsigned int _fexcept = fetestexcept (FE_ALL_EXCEPT); /*save excepts */
+ unsigned int _fexcept;
+ __asm__ ("fnstsw %%ax" : "=a" (_fexcept)); /*save excepts */
+ if (__HAS_SSE)
+ {
+ unsigned int _csr;
+ __asm__ ("stmxcsr %0" : "=m" (_csr));
+ _fexcept |= _csr;
+ }
fesetenv (envp); /* install the env */
- feraiseexcept (_fexcept); /* raise the execept */
+ feraiseexcept (_fexcept & FE_ALL_EXCEPT); /* raise the execeptions */
return 0;
}
-