Home | History | Annotate | Line # | Download | only in i386
crtfastmath.c revision 1.1
      1  1.1  mrg /*
      2  1.1  mrg  * Copyright (C) 2005-2013 Free Software Foundation, Inc.
      3  1.1  mrg  *
      4  1.1  mrg  * This file is free software; you can redistribute it and/or modify it
      5  1.1  mrg  * under the terms of the GNU General Public License as published by the
      6  1.1  mrg  * Free Software Foundation; either version 3, or (at your option) any
      7  1.1  mrg  * later version.
      8  1.1  mrg  *
      9  1.1  mrg  * This file is distributed in the hope that it will be useful, but
     10  1.1  mrg  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  1.1  mrg  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  1.1  mrg  * General Public License for more details.
     13  1.1  mrg  *
     14  1.1  mrg  * Under Section 7 of GPL version 3, you are granted additional
     15  1.1  mrg  * permissions described in the GCC Runtime Library Exception, version
     16  1.1  mrg  * 3.1, as published by the Free Software Foundation.
     17  1.1  mrg  *
     18  1.1  mrg  * You should have received a copy of the GNU General Public License and
     19  1.1  mrg  * a copy of the GCC Runtime Library Exception along with this program;
     20  1.1  mrg  * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     21  1.1  mrg  * <http://www.gnu.org/licenses/>.
     22  1.1  mrg  */
     23  1.1  mrg 
     24  1.1  mrg #define MXCSR_DAZ (1 << 6)	/* Enable denormals are zero mode */
     25  1.1  mrg #define MXCSR_FTZ (1 << 15)	/* Enable flush to zero mode */
     26  1.1  mrg 
     27  1.1  mrg #ifndef __x86_64__
     28  1.1  mrg /* All 64-bit targets have SSE and DAZ;
     29  1.1  mrg    only check them explicitly for 32-bit ones. */
     30  1.1  mrg #include "cpuid.h"
     31  1.1  mrg #endif
     32  1.1  mrg 
     33  1.1  mrg #if !defined __x86_64__ && defined __sun__ && defined __svr4__
     34  1.1  mrg #include <signal.h>
     35  1.1  mrg #include <ucontext.h>
     36  1.1  mrg 
     37  1.1  mrg static volatile sig_atomic_t sigill_caught;
     38  1.1  mrg 
     39  1.1  mrg static void
     40  1.1  mrg sigill_hdlr (int sig __attribute((unused)),
     41  1.1  mrg 	     siginfo_t *sip __attribute__((unused)),
     42  1.1  mrg 	     ucontext_t *ucp)
     43  1.1  mrg {
     44  1.1  mrg   sigill_caught = 1;
     45  1.1  mrg   /* Set PC to the instruction after the faulting one to skip over it,
     46  1.1  mrg      otherwise we enter an infinite loop.  3 is the size of the movaps
     47  1.1  mrg      instruction.  */
     48  1.1  mrg   ucp->uc_mcontext.gregs[EIP] += 3;
     49  1.1  mrg   setcontext (ucp);
     50  1.1  mrg }
     51  1.1  mrg #endif
     52  1.1  mrg 
     53  1.1  mrg static void __attribute__((constructor))
     54  1.1  mrg #ifndef __x86_64__
     55  1.1  mrg /* The i386 ABI only requires 4-byte stack alignment, so this is necessary
     56  1.1  mrg    to make sure the fxsave struct gets correct alignment.
     57  1.1  mrg    See PR27537 and PR28621.  */
     58  1.1  mrg __attribute__ ((force_align_arg_pointer))
     59  1.1  mrg #endif
     60  1.1  mrg set_fast_math (void)
     61  1.1  mrg {
     62  1.1  mrg #ifndef __x86_64__
     63  1.1  mrg   unsigned int eax, ebx, ecx, edx;
     64  1.1  mrg 
     65  1.1  mrg   if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
     66  1.1  mrg     return;
     67  1.1  mrg 
     68  1.1  mrg   if (edx & bit_SSE)
     69  1.1  mrg     {
     70  1.1  mrg       unsigned int mxcsr;
     71  1.1  mrg 
     72  1.1  mrg #if defined __sun__ && defined __svr4__
     73  1.1  mrg       /* Solaris 2 before Solaris 9 4/04 cannot execute SSE instructions even
     74  1.1  mrg 	 if the CPU supports them.  Programs receive SIGILL instead, so check
     75  1.1  mrg 	 for that at runtime.  */
     76  1.1  mrg       struct sigaction act, oact;
     77  1.1  mrg 
     78  1.1  mrg       act.sa_handler = sigill_hdlr;
     79  1.1  mrg       sigemptyset (&act.sa_mask);
     80  1.1  mrg       /* Need to set SA_SIGINFO so a ucontext_t * is passed to the handler.  */
     81  1.1  mrg       act.sa_flags = SA_SIGINFO;
     82  1.1  mrg       sigaction (SIGILL, &act, &oact);
     83  1.1  mrg 
     84  1.1  mrg       /* We need a single SSE instruction here so the handler can safely skip
     85  1.1  mrg 	 over it.  */
     86  1.1  mrg       __asm__ volatile ("movaps %xmm0,%xmm0");
     87  1.1  mrg 
     88  1.1  mrg       sigaction (SIGILL, &oact, NULL);
     89  1.1  mrg 
     90  1.1  mrg       if (sigill_caught)
     91  1.1  mrg 	return;
     92  1.1  mrg #endif /* __sun__ && __svr4__ */
     93  1.1  mrg 
     94  1.1  mrg       if (edx & bit_FXSAVE)
     95  1.1  mrg 	{
     96  1.1  mrg 	  /* Check if DAZ is available.  */
     97  1.1  mrg 	  struct
     98  1.1  mrg 	    {
     99  1.1  mrg 	      unsigned short cwd;
    100  1.1  mrg 	      unsigned short swd;
    101  1.1  mrg 	      unsigned short twd;
    102  1.1  mrg 	      unsigned short fop;
    103  1.1  mrg 	      unsigned int fip;
    104  1.1  mrg 	      unsigned int fcs;
    105  1.1  mrg 	      unsigned int foo;
    106  1.1  mrg 	      unsigned int fos;
    107  1.1  mrg 	      unsigned int mxcsr;
    108  1.1  mrg 	      unsigned int mxcsr_mask;
    109  1.1  mrg 	      unsigned int st_space[32];
    110  1.1  mrg 	      unsigned int xmm_space[32];
    111  1.1  mrg 	      unsigned int padding[56];
    112  1.1  mrg 	    } __attribute__ ((aligned (16))) fxsave;
    113  1.1  mrg 
    114  1.1  mrg 	  /* This is necessary since some implementations of FXSAVE
    115  1.1  mrg 	     do not modify reserved areas within the image.  */
    116  1.1  mrg 	  fxsave.mxcsr_mask = 0;
    117  1.1  mrg 
    118  1.1  mrg 	  __builtin_ia32_fxsave (&fxsave);
    119  1.1  mrg 
    120  1.1  mrg 	  mxcsr = fxsave.mxcsr;
    121  1.1  mrg 
    122  1.1  mrg 	  if (fxsave.mxcsr_mask & MXCSR_DAZ)
    123  1.1  mrg 	    mxcsr |= MXCSR_DAZ;
    124  1.1  mrg 	}
    125  1.1  mrg       else
    126  1.1  mrg 	mxcsr = __builtin_ia32_stmxcsr ();
    127  1.1  mrg 
    128  1.1  mrg       mxcsr |= MXCSR_FTZ;
    129  1.1  mrg       __builtin_ia32_ldmxcsr (mxcsr);
    130  1.1  mrg     }
    131  1.1  mrg #else
    132  1.1  mrg   unsigned int mxcsr = __builtin_ia32_stmxcsr ();
    133  1.1  mrg   mxcsr |= MXCSR_DAZ | MXCSR_FTZ;
    134  1.1  mrg   __builtin_ia32_ldmxcsr (mxcsr);
    135  1.1  mrg #endif
    136  1.1  mrg }
    137