Tolerate a SEQUENCE in DN components.
[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 _sparcv9_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 _sparcv9_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))  /* covers II,III,IV */
59                 {
60                 OPENSSL_sparcv9cap_P |= SPARCV9_PREFER_FPU|SPARCV9_VIS1;
61
62                 /* %tick is privileged only on UltraSPARC-I/II, but not IIe */
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 UltraSPARCs, such as T1 */
69         else if (!strncmp(name,"SUNW,UltraSPARC",15))
70                 {
71                 OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED;
72
73                 return DI_WALK_TERMINATE;
74                 }
75
76         return DI_WALK_CONTINUE;
77         }
78
79 void OPENSSL_cpuid_setup(void)
80         {
81         void *h;
82         char *e;
83         static int trigger=0;
84
85         if (trigger) return;
86         trigger=1;
87
88         if ((e=getenv("OPENSSL_sparcv9cap")))
89                 {
90                 OPENSSL_sparcv9cap_P=strtoul(e,NULL,0);
91                 return;
92                 }
93
94         if ((h = dlopen("libdevinfo.so.1",RTLD_LAZY))) do
95                 {
96                 di_init_t       di_init;
97                 di_fini_t       di_fini;
98                 di_walk_node_t  di_walk_node;
99                 di_node_name_t  di_node_name;
100                 di_node_t       root_node;
101
102                 if (!DLLINK(h,di_init))         break;
103                 if (!DLLINK(h,di_fini))         break;
104                 if (!DLLINK(h,di_walk_node))    break;
105                 if (!DLLINK(h,di_node_name))    break;
106
107                 if ((root_node = (*di_init)("/",DINFOSUBTREE))!=DI_NODE_NIL)
108                         {
109                         (*di_walk_node)(root_node,DI_WALK_SIBFIRST,
110                                         di_node_name,walk_nodename);
111                         (*di_fini)(root_node);
112                         }
113                 } while(0);
114
115         if (h) dlclose(h);
116         }
117
118 #else
119
120 void OPENSSL_cpuid_setup(void)
121         {
122         char *e;
123  
124         if ((e=getenv("OPENSSL_sparcv9cap")))
125                 {
126                 OPENSSL_sparcv9cap_P=strtoul(env,NULL,0);
127                 return;
128                 }
129
130         /* For now we assume that the rest supports UltraSPARC-I* only */
131         OPENSSL_sparcv9cap_P |= SPARCV9_PREFER_FPU|SPARCV9_VIS1;
132         }
133
134 #endif