diff --git a/src/asmjit/x86/x86cpuinfo.cpp b/src/asmjit/x86/x86cpuinfo.cpp index 7b2583b..bd36dde 100644 --- a/src/asmjit/x86/x86cpuinfo.cpp +++ b/src/asmjit/x86/x86cpuinfo.cpp @@ -99,15 +99,19 @@ union X86XCR { // callCpuId() and detectCpuInfo() for x86 and x64 platforms begins here. #if defined(ASMJIT_ARCH_X86) || defined(ASMJIT_ARCH_X64) -void X86CpuUtil::callCpuId(uint32_t inEax, uint32_t inEcx, X86CpuId* result) { +void X86CpuUtil::_docpuid(uint32_t inEcx, uint32_t inEax, X86CpuId* result) { #if defined(_MSC_VER) -// 2009-02-05: Thanks to Mike Tajmajer for supporting VC7.1 compiler. -// ASMJIT_ARCH_X64 is here only for readibility, only VS2005 can compile 64-bit code. -# if _MSC_VER >= 1400 || defined(ASMJIT_ARCH_X64) - // Done by intrinsics. +// __cpuidex was introduced by VS2008-SP1. +# if _MSC_FULL_VER >= 150030729 __cpuidex(reinterpret_cast(result->i), inEax, inEcx); -# else // _MSC_VER < 1400 +# elif defined(ASMJIT_ARCH_X64) + // VS2008 or less, 64-bit mode - `__cpuidex` doesn't exist! However, 64-bit + // calling convention specifies parameter to be passed in ECX/RCX, so we may + // be lucky if compiler doesn't move the register, otherwise the result is + // undefined. + __cpuid(reinterpret_cast(result->i), inEax); +# else uint32_t cpuid_eax = inEax; uint32_t cpuid_ecx = inEcx; uint32_t* cpuid_out = result->i; @@ -122,7 +126,7 @@ void X86CpuUtil::callCpuId(uint32_t inEax, uint32_t inEcx, X86CpuId* result) { mov dword ptr[edi + 8], ecx mov dword ptr[edi + 12], edx } -# endif // _MSC_VER < 1400 +# endif #elif defined(__GNUC__) // Note, patched to preserve ebx/rbx register which is used by GCC. @@ -144,10 +148,13 @@ void X86CpuUtil::callCpuId(uint32_t inEax, uint32_t inEcx, X86CpuId* result) { : "a" (inEax), "c" (inEcx)) # endif __myCpuId(inEax, inEcx, result->eax, result->ebx, result->ecx, result->edx); -#endif // COMPILER + +#else +# error "asmjit::X86CpuUtil::_docpuid() unimplemented!" +#endif } -static void callXGetBV(uint32_t inEcx, X86XCR* result) { +static void callXGetBV(X86XCR* result, uint32_t inEcx) { #if defined(_MSC_VER) @@ -197,7 +204,7 @@ void X86CpuUtil::detect(X86CpuInfo* cpuInfo) { // -------------------------------------------------------------------------- // Get vendor string/id. - callCpuId(0x0, 0x0, ®s); + callCpuId(®s, 0x0); maxBaseId = regs.eax; ::memcpy(cpuInfo->_vendorString, ®s.ebx, 4); @@ -217,7 +224,7 @@ void X86CpuUtil::detect(X86CpuInfo* cpuInfo) { if (maxBaseId >= 0x1) { // Get feature flags in ECX/EDX and family/model in EAX. - callCpuId(0x1, 0x0, ®s); + callCpuId(®s, 0x1); // Fill family and model fields. cpuInfo->_family = (regs.eax >> 8) & 0x0F; @@ -266,7 +273,7 @@ void X86CpuUtil::detect(X86CpuInfo* cpuInfo) { // Get the content of XCR0 if supported by CPU and enabled by OS. if ((regs.ecx & 0x0C000000U) == 0x0C000000U) { - callXGetBV(0, &xcr0); + callXGetBV(&xcr0, 0); } // Detect AVX+. @@ -290,7 +297,7 @@ void X86CpuUtil::detect(X86CpuInfo* cpuInfo) { // Detect new features if the processor supports CPUID-07. if (maxBaseId >= 0x7) { - callCpuId(0x7, 0x0, ®s); + callCpuId(®s, 0x7); if (regs.ebx & 0x00000001U) cpuInfo->addFeature(kX86CpuFeatureFSGSBase); if (regs.ebx & 0x00000008U) cpuInfo->addFeature(kX86CpuFeatureBMI); @@ -335,7 +342,7 @@ void X86CpuUtil::detect(X86CpuInfo* cpuInfo) { // -------------------------------------------------------------------------- if (maxBaseId >= 0xD && maybeMPX) { - callCpuId(0xD, 0x0, ®s); + callCpuId(®s, 0xD); // Both CPUID result and XCR0 has to be enabled to have support for MPX. if (((regs.eax & xcr0.eax) & 0x00000018U) == 0x00000018U) { @@ -349,13 +356,13 @@ void X86CpuUtil::detect(X86CpuInfo* cpuInfo) { // Calling cpuid with 0x80000000 as the in argument gets the number of valid // extended IDs. - callCpuId(0x80000000, 0x0, ®s); + callCpuId(®s, 0x80000000); uint32_t maxExtId = IntUtil::iMin(regs.eax, 0x80000004); uint32_t* brand = reinterpret_cast(cpuInfo->_brandString); for (i = 0x80000001; i <= maxExtId; i++) { - callCpuId(i, 0x0, ®s); + callCpuId(®s, i); switch (i) { case 0x80000001: diff --git a/src/asmjit/x86/x86cpuinfo.h b/src/asmjit/x86/x86cpuinfo.h index 96e1962..8268ef2 100644 --- a/src/asmjit/x86/x86cpuinfo.h +++ b/src/asmjit/x86/x86cpuinfo.h @@ -181,8 +181,16 @@ union X86CpuId { #if defined(ASMJIT_ARCH_X86) || defined(ASMJIT_ARCH_X64) //! CPU utilities available only if the host processor is X86/X64. struct X86CpuUtil { + //! \internal + //! + //! Designed to support VS2008 and less in 64-bit mode, even if this compiler + //! doesn't have `__cpuidex` intrinsic. + ASMJIT_API static void _docpuid(uint32_t inEcx, uint32_t inEax, X86CpuId* out); + //! Get the result of calling CPUID instruction to `out`. - ASMJIT_API static void callCpuId(uint32_t inEax, uint32_t inEcx, X86CpuId* out); + static ASMJIT_INLINE void callCpuId(X86CpuId* out, uint32_t inEax, uint32_t inEcx = 0) { + return _docpuid(inEcx, inEax, out); + } //! Detect the Host CPU. ASMJIT_API static void detect(X86CpuInfo* cpuInfo);