diff options
Diffstat (limited to 'libgfortran')
-rw-r--r-- | libgfortran/ChangeLog | 9 | ||||
-rw-r--r-- | libgfortran/config/fpu-387.h | 47 |
2 files changed, 55 insertions, 1 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 943e8e1db51..0a69beba590 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,12 @@ +2010-07-12 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * config/fpu-387.h [__sun__ && __svr4__] Include <signal.h>, + <ucontext.h>. + (sigill_caught): New. + (sigill_hdlr): New function + (has_sse) [__sun__ && __svr4__]: Check if SSE instruction causes + SIGILL. + 2010-07-11 Kai Tietz <kai.tietz@onevision.com> PR libfortran/44698 diff --git a/libgfortran/config/fpu-387.h b/libgfortran/config/fpu-387.h index 573fabcac6d..5fe51b2d209 100644 --- a/libgfortran/config/fpu-387.h +++ b/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; |