mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 06:49:13 +02:00
Disable specific coprocessor int 0x10 handler if possible
git-svn-id: trunk@36488 -
This commit is contained in:
parent
903548b21a
commit
d68ebf7cfb
@ -156,11 +156,20 @@ end;
|
|||||||
|
|
||||||
{$define FPC_SYSTEM_HAS_SYSINITFPU}
|
{$define FPC_SYSTEM_HAS_SYSINITFPU}
|
||||||
Procedure SysInitFPU;
|
Procedure SysInitFPU;
|
||||||
|
|
||||||
|
const
|
||||||
|
CR0_NE = $20;
|
||||||
|
CR0_NOT_NE = $FFFF - CR0_NE;
|
||||||
var
|
var
|
||||||
{ these locals are so we don't have to hack pic code in the assembler }
|
{ these locals are so we don't have to hack pic code in the assembler }
|
||||||
localfpucw: word;
|
localfpucw: word;
|
||||||
prevInt06 : FarPointer;
|
prevInt06 : FarPointer;
|
||||||
|
_newcr0_lw : word;
|
||||||
|
restore_old_int10 : boolean;
|
||||||
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
restore_old_int10:=false;
|
||||||
localfpucw:=Default8087CW;
|
localfpucw:=Default8087CW;
|
||||||
asm
|
asm
|
||||||
fninit
|
fninit
|
||||||
@ -168,54 +177,84 @@ Procedure SysInitFPU;
|
|||||||
fwait
|
fwait
|
||||||
end;
|
end;
|
||||||
if Test8087 < 2 then
|
if Test8087 < 2 then
|
||||||
exit;
|
|
||||||
asm
|
|
||||||
push es
|
|
||||||
push ds
|
|
||||||
{ Get previous interrupt 06 handler }
|
|
||||||
mov ax, $3506
|
|
||||||
int $21
|
|
||||||
mov word [prevInt06],bx
|
|
||||||
mov dx,es
|
|
||||||
mov word [prevInt06+2],dx
|
|
||||||
{ Install local interrupt 06 handler }
|
|
||||||
{$ifdef FPC_MM_TINY}
|
|
||||||
{ Do not use SEG here, as this introduces a relocation that
|
|
||||||
is incompatible with COM executable generation }
|
|
||||||
mov dx, cs
|
|
||||||
{$else FPC_MM_TINY}
|
|
||||||
mov dx, SEG InterceptInvalidInstruction
|
|
||||||
{$endif FPC_MM_TINY}
|
|
||||||
mov ds, dx
|
|
||||||
mov dx, Offset InterceptInvalidInstruction
|
|
||||||
mov ax, $2506
|
|
||||||
int $21
|
|
||||||
pop ds
|
|
||||||
pop es
|
|
||||||
end;
|
|
||||||
if setjmp(test_fpu_jmpbuf)=0 then
|
|
||||||
begin
|
begin
|
||||||
asm
|
restore_old_int10:=true;
|
||||||
db $0f, $20, $c0 { mov eax,cr0 }
|
|
||||||
db $83, $c8, $20 { or $0x20,eax }
|
|
||||||
db $0f, $22, $c0 { mov cr0,eax }
|
|
||||||
end;
|
|
||||||
//writeln(stderr,'Change of cr0 succeeded');
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
//writeln(stderr,'Change of cr0 failed');
|
asm
|
||||||
|
push es
|
||||||
|
push ds
|
||||||
|
{ Get previous interrupt 06 handler }
|
||||||
|
mov ax, $3506
|
||||||
|
int $21
|
||||||
|
mov word [prevInt06],bx
|
||||||
|
mov dx,es
|
||||||
|
mov word [prevInt06+2],dx
|
||||||
|
{ Install local interrupt 06 handler }
|
||||||
|
{$ifdef FPC_MM_TINY}
|
||||||
|
{ Do not use SEG here, as this introduces a relocation that
|
||||||
|
is incompatible with COM executable generation }
|
||||||
|
mov dx, cs
|
||||||
|
{$else FPC_MM_TINY}
|
||||||
|
mov dx, SEG InterceptInvalidInstruction
|
||||||
|
{$endif FPC_MM_TINY}
|
||||||
|
mov ds, dx
|
||||||
|
mov dx, Offset InterceptInvalidInstruction
|
||||||
|
mov ax, $2506
|
||||||
|
int $21
|
||||||
|
pop ds
|
||||||
|
pop es
|
||||||
|
end;
|
||||||
|
if setjmp(test_fpu_jmpbuf)=0 then
|
||||||
|
begin
|
||||||
|
asm
|
||||||
|
db $0f, $20, $c0 { mov eax,cr0 }
|
||||||
|
{ Reset CR0 Numeric Error bit,
|
||||||
|
to trigger IRQ13 - interrupt $75,
|
||||||
|
and thus avoid the generation of a $10 trap
|
||||||
|
which iterferes with video interrupt handler }
|
||||||
|
and ax,CR0_NOT_NE
|
||||||
|
db $0f, $22, $c0 { mov cr0,eax }
|
||||||
|
end;
|
||||||
|
//writeln(stderr,'Change of cr0 succeeded');
|
||||||
|
// Test that NE bit is indeed reset
|
||||||
|
asm
|
||||||
|
db $0f, $20, $c0 { mov eax,cr0 }
|
||||||
|
mov _newcr0_lw, ax
|
||||||
|
end;
|
||||||
|
if (_newcr0_lw and CR0_NE) = 0 then
|
||||||
|
restore_old_int10:=true;
|
||||||
|
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
//writeln(stderr,'Change of cr0 failed');
|
||||||
|
end;
|
||||||
|
{ Restore previous interrupt 06 handler }
|
||||||
|
asm
|
||||||
|
push es
|
||||||
|
mov bx,word [prevInt06]
|
||||||
|
mov dx,word [prevInt06+2]
|
||||||
|
mov es,dx
|
||||||
|
mov ax, $2506
|
||||||
|
int $21
|
||||||
|
pop es
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
{ Restore previous interrupt 06 handler }
|
{ Special handler of interrupt $10
|
||||||
asm
|
not needed anymore
|
||||||
push es
|
Restore previous interrupt $10 handler }
|
||||||
mov bx,word [prevInt06]
|
if restore_old_int10 then
|
||||||
mov dx,word [prevInt06+2]
|
asm
|
||||||
mov es,dx
|
push es
|
||||||
mov ax, $2506
|
mov bx,word [SaveInt10]
|
||||||
int $21
|
mov dx,word [SaveInt10+2]
|
||||||
pop es
|
mov es,dx
|
||||||
end;
|
mov ax, $2506
|
||||||
|
int $21
|
||||||
|
pop es
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$I system.inc}
|
{$I system.inc}
|
||||||
|
Loading…
Reference in New Issue
Block a user