PATCH: Fix SSE and SSE2 (take 2)
H. J. Lu
hjl@lucon.org
Sat May 24 00:18:00 GMT 2003
On Wed, May 21, 2003 at 11:46:04PM -0700, H. J. Lu wrote:
> MMX is not that useful when we have to support x87. I don't think we
> should even bother with it. We should support SSE and SSE2 instead.
> I fixed a typo in sysdeps/i386/fpu/feenablxcpt.c. We switched stmxcsr
> with ldmxcsr. Also we should left shift MXCSR control word by 7.
>
>
It turns out that there are many thing wrong. We should check
GL(dl_hwcap) not GL(dl_hwcap_mask) for SSE and SSE2.
H.J.
-------------- next part --------------
2003-05-23 H.J. Lu <hongjiu.lu@intel.com>
* elf/dl-support.c (_dl_hwcap): New.
(_dl_aux_init): Initialize GL(dl_hwcap).
* sysdeps/i386/fpu/fclrexcpt.c: Include <unistd.h>, <ldsodefs.h>
and <dl-procinfo.h>.
(__feclearexcept): Clear MXCSR if needed.
* sysdeps/i386/fpu/fsetexcptflg.c: Likewise.
* sysdeps/i386/fpu/fedisblxcpt.c (fedisableexcept): Check
GL(dl_hwcap) instead of GL(dl_hwcap_mask). Also set MXCSR for
HWCAP_I386_XMM2.
* sysdeps/i386/fpu/feholdexcpt.c (feholdexcept): Likewise.
* sysdeps/i386/fpu/fesetround.c (fesetround): Likewise.
* sysdeps/i386/fpu/ftestexcept.c (fetestexcept): Likewise.
* sysdeps/i386/fpu/fedisblxcpt.c (fedisableexcept): Left shift
MXCSR control word by 7.
* sysdeps/i386/fpu/feenablxcpt.c (feenableexcept): Likewise.
Fix typo.
* sysdeps/i386/fpu_control.h (_FPU_GETCW): Commented out.
(_FPU_SETCW): Likewise.
* sysdeps/i386/setfpucw.c: New file. Support SSE and SSE2.
--- libc/elf/dl-support.c.p4 2003-05-06 19:22:16.000000000 -0700
+++ libc/elf/dl-support.c 2003-05-23 16:48:03.000000000 -0700
@@ -123,6 +123,7 @@ int _dl_correct_cache_id = _DL_CACHE_DEF
struct ElfW(Phdr) *_dl_phdr;
size_t _dl_phnum;
+unsigned long int _dl_hwcap;
#ifdef NEED_DL_SYSINFO
/* Needed for improved syscall handling on at least x86/Linux. */
@@ -167,6 +168,9 @@ _dl_aux_init (ElfW(auxv_t) *av)
case AT_PHNUM:
GL(dl_phnum) = av->a_un.a_val;
break;
+ case AT_HWCAP:
+ GL(dl_hwcap) = av->a_un.a_val;
+ break;
#ifdef NEED_DL_SYSINFO
case AT_SYSINFO:
GL(dl_sysinfo) = av->a_un.a_val;
--- libc/sysdeps/i386/fpu/fclrexcpt.c.p4 2001-07-05 21:55:53.000000000 -0700
+++ libc/sysdeps/i386/fpu/fclrexcpt.c 2003-05-23 15:36:08.000000000 -0700
@@ -19,6 +19,9 @@
02111-1307 USA. */
#include <fenv.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
int
__feclearexcept (int excepts)
@@ -38,6 +41,21 @@ __feclearexcept (int excepts)
/* Put the new data in effect. */
__asm__ ("fldenv %0" : : "m" (*&temp));
+ /* If the CPU supports SSE, we clear the MXCSR as well. */
+ if ((GL(dl_hwcap) & (HWCAP_I386_XMM | HWCAP_I386_XMM2)) != 0)
+ {
+ unsigned int xnew_exc;
+
+ /* Get the current MXCSR. */
+ __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc));
+
+ /* Clear the relevant bits. */
+ xnew_exc &= excepts ^ FE_ALL_EXCEPT;
+
+ /* Put the new data in effect. */
+ __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc));
+ }
+
/* Success. */
return 0;
}
--- libc/sysdeps/i386/fpu/fedisblxcpt.c.p4 2003-04-29 08:38:11.000000000 -0700
+++ libc/sysdeps/i386/fpu/fedisblxcpt.c 2003-05-23 15:36:12.000000000 -0700
@@ -38,15 +38,15 @@ fedisableexcept (int excepts)
new_exc |= excepts;
__asm__ ("fldcw %0" : : "m" (*&new_exc));
- /* If the CPU supports SSE we set the MXCSR as well. */
- if ((GL(dl_hwcap_mask) & HWCAP_I386_XMM) != 0)
+ /* If the CPU supports SSE, we set the MXCSR as well. */
+ if ((GL(dl_hwcap) & (HWCAP_I386_XMM | HWCAP_I386_XMM2)) != 0)
{
unsigned int xnew_exc;
- /* Get the current control word. */
+ /* Get the current MXCSR. */
__asm__ ("stmxcsr %0" : "=m" (*&xnew_exc));
- xnew_exc |= excepts;
+ xnew_exc |= excepts << 7;
__asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc));
}
--- libc/sysdeps/i386/fpu/feenablxcpt.c.p4 2003-04-29 08:38:11.000000000 -0700
+++ libc/sysdeps/i386/fpu/feenablxcpt.c 2003-05-23 15:36:15.000000000 -0700
@@ -38,17 +38,17 @@ feenableexcept (int excepts)
new_exc &= ~excepts;
__asm__ ("fldcw %0" : : "m" (*&new_exc));
- /* If the CPU supports SSE we set the MXCSR as well. */
- if ((GL(dl_hwcap_mask) & HWCAP_I386_XMM) != 0)
+ /* If the CPU supports SSE, we set the MXCSR as well. */
+ if ((GL(dl_hwcap) & (HWCAP_I386_XMM | HWCAP_I386_XMM2)) != 0)
{
unsigned int xnew_exc;
- /* Get the current control word. */
- __asm__ ("ldmxcsr %0" : "=m" (*&xnew_exc));
+ /* Get the current MXCSR. */
+ __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc));
- xnew_exc &= ~excepts;
+ xnew_exc &= (~excepts) << 7;
- __asm__ ("stmxcsr %0" : : "m" (*&xnew_exc));
+ __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc));
}
return old_exc;
--- libc/sysdeps/i386/fpu/feholdexcpt.c.p4 2003-04-29 08:38:11.000000000 -0700
+++ libc/sysdeps/i386/fpu/feholdexcpt.c 2003-05-23 15:36:19.000000000 -0700
@@ -35,12 +35,12 @@ feholdexcept (fenv_t *envp)
work = envp->__control_word | 0x3f;
__asm__ ("fldcw %0" : : "m" (*&work));
- /* If the CPU supports SSE we set the MXCSR as well. */
- if ((GL(dl_hwcap_mask) & HWCAP_I386_XMM) != 0)
+ /* If the CPU supports SSE, we set the MXCSR as well. */
+ if ((GL(dl_hwcap) & (HWCAP_I386_XMM | HWCAP_I386_XMM2)) != 0)
{
unsigned int xwork;
- /* Get the current control word. */
+ /* Get the current MXCSR. */
__asm__ ("stmxcsr %0" : "=m" (*&xwork));
/* Set all exceptions to non-stop. */
--- libc/sysdeps/i386/fpu/fesetround.c.p4 2003-05-01 20:06:49.000000000 -0700
+++ libc/sysdeps/i386/fpu/fesetround.c 2003-05-23 15:36:24.000000000 -0700
@@ -37,8 +37,8 @@ fesetround (int round)
cw |= round;
__asm__ ("fldcw %0" : : "m" (*&cw));
- /* If the CPU supports SSE we set the MXCSR as well. */
- if ((GL(dl_hwcap_mask) & HWCAP_I386_XMM) != 0)
+ /* If the CPU supports SSE, we set the MXCSR as well. */
+ if ((GL(dl_hwcap) & (HWCAP_I386_XMM | HWCAP_I386_XMM2)) != 0)
{
unsigned int xcw;
--- libc/sysdeps/i386/fpu/fsetexcptflg.c.p4 2001-07-05 21:55:53.000000000 -0700
+++ libc/sysdeps/i386/fpu/fsetexcptflg.c 2003-05-23 15:36:27.000000000 -0700
@@ -21,6 +21,9 @@
#include <fenv.h>
#include <math.h>
#include <bp-sym.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
int
__fesetexceptflag (const fexcept_t *flagp, int excepts)
@@ -39,6 +42,22 @@ __fesetexceptflag (const fexcept_t *flag
the next floating-point instruction. */
__asm__ ("fldenv %0" : : "m" (*&temp));
+ /* If the CPU supports SSE, we set the MXCSR as well. */
+ if ((GL(dl_hwcap) & (HWCAP_I386_XMM | HWCAP_I386_XMM2)) != 0)
+ {
+ unsigned int xnew_exc;
+
+ /* Get the current MXCSR. */
+ __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc));
+
+ /* Set the relevant bits. */
+ xnew_exc &= ~(excepts & FE_ALL_EXCEPT);
+ xnew_exc |= *flagp & excepts & FE_ALL_EXCEPT;
+
+ /* Put the new data in effect. */
+ __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc));
+ }
+
/* Success. */
return 0;
}
--- libc/sysdeps/i386/fpu/ftestexcept.c.p4 2003-05-01 20:06:49.000000000 -0700
+++ libc/sysdeps/i386/fpu/ftestexcept.c 2003-05-23 15:36:33.000000000 -0700
@@ -32,8 +32,8 @@ fetestexcept (int excepts)
/* Get current exceptions. */
__asm__ ("fnstsw %0" : "=a" (temp));
- /* If the CPU supports SSE we test the MXCSR as well. */
- if ((GL(dl_hwcap_mask) & HWCAP_I386_XMM) != 0)
+ /* If the CPU supports SSE, we test the MXCSR as well. */
+ if ((GL(dl_hwcap) & (HWCAP_I386_XMM | HWCAP_I386_XMM2)) != 0)
__asm__ ("stmxcsr %0" : "=m" (*&xtemp));
return (temp | xtemp) & excepts & FE_ALL_EXCEPT;
--- libc/sysdeps/i386/fpu_control.h.p4 2001-07-05 21:55:52.000000000 -0700
+++ libc/sysdeps/i386/fpu_control.h 2003-05-23 15:42:59.000000000 -0700
@@ -88,9 +88,12 @@
/* Type of the control word. */
typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__)));
+#if 0
+/* Need to set MXCSR for SSE/SSE2. */
/* Macros for accessing the hardware control word. */
#define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw))
#define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw))
+#endif
/* Default control word set at startup. */
extern fpu_control_t __fpu_control;
--- libc/sysdeps/i386/setfpucw.c.p4 2003-05-23 15:51:14.000000000 -0700
+++ libc/sysdeps/i386/setfpucw.c 2003-05-23 17:15:33.000000000 -0700
@@ -0,0 +1,54 @@
+/* Set the FPU control word for x86.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <math.h>
+#include <fpu_control.h>
+#include <fenv.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <dl-procinfo.h>
+
+void
+__setfpucw (fpu_control_t set)
+{
+ fpu_control_t cw;
+
+ /* Fetch the current control word. */
+ __asm__ ("fnstcw %0" : "=m" (*&cw));
+
+ /* Preserve the reserved bits, and set the rest as the user
+ specified (or the default, if the user gave zero). */
+ cw &= _FPU_RESERVED;
+ cw |= set & ~_FPU_RESERVED;
+
+ __asm__ ("fldcw %0" : : "m" (*&cw));
+
+ /* If the CPU supports SSE, we set the MXCSR as well. */
+ if ((GL(dl_hwcap) & (HWCAP_I386_XMM | HWCAP_I386_XMM2)) != 0)
+ {
+ unsigned int xnew_exc;
+
+ /* Get the current MXCSR. */
+ __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc));
+
+ xnew_exc |= ((set & 0xc00) << 3) | ((set & FE_ALL_EXCEPT) << 7);
+
+ __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc));
+ }
+}
More information about the Libc-alpha
mailing list