5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2008 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 #include <silcruntime.h>
22 #if defined(SILC_I486) || defined(SILC_X86_64)
23 static void silc_cpuid(SilcUInt32 level, SilcUInt32 *ecx, SilcUInt32 *edx)
25 /* This works on modern CPUs. Probably fails on some ancient CPUs. */
26 asm volatile ("xorl %%ecx, %%ecx \n"
27 "xorl %%edx, %%edx \n"
32 : "=m" (*edx), "=m" (*ecx)
34 : "ebx", "eax", "ecx", "edx");
36 SILC_LOG_DEBUG(("CPUID 0x%08x: ecx=0x%08x, edx=0x%08x", level, *ecx, *edx));
38 #endif /* SILC_I486 || SILC_X86_64 */
40 SilcCPUIdFeatures silc_cpuid_features(void)
42 SilcCPUIdFeatures id = SILC_CPUID_UNKNOWN;
43 #if defined(SILC_I486) || defined(SILC_X86_64)
44 SilcUInt32 ecx = 0, edx = 0;
47 silc_cpuid(1, &ecx, &edx);
49 return SILC_CPUID_UNKNOWN;
51 SILC_LOG_DEBUG(("386"));
54 if (edx & (1 << 23)) {
55 SILC_LOG_DEBUG(("MMX"));
59 if (edx & (1 << 15)) {
60 SILC_LOG_DEBUG(("CMOV"));
61 id |= SILC_CPUID_CMOV;
64 if (edx & (1 << 25)) {
65 SILC_LOG_DEBUG(("SSE"));
69 if (edx & (1 << 26)) {
70 SILC_LOG_DEBUG(("SSE2"));
71 id |= SILC_CPUID_SSE2;
75 SILC_LOG_DEBUG(("SSE3"));
76 id |= SILC_CPUID_SSE3;
80 SILC_LOG_DEBUG(("SSSE3"));
81 id |= SILC_CPUID_SSSE3;
84 if (ecx & (1 << 19)) {
85 SILC_LOG_DEBUG(("SSE4.1"));
86 id |= SILC_CPUID_SSE41;
89 if (ecx & (1 << 20)) {
90 SILC_LOG_DEBUG(("SSE4.2"));
91 id |= SILC_CPUID_SSE41;
94 if (ecx & (1 << 28)) {
95 SILC_LOG_DEBUG(("AVX"));
99 if (ecx & (1 << 25)) {
100 SILC_LOG_DEBUG(("AES"));
101 id |= SILC_CPUID_AES;
106 silc_cpuid(0x80000001, &ecx, &edx);
110 if (ecx & (1 << 6)) {
111 SILC_LOG_DEBUG(("SSE4a"));
112 id |= SILC_CPUID_SSE4A;
115 if (ecx & (1 << 25)) {
116 SILC_LOG_DEBUG(("SSE5"));
117 id |= SILC_CPUID_SSE5;
121 #endif /* SILC_I486 || SILC_X86_64 */