mirror of
https://github.com/reactos/reactos.git
synced 2025-02-25 01:39:30 +00:00
- Implement FPU Exception Handler.
- We can now properly handle FPU faults (wrote a small test for invalid fpu precision). - OpenGL probably still doesn't work, as there might be some bugs around the place. However, you should not see FPU Bugchecks anymore. svn path=/trunk/; revision=24187
This commit is contained in:
parent
03c36d1a35
commit
8b094bf093
2 changed files with 168 additions and 33 deletions
|
@ -200,14 +200,29 @@ Author:
|
|||
//
|
||||
// FPU Save Area Offsets
|
||||
//
|
||||
#define FN_CONTROL_WORD 0x0
|
||||
#define FN_STATUS_WORD 0x4
|
||||
#define FN_TAG_WORD 0x8
|
||||
#define FN_DATA_SELECTOR 0x18
|
||||
#define FP_CONTROL_WORD 0x0
|
||||
#define FP_STATUS_WORD 0x4
|
||||
#define FP_TAG_WORD 0x8
|
||||
#define FP_ERROR_OFFSET 0xC
|
||||
#define FP_ERROR_SELECTOR 0x10
|
||||
#define FP_DATA_OFFSET 0x14
|
||||
#define FP_DATA_SELECTOR 0x18
|
||||
#define FN_CR0_NPX_STATE 0x20C
|
||||
#define SIZEOF_FX_SAVE_AREA 528
|
||||
#define NPX_FRAME_LENGTH 0x210
|
||||
|
||||
//
|
||||
// FX Save Area Offsets
|
||||
//
|
||||
#define FX_CONTROL_WORD 0x0
|
||||
#define FX_STATUS_WORD 0x2
|
||||
#define FX_TAG_WORD 0x4
|
||||
#define FX_ERROR_OPCODE 0x6
|
||||
#define FX_ERROR_OFFSET 0x8
|
||||
#define FX_ERROR_SELECTOR 0xC
|
||||
#define FX_DATA_OFFSET 0x10
|
||||
#define FX_DATA_SELECTOR 0x14
|
||||
|
||||
//
|
||||
// NPX States
|
||||
//
|
||||
|
@ -464,6 +479,15 @@ Author:
|
|||
#define STATUS_SINGLE_STEP 0x80000004
|
||||
#define STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000094
|
||||
#define STATUS_INTEGER_OVERFLOW 0xC0000095
|
||||
#define STATUS_FLOAT_DENORMAL_OPERAND 0xC000008D
|
||||
#define STATUS_FLOAT_DIVIDE_BY_ZERO 0xC000008E
|
||||
#define STATUS_FLOAT_INEXACT_RESULT 0xC000008F
|
||||
#define STATUS_FLOAT_INVALID_OPERATION 0xC0000090
|
||||
#define STATUS_FLOAT_OVERFLOW 0xC0000091
|
||||
#define STATUS_FLOAT_STACK_CHECK 0xC0000092
|
||||
#define STATUS_FLOAT_UNDERFLOW 0xC0000093
|
||||
#define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4
|
||||
#define STATUS_FLOAT_MULTIPLE_TRAPS 0xC00002B5
|
||||
#define APC_INDEX_MISMATCH 0x01
|
||||
#define TRAP_CAUSE_UNKNOWN 0x12
|
||||
#define KMODE_EXCEPTION_NOT_HANDLED 0x13
|
||||
|
|
|
@ -1220,32 +1220,135 @@ HandleUserNpx:
|
|||
and ebx, ~(CR0_MP + CR0_EM + CR0_TS)
|
||||
mov cr0, ebx
|
||||
|
||||
/* FIXME: Implement the rest */
|
||||
int 3
|
||||
jmp $
|
||||
/* Check if we have FX support */
|
||||
test byte ptr _KeI386FxsrPresent, 1
|
||||
jz FnSave2
|
||||
|
||||
/* Save the state */
|
||||
fxsave [ecx]
|
||||
jmp MakeCr0Dirty
|
||||
FnSave2:
|
||||
fnsave [ecx]
|
||||
wait
|
||||
|
||||
MakeCr0Dirty:
|
||||
/* Make CR0 state not loaded */
|
||||
or ebx, NPX_STATE_NOT_LOADED
|
||||
or ebx, [ecx+FN_CR0_NPX_STATE]
|
||||
mov cr0, ebx
|
||||
|
||||
/* Update NPX state */
|
||||
mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
|
||||
mov dword ptr fs:[KPCR_NPX_THREAD], 0
|
||||
|
||||
NoSaveRestore:
|
||||
/* FIXME: Implement the rest */
|
||||
int 3
|
||||
jmp $
|
||||
/* Clear the TS bit and re-enable interrupts */
|
||||
and dword ptr [ecx+FN_CR0_NPX_STATE], ~CR0_TS
|
||||
sti
|
||||
|
||||
EmulationEnabled:
|
||||
/* Did this come from kernel-mode? */
|
||||
cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R0_CODE
|
||||
jz CheckState
|
||||
/* Check if we have FX support */
|
||||
test byte ptr _KeI386FxsrPresent, 1
|
||||
jz FnError
|
||||
|
||||
/* It came from user-mode, so this would only be valid inside a VDM */
|
||||
/* Since we don't actually have VDMs in ROS, bugcheck. */
|
||||
jmp BogusTrap2
|
||||
/* Get error offset, control and status words */
|
||||
mov ebx, [ecx+FX_ERROR_OFFSET]
|
||||
movzx eax, word ptr [ecx+FX_CONTROL_WORD]
|
||||
movzx edx, word ptr [ecx+FX_STATUS_WORD]
|
||||
|
||||
TsSetOnLoadedState:
|
||||
/* TS shouldn't be set, unless this we don't have a Math Processor */
|
||||
test bl, CR0_MP
|
||||
jnz BogusTrap
|
||||
/* Get the faulting opcode */
|
||||
mov esi, [ecx+FX_DATA_OFFSET]
|
||||
jmp CheckError
|
||||
|
||||
/* Strange that we got a trap at all, but ignore and continue */
|
||||
clts
|
||||
jmp _Kei386EoiHelper@0
|
||||
FnError:
|
||||
/* Get error offset, control and status words */
|
||||
mov ebx, [ecx+FP_ERROR_OFFSET]
|
||||
movzx eax, word ptr [ecx+FP_CONTROL_WORD]
|
||||
movzx edx, word ptr [ecx+FP_STATUS_WORD]
|
||||
|
||||
/* Get the faulting opcode */
|
||||
mov esi, [ecx+FP_DATA_OFFSET]
|
||||
|
||||
CheckError:
|
||||
/* Mask exceptions */
|
||||
and eax, 0x3F
|
||||
not eax
|
||||
and eax, edx
|
||||
|
||||
/* Check if what's left is invalid */
|
||||
test al, 1
|
||||
jz ValidNpxOpcode
|
||||
|
||||
/* Check if it was a stack fault */
|
||||
test al, 64
|
||||
jnz InvalidStack
|
||||
|
||||
/* Raise exception */
|
||||
mov eax, STATUS_FLOAT_INVALID_OPERATION
|
||||
jmp _DispatchOneParam
|
||||
|
||||
InvalidStack:
|
||||
|
||||
/* Raise exception */
|
||||
mov eax, STATUS_FLOAT_STACK_CHECK
|
||||
jmp _DispatchTwoParam
|
||||
|
||||
ValidNpxOpcode:
|
||||
|
||||
/* Check for divide by 0 */
|
||||
test al, 4
|
||||
jz 1f
|
||||
|
||||
/* Raise exception */
|
||||
mov eax, STATUS_FLOAT_DIVIDE_BY_ZERO
|
||||
jmp _DispatchOneParam
|
||||
|
||||
1:
|
||||
/* Check for denormal */
|
||||
test al, 2
|
||||
jz 1f
|
||||
|
||||
/* Raise exception */
|
||||
mov eax, STATUS_FLOAT_INVALID_OPERATION
|
||||
jmp _DispatchOneParam
|
||||
|
||||
1:
|
||||
/* Check for overflow */
|
||||
test al, 8
|
||||
jz 1f
|
||||
|
||||
/* Raise exception */
|
||||
mov eax, STATUS_FLOAT_OVERFLOW
|
||||
jmp _DispatchOneParam
|
||||
|
||||
1:
|
||||
/* Check for underflow */
|
||||
test al, 16
|
||||
jz 1f
|
||||
|
||||
/* Raise exception */
|
||||
mov eax, STATUS_FLOAT_UNDERFLOW
|
||||
jmp _DispatchOneParam
|
||||
|
||||
1:
|
||||
/* Check for precision fault */
|
||||
test al, 32
|
||||
jz UnexpectedNpx
|
||||
|
||||
/* Raise exception */
|
||||
mov eax, STATUS_FLOAT_INEXACT_RESULT
|
||||
jmp _DispatchOneParam
|
||||
|
||||
UnexpectedNpx:
|
||||
|
||||
/* Strange result, bugcheck the OS */
|
||||
sti
|
||||
push ebp
|
||||
push 0
|
||||
push 0
|
||||
push eax
|
||||
push 1
|
||||
push TRAP_CAUSE_UNKNOWN
|
||||
call _KeBugCheckWithTf@24
|
||||
|
||||
V86Npx:
|
||||
/* Check if this is a VDM */
|
||||
|
@ -1258,15 +1361,23 @@ V86Npx:
|
|||
int 3
|
||||
jmp $
|
||||
|
||||
BogusTrap2:
|
||||
/* Cause a bugcheck */
|
||||
sti
|
||||
push 0
|
||||
push 0
|
||||
push eax
|
||||
push 1
|
||||
push TRAP_CAUSE_UNKNOWN
|
||||
call _KeBugCheckEx@20
|
||||
EmulationEnabled:
|
||||
/* Did this come from kernel-mode? */
|
||||
cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R0_CODE
|
||||
jz CheckState
|
||||
|
||||
/* It came from user-mode, so this would only be valid inside a VDM */
|
||||
/* Since we don't actually have VDMs in ROS, bugcheck. */
|
||||
jmp UnexpectedNpx
|
||||
|
||||
TsSetOnLoadedState:
|
||||
/* TS shouldn't be set, unless this we don't have a Math Processor */
|
||||
test bl, CR0_MP
|
||||
jnz BogusTrap
|
||||
|
||||
/* Strange that we got a trap at all, but ignore and continue */
|
||||
clts
|
||||
jmp _Kei386EoiHelper@0
|
||||
|
||||
BogusTrap:
|
||||
/* Cause a bugcheck */
|
||||
|
|
Loading…
Reference in a new issue