Mail Archives: djgpp-workers/2000/01/02/06:24:27
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 -