mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-05 14:18:50 +02:00
927 lines
23 KiB
ObjectPascal
927 lines
23 KiB
ObjectPascal
{
|
||
$Id$
|
||
This file is part of the Free Pascal run time library.
|
||
Copyright (c) 1997-98 by Pierre Muller
|
||
|
||
DPMI Exception routines for Go32V2
|
||
|
||
See the file COPYING.FPC, included in this distribution,
|
||
for details about the copyright.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
||
**********************************************************************}
|
||
Unit DPMIExcp;
|
||
|
||
{$define UseRMcbrk}
|
||
|
||
interface
|
||
|
||
uses
|
||
go32;
|
||
|
||
{ No stack checking ! }
|
||
{$S-}
|
||
|
||
{ Error Messages }
|
||
function do_faulting_finish_message : integer;
|
||
|
||
{ SetJmp/LongJmp }
|
||
type
|
||
dpmi_jmp_buf = packed record
|
||
eax,ebx,ecx,edx,esi,edi,ebp,esp,eip,flags : longint;
|
||
cs,ds,es,fs,gs,ss : word;
|
||
end;
|
||
pdpmi_jmp_buf = ^dpmi_jmp_buf;
|
||
function dpmi_setjmp(var rec : dpmi_jmp_buf) : longint;
|
||
procedure dpmi_longjmp(var rec : dpmi_jmp_buf;return_value : longint);
|
||
|
||
{ Signals }
|
||
const
|
||
SIGABRT = 288;
|
||
SIGFPE = 289;
|
||
SIGILL = 290;
|
||
SIGSEGV = 291;
|
||
SIGTERM = 292;
|
||
SIGALRM = 293;
|
||
SIGHUP = 294;
|
||
SIGINT = 295;
|
||
SIGKILL = 296;
|
||
SIGPIPE = 297;
|
||
SIGQUIT = 298;
|
||
SIGUSR1 = 299;
|
||
SIGUSR2 = 300;
|
||
SIGNOFP = 301;
|
||
SIGTRAP = 302;
|
||
SIGTIMR = 303; { Internal for setitimer (SIGALRM, SIGPROF) }
|
||
SIGPROF = 304;
|
||
SIGMAX = 320;
|
||
|
||
SIG_BLOCK = 1;
|
||
SIG_SETMASK = 2;
|
||
SIG_UNBLOCK = 3;
|
||
|
||
function SIG_DFL( x: longint) : longint;
|
||
function SIG_ERR( x: longint) : longint;
|
||
function SIG_IGN( x: longint) : longint;
|
||
|
||
type
|
||
SignalHandler = function (v : longint) : longint;
|
||
PSignalHandler = SignalHandler; { to be compatible with linux.pp }
|
||
|
||
function signal(sig : longint;func : SignalHandler) : SignalHandler;
|
||
function _raise(sig : longint) : longint;
|
||
|
||
{ Exceptions }
|
||
type
|
||
texception_state = record
|
||
__eax, __ebx, __ecx, __edx, __esi : longint;
|
||
__edi, __ebp, __esp, __eip, __eflags : longint;
|
||
__cs, __ds, __es, __fs, __gs, __ss : word;
|
||
__sigmask : longint; { for POSIX signals only }
|
||
__signum : longint; { for expansion }
|
||
__exception_ptr : longint; { pointer to previous exception }
|
||
__fpu_state : array [0..108-1] of byte; { for future use }
|
||
end;
|
||
pexception_state = ^texception_state;
|
||
|
||
procedure djgpp_exception_toggle;
|
||
procedure djgpp_exception_setup;
|
||
function djgpp_exception_state : pexception_state;
|
||
function djgpp_set_ctrl_c(enable : boolean) : boolean;
|
||
|
||
{ Other }
|
||
function dpmi_set_coprocessor_emulation(flag : longint) : longint;
|
||
|
||
|
||
implementation
|
||
|
||
{$ifdef VER0_99_5}
|
||
{$I386_DIRECT}
|
||
{$endif}
|
||
|
||
{$ASMMODE DIRECT}
|
||
|
||
{$L exceptn.o}
|
||
|
||
var
|
||
exceptions_on : boolean;
|
||
starttext, endtext : pointer;
|
||
|
||
{****************************************************************************
|
||
Helpers
|
||
****************************************************************************}
|
||
|
||
procedure err(const x : string);
|
||
begin
|
||
write(stderr, x);
|
||
{$ifdef VER0_99_5}
|
||
flush(stderr);
|
||
{$endif}
|
||
end;
|
||
|
||
procedure errln(const x : string);
|
||
begin
|
||
writeln(stderr, x);
|
||
{$ifdef VER0_99_5}
|
||
flush(stderr);
|
||
{$endif}
|
||
end;
|
||
|
||
|
||
procedure itox(v,len : longint);
|
||
var
|
||
st : string;
|
||
begin
|
||
st:=hexstr(v,len);
|
||
err(st);
|
||
end;
|
||
|
||
|
||
{****************************************************************************
|
||
SetJmp/LongJmp
|
||
****************************************************************************}
|
||
|
||
function dpmi_setjmp(var rec : dpmi_jmp_buf) : longint;
|
||
begin
|
||
asm
|
||
pushl %edi
|
||
movl rec,%edi
|
||
movl %eax,(%edi)
|
||
movl %ebx,4(%edi)
|
||
movl %ecx,8(%edi)
|
||
movl %edx,12(%edi)
|
||
movl %esi,16(%edi)
|
||
{ load edi }
|
||
movl -4(%ebp),%eax
|
||
{ ... and store it }
|
||
movl %eax,20(%edi)
|
||
{ ebp ... }
|
||
movl (%ebp),%eax
|
||
movl %eax,24(%edi)
|
||
{ esp ... }
|
||
movl %esp,%eax
|
||
addl $12,%eax
|
||
movl %eax,28(%edi)
|
||
{ the return address }
|
||
movl 4(%ebp),%eax
|
||
movl %eax,32(%edi)
|
||
{ flags ... }
|
||
pushfl
|
||
popl 36(%edi)
|
||
{ !!!!! the segment registers, not yet needed }
|
||
{ you need them if the exception comes from
|
||
an interrupt or a seg_move }
|
||
movw %cs,40(%edi)
|
||
movw %ds,42(%edi)
|
||
movw %es,44(%edi)
|
||
movw %fs,46(%edi)
|
||
movw %gs,48(%edi)
|
||
movw %ss,50(%edi)
|
||
movl ___djgpp_exception_state_ptr, %eax
|
||
movl %eax, 60(%edi)
|
||
{ restore EDI }
|
||
pop %edi
|
||
{ we come from the initial call }
|
||
xorl %eax,%eax
|
||
leave
|
||
ret $4
|
||
end;
|
||
end;
|
||
|
||
|
||
const
|
||
exception_level : longint = 0;
|
||
|
||
procedure dpmi_longjmp(var rec : dpmi_jmp_buf;return_value : longint);
|
||
begin
|
||
if (@rec=pdpmi_jmp_buf(djgpp_exception_state)) and (exception_level>0) then
|
||
dec(exception_level);
|
||
asm
|
||
{ restore compiler shit }
|
||
popl %ebp
|
||
{ copy from longjmp.S }
|
||
movl 4(%esp),%edi { get dpmi_jmp_buf }
|
||
movl 8(%esp),%eax { store retval in j->eax }
|
||
movl %eax,0(%edi)
|
||
|
||
movw 46(%edi),%fs
|
||
movw 48(%edi),%gs
|
||
movl 4(%edi),%ebx
|
||
movl 8(%edi),%ecx
|
||
movl 12(%edi),%edx
|
||
movl 24(%edi),%ebp
|
||
{ Now for some uglyness. The dpmi_jmp_buf structure may be ABOVE the
|
||
point on the new SS:ESP we are moving to. We don't allow overlap,
|
||
but do force that it always be valid. We will use ES:ESI for
|
||
our new stack before swapping to it. }
|
||
movw 50(%edi),%es
|
||
movl 28(%edi),%esi
|
||
subl $28,%esi { We need 7 working longwords on stack }
|
||
movl 60(%edi),%eax
|
||
es
|
||
movl %eax,(%esi) { Exception pointer }
|
||
movzwl 42(%edi),%eax
|
||
es
|
||
movl %eax,4(%esi) { DS }
|
||
movl 20(%edi),%eax
|
||
es
|
||
movl %eax,8(%esi) { EDI }
|
||
movl 16(%edi),%eax
|
||
es
|
||
movl %eax,12(%esi) { ESI }
|
||
movl 32(%edi),%eax
|
||
es
|
||
movl %eax,16(%esi) { EIP - start of IRET frame }
|
||
movl 40(%edi),%eax
|
||
es
|
||
movl %eax,20(%esi) { CS }
|
||
movl 36(%edi),%eax
|
||
es
|
||
movl %eax,24(%esi) { EFLAGS }
|
||
movl 0(%edi),%eax
|
||
movw 44(%edi),%es
|
||
movw 50(%edi),%ss
|
||
movl %esi,%esp
|
||
popl ___djgpp_exception_state_ptr
|
||
popl %ds
|
||
popl %edi
|
||
popl %esi
|
||
iret { actually jump to new cs:eip loading flags }
|
||
end;
|
||
end;
|
||
|
||
|
||
{****************************************************************************
|
||
Signals
|
||
****************************************************************************}
|
||
|
||
var
|
||
signal_list : Array[0..SIGMAX] of SignalHandler;
|
||
|
||
function SIG_ERR( x: longint) : longint;
|
||
begin
|
||
SIG_ERR:=-1;
|
||
end;
|
||
|
||
|
||
function SIG_IGN( x: longint) : longint;
|
||
begin
|
||
SIG_IGN:=-1;
|
||
end;
|
||
|
||
|
||
function SIG_DFL( x: longint) : longint;
|
||
begin
|
||
SIG_DFL:=0;
|
||
end;
|
||
|
||
|
||
function signal(sig : longint;func : SignalHandler) : SignalHandler;
|
||
var
|
||
temp : SignalHandler;
|
||
begin
|
||
if ((sig <= 0) or (sig > SIGMAX) or (sig = SIGKILL)) then
|
||
begin
|
||
signal:=@SIG_ERR;
|
||
runerror(201);
|
||
end;
|
||
temp := signal_list[sig - 1];
|
||
signal_list[sig - 1] := func;
|
||
signal:=temp;
|
||
end;
|
||
|
||
|
||
const signames : array [0..14] of string[4] = (
|
||
'ABRT','FPE ','ILL ','SEGV','TERM','ALRM','HUP ',
|
||
'INT ','KILL','PIPE','QUIT','USR1','USR2','NOFP','TRAP');
|
||
|
||
|
||
function _raise(sig : longint) : longint;
|
||
var
|
||
temp : SignalHandler;
|
||
label
|
||
traceback_exit;
|
||
begin
|
||
if(sig <= 0) or (sig > SIGMAX) then
|
||
exit(-1);
|
||
temp:=signal_list[sig - 1];
|
||
if (temp = SignalHandler(@SIG_IGN)) then
|
||
exit(0);
|
||
if (temp = SignalHandler(@SIG_DFL)) then
|
||
begin
|
||
traceback_exit:
|
||
if ((sig >= SIGABRT) and (sig <= SIGTRAP)) then
|
||
begin
|
||
err('Exiting due to signal SIG');
|
||
err(signames[sig-sigabrt]);
|
||
end
|
||
else
|
||
begin
|
||
err('Exiting due to signal $');
|
||
itox(sig, 4);
|
||
end;
|
||
errln('');
|
||
{ if(djgpp_exception_state<>nil) then }
|
||
do_faulting_finish_message(); { Exits, does not return }
|
||
exit(-1);
|
||
end;
|
||
if ((longint(temp) < longint(starttext)) or (longint(temp) > longint(endtext))) then
|
||
begin
|
||
errln('Bad signal handler, ');
|
||
goto traceback_exit;
|
||
end;
|
||
temp(sig);
|
||
exit(0);
|
||
end;
|
||
|
||
{****************************************************************************
|
||
Exceptions
|
||
****************************************************************************}
|
||
|
||
const
|
||
cbrk_vect : byte = $1b;
|
||
|
||
function except_to_sig(excep : longint) : longint;
|
||
begin
|
||
case excep of
|
||
5,8,9,11,12,13,14 : exit(SIGSEGV);
|
||
0,4,16 : exit(SIGFPE);
|
||
1,3 : exit(SIGTRAP);
|
||
7 : exit(SIGNOFP);
|
||
else
|
||
begin
|
||
if(excep = $75) then {/* HW int to fake exception values hardcoded in exceptn.S */}
|
||
exit(SIGFPE)
|
||
else if (excep = $78) then
|
||
exit(SIGTIMR)
|
||
else if ((excep = $79) or (excep = $1b)) then
|
||
exit(SIGINT)
|
||
else
|
||
exit(SIGILL);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
{
|
||
function except_to_sig(excep : longint) : longint;
|
||
begin
|
||
case excep of
|
||
5,8,9,
|
||
11,12,13,14 : exit(SIGSEGV);
|
||
0,4,16 : exit(SIGFPE);
|
||
1,3 : exit(SIGTRAP);
|
||
7 : exit(SIGNOFP);
|
||
$75 : exit(SIGFPE);
|
||
$78 : exit(SIGTIMR);
|
||
$1b,$79 : exit(SIGINT);
|
||
else
|
||
exit(SIGILL);
|
||
end;
|
||
end;
|
||
}
|
||
|
||
procedure show_call_frame;
|
||
begin
|
||
errln('Call frame traceback EIPs:');
|
||
errln(' 0x'+hexstr(djgpp_exception_state^.__eip, 8));
|
||
dump_stack(djgpp_exception_state^.__ebp);
|
||
end;
|
||
|
||
|
||
const
|
||
EXCEPTIONCOUNT = 18;
|
||
exception_names : array[0..EXCEPTIONCOUNT-1] of pchar = (
|
||
'Division by Zero',
|
||
'Debug',
|
||
'NMI',
|
||
'Breakpoint',
|
||
'Overflow',
|
||
'Bounds Check',
|
||
'Invalid Opcode',
|
||
'Coprocessor not available',
|
||
'Double Fault',
|
||
'Coprocessor overrun',
|
||
'Invalid TSS',
|
||
'Segment Not Present',
|
||
'Stack Fault',
|
||
'General Protection Fault',
|
||
'Page fault',
|
||
' ',
|
||
'Coprocessor Error',
|
||
'Alignment Check');
|
||
|
||
has_error : array [0..EXCEPTIONCOUNT-1] of byte =
|
||
(0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1);
|
||
|
||
cbrk_hooked : boolean = false;
|
||
old_video_mode : byte = 3;
|
||
|
||
|
||
procedure dump_selector(const name : string; sel : word);
|
||
var
|
||
base,limit : longint;
|
||
begin
|
||
err(name);
|
||
err(': sel=');
|
||
itox(sel, 4);
|
||
if (sel<>0) then
|
||
begin
|
||
base:=get_segment_base_address(sel);
|
||
err(' base='); itox(base, 8);
|
||
limit:=get_segment_limit(sel);
|
||
err(' limit='); itox(limit, 8);
|
||
end;
|
||
errln('');
|
||
end;
|
||
|
||
|
||
function farpeekb(sel : word;offset : longint) : byte;
|
||
var
|
||
b : byte;
|
||
begin
|
||
seg_move(sel,offset,get_ds,longint(@b),1);
|
||
farpeekb:=b;
|
||
end;
|
||
|
||
|
||
|
||
function do_faulting_finish_message : integer;
|
||
var
|
||
en : pchar;
|
||
signum,i : longint;
|
||
old_vid : byte;
|
||
begin
|
||
do_faulting_finish_message:=0;
|
||
signum:=djgpp_exception_state^.__signum;
|
||
{ check video mode for original here and reset (not if PC98) */ }
|
||
if ((go32_info_block.linear_address_of_primary_screen <> $a0000) and
|
||
(farpeekb(dosmemselector, $449) <> old_video_mode)) then
|
||
begin
|
||
old_vid:=old_video_mode;
|
||
asm
|
||
pusha
|
||
movzbl old_vid,%eax
|
||
int $0x10
|
||
popa
|
||
nop
|
||
end;
|
||
end;
|
||
|
||
if (signum >= EXCEPTIONCOUNT) then
|
||
en:=nil
|
||
else
|
||
en:=exception_names[signum];
|
||
if (signum = $75) then
|
||
en:='Floating Point exception';
|
||
if (signum = $1b) then
|
||
en:='Control-Break Pressed';
|
||
if (signum = $79) then
|
||
en:='Control-C Pressed';
|
||
if (en = nil) then
|
||
begin
|
||
err('Exception ');
|
||
itox(signum, 2);
|
||
err(' at eip=');
|
||
itox(djgpp_exception_state^.__eip, 8);
|
||
end
|
||
else
|
||
begin
|
||
write(stderr, 'FPC ',en);
|
||
err(' at eip=');
|
||
itox(djgpp_exception_state^.__eip, 8);
|
||
end;
|
||
{ Control-C should stop the program also !}
|
||
{if (signum = $79) then
|
||
begin
|
||
errln('');
|
||
exit(-1);
|
||
end;}
|
||
if ((signum < EXCEPTIONCOUNT) and (has_error[signum]=1)) then
|
||
begin
|
||
errorcode := djgpp_exception_state^.__sigmask and $ffff;
|
||
if(errorcode<>0) then
|
||
begin
|
||
err(', error=');
|
||
itox(errorcode, 4);
|
||
end;
|
||
end;
|
||
errln('');
|
||
err('eax=');
|
||
itox(djgpp_exception_state^.__eax, 8);
|
||
err(' ebx='); itox(djgpp_exception_state^.__ebx, 8);
|
||
err(' ecx='); itox(djgpp_exception_state^.__ecx, 8);
|
||
err(' edx='); itox(djgpp_exception_state^.__edx, 8);
|
||
err(' esi='); itox(djgpp_exception_state^.__esi, 8);
|
||
err(' edi='); itox(djgpp_exception_state^.__edi, 8);
|
||
errln('');
|
||
err('ebp='); itox(djgpp_exception_state^.__ebp, 8);
|
||
err(' esp='); itox(djgpp_exception_state^.__esp, 8);
|
||
err(' program=');
|
||
errln(paramstr(0));
|
||
dump_selector('cs', djgpp_exception_state^.__cs);
|
||
dump_selector('ds', djgpp_exception_state^.__ds);
|
||
dump_selector('es', djgpp_exception_state^.__es);
|
||
dump_selector('fs', djgpp_exception_state^.__fs);
|
||
dump_selector('gs', djgpp_exception_state^.__gs);
|
||
dump_selector('ss', djgpp_exception_state^.__ss);
|
||
errln('');
|
||
if (djgpp_exception_state^.__cs = get_cs) then
|
||
show_call_frame;
|
||
{ must not return !! }
|
||
if exceptions_on then
|
||
djgpp_exception_toggle;
|
||
asm
|
||
pushw $1
|
||
call ___exit
|
||
end;
|
||
end;
|
||
|
||
|
||
function djgpp_exception_state:pexception_state;assembler;
|
||
asm
|
||
movl ___djgpp_exception_state_ptr,%eax
|
||
end;
|
||
|
||
|
||
procedure djgpp_exception_processor;[public,alias : '___djgpp_exception_processor'];
|
||
var
|
||
sig : longint;
|
||
begin
|
||
inc(exception_level);
|
||
sig:=djgpp_exception_state^.__signum;
|
||
if (exception_level=1) or (sig=$78) then
|
||
begin
|
||
sig := except_to_sig(sig);
|
||
_raise(sig);
|
||
if (djgpp_exception_state^.__signum >= EXCEPTIONCOUNT) then
|
||
{ Not exception so continue OK }
|
||
dpmi_longjmp(pdpmi_jmp_buf(djgpp_exception_state)^, djgpp_exception_state^.__eax);
|
||
{ User handler did not exit or longjmp, we must exit }
|
||
err('FPC cannot continue from exception, exiting due to signal ');
|
||
itox(sig, 4);
|
||
errln('');
|
||
end
|
||
else
|
||
begin
|
||
if exception_level>2 then
|
||
begin
|
||
errln('FPC triple exception, exiting !!! ');
|
||
if (exceptions_on) then
|
||
djgpp_exception_toggle;
|
||
asm
|
||
pushw $1
|
||
call ___exit
|
||
end;
|
||
end;
|
||
err('FPC double exception, exiting due to signal ');
|
||
itox(sig, 4);
|
||
errln('');
|
||
end;
|
||
do_faulting_finish_message;
|
||
end;
|
||
|
||
|
||
type
|
||
trealseginfo = tseginfo;
|
||
pseginfo = ^tseginfo;
|
||
var
|
||
except_ori : array [0..EXCEPTIONCOUNT-1] of tseginfo;
|
||
kbd_ori : tseginfo;
|
||
npx_ori : tseginfo;
|
||
cbrk_ori,
|
||
cbrk_rmcb : trealseginfo;
|
||
cbrk_regs : registers;
|
||
|
||
function djgpp_cbrk_hdlr : pointer;
|
||
begin
|
||
asm
|
||
movl ___djgpp_cbrk_hdlr,%eax
|
||
movl %eax,__RESULT
|
||
end;
|
||
end;
|
||
|
||
|
||
function djgpp_old_kbd : pseginfo;
|
||
begin
|
||
asm
|
||
movl ___djgpp_old_kbd,%eax
|
||
movl %eax,__RESULT
|
||
end;
|
||
end;
|
||
|
||
procedure djgpp_exception_toggle;
|
||
var
|
||
_except : tseginfo;
|
||
i : longint;
|
||
local_ex : boolean;
|
||
begin
|
||
{$ifdef SYSTEMDEBUG}
|
||
if exceptions_on then
|
||
errln('Disabling FPC exceptions')
|
||
else
|
||
errln('Enabling FPC exceptions');
|
||
{$endif SYSTEMDEBUG}
|
||
{ toggle here to avoid infinite recursion }
|
||
{ if a subfunction calls runerror !! }
|
||
exceptions_on:=not exceptions_on;
|
||
local_ex:=exceptions_on;
|
||
asm
|
||
movzbl local_ex,%eax
|
||
movl %eax,_v2prt0_exceptions_on
|
||
end;
|
||
for i:=0 to EXCEPTIONCOUNT-1 do
|
||
begin
|
||
if get_pm_exception_handler(i,_except) then
|
||
begin
|
||
if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
|
||
begin
|
||
if not set_pm_exception_handler(i,except_ori[i]) then
|
||
errln('error setting exception n<>'+hexstr(i,2));
|
||
end;
|
||
except_ori[i]:=_except;
|
||
end
|
||
else
|
||
begin
|
||
if get_exception_handler(i,_except) then
|
||
begin
|
||
if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
|
||
begin
|
||
if not set_exception_handler(i,except_ori[i]) then
|
||
errln('error setting exception n<>'+hexstr(i,2));
|
||
end;
|
||
except_ori[i]:=_except;
|
||
end;
|
||
end;
|
||
end;
|
||
get_pm_interrupt($75, _except);
|
||
set_pm_interrupt($75, npx_ori);
|
||
npx_ori:=_except;
|
||
get_pm_interrupt(9, _except);
|
||
set_pm_interrupt(9, kbd_ori);
|
||
kbd_ori := _except;
|
||
{$ifdef UseRMcbrk}
|
||
if (cbrk_hooked) then
|
||
begin
|
||
set_rm_interrupt(cbrk_vect,cbrk_ori);
|
||
free_rm_callback(cbrk_rmcb);
|
||
cbrk_hooked := false;
|
||
{$ifdef SYSTEMDEBUG}
|
||
errln('back to ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
|
||
{$endif SYSTEMDEBUG}
|
||
end
|
||
else
|
||
begin
|
||
get_rm_interrupt(cbrk_vect, cbrk_ori);
|
||
{$ifdef SYSTEMDEBUG}
|
||
errln('ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
|
||
{$endif SYSTEMDEBUG}
|
||
get_rm_callback(djgpp_cbrk_hdlr, cbrk_regs, cbrk_rmcb);
|
||
set_rm_interrupt(cbrk_vect, cbrk_rmcb);
|
||
{$ifdef SYSTEMDEBUG}
|
||
errln('now rm cbrk '+hexstr(cbrk_rmcb.segment,4)+':'+hexstr(longint(cbrk_rmcb.offset),4));
|
||
{$endif SYSTEMDEBUG}
|
||
cbrk_hooked := true;
|
||
end;
|
||
{$endif UseRMcbrk}
|
||
end;
|
||
|
||
|
||
function dpmi_set_coprocessor_emulation(flag : longint) : longint;
|
||
var
|
||
res : longint;
|
||
begin
|
||
asm
|
||
movl flag,%ebx
|
||
movl $0xe01,%eax
|
||
int $0x31
|
||
jc .L_coproc_error
|
||
xorl %eax,%eax
|
||
.L_coproc_error:
|
||
movl %eax,res
|
||
end;
|
||
dpmi_set_coprocessor_emulation:=res;
|
||
end;
|
||
|
||
|
||
procedure dpmiexcp_exit{(status : longint)};[alias : 'excep_exit'];
|
||
{ We need to restore hardware interrupt handlers even if somebody calls
|
||
`_exit' directly, or else we crash the machine in nested programs.
|
||
We only toggle the handlers if the original keyboard handler is intact
|
||
(otherwise, they might have already toggled them). }
|
||
begin
|
||
if (exceptions_on) then
|
||
djgpp_exception_toggle;
|
||
asm
|
||
xorl %eax,%eax
|
||
movl %eax,_exception_exit
|
||
movl %eax,_swap_in
|
||
movl %eax,_swap_out
|
||
end;
|
||
{ restore the FPU state }
|
||
dpmi_set_coprocessor_emulation(1);
|
||
end;
|
||
|
||
|
||
{ used by dos.pp for swap vectors }
|
||
procedure dpmi_swap_in;[alias : 'swap_in'];
|
||
begin
|
||
if not (exceptions_on) then
|
||
djgpp_exception_toggle;
|
||
end;
|
||
|
||
|
||
procedure dpmi_swap_out;[alias : 'swap_out'];
|
||
begin
|
||
if (exceptions_on) then
|
||
djgpp_exception_toggle;
|
||
end;
|
||
|
||
|
||
procedure djgpp_exception_setup;
|
||
var
|
||
temp_kbd,
|
||
temp_npx : pointer;
|
||
_except,
|
||
old_kbd : tseginfo;
|
||
locksize : longint;
|
||
hw_lock_start,
|
||
hw_lock_end : longint;
|
||
i : longint;
|
||
dossel : word;
|
||
begin
|
||
asm
|
||
movl _exception_exit,%eax
|
||
xorl %eax,%eax
|
||
jne .L_already
|
||
leal excep_exit,%eax
|
||
movl %eax,_exception_exit
|
||
leal swap_in,%eax
|
||
movl %eax,_swap_in
|
||
leal swap_out,%eax
|
||
movl %eax,_swap_out
|
||
end;
|
||
{ reset signals }
|
||
for i := 0 to SIGMAX-1 do
|
||
signal_list[i] := SignalHandler(@SIG_DFL);
|
||
{ app_DS only used when converting HW interrupts to exceptions }
|
||
asm
|
||
movw %ds,___djgpp_app_DS
|
||
movw %ds,___djgpp_our_DS
|
||
movl $___djgpp_hw_lock_start,%eax
|
||
movl %eax,hw_lock_start
|
||
movl $___djgpp_hw_lock_end,%eax
|
||
movl %eax,hw_lock_end
|
||
end;
|
||
dossel := dosmemselector;
|
||
asm
|
||
movw dossel,%ax
|
||
movw %ax,___djgpp_dos_sel
|
||
end;
|
||
{ lock addresses which may see HW interrupts }
|
||
{ lockmem.address = __djgpp_base_address + (unsigned) &__djgpp_hw_lock_start;}
|
||
locksize := hw_lock_end - hw_lock_start;
|
||
lock_code(pointer(hw_lock_start),locksize);
|
||
_except.segment:=get_cs;
|
||
{ _except.offset:= (unsigned) &__djgpp_exception_table;}
|
||
asm
|
||
leal _except,%eax
|
||
movl $___djgpp_exception_table,(%eax)
|
||
end;
|
||
for i:=0 to ExceptionCount-1 do
|
||
begin
|
||
except_ori[i] := _except; { New value to set }
|
||
_except.offset:=_except.offset + 4; { This is the size of push n, jmp }
|
||
end;
|
||
|
||
kbd_ori.segment := _except.segment;
|
||
npx_ori.segment := _except.segment;
|
||
{ make local copy to solve mangledname problem (PFV) }
|
||
temp_npx:=@npx_ori;
|
||
temp_kbd:=@kbd_ori;
|
||
asm
|
||
movl temp_npx,%eax
|
||
movl $___djgpp_npx_hdlr,(%eax)
|
||
end;
|
||
if (go32_info_block.linear_address_of_primary_screen <> $a0000) then
|
||
begin
|
||
asm
|
||
movl temp_kbd,%eax
|
||
movl $___djgpp_kbd_hdlr,(%eax)
|
||
end;
|
||
end
|
||
else
|
||
begin
|
||
asm
|
||
movl temp_kbd,%eax
|
||
movl $___djgpp_kbd_hdlr_pc98,(%eax)
|
||
end;
|
||
cbrk_vect := $06;
|
||
asm
|
||
leal _except,%eax
|
||
movl $___djgpp_iret,(%eax)
|
||
end;
|
||
set_pm_interrupt($23,_except);
|
||
end;
|
||
asm
|
||
leal _except,%eax
|
||
movl $___djgpp_i24,(%eax)
|
||
end;
|
||
set_pm_interrupt($24, _except);
|
||
get_pm_interrupt(9,old_kbd);
|
||
asm
|
||
movl $___djgpp_old_kbd,%edi
|
||
leal old_kbd,%esi
|
||
movl $6,%ecx { sier of tseginfo }
|
||
rep
|
||
movsb
|
||
end;
|
||
djgpp_exception_toggle; { Set new values & save old values }
|
||
{ get original video mode and save }
|
||
old_video_mode := farpeekb(dosmemselector, $449);
|
||
asm
|
||
.L_already:
|
||
end;
|
||
end;
|
||
|
||
|
||
function djgpp_set_ctrl_c(enable : boolean) : boolean;
|
||
var
|
||
oldenable : boolean;
|
||
begin
|
||
asm
|
||
movb ___djgpp_hwint_flags,%al
|
||
andb $1,%al
|
||
movb %al,oldenable
|
||
end;
|
||
if (enable) then
|
||
asm
|
||
movl ___djgpp_hwint_flags,%eax
|
||
andl $0xfffe,%eax
|
||
movl %eax,___djgpp_hwint_flags
|
||
end
|
||
else
|
||
asm
|
||
movl ___djgpp_hwint_flags,%eax
|
||
orl $1,%eax
|
||
movl %eax,___djgpp_hwint_flags
|
||
end;
|
||
{ __djgpp_hwint_flags |= 1;}
|
||
djgpp_set_ctrl_c:=oldenable;
|
||
end;
|
||
|
||
|
||
procedure InitDPMIExcp;
|
||
var
|
||
tempendtext,
|
||
tempstarttext : pointer;
|
||
begin
|
||
{ We need to use tempendtext becuase the mangledname of endtext could be
|
||
different }
|
||
asm
|
||
movl $_etext,tempendtext
|
||
movl $start,tempstarttext
|
||
movl ___v2prt0_ds_alias,%eax
|
||
movl %eax,___djgpp_ds_alias
|
||
end;
|
||
endtext:=tempendtext;
|
||
starttext:=tempstarttext;
|
||
djgpp_exception_setup;
|
||
end;
|
||
|
||
|
||
begin
|
||
InitDPMIExcp;
|
||
end.
|
||
{
|
||
$Log$
|
||
Revision 1.7 1998-08-15 17:01:13 peter
|
||
* smartlinking the units works now
|
||
* setjmp/longjmp -> dmpi_setjmp/dpmi_longjmp to solve systemunit
|
||
conflict
|
||
|
||
Revision 1.6 1998/08/04 13:31:32 pierre
|
||
* changed all FPK into FPC
|
||
|
||
Revision 1.5 1998/07/08 12:02:19 carl
|
||
* make it compiler under fpc v0995
|
||
|
||
Revision 1.4 1998/06/26 08:19:08 pierre
|
||
+ all debug in ifdef SYSTEMDEBUG
|
||
+ added local arrays :
|
||
opennames names of opened files
|
||
fileopen boolean array to know if still open
|
||
usefull with gdb if you get problems about too
|
||
many open files !!
|
||
|
||
Revision 1.3 1998/05/31 14:18:23 peter
|
||
* force att or direct assembling
|
||
* cleanup of some files
|
||
|
||
Revision 1.2 1998/04/21 14:46:33 pierre
|
||
+ debug info better output
|
||
no normal code changed
|
||
}
|