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)