; Determine which CPU is running. (based on Intel's suggested method)
;  - R. A. Rose 02/01/92
;    * added DPMI acceptable method.  RARose 03/31/92
;
;	int cputype(void);
; Returns:
;	88	8088/8086/V20
;	186	80186
;	286	80286
;	386	80386
;	486	80486

ifdef LARGEMAC
; large model
	include modelmtl.mac
else
; huge model
	include modelhpl.mac
endif

	dseg	cpuids
cpuids	dw	88,186,286,386,486	; CPU id's as a function of index
	endds

	pseg	cpuids

	proc_def    cputype

	chappy				; keep C happy
ifdef HUGEMAC
	mov	ax,0400h
	int	31h
	xor	bx,bx
	mov	bl,cl
	shl	bx,1
	mov	AX,cpuids[BX]
else
	pushf
	xor	ax,ax
	push	AX
	popf		;try forcing flag word to all 0
	pushf
	pop	AX	;retrieve them for testing
	and	AH,0F0h
	cmp	ah,0F0h
	jnz	L2		;it's a 286 or 386

	;Distinguish between 8088/8086 and 80186
	xor	ax,ax
	push	sp		;is SP pushed before or after it's decremented?
	pop	bx
	cmp	bx,sp
	jne	L1
	jmp short L3		;it's an 80186

L2:	mov	AX,0F000h
	push	AX		;try to force high bits on in flags
	popf
	pushf
	pop	AX		;AX = what was actually stored
	and	AH,0F0h
	mov	AX,2
	jz	L1		;no, it's a 286

	;Distinguish between 386 and 486
L4:
	.386
	mov	BX,SP
	and	SP,0FFFCh	;round down to a dword boundary
	pushfd
	pushfd
	pop	EDX
	mov	ECX,EDX
	xor	EDX,40000h	;toggle AC bit
	and	ECX,40000h
	push	EDX
	popfd
	pushfd
	pop	EDX
	popfd			;restore original flags
	mov	SP,BX		;restore original stack pointer
	and	EDX,40000h
	inc	AX		;AX = 3
	cmp	edx,ecx
	jz	L1
L3:	inc	AX		;it's a 186 or 486
L1:	popf			;original flags
	mov	BX,AX
	add	BX,BX
	mov	AX,cpuids[BX]
endif
	goaway
	end_proc

	endps

	end
