2006-04-12 01:59:08 +02:00
|
|
|
/**
|
|
|
|
* =========================================================================
|
|
|
|
* File : ia32.h
|
|
|
|
* Project : 0 A.D.
|
2007-05-08 17:11:53 +02:00
|
|
|
* Description : C++ and inline asm implementations of IA-32 functions
|
2006-04-12 01:59:08 +02:00
|
|
|
* =========================================================================
|
|
|
|
*/
|
|
|
|
|
2007-05-07 18:33:24 +02:00
|
|
|
// license: GPL; see lib/license.txt
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2007-04-30 21:58:04 +02:00
|
|
|
#ifndef INCLUDED_IA32
|
|
|
|
#define INCLUDED_IA32
|
2005-01-31 00:07:55 +01:00
|
|
|
|
2005-08-09 18:23:19 +02:00
|
|
|
#if !CPU_IA32
|
2005-09-13 01:37:52 +02:00
|
|
|
#error "including ia32.h without CPU_IA32=1"
|
2004-03-03 00:56:51 +01:00
|
|
|
#endif
|
|
|
|
|
2007-04-25 20:19:35 +02:00
|
|
|
#include "ia32_asm.h"
|
|
|
|
#include "ia32_memcpy.h"
|
2005-09-13 06:00:41 +02:00
|
|
|
|
2007-04-30 21:58:04 +02:00
|
|
|
/**
|
2007-05-26 18:57:39 +02:00
|
|
|
* must be called before any of the following functions.
|
2007-04-30 21:58:04 +02:00
|
|
|
**/
|
2007-05-02 14:07:08 +02:00
|
|
|
extern void ia32_Init();
|
2007-05-26 18:57:39 +02:00
|
|
|
extern void ia32_Shutdown();
|
2007-04-25 20:19:35 +02:00
|
|
|
|
2007-04-30 21:58:04 +02:00
|
|
|
/**
|
|
|
|
* bit indices of CPU capability flags (128 bits).
|
|
|
|
* values are defined by IA-32 CPUID feature flags - do not change!
|
|
|
|
**/
|
2006-05-31 06:01:59 +02:00
|
|
|
enum IA32Cap
|
2004-03-03 00:56:51 +01:00
|
|
|
{
|
2005-09-14 03:34:16 +02:00
|
|
|
// standard (ecx) - currently only defined by Intel
|
2006-05-31 06:01:59 +02:00
|
|
|
IA32_CAP_SSE3 = 0+0, // Streaming SIMD Extensions 3
|
|
|
|
IA32_CAP_EST = 0+7, // Enhanced Speedstep Technology
|
2004-06-21 16:17:48 +02:00
|
|
|
|
|
|
|
// standard (edx)
|
2006-05-31 06:01:59 +02:00
|
|
|
IA32_CAP_FPU = 32+0, // Floating Point Unit
|
|
|
|
IA32_CAP_TSC = 32+4, // TimeStamp Counter
|
|
|
|
IA32_CAP_CMOV = 32+15, // Conditional MOVe
|
|
|
|
IA32_CAP_MMX = 32+23, // MultiMedia eXtensions
|
|
|
|
IA32_CAP_SSE = 32+25, // Streaming SIMD Extensions
|
|
|
|
IA32_CAP_SSE2 = 32+26, // Streaming SIMD Extensions 2
|
|
|
|
IA32_CAP_HT = 32+28, // HyperThreading
|
2004-06-21 16:17:48 +02:00
|
|
|
|
|
|
|
// extended (ecx)
|
|
|
|
|
2005-09-14 03:34:16 +02:00
|
|
|
// extended (edx) - currently only defined by AMD
|
2006-05-31 06:01:59 +02:00
|
|
|
IA32_CAP_AMD_MP = 96+19, // MultiProcessing capable; reserved on AMD64
|
|
|
|
IA32_CAP_AMD_MMX_EXT = 96+22,
|
|
|
|
IA32_CAP_AMD_3DNOW_PRO = 96+30,
|
|
|
|
IA32_CAP_AMD_3DNOW = 96+31
|
2004-03-03 00:56:51 +01:00
|
|
|
};
|
|
|
|
|
2007-04-30 21:58:04 +02:00
|
|
|
/**
|
|
|
|
* @return whether the CPU supports the indicated IA32Cap / feature flag.
|
|
|
|
**/
|
2006-05-31 06:01:59 +02:00
|
|
|
extern bool ia32_cap(IA32Cap cap);
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2007-04-30 21:58:04 +02:00
|
|
|
|
|
|
|
// CPU detection
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string identifying the CPU (usually a cleaned-up version of the
|
|
|
|
* brand string)
|
|
|
|
**/
|
2007-05-02 14:07:08 +02:00
|
|
|
extern const char* ia32_IdentifierString();
|
2007-04-30 21:58:04 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return whether CPU frequency throttling is possible or
|
|
|
|
* may potentially happen (if so, using RDTSC is unsafe).
|
|
|
|
**/
|
2007-05-02 14:07:08 +02:00
|
|
|
extern int ia32_IsThrottlingPossible();
|
2007-04-30 21:58:04 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return the cached result of a precise measurement of the
|
|
|
|
* CPU frequency.
|
|
|
|
**/
|
2007-05-02 14:07:08 +02:00
|
|
|
extern double ia32_ClockFrequency();
|
2005-09-13 06:00:41 +02:00
|
|
|
|
2007-04-30 21:58:04 +02:00
|
|
|
/**
|
|
|
|
* @return number of *enabled* CPU packages / sockets.
|
|
|
|
**/
|
2007-05-02 14:07:08 +02:00
|
|
|
extern uint ia32_NumPackages();
|
2007-04-30 21:58:04 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return number of *enabled* CPU cores per package.
|
|
|
|
* (2 on dual-core systems)
|
|
|
|
**/
|
2007-05-02 14:07:08 +02:00
|
|
|
extern uint ia32_CoresPerPackage();
|
2007-04-30 21:58:04 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return number of *enabled* hyperthreading units per core.
|
|
|
|
* (2 on P4 EE)
|
|
|
|
**/
|
2007-05-02 14:07:08 +02:00
|
|
|
extern uint ia32_LogicalPerCore();
|
2005-09-13 06:00:41 +02:00
|
|
|
|
2007-04-30 21:58:04 +02:00
|
|
|
|
2007-05-26 18:57:39 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// stateless
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return APIC ID of the currently executing processor
|
|
|
|
**/
|
|
|
|
extern uint ia32_ApicId();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* check if there is an IA-32 CALL instruction right before ret_addr.
|
|
|
|
* @return INFO::OK if so and ERR::FAIL if not.
|
|
|
|
*
|
|
|
|
* also attempts to determine the call target. if that is possible
|
|
|
|
* (directly addressed relative or indirect jumps), it is stored in
|
|
|
|
* target, which is otherwise 0.
|
|
|
|
*
|
|
|
|
* this function is used for walking the call stack.
|
|
|
|
**/
|
|
|
|
extern LibError ia32_GetCallTarget(void* ret_addr, void** target);
|
|
|
|
|
|
|
|
|
|
|
|
/// safe but slow inline-asm version
|
|
|
|
extern u64 ia32_rdtsc_safe(void);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return the current value of the TimeStampCounter (a counter of
|
|
|
|
* CPU cycles since power-on, which is useful for high-resolution timing
|
|
|
|
* but potentially differs between multiple CPUs)
|
|
|
|
**/
|
|
|
|
extern u64 ia32_rdtsc(); // only for CppDoc's benefit
|
|
|
|
#if CONFIG_RETURN64_EDX_EAX
|
|
|
|
# define ia32_rdtsc ia32_asm_rdtsc_edx_eax
|
|
|
|
#else
|
|
|
|
# define ia32_rdtsc ia32_rdtsc_safe
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* trigger a breakpoint inside this function when it is called.
|
|
|
|
**/
|
|
|
|
extern void ia32_DebugBreak(void);
|
|
|
|
|
|
|
|
|
2007-04-30 21:58:04 +02:00
|
|
|
// implementations of the cpu.h interface
|
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
/// see cpu_MemoryFence
|
|
|
|
extern void ia32_MemoryFence();
|
2007-04-30 21:58:04 +02:00
|
|
|
|
2007-05-02 14:07:08 +02:00
|
|
|
// see cpu_Serialize
|
|
|
|
extern void ia32_Serialize();
|
2007-04-30 21:58:04 +02:00
|
|
|
|
2007-05-26 18:57:39 +02:00
|
|
|
|
|
|
|
/// fpclassify return values
|
|
|
|
#define IA32_FP_NAN 0x0100
|
|
|
|
#define IA32_FP_NORMAL 0x0400
|
|
|
|
#define IA32_FP_INFINITE (IA32_FP_NAN | IA32_FP_NORMAL)
|
|
|
|
#define IA32_FP_ZERO 0x4000
|
|
|
|
#define IA32_FP_SUBNORMAL (IA32_FP_NORMAL | IA32_FP_ZERO)
|
|
|
|
|
|
|
|
// FPU control word (for ia32_asm_control87)
|
|
|
|
// .. Precision Control:
|
|
|
|
#define IA32_MCW_PC 0x0300
|
|
|
|
#define IA32_PC_24 0x0000
|
|
|
|
// .. Rounding Control:
|
|
|
|
#define IA32_MCW_RC 0x0C00
|
|
|
|
#define IA32_RC_NEAR 0x0000
|
|
|
|
#define IA32_RC_DOWN 0x0400
|
|
|
|
#define IA32_RC_UP 0x0800
|
|
|
|
#define IA32_RC_CHOP 0x0C00
|
|
|
|
// .. Exception Mask:
|
|
|
|
#define IA32_MCW_EM 0x003f
|
|
|
|
#define IA32_EM_INVALID BIT(0)
|
|
|
|
#define IA32_EM_DENORMAL BIT(1)
|
|
|
|
#define IA32_EM_ZERODIVIDE BIT(2)
|
|
|
|
#define IA32_EM_OVERFLOW BIT(3)
|
|
|
|
#define IA32_EM_UNDERFLOW BIT(4)
|
|
|
|
#define IA32_EM_INEXACT BIT(5)
|
|
|
|
|
2007-04-30 21:58:04 +02:00
|
|
|
#endif // #ifndef INCLUDED_IA32
|