1 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
\r
2 ³ Testing the Intel CPU Type ³
\r
3 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
\r
5 Written for the PC-GPE by Mark Feldman
\r
6 e-mail address : u914097@student.canberra.edu.au
\r
7 myndale@cairo.anu.edu.au
\r
9 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
\r
10 ³ THIS FILE MAY NOT BE DISTRIBUTED ³
\r
11 ³ SEPERATE TO THE ENTIRE PC-GPE COLLECTION. ³
\r
12 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
\r
15 ÚÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
\r
19 I assume no responsibility whatsoever for any effect that this file, the
\r
20 information contained therein or the use thereof has on you, your sanity,
\r
21 computer, spouse, children, pets or anything else related to you or your
\r
22 existance. No warranty is provided nor implied with this information.
\r
24 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
\r
28 Believe it or not there are people in the world who still own 8088s! Heck I
\r
29 only just upgraded my 286 to a 486SUX33 a couple of months ago.
\r
31 As we all know, 286's and below just don't make the cut anymore, and even
\r
32 386's are becoming a thing of the past. Personally I think a program should
\r
33 politely tell someone they are a phleb rather than unceremoniously hanging
\r
34 their machine for them.
\r
36 This text file will show one mothed of detecting the CPU type. Unfortunately
\r
37 I don't have a Pentium op code list so it'll only detect up to a 486.
\r
39 Most of the information in this file came from a well documented assembly
\r
40 program available on various ftp sites called 80486.asm, written by Robert
\r
41 Collins. I tried calling Robert for permission to use his original file, but
\r
42 he appears to have moved house.
\r
44 ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
\r
48 80186 chips and higher generate an interrupt 6 when they come across an
\r
49 instruction they don't support, this provides us with a real simple method
\r
50 of determining the cpu type (coupled with the trap interrupt it would
\r
51 conceivably also allow us to write a Pentium emulator for the 80286, but
\r
52 that's another story). We simply have to try execting a 486 command, if it
\r
53 causes an interrupt 6 then we know the machine is a 386 or lower.
\r
55 The op codes used in the program below all modify the dx register.
\r
57 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
\r
58 ³ Op Code Machine Language Bytes Supported by ³
\r
59 ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
\r
60 ³ shl dx, 5 C1 E2 05 80186 and higher ³
\r
61 ³ smsw dx 0F 01 E2 80286 and higher ³
\r
62 ³ mov edx, cr0 0F 20 C2 80386 and higher ³
\r
63 ³ xadd dx, dx 0F C1 D2 80486 and higher ³
\r
64 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
\r
66 When an interrupt 6 is generated you have to modify the value of the IP
\r
67 register which was pushed onto the stack when the interrupt occurred,
\r
68 otherwise the CPU will go back to it after the interrupt and keep trying
\r
69 to execute it. Each of the instructions in the table above are 3 bytes long
\r
70 so our interrupt handler can simply add 3 to the IP value on the stack.
\r
72 Identifying an 8088 chip is even simpler. If you push the SP register onto
\r
73 the stack the 8088 increments the SP value before it pushes it, the other
\r
74 chips all increment it afterwards. So to test for the presence of an 8088
\r
75 push SP onto the stack and pop it off into another variable, say AX. If AX
\r
76 and SP are not equal then the chip is an 8088.
\r
78 Keep in mind that you *MUST* check for the presence of an 8088 before
\r
79 doing anything else. Attempting to execute an invalid op code on an 8088
\r
80 will cause it to hang. Each of the functions in the unit below check for
\r
81 an 8088 first to prevent this happening.
\r
83 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
\r
84 ³ A Pascal Unit to Test the CPU Type ³
\r
85 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
\r
87 The following pascal unit contains some functions your program can use to
\r
88 make sure it's running on the right kind of machine. If your program will
\r
89 only work on a 386 and higher (for example) then put this unit first in your
\r
90 Uses clause and modify the unit's initialization code to terminate the
\r
91 program if the wrong CPU type is detected. The unit's current initialization
\r
92 simply test the CPU type and store it in the 'cpu' variable.
\r
96 CPUTYPE - A Pascal Unit to Test the CPU Type
\r
97 By Mark Feldman u914097@student.canberra.edu
\r
98 myndale@cairo.anu.edu.au
\r
100 Based on an original assembly program by Robert Collins.
\r
111 const CPU_8088 = 0;
\r
118 { The cpu variable is initialised to the cpu type }
\r
121 { Isa8088 returns true only if cpu is an 8088 or 8086 }
\r
122 function Isa8088 : boolean;
\r
124 { Isa80186 returns true if cpu is an 80186 or higher }
\r
125 function Isa80186 : boolean;
\r
127 { Isa80286 returns true if cpu is an 80286 or higher }
\r
128 function Isa80286 : boolean;
\r
130 { Isa80386 returns true if cpu is an 80386 or higher }
\r
131 function Isa80386 : boolean;
\r
133 { Isa80486 returns true if cpu is an 80486 or higher }
\r
134 function Isa80486 : boolean;
\r
143 var OldIntr6Handler : procedure;
\r
144 valid_op_code : boolean;
\r
146 procedure Intr6Handler;
\r
149 valid_op_code := false;
\r
151 { Stoopid TP7 won't let me modify IP directly }
\r
153 add word ptr ss:[bp + 18], 3
\r
157 function Isa8088 : boolean;
\r
158 var sp1, sp2 : word;
\r
171 function Isa80186 : boolean;
\r
177 valid_op_code := true;
\r
178 GetIntVec(6, @OldIntr6Handler);
\r
179 SetIntVec(6, Addr(Intr6Handler));
\r
180 inline($C1/$E2/$05); { shl dx, 5 }
\r
181 SetIntVec(6, @OldIntr6Handler);
\r
182 Isa80186 := valid_op_code;
\r
186 function Isa80286 : boolean;
\r
192 valid_op_code := true;
\r
193 GetIntVec(6, @OldIntr6Handler);
\r
194 SetIntVec(6, Addr(Intr6Handler));
\r
195 inline($0F/$01/$E2); { smsw dx }
\r
196 SetIntVec(6, @OldIntr6Handler);
\r
197 Isa80286 := valid_op_code;
\r
201 function Isa80386 : boolean;
\r
207 valid_op_code := true;
\r
208 GetIntVec(6, @OldIntr6Handler);
\r
209 SetIntVec(6, Addr(Intr6Handler));
\r
210 inline($0F/$20/$C2); { mov edx, cr0 }
\r
211 SetIntVec(6, @OldIntr6Handler);
\r
212 Isa80386 := valid_op_code;
\r
216 function Isa80486 : boolean;
\r
222 valid_op_code := true;
\r
223 GetIntVec(6, @OldIntr6Handler);
\r
224 SetIntVec(6, Addr(Intr6Handler));
\r
225 inline($0F/$C1/$D2); { xadd dx, dx }
\r
226 SetIntVec(6, @OldIntr6Handler);
\r
227 Isa80486 := valid_op_code;
\r
235 else if Isa80486 then
\r
237 else if Isa80386 then
\r
239 else if Isa80286 then
\r
241 else if Isa80186 then
\r
244 cpu := CPU_UNKNOWN;
\r