diff options
author | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2010-06-24 15:01:34 +0000 |
---|---|---|
committer | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2010-06-24 15:01:34 +0000 |
commit | 6d5d61ad6033044a890eeecdcc60427f5e52d03d (patch) | |
tree | a44f28cb8ea13826ebf53e5db0b29ea56282128b /ports/sysdeps/unix/sysv/linux/hppa | |
parent | 88e95b91302a82653053490ef1064fa903e75c27 (diff) | |
download | eglibc2-6d5d61ad6033044a890eeecdcc60427f5e52d03d.tar.gz |
Merge changes between r10687 and r10807 from /fsf/trunk.
git-svn-id: svn://svn.eglibc.org/trunk@10808 7b3dc134-2b1b-0410-93df-9e9f96275f8d
Diffstat (limited to 'ports/sysdeps/unix/sysv/linux/hppa')
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/hppa/getcontext.S | 21 | ||||
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/hppa/makecontext.c | 53 | ||||
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/hppa/setcontext.S | 16 |
3 files changed, 62 insertions, 28 deletions
diff --git a/ports/sysdeps/unix/sysv/linux/hppa/getcontext.S b/ports/sysdeps/unix/sysv/linux/hppa/getcontext.S index f88fa03d9..af810b3df 100644 --- a/ports/sysdeps/unix/sysv/linux/hppa/getcontext.S +++ b/ports/sysdeps/unix/sysv/linux/hppa/getcontext.S @@ -23,17 +23,21 @@ #include "ucontext_i.h" - /* Trampoline function. */ + /* Trampoline function. Non-standard calling ABI. */ /* Can not use ENTRY(__getcontext_ret) here. */ .type __getcontext_ret, @function .hidden __getcontext_ret __getcontext_ret: .proc .callinfo FRAME=0,NO_CALLS + /* r26-r23 contain original r3-r6, but because setcontext + does not reload r3-r6 (it's using them as temporaries) + we must save them elsewhere and swap them back in. */ copy %r23, %r3 copy %r24, %r4 copy %r25, %r5 copy %r26, %r6 + /* r20 contains original return pointer. */ bv 0(%r20) copy %r0, %ret0 .procend @@ -72,13 +76,12 @@ ENTRY(__getcontext) stw %r27, oR27(%r26) stw %r28, oR28(%r26) stw %r29, oR29(%r26) - ldo -64(%sp), %r1 /* Calculate %sp in %r1. */ - stw %r1, oR30(%r26) /* Save new %sp. */ + stw %sp, oR30(%r26) stw %r31, oR31(%r26) stw %r0, oUC_FLAGS(%r26) /* stw %r0, oUC_LINK(%r26) - Do not overwrite. */ - stw %r1, oSS_SP(%r26) + stw %sp, oSS_SP(%r26) stw %r0, oSS_FLAGS(%r26) stw %r0, oSS_SIZE(%r26) @@ -127,9 +130,9 @@ ENTRY(__getcontext) fstds %fr31, 0(%r1) /* Prologue */ - stwm %r4, 64(%r30) + stwm %r4, 64(%sp) #ifdef PIC - stw %r19, -32(%r30) + stw %r19, -32(%sp) #endif /* Set up the trampoline registers. @@ -152,12 +155,12 @@ ENTRY(__getcontext) ldi SIG_BLOCK, %r26 /* Epilogue */ - ldw -84(%r30), %r2 + ldw -84(%sp), %r2 #ifdef PIC - ldw -96(%r30), %r19 + ldw -96(%sp), %r19 #endif bv %r0(%r2) - ldwm -64(%r30), %r4 + ldwm -64(%sp), %r4 END(__getcontext) weak_alias (__getcontext, getcontext) diff --git a/ports/sysdeps/unix/sysv/linux/hppa/makecontext.c b/ports/sysdeps/unix/sysv/linux/hppa/makecontext.c index cb036d041..d3e3fb8c7 100644 --- a/ports/sysdeps/unix/sysv/linux/hppa/makecontext.c +++ b/ports/sysdeps/unix/sysv/linux/hppa/makecontext.c @@ -26,26 +26,57 @@ #include <ucontext.h> /* POSIX only supports integer arguments. */ + +/* Stack must be 64-byte aligned at all times. */ #define STACK_ALIGN 64 -#define FRAME_SIZE 8 +/* Size of frame marker in unsigned long words. */ +#define FRAME_SIZE_UL 8 +/* Size of frame marker in bytes. */ +#define FRAME_SIZE_BYTES (8 * sizeof(unsigned long)) +/* Size of X arguments in bytes. */ +#define ARGS(x) (x * sizeof(unsigned long)) void __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) { - unsigned long *sp; + unsigned long *sp, *osp; va_list ap; int i; - /* Get stack pointer (64-byte aligned). */ - sp = (unsigned long *)((((unsigned long) ucp->uc_stack.ss_sp) - + FRAME_SIZE + argc + STACK_ALIGN) - & ~(STACK_ALIGN - 1)); + /* Create a 64-byte aligned frame to store args. Use ss_sp if + it is available, otherwise be robust and use the currently + saved stack pointer. */ + if (ucp->uc_stack.ss_sp && ucp->uc_stack.ss_size) + osp = (unsigned long *)ucp->uc_stack.ss_sp; + else + osp = (unsigned long *)ucp->uc_mcontext.sc_gr[30]; + + sp = (unsigned long *)((((unsigned long) osp) + + FRAME_SIZE_BYTES + ARGS(argc) + STACK_ALIGN) + & ~(STACK_ALIGN - 1)); + + /* Use new frame. */ + ucp->uc_mcontext.sc_gr[30] = ((unsigned long) sp); + + /* Finish frame setup. */ + if (ucp->uc_link) + { + /* Returning to the next context and next frame. */ + sp[-4/sizeof(unsigned long)] = ucp->uc_link->uc_mcontext.sc_gr[30]; + sp[-20/sizeof(unsigned long)] = ucp->uc_link->uc_mcontext.sc_gr[2]; + } + else + { + /* This is the main context. No frame marker, and no return address. */ + sp[-4/sizeof(unsigned long)] = 0x0; + sp[-20/sizeof(unsigned long)] = 0x0; + } /* Store address to jump to. */ ucp->uc_mcontext.sc_gr[2] = (unsigned long) func; + /* Process arguments. */ va_start (ap, argc); - /* Handle arguments. */ for (i = 0; i < argc; ++i) { if (i < 4) @@ -62,13 +93,9 @@ __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) } /* All other arguments go on the stack. */ - sp[-1 * (FRAME_SIZE + 1 + i)] = va_arg (ap, int); + sp[-1 * (FRAME_SIZE_UL + 1 + i)] = va_arg (ap, int); } va_end (ap); - - /* Adjust the stack pointer to last used argument. */ - ucp->uc_mcontext.sc_gr[30] = (unsigned long) sp; } - - weak_alias(__makecontext, makecontext) + diff --git a/ports/sysdeps/unix/sysv/linux/hppa/setcontext.S b/ports/sysdeps/unix/sysv/linux/hppa/setcontext.S index 43ccf24d2..3353d4e6e 100644 --- a/ports/sysdeps/unix/sysv/linux/hppa/setcontext.S +++ b/ports/sysdeps/unix/sysv/linux/hppa/setcontext.S @@ -25,9 +25,9 @@ ENTRY(__setcontext) /* Prologue */ - stwm %r3, 64(%r30) + stwm %r3, 64(%sp) #ifdef PIC - stw %r19, -32(%r30) + stw %r19, -32(%sp) #endif /* Save ucp. */ @@ -78,7 +78,7 @@ ENTRY(__setcontext) ldw oR27(%r3), %r27 ldw oR28(%r3), %r28 ldw oR29(%r3), %r29 - ldw oR30(%r3), %r30 + ldw oR30(%r3), %sp /* ldw oR31(%r3), %r31 - dyncall scratch register */ /* Restore floating-point registers. */ @@ -116,9 +116,13 @@ ENTRY(__setcontext) fldds,mb -8(%r22), %fr1 fldds,mb -8(%r22), %fr0 - /* Calculate new stack pointer. */ - ldw oSS_SP(%r3), %sp - ldo 64(%sp), %sp + /* Do not load oSS_SP into %sp. The value of oSS_SP indicates + the start of the user allocated stack, but not the sp that + should be used by the new context. In fact makecontext + will create a frame, and adjust sp as required. We do not + support calling getcontext and modifying ss_sp without + a call to makecontext to synchronize ss_sp into the machine + context. */ /* Call external function. */ copy %r2, %r22 |