This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]