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