upstream: https://github.com/mirage/mirage-crypto
1#include "crypto.h"
2
3#ifdef __mc_detect_features__
4
5#ifndef _MSC_VER
6# include <cpuid.h>
7#endif
8
9struct _mc_cpu_features mc_detected_cpu_features = { 0 };
10
11#ifdef _MSC_VER
12#define bit_PCLMUL ((int)1 << 1)
13#define bit_SSSE3 ((int)1 << 9)
14#define bit_AES ((int)1 << 25)
15#define bit_RDRND ((int)1 << 30)
16#define bit_RDSEED ((int)1 << 18)
17
18CAMLprim value
19mc_detect_cpu_features (__unit ()) {
20 int cpuInfo[4] = {-1};
21 int ebx;
22 int ecx;
23
24 __cpuid(cpuInfo, 0x00000000);
25 int max = cpuInfo[0];
26 if (max < 1) return Val_unit;
27
28 __cpuid(cpuInfo, 0x00000001);
29 ecx = cpuInfo[2];
30
31 if (ecx & bit_PCLMUL)
32 mc_detected_cpu_features.pclmul = 1;
33 if (ecx & bit_SSSE3)
34 mc_detected_cpu_features.ssse3 = 1;
35 if (ecx & bit_AES)
36 mc_detected_cpu_features.aesni = 1;
37 if (ecx & bit_RDRND)
38 mc_detected_cpu_features.rdrand = 1;
39
40 if (max > 7) {
41 __cpuid(cpuInfo, 0x00000007);
42 ebx = cpuInfo[1];
43 if (ebx & bit_RDSEED)
44 mc_detected_cpu_features.rdseed = 1;
45 }
46
47 return Val_unit;
48}
49
50#else
51
52CAMLprim value
53mc_detect_cpu_features (__unit ()) {
54 unsigned int sig = 0, eax = 0, ebx = 0, ecx = 0, edx = 0;
55
56 int max = __get_cpuid_max(0, &sig);
57
58 if (max < 1) return Val_unit;
59
60 __cpuid(1, eax, ebx, ecx, edx);
61 if (ecx & bit_PCLMUL)
62 mc_detected_cpu_features.pclmul = 1;
63 if (ecx & bit_SSSE3)
64 mc_detected_cpu_features.ssse3 = 1;
65 if (ecx & bit_AES)
66 mc_detected_cpu_features.aesni = 1;
67 if (ecx & bit_RDRND)
68 mc_detected_cpu_features.rdrand = 1;
69
70 if (max > 7) {
71 __cpuid_count(7, 0, eax, ebx, ecx, edx);
72 if (ebx & bit_RDSEED)
73 mc_detected_cpu_features.rdseed = 1;
74 }
75
76 return Val_unit;
77}
78#endif /* _MSC_VER */
79
80#else /* __mc_detect_features__ */
81
82CAMLprim value
83mc_detect_cpu_features (__unit ()) {
84 return Val_unit;
85}
86
87#endif /* __mc_detect_features__ */