delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2000/01/02/06:24:27

Message-ID: <386F355D.AD5F2D14@softhome.net>
Date: Sun, 02 Jan 2000 13:24:13 +0200
From: Laurynas Biveinis <lauras AT softhome DOT net>
X-Mailer: Mozilla 4.6 [en] (Win98; I)
X-Accept-Language: en
MIME-Version: 1.0
To: djgpp-workers AT delorie DOT com
Subject: uname() patch - second version
Reply-To: djgpp-workers AT delorie DOT com

The version I recovered from mail archives is buggy.
It does not correctly restore EFLAGS and PUSHes to stack
more than POPs, with all effects from it - strange failures
and SIGSEGVs. 

This version corrects those bugs.

Laurynas Biveinis
---------------------
--- uname.c.old	Sun Oct  6 00:39:50 1996
+++ uname.c	Sun Jan  2 13:14:10 2000
@@ -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,81 @@
   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;"
+       "popl   %%eax;"
+       "movl   %%eax, %%ebx;"
+       "xorl   $0x40000, %%eax;"
+       "pushl  %%eax;"
+       "popf;"
+       "pushf;"
+       "popl   %%eax;"
+       "cmpl   %%ebx, %%eax;"
+       "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;

- Raw text -


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