/*
* Copyright © 2010-2012, 2014 Université Bordeaux
* Copyright © 2010 Cisco Systems, Inc. All rights reserved.
* Copyright © 2014 Inria. All rights reserved.
*
* See COPYING in top-level directory.
*/
/* Internals for x86's cpuid. */
#ifndef HWLOC_PRIVATE_CPUID_X86_H
#define HWLOC_PRIVATE_CPUID_X86_H
#if (defined HWLOC_X86_32_ARCH) && (!defined HWLOC_HAVE_MSVC_CPUIDEX)
static __hwloc_inline int hwloc_have_x86_cpuid(void)
{
int ret;
unsigned tmp, tmp2;
__asm__(
"mov $0,%0\n\t" /* Not supported a priori */
"pushfl \n\t" /* Save flags */
"pushfl \n\t" \
"pop %1 \n\t" /* Get flags */ \
#define TRY_TOGGLE \
"xor $0x00200000,%1\n\t" /* Try to toggle ID */ \
"mov %1,%2\n\t" /* Save expected value */ \
"push %1 \n\t" \
"popfl \n\t" /* Try to toggle */ \
"pushfl \n\t" \
"pop %1 \n\t" \
"cmp %1,%2\n\t" /* Compare with expected value */ \
"jnz 0f\n\t" /* Unexpected, failure */ \
TRY_TOGGLE /* Try to set/clear */
TRY_TOGGLE /* Try to clear/set */
"mov $1,%0\n\t" /* Passed the test! */
"0: \n\t"
"popfl \n\t" /* Restore flags */
: "=r" (ret), "=&r" (tmp), "=&r" (tmp2));
return ret;
}
#endif /* !defined HWLOC_X86_32_ARCH && !defined HWLOC_HAVE_MSVC_CPUIDEX*/
#if (defined HWLOC_X86_64_ARCH) || (defined HWLOC_HAVE_MSVC_CPUIDEX)
static __hwloc_inline int hwloc_have_x86_cpuid(void) { return 1; }
#endif /* HWLOC_X86_64_ARCH */
static __hwloc_inline void hwloc_x86_cpuid(unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
{
#ifdef HWLOC_HAVE_MSVC_CPUIDEX
int regs[4];
__cpuidex(regs, *eax, *ecx);
*eax = regs[0];
*ebx = regs[1];
*ecx = regs[2];
*edx = regs[3];
#else /* HWLOC_HAVE_MSVC_CPUIDEX */
/* Note: gcc might want to use bx or the stack for %1 addressing, so we can't
* use them :/ */
#ifdef HWLOC_X86_64_ARCH
hwloc_uint64_t sav_rbx;
__asm__(
"mov %%rbx,%2\n\t"
"cpuid\n\t"
"xchg %2,%%rbx\n\t"
"movl %k2,%1\n\t"
: "+a" (*eax), "=m" (*ebx), "=&r"(sav_rbx),
"+c" (*ecx), "=&d" (*edx));
#elif defined(HWLOC_X86_32_ARCH)
__asm__(
"mov %%ebx,%1\n\t"
"cpuid\n\t"
"xchg %%ebx,%1\n\t"
: "+a" (*eax), "=&SD" (*ebx), "+c" (*ecx), "=&d" (*edx));
#else
#error unknown architecture
#endif
#endif /* HWLOC_HAVE_MSVC_CPUIDEX */
}
#endif /* HWLOC_PRIVATE_X86_CPUID_H */