]>
Commit | Line | Data |
---|---|---|
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 | ||
5 | This file is part of the GNU Fortran 95 runtime library (libgfortran). | |
6 | ||
7 | Libgfortran is free software; you can redistribute it and/or | |
8 | modify it under the terms of the GNU General Public | |
9 | License as published by the Free Software Foundation; either | |
748086b7 | 10 | version 3 of the License, or (at your option) any later version. |
944b8b35 FXC |
11 | |
12 | Libgfortran is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
748086b7 JJ |
17 | Under Section 7 of GPL version 3, you are granted additional |
18 | permissions described in the GCC Runtime Library Exception, version | |
19 | 3.1, as published by the Free Software Foundation. | |
20 | ||
21 | You should have received a copy of the GNU General Public License and | |
22 | a copy of the GCC Runtime Library Exception along with this program; | |
23 | see 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 | |
30 | static int | |
31 | has_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 | |
53 | void 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 | } |