summary refs log tree commit diff
path: root/sysdeps/powerpc/nofpu
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/powerpc/nofpu')
-rw-r--r--sysdeps/powerpc/nofpu/Versions5
-rw-r--r--sysdeps/powerpc/nofpu/fclrexcpt.c3
-rw-r--r--sysdeps/powerpc/nofpu/fedisblxcpt.c6
-rw-r--r--sysdeps/powerpc/nofpu/feenablxcpt.c9
-rw-r--r--sysdeps/powerpc/nofpu/fegetenv.c10
-rw-r--r--sysdeps/powerpc/nofpu/fegetexcept.c2
-rw-r--r--sysdeps/powerpc/nofpu/fegetround.c2
-rw-r--r--sysdeps/powerpc/nofpu/fesetenv.c10
-rw-r--r--sysdeps/powerpc/nofpu/fesetround.c3
-rw-r--r--sysdeps/powerpc/nofpu/feupdateenv.c7
-rw-r--r--sysdeps/powerpc/nofpu/fgetexcptflg.c2
-rw-r--r--sysdeps/powerpc/nofpu/fraiseexcpt.c5
-rw-r--r--sysdeps/powerpc/nofpu/fsetexcptflg.c4
-rw-r--r--sysdeps/powerpc/nofpu/ftestexcept.c2
-rw-r--r--sysdeps/powerpc/nofpu/get-rounding-mode.h2
-rw-r--r--sysdeps/powerpc/nofpu/sim-full.c39
-rw-r--r--sysdeps/powerpc/nofpu/soft-supp.h37
17 files changed, 94 insertions, 54 deletions
diff --git a/sysdeps/powerpc/nofpu/Versions b/sysdeps/powerpc/nofpu/Versions
index 1a29319d5a..8ba6021e9e 100644
--- a/sysdeps/powerpc/nofpu/Versions
+++ b/sysdeps/powerpc/nofpu/Versions
@@ -17,4 +17,9 @@ libc {
     __gtdf2; __gtsf2;
     __ltdf2; __ltsf2;
   }
+  GLIBC_PRIVATE {
+    __sim_exceptions_thread;
+    __sim_disabled_exceptions_thread;
+    __sim_round_mode_thread;
+  }
 }
diff --git a/sysdeps/powerpc/nofpu/fclrexcpt.c b/sysdeps/powerpc/nofpu/fclrexcpt.c
index fabda0ab98..da0b61a894 100644
--- a/sysdeps/powerpc/nofpu/fclrexcpt.c
+++ b/sysdeps/powerpc/nofpu/fclrexcpt.c
@@ -23,7 +23,8 @@
 int
 __feclearexcept (int x)
 {
-  __sim_exceptions &= ~x;
+  __sim_exceptions_thread &= ~x;
+  SIM_SET_GLOBAL (__sim_exceptions_global, __sim_exceptions_thread);
   return 0;
 }
 
diff --git a/sysdeps/powerpc/nofpu/fedisblxcpt.c b/sysdeps/powerpc/nofpu/fedisblxcpt.c
index e06c8f7676..00490fd6ed 100644
--- a/sysdeps/powerpc/nofpu/fedisblxcpt.c
+++ b/sysdeps/powerpc/nofpu/fedisblxcpt.c
@@ -24,9 +24,11 @@
 int
 fedisableexcept (int x)
 {
-  int old_exceptions = ~__sim_disabled_exceptions & FE_ALL_EXCEPT;
+  int old_exceptions = ~__sim_disabled_exceptions_thread & FE_ALL_EXCEPT;
 
-  __sim_disabled_exceptions |= x;
+  __sim_disabled_exceptions_thread |= x;
+  SIM_SET_GLOBAL (__sim_disabled_exceptions_global,
+		  __sim_disabled_exceptions_thread);
 
   return old_exceptions;
 }
diff --git a/sysdeps/powerpc/nofpu/feenablxcpt.c b/sysdeps/powerpc/nofpu/feenablxcpt.c
index 93249abf6c..09eb823b8b 100644
--- a/sysdeps/powerpc/nofpu/feenablxcpt.c
+++ b/sysdeps/powerpc/nofpu/feenablxcpt.c
@@ -17,16 +17,17 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include "soft-supp.h"
 #include <fenv.h>
 
-extern int __sim_disabled_exceptions;
-
 int
 feenableexcept (int exceptions)
 {
-  int old_exceptions = ~__sim_disabled_exceptions & FE_ALL_EXCEPT;
+  int old_exceptions = ~__sim_disabled_exceptions_thread & FE_ALL_EXCEPT;
 
-  __sim_disabled_exceptions &= ~exceptions;
+  __sim_disabled_exceptions_thread &= ~exceptions;
+  SIM_SET_GLOBAL (__sim_disabled_exceptions_global,
+		  __sim_disabled_exceptions_thread);
 
   return old_exceptions;
 }
diff --git a/sysdeps/powerpc/nofpu/fegetenv.c b/sysdeps/powerpc/nofpu/fegetenv.c
index 51bcef30a1..351e5526c7 100644
--- a/sysdeps/powerpc/nofpu/fegetenv.c
+++ b/sysdeps/powerpc/nofpu/fegetenv.c
@@ -20,18 +20,14 @@
 #include "soft-fp.h"
 #include "soft-supp.h"
 
-extern int __sim_exceptions;
-extern int __sim_disabled_exceptions;
-extern int __sim_round_mode;
-
 int
 __fegetenv (fenv_t *envp)
 {
   fenv_union_t u;
 
-  u.l[0] = __sim_exceptions;
-  u.l[0] |= __sim_round_mode;
-  u.l[1] = __sim_disabled_exceptions;
+  u.l[0] = __sim_exceptions_thread;
+  u.l[0] |= __sim_round_mode_thread;
+  u.l[1] = __sim_disabled_exceptions_thread;
 
   *envp = u.fenv;
 
diff --git a/sysdeps/powerpc/nofpu/fegetexcept.c b/sysdeps/powerpc/nofpu/fegetexcept.c
index ea39a82b73..d907555fb6 100644
--- a/sysdeps/powerpc/nofpu/fegetexcept.c
+++ b/sysdeps/powerpc/nofpu/fegetexcept.c
@@ -23,5 +23,5 @@
 int
 fegetexcept (void)
 {
-  return (__sim_disabled_exceptions ^ FE_ALL_EXCEPT) & FE_ALL_EXCEPT;
+  return (__sim_disabled_exceptions_thread ^ FE_ALL_EXCEPT) & FE_ALL_EXCEPT;
 }
diff --git a/sysdeps/powerpc/nofpu/fegetround.c b/sysdeps/powerpc/nofpu/fegetround.c
index c232ae3794..016602fac6 100644
--- a/sysdeps/powerpc/nofpu/fegetround.c
+++ b/sysdeps/powerpc/nofpu/fegetround.c
@@ -24,5 +24,5 @@
 int
 fegetround (void)
 {
-  return __sim_round_mode;
+  return __sim_round_mode_thread;
 }
diff --git a/sysdeps/powerpc/nofpu/fesetenv.c b/sysdeps/powerpc/nofpu/fesetenv.c
index 3f35909b6d..fa84169836 100644
--- a/sysdeps/powerpc/nofpu/fesetenv.c
+++ b/sysdeps/powerpc/nofpu/fesetenv.c
@@ -26,9 +26,13 @@ __fesetenv (const fenv_t *envp)
   fenv_union_t u;
 
   u.fenv = *envp;
-  __sim_exceptions = u.l[0] & FE_ALL_EXCEPT;
-  __sim_round_mode = u.l[0] & 0x3;
-  __sim_disabled_exceptions = u.l[1];
+  __sim_exceptions_thread = u.l[0] & FE_ALL_EXCEPT;
+  SIM_SET_GLOBAL (__sim_exceptions_global, __sim_exceptions_thread);
+  __sim_round_mode_thread = u.l[0] & 0x3;
+  SIM_SET_GLOBAL (__sim_round_mode_global, __sim_round_mode_thread);
+  __sim_disabled_exceptions_thread = u.l[1];
+  SIM_SET_GLOBAL (__sim_disabled_exceptions_global,
+		  __sim_disabled_exceptions_thread);
   return 0;
 }
 
diff --git a/sysdeps/powerpc/nofpu/fesetround.c b/sysdeps/powerpc/nofpu/fesetround.c
index 028c1300cc..ab0d52f237 100644
--- a/sysdeps/powerpc/nofpu/fesetround.c
+++ b/sysdeps/powerpc/nofpu/fesetround.c
@@ -26,7 +26,8 @@ fesetround (int round)
   if ((unsigned int) round > FE_DOWNWARD)
     return 1;
 
-  __sim_round_mode = round;
+  __sim_round_mode_thread = round;
+  SIM_SET_GLOBAL (__sim_round_mode_global, __sim_round_mode_thread);
 
   return 0;
 }
diff --git a/sysdeps/powerpc/nofpu/feupdateenv.c b/sysdeps/powerpc/nofpu/feupdateenv.c
index 163f673102..8a26cb86d1 100644
--- a/sysdeps/powerpc/nofpu/feupdateenv.c
+++ b/sysdeps/powerpc/nofpu/feupdateenv.c
@@ -28,14 +28,15 @@ __feupdateenv (const fenv_t *envp)
   int saved_exceptions;
 
   /* Save currently set exceptions.  */
-  saved_exceptions = __sim_exceptions;
+  saved_exceptions = __sim_exceptions_thread;
 
   /* Set environment.  */
   fesetenv (envp);
 
   /* Raise old exceptions.  */
-  __sim_exceptions |= saved_exceptions;
-  if (saved_exceptions & ~__sim_disabled_exceptions)
+  __sim_exceptions_thread |= saved_exceptions;
+  SIM_SET_GLOBAL (__sim_exceptions_global, __sim_exceptions_thread);
+  if (saved_exceptions & ~__sim_disabled_exceptions_thread)
     raise (SIGFPE);
 
   return 0;
diff --git a/sysdeps/powerpc/nofpu/fgetexcptflg.c b/sysdeps/powerpc/nofpu/fgetexcptflg.c
index 2373fa4002..b7fd90d71e 100644
--- a/sysdeps/powerpc/nofpu/fgetexcptflg.c
+++ b/sysdeps/powerpc/nofpu/fgetexcptflg.c
@@ -23,7 +23,7 @@
 int
 __fegetexceptflag (fexcept_t *flagp, int excepts)
 {
-  *flagp = (fexcept_t) __sim_exceptions  & excepts & FE_ALL_EXCEPT;
+  *flagp = (fexcept_t) __sim_exceptions_thread & excepts & FE_ALL_EXCEPT;
 
   return 0;
 }
diff --git a/sysdeps/powerpc/nofpu/fraiseexcpt.c b/sysdeps/powerpc/nofpu/fraiseexcpt.c
index cd142b60be..215a70b4bf 100644
--- a/sysdeps/powerpc/nofpu/fraiseexcpt.c
+++ b/sysdeps/powerpc/nofpu/fraiseexcpt.c
@@ -25,8 +25,9 @@
 int
 __feraiseexcept (int x)
 {
-  __sim_exceptions |= x;
-  if (x & ~__sim_disabled_exceptions)
+  __sim_exceptions_thread |= x;
+  SIM_SET_GLOBAL (__sim_exceptions_global, __sim_exceptions_thread);
+  if (x & ~__sim_disabled_exceptions_thread)
     raise (SIGFPE);
   return 0;
 }
diff --git a/sysdeps/powerpc/nofpu/fsetexcptflg.c b/sysdeps/powerpc/nofpu/fsetexcptflg.c
index 3dc368fdda..ee2aa81a4e 100644
--- a/sysdeps/powerpc/nofpu/fsetexcptflg.c
+++ b/sysdeps/powerpc/nofpu/fsetexcptflg.c
@@ -24,7 +24,9 @@ int
 __fesetexceptflag(const fexcept_t *flagp, int excepts)
 {
   /* Ignore exceptions not listed in 'excepts'.  */
-  __sim_exceptions = (__sim_exceptions & ~excepts) | (*flagp & excepts);
+  __sim_exceptions_thread
+    = (__sim_exceptions_thread & ~excepts) | (*flagp & excepts);
+  SIM_SET_GLOBAL (__sim_exceptions_global, __sim_exceptions_thread);
 
   return 0;
 }
diff --git a/sysdeps/powerpc/nofpu/ftestexcept.c b/sysdeps/powerpc/nofpu/ftestexcept.c
index f5d01e881c..42e861da33 100644
--- a/sysdeps/powerpc/nofpu/ftestexcept.c
+++ b/sysdeps/powerpc/nofpu/ftestexcept.c
@@ -23,6 +23,6 @@
 int
 fetestexcept (int x)
 {
-  return __sim_exceptions & x;
+  return __sim_exceptions_thread & x;
 }
 libm_hidden_def (fetestexcept)
diff --git a/sysdeps/powerpc/nofpu/get-rounding-mode.h b/sysdeps/powerpc/nofpu/get-rounding-mode.h
index 20eb81030f..6d327f57c7 100644
--- a/sysdeps/powerpc/nofpu/get-rounding-mode.h
+++ b/sysdeps/powerpc/nofpu/get-rounding-mode.h
@@ -29,7 +29,7 @@
 static inline int
 get_rounding_mode (void)
 {
-  return __sim_round_mode;
+  return __sim_round_mode_thread;
 }
 
 #endif /* get-rounding-mode.h */
diff --git a/sysdeps/powerpc/nofpu/sim-full.c b/sysdeps/powerpc/nofpu/sim-full.c
index e16703323d..fb09d1bc9d 100644
--- a/sysdeps/powerpc/nofpu/sim-full.c
+++ b/sysdeps/powerpc/nofpu/sim-full.c
@@ -21,26 +21,37 @@
 #include "soft-fp.h"
 #include "soft-supp.h"
 
-/* FIXME: these variables should be thread specific (see bugzilla bug
-   15483) and ideally preserved across signal handlers, like hardware
-   FP status words, but the latter is quite difficult to accomplish in
-   userland.  */
-
-/* Global to store sticky exceptions.  */
-int __sim_exceptions __attribute__ ((nocommon));
-libc_hidden_data_def (__sim_exceptions);
+/* Thread-local to store sticky exceptions.  */
+__thread int __sim_exceptions_thread __attribute__ ((nocommon));
+libc_hidden_data_def (__sim_exceptions_thread);
 
 /* By default, no exceptions should trap.  */
-int __sim_disabled_exceptions = 0xffffffff;
-libc_hidden_data_def (__sim_disabled_exceptions);
+__thread int __sim_disabled_exceptions_thread = 0xffffffff;
+libc_hidden_data_def (__sim_disabled_exceptions_thread);
+
+__thread int __sim_round_mode_thread __attribute__ ((nocommon));
+libc_hidden_data_def (__sim_round_mode_thread);
+
+#if SIM_GLOBAL_COMPAT
+int __sim_exceptions_global __attribute__ ((nocommon));
+libc_hidden_data_def (__sim_exceptions_global);
+SIM_COMPAT_SYMBOL (__sim_exceptions_global, __sim_exceptions);
+
+int __sim_disabled_exceptions_global = 0xffffffff;
+libc_hidden_data_def (__sim_disabled_exceptions_global);
+SIM_COMPAT_SYMBOL (__sim_disabled_exceptions_global,
+		   __sim_disabled_exceptions);
 
-int __sim_round_mode __attribute__ ((nocommon));
-libc_hidden_data_def (__sim_round_mode);
+int __sim_round_mode_global __attribute__ ((nocommon));
+libc_hidden_data_def (__sim_round_mode_global);
+SIM_COMPAT_SYMBOL (__sim_round_mode_global, __sim_round_mode);
+#endif
 
 void
 __simulate_exceptions (int x)
 {
-  __sim_exceptions |= x;
-  if (x & ~__sim_disabled_exceptions)
+  __sim_exceptions_thread |= x;
+  SIM_SET_GLOBAL (__sim_exceptions_global, __sim_exceptions_thread);
+  if (x & ~__sim_disabled_exceptions_thread)
     raise (SIGFPE);
 }
diff --git a/sysdeps/powerpc/nofpu/soft-supp.h b/sysdeps/powerpc/nofpu/soft-supp.h
index 18b4550e3b..0a0614aa6a 100644
--- a/sysdeps/powerpc/nofpu/soft-supp.h
+++ b/sysdeps/powerpc/nofpu/soft-supp.h
@@ -33,16 +33,31 @@ typedef union
 
 #endif
 
-/* FIXME: these variables should be thread specific (see bugzilla bug
-   15483) and ideally preserved across signal handlers, like hardware
-   FP status words, but the latter is quite difficult to accomplish in
-   userland.  */
-
-extern int __sim_exceptions;
-libc_hidden_proto (__sim_exceptions);
-extern int __sim_disabled_exceptions;
-libc_hidden_proto (__sim_disabled_exceptions);
-extern int __sim_round_mode;
-libc_hidden_proto (__sim_round_mode);
+extern __thread int __sim_exceptions_thread attribute_tls_model_ie;
+libc_hidden_tls_proto (__sim_exceptions_thread, tls_model ("initial-exec"));
+extern __thread int __sim_disabled_exceptions_thread attribute_tls_model_ie;
+libc_hidden_tls_proto (__sim_disabled_exceptions_thread,
+		       tls_model ("initial-exec"));
+extern __thread int __sim_round_mode_thread attribute_tls_model_ie;
+libc_hidden_tls_proto (__sim_round_mode_thread, tls_model ("initial-exec"));
+
+/* These variables were formerly global, so there are compat symbols
+   for global versions as well.  */
+
+#include <shlib-compat.h>
+#define SIM_GLOBAL_COMPAT SHLIB_COMPAT (libc, GLIBC_2_3_2, GLIBC_2_19)
+#if SIM_GLOBAL_COMPAT
+extern int __sim_exceptions_global;
+libc_hidden_proto (__sim_exceptions_global);
+extern int __sim_disabled_exceptions_global ;
+libc_hidden_proto (__sim_disabled_exceptions_global);
+extern int __sim_round_mode_global;
+libc_hidden_proto (__sim_round_mode_global);
+# define SIM_COMPAT_SYMBOL(GLOBAL_NAME, NAME) \
+  compat_symbol (libc, GLOBAL_NAME, NAME, GLIBC_2_3_2)
+# define SIM_SET_GLOBAL(GLOBAL_VAR, THREAD_VAR) ((GLOBAL_VAR) = (THREAD_VAR))
+#else
+# define SIM_SET_GLOBAL(GLOBAL_VAR, THREAD_VAR) ((void) 0)
+#endif
 
 extern void __simulate_exceptions (int x) attribute_hidden;