doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
win_cpu.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "win_local.h"
33 
34 
35 /*
36 ==============================================================
37 
38  Clock ticks
39 
40 ==============================================================
41 */
42 
43 /*
44 ================
45 Sys_GetClockTicks
46 ================
47 */
48 double Sys_GetClockTicks( void ) {
49 #if 0
50 
51  LARGE_INTEGER li;
52 
53  QueryPerformanceCounter( &li );
54  return = (double ) li.LowPart + (double) 0xFFFFFFFF * li.HighPart;
55 
56 #else
57 
58  unsigned long lo, hi;
59 
60  __asm {
61  push ebx
62  xor eax, eax
63  cpuid
64  rdtsc
65  mov lo, eax
66  mov hi, edx
67  pop ebx
68  }
69  return (double ) lo + (double) 0xFFFFFFFF * hi;
70 
71 #endif
72 }
73 
74 /*
75 ================
76 Sys_ClockTicksPerSecond
77 ================
78 */
79 double Sys_ClockTicksPerSecond( void ) {
80  static double ticks = 0;
81 #if 0
82 
83  if ( !ticks ) {
84  LARGE_INTEGER li;
85  QueryPerformanceFrequency( &li );
86  ticks = li.QuadPart;
87  }
88 
89 #else
90 
91  if ( !ticks ) {
92  HKEY hKey;
93  LPBYTE ProcSpeed;
94  DWORD buflen, ret;
95 
96  if ( !RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey ) ) {
97  ProcSpeed = 0;
98  buflen = sizeof( ProcSpeed );
99  ret = RegQueryValueEx( hKey, "~MHz", NULL, NULL, (LPBYTE) &ProcSpeed, &buflen );
100  // If we don't succeed, try some other spellings.
101  if ( ret != ERROR_SUCCESS ) {
102  ret = RegQueryValueEx( hKey, "~Mhz", NULL, NULL, (LPBYTE) &ProcSpeed, &buflen );
103  }
104  if ( ret != ERROR_SUCCESS ) {
105  ret = RegQueryValueEx( hKey, "~mhz", NULL, NULL, (LPBYTE) &ProcSpeed, &buflen );
106  }
107  RegCloseKey( hKey );
108  if ( ret == ERROR_SUCCESS ) {
109  ticks = (double) ((unsigned long)ProcSpeed) * 1000000;
110  }
111  }
112  }
113 
114 #endif
115  return ticks;
116 }
117 
118 
119 /*
120 ==============================================================
121 
122  CPU
123 
124 ==============================================================
125 */
126 
127 /*
128 ================
129 HasCPUID
130 ================
131 */
132 static bool HasCPUID( void ) {
133  __asm
134  {
135  pushfd // save eflags
136  pop eax
137  test eax, 0x00200000 // check ID bit
138  jz set21 // bit 21 is not set, so jump to set_21
139  and eax, 0xffdfffff // clear bit 21
140  push eax // save new value in register
141  popfd // store new value in flags
142  pushfd
143  pop eax
144  test eax, 0x00200000 // check ID bit
145  jz good
146  jmp err // cpuid not supported
147 set21:
148  or eax, 0x00200000 // set ID bit
149  push eax // store new value
150  popfd // store new value in EFLAGS
151  pushfd
152  pop eax
153  test eax, 0x00200000 // if bit 21 is on
154  jnz good
155  jmp err
156  }
157 
158 err:
159  return false;
160 good:
161  return true;
162 }
163 
164 #define _REG_EAX 0
165 #define _REG_EBX 1
166 #define _REG_ECX 2
167 #define _REG_EDX 3
168 
169 /*
170 ================
171 CPUID
172 ================
173 */
174 static void CPUID( int func, unsigned regs[4] ) {
175  unsigned regEAX, regEBX, regECX, regEDX;
176 
177  __asm pusha
178  __asm mov eax, func
179  __asm __emit 00fh
180  __asm __emit 0a2h
181  __asm mov regEAX, eax
182  __asm mov regEBX, ebx
183  __asm mov regECX, ecx
184  __asm mov regEDX, edx
185  __asm popa
186 
187  regs[_REG_EAX] = regEAX;
188  regs[_REG_EBX] = regEBX;
189  regs[_REG_ECX] = regECX;
190  regs[_REG_EDX] = regEDX;
191 }
192 
193 
194 /*
195 ================
196 IsAMD
197 ================
198 */
199 static bool IsAMD( void ) {
200  char pstring[16];
201  char processorString[13];
202 
203  // get name of processor
204  CPUID( 0, ( unsigned int * ) pstring );
205  processorString[0] = pstring[4];
206  processorString[1] = pstring[5];
207  processorString[2] = pstring[6];
208  processorString[3] = pstring[7];
209  processorString[4] = pstring[12];
210  processorString[5] = pstring[13];
211  processorString[6] = pstring[14];
212  processorString[7] = pstring[15];
213  processorString[8] = pstring[8];
214  processorString[9] = pstring[9];
215  processorString[10] = pstring[10];
216  processorString[11] = pstring[11];
217  processorString[12] = 0;
218 
219  if ( strcmp( processorString, "AuthenticAMD" ) == 0 ) {
220  return true;
221  }
222  return false;
223 }
224 
225 /*
226 ================
227 HasCMOV
228 ================
229 */
230 static bool HasCMOV( void ) {
231  unsigned regs[4];
232 
233  // get CPU feature bits
234  CPUID( 1, regs );
235 
236  // bit 15 of EDX denotes CMOV existence
237  if ( regs[_REG_EDX] & ( 1 << 15 ) ) {
238  return true;
239  }
240  return false;
241 }
242 
243 /*
244 ================
245 Has3DNow
246 ================
247 */
248 static bool Has3DNow( void ) {
249  unsigned regs[4];
250 
251  // check AMD-specific functions
252  CPUID( 0x80000000, regs );
253  if ( regs[_REG_EAX] < 0x80000000 ) {
254  return false;
255  }
256 
257  // bit 31 of EDX denotes 3DNow! support
258  CPUID( 0x80000001, regs );
259  if ( regs[_REG_EDX] & ( 1 << 31 ) ) {
260  return true;
261  }
262 
263  return false;
264 }
265 
266 /*
267 ================
268 HasMMX
269 ================
270 */
271 static bool HasMMX( void ) {
272  unsigned regs[4];
273 
274  // get CPU feature bits
275  CPUID( 1, regs );
276 
277  // bit 23 of EDX denotes MMX existence
278  if ( regs[_REG_EDX] & ( 1 << 23 ) ) {
279  return true;
280  }
281  return false;
282 }
283 
284 /*
285 ================
286 HasSSE
287 ================
288 */
289 static bool HasSSE( void ) {
290  unsigned regs[4];
291 
292  // get CPU feature bits
293  CPUID( 1, regs );
294 
295  // bit 25 of EDX denotes SSE existence
296  if ( regs[_REG_EDX] & ( 1 << 25 ) ) {
297  return true;
298  }
299  return false;
300 }
301 
302 /*
303 ================
304 HasSSE2
305 ================
306 */
307 static bool HasSSE2( void ) {
308  unsigned regs[4];
309 
310  // get CPU feature bits
311  CPUID( 1, regs );
312 
313  // bit 26 of EDX denotes SSE2 existence
314  if ( regs[_REG_EDX] & ( 1 << 26 ) ) {
315  return true;
316  }
317  return false;
318 }
319 
320 /*
321 ================
322 HasSSE3
323 ================
324 */
325 static bool HasSSE3( void ) {
326  unsigned regs[4];
327 
328  // get CPU feature bits
329  CPUID( 1, regs );
330 
331  // bit 0 of ECX denotes SSE3 existence
332  if ( regs[_REG_ECX] & ( 1 << 0 ) ) {
333  return true;
334  }
335  return false;
336 }
337 
338 /*
339 ================
340 LogicalProcPerPhysicalProc
341 ================
342 */
343 #define NUM_LOGICAL_BITS 0x00FF0000 // EBX[23:16] Bit 16-23 in ebx contains the number of logical
344  // processors per physical processor when execute cpuid with
345  // eax set to 1
346 static unsigned char LogicalProcPerPhysicalProc( void ) {
347  unsigned int regebx = 0;
348  __asm {
349  mov eax, 1
350  cpuid
351  mov regebx, ebx
352  }
353  return (unsigned char) ((regebx & NUM_LOGICAL_BITS) >> 16);
354 }
355 
356 /*
357 ================
358 GetAPIC_ID
359 ================
360 */
361 #define INITIAL_APIC_ID_BITS 0xFF000000 // EBX[31:24] Bits 24-31 (8 bits) return the 8-bit unique
362  // initial APIC ID for the processor this code is running on.
363  // Default value = 0xff if HT is not supported
364 static unsigned char GetAPIC_ID( void ) {
365  unsigned int regebx = 0;
366  __asm {
367  mov eax, 1
368  cpuid
369  mov regebx, ebx
370  }
371  return (unsigned char) ((regebx & INITIAL_APIC_ID_BITS) >> 24);
372 }
373 
374 /*
375 ================
376 CPUCount
377 
378  logicalNum is the number of logical CPU per physical CPU
379  physicalNum is the total number of physical processor
380  returns one of the HT_* flags
381 ================
382 */
383 #define HT_NOT_CAPABLE 0
384 #define HT_ENABLED 1
385 #define HT_DISABLED 2
386 #define HT_SUPPORTED_NOT_ENABLED 3
387 #define HT_CANNOT_DETECT 4
388 
389 int CPUCount( int &logicalNum, int &physicalNum ) {
390  int statusFlag;
391  SYSTEM_INFO info;
392 
393  physicalNum = 1;
394  logicalNum = 1;
395  statusFlag = HT_NOT_CAPABLE;
396 
397  info.dwNumberOfProcessors = 0;
398  GetSystemInfo (&info);
399 
400  // Number of physical processors in a non-Intel system
401  // or in a 32-bit Intel system with Hyper-Threading technology disabled
402  physicalNum = info.dwNumberOfProcessors;
403 
404  unsigned char HT_Enabled = 0;
405 
406  logicalNum = LogicalProcPerPhysicalProc();
407 
408  if ( logicalNum >= 1 ) { // > 1 doesn't mean HT is enabled in the BIOS
409  HANDLE hCurrentProcessHandle;
410  DWORD dwProcessAffinity;
411  DWORD dwSystemAffinity;
412  DWORD dwAffinityMask;
413 
414  // Calculate the appropriate shifts and mask based on the
415  // number of logical processors.
416 
417  unsigned char i = 1, PHY_ID_MASK = 0xFF, PHY_ID_SHIFT = 0;
418 
419  while( i < logicalNum ) {
420  i *= 2;
421  PHY_ID_MASK <<= 1;
422  PHY_ID_SHIFT++;
423  }
424 
425  hCurrentProcessHandle = GetCurrentProcess();
426  GetProcessAffinityMask( hCurrentProcessHandle, &dwProcessAffinity, &dwSystemAffinity );
427 
428  // Check if available process affinity mask is equal to the
429  // available system affinity mask
430  if ( dwProcessAffinity != dwSystemAffinity ) {
431  statusFlag = HT_CANNOT_DETECT;
432  physicalNum = -1;
433  return statusFlag;
434  }
435 
436  dwAffinityMask = 1;
437  while ( dwAffinityMask != 0 && dwAffinityMask <= dwProcessAffinity ) {
438  // Check if this CPU is available
439  if ( dwAffinityMask & dwProcessAffinity ) {
440  if ( SetProcessAffinityMask( hCurrentProcessHandle, dwAffinityMask ) ) {
441  unsigned char APIC_ID, LOG_ID, PHY_ID;
442 
443  Sleep( 0 ); // Give OS time to switch CPU
444 
445  APIC_ID = GetAPIC_ID();
446  LOG_ID = APIC_ID & ~PHY_ID_MASK;
447  PHY_ID = APIC_ID >> PHY_ID_SHIFT;
448 
449  if ( LOG_ID != 0 ) {
450  HT_Enabled = 1;
451  }
452  }
453  }
454  dwAffinityMask = dwAffinityMask << 1;
455  }
456 
457  // Reset the processor affinity
458  SetProcessAffinityMask( hCurrentProcessHandle, dwProcessAffinity );
459 
460  if ( logicalNum == 1 ) { // Normal P4 : HT is disabled in hardware
461  statusFlag = HT_DISABLED;
462  } else {
463  if ( HT_Enabled ) {
464  // Total physical processors in a Hyper-Threading enabled system.
465  physicalNum /= logicalNum;
466  statusFlag = HT_ENABLED;
467  } else {
468  statusFlag = HT_SUPPORTED_NOT_ENABLED;
469  }
470  }
471  }
472  return statusFlag;
473 }
474 
475 /*
476 ================
477 HasHTT
478 ================
479 */
480 static bool HasHTT( void ) {
481  unsigned regs[4];
482  int logicalNum, physicalNum, HTStatusFlag;
483 
484  // get CPU feature bits
485  CPUID( 1, regs );
486 
487  // bit 28 of EDX denotes HTT existence
488  if ( !( regs[_REG_EDX] & ( 1 << 28 ) ) ) {
489  return false;
490  }
491 
492  HTStatusFlag = CPUCount( logicalNum, physicalNum );
493  if ( HTStatusFlag != HT_ENABLED ) {
494  return false;
495  }
496  return true;
497 }
498 
499 /*
500 ================
501 HasHTT
502 ================
503 */
504 static bool HasDAZ( void ) {
505  __declspec(align(16)) unsigned char FXSaveArea[512];
506  unsigned char *FXArea = FXSaveArea;
507  DWORD dwMask = 0;
508  unsigned regs[4];
509 
510  // get CPU feature bits
511  CPUID( 1, regs );
512 
513  // bit 24 of EDX denotes support for FXSAVE
514  if ( !( regs[_REG_EDX] & ( 1 << 24 ) ) ) {
515  return false;
516  }
517 
518  memset( FXArea, 0, sizeof( FXSaveArea ) );
519 
520  __asm {
521  mov eax, FXArea
522  FXSAVE [eax]
523  }
524 
525  dwMask = *(DWORD *)&FXArea[28]; // Read the MXCSR Mask
526  return ( ( dwMask & ( 1 << 6 ) ) == ( 1 << 6 ) ); // Return if the DAZ bit is set
527 }
528 
529 /*
530 ================
531 Sys_GetCPUId
532 ================
533 */
535  int flags;
536 
537  // verify we're at least a Pentium or 486 with CPUID support
538  if ( !HasCPUID() ) {
539  return CPUID_UNSUPPORTED;
540  }
541 
542  // check for an AMD
543  if ( IsAMD() ) {
544  flags = CPUID_AMD;
545  } else {
546  flags = CPUID_INTEL;
547  }
548 
549  // check for Multi Media Extensions
550  if ( HasMMX() ) {
551  flags |= CPUID_MMX;
552  }
553 
554  // check for 3DNow!
555  if ( Has3DNow() ) {
556  flags |= CPUID_3DNOW;
557  }
558 
559  // check for Streaming SIMD Extensions
560  if ( HasSSE() ) {
561  flags |= CPUID_SSE | CPUID_FTZ;
562  }
563 
564  // check for Streaming SIMD Extensions 2
565  if ( HasSSE2() ) {
566  flags |= CPUID_SSE2;
567  }
568 
569  // check for Streaming SIMD Extensions 3 aka Prescott's New Instructions
570  if ( HasSSE3() ) {
571  flags |= CPUID_SSE3;
572  }
573 
574  // check for Hyper-Threading Technology
575  if ( HasHTT() ) {
576  flags |= CPUID_HTT;
577  }
578 
579  // check for Conditional Move (CMOV) and fast floating point comparison (FCOMI) instructions
580  if ( HasCMOV() ) {
581  flags |= CPUID_CMOV;
582  }
583 
584  // check for Denormals-Are-Zero mode
585  if ( HasDAZ() ) {
586  flags |= CPUID_DAZ;
587  }
588 
589  return (cpuid_t)flags;
590 }
591 
592 
593 /*
594 ===============================================================================
595 
596  FPU
597 
598 ===============================================================================
599 */
600 
601 typedef struct bitFlag_s {
602  char * name;
603  int bit;
604 } bitFlag_t;
605 
606 static byte fpuState[128], *statePtr = fpuState;
607 static char fpuString[2048];
608 static bitFlag_t controlWordFlags[] = {
609  { "Invalid operation", 0 },
610  { "Denormalized operand", 1 },
611  { "Divide-by-zero", 2 },
612  { "Numeric overflow", 3 },
613  { "Numeric underflow", 4 },
614  { "Inexact result (precision)", 5 },
615  { "Infinity control", 12 },
616  { "", 0 }
617 };
618 static char *precisionControlField[] = {
619  "Single Precision (24-bits)",
620  "Reserved",
621  "Double Precision (53-bits)",
622  "Double Extended Precision (64-bits)"
623 };
624 static char *roundingControlField[] = {
625  "Round to nearest",
626  "Round down",
627  "Round up",
628  "Round toward zero"
629 };
630 static bitFlag_t statusWordFlags[] = {
631  { "Invalid operation", 0 },
632  { "Denormalized operand", 1 },
633  { "Divide-by-zero", 2 },
634  { "Numeric overflow", 3 },
635  { "Numeric underflow", 4 },
636  { "Inexact result (precision)", 5 },
637  { "Stack fault", 6 },
638  { "Error summary status", 7 },
639  { "FPU busy", 15 },
640  { "", 0 }
641 };
642 
643 /*
644 ===============
645 Sys_FPU_PrintStateFlags
646 ===============
647 */
648 int Sys_FPU_PrintStateFlags( char *ptr, int ctrl, int stat, int tags, int inof, int inse, int opof, int opse ) {
649  int i, length = 0;
650 
651  length += sprintf( ptr+length, "CTRL = %08x\n"
652  "STAT = %08x\n"
653  "TAGS = %08x\n"
654  "INOF = %08x\n"
655  "INSE = %08x\n"
656  "OPOF = %08x\n"
657  "OPSE = %08x\n"
658  "\n",
659  ctrl, stat, tags, inof, inse, opof, opse );
660 
661  length += sprintf( ptr+length, "Control Word:\n" );
662  for ( i = 0; controlWordFlags[i].name[0]; i++ ) {
663  length += sprintf( ptr+length, " %-30s = %s\n", controlWordFlags[i].name, ( ctrl & ( 1 << controlWordFlags[i].bit ) ) ? "true" : "false" );
664  }
665  length += sprintf( ptr+length, " %-30s = %s\n", "Precision control", precisionControlField[(ctrl>>8)&3] );
666  length += sprintf( ptr+length, " %-30s = %s\n", "Rounding control", roundingControlField[(ctrl>>10)&3] );
667 
668  length += sprintf( ptr+length, "Status Word:\n" );
669  for ( i = 0; statusWordFlags[i].name[0]; i++ ) {
670  ptr += sprintf( ptr+length, " %-30s = %s\n", statusWordFlags[i].name, ( stat & ( 1 << statusWordFlags[i].bit ) ) ? "true" : "false" );
671  }
672  length += sprintf( ptr+length, " %-30s = %d%d%d%d\n", "Condition code", (stat>>8)&1, (stat>>9)&1, (stat>>10)&1, (stat>>14)&1 );
673  length += sprintf( ptr+length, " %-30s = %d\n", "Top of stack pointer", (stat>>11)&7 );
674 
675  return length;
676 }
677 
678 /*
679 ===============
680 Sys_FPU_StackIsEmpty
681 ===============
682 */
683 bool Sys_FPU_StackIsEmpty( void ) {
684  __asm {
685  mov eax, statePtr
686  fnstenv [eax]
687  mov eax, [eax+8]
688  xor eax, 0xFFFFFFFF
689  and eax, 0x0000FFFF
690  jz empty
691  }
692  return false;
693 empty:
694  return true;
695 }
696 
697 /*
698 ===============
699 Sys_FPU_ClearStack
700 ===============
701 */
702 void Sys_FPU_ClearStack( void ) {
703  __asm {
704  mov eax, statePtr
705  fnstenv [eax]
706  mov eax, [eax+8]
707  xor eax, 0xFFFFFFFF
708  mov edx, (3<<14)
709  emptyStack:
710  mov ecx, eax
711  and ecx, edx
712  jz done
713  fstp st
714  shr edx, 2
715  jmp emptyStack
716  done:
717  }
718 }
719 
720 /*
721 ===============
722 Sys_FPU_GetState
723 
724  gets the FPU state without changing the state
725 ===============
726 */
727 const char *Sys_FPU_GetState( void ) {
728  double fpuStack[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
729  double *fpuStackPtr = fpuStack;
730  int i, numValues;
731  char *ptr;
732 
733  __asm {
734  mov esi, statePtr
735  mov edi, fpuStackPtr
736  fnstenv [esi]
737  mov esi, [esi+8]
738  xor esi, 0xFFFFFFFF
739  mov edx, (3<<14)
740  xor eax, eax
741  mov ecx, esi
742  and ecx, edx
743  jz done
744  fst qword ptr [edi+0]
745  inc eax
746  shr edx, 2
747  mov ecx, esi
748  and ecx, edx
749  jz done
750  fxch st(1)
751  fst qword ptr [edi+8]
752  inc eax
753  fxch st(1)
754  shr edx, 2
755  mov ecx, esi
756  and ecx, edx
757  jz done
758  fxch st(2)
759  fst qword ptr [edi+16]
760  inc eax
761  fxch st(2)
762  shr edx, 2
763  mov ecx, esi
764  and ecx, edx
765  jz done
766  fxch st(3)
767  fst qword ptr [edi+24]
768  inc eax
769  fxch st(3)
770  shr edx, 2
771  mov ecx, esi
772  and ecx, edx
773  jz done
774  fxch st(4)
775  fst qword ptr [edi+32]
776  inc eax
777  fxch st(4)
778  shr edx, 2
779  mov ecx, esi
780  and ecx, edx
781  jz done
782  fxch st(5)
783  fst qword ptr [edi+40]
784  inc eax
785  fxch st(5)
786  shr edx, 2
787  mov ecx, esi
788  and ecx, edx
789  jz done
790  fxch st(6)
791  fst qword ptr [edi+48]
792  inc eax
793  fxch st(6)
794  shr edx, 2
795  mov ecx, esi
796  and ecx, edx
797  jz done
798  fxch st(7)
799  fst qword ptr [edi+56]
800  inc eax
801  fxch st(7)
802  done:
803  mov numValues, eax
804  }
805 
806  int ctrl = *(int *)&fpuState[0];
807  int stat = *(int *)&fpuState[4];
808  int tags = *(int *)&fpuState[8];
809  int inof = *(int *)&fpuState[12];
810  int inse = *(int *)&fpuState[16];
811  int opof = *(int *)&fpuState[20];
812  int opse = *(int *)&fpuState[24];
813 
814  ptr = fpuString;
815  ptr += sprintf( ptr,"FPU State:\n"
816  "num values on stack = %d\n", numValues );
817  for ( i = 0; i < 8; i++ ) {
818  ptr += sprintf( ptr, "ST%d = %1.10e\n", i, fpuStack[i] );
819  }
820 
821  Sys_FPU_PrintStateFlags( ptr, ctrl, stat, tags, inof, inse, opof, opse );
822 
823  return fpuString;
824 }
825 
826 /*
827 ===============
828 Sys_FPU_EnableExceptions
829 ===============
830 */
831 void Sys_FPU_EnableExceptions( int exceptions ) {
832  __asm {
833  mov eax, statePtr
834  mov ecx, exceptions
835  and cx, 63
836  not cx
837  fnstcw word ptr [eax]
838  mov bx, word ptr [eax]
839  or bx, 63
840  and bx, cx
841  mov word ptr [eax], bx
842  fldcw word ptr [eax]
843  }
844 }
845 
846 /*
847 ===============
848 Sys_FPU_SetPrecision
849 ===============
850 */
851 void Sys_FPU_SetPrecision( int precision ) {
852  short precisionBitTable[4] = { 0, 1, 3, 0 };
853  short precisionBits = precisionBitTable[precision & 3] << 8;
854  short precisionMask = ~( ( 1 << 9 ) | ( 1 << 8 ) );
855 
856  __asm {
857  mov eax, statePtr
858  mov cx, precisionBits
859  fnstcw word ptr [eax]
860  mov bx, word ptr [eax]
861  and bx, precisionMask
862  or bx, cx
863  mov word ptr [eax], bx
864  fldcw word ptr [eax]
865  }
866 }
867 
868 /*
869 ================
870 Sys_FPU_SetRounding
871 ================
872 */
873 void Sys_FPU_SetRounding( int rounding ) {
874  short roundingBitTable[4] = { 0, 1, 2, 3 };
875  short roundingBits = roundingBitTable[rounding & 3] << 10;
876  short roundingMask = ~( ( 1 << 11 ) | ( 1 << 10 ) );
877 
878  __asm {
879  mov eax, statePtr
880  mov cx, roundingBits
881  fnstcw word ptr [eax]
882  mov bx, word ptr [eax]
883  and bx, roundingMask
884  or bx, cx
885  mov word ptr [eax], bx
886  fldcw word ptr [eax]
887  }
888 }
889 
890 /*
891 ================
892 Sys_FPU_SetDAZ
893 ================
894 */
895 void Sys_FPU_SetDAZ( bool enable ) {
896  DWORD dwData;
897 
898  _asm {
899  movzx ecx, byte ptr enable
900  and ecx, 1
901  shl ecx, 6
902  STMXCSR dword ptr dwData
903  mov eax, dwData
904  and eax, ~(1<<6) // clear DAX bit
905  or eax, ecx // set the DAZ bit
906  mov dwData, eax
907  LDMXCSR dword ptr dwData
908  }
909 }
910 
911 /*
912 ================
913 Sys_FPU_SetFTZ
914 ================
915 */
916 void Sys_FPU_SetFTZ( bool enable ) {
917  DWORD dwData;
918 
919  _asm {
920  movzx ecx, byte ptr enable
921  and ecx, 1
922  shl ecx, 15
923  STMXCSR dword ptr dwData
924  mov eax, dwData
925  and eax, ~(1<<15) // clear FTZ bit
926  or eax, ecx // set the FTZ bit
927  mov dwData, eax
928  LDMXCSR dword ptr dwData
929  }
930 }
#define HT_DISABLED
Definition: win_cpu.cpp:385
bool Sys_FPU_StackIsEmpty(void)
Definition: win_cpu.cpp:683
#define strcmp
Definition: Str.h:41
unsigned int dword
Definition: Lib.h:77
__declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate(GUID *
DWORD
Definition: win_qgl.cpp:61
#define _REG_EDX
Definition: win_cpu.cpp:167
typedef HANDLE(WINAPI *PFNWGLCREATEBUFFERREGIONARBPROC)(HDC hDC
struct bitFlag_s bitFlag_t
int Sys_FPU_PrintStateFlags(char *ptr, int ctrl, int stat, int tags, int inof, int inse, int opof, int opse)
Definition: win_cpu.cpp:648
double Sys_GetClockTicks(void)
Definition: win_cpu.cpp:48
#define HT_NOT_CAPABLE
Definition: win_cpu.cpp:383
void Sleep(const int time)
int i
Definition: process.py:33
int test(char *url)
Definition: lib500.c:3
double Sys_ClockTicksPerSecond(void)
Definition: win_cpu.cpp:79
#define HT_ENABLED
Definition: win_cpu.cpp:384
cpuid_t Sys_GetCPUId(void)
Definition: win_cpu.cpp:534
int CPUCount(int &logicalNum, int &physicalNum)
Definition: win_cpu.cpp:389
#define NULL
Definition: Lib.h:88
cpuid_t
Definition: sys_public.h:142
#define _REG_ECX
Definition: win_cpu.cpp:166
const char * Sys_FPU_GetState(void)
Definition: win_cpu.cpp:727
#define _REG_EAX
Definition: win_cpu.cpp:164
char * name
Definition: win_cpu.cpp:602
void Sys_FPU_ClearStack(void)
Definition: win_cpu.cpp:702
void Sys_FPU_SetFTZ(bool enable)
Definition: win_cpu.cpp:916
static WindowRef ValidModeCallbackProc inCallback OSStatus err
#define INITIAL_APIC_ID_BITS
Definition: win_cpu.cpp:361
void Sys_FPU_SetDAZ(bool enable)
Definition: win_cpu.cpp:895
#define _REG_EBX
Definition: win_cpu.cpp:165
unsigned short word
Definition: Lib.h:76
unsigned char byte
Definition: Lib.h:75
const GLcharARB * name
Definition: glext.h:3629
GLfloat * st
Definition: qgl.h:89
GLsizei const GLcharARB const GLint * length
Definition: glext.h:3599
#define HT_SUPPORTED_NOT_ENABLED
Definition: win_cpu.cpp:386
void Sys_FPU_EnableExceptions(int exceptions)
Definition: win_cpu.cpp:831
#define HT_CANNOT_DETECT
Definition: win_cpu.cpp:387
#define NUM_LOGICAL_BITS
Definition: win_cpu.cpp:343
if(!ValidDisplayID(prefInfo.prefDisplayID)) prefInfo.prefDisplayID
int sprintf(idStr &string, const char *fmt,...)
Definition: Str.cpp:1528
void Sys_FPU_SetPrecision(int precision)
Definition: win_cpu.cpp:851
void Sys_FPU_SetRounding(int rounding)
Definition: win_cpu.cpp:873