]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Revert of a previous change.
authorVMware, Inc <>
Thu, 22 Dec 2011 00:33:35 +0000 (16:33 -0800)
committerMarcelo Vanzin <mvanzin@vmware.com>
Thu, 22 Dec 2011 00:33:35 +0000 (16:33 -0800)
Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/include/vm_atomic.h
open-vm-tools/lib/include/vm_basic_asm.h
open-vm-tools/lib/include/vm_basic_asm_x86_64.h
open-vm-tools/lib/include/vm_basic_types.h
open-vm-tools/lib/include/x86cpuid_asm.h

index 594ec8422c527bfabda57e2452819a7c40551776..3e92754f85981d9bbd1c88bd4499a6da9327634d 100644 (file)
@@ -66,6 +66,61 @@ typedef struct  Atomic_uint64 {
 } Atomic_uint64 ALIGNED(8);
 
 
+/*
+ * Prototypes for msft atomics.  These are defined & inlined by the
+ * compiler so no function definition is needed.  The prototypes are
+ * needed for c++.  Since amd64 compiler doesn't support inline asm we
+ * have to use these.  Unfortunately, we still have to use some inline asm
+ * for the 32 bit code since the and/or/xor implementations didn't show up
+ * untill xp or 2k3.
+ *
+ * The declarations for the intrinsic functions were taken from ntddk.h
+ * in the DDK. The declarations must match otherwise the 64-bit c++
+ * compiler will complain about second linkage of the intrinsic functions.
+ * We define the intrinsic using the basic types corresponding to the
+ * Windows typedefs. This avoids having to include windows header files
+ * to get to the windows types.
+ */
+#if defined(_MSC_VER) && _MSC_VER >= 1310
+#ifdef __cplusplus
+extern "C" {
+#endif
+long  _InterlockedExchange(long volatile*, long);
+long  _InterlockedCompareExchange(long volatile*, long, long);
+long  _InterlockedExchangeAdd(long volatile*, long);
+long  _InterlockedDecrement(long volatile*);
+long  _InterlockedIncrement(long volatile*);
+#pragma intrinsic(_InterlockedExchange, _InterlockedCompareExchange)
+#pragma intrinsic(_InterlockedExchangeAdd, _InterlockedDecrement)
+#pragma intrinsic(_InterlockedIncrement)
+
+#if defined(VM_X86_64)
+long     _InterlockedAnd(long volatile*, long);
+__int64  _InterlockedAnd64(__int64 volatile*, __int64);
+long     _InterlockedOr(long volatile*, long);
+__int64  _InterlockedOr64(__int64 volatile*, __int64);
+long     _InterlockedXor(long volatile*, long);
+__int64  _InterlockedXor64(__int64 volatile*, __int64);
+__int64  _InterlockedExchangeAdd64(__int64 volatile*, __int64);
+__int64  _InterlockedIncrement64(__int64 volatile*);
+__int64  _InterlockedDecrement64(__int64 volatile*);
+__int64  _InterlockedExchange64(__int64 volatile*, __int64);
+__int64  _InterlockedCompareExchange64(__int64 volatile*, __int64, __int64);
+#if !defined(_WIN64)
+#pragma intrinsic(_InterlockedAnd, _InterlockedAnd64)
+#pragma intrinsic(_InterlockedOr, _InterlockedOr64)
+#pragma intrinsic(_InterlockedXor, _InterlockedXor64)
+#pragma intrinsic(_InterlockedExchangeAdd64, _InterlockedIncrement64)
+#pragma intrinsic(_InterlockedDecrement64, _InterlockedExchange64)
+#pragma intrinsic(_InterlockedCompareExchange64)
+#endif /* !_WIN64 */
+#endif /* __x86_64__ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _MSC_VER */
+
 /*
  * LDREX without STREX or CLREX may cause problems in environments where the
  * context switch may not clear the reference monitor - according ARM manual
@@ -345,8 +400,20 @@ Atomic_ReadWrite(Atomic_uint32 *var, // IN
    return val;
 #endif // VM_ARM_V7
 #elif defined _MSC_VER
+#if _MSC_VER >= 1310
    return _InterlockedExchange((long *)&var->value, (long)val);
 #else
+#pragma warning(push)
+#pragma warning(disable : 4035)         // disable no-return warning
+   {
+      __asm mov eax, val
+      __asm mov ebx, var
+      __asm xchg [ebx]Atomic_uint32.value, eax
+      // eax is the return value, this is documented to work - edward
+   }
+#pragma warning(pop)
+#endif // _MSC_VER >= 1310
+#else
 #error No compiler defined for Atomic_ReadWrite
 #endif // __GNUC__
 }
@@ -412,9 +479,24 @@ Atomic_ReadIfEqualWrite(Atomic_uint32 *var, // IN
    return val;
 #endif // VM_ARM_V7
 #elif defined _MSC_VER
+#if _MSC_VER >= 1310
    return _InterlockedCompareExchange((long *)&var->value,
                                      (long)newVal,
                                      (long)oldVal);
+#else
+#pragma warning(push)
+#pragma warning(disable : 4035)         // disable no-return warning
+   {
+      __asm mov eax, oldVal
+      __asm mov ebx, var
+      __asm mov ecx, newVal
+      __asm lock cmpxchg [ebx]Atomic_uint32.value, ecx
+      // eax is the return value, this is documented to work - edward
+   }
+#pragma warning(pop)
+#endif
+#else
+#error No compiler defined for Atomic_ReadIfEqualWrite
 #endif
 }
 #define Atomic_ReadIfEqualWrite32 Atomic_ReadIfEqualWrite
@@ -541,7 +623,13 @@ Atomic_And(Atomic_uint32 *var, // IN
    AtomicEpilogue();
 #endif // VM_ARM_V7
 #elif defined _MSC_VER
+#if defined(__x86_64__)
    _InterlockedAnd((long *)&var->value, (long)val);
+#else
+   __asm mov eax, val
+   __asm mov ebx, var
+   __asm lock and [ebx]Atomic_uint32.value, eax
+#endif
 #else
 #error No compiler defined for Atomic_And
 #endif
@@ -599,7 +687,13 @@ Atomic_Or(Atomic_uint32 *var, // IN
    AtomicEpilogue();
 #endif // VM_ARM_V7
 #elif defined _MSC_VER
+#if defined(__x86_64__)
    _InterlockedOr((long *)&var->value, (long)val);
+#else
+   __asm mov eax, val
+   __asm mov ebx, var
+   __asm lock or [ebx]Atomic_uint32.value, eax
+#endif
 #else
 #error No compiler defined for Atomic_Or
 #endif
@@ -657,7 +751,13 @@ Atomic_Xor(Atomic_uint32 *var, // IN
    AtomicEpilogue();
 #endif // VM_ARM_V7
 #elif defined _MSC_VER
+#if defined(__x86_64__)
    _InterlockedXor((long *)&var->value, (long)val);
+#else
+   __asm mov eax, val
+   __asm mov ebx, var
+   __asm lock xor [ebx]Atomic_uint32.value, eax
+#endif
 #else
 #error No compiler defined for Atomic_Xor
 #endif
@@ -754,7 +854,13 @@ Atomic_Add(Atomic_uint32 *var, // IN
    AtomicEpilogue();
 #endif // VM_ARM_V7
 #elif defined _MSC_VER
+#if _MSC_VER >= 1310
    _InterlockedExchangeAdd((long *)&var->value, (long)val);
+#else
+   __asm mov eax, val
+   __asm mov ebx, var
+   __asm lock add [ebx]Atomic_uint32.value, eax
+#endif
 #else
 #error No compiler defined for Atomic_Add
 #endif
@@ -851,7 +957,13 @@ Atomic_Sub(Atomic_uint32 *var, // IN
    AtomicEpilogue();
 #endif // VM_ARM_V7
 #elif defined _MSC_VER
+#if _MSC_VER >= 1310
    _InterlockedExchangeAdd((long *)&var->value, (long)-val);
+#else
+   __asm mov eax, val
+   __asm mov ebx, var
+   __asm lock sub [ebx]Atomic_uint32.value, eax
+#endif
 #else
 #error No compiler defined for Atomic_Sub
 #endif
@@ -931,7 +1043,12 @@ Atomic_Inc(Atomic_uint32 *var) // IN
    AtomicEpilogue();
 #endif // VM_ARM_V7
 #elif defined _MSC_VER
+#if _MSC_VER >= 1310
    _InterlockedIncrement((long *)&var->value);
+#else
+   __asm mov ebx, var
+   __asm lock inc [ebx]Atomic_uint32.value
+#endif
 #else
 #error No compiler defined for Atomic_Inc
 #endif
@@ -972,7 +1089,12 @@ Atomic_Dec(Atomic_uint32 *var) // IN
    AtomicEpilogue();
 #endif // VM_ARM_V7
 #elif defined _MSC_VER
+#if _MSC_VER >= 1310
    _InterlockedDecrement((long *)&var->value);
+#else
+   __asm mov ebx, var
+   __asm lock dec [ebx]Atomic_uint32.value
+#endif
 #else
 #error No compiler defined for Atomic_Dec
 #endif
@@ -1169,8 +1291,19 @@ Atomic_FetchAndAddUnfenced(Atomic_uint32 *var, // IN
    return val;
 #endif // VM_ARM_V7
 #elif defined _MSC_VER
+#if _MSC_VER >= 1310
    return _InterlockedExchangeAdd((long *)&var->value, (long)val);
 #else
+#pragma warning(push)
+#pragma warning(disable : 4035)         // disable no-return warning
+   {
+      __asm mov eax, val
+      __asm mov ebx, var
+      __asm lock xadd [ebx]Atomic_uint32.value, eax
+   }
+#pragma warning(pop)
+#endif
+#else
 #error No compiler defined for Atomic_FetchAndAdd
 #endif
 }
@@ -1542,10 +1675,29 @@ Atomic_CMPXCHG64(Atomic_uint64 *var,   // IN/OUT
    return equal;
 #endif //VM_ARM_V7
 #elif defined _MSC_VER
+#if defined(__x86_64__)
    return (__int64)*oldVal == _InterlockedCompareExchange64((__int64 *)&var->value,
                                                             (__int64)*newVal,
                                                             (__int64)*oldVal);
 #else
+#pragma warning(push)
+#pragma warning(disable : 4035)                // disable no-return warning
+   {
+      __asm mov esi, var
+      __asm mov edx, oldVal
+      __asm mov ecx, newVal
+      __asm mov eax, [edx]S_uint64.lowValue
+      __asm mov edx, [edx]S_uint64.highValue
+      __asm mov ebx, [ecx]S_uint64.lowValue
+      __asm mov ecx, [ecx]S_uint64.highValue
+      __asm lock cmpxchg8b [esi]
+      __asm sete al
+      __asm movzx eax, al
+      // eax is the return value, this is documented to work - edward
+   }
+#pragma warning(pop)
+#endif
+#else
 #error No compiler defined for Atomic_CMPXCHG64
 #endif // !GNUC
 }
@@ -1663,7 +1815,6 @@ Atomic_Read64(Atomic_uint64 const *var) // IN
     */
    return var->value;
 #elif defined (_MSC_VER) && defined(__i386__)
-// _InterlockedCompareExchange64 is not optimal here, see the comment for gcc.
 #   pragma warning(push)
 #   pragma warning(disable : 4035)             // disable no-return warning
    {
@@ -2107,8 +2258,12 @@ Atomic_SetBit64(Atomic_uint64 *var, // IN/OUT
    );
    AtomicEpilogue();
 #elif defined _MSC_VER
-   // It also works as a memory barrier for MSVC (_ReadWriteBarrier).
-   _interlockedbittestandset64((__int64*)&var->value, (__int64)bit);
+   uint64 oldVal;
+   uint64 newVal;
+   do {
+      oldVal = var->value;
+      newVal = oldVal | (CONST64U(1) << bit);
+   } while (!Atomic_CMPXCHG64(var, &oldVal, &newVal));
 #else
 #error No compiler defined for Atomic_SetBit64
 #endif
@@ -2154,8 +2309,12 @@ Atomic_ClearBit64(Atomic_uint64 *var, // IN/OUT
    );
    AtomicEpilogue();
 #elif defined _MSC_VER
-   // It also works as a memory barrier for MSVC (_ReadWriteBarrier).
-   _interlockedbittestandreset64((__int64*) &var->value, (__int64)bit);
+   uint64 oldVal;
+   uint64 newVal;
+   do {
+      oldVal = var->value;
+      newVal = oldVal & ~(CONST64U(1) << bit);
+   } while (!Atomic_CMPXCHG64(var, &oldVal, &newVal));
 #else
 #error No compiler defined for Atomic_ClearBit64
 #endif
@@ -2203,7 +2362,7 @@ Atomic_TestBit64(Atomic_uint64 *var, // IN
    );
    return out;
 #elif defined _MSC_VER
-   return _bittest64((__int64*)&var->value, (__int64)bit);
+   return (var->value & (CONST64U(1) << bit)) != 0;
 #else
 #error No compiler defined for Atomic_TestBit64
 #endif
index b62cb88ef54661421bad021cde2b2d5cd912adee..b47c94d2fa194a29f77c6a98562ba6fac8b12e61 100644 (file)
 #include "vm_basic_asm_x86.h"
 #endif
 
+/*
+ * x86-64 windows doesn't support inline asm so we have to use these
+ * intrinsic functions defined in the compiler.  Not all of these are well
+ * documented.  There is an array in the compiler dll (c1.dll) which has
+ * an array of the names of all the intrinsics minus the leading
+ * underscore.  Searching around in the ntddk.h file can also be helpful.
+ *
+ * The declarations for the intrinsic functions were taken from the DDK. 
+ * Our declarations must match the ddk's otherwise the 64-bit c++ compiler
+ * will complain about second linkage of the intrinsic functions.
+ * We define the intrinsic using the basic types corresponding to the 
+ * Windows typedefs. This avoids having to include windows header files
+ * to get to the windows types.
+ */
+#ifdef _MSC_VER
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * It seems x86 & x86-64 windows still implements these intrinsic
+ * functions.  The documentation for the x86-64 suggest the
+ * __inbyte/__outbyte intrinsics even though the _in/_out work fine and
+ * __inbyte/__outbyte aren't supported on x86.
+ */
+int            _inp(unsigned short);
+unsigned short _inpw(unsigned short);
+unsigned long  _inpd(unsigned short);
+
+int            _outp(unsigned short, int);
+unsigned short _outpw(unsigned short, unsigned short);
+unsigned long  _outpd(uint16, unsigned long);
+#pragma intrinsic(_inp, _inpw, _inpd, _outp, _outpw, _outpw, _outpd)
+
+/*
+ * Prevents compiler from re-ordering reads, writes and reads&writes.
+ * These functions do not add any instructions thus only affect
+ * the compiler ordering.
+ *
+ * See:
+ * `Lockless Programming Considerations for Xbox 360 and Microsoft Windows'
+ * http://msdn.microsoft.com/en-us/library/bb310595(VS.85).aspx
+ */
+void _ReadBarrier(void);
+void _WriteBarrier(void);
+void _ReadWriteBarrier(void);
+#pragma intrinsic(_ReadBarrier, _WriteBarrier, _ReadWriteBarrier)
+
+void _mm_mfence(void);
+void _mm_lfence(void);
+#pragma intrinsic(_mm_mfence, _mm_lfence)
+
+#ifdef VM_X86_64
+/*
+ * intrinsic functions only supported by x86-64 windows as of 2k3sp1
+ */
+unsigned __int64 __rdtsc(void);
+void             __stosw(unsigned short *, unsigned short, size_t);
+void             __stosd(unsigned long *, unsigned long, size_t);
+void             _mm_pause(void);
+#pragma intrinsic(__rdtsc, __stosw, __stosd, _mm_pause)
+
+unsigned char  _BitScanForward64(unsigned long *, unsigned __int64);
+unsigned char  _BitScanReverse64(unsigned long *, unsigned __int64);
+#pragma intrinsic(_BitScanForward64, _BitScanReverse64)
+#endif /* VM_X86_64 */
+
+unsigned char  _BitScanForward(unsigned long *, unsigned long);
+unsigned char  _BitScanReverse(unsigned long *, unsigned long);
+#pragma intrinsic(_BitScanForward, _BitScanReverse)
+
+unsigned char  _bittestandset(long *, long);
+unsigned char  _bittestandreset(long *, long);
+#pragma intrinsic(_bittestandset, _bittestandreset)
+#ifdef VM_X86_64
+unsigned char  _bittestandset64(__int64 *, __int64);
+unsigned char  _bittestandreset64(__int64 *, __int64);
+#pragma intrinsic(_bittestandset64, _bittestandreset64)
+#endif /* VM_X86_64 */
+#ifdef __cplusplus
+}
+#endif
+#endif /* _MSC_VER */
+
 
 #ifdef __GNUC__ // {
 #if defined(__i386__) || defined(__x86_64__) // Only on x86*
@@ -113,40 +196,55 @@ __GCC_IN(l, uint32, IN32)
 #define OUTW(port, val) __GCC_OUT(w, w, port, val)
 #define OUT32(port, val) __GCC_OUT(l, , port, val)
 
+#define GET_CURRENT_EIP(_eip) \
+      __asm__ __volatile("call 0\n\tpopl %0" : "=r" (_eip): );
+
 #endif // x86*
 
 #elif defined(_MSC_VER) // } {
 static INLINE  uint8
 INB(uint16 port)
 {
-   return __inbyte(port);
+   return (uint8)_inp(port);
 }
 static INLINE void
 OUTB(uint16 port, uint8 value)
 {
-   __outbyte(port, value);
+   _outp(port, value);
 }
 static INLINE uint16
 INW(uint16 port)
 {
-   return __inword(port);
+   return _inpw(port);
 }
 static INLINE void
 OUTW(uint16 port, uint16 value)
 {
-   __outword(port, value);
+   _outpw(port, value);
 }
 static INLINE  uint32
 IN32(uint16 port)
 {
-   return __indword(port);
+   return _inpd(port);
 }
 static INLINE void
 OUT32(uint16 port, uint32 value)
 {
-   __outdword(port, value);
+   _outpd(port, value);
 }
 
+#ifndef VM_X86_64
+#ifdef NEAR
+#undef NEAR
+#endif
+
+#define GET_CURRENT_EIP(_eip) do { \
+   __asm call NEAR PTR $+5 \
+   __asm pop eax \
+   __asm mov _eip, eax \
+} while (0)
+#endif // VM_X86_64
+
 #else // } {
 #error
 #endif // }
@@ -576,14 +674,36 @@ uint32set(void *dst, uint32 val, size_t count)
 static INLINE void *
 uint16set(void *dst, uint16 val, size_t count)
 {
+#ifdef VM_X86_64
    __stosw((uint16*)dst, val, count);
+#else
+   __asm { pushf;
+           mov ax, val;
+           mov ecx, count;
+           mov edi, dst;
+           cld;
+           rep stosw;
+           popf;
+   }
+#endif
    return dst;
 }
 
 static INLINE void *
 uint32set(void *dst, uint32 val, size_t count)
 {
+#ifdef VM_X86_64
    __stosd((unsigned long*)dst, (unsigned long)val, count);
+#else
+   __asm { pushf;
+           mov eax, val;
+           mov ecx, count;
+           mov edi, dst;
+           cld;
+           rep stosd;
+           popf;
+   }
+#endif
    return dst;
 }
 
@@ -696,9 +816,17 @@ PAUSE(void)
 #endif
 }
 #elif defined(_MSC_VER)
+#ifdef VM_X86_64
 {
    _mm_pause();
 }
+#else /* VM_X86_64 */
+#pragma warning( disable : 4035)
+{
+   __asm _emit 0xf3 __asm _emit 0x90
+}
+#pragma warning (default: 4035)
+#endif /* VM_X86_64 */
 #else  /* __GNUC__  */
 #error No compiler defined for PAUSE
 #endif
@@ -740,9 +868,17 @@ RDTSC(void)
 #endif
 }
 #elif defined(_MSC_VER)
+#ifdef VM_X86_64
 {
    return __rdtsc();
 }
+#else
+#pragma warning( disable : 4035)
+{
+   __asm _emit 0x0f __asm _emit 0x31
+}
+#pragma warning (default: 4035)
+#endif /* VM_X86_64 */
 #else  /* __GNUC__  */
 #error No compiler defined for RDTSC
 #endif /* __GNUC__  */
index 1e27a779c18e3e8c17c2ff5d001f3a602441d6ba..64d95122c5001b8f6020fc93a147e9e346a42094 100644 (file)
 #error "This file is x86-64 only!"
 #endif
 
+#ifdef _MSC_VER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+uint64 _umul128(uint64 multiplier, uint64 multiplicand, 
+                uint64 *highProduct);
+int64 _mul128(int64 multiplier, int64 multiplicand, 
+              int64 *highProduct);
+uint64 __shiftright128(uint64 lowPart, uint64 highPart, uint8 shift);
+#ifdef __cplusplus
+}
+#endif
+
+#pragma intrinsic(_umul128, _mul128, __shiftright128)
+
+#endif // _MSC_VER
+
 /*
  * GET_CURRENT_RIP
  *
index df53e16e08b25fa54fcebb63a54e5c06e8cbdd65..f871d474f59f24738056f04fad4730ae6911cce1 100644 (file)
@@ -134,42 +134,6 @@ typedef char           Bool;
 
 #endif
 
-// Intrinsic funtions. WDK/DDK has its own pragmas for intrinsic functions.
-#if defined(_MSC_VER) && !defined (WINNT_DDK)
-#ifndef _IVEC_H_INCLUDED
-#define _IVEC_H_INCLUDED
-#define _IVEC_H_INCLUDED_2
-#endif
-
-#ifndef _FVEC_H_INCLUDED
-#define _FVEC_H_INCLUDED
-#define _FVEC_H_INCLUDED_2
-#endif
-
-#ifndef _DVEC_H_INCLUDED
-#define _DVEC_H_INCLUDED
-#define _DVEC_H_INCLUDED_2
-#endif
-
-#include <intrin.h> 
-
-#ifdef _IVEC_H_INCLUDED_2
-#undef _IVEC_H_INCLUDED
-#undef _IVEC_H_INCLUDED_2
-#endif
-
-#ifdef _FVEC_H_INCLUDED_2
-#undef _FVEC_H_INCLUDED
-#undef _FVEC_H_INCLUDED_2
-#endif
-
-#ifdef _DVEC_H_INCLUDED_2
-#undef _DVEC_H_INCLUDED
-#undef _DVEC_H_INCLUDED_2
-#endif
-#endif /* _MSC_VER */
-
-
 #if defined(__APPLE__) || defined(HAVE_STDINT_H)
 
 /*
index 1de11615d23ae17388751175cfff5eff2cc85d47..a3b5e484cecb6c8d5755555707d139da7926c91c 100644 (file)
 #define INCLUDE_ALLOW_VMCORE
 #include "includeCheck.h"
 
-#include "vm_basic_types.h"
 #include "vm_basic_asm.h"
 #include "x86cpuid.h"
 
 
+/*
+ * x86-64 windows doesn't support inline asm so we have to use these
+ * intrinsic functions defined in the compiler.  Not all of these are well
+ * documented.  There is an array in the compiler dll (c1.dll) which has
+ * an array of the names of all the intrinsics minus the leading
+ * underscore.  Searching around in the ntddk.h file can also be helpful.
+ *
+ * The declarations for the intrinsic functions were taken from the DDK. 
+ * Our declarations must match the ddk's otherwise the 64-bit c++ compiler
+ * will complain about second linkage of the intrinsic functions.
+ * We define the intrinsic using the basic types corresponding to the 
+ * Windows typedefs. This avoids having to include windows header files
+ * to get to the windows types.
+ */
+#ifdef _MSC_VER
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef VM_X86_64
+/*
+ * intrinsic functions only supported by x86-64 windows as of 2k3sp1
+ */
+void             __cpuid(unsigned int*, unsigned int);
+#pragma intrinsic(__cpuid)
+#endif /* VM_X86_64 */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _MSC_VER */
+
+
 #ifdef __GNUC__ // {
 
 /*
@@ -205,55 +236,209 @@ __GET_EAX_FROM_CPUID4(int ecx) // IN
 static INLINE void
 __GET_CPUID(int input, CPUIDRegs *regs)
 {
-   __cpuid((int *)regs, input);
+#ifdef VM_X86_64
+   __cpuid((unsigned int *)regs, input);
+#else
+   __asm push esi
+   __asm push ebx
+   __asm push ecx
+   __asm push edx
+
+   __asm mov  eax, input
+   __asm mov  esi, regs
+   __asm _emit 0x0f __asm _emit 0xa2
+   __asm mov 0x0[esi], eax
+   __asm mov 0x4[esi], ebx
+   __asm mov 0x8[esi], ecx
+   __asm mov 0xC[esi], edx
+
+   __asm pop edx
+   __asm pop ecx
+   __asm pop ebx
+   __asm pop esi
+#endif
 }
 
+#ifdef VM_X86_64
+
+/*
+ * No inline assembly in Win64. Implemented in bora/lib/misc in
+ * cpuidMasm64.asm.
+ */
+
+extern void
+__GET_CPUID2(int inputEax, int inputEcx, CPUIDRegs *regs);
+
+#else // VM_X86_64
+
 static INLINE void
 __GET_CPUID2(int inputEax, int inputEcx, CPUIDRegs *regs)
 {
-   __cpuidex((int *)regs, inputEax, inputEcx);
+   __asm push esi
+   __asm push ebx
+   __asm push ecx
+   __asm push edx
+
+   __asm mov  eax, inputEax
+   __asm mov  ecx, inputEcx
+   __asm mov  esi, regs
+   __asm _emit 0x0f __asm _emit 0xa2
+   __asm mov 0x0[esi], eax
+   __asm mov 0x4[esi], ebx
+   __asm mov 0x8[esi], ecx
+   __asm mov 0xC[esi], edx
+
+   __asm pop edx
+   __asm pop ecx
+   __asm pop ebx
+   __asm pop esi
 }
+#endif
 
 static INLINE uint32
 __GET_EAX_FROM_CPUID(int input)
 {
+#ifdef VM_X86_64
    CPUIDRegs regs;
-   __cpuid((int *)&regs, input);
+   __cpuid((unsigned int *)&regs, input);
    return regs.eax;
+#else
+   uint32 output;
+
+   //NOT_TESTED();
+   __asm push ebx
+   __asm push ecx
+   __asm push edx
+
+   __asm mov  eax, input
+   __asm _emit 0x0f __asm _emit 0xa2
+   __asm mov  output, eax
+
+   __asm pop edx
+   __asm pop ecx
+   __asm pop ebx
+
+   return output;
+#endif
 }
 
 static INLINE uint32
 __GET_EBX_FROM_CPUID(int input)
 {
+#ifdef VM_X86_64
    CPUIDRegs regs;
-   __cpuid((int *)&regs, input);
+   __cpuid((unsigned int *)&regs, input);
    return regs.ebx;
+#else
+   uint32 output;
+
+   //NOT_TESTED();
+   __asm push ebx
+   __asm push ecx
+   __asm push edx
+
+   __asm mov  eax, input
+   __asm _emit 0x0f __asm _emit 0xa2
+   __asm mov  output, ebx
+
+   __asm pop edx
+   __asm pop ecx
+   __asm pop ebx
+
+   return output;
+#endif
 }
 
 static INLINE uint32
 __GET_ECX_FROM_CPUID(int input)
 {
+#ifdef VM_X86_64
    CPUIDRegs regs;
-   __cpuid((int *)&regs, input);
+   __cpuid((unsigned int *)&regs, input);
    return regs.ecx;
+#else
+   uint32 output;
+
+   //NOT_TESTED();
+   __asm push ebx
+   __asm push ecx
+   __asm push edx
+
+   __asm mov  eax, input
+   __asm _emit 0x0f __asm _emit 0xa2
+   __asm mov  output, ecx
+
+   __asm pop edx
+   __asm pop ecx
+   __asm pop ebx
+
+   return output;
+#endif
 }
 
 static INLINE uint32
 __GET_EDX_FROM_CPUID(int input)
 {
+#ifdef VM_X86_64
    CPUIDRegs regs;
-   __cpuid(( int *)&regs, input);
+   __cpuid((unsigned int *)&regs, input);
    return regs.edx;
+#else
+   uint32 output;
+
+   //NOT_TESTED();
+   __asm push ebx
+   __asm push ecx
+   __asm push edx
+
+   __asm mov  eax, input
+   __asm _emit 0x0f __asm _emit 0xa2
+   __asm mov  output, edx
+
+   __asm pop edx
+   __asm pop ecx
+   __asm pop ebx
+
+   return output;
+#endif
 }
 
+#ifdef VM_X86_64
+
+/*
+ * No inline assembly in Win64. Implemented in bora/lib/misc in
+ * cpuidMasm64.asm.
+ */
+
+extern uint32
+__GET_EAX_FROM_CPUID4(int inputEcx);
+
+#else // VM_X86_64
+
 static INLINE uint32
 __GET_EAX_FROM_CPUID4(int inputEcx)
 {
-   CPUIDRegs regs;
-   __GET_CPUID2(4, inputEcx, &regs);
-   return regs.eax;
+   uint32 output;
+
+   //NOT_TESTED();
+   __asm push ebx
+   __asm push ecx
+   __asm push edx
+
+   __asm mov  eax, 4
+   __asm mov  ecx, inputEcx
+   __asm _emit 0x0f __asm _emit 0xa2
+   __asm mov  output, eax
+
+   __asm pop edx
+   __asm pop ecx
+   __asm pop ebx
+
+   return output;
 }
 
+#endif // VM_X86_64
+
 #else // }
 #error 
 #endif