RT3548: Remove unsupported platforms
[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 <unistd.h>
7 #if defined(__linux) || defined(_AIX)
8 #include <sys/utsname.h>
9 #endif
10 #include <crypto.h>
11 #include <openssl/bn.h>
12
13 #include "ppc_arch.h"
14
15 unsigned int OPENSSL_ppccap_P = 0;
16
17 static sigset_t all_masked;
18
19 #ifdef OPENSSL_BN_ASM_MONT
20 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)
21         {
22         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);
23         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);
24
25         if (sizeof(size_t)==4)
26                 {
27 #if 1 || (defined(__APPLE__) && defined(__MACH__))
28                 if (num>=8 && (num&3)==0 && (OPENSSL_ppccap_P&PPC_FPU64))
29                         return bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
30 #else
31                 /* boundary of 32 was experimentally determined on
32                    Linux 2.6.22, might have to be adjusted on AIX... */
33                 if (num>=32 && (num&3)==0 && (OPENSSL_ppccap_P&PPC_FPU64))
34                         {
35                         sigset_t oset;
36                         int ret;
37
38                         sigprocmask(SIG_SETMASK,&all_masked,&oset);
39                         ret=bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
40                         sigprocmask(SIG_SETMASK,&oset,NULL);
41
42                         return ret;
43                         }
44 #endif
45                 }
46         else if ((OPENSSL_ppccap_P&PPC_FPU64))
47                 /* this is a "must" on POWER6, but run-time detection
48                  * is not implemented yet... */
49                 return bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
50
51         return bn_mul_mont_int(rp,ap,bp,np,n0,num);
52         }
53 #endif
54
55 void sha256_block_p8(void *ctx,const void *inp,size_t len);
56 void sha256_block_ppc(void *ctx,const void *inp,size_t len);
57 void sha256_block_data_order(void *ctx,const void *inp,size_t len)
58         {
59         OPENSSL_ppccap_P&PPC_CRYPTO207? sha256_block_p8(ctx,inp,len):
60                                         sha256_block_ppc(ctx,inp,len);
61         }
62
63 void sha512_block_p8(void *ctx,const void *inp,size_t len);
64 void sha512_block_ppc(void *ctx,const void *inp,size_t len);
65 void sha512_block_data_order(void *ctx,const void *inp,size_t len)
66         {
67         OPENSSL_ppccap_P&PPC_CRYPTO207? sha512_block_p8(ctx,inp,len):
68                                         sha512_block_ppc(ctx,inp,len);
69         }
70
71 static sigjmp_buf ill_jmp;
72 static void ill_handler (int sig) { siglongjmp(ill_jmp,sig); }
73
74 void OPENSSL_ppc64_probe(void);
75 void OPENSSL_altivec_probe(void);
76 void OPENSSL_crypto207_probe(void);
77
78 void OPENSSL_cpuid_setup(void)
79         {
80         char *e;
81         struct sigaction        ill_oact,ill_act;
82         sigset_t                oset;
83         static int trigger=0;
84
85         if (trigger) return;
86         trigger=1;
87  
88         sigfillset(&all_masked);
89         sigdelset(&all_masked,SIGILL);
90         sigdelset(&all_masked,SIGTRAP);
91 #ifdef SIGEMT
92         sigdelset(&all_masked,SIGEMT);
93 #endif
94         sigdelset(&all_masked,SIGFPE);
95         sigdelset(&all_masked,SIGBUS);
96         sigdelset(&all_masked,SIGSEGV);
97
98         if ((e=getenv("OPENSSL_ppccap")))
99                 {
100                 OPENSSL_ppccap_P=strtoul(e,NULL,0);
101                 return;
102                 }
103
104         OPENSSL_ppccap_P = 0;
105
106 #if defined(_AIX)
107         if (sizeof(size_t)==4)
108                 {
109                 struct utsname uts;
110 # if defined(_SC_AIX_KERNEL_BITMODE)
111                 if (sysconf(_SC_AIX_KERNEL_BITMODE)!=64)        return;
112 # endif
113                 if (uname(&uts)!=0 || atoi(uts.version)<6)      return;
114                 }
115 #endif
116
117         memset(&ill_act,0,sizeof(ill_act));
118         ill_act.sa_handler = ill_handler;
119         ill_act.sa_mask    = all_masked;
120
121         sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset);
122         sigaction(SIGILL,&ill_act,&ill_oact);
123
124         if (sizeof(size_t)==4)
125                 {
126 #ifdef __linux
127                 struct utsname uts;
128                 if (uname(&uts)==0 && strcmp(uts.machine,"ppc64")==0)
129 #endif
130                 if (sigsetjmp(ill_jmp,1) == 0)
131                         {
132                         OPENSSL_ppc64_probe();
133                         OPENSSL_ppccap_P |= PPC_FPU64;
134                         }
135                 }
136         else
137                 {
138                 /*
139                  * Wanted code detecting POWER6 CPU and setting PPC_FPU64
140                  */
141                 }
142
143         if (sigsetjmp(ill_jmp,1) == 0)
144                 {
145                 OPENSSL_altivec_probe();
146                 OPENSSL_ppccap_P |= PPC_ALTIVEC;
147                 if (sigsetjmp(ill_jmp,1) == 0)
148                         {
149                         OPENSSL_crypto207_probe();
150                         OPENSSL_ppccap_P |= PPC_CRYPTO207;
151                         }
152                 }
153
154         sigaction (SIGILL,&ill_oact,NULL);
155         sigprocmask(SIG_SETMASK,&oset,NULL);
156         }