]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/config/fpu-387.h
Licensing changes to GPLv3 resp. GPLv3 with GCC Runtime Exception.
[thirdparty/gcc.git] / libgfortran / config / fpu-387.h
CommitLineData
944b8b35 1/* FPU-related code for x86 and x86_64 processors.
748086b7 2 Copyright 2005, 2007, 2009 Free Software Foundation, Inc.
944b8b35
FXC
3 Contributed by Francois-Xavier Coudert <coudert@clipper.ens.fr>
4
5This file is part of the GNU Fortran 95 runtime library (libgfortran).
6
7Libgfortran is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public
9License as published by the Free Software Foundation; either
748086b7 10version 3 of the License, or (at your option) any later version.
944b8b35
FXC
11
12Libgfortran is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
748086b7
JJ
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
944b8b35 25
c664bb1b
UB
26#ifndef __x86_64__
27#include "cpuid.h"
28#endif
944b8b35
FXC
29
30static int
31has_sse (void)
32{
c664bb1b 33#ifndef __x86_64__
944b8b35
FXC
34 unsigned int eax, ebx, ecx, edx;
35
c664bb1b 36 if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
944b8b35
FXC
37 return 0;
38
c664bb1b
UB
39 return edx & bit_SSE;
40#else
41 return 1;
944b8b35
FXC
42#endif
43}
44
c664bb1b 45/* i387 -- see linux <fpu_control.h> header file for details. */
944b8b35
FXC
46#define _FPU_MASK_IM 0x01
47#define _FPU_MASK_DM 0x02
48#define _FPU_MASK_ZM 0x04
49#define _FPU_MASK_OM 0x08
50#define _FPU_MASK_UM 0x10
51#define _FPU_MASK_PM 0x20
c664bb1b
UB
52
53void set_fpu (void)
54{
55 unsigned short cw;
56
944b8b35 57 asm volatile ("fnstcw %0" : "=m" (cw));
c664bb1b
UB
58
59 cw |= (_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM | _FPU_MASK_OM
60 | _FPU_MASK_UM | _FPU_MASK_PM);
61
944b8b35
FXC
62 if (options.fpe & GFC_FPE_INVALID) cw &= ~_FPU_MASK_IM;
63 if (options.fpe & GFC_FPE_DENORMAL) cw &= ~_FPU_MASK_DM;
64 if (options.fpe & GFC_FPE_ZERO) cw &= ~_FPU_MASK_ZM;
65 if (options.fpe & GFC_FPE_OVERFLOW) cw &= ~_FPU_MASK_OM;
66 if (options.fpe & GFC_FPE_UNDERFLOW) cw &= ~_FPU_MASK_UM;
67 if (options.fpe & GFC_FPE_PRECISION) cw &= ~_FPU_MASK_PM;
c664bb1b 68
944b8b35
FXC
69 asm volatile ("fldcw %0" : : "m" (cw));
70
71 if (has_sse())
72 {
c664bb1b
UB
73 unsigned int cw_sse;
74
771c0562 75 asm volatile ("stmxcsr %0" : "=m" (cw_sse));
c664bb1b
UB
76
77 cw_sse &= 0xffff0000;
7d30b888
FXC
78 cw_sse |= (_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM | _FPU_MASK_OM
79 | _FPU_MASK_UM | _FPU_MASK_PM ) << 7;
c664bb1b 80
7d30b888
FXC
81 if (options.fpe & GFC_FPE_INVALID) cw_sse &= ~(_FPU_MASK_IM << 7);
82 if (options.fpe & GFC_FPE_DENORMAL) cw_sse &= ~(_FPU_MASK_DM << 7);
83 if (options.fpe & GFC_FPE_ZERO) cw_sse &= ~(_FPU_MASK_ZM << 7);
84 if (options.fpe & GFC_FPE_OVERFLOW) cw_sse &= ~(_FPU_MASK_OM << 7);
85 if (options.fpe & GFC_FPE_UNDERFLOW) cw_sse &= ~(_FPU_MASK_UM << 7);
86 if (options.fpe & GFC_FPE_PRECISION) cw_sse &= ~(_FPU_MASK_PM << 7);
c664bb1b 87
7d30b888 88 asm volatile ("ldmxcsr %0" : : "m" (cw_sse));
944b8b35
FXC
89 }
90}