b38eacfa8ba7463665df7fa358b10a7d0016ca92
[reactos.git] / ntoskrnl / ke / i386 / fpu.c
1 /* $Id$
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 
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   VOID **FpState = (VOID **) Save;
86
87   *FpState = ExAllocatePool(PagedPool, FPU_STATE_SIZE);
88   if (NULL == *FpState)
89     {
90       return STATUS_INSUFFICIENT_RESOURCES;
91     }
92
93   __asm__("fsave %0\n\t" : /* no output */ : "m" (*FpState));
94
95   return STATUS_SUCCESS;
96 }
97
98 NTSTATUS STDCALL
99 KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save)
100 {
101   VOID **FpState = (VOID **) Save;
102
103   __asm__("frstor %0\n\t" : /* no output */ : "m" (*FpState));
104   ExFreePool(*FpState);
105
106   return STATUS_SUCCESS;
107 }