Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
CpuArch.c
Go to the documentation of this file.
1 /* CpuArch.c -- CPU specific code
2 2016-02-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  "%eax", "%edx");
50  #endif
51  return flag;
52 }
53 #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
54 #else
55 #define CHECK_CPUID_IS_SUPPORTED
56 #endif
57 
58 void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
59 {
60  #ifdef USE_ASM
61 
62  #ifdef _MSC_VER
63 
64  UInt32 a2, b2, c2, d2;
65  __asm xor EBX, EBX;
66  __asm xor ECX, ECX;
67  __asm xor EDX, EDX;
68  __asm mov EAX, function;
69  __asm cpuid;
70  __asm mov a2, EAX;
71  __asm mov b2, EBX;
72  __asm mov c2, ECX;
73  __asm mov d2, EDX;
74 
75  *a = a2;
76  *b = b2;
77  *c = c2;
78  *d = d2;
79 
80  #else
81 
82  __asm__ __volatile__ (
83  #if defined(MY_CPU_AMD64) && defined(__PIC__)
84  "mov %%rbx, %%rdi;"
85  "cpuid;"
86  "xchg %%rbx, %%rdi;"
87  : "=a" (*a) ,
88  "=D" (*b) ,
89  #elif defined(MY_CPU_X86) && defined(__PIC__)
90  "mov %%ebx, %%edi;"
91  "cpuid;"
92  "xchgl %%ebx, %%edi;"
93  : "=a" (*a) ,
94  "=D" (*b) ,
95  #else
96  "cpuid"
97  : "=a" (*a) ,
98  "=b" (*b) ,
99  #endif
100  "=c" (*c) ,
101  "=d" (*d)
102  : "0" (function)) ;
103 
104  #endif
105 
106  #else
107 
108  int CPUInfo[4];
109  __cpuid(CPUInfo, function);
110  *a = CPUInfo[0];
111  *b = CPUInfo[1];
112  *c = CPUInfo[2];
113  *d = CPUInfo[3];
114 
115  #endif
116 }
117 
118 Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
119 {
120  CHECK_CPUID_IS_SUPPORTED
121  MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
122  MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
123  return True;
124 }
125 
126 static const UInt32 kVendors[][3] =
127 {
128  { 0x756E6547, 0x49656E69, 0x6C65746E},
129  { 0x68747541, 0x69746E65, 0x444D4163},
130  { 0x746E6543, 0x48727561, 0x736C7561}
131 };
132 
133 int x86cpuid_GetFirm(const Cx86cpuid *p)
134 {
135  unsigned i;
136  for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
137  {
138  const UInt32 *v = kVendors[i];
139  if (v[0] == p->vendor[0] &&
140  v[1] == p->vendor[1] &&
141  v[2] == p->vendor[2])
142  return (int)i;
143  }
144  return -1;
145 }
146 
147 Bool CPU_Is_InOrder(void)
148 {
149  Cx86cpuid p;
150  int firm;
151  UInt32 family, model;
152  if (!x86cpuid_CheckAndRead(&p))
153  return True;
154 
155  family = x86cpuid_GetFamily(p.ver);
156  model = x86cpuid_GetModel(p.ver);
157 
158  firm = x86cpuid_GetFirm(&p);
159 
160  switch (firm)
161  {
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  )));
170  case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
171  case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
172  }
173  return True;
174 }
175 
176 #if !defined(MY_CPU_AMD64) && defined(_WIN32)
177 #include <windows.h>
178 static Bool CPU_Sys_Is_SSE_Supported()
179 {
180  OSVERSIONINFO vi;
181  vi.dwOSVersionInfoSize = sizeof(vi);
182  if (!GetVersionEx(&vi))
183  return False;
184  return (vi.dwMajorVersion >= 5);
185 }
186 #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
187 #else
188 #define CHECK_SYS_SSE_SUPPORT
189 #endif
190 
191 Bool CPU_Is_Aes_Supported(void)
192 {
193  Cx86cpuid p;
194  CHECK_SYS_SSE_SUPPORT
195  if (!x86cpuid_CheckAndRead(&p))
196  return False;
197  return (p.c >> 25) & 1;
198 }
199 
200 #endif