Message-ID: <328E6D0D.168E@ananke.amu.edu.pl> Date: Sun, 17 Nov 1996 02:40:29 +0100 From: Mark Habersack Reply-To: grendel AT ananke DOT amu DOT edu DOT pl Organization: Home, sweet home MIME-Version: 1.0 To: Morten Welinder CC: "John M. Aldrich" , DJGPP Workers mailing list Subject: Re: djverify and cpu detection Content-Type: multipart/mixed; boundary="------------4182367F18A5" This is a multi-part message in MIME format. --------------4182367F18A5 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Mark Habersack wrote: Morten Welinder wrote: > > 1. The asm ("...") code in diagnose.c fails to specify that > ebx/ecx/edx get destroyed. Bad code may be generated. My fault. Shall be corrected. Thanks for pointing it. > 2. Why does it .byte and .long so often? (And what are all > those '\r's doing _after_ the '\n's?) a) The .byte and .long emit the code of the "xorl $0xXXXX, %%eax" instruction. The code was originally written for a 16-bit assembler which didn't accept 32-bit instructions, so they had to be emited manually (the same concerns CPUID in this code). I just thoughtlessly converted the code forgetting to change the .directives to something more readable. b) Frankly.... I don't know why did I put the '\r's there... ;-))) > > 3. The method used -- as used everywhere else in djgpp -- > may have a problem: it is said that an interrupt (the > event, not the handler) will clear the AC flag. Hmm... That's correct, but the method is recommended by Intel and I assume that they recommend a technique which is reliable enough to use it in serious software. It's possible to disable interrupts before flipping and checking the AC bit. If the code will run in V86 mode and the DPMI server will virtualize the interrupt flag properly - nothing wrong should happen. > If this is true then we will occasionally detect 486s > and up as 386s. > > So someone with a PC should run the cpu detection code > 10^8 times and see if it is reliable. Don't forget to > run it in real mode as well as v86 mode. If it turns > out we do have a problem we can think of a solution then. I've been using the code for more than two years now and it detected properly all computers ranging from 386's, through Pentium up to PentiumPro. In fact the code was more reliable than Quarterdeck's MFT which sometimes reported Pentium/486 to be a 386. But I think you're right, if there are doubts they have to be dealt with. In attachment to this mail you'll find the diff file that applies all the changes to diagnose.c from v0.31 of DJVERIFY. -- =========================================================== October. And the trees are stripped bare of all they wear. What do I care? October. And Kingdoms rise, And Kingdoms fall, But you go on, and on. =========================================================== --------------4182367F18A5 Content-Type: text/plain; charset=us-ascii; name="diagnose.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="diagnose.diff" *** diagnose.org Fri Nov 15 23:39:20 1996 --- diagnose.c Sun Nov 17 02:28:28 1996 *************** *** 71,77 **** void analyze_environment ( void ); void find_djgpp_file ( char **s, const char *filename ); ! unsigned getCPU ( void ); static void usec_sleep ( int usec ); static unsigned char read_cmos ( int reg ); int installed_memory_size ( void ); --- 71,77 ---- void analyze_environment ( void ); void find_djgpp_file ( char **s, const char *filename ); ! volatile unsigned getCPU ( void ); static void usec_sleep ( int usec ); static unsigned char read_cmos ( int reg ); int installed_memory_size ( void ); *************** *** 672,728 **** /* architecture, not yet available) I read about. */ /****************************************************************/ ! unsigned getCPU( void ) { ! unsigned short wcpu; ! asm ("movl %%esp, %%ebx\n\r" ! "andl $0xFFFFFFFC, %%esp\n\r" /* This aligns stack to avoid AC fault */ ! "pushfl\n\r" ! "popl %%eax\n\r" ! "movl %%eax, %%ecx\n\r" ! ".byte 0x35\n\r" ! ".long 0x40000\n\r" ! "pushl %%eax\n\r" ! "popfl\n\r" ! "pushfl\n\r" ! "popl %%eax\n\r" ! "xorl %%ecx, %%eax\n\r" ! "movw $2, %0\n\r" /* It's 80386 - cannot flip the AC bit in EFLAGS */ ! "movl %%ebx, %%esp\n\r" ! "jz 1f\n\r" ! "andl $0xFFFFFFFC, %%esp\n\r" /* This aligns stack to avoid AC fault */ ! "pushl %%ecx\n\r" ! "popfl\n\r" ! "movl %%ebx, %%esp\n\r" ! "movl $3, %0\n\r" /* Assume it's i486 */ ! "movl %%ecx, %%eax\n\r" ! ".byte 0x35\n\r" ! ".long 0x200000\n\r" ! "pushl %%eax\n\r" ! "popfl\n\r" ! "pushfl\n\r" ! "popl %%eax\n\r" ! "xorl %%ecx, %%eax\n\r" ! "je 1f\n\r" /* If can toggle ID bit in EFLAGS - it's */ ! "movw $4, %0\n\r" /* "new" i486 code */ ! "xorl %%eax, %%eax\n\r" /* "new" i486 with CPUID instruction */ ! ".byte 0x0F\n\r" /* or Pentium and higher */ ! ".byte 0xA2\n\r" /* Issue CPUID instruction code */ ! "cmpl $1, %%eax\n\r" /* See whether 1 is supported with CPUID */ ! "jl 1f\n\r" /* No. So let's report we have "new" i486 */ ! "xorl %%eax, %%eax\n\r" ! "incl %%eax\n\r" ! ".byte 0x0F\n\r" ! ".byte 0xA2\n\r" /* CPUID again */ ! "andl $0x0F00, %%eax\n\r" ! "shrl $8, %%eax\n\r" ! "xorb %%ah, %%ah\n\r" ! "movw %%ax, %0\n\r" ! "1:" : "g=" (wcpu) : ! : "%eax"); return (unsigned)wcpu; } --- 672,732 ---- /* architecture, not yet available) I read about. */ /****************************************************************/ ! volatile unsigned getCPU( void ) { ! volatile unsigned short wcpu; ! /* The code below tries to disable interrupts to be sure that no bit ! in eflags register will be modified by interrupt event/handler. ! Thanks to Morten for pointing that problem. ! */ ! asm volatile ("cli\n" ! "movl %%esp, %%ebx\n" ! "andl $0xFFFFFFFC, %%esp\n" /* This aligns stack to avoid AC fault */ ! "pushfl\n" ! "popl %%eax\n" ! "movl %%eax, %%ecx\n" ! "xorl $0x40000, %%eax\n" ! "pushl %%eax\n" ! "popfl\n" ! "pushfl\n" ! "popl %%eax\n" ! "xorl %%ecx, %%eax\n" ! "movw $2, %0\n" /* It's 80386 - cannot flip the AC bit in EFLAGS */ ! "movl %%ebx, %%esp\n" ! "jz 1f\n" ! "andl $0xFFFFFFFC, %%esp\n" /* This aligns stack to avoid AC fault */ ! "pushl %%ecx\n" ! "popfl\n" ! "movl %%ebx, %%esp\n" ! "movl $3, %0\n" /* Assume it's i486 */ ! "movl %%ecx, %%eax\n" ! "xorl $0x200000, %%eax\n" ! "pushl %%eax\n" ! "popfl\n" ! "pushfl\n" ! "popl %%eax\n" ! "xorl %%ecx, %%eax\n" ! "je 1f\n" /* If can toggle ID bit in EFLAGS - it's */ ! "movw $4, %0\n" /* "new" i486 code */ ! "xorl %%eax, %%eax\n" /* "new" i486 with CPUID instruction */ ! ".byte 0x0F\n" /* or Pentium and higher */ ! ".byte 0xA2\n" /* Issue CPUID instruction code */ ! "cmpl $1, %%eax\n" /* See whether 1 is supported with CPUID */ ! "jl 1f\n" /* No. So let's report we have "new" i486 */ ! "xorl %%eax, %%eax\n" ! "incl %%eax\n" ! ".byte 0x0F\n" ! ".byte 0xA2\n" /* CPUID again */ ! "andl $0x0F00, %%eax\n" ! "shrl $8, %%eax\n" ! "xorb %%ah, %%ah\n" ! "movw %%ax, %0\n" ! "1:\n" ! "sti\n" : "g=" (wcpu) : ! : "%eax", "%ebx", "%ecx", "%edx"); return (unsigned)wcpu; } --------------4182367F18A5--