From 6415dd7b2f6f8ecea16891e98f990731078dd57c Mon Sep 17 00:00:00 2001
From: Andy Polyakov <appro@openssl.org>
Date: Fri, 10 Sep 2010 15:00:51 +0000
Subject: [PATCH] crypto/ppc[cpuid|cap]: call CPU detection once and detect
 AltiVec.

---
 crypto/ppccap.c    | 49 +++++++++++++++++++++++++++++++---------------
 crypto/ppccpuid.pl |  6 ++++++
 2 files changed, 39 insertions(+), 16 deletions(-)

diff --git a/crypto/ppccap.c b/crypto/ppccap.c
index 4d88a3d65b..4da696be4d 100644
--- a/crypto/ppccap.c
+++ b/crypto/ppccap.c
@@ -6,6 +6,7 @@
 #include <openssl/bn.h>
 
 #define PPC_FPU64	(1<<0)
+#define PPC_ALTIVEC	(1<<1)
 
 static int OPENSSL_ppccap_P = 0;
 
@@ -39,7 +40,7 @@ int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_U
 #endif
 		}
 	else if ((OPENSSL_ppccap_P&PPC_FPU64))
-		/* this is a "must" on Power 6, but run-time detection
+		/* this is a "must" on POWER6, but run-time detection
 		 * is not implemented yet... */
 		return bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
 
@@ -55,7 +56,13 @@ void OPENSSL_ppc64_probe(void);
 void OPENSSL_cpuid_setup(void)
 	{
 	char *e;
+	struct sigaction	ill_oact,ill_act;
+	sigset_t		oset;
+	static int trigger=0;
 
+	if (trigger) return;
+	trigger=1;
+ 
 	sigfillset(&all_masked);
 	sigdelset(&all_masked,SIGILL);
 	sigdelset(&all_masked,SIGTRAP);
@@ -72,26 +79,36 @@ void OPENSSL_cpuid_setup(void)
 		return;
 		}
 
+	OPENSSL_ppccap_P = 0;
+
+	memset(&ill_act,0,sizeof(ill_act));
+	ill_act.sa_handler = ill_handler;
+	ill_act.sa_mask    = all_masked;
+
+	sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset);
+	sigaction(SIGILL,&ill_act,&ill_oact);
+
 	if (sizeof(size_t)==4)
 		{
-		struct sigaction	ill_oact,ill_act;
-		sigset_t		oset;
-
-		memset(&ill_act,0,sizeof(ill_act));
-		ill_act.sa_handler = ill_handler;
-		ill_act.sa_mask    = all_masked;
-		sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset);
-		sigaction (SIGILL,&ill_act,&ill_oact);
-		if (sigsetjmp(ill_jmp,0) == 0)
+		if (sigsetjmp(ill_jmp,1) == 0)
 			{
 			OPENSSL_ppc64_probe();
 			OPENSSL_ppccap_P |= PPC_FPU64;
 			}
-		else
-			{
-			OPENSSL_ppccap_P &= ~PPC_FPU64;
-			}
-		sigaction (SIGILL,&ill_oact,NULL);
-		sigprocmask(SIG_SETMASK,&oset,NULL);
 		}
+	else
+		{
+		/*
+		 * Wanted code detecting POWER6 CPU and setting PPC_FPU64
+		 */
+		}
+
+	if (sigsetjmp(ill_jmp,1) == 0)
+		{
+		OPENSSL_altivec_probe();
+		OPENSSL_ppccap_P |= PPC_ALTIVEC;
+		}
+
+	sigaction (SIGILL,&ill_oact,NULL);
+	sigprocmask(SIG_SETMASK,&oset,NULL);
 	}
diff --git a/crypto/ppccpuid.pl b/crypto/ppccpuid.pl
index 7e8d233b72..2131d30c1d 100755
--- a/crypto/ppccpuid.pl
+++ b/crypto/ppccpuid.pl
@@ -30,6 +30,12 @@ $code=<<___;
 	extrdi	r0,r0,32,0
 	blr
 
+.globl	.OPENSSL_altivec_probe
+.align	4
+.OPENSSL_altivec_probe:
+	.long	0x10000484	# vor	v0,v0,v0
+	blr
+
 .globl	.OPENSSL_wipe_cpu
 .align	4
 .OPENSSL_wipe_cpu:
-- 
2.25.1