File indexing completed on 2025-02-02 04:25:58
0001 /* CpuArch.c -- CPU specific code 0002 2012-05-29: Igor Pavlov : Public domain */ 0003 0004 #include "Precomp.h" 0005 0006 #include "CpuArch.h" 0007 0008 #ifdef MY_CPU_X86_OR_AMD64 0009 0010 #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) 0011 #define USE_ASM 0012 #endif 0013 0014 #if !defined(USE_ASM) && _MSC_VER >= 1500 0015 #include <intrin.h> 0016 #endif 0017 0018 #if defined(USE_ASM) && !defined(MY_CPU_AMD64) 0019 static UInt32 CheckFlag(UInt32 flag) 0020 { 0021 #ifdef _MSC_VER 0022 __asm pushfd; 0023 __asm pop EAX; 0024 __asm mov EDX, EAX; 0025 __asm xor EAX, flag; 0026 __asm push EAX; 0027 __asm popfd; 0028 __asm pushfd; 0029 __asm pop EAX; 0030 __asm xor EAX, EDX; 0031 __asm push EDX; 0032 __asm popfd; 0033 __asm and flag, EAX; 0034 #else 0035 __asm__ __volatile__ ( 0036 "pushf\n\t" 0037 "pop %%EAX\n\t" 0038 "movl %%EAX,%%EDX\n\t" 0039 "xorl %0,%%EAX\n\t" 0040 "push %%EAX\n\t" 0041 "popf\n\t" 0042 "pushf\n\t" 0043 "pop %%EAX\n\t" 0044 "xorl %%EDX,%%EAX\n\t" 0045 "push %%EDX\n\t" 0046 "popf\n\t" 0047 "andl %%EAX, %0\n\t": 0048 "=c" (flag) : "c" (flag)); 0049 #endif 0050 return flag; 0051 } 0052 #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; 0053 #else 0054 #define CHECK_CPUID_IS_SUPPORTED 0055 #endif 0056 0057 static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) 0058 { 0059 #ifdef USE_ASM 0060 0061 #ifdef _MSC_VER 0062 0063 UInt32 a2, b2, c2, d2; 0064 __asm xor EBX, EBX; 0065 __asm xor ECX, ECX; 0066 __asm xor EDX, EDX; 0067 __asm mov EAX, function; 0068 __asm cpuid; 0069 __asm mov a2, EAX; 0070 __asm mov b2, EBX; 0071 __asm mov c2, ECX; 0072 __asm mov d2, EDX; 0073 0074 *a = a2; 0075 *b = b2; 0076 *c = c2; 0077 *d = d2; 0078 0079 #else 0080 0081 __asm__ __volatile__ ( 0082 #if defined(MY_CPU_X86) && defined(__PIC__) 0083 "mov %%ebx, %%edi;" 0084 "cpuid;" 0085 "xchgl %%ebx, %%edi;" 0086 : "=a" (*a) , 0087 "=D" (*b) , 0088 #else 0089 "cpuid" 0090 : "=a" (*a) , 0091 "=b" (*b) , 0092 #endif 0093 "=c" (*c) , 0094 "=d" (*d) 0095 : "0" (function)) ; 0096 0097 #endif 0098 0099 #else 0100 0101 int CPUInfo[4]; 0102 __cpuid(CPUInfo, function); 0103 *a = CPUInfo[0]; 0104 *b = CPUInfo[1]; 0105 *c = CPUInfo[2]; 0106 *d = CPUInfo[3]; 0107 0108 #endif 0109 } 0110 0111 Bool x86cpuid_CheckAndRead(Cx86cpuid *p) 0112 { 0113 CHECK_CPUID_IS_SUPPORTED 0114 MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); 0115 MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); 0116 return True; 0117 } 0118 0119 static UInt32 kVendors[][3] = 0120 { 0121 { 0x756E6547, 0x49656E69, 0x6C65746E}, 0122 { 0x68747541, 0x69746E65, 0x444D4163}, 0123 { 0x746E6543, 0x48727561, 0x736C7561} 0124 }; 0125 0126 int x86cpuid_GetFirm(const Cx86cpuid *p) 0127 { 0128 unsigned i; 0129 for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) 0130 { 0131 const UInt32 *v = kVendors[i]; 0132 if (v[0] == p->vendor[0] && 0133 v[1] == p->vendor[1] && 0134 v[2] == p->vendor[2]) 0135 return (int)i; 0136 } 0137 return -1; 0138 } 0139 0140 Bool CPU_Is_InOrder() 0141 { 0142 Cx86cpuid p; 0143 int firm; 0144 UInt32 family, model; 0145 if (!x86cpuid_CheckAndRead(&p)) 0146 return True; 0147 family = x86cpuid_GetFamily(&p); 0148 model = x86cpuid_GetModel(&p); 0149 firm = x86cpuid_GetFirm(&p); 0150 switch (firm) 0151 { 0152 case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && ( 0153 /* Atom CPU */ 0154 model == 0x100C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */ 0155 || model == 0x2006 /* 45 nm, Z6xx */ 0156 || model == 0x2007 /* 32 nm, Z2460 */ 0157 || model == 0x3005 /* 32 nm, Z2760 */ 0158 || model == 0x3006 /* 32 nm, N2xxx, D2xxx */ 0159 ))); 0160 case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); 0161 case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); 0162 } 0163 return True; 0164 } 0165 0166 #if !defined(MY_CPU_AMD64) && defined(_WIN32) 0167 #include <windows.h> 0168 static Bool CPU_Sys_Is_SSE_Supported() 0169 { 0170 OSVERSIONINFO vi; 0171 vi.dwOSVersionInfoSize = sizeof(vi); 0172 if (!GetVersionEx(&vi)) 0173 return False; 0174 return (vi.dwMajorVersion >= 5); 0175 } 0176 #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; 0177 #else 0178 #define CHECK_SYS_SSE_SUPPORT 0179 #endif 0180 0181 Bool CPU_Is_Aes_Supported() 0182 { 0183 Cx86cpuid p; 0184 CHECK_SYS_SSE_SUPPORT 0185 if (!x86cpuid_CheckAndRead(&p)) 0186 return False; 0187 return (p.c >> 25) & 1; 0188 } 0189 0190 #endif