Home | History | Annotate | Line # | Download | only in i386
      1 /*
      2  * Copyright (C) 2005-2024 Free Software Foundation, Inc.
      3  *
      4  * This file is free software; you can redistribute it and/or modify it
      5  * under the terms of the GNU General Public License as published by the
      6  * Free Software Foundation; either version 3, or (at your option) any
      7  * later version.
      8  *
      9  * This file is distributed in the hope that it will be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * General Public License for more details.
     13  *
     14  * Under Section 7 of GPL version 3, you are granted additional
     15  * permissions described in the GCC Runtime Library Exception, version
     16  * 3.1, as published by the Free Software Foundation.
     17  *
     18  * You should have received a copy of the GNU General Public License and
     19  * a copy of the GCC Runtime Library Exception along with this program;
     20  * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     21  * <http://www.gnu.org/licenses/>.
     22  */
     23 
     24 #ifndef _SOFT_FLOAT
     25 #define MXCSR_DAZ (1 << 6)	/* Enable denormals are zero mode */
     26 #define MXCSR_FTZ (1 << 15)	/* Enable flush to zero mode */
     27 
     28 #ifndef __x86_64__
     29 /* All 64-bit targets have SSE and DAZ;
     30    only check them explicitly for 32-bit ones. */
     31 #include "cpuid.h"
     32 
     33 __attribute__ ((target("fxsr,sse")))
     34 static void
     35 /* The i386 ABI only requires 4-byte stack alignment, so this is necessary
     36    to make sure the fxsave struct gets correct alignment.
     37    See PR27537 and PR28621.  */
     38 __attribute__ ((force_align_arg_pointer))
     39 set_fast_math_sse (unsigned int edx)
     40 {
     41   unsigned int mxcsr;
     42 
     43   if (edx & bit_FXSAVE)
     44     {
     45       /* Check if DAZ is available.  */
     46       struct
     47       {
     48 	unsigned short cwd;
     49 	unsigned short swd;
     50 	unsigned short twd;
     51 	unsigned short fop;
     52 	unsigned int fip;
     53 	unsigned int fcs;
     54 	unsigned int foo;
     55 	unsigned int fos;
     56 	unsigned int mxcsr;
     57 	unsigned int mxcsr_mask;
     58 	unsigned int st_space[32];
     59 	unsigned int xmm_space[32];
     60 	unsigned int padding[56];
     61       } __attribute__ ((aligned (16))) fxsave;
     62 
     63       /* This is necessary since some implementations of FXSAVE
     64 	 do not modify reserved areas within the image.  */
     65       fxsave.mxcsr_mask = 0;
     66 
     67       __builtin_ia32_fxsave (&fxsave);
     68 
     69       mxcsr = fxsave.mxcsr;
     70 
     71       if (fxsave.mxcsr_mask & MXCSR_DAZ)
     72 	mxcsr |= MXCSR_DAZ;
     73     }
     74   else
     75     mxcsr = __builtin_ia32_stmxcsr ();
     76 
     77   mxcsr |= MXCSR_FTZ;
     78   __builtin_ia32_ldmxcsr (mxcsr);
     79 }
     80 #endif
     81 
     82 static void __attribute__((constructor))
     83 set_fast_math (void)
     84 {
     85 #ifndef __x86_64__
     86   unsigned int eax, ebx, ecx, edx;
     87 
     88   if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
     89     return;
     90 
     91   if (edx & bit_SSE)
     92     set_fast_math_sse (edx);
     93 #else
     94   unsigned int mxcsr = __builtin_ia32_stmxcsr ();
     95   mxcsr |= MXCSR_DAZ | MXCSR_FTZ;
     96   __builtin_ia32_ldmxcsr (mxcsr);
     97 #endif
     98 }
     99 #endif
    100