Submitted By: Robert Connolly <robert@linuxfromscratch.org> (ashes)
Date: 2005-03-07
Initial Package Version: 5.2.1
Upstream Status: pending
Origin: Scot McPherson and Zack Winkles
Description: Fix the output of uname once and for all.

	$ uname -m      # This always worked.
	i686
	$ uname -i      # Used to report 'unknown'.
	i386
	$ uname -p      # Likewise.
	athlon-4

Now 'uname -p' can be used by GCC's mtune/mcpu and march options. For example:

	CFLAGS="-march=$(uname -m) -mtune=$(uname -p)"

diff -Naur coreutils-5.2.1.orig/src/uname.c coreutils-5.2.1/src/uname.c
--- coreutils-5.2.1.orig/src/uname.c	2004-01-21 22:27:02.000000000 +0000
+++ coreutils-5.2.1/src/uname.c	2005-03-07 22:23:17.659010480 +0000
@@ -29,6 +29,26 @@
 # include <sys/systeminfo.h>
 #endif
 
+#ifdef linux
+/* Thanks to the ffmpeg team for this PIC version of cpuid() */
+#ifdef ARCH_X86_64
+#  define REG_b "rbx"
+#  define REG_S "rsi"
+#else
+#  define REG_b "ebx"
+#  define REG_S "esi"
+#endif
+#define cpuid(index,eax,ebx,ecx,edx)\
+     __asm __volatile\
+        ("mov %%"REG_b", %%"REG_S"\n\t"\
+          "cpuid\n\t"\
+          "xchg %%"REG_b", %%"REG_S\
+        : "=a" (eax), "=S" (ebx),\
+          "=c" (ecx), "=d" (edx)\
+        : "0" (index));
+int has_sse( void );
+#endif
+
 #if HAVE_SYSCTL && HAVE_SYS_SYSCTL_H
 # include <sys/param.h> /* needed for OpenBSD 3.0 */
 # include <sys/sysctl.h>
@@ -249,6 +269,99 @@
 	if (0 <= sysinfo (SI_ARCHITECTURE, processor, sizeof processor))
 	  element = processor;
       }
+#else
+      {
+	struct utsname u;
+	uname (&u);
+	element = u.machine;
+#ifdef linux
+/******************************************************************************
+ *
+ * Hello, major hack.  I shouldn't have to do this.  struct utsname should
+ * have another element with this info in it.  There's probably a struct
+ * somewhere that has this info, I just don't know where it is.
+ *
+ *****************************************************************************/
+
+	if( !strcmp( element, "i586" ) || !strcmp( element, "i686" ) ) {
+	  int eax, ebx, ecx, edx, unused;
+	  int model, family, sse;
+     
+	  cpuid(0,unused,ebx,ecx,edx);
+	  cpuid(1,eax,unused,unused,unused);
+	  model = (eax >> 4) & 0xf;
+	  family = (eax >> 8) & 0xf;
+
+	  switch(ebx) {
+	  case 0x756e6547: // Intel
+	    switch( family ) {
+	    case 5: // Pentium
+	      if( model <= 3 )
+		element="pentium";
+	      if( model > 3 )
+		element="pentium-mmx";
+	      break;
+	    case 6: // PentiumPro - Pentium III
+	      if( model == 1 ) // Pentium Pro
+		element="pentiumpro";
+	      if( ( model == 3 ) || ( model == 5 ) ||
+		  ( model == 6 ) ) // Pentium II
+		element="pentium2";
+	      if( ( model == 7 ) || ( model == 8 ) ||
+		  ( model == 10 ) || ( model == 11 ) ) // These are all Pentium III
+		element="pentium3";
+	      break;
+	    case 15: // Pentium4
+	      if( model == 3 ) // Prescott
+                element="prescott";
+	      else
+	      element="pentium4";
+	      break;
+	    default:
+	      break;
+	    } // end switch( family )
+	    break;
+	  case 0x68747541: // AMD
+	    switch(family) {
+	    case 5:
+	      if( ( model == 0 ) || ( model == 1 ) || 
+		  ( model == 2 ) || ( model == 3 ) ) // K5
+		element="i586";
+	      if( ( model == 6 ) || ( model == 7 ) ) // K6
+		element="k6";
+	      if( model == 8 ) // K6-2
+		element="k6-2";
+	      if( model == 9 ) // K6-3
+		element="k6-3";
+	      break;
+	    case 6:
+	      if( model <= 4 )
+		element="athlon";
+	      if( model > 4 ) {
+		sse = has_sse();
+		if( sse == 0 )
+		  element="athlon";
+		if( sse == 1 )
+		  element="athlon-4";
+	      }
+	      break;
+	    case 15:
+	      element="athlon-4";
+	      break;
+	    default:
+	      break;
+	    } // end switch( family )
+	    break;
+	  case 0x69727943: // Cyrix
+	    element="i386"; // who knows what cyrix supports, lets be safe
+	    break;
+	  default:
+	    break;
+	  } // end switch(ebx)
+	}
+
+#endif
+      }
 #endif
 #ifdef UNAME_PROCESSOR
       if (element == unknown)
@@ -265,7 +378,7 @@
 
   if (toprint & PRINT_HARDWARE_PLATFORM)
     {
-      char const *element = unknown;
+      char *element = unknown;
 #if HAVE_SYSINFO && defined SI_PLATFORM
       {
 	static char hardware_platform[257];
@@ -273,6 +386,15 @@
 			  hardware_platform, sizeof hardware_platform))
 	  element = hardware_platform;
       }
+#else
+      {
+	struct utsname u;
+	uname (&u);
+	element = u.machine;
+	if (strlen (element) == 4 && element[0] == 'i' && element[2] == '8'
+	    && element[3] == '6')
+	  element[1] = '3';
+      }
 #endif
 #ifdef UNAME_HARDWARE_PLATFORM
       if (element == unknown)
@@ -294,3 +416,29 @@
 
   exit (EXIT_SUCCESS);
 }
+
+#ifdef linux
+
+/******************************************************************************
+ *
+ * int has_sse( void )
+ * Checks Athlon CPU's to see if they support SSE.
+ *
+ *****************************************************************************/
+
+int has_sse( void )
+{
+  unsigned long edx, unused;
+  int sse;
+  cpuid(1,unused,unused,unused,edx);
+  // I think, I need this tested on a Duron with SSE
+  // and one without it.
+  sse = edx & 0x2000000;
+  if( sse == 0 ) {
+    return 0;
+  } else {
+    return 1;
+  }
+
+}
+#endif
