mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-24 10:29:14 +02:00
Fix for FPU generated exception as interrupt 0x10, contributed by Max Nazhalov
git-svn-id: trunk@36813 -
This commit is contained in:
parent
301fc9af70
commit
ba7586a5c8
@ -73,7 +73,6 @@
|
||||
extern __SaveInt75
|
||||
|
||||
extern __fpu_status
|
||||
extern __fpu_control
|
||||
|
||||
extern FPC_HANDLE_I8086_ERROR
|
||||
|
||||
@ -283,7 +282,8 @@ error_msg:
|
||||
|
||||
global FPC_INT00_HANDLER
|
||||
FPC_INT00_HANDLER:
|
||||
sub sp, 4 ; reserve space on the stack for the retf
|
||||
pushf
|
||||
sub sp, 4 ; reserve space on the stack for the iret
|
||||
|
||||
push cx
|
||||
push ds
|
||||
@ -310,7 +310,7 @@ FPC_INT00_HANDLER:
|
||||
%ifndef __FAR_CODE__
|
||||
; check whether we're coming from the same code segment
|
||||
mov bp, sp
|
||||
mov cx, [bp + 3*2 + 6] ; get caller segment
|
||||
mov cx, [bp + 3*2 + 6 + 2] ; get caller segment
|
||||
mov bp, cs
|
||||
cmp bp, cx
|
||||
jne .call_previous_handler00
|
||||
@ -318,12 +318,12 @@ FPC_INT00_HANDLER:
|
||||
|
||||
; Call Fpc_Handle_I8086_Error, with err=0
|
||||
mov bp, sp
|
||||
mov cx, [bp + 3*2 + 4] ; get caller offset
|
||||
mov cx, [bp + 3*2 + 6] ; get caller offset
|
||||
%ifdef __FAR_CODE__
|
||||
mov dx, [bp + 3*2 + 6] ; get caller segment
|
||||
mov dx, [bp + 3*2 + 6 + 2] ; get caller segment
|
||||
%endif
|
||||
pop bp
|
||||
add sp, 2*2 + 4 + 6
|
||||
add sp, 2*2 + 6 + 6
|
||||
xor ax, ax
|
||||
push ax
|
||||
mov ax, 0
|
||||
@ -333,6 +333,7 @@ FPC_INT00_HANDLER:
|
||||
%endif
|
||||
push cx
|
||||
cld
|
||||
sti
|
||||
%ifdef __FAR_CODE__
|
||||
jmp far FPC_HANDLE_I8086_ERROR
|
||||
%else
|
||||
@ -348,11 +349,12 @@ FPC_INT00_HANDLER:
|
||||
pop bp
|
||||
pop ds
|
||||
pop cx
|
||||
retf ; jumps to the previous handler with all registers and stack intact
|
||||
iret ; jumps to the previous handler with all registers and stack intact
|
||||
|
||||
global FPC_INT10_HANDLER
|
||||
FPC_INT10_HANDLER:
|
||||
sub sp, 4 ; reserve space on the stack for the retf
|
||||
pushf
|
||||
sub sp, 4 ; reserve space on the stack for the iret
|
||||
|
||||
push cx
|
||||
push ds
|
||||
@ -368,21 +370,8 @@ FPC_INT10_HANDLER:
|
||||
%endif
|
||||
mov ds, bp
|
||||
; Check that an unmasked exception is indeed set
|
||||
; First load FPU control register to __fpu_control
|
||||
fnstcw word [__fpu_control]
|
||||
; Move control register value to bx register
|
||||
mov bx,word [__fpu_control]
|
||||
; Now load status register to ax
|
||||
fnstsw word [__fpu_status]
|
||||
; Only the exception part is useful, clear other parts
|
||||
and bx,3fh
|
||||
; at least one same bit must also be set in bx
|
||||
; in that case with a bit set in status register
|
||||
; which means an exception has been generated by the FPU
|
||||
; and the exeception is not masked, as the same
|
||||
; bit is set in control register
|
||||
mov ax,word [__fpu_status]
|
||||
and ax,bx
|
||||
test byte [__fpu_status], 80h ; really just this bit is enough, see i8087 datasheet
|
||||
je .call_previous_handler10
|
||||
|
||||
%ifdef __NEAR_DATA__
|
||||
@ -396,7 +385,7 @@ FPC_INT10_HANDLER:
|
||||
%ifndef __FAR_CODE__
|
||||
; check whether we're coming from the same code segment
|
||||
mov bp, sp
|
||||
mov cx, [bp + 3*2 + 6] ; get caller segment
|
||||
mov cx, [bp + 3*2 + 6 + 2] ; get caller segment
|
||||
mov bp, cs
|
||||
cmp bp, cx
|
||||
jne .call_previous_handler10
|
||||
@ -404,12 +393,12 @@ FPC_INT10_HANDLER:
|
||||
|
||||
; Call Fpc_Handle_I8086_Error, with err=$10
|
||||
mov bp, sp
|
||||
mov cx, [bp + 3*2 + 4] ; get caller offset
|
||||
mov cx, [bp + 3*2 + 6] ; get caller offset
|
||||
%ifdef __FAR_CODE__
|
||||
mov dx, [bp + 3*2 + 6] ; get caller segment
|
||||
mov dx, [bp + 3*2 + 6 + 2] ; get caller segment
|
||||
%endif
|
||||
pop bp
|
||||
add sp, 2*2 + 4 + 6
|
||||
add sp, 2*2 + 6 + 6
|
||||
xor ax, ax
|
||||
push ax
|
||||
mov ax, 10h
|
||||
@ -419,6 +408,7 @@ FPC_INT10_HANDLER:
|
||||
%endif
|
||||
push cx
|
||||
cld
|
||||
sti
|
||||
%ifdef __FAR_CODE__
|
||||
jmp far FPC_HANDLE_I8086_ERROR
|
||||
%else
|
||||
@ -434,11 +424,12 @@ FPC_INT10_HANDLER:
|
||||
pop bp
|
||||
pop ds
|
||||
pop cx
|
||||
retf ; jumps to the previous handler with all registers and stack intact
|
||||
iret ; jumps to the previous handler with all registers and stack intact
|
||||
|
||||
global FPC_INT75_HANDLER
|
||||
FPC_INT75_HANDLER:
|
||||
sub sp, 4 ; reserve space on the stack for the retf
|
||||
pushf
|
||||
sub sp, 4 ; reserve space on the stack for the iret
|
||||
|
||||
push cx
|
||||
push ds
|
||||
@ -465,7 +456,7 @@ FPC_INT75_HANDLER:
|
||||
%ifndef __FAR_CODE__
|
||||
; check whether we're coming from the same code segment
|
||||
mov bp, sp
|
||||
mov cx, [bp + 3*2 + 6] ; get caller segment
|
||||
mov cx, [bp + 3*2 + 6 + 2] ; get caller segment
|
||||
mov bp, cs
|
||||
cmp bp, cx
|
||||
jne .call_previous_handler75
|
||||
@ -473,12 +464,12 @@ FPC_INT75_HANDLER:
|
||||
|
||||
; Call Fpc_Handle_I8086_Error, with err=$75
|
||||
mov bp, sp
|
||||
mov cx, [bp + 3*2 + 4] ; get caller offset
|
||||
mov cx, [bp + 3*2 + 6] ; get caller offset
|
||||
%ifdef __FAR_CODE__
|
||||
mov dx, [bp + 3*2 + 6] ; get caller segment
|
||||
mov dx, [bp + 3*2 + 6 + 2] ; get caller segment
|
||||
%endif
|
||||
pop bp
|
||||
add sp, 2*2 + 4 + 6
|
||||
add sp, 2*2 + 6 + 6
|
||||
xor ax, ax
|
||||
push ax
|
||||
mov ax, 75h
|
||||
@ -488,6 +479,14 @@ FPC_INT75_HANDLER:
|
||||
%endif
|
||||
push cx
|
||||
cld
|
||||
|
||||
; Reset IRQ/#IGNNE latch; signal EOI; enable interrupts
|
||||
mov al,20h
|
||||
out 0F0h,al ; al=any
|
||||
out 0A0h,al
|
||||
out 020h,al
|
||||
sti
|
||||
|
||||
%ifdef __FAR_CODE__
|
||||
jmp far FPC_HANDLE_I8086_ERROR
|
||||
%else
|
||||
@ -509,9 +508,9 @@ FPC_INT75_HANDLER:
|
||||
|
||||
global FPC_INSTALL_INTERRUPT_HANDLERS
|
||||
FPC_INSTALL_INTERRUPT_HANDLERS:
|
||||
push ds
|
||||
|
||||
%ifdef __HUGE__
|
||||
push ds
|
||||
mov ax, SYSTEM_DATA
|
||||
mov ds, ax
|
||||
%endif
|
||||
@ -525,14 +524,16 @@ FPC_INSTALL_INTERRUPT_HANDLERS:
|
||||
|
||||
; install the new int 00 handler
|
||||
%ifndef __TINY__
|
||||
push ds
|
||||
push cs
|
||||
pop ds
|
||||
%endif
|
||||
mov dx, FPC_INT00_HANDLER
|
||||
pop ds
|
||||
push ds
|
||||
mov ax, 2500h
|
||||
int 21h
|
||||
%ifndef __TINY__
|
||||
pop ds
|
||||
%endif
|
||||
|
||||
; save old int $10 handler
|
||||
mov ax, 3510h
|
||||
@ -543,14 +544,16 @@ FPC_INSTALL_INTERRUPT_HANDLERS:
|
||||
|
||||
; install the new int $10 handler
|
||||
%ifndef __TINY__
|
||||
push ds
|
||||
push cs
|
||||
pop ds
|
||||
%endif
|
||||
mov dx, FPC_INT10_HANDLER
|
||||
mov ax, 2510h
|
||||
int 21h
|
||||
%ifndef __TINY__
|
||||
pop ds
|
||||
push ds
|
||||
%endif
|
||||
|
||||
; save old int $75 handler
|
||||
mov ax, 3575h
|
||||
@ -561,15 +564,21 @@ FPC_INSTALL_INTERRUPT_HANDLERS:
|
||||
|
||||
; install the new int $75 handler
|
||||
%ifndef __TINY__
|
||||
push ds
|
||||
push cs
|
||||
pop ds
|
||||
%endif
|
||||
mov dx, FPC_INT75_HANDLER
|
||||
mov ax, 2575h
|
||||
int 21h
|
||||
|
||||
|
||||
%ifndef __TINY__
|
||||
pop ds
|
||||
%endif
|
||||
|
||||
|
||||
%ifdef __HUGE__
|
||||
pop ds
|
||||
%endif
|
||||
%ifdef __FAR_CODE__
|
||||
retf
|
||||
%else
|
||||
@ -579,26 +588,33 @@ FPC_INSTALL_INTERRUPT_HANDLERS:
|
||||
|
||||
global FPC_RESTORE_INTERRUPT_HANDLERS
|
||||
FPC_RESTORE_INTERRUPT_HANDLERS:
|
||||
push ds
|
||||
|
||||
%ifdef __HUGE__
|
||||
push ds
|
||||
mov ax, SYSTEM_DATA
|
||||
mov ds, ax
|
||||
%endif
|
||||
|
||||
push ds
|
||||
mov ax, 2500h
|
||||
lds dx, [__SaveInt00]
|
||||
int 21h
|
||||
pop ds
|
||||
|
||||
push ds
|
||||
mov ax, 2510h
|
||||
lds dx, [__SaveInt10]
|
||||
int 21h
|
||||
pop ds
|
||||
|
||||
push ds
|
||||
mov ax, 2575h
|
||||
lds dx, [__SaveInt75]
|
||||
int 21h
|
||||
|
||||
pop ds
|
||||
|
||||
%ifdef __HUGE__
|
||||
pop ds
|
||||
%endif
|
||||
%ifdef __FAR_CODE__
|
||||
retf
|
||||
%else
|
||||
|
@ -84,7 +84,6 @@ var
|
||||
SaveInt10: FarPointer;public name '__SaveInt10';
|
||||
SaveInt75: FarPointer;public name '__SaveInt75';
|
||||
fpu_status: word;public name '__fpu_status';
|
||||
fpu_control: word;public name '__fpu_control';
|
||||
|
||||
|
||||
AllFilesMask: string [3];
|
||||
@ -182,7 +181,7 @@ Procedure SysInitFPU;
|
||||
fldcw localfpucw
|
||||
fwait
|
||||
end;
|
||||
if Test8087 < 2 then
|
||||
if Test8087 < 3 then { i8087/i80287 do not have "native" exception mode (CR0:NE) }
|
||||
begin
|
||||
restore_old_int10:=true;
|
||||
end
|
||||
@ -239,13 +238,11 @@ Procedure SysInitFPU;
|
||||
end;
|
||||
{ Restore previous interrupt 06 handler }
|
||||
asm
|
||||
push es
|
||||
mov bx,word [prevInt06]
|
||||
mov dx,word [prevInt06+2]
|
||||
mov es,dx
|
||||
push ds
|
||||
mov ax, $2506
|
||||
lds dx,[prevInt06]
|
||||
int $21
|
||||
pop es
|
||||
pop ds
|
||||
end;
|
||||
end;
|
||||
{ Special handler of interrupt $10
|
||||
@ -254,13 +251,11 @@ Procedure SysInitFPU;
|
||||
{$ifndef TEST_FPU_INT10}
|
||||
if restore_old_int10 then
|
||||
asm
|
||||
push es
|
||||
mov bx,word [SaveInt10]
|
||||
mov dx,word [SaveInt10+2]
|
||||
mov es,dx
|
||||
push ds
|
||||
mov ax, $2510
|
||||
lds dx,[SaveInt10]
|
||||
int $21
|
||||
pop es
|
||||
pop ds
|
||||
end;
|
||||
{$endif ndef TEST_FPU_INT10}
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user