mcdonald@uxe.cso.uiuc.edu (10/17/88)
Does anyone out there know a reliable, safe (hopefully not generating traps) method of having a running program (Microsoft C 5.1) determine whether it is running on an 80386 (as opposed to an 8086 or 80286)? I discovered that by coding one 11 line subroutine from my TeX screen previewer in assembler, using real 32 bit moves and shifts, that I can get a 35% speed improvement. (I made my non-386 assembler do this by sticking in db 066h opcode prefixes explicitly.) I would like to put this change in my distributed version, with a run time test to distinguish it from the 8086/80286 version in C. Doug McDonald (mcdonald@uiucuxe)
nfs@notecnirp.Princeton.EDU (Norbert Schlenker) (10/27/88)
In article <45900168@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.edu writes: > >Does anyone out there know a reliable, safe (hopefully not generating >traps) method of having a running program (Microsoft C 5.1) >determine whether it is running on an 80386 (as opposed to an 8086 or >80286)? ... > >Doug McDonald (mcdonald@uiucuxe) I thought someone else would post this, so I left it sitting for a while. Below is a routine to do what you ask, in small model for MASM 5.0 and above. (There may be syntax errors - I typed it from memory - but the ideas are correct.) The code relies on the fact that Intel CPU's have their own idiosyncracies. Some of the peculiarities are documented, others are NOT. In particular, the trick used in the following code to distinguish an 80286 from an 80386 is NOT documented, although it has worked on every '386 I've used. As far as I know, the documented methods of distinguishing these CPUs either operate only at RESET time (which makes them useless for most purposes), or do not work (i.e. an 80386 looks like an 80286 by Intel documented methods). Note also that this code does not take into account the oddities of the NEC V-20/V-30 chips. If someone has code that can detect them, I would be pleased to have it. And finally, I'm not sure what this routine returns if invoked by a task running in V86 mode on an 80386 (say under Windows/386, or VM/386). ; cpuid - MASM 5.0+ routine callable from C to determine CPU type ; ; C: int cpuid(); ; ; Returns:0 - for an 8086/8088 ; 1 - for an 80186/80188 ; 2 - for an 80286 ; 3 - for an 80386 ; .MODEL SMALL PUBLIC _cpuid .CODE _cpuid PROC mov ax,0 ; set default result to 8086/8088 mov dx,0 ; try to push zero into FLAGS push dx popf pushf pop dx and dh,0f0h ; mask high nybble cmp dh,0f0h ; if 0000b turns into 1111b, je exit ; this is an 8086/8088 inc ax ; bump result to 80186/80188 push sp ; compare stack pointer when pushed pop dx cmp dx,sp ; if SP changed before push, jne exit ; this is an 80186/80188 inc ax ; bump result to 80286 mov dx,7000h ; try to push 0111b into high nybble of FLAGS push dx popf pushf pop dx and dh,70h ; if no bit stayed set, jz exit ; this is an 80286 inc ax ; bump result to 80386 exit: ret _cpuid ENDP END