ce426f
# commit be1e5d311342e08ae1f8013342df27b7ded2c156
ce426f
# Author: Anton Blanchard <anton@au1.ibm.com>
ce426f
# Date:   Sat Aug 17 18:34:40 2013 +0930
ce426f
# 
ce426f
#     PowerPC LE setjmp/longjmp
ce426f
#     http://sourceware.org/ml/libc-alpha/2013-08/msg00089.html
ce426f
#     
ce426f
#     Little-endian fixes for setjmp/longjmp.  When writing these I noticed
ce426f
#     the setjmp code corrupts the non volatile VMX registers when using an
ce426f
#     unaligned buffer.  Anton fixed this, and also simplified it quite a
ce426f
#     bit.
ce426f
#     
ce426f
#     The current code uses boilerplate for the case where we want to store
ce426f
#     16 bytes to an unaligned address.  For that we have to do a
ce426f
#     read/modify/write of two aligned 16 byte quantities.  In our case we
ce426f
#     are storing a bunch of back to back data (consective VMX registers),
ce426f
#     and only the start and end of the region need the read/modify/write.
ce426f
#     
ce426f
#         [BZ #15723]
ce426f
#         * sysdeps/powerpc/jmpbuf-offsets.h: Comment fix.
ce426f
#         * sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S: Correct
ce426f
#         _dl_hwcap access for little-endian.
ce426f
#         * sysdeps/powerpc/powerpc32/fpu/setjmp-common.S: Likewise.  Don't
ce426f
#         destroy vmx regs when saving unaligned.
ce426f
#         * sysdeps/powerpc/powerpc64/__longjmp-common.S: Correct CR load.
ce426f
#         * sysdeps/powerpc/powerpc64/setjmp-common.S: Likewise CR save.  Don't
ce426f
#         destroy vmx regs when saving unaligned.
ce426f
# 
ce426f
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/jmpbuf-offsets.h glibc-2.17-c758a686/sysdeps/powerpc/jmpbuf-offsets.h
ce426f
--- glibc-2.17-c758a686/sysdeps/powerpc/jmpbuf-offsets.h	2014-05-27 22:55:23.000000000 -0500
ce426f
+++ glibc-2.17-c758a686/sysdeps/powerpc/jmpbuf-offsets.h	2014-05-27 22:55:27.000000000 -0500
ce426f
@@ -21,12 +21,10 @@
ce426f
 #define JB_LR     2  /* The address we will return to */
ce426f
 #if __WORDSIZE == 64
ce426f
 # define JB_GPRS   3  /* GPRs 14 through 31 are saved, 18*2 words total.  */
ce426f
-# define JB_CR     21 /* Condition code registers with the VRSAVE at */
ce426f
-                       /* offset 172 (low half of the double word.  */
ce426f
+# define JB_CR     21 /* Shared dword with VRSAVE.  CR word at offset 172.  */
ce426f
 # define JB_FPRS   22 /* FPRs 14 through 31 are saved, 18*2 words total.  */
ce426f
 # define JB_SIZE   (64 * 8) /* As per PPC64-VMX ABI.  */
ce426f
-# define JB_VRSAVE 21 /* VRSAVE shares a double word with the CR at offset */
ce426f
-                       /* 168 (high half of the double word).  */
ce426f
+# define JB_VRSAVE 21 /* Shared dword with CR.  VRSAVE word at offset 168.  */
ce426f
 # define JB_VRS    40 /* VRs 20 through 31 are saved, 12*4 words total.  */
ce426f
 #else
ce426f
 # define JB_GPRS   3  /* GPRs 14 through 31 are saved, 18 in total.  */
ce426f
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S
ce426f
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S	2014-05-27 22:55:23.000000000 -0500
ce426f
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S	2014-05-27 22:55:27.000000000 -0500
ce426f
@@ -46,16 +46,16 @@
ce426f
 #   endif
ce426f
 	mtlr    r6
ce426f
 	cfi_same_value (lr)
ce426f
-	lwz     r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r5)
ce426f
+	lwz     r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r5)
ce426f
 #  else
ce426f
 	lwz     r5,_dl_hwcap@got(r5)
ce426f
 	mtlr    r6
ce426f
 	cfi_same_value (lr)
ce426f
-	lwz     r5,4(r5)
ce426f
+	lwz     r5,LOWORD(r5)
ce426f
 #  endif
ce426f
 # else
ce426f
-	lis	r5,(_dl_hwcap+4)@ha
ce426f
-	lwz     r5,(_dl_hwcap+4)@l(r5)
ce426f
+	lis	r5,(_dl_hwcap+LOWORD)@ha
ce426f
+	lwz     r5,(_dl_hwcap+LOWORD)@l(r5)
ce426f
 # endif
ce426f
 	andis.	r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
ce426f
 	beq	L(no_vmx)
ce426f
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S
ce426f
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S	2014-05-27 22:55:23.000000000 -0500
ce426f
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S	2014-05-27 22:55:27.000000000 -0500
ce426f
@@ -97,14 +97,14 @@
ce426f
 #   else
ce426f
 	lwz     r5,_rtld_global_ro@got(r5)
ce426f
 #   endif
ce426f
-	lwz     r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r5)
ce426f
+	lwz     r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r5)
ce426f
 #  else
ce426f
 	lwz     r5,_dl_hwcap@got(r5)
ce426f
-	lwz     r5,4(r5)
ce426f
+	lwz     r5,LOWORD(r5)
ce426f
 #  endif
ce426f
 # else
ce426f
-	lis	r6,(_dl_hwcap+4)@ha
ce426f
-	lwz     r5,(_dl_hwcap+4)@l(r6)
ce426f
+	lis	r6,(_dl_hwcap+LOWORD)@ha
ce426f
+	lwz     r5,(_dl_hwcap+LOWORD)@l(r6)
ce426f
 # endif
ce426f
 	andis.	r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
ce426f
 	beq	L(no_vmx)
ce426f
@@ -114,44 +114,43 @@
ce426f
 	stw	r0,((JB_VRSAVE)*4)(3)
ce426f
 	addi	r6,r5,16
ce426f
 	beq+	L(aligned_save_vmx)
ce426f
+
ce426f
 	lvsr	v0,0,r5
ce426f
-	vspltisb v1,-1         /* set v1 to all 1's */
ce426f
-	vspltisb v2,0          /* set v2 to all 0's */
ce426f
-	vperm   v3,v2,v1,v0   /* v3 contains shift mask with num all 1 bytes on left = misalignment  */
ce426f
-
ce426f
-
ce426f
-	/* Special case for v20 we need to preserve what is in save area below v20 before obliterating it */
ce426f
-	lvx     v5,0,r5
ce426f
-	vperm   v20,v20,v20,v0
ce426f
-	vsel    v5,v5,v20,v3
ce426f
-	vsel    v20,v20,v2,v3
ce426f
-	stvx    v5,0,r5
ce426f
-
ce426f
-#define save_2vmx_partial(savevr,prev_savevr,hivr,shiftvr,maskvr,savegpr,addgpr) \
ce426f
-	addi    addgpr,addgpr,32; \
ce426f
-	vperm   savevr,savevr,savevr,shiftvr; \
ce426f
-	vsel    hivr,prev_savevr,savevr,maskvr; \
ce426f
-	stvx    hivr,0,savegpr;
ce426f
-
ce426f
-	save_2vmx_partial(v21,v20,v5,v0,v3,r6,r5)
ce426f
-	save_2vmx_partial(v22,v21,v5,v0,v3,r5,r6)
ce426f
-	save_2vmx_partial(v23,v22,v5,v0,v3,r6,r5)
ce426f
-	save_2vmx_partial(v24,v23,v5,v0,v3,r5,r6)
ce426f
-	save_2vmx_partial(v25,v24,v5,v0,v3,r6,r5)
ce426f
-	save_2vmx_partial(v26,v25,v5,v0,v3,r5,r6)
ce426f
-	save_2vmx_partial(v27,v26,v5,v0,v3,r6,r5)
ce426f
-	save_2vmx_partial(v28,v27,v5,v0,v3,r5,r6)
ce426f
-	save_2vmx_partial(v29,v28,v5,v0,v3,r6,r5)
ce426f
-	save_2vmx_partial(v30,v29,v5,v0,v3,r5,r6)
ce426f
-
ce426f
-	/* Special case for r31 we need to preserve what is in save area above v31 before obliterating it */
ce426f
-	addi    r5,r5,32
ce426f
-	vperm   v31,v31,v31,v0
ce426f
-	lvx     v4,0,r5
ce426f
-	vsel    v5,v30,v31,v3
ce426f
-	stvx    v5,0,r6
ce426f
-	vsel    v4,v31,v4,v3
ce426f
-	stvx    v4,0,r5
ce426f
+	lvsl	v1,0,r5
ce426f
+	addi	r6,r5,-16
ce426f
+
ce426f
+# define save_misaligned_vmx(savevr,prevvr,shiftvr,tmpvr,savegpr,addgpr) \
ce426f
+	addi	addgpr,addgpr,32;					 \
ce426f
+	vperm	tmpvr,prevvr,savevr,shiftvr;				 \
ce426f
+	stvx	tmpvr,0,savegpr
ce426f
+
ce426f
+	/*
ce426f
+	 * We have to be careful not to corrupt the data below v20 and
ce426f
+	 * above v31. To keep things simple we just rotate both ends in
ce426f
+	 * the opposite direction to our main permute so we can use
ce426f
+	 * the common macro.
ce426f
+	 */
ce426f
+
ce426f
+	/* load and rotate data below v20 */
ce426f
+	lvx	v2,0,r5
ce426f
+	vperm	v2,v2,v2,v1
ce426f
+	save_misaligned_vmx(v20,v2,v0,v3,r5,r6)
ce426f
+	save_misaligned_vmx(v21,v20,v0,v3,r6,r5)
ce426f
+	save_misaligned_vmx(v22,v21,v0,v3,r5,r6)
ce426f
+	save_misaligned_vmx(v23,v22,v0,v3,r6,r5)
ce426f
+	save_misaligned_vmx(v24,v23,v0,v3,r5,r6)
ce426f
+	save_misaligned_vmx(v25,v24,v0,v3,r6,r5)
ce426f
+	save_misaligned_vmx(v26,v25,v0,v3,r5,r6)
ce426f
+	save_misaligned_vmx(v27,v26,v0,v3,r6,r5)
ce426f
+	save_misaligned_vmx(v28,v27,v0,v3,r5,r6)
ce426f
+	save_misaligned_vmx(v29,v28,v0,v3,r6,r5)
ce426f
+	save_misaligned_vmx(v30,v29,v0,v3,r5,r6)
ce426f
+	save_misaligned_vmx(v31,v30,v0,v3,r6,r5)
ce426f
+	/* load and rotate data above v31 */
ce426f
+	lvx	v2,0,r6
ce426f
+	vperm	v2,v2,v2,v1
ce426f
+	save_misaligned_vmx(v2,v31,v0,v3,r5,r6)
ce426f
+
ce426f
 	b	L(no_vmx)
ce426f
 
ce426f
 L(aligned_save_vmx):
ce426f
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/__longjmp-common.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/__longjmp-common.S
ce426f
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/__longjmp-common.S	2014-05-27 22:55:23.000000000 -0500
ce426f
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/__longjmp-common.S	2014-05-27 22:55:27.000000000 -0500
ce426f
@@ -60,7 +60,7 @@
ce426f
 	beq	L(no_vmx)
ce426f
 	la	r5,((JB_VRS)*8)(3)
ce426f
 	andi.	r6,r5,0xf
ce426f
-	lwz	r0,((JB_VRSAVE)*8)(3)
ce426f
+	lwz	r0,((JB_VRSAVE)*8)(3)	/* 32-bit VRSAVE.  */
ce426f
 	mtspr	VRSAVE,r0
ce426f
 	beq+	L(aligned_restore_vmx)
ce426f
 	addi    r6,r5,16
ce426f
@@ -156,7 +156,7 @@
ce426f
 	lfd fp21,((JB_FPRS+7)*8)(r3)
ce426f
 	ld r22,((JB_GPRS+8)*8)(r3)
ce426f
 	lfd fp22,((JB_FPRS+8)*8)(r3)
ce426f
-	ld r0,(JB_CR*8)(r3)
ce426f
+	lwz r0,((JB_CR*8)+4)(r3)	/* 32-bit CR.  */
ce426f
 	ld r23,((JB_GPRS+9)*8)(r3)
ce426f
 	lfd fp23,((JB_FPRS+9)*8)(r3)
ce426f
 	ld r24,((JB_GPRS+10)*8)(r3)
ce426f
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S
ce426f
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S	2014-05-27 22:55:23.000000000 -0500
ce426f
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S	2014-05-27 22:55:27.000000000 -0500
ce426f
@@ -98,7 +98,7 @@
ce426f
 	mfcr r0
ce426f
 	std  r16,((JB_GPRS+2)*8)(3)
ce426f
 	stfd fp16,((JB_FPRS+2)*8)(3)
ce426f
-	std  r0,(JB_CR*8)(3)
ce426f
+	stw  r0,((JB_CR*8)+4)(3)	/* 32-bit CR.  */
ce426f
 	std  r17,((JB_GPRS+3)*8)(3)
ce426f
 	stfd fp17,((JB_FPRS+3)*8)(3)
ce426f
 	std  r18,((JB_GPRS+4)*8)(3)
ce426f
@@ -142,50 +142,46 @@
ce426f
 	la	r5,((JB_VRS)*8)(3)
ce426f
 	andi.	r6,r5,0xf
ce426f
 	mfspr	r0,VRSAVE
ce426f
-	stw	r0,((JB_VRSAVE)*8)(3)
ce426f
+	stw	r0,((JB_VRSAVE)*8)(3)	/* 32-bit VRSAVE.  */
ce426f
 	addi	r6,r5,16
ce426f
 	beq+	L(aligned_save_vmx)
ce426f
+
ce426f
 	lvsr	v0,0,r5
ce426f
-	vspltisb v1,-1         /* set v1 to all 1's */
ce426f
-	vspltisb v2,0          /* set v2 to all 0's */
ce426f
-	vperm   v3,v2,v1,v0   /* v3 contains shift mask with num all 1 bytes
ce426f
-				 on left = misalignment  */
ce426f
-
ce426f
-
ce426f
-	/* Special case for v20 we need to preserve what is in save area
ce426f
-	   below v20 before obliterating it */
ce426f
-	lvx     v5,0,r5
ce426f
-	vperm   v20,v20,v20,v0
ce426f
-	vsel    v5,v5,v20,v3
ce426f
-	vsel    v20,v20,v2,v3
ce426f
-	stvx    v5,0,r5
ce426f
-
ce426f
-# define save_2vmx_partial(savevr,prev_savevr,hivr,shiftvr,maskvr,savegpr,addgpr) \
ce426f
-	addi    addgpr,addgpr,32; \
ce426f
-	vperm   savevr,savevr,savevr,shiftvr; \
ce426f
-	vsel    hivr,prev_savevr,savevr,maskvr; \
ce426f
-	stvx    hivr,0,savegpr;
ce426f
-
ce426f
-	save_2vmx_partial(v21,v20,v5,v0,v3,r6,r5)
ce426f
-	save_2vmx_partial(v22,v21,v5,v0,v3,r5,r6)
ce426f
-	save_2vmx_partial(v23,v22,v5,v0,v3,r6,r5)
ce426f
-	save_2vmx_partial(v24,v23,v5,v0,v3,r5,r6)
ce426f
-	save_2vmx_partial(v25,v24,v5,v0,v3,r6,r5)
ce426f
-	save_2vmx_partial(v26,v25,v5,v0,v3,r5,r6)
ce426f
-	save_2vmx_partial(v27,v26,v5,v0,v3,r6,r5)
ce426f
-	save_2vmx_partial(v28,v27,v5,v0,v3,r5,r6)
ce426f
-	save_2vmx_partial(v29,v28,v5,v0,v3,r6,r5)
ce426f
-	save_2vmx_partial(v30,v29,v5,v0,v3,r5,r6)
ce426f
-
ce426f
-	/* Special case for r31 we need to preserve what is in save area
ce426f
-	   above v31 before obliterating it */
ce426f
-	addi    r5,r5,32
ce426f
-	vperm   v31,v31,v31,v0
ce426f
-	lvx     v4,0,r5
ce426f
-	vsel    v5,v30,v31,v3
ce426f
-	stvx    v5,0,r6
ce426f
-	vsel    v4,v31,v4,v3
ce426f
-	stvx    v4,0,r5
ce426f
+	lvsl	v1,0,r5
ce426f
+	addi	r6,r5,-16
ce426f
+
ce426f
+# define save_misaligned_vmx(savevr,prevvr,shiftvr,tmpvr,savegpr,addgpr) \
ce426f
+	addi	addgpr,addgpr,32;					 \
ce426f
+	vperm	tmpvr,prevvr,savevr,shiftvr;				 \
ce426f
+	stvx	tmpvr,0,savegpr
ce426f
+
ce426f
+	/*
ce426f
+	 * We have to be careful not to corrupt the data below v20 and
ce426f
+	 * above v31. To keep things simple we just rotate both ends in
ce426f
+	 * the opposite direction to our main permute so we can use
ce426f
+	 * the common macro.
ce426f
+	 */
ce426f
+
ce426f
+	/* load and rotate data below v20 */
ce426f
+	lvx	v2,0,r5
ce426f
+	vperm	v2,v2,v2,v1
ce426f
+	save_misaligned_vmx(v20,v2,v0,v3,r5,r6)
ce426f
+	save_misaligned_vmx(v21,v20,v0,v3,r6,r5)
ce426f
+	save_misaligned_vmx(v22,v21,v0,v3,r5,r6)
ce426f
+	save_misaligned_vmx(v23,v22,v0,v3,r6,r5)
ce426f
+	save_misaligned_vmx(v24,v23,v0,v3,r5,r6)
ce426f
+	save_misaligned_vmx(v25,v24,v0,v3,r6,r5)
ce426f
+	save_misaligned_vmx(v26,v25,v0,v3,r5,r6)
ce426f
+	save_misaligned_vmx(v27,v26,v0,v3,r6,r5)
ce426f
+	save_misaligned_vmx(v28,v27,v0,v3,r5,r6)
ce426f
+	save_misaligned_vmx(v29,v28,v0,v3,r6,r5)
ce426f
+	save_misaligned_vmx(v30,v29,v0,v3,r5,r6)
ce426f
+	save_misaligned_vmx(v31,v30,v0,v3,r6,r5)
ce426f
+	/* load and rotate data above v31 */
ce426f
+	lvx	v2,0,r6
ce426f
+	vperm	v2,v2,v2,v1
ce426f
+	save_misaligned_vmx(v2,v31,v0,v3,r5,r6)
ce426f
+
ce426f
 	b	L(no_vmx)
ce426f
 
ce426f
 L(aligned_save_vmx):