Better wording for transaction fee notification messages
[novacoin.git] / src / cryptopp / cpu.cpp
1 // cpu.cpp - written and placed in the public domain by Wei Dai
2
3 #include "pch.h"
4
5 #ifndef CRYPTOPP_IMPORTS
6
7 #include "cpu.h"
8 #include "misc.h"
9 #include <algorithm>
10
11 #ifdef __GNUC__
12 #include <signal.h>
13 #include <setjmp.h>
14 #endif
15
16 #ifdef CRYPTOPP_MSVC6PP_OR_LATER
17 #include <emmintrin.h>
18 #endif
19
20 NAMESPACE_BEGIN(CryptoPP)
21
22 #ifdef CRYPTOPP_X86_ASM_AVAILABLE
23
24 #ifndef _MSC_VER
25 typedef void (*SigHandler)(int);
26
27 static jmp_buf s_jmpNoCPUID;
28 static void SigIllHandlerCPUID(int)
29 {
30         longjmp(s_jmpNoCPUID, 1);
31 }
32 #endif
33
34 bool CpuId(word32 input, word32 *output)
35 {
36 #ifdef _MSC_VER
37     __try
38         {
39                 __asm
40                 {
41                         mov eax, input
42                         cpuid
43                         mov edi, output
44                         mov [edi], eax
45                         mov [edi+4], ebx
46                         mov [edi+8], ecx
47                         mov [edi+12], edx
48                 }
49         }
50     __except (1)
51         {
52                 return false;
53     }
54         return true;
55 #else
56         SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
57         if (oldHandler == SIG_ERR)
58                 return false;
59
60         bool result = true;
61         if (setjmp(s_jmpNoCPUID))
62                 result = false;
63         else
64         {
65                 __asm__
66                 (
67                         // save ebx in case -fPIC is being used
68 #if CRYPTOPP_BOOL_X86
69                         "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
70 #else
71                         "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
72 #endif
73                         : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
74                         : "a" (input)
75                 );
76         }
77
78         signal(SIGILL, oldHandler);
79         return result;
80 #endif
81 }
82
83 #ifndef _MSC_VER
84 static jmp_buf s_jmpNoSSE2;
85 static void SigIllHandlerSSE2(int)
86 {
87         longjmp(s_jmpNoSSE2, 1);
88 }
89 #endif
90
91 #elif _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
92
93 bool CpuId(word32 input, word32 *output)
94 {
95         __cpuid((int *)output, input);
96         return true;
97 }
98
99 #endif
100
101 #ifdef CRYPTOPP_CPUID_AVAILABLE
102
103 static bool TrySSE2()
104 {
105 #if CRYPTOPP_BOOL_X64
106         return true;
107 #elif defined(_MSC_VER)
108     __try
109         {
110 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
111         AS2(por xmm0, xmm0)        // executing SSE2 instruction
112 #elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
113                 __mm128i x = _mm_setzero_si128();
114                 return _mm_cvtsi128_si32(x) == 0;
115 #endif
116         }
117     __except (1)
118         {
119                 return false;
120     }
121         return true;
122 #elif defined(__GNUC__)
123         SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2);
124         if (oldHandler == SIG_ERR)
125                 return false;
126
127         bool result = true;
128         if (setjmp(s_jmpNoSSE2))
129                 result = false;
130         else
131         {
132 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
133                 __asm __volatile ("por %xmm0, %xmm0");
134 #elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
135                 __mm128i x = _mm_setzero_si128();
136                 result = _mm_cvtsi128_si32(x) == 0;
137 #endif
138         }
139
140         signal(SIGILL, oldHandler);
141         return result;
142 #else
143         return false;
144 #endif
145 }
146
147 bool g_x86DetectionDone = false;
148 bool g_hasISSE = false, g_hasSSE2 = false, g_hasSSSE3 = false, g_hasMMX = false, g_isP4 = false;
149 word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
150
151 void DetectX86Features()
152 {
153         word32 cpuid[4], cpuid1[4];
154         if (!CpuId(0, cpuid))
155                 return;
156         if (!CpuId(1, cpuid1))
157                 return;
158
159         g_hasMMX = (cpuid1[3] & (1 << 23)) != 0;
160         if ((cpuid1[3] & (1 << 26)) != 0)
161                 g_hasSSE2 = TrySSE2();
162         g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9));
163
164         if ((cpuid1[3] & (1 << 25)) != 0)
165                 g_hasISSE = true;
166         else
167         {
168                 word32 cpuid2[4];
169                 CpuId(0x080000000, cpuid2);
170                 if (cpuid2[0] >= 0x080000001)
171                 {
172                         CpuId(0x080000001, cpuid2);
173                         g_hasISSE = (cpuid2[3] & (1 << 22)) != 0;
174                 }
175         }
176
177         std::swap(cpuid[2], cpuid[3]);
178         if (memcmp(cpuid+1, "GenuineIntel", 12) == 0)
179         {
180                 g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
181                 g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
182         }
183         else if (memcmp(cpuid+1, "AuthenticAMD", 12) == 0)
184         {
185                 CpuId(0x80000005, cpuid);
186                 g_cacheLineSize = GETBYTE(cpuid[2], 0);
187         }
188
189         if (!g_cacheLineSize)
190                 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
191
192         g_x86DetectionDone = true;
193 }
194
195 #endif
196
197 NAMESPACE_END
198
199 #endif