| OLD | NEW |
| 1 /* CpuArch.c -- CPU specific code | 1 /* CpuArch.c -- CPU specific code |
| 2 2010-10-26: Igor Pavlov : Public domain */ | 2 2015-03-25: Igor Pavlov : Public domain */ |
| 3 |
| 4 #include "Precomp.h" |
| 3 | 5 |
| 4 #include "CpuArch.h" | 6 #include "CpuArch.h" |
| 5 | 7 |
| 6 #ifdef MY_CPU_X86_OR_AMD64 | 8 #ifdef MY_CPU_X86_OR_AMD64 |
| 7 | 9 |
| 8 #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) | 10 #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) |
| 9 #define USE_ASM | 11 #define USE_ASM |
| 10 #endif | 12 #endif |
| 11 | 13 |
| 14 #if !defined(USE_ASM) && _MSC_VER >= 1500 |
| 15 #include <intrin.h> |
| 16 #endif |
| 17 |
| 12 #if defined(USE_ASM) && !defined(MY_CPU_AMD64) | 18 #if defined(USE_ASM) && !defined(MY_CPU_AMD64) |
| 13 static UInt32 CheckFlag(UInt32 flag) | 19 static UInt32 CheckFlag(UInt32 flag) |
| 14 { | 20 { |
| 15 #ifdef _MSC_VER | 21 #ifdef _MSC_VER |
| 16 __asm pushfd; | 22 __asm pushfd; |
| 17 __asm pop EAX; | 23 __asm pop EAX; |
| 18 __asm mov EDX, EAX; | 24 __asm mov EDX, EAX; |
| 19 __asm xor EAX, flag; | 25 __asm xor EAX, flag; |
| 20 __asm push EAX; | 26 __asm push EAX; |
| 21 __asm popfd; | 27 __asm popfd; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 42 "=c" (flag) : "c" (flag): | 48 "=c" (flag) : "c" (flag): |
| 43 "%eax", "%edx" ); | 49 "%eax", "%edx" ); |
| 44 #endif | 50 #endif |
| 45 return flag; | 51 return flag; |
| 46 } | 52 } |
| 47 #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 2
1) == 0) return False; | 53 #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 2
1) == 0) return False; |
| 48 #else | 54 #else |
| 49 #define CHECK_CPUID_IS_SUPPORTED | 55 #define CHECK_CPUID_IS_SUPPORTED |
| 50 #endif | 56 #endif |
| 51 | 57 |
| 52 static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) | 58 void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) |
| 53 { | 59 { |
| 54 #ifdef USE_ASM | 60 #ifdef USE_ASM |
| 55 | 61 |
| 56 #ifdef _MSC_VER | 62 #ifdef _MSC_VER |
| 57 | 63 |
| 58 UInt32 a2, b2, c2, d2; | 64 UInt32 a2, b2, c2, d2; |
| 59 __asm xor EBX, EBX; | 65 __asm xor EBX, EBX; |
| 60 __asm xor ECX, ECX; | 66 __asm xor ECX, ECX; |
| 61 __asm xor EDX, EDX; | 67 __asm xor EDX, EDX; |
| 62 __asm mov EAX, function; | 68 __asm mov EAX, function; |
| 63 __asm cpuid; | 69 __asm cpuid; |
| 64 __asm mov a2, EAX; | 70 __asm mov a2, EAX; |
| 65 __asm mov b2, EBX; | 71 __asm mov b2, EBX; |
| 66 __asm mov c2, ECX; | 72 __asm mov c2, ECX; |
| 67 __asm mov d2, EDX; | 73 __asm mov d2, EDX; |
| 68 | 74 |
| 69 *a = a2; | 75 *a = a2; |
| 70 *b = b2; | 76 *b = b2; |
| 71 *c = c2; | 77 *c = c2; |
| 72 *d = d2; | 78 *d = d2; |
| 73 | 79 |
| 74 #else | 80 #else |
| 75 | 81 |
| 82 __asm__ __volatile__ ( |
| 76 #if defined(MY_CPU_AMD64) | 83 #if defined(MY_CPU_AMD64) |
| 77 | |
| 78 __asm__ __volatile__ ( | |
| 79 "mov %%rbx, %%rdi\n" | 84 "mov %%rbx, %%rdi\n" |
| 80 "cpuid\n" | 85 "cpuid\n" |
| 81 "xchg %%rdi, %%rbx\n" | 86 "xchg %%rdi, %%rbx\n" |
| 82 : "=a" (*a) , | 87 : "=a" (*a) , |
| 83 "=D" (*b) , | 88 "=D" (*b) , |
| 84 "=c" (*c) , | 89 #elif defined(MY_CPU_X86) && defined(__PIC__) |
| 85 "=d" (*d) | 90 "mov %%ebx, %%edi;" |
| 86 : "0" (function)) ; | 91 "cpuid;" |
| 87 | 92 "xchgl %%ebx, %%edi;" |
| 88 #else | |
| 89 | |
| 90 __asm__ __volatile__ ( | |
| 91 "mov %%ebx, %%edi\n" | |
| 92 "cpuid\n" | |
| 93 "xchg %%edi, %%ebx\n" | |
| 94 : "=a" (*a) , | 93 : "=a" (*a) , |
| 95 "=D" (*b) , | 94 "=D" (*b) , |
| 95 #else |
| 96 "cpuid" |
| 97 : "=a" (*a) , |
| 98 "=b" (*b) , |
| 99 #endif |
| 96 "=c" (*c) , | 100 "=c" (*c) , |
| 97 "=d" (*d) | 101 "=d" (*d) |
| 98 : "0" (function)) ; | 102 : "0" (function)) ; |
| 99 | 103 |
| 100 #endif | 104 #endif |
| 101 | |
| 102 #endif | |
| 103 | 105 |
| 104 #else | 106 #else |
| 105 | 107 |
| 106 int CPUInfo[4]; | 108 int CPUInfo[4]; |
| 107 __cpuid(CPUInfo, function); | 109 __cpuid(CPUInfo, function); |
| 108 *a = CPUInfo[0]; | 110 *a = CPUInfo[0]; |
| 109 *b = CPUInfo[1]; | 111 *b = CPUInfo[1]; |
| 110 *c = CPUInfo[2]; | 112 *c = CPUInfo[2]; |
| 111 *d = CPUInfo[3]; | 113 *d = CPUInfo[3]; |
| 112 | 114 |
| 113 #endif | 115 #endif |
| 114 } | 116 } |
| 115 | 117 |
| 116 Bool x86cpuid_CheckAndRead(Cx86cpuid *p) | 118 Bool x86cpuid_CheckAndRead(Cx86cpuid *p) |
| 117 { | 119 { |
| 118 CHECK_CPUID_IS_SUPPORTED | 120 CHECK_CPUID_IS_SUPPORTED |
| 119 MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); | 121 MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); |
| 120 MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); | 122 MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); |
| 121 return True; | 123 return True; |
| 122 } | 124 } |
| 123 | 125 |
| 124 static UInt32 kVendors[][3] = | 126 static const UInt32 kVendors[][3] = |
| 125 { | 127 { |
| 126 { 0x756E6547, 0x49656E69, 0x6C65746E}, | 128 { 0x756E6547, 0x49656E69, 0x6C65746E}, |
| 127 { 0x68747541, 0x69746E65, 0x444D4163}, | 129 { 0x68747541, 0x69746E65, 0x444D4163}, |
| 128 { 0x746E6543, 0x48727561, 0x736C7561} | 130 { 0x746E6543, 0x48727561, 0x736C7561} |
| 129 }; | 131 }; |
| 130 | 132 |
| 131 int x86cpuid_GetFirm(const Cx86cpuid *p) | 133 int x86cpuid_GetFirm(const Cx86cpuid *p) |
| 132 { | 134 { |
| 133 unsigned i; | 135 unsigned i; |
| 134 for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) | 136 for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) |
| 135 { | 137 { |
| 136 const UInt32 *v = kVendors[i]; | 138 const UInt32 *v = kVendors[i]; |
| 137 if (v[0] == p->vendor[0] && | 139 if (v[0] == p->vendor[0] && |
| 138 v[1] == p->vendor[1] && | 140 v[1] == p->vendor[1] && |
| 139 v[2] == p->vendor[2]) | 141 v[2] == p->vendor[2]) |
| 140 return (int)i; | 142 return (int)i; |
| 141 } | 143 } |
| 142 return -1; | 144 return -1; |
| 143 } | 145 } |
| 144 | 146 |
| 145 Bool CPU_Is_InOrder() | 147 Bool CPU_Is_InOrder() |
| 146 { | 148 { |
| 147 Cx86cpuid p; | 149 Cx86cpuid p; |
| 148 int firm; | 150 int firm; |
| 149 UInt32 family, model; | 151 UInt32 family, model; |
| 150 if (!x86cpuid_CheckAndRead(&p)) | 152 if (!x86cpuid_CheckAndRead(&p)) |
| 151 return True; | 153 return True; |
| 152 family = x86cpuid_GetFamily(&p); | 154 |
| 153 model = x86cpuid_GetModel(&p); | 155 family = x86cpuid_GetFamily(p.ver); |
| 156 model = x86cpuid_GetModel(p.ver); |
| 157 |
| 154 firm = x86cpuid_GetFirm(&p); | 158 firm = x86cpuid_GetFirm(&p); |
| 159 |
| 155 switch (firm) | 160 switch (firm) |
| 156 { | 161 { |
| 157 case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C))
; | 162 case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && ( |
| 163 /* In-Order Atom CPU */ |
| 164 model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */ |
| 165 || model == 0x26 /* 45 nm, Z6xx */ |
| 166 || model == 0x27 /* 32 nm, Z2460 */ |
| 167 || model == 0x35 /* 32 nm, Z2760 */ |
| 168 || model == 0x36 /* 32 nm, N2xxx, D2xxx */ |
| 169 ))); |
| 158 case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model
== 0xA))); | 170 case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model
== 0xA))); |
| 159 case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); | 171 case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); |
| 160 } | 172 } |
| 161 return True; | 173 return True; |
| 162 } | 174 } |
| 163 | 175 |
| 164 #if !defined(MY_CPU_AMD64) && defined(_WIN32) | 176 #if !defined(MY_CPU_AMD64) && defined(_WIN32) |
| 177 #include <windows.h> |
| 165 static Bool CPU_Sys_Is_SSE_Supported() | 178 static Bool CPU_Sys_Is_SSE_Supported() |
| 166 { | 179 { |
| 167 OSVERSIONINFO vi; | 180 OSVERSIONINFO vi; |
| 168 vi.dwOSVersionInfoSize = sizeof(vi); | 181 vi.dwOSVersionInfoSize = sizeof(vi); |
| 169 if (!GetVersionEx(&vi)) | 182 if (!GetVersionEx(&vi)) |
| 170 return False; | 183 return False; |
| 171 return (vi.dwMajorVersion >= 5); | 184 return (vi.dwMajorVersion >= 5); |
| 172 } | 185 } |
| 173 #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; | 186 #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; |
| 174 #else | 187 #else |
| 175 #define CHECK_SYS_SSE_SUPPORT | 188 #define CHECK_SYS_SSE_SUPPORT |
| 176 #endif | 189 #endif |
| 177 | 190 |
| 178 Bool CPU_Is_Aes_Supported() | 191 Bool CPU_Is_Aes_Supported() |
| 179 { | 192 { |
| 180 Cx86cpuid p; | 193 Cx86cpuid p; |
| 181 CHECK_SYS_SSE_SUPPORT | 194 CHECK_SYS_SSE_SUPPORT |
| 182 if (!x86cpuid_CheckAndRead(&p)) | 195 if (!x86cpuid_CheckAndRead(&p)) |
| 183 return False; | 196 return False; |
| 184 return (p.c >> 25) & 1; | 197 return (p.c >> 25) & 1; |
| 185 } | 198 } |
| 186 | 199 |
| 187 #endif | 200 #endif |
| OLD | NEW |