Index: gcc/libgfortran/config/fpu-387.h |
diff --git a/gcc/libgfortran/config/fpu-387.h b/gcc/libgfortran/config/fpu-387.h |
index 573fabcac6dead395928394089ab11b82dc44333..5fe51b2d20959b4acaaacf608d286bf5e66db978 100644 |
--- a/gcc/libgfortran/config/fpu-387.h |
+++ b/gcc/libgfortran/config/fpu-387.h |
@@ -1,5 +1,5 @@ |
/* FPU-related code for x86 and x86_64 processors. |
- Copyright 2005, 2007, 2009 Free Software Foundation, Inc. |
+ Copyright 2005, 2007, 2009, 2010 Free Software Foundation, Inc. |
Contributed by Francois-Xavier Coudert <coudert@clipper.ens.fr> |
This file is part of the GNU Fortran 95 runtime library (libgfortran). |
@@ -27,6 +27,26 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
#include "cpuid.h" |
#endif |
+#if defined(__sun__) && defined(__svr4__) |
+#include <signal.h> |
+#include <ucontext.h> |
+ |
+static volatile sig_atomic_t sigill_caught; |
+ |
+static void |
+sigill_hdlr (int sig __attribute((unused)), |
+ siginfo_t *sip __attribute__((unused)), |
+ ucontext_t *ucp) |
+{ |
+ sigill_caught = 1; |
+ /* Set PC to the instruction after the faulting one to skip over it, |
+ otherwise we enter an infinite loop. 4 is the size of the stmxcsr |
+ instruction. */ |
+ ucp->uc_mcontext.gregs[EIP] += 4; |
+ setcontext (ucp); |
+} |
+#endif |
+ |
static int |
has_sse (void) |
{ |
@@ -36,6 +56,31 @@ has_sse (void) |
if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) |
return 0; |
+#if defined(__sun__) && defined(__svr4__) |
+ /* Solaris 2 before Solaris 9 4/04 cannot execute SSE instructions even |
+ if the CPU supports them. Programs receive SIGILL instead, so check |
+ for that at runtime. */ |
+ |
+ if (edx & bit_SSE) |
+ { |
+ struct sigaction act, oact; |
+ unsigned int cw_sse; |
+ |
+ act.sa_handler = sigill_hdlr; |
+ sigemptyset (&act.sa_mask); |
+ /* Need to set SA_SIGINFO so a ucontext_t * is passed to the handler. */ |
+ act.sa_flags = SA_SIGINFO; |
+ sigaction (SIGILL, &act, &oact); |
+ |
+ asm volatile ("stmxcsr %0" : "=m" (cw_sse)); |
+ |
+ sigaction (SIGILL, &oact, NULL); |
+ |
+ if (sigill_caught) |
+ return 0; |
+ } |
+#endif /* __sun__ && __svr4__ */ |
+ |
return edx & bit_SSE; |
#else |
return 1; |