On 09/12/2013 02:53 PM, Florian Weimer wrote:
By the way, we could generate much better code if the registers were
passed as an array or struct, so that they are in consecutive memory:
struct regs {
unsigned eax, ebx, ecx, edx;
};
void
cpuid(struct regs *r)
{
__asm volatile
("push %%ebx\n\t"
"cpuid\n\t"
"mov %%eax, (%0)\n\t"
"mov %%ebx, 4(%0)\n\t"
"mov %%ecx, 8(%0)\n\t"
"mov %%edx, 12(%0)\n\t"
"pop %%ebx"
:
: "S" (r)
: "eax", "ecx", "edx", "memory");
}
Okay, I forgot to load the %eax register. This version has actually
been tested (on x86_64):
void
cpuid(struct regs *r)
{
__asm volatile
("mov (%0), %%eax\n\t"
"push %%rbx\n\t"
"cpuid\n\t"
"mov %%eax, (%0)\n\t"
"mov %%ebx, 4(%0)\n\t"
"mov %%ecx, 8(%0)\n\t"
"mov %%edx, 12(%0)\n\t"
"pop %%rbx"
:
: "D" (r)
: "eax", "ecx", "edx", "memory");
}
"D" picks the %edi register, which saves another move because it
contains the first function parameter on x86_64.
For the i386 version, replace %rbx with %ebx.
--
Florian Weimer / Red Hat Product Security Team
--
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxxx
https://admin.fedoraproject.org/mailman/listinfo/devel
Fedora Code of Conduct: http://fedoraproject.org/code-of-conduct