Disable specific coprocessor int 0x10 handler if possible

git-svn-id: trunk@36488 -
This commit is contained in:
pierre 2017-06-12 06:52:35 +00:00
parent 903548b21a
commit d68ebf7cfb

View File

@ -156,11 +156,20 @@ end;
{$define FPC_SYSTEM_HAS_SYSINITFPU}
Procedure SysInitFPU;
const
CR0_NE = $20;
CR0_NOT_NE = $FFFF - CR0_NE;
var
{ these locals are so we don't have to hack pic code in the assembler }
localfpucw: word;
prevInt06 : FarPointer;
_newcr0_lw : word;
restore_old_int10 : boolean;
begin
restore_old_int10:=false;
localfpucw:=Default8087CW;
asm
fninit
@ -168,54 +177,84 @@ Procedure SysInitFPU;
fwait
end;
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
asm
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');
restore_old_int10:=true;
end
else
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;
{ 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;
{ Special handler of interrupt $10
not needed anymore
Restore previous interrupt $10 handler }
if restore_old_int10 then
asm
push es
mov bx,word [SaveInt10]
mov dx,word [SaveInt10+2]
mov es,dx
mov ax, $2506
int $21
pop es
end;
end;
{$I system.inc}