On Fri, Dec 28, 2012 at 9:27 PM, Richard Henderson <r...@redhat.com> wrote:
> On 12/27/2012 12:08 AM, Uros Bizjak wrote:
>> 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.
>
> Certainly we can.  We also control the preprocessor defines.
> All that's needed is that we create one for the code model.

Something like attached?

I have also included all suggestions (earlyclobber and operand prefix
on temporary register).

2012-12-30  Uros Bizjak  <ubiz...@gmail.com>

        PR target/55712
        * config/i386/i386-c.c (ix86_target_macros_internal): Depending on
        selected code model, define __code_mode_small__, __code_model_medium__,
        __code_model_large__, __code_model_32__ or __code_model_kernel__.
        * config/i386/cpuid.h (__cpuid, __cpuid_count) [__i386__]: Prefix
        xchg temporary register with %k.  Declare temporary register as
        early clobbered.
        [__x86_64__]: For medium and large code models, preserve %rbx register.

Tested on x86_64-pc-linux-gnu {,-m32}.

Uros.
Index: config/i386/cpuid.h
===================================================================
--- config/i386/cpuid.h (revision 194757)
+++ config/i386/cpuid.h (working copy)
@@ -136,35 +136,50 @@
 /* %ebx may be the PIC register.  */
 #if __GNUC__ >= 3
 #define __cpuid(level, a, b, c, d)                     \
-  __asm__ ("xchg{l}\t{%%}ebx, %1\n\t"                  \
+  __asm__ ("xchg{l}\t{%%}ebx, %k1\n\t"                 \
           "cpuid\n\t"                                  \
-          "xchg{l}\t{%%}ebx, %1\n\t"                   \
-          : "=a" (a), "=r" (b), "=c" (c), "=d" (d)     \
+          "xchg{l}\t{%%}ebx, %k1\n\t"                  \
+          : "=a" (a), "=&r" (b), "=c" (c), "=d" (d)    \
           : "0" (level))
 
 #define __cpuid_count(level, count, a, b, c, d)                \
-  __asm__ ("xchg{l}\t{%%}ebx, %1\n\t"                  \
+  __asm__ ("xchg{l}\t{%%}ebx, %k1\n\t"                 \
           "cpuid\n\t"                                  \
-          "xchg{l}\t{%%}ebx, %1\n\t"                   \
-          : "=a" (a), "=r" (b), "=c" (c), "=d" (d)     \
+          "xchg{l}\t{%%}ebx, %k1\n\t"                  \
+          : "=a" (a), "=&r" (b), "=c" (c), "=d" (d)    \
           : "0" (level), "2" (count))
 #else
 /* Host GCCs older than 3.0 weren't supporting Intel asm syntax
    nor alternatives in i386 code.  */
 #define __cpuid(level, a, b, c, d)                     \
-  __asm__ ("xchgl\t%%ebx, %1\n\t"                      \
+  __asm__ ("xchgl\t%%ebx, %k1\n\t"                     \
           "cpuid\n\t"                                  \
-          "xchgl\t%%ebx, %1\n\t"                       \
-          : "=a" (a), "=r" (b), "=c" (c), "=d" (d)     \
+          "xchgl\t%%ebx, %k1\n\t"                      \
+          : "=a" (a), "=&r" (b), "=c" (c), "=d" (d)    \
           : "0" (level))
 
 #define __cpuid_count(level, count, a, b, c, d)                \
-  __asm__ ("xchgl\t%%ebx, %1\n\t"                      \
+  __asm__ ("xchgl\t%%ebx, %k1\n\t"                     \
           "cpuid\n\t"                                  \
-          "xchgl\t%%ebx, %1\n\t"                       \
-          : "=a" (a), "=r" (b), "=c" (c), "=d" (d)     \
+          "xchgl\t%%ebx, %k1\n\t"                      \
+          : "=a" (a), "=&r" (b), "=c" (c), "=d" (d)    \
           : "0" (level), "2" (count))
 #endif
+#elif defined(__x86_64__) && (defined(__code_model_medium__) || 
defined(__code_model_large__)) && defined(__PIC__)
+/* %ebx may be the PIC register.  */
+#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))
 #else
 #define __cpuid(level, a, b, c, d)                     \
   __asm__ ("cpuid\n\t"                                 \
Index: config/i386/i386-c.c
===================================================================
--- config/i386/i386-c.c        (revision 194757)
+++ config/i386/i386-c.c        (working copy)
@@ -243,6 +243,30 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_fla
       break;
     }
 
+  switch (ix86_cmodel)
+    {
+    case CM_SMALL:
+    case CM_SMALL_PIC:
+      def_or_undef (parse_in, "__code_model_small__");
+      break;
+    case CM_MEDIUM:
+    case CM_MEDIUM_PIC:
+      def_or_undef (parse_in, "__code_model_medium__");
+      break;
+    case CM_LARGE:
+    case CM_LARGE_PIC:
+      def_or_undef (parse_in, "__code_model_large__");
+      break;
+    case CM_32:
+      def_or_undef (parse_in, "__code_model_32__");
+      break;
+    case CM_KERNEL:
+      def_or_undef (parse_in, "__code_model_kernel__");
+      break;
+    default:
+      ;
+    }
+
   if (isa_flag & OPTION_MASK_ISA_MMX)
     def_or_undef (parse_in, "__MMX__");
   if (isa_flag & OPTION_MASK_ISA_3DNOW)

Reply via email to