In FIPS mode only use "Generation by Testing Candidates" equivalent.
[openssl.git] / crypto / ppccap.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <setjmp.h>
5 #include <signal.h>
6 #include <openssl/bn.h>
7
8 #define PPC_FPU64       (1<<0)
9 #define PPC_ALTIVEC     (1<<1)
10
11 static int OPENSSL_ppccap_P = 0;
12
13 static sigset_t all_masked;
14
15 #ifdef OPENSSL_BN_ASM_MONT
16 int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np, const BN_ULONG *n0, int num)
17         {
18         int bn_mul_mont_fpu64(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np, const BN_ULONG *n0, int num);
19         int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np, const BN_ULONG *n0, int num);
20
21         if (sizeof(size_t)==4)
22                 {
23 #if (defined(__APPLE__) && defined(__MACH__))
24                 if ((OPENSSL_ppccap_P&PPC_FPU64))
25                         return bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
26 #else
27                 /* boundary of 32 was experimentally determined on
28                    Linux 2.6.22, might have to be adjusted on AIX... */
29                 if (num>=32 && (num&3)==0 && (OPENSSL_ppccap_P&PPC_FPU64))
30                         {
31                         sigset_t oset;
32                         int ret;
33
34                         sigprocmask(SIG_SETMASK,&all_masked,&oset);
35                         ret=bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
36                         sigprocmask(SIG_SETMASK,&oset,NULL);
37
38                         return ret;
39                         }
40 #endif
41                 }
42         else if ((OPENSSL_ppccap_P&PPC_FPU64))
43                 /* this is a "must" on POWER6, but run-time detection
44                  * is not implemented yet... */
45                 return bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
46
47         return bn_mul_mont_int(rp,ap,bp,np,n0,num);
48         }
49 #endif
50
51 static sigjmp_buf ill_jmp;
52 static void ill_handler (int sig) { siglongjmp(ill_jmp,sig); }
53
54 void OPENSSL_ppc64_probe(void);
55
56 void OPENSSL_cpuid_setup(void)
57         {
58         char *e;
59         struct sigaction        ill_oact,ill_act;
60         sigset_t                oset;
61         static int trigger=0;
62
63         if (trigger) return;
64         trigger=1;
65  
66         sigfillset(&all_masked);
67         sigdelset(&all_masked,SIGILL);
68         sigdelset(&all_masked,SIGTRAP);
69 #ifdef SIGEMT
70         sigdelset(&all_masked,SIGEMT);
71 #endif
72         sigdelset(&all_masked,SIGFPE);
73         sigdelset(&all_masked,SIGBUS);
74         sigdelset(&all_masked,SIGSEGV);
75
76         if ((e=getenv("OPENSSL_ppccap")))
77                 {
78                 OPENSSL_ppccap_P=strtoul(e,NULL,0);
79                 return;
80                 }
81
82         OPENSSL_ppccap_P = 0;
83
84         memset(&ill_act,0,sizeof(ill_act));
85         ill_act.sa_handler = ill_handler;
86         ill_act.sa_mask    = all_masked;
87
88         sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset);
89         sigaction(SIGILL,&ill_act,&ill_oact);
90
91         if (sizeof(size_t)==4)
92                 {
93                 if (sigsetjmp(ill_jmp,1) == 0)
94                         {
95                         OPENSSL_ppc64_probe();
96                         OPENSSL_ppccap_P |= PPC_FPU64;
97                         }
98                 }
99         else
100                 {
101                 /*
102                  * Wanted code detecting POWER6 CPU and setting PPC_FPU64
103                  */
104                 }
105
106         if (sigsetjmp(ill_jmp,1) == 0)
107                 {
108                 OPENSSL_altivec_probe();
109                 OPENSSL_ppccap_P |= PPC_ALTIVEC;
110                 }
111
112         sigaction (SIGILL,&ill_oact,NULL);
113         sigprocmask(SIG_SETMASK,&oset,NULL);
114         }