405e235e0c891b748f3730064b11bb469e7b204e
[reactos.git] / reactos / ntoskrnl / ke / i386 / fpu.c
1 /* $Id: fpu.c,v 1.11 2003/11/06 20:40:25 gvg 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 __asm__("movl %%cr0, %0\n\t" : "=a" (cr0));
54 /* Set NE and MP. */
55 cr0 = cr0 | 0x22;
56 /* Clear EM */
57 cr0 = cr0 & (~0x4);
58 __asm__("movl %0, %%cr0\n\t" : : "a" (cr0));
59
60 __asm__("clts\n\t");
61 __asm__("fninit\n\t");
62 __asm__("fstsw %0\n\t" : "=a" (status));
63 if (status != 0)
64 {
65 __asm__("movl %%cr0, %0\n\t" : "=a" (cr0));
66 /* Set the EM flag in CR0 so any FPU instructions cause a trap. */
67 cr0 = cr0 | 0x4;
68 __asm__("movl %0, %%cr0\n\t" :
69 : "a" (cr0));
70 return;
71 }
72 /* fsetpm for i287, ignored by i387 */
73 __asm__(".byte 0xDB, 0xE4\n\t");
74 HardwareMathSupport = 1;
75 }
76
77 /* This is a rather naive implementation of Ke(Save/Restore)FloatingPointState
78 which will not work for WDM drivers. Please feel free to improve */
79
80 #define FPU_STATE_SIZE 108
81
82 NTSTATUS STDCALL
83 KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save)
84 {
85 char *FpState;
86
87 FpState = ExAllocatePool(PagedPool, FPU_STATE_SIZE);
88 if (NULL == FpState)
89 {
90 return STATUS_INSUFFICIENT_RESOURCES;
91 }
92 *((PVOID *) Save) = FpState;
93
94 __asm__("fsave %0\n\t" : "=m" (*FpState));
95
96 return STATUS_SUCCESS;
97 }
98
99 NTSTATUS STDCALL
100 KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save)
101 {
102 char *FpState = *((PVOID *) Save);
103
104 __asm__("frstor %0\n\t" : "=m" (*FpState));
105 ExFreePool(FpState);
106
107 return STATUS_SUCCESS;
108 }