This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
[patch] newlib: Tweak setjmp for E500
- From: Kazu Hirata <kazu at codesourcery dot com>
- To: newlib at sources dot redhat dot com
- Date: Fri, 12 Jan 2007 15:28:06 -0800
- Subject: [patch] newlib: Tweak setjmp for E500
Hi,
Attached is a patch to tweak setjmp for E500.
On E500V1 and E500V2, GPRs (general purpose registers) are 64-bit
wide, so we need to modify setjmp and longjmp to save and restore
64-bit registers. I've put various comments in the code, so I hope
the rest is fairly obvious.
Tested by running setjmp and lonjmp on a simulator. OK to apply?
Kazu Hirata
2007-01-12 Joseph Myers <joseph@codesourcery.com>
Kazu Hirata <kazu@codesourcery.com>
newlib/
* libc/machine/powerpc/setjmp.S (setjmp, longjmp): Add support
for E500V1 and E500V2.
Index: newlib/libc/machine/powerpc/setjmp.S
===================================================================
RCS file: /cvs/src/src/newlib/libc/machine/powerpc/setjmp.S,v
retrieving revision 1.2
diff -u -d -p -r1.2 setjmp.S
--- newlib/libc/machine/powerpc/setjmp.S 19 Apr 2002 19:16:17 -0000 1.2
+++ newlib/libc/machine/powerpc/setjmp.S 12 Jan 2007 23:24:19 -0000
@@ -12,6 +12,35 @@ FUNC_START(setjmp)
addi 3,3,7 # align to 8 byte boundary
rlwinm 3,3,0,0,28
#endif
+#if __SPE__
+ /* If we are E500, then save 64-bit registers. */
+ evstdd 1,0(3) # offset 0
+ evstdd 2,8(3) # offset 8
+ evstdd 13,16(3) # offset 16
+ evstdd 14,24(3) # offset 24
+ evstdd 15,32(3) # offset 32
+ evstdd 16,40(3) # offset 40
+ evstdd 17,48(3) # offset 48
+ evstdd 18,56(3) # offset 56
+ evstdd 19,64(3) # offset 64
+ evstdd 20,72(3) # offset 72
+ evstdd 21,80(3) # offset 80
+ evstdd 22,88(3) # offset 88
+ evstdd 23,96(3) # offset 96
+ evstdd 24,104(3) # offset 104
+ evstdd 25,112(3) # offset 112
+ evstdd 26,120(3) # offset 120
+ evstdd 27,128(3) # offset 128
+ evstdd 28,136(3) # offset 136
+ evstdd 29,144(3) # offset 144
+ evstdd 30,152(3) # offset 152
+ evstdd 31,160(3) # offset 160
+
+ /* Add 164 to r3 to account for the amount of data we just
+ stored. Note that we are not adding 168 because the next
+ store instruction uses an offset of 4. */
+ addi 3,3,164
+#else
stw 1,0(3) # offset 0
stwu 2,4(3) # offset 4
stwu 13,4(3) # offset 8
@@ -33,12 +62,22 @@ FUNC_START(setjmp)
stwu 29,4(3) # offset 72
stwu 30,4(3) # offset 76
stwu 31,4(3) # offset 80
+#endif
+
+ /* From this point on until the end of this function, add 84
+ to the offset shown if __SPE__. This difference comes from
+ the fact that we save 21 64-bit registers instead of 21
+ 32-bit registers above. */
mflr 4
stwu 4,4(3) # offset 84
mfcr 4
stwu 4,4(3) # offset 88
# one word pad to get floating point aligned on 8 byte boundary
-#ifndef _SOFT_FLOAT
+
+ /* Check whether we need to save FPRs. Checking __NO_FPRS__
+ on its own would be enough for GCC 4.1 and above, but older
+ compilers only define _SOFT_FLOAT, so check both. */
+#if !defined (__NO_FPRS__) && !defined (_SOFT_FLOAT)
stfdu 14,8(3) # offset 96
stfdu 15,8(3) # offset 104
stfdu 16,8(3) # offset 112
@@ -106,6 +145,35 @@ FUNC_START(longjmp)
addi 3,3,7 # align to 8 byte boundary
rlwinm 3,3,0,0,28
#endif
+#if __SPE__
+ /* If we are E500, then restore 64-bit registers. */
+ evldd 1,0(3) # offset 0
+ evldd 2,8(3) # offset 8
+ evldd 13,16(3) # offset 16
+ evldd 14,24(3) # offset 24
+ evldd 15,32(3) # offset 32
+ evldd 16,40(3) # offset 40
+ evldd 17,48(3) # offset 48
+ evldd 18,56(3) # offset 56
+ evldd 19,64(3) # offset 64
+ evldd 20,72(3) # offset 72
+ evldd 21,80(3) # offset 80
+ evldd 22,88(3) # offset 88
+ evldd 23,96(3) # offset 96
+ evldd 24,104(3) # offset 104
+ evldd 25,112(3) # offset 112
+ evldd 26,120(3) # offset 120
+ evldd 27,128(3) # offset 128
+ evldd 28,136(3) # offset 136
+ evldd 29,144(3) # offset 144
+ evldd 30,152(3) # offset 152
+ evldd 31,160(3) # offset 160
+
+ /* Add 164 to r3 to account for the amount of data we just
+ loaded. Note that we are not adding 168 because the next
+ load instruction uses an offset of 4. */
+ addi 3,3,164
+#else
lwz 1,0(3) # offset 0
lwzu 2,4(3) # offset 4
lwzu 13,4(3) # offset 8
@@ -127,12 +195,22 @@ FUNC_START(longjmp)
lwzu 29,4(3) # offset 72
lwzu 30,4(3) # offset 76
lwzu 31,4(3) # offset 80
+#endif
+ /* From this point on until the end of this function, add 84
+ to the offset shown if __SPE__. This difference comes from
+ the fact that we restore 21 64-bit registers instead of 21
+ 32-bit registers above. */
lwzu 5,4(3) # offset 84
mtlr 5
lwzu 5,4(3) # offset 88
mtcrf 255,5
# one word pad to get floating point aligned on 8 byte boundary
-#ifndef _SOFT_FLOAT
+
+ /* Check whether we need to restore FPRs. Checking
+ __NO_FPRS__ on its own would be enough for GCC 4.1 and
+ above, but older compilers only define _SOFT_FLOAT, so
+ check both. */
+#if !defined (__NO_FPRS__) && !defined (_SOFT_FLOAT)
lfdu 14,8(3) # offset 96
lfdu 15,8(3) # offset 104
lfdu 16,8(3) # offset 112