fpc/rtl/darwin/x86/x86hnd.inc
Jonas Maebe 5c20481c7b * fixed floating point div-by-zero RTE code on Darwin (208 instead of 200,
fixes webtbs/tw32671)

git-svn-id: trunk@42045 -
2019-05-12 14:28:55 +00:00

106 lines
3.9 KiB
PHP

{
This file is part of the Free Pascal run time library.
(c) 2000-2003 by Marco van de Voort
member of the Free Pascal development team.
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
Signalhandler for FreeBSD/i386
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.
}
procedure SignalToRunerror(Sig: cint; info : psiginfo; SigContext:PSigContext); public name '_FPC_DEFAULTSIGHANDLER'; cdecl;
var
p: pbyte;
res : word;
begin
res:=0;
case sig of
SIGFPE :
begin
Case Info^.si_code Of
FPE_INTDIV : Res:=200; { integer divide by zero -NOTIMP on Mac OS X 10.4.7 }
FPE_FLTDIV : Res:=208; { floating point divide by zero }
FPE_FLTOVF : Res:=205; { floating point overflow }
FPE_FLTUND : Res:=206; { floating point underflow }
FPE_FLTRES, { floating point inexact result }
FPE_FLTINV : Res:=207; { invalid floating point operation }
else
begin
{ Assume that if an integer divide was executed, the }
{ error was a divide-by-zero (FPE_INTDIV is not }
{ implemented as of 10.5.0) }
{$ifdef cpu64}
p:=pbyte(sigcontext^.uc_mcontext^.ts.rip);
{$else cpu64}
p:=pbyte(sigcontext^.uc_mcontext^.ts.eip);
{$endif cpu64}
{ skip some prefix bytes }
while (p^ in [{$ifdef cpu64}$40..$4f,{$endif}$66,$67]) do
inc(p);
if (p^ in [$f6,$f7]) and
(((p+1)^ and (%110 shl 3)) = (%110 shl 3)) then
Res:=200
else
Res:=207; { coprocessor error }
end;
end;
{ make sure any fpu operations won't trigger new exceptions in handler }
sysResetFPU;
{ Now clear exception flags in the context }
{ perform an fnclex: clear exception and busy flags }
sigcontext^.uc_mcontext^.fs.fpu_fsw.flag0:=
sigcontext^.uc_mcontext^.fs.fpu_fsw.flag0 and (not(%11111111) and not(1 shl 15));
{ also clear sse exception flags }
sigcontext^.uc_mcontext^.fs.fpu_mxcsr:=
sigcontext^.uc_mcontext^.fs.fpu_mxcsr and not(%111111)
end;
SIGILL,
SIGBUS,
SIGSEGV :
res:=216;
SIGINT:
res:=217;
SIGQUIT:
res:=233;
end;
{$ifdef FPC_USE_SIGPROCMASK}
reenable_signal(sig);
{$endif }
if (res <> 0) then
begin
{$ifdef cpu64}
sigcontext^.uc_mcontext^.ts.rdi:=res;
sigcontext^.uc_mcontext^.ts.rsi:=sigcontext^.uc_mcontext^.ts.rip;
sigcontext^.uc_mcontext^.ts.rdx:=sigcontext^.uc_mcontext^.ts.rbp;
{ the ABI expects the stack pointer to be 8 bytes off alignment
due to the return address which has been pushed -- but take into account
that rsp may already unaligned in case of a leaf routine }
if (sigcontext^.uc_mcontext^.ts.rsp and 15)=0 then
dec(sigcontext^.uc_mcontext^.ts.rsp,sizeof(pointer));
{ return to run time error handler }
sigcontext^.uc_mcontext^.ts.rip:=ptruint(@HandleErrorAddrFrame);
{$else cpu64}
{ assume regcall calling convention is the default }
sigcontext^.uc_mcontext^.ts.eax:=res;
sigcontext^.uc_mcontext^.ts.edx:=sigcontext^.uc_mcontext^.ts.eip;
sigcontext^.uc_mcontext^.ts.ecx:=sigcontext^.uc_mcontext^.ts.ebp;
{ the ABI expects the stack pointer to be 4 bytes off alignment }
{ due to the return address which has been pushed -- but take into account
that esp may already unaligned in case of a leaf routine }
if (sigcontext^.uc_mcontext^.ts.esp and 15)=0 then
dec(sigcontext^.uc_mcontext^.ts.esp,sizeof(pointer));
{ return to run time error handler }
sigcontext^.uc_mcontext^.ts.eip:=ptruint(@HandleErrorAddrFrame);
{$endif cpu64}
end;
end;