diff options
Diffstat (limited to 'mips/rtl/linux/mips/sighnd.inc')
-rw-r--r-- | mips/rtl/linux/mips/sighnd.inc | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/mips/rtl/linux/mips/sighnd.inc b/mips/rtl/linux/mips/sighnd.inc index ae71d813c4..2a782e21f1 100644 --- a/mips/rtl/linux/mips/sighnd.inc +++ b/mips/rtl/linux/mips/sighnd.inc @@ -15,10 +15,11 @@ **********************************************************************} -procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigContext);cdecl; +procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; UContext: PUContext);cdecl; var res : word; addr : pointer; + frame : pointer; begin res:=0; addr:=nil; @@ -27,11 +28,12 @@ begin begin addr := siginfo^._sifields._sigfault._addr; res := 207; + case siginfo^.si_code of FPE_INTDIV: res:=200; FPE_INTOVF: - res:=205; + res:=215; FPE_FLTDIV: res:=200; FPE_FLTOVF: @@ -57,5 +59,32 @@ begin reenable_signal(sig); { give runtime error at the position where the signal was raised } if res<>0 then - HandleErrorAddrFrame(res,addr,nil); + begin + if assigned(UContext) then + begin + frame:=pointer(ptruint(UContext^.uc_mcontext.sigc_regs[29])); { stack pointer } + addr:=pointer(ptruint(UContext^.uc_mcontext.sigc_pc)); { program counter } + if sig=SIGFPE then + begin + { Clear FPU exception bits } + UContext^.uc_mcontext.sigc_fpc_csr := UContext^.uc_mcontext.sigc_fpc_csr + and not (fpu_cause_mask or fpu_flags_mask); + end; + { Change $a1, $a2, $a3 and sig_pc to HandleErrorAddrFrame parameters } + UContext^.uc_mcontext.sigc_regs[4]:=res; + UContext^.uc_mcontext.sigc_regs[5]:=ptrint(addr); + UContext^.uc_mcontext.sigc_regs[6]:=ptrint(frame); + UContext^.uc_mcontext.sigc_pc:=ptrint(@HandleErrorAddrFrame); + { Let the system call HandleErrorAddrFrame } + exit; + end + else + begin + frame:=nil; + addr:=nil; + end; + if sig=SIGFPE then + set_fsr(get_fsr and not (fpu_cause_mask or fpu_flags_mask)); + HandleErrorAddrFrame(res,addr,frame); + end; end; |