Continue of MSVC-compiling changes....
[reactos.git] / reactos / ntoskrnl / ke / i386 / fpu.c
1 /* $Id: fpu.c,v 1.12 2003/12/30 18:52:04 fireball Exp $
2 *
3 * ReactOS kernel
4 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 /*
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ke/i386/fpu.c
23 * PURPOSE: Handles the FPU
24 * PROGRAMMER: David Welch (welch@mcmail.com)
25 * UPDATE HISTORY:
26 * Created 22/05/98
27 */
28
29 /* INCLUDES *****************************************************************/
30
31 #include <ddk/ntddk.h>
32 #include <internal/ke.h>
33 #include <internal/mm.h>
34 #include <internal/ps.h>
35
36 #define NDEBUG
37 #include <internal/debug.h>
38
39 /* GLOBALS *******************************************************************/
40
41 ULONG HardwareMathSupport;
42
43 /* FUNCTIONS *****************************************************************/
44
45 VOID INIT_FUNCTION
46 KiCheckFPU(VOID)
47 {
48 unsigned short int status;
49 int cr0_;
50
51 HardwareMathSupport = 0;
52
53 #if defined(__GNUC__)
54 __asm__("movl %%cr0, %0\n\t" : "=a" (cr0_));
55 /* Set NE and MP. */
56 cr0_ = cr0_ | 0x22;
57 /* Clear EM */
58 cr0_ = cr0_ & (~0x4);
59 __asm__("movl %0, %%cr0\n\t" : : "a" (cr0_));
60
61 __asm__("clts\n\t");
62 __asm__("fninit\n\t");
63 __asm__("fstsw %0\n\t" : "=a" (status));
64 if (status != 0)
65 {
66 __asm__("movl %%cr0, %0\n\t" : "=a" (cr0_));
67 /* Set the EM flag in CR0 so any FPU instructions cause a trap. */
68 cr0_ = cr0_ | 0x4;
69 __asm__("movl %0, %%cr0\n\t" :
70 : "a" (cr0_));
71 return;
72 }
73 /* fsetpm for i287, ignored by i387 */
74 __asm__(".byte 0xDB, 0xE4\n\t");
75 #elif defined(_MSC_VER)
76 __asm mov eax, cr0;
77 __asm mov cr0_, eax;
78 cr0_ |= 0x22; /* Set NE and MP. */
79 cr0_ &= ~0x4; /* Clear EM */
80 __asm
81 {
82 mov eax, cr0_;
83 mov cr0, eax;
84 clts;
85 fninit;
86 fstsw status
87 }
88 if (status != 0)
89 {
90 __asm mov eax, cr0_;
91 __asm or eax, 4; /* Set the EM flag in CR0 so any FPU instructions cause a trap. */
92 __asm mov cr0, eax;
93 return;
94 }
95 /* fsetpm for i287, ignored by i387 */
96 __asm _emit 0xDB __asm _emit 0xe4
97 // __asm fsetpm;
98 // __asm__(".byte 0xDB, 0xE4\n\t");
99 #else
100 #error Unknown compiler for inline assembler
101 #endif
102
103 HardwareMathSupport = 1;
104 }
105
106 /* This is a rather naive implementation of Ke(Save/Restore)FloatingPointState
107 which will not work for WDM drivers. Please feel free to improve */
108
109 #define FPU_STATE_SIZE 108
110
111 NTSTATUS STDCALL
112 KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save)
113 {
114 char *FpState;
115
116 FpState = ExAllocatePool(PagedPool, FPU_STATE_SIZE);
117 if (NULL == FpState)
118 {
119 return STATUS_INSUFFICIENT_RESOURCES;
120 }
121 *((PVOID *) Save) = FpState;
122
123 #if defined(__GNUC__)
124 __asm__("fsave %0\n\t" : "=m" (*FpState));
125 #elif defined(_MSC_VER)
126 __asm mov eax, FpState;
127 __asm fsave [eax];
128 #else
129 #error Unknown compiler for inline assembler
130 #endif
131
132 return STATUS_SUCCESS;
133 }
134
135 NTSTATUS STDCALL
136 KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save)
137 {
138 char *FpState = *((PVOID *) Save);
139
140 #if defined(__GNUC__)
141 __asm__("frstor %0\n\t" : "=m" (*FpState));
142 #elif defined(_MSC_VER)
143 __asm mov eax, FpState;
144 __asm frstor [eax];
145 #else
146 #error Unknown compiler for inline assembler
147 #endif
148
149 ExFreePool(FpState);
150
151 return STATUS_SUCCESS;
152 }