11,168c1,187 2< /* CpuArch.c -- CPU specific code 3< 2010-10-26: Igor Pavlov : Public domain */ 4< 5< #include "CpuArch.h" 6< 7< #ifdef MY_CPU_X86_OR_AMD64 8< 9< #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) 10< #define USE_ASM 11< #endif 12< 13< #if defined(USE_ASM) && !defined(MY_CPU_AMD64) 14< static UInt32 CheckFlag(UInt32 flag) 15< { 16< #ifdef _MSC_VER 17< __asm pushfd; 18< __asm pop EAX; 19< __asm mov EDX, EAX; 20< __asm xor EAX, flag; 21< __asm push EAX; 22< __asm popfd; 23< __asm pushfd; 24< __asm pop EAX; 25< __asm xor EAX, EDX; 26< __asm push EDX; 27< __asm popfd; 28< __asm and flag, EAX; 29< #else 30< __asm__ __volatile__ ( 31< "pushf\n\t" 32< "pop %%EAX\n\t" 33< "movl %%EAX,%%EDX\n\t" 34< "xorl %0,%%EAX\n\t" 35< "push %%EAX\n\t" 36< "popf\n\t" 37< "pushf\n\t" 38< "pop %%EAX\n\t" 39< "xorl %%EDX,%%EAX\n\t" 40< "push %%EDX\n\t" 41< "popf\n\t" 42< "andl %%EAX, %0\n\t": 43< "=c" (flag) : "c" (flag)); 44< #endif 45< return flag; 46< } 47< #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; 48< #else 49< #define CHECK_CPUID_IS_SUPPORTED 50< #endif 51< 52< static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) 53< { 54< #ifdef USE_ASM 55< 56< #ifdef _MSC_VER 57< 58< UInt32 a2, b2, c2, d2; 59< __asm xor EBX, EBX; 60< __asm xor ECX, ECX; 61< __asm xor EDX, EDX; 62< __asm mov EAX, function; 63< __asm cpuid; 64< __asm mov a2, EAX; 65< __asm mov b2, EBX; 66< __asm mov c2, ECX; 67< __asm mov d2, EDX; 68< 69< *a = a2; 70< *b = b2; 71< *c = c2; 72< *d = d2; 73< 74< #else 75< 76< __asm__ __volatile__ ( 77< "cpuid" 78< : "=a" (*a) , 79< "=b" (*b) , 80< "=c" (*c) , 81< "=d" (*d) 82< : "0" (function)) ; 83< 84< #endif 85< 86< #else 87< 88< int CPUInfo[4]; 89< __cpuid(CPUInfo, function); 90< *a = CPUInfo[0]; 91< *b = CPUInfo[1]; 92< *c = CPUInfo[2]; 93< *d = CPUInfo[3]; 94< 95< #endif 96< } 97< 98< Bool x86cpuid_CheckAndRead(Cx86cpuid *p) 99< { 100< CHECK_CPUID_IS_SUPPORTED 101< MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); 102< MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); 103< return True; 104< } 105< 106< static UInt32 kVendors[][3] = 107< { 108< { 0x756E6547, 0x49656E69, 0x6C65746E}, 109< { 0x68747541, 0x69746E65, 0x444D4163}, 110< { 0x746E6543, 0x48727561, 0x736C7561} 111< }; 112< 113< int x86cpuid_GetFirm(const Cx86cpuid *p) 114< { 115< unsigned i; 116< for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) 117< { 118< const UInt32 *v = kVendors[i]; 119< if (v[0] == p->vendor[0] && 120< v[1] == p->vendor[1] && 121< v[2] == p->vendor[2]) 122< return (int)i; 123< } 124< return -1; 125< } 126< 127< Bool CPU_Is_InOrder() 128< { 129< Cx86cpuid p; 130< int firm; 131< UInt32 family, model; 132< if (!x86cpuid_CheckAndRead(&p)) 133< return True; 134< family = x86cpuid_GetFamily(&p); 135< model = x86cpuid_GetModel(&p); 136< firm = x86cpuid_GetFirm(&p); 137< switch (firm) 138< { 139< case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C)); 140< case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); 141< case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); 142< } 143< return True; 144< } 145< 146< #if !defined(MY_CPU_AMD64) && defined(_WIN32) 147< static Bool CPU_Sys_Is_SSE_Supported() 148< { 149< OSVERSIONINFO vi; 150< vi.dwOSVersionInfoSize = sizeof(vi); 151< if (!GetVersionEx(&vi)) 152< return False; 153< return (vi.dwMajorVersion >= 5); 154< } 155< #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; 156< #else 157< #define CHECK_SYS_SSE_SUPPORT 158< #endif 159< 160< Bool CPU_Is_Aes_Supported() 161< { 162< Cx86cpuid p; 163< CHECK_SYS_SSE_SUPPORT 164< if (!x86cpuid_CheckAndRead(&p)) 165< return False; 166< return (p.c >> 25) & 1; 167< } 168< 169< #endif 170--- 171> /* CpuArch.c -- CPU specific code 172> 2010-10-26: Igor Pavlov : Public domain */ 173> 174> #include "CpuArch.h" 175> 176> #ifdef MY_CPU_X86_OR_AMD64 177> 178> #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) 179> #define USE_ASM 180> #endif 181> 182> #if defined(USE_ASM) && !defined(MY_CPU_AMD64) 183> static UInt32 CheckFlag(UInt32 flag) 184> { 185> #ifdef _MSC_VER 186> __asm pushfd; 187> __asm pop EAX; 188> __asm mov EDX, EAX; 189> __asm xor EAX, flag; 190> __asm push EAX; 191> __asm popfd; 192> __asm pushfd; 193> __asm pop EAX; 194> __asm xor EAX, EDX; 195> __asm push EDX; 196> __asm popfd; 197> __asm and flag, EAX; 198> #else 199> __asm__ __volatile__ ( 200> "pushf\n\t" 201> "pop %%EAX\n\t" 202> "movl %%EAX,%%EDX\n\t" 203> "xorl %0,%%EAX\n\t" 204> "push %%EAX\n\t" 205> "popf\n\t" 206> "pushf\n\t" 207> "pop %%EAX\n\t" 208> "xorl %%EDX,%%EAX\n\t" 209> "push %%EDX\n\t" 210> "popf\n\t" 211> "andl %%EAX, %0\n\t": 212> "=c" (flag) : "c" (flag): 213> "%eax", "%edx" ); 214> #endif 215> return flag; 216> } 217> #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; 218> #else 219> #define CHECK_CPUID_IS_SUPPORTED 220> #endif 221> 222> static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) 223> { 224> #ifdef USE_ASM 225> 226> #ifdef _MSC_VER 227> 228> UInt32 a2, b2, c2, d2; 229> __asm xor EBX, EBX; 230> __asm xor ECX, ECX; 231> __asm xor EDX, EDX; 232> __asm mov EAX, function; 233> __asm cpuid; 234> __asm mov a2, EAX; 235> __asm mov b2, EBX; 236> __asm mov c2, ECX; 237> __asm mov d2, EDX; 238> 239> *a = a2; 240> *b = b2; 241> *c = c2; 242> *d = d2; 243> 244> #else 245> 246> #if defined(MY_CPU_AMD64) 247> 248> __asm__ __volatile__ ( 249> "mov %%rbx, %%rdi\n" 250> "cpuid\n" 251> "xchg %%rdi, %%rbx\n" 252> : "=a" (*a) , 253> "=D" (*b) , 254> "=c" (*c) , 255> "=d" (*d) 256> : "0" (function)) ; 257> 258> #else 259> 260> __asm__ __volatile__ ( 261> "mov %%ebx, %%edi\n" 262> "cpuid\n" 263> "xchg %%edi, %%ebx\n" 264> : "=a" (*a) , 265> "=D" (*b) , 266> "=c" (*c) , 267> "=d" (*d) 268> : "0" (function)) ; 269> 270> #endif 271> 272> #endif 273> 274> #else 275> 276> int CPUInfo[4]; 277> __cpuid(CPUInfo, function); 278> *a = CPUInfo[0]; 279> *b = CPUInfo[1]; 280> *c = CPUInfo[2]; 281> *d = CPUInfo[3]; 282> 283> #endif 284> } 285> 286> Bool x86cpuid_CheckAndRead(Cx86cpuid *p) 287> { 288> CHECK_CPUID_IS_SUPPORTED 289> MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); 290> MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); 291> return True; 292> } 293> 294> static UInt32 kVendors[][3] = 295> { 296> { 0x756E6547, 0x49656E69, 0x6C65746E}, 297> { 0x68747541, 0x69746E65, 0x444D4163}, 298> { 0x746E6543, 0x48727561, 0x736C7561} 299> }; 300> 301> int x86cpuid_GetFirm(const Cx86cpuid *p) 302> { 303> unsigned i; 304> for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) 305> { 306> const UInt32 *v = kVendors[i]; 307> if (v[0] == p->vendor[0] && 308> v[1] == p->vendor[1] && 309> v[2] == p->vendor[2]) 310> return (int)i; 311> } 312> return -1; 313> } 314> 315> Bool CPU_Is_InOrder() 316> { 317> Cx86cpuid p; 318> int firm; 319> UInt32 family, model; 320> if (!x86cpuid_CheckAndRead(&p)) 321> return True; 322> family = x86cpuid_GetFamily(&p); 323> model = x86cpuid_GetModel(&p); 324> firm = x86cpuid_GetFirm(&p); 325> switch (firm) 326> { 327> case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C)); 328> case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); 329> case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); 330> } 331> return True; 332> } 333> 334> #if !defined(MY_CPU_AMD64) && defined(_WIN32) 335> static Bool CPU_Sys_Is_SSE_Supported() 336> { 337> OSVERSIONINFO vi; 338> vi.dwOSVersionInfoSize = sizeof(vi); 339> if (!GetVersionEx(&vi)) 340> return False; 341> return (vi.dwMajorVersion >= 5); 342> } 343> #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; 344> #else 345> #define CHECK_SYS_SSE_SUPPORT 346> #endif 347> 348> Bool CPU_Is_Aes_Supported() 349> { 350> Cx86cpuid p; 351> CHECK_SYS_SSE_SUPPORT 352> if (!x86cpuid_CheckAndRead(&p)) 353> return False; 354> return (p.c >> 25) & 1; 355> } 356> 357> #endif 358