Return an error if no recipient type matches.
[openssl.git] / crypto / ppccap.c
index 2c3e1f2fcbe2c0da53c3780255d5fb11602bda8d..d78bfbcdbb88265e1906ba03fa1b92280dcc9f34 100644 (file)
@@ -3,11 +3,17 @@
 #include <string.h>
 #include <setjmp.h>
 #include <signal.h>
+#include <unistd.h>
+#if defined(__linux) || defined(_AIX)
+#include <sys/utsname.h>
+#endif
+#include <crypto.h>
 #include <openssl/bn.h>
 
 #define PPC_FPU64      (1<<0)
+#define PPC_ALTIVEC    (1<<1)
 
-static int OPENSSL_ppccap_P = 0;
+unsigned int OPENSSL_ppccap_P = 0;
 
 static sigset_t all_masked;
 
@@ -19,8 +25,8 @@ int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_U
 
        if (sizeof(size_t)==4)
                {
-#if (defined(__APPLE__) && defined(__MACH__))
-               if ((OPENSSL_ppccap_P&PPC_FPU64))
+#if 1 || (defined(__APPLE__) && defined(__MACH__))
+               if (num>=8 && (num&3)==0 && (OPENSSL_ppccap_P&PPC_FPU64))
                        return bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
 #else
                /* boundary of 32 was experimentally determined on
@@ -39,7 +45,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);
 
@@ -51,16 +57,27 @@ static sigjmp_buf ill_jmp;
 static void ill_handler (int sig) { siglongjmp(ill_jmp,sig); }
 
 void OPENSSL_ppc64_probe(void);
+void OPENSSL_altivec_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,SIGSEGV);
        sigdelset(&all_masked,SIGILL);
-       sigdelset(&all_masked,SIGBUS);
+       sigdelset(&all_masked,SIGTRAP);
+#ifdef SIGEMT
+       sigdelset(&all_masked,SIGEMT);
+#endif
        sigdelset(&all_masked,SIGFPE);
+       sigdelset(&all_masked,SIGBUS);
+       sigdelset(&all_masked,SIGSEGV);
 
        if ((e=getenv("OPENSSL_ppccap")))
                {
@@ -68,26 +85,51 @@ void OPENSSL_cpuid_setup(void)
                return;
                }
 
+       OPENSSL_ppccap_P = 0;
+
+#if defined(_AIX)
        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)
+               struct utsname uts;
+# if defined(_SC_AIX_KERNEL_BITMODE)
+               if (sysconf(_SC_AIX_KERNEL_BITMODE)!=64)        return;
+# endif
+               if (uname(&uts)!=0 || atoi(uts.version)<6)      return;
+               }
+#endif
+
+       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)
+               {
+#ifdef __linux
+               struct utsname uts;
+               if (uname(&uts)==0 && strcmp(uts.machine,"ppc64")==0)
+#endif
+               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);
        }