diff options
author | florian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2020-12-30 13:53:10 +0000 |
---|---|---|
committer | florian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2020-12-30 13:53:10 +0000 |
commit | 6568978b5169330bb3f70d19a01896ab44495274 (patch) | |
tree | 2ea3bcfc81b0ea9b227210c895e1a732a423e821 | |
parent | 54cadc35491ef342de7f66077144fcb1e11a96cd (diff) | |
download | fpc-6568978b5169330bb3f70d19a01896ab44495274.tar.gz |
* manually merged parts of r42260 to enable further merges
git-svn-id: https://svn.freepascal.org/svn/fpc/branches/fixes_3_2@47905 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r-- | rtl/i386/i386.inc | 8 | ||||
-rw-r--r-- | rtl/linux/i386/sighnd.inc | 89 | ||||
-rw-r--r-- | rtl/linux/i386/sighndh.inc | 27 | ||||
-rw-r--r-- | rtl/linux/x86_64/sighnd.inc | 79 | ||||
-rw-r--r-- | rtl/x86_64/x86_64.inc | 9 |
5 files changed, 159 insertions, 53 deletions
diff --git a/rtl/i386/i386.inc b/rtl/i386/i386.inc index 01bc03e442..64dc6f7332 100644 --- a/rtl/i386/i386.inc +++ b/rtl/i386/i386.inc @@ -1299,6 +1299,14 @@ const FPU_StackOverflow = $40; FPU_ExceptionMask = $ff; + MM_Invalid = 1; + MM_Denormal = 2; + MM_DivisionByZero = 4; + MM_Overflow = 8; + MM_Underflow = $10; + MM_Precicion = $20; + MM_ExceptionMask = $3f; + MM_MaskInvalidOp = %0000000010000000; MM_MaskDenorm = %0000000100000000; MM_MaskDivZero = %0000001000000000; diff --git a/rtl/linux/i386/sighnd.inc b/rtl/linux/i386/sighnd.inc index 2a83e47c1c..4a7a0dd3f3 100644 --- a/rtl/linux/i386/sighnd.inc +++ b/rtl/linux/i386/sighnd.inc @@ -16,9 +16,16 @@ **********************************************************************} +{ use a trampoline which pushes the return address for proper unwinding } +Procedure SignalToHandleErrorAddrFrame (Errno : longint;addr : CodePointer; frame : Pointer); nostackframe; assembler; +asm + pushl addr + jmp HandleErrorAddrFrame +end; + procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; UContext: Pucontext);public name '_FPC_DEFAULTSIGHANDLER';cdecl; var - res,fpustate : word; + res,fpustate,MMState : word; begin res:=0; case sig of @@ -27,35 +34,59 @@ begin { this is not allways necessary but I don't know yet how to tell if it is or not PM } res:=200; - if assigned(ucontext^.uc_mcontext.fpstate) then + if SigInfo^.si_code<>FPE_INTDIV then begin - FpuState:=ucontext^.uc_mcontext.fpstate^.sw; - if (FpuState and FPU_ExceptionMask) <> 0 then - begin - { first check the more precise options } - if (FpuState and FPU_DivisionByZero)<>0 then - res:=200 - else if (FpuState and (FPU_StackOverflow or FPU_StackUnderflow or FPU_Invalid))<>0 Then - res:=207 - else if (FpuState and FPU_Overflow)<>0 then - res:=205 - else if (FpuState and FPU_Underflow)<>0 then - res:=206 - else if (FpuState and FPU_Denormal)<>0 then - res:=216 - else - res:=207; {'Coprocessor Error'} - end; - with ucontext^.uc_mcontext.fpstate^ do + if assigned(ucontext^.uc_mcontext.fpstate) then begin - { Reset Status word } - sw:=sw and not FPU_ExceptionMask; - { Restoree default control word } - cw:=Default8087CW; - { Reset Tag word to $ffff for all empty } - tag:=$ffff; - end; - end; + FpuState:=ucontext^.uc_mcontext.fpstate^.sw; + if (FpuState and FPU_ExceptionMask) <> 0 then + begin + { first check the more precise options } + if (FpuState and FPU_DivisionByZero)<>0 then + res:=208 + else if (FpuState and (FPU_StackOverflow or FPU_StackUnderflow or FPU_Invalid))<>0 Then + res:=207 + else if (FpuState and FPU_Overflow)<>0 then + res:=205 + else if (FpuState and FPU_Underflow)<>0 then + res:=206 + else if (FpuState and FPU_Denormal)<>0 then + res:=216 + else + res:=207; {'Coprocessor Error'} + end; + { SSE data? } + if ucontext^.uc_mcontext.fpstate^.magic<>$ffff then + begin + MMState:=ucontext^.uc_mcontext.fpstate^.mxcsr; + if (MMState and MM_ExceptionMask)<>0 then + begin + { first check the more precise options } + if (MMState and MM_DivisionByZero)<>0 then + res:=208 + else if (MMState and MM_Invalid)<>0 Then + res:=207 + else if (MMState and MM_Overflow)<>0 then + res:=205 + else if (MMState and MM_Underflow)<>0 then + res:=206 + else if (MMState and MM_Denormal)<>0 then + res:=216 + else + res:=207; {'Coprocessor Error'} + end; + end; + with ucontext^.uc_mcontext.fpstate^ do + begin + { Reset Status word } + sw:=sw and not FPU_ExceptionMask; + { Restoree default control word } + cw:=Default8087CW; + { Reset Tag word to $ffff for all empty } + tag:=$ffff; + end; + end; + end; end; SIGBUS: res:=214; @@ -82,7 +113,7 @@ begin ucontext^.uc_mcontext.eax := res; ucontext^.uc_mcontext.edx := ucontext^.uc_mcontext.eip; ucontext^.uc_mcontext.ecx := ucontext^.uc_mcontext.ebp; - ucontext^.uc_mcontext.eip := ptruint(@HandleErrorAddrFrame); + ucontext^.uc_mcontext.eip := ptruint(@SignalToHandleErrorAddrFrame); end; end; diff --git a/rtl/linux/i386/sighndh.inc b/rtl/linux/i386/sighndh.inc index ecb5a92b30..999eeeac84 100644 --- a/rtl/linux/i386/sighndh.inc +++ b/rtl/linux/i386/sighndh.inc @@ -18,15 +18,32 @@ type tfpreg = record - significand: array[0..3] of word; - exponent: word; + significand: array[0..3] of word; + exponent: word; end; + tfpxreg = record + significand: array[0..3] of word; + exponent: word; + padding : array[0..2] of word; + end; + + txmmreg = record + element : array[0..3] of dword; + end; + + pfpstate = ^tfpstate; tfpstate = record - cw, sw, tag, ipoff, cssel, dataoff, datasel: cardinal; - st: array[0..7] of tfpreg; - status: cardinal; + cw, sw, tag, ipoff, cssel, dataoff, datasel: cardinal; + st: array[0..7] of tfpreg; + status, magic: word; + fxsr_env : array[0..5] of dword; + mxcsr : dword; + reserved : dword; + fxsr_st : array[0..7] of tfpxreg; + xmmreg : array[0..7] of txmmreg; + padding : array[0..55] of dword; end; PSigContext = ^TSigContext; diff --git a/rtl/linux/x86_64/sighnd.inc b/rtl/linux/x86_64/sighnd.inc index e8fa3cac0c..da570a90d5 100644 --- a/rtl/linux/x86_64/sighnd.inc +++ b/rtl/linux/x86_64/sighnd.inc @@ -16,6 +16,13 @@ **********************************************************************} +{ use a trampoline which pushes the return address for proper unwinding } +Procedure SignalToHandleErrorAddrFrame (Errno : longint;addr : CodePointer; frame : Pointer); nostackframe; assembler; +asm + pushq addr + jmp HandleErrorAddrFrame +end; + const FPU_All = $7f; @@ -33,10 +40,21 @@ function GetFPUState(const SigContext : TSigContext) : word; {$endif SYSTEM_DEBUG} end; +function GetMMState(const SigContext : TSigContext) : dword; + begin + if assigned(SigContext.fpstate) then + Result:=SigContext.fpstate^.mxcsr + else + Result:=0; + {$ifdef SYSTEM_DEBUG} + Writeln(stderr,'MMState = ',result); + {$endif SYSTEM_DEBUG} + end; + procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigContext); public name '_FPC_DEFAULTSIGHANDLER'; cdecl; var - res,fpustate : word; + res,fpustate,MMState : word; begin res:=0; case sig of @@ -45,24 +63,44 @@ procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigCon { this is not allways necessary but I don't know yet how to tell if it is or not PM } res:=200; - fpustate:=GetFPUState(SigContext^); - if (FpuState and FPU_All) <> 0 then + if SigInfo^.si_code<>FPE_INTDIV then begin - { first check the more precise options } - if (FpuState and FPU_DivisionByZero)<>0 then - res:=200 - else if (FpuState and FPU_Overflow)<>0 then - res:=205 - else if (FpuState and FPU_Underflow)<>0 then - res:=206 - else if (FpuState and FPU_Denormal)<>0 then - res:=216 - else if (FpuState and (FPU_StackOverflow or FPU_StackUnderflow or FPU_Invalid))<>0 Then - res:=207 - else - res:=207; {'Coprocessor Error'} + fpustate:=GetFPUState(SigContext^); + if (FpuState and FPU_All) <> 0 then + begin + { first check the more precise options } + if (FpuState and FPU_DivisionByZero)<>0 then + res:=200 + else if (FpuState and FPU_Overflow)<>0 then + res:=205 + else if (FpuState and FPU_Underflow)<>0 then + res:=206 + else if (FpuState and FPU_Denormal)<>0 then + res:=216 + else if (FpuState and (FPU_StackOverflow or FPU_StackUnderflow or FPU_Invalid))<>0 Then + res:=207 + else + res:=207; {'Coprocessor Error'} + end; + MMState:=getMMState(SigContext^); + if (MMState and MM_ExceptionMask)<>0 then + begin + { first check the more precise options } + if (MMState and MM_DivisionByZero)<>0 then + res:=208 + else if (MMState and MM_Invalid)<>0 Then + res:=207 + else if (MMState and MM_Overflow)<>0 then + res:=205 + else if (MMState and MM_Underflow)<>0 then + res:=206 + else if (MMState and MM_Denormal)<>0 then + res:=216 + else + res:=207; {'Coprocessor Error'} + end; end; - SysResetFPU; + SysResetFPU; end; SIGILL, SIGBUS, @@ -75,7 +113,12 @@ procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigCon end; reenable_signal(sig); if res<>0 then - HandleErrorAddrFrame(res,pointer(SigContext^.rip),pointer(SigContext^.rbp)); + begin + SigContext^.rdi := res; + SigContext^.rsi := SigContext^.rip; + SigContext^.rdx := SigContext^.rbp; + SigContext^.rip := ptruint(@SignalToHandleErrorAddrFrame); + end; end; diff --git a/rtl/x86_64/x86_64.inc b/rtl/x86_64/x86_64.inc index ae6b6c99f5..c3412ca53b 100644 --- a/rtl/x86_64/x86_64.inc +++ b/rtl/x86_64/x86_64.inc @@ -933,6 +933,14 @@ const FPU_StackOverflow = $40; FPU_ExceptionMask = $ff; + MM_Invalid = 1; + MM_Denormal = 2; + MM_DivisionByZero = 4; + MM_Overflow = 8; + MM_Underflow = $10; + MM_Precicion = $20; + MM_ExceptionMask = $3f; + MM_MaskInvalidOp = %0000000010000000; MM_MaskDenorm = %0000000100000000; MM_MaskDivZero = %0000001000000000; @@ -940,7 +948,6 @@ const MM_MaskUnderflow = %0000100000000000; MM_MaskPrecision = %0001000000000000; - procedure fpc_cpuinit; begin { don't let libraries influence the FPU cw set by the host program } |