1 1,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