On Thu, Dec 27, 2012 at 9:08 AM, Uros Bizjak <ubiz...@gmail.com> wrote:
> On Wed, Dec 26, 2012 at 9:16 PM, Andi Kleen <a...@firstfloor.org> wrote:
>>> Can you please post a real-world example, where using %r15 would break
>>> existing code?
>>
>> I used to run into problems like this when porting code to gcc from icc or 
>> VC.
>> A lot of hyper optimized inline assembler snippets wants to use all registers
>> and icc/VC support that. With gcc usually had to add some manual
>> push/pops. In older gcc versions usually more than one because reload
>> tended to error out otherwise.
>>
>> So by try and error used the non fixed registers, but let the compiler know
>> about the others. This case would break.
>>
>> In 64bit it was less a problem than on 32bit, but could still happen.
>>
>> Admittedly medium is somewhat obscure and rarely used (and very slow),
>> but someone could be still using it.
>
> The alternative approach is changing cpuid definition in cpuid.h (as
> in attached patch) to preserve %rbx, but we can't detect various code
> model settings there. Since the change depends on the definition of
> __PIC__, we unnecessary preserve %rbx also for -mcmodel=small.
> However, code that involves cpuid is rarely performance critical, so
> perhaps we can live with this tradeoff.
>
> IMO, this patch can be used on 4.7 branch, too.

Now with the patch ...

Uros.
Index: i386/cpuid.h
===================================================================
--- i386/cpuid.h        (revision 194723)
+++ i386/cpuid.h        (working copy)
@@ -132,8 +132,9 @@
 #define signature_VORTEX_ecx   0x436f5320
 #define signature_VORTEX_edx   0x36387865
 
-#if defined(__i386__) && defined(__PIC__)
+#if defined(__PIC__)
 /* %ebx may be the PIC register.  */
+#if defined(__i386__)
 #if __GNUC__ >= 3
 #define __cpuid(level, a, b, c, d)                     \
   __asm__ ("xchg{l}\t{%%}ebx, %1\n\t"                  \
@@ -165,6 +166,21 @@
           : "=a" (a), "=r" (b), "=c" (c), "=d" (d)     \
           : "0" (level), "2" (count))
 #endif
+#elif defined(__x86_64__)
+#define __cpuid(level, a, b, c, d)                     \
+  __asm__ ("xchg{q}\t{%%}rbx, %q1\n\t"                 \
+          "cpuid\n\t"                                  \
+          "xchg{q}\t{%%}rbx, %q1\n\t"                  \
+          : "=a" (a), "=r" (b), "=c" (c), "=d" (d)     \
+          : "0" (level))
+
+#define __cpuid_count(level, count, a, b, c, d)                \
+  __asm__ ("xchg{q}\t{%%}rbx, %q1\n\t"                 \
+          "cpuid\n\t"                                  \
+          "xchg{q}\t{%%}rbx, %q1\n\t"                  \
+          : "=a" (a), "=r" (b), "=c" (c), "=d" (d)     \
+          : "0" (level), "2" (count))
+#endif
 #else
 #define __cpuid(level, a, b, c, d)                     \
   __asm__ ("cpuid\n\t"                                 \

Reply via email to