mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-29 07:22:18 +01: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 __SaveInt75
|
||||||
|
|
||||||
extern __fpu_status
|
extern __fpu_status
|
||||||
extern __fpu_control
|
|
||||||
|
|
||||||
extern FPC_HANDLE_I8086_ERROR
|
extern FPC_HANDLE_I8086_ERROR
|
||||||
|
|
||||||
@ -283,7 +282,8 @@ error_msg:
|
|||||||
|
|
||||||
global FPC_INT00_HANDLER
|
global FPC_INT00_HANDLER
|
||||||
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 cx
|
||||||
push ds
|
push ds
|
||||||
@ -310,7 +310,7 @@ FPC_INT00_HANDLER:
|
|||||||
%ifndef __FAR_CODE__
|
%ifndef __FAR_CODE__
|
||||||
; check whether we're coming from the same code segment
|
; check whether we're coming from the same code segment
|
||||||
mov bp, sp
|
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
|
mov bp, cs
|
||||||
cmp bp, cx
|
cmp bp, cx
|
||||||
jne .call_previous_handler00
|
jne .call_previous_handler00
|
||||||
@ -318,12 +318,12 @@ FPC_INT00_HANDLER:
|
|||||||
|
|
||||||
; Call Fpc_Handle_I8086_Error, with err=0
|
; Call Fpc_Handle_I8086_Error, with err=0
|
||||||
mov bp, sp
|
mov bp, sp
|
||||||
mov cx, [bp + 3*2 + 4] ; get caller offset
|
mov cx, [bp + 3*2 + 6] ; get caller offset
|
||||||
%ifdef __FAR_CODE__
|
%ifdef __FAR_CODE__
|
||||||
mov dx, [bp + 3*2 + 6] ; get caller segment
|
mov dx, [bp + 3*2 + 6 + 2] ; get caller segment
|
||||||
%endif
|
%endif
|
||||||
pop bp
|
pop bp
|
||||||
add sp, 2*2 + 4 + 6
|
add sp, 2*2 + 6 + 6
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
push ax
|
push ax
|
||||||
mov ax, 0
|
mov ax, 0
|
||||||
@ -333,6 +333,7 @@ FPC_INT00_HANDLER:
|
|||||||
%endif
|
%endif
|
||||||
push cx
|
push cx
|
||||||
cld
|
cld
|
||||||
|
sti
|
||||||
%ifdef __FAR_CODE__
|
%ifdef __FAR_CODE__
|
||||||
jmp far FPC_HANDLE_I8086_ERROR
|
jmp far FPC_HANDLE_I8086_ERROR
|
||||||
%else
|
%else
|
||||||
@ -348,11 +349,12 @@ FPC_INT00_HANDLER:
|
|||||||
pop bp
|
pop bp
|
||||||
pop ds
|
pop ds
|
||||||
pop cx
|
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
|
global FPC_INT10_HANDLER
|
||||||
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 cx
|
||||||
push ds
|
push ds
|
||||||
@ -368,21 +370,8 @@ FPC_INT10_HANDLER:
|
|||||||
%endif
|
%endif
|
||||||
mov ds, bp
|
mov ds, bp
|
||||||
; Check that an unmasked exception is indeed set
|
; 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]
|
fnstsw word [__fpu_status]
|
||||||
; Only the exception part is useful, clear other parts
|
test byte [__fpu_status], 80h ; really just this bit is enough, see i8087 datasheet
|
||||||
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
|
|
||||||
je .call_previous_handler10
|
je .call_previous_handler10
|
||||||
|
|
||||||
%ifdef __NEAR_DATA__
|
%ifdef __NEAR_DATA__
|
||||||
@ -396,7 +385,7 @@ FPC_INT10_HANDLER:
|
|||||||
%ifndef __FAR_CODE__
|
%ifndef __FAR_CODE__
|
||||||
; check whether we're coming from the same code segment
|
; check whether we're coming from the same code segment
|
||||||
mov bp, sp
|
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
|
mov bp, cs
|
||||||
cmp bp, cx
|
cmp bp, cx
|
||||||
jne .call_previous_handler10
|
jne .call_previous_handler10
|
||||||
@ -404,12 +393,12 @@ FPC_INT10_HANDLER:
|
|||||||
|
|
||||||
; Call Fpc_Handle_I8086_Error, with err=$10
|
; Call Fpc_Handle_I8086_Error, with err=$10
|
||||||
mov bp, sp
|
mov bp, sp
|
||||||
mov cx, [bp + 3*2 + 4] ; get caller offset
|
mov cx, [bp + 3*2 + 6] ; get caller offset
|
||||||
%ifdef __FAR_CODE__
|
%ifdef __FAR_CODE__
|
||||||
mov dx, [bp + 3*2 + 6] ; get caller segment
|
mov dx, [bp + 3*2 + 6 + 2] ; get caller segment
|
||||||
%endif
|
%endif
|
||||||
pop bp
|
pop bp
|
||||||
add sp, 2*2 + 4 + 6
|
add sp, 2*2 + 6 + 6
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
push ax
|
push ax
|
||||||
mov ax, 10h
|
mov ax, 10h
|
||||||
@ -419,6 +408,7 @@ FPC_INT10_HANDLER:
|
|||||||
%endif
|
%endif
|
||||||
push cx
|
push cx
|
||||||
cld
|
cld
|
||||||
|
sti
|
||||||
%ifdef __FAR_CODE__
|
%ifdef __FAR_CODE__
|
||||||
jmp far FPC_HANDLE_I8086_ERROR
|
jmp far FPC_HANDLE_I8086_ERROR
|
||||||
%else
|
%else
|
||||||
@ -434,11 +424,12 @@ FPC_INT10_HANDLER:
|
|||||||
pop bp
|
pop bp
|
||||||
pop ds
|
pop ds
|
||||||
pop cx
|
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
|
global FPC_INT75_HANDLER
|
||||||
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 cx
|
||||||
push ds
|
push ds
|
||||||
@ -465,7 +456,7 @@ FPC_INT75_HANDLER:
|
|||||||
%ifndef __FAR_CODE__
|
%ifndef __FAR_CODE__
|
||||||
; check whether we're coming from the same code segment
|
; check whether we're coming from the same code segment
|
||||||
mov bp, sp
|
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
|
mov bp, cs
|
||||||
cmp bp, cx
|
cmp bp, cx
|
||||||
jne .call_previous_handler75
|
jne .call_previous_handler75
|
||||||
@ -473,12 +464,12 @@ FPC_INT75_HANDLER:
|
|||||||
|
|
||||||
; Call Fpc_Handle_I8086_Error, with err=$75
|
; Call Fpc_Handle_I8086_Error, with err=$75
|
||||||
mov bp, sp
|
mov bp, sp
|
||||||
mov cx, [bp + 3*2 + 4] ; get caller offset
|
mov cx, [bp + 3*2 + 6] ; get caller offset
|
||||||
%ifdef __FAR_CODE__
|
%ifdef __FAR_CODE__
|
||||||
mov dx, [bp + 3*2 + 6] ; get caller segment
|
mov dx, [bp + 3*2 + 6 + 2] ; get caller segment
|
||||||
%endif
|
%endif
|
||||||
pop bp
|
pop bp
|
||||||
add sp, 2*2 + 4 + 6
|
add sp, 2*2 + 6 + 6
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
push ax
|
push ax
|
||||||
mov ax, 75h
|
mov ax, 75h
|
||||||
@ -488,6 +479,14 @@ FPC_INT75_HANDLER:
|
|||||||
%endif
|
%endif
|
||||||
push cx
|
push cx
|
||||||
cld
|
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__
|
%ifdef __FAR_CODE__
|
||||||
jmp far FPC_HANDLE_I8086_ERROR
|
jmp far FPC_HANDLE_I8086_ERROR
|
||||||
%else
|
%else
|
||||||
@ -509,9 +508,9 @@ FPC_INT75_HANDLER:
|
|||||||
|
|
||||||
global FPC_INSTALL_INTERRUPT_HANDLERS
|
global FPC_INSTALL_INTERRUPT_HANDLERS
|
||||||
FPC_INSTALL_INTERRUPT_HANDLERS:
|
FPC_INSTALL_INTERRUPT_HANDLERS:
|
||||||
push ds
|
|
||||||
|
|
||||||
%ifdef __HUGE__
|
%ifdef __HUGE__
|
||||||
|
push ds
|
||||||
mov ax, SYSTEM_DATA
|
mov ax, SYSTEM_DATA
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
%endif
|
%endif
|
||||||
@ -525,14 +524,16 @@ FPC_INSTALL_INTERRUPT_HANDLERS:
|
|||||||
|
|
||||||
; install the new int 00 handler
|
; install the new int 00 handler
|
||||||
%ifndef __TINY__
|
%ifndef __TINY__
|
||||||
|
push ds
|
||||||
push cs
|
push cs
|
||||||
pop ds
|
pop ds
|
||||||
%endif
|
%endif
|
||||||
mov dx, FPC_INT00_HANDLER
|
mov dx, FPC_INT00_HANDLER
|
||||||
pop ds
|
|
||||||
push ds
|
|
||||||
mov ax, 2500h
|
mov ax, 2500h
|
||||||
int 21h
|
int 21h
|
||||||
|
%ifndef __TINY__
|
||||||
|
pop ds
|
||||||
|
%endif
|
||||||
|
|
||||||
; save old int $10 handler
|
; save old int $10 handler
|
||||||
mov ax, 3510h
|
mov ax, 3510h
|
||||||
@ -543,14 +544,16 @@ FPC_INSTALL_INTERRUPT_HANDLERS:
|
|||||||
|
|
||||||
; install the new int $10 handler
|
; install the new int $10 handler
|
||||||
%ifndef __TINY__
|
%ifndef __TINY__
|
||||||
|
push ds
|
||||||
push cs
|
push cs
|
||||||
pop ds
|
pop ds
|
||||||
%endif
|
%endif
|
||||||
mov dx, FPC_INT10_HANDLER
|
mov dx, FPC_INT10_HANDLER
|
||||||
mov ax, 2510h
|
mov ax, 2510h
|
||||||
int 21h
|
int 21h
|
||||||
|
%ifndef __TINY__
|
||||||
pop ds
|
pop ds
|
||||||
push ds
|
%endif
|
||||||
|
|
||||||
; save old int $75 handler
|
; save old int $75 handler
|
||||||
mov ax, 3575h
|
mov ax, 3575h
|
||||||
@ -561,15 +564,21 @@ FPC_INSTALL_INTERRUPT_HANDLERS:
|
|||||||
|
|
||||||
; install the new int $75 handler
|
; install the new int $75 handler
|
||||||
%ifndef __TINY__
|
%ifndef __TINY__
|
||||||
|
push ds
|
||||||
push cs
|
push cs
|
||||||
pop ds
|
pop ds
|
||||||
%endif
|
%endif
|
||||||
mov dx, FPC_INT75_HANDLER
|
mov dx, FPC_INT75_HANDLER
|
||||||
mov ax, 2575h
|
mov ax, 2575h
|
||||||
int 21h
|
int 21h
|
||||||
|
%ifndef __TINY__
|
||||||
|
|
||||||
pop ds
|
pop ds
|
||||||
|
%endif
|
||||||
|
|
||||||
|
|
||||||
|
%ifdef __HUGE__
|
||||||
|
pop ds
|
||||||
|
%endif
|
||||||
%ifdef __FAR_CODE__
|
%ifdef __FAR_CODE__
|
||||||
retf
|
retf
|
||||||
%else
|
%else
|
||||||
@ -579,26 +588,33 @@ FPC_INSTALL_INTERRUPT_HANDLERS:
|
|||||||
|
|
||||||
global FPC_RESTORE_INTERRUPT_HANDLERS
|
global FPC_RESTORE_INTERRUPT_HANDLERS
|
||||||
FPC_RESTORE_INTERRUPT_HANDLERS:
|
FPC_RESTORE_INTERRUPT_HANDLERS:
|
||||||
push ds
|
|
||||||
|
|
||||||
%ifdef __HUGE__
|
%ifdef __HUGE__
|
||||||
|
push ds
|
||||||
mov ax, SYSTEM_DATA
|
mov ax, SYSTEM_DATA
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
%endif
|
%endif
|
||||||
|
push ds
|
||||||
mov ax, 2500h
|
mov ax, 2500h
|
||||||
lds dx, [__SaveInt00]
|
lds dx, [__SaveInt00]
|
||||||
int 21h
|
int 21h
|
||||||
|
pop ds
|
||||||
|
|
||||||
|
push ds
|
||||||
mov ax, 2510h
|
mov ax, 2510h
|
||||||
lds dx, [__SaveInt10]
|
lds dx, [__SaveInt10]
|
||||||
int 21h
|
int 21h
|
||||||
|
pop ds
|
||||||
|
|
||||||
|
push ds
|
||||||
mov ax, 2575h
|
mov ax, 2575h
|
||||||
lds dx, [__SaveInt75]
|
lds dx, [__SaveInt75]
|
||||||
int 21h
|
int 21h
|
||||||
|
|
||||||
pop ds
|
pop ds
|
||||||
|
|
||||||
|
%ifdef __HUGE__
|
||||||
|
pop ds
|
||||||
|
%endif
|
||||||
%ifdef __FAR_CODE__
|
%ifdef __FAR_CODE__
|
||||||
retf
|
retf
|
||||||
%else
|
%else
|
||||||
|
|||||||
@ -84,7 +84,6 @@ var
|
|||||||
SaveInt10: FarPointer;public name '__SaveInt10';
|
SaveInt10: FarPointer;public name '__SaveInt10';
|
||||||
SaveInt75: FarPointer;public name '__SaveInt75';
|
SaveInt75: FarPointer;public name '__SaveInt75';
|
||||||
fpu_status: word;public name '__fpu_status';
|
fpu_status: word;public name '__fpu_status';
|
||||||
fpu_control: word;public name '__fpu_control';
|
|
||||||
|
|
||||||
|
|
||||||
AllFilesMask: string [3];
|
AllFilesMask: string [3];
|
||||||
@ -182,7 +181,7 @@ Procedure SysInitFPU;
|
|||||||
fldcw localfpucw
|
fldcw localfpucw
|
||||||
fwait
|
fwait
|
||||||
end;
|
end;
|
||||||
if Test8087 < 2 then
|
if Test8087 < 3 then { i8087/i80287 do not have "native" exception mode (CR0:NE) }
|
||||||
begin
|
begin
|
||||||
restore_old_int10:=true;
|
restore_old_int10:=true;
|
||||||
end
|
end
|
||||||
@ -239,13 +238,11 @@ Procedure SysInitFPU;
|
|||||||
end;
|
end;
|
||||||
{ Restore previous interrupt 06 handler }
|
{ Restore previous interrupt 06 handler }
|
||||||
asm
|
asm
|
||||||
push es
|
push ds
|
||||||
mov bx,word [prevInt06]
|
|
||||||
mov dx,word [prevInt06+2]
|
|
||||||
mov es,dx
|
|
||||||
mov ax, $2506
|
mov ax, $2506
|
||||||
|
lds dx,[prevInt06]
|
||||||
int $21
|
int $21
|
||||||
pop es
|
pop ds
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{ Special handler of interrupt $10
|
{ Special handler of interrupt $10
|
||||||
@ -254,13 +251,11 @@ Procedure SysInitFPU;
|
|||||||
{$ifndef TEST_FPU_INT10}
|
{$ifndef TEST_FPU_INT10}
|
||||||
if restore_old_int10 then
|
if restore_old_int10 then
|
||||||
asm
|
asm
|
||||||
push es
|
push ds
|
||||||
mov bx,word [SaveInt10]
|
|
||||||
mov dx,word [SaveInt10+2]
|
|
||||||
mov es,dx
|
|
||||||
mov ax, $2510
|
mov ax, $2510
|
||||||
|
lds dx,[SaveInt10]
|
||||||
int $21
|
int $21
|
||||||
pop es
|
pop ds
|
||||||
end;
|
end;
|
||||||
{$endif ndef TEST_FPU_INT10}
|
{$endif ndef TEST_FPU_INT10}
|
||||||
end;
|
end;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user