[comp.sys.intel] 386 cpu detection

ray@ole.UUCP (Ray Berry) (02/25/89)

    Does anyone know a simple way of detecting whether code is executing
(in real mode) on a 386 vs non-386 (286/86) cpu?  I'll summarize responses.
Thanks.
-- 
Ray Berry  KB7HT uucp: ...{uw-beaver|uiucuxc}tikal!ole!ray CS: 73407,3152 
Seattle Silicon Corp. 3075 112th Ave NE. Bellevue WA 98004 (206) 828 4422

martin@zeus.hf.intel.com (Martin Wilde) (02/28/89)

>    Does anyone know a simple way of detecting whether code is executing
>(in real mode) on a 386 vs non-386 (286/86) cpu?  I'll summarize responses.
>Thanks.
>-- 
>Ray Berry  KB7HT uucp: ...{uw-beaver|uiucuxc}tikal!ole!ray CS: 73407,3152 
>Seattle Silicon Corp. 3075 112th Ave NE. Bellevue WA 98004 (206) 828 4422

Here is a small program that was presented in IBM PC Technical Journal
a while back.  It seems to work fine.  I have tried it on both 286 Xenix
and 386 Unix and it reports the cputype correctly.

The source is in Microsoft Assembler and normal C code.  I make to
warranties or guarantees about the code, just passing it on.

#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  Makefile
#	  cpu.asm
#	  cputype.c
#
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
XCC = /bin/cc
XASM=/bin/masm
XCFLAGS = -O -Ml
XASMFLAGS = -Mx
X
Xall: cpu.o 
X	$(CC) $(CFLAGS) -o cputype cputype.c cpu.o
X
Xcpu.o:
X	$(ASM) $(ASMFLAGS) cpu.asm
X
Xclean:
X	rm -f cpu.o cputype cputype.o
SHAR_EOF
chmod 0644 Makefile || echo "restore of Makefile fails"
sed 's/^X//' << 'SHAR_EOF' > cpu.asm &&
X; Function cputype(), for real OR protected mode.  Returns (in AX)
X; the value 0 (86), 20 (186), 30 (286), 40 (386);  negative if protected mode.
X
X		.286p			;enable protected-mode instructions
X_text		segment byte public 'code'	; use Microsoft C names
X		assume	cs:_text
X		public	_cputype
X_cputype	proc 	far
X		push	bp
X		push	sp		;86/186 will push SP-2,
X		pop	ax		;286/386 will push SP
X		cmp	ax,sp
X		jz	not86		;if equal, SP was pushed
X		mov	ax,10		;is it 86 or 186
X		mov	cl,32		;186 uses count mod32 = 0
X		shl	ax,cl		;86 shifts 32 so ax = 0
X		jnz	exit		;non-zero: no shift, so 186
X		mov	ax,20		;zero: shifted out all bits
X		jmp	exit
Xnot86:		pushf			;Test 16 or 23 operand size:
X		mov	ax,sp		;pushed 2 or 4 bytes flags?
X		popf			;restore SP
X		inc	ax		;restore AX by 2 bytes
X		inc	ax
X		cmp	ax,sp		;did pushf change SP by 2?
X		jnz	is32bit		;if not, then 4 bytes of flags
X	
Xis16bit:	sub	sp,6		;Is it 286 or 386 in 16-bit mode?
X		mov	bp,sp		;allocate space for GDT ptr
X		sgdt	qword ptr [bp]	;(use PWORD PTR for MASM5)
X		add	sp,4		;discard 2 words of GDT pointer
X		pop	ax		;get third word
X		inc	ah		;286 stores -1, 386 0 or 1
X		jnz	is386
X
Xis286:		mov	ax,30		;set return value
X		jmp	testprot
Xis32bit:	db	66H		;16-bit override in 32-bit mode
Xis386:		mov	ax,40
Xtestprot:	smsw	cx		;Protected? Machine status -> CX
X		ror	cx,1		;protection bit -> carry flag
X		jnc	exit		;real mode if no carry
X		neg	ax		;protected: return neg value
Xexit:		pop	bp
X		ret
X_cputype	endp
X_text		ends
X		end
SHAR_EOF
chmod 0644 cpu.asm || echo "restore of cpu.asm fails"
sed 's/^X//' << 'SHAR_EOF' > cputype.c &&
X/*
X *  This program determines the cputype.
X *  The function returns the type.
X */
X
Xextern	short	cputype();
X
Xmain()
X{
X	short	type;
X
X	type = cputype();
X
X	switch (type) {
X	
X		case 0: printf("cpu is 8086\n");
X			break;
X
X		case 20: printf("cpu is 80186\n");
X			break;
X
X		case 30: printf("cpu is 80286 in real mode\n");
X			break;
X
X		case 40: printf("cpu is 80386 in real mode\n");
X			break;
X
X		case -30: printf("cpu is 80286 in protected mode\n");
X			break;
X
X		case -40: printf("cpu is 80386 in protected mode\n");
X			break;
X
X		default: printf("unknown cpu type!\n");
X			break;
X	}
X}
SHAR_EOF
chmod 0644 cputype.c || echo "restore of cputype.c fails"
exit 0

                          
                  _/_          |
 ______  __.  __  /  o ____    |  textronix!reed!littlei!zeus:martin
/ / / <_(_/|_/ (_<__<_/ / <    |