OSDN Git Service

d8cc7b3406f7eacaed2a20582b3ac4dda3575c2b
[proj16/16.git] / 16 / PCGPE10 / CPUTYPE.TXT
1                    ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\r
2                    ³ Testing the Intel CPU Type ³\r
3                    ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
4 \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
8 \r
9            ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\r
10            ³      THIS FILE MAY NOT BE DISTRIBUTED     ³\r
11            ³ SEPERATE TO THE ENTIRE PC-GPE COLLECTION. ³\r
12            ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
13 \r
14 \r
15 ÚÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
16 ³ Disclaimer ³\r
17 ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
18 \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
23 \r
24 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
25 ³ Introduction ³\r
26 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
27 \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
30 \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
35 \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
38 \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
43 \r
44 ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
45 ³ Method ³\r
46 ÀÄÄÄÄÄÄÄÄÙ\r
47 \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
54 \r
55 The op codes used in the program below all modify the dx register.\r
56 \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
65 \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
71 \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
77 \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
82 \r
83 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
84 ³ A Pascal Unit to Test the CPU Type ³\r
85 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
86 \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
93 \r
94 {\r
95 \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
99 \r
100             Based on an original assembly program by Robert Collins.\r
101 \r
102 \r
103 }\r
104 \r
105 \r
106 Unit CPUTYPE;\r
107 \r
108 \r
109 Interface\r
110 \r
111 const CPU_8088    =  0;\r
112       CPU_80186   =  1;\r
113       CPU_80286   =  2;\r
114       CPU_80386   =  3;\r
115       CPU_80486   =  4;\r
116       CPU_UNKNOWN = -1;\r
117 \r
118 { The cpu variable is initialised to the cpu type }\r
119 var cpu : integer;\r
120 \r
121 { Isa8088 returns true only if cpu is an 8088 or 8086 }\r
122 function Isa8088 : boolean;\r
123 \r
124 { Isa80186 returns true if cpu is an 80186 or higher }\r
125 function Isa80186 : boolean;\r
126 \r
127 { Isa80286 returns true if cpu is an 80286 or higher }\r
128 function Isa80286 : boolean;\r
129 \r
130 { Isa80386 returns true if cpu is an 80386 or higher }\r
131 function Isa80386 : boolean;\r
132 \r
133 { Isa80486 returns true if cpu is an 80486 or higher }\r
134 function Isa80486 : boolean;\r
135 \r
136 \r
137 \r
138 \r
139 Implementation\r
140 \r
141 Uses Dos;\r
142 \r
143 var OldIntr6Handler : procedure;\r
144       valid_op_code : boolean;\r
145 \r
146 procedure Intr6Handler;\r
147 interrupt;\r
148 begin\r
149   valid_op_code := false;\r
150 \r
151   { Stoopid TP7 won't let me modify IP directly }\r
152   asm\r
153     add word ptr ss:[bp + 18], 3\r
154   end;\r
155 end;\r
156 \r
157 function Isa8088 : boolean;\r
158 var sp1, sp2 : word;\r
159 begin\r
160   asm\r
161     mov sp1, sp\r
162     push sp\r
163     pop sp2\r
164   end;\r
165   if sp1 <> sp2 then\r
166     Isa8088 := true\r
167   else\r
168     Isa8088 := false;\r
169 end;\r
170 \r
171 function Isa80186 : boolean;\r
172 begin\r
173   if Isa8088 then\r
174     Isa80186 := false\r
175   else\r
176     begin\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
183     end;\r
184 end;\r
185 \r
186 function Isa80286 : boolean;\r
187 begin\r
188   if Isa8088 then\r
189     Isa80286 := false\r
190   else\r
191     begin\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
198     end;\r
199 end;\r
200 \r
201 function Isa80386 : boolean;\r
202 begin\r
203   if Isa8088 then\r
204     Isa80386 := false\r
205   else\r
206     begin\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
213     end;\r
214 end;\r
215 \r
216 function Isa80486 : boolean;\r
217 begin\r
218   if Isa8088 then\r
219     Isa80486 := false\r
220   else\r
221     begin\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
228     end;\r
229 end;\r
230 \r
231 \r
232 begin\r
233   if Isa8088 then\r
234     cpu := CPU_8088\r
235   else if Isa80486 then\r
236     cpu := CPU_80486\r
237   else if Isa80386 then\r
238     cpu := CPU_80386\r
239   else if Isa80286 then\r
240     cpu := CPU_80286\r
241   else if Isa80186 then\r
242     cpu := CPU_80186\r
243   else\r
244     cpu := CPU_UNKNOWN;\r
245 end.\r