0ad/source/lib/sysdep/cpu.h
janwas 383cf7b220 cleanup:
use intrinsics for cpu_AtomicAdd and cpu_CAS, get rid of the
corresponding assembly implementations. (wrapper functions are necessary
at work because mere declarations aren't enough to export the functions
from DLL)
also remove no longer needed fminf

This was SVN commit r8521.
2010-11-02 13:38:56 +00:00

118 lines
3.5 KiB
C++

/* Copyright (c) 2010 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* CPU and memory detection.
*/
#ifndef INCLUDED_CPU
#define INCLUDED_CPU
#include "lib/sysdep/compiler.h"
namespace ERR
{
const LibError CPU_FEATURE_MISSING = -130000;
const LibError CPU_UNKNOWN_OPCODE = -130001;
const LibError CPU_UNKNOWN_VENDOR = -130002;
}
//-----------------------------------------------------------------------------
// CPU detection
/**
* @return string identifying the CPU (usually a cleaned-up version of the
* brand string)
**/
LIB_API const char* cpu_IdentifierString();
//-----------------------------------------------------------------------------
// lock-free support routines
/**
* add a signed value to a variable without the possibility of interference
* from other threads/CPUs.
*
* @return the previous value.
**/
LIB_API intptr_t cpu_AtomicAdd(volatile intptr_t* location, intptr_t increment);
/**
* atomic "compare and swap".
*
* @param location address of the word to compare and possibly overwrite
* @param expected its expected value
* @param newValue the value with which to replace it
* @return false if the target word doesn't match the expected value,
* otherwise true (also overwriting the contents of location)
**/
LIB_API bool cpu_CAS(volatile intptr_t* location, intptr_t expected, intptr_t newValue);
LIB_API bool cpu_CAS64(volatile i64* location, i64 expected, i64 newValue);
/**
* specialization of cpu_CAS for pointer types. this avoids error-prone
* casting in user code.
**/
template<typename T>
bool cpu_CAS(volatile T* location, T expected, T new_value)
{
return cpu_CAS((volatile intptr_t*)location, (intptr_t)expected, (intptr_t)new_value);
}
LIB_API void cpu_Test();
/**
* enforce strict instruction ordering in the CPU pipeline.
**/
LIB_API void cpu_Serialize();
/**
* pause in spin-wait loops, as a performance optimisation.
**/
inline void cpu_Pause()
{
#if MSC_VERSION && ARCH_X86_X64
_mm_pause();
#elif GCC_VERSION && ARCH_X86_X64
__asm__ __volatile__( "rep; nop" : : : "memory" );
#endif
}
//-----------------------------------------------------------------------------
// misc
/**
* set the FPU control word to "desirable" values (see implementation)
**/
LIB_API void cpu_ConfigureFloatingPoint();
// NB: cpu_i64FromDouble et al. were faster than _ftol2, but are obsolete
// since VC8 and GCC (with -ffast-math) generate SSE instructions.
#endif // #ifndef INCLUDED_CPU