diff --git a/headers/posix/arch/ppc/arch_setjmp.h b/headers/posix/arch/ppc/arch_setjmp.h new file mode 100644 index 0000000000..567e42f7ad --- /dev/null +++ b/headers/posix/arch/ppc/arch_setjmp.h @@ -0,0 +1,10 @@ +/* + * Copyright 2005, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _ARCH_SETJMP_H_ +#define _ARCH_SETJMP_H_ + +typedef int __jmp_buf[23]; + +#endif /* _ARCH_SETJMP_H_ */ diff --git a/headers/posix/arch/x86/arch_setjmp.h b/headers/posix/arch/x86/arch_setjmp.h new file mode 100644 index 0000000000..6ae972b5b7 --- /dev/null +++ b/headers/posix/arch/x86/arch_setjmp.h @@ -0,0 +1,10 @@ +/* + * Copyright 2005, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _ARCH_SETJMP_H_ +#define _ARCH_SETJMP_H_ + +typedef int __jmp_buf[6]; + +#endif /* _ARCH_SETJMP_H_ */ diff --git a/headers/posix/setjmp.h b/headers/posix/setjmp.h index d9a011ad57..65741a1fa2 100644 --- a/headers/posix/setjmp.h +++ b/headers/posix/setjmp.h @@ -5,12 +5,17 @@ #ifndef _SETJMP_H_ #define _SETJMP_H_ - #include +// include architecture specific definitions +#ifdef __INTEL__ + #include +#elif __POWERPC__ + #include +#endif -typedef struct __jmp_buf { - int regs[6]; /* saved registers, stack & program pointer */ +typedef struct __jmp_buf_tag { + __jmp_buf regs; /* saved registers, stack & program pointer */ int mask_was_saved; sigset_t saved_mask; } jmp_buf[1]; diff --git a/src/system/libroot/posix/arch/generic/longjmp_return.c b/src/system/libroot/posix/arch/generic/longjmp_return.c new file mode 100644 index 0000000000..86b97d76b4 --- /dev/null +++ b/src/system/libroot/posix/arch/generic/longjmp_return.c @@ -0,0 +1,23 @@ +/* + * Copyright 2005, Ingo Weinhold . All rights + * reserved. Distributed under the terms of the Haiku License. + */ + +#include + +/** This function is called by [sig]longjmp(). The caller has already + set up the registers and stack, so that returning from the function + will return to the place where [sig]setjmp() was invoked. It resets + the signal mask and validates the value supplied to [sig]longjmp(). + */ + +int __longjmp_return(jmp_buf buffer, int value); + +int +__longjmp_return(jmp_buf buffer, int value) +{ + if (buffer[0].mask_was_saved) + sigprocmask(SIG_SETMASK, &buffer[0].saved_mask, NULL); + + return (value == 0 ? 1 : value); +} diff --git a/src/system/libroot/posix/arch/x86/setjmp_save_sigs.c b/src/system/libroot/posix/arch/generic/setjmp_save_sigs.c similarity index 100% rename from src/system/libroot/posix/arch/x86/setjmp_save_sigs.c rename to src/system/libroot/posix/arch/generic/setjmp_save_sigs.c diff --git a/src/system/libroot/posix/arch/ppc/Jamfile b/src/system/libroot/posix/arch/ppc/Jamfile index 907b84d2f3..0bc7feba66 100644 --- a/src/system/libroot/posix/arch/ppc/Jamfile +++ b/src/system/libroot/posix/arch/ppc/Jamfile @@ -1,9 +1,17 @@ SubDir HAIKU_TOP src system libroot posix arch ppc ; -# TODO: Implement! +local genericSources = + setjmp_save_sigs.c + longjmp_return.c +; + MergeObject posix_arch_$(TARGET_ARCH).o : setjmp.S -# setjmp_save_sigs.c -# sigsetjmp.S -# siglongjmp.S + sigsetjmp.S + siglongjmp.S + + $(genericSources) ; + +SEARCH on [ FGristFiles $(genericSources) ] + = [ FDirName $(SUBDIR) $(DOTDOT) generic ] ; diff --git a/src/system/libroot/posix/arch/ppc/setjmp.S b/src/system/libroot/posix/arch/ppc/setjmp.S index e69de29bb2..ac0d8420b6 100644 --- a/src/system/libroot/posix/arch/ppc/setjmp.S +++ b/src/system/libroot/posix/arch/ppc/setjmp.S @@ -0,0 +1,15 @@ +/* + * Copyright 2005, Ingo Weinhold . All rights + * reserved. Distributed under the terms of the Haiku License. + */ + +#include "setjmp_internal.h" + +/* int setjmp(jmp_buf buffer) */ +FUNCTION(setjmp): + // call __sigsetjmp with saveMask = 0 + addi %r4, 0, 0 + b __sigsetjmp + +#pragma weak _setjmp=setjmp + diff --git a/src/system/libroot/posix/arch/ppc/setjmp_internal.h b/src/system/libroot/posix/arch/ppc/setjmp_internal.h new file mode 100644 index 0000000000..d465609cea --- /dev/null +++ b/src/system/libroot/posix/arch/ppc/setjmp_internal.h @@ -0,0 +1,47 @@ +/* + * Copyright 2005, Ingo Weinhold . All rights + * reserved. Distributed under the terms of the Haiku License. + */ +#ifndef SETJMP_INTERNAL_H +#define SETJMP_INTERNAL_H + +/* PPC function call ABI register use: + r0 - volatile + r1 - stack frame + r2 - reserved + r3-r4 - param passing, return values + r5-r10 - param passing + r11-r12 - volatile + r13 - small data pointer + r14-r30 - local vars + r31 - local vars/environment +*/ + +/* These are the fields of the __jmp_regs structure */ +#define JMP_REGS_R1 0 +#define JMP_REGS_R2 4 +#define JMP_REGS_R13 8 +#define JMP_REGS_R14 12 +#define JMP_REGS_R15 16 +#define JMP_REGS_R16 20 +#define JMP_REGS_R17 24 +#define JMP_REGS_R18 28 +#define JMP_REGS_R19 32 +#define JMP_REGS_R20 36 +#define JMP_REGS_R21 40 +#define JMP_REGS_R22 44 +#define JMP_REGS_R23 48 +#define JMP_REGS_R24 52 +#define JMP_REGS_R25 56 +#define JMP_REGS_R26 60 +#define JMP_REGS_R27 64 +#define JMP_REGS_R28 68 +#define JMP_REGS_R29 72 +#define JMP_REGS_R30 76 +#define JMP_REGS_R31 80 +#define JMP_REGS_LR 84 +#define JMP_REGS_CR 88 + +#define FUNCTION(x) .global x; .type x,@function; x + +#endif /* SETJMP_INTERNAL_H */ diff --git a/src/system/libroot/posix/arch/ppc/siglongjmp.S b/src/system/libroot/posix/arch/ppc/siglongjmp.S new file mode 100644 index 0000000000..f5d5a5bd32 --- /dev/null +++ b/src/system/libroot/posix/arch/ppc/siglongjmp.S @@ -0,0 +1,45 @@ +/* + * Copyright 2005, Ingo Weinhold . All rights + * reserved. Distributed under the terms of the Haiku License. + */ + +#include "setjmp_internal.h" + +/* int __siglongjmp(jmp_buf buffer, int value) */ +FUNCTION(siglongjmp): +FUNCTION(longjmp): +FUNCTION(_longjmp): + // r3: buffer, r4: saveMask + + // restore non-volatile general purpose registers + lwz %r1, JMP_REGS_R1(3) + lwz %r2, JMP_REGS_R2(3) + lwz %r13, JMP_REGS_R13(3) + lwz %r14, JMP_REGS_R14(3) + lwz %r15, JMP_REGS_R15(3) + lwz %r16, JMP_REGS_R16(3) + lwz %r17, JMP_REGS_R17(3) + lwz %r18, JMP_REGS_R18(3) + lwz %r19, JMP_REGS_R19(3) + lwz %r20, JMP_REGS_R20(3) + lwz %r21, JMP_REGS_R21(3) + lwz %r22, JMP_REGS_R22(3) + lwz %r23, JMP_REGS_R23(3) + lwz %r24, JMP_REGS_R24(3) + lwz %r25, JMP_REGS_R25(3) + lwz %r26, JMP_REGS_R26(3) + lwz %r27, JMP_REGS_R27(3) + lwz %r28, JMP_REGS_R28(3) + lwz %r29, JMP_REGS_R29(3) + lwz %r30, JMP_REGS_R30(3) + lwz %r31, JMP_REGS_R31(3) + + // restore special registers (link, condition) + lwz %r0, JMP_REGS_LR(3) + mtlr %r0 + lwz %r0, JMP_REGS_CR(3) + mtcr %r0 + + b __longjmp_return + +#pragma weak longjmp=siglongjmp diff --git a/src/system/libroot/posix/arch/ppc/sigsetjmp.S b/src/system/libroot/posix/arch/ppc/sigsetjmp.S new file mode 100644 index 0000000000..91065ca116 --- /dev/null +++ b/src/system/libroot/posix/arch/ppc/sigsetjmp.S @@ -0,0 +1,42 @@ +/* + * Copyright 2005, Ingo Weinhold . All rights + * reserved. Distributed under the terms of the Haiku License. + */ + +#include "setjmp_internal.h" + +/* int sigsetjmp(jmp_buf buffer, int saveMask) */ +FUNCTION(__sigsetjmp): +FUNCTION(sigsetjmp): + // r3: buffer, r4: saveMask + + // store non-volatile general purpose registers + stw %r1, JMP_REGS_R1(3) + stw %r2, JMP_REGS_R2(3) + stw %r13, JMP_REGS_R13(3) + stw %r14, JMP_REGS_R14(3) + stw %r15, JMP_REGS_R15(3) + stw %r16, JMP_REGS_R16(3) + stw %r17, JMP_REGS_R17(3) + stw %r18, JMP_REGS_R18(3) + stw %r19, JMP_REGS_R19(3) + stw %r20, JMP_REGS_R20(3) + stw %r21, JMP_REGS_R21(3) + stw %r22, JMP_REGS_R22(3) + stw %r23, JMP_REGS_R23(3) + stw %r24, JMP_REGS_R24(3) + stw %r25, JMP_REGS_R25(3) + stw %r26, JMP_REGS_R26(3) + stw %r27, JMP_REGS_R27(3) + stw %r28, JMP_REGS_R28(3) + stw %r29, JMP_REGS_R29(3) + stw %r30, JMP_REGS_R30(3) + stw %r31, JMP_REGS_R31(3) + + // store special registers (link, condition) + mflr %r0 + stw %r0, JMP_REGS_LR(3) + mfcr %r0 + stw %r0, JMP_REGS_CR(3) + + b __setjmp_save_sigs diff --git a/src/system/libroot/posix/arch/x86/Jamfile b/src/system/libroot/posix/arch/x86/Jamfile index b15aa17b83..7d647140f2 100644 --- a/src/system/libroot/posix/arch/x86/Jamfile +++ b/src/system/libroot/posix/arch/x86/Jamfile @@ -1,8 +1,18 @@ SubDir HAIKU_TOP src system libroot posix arch x86 ; +# TODO: siglongjmp.S should use __longjmp_return to restore the signal mask. +local genericSources = + setjmp_save_sigs.c +# longjmp_return.c +; + MergeObject posix_arch_$(TARGET_ARCH).o : setjmp.S - setjmp_save_sigs.c sigsetjmp.S siglongjmp.S + + $(genericSources) ; + +SEARCH on [ FGristFiles $(genericSources) ] + = [ FDirName $(SUBDIR) $(DOTDOT) generic ] ;