PCem
view src/cpu.c @ 116:4081a8dbce5b
Switched IBM AT to more recent BIOS. Added 8 MHz option. Patch from SA1988.
| author | TomW |
|---|---|
| date | Tue Jul 08 20:35:39 2014 +0100 |
| parents | 923b243eba54 |
| children | 871b132c6158 |
line source
1 #include "ibm.h"
2 #include "cpu.h"
3 #include "model.h"
4 #include "io.h"
5 #include "x86_ops.h"
7 enum
8 {
9 CPUID_FPU = (1 << 0),
10 CPUID_TSC = (1 << 4),
11 CPUID_MSR = (1 << 5),
12 CPUID_MMX = (1 << 23)
13 };
15 int cpu = 3, cpu_manufacturer = 0;
16 CPU *cpu_s;
17 int cpu_multi;
18 int cpu_iscyrix;
19 int cpu_16bitbus;
20 int cpu_busspeed;
21 int cpu_hasrdtsc;
22 int cpu_hasMMX, cpu_hasMSR;
23 uint64_t tsc = 0;
25 int timing_rr;
26 int timing_mr, timing_mrl;
27 int timing_rm, timing_rml;
28 int timing_mm, timing_mml;
29 int timing_bt, timing_bnt;
31 static struct
32 {
33 uint32_t tr1, tr12;
34 uint32_t cesr;
35 uint32_t fcr;
36 uint64_t fcr2, fcr3;
37 } msr;
39 /*Available cpuspeeds :
40 0 = 16 MHz
41 1 = 20 MHz
42 2 = 25 MHz
43 3 = 33 MHz
44 4 = 40 MHz
45 5 = 50 MHz
46 6 = 66 MHz
47 7 = 75 MHz
48 8 = 80 MHz
49 9 = 90 MHz
50 10 = 100 MHz
51 11 = 120 MHz
52 12 = 133 MHz
53 13 = 150 MHz
54 14 = 160 MHz
55 15 = 166 MHz
56 16 = 180 MHz
57 17 = 200 MHz
58 */
60 CPU cpus_8088[] =
61 {
62 /*8088 standard*/
63 {"8088/4.77", CPU_8088, 0, 4772727, 1, 0, 0, 0},
64 {"8088/8", CPU_8088, 1, 8000000, 1, 0, 0, 0},
65 {"8088/10", CPU_8088, 2, 10000000, 1, 0, 0, 0},
66 {"8088/12", CPU_8088, 3, 12000000, 1, 0, 0, 0},
67 {"8088/16", CPU_8088, 4, 16000000, 1, 0, 0, 0},
68 {"", -1, 0, 0, 0, 0}
69 };
71 CPU cpus_pcjr[] =
72 {
73 /*8088 PCjr*/
74 {"8088/4.77", CPU_8088, 0, 4772727, 1, 0, 0, 0},
75 {"", -1, 0, 0, 0, 0}
76 };
78 CPU cpus_8086[] =
79 {
80 /*8086 standard*/
81 {"8086/7.16", CPU_8086, 1, 3579545*2, 1, 0, 0, 0},
82 {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0},
83 {"8086/9.54", CPU_8086, 1, (3579545*8)/3, 1, 0, 0, 0},
84 {"8086/10", CPU_8086, 2, 10000000, 1, 0, 0, 0},
85 {"8086/12", CPU_8086, 3, 12000000, 1, 0, 0, 0},
86 {"8086/16", CPU_8086, 4, 16000000, 1, 0, 0, 0},
87 {"", -1, 0, 0, 0, 0}
88 };
90 CPU cpus_pc1512[] =
91 {
92 /*8086 Amstrad*/
93 {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0},
94 {"", -1, 0, 0, 0, 0}
95 };
97 CPU cpus_286[] =
98 {
99 /*286*/
100 {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0},
101 {"286/8", CPU_286, 1, 8000000, 1, 0, 0, 0},
102 {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0},
103 {"286/12", CPU_286, 3, 12000000, 1, 0, 0, 0},
104 {"286/16", CPU_286, 4, 16000000, 1, 0, 0, 0},
105 {"286/20", CPU_286, 5, 20000000, 1, 0, 0, 0},
106 {"286/25", CPU_286, 6, 25000000, 1, 0, 0, 0},
107 {"", -1, 0, 0, 0, 0}
108 };
110 CPU cpus_ibmat[] =
111 {
112 /*286*/
113 {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0},
114 {"286/8", CPU_286, 0, 8000000, 1, 0, 0, 0},
115 {"", -1, 0, 0, 0, 0}
116 };
118 CPU cpus_i386[] =
119 {
120 /*i386*/
121 {"i386SX/16", CPU_386SX, 0, 16000000, 1, 0x2308, 0, 0},
122 {"i386SX/20", CPU_386SX, 1, 20000000, 1, 0x2308, 0, 0},
123 {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0x2308, 0, 0},
124 {"i386SX/33", CPU_386SX, 3, 33333333, 1, 0x2308, 0, 0},
125 {"i386DX/16", CPU_386DX, 0, 16000000, 1, 0x0308, 0, 0},
126 {"i386DX/20", CPU_386DX, 1, 20000000, 1, 0x0308, 0, 0},
127 {"i386DX/25", CPU_386DX, 2, 25000000, 1, 0x0308, 0, 0},
128 {"i386DX/33", CPU_386DX, 3, 33333333, 1, 0x0308, 0, 0},
129 {"", -1, 0, 0, 0}
130 };
132 CPU cpus_acer[] =
133 {
134 /*i386*/
135 {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0x2308, 0, 0},
136 {"", -1, 0, 0, 0}
137 };
139 CPU cpus_Am386[] =
140 {
141 /*Am386*/
142 {"Am386SX/16", CPU_386SX, 0, 16000000, 1, 0x2308, 0, 0},
143 {"Am386SX/20", CPU_386SX, 1, 20000000, 1, 0x2308, 0, 0},
144 {"Am386SX/25", CPU_386SX, 2, 25000000, 1, 0x2308, 0, 0},
145 {"Am386SX/33", CPU_386SX, 3, 33333333, 1, 0x2308, 0, 0},
146 {"Am386SX/40", CPU_386SX, 4, 40000000, 1, 0x2308, 0, 0},
147 {"Am386DX/25", CPU_386DX, 2, 25000000, 1, 0x0308, 0, 0},
148 {"Am386DX/33", CPU_386DX, 3, 33333333, 1, 0x0308, 0, 0},
149 {"Am386DX/40", CPU_386DX, 4, 40000000, 1, 0x0308, 0, 0},
150 {"", -1, 0, 0, 0}
151 };
153 CPU cpus_486SDLC[] =
154 {
155 /*Cx486SLC/DLC*/
156 {"Cx486SLC/20", CPU_486SLC, 1, 20000000, 1, 0, 0, 0x0000},
157 {"Cx486SLC/25", CPU_486SLC, 2, 25000000, 1, 0, 0, 0x0000},
158 {"Cx486SLC/33", CPU_486SLC, 3, 33333333, 1, 0, 0, 0x0000},
159 {"Cx486SRx2/32", CPU_486SLC, 3, 32000000, 2, 0, 0, 0x0006},
160 {"Cx486SRx2/40", CPU_486SLC, 4, 40000000, 2, 0, 0, 0x0006},
161 {"Cx486SRx2/50", CPU_486SLC, 5, 50000000, 2, 0, 0, 0x0006},
162 {"Cx486DLC/25", CPU_486DLC, 2, 25000000, 1, 0, 0, 0x0001},
163 {"Cx486DLC/33", CPU_486DLC, 3, 33333333, 1, 0, 0, 0x0001},
164 {"Cx486DLC/40", CPU_486DLC, 4, 40000000, 1, 0, 0, 0x0001},
165 {"Cx486DRx2/32", CPU_486DLC, 3, 32000000, 2, 0, 0, 0x0007},
166 {"Cx486DRx2/40", CPU_486DLC, 4, 40000000, 2, 0, 0, 0x0007},
167 {"Cx486DRx2/50", CPU_486DLC, 5, 50000000, 2, 0, 0, 0x0007},
168 {"Cx486DRx2/66", CPU_486DLC, 6, 66666666, 2, 0, 0, 0x0007},
169 {"", -1, 0, 0, 0}
170 };
172 CPU cpus_i486[] =
173 {
174 /*i486*/
175 {"i486SX/16", CPU_i486SX, 0, 16000000, 1, 0x42a, 0, 0},
176 {"i486SX/20", CPU_i486SX, 1, 20000000, 1, 0x42a, 0, 0},
177 {"i486SX/25", CPU_i486SX, 2, 25000000, 1, 0x42a, 0, 0},
178 {"i486SX/33", CPU_i486SX, 3, 33333333, 1, 0x42a, 0, 0},
179 {"i486SX2/50", CPU_i486SX, 5, 50000000, 2, 0x45b, 0, 0},
180 {"i486DX/25", CPU_i486DX, 2, 25000000, 1, 0x404, 0, 0},
181 {"i486DX/33", CPU_i486DX, 3, 33333333, 1, 0x404, 0, 0},
182 {"i486DX/50", CPU_i486DX, 5, 50000000, 1, 0x404, 0, 0},
183 {"i486DX2/40", CPU_i486DX, 4, 40000000, 2, 0x430, 0, 0},
184 {"i486DX2/50", CPU_i486DX, 5, 50000000, 2, 0x430, 0, 0},
185 {"i486DX2/66", CPU_i486DX, 6, 66666666, 2, 0x430, 0, 0},
186 {"iDX4/75", CPU_i486DX, 7, 75000000, 3, 0x481, 0x481, 0}, /*CPUID available on DX4, >= 75 MHz*/
187 {"iDX4/100", CPU_i486DX,10, 100000000, 3, 0x481, 0x481, 0}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
188 {"", -1, 0, 0, 0}
189 };
191 CPU cpus_Am486[] =
192 {
193 /*Am486/5x86*/
194 {"Am486SX/33", CPU_Am486SX, 3, 33333333, 1, 0x42a, 0, 0},
195 {"Am486SX/40", CPU_Am486SX, 4, 40000000, 1, 0x42a, 0, 0},
196 {"Am486SX2/50", CPU_Am486SX, 5, 50000000, 2, 0x45b, 0x45b, 0}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/
197 {"Am486SX2/66", CPU_Am486SX, 6, 66666666, 2, 0x45b, 0x45b, 0}, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/
198 {"Am486DX/33", CPU_Am486DX, 3, 33333333, 1, 0x430, 0, 0},
199 {"Am486DX/40", CPU_Am486DX, 4, 40000000, 1, 0x430, 0, 0},
200 {"Am486DX2/50", CPU_Am486DX, 5, 50000000, 2, 0x470, 0x470, 0},
201 {"Am486DX2/66", CPU_Am486DX, 6, 66666666, 2, 0x470, 0x470, 0},
202 {"Am486DX2/80", CPU_Am486DX, 8, 80000000, 2, 0x470, 0x470, 0},
203 {"Am486DX4/75", CPU_Am486DX, 7, 75000000, 3, 0x482, 0x482, 0},
204 {"Am486DX4/90", CPU_Am486DX, 9, 90000000, 3, 0x482, 0x482, 0},
205 {"Am486DX4/100", CPU_Am486DX, 10, 100000000, 3, 0x482, 0x482, 0},
206 {"Am486DX4/120", CPU_Am486DX, 11, 120000000, 3, 0x482, 0x482, 0},
207 {"Am5x86/P75", CPU_Am486DX, 12, 133333333, 4, 0x4e0, 0x4e0, 0},
208 {"Am5x86/P75+", CPU_Am486DX, 13, 150000000, 4, 0x4e0, 0x4e0, 0},
209 {"", -1, 0, 0, 0}
210 };
212 CPU cpus_Cx486[] =
213 {
214 /*Cx486/5x86*/
215 {"Cx486S/25", CPU_Cx486S, 2, 25000000, 1, 0x420, 0, 0x0010},
216 {"Cx486S/33", CPU_Cx486S, 3, 33333333, 1, 0x420, 0, 0x0010},
217 {"Cx486S/40", CPU_Cx486S, 4, 40000000, 1, 0x420, 0, 0x0010},
218 {"Cx486DX/33", CPU_Cx486DX, 3, 33333333, 1, 0x430, 0, 0x051a},
219 {"Cx486DX/40", CPU_Cx486DX, 4, 40000000, 1, 0x430, 0, 0x051a},
220 {"Cx486DX2/50", CPU_Cx486DX, 5, 50000000, 2, 0x430, 0, 0x081b},
221 {"Cx486DX2/66", CPU_Cx486DX, 6, 66666666, 2, 0x430, 0, 0x0b1b},
222 {"Cx486DX2/80", CPU_Cx486DX, 8, 80000000, 2, 0x430, 0, 0x311b},
223 {"Cx486DX4/75", CPU_Cx486DX, 7, 75000000, 3, 0x480, 0, 0x361f},
224 {"Cx486DX4/100", CPU_Cx486DX, 10, 100000000, 3, 0x480, 0, 0x361f},
225 {"Cx5x86/100", CPU_Cx5x86, 10, 100000000, 3, 0x480, 0, 0x002f},
226 {"Cx5x86/120", CPU_Cx5x86, 11, 120000000, 3, 0x480, 0, 0x002f},
227 {"Cx5x86/133", CPU_Cx5x86, 12, 133333333, 4, 0x480, 0, 0x002f},
228 {"", -1, 0, 0, 0}
229 };
231 CPU cpus_WinChip[] =
232 {
233 /*IDT WinChip*/
234 {"WinChip 75", CPU_WINCHIP, 7, 75000000, 2, 0x540, 0x540, 0},
235 {"WinChip 90", CPU_WINCHIP, 9, 90000000, 2, 0x540, 0x540, 0},
236 {"WinChip 100", CPU_WINCHIP, 10, 100000000, 2, 0x540, 0x540, 0},
237 {"WinChip 120", CPU_WINCHIP, 11, 120000000, 2, 0x540, 0x540, 0},
238 {"WinChip 133", CPU_WINCHIP, 12, 133333333, 2, 0x540, 0x540, 0},
239 {"WinChip 150", CPU_WINCHIP, 13, 150000000, 3, 0x540, 0x540, 0},
240 {"WinChip 166", CPU_WINCHIP, 15, 166666666, 3, 0x540, 0x540, 0},
241 {"WinChip 180", CPU_WINCHIP, 16, 180000000, 3, 0x540, 0x540, 0},
242 {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 0x540, 0x540, 0},
243 {"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 0x540, 0x540, 0},
244 {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 0x540, 0x540, 0},
245 {"", -1, 0, 0, 0}
246 };
248 void cpu_set_edx()
249 {
250 EDX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset;
251 }
253 void cpu_set()
254 {
255 CPU *cpu_s = &models[model].cpu[cpu_manufacturer].cpus[cpu];
257 CPUID = cpu_s->cpuid_model;
258 cpuspeed = cpu_s->speed;
259 is8086 = (cpu_s->cpu_type >= CPU_8088);
260 is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC);
261 hasfpu = (cpu_s->cpu_type >= CPU_i486DX);
262 cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86);
263 cpu_16bitbus = (cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC);
264 if (cpu_s->multi)
265 cpu_busspeed = cpu_s->rspeed / cpu_s->multi;
266 cpu_multi = cpu_s->multi;
267 cpu_hasrdtsc = 0;
268 cpu_hasMMX = 0;
269 cpu_hasMSR = 0;
271 if (cpu_iscyrix)
272 io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL);
273 else
274 io_removehandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL);
276 pclog("hasfpu - %i\n",hasfpu);
277 pclog("is486 - %i %i\n",is486,cpu_s->cpu_type);
279 x86_setopcodes(ops_386, ops_386_0f);
281 memset(&msr, 0, sizeof(msr));
283 switch (cpu_s->cpu_type)
284 {
285 case CPU_8088:
286 case CPU_8086:
287 break;
289 case CPU_286:
290 x86_setopcodes(ops_286, ops_286_0f);
291 timing_rr = 2; /*register dest - register src*/
292 timing_rm = 7; /*register dest - memory src*/
293 timing_mr = 7; /*memory dest - register src*/
294 timing_mm = 7; /*memory dest - memory src*/
295 timing_rml = 9; /*register dest - memory src long*/
296 timing_mrl = 11; /*memory dest - register src long*/
297 timing_mml = 11; /*memory dest - memory src*/
298 timing_bt = 7-3; /*branch taken*/
299 timing_bnt = 3; /*branch not taken*/
300 break;
302 case CPU_386SX:
303 timing_rr = 2; /*register dest - register src*/
304 timing_rm = 6; /*register dest - memory src*/
305 timing_mr = 7; /*memory dest - register src*/
306 timing_mm = 6; /*memory dest - memory src*/
307 timing_rml = 8; /*register dest - memory src long*/
308 timing_mrl = 11; /*memory dest - register src long*/
309 timing_mml = 10; /*memory dest - memory src*/
310 timing_bt = 7-3; /*branch taken*/
311 timing_bnt = 3; /*branch not taken*/
312 break;
314 case CPU_386DX:
315 timing_rr = 2; /*register dest - register src*/
316 timing_rm = 6; /*register dest - memory src*/
317 timing_mr = 7; /*memory dest - register src*/
318 timing_mm = 6; /*memory dest - memory src*/
319 timing_rml = 6; /*register dest - memory src long*/
320 timing_mrl = 7; /*memory dest - register src long*/
321 timing_mml = 6; /*memory dest - memory src*/
322 timing_bt = 7-3; /*branch taken*/
323 timing_bnt = 3; /*branch not taken*/
324 break;
326 case CPU_486SLC:
327 timing_rr = 1; /*register dest - register src*/
328 timing_rm = 3; /*register dest - memory src*/
329 timing_mr = 5; /*memory dest - register src*/
330 timing_mm = 3;
331 timing_rml = 5; /*register dest - memory src long*/
332 timing_mrl = 7; /*memory dest - register src long*/
333 timing_mml = 7;
334 timing_bt = 6-1; /*branch taken*/
335 timing_bnt = 1; /*branch not taken*/
336 break;
338 case CPU_486DLC:
339 timing_rr = 1; /*register dest - register src*/
340 timing_rm = 3; /*register dest - memory src*/
341 timing_mr = 3; /*memory dest - register src*/
342 timing_mm = 3;
343 timing_rml = 3; /*register dest - memory src long*/
344 timing_mrl = 3; /*memory dest - register src long*/
345 timing_mml = 3;
346 timing_bt = 6-1; /*branch taken*/
347 timing_bnt = 1; /*branch not taken*/
348 break;
350 case CPU_i486SX:
351 case CPU_i486DX:
352 timing_rr = 1; /*register dest - register src*/
353 timing_rm = 2; /*register dest - memory src*/
354 timing_mr = 3; /*memory dest - register src*/
355 timing_mm = 3;
356 timing_rml = 2; /*register dest - memory src long*/
357 timing_mrl = 3; /*memory dest - register src long*/
358 timing_mml = 3;
359 timing_bt = 3-1; /*branch taken*/
360 timing_bnt = 1; /*branch not taken*/
361 break;
363 case CPU_Am486SX:
364 case CPU_Am486DX:
365 /*AMD timing identical to Intel*/
366 timing_rr = 1; /*register dest - register src*/
367 timing_rm = 2; /*register dest - memory src*/
368 timing_mr = 3; /*memory dest - register src*/
369 timing_mm = 3;
370 timing_rml = 2; /*register dest - memory src long*/
371 timing_mrl = 3; /*memory dest - register src long*/
372 timing_mml = 3;
373 timing_bt = 3-1; /*branch taken*/
374 timing_bnt = 1; /*branch not taken*/
375 break;
377 case CPU_Cx486S:
378 case CPU_Cx486DX:
379 timing_rr = 1; /*register dest - register src*/
380 timing_rm = 3; /*register dest - memory src*/
381 timing_mr = 3; /*memory dest - register src*/
382 timing_mm = 3;
383 timing_rml = 3; /*register dest - memory src long*/
384 timing_mrl = 3; /*memory dest - register src long*/
385 timing_mml = 3;
386 timing_bt = 4-1; /*branch taken*/
387 timing_bnt = 1; /*branch not taken*/
388 break;
390 case CPU_Cx5x86:
391 timing_rr = 1; /*register dest - register src*/
392 timing_rm = 1; /*register dest - memory src*/
393 timing_mr = 2; /*memory dest - register src*/
394 timing_mm = 2;
395 timing_rml = 1; /*register dest - memory src long*/
396 timing_mrl = 2; /*memory dest - register src long*/
397 timing_mml = 2;
398 timing_bt = 5-1; /*branch taken*/
399 timing_bnt = 1; /*branch not taken*/
400 break;
402 case CPU_WINCHIP:
403 x86_setopcodes(ops_386, ops_winchip_0f);
404 timing_rr = 1; /*register dest - register src*/
405 timing_rm = 2; /*register dest - memory src*/
406 timing_mr = 3; /*memory dest - register src*/
407 timing_mm = 3;
408 timing_rml = 2; /*register dest - memory src long*/
409 timing_mrl = 3; /*memory dest - register src long*/
410 timing_mml = 3;
411 timing_bt = 3-1; /*branch taken*/
412 timing_bnt = 1; /*branch not taken*/
413 cpu_hasrdtsc = 1;
414 msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
415 cpu_hasMMX = cpu_hasMSR = 1;
416 break;
418 default:
419 fatal("cpu_set : unknown CPU type %i\n", cpu_s->cpu_type);
420 }
421 }
423 void cpu_CPUID()
424 {
425 switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type)
426 {
427 case CPU_i486DX:
428 if (!EAX)
429 {
430 EAX = 0x00000001;
431 EBX = 0x756e6547;
432 EDX = 0x49656e69;
433 ECX = 0x6c65746e;
434 }
435 else if (EAX == 1)
436 {
437 EAX = CPUID;
438 EBX = ECX = 0;
439 EDX = CPUID_FPU; /*FPU*/
440 }
441 else
442 EAX = 0;
443 break;
445 case CPU_Am486SX:
446 if (!EAX)
447 {
448 EAX = 1;
449 EBX = 0x68747541;
450 ECX = 0x444D4163;
451 EDX = 0x69746E65;
452 }
453 else if (EAX == 1)
454 {
455 EAX = CPUID;
456 EBX = ECX = EDX = 0; /*No FPU*/
457 }
458 else
459 EAX = 0;
460 break;
462 case CPU_Am486DX:
463 if (!EAX)
464 {
465 EAX = 1;
466 EBX = 0x68747541;
467 ECX = 0x444D4163;
468 EDX = 0x69746E65;
469 }
470 else if (EAX == 1)
471 {
472 EAX = CPUID;
473 EBX = ECX = 0;
474 EDX = CPUID_FPU; /*FPU*/
475 }
476 else
477 EAX = 0;
478 break;
480 case CPU_WINCHIP:
481 if (!EAX)
482 {
483 EAX = 1;
484 if (msr.fcr2 & (1 << 14))
485 {
486 EBX = msr.fcr3 >> 32;
487 ECX = msr.fcr3 & 0xffffffff;
488 EDX = msr.fcr2 >> 32;
489 }
490 else
491 {
492 EBX = 0x746e6543; /*CentaurHauls*/
493 ECX = 0x736c7561;
494 EDX = 0x48727561;
495 }
496 }
497 else if (EAX == 1)
498 {
499 EAX = 0x540;
500 EBX = ECX = 0;
501 EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
502 if (msr.fcr & (1 << 9))
503 EDX |= CPUID_MMX;
504 }
505 else
506 EAX = 0;
507 break;
508 }
509 }
511 void cpu_RDMSR()
512 {
513 switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type)
514 {
515 case CPU_WINCHIP:
516 EAX = EDX = 0;
517 switch (ECX)
518 {
519 case 0x02:
520 EAX = msr.tr1;
521 break;
522 case 0x0e:
523 EAX = msr.tr12;
524 break;
525 case 0x10:
526 EAX = tsc & 0xffffffff;
527 EDX = tsc >> 32;
528 break;
529 case 0x11:
530 EAX = msr.cesr;
531 break;
532 case 0x107:
533 EAX = msr.fcr;
534 break;
535 case 0x108:
536 EAX = msr.fcr2 & 0xffffffff;
537 EDX = msr.fcr2 >> 32;
538 break;
539 case 0x10a:
540 EAX = cpu_multi & 3;
541 break;
542 }
543 break;
544 }
545 }
547 void cpu_WRMSR()
548 {
549 switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type)
550 {
551 case CPU_WINCHIP:
552 EAX = EDX = 0;
553 switch (ECX)
554 {
555 case 0x02:
556 msr.tr1 = EAX & 2;
557 break;
558 case 0x0e:
559 msr.tr12 = EAX & 0x228;
560 break;
561 case 0x10:
562 tsc = EAX | ((uint64_t)EDX << 32);
563 break;
564 case 0x11:
565 msr.cesr = EAX & 0xff00ff;
566 break;
567 case 0x107:
568 msr.fcr = EAX;
569 cpu_hasMMX = EAX & (1 << 9);
570 if (EAX & (1 << 29))
571 CPUID = 0;
572 else
573 CPUID = models[model].cpu[cpu_manufacturer].cpus[cpu].cpuid_model;
574 break;
575 case 0x108:
576 msr.fcr2 = EAX | ((uint64_t)EDX << 32);
577 break;
578 case 0x109:
579 msr.fcr3 = EAX | ((uint64_t)EDX << 32);
580 break;
581 }
582 break;
583 }
584 }
586 static int cyrix_addr;
588 void cyrix_write(uint16_t addr, uint8_t val, void *priv)
589 {
590 if (!(addr & 1)) cyrix_addr = val;
591 // else pclog("Write Cyrix %02X %02X\n",cyrix_addr,val);
592 }
594 uint8_t cyrix_read(uint16_t addr, void *priv)
595 {
596 if (addr & 1)
597 {
598 switch (cyrix_addr)
599 {
600 case 0xfe: return models[model].cpu[cpu_manufacturer].cpus[cpu].cyrix_id & 0xff;
601 case 0xff: return models[model].cpu[cpu_manufacturer].cpus[cpu].cyrix_id >> 8;
602 }
603 if ((cyrix_addr & ~0xf0) == 0xc0) return 0xff;
604 if (cyrix_addr == 0x20 && models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_Cx5x86) return 0xff;
605 }
606 return 0xff;
607 }
