123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- 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.
- 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.
- ===========================================================================
- */
- #include "../../idlib/precompiled.h"
- #pragma hdrstop
- #include "win_local.h"
- /*
- ==============================================================
- Clock ticks
- ==============================================================
- */
- /*
- ================
- Sys_GetClockTicks
- ================
- */
- double Sys_GetClockTicks( void ) {
- #if 0
- LARGE_INTEGER li;
- QueryPerformanceCounter( &li );
- return = (double ) li.LowPart + (double) 0xFFFFFFFF * li.HighPart;
- #else
- unsigned long lo, hi;
- __asm {
- push ebx
- xor eax, eax
- cpuid
- rdtsc
- mov lo, eax
- mov hi, edx
- pop ebx
- }
- return (double ) lo + (double) 0xFFFFFFFF * hi;
- #endif
- }
- /*
- ================
- Sys_ClockTicksPerSecond
- ================
- */
- double Sys_ClockTicksPerSecond( void ) {
- static double ticks = 0;
- #if 0
- if ( !ticks ) {
- LARGE_INTEGER li;
- QueryPerformanceFrequency( &li );
- ticks = li.QuadPart;
- }
- #else
- if ( !ticks ) {
- HKEY hKey;
- LPBYTE ProcSpeed;
- DWORD buflen, ret;
- if ( !RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey ) ) {
- ProcSpeed = 0;
- buflen = sizeof( ProcSpeed );
- ret = RegQueryValueEx( hKey, "~MHz", NULL, NULL, (LPBYTE) &ProcSpeed, &buflen );
- // If we don't succeed, try some other spellings.
- if ( ret != ERROR_SUCCESS ) {
- ret = RegQueryValueEx( hKey, "~Mhz", NULL, NULL, (LPBYTE) &ProcSpeed, &buflen );
- }
- if ( ret != ERROR_SUCCESS ) {
- ret = RegQueryValueEx( hKey, "~mhz", NULL, NULL, (LPBYTE) &ProcSpeed, &buflen );
- }
- RegCloseKey( hKey );
- if ( ret == ERROR_SUCCESS ) {
- ticks = (double) ((unsigned long)ProcSpeed) * 1000000;
- }
- }
- }
- #endif
- return ticks;
- }
- /*
- ==============================================================
- CPU
- ==============================================================
- */
- /*
- ================
- HasCPUID
- ================
- */
- static bool HasCPUID( void ) {
- __asm
- {
- pushfd // save eflags
- pop eax
- test eax, 0x00200000 // check ID bit
- jz set21 // bit 21 is not set, so jump to set_21
- and eax, 0xffdfffff // clear bit 21
- push eax // save new value in register
- popfd // store new value in flags
- pushfd
- pop eax
- test eax, 0x00200000 // check ID bit
- jz good
- jmp err // cpuid not supported
- set21:
- or eax, 0x00200000 // set ID bit
- push eax // store new value
- popfd // store new value in EFLAGS
- pushfd
- pop eax
- test eax, 0x00200000 // if bit 21 is on
- jnz good
- jmp err
- }
- err:
- return false;
- good:
- return true;
- }
- #define _REG_EAX 0
- #define _REG_EBX 1
- #define _REG_ECX 2
- #define _REG_EDX 3
- /*
- ================
- CPUID
- ================
- */
- static void CPUID( int func, unsigned regs[4] ) {
- unsigned regEAX, regEBX, regECX, regEDX;
- __asm pusha
- __asm mov eax, func
- __asm __emit 00fh
- __asm __emit 0a2h
- __asm mov regEAX, eax
- __asm mov regEBX, ebx
- __asm mov regECX, ecx
- __asm mov regEDX, edx
- __asm popa
- regs[_REG_EAX] = regEAX;
- regs[_REG_EBX] = regEBX;
- regs[_REG_ECX] = regECX;
- regs[_REG_EDX] = regEDX;
- }
- /*
- ================
- IsAMD
- ================
- */
- static bool IsAMD( void ) {
- char pstring[16];
- char processorString[13];
- // get name of processor
- CPUID( 0, ( unsigned int * ) pstring );
- processorString[0] = pstring[4];
- processorString[1] = pstring[5];
- processorString[2] = pstring[6];
- processorString[3] = pstring[7];
- processorString[4] = pstring[12];
- processorString[5] = pstring[13];
- processorString[6] = pstring[14];
- processorString[7] = pstring[15];
- processorString[8] = pstring[8];
- processorString[9] = pstring[9];
- processorString[10] = pstring[10];
- processorString[11] = pstring[11];
- processorString[12] = 0;
- if ( strcmp( processorString, "AuthenticAMD" ) == 0 ) {
- return true;
- }
- return false;
- }
- /*
- ================
- HasCMOV
- ================
- */
- static bool HasCMOV( void ) {
- unsigned regs[4];
- // get CPU feature bits
- CPUID( 1, regs );
- // bit 15 of EDX denotes CMOV existence
- if ( regs[_REG_EDX] & ( 1 << 15 ) ) {
- return true;
- }
- return false;
- }
- /*
- ================
- Has3DNow
- ================
- */
- static bool Has3DNow( void ) {
- unsigned regs[4];
- // check AMD-specific functions
- CPUID( 0x80000000, regs );
- if ( regs[_REG_EAX] < 0x80000000 ) {
- return false;
- }
- // bit 31 of EDX denotes 3DNow! support
- CPUID( 0x80000001, regs );
- if ( regs[_REG_EDX] & ( 1 << 31 ) ) {
- return true;
- }
- return false;
- }
- /*
- ================
- HasMMX
- ================
- */
- static bool HasMMX( void ) {
- unsigned regs[4];
- // get CPU feature bits
- CPUID( 1, regs );
- // bit 23 of EDX denotes MMX existence
- if ( regs[_REG_EDX] & ( 1 << 23 ) ) {
- return true;
- }
- return false;
- }
- /*
- ================
- HasSSE
- ================
- */
- static bool HasSSE( void ) {
- unsigned regs[4];
- // get CPU feature bits
- CPUID( 1, regs );
- // bit 25 of EDX denotes SSE existence
- if ( regs[_REG_EDX] & ( 1 << 25 ) ) {
- return true;
- }
- return false;
- }
- /*
- ================
- HasSSE2
- ================
- */
- static bool HasSSE2( void ) {
- unsigned regs[4];
- // get CPU feature bits
- CPUID( 1, regs );
- // bit 26 of EDX denotes SSE2 existence
- if ( regs[_REG_EDX] & ( 1 << 26 ) ) {
- return true;
- }
- return false;
- }
- /*
- ================
- HasSSE3
- ================
- */
- static bool HasSSE3( void ) {
- unsigned regs[4];
- // get CPU feature bits
- CPUID( 1, regs );
- // bit 0 of ECX denotes SSE3 existence
- if ( regs[_REG_ECX] & ( 1 << 0 ) ) {
- return true;
- }
- return false;
- }
- /*
- ================
- LogicalProcPerPhysicalProc
- ================
- */
- #define NUM_LOGICAL_BITS 0x00FF0000 // EBX[23:16] Bit 16-23 in ebx contains the number of logical
- // processors per physical processor when execute cpuid with
- // eax set to 1
- static unsigned char LogicalProcPerPhysicalProc( void ) {
- unsigned int regebx = 0;
- __asm {
- mov eax, 1
- cpuid
- mov regebx, ebx
- }
- return (unsigned char) ((regebx & NUM_LOGICAL_BITS) >> 16);
- }
- /*
- ================
- GetAPIC_ID
- ================
- */
- #define INITIAL_APIC_ID_BITS 0xFF000000 // EBX[31:24] Bits 24-31 (8 bits) return the 8-bit unique
- // initial APIC ID for the processor this code is running on.
- // Default value = 0xff if HT is not supported
- static unsigned char GetAPIC_ID( void ) {
- unsigned int regebx = 0;
- __asm {
- mov eax, 1
- cpuid
- mov regebx, ebx
- }
- return (unsigned char) ((regebx & INITIAL_APIC_ID_BITS) >> 24);
- }
- /*
- ================
- CPUCount
- logicalNum is the number of logical CPU per physical CPU
- physicalNum is the total number of physical processor
- returns one of the HT_* flags
- ================
- */
- #define HT_NOT_CAPABLE 0
- #define HT_ENABLED 1
- #define HT_DISABLED 2
- #define HT_SUPPORTED_NOT_ENABLED 3
- #define HT_CANNOT_DETECT 4
- int CPUCount( int &logicalNum, int &physicalNum ) {
- int statusFlag;
- SYSTEM_INFO info;
- physicalNum = 1;
- logicalNum = 1;
- statusFlag = HT_NOT_CAPABLE;
- info.dwNumberOfProcessors = 0;
- GetSystemInfo (&info);
- // Number of physical processors in a non-Intel system
- // or in a 32-bit Intel system with Hyper-Threading technology disabled
- physicalNum = info.dwNumberOfProcessors;
- unsigned char HT_Enabled = 0;
- logicalNum = LogicalProcPerPhysicalProc();
- if ( logicalNum >= 1 ) { // > 1 doesn't mean HT is enabled in the BIOS
- HANDLE hCurrentProcessHandle;
- DWORD dwProcessAffinity;
- DWORD dwSystemAffinity;
- DWORD dwAffinityMask;
- // Calculate the appropriate shifts and mask based on the
- // number of logical processors.
- unsigned char i = 1, PHY_ID_MASK = 0xFF, PHY_ID_SHIFT = 0;
- while( i < logicalNum ) {
- i *= 2;
- PHY_ID_MASK <<= 1;
- PHY_ID_SHIFT++;
- }
-
- hCurrentProcessHandle = GetCurrentProcess();
- GetProcessAffinityMask( hCurrentProcessHandle, &dwProcessAffinity, &dwSystemAffinity );
- // Check if available process affinity mask is equal to the
- // available system affinity mask
- if ( dwProcessAffinity != dwSystemAffinity ) {
- statusFlag = HT_CANNOT_DETECT;
- physicalNum = -1;
- return statusFlag;
- }
- dwAffinityMask = 1;
- while ( dwAffinityMask != 0 && dwAffinityMask <= dwProcessAffinity ) {
- // Check if this CPU is available
- if ( dwAffinityMask & dwProcessAffinity ) {
- if ( SetProcessAffinityMask( hCurrentProcessHandle, dwAffinityMask ) ) {
- unsigned char APIC_ID, LOG_ID, PHY_ID;
- Sleep( 0 ); // Give OS time to switch CPU
- APIC_ID = GetAPIC_ID();
- LOG_ID = APIC_ID & ~PHY_ID_MASK;
- PHY_ID = APIC_ID >> PHY_ID_SHIFT;
- if ( LOG_ID != 0 ) {
- HT_Enabled = 1;
- }
- }
- }
- dwAffinityMask = dwAffinityMask << 1;
- }
-
- // Reset the processor affinity
- SetProcessAffinityMask( hCurrentProcessHandle, dwProcessAffinity );
-
- if ( logicalNum == 1 ) { // Normal P4 : HT is disabled in hardware
- statusFlag = HT_DISABLED;
- } else {
- if ( HT_Enabled ) {
- // Total physical processors in a Hyper-Threading enabled system.
- physicalNum /= logicalNum;
- statusFlag = HT_ENABLED;
- } else {
- statusFlag = HT_SUPPORTED_NOT_ENABLED;
- }
- }
- }
- return statusFlag;
- }
- /*
- ================
- HasHTT
- ================
- */
- static bool HasHTT( void ) {
- unsigned regs[4];
- int logicalNum, physicalNum, HTStatusFlag;
- // get CPU feature bits
- CPUID( 1, regs );
- // bit 28 of EDX denotes HTT existence
- if ( !( regs[_REG_EDX] & ( 1 << 28 ) ) ) {
- return false;
- }
- HTStatusFlag = CPUCount( logicalNum, physicalNum );
- if ( HTStatusFlag != HT_ENABLED ) {
- return false;
- }
- return true;
- }
- /*
- ================
- HasHTT
- ================
- */
- static bool HasDAZ( void ) {
- __declspec(align(16)) unsigned char FXSaveArea[512];
- unsigned char *FXArea = FXSaveArea;
- DWORD dwMask = 0;
- unsigned regs[4];
- // get CPU feature bits
- CPUID( 1, regs );
- // bit 24 of EDX denotes support for FXSAVE
- if ( !( regs[_REG_EDX] & ( 1 << 24 ) ) ) {
- return false;
- }
- memset( FXArea, 0, sizeof( FXSaveArea ) );
- __asm {
- mov eax, FXArea
- FXSAVE [eax]
- }
- dwMask = *(DWORD *)&FXArea[28]; // Read the MXCSR Mask
- return ( ( dwMask & ( 1 << 6 ) ) == ( 1 << 6 ) ); // Return if the DAZ bit is set
- }
- /*
- ================
- Sys_GetCPUId
- ================
- */
- cpuid_t Sys_GetCPUId( void ) {
- int flags;
- // verify we're at least a Pentium or 486 with CPUID support
- if ( !HasCPUID() ) {
- return CPUID_UNSUPPORTED;
- }
- // check for an AMD
- if ( IsAMD() ) {
- flags = CPUID_AMD;
- } else {
- flags = CPUID_INTEL;
- }
- // check for Multi Media Extensions
- if ( HasMMX() ) {
- flags |= CPUID_MMX;
- }
- // check for 3DNow!
- if ( Has3DNow() ) {
- flags |= CPUID_3DNOW;
- }
- // check for Streaming SIMD Extensions
- if ( HasSSE() ) {
- flags |= CPUID_SSE | CPUID_FTZ;
- }
- // check for Streaming SIMD Extensions 2
- if ( HasSSE2() ) {
- flags |= CPUID_SSE2;
- }
- // check for Streaming SIMD Extensions 3 aka Prescott's New Instructions
- if ( HasSSE3() ) {
- flags |= CPUID_SSE3;
- }
- // check for Hyper-Threading Technology
- if ( HasHTT() ) {
- flags |= CPUID_HTT;
- }
- // check for Conditional Move (CMOV) and fast floating point comparison (FCOMI) instructions
- if ( HasCMOV() ) {
- flags |= CPUID_CMOV;
- }
- // check for Denormals-Are-Zero mode
- if ( HasDAZ() ) {
- flags |= CPUID_DAZ;
- }
- return (cpuid_t)flags;
- }
- /*
- ===============================================================================
- FPU
- ===============================================================================
- */
- typedef struct bitFlag_s {
- char * name;
- int bit;
- } bitFlag_t;
- static byte fpuState[128], *statePtr = fpuState;
- static char fpuString[2048];
- static bitFlag_t controlWordFlags[] = {
- { "Invalid operation", 0 },
- { "Denormalized operand", 1 },
- { "Divide-by-zero", 2 },
- { "Numeric overflow", 3 },
- { "Numeric underflow", 4 },
- { "Inexact result (precision)", 5 },
- { "Infinity control", 12 },
- { "", 0 }
- };
- static char *precisionControlField[] = {
- "Single Precision (24-bits)",
- "Reserved",
- "Double Precision (53-bits)",
- "Double Extended Precision (64-bits)"
- };
- static char *roundingControlField[] = {
- "Round to nearest",
- "Round down",
- "Round up",
- "Round toward zero"
- };
- static bitFlag_t statusWordFlags[] = {
- { "Invalid operation", 0 },
- { "Denormalized operand", 1 },
- { "Divide-by-zero", 2 },
- { "Numeric overflow", 3 },
- { "Numeric underflow", 4 },
- { "Inexact result (precision)", 5 },
- { "Stack fault", 6 },
- { "Error summary status", 7 },
- { "FPU busy", 15 },
- { "", 0 }
- };
- /*
- ===============
- Sys_FPU_PrintStateFlags
- ===============
- */
- int Sys_FPU_PrintStateFlags( char *ptr, int ctrl, int stat, int tags, int inof, int inse, int opof, int opse ) {
- int i, length = 0;
- length += sprintf( ptr+length, "CTRL = %08x\n"
- "STAT = %08x\n"
- "TAGS = %08x\n"
- "INOF = %08x\n"
- "INSE = %08x\n"
- "OPOF = %08x\n"
- "OPSE = %08x\n"
- "\n",
- ctrl, stat, tags, inof, inse, opof, opse );
- length += sprintf( ptr+length, "Control Word:\n" );
- for ( i = 0; controlWordFlags[i].name[0]; i++ ) {
- length += sprintf( ptr+length, " %-30s = %s\n", controlWordFlags[i].name, ( ctrl & ( 1 << controlWordFlags[i].bit ) ) ? "true" : "false" );
- }
- length += sprintf( ptr+length, " %-30s = %s\n", "Precision control", precisionControlField[(ctrl>>8)&3] );
- length += sprintf( ptr+length, " %-30s = %s\n", "Rounding control", roundingControlField[(ctrl>>10)&3] );
- length += sprintf( ptr+length, "Status Word:\n" );
- for ( i = 0; statusWordFlags[i].name[0]; i++ ) {
- ptr += sprintf( ptr+length, " %-30s = %s\n", statusWordFlags[i].name, ( stat & ( 1 << statusWordFlags[i].bit ) ) ? "true" : "false" );
- }
- length += sprintf( ptr+length, " %-30s = %d%d%d%d\n", "Condition code", (stat>>8)&1, (stat>>9)&1, (stat>>10)&1, (stat>>14)&1 );
- length += sprintf( ptr+length, " %-30s = %d\n", "Top of stack pointer", (stat>>11)&7 );
- return length;
- }
- /*
- ===============
- Sys_FPU_StackIsEmpty
- ===============
- */
- bool Sys_FPU_StackIsEmpty( void ) {
- __asm {
- mov eax, statePtr
- fnstenv [eax]
- mov eax, [eax+8]
- xor eax, 0xFFFFFFFF
- and eax, 0x0000FFFF
- jz empty
- }
- return false;
- empty:
- return true;
- }
- /*
- ===============
- Sys_FPU_ClearStack
- ===============
- */
- void Sys_FPU_ClearStack( void ) {
- __asm {
- mov eax, statePtr
- fnstenv [eax]
- mov eax, [eax+8]
- xor eax, 0xFFFFFFFF
- mov edx, (3<<14)
- emptyStack:
- mov ecx, eax
- and ecx, edx
- jz done
- fstp st
- shr edx, 2
- jmp emptyStack
- done:
- }
- }
- /*
- ===============
- Sys_FPU_GetState
- gets the FPU state without changing the state
- ===============
- */
- const char *Sys_FPU_GetState( void ) {
- double fpuStack[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
- double *fpuStackPtr = fpuStack;
- int i, numValues;
- char *ptr;
- __asm {
- mov esi, statePtr
- mov edi, fpuStackPtr
- fnstenv [esi]
- mov esi, [esi+8]
- xor esi, 0xFFFFFFFF
- mov edx, (3<<14)
- xor eax, eax
- mov ecx, esi
- and ecx, edx
- jz done
- fst qword ptr [edi+0]
- inc eax
- shr edx, 2
- mov ecx, esi
- and ecx, edx
- jz done
- fxch st(1)
- fst qword ptr [edi+8]
- inc eax
- fxch st(1)
- shr edx, 2
- mov ecx, esi
- and ecx, edx
- jz done
- fxch st(2)
- fst qword ptr [edi+16]
- inc eax
- fxch st(2)
- shr edx, 2
- mov ecx, esi
- and ecx, edx
- jz done
- fxch st(3)
- fst qword ptr [edi+24]
- inc eax
- fxch st(3)
- shr edx, 2
- mov ecx, esi
- and ecx, edx
- jz done
- fxch st(4)
- fst qword ptr [edi+32]
- inc eax
- fxch st(4)
- shr edx, 2
- mov ecx, esi
- and ecx, edx
- jz done
- fxch st(5)
- fst qword ptr [edi+40]
- inc eax
- fxch st(5)
- shr edx, 2
- mov ecx, esi
- and ecx, edx
- jz done
- fxch st(6)
- fst qword ptr [edi+48]
- inc eax
- fxch st(6)
- shr edx, 2
- mov ecx, esi
- and ecx, edx
- jz done
- fxch st(7)
- fst qword ptr [edi+56]
- inc eax
- fxch st(7)
- done:
- mov numValues, eax
- }
- int ctrl = *(int *)&fpuState[0];
- int stat = *(int *)&fpuState[4];
- int tags = *(int *)&fpuState[8];
- int inof = *(int *)&fpuState[12];
- int inse = *(int *)&fpuState[16];
- int opof = *(int *)&fpuState[20];
- int opse = *(int *)&fpuState[24];
- ptr = fpuString;
- ptr += sprintf( ptr,"FPU State:\n"
- "num values on stack = %d\n", numValues );
- for ( i = 0; i < 8; i++ ) {
- ptr += sprintf( ptr, "ST%d = %1.10e\n", i, fpuStack[i] );
- }
- Sys_FPU_PrintStateFlags( ptr, ctrl, stat, tags, inof, inse, opof, opse );
- return fpuString;
- }
- /*
- ===============
- Sys_FPU_EnableExceptions
- ===============
- */
- void Sys_FPU_EnableExceptions( int exceptions ) {
- __asm {
- mov eax, statePtr
- mov ecx, exceptions
- and cx, 63
- not cx
- fnstcw word ptr [eax]
- mov bx, word ptr [eax]
- or bx, 63
- and bx, cx
- mov word ptr [eax], bx
- fldcw word ptr [eax]
- }
- }
- /*
- ===============
- Sys_FPU_SetPrecision
- ===============
- */
- void Sys_FPU_SetPrecision( int precision ) {
- short precisionBitTable[4] = { 0, 1, 3, 0 };
- short precisionBits = precisionBitTable[precision & 3] << 8;
- short precisionMask = ~( ( 1 << 9 ) | ( 1 << 8 ) );
- __asm {
- mov eax, statePtr
- mov cx, precisionBits
- fnstcw word ptr [eax]
- mov bx, word ptr [eax]
- and bx, precisionMask
- or bx, cx
- mov word ptr [eax], bx
- fldcw word ptr [eax]
- }
- }
- /*
- ================
- Sys_FPU_SetRounding
- ================
- */
- void Sys_FPU_SetRounding( int rounding ) {
- short roundingBitTable[4] = { 0, 1, 2, 3 };
- short roundingBits = roundingBitTable[rounding & 3] << 10;
- short roundingMask = ~( ( 1 << 11 ) | ( 1 << 10 ) );
- __asm {
- mov eax, statePtr
- mov cx, roundingBits
- fnstcw word ptr [eax]
- mov bx, word ptr [eax]
- and bx, roundingMask
- or bx, cx
- mov word ptr [eax], bx
- fldcw word ptr [eax]
- }
- }
- /*
- ================
- Sys_FPU_SetDAZ
- ================
- */
- void Sys_FPU_SetDAZ( bool enable ) {
- DWORD dwData;
- _asm {
- movzx ecx, byte ptr enable
- and ecx, 1
- shl ecx, 6
- STMXCSR dword ptr dwData
- mov eax, dwData
- and eax, ~(1<<6) // clear DAX bit
- or eax, ecx // set the DAZ bit
- mov dwData, eax
- LDMXCSR dword ptr dwData
- }
- }
- /*
- ================
- Sys_FPU_SetFTZ
- ================
- */
- void Sys_FPU_SetFTZ( bool enable ) {
- DWORD dwData;
- _asm {
- movzx ecx, byte ptr enable
- and ecx, 1
- shl ecx, 15
- STMXCSR dword ptr dwData
- mov eax, dwData
- and eax, ~(1<<15) // clear FTZ bit
- or eax, ecx // set the FTZ bit
- mov dwData, eax
- LDMXCSR dword ptr dwData
- }
- }
|