Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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