From c81acb7ff39d5b783548b07ed6d2cc0c3a7b7195 Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko <phcoder@gmail.com>
Date: Sun, 27 Oct 2013 00:02:01 +0200
Subject: [PATCH] 	Consolidate cpuid code.

---
 ChangeLog                          |  4 +++
 grub-core/efiemu/i386/coredetect.c | 36 ++-------------------------
 grub-core/kern/i386/tsc.c          | 49 +++++--------------------------------
 grub-core/loader/i386/xnu.c        | 50 +++-----------------------------------
 include/grub/i386/cpuid.h          |  7 ++++++
 5 files changed, 22 insertions(+), 124 deletions(-)

Index: grub-2.00/grub-core/efiemu/i386/coredetect.c
===================================================================
--- grub-2.00.orig/grub-core/efiemu/i386/coredetect.c
+++ grub-2.00/grub-core/efiemu/i386/coredetect.c
@@ -18,42 +18,10 @@
 
 #include <grub/efiemu/efiemu.h>
 #include <grub/command.h>
-
-#define cpuid(num,a,b,c,d) \
-  asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
-		: "=a" (a), "=r" (b), "=c" (c), "=d" (d)  \
-		: "0" (num))
-
-#define bit_LM (1 << 29)
+#include <grub/i386/cpuid.h>
 
 const char *
 grub_efiemu_get_default_core_name (void)
 {
-
-  unsigned int eax, ebx, ecx, edx;
-  unsigned int max_level;
-  unsigned int ext_level;
-
-  /* See if we can use cpuid.  */
-  asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
-		"pushl %0; popfl; pushfl; popl %0; popfl"
-		: "=&r" (eax), "=&r" (ebx)
-		: "i" (0x00200000));
-  if (((eax ^ ebx) & 0x00200000) == 0)
-    return "efiemu32.o";
-
-  /* Check the highest input value for eax.  */
-  cpuid (0, eax, ebx, ecx, edx);
-  /* We only look at the first four characters.  */
-  max_level = eax;
-  if (max_level == 0)
-    return "efiemu32.o";
-
-  cpuid (0x80000000, eax, ebx, ecx, edx);
-  ext_level = eax;
-  if (ext_level < 0x80000000)
-    return "efiemu32.o";
-
-  cpuid (0x80000001, eax, ebx, ecx, edx);
-  return (edx & bit_LM) ? "efiemu64.o" : "efiemu32.o";
+  return grub_cpuid_has_longmode ? "efiemu64.o" : "efiemu32.o";
 }
Index: grub-2.00/grub-core/kern/i386/tsc.c
===================================================================
--- grub-2.00.orig/grub-core/kern/i386/tsc.c
+++ grub-2.00/grub-core/kern/i386/tsc.c
@@ -45,27 +45,11 @@ static __inline grub_uint64_t
 grub_get_tsc (void)
 {
   grub_uint32_t lo, hi;
+  grub_uint32_t a,b,c,d;
 
   /* The CPUID instruction is a 'serializing' instruction, and
      avoids out-of-order execution of the RDTSC instruction. */
-#ifdef __APPLE__
-  __asm__ __volatile__ ("xorl %%eax, %%eax\n\t"
-#ifdef __x86_64__
-			"push %%rbx\n"
-#else
-			"push %%ebx\n"
-#endif
-			"cpuid\n"
-#ifdef __x86_64__
-			"pop %%rbx\n"
-#else
-			"pop %%ebx\n"
-#endif
-			:::"%rax", "%rcx", "%rdx");
-#else
-  __asm__ __volatile__ ("xorl %%eax, %%eax\n\t"
-			"cpuid":::"%rax", "%rbx", "%rcx", "%rdx");
-#endif
+  grub_cpuid (0,a,b,c,d);
   /* Read TSC value.  We cannot use "=A", since this would use
      %rax on x86_64. */
   __asm__ __volatile__ ("rdtsc":"=a" (lo), "=d" (hi));
@@ -76,34 +60,13 @@ grub_get_tsc (void)
 static __inline int
 grub_cpu_is_tsc_supported (void)
 {
+  grub_uint32_t a,b,c,d;
   if (! grub_cpu_is_cpuid_supported ())
     return 0;
 
-  grub_uint32_t features;
-#ifdef __APPLE__
-  __asm__ ("movl $1, %%eax\n\t"
-#ifdef __x86_64__
-	   "push %%rbx\n"
-#else
-	   "push %%ebx\n"
-#endif
-	   "cpuid\n"
-#ifdef __x86_64__
-	   "pop %%rbx\n"
-#else
-	   "pop %%ebx\n"
-#endif
-           : "=d" (features)
-           : /* No inputs.  */
-	   : /* Clobbered:  */ "%rax", "%rcx");
-#else
-  __asm__ ("movl $1, %%eax\n\t"
-           "cpuid\n"
-           : "=d" (features)
-           : /* No inputs.  */
-           : /* Clobbered:  */ "%rax", "%rbx", "%rcx");
-#endif
-  return (features & (1 << 4)) != 0;
+  grub_cpuid(1,a,b,c,d);
+
+  return (d & (1 << 4)) != 0;
 }
 
 #ifndef GRUB_MACHINE_XEN
Index: grub-2.00/grub-core/loader/i386/xnu.c
===================================================================
--- grub-2.00.orig/grub-core/loader/i386/xnu.c
+++ grub-2.00/grub-core/loader/i386/xnu.c
@@ -126,66 +126,22 @@ guessfsb (void)
 {
   const grub_uint64_t sane_value = 100000000;
   grub_uint32_t manufacturer[3], max_cpuid, capabilities, msrlow;
+  grub_uint32_t a, b, d;
 
   if (! grub_cpu_is_cpuid_supported ())
     return sane_value;
 
-#ifdef __APPLE__
-  asm volatile ("movl $0, %%eax\n"
-#ifdef __x86_64__
-		"push %%rbx\n"
-#else
-		"push %%ebx\n"
-#endif
-		"cpuid\n"
-#ifdef __x86_64__
-		"pop %%rbx\n"
-#else
-		"pop %%ebx\n"
-#endif
-		: "=a" (max_cpuid),
-		  "=d" (manufacturer[1]), "=c" (manufacturer[2]));
-
-  /* Only Intel for now is done. */
-  if (grub_memcmp (manufacturer + 1, "ineIntel", 12) != 0)
-    return sane_value;
-
-#else
-  asm volatile ("movl $0, %%eax\n"
-		"cpuid"
-		: "=a" (max_cpuid), "=b" (manufacturer[0]),
-		  "=d" (manufacturer[1]), "=c" (manufacturer[2]));
+  grub_cpuid (0, max_cpuid, manufacturer[0], manufacturer[2], manufacturer[1]);
 
   /* Only Intel for now is done. */
   if (grub_memcmp (manufacturer, "GenuineIntel", 12) != 0)
     return sane_value;
-#endif
 
   /* Check Speedstep. */
   if (max_cpuid < 1)
     return sane_value;
 
-#ifdef __APPLE__
-  asm volatile ("movl $1, %%eax\n"
-#ifdef __x86_64__
-		"push %%rbx\n"
-#else
-		"push %%ebx\n"
-#endif
-		"cpuid\n"
-#ifdef __x86_64__
-		"pop %%rbx\n"
-#else
-		"pop %%ebx\n"
-#endif
-		: "=c" (capabilities):
-		: "%rax", "%rdx");
-#else
-  asm volatile ("movl $1, %%eax\n"
-		"cpuid"
-		: "=c" (capabilities):
-		: "%rax", "%rbx", "%rdx");
-#endif
+  grub_cpuid (1, a, b, capabilities, d);
 
   if (! (capabilities & (1 << 7)))
     return sane_value;
Index: grub-2.00/include/grub/i386/cpuid.h
===================================================================
--- grub-2.00.orig/include/grub/i386/cpuid.h
+++ grub-2.00/include/grub/i386/cpuid.h
@@ -69,9 +69,16 @@ grub_cpu_is_cpuid_supported (void)
 
 #endif
 
+#ifdef __PIC__
 #define grub_cpuid(num,a,b,c,d) \
   asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
                 : "=a" (a), "=r" (b), "=c" (c), "=d" (d)  \
                 : "0" (num))
+#else
+#define grub_cpuid(num,a,b,c,d) \
+  asm volatile ("cpuid" \
+                : "=a" (a), "=b" (b), "=c" (c), "=d" (d)  \
+                : "0" (num))
+#endif
 
 #endif
