You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
5.9 KiB
177 lines
5.9 KiB
commit f610d2935f041c5f41ddcb96924ea42ca2fb5ea5 |
|
Author: John David Anglin <danglin@gcc.gnu.org> |
|
Date: Tue Feb 22 17:28:46 2022 +0000 |
|
|
|
hppa: Revise gettext trampoline design |
|
|
|
The current getcontext return trampoline is overly complex and it |
|
unnecessarily clobbers several registers. By saving the context |
|
pointer (r26) in the context, __getcontext_ret can restore any |
|
registers not restored by setcontext. This allows getcontext to |
|
save and restore the entire register context present when getcontext |
|
is entered. We use the unused oR0 context slot for the return |
|
from __getcontext_ret. |
|
|
|
While this is not directly useful in C, it can be exploited in |
|
assembly code. Registers r20, r23, r24 and r25 are not clobbered |
|
in the call path to getcontext. This allows a small simplification |
|
of swapcontext. |
|
|
|
It also allows saving and restoring the 6-bit SAR register in the |
|
LSB of the oSAR context slot. The getcontext flag value can be |
|
stored in the MSB of the oSAR slot. |
|
|
|
(cherry picked from commit 9e7e5fda38471e00d1190479ea91d7b08ae3e304) |
|
|
|
diff --git a/sysdeps/unix/sysv/linux/hppa/getcontext.S b/sysdeps/unix/sysv/linux/hppa/getcontext.S |
|
index c8b690aab8ecc47c..4f2e2587d60effc8 100644 |
|
--- a/sysdeps/unix/sysv/linux/hppa/getcontext.S |
|
+++ b/sysdeps/unix/sysv/linux/hppa/getcontext.S |
|
@@ -22,22 +22,28 @@ |
|
#include "ucontext_i.h" |
|
|
|
|
|
- /* Trampoline function. Non-standard calling ABI. */ |
|
+ /* 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) |
|
+ /* Because setcontext does not reload r3-r6 (it's using them |
|
+ as temporaries), we must load them ourself. */ |
|
+ ldw oR3(%r26), %r3 |
|
+ ldw oR4(%r26), %r4 |
|
+ ldw oR5(%r26), %r5 |
|
+ ldw oR6(%r26), %r6 |
|
+ |
|
+ /* Also reload registers clobbered by $$dyncall. */ |
|
+ ldw oR21(%r26), %r21 |
|
+ ldw oR22(%r26), %r22 |
|
+ ldw oR31(%r26), %r31 |
|
+ |
|
+ /* oR0 contains original return pointer. */ |
|
+ ldw oR0(%r26), %rp |
|
+ bv 0(%rp) |
|
copy %r0, %ret0 |
|
.procend |
|
.size __getcontext_ret, .-__getcontext_ret |
|
@@ -65,13 +71,13 @@ ENTRY(__getcontext) |
|
stw %r17, oR17(%r26) |
|
stw %r18, oR18(%r26) |
|
stw %r19, oR19(%r26) |
|
- /* stw %r20, oR20(%r26) - used for trampoline. */ |
|
+ stw %r20, oR20(%r26) |
|
stw %r21, oR21(%r26) |
|
stw %r22, oR22(%r26) |
|
- /* stw %r23, oR23(%r26) - used for trampoline. */ |
|
- /* stw %r24, oR24(%r26) - used for trampoline. */ |
|
- /* stw %r25, oR25(%r26) - used for trampoline. */ |
|
- /* stw %r26, oR26(%r26) - used for trampoline. */ |
|
+ stw %r23, oR23(%r26) |
|
+ stw %r24, oR24(%r26) |
|
+ stw %r25, oR25(%r26) |
|
+ stw %r26, oR26(%r26) |
|
stw %r27, oR27(%r26) |
|
stw %r28, oR28(%r26) |
|
stw %r29, oR29(%r26) |
|
@@ -90,7 +96,10 @@ ENTRY(__getcontext) |
|
stw %r0, oIASQ1(%r26) |
|
stw %r0, oIAOQ0(%r26) |
|
stw %r0, oIAOQ1(%r26) |
|
- stw %r0, oSAR(%r26) /* used as flag in swapcontext(). */ |
|
+ |
|
+ /* Save SAR register. */ |
|
+ mfctl %sar, %r1 |
|
+ stw %r1, oSAR(%r26) /* MSB used as flag in swapcontext(). */ |
|
|
|
|
|
/* Store floating-point regs. */ |
|
@@ -142,13 +151,8 @@ ENTRY(__getcontext) |
|
.cfi_offset 29, 4 |
|
|
|
/* Set up the trampoline registers. |
|
- r20, r23, r24, r25, r26 and r2 are clobbered |
|
- by call to getcontext() anyway. Reuse them. */ |
|
- stw %r2, oR20(%r26) |
|
- stw %r3, oR23(%r26) |
|
- stw %r4, oR24(%r26) |
|
- stw %r5, oR25(%r26) |
|
- stw %r6, oR26(%r26) |
|
+ Use oR0 context slot to save return value. */ |
|
+ stw %r2, oR0(%r26) |
|
#ifdef PIC |
|
addil LT%__getcontext_ret, %r19 |
|
ldw RT%__getcontext_ret(%r1), %r1 |
|
diff --git a/sysdeps/unix/sysv/linux/hppa/setcontext.S b/sysdeps/unix/sysv/linux/hppa/setcontext.S |
|
index e1ae3aefcaac198d..616405b80c61d531 100644 |
|
--- a/sysdeps/unix/sysv/linux/hppa/setcontext.S |
|
+++ b/sysdeps/unix/sysv/linux/hppa/setcontext.S |
|
@@ -76,7 +76,7 @@ ENTRY(__setcontext) |
|
ldw oR18(%r3), %r18 |
|
ldw oR19(%r3), %r19 |
|
ldw oR20(%r3), %r20 |
|
- ldw oR21(%r3), %r21 |
|
+ ldw oR21(%r3), %r21 /* maybe clobbered by dyncall */ |
|
/* ldw oR22(%r3), %r22 - dyncall arg. */ |
|
ldw oR23(%r3), %r23 |
|
ldw oR24(%r3), %r24 |
|
@@ -88,6 +88,10 @@ ENTRY(__setcontext) |
|
ldw oR30(%r3), %sp |
|
/* ldw oR31(%r3), %r31 - dyncall scratch register */ |
|
|
|
+ /* Restore SAR register. */ |
|
+ ldw oSAR(%r3), %r22 |
|
+ mtsar %r22 |
|
+ |
|
/* Restore floating-point registers. */ |
|
ldo oFPREGS31(%r3), %r22 |
|
fldds 0(%r22), %fr31 |
|
diff --git a/sysdeps/unix/sysv/linux/hppa/swapcontext.c b/sysdeps/unix/sysv/linux/hppa/swapcontext.c |
|
index 562f00ff0546177d..1664f68c7b9982e8 100644 |
|
--- a/sysdeps/unix/sysv/linux/hppa/swapcontext.c |
|
+++ b/sysdeps/unix/sysv/linux/hppa/swapcontext.c |
|
@@ -26,10 +26,6 @@ extern int __setcontext (const ucontext_t *ucp); |
|
int |
|
__swapcontext (ucontext_t *oucp, const ucontext_t *ucp) |
|
{ |
|
- /* Save ucp in stack argument slot. */ |
|
- asm ("stw %r25,-40(%sp)"); |
|
- asm (".cfi_offset 25, -40"); |
|
- |
|
/* Save rp for debugger. */ |
|
asm ("stw %rp,-20(%sp)"); |
|
asm (".cfi_offset 2, -20"); |
|
@@ -60,7 +56,7 @@ __swapcontext (ucontext_t *oucp, const ucontext_t *ucp) |
|
asm ("bv,n %r0(%rp)"); |
|
|
|
/* Load sc_sar flag. */ |
|
- asm ("ldw %0(%%ret1),%%r20" : : "i" (oSAR)); |
|
+ asm ("ldb %0(%%ret1),%%r20" : : "i" (oSAR)); |
|
|
|
/* Return if oucp context has been reactivated. */ |
|
asm ("or,= %r0,%r20,%r0"); |
|
@@ -68,11 +64,11 @@ __swapcontext (ucontext_t *oucp, const ucontext_t *ucp) |
|
|
|
/* Mark sc_sar flag. */ |
|
asm ("1: ldi 1,%r20"); |
|
- asm ("stw %%r20,%0(%%ret1)" : : "i" (oSAR)); |
|
+ asm ("stb %%r20,%0(%%ret1)" : : "i" (oSAR)); |
|
|
|
/* Activate the machine context in ucp. */ |
|
asm ("bl __setcontext,%rp"); |
|
- asm ("ldw -40(%sp),%r26"); |
|
+ asm ("ldw %0(%%ret1),%%r26" : : "i" (oR25)); |
|
|
|
/* Load return pointer. */ |
|
asm ("ldw %0(%%ret1),%%rp" : : "i" (oR28));
|
|
|