delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1999/08/04/13:39:26

Message-ID: <37A8643F.CCFFBD9A@softhome.net>
Date: Wed, 04 Aug 1999 18:03:11 +0200
From: Laurynas Biveinis <lauras AT softhome DOT net>
X-Mailer: Mozilla 4.61 [en] (Win98; I)
X-Accept-Language: lt,en
MIME-Version: 1.0
To: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
CC: DJGPP Workers <djgpp-workers AT delorie DOT com>
Subject: Re: CPU ID program, second version
References: <Pine DOT SUN DOT 3 DOT 91 DOT 990804162240 DOT 1514C-100000 AT is>
Reply-To: djgpp-workers AT delorie DOT com

Eli Zaretskii wrote:
> Could you please modify the library function `uname' to include this
> code, and send the results of "diff -c" against the current source?

OK. Code was in program for testing purposes, if you consider that
it is production quality - here is diff against CVS version of 
library. It compiled and worked for me. Also there is a patch for 
docs which describes the new behaviour and corrects a typo ("#" char 
before function prototype).

BTW, I made "diff -u" not "diff -c", but I think you will accept that? :)

Bye,
Laurynas Biveinis
-----------------
diff -r -u utsname.old/uname.c utsname/uname.c
--- utsname.old/uname.c	Sat Oct  5 23:39:50 1996
+++ utsname/uname.c	Wed Aug  4 17:35:24 1999
@@ -13,6 +13,9 @@
 {
   __dpmi_regs r;
   unsigned short dos_version;
+  unsigned is_486_or_better;
+  unsigned cpuid_support;
+  unsigned cpuid_info;
 
   if (!u)
   {
@@ -25,7 +28,80 @@
   u->sysname[sizeof(u->sysname) - 1] = '\0';
   sprintf(u->release, "%d", dos_version >> 8);
   sprintf(u->version, "%02d", dos_version & 0xff);
-  strcpy(u->machine, "pc");
+
+  /* CPU detection code by Laurynas Biveinis            */
+  /* Uses Phil Frisbie, Jr 386 and CPUID detection code */
+
+  /* Let's check for 386. Intel says that 386 is unable to set or clear */
+  /* value of 18 bit in EFLAGS (AC). So we toggle this bit and see if   */
+  /* we succeed */
+  asm volatile (
+       "pushf;"                       /* save EFLAGS */
+       "movl   %%eax, %%ebx;"         /* temp storage EFLAGS */
+       "xorl   $0x40000, %%eax;"      /* change AC bit in EFLAGS */
+       "pushl  %%eax;"                /* put new EFLAGS value on stack */
+       "popf;"                        /* replace current EFLAGS value */
+       "pushf;"                       /* get EFLAGS */
+       "popl   %%eax;"                /* save new EFLAGS in EAX */
+       "cmpl   %%ebx, %%eax;"         /* compare temp and new EFLAGS */
+       "jz     0f;"
+       "movl   $1, %0;"               /* 80486+ present */
+       "jmp    1f;"
+       "0:"
+       "movl   $0, %0;"               /* 80386 present */
+       "1:"
+       "pushl  %%ebx;"                /* get original EFLAGS */
+       "popf;"                        /* restore EFLAGS */
+       : "=g" (is_486_or_better)
+       :
+       : "eax", "ebx");
+  if (is_486_or_better)
+  {
+      /* In the same way we checked for 386, we will check for CPUID now, */
+      /* using 21 bit in EFLAGS (ID bit)      */
+      asm volatile (
+         "pushf;"                      /* get extended flags */
+         "popl     %%eax;"
+         "movl     %%eax, %%ebx;"       /* save current flags */
+         "xorl     $0x200000, %%eax;"   /* toggle bit 21 */
+         "pushl    %%eax;"              /* put new flags on stack */
+         "popfl;"                       /* flags updated now in flags */
+         "pushfl;"                      /* get extended flags */
+         "popl     %%eax;"
+         "xorl     %%ebx, %%eax;"       /* if bit 21 r/w then supports cpuid */
+         "jz       0f;"
+         "movl     $1, %0;"
+         "jmp      1f;"
+         "0:"
+         "movl     $0, %0;"
+         "1:"
+         "pushl    %%ebx;"              /* Restore */
+         "popfl;"                       /* original EFLAGS */
+         : "=g" (cpuid_support)
+         :
+         : "%eax", "%ebx");
+      if (cpuid_support)
+      {
+         /* Now we can use CPUID */
+         asm volatile (
+            "movl   $1, %%eax;"
+            "cpuid;"
+            : "=a" (cpuid_info)
+            :
+            : "%ebx", "%ecx", "%edx");
+            /* What we need is instruction family info in 8-11 bits */
+            switch ((cpuid_info & 0x780) >> 8)
+            {
+               case 0x6: strcpy(u->machine, "i686"); break;
+               case 0x5: strcpy(u->machine, "i586"); break;
+               case 0x4: strcpy(u->machine, "i486"); break;
+            }
+      }
+      else
+         strcpy(u->machine, "i486"); // i486 not supporting CPUID
+  }
+  else
+     strcpy(u->machine, "i386");
 
   r.x.ax = 0x5e00;
   r.x.ds = __tb >> 4;
diff -r -u utsname.old/uname.txh utsname/uname.txh
--- utsname.old/uname.txh	Sun Sep 27 17:22:28 1998
+++ utsname/uname.txh	Wed Aug  4 17:43:36 1999
@@ -4,7 +4,7 @@
 @example
 #include <sys/utsname.h>
 
-#int uname(struct utsname *u);
+int uname(struct utsname *u);
 @end example
 
 @subheading Description
@@ -25,7 +25,7 @@
 
 @item machine
 
-"pc"
+The CPU family type: "i386", "i486", "i586" or "i686".
 
 @item nodename

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019