diff options
author | Florian Weimer <fweimer@redhat.com> | 2016-03-07 16:45:32 +0100 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2016-03-08 14:54:41 +0100 |
commit | 5a41b86028cd5068d8e74d7481dca60aefeff75d (patch) | |
tree | eec7e38872e8c2cb4af9c62ca33069dcf04dd0fc /libs | |
parent | d35e75554f1f88fac998314a78b03e554a4ded0a (diff) |
fix __cpuid() on x86
The previous version used memory operands that gcc (probably dependent
on optimization flags and/or version) could address relative to the
stack pointer, but pushing %ebx onto the stack changed it. Here, the
address of the regs array is put into %esi and the individual members
are written into directly.
Diffstat (limited to 'libs')
-rw-r--r-- | libs/pbd/fpu.cc | 23 |
1 files changed, 8 insertions, 15 deletions
diff --git a/libs/pbd/fpu.cc b/libs/pbd/fpu.cc index fe2a329439..c72f65d303 100644 --- a/libs/pbd/fpu.cc +++ b/libs/pbd/fpu.cc @@ -48,32 +48,25 @@ FPU* FPU::_instance (0); static void __cpuid(int regs[4], int cpuid_leaf) { - int eax, ebx, ecx, edx; asm volatile ( #if defined(__i386__) "pushl %%ebx;\n\t" #endif - "movl %4, %%eax;\n\t" "cpuid;\n\t" - "movl %%eax, %0;\n\t" - "movl %%ebx, %1;\n\t" - "movl %%ecx, %2;\n\t" - "movl %%edx, %3;\n\t" + "movl %%eax, (%1);\n\t" + "movl %%ebx, 4(%1);\n\t" + "movl %%ecx, 8(%1);\n\t" + "movl %%edx, 12(%1);\n\t" #if defined(__i386__) "popl %%ebx;\n\t" #endif - :"=m" (eax), "=m" (ebx), "=m" (ecx), "=m" (edx) - :"r" (cpuid_leaf) - :"%eax", + :"=a" (cpuid_leaf) /* %eax clobbered by CPUID */ + :"S" (regs), "a" (cpuid_leaf) + : #if !defined(__i386__) "%ebx", #endif - "%ecx", "%edx"); - - regs[0] = eax; - regs[1] = ebx; - regs[2] = ecx; - regs[3] = edx; + "%ecx", "%edx", "memory"); } #endif /* !PLATFORM_WINDOWS */ |