delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1999/08/03/12:01:49

Message-ID: <37A6E429.6245A110@softhome.net>
Date: Tue, 03 Aug 1999 14:44:25 +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: DJGPP Workers <djgpp-workers AT delorie DOT com>
Subject: CPU identification (Was: Re: uname -m ?)
References: <Pine DOT SUN DOT 3 DOT 91 DOT 990803104713 DOT 1847N-100000 AT is>
Reply-To: djgpp-workers AT delorie DOT com

Eli Zaretskii wrote:
> Because there's no easy way to identify the exact CPU type.  If you
> know about a safe way to do that without crashing on all supported
> platforms, including NT and DOSEmu, please submit a change for the
> `uname' library function.

I wrote program for this. It uses ways to detect CPU type
strictly according to Pentium II documentation. It doesn't 
use any privileged instructions, so it should (?) work on 
NT and DOSEMU. However: 
  - It detects any better than 486 clone as "i586" 
  - it won't detect any 386/486 clone which differently
uses undefined EFLAGS bits
  - it has been tested only on one system and correctly
reported that original Intel Pentium II 333MHz is a "i686"

So anybody is welcome to check it and/or add support
for clones

Laurynas Biveinis
-----------------
/* CPU type under DJGPP checker, v1.0alpha */
/* (C) 1999 Laurynas Biveinis */

#include <stdio.h>

int main(void)
{
   unsigned is_486_or_better;
   unsigned is_586_or_better;
   unsigned vendor_id[3];
   unsigned version_info;
   
   /* 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 */
       "popl   %%eax;"                /* get 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 486 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:"
         : "=g" (is_586_or_better)
         :
         : "%eax", "%ebx");
         if (is_586_or_better)
         {
            /* Now we can use CPUID */
            asm volatile (
              "movl   $0, %%eax;"
              "cpuid;"
              : "=b" (vendor_id[0]), "=d" (vendor_id[1]), "=c"
(vendor_id[2])
              :
              : "%eax");
              /* If we have "GenuineIntel" CPU */
              if ((vendor_id[0] == 0x756E6547) &&
                  (vendor_id[1] == 0x49656E69) &&
                  (vendor_id[2] == 0x6C65746E))
              {
                 /* Then we can check, is it Pentium or
PentiumPro/PentiumII*/
                 asm volatile (
                    "movl   $1, %%eax;"
                    "cpuid;"
                    : "=a" (version_info)
                    :
                    : "%ebx", "%ecx", "%edx");
                 /* What we need is family info in 8-11 bits */
                 version_info = (version_info & 0x780) >> 8;
                 if (version_info == 0x6)
                    printf("i686\n");
                 else
                    printf("i586\n");
              }
              else
                 /* TODO: add detection for clones */
                 printf("i586\n");
         }
         else
            printf("i486\n");
   }
   else
      printf("i386\n");
   return 0;
}

- Raw text -


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