Pyrogenesis  trunk
x86_x64.h
Go to the documentation of this file.
1 /* Copyright (C) 2022 Wildfire Games.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 /*
24  * CPU-specific routines common to 32 and 64-bit x86
25  */
26 
27 #ifndef INCLUDED_X86_X64
28 #define INCLUDED_X86_X64
29 
30 #if !ARCH_X86_X64
31 #error "including x86_x64.h without ARCH_X86_X64=1"
32 #endif
33 
34 #if MSC_VERSION
35 #include <intrin.h> // __rdtsc
36 #endif
37 
38 namespace x86_x64 {
39 
40 /**
41  * registers used/returned by cpuid
42  **/
43 #pragma pack(push, 1) // (allows casting to int*)
44 struct CpuidRegs
45 {
50 };
51 #pragma pack(pop)
52 
53 /**
54  * invoke CPUID instruction.
55  * @param regs input/output registers.
56  * regs->eax must be set to the desired function.
57  * some functions (e.g. 4) require regs->ecx to be set as well.
58  * rationale: this interface (input/output structure vs. function parameters)
59  * avoids unnecessary copying/initialization if some inputs aren't needed
60  * and allows graceful expansion to functions that require further inputs.
61  * @return true on success or false if the sub-function isn't supported.
62  **/
63 bool cpuid(CpuidRegs* regs);
64 
65 /**
66  * CPU vendor.
67  * (this is exposed because some CPUID functions are vendor-specific.)
68  * (an enum is easier to compare than the original string values.)
69  **/
70 enum Vendors
71 {
75 };
76 
77 Vendors Vendor();
78 
79 
80 enum Models
81 {
82  MODEL_NEHALEM_EP = 0x1A, // Bloomfield (X35xx), Gainestown (X55xx)
83  MODEL_NEHALEM_EP_2 = 0x1E, // Clarksfield, Lynnfield (X34xx), Jasper Forest (C35xx, C55xx)
84  MODEL_I7_I5 = 0x1F, // similar to 1E; mentioned in 253665-041US, no codename known
85  MODEL_CLARKDALE = 0x25, // Arrandale, Clarkdale (L34xx)
86  MODEL_WESTMERE_EP = 0x2C, // Gulftown (X36xx, X56xx)
87  MODEL_NEHALEM_EX = 0x2E, // Beckton (X75xx)
88  MODEL_WESTMERE_EX = 0x2F, // Gulftown uarch, Beckton package (E7-48xx)
89  MODEL_SANDY_BRIDGE = 0x2A, // (E3-12xx, E5-26xx)
90  MODEL_SANDY_BRIDGE_2 = 0x2D, // (E5-26xx, E5-46xx)
91 };
92 
93 size_t Model();
94 
95 size_t Family();
96 
97 
98 /**
99  * @return the colloquial processor generation
100  * (5 = Pentium, 6 = Pentium Pro/II/III / K6, 7 = Pentium4 / Athlon, 8 = Core / Opteron)
101  **/
102 size_t Generation();
103 
104 
105 /**
106  * bit indices of CPU capability flags (128 bits).
107  * values are defined by IA-32 CPUID feature flags - do not change!
108  **/
109 enum Caps
110 {
111  // standard (ecx) - currently only defined by Intel
112  CAP_SSE3 = 0+0, // Streaming SIMD Extensions 3
113  CAP_EST = 0+7, // Enhanced Speedstep Technology
114  CAP_SSSE3 = 0+9, // Supplemental Streaming SIMD Extensions 3
115  CAP_SSE41 = 0+19, // Streaming SIMD Extensions 4.1
116  CAP_SSE42 = 0+20, // Streaming SIMD Extensions 4.2
117 
118  // standard (edx)
119  CAP_FPU = 32+0, // Floating Point Unit
120  CAP_TSC = 32+4, // TimeStamp Counter
121  CAP_MSR = 32+5, // Model Specific Registers
122  CAP_CMOV = 32+15, // Conditional MOVe
123  CAP_TM_SCC = 32+22, // Thermal Monitoring and Software Controlled Clock
124  CAP_MMX = 32+23, // MultiMedia eXtensions
125  CAP_SSE = 32+25, // Streaming SIMD Extensions
126  CAP_SSE2 = 32+26, // Streaming SIMD Extensions 2
127  CAP_HT = 32+28, // HyperThreading
128 
129  // extended (ecx)
130  CAP_AMD_CMP_LEGACY = 64+1, // N-core and CAP_HT is falsely set
131 
132  // extended (edx)
133  CAP_AMD_MP = 96+19, // MultiProcessing capable; reserved on AMD64
137 };
138 
139 /**
140  * @return whether the CPU supports the indicated Cap / feature flag.
141  **/
142 bool Cap(Caps cap);
143 
144 void GetCapBits(u32* d0, u32* d1, u32* d2, u32* d3);
145 
146 
147 //-----------------------------------------------------------------------------
148 // stateless
149 
150 /**
151  * @return the current value of the TimeStampCounter (a counter of
152  * CPU cycles since power-on, which is useful for high-resolution timing
153  * but potentially differs between multiple CPUs)
154  *
155  * notes:
156  * - a macro avoids call overhead, which is important for TIMER_ACCRUE.
157  * - x64 RDTSC writes to edx:eax and clears the upper halves of rdx and rax.
158  **/
159 #if MSC_VERSION
160 static inline u64 rdtsc() { return __rdtsc(); }
161 #else
162 u64 rdtsc();
163 #endif
164 
165 /**
166  * trigger a breakpoint inside this function when it is called.
167  **/
168 void DebugBreak();
169 
170 /**
171  * measure the CPU clock frequency via rdtsc and timer_Time.
172  * (it follows that this must not be called from WHRT init.)
173  * this takes several milliseconds (i.e. much longer than
174  * os_cpu_ClockFrequency) but delivers accurate measurements.
175  **/
176 double ClockFrequency();
177 
178 } // namespace x86_x64
179 
180 #endif // #ifndef INCLUDED_X86_X64
Definition: x86_x64.h:121
double ClockFrequency()
measure the CPU clock frequency via rdtsc and timer_Time.
Definition: x86_x64.cpp:429
u32 ecx
Definition: x86_x64.h:48
Definition: x86_x64.h:124
Definition: x86_x64.h:135
Definition: x86_x64.h:125
Definition: x86_x64.h:88
bool cpuid(CpuidRegs *regs)
invoke CPUID instruction.
Definition: x86_x64.cpp:98
Definition: x86_x64.h:89
size_t Generation()
void DebugBreak()
trigger a breakpoint inside this function when it is called.
Definition: x86_x64.cpp:385
Definition: x86_x64.h:119
Definition: x86_x64.h:122
Definition: x86_x64.h:127
Definition: x86_x64.h:73
u32 edx
Definition: x86_x64.h:49
uint64_t u64
Definition: types.h:40
Definition: x86_x64.h:134
Definition: x86_x64.h:112
size_t Family()
Definition: x86_x64.cpp:238
Definition: x86_x64.h:116
Definition: x86_x64.h:114
uint32_t u32
Definition: types.h:39
Definition: x86_x64.h:72
Definition: x86_x64.h:136
Models
Definition: x86_x64.h:80
Caps
bit indices of CPU capability flags (128 bits).
Definition: x86_x64.h:109
u64 rdtsc()
Definition: x86_x64.cpp:373
bool Cap(Caps cap)
Definition: x86_x64.cpp:142
u32 ebx
Definition: x86_x64.h:47
Definition: x86_x64.h:85
Definition: x86_x64.h:83
Definition: x86_x64.h:113
Definition: x86_x64.h:120
Definition: x86_x64.h:74
Definition: x86_x64.h:86
Definition: x86_x64.h:130
void GetCapBits(u32 *d0, u32 *d1, u32 *d2, u32 *d3)
Definition: x86_x64.cpp:156
Definition: x86_x64.cpp:47
Definition: x86_x64.h:87
Definition: x86_x64.h:123
u32 eax
Definition: x86_x64.h:46
Definition: x86_x64.h:126
size_t Model()
Definition: x86_x64.cpp:232
registers used/returned by cpuid
Definition: x86_x64.h:44
Vendors Vendor()
Definition: x86_x64.cpp:200
Definition: x86_x64.h:90
Definition: x86_x64.h:133
Definition: x86_x64.h:82
Vendors
CPU vendor.
Definition: x86_x64.h:70
Definition: x86_x64.h:84
Definition: x86_x64.h:115