7012f78604b294fd8dcc202b86058d312282e5d8
[openssl.git] / crypto / sparcv9cap.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/time.h>
5 #include <openssl/bn.h>
6
7 #define SPARCV9_TICK_PRIVILEGED (1<<0)
8 #define SPARCV9_PREFER_FPU      (1<<1)
9 #define SPARCV9_VIS1            (1<<2)
10 #define SPARCV9_VIS2            (1<<3)  /* reserved */
11 #define SPARCV9_FMADD           (1<<4)  /* reserved for SPARC64 V */
12 static int OPENSSL_sparcv9cap_P=SPARCV9_TICK_PRIVILEGED;
13
14 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)
15         {
16         int bn_mul_mont_fpu(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np,const BN_ULONG *n0, int num);
17         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);
18
19         if (OPENSSL_sparcv9cap_P&(SPARCV9_PREFER_FPU|SPARCV9_VIS1) ==
20                 (SPARCV9_PREFER_FPU|SPARCV9_VIS1))
21                 return bn_mul_mont_fpu(rp,ap,bp,np,n0,num);
22         else
23                 return bn_mul_mont_int(rp,ap,bp,np,n0,num);
24         }
25
26 unsigned long OPENSSL_rdtsc(void)
27         {
28         unsigned long OPENSSL_rdtick(void);
29
30         if (OPENSSL_sparcv9cap_P&SPARCV9_TICK_PRIVILEGED)
31 #if defined(__sun) && defined(__SVR4)
32                 return gethrtime();
33 #else
34                 return 0;
35 #endif
36         else
37                 return OPENSSL_rdtick();
38         }
39
40 #if defined(__sun) && defined(__SVR4)
41
42 #include <dlfcn.h>
43 #include <libdevinfo.h>
44
45 typedef di_node_t (*di_init_t)(const char *,uint_t);
46 typedef void      (*di_fini_t)(di_node_t);
47 typedef char *    (*di_node_name_t)(di_node_t);
48 typedef int       (*di_walk_node_t)(di_node_t,uint_t,di_node_name_t,int (*)(di_node_t,di_node_name_t));
49
50 #define DLLINK(h,name) (name=(name##_t)dlsym((h),#name))
51
52 static int walk_nodename(di_node_t node, di_node_name_t di_node_name)
53         {
54         char *name = (*di_node_name)(node);
55
56         /* This is expected to catch all UltraSPARC flavors prior T1 */
57         if (!strcmp (name,"SUNW,UltraSPARC") ||
58             !strncmp(name,"SUNW,UltraSPARC-I",17))
59                 {
60                 OPENSSL_sparcv9cap_P |= SPARCV9_PREFER_FPU|SPARCV9_VIS1;
61
62                 /* %tick is privileged only on UltraSPARC-I/II */
63                 if (name[14]!='\0' && name[17]!='\0' && name[18]!='\0')
64                         OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED;
65
66                 return DI_WALK_TERMINATE;
67                 }
68         /* This is expected to catch remaining UltraSPARC T1 */
69         else if (!strncmp(name,"SUNW,UltraSPARC",15))
70                 {
71                 OPENSSL_sparcv9cap_P |= SPARCV9_VIS1;
72                 OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED;
73                 }
74
75         return DI_WALK_CONTINUE;
76         }
77
78 void OPENSSL_cpuid_setup(void)
79         {
80         void *h;
81         char *e;
82
83         if (e=getenv("OPENSSL_sparcv9cap"))
84                 {
85                 OPENSSL_sparcv9cap_P=strtoul(e,NULL,0);
86                 return;
87                 }
88
89         if (h = dlopen("libdevinfo.so.1",RTLD_LAZY)) do
90                 {
91                 di_init_t       di_init;
92                 di_fini_t       di_fini;
93                 di_walk_node_t  di_walk_node;
94                 di_node_name_t  di_node_name;
95                 di_node_t       root_node;
96
97                 if (!DLLINK(h,di_init))         break;
98                 if (!DLLINK(h,di_fini))         break;
99                 if (!DLLINK(h,di_walk_node))    break;
100                 if (!DLLINK(h,di_node_name))    break;
101
102                 if ((root_node = (*di_init)("/",DINFOSUBTREE))!=DI_NODE_NIL)
103                         {
104                         (*di_walk_node)(root_node,DI_WALK_SIBFIRST,
105                                         di_node_name,walk_nodename);
106                         (*di_fini)(root_node);
107                         }
108                 } while(0);
109
110         if (h) dlclose(h);
111         }
112
113 #elif defined(__linux)
114
115 void OPENSSL_cpuid_setup(void)
116         {
117         char *e;
118  
119         if (e=getenv("OPENSSL_sparcv9cap"))
120                 {
121                 OPENSSL_sparcv9cap_P=strtoul(env,NULL,0);
122                 return;
123                 }
124
125         /* Linux apparently supports UltraSPARC-I/II/III only */
126         OPENSSL_sparcv9cap_P |= SPARCV9_PREFER_FPU|SPARCV9_VIS1;
127         }
128
129 #else
130
131 void OPENSSL_cpuid_setup(void) {}
132
133 #endif