Proper use of x86/x86_64 CPUID instruction with extended assembler

Jeffrey Walton noloader@gmail.com
Wed Aug 19 06:28:00 GMT 2015


Forgive my ignorance....

The following retrieves information from a x86/x86_64 processor. Its
used in an inline assembly block under Linux. The function is also
inlined in a header. The other detail is, its System V ABI, so the
caller owns RBP, RBX and R12-R15 under x86_64 (I'm not sure about the
i386 variant).

    struct CPUIDinfo
    {
        word32 EAX;
        word32 EBX;
        word32 ECX;
        word32 EDX;
    };
    ....

    static inline void CpuId(unsigned int func, unsigned int subfunc,
CPUIDinfo& info)
    {
        __asm__ __volatile__ (
            "cpuid"
            : "=a"(info.EAX), "=b"(info.EBX), "=c"(info.ECX), "=d"(info.EDX)
            : "a"(func), "c"(subfunc)
            : "b"
        );
    }

The CPUID instruction always uses EAX/EBX/ECX/EDX, even on 64-bit
platforms. On 64-bit platforms, the CPUID instruction sets the high
32-bit words of RAX/RBX/RCX.RDX equal to 0.

My question is, will the extended assembly preserve the registers? Is
it sufficient to list "b" as a clobber? Or do I need to do something
special?

If I need to do something special, then what needs to be done?

(I also looked at
https://gcc.gnu.org/ml/gcc-patches/2007-09/msg00324.html, which is a
GCC patch for cpuid.h. But its not clear to me if the above is correct
because the operands are 32-bit in size. Naively, if I use "a" and "b"
with a 32-bit operand, then I would expect code for EAX and EBX; and
not RAX and RBX).

Thanks in advance.



More information about the Gcc-help mailing list