Added FPU Safety check method
This commit is contained in:
parent
472e34dc6c
commit
3dc0e69441
|
@ -24,6 +24,7 @@
|
||||||
#include "network_manager.h"
|
#include "network_manager.h"
|
||||||
#include "checksum.h"
|
#include "checksum.h"
|
||||||
#include "auto_test.h"
|
#include "auto_test.h"
|
||||||
|
#include "FPUCheck.h"
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
|
||||||
using namespace Shared::Graphics;
|
using namespace Shared::Graphics;
|
||||||
|
@ -98,6 +99,7 @@ void Game::load(){
|
||||||
}
|
}
|
||||||
|
|
||||||
Config &config = Config::getInstance();
|
Config &config = Config::getInstance();
|
||||||
|
good_fpu_control_registers(NULL,__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
string scenarioDir = "";
|
string scenarioDir = "";
|
||||||
if(gameSettings.getScenarioDir() != "") {
|
if(gameSettings.getScenarioDir() != "") {
|
||||||
|
@ -212,6 +214,8 @@ void Game::load(){
|
||||||
Lang::getInstance().loadScenarioStrings(gameSettings.getScenarioDir(), scenarioName);
|
Lang::getInstance().loadScenarioStrings(gameSettings.getScenarioDir(), scenarioName);
|
||||||
world.loadScenario(gameSettings.getScenarioDir(), &checksum);
|
world.loadScenario(gameSettings.getScenarioDir(), &checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
good_fpu_control_registers(NULL,__FILE__,__FUNCTION__,__LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::init()
|
void Game::init()
|
||||||
|
@ -243,6 +247,8 @@ void Game::init()
|
||||||
gameCamera.setPos(Vec2f(v.x, v.y));
|
gameCamera.setPos(Vec2f(v.x, v.y));
|
||||||
scriptManager.init(&world, &gameCamera);
|
scriptManager.init(&world, &gameCamera);
|
||||||
|
|
||||||
|
good_fpu_control_registers(NULL,__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] creating AI's\n",__FILE__,__FUNCTION__);
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] creating AI's\n",__FILE__,__FUNCTION__);
|
||||||
|
|
||||||
//create IAs
|
//create IAs
|
||||||
|
@ -280,6 +286,8 @@ void Game::init()
|
||||||
logger.add("Initializing renderer", true);
|
logger.add("Initializing renderer", true);
|
||||||
renderer.initGame(this);
|
renderer.initGame(this);
|
||||||
|
|
||||||
|
good_fpu_control_registers(NULL,__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
//sounds
|
//sounds
|
||||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||||
|
|
||||||
|
@ -356,6 +364,8 @@ void Game::update(){
|
||||||
weatherParticleSystem->setPos(gameCamera.getPos());
|
weatherParticleSystem->setPos(gameCamera.getPos());
|
||||||
}
|
}
|
||||||
renderer.updateParticleManager(rsGame);
|
renderer.updateParticleManager(rsGame);
|
||||||
|
|
||||||
|
good_fpu_control_registers(NULL,__FILE__,__FUNCTION__,__LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
//call the chat manager
|
//call the chat manager
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/**
|
||||||
|
* @file FPUCheck.h
|
||||||
|
* @brief good_fpu_control_registers function
|
||||||
|
* @author Tobi Vollebregt
|
||||||
|
*
|
||||||
|
* Assertions on floating point unit control registers.
|
||||||
|
* For now it only defines the good_fpu_control_registers() function.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006. Licensed under the terms of the
|
||||||
|
* GNU GPL, v2 or later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FPUCHECK_H
|
||||||
|
#define FPUCHECK_H
|
||||||
|
|
||||||
|
//#include "LogOutput.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "streflop_cond.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief checks FPU control registers.
|
||||||
|
@return true if everything is fine, false otherwise
|
||||||
|
|
||||||
|
Can be used in an assert() to check the FPU control registers MXCSR and FPUCW,
|
||||||
|
e.g. `assert(good_fpu_control_registers());'
|
||||||
|
|
||||||
|
For reference, the layout of the MXCSR register:
|
||||||
|
FZ:RC:RC:PM:UM:OM:ZM:DM:IM:Rsvd:PE:UE:OE:ZE:DE:IE
|
||||||
|
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||||
|
Spring1: 0 0 0 1 1 1 0 1 0 0 0 0 0 0 0 0 = 0x1D00 = 7424
|
||||||
|
Spring2: 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 = 0x1F80 = 8064
|
||||||
|
Default: 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 = 0x1F80 = 8064
|
||||||
|
MaskRsvd:1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 = 0xFF80
|
||||||
|
|
||||||
|
And the layout of the 387 FPU control word register:
|
||||||
|
Rsvd:Rsvd:Rsvd:X:RC:RC:PC:PC:Rsvd:Rsvd:PM:UM:OM:ZM:DM:IM
|
||||||
|
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||||
|
Spring1: 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 0 = 0x003A = 58
|
||||||
|
Spring2: 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 = 0x003F = 63
|
||||||
|
Default: 0 0 0 0 0 0 1 1 0 0 1 1 1 1 1 1 = 0x033F = 831
|
||||||
|
MaskRsvd: 0 0 0 1 1 1 1 1 0 0 1 1 1 1 1 1 = 0x1F3F
|
||||||
|
|
||||||
|
Where:
|
||||||
|
Rsvd - Reserved
|
||||||
|
FZ - Flush to Zero
|
||||||
|
RC - Rounding Control
|
||||||
|
PM - Precision Mask
|
||||||
|
UM - Underflow Mask
|
||||||
|
OM - Overflow Mask
|
||||||
|
ZM - Zerodivide Mask
|
||||||
|
DM - Denormal Mask
|
||||||
|
IM - Invalid Mask
|
||||||
|
PE - Precision Exception
|
||||||
|
UE - Underflow Exception
|
||||||
|
OE - Overflow Exception
|
||||||
|
ZE - Zerodivide Exception
|
||||||
|
DE - Denormal Exception
|
||||||
|
IE - Invalid Exception
|
||||||
|
X - Infinity control (unused on 387 and higher)
|
||||||
|
PC - Precision Control
|
||||||
|
|
||||||
|
Spring1 - Control word used by spring in code in CGame::SimFrame().
|
||||||
|
Spring2 - Control word used by spring in code everywhere else.
|
||||||
|
Default - Default control word according to Intel.
|
||||||
|
MaskRsvd - Masks out the reserved bits.
|
||||||
|
|
||||||
|
Source: Intel Architecture Software Development Manual, Volume 1, Basic Architecture
|
||||||
|
*/
|
||||||
|
static inline void good_fpu_control_registers(const char* text, const char *file=NULL, const char *classname=NULL, const int line=-1)
|
||||||
|
{
|
||||||
|
const char *outText = text;
|
||||||
|
char szBuf[256]="";
|
||||||
|
if(outText == NULL) {
|
||||||
|
sprintf(szBuf,"In [%s::%s Line: %d]",file=NULL, classname, line);
|
||||||
|
outText = &szBuf[0];
|
||||||
|
}
|
||||||
|
// We are paranoid.
|
||||||
|
// We don't trust the enumeration constants from streflop / (g)libc.
|
||||||
|
#if defined(STREFLOP_SSE)
|
||||||
|
fenv_t fenv;
|
||||||
|
fegetenv(&fenv);
|
||||||
|
|
||||||
|
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML) // -fsignaling-nans
|
||||||
|
bool ret = ((fenv.sse_mode & 0xFF80) == (0x1937 & 0xFF80) || (fenv.sse_mode & 0xFF80) == (0x1925 & 0xFF80)) &&
|
||||||
|
((fenv.x87_mode & 0x1F3F) == (0x0072 & 0x1F3F) || (fenv.x87_mode & 0x1F3F) == 0x003F);
|
||||||
|
#else
|
||||||
|
bool ret = ((fenv.sse_mode & 0xFF80) == 0x1D00 || (fenv.sse_mode & 0xFF80) == 0x1F80) &&
|
||||||
|
((fenv.x87_mode & 0x1F3F) == 0x003A || (fenv.x87_mode & 0x1F3F) == 0x003F);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,"Sync warning: MXCSR 0x%04X instead of 0x1D00 or 0x1F80 (\"%s\")", fenv.sse_mode, outText);
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,"Sync warning: FPUCW 0x%04X instead of 0x003A or 0x003F (\"%s\")", fenv.x87_mode, outText);
|
||||||
|
// Set single precision floating point math.
|
||||||
|
streflop_init<streflop::Simple>();
|
||||||
|
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML)
|
||||||
|
feraiseexcept(streflop::FPU_Exceptions(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#elif defined(STREFLOP_X87)
|
||||||
|
fenv_t fenv;
|
||||||
|
fegetenv(&fenv);
|
||||||
|
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML)
|
||||||
|
bool ret = (fenv & 0x1F3F) == 0x0072 || (fenv & 0x1F3F) == 0x003F;
|
||||||
|
#else
|
||||||
|
bool ret = (fenv & 0x1F3F) == 0x003A || (fenv & 0x1F3F) == 0x003F;
|
||||||
|
#endif
|
||||||
|
if (!ret) {
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,"Sync warning: FPUCW 0x%04X instead of 0x003A or 0x003F (\"%s\")", fenv, outText);
|
||||||
|
// Set single precision floating point math.
|
||||||
|
streflop_init<streflop::Simple>();
|
||||||
|
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML)
|
||||||
|
feraiseexcept(streflop::FPU_Exceptions(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !FPUCHECK_H
|
Loading…
Reference in New Issue