1 /*
2     Intel 386 emulator
3 
4     Written by Ville Linde
5 
6     Currently supports:
7         Intel 386
8         Intel 486
9         Intel Pentium
10         Cyrix MediaGX
11 */
12 
13 #include "burnint.h"
14 #include "driver.h"
15 #include <stddef.h>
16 
17 static UINT8 **memmap[2];
18 static INT32 cpu_running = 1;
19 static INT32 current_num_cycles = 0;
20 
21 #define MAP_BITS		32
22 #define MAP_PAGE_SHIFT	12
23 #define MAP_PAGE_MASK	0xfff
24 #define MAP_MASK		0xfffff
25 
map_init()26 static void map_init()
27 {
28 	memmap[0] = (UINT8**)BurnMalloc((MAP_MASK + 1) * sizeof(UINT8**));
29 	memmap[1] = (UINT8**)BurnMalloc((MAP_MASK + 1) * sizeof(UINT8**));
30 }
31 
32 static UINT8 (*program_read_byte)(UINT32) = NULL;
33 static UINT16 (*program_read_word)(UINT32) = NULL;
34 static UINT32 (*program_read_dword)(UINT32) = NULL;
35 static void (*program_write_byte)(UINT32,UINT8) = NULL;
36 static void (*program_write_word)(UINT32,UINT16) = NULL;
37 static void (*program_write_dword)(UINT32,UINT32) = NULL;
38 
39 static UINT8 (*io_read_byte)(UINT32);
40 static UINT16 (*io_read_word)(UINT32);
41 static UINT32 (*io_read_dword)(UINT32);
42 static void (*io_write_byte)(UINT32,UINT8);
43 static void (*io_write_word)(UINT32,UINT16);
44 static void (*io_write_dword)(UINT32,UINT32);
45 
i386SetReadHandlers(UINT8 (* read8)(UINT32),UINT16 (* read16)(UINT32),UINT32 (* read32)(UINT32))46 void i386SetReadHandlers(UINT8 (*read8)(UINT32), UINT16 (*read16)(UINT32), UINT32 (*read32)(UINT32))
47 {
48 	program_read_byte = read8;
49 	program_read_word = read16;
50 	program_read_dword = read32;
51 }
52 
i386SetWriteHandlers(void (* write8)(UINT32,UINT8),void (* write16)(UINT32,UINT16),void (* write32)(UINT32,UINT32))53 void i386SetWriteHandlers(void (*write8)(UINT32,UINT8), void (*write16)(UINT32,UINT16), void (*write32)(UINT32,UINT32))
54 {
55 	program_write_byte = write8;
56 	program_write_word = write16;
57 	program_write_dword = write32;
58 }
59 
i386MapMemory(UINT8 * mem,UINT64 start,UINT64 end,UINT32 flags)60 void i386MapMemory(UINT8 *mem, UINT64 start, UINT64 end, UINT32 flags)
61 {
62 	for (UINT64 i = start; i < end; i += (1 << MAP_PAGE_SHIFT)) {
63 		if (flags & MAP_ROM) memmap[0][i >> MAP_PAGE_SHIFT] = mem == NULL ? NULL : (mem + (i - start));
64 		if (flags & MAP_WRITE) memmap[1][i >> MAP_PAGE_SHIFT] = mem == NULL ? NULL : (mem + (i - start));
65 	}
66 }
67 
program_read_byte_32le(UINT32 address)68 static UINT8 program_read_byte_32le(UINT32 address)
69 {
70 	if (memmap[0][address >> MAP_PAGE_SHIFT]) {
71 		return memmap[0][address >> MAP_PAGE_SHIFT][address & MAP_PAGE_MASK];
72 	}
73 
74 	if (program_read_byte) {
75 		return program_read_byte(address);
76 	}
77 
78 	bprintf (0, _T("program_read_byte_32le(0x%5.5x)"), address);
79 	return 0;
80 }
81 
i386ReadByte(UINT32 address)82 UINT8 i386ReadByte(UINT32 address)
83 {
84 	return program_read_byte_32le(address);
85 }
86 
program_read_word_32le(UINT32 address)87 static UINT16 program_read_word_32le(UINT32 address)
88 {
89 	UINT16 *ptr = (UINT16*)memmap[0][address >> MAP_PAGE_SHIFT];
90 	if (ptr) {
91 		return BURN_ENDIAN_SWAP_INT16(ptr[(address & MAP_PAGE_MASK) / 2]);
92 	}
93 
94 	if (program_read_word) {
95 		return program_read_word(address);
96 	}
97 
98 	bprintf (0, _T("program_read_word_32le(0x%5.5x)"), address);
99 	return 0;
100 }
101 
program_read_dword_32le(UINT32 address)102 static UINT32 program_read_dword_32le(UINT32 address)
103 {
104 	UINT32 *ptr = (UINT32*)memmap[0][address >> MAP_PAGE_SHIFT];
105 	if (ptr) {
106 		return BURN_ENDIAN_SWAP_INT32(ptr[(address & MAP_PAGE_MASK) / 4]);
107 	}
108 
109 	if (program_read_dword) {
110 		return program_read_dword(address);
111 	}
112 
113 	bprintf (0, _T("program_read_dword_32le(0x%5.5x)"), address);
114 	return 0;
115 }
116 
i386ReadLong(UINT32 address)117 UINT32 i386ReadLong(UINT32 address)
118 {
119 	return program_read_dword_32le(address);
120 }
121 
program_write_byte_32le(UINT32 address,UINT8 data)122 static void program_write_byte_32le(UINT32 address, UINT8 data)
123 {
124 	if (memmap[1][address >> MAP_PAGE_SHIFT]) {
125 		memmap[1][address >> MAP_PAGE_SHIFT][address & MAP_PAGE_MASK] = data;
126 		return;
127 	}
128 
129 	if (program_write_byte) {
130 		program_write_byte(address, data);
131 		return;
132 	}
133 
134 	bprintf (0, _T("program_write_byte_32le(0x%5.5x, 0x%2.2x)"), address, data);
135 }
136 
program_write_word_32le(UINT32 address,UINT16 data)137 static void program_write_word_32le(UINT32 address, UINT16 data)
138 {
139 	UINT16 *ptr = (UINT16*)memmap[1][address >> MAP_PAGE_SHIFT];
140 	if (ptr) {
141 		ptr[(address & MAP_PAGE_MASK) / 2] = BURN_ENDIAN_SWAP_INT16(data);
142 		return;
143 	}
144 
145 	if (program_write_word) {
146 		program_write_word(address, data);
147 		return;
148 	}
149 
150 	bprintf (0, _T("program_write_word_32le(0x%5.5x, 0x%4.4x)"), address, data);
151 }
152 
program_write_dword_32le(UINT32 address,UINT32 data)153 static void program_write_dword_32le(UINT32 address, UINT32 data)
154 {
155 	UINT32 *ptr = (UINT32*)memmap[1][address >> MAP_PAGE_SHIFT];
156 
157 	if (ptr) {
158 		ptr[(address & MAP_PAGE_MASK) / 4] = BURN_ENDIAN_SWAP_INT32(data);
159 		return;
160 	}
161 
162 	if (program_write_dword) {
163 		program_write_dword(address, data);
164 		return;
165 	}
166 
167 	bprintf (0, _T("program_write_dword_32le(0x%5.5x, 0x%8.8x)"), address, data);
168 }
169 
cpu_readop(UINT32 address)170 static UINT8 cpu_readop(UINT32 address)
171 {
172 //	bprintf (0, _T("cpu_readop(0x%5.5x)\n"), address);
173 	return program_read_byte_32le(address);
174 }
175 
cpu_readop16(UINT32 address)176 static UINT16 cpu_readop16(UINT32 address)
177 {
178 //	bprintf (0, _T("cpu_readop16(0x%5.5x)\n"), address);
179 	return program_read_word_32le(address);
180 }
181 
cpu_readop32(UINT32 address)182 static UINT32 cpu_readop32(UINT32 address)
183 {
184 //	bprintf (0, _T("cpu_readop32(0x%5.5x)\n"), address);
185 	return program_read_dword_32le(address);
186 }
187 
io_read_byte_32le(UINT32 address)188 static UINT8 io_read_byte_32le(UINT32 address)
189 {
190 	bprintf (0, _T("io_read_byte_32le(0x%5.5x)"), address);
191 
192 	if (io_read_byte) {
193 		return io_read_byte(address);
194 	}
195 
196 	return 0;
197 }
198 
io_read_word_32le(UINT32 address)199 static UINT16 io_read_word_32le(UINT32 address)
200 {
201 	if (io_read_word) {
202 		return io_read_word(address);
203 	}
204 
205 	bprintf (0, _T("io_read_word_32le(0x%5.5x)"), address);
206 
207 	return 0;
208 }
209 
io_read_dword_32le(UINT32 address)210 static UINT32 io_read_dword_32le(UINT32 address)
211 {
212 	if (io_read_dword) {
213 		return io_read_dword(address);
214 	}
215 
216 	bprintf (0, _T("io_read_dword_32le(0x%5.5x)"), address);
217 
218 	return 0;
219 }
220 
io_write_byte_32le(UINT32 address,UINT8 data)221 static void io_write_byte_32le(UINT32 address, UINT8 data)
222 {
223 	if (io_write_byte) {
224 		io_write_byte(address, data);
225 		return;
226 	}
227 
228 	bprintf (0, _T("io_write_byte_32le(0x%5.5x, 0x%2.2x)"), address, data);
229 }
230 
io_write_word_32le(UINT32 address,UINT16 data)231 static void io_write_word_32le(UINT32 address, UINT16 data)
232 {
233 	if (io_write_word) {
234 		io_write_word(address, data);
235 		return;
236 	}
237 
238 	bprintf (0, _T("io_write_word_32le(0x%5.5x, 0x%4.4x)"), address, data);
239 }
240 
io_write_dword_32le(UINT32 address,UINT32 data)241 static void io_write_dword_32le(UINT32 address, UINT32 data)
242 {
243 	if (io_write_dword) {
244 		io_write_dword(address, data);
245 		return;
246 	}
247 
248 	bprintf (0, _T("io_write_dword_32le(0x%5.5x, 0x%8.8x)"), address, data);
249 }
250 
cheat_write_byte(UINT32 address,UINT8 data)251 static void cheat_write_byte(UINT32 address, UINT8 data)
252 {
253 	if (memmap[0][address >> 12]) memmap[0][address >> 12][address & 0xfff] = data;
254 	if (memmap[1][address >> 12]) memmap[1][address >> 12][address & 0xfff] = data;
255 
256 	if (program_write_byte) {
257 		program_write_byte(address, data);
258 		return;
259 	}
260 
261 	bprintf (0, _T("cheat_write_byte(0x%5.5x, 0x%2.2x)"), address, data);
262 }
263 
264 #define change_pc(x)	I.pc = (x)
265 
266 #include "i386.h"
267 #include "i386intf.h"
268 
269 int parity_table[256];
270 MODRM_TABLE MODRM_table[256];
271 
272 /*************************************************************************/
273 
274 #define INT_DEBUG	1
275 
i386_load_segment_descriptor(int segment)276 void i386_load_segment_descriptor( int segment )
277 {
278 	UINT32 v1,v2;
279 	UINT32 base, limit;
280 	int entry;
281 
282 	if (PROTECTED_MODE)
283 	{
284 		if( I.sreg[segment].selector & 0x4 ) {
285 			base = I.ldtr.base;
286 			limit = I.ldtr.limit;
287 		} else {
288 			base = I.gdtr.base;
289 			limit = I.gdtr.limit;
290 		}
291 
292 		if (limit == 0)
293 			return;
294 		entry = (I.sreg[segment].selector % limit) & ~0x7;
295 
296 		v1 = READ32( base + entry );
297 		v2 = READ32( base + entry + 4 );
298 
299 		I.sreg[segment].base = (v2 & 0xff000000) | ((v2 & 0xff) << 16) | ((v1 >> 16) & 0xffff);
300 		I.sreg[segment].limit = ((v2 << 16) & 0xf0000) | (v1 & 0xffff);
301 		I.sreg[segment].d = ((v2 & 0x400000) && PROTECTED_MODE && !V8086_MODE) ? 1 : 0;
302 	}
303 	else
304 	{
305 		I.sreg[segment].base = I.sreg[segment].selector << 4;
306 
307 		if( segment == CS && !I.performed_intersegment_jump )
308 			I.sreg[segment].base |= 0xfff00000;
309 	}
310 }
311 
get_flags(void)312 UINT32 get_flags(void)
313 {
314 	UINT32 f = 0x2;
315 	f |= I.CF;
316 	f |= I.PF << 2;
317 	f |= I.AF << 4;
318 	f |= I.ZF << 6;
319 	f |= I.SF << 7;
320 	f |= I.TF << 8;
321 	f |= I.IF << 9;
322 	f |= I.DF << 10;
323 	f |= I.OF << 11;
324 	return (I.eflags & 0xFFFF0000) | (f & 0xFFFF);
325 }
326 
set_flags(UINT32 f)327 void set_flags( UINT32 f )
328 {
329 	I.CF = (f & 0x1) ? 1 : 0;
330 	I.PF = (f & 0x4) ? 1 : 0;
331 	I.AF = (f & 0x10) ? 1 : 0;
332 	I.ZF = (f & 0x40) ? 1 : 0;
333 	I.SF = (f & 0x80) ? 1 : 0;
334 	I.TF = (f & 0x100) ? 1 : 0;
335 	I.IF = (f & 0x200) ? 1 : 0;
336 	I.DF = (f & 0x400) ? 1 : 0;
337 	I.OF = (f & 0x800) ? 1 : 0;
338 }
339 
sib_byte(UINT8 mod,UINT32 * out_ea,UINT8 * out_segment)340 static void sib_byte(UINT8 mod, UINT32* out_ea, UINT8* out_segment)
341 {
342 	UINT32 ea = 0;
343 	UINT8 segment = 0;
344 	UINT8 scale, i, base;
345 	UINT8 sib = FETCH();
346 	scale = (sib >> 6) & 0x3;
347 	i = (sib >> 3) & 0x7;
348 	base = sib & 0x7;
349 
350 	switch( base )
351 	{
352 		case 0: ea = REG32(EAX); segment = DS; break;
353 		case 1: ea = REG32(ECX); segment = DS; break;
354 		case 2: ea = REG32(EDX); segment = DS; break;
355 		case 3: ea = REG32(EBX); segment = DS; break;
356 		case 4: ea = REG32(ESP); segment = SS; break;
357 		case 5:
358 			if( mod == 0 ) {
359 				ea = FETCH32();
360 				segment = DS;
361 			} else if( mod == 1 ) {
362 				ea = REG32(EBP);
363 				segment = SS;
364 			} else if( mod == 2 ) {
365 				ea = REG32(EBP);
366 				segment = SS;
367 			}
368 			break;
369 		case 6: ea = REG32(ESI); segment = DS; break;
370 		case 7: ea = REG32(EDI); segment = DS; break;
371 	}
372 	switch( i )
373 	{
374 		case 0: ea += REG32(EAX) * (1 << scale); break;
375 		case 1: ea += REG32(ECX) * (1 << scale); break;
376 		case 2: ea += REG32(EDX) * (1 << scale); break;
377 		case 3: ea += REG32(EBX) * (1 << scale); break;
378 		case 4: break;
379 		case 5: ea += REG32(EBP) * (1 << scale); break;
380 		case 6: ea += REG32(ESI) * (1 << scale); break;
381 		case 7: ea += REG32(EDI) * (1 << scale); break;
382 	}
383 	*out_ea = ea;
384 	*out_segment = segment;
385 }
386 
modrm_to_EA(UINT8 mod_rm,UINT32 * out_ea,UINT8 * out_segment)387 static void modrm_to_EA(UINT8 mod_rm, UINT32* out_ea, UINT8* out_segment)
388 {
389 	INT8 disp8;
390 	INT16 disp16;
391 	INT32 disp32;
392 	UINT8 mod = (mod_rm >> 6) & 0x3;
393 	UINT8 rm = mod_rm & 0x7;
394 	UINT32 ea;
395 	UINT8 segment;
396 
397 	//if( mod_rm >= 0xc0 )
398 	//	osd_die("i386: Called modrm_to_EA with modrm value %02X !\n",mod_rm);
399 
400 	if( I.address_size ) {
401 		switch( rm )
402 		{
403 			default:
404 			case 0: ea = REG32(EAX); segment = DS; break;
405 			case 1: ea = REG32(ECX); segment = DS; break;
406 			case 2: ea = REG32(EDX); segment = DS; break;
407 			case 3: ea = REG32(EBX); segment = DS; break;
408 			case 4: sib_byte( mod, &ea, &segment ); break;
409 			case 5:
410 				if( mod == 0 ) {
411 					ea = FETCH32(); segment = DS;
412 				} else {
413 					ea = REG32(EBP); segment = SS;
414 				}
415 				break;
416 			case 6: ea = REG32(ESI); segment = DS; break;
417 			case 7: ea = REG32(EDI); segment = DS; break;
418 		}
419 		if( mod == 1 ) {
420 			disp8 = FETCH();
421 			ea += (INT32)disp8;
422 		} else if( mod == 2 ) {
423 			disp32 = FETCH32();
424 			ea += disp32;
425 		}
426 
427 		if( I.segment_prefix )
428 			segment = I.segment_override;
429 
430 		*out_ea = ea;
431 		*out_segment = segment;
432 
433 	} else {
434 		switch( rm )
435 		{
436 			default:
437 			case 0: ea = REG16(BX) + REG16(SI); segment = DS; break;
438 			case 1: ea = REG16(BX) + REG16(DI); segment = DS; break;
439 			case 2: ea = REG16(BP) + REG16(SI); segment = SS; break;
440 			case 3: ea = REG16(BP) + REG16(DI); segment = SS; break;
441 			case 4: ea = REG16(SI); segment = DS; break;
442 			case 5: ea = REG16(DI); segment = DS; break;
443 			case 6:
444 				if( mod == 0 ) {
445 					ea = FETCH16(); segment = DS;
446 				} else {
447 					ea = REG16(BP); segment = SS;
448 				}
449 				break;
450 			case 7: ea = REG16(BX); segment = DS; break;
451 		}
452 		if( mod == 1 ) {
453 			disp8 = FETCH();
454 			ea += (INT32)disp8;
455 		} else if( mod == 2 ) {
456 			disp16 = FETCH16();
457 			ea += (INT32)disp16;
458 		}
459 
460 		if( I.segment_prefix )
461 			segment = I.segment_override;
462 
463 		*out_ea = ea & 0xffff;
464 		*out_segment = segment;
465 	}
466 }
467 
GetNonTranslatedEA(UINT8 modrm)468 static UINT32 GetNonTranslatedEA(UINT8 modrm)
469 {
470 	UINT8 segment;
471 	UINT32 ea;
472 	modrm_to_EA( modrm, &ea, &segment );
473 	return ea;
474 }
475 
GetEA(UINT8 modrm)476 static UINT32 GetEA(UINT8 modrm)
477 {
478 	UINT8 segment;
479 	UINT32 ea;
480 	modrm_to_EA( modrm, &ea, &segment );
481 	return i386_translate( segment, ea );
482 }
483 
i386_trap(int irq,int irq_gate)484 static void i386_trap(int irq, int irq_gate)
485 {
486 	/*  I386 Interrupts/Traps/Faults:
487      *
488      *  0x00    Divide by zero
489      *  0x01    Debug exception
490      *  0x02    NMI
491      *  0x03    Int3
492      *  0x04    Overflow
493      *  0x05    Array bounds check
494      *  0x06    Illegal Opcode
495      *  0x07    FPU not available
496      *  0x08    Double fault
497      *  0x09    Coprocessor segment overrun
498      *  0x0a    Invalid task state
499      *  0x0b    Segment not present
500      *  0x0c    Stack exception
501      *  0x0d    General Protection Fault
502      *  0x0e    Page fault
503      *  0x0f    Reserved
504      *  0x10    Coprocessor error
505      */
506 	UINT32 v1, v2;
507 	UINT32 offset;
508 	UINT16 segment;
509 	int entry = irq * (I.sreg[CS].d ? 8 : 4);
510 
511 	/* Check if IRQ is out of IDTR's bounds */
512 	if( entry > I.idtr.limit ) {
513 		//osd_die("I386 Interrupt: IRQ out of IDTR bounds (IRQ: %d, IDTR Limit: %d)\n", irq, I.idtr.limit);
514 	}
515 
516 	if( !I.sreg[CS].d )
517 	{
518 		/* 16-bit */
519 		PUSH16( get_flags() & 0xffff );
520 		PUSH16( I.sreg[CS].selector );
521 		PUSH16( I.eip );
522 
523 		I.sreg[CS].selector = READ16( I.idtr.base + entry + 2 );
524 		I.eip = READ16( I.idtr.base + entry );
525 	}
526 	else
527 	{
528 		/* 32-bit */
529 		PUSH32( get_flags() & 0x00fcffff );
530 		PUSH32( I.sreg[CS].selector );
531 		PUSH32( I.eip );
532 
533 		v1 = READ32( I.idtr.base + entry );
534 		v2 = READ32( I.idtr.base + entry + 4 );
535 		offset = (v2 & 0xffff0000) | (v1 & 0xffff);
536 		segment = (v1 >> 16) & 0xffff;
537 
538 		I.sreg[CS].selector = segment;
539 		I.eip = offset;
540 	}
541 
542 	if (irq_gate)
543 	{
544 		I.IF = 0;
545 	}
546 
547 	i386_load_segment_descriptor(CS);
548 	CHANGE_PC(I.eip);
549 }
550 
i386_check_irq_line(void)551 static void i386_check_irq_line(void)
552 {
553 	/* Check if the interrupts are enabled */
554 	if ( I.irq_line && I.IF )
555 	{
556 		i386_trap(I.irq_callback(0), 1);
557 
558 		if (I.irq_hold) {
559 			I.irq_hold = 0;
560 			I.irq_line = 0;
561 		}
562 	}
563 }
564 
565 #include "cycles.h"
566 
567 UINT8 *cycle_table_rm[X86_NUM_CPUS];
568 UINT8 *cycle_table_pm[X86_NUM_CPUS];
569 
570 #define CYCLES_NUM(x)	(I.cycles -= (x))
571 
CYCLES(int x)572 INLINE void CYCLES(int x)
573 {
574 	if (PROTECTED_MODE)
575 	{
576 		I.cycles -= I.cycle_table_pm[x];
577 	}
578 	else
579 	{
580 		I.cycles -= I.cycle_table_rm[x];
581 	}
582 }
583 
CYCLES_RM(int modrm,int r,int m)584 INLINE void CYCLES_RM(int modrm, int r, int m)
585 {
586 	if (modrm >= 0xc0)
587 	{
588 		if (PROTECTED_MODE)
589 		{
590 			I.cycles -= I.cycle_table_pm[r];
591 		}
592 		else
593 		{
594 			I.cycles -= I.cycle_table_rm[r];
595 		}
596 	}
597 	else
598 	{
599 		if (PROTECTED_MODE)
600 		{
601 			I.cycles -= I.cycle_table_pm[m];
602 		}
603 		else
604 		{
605 			I.cycles -= I.cycle_table_rm[m];
606 		}
607 	}
608 }
609 
build_cycle_table(void)610 static void build_cycle_table(void)
611 {
612 	int i, j;
613 	for (j=0; j < X86_NUM_CPUS; j++)
614 	{
615 		if (!cycle_table_rm[j])
616 		{
617 			cycle_table_rm[j] = (UINT8*)BurnMalloc(sizeof(UINT8) * CYCLES_NUM_OPCODES);
618 		}
619 		if (!cycle_table_pm[j])
620 		{
621 			cycle_table_pm[j] = (UINT8*)BurnMalloc(sizeof(UINT8) * CYCLES_NUM_OPCODES);
622 		}
623 
624 		for (i=0; i < sizeof(x86_cycle_table)/sizeof(X86_CYCLE_TABLE); i++)
625 		{
626 			int opcode = x86_cycle_table[i].op;
627 			cycle_table_rm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][0];
628 			cycle_table_pm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][1];
629 		}
630 	}
631 }
632 
633 
634 
635 #include "i386ops.c"
636 #include "i386op16.c"
637 #include "i386op32.c"
638 #include "i486ops.c"
639 #include "pentops.c"
640 #include "x87ops.c"
641 #include "i386ops.h"
642 
I386OP(decode_opcode)643 static void I386OP(decode_opcode)(void)
644 {
645 	I.opcode = FETCH();
646 	if( I.operand_size )
647 		I.opcode_table1_32[I.opcode]();
648 	else
649 		I.opcode_table1_16[I.opcode]();
650 }
651 
652 /* Two-byte opcode prefix */
I386OP(decode_two_byte)653 static void I386OP(decode_two_byte)(void)
654 {
655 	I.opcode = FETCH();
656 	if( I.operand_size )
657 		I.opcode_table2_32[I.opcode]();
658 	else
659 		I.opcode_table2_16[I.opcode]();
660 }
661 
662 /*************************************************************************/
663 
i386_postload()664 static void i386_postload()
665 {
666 	int i;
667 	for (i = 0; i < 6; i++)
668 		i386_load_segment_descriptor(i);
669 	CHANGE_PC(I.eip);
670 }
671 
build_opcode_table(UINT32 features)672 static void build_opcode_table(UINT32 features)
673 {
674 	int i;
675 	for (i=0; i < 256; i++)
676 	{
677 		I.opcode_table1_16[i] = I386OP(invalid);
678 		I.opcode_table1_32[i] = I386OP(invalid);
679 		I.opcode_table2_16[i] = I386OP(invalid);
680 		I.opcode_table2_32[i] = I386OP(invalid);
681 	}
682 
683 	for (i=0; i < sizeof(x86_opcode_table)/sizeof(X86_OPCODE); i++)
684 	{
685 		X86_OPCODE *op = &x86_opcode_table[i];
686 
687 		if ((op->flags & features))
688 		{
689 			if (op->flags & OP_2BYTE)
690 			{
691 				I.opcode_table2_32[op->opcode] = op->handler32;
692 				I.opcode_table2_16[op->opcode] = op->handler16;
693 			}
694 			else
695 			{
696 				I.opcode_table1_32[op->opcode] = op->handler32;
697 				I.opcode_table1_16[op->opcode] = op->handler16;
698 			}
699 		}
700 	}
701 }
702 
i386Open(INT32)703 void i386Open(INT32)
704 {
705 
706 }
707 
i386Close()708 void i386Close()
709 {
710 
711 }
712 
i386Reset()713 void i386Reset()
714 {
715 	INT32 (*irqcb)(INT32);
716 	irqcb = I.irq_callback;
717 	memset( &I, 0, sizeof(I386_REGS) );
718 	I.irq_callback = irqcb;
719 
720 	I.sreg[CS].selector = 0xf000;
721 	I.sreg[CS].base		= 0xffff0000;
722 	I.sreg[CS].limit	= 0xffff;
723 
724 	I.idtr.base = 0;
725 	I.idtr.limit = 0x3ff;
726 
727 	I.a20_mask = ~0;
728 
729 	I.cr[0] = 0;
730 	I.eflags = 0;
731 	I.eip = 0xfff0;
732 
733 	REG32(EAX) = 0x0308;	// Intel 386, stepping D1
734 	REG32(EDX) = 0;
735 
736 	build_opcode_table(OP_I386);
737 	I.cycle_table_rm = cycle_table_rm[CPU_CYCLES_I386];
738 	I.cycle_table_pm = cycle_table_pm[CPU_CYCLES_I386];
739 
740 	CHANGE_PC(I.eip);
741 
742 	cpu_running = 1;
743 	current_num_cycles = 0;
744 }
745 
i386Exit()746 void i386Exit()
747 {
748 	BurnFree(memmap[0]);
749 	BurnFree(memmap[1]);
750 
751 	for (int j=0; j < X86_NUM_CPUS; j++)
752 	{
753 		if (cycle_table_rm[j])
754 		{
755 			BurnFree(cycle_table_rm[j]);
756 		}
757 		if (cycle_table_pm[j])
758 		{
759 			BurnFree(cycle_table_pm[j]);
760 		}
761 	}
762 }
763 
764 #if 0
765 static void i386_get_context(void *dst)
766 {
767 	if(dst) {
768 		*(I386_REGS *)dst = I;
769 	}
770 }
771 
772 static void i386_set_context(void *src)
773 {
774 	if(src) {
775 		I = *(I386_REGS *)src;
776 	}
777 
778 	CHANGE_PC(I.eip);
779 }
780 #endif
781 
i386_get_reg(int regnum)782 unsigned i386_get_reg(int regnum)
783 {
784 	switch(regnum)
785 	{
786 		case I386_PC:		return I.pc;
787 		case I386_EIP:		return I.eip;
788 		case I386_EAX:		return REG32(EAX);
789 		case I386_EBX:		return REG32(EBX);
790 		case I386_ECX:		return REG32(ECX);
791 		case I386_EDX:		return REG32(EDX);
792 		case I386_EBP:		return REG32(EBP);
793 		case I386_ESP:		return REG32(ESP);
794 		case I386_ESI:		return REG32(ESI);
795 		case I386_EDI:		return REG32(EDI);
796 		case I386_EFLAGS:	return I.eflags;
797 		case I386_CS:		return I.sreg[CS].selector;
798 		case I386_SS:		return I.sreg[SS].selector;
799 		case I386_DS:		return I.sreg[DS].selector;
800 		case I386_ES:		return I.sreg[ES].selector;
801 		case I386_FS:		return I.sreg[FS].selector;
802 		case I386_GS:		return I.sreg[GS].selector;
803 		case I386_CR0:		return I.cr[0];
804 		case I386_CR1:		return I.cr[1];
805 		case I386_CR2:		return I.cr[2];
806 		case I386_CR3:		return I.cr[3];
807 		case I386_DR0:		return I.dr[0];
808 		case I386_DR1:		return I.dr[1];
809 		case I386_DR2:		return I.dr[2];
810 		case I386_DR3:		return I.dr[3];
811 		case I386_DR4:		return I.dr[4];
812 		case I386_DR5:		return I.dr[5];
813 		case I386_DR6:		return I.dr[6];
814 		case I386_DR7:		return I.dr[7];
815 		case I386_TR6:		return I.tr[6];
816 		case I386_TR7:		return I.tr[7];
817 	}
818 	return 0;
819 }
820 
i386_set_reg(int regnum,unsigned value)821 void i386_set_reg(int regnum, unsigned value)
822 {
823 	switch(regnum)
824 	{
825 		case I386_EIP:		I.eip = value; break;
826 		case I386_EAX:		REG32(EAX) = value; break;
827 		case I386_EBX:		REG32(EBX) = value; break;
828 		case I386_ECX:		REG32(ECX) = value; break;
829 		case I386_EDX:		REG32(EDX) = value; break;
830 		case I386_EBP:		REG32(EBP) = value; break;
831 		case I386_ESP:		REG32(ESP) = value; break;
832 		case I386_ESI:		REG32(ESI) = value; break;
833 		case I386_EDI:		REG32(EDI) = value; break;
834 		case I386_EFLAGS:	I.eflags = value; break;
835 		case I386_CS:		I.sreg[CS].selector = value & 0xffff; break;
836 		case I386_SS:		I.sreg[SS].selector = value & 0xffff; break;
837 		case I386_DS:		I.sreg[DS].selector = value & 0xffff; break;
838 		case I386_ES:		I.sreg[ES].selector = value & 0xffff; break;
839 		case I386_FS:		I.sreg[FS].selector = value & 0xffff; break;
840 		case I386_GS:		I.sreg[GS].selector = value & 0xffff; break;
841 		case I386_CR0:		I.cr[0] = value; break;
842 		case I386_CR1:		I.cr[1] = value; break;
843 		case I386_CR2:		I.cr[2] = value; break;
844 		case I386_CR3:		I.cr[3] = value; break;
845 		case I386_DR0:		I.dr[0] = value; break;
846 		case I386_DR1:		I.dr[1] = value; break;
847 		case I386_DR2:		I.dr[2] = value; break;
848 		case I386_DR3:		I.dr[3] = value; break;
849 		case I386_DR4:		I.dr[4] = value; break;
850 		case I386_DR5:		I.dr[5] = value; break;
851 		case I386_DR6:		I.dr[6] = value; break;
852 		case I386_DR7:		I.dr[7] = value; break;
853 		case I386_TR6:		I.tr[6] = value; break;
854 		case I386_TR7:		I.tr[7] = value; break;
855 	}
856 }
857 
i386GetPC(INT32)858 UINT32 i386GetPC(INT32)
859 {
860 	return i386_get_reg(I386_PC);
861 }
862 
863 #if 0
864 static void i386_set_a20_line(int state)
865 {
866 	if (state)
867 	{
868 		I.a20_mask = ~(1 << 20);
869 	}
870 	else
871 	{
872 		I.a20_mask = ~0;
873 	}
874 }
875 #endif
876 
i386NewFrame()877 void i386NewFrame()
878 {
879 	I.tsc = 0;
880 }
881 
i386RunEnd()882 void i386RunEnd()
883 {
884 	cpu_running = 0;
885 }
886 
i386HaltUntilInterrupt(INT32 val)887 void i386HaltUntilInterrupt(INT32 val)
888 {
889 	I.halted = val;
890 }
891 
i386TotalCycles()892 INT32 i386TotalCycles()
893 {
894 	return I.tsc + (current_num_cycles - I.cycles);
895 }
896 
i386Run(INT32 num_cycles)897 INT32 i386Run(INT32 num_cycles)
898 {
899 	cpu_running = 1;
900 	current_num_cycles = num_cycles;
901 	I.cycles = num_cycles;
902 	I.base_cycles = num_cycles;
903 	CHANGE_PC(I.eip);
904 
905 	if (I.halted)
906 	{
907 		I.tsc += num_cycles;
908 		return num_cycles;
909 	}
910 
911 	while( I.cycles > 0 && cpu_running )
912 	{
913 		i386_check_irq_line();
914 
915 		I.operand_size = I.sreg[CS].d;
916 		I.address_size = I.sreg[CS].d;
917 		I.segment_prefix = 0;
918 		I.prev_eip = I.eip;
919 
920 	//	CALL_MAME_DEBUG;
921 
922 		I386OP(decode_opcode)();
923 	}
924 
925 	num_cycles = current_num_cycles - I.cycles;
926 	current_num_cycles = I.cycles = 0;
927 
928 	I.tsc += num_cycles;
929 
930 	return num_cycles;
931 }
932 
i386SetIRQLine(INT32 irqline,INT32 state)933 void i386SetIRQLine(INT32 irqline, INT32 state)
934 {
935 	if (I.halted)
936 	{
937 		I.halted = 0;
938 	}
939 
940 	if ( irqline == CPU_IRQLINE_NMI )
941 	{
942 		/* NMI (I do not think that this is 100% right) */
943 		if ( state )
944 			i386_trap(2, 1);
945 	}
946 	else
947 	{
948 		if (state == CPU_IRQSTATUS_AUTO || state == CPU_IRQSTATUS_HOLD)
949 		{
950 			I.irq_line = 1;
951 			I.irq_hold = 1;
952 		}
953 		else
954 		{
955 			I.irq_line = state;
956 			i386_check_irq_line();
957 		}
958 	}
959 }
960 
i386GetActive()961 INT32 i386GetActive()
962 {
963 	return 0;
964 }
965 
i386Idle(INT32 cycles)966 INT32 i386Idle(INT32 cycles)
967 {
968 	I.tsc += cycles;
969 
970 	return cycles;
971 }
972 
core_set_irq_line(INT32,INT32 line,INT32 state)973 static void core_set_irq_line(INT32, INT32 line, INT32 state)
974 {
975 	i386SetIRQLine(line, state);
976 }
977 
978 cpu_core_config i386Config =
979 {
980 	"i386",
981 	i386Open,
982 	i386Close,
983 	program_read_byte_32le,
984 	cheat_write_byte,
985 	i386GetActive,
986 	i386TotalCycles,
987 	i386NewFrame,
988 	i386Idle,
989 	core_set_irq_line,
990 	i386Run,
991 	i386RunEnd,
992 	i386Reset,
993 	0xffffffff,
994 	0
995 };
996 
dummy_irq_callback(INT32)997 static INT32 dummy_irq_callback(INT32) { return 0; }
998 
i386SetIRQCallback(INT32 (* irq_callback)(INT32))999 void i386SetIRQCallback(INT32 (*irq_callback)(INT32))
1000 {
1001 	I.irq_callback = irq_callback;
1002 }
1003 
i386Init(INT32)1004 void i386Init(INT32)
1005 {
1006 	int i, j;
1007 	int regs8[8] = {AL,CL,DL,BL,AH,CH,DH,BH};
1008 	int regs16[8] = {AX,CX,DX,BX,SP,BP,SI,DI};
1009 	int regs32[8] = {EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI};
1010 	int cpu = i386GetActive();
1011 //	const char *state_type = "I386";
1012 
1013 	build_cycle_table();
1014 
1015 	for( i=0; i < 256; i++ ) {
1016 		int c=0;
1017 		for( j=0; j < 8; j++ ) {
1018 			if( i & (1 << j) )
1019 				c++;
1020 		}
1021 		parity_table[i] = ~(c & 0x1) & 0x1;
1022 	}
1023 
1024 	for( i=0; i < 256; i++ ) {
1025 		MODRM_table[i].reg.b = regs8[(i >> 3) & 0x7];
1026 		MODRM_table[i].reg.w = regs16[(i >> 3) & 0x7];
1027 		MODRM_table[i].reg.d = regs32[(i >> 3) & 0x7];
1028 
1029 		MODRM_table[i].rm.b = regs8[i & 0x7];
1030 		MODRM_table[i].rm.w = regs16[i & 0x7];
1031 		MODRM_table[i].rm.d = regs32[i & 0x7];
1032 	}
1033 
1034 	CpuCheatRegister(cpu, &i386Config);
1035 
1036 	map_init();
1037 	i386SetReadHandlers(NULL, NULL, NULL);
1038 	i386SetWriteHandlers(NULL, NULL, NULL);
1039 	i386SetIRQCallback(dummy_irq_callback);
1040 
1041 #if 0
1042 	state_save_register_UINT32(state_type, cpu,	"REGS",			I.reg.d, 8);
1043 	state_save_register_UINT16(state_type, cpu,	"ES",			&I.sreg[ES].selector, 1);
1044 	state_save_register_UINT16(state_type, cpu,	"CS",			&I.sreg[CS].selector, 1);
1045 	state_save_register_UINT16(state_type, cpu,	"SS",			&I.sreg[SS].selector, 1);
1046 	state_save_register_UINT16(state_type, cpu,	"DS",			&I.sreg[DS].selector, 1);
1047 	state_save_register_UINT16(state_type, cpu,	"FS",			&I.sreg[FS].selector, 1);
1048 	state_save_register_UINT16(state_type, cpu,	"GS",			&I.sreg[GS].selector, 1);
1049 	state_save_register_UINT32(state_type, cpu,	"EIP",			&I.eip, 1);
1050 	state_save_register_UINT32(state_type, cpu,	"PREV_EIP",		&I.prev_eip, 1);
1051 	state_save_register_UINT8(state_type, cpu,	"CF",			&I.CF, 1);
1052 	state_save_register_UINT8(state_type, cpu,	"DF",			&I.DF, 1);
1053 	state_save_register_UINT8(state_type, cpu,	"SF",			&I.SF, 1);
1054 	state_save_register_UINT8(state_type, cpu,	"OF",			&I.OF, 1);
1055 	state_save_register_UINT8(state_type, cpu,	"ZF",			&I.ZF, 1);
1056 	state_save_register_UINT8(state_type, cpu,	"PF",			&I.PF, 1);
1057 	state_save_register_UINT8(state_type, cpu,	"AF",			&I.AF, 1);
1058 	state_save_register_UINT8(state_type, cpu,	"IF",			&I.IF, 1);
1059 	state_save_register_UINT8(state_type, cpu,	"TF",			&I.TF, 1);
1060 	state_save_register_UINT32(state_type, cpu,	"CR",			I.cr, 4);
1061 	state_save_register_UINT32(state_type, cpu,	"DR",			I.dr, 8);
1062 	state_save_register_UINT32(state_type, cpu,	"TR",			I.tr, 8);
1063 	state_save_register_UINT32(state_type, cpu,	"IDTR_BASE",	&I.idtr.base, 1);
1064 	state_save_register_UINT16(state_type, cpu,	"IDTR_LIMIT",	&I.idtr.limit, 1);
1065 	state_save_register_UINT32(state_type, cpu,	"GDTR_BASE",	&I.gdtr.base, 1);
1066 	state_save_register_UINT16(state_type, cpu,	"GDTR_LIMIT",	&I.gdtr.limit, 1);
1067 	state_save_register_int(state_type, cpu, "IRQ_LINE",		&I.irq_line);
1068 	state_save_register_UINT8(state_type, cpu,	"ISEGJMP",		&I.performed_intersegment_jump, 1);
1069 	state_save_register_func_postload(i386_postload);
1070 #endif
1071 }
1072 
1073 
i386Scan(INT32 nAction)1074 INT32 i386Scan(INT32 nAction)
1075 {
1076 	if (nAction & ACB_VOLATILE) {
1077 		struct BurnArea ba;
1078 
1079 		memset(&ba, 0, sizeof(ba));
1080 		ba.Data	  = (unsigned char*)&I;
1081 		ba.nLen	  = STRUCT_SIZE_HELPER(I386_REGS, fpu_top);
1082 		ba.szName = "I386 Registers";
1083 		BurnAcb(&ba);
1084 
1085 		SCAN_VAR(cpu_running);
1086 		SCAN_VAR(current_num_cycles);
1087 	}
1088 
1089 	if (nAction & ACB_WRITE) {
1090 		i386_postload();
1091 	}
1092 
1093 	return 0;
1094 }
1095 
1096 /*************************************************************************/
1097 
1098 #if 0
1099 static UINT8 i386_reg_layout[] =
1100 {
1101 	I386_EIP,		I386_ESP,		(UINT8)-1,
1102 	I386_EAX,		I386_EBP,		(UINT8)-1,
1103 	I386_EBX,		I386_ESI,		(UINT8)-1,
1104 	I386_ECX,		I386_EDI,		(UINT8)-1,
1105 	I386_EDX,		(UINT8)-1,
1106 	I386_CS,		I386_CR0,		(UINT8)-1,
1107 	I386_SS,		I386_CR1,		(UINT8)-1,
1108 	I386_DS,		I386_CR2,		(UINT8)-1,
1109 	I386_ES,		I386_CR3,		(UINT8)-1,
1110 	I386_FS,		I386_TR6,		(UINT8)-1,
1111 	I386_GS,		I386_TR7,		(UINT8)-1,
1112 	I386_DR0,		I386_DR1,		(UINT8)-1,
1113 	I386_DR2,		I386_DR3,		(UINT8)-1,
1114 	I386_DR4,		I386_DR5,		(UINT8)-1,
1115 	I386_DR6,		I386_DR7,		0
1116 };
1117 
1118 static UINT8 i386_win_layout[] =
1119 {
1120 	 0, 0,32,12,	/* register window (top rows) */
1121 	33, 0,46,15,	/* disassembler window (left colums) */
1122 	33,10,46,12,	/* memory #2 window (right, lower middle) */
1123 	 0,19,32, 3,	/* memory #1 window (right, upper middle) */
1124 	 0,23,80, 1,	/* command line window (bottom rows) */
1125 };
1126 #endif
1127 
1128 /*************************************************************************/
1129 
1130 #if 0
1131 static int translate_address_cb(int space, UINT32 *addr)
1132 {
1133 #define ADDRESS_SPACE_PROGRAM 0	// ??
1134 
1135 	if (space == ADDRESS_SPACE_PROGRAM && (I.cr[0] & 0x80000000))
1136 		return translate_address(addr);
1137 	return 1;
1138 }
1139 
1140 static INT32 i386_dasm(char *buffer, offs_t pc, UINT8 *oprom, UINT8 *opram, int bytes)
1141 {
1142 #ifdef MAME_DEBUG
1143 	return i386_dasm_one(buffer, pc, oprom, I.sreg[CS].d, I.sreg[CS].d);
1144 #else
1145 	sprintf( buffer, "$%02X", *oprom );
1146 	return 1;
1147 #endif
1148 }
1149 #endif
1150 
1151 #if 0
1152 
1153 static void i386_set_info(UINT32 state, union cpuinfo *info)
1154 {
1155 	if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 1)
1156 	{
1157 		i386_set_irq_line(state-CPUINFO_INT_INPUT_STATE, info->i);
1158 		return;
1159 	}
1160 	else if (state == CPUINFO_INT_INPUT_STATE+INPUT_LINE_A20)
1161 	{
1162 		i386_set_a20_line(info->i);
1163 		return;
1164 	}
1165 
1166 	switch (state)
1167 	{
1168 		/* --- the following bits of info are set as 64-bit signed integers --- */
1169 		case CPUINFO_INT_PC:
1170 		case CPUINFO_INT_REGISTER + I386_PC:			I.pc = info->i;break;
1171 		case CPUINFO_INT_REGISTER + I386_EIP:			I.eip = info->i; CHANGE_PC(I.eip); break;
1172 		case CPUINFO_INT_REGISTER + I386_EAX:			REG32(EAX) = info->i; break;
1173 		case CPUINFO_INT_REGISTER + I386_EBX:			REG32(EBX) = info->i; break;
1174 		case CPUINFO_INT_REGISTER + I386_ECX:			REG32(ECX) = info->i; break;
1175 		case CPUINFO_INT_REGISTER + I386_EDX:			REG32(EDX) = info->i; break;
1176 		case CPUINFO_INT_REGISTER + I386_EBP:			REG32(EBP) = info->i; break;
1177 		case CPUINFO_INT_SP:
1178 		case CPUINFO_INT_REGISTER + I386_ESP:			REG32(ESP) = info->i; break;
1179 		case CPUINFO_INT_REGISTER + I386_ESI:			REG32(ESI) = info->i; break;
1180 		case CPUINFO_INT_REGISTER + I386_EDI:			REG32(EDI) = info->i; break;
1181 		case CPUINFO_INT_REGISTER + I386_EFLAGS:		I.eflags = info->i; break;
1182 		case CPUINFO_INT_REGISTER + I386_CS:			I.sreg[CS].selector = info->i & 0xffff; break;
1183 		case CPUINFO_INT_REGISTER + I386_SS:			I.sreg[SS].selector = info->i & 0xffff; break;
1184 		case CPUINFO_INT_REGISTER + I386_DS:			I.sreg[DS].selector = info->i & 0xffff; break;
1185 		case CPUINFO_INT_REGISTER + I386_ES:			I.sreg[ES].selector = info->i & 0xffff; break;
1186 		case CPUINFO_INT_REGISTER + I386_FS:			I.sreg[FS].selector = info->i & 0xffff; break;
1187 		case CPUINFO_INT_REGISTER + I386_GS:			I.sreg[GS].selector = info->i & 0xffff; break;
1188 		case CPUINFO_INT_REGISTER + I386_CR0:			I.cr[0] = info->i; break;
1189 		case CPUINFO_INT_REGISTER + I386_CR1:			I.cr[1] = info->i; break;
1190 		case CPUINFO_INT_REGISTER + I386_CR2:			I.cr[2] = info->i; break;
1191 		case CPUINFO_INT_REGISTER + I386_CR3:			I.cr[3] = info->i; break;
1192 		case CPUINFO_INT_REGISTER + I386_DR0:			I.dr[0] = info->i; break;
1193 		case CPUINFO_INT_REGISTER + I386_DR1:			I.dr[1] = info->i; break;
1194 		case CPUINFO_INT_REGISTER + I386_DR2:			I.dr[2] = info->i; break;
1195 		case CPUINFO_INT_REGISTER + I386_DR3:			I.dr[3] = info->i; break;
1196 		case CPUINFO_INT_REGISTER + I386_DR4:			I.dr[4] = info->i; break;
1197 		case CPUINFO_INT_REGISTER + I386_DR5:			I.dr[5] = info->i; break;
1198 		case CPUINFO_INT_REGISTER + I386_DR6:			I.dr[6] = info->i; break;
1199 		case CPUINFO_INT_REGISTER + I386_DR7:			I.dr[7] = info->i; break;
1200 		case CPUINFO_INT_REGISTER + I386_TR6:			I.tr[6] = info->i; break;
1201 		case CPUINFO_INT_REGISTER + I386_TR7:			I.tr[7] = info->i; break;
1202 
1203 		/* --- the following bits of info are set as pointers to data or functions --- */
1204 		case CPUINFO_PTR_IRQ_CALLBACK:					I.irq_callback = info->irqcallback; break;
1205 	}
1206 }
1207 
1208 void i386_get_info(UINT32 state, union cpuinfo *info)
1209 {
1210 	switch (state)
1211 	{
1212 		/* --- the following bits of info are returned as 64-bit signed integers --- */
1213 		case CPUINFO_INT_CONTEXT_SIZE:				info->i = sizeof(I386_REGS);			break;
1214 		case CPUINFO_INT_INPUT_LINES:				info->i = 32;							break;
1215 		case CPUINFO_INT_DEFAULT_IRQ_VECTOR:		info->i = 0;							break;
1216 		case CPUINFO_INT_ENDIANNESS:				info->i = CPU_IS_LE;					break;
1217 		case CPUINFO_INT_CLOCK_DIVIDER:				info->i = 1;							break;
1218 		case CPUINFO_INT_MIN_INSTRUCTION_BYTES:		info->i = 1;							break;
1219 		case CPUINFO_INT_MAX_INSTRUCTION_BYTES:		info->i = 8;							break;
1220 		case CPUINFO_INT_MIN_CYCLES:				info->i = 1;							break;
1221 		case CPUINFO_INT_MAX_CYCLES:				info->i = 40;							break;
1222 
1223 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM:	info->i = 32;					break;
1224 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32;					break;
1225 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0;					break;
1226 		case CPUINFO_INT_LOGADDR_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32;					break;
1227 		case CPUINFO_INT_PAGE_SHIFT + ADDRESS_SPACE_PROGRAM: 	info->i = 12;					break;
1228 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA:	info->i = 0;					break;
1229 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
1230 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
1231 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 32;					break;
1232 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 32;					break;
1233 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: 		info->i = 0;					break;
1234 
1235 		case CPUINFO_INT_INPUT_STATE:			info->i = CLEAR_LINE;	break;
1236 
1237 		case CPUINFO_INT_PREVIOUSPC:				/* not implemented */					break;
1238 
1239 		case CPUINFO_INT_PC:
1240 		case CPUINFO_INT_REGISTER + I386_PC:			info->i = I.pc; break;
1241 		case CPUINFO_INT_REGISTER + I386_EIP:			info->i = I.eip; break;
1242 		case CPUINFO_INT_REGISTER + I386_EAX:			info->i = REG32(EAX); break;
1243 		case CPUINFO_INT_REGISTER + I386_EBX:			info->i = REG32(EBX); break;
1244 		case CPUINFO_INT_REGISTER + I386_ECX:			info->i = REG32(ECX); break;
1245 		case CPUINFO_INT_REGISTER + I386_EDX:			info->i = REG32(EDX); break;
1246 		case CPUINFO_INT_REGISTER + I386_EBP:			info->i = REG32(EBP); break;
1247 		case CPUINFO_INT_REGISTER + I386_ESP:			info->i = REG32(ESP); break;
1248 		case CPUINFO_INT_REGISTER + I386_ESI:			info->i = REG32(ESI); break;
1249 		case CPUINFO_INT_REGISTER + I386_EDI:			info->i = REG32(EDI); break;
1250 		case CPUINFO_INT_REGISTER + I386_EFLAGS:		info->i = I.eflags; break;
1251 		case CPUINFO_INT_REGISTER + I386_CS:			info->i = I.sreg[CS].selector; break;
1252 		case CPUINFO_INT_REGISTER + I386_SS:			info->i = I.sreg[SS].selector; break;
1253 		case CPUINFO_INT_REGISTER + I386_DS:			info->i = I.sreg[DS].selector; break;
1254 		case CPUINFO_INT_REGISTER + I386_ES:			info->i = I.sreg[ES].selector; break;
1255 		case CPUINFO_INT_REGISTER + I386_FS:			info->i = I.sreg[FS].selector; break;
1256 		case CPUINFO_INT_REGISTER + I386_GS:			info->i = I.sreg[GS].selector; break;
1257 		case CPUINFO_INT_REGISTER + I386_CR0:			info->i = I.cr[0]; break;
1258 		case CPUINFO_INT_REGISTER + I386_CR1:			info->i = I.cr[1]; break;
1259 		case CPUINFO_INT_REGISTER + I386_CR2:			info->i = I.cr[2]; break;
1260 		case CPUINFO_INT_REGISTER + I386_CR3:			info->i = I.cr[3]; break;
1261 		case CPUINFO_INT_REGISTER + I386_DR0:			info->i = I.dr[0]; break;
1262 		case CPUINFO_INT_REGISTER + I386_DR1:			info->i = I.dr[1]; break;
1263 		case CPUINFO_INT_REGISTER + I386_DR2:			info->i = I.dr[2]; break;
1264 		case CPUINFO_INT_REGISTER + I386_DR3:			info->i = I.dr[3]; break;
1265 		case CPUINFO_INT_REGISTER + I386_DR4:			info->i = I.dr[4]; break;
1266 		case CPUINFO_INT_REGISTER + I386_DR5:			info->i = I.dr[5]; break;
1267 		case CPUINFO_INT_REGISTER + I386_DR6:			info->i = I.dr[6]; break;
1268 		case CPUINFO_INT_REGISTER + I386_DR7:			info->i = I.dr[7]; break;
1269 		case CPUINFO_INT_REGISTER + I386_TR6:			info->i = I.tr[6]; break;
1270 		case CPUINFO_INT_REGISTER + I386_TR7:			info->i = I.tr[7]; break;
1271 
1272 		/* --- the following bits of info are returned as pointers to data or functions --- */
1273 		case CPUINFO_PTR_SET_INFO:	      				info->setinfo = i386_set_info;		break;
1274 		case CPUINFO_PTR_GET_CONTEXT:					info->getcontext = i386_get_context;	break;
1275 		case CPUINFO_PTR_SET_CONTEXT:					info->setcontext = i386_set_context;	break;
1276 		case CPUINFO_PTR_INIT:		      				info->init = i386_init;			break;
1277 		case CPUINFO_PTR_RESET:		      				info->reset = i386_reset;		break;
1278 		case CPUINFO_PTR_EXIT:		      				info->exit = i386_exit;			break;
1279 		case CPUINFO_PTR_EXECUTE:	      				info->execute = i386_execute;		break;
1280 		case CPUINFO_PTR_BURN:		      				info->burn = NULL;			break;
1281 		case CPUINFO_PTR_DISASSEMBLE_NEW:				info->disassemble_new = i386_dasm;		break;
1282 		case CPUINFO_PTR_IRQ_CALLBACK:					info->irqcallback = I.irq_callback;	break;
1283 		case CPUINFO_PTR_INSTRUCTION_COUNTER: 			info->icount = &I.cycles;		break;
1284 		case CPUINFO_PTR_REGISTER_LAYOUT:				info->p = i386_reg_layout;		break;
1285 		case CPUINFO_PTR_WINDOW_LAYOUT:					info->p = i386_win_layout;		break;
1286 		case CPUINFO_PTR_TRANSLATE:						info->translate = translate_address_cb;	break;
1287 
1288 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1289 		case CPUINFO_STR_NAME:							strcpy(info->s = cpuintrf_temp_str(), "I386"); break;
1290 		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s = cpuintrf_temp_str(), "Intel 386"); break;
1291 		case CPUINFO_STR_CORE_VERSION:					strcpy(info->s = cpuintrf_temp_str(), "1.0"); break;
1292 		case CPUINFO_STR_CORE_FILE:						strcpy(info->s = cpuintrf_temp_str(), __FILE__); break;
1293 		case CPUINFO_STR_CORE_CREDITS:					strcpy(info->s = cpuintrf_temp_str(), "Copyright (C) 2003-2004 Ville Linde"); break;
1294 
1295 		case CPUINFO_STR_FLAGS:	   				sprintf(info->s = cpuintrf_temp_str(), "%08X", get_flags()); break;
1296 
1297 		case CPUINFO_STR_REGISTER + I386_PC:			sprintf(info->s = cpuintrf_temp_str(), "PC: %08X", I.pc); break;
1298 		case CPUINFO_STR_REGISTER + I386_EIP:			sprintf(info->s = cpuintrf_temp_str(), "EIP: %08X", I.eip); break;
1299 		case CPUINFO_STR_REGISTER + I386_EAX:			sprintf(info->s = cpuintrf_temp_str(), "EAX: %08X", I.reg.d[EAX]); break;
1300 		case CPUINFO_STR_REGISTER + I386_EBX:			sprintf(info->s = cpuintrf_temp_str(), "EBX: %08X", I.reg.d[EBX]); break;
1301 		case CPUINFO_STR_REGISTER + I386_ECX:			sprintf(info->s = cpuintrf_temp_str(), "ECX: %08X", I.reg.d[ECX]); break;
1302 		case CPUINFO_STR_REGISTER + I386_EDX:			sprintf(info->s = cpuintrf_temp_str(), "EDX: %08X", I.reg.d[EDX]); break;
1303 		case CPUINFO_STR_REGISTER + I386_EBP:			sprintf(info->s = cpuintrf_temp_str(), "EBP: %08X", I.reg.d[EBP]); break;
1304 		case CPUINFO_STR_REGISTER + I386_ESP:			sprintf(info->s = cpuintrf_temp_str(), "ESP: %08X", I.reg.d[ESP]); break;
1305 		case CPUINFO_STR_REGISTER + I386_ESI:			sprintf(info->s = cpuintrf_temp_str(), "ESI: %08X", I.reg.d[ESI]); break;
1306 		case CPUINFO_STR_REGISTER + I386_EDI:			sprintf(info->s = cpuintrf_temp_str(), "EDI: %08X", I.reg.d[EDI]); break;
1307 		case CPUINFO_STR_REGISTER + I386_EFLAGS:		sprintf(info->s = cpuintrf_temp_str(), "EFLAGS: %08X", I.eflags); break;
1308 		case CPUINFO_STR_REGISTER + I386_CS:			sprintf(info->s = cpuintrf_temp_str(), "CS: %04X:%08X", I.sreg[CS].selector, I.sreg[CS].base); break;
1309 		case CPUINFO_STR_REGISTER + I386_SS:			sprintf(info->s = cpuintrf_temp_str(), "SS: %04X:%08X", I.sreg[SS].selector, I.sreg[SS].base); break;
1310 		case CPUINFO_STR_REGISTER + I386_DS:			sprintf(info->s = cpuintrf_temp_str(), "DS: %04X:%08X", I.sreg[DS].selector, I.sreg[DS].base); break;
1311 		case CPUINFO_STR_REGISTER + I386_ES:			sprintf(info->s = cpuintrf_temp_str(), "ES: %04X:%08X", I.sreg[ES].selector, I.sreg[ES].base); break;
1312 		case CPUINFO_STR_REGISTER + I386_FS:			sprintf(info->s = cpuintrf_temp_str(), "FS: %04X:%08X", I.sreg[FS].selector, I.sreg[FS].base); break;
1313 		case CPUINFO_STR_REGISTER + I386_GS:			sprintf(info->s = cpuintrf_temp_str(), "GS: %04X:%08X", I.sreg[GS].selector, I.sreg[GS].base); break;
1314 		case CPUINFO_STR_REGISTER + I386_CR0:			sprintf(info->s = cpuintrf_temp_str(), "CR0: %08X", I.cr[0]); break;
1315 		case CPUINFO_STR_REGISTER + I386_CR1:			sprintf(info->s = cpuintrf_temp_str(), "CR1: %08X", I.cr[1]); break;
1316 		case CPUINFO_STR_REGISTER + I386_CR2:			sprintf(info->s = cpuintrf_temp_str(), "CR2: %08X", I.cr[2]); break;
1317 		case CPUINFO_STR_REGISTER + I386_CR3:			sprintf(info->s = cpuintrf_temp_str(), "CR3: %08X", I.cr[3]); break;
1318 		case CPUINFO_STR_REGISTER + I386_DR0:			sprintf(info->s = cpuintrf_temp_str(), "DR0: %08X", I.dr[0]); break;
1319 		case CPUINFO_STR_REGISTER + I386_DR1:			sprintf(info->s = cpuintrf_temp_str(), "DR1: %08X", I.dr[1]); break;
1320 		case CPUINFO_STR_REGISTER + I386_DR2:			sprintf(info->s = cpuintrf_temp_str(), "DR2: %08X", I.dr[2]); break;
1321 		case CPUINFO_STR_REGISTER + I386_DR3:			sprintf(info->s = cpuintrf_temp_str(), "DR3: %08X", I.dr[3]); break;
1322 		case CPUINFO_STR_REGISTER + I386_DR4:			sprintf(info->s = cpuintrf_temp_str(), "DR4: %08X", I.dr[4]); break;
1323 		case CPUINFO_STR_REGISTER + I386_DR5:			sprintf(info->s = cpuintrf_temp_str(), "DR5: %08X", I.dr[5]); break;
1324 		case CPUINFO_STR_REGISTER + I386_DR6:			sprintf(info->s = cpuintrf_temp_str(), "DR6: %08X", I.dr[6]); break;
1325 		case CPUINFO_STR_REGISTER + I386_DR7:			sprintf(info->s = cpuintrf_temp_str(), "DR7: %08X", I.dr[7]); break;
1326 		case CPUINFO_STR_REGISTER + I386_TR6:			sprintf(info->s = cpuintrf_temp_str(), "TR6: %08X", I.tr[6]); break;
1327 		case CPUINFO_STR_REGISTER + I386_TR7:			sprintf(info->s = cpuintrf_temp_str(), "TR7: %08X", I.tr[7]); break;
1328 	}
1329 }
1330 
1331 #endif
1332 
1333 /*****************************************************************************/
1334 /* Intel 486 */
1335 
1336 #if (HAS_I486)
1337 
1338 static UINT8 i486_reg_layout[] =
1339 {
1340 	I386_EIP,		I386_ESP,		-1,
1341 	I386_EAX,		I386_EBP,		-1,
1342 	I386_EBX,		I386_ESI,		-1,
1343 	I386_ECX,		I386_EDI,		-1,
1344 	I386_EDX,		-1,
1345 	I386_CS,		I386_CR0,		-1,
1346 	I386_SS,		I386_CR1,		-1,
1347 	I386_DS,		I386_CR2,		-1,
1348 	I386_ES,		I386_CR3,		-1,
1349 	I386_FS,		I386_TR6,		-1,
1350 	I386_GS,		I386_TR7,		-1,
1351 	I386_DR0,		I386_DR1,		-1,
1352 	I386_DR2,		I386_DR3,		-1,
1353 	I386_DR4,		I386_DR5,		-1,
1354 	I386_DR6,		I386_DR7,		-1,
1355 	X87_CTRL,		X87_STATUS,		-1,
1356 	X87_ST0,		X87_ST1,		-1,
1357 	X87_ST2,		X87_ST3,		-1,
1358 	X87_ST4,		X87_ST5,		-1,
1359 	X87_ST6,		X87_ST7,		0
1360 };
1361 
1362 static UINT8 i486_win_layout[] =
1363 {
1364 	 0, 0,32,12,	/* register window (top rows) */
1365 	33, 0,46,15,	/* disassembler window (left colums) */
1366 	33,10,46,12,	/* memory #2 window (right, lower middle) */
1367 	 0,19,32, 3,	/* memory #1 window (right, upper middle) */
1368 	 0,23,80, 1,	/* command line window (bottom rows) */
1369 };
1370 
i486_init(void)1371 void i486_init(void)
1372 {
1373 	i386_init();
1374 }
1375 
i486_reset(void * param)1376 static void i486_reset(void *param)
1377 {
1378 	memset( &I, 0, sizeof(I386_REGS) );
1379 	I.sreg[CS].selector = 0xf000;
1380 	I.sreg[CS].base		= 0xffff0000;
1381 	I.sreg[CS].limit	= 0xffff;
1382 
1383 	I.idtr.base = 0;
1384 	I.idtr.limit = 0x3ff;
1385 
1386 	I.a20_mask = ~0;
1387 
1388 	I.cr[0] = 0;
1389 	I.eflags = 0;
1390 	I.eip = 0xfff0;
1391 
1392 	REG32(EAX) = 0x0308;	// Intel 386, stepping D1
1393 	REG32(EDX) = 0;
1394 
1395 	build_opcode_table(OP_I386 | OP_FPU | OP_I486);
1396 	I.cycle_table_rm = cycle_table_rm[CPU_CYCLES_I486];
1397 	I.cycle_table_pm = cycle_table_pm[CPU_CYCLES_I486];
1398 
1399 	CHANGE_PC(I.eip);
1400 }
1401 
i486_exit(void)1402 static void i486_exit(void)
1403 {
1404 
1405 }
1406 
i486_set_info(UINT32 state,union cpuinfo * info)1407 static void i486_set_info(UINT32 state, union cpuinfo *info)
1408 {
1409 	switch (state)
1410 	{
1411 		case CPUINFO_INT_REGISTER + X87_CTRL:			I.fpu_control_word = info->i; break;
1412 		case CPUINFO_INT_REGISTER + X87_STATUS:			I.fpu_status_word = info->i; break;
1413 		case CPUINFO_INT_REGISTER + X87_ST0:			ST(0).f = info->i; break;
1414 		case CPUINFO_INT_REGISTER + X87_ST1:			ST(1).f = info->i; break;
1415 		case CPUINFO_INT_REGISTER + X87_ST2:			ST(2).f = info->i; break;
1416 		case CPUINFO_INT_REGISTER + X87_ST3:			ST(3).f = info->i; break;
1417 		case CPUINFO_INT_REGISTER + X87_ST4:			ST(4).f = info->i; break;
1418 		case CPUINFO_INT_REGISTER + X87_ST5:			ST(5).f = info->i; break;
1419 		case CPUINFO_INT_REGISTER + X87_ST6:			ST(6).f = info->i; break;
1420 		case CPUINFO_INT_REGISTER + X87_ST7:			ST(7).f = info->i; break;
1421 
1422 		default: i386_set_info(state, info); break;
1423 	}
1424 }
1425 
i486_get_info(UINT32 state,union cpuinfo * info)1426 void i486_get_info(UINT32 state, union cpuinfo *info)
1427 {
1428 	switch (state)
1429 	{
1430 		case CPUINFO_PTR_SET_INFO:	      				info->setinfo = i486_set_info;		break;
1431 		case CPUINFO_PTR_INIT:		      				info->init = i486_init;				break;
1432 		case CPUINFO_PTR_RESET:		      				info->reset = i486_reset;			break;
1433 		case CPUINFO_PTR_EXIT:		      				info->exit = i486_exit;				break;
1434 		case CPUINFO_PTR_REGISTER_LAYOUT:				info->p = i486_reg_layout;			break;
1435 		case CPUINFO_PTR_WINDOW_LAYOUT:					info->p = i486_win_layout;			break;
1436 
1437 		case CPUINFO_INT_REGISTER + X87_CTRL:			info->i = I.fpu_control_word; break;
1438 		case CPUINFO_INT_REGISTER + X87_STATUS:			info->i = I.fpu_status_word; break;
1439 		case CPUINFO_INT_REGISTER + X87_ST0:			info->i = ST(0).f; break;
1440 		case CPUINFO_INT_REGISTER + X87_ST1:			info->i = ST(1).f; break;
1441 		case CPUINFO_INT_REGISTER + X87_ST2:			info->i = ST(2).f; break;
1442 		case CPUINFO_INT_REGISTER + X87_ST3:			info->i = ST(3).f; break;
1443 		case CPUINFO_INT_REGISTER + X87_ST4:			info->i = ST(4).f; break;
1444 		case CPUINFO_INT_REGISTER + X87_ST5:			info->i = ST(5).f; break;
1445 		case CPUINFO_INT_REGISTER + X87_ST6:			info->i = ST(6).f; break;
1446 		case CPUINFO_INT_REGISTER + X87_ST7:			info->i = ST(7).f; break;
1447 
1448 		case CPUINFO_STR_NAME:							strcpy(info->s = cpuintrf_temp_str(), "I486"); break;
1449 		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s = cpuintrf_temp_str(), "Intel 486"); break;
1450 		case CPUINFO_STR_REGISTER + X87_CTRL:			sprintf(info->s = cpuintrf_temp_str(), "FPU_CW: %04X", I.fpu_control_word); break;
1451 		case CPUINFO_STR_REGISTER + X87_STATUS:			sprintf(info->s = cpuintrf_temp_str(), "FPU_SW: %04X", I.fpu_status_word); break;
1452 		case CPUINFO_STR_REGISTER + X87_ST0:			sprintf(info->s = cpuintrf_temp_str(), "ST0: %f", ST(0).f); break;
1453 		case CPUINFO_STR_REGISTER + X87_ST1:			sprintf(info->s = cpuintrf_temp_str(), "ST1: %f", ST(1).f); break;
1454 		case CPUINFO_STR_REGISTER + X87_ST2:			sprintf(info->s = cpuintrf_temp_str(), "ST2: %f", ST(2).f); break;
1455 		case CPUINFO_STR_REGISTER + X87_ST3:			sprintf(info->s = cpuintrf_temp_str(), "ST3: %f", ST(3).f); break;
1456 		case CPUINFO_STR_REGISTER + X87_ST4:			sprintf(info->s = cpuintrf_temp_str(), "ST4: %f", ST(4).f); break;
1457 		case CPUINFO_STR_REGISTER + X87_ST5:			sprintf(info->s = cpuintrf_temp_str(), "ST5: %f", ST(5).f); break;
1458 		case CPUINFO_STR_REGISTER + X87_ST6:			sprintf(info->s = cpuintrf_temp_str(), "ST6: %f", ST(6).f); break;
1459 		case CPUINFO_STR_REGISTER + X87_ST7:			sprintf(info->s = cpuintrf_temp_str(), "ST7: %f", ST(7).f); break;
1460 
1461 		default:	i386_get_info(state, info); break;
1462 	}
1463 }
1464 #endif
1465 
1466 /*****************************************************************************/
1467 /* Pentium */
1468 
1469 #if (HAS_PENTIUM)
1470 
1471 static UINT8 pentium_reg_layout[] =
1472 {
1473 	I386_EIP,		I386_ESP,		-1,
1474 	I386_EAX,		I386_EBP,		-1,
1475 	I386_EBX,		I386_ESI,		-1,
1476 	I386_ECX,		I386_EDI,		-1,
1477 	I386_EDX,		-1,
1478 	I386_CS,		I386_CR0,		-1,
1479 	I386_SS,		I386_CR1,		-1,
1480 	I386_DS,		I386_CR2,		-1,
1481 	I386_ES,		I386_CR3,		-1,
1482 	I386_FS,		I386_TR6,		-1,
1483 	I386_GS,		I386_TR7,		-1,
1484 	I386_DR0,		I386_DR1,		-1,
1485 	I386_DR2,		I386_DR3,		-1,
1486 	I386_DR4,		I386_DR5,		-1,
1487 	I386_DR6,		I386_DR7,		-1,
1488 	X87_CTRL,		X87_STATUS,		-1,
1489 	X87_ST0,		X87_ST1,		-1,
1490 	X87_ST2,		X87_ST3,		-1,
1491 	X87_ST4,		X87_ST5,		-1,
1492 	X87_ST6,		X87_ST7,		0
1493 };
1494 
1495 static UINT8 pentium_win_layout[] =
1496 {
1497 	 0, 0,32,12,	/* register window (top rows) */
1498 	33, 0,46,15,	/* disassembler window (left colums) */
1499 	33,10,46,12,	/* memory #2 window (right, lower middle) */
1500 	 0,19,32, 3,	/* memory #1 window (right, upper middle) */
1501 	 0,23,80, 1,	/* command line window (bottom rows) */
1502 };
1503 
pentium_init(void)1504 void pentium_init(void)
1505 {
1506 	i386_init();
1507 }
1508 
pentium_reset(void * param)1509 static void pentium_reset(void *param)
1510 {
1511 	memset( &I, 0, sizeof(I386_REGS) );
1512 	I.sreg[CS].selector = 0xf000;
1513 	I.sreg[CS].base		= 0xffff0000;
1514 	I.sreg[CS].limit	= 0xffff;
1515 
1516 	I.idtr.base = 0;
1517 	I.idtr.limit = 0x3ff;
1518 
1519 	I.a20_mask = ~0;
1520 
1521 	I.cr[0] = 0;
1522 	I.eflags = 0;
1523 	I.eip = 0xfff0;
1524 
1525 	REG32(EAX) = 0x0308;	// Intel 386, stepping D1
1526 	REG32(EDX) = 0;
1527 
1528 	build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM);
1529 	I.cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM];
1530 	I.cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM];
1531 
1532 	I.cpuid_id0 = 0x756e6547;	// Genu
1533 	I.cpuid_id1 = 0x49656e69;	// ineI
1534 	I.cpuid_id2 = 0x6c65746e;	// ntel
1535 
1536 	I.cpuid_max_input_value_eax = 0x01;
1537 
1538 	// [11:8] Family
1539 	// [ 7:4] Model
1540 	// [ 3:0] Stepping ID
1541 	// Family 5 (Pentium), Model 2 (75 - 200MHz), Stepping 1
1542 	I.cpu_version = (5 << 8) | (2 << 4) | (1);
1543 
1544 	// [ 0:0] FPU on chip
1545 	// [ 2:2] I/O breakpoints
1546 	// [ 4:4] Time Stamp Counter
1547 	// [ 5:5] Pentium CPU style model specific registers
1548 	// [ 7:7] Machine Check Exception
1549 	// [ 8:8] CMPXCHG8B instruction
1550 	I.feature_flags = 0x00000000;
1551 
1552 	CHANGE_PC(I.eip);
1553 }
1554 
pentium_exit(void)1555 static void pentium_exit(void)
1556 {
1557 
1558 }
1559 
pentium_set_info(UINT32 state,union cpuinfo * info)1560 static void pentium_set_info(UINT32 state, union cpuinfo *info)
1561 {
1562 	switch (state)
1563 	{
1564 		case CPUINFO_INT_REGISTER + X87_CTRL:			I.fpu_control_word = info->i; break;
1565 		case CPUINFO_INT_REGISTER + X87_STATUS:			I.fpu_status_word = info->i; break;
1566 		case CPUINFO_INT_REGISTER + X87_ST0:			ST(0).f = info->i; break;
1567 		case CPUINFO_INT_REGISTER + X87_ST1:			ST(1).f = info->i; break;
1568 		case CPUINFO_INT_REGISTER + X87_ST2:			ST(2).f = info->i; break;
1569 		case CPUINFO_INT_REGISTER + X87_ST3:			ST(3).f = info->i; break;
1570 		case CPUINFO_INT_REGISTER + X87_ST4:			ST(4).f = info->i; break;
1571 		case CPUINFO_INT_REGISTER + X87_ST5:			ST(5).f = info->i; break;
1572 		case CPUINFO_INT_REGISTER + X87_ST6:			ST(6).f = info->i; break;
1573 		case CPUINFO_INT_REGISTER + X87_ST7:			ST(7).f = info->i; break;
1574 
1575 		default: i386_set_info(state, info); break;
1576 	}
1577 }
1578 
pentium_get_info(UINT32 state,union cpuinfo * info)1579 void pentium_get_info(UINT32 state, union cpuinfo *info)
1580 {
1581 	switch (state)
1582 	{
1583 		case CPUINFO_PTR_SET_INFO:	      				info->setinfo = pentium_set_info;		break;
1584 		case CPUINFO_PTR_INIT:		      				info->init = pentium_init;				break;
1585 		case CPUINFO_PTR_RESET:		      				info->reset = pentium_reset;			break;
1586 		case CPUINFO_PTR_EXIT:		      				info->exit = pentium_exit;				break;
1587 		case CPUINFO_PTR_REGISTER_LAYOUT:				info->p = pentium_reg_layout;			break;
1588 		case CPUINFO_PTR_WINDOW_LAYOUT:					info->p = pentium_win_layout;			break;
1589 
1590 		case CPUINFO_INT_REGISTER + X87_CTRL:			info->i = I.fpu_control_word; break;
1591 		case CPUINFO_INT_REGISTER + X87_STATUS:			info->i = I.fpu_status_word; break;
1592 		case CPUINFO_INT_REGISTER + X87_ST0:			info->i = ST(0).f; break;
1593 		case CPUINFO_INT_REGISTER + X87_ST1:			info->i = ST(1).f; break;
1594 		case CPUINFO_INT_REGISTER + X87_ST2:			info->i = ST(2).f; break;
1595 		case CPUINFO_INT_REGISTER + X87_ST3:			info->i = ST(3).f; break;
1596 		case CPUINFO_INT_REGISTER + X87_ST4:			info->i = ST(4).f; break;
1597 		case CPUINFO_INT_REGISTER + X87_ST5:			info->i = ST(5).f; break;
1598 		case CPUINFO_INT_REGISTER + X87_ST6:			info->i = ST(6).f; break;
1599 		case CPUINFO_INT_REGISTER + X87_ST7:			info->i = ST(7).f; break;
1600 
1601 		case CPUINFO_STR_NAME:							strcpy(info->s = cpuintrf_temp_str(), "PENTIUM"); break;
1602 		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s = cpuintrf_temp_str(), "Intel Pentium"); break;
1603 		case CPUINFO_STR_REGISTER + X87_CTRL:			sprintf(info->s = cpuintrf_temp_str(), "FPU_CW: %04X", I.fpu_control_word); break;
1604 		case CPUINFO_STR_REGISTER + X87_STATUS:			sprintf(info->s = cpuintrf_temp_str(), "FPU_SW: %04X", I.fpu_status_word); break;
1605 		case CPUINFO_STR_REGISTER + X87_ST0:			sprintf(info->s = cpuintrf_temp_str(), "ST0: %f", ST(0).f); break;
1606 		case CPUINFO_STR_REGISTER + X87_ST1:			sprintf(info->s = cpuintrf_temp_str(), "ST1: %f", ST(1).f); break;
1607 		case CPUINFO_STR_REGISTER + X87_ST2:			sprintf(info->s = cpuintrf_temp_str(), "ST2: %f", ST(2).f); break;
1608 		case CPUINFO_STR_REGISTER + X87_ST3:			sprintf(info->s = cpuintrf_temp_str(), "ST3: %f", ST(3).f); break;
1609 		case CPUINFO_STR_REGISTER + X87_ST4:			sprintf(info->s = cpuintrf_temp_str(), "ST4: %f", ST(4).f); break;
1610 		case CPUINFO_STR_REGISTER + X87_ST5:			sprintf(info->s = cpuintrf_temp_str(), "ST5: %f", ST(5).f); break;
1611 		case CPUINFO_STR_REGISTER + X87_ST6:			sprintf(info->s = cpuintrf_temp_str(), "ST6: %f", ST(6).f); break;
1612 		case CPUINFO_STR_REGISTER + X87_ST7:			sprintf(info->s = cpuintrf_temp_str(), "ST7: %f", ST(7).f); break;
1613 
1614 		default:	i386_get_info(state, info); break;
1615 	}
1616 }
1617 #endif
1618 
1619 /*****************************************************************************/
1620 /* Cyrix MediaGX */
1621 
1622 #if (HAS_MEDIAGX)
1623 
1624 static UINT8 mediagx_reg_layout[] =
1625 {
1626 	I386_EIP,		I386_ESP,		-1,
1627 	I386_EAX,		I386_EBP,		-1,
1628 	I386_EBX,		I386_ESI,		-1,
1629 	I386_ECX,		I386_EDI,		-1,
1630 	I386_EDX,		-1,
1631 	I386_CS,		I386_CR0,		-1,
1632 	I386_SS,		I386_CR1,		-1,
1633 	I386_DS,		I386_CR2,		-1,
1634 	I386_ES,		I386_CR3,		-1,
1635 	I386_FS,		I386_TR6,		-1,
1636 	I386_GS,		I386_TR7,		-1,
1637 	I386_DR0,		I386_DR1,		-1,
1638 	I386_DR2,		I386_DR3,		-1,
1639 	I386_DR4,		I386_DR5,		-1,
1640 	I386_DR6,		I386_DR7,		-1,
1641 	X87_CTRL,		X87_STATUS,		-1,
1642 	X87_ST0,		X87_ST1,		-1,
1643 	X87_ST2,		X87_ST3,		-1,
1644 	X87_ST4,		X87_ST5,		-1,
1645 	X87_ST6,		X87_ST7,		0
1646 };
1647 
1648 static UINT8 mediagx_win_layout[] =
1649 {
1650 	 0, 0,32,12,	/* register window (top rows) */
1651 	33, 0,46,15,	/* disassembler window (left colums) */
1652 	33,10,46,12,	/* memory #2 window (right, lower middle) */
1653 	 0,19,32, 3,	/* memory #1 window (right, upper middle) */
1654 	 0,23,80, 1,	/* command line window (bottom rows) */
1655 };
1656 
mediagx_init(void)1657 void mediagx_init(void)
1658 {
1659 	i386_init();
1660 }
1661 
mediagx_reset(void * param)1662 static void mediagx_reset(void *param)
1663 {
1664 	memset( &I, 0, sizeof(I386_REGS) );
1665 	I.sreg[CS].selector = 0xf000;
1666 	I.sreg[CS].base		= 0xffff0000;
1667 	I.sreg[CS].limit	= 0xffff;
1668 
1669 	I.idtr.base = 0;
1670 	I.idtr.limit = 0x3ff;
1671 
1672 	I.a20_mask = ~0;
1673 
1674 	I.cr[0] = 0;
1675 	I.eflags = 0;
1676 	I.eip = 0xfff0;
1677 
1678 	REG32(EAX) = 0x0308;	// Intel 386, stepping D1
1679 	REG32(EDX) = 0;
1680 
1681 	build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_CYRIX);
1682 	I.cycle_table_rm = cycle_table_rm[CPU_CYCLES_MEDIAGX];
1683 	I.cycle_table_pm = cycle_table_pm[CPU_CYCLES_MEDIAGX];
1684 
1685 	I.cpuid_id0 = 0x69727943;	// Cyri
1686 	I.cpuid_id1 = 0x736e4978;	// xIns
1687 	I.cpuid_id2 = 0x6d616574;	// tead
1688 
1689 	I.cpuid_max_input_value_eax = 0x01;
1690 
1691 	// [11:8] Family
1692 	// [ 7:4] Model
1693 	// [ 3:0] Stepping ID
1694 	// Family 4, Model 4 (MediaGX)
1695 	I.cpu_version = (4 << 8) | (4 << 4) | (1);
1696 
1697 	// [ 0:0] FPU on chip
1698 	// [ 2:2] I/O breakpoints
1699 	// [ 4:4] Time Stamp Counter
1700 	// [ 5:5] Pentium CPU style model specific registers
1701 	// [ 7:7] Machine Check Exception
1702 	// [ 8:8] CMPXCHG8B instruction
1703 	I.feature_flags = 0x00000001;
1704 
1705 	CHANGE_PC(I.eip);
1706 }
1707 
mediagx_exit(void)1708 static void mediagx_exit(void)
1709 {
1710 
1711 }
1712 
mediagx_set_info(UINT32 state,union cpuinfo * info)1713 static void mediagx_set_info(UINT32 state, union cpuinfo *info)
1714 {
1715 	switch (state)
1716 	{
1717 		case CPUINFO_INT_REGISTER + X87_CTRL:			I.fpu_control_word = info->i; break;
1718 		case CPUINFO_INT_REGISTER + X87_STATUS:			I.fpu_status_word = info->i; break;
1719 		case CPUINFO_INT_REGISTER + X87_ST0:			ST(0).f = info->i; break;
1720 		case CPUINFO_INT_REGISTER + X87_ST1:			ST(1).f = info->i; break;
1721 		case CPUINFO_INT_REGISTER + X87_ST2:			ST(2).f = info->i; break;
1722 		case CPUINFO_INT_REGISTER + X87_ST3:			ST(3).f = info->i; break;
1723 		case CPUINFO_INT_REGISTER + X87_ST4:			ST(4).f = info->i; break;
1724 		case CPUINFO_INT_REGISTER + X87_ST5:			ST(5).f = info->i; break;
1725 		case CPUINFO_INT_REGISTER + X87_ST6:			ST(6).f = info->i; break;
1726 		case CPUINFO_INT_REGISTER + X87_ST7:			ST(7).f = info->i; break;
1727 
1728 		default: i386_set_info(state, info); break;
1729 	}
1730 }
1731 
mediagx_get_info(UINT32 state,union cpuinfo * info)1732 void mediagx_get_info(UINT32 state, union cpuinfo *info)
1733 {
1734 	switch (state)
1735 	{
1736 		case CPUINFO_PTR_SET_INFO:	      				info->setinfo = mediagx_set_info;		break;
1737 		case CPUINFO_PTR_INIT:		      				info->init = mediagx_init;				break;
1738 		case CPUINFO_PTR_RESET:		      				info->reset = mediagx_reset;			break;
1739 		case CPUINFO_PTR_EXIT:		      				info->exit = mediagx_exit;				break;
1740 		case CPUINFO_PTR_REGISTER_LAYOUT:				info->p = mediagx_reg_layout;			break;
1741 		case CPUINFO_PTR_WINDOW_LAYOUT:					info->p = mediagx_win_layout;			break;
1742 
1743 		case CPUINFO_INT_REGISTER + X87_CTRL:			info->i = I.fpu_control_word; break;
1744 		case CPUINFO_INT_REGISTER + X87_STATUS:			info->i = I.fpu_status_word; break;
1745 		case CPUINFO_INT_REGISTER + X87_ST0:			info->i = ST(0).f; break;
1746 		case CPUINFO_INT_REGISTER + X87_ST1:			info->i = ST(1).f; break;
1747 		case CPUINFO_INT_REGISTER + X87_ST2:			info->i = ST(2).f; break;
1748 		case CPUINFO_INT_REGISTER + X87_ST3:			info->i = ST(3).f; break;
1749 		case CPUINFO_INT_REGISTER + X87_ST4:			info->i = ST(4).f; break;
1750 		case CPUINFO_INT_REGISTER + X87_ST5:			info->i = ST(5).f; break;
1751 		case CPUINFO_INT_REGISTER + X87_ST6:			info->i = ST(6).f; break;
1752 		case CPUINFO_INT_REGISTER + X87_ST7:			info->i = ST(7).f; break;
1753 
1754 		case CPUINFO_STR_NAME:							strcpy(info->s = cpuintrf_temp_str(), "MEDIAGX"); break;
1755 		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s = cpuintrf_temp_str(), "Cyrix MediaGX"); break;
1756 		case CPUINFO_STR_REGISTER + X87_CTRL:			sprintf(info->s = cpuintrf_temp_str(), "FPU_CW: %04X", I.fpu_control_word); break;
1757 		case CPUINFO_STR_REGISTER + X87_STATUS:			sprintf(info->s = cpuintrf_temp_str(), "FPU_SW: %04X", I.fpu_status_word); break;
1758 		case CPUINFO_STR_REGISTER + X87_ST0:			sprintf(info->s = cpuintrf_temp_str(), "ST0: %f", ST(0).f); break;
1759 		case CPUINFO_STR_REGISTER + X87_ST1:			sprintf(info->s = cpuintrf_temp_str(), "ST1: %f", ST(1).f); break;
1760 		case CPUINFO_STR_REGISTER + X87_ST2:			sprintf(info->s = cpuintrf_temp_str(), "ST2: %f", ST(2).f); break;
1761 		case CPUINFO_STR_REGISTER + X87_ST3:			sprintf(info->s = cpuintrf_temp_str(), "ST3: %f", ST(3).f); break;
1762 		case CPUINFO_STR_REGISTER + X87_ST4:			sprintf(info->s = cpuintrf_temp_str(), "ST4: %f", ST(4).f); break;
1763 		case CPUINFO_STR_REGISTER + X87_ST5:			sprintf(info->s = cpuintrf_temp_str(), "ST5: %f", ST(5).f); break;
1764 		case CPUINFO_STR_REGISTER + X87_ST6:			sprintf(info->s = cpuintrf_temp_str(), "ST6: %f", ST(6).f); break;
1765 		case CPUINFO_STR_REGISTER + X87_ST7:			sprintf(info->s = cpuintrf_temp_str(), "ST7: %f", ST(7).f); break;
1766 
1767 		default:	i386_get_info(state, info); break;
1768 	}
1769 }
1770 #endif
1771