diff --git a/rtl/linux/powerpc64/sighnd.inc b/rtl/linux/powerpc64/sighnd.inc index 0f70825adf..a575fab2ca 100644 --- a/rtl/linux/powerpc64/sighnd.inc +++ b/rtl/linux/powerpc64/sighnd.inc @@ -19,43 +19,78 @@ procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigContext);cdecl; var res : word; -{ fpustate: longint; } + fpustate : qword; + {$IFDEF EXCDEBUG} + p : pbyte; + i, j : integer; + {$ENDIF} begin res:=0; {$IFDEF EXCDEBUG} writeln('signaltorunerror'); + { dump SigContext } + p := pbyte(SigContext); + for j := 0 to sizeof(TSigContext) div 8 do begin + for i := 0 to 7 do begin + write(hexstr(p^, 2)); + inc(p); + end; + write(' '); + end; + writeln; {$ENDIF} + + { SigContext is actally a pointer to a ucontext structure. + So we do some ugly pointer casting to get it right again. + + See also in the *kernel* sources arch/ppc64/kernel/signal.c, + function setup_rt_sigframe() } + + SigContext := @(PUContext(SigContext)^.uc_mcontext); + { exception flags are turned off by kernel } fpc_enable_ppc_fpu_exceptions; case sig of SIGFPE : - begin -{ - fpscr is cleared by the kernel -> can't find out cause :( - fpustate := fpc_get_ppc_fpscr; - if (fpustate and ppc_fpu_underflow) <> 0 then - res := 206 - else if (fpustate and ppc_fpu_overflow) <> 0 then - res := 205 - else if (fpustate and ppc_fpu_divbyzero) <> 0 then - res := 200 - else -} - res := 207; - end; + begin + { ugly typecast to get the FPSCR register contents } + fpustate := QWord(PQWord(@SigContext^.fp_regs[PT_FPSCR])^); + {$IFDEF EXCDEBUG} + writeln('fpustate = ', hexstr(fpustate, sizeof(fpustate)*2)); + {$ENDIF} + + { TODO: distinguishing FPU signal type does not work as it should + if (fpustate and ppc_fpu_underflow) <> 0 then + res := 206 + else if (fpustate and ppc_fpu_overflow) <> 0 then + res := 205 + else if (fpustate and ppc_fpu_divbyzero) <> 0 then + res := 200 + else } + res := 207; + end; SIGBUS : - res:=214; + res:=214; SIGILL, SIGSEGV : - res:=216; + res:=216; end; {$IFDEF EXCDEBUG} writeln('sig = ', sig); writeln('siginfo = ', hexstr(ptrint(siginfo), sizeof(siginfo)*2)); writeln('sigcontext = ', hexstr(ptrint(sigcontext), sizeof(sigcontext)*2)); + + writeln('sigcontext...signal = ', hexstr(sigcontext^.signal, 16)); + + writeln('sigcontext^...regs = ', hexstr(ptrint(sigcontext^.regs), 16)); {$ENDIF} + reenable_signal(sig); { give runtime error at the position where the signal was raised } + if res<>0 then - HandleErrorAddrFrame(res,pointer(SigContext^.pt_regs^.nip),pointer(SigContext^.pt_regs^.gpr[1])); + HandleErrorAddrFrame(res, pointer(SigContext^.gp_regs[PT_NIP]), pointer(SigContext^.gp_regs[PT_R1])); + {$IFDEF EXCDEBUG} + readln; + {$ENDIF} end; diff --git a/rtl/linux/powerpc64/sighndh.inc b/rtl/linux/powerpc64/sighndh.inc index 6cb1a81cf9..8c8d94c5df 100644 --- a/rtl/linux/powerpc64/sighndh.inc +++ b/rtl/linux/powerpc64/sighndh.inc @@ -1,9 +1,8 @@ { This file is part of the Free Pascal run time library. - Copyright (c) 1999-2000 by Jonas Maebe, - member of the Free Pascal development team. + Copyright (c) 2005 by Thomas Schatzl - TSigContext + TSigContext and associated structures See the file COPYING.FPC, included in this distribution, for details about the copyright. @@ -17,65 +16,151 @@ {$packrecords C} type - TPPC_Reg = QWord; + gpr_reg = cULong; + fpr_reg = double; + vvr_reg = array[0..1] of cULong; + +type { from include/asm-ppc64/ptrace.h } - pptregs = ^tptregs; - tptregs = record - gpr: array[0..31] of TPPC_Reg; - nip: TPPC_Reg; - msr: TPPC_Reg; - orig_gpr3: TPPC_Reg; { Used for restarting system calls } - ctr: TPPC_Reg; - link: TPPC_Reg; - xer: TPPC_Reg; - ccr: TPPC_Reg; - softe: TPPC_Reg; { soft enabled/disabled } - trap: TPPC_Reg; { Reason for being here } - dar: TPPC_Reg; { Fault registers } - dsisr: TPPC_Reg; - result: TPPC_Reg; { Result of a system call } + ppt_regs = ^pt_regs; + pt_regs = record + gpr : array[0..31] of gpr_reg; + nip : gpr_reg; + msr : gpr_reg; + orig_gpr3 : gpr_reg; { Used for restarting system calls } + ctr : gpr_reg; + link : gpr_reg; + xer : gpr_reg; + ccr : gpr_reg; + softe : gpr_reg; { Soft enabled/disabled } + trap : gpr_reg; { Reason for being here } + dar : gpr_reg; { Fault registers } + dsisr : gpr_reg; + result : gpr_reg; { Result of a system call } end; +{ index constants for the different register set arrays in TSigContext. + Comments were directly pasted from the sources. +} +const + PT_R0 = 0; + PT_R1 = 1; + PT_R2 = 2; + PT_R3 = 3; + PT_R4 = 4; + PT_R5 = 5; + PT_R6 = 6; + PT_R7 = 7; + PT_R8 = 8; + PT_R9 = 9; + PT_R10 = 10; + PT_R11 = 11; + PT_R12 = 12; + PT_R13 = 13; + PT_R14 = 14; + PT_R15 = 15; + PT_R16 = 16; + PT_R17 = 17; + PT_R18 = 18; + PT_R19 = 19; + PT_R20 = 20; + PT_R21 = 21; + PT_R22 = 22; + PT_R23 = 23; + PT_R24 = 24; + PT_R25 = 25; + PT_R26 = 26; + PT_R27 = 27; + PT_R28 = 28; + PT_R29 = 29; + PT_R30 = 30; + PT_R31 = 31; + PT_NIP = 32; + PT_MSR = 33; + PT_CTR = 35; + PT_LNK = 36; + PT_XER = 37; + PT_CCR = 38; + PT_SOFTE = 39; + PT_RESULT = 43; + PT_FPR0 = 48; + PT_FPR31 = PT_FPR0+31; + { Kernel and userspace will both use this PT_FPSCR value. 32-bit apps will have + visibility to the asm-ppc/ptrace.h header instead of this one. } + { each FP reg occupies 1 slot in 64-bit space } + PT_FPSCR = PT_FPR0+32; + { each Vector reg occupies 2 slots in 64-bit } + PT_VR0 = 82; + PT_VSCR = (PT_VR0+(32*2))+1; + PT_VRSAVE = PT_VR0+(33*2); + { from include/asm-ppc64/signal.h } +type stack_t = record - ss_sp: pointer; - ss_flags: longint; - ss_size: size_t; + ss_sp : pointer; + ss_flags : cInt; + ss_size : size_t; end; - { from include/asm-ppc64/sigcontext.h } - tsigcontext_struct = record - _unused: array[0..3] of qword; - signal: longint; - pad0 : longint; - handler: qword; - oldmask: qword; - pt_regs: pptregs; + { from include/asm-ppc64/sigcontext.h and + include/asm-ppc64/elf.h + } +const + ELF_NGREG = 48; { includes nip, msr, lr, etc. } + ELF_NFPREG = 33; { includes fpscr } + ELF_NVRREG = 34; { includes vscr & vrsave in split vectors } + +type + elf_gregset_t = array[0..ELF_NGREG-1] of gpr_reg; + elf_fpregset_t = array[0..ELF_NFPREG-1] of fpr_reg; + + elf_vrreg_t = array[0..ELF_NVRREG-1] of vvr_reg; + + TSigContext = record + _unused : array[0..3] of cULong; + signal : cInt; + _pad0 : cInt; + handler : cULong; + oldmask : cULong; + regs : ppt_regs; + gp_regs : elf_gregset_t; + fp_regs : elf_fpregset_t; + + { To maintain compatibility with current implementations the sigcontext is + extended by appending a pointer (v_regs) to a quadword type (elf_vrreg_t) + followed by an unstructured (vmx_reserve) field of 69 doublewords. This + allows the array of vector registers to be quadword aligned independent of + the alignment of the containing sigcontext or ucontext. It is the + responsibility of the code setting the sigcontext to set this pointer to + either NULL (if this processor does not support the VMX feature) or the + address of the first quadword within the allocated (vmx_reserve) area. + + The pointer (v_regs) of vector type (elf_vrreg_t) is type compatible with + an array of 34 quadword entries (elf_vrregset_t). The entries with + indexes 0-31 contain the corresponding vector registers. The entry with + index 32 contains the vscr as the last word (offset 12) within the + quadword. This allows the vscr to be stored as either a quadword (since + it must be copied via a vector register to/from storage) or as a word. + The entry with index 33 contains the vrsave as the first word (offset 0) + within the quadword. } + v_regs : ^elf_vrreg_t; + vmx_reserve : array[0..ELF_NVRREG+ELF_NVRREG] of cLong; end; + { the kernel uses a different sigset_t type for the ucontext structure and the + sigset_t used for masking signals. To avoid name clash, and still use a dedicated + type for the fields, use _sigset_t } + _sigset_t = cULong; + { from include/asm-ppc64/ucontext.h } pucontext = ^tucontext; tucontext = record - uc_flags : qword; + uc_flags : cuLong; uc_link : pucontext; uc_stack : stack_t; - uc_sigmask : qword;{sigset_t;} - __unused : array[0..14] of qword;{sigset_t;} - uc_mcontext : tsigcontext_struct; - end; - - - { from arch/ppc/kernel/signal.c, the type of the actual parameter passed } - { to the sigaction handler } - t_rt_sigframe = record - uc: tucontext; - _unused: array[0..1] of qword; - tramp: array[0..5] of dword; - pinfo: psiginfo; - puc: pointer; - siginfo: tsiginfo; - abigap: array[0..287] of byte; + uc_sigmask : _sigset_t; + __unused : array[0..14] of _sigset_t; { Allow for uc_sigmask growth } + uc_mcontext : TSigContext; { last for extensibility } end; PSigContext = ^TSigContext; - TSigContext= tsigcontext_struct; diff --git a/rtl/powerpc64/powerpc64.inc b/rtl/powerpc64/powerpc64.inc index 9187e5dc71..3fa159a9ad 100644 --- a/rtl/powerpc64/powerpc64.inc +++ b/rtl/powerpc64/powerpc64.inc @@ -21,14 +21,14 @@ {**************************************************************************** PowerPC specific stuff ****************************************************************************} -{ + const ppc_fpu_overflow = (1 shl (32-3)); ppc_fpu_underflow = (1 shl (32-4)); ppc_fpu_divbyzero = (1 shl (32-5)); ppc_fpu_inexact = (1 shl (32-6)); ppc_fpu_invalid_snan = (1 shl (32-7)); -} + procedure fpc_enable_ppc_fpu_exceptions; assembler; nostackframe; @@ -67,12 +67,12 @@ asm stfd f0,temp lwz r3,temp.b { clear all exception flags } -{ +{ TODO rlwinm r4,r3,0,16,31 stw r4,temp.b lfd f0,temp - a_mtfsf f0 -} + mtfsf f0 + } end; @@ -930,20 +930,16 @@ asm mr r3, r1 end; -{NOTE: On MACOS, 68000 code might call powerpc code, through the MixedMode manager, -(even in the OS in system 9). The pointer to the switching stack frame is -indicated by the first bit set to 1. This is checked below.} - {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR} function get_caller_addr(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif} nostackframe; asm cmpldi r3,0 beq .Lcaller_addr_frame_null - ld r3,0(r3) + ld r3, 0(r3) cmpldi r3,0 beq .Lcaller_addr_frame_null - ld r3,16(r3) + ld r3, 16(r3) .Lcaller_addr_frame_null: end; @@ -953,7 +949,7 @@ function get_caller_frame(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLIN asm cmpldi r3,0 beq .Lcaller_frame_null - ld r3,0(r3) + ld r3, 0(r3) .Lcaller_frame_null: end;