3 * Runtime CPU detection library.
4 * (C) 2009-2012 Jonathan Campbell.
5 * Hackipedia DOS library.
7 * This code is licensed under the LGPL.
8 * <insert LGPL legal text here>
12 #ifndef __HW_CPU_CPU_H
13 #define __HW_CPU_CPU_H
17 #include "src/lib/16_head.h"
20 # if defined(TARGET_WINDOWS)
23 # if TARGET_MSDOS == 32
31 /* FIX: Open Watcom does not provide inpd/outpd in 16-bit real mode, so we have to provide it ourself */
32 /* We assume for the same stupid reasons the pragma aux function can't be used because it's a 386 level instruction */
33 #if TARGET_MSDOS == 16
34 uint32_t __cdecl inpd(uint16_t port);
35 void __cdecl outpd(uint16_t port,uint32_t data);
38 #if TARGET_MSDOS == 16
39 static inline uint32_t ptr2phys(void far *p) {
40 return (((uint32_t)FP_SEG(p)) << 4UL) +
41 ((uint32_t)FP_OFF(p));
46 struct cpu_cpuid_features {
48 uint32_t raw[4]; /* EAX, EBX, EDX, ECX */
55 struct cpu_cpuid_ext_features {
57 uint32_t raw[4]; /* EAX, EBX, ECX, EDX */
64 struct cpu_cpuid_ext_cache_tlb {
66 uint32_t raw[4]; /* EAX, EBX, ECX, EDX */
73 struct cpu_cpuid_ext_cache_tlb_l2 {
75 uint32_t raw[4]; /* EAX, EBX, ECX, EDX */
82 struct cpu_cpuid_ext_longmode {
84 uint32_t raw[4]; /* EAX, EBX, ECX, EDX */
91 struct cpu_cpuid_ext_apm {
93 uint32_t raw[1]; /* EAX */
100 struct cpuid_result {
101 uint32_t eax,ebx,ecx,edx;
105 /* "Basic" CPU level */
117 extern const char * cpu_basic_level_str[CPU_MAX];
118 extern char cpu_cpuid_vendor[13];
119 extern struct cpu_cpuid_features cpu_cpuid_features;
120 extern signed char cpu_basic_level;
121 extern uint32_t cpu_cpuid_max;
122 extern unsigned char cpu_flags;
123 extern uint16_t cpu_tmp1;
126 #define cpu_v86_active (cpu_flags & CPU_FLAG_V86_ACTIVE)
128 #define cpu_basic_level_to_string(x) (x >= 0 ? cpu_basic_level_str[x] : "?")
130 /* CPU flag: CPU supports CPUID */
131 #define CPU_FLAG_CPUID (1 << 0)
132 #define CPU_FLAG_FPU (1 << 1)
133 #define CPU_FLAG_CPUID_EXT (1 << 2)
134 #define CPU_FLAG_V86_ACTIVE (1 << 3)
135 #define CPU_FLAG_PROTECTED_MODE (1 << 4)
136 #define CPU_FLAG_PROTECTED_MODE_32 (1 << 5)
137 /* ^ Windows-specific: we are not only a 16-bit Win16 app, but Windows is running in 386 enhanced mode
138 * and we can safely use 32-bit registers and hacks. This will always be set for
139 * Win32 and 32-bit DOS, obviously. If set, PROTECTED_MODE is also set. */
140 #define CPU_FLAG_DONT_WRITE_RDTSC (1 << 6)
143 int cpu_basic_probe(); /* external assembly language function */
146 #pragma aux _cli = "cli"
148 #pragma aux _sti = "sti"
150 static inline void _sti_if_flags(unsigned int f) {
151 if (f&0x200) _sti(); /* if IF bit was set, then restore interrupts by STI */
154 /* NTS: remember for Watcom: 16-bit realmode sizeof(int) == 2, 32-bit flat mode sizeof(int) == 4 */
155 static unsigned int get_cpu_flags();
156 #if TARGET_MSDOS == 32
157 #pragma aux get_cpu_flags = \
162 #pragma aux get_cpu_flags = \
168 static void set_cpu_flags(unsigned int f);
169 #if TARGET_MSDOS == 32
170 #pragma aux set_cpu_flags = \
175 #pragma aux set_cpu_flags = \
181 #if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32
182 /* Watcom does not offer int86/int386 for Win32s/Win9x/NT/etc */
184 static inline void just_int86(unsigned char c,union REGS *r1,union REGS *r2) {
193 #if TARGET_MSDOS == 32
194 static inline void cpu_cpuid(uint32_t idx,struct cpuid_result *x);
195 #pragma aux cpu_cpuid = \
208 void cpu_cpuid(uint32_t idx,struct cpuid_result *x);
211 #if TARGET_MSDOS == 32
212 static inline uint64_t cpu_rdmsr(const uint32_t idx);
213 #pragma aux cpu_rdmsr = \
219 static inline void cpu_wrmsr(const uint32_t idx,const uint64_t val);
220 #pragma aux cpu_wrmsr = \
225 /* This is too much code to inline insert everywhere---unless you want extra-large EXEs.
226 * It's better to conform to Watcom's register calling convention and make it a function.
227 * Note that if you look at the assembly language most of the code is shuffling the values
228 * around to convert EDX:EAX to AX:BX:CX:DX and disabling interrupts during the call. */
230 uint64_t cpu_rdmsr(const uint32_t idx);
231 void cpu_wrmsr(const uint32_t idx,const uint64_t val);
234 int cpu_basic_probe();
236 #endif /* __HW_CPU_CPU_H */