2 Skelton for retropc emulator
4 Origin : MAME i386 core
5 Author : Takeda.Toshiya
8 [ i386/i486/Pentium/MediaGX ]
16 /* ----------------------------------------------------------------------------
18 ---------------------------------------------------------------------------- */
20 // API of bios_int_i86() / bios_caii_i86() has changed.
21 // regs[8] regs[9] are added.These entries set redirect-address by PSEUDO-BIOS.
22 // If need, will add more entries for cycle#.
25 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
26 #pragma warning( disable : 4018 )
27 #pragma warning( disable : 4065 )
28 #pragma warning( disable : 4146 )
29 #pragma warning( disable : 4244 )
30 #pragma warning( disable : 4996 )
35 #define CPU_MODEL i386
36 #elif defined(HAS_I486)
37 #define CPU_MODEL i486
38 #elif defined(HAS_PENTIUM)
39 #define CPU_MODEL pentium
40 #elif defined(HAS_MEDIAGX)
41 #define CPU_MODEL mediagx
42 #elif defined(HAS_PENTIUM_PRO)
43 #define CPU_MODEL pentium_pro
44 #elif defined(HAS_PENTIUM_MMX)
45 #define CPU_MODEL pentium_mmx
46 #elif defined(HAS_PENTIUM2)
47 #define CPU_MODEL pentium2
48 #elif defined(HAS_PENTIUM3)
49 #define CPU_MODEL pentium3
50 #elif defined(HAS_PENTIUM4)
51 #define CPU_MODEL pentium4
55 #ifndef __BIG_ENDIAN__
63 #define U64(v) UINT64(v)
65 #define fatalerror(...) exit(1)
67 #define logdebug(...) \
69 if(cpustate != NULL) { \
70 if(cpustate->parent_device != NULL) { \
71 cpustate->parent_device->out_debug_log(__VA_ARGS__); \
76 #define loginfo(...) \
78 if(cpustate != NULL) { \
79 if(cpustate->parent_device != NULL) { \
80 cpustate->parent_device->out_debug_log(__VA_ARGS__); \
89 #define logerror(...) \
91 if(cpustate != NULL) { \
92 if(cpustate->parent_device != NULL) { \
93 cpustate->parent_device->out_debug_log(__VA_ARGS__); \
99 #define popmessage(...)
101 /*****************************************************************************/
102 /* src/emu/devcpu.h */
104 // CPU interface functions
105 #define CPU_INIT_NAME(name) cpu_init_##name
106 #define CPU_INIT(name) void* CPU_INIT_NAME(name)()
107 #define CPU_INIT_CALL(name) CPU_INIT_NAME(name)()
109 #define CPU_RESET_NAME(name) cpu_reset_##name
110 #define CPU_RESET(name) void CPU_RESET_NAME(name)(i386_state *cpustate)
111 #define CPU_RESET_CALL(name) CPU_RESET_NAME(name)(cpustate)
113 #define CPU_EXECUTE_NAME(name) cpu_execute_##name
114 #define CPU_EXECUTE(name) int CPU_EXECUTE_NAME(name)(i386_state *cpustate, int cycles)
115 #define CPU_EXECUTE_CALL(name) CPU_EXECUTE_NAME(name)(cpustate, cycles)
117 #define CPU_TRANSLATE_NAME(name) cpu_translate_##name
118 #define CPU_TRANSLATE(name) int CPU_TRANSLATE_NAME(name)(void *cpudevice, address_spacenum space, int intention, offs_t *address)
119 #define CPU_TRANSLATE_CALL(name) CPU_TRANSLATE_NAME(name)(cpudevice, space, intention, address)
121 #define CPU_DISASSEMBLE_NAME(name) cpu_disassemble_##name
122 #define CPU_DISASSEMBLE(name) int CPU_DISASSEMBLE_NAME(name)(_TCHAR *buffer, offs_t eip, const UINT8 *oprom)
123 #define CPU_DISASSEMBLE_CALL(name) CPU_DISASSEMBLE_NAME(name)(buffer, eip, oprom)
125 /*****************************************************************************/
126 /* src/emu/didisasm.h */
128 // Disassembler constants
129 const UINT32 DASMFLAG_SUPPORTED = 0x80000000; // are disassembly flags supported?
130 const UINT32 DASMFLAG_STEP_OUT = 0x40000000; // this instruction should be the end of a step out sequence
131 const UINT32 DASMFLAG_STEP_OVER = 0x20000000; // this instruction should be stepped over by setting a breakpoint afterwards
132 const UINT32 DASMFLAG_OVERINSTMASK = 0x18000000; // number of extra instructions to skip when stepping over
133 const UINT32 DASMFLAG_OVERINSTSHIFT = 27; // bits to shift after masking to get the value
134 const UINT32 DASMFLAG_LENGTHMASK = 0x0000ffff; // the low 16-bits contain the actual length
136 /*****************************************************************************/
137 /* src/emu/diexec.h */
142 CLEAR_LINE = 0, // clear (a fired or held) line
143 ASSERT_LINE, // assert an interrupt immediately
144 HOLD_LINE, // hold interrupt line until acknowledged
145 PULSE_LINE // pulse interrupt line instantaneously (only for NMI, RESET)
154 /*****************************************************************************/
155 /* src/emu/dimemory.h */
157 // Translation intentions
158 const int TRANSLATE_TYPE_MASK = 0x03; // read write or fetch
159 const int TRANSLATE_USER_MASK = 0x04; // user mode or fully privileged
160 const int TRANSLATE_DEBUG_MASK = 0x08; // debug mode (no side effects)
162 const int TRANSLATE_READ = 0; // translate for read
163 const int TRANSLATE_WRITE = 1; // translate for write
164 const int TRANSLATE_FETCH = 2; // translate for instruction fetch
165 const int TRANSLATE_READ_USER = (TRANSLATE_READ | TRANSLATE_USER_MASK);
166 const int TRANSLATE_WRITE_USER = (TRANSLATE_WRITE | TRANSLATE_USER_MASK);
167 const int TRANSLATE_FETCH_USER = (TRANSLATE_FETCH | TRANSLATE_USER_MASK);
168 const int TRANSLATE_READ_DEBUG = (TRANSLATE_READ | TRANSLATE_DEBUG_MASK);
169 const int TRANSLATE_WRITE_DEBUG = (TRANSLATE_WRITE | TRANSLATE_DEBUG_MASK);
170 const int TRANSLATE_FETCH_DEBUG = (TRANSLATE_FETCH | TRANSLATE_DEBUG_MASK);
172 /*****************************************************************************/
173 /* src/emu/emucore.h */
175 // constants for expression endianness
182 // declare native endianness to be one or the other
184 const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_LITTLE;
186 const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_BIG;
188 // endian-based value: first value is if 'endian' is little-endian, second is if 'endian' is big-endian
189 #define ENDIAN_VALUE_LE_BE(endian,leval,beval) (((endian) == ENDIANNESS_LITTLE) ? (leval) : (beval))
190 // endian-based value: first value is if native endianness is little-endian, second is if native is big-endian
191 #define NATIVE_ENDIAN_VALUE_LE_BE(leval,beval) ENDIAN_VALUE_LE_BE(ENDIANNESS_NATIVE, leval, beval)
192 // endian-based value: first value is if 'endian' matches native, second is if 'endian' doesn't match native
193 #define ENDIAN_VALUE_NE_NNE(endian,leval,beval) (((endian) == ENDIANNESS_NATIVE) ? (neval) : (nneval))
195 /*****************************************************************************/
196 /* src/emu/emumem.h */
198 // helpers for checking address alignment
199 #define WORD_ALIGNED(a) (((a) & 1) == 0)
200 #define DWORD_ALIGNED(a) (((a) & 3) == 0)
201 #define QWORD_ALIGNED(a) (((a) & 7) == 0)
203 /*****************************************************************************/
204 /* src/emu/memory.h */
207 enum address_spacenum
209 AS_0, // first address space
210 AS_1, // second address space
211 AS_2, // third address space
212 AS_3, // fourth address space
213 ADDRESS_SPACES, // maximum number of address spaces
215 // alternate address space names for common use
216 AS_PROGRAM = AS_0, // program address space
217 AS_DATA = AS_1, // data address space
218 AS_IO = AS_2 // I/O address space
221 // offsets and addresses are 32-bit (for now...)
222 typedef UINT32 offs_t;
224 /*****************************************************************************/
225 /* src/osd/osdcomm.h */
227 /* Highly useful macro for compile-time knowledge of an array size */
228 #define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
230 //#ifdef I386_PSEUDO_BIOS
231 #define BIOS_INT(num) if(cpustate->bios != NULL) { \
232 /*if(((cpustate->cr[0] & 0x0001) == 0) || (cpustate->VM != 0)) */{ /* VM8086 or Not Protected */ \
233 uint16_t regs[10], sregs[4]; \
234 regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
235 regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
236 regs[8] = 0x0000; regs[9] = 0x0000; \
237 sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
238 sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
239 int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \
240 if(cpustate->bios->bios_int_i86(num, regs, sregs, &ZeroFlag, &CarryFlag, &(cpustate->cycles), &(cpustate->total_cycles))) { \
241 REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
242 REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
243 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
244 CYCLES(cpustate,CYCLES_IRET); \
245 if((regs[8] != 0x0000) || (regs[9] != 0x0000)) { \
246 uint32_t hi = regs[9]; \
247 uint32_t lo = regs[8]; \
248 uint32_t addr = (hi << 16) | lo; \
249 cpustate->eip = addr; \
256 #define BIOS_INT32(num) if(cpustate->bios != NULL) { \
257 /*if(((cpustate->cr[0] & 0x0001) == 0) || (cpustate->VM != 0)) */{ /* VM8086 or Not Protected */ \
260 regs[0] = REG32(EAX); regs[1] = REG32(ECX); regs[2] = REG32(EDX); regs[3] = REG32(EBX); \
261 regs[4] = REG32(ESP); regs[5] = REG32(EBP); regs[6] = REG32(ESI); regs[7] = REG32(EDI); \
262 regs[8] = 0x0000; regs[9] = 0x0000; \
263 sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
264 sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
265 int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \
266 if(cpustate->bios->bios_int_ia32(num, regs, sregs, &ZeroFlag, &CarryFlag, &(cpustate->cycles), &(cpustate->total_cycles))) { \
267 REG32(EAX) = regs[0]; REG32(ECX) = regs[1]; REG32(EDX) = regs[2]; REG32(EBX) = regs[3]; \
268 REG32(ESP) = regs[4]; REG32(EBP) = regs[5]; REG32(ESI) = regs[6]; REG32(EDI) = regs[7]; \
269 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
270 CYCLES(cpustate,CYCLES_IRET); \
271 if((regs[8] != 0x0000) || (regs[9] != 0x0000)) { \
272 uint32_t hi = regs[9]; \
273 uint32_t lo = regs[8]; \
274 uint32_t addr = (hi << 16) | lo; \
275 cpustate->eip = addr; \
282 #define BIOS_CALL_FAR(address) if(cpustate->bios != NULL) { \
283 if(((cpustate->cr[0] & 0x0001) == 0) || (cpustate->VM != 0)) { /* VM8086 or Not Protected */ \
284 uint16_t regs[10], sregs[4]; \
285 regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
286 regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
287 regs[8] = 0x0000; regs[9] = 0x0000; \
288 sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
289 sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
290 int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \
291 if(cpustate->bios->bios_call_far_i86(address, regs, sregs, &ZeroFlag, &CarryFlag, &(cpustate->cycles), &(cpustate->total_cycles))) { \
292 REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
293 REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
294 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
295 CYCLES(cpustate,CYCLES_RET_INTERSEG); \
296 if((regs[8] != 0x0000) || (regs[9] != 0x0000)) { \
297 uint32_t hi = regs[9]; \
298 uint32_t lo = regs[8]; \
299 uint32_t addr = (hi << 16) | lo; \
300 cpustate->eip = addr; \
307 #define BIOS_CALL_FAR32(address) if(cpustate->bios != NULL) { \
308 if(((cpustate->cr[0] & 0x0001) == 0) || (cpustate->VM != 0)) { /* VM8086 or Not Protected */ \
311 regs[0] = REG32(EAX); regs[1] = REG32(ECX); regs[2] = REG32(EDX); regs[3] = REG32(EBX); \
312 regs[4] = REG32(ESP); regs[5] = REG32(EBP); regs[6] = REG32(ESI); regs[7] = REG32(EDI); \
313 regs[8] = 0x0000; regs[9] = 0x0000; \
314 sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
315 sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
316 int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \
317 if(cpustate->bios->bios_call_far_ia32(address, regs, sregs, &ZeroFlag, &CarryFlag, &(cpustate->cycles), &(cpustate->total_cycles))) { \
318 REG32(EAX) = regs[0]; REG32(ECX) = regs[1]; REG32(EDX) = regs[2]; REG32(EBX) = regs[3]; \
319 REG32(ESP) = regs[4]; REG32(EBP) = regs[5]; REG32(ESI) = regs[6]; REG32(EDI) = regs[7]; \
320 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
321 CYCLES(cpustate,CYCLES_RET_INTERSEG); \
322 if((regs[8] != 0x0000) || (regs[9] != 0x0000)) { \
323 uint32_t hi = regs[9]; \
324 uint32_t lo = regs[8]; \
325 uint32_t addr = (hi << 16) | lo; \
326 cpustate->eip = addr; \
335 static CPU_TRANSLATE(i386);
338 printf("WARN: unexpected exception\n");
341 #include "mame/lib/softfloat/softfloat.c"
342 #include "mame/lib/softfloat/fsincos.c"
343 #include "mame/emu/cpu/vtlb.c"
344 #include "mame/emu/cpu/i386/i386.c"
345 //#ifdef USE_DEBUGGER
346 #include "mame/emu/cpu/i386/i386dasm.c"
349 void I386::initialize()
351 DEVICE::initialize();
352 uint32_t n_cpu_type = N_CPU_TYPE_I386;
353 if(osd->check_feature("HAS_I386")) {
354 n_cpu_type = N_CPU_TYPE_I386;
355 } else if(osd->check_feature("HAS_I486")) {
356 n_cpu_type = N_CPU_TYPE_I486;
357 } else if(osd->check_feature("HAS_PENTIUM")) {
358 n_cpu_type = N_CPU_TYPE_PENTIUM;
359 } else if(osd->check_feature("HAS_MEDIAGX")) {
360 n_cpu_type = N_CPU_TYPE_MEDIAGX;
361 } else if(osd->check_feature("HAS_PENTIUM_PRO")) {
362 n_cpu_type = N_CPU_TYPE_PENTIUM_PRO;
363 } else if(osd->check_feature("HAS_PENTIUM_MMX")) {
364 n_cpu_type = N_CPU_TYPE_PENTIUM_MMX;
365 } else if(osd->check_feature("HAS_PENTIUM2")) {
366 n_cpu_type = N_CPU_TYPE_PENTIUM2;
367 } else if(osd->check_feature("HAS_PENTIUM3")) {
368 n_cpu_type = N_CPU_TYPE_PENTIUM3;
369 } else if(osd->check_feature("HAS_PENTIUM4")) {
370 n_cpu_type = N_CPU_TYPE_PENTIUM4;
373 case N_CPU_TYPE_I386:
374 set_device_name(_T("i80386 CPU"));
375 opaque = CPU_INIT_CALL( i386 );
377 case N_CPU_TYPE_I486:
378 set_device_name(_T("i80486 CPU"));
379 opaque = CPU_INIT_CALL( i486 );
381 case N_CPU_TYPE_PENTIUM:
382 set_device_name(_T("Pentium CPU"));
383 opaque = CPU_INIT_CALL( pentium );
385 case N_CPU_TYPE_MEDIAGX:
386 set_device_name(_T("Media GX CPU"));
387 opaque = CPU_INIT_CALL( mediagx );
389 case N_CPU_TYPE_PENTIUM_PRO:
390 set_device_name(_T("Pentium PRO CPU"));
391 opaque = CPU_INIT_CALL( pentium_pro );
393 case N_CPU_TYPE_PENTIUM_MMX:
394 set_device_name(_T("Pentium MMX CPU"));
395 opaque = CPU_INIT_CALL( pentium_mmx );
397 case N_CPU_TYPE_PENTIUM2:
398 set_device_name(_T("Pentium2 CPU"));
399 opaque = CPU_INIT_CALL( pentium2 );
401 case N_CPU_TYPE_PENTIUM3:
402 set_device_name(_T("Pentium3 CPU"));
403 opaque = CPU_INIT_CALL( pentium3 );
405 case N_CPU_TYPE_PENTIUM4:
406 set_device_name(_T("Pentium4 CPU"));
407 opaque = CPU_INIT_CALL( pentium4 );
410 set_device_name(_T("i80386 CPU"));
411 opaque = CPU_INIT_CALL( i386 );
415 i386_state *cpustate = (i386_state *)opaque;
416 cpustate->pic = d_pic;
417 cpustate->program = d_mem;
419 //#ifdef I386_PSEUDO_BIOS
420 cpustate->bios = d_bios;
422 //#ifdef SINGLE_MODE_DMA
423 cpustate->dma = d_dma;
425 //#ifdef USE_DEBUGGER
427 cpustate->debugger = d_debugger;
428 cpustate->program_stored = d_mem;
429 cpustate->io_stored = d_io;
431 d_debugger->set_context_mem(d_mem);
432 d_debugger->set_context_io(d_io);
434 cpustate->parent_device = this; // This aims to log.
435 cpustate->cpu_type = n_cpu_type; // check cpu type
436 cpustate->shutdown = 0;
441 i386_state *cpustate = (i386_state *)opaque;
442 vtlb_free(cpustate->vtlb);
448 i386_state *cpustate = (i386_state *)opaque;
449 logerror(_T("I386::reset()"));
450 cpu_reset_generic(cpustate);
451 write_signals(&outputs_extreset, 0xffffffff);
454 int I386::run(int cycles)
456 i386_state *cpustate = (i386_state *)opaque;
457 return CPU_EXECUTE_CALL(i386); // OK?
460 void I386::write_signal(int id, uint32_t data, uint32_t mask)
462 i386_state *cpustate = (i386_state *)opaque;
464 if(id == SIG_CPU_NMI) {
465 i386_set_irq_line(cpustate, INPUT_LINE_NMI, (data & mask) ? HOLD_LINE : CLEAR_LINE);
466 } else if(id == SIG_CPU_IRQ) {
467 i386_set_irq_line(cpustate, INPUT_LINE_IRQ, (data & mask) ? HOLD_LINE : CLEAR_LINE);
468 } else if(id == SIG_CPU_BUSREQ) {
469 cpustate->busreq = (data & mask) ? 1 : 0;
470 } else if(id == SIG_I386_A20) {
471 i386_set_a20_line(cpustate, data & mask);
472 } else if(id == SIG_I386_NOTIFY_RESET) {
473 write_signals(&outputs_extreset, ((data & mask == 0) ? 0x00000000 : 0xffffffff));
477 void I386::set_intr_line(bool line, bool pending, uint32_t bit)
479 i386_state *cpustate = (i386_state *)opaque;
480 i386_set_irq_line(cpustate, INPUT_LINE_IRQ, line ? HOLD_LINE : CLEAR_LINE);
483 void I386::set_extra_clock(int cycles)
485 i386_state *cpustate = (i386_state *)opaque;
486 cpustate->extra_cycles += cycles;
489 int I386::get_extra_clock()
491 i386_state *cpustate = (i386_state *)opaque;
492 return cpustate->extra_cycles;
495 uint32_t I386::get_pc()
497 i386_state *cpustate = (i386_state *)opaque;
498 return cpustate->prev_pc;
501 uint32_t I386::get_next_pc()
503 i386_state *cpustate = (i386_state *)opaque;
507 //#ifdef USE_DEBUGGER
508 void I386::write_debug_data8(uint32_t addr, uint32_t data)
511 d_mem->write_data8w(addr, data, &wait);
514 uint32_t I386::translate_address(int segment, uint32_t offset)
516 i386_state *cpustate = (i386_state *)opaque;
518 if((segment >= 0) && (segment <= GS)) {
519 addr = cpustate->sreg[segment].base + offset;
520 // addr = (((uint32_t)(cpustate->sreg[segment].selector)) << 4) + offset;
525 uint32_t I386::read_debug_data8(uint32_t addr)
528 return d_mem->read_data8w(addr, &wait);
531 void I386::write_debug_data16(uint32_t addr, uint32_t data)
534 d_mem->write_data16w(addr, data, &wait);
537 uint32_t I386::read_debug_data16(uint32_t addr)
540 return d_mem->read_data16w(addr, &wait);
543 void I386::write_debug_data32(uint32_t addr, uint32_t data)
546 d_mem->write_data32w(addr, data, &wait);
549 uint32_t I386::read_debug_data32(uint32_t addr)
552 return d_mem->read_data32w(addr, &wait);
555 void I386::write_debug_io8(uint32_t addr, uint32_t data)
558 d_io->write_io8w(addr, data, &wait);
561 uint32_t I386::read_debug_io8(uint32_t addr) {
563 return d_io->read_io8w(addr, &wait);
566 void I386::write_debug_io16(uint32_t addr, uint32_t data)
569 d_io->write_io16w(addr, data, &wait);
572 uint32_t I386::read_debug_io16(uint32_t addr) {
574 return d_io->read_io16w(addr, &wait);
577 void I386::write_debug_io32(uint32_t addr, uint32_t data)
580 d_io->write_io32w(addr, data, &wait);
583 uint32_t I386::read_debug_io32(uint32_t addr) {
585 return d_io->read_io32w(addr, &wait);
588 bool I386::write_debug_reg(const _TCHAR *reg, uint32_t data)
590 i386_state *cpustate = (i386_state *)opaque;
591 if(_tcsicmp(reg, _T("IP")) == 0) {
592 cpustate->eip = data & 0xffff;
593 CHANGE_PC(cpustate, cpustate->eip);
594 } else if(_tcsicmp(reg, _T("EIP")) == 0) {
595 cpustate->eip = data;
596 CHANGE_PC(cpustate, cpustate->eip);
597 } else if(_tcsicmp(reg, _T("EAX")) == 0) {
599 } else if(_tcsicmp(reg, _T("EBX")) == 0) {
601 } else if(_tcsicmp(reg, _T("ECX")) == 0) {
603 } else if(_tcsicmp(reg, _T("EDX")) == 0) {
605 } else if(_tcsicmp(reg, _T("ESP")) == 0) {
607 } else if(_tcsicmp(reg, _T("EBP")) == 0) {
609 } else if(_tcsicmp(reg, _T("ESI")) == 0) {
611 } else if(_tcsicmp(reg, _T("EDI")) == 0) {
613 } else if(_tcsicmp(reg, _T("AX")) == 0) {
615 } else if(_tcsicmp(reg, _T("BX")) == 0) {
617 } else if(_tcsicmp(reg, _T("CX")) == 0) {
619 } else if(_tcsicmp(reg, _T("DX")) == 0) {
621 } else if(_tcsicmp(reg, _T("SP")) == 0) {
623 } else if(_tcsicmp(reg, _T("BP")) == 0) {
625 } else if(_tcsicmp(reg, _T("SI")) == 0) {
627 } else if(_tcsicmp(reg, _T("DI")) == 0) {
629 } else if(_tcsicmp(reg, _T("AL")) == 0) {
631 } else if(_tcsicmp(reg, _T("AH")) == 0) {
633 } else if(_tcsicmp(reg, _T("BL")) == 0) {
635 } else if(_tcsicmp(reg, _T("BH")) == 0) {
637 } else if(_tcsicmp(reg, _T("CL")) == 0) {
639 } else if(_tcsicmp(reg, _T("CH")) == 0) {
641 } else if(_tcsicmp(reg, _T("DL")) == 0) {
643 } else if(_tcsicmp(reg, _T("DH")) == 0) {
651 uint32_t I386::read_debug_reg(const _TCHAR *reg)
653 i386_state *cpustate = (i386_state *)opaque;
654 if(_tcsicmp(reg, _T("EIP")) == 0) {
655 return cpustate->eip;
656 } else if(_tcsicmp(reg, _T("IP")) == 0) {
657 return cpustate->eip & 0xffff;
658 } else if(_tcsicmp(reg, _T("EAX")) == 0) {
660 } else if(_tcsicmp(reg, _T("EBX")) == 0) {
662 } else if(_tcsicmp(reg, _T("ECX")) == 0) {
664 } else if(_tcsicmp(reg, _T("EDX")) == 0) {
666 } else if(_tcsicmp(reg, _T("ESP")) == 0) {
668 } else if(_tcsicmp(reg, _T("EBP")) == 0) {
670 } else if(_tcsicmp(reg, _T("ESI")) == 0) {
672 } else if(_tcsicmp(reg, _T("EDI")) == 0) {
674 } else if(_tcsicmp(reg, _T("AX")) == 0) {
676 } else if(_tcsicmp(reg, _T("BX")) == 0) {
678 } else if(_tcsicmp(reg, _T("CX")) == 0) {
680 } else if(_tcsicmp(reg, _T("DX")) == 0) {
682 } else if(_tcsicmp(reg, _T("SP")) == 0) {
684 } else if(_tcsicmp(reg, _T("BP")) == 0) {
686 } else if(_tcsicmp(reg, _T("SI")) == 0) {
688 } else if(_tcsicmp(reg, _T("DI")) == 0) {
690 } else if(_tcsicmp(reg, _T("AL")) == 0) {
692 } else if(_tcsicmp(reg, _T("AH")) == 0) {
694 } else if(_tcsicmp(reg, _T("BL")) == 0) {
696 } else if(_tcsicmp(reg, _T("BH")) == 0) {
698 } else if(_tcsicmp(reg, _T("CL")) == 0) {
700 } else if(_tcsicmp(reg, _T("CH")) == 0) {
702 } else if(_tcsicmp(reg, _T("DL")) == 0) {
704 } else if(_tcsicmp(reg, _T("DH")) == 0) {
710 bool I386::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
712 i386_state *cpustate = (i386_state *)opaque;
714 if(cpustate->operand_size) {
715 my_stprintf_s(buffer, buffer_len,
716 _T("MODE=%s PC=%08X PREV_PC=%08X SP(REAL)=%08X\n")
717 _T("CR[0-4]=%08X %08X %08X %08X %08X IOPL=%d CPL=%d\n")
718 _T("EAX=%08X EBX=%08X ECX=%08X EDX=%08X ESP=%08X EBP=%08X ESI=%08X EDI=%08X\n")
719 _T("DS=%04X ES=%04X SS=%04X CS=%04X FS=%04X GS=%04X\n")
720 _T("A20_MASK=%08X EIP=%08X EFLAGS=%08X FLAG=[%c%c%c%c%c%c%c%c%c]\n")
721 _T("Clocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
722 (PROTECTED_MODE != 0) ? ((V8086_MODE) ? _T("PROTECTED V8086(32bit)") : _T("PROTECTED 32bit")) : ((V8086_MODE) ? _T("V8086(32bit)") : _T("32bit")),
723 cpustate->pc, cpustate->prev_pc, cpustate->sreg[SS].base + ((uint32_t)REG32(ESP)),
724 cpustate->cr[0] ,cpustate->cr[1], cpustate->cr[2], cpustate->cr[3], cpustate->cr[4], (cpustate->IOP1) | (cpustate->IOP2 << 1), cpustate->CPL,
725 REG32(EAX), REG32(EBX), REG32(ECX), REG32(EDX), REG32(ESP), REG32(EBP), REG32(ESI), REG32(EDI),
726 cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->sreg[FS].selector, cpustate->sreg[GS].selector, cpustate->a20_mask, cpustate->eip, cpustate->eflags,
727 cpustate->OF ? _T('O') : _T('-'), cpustate->DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
728 cpustate->SF ? _T('S') : _T('-'), cpustate->ZF ? _T('Z') : _T('-'), cpustate->AF ? _T('A') : _T('-'), cpustate->PF ? _T('P') : _T('-'), cpustate->CF ? _T('C') : _T('-'),
729 cpustate->total_cycles, cpustate->total_cycles - cpustate->prev_total_cycles,
730 get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame());
732 if((PROTECTED_MODE) != 0) {
734 my_stprintf_s(buffer, buffer_len,
735 _T("MODE=V8086 (PROTECTED) PC=%08X PREV_PC=%08X SP(REAL)=%08X\n")
736 _T("CR[0-4]=%08X %08X %08X %08X %08X IOP=%d CPL=%d\n")
737 _T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\n")
738 _T("DS=%04X ES=%04X SS=%04X CS=%04X FS=%04X GS=%04X A20_MASK=%08X IP=%04X FLAG=[%c%c%c%c%c%c%c%c%c]\n")
739 _T("Clocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
740 cpustate->pc, cpustate->prev_pc, cpustate->sreg[SS].base + ((uint32_t)REG32(ESP) & 0xffff),
741 cpustate->cr[0] ,cpustate->cr[1], cpustate->cr[2], cpustate->cr[3], cpustate->cr[4], (cpustate->IOP1) | (cpustate->IOP2 << 1), cpustate->CPL,
742 REG16(AX), REG16(BX), REG16(CX), REG16(DX), REG16(SP), REG16(BP), REG16(SI), REG16(DI),
743 cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->sreg[FS].selector, cpustate->sreg[GS].selector, cpustate->a20_mask, cpustate->eip,
744 cpustate->OF ? _T('O') : _T('-'), cpustate->DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
745 cpustate->SF ? _T('S') : _T('-'), cpustate->ZF ? _T('Z') : _T('-'), cpustate->AF ? _T('A') : _T('-'), cpustate->PF ? _T('P') : _T('-'), cpustate->CF ? _T('C') : _T('-'),
746 cpustate->total_cycles, cpustate->total_cycles - cpustate->prev_total_cycles,
747 get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame());
749 my_stprintf_s(buffer, buffer_len,
750 _T("MODE=PROTECTED 16bit PC=%08X PREV_PC=%08X SP(REAL)=%08X\n")
751 _T("CR[0-4]=%08X %08X %08X %08X %08X IOP=%d CPL=%d\n")
752 _T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\n")
753 _T("DS=%04X ES=%04X SS=%04X CS=%04X FS=%04X GS=%04X A20_MASK=%08X IP=%04X EFLAGS=%08X FLAG=[%c%c%c%c%c%c%c%c%c]\n")
754 _T("Clocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
755 cpustate->pc, cpustate->prev_pc, cpustate->sreg[SS].base + ((uint32_t)REG32(ESP)),
756 cpustate->cr[0] ,cpustate->cr[1], cpustate->cr[2], cpustate->cr[3], cpustate->cr[4], (cpustate->IOP1) | (cpustate->IOP2 << 1), cpustate->CPL,
757 REG16(AX), REG16(BX), REG16(CX), REG16(DX), REG16(SP), REG16(BP), REG16(SI), REG16(DI),
758 cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->sreg[FS].selector, cpustate->sreg[GS].selector, cpustate->a20_mask, cpustate->eip, cpustate->eflags,
759 cpustate->OF ? _T('O') : _T('-'), cpustate->DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
760 cpustate->SF ? _T('S') : _T('-'), cpustate->ZF ? _T('Z') : _T('-'), cpustate->AF ? _T('A') : _T('-'), cpustate->PF ? _T('P') : _T('-'), cpustate->CF ? _T('C') : _T('-'),
761 cpustate->total_cycles, cpustate->total_cycles - cpustate->prev_total_cycles,
762 get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame());
765 my_stprintf_s(buffer, buffer_len,
766 _T("MODE=16bit PC=%08X PREV_PC=%08X SP(REAL)=%08X\n")
767 _T("CR[0-4]=%08X %08X %08X %08X %08X IOP=%d CPL=%d\n")
768 _T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\n")
769 _T("DS=%04X ES=%04X SS=%04X CS=%04X FS=%04X GS=%04X A20_MASK=%08X IP=%04X EFLAGS=%08X FLAG=[%c%c%c%c%c%c%c%c%c]\n")
770 _T("Clocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
771 cpustate->pc, cpustate->prev_pc, cpustate->sreg[SS].base + ((uint32_t)REG16(SP) & 0xffff),
772 cpustate->cr[0] ,cpustate->cr[1], cpustate->cr[2], cpustate->cr[3], cpustate->cr[4], (cpustate->IOP1) | (cpustate->IOP2 << 1), cpustate->CPL,
773 REG16(AX), REG16(BX), REG16(CX), REG16(DX), REG16(SP), REG16(BP), REG16(SI), REG16(DI),
774 cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->sreg[FS].selector, cpustate->sreg[GS].selector, cpustate->a20_mask, cpustate->eip, cpustate->eflags,
775 cpustate->OF ? _T('O') : _T('-'), cpustate->DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
776 cpustate->SF ? _T('S') : _T('-'), cpustate->ZF ? _T('Z') : _T('-'), cpustate->AF ? _T('A') : _T('-'), cpustate->PF ? _T('P') : _T('-'), cpustate->CF ? _T('C') : _T('-'),
777 cpustate->total_cycles, cpustate->total_cycles - cpustate->prev_total_cycles,
778 get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame());
781 cpustate->prev_total_cycles = cpustate->total_cycles;
785 int I386::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
787 i386_state *cpustate = (i386_state *)opaque;
788 UINT64 eip = pc - cpustate->sreg[CS].base;
790 for(int i = 0; i < 16; i++) {
792 ops[i] = d_mem->read_data8w(pc + i, &wait);
796 if(cpustate->operand_size) {
797 return CPU_DISASSEMBLE_CALL(x86_32) & DASMFLAG_LENGTHMASK;
799 return CPU_DISASSEMBLE_CALL(x86_16) & DASMFLAG_LENGTHMASK;
804 void I386::set_address_mask(uint32_t mask)
806 i386_state *cpustate = (i386_state *)opaque;
807 cpustate->a20_mask = mask;
809 // TODO: how does A20M and the tlb interact
810 vtlb_flush_dynamic(cpustate->vtlb);
813 uint32_t I386::get_address_mask()
815 i386_state *cpustate = (i386_state *)opaque;
816 return cpustate->a20_mask;
819 void I386::set_shutdown_flag(int shutdown)
821 i386_state *cpustate = (i386_state *)opaque;
822 cpustate->shutdown = shutdown;
825 int I386::get_shutdown_flag()
827 i386_state *cpustate = (i386_state *)opaque;
828 return cpustate->shutdown;
831 #define STATE_VERSION 5
833 void process_state_SREG(I386_SREG* val, FILEIO* state_fio)
835 state_fio->StateValue(val->selector);
836 state_fio->StateValue(val->flags);
837 state_fio->StateValue(val->base);
838 state_fio->StateValue(val->limit);
839 state_fio->StateValue(val->d);
840 state_fio->StateValue(val->valid);
843 void process_state_SYS_TABLE(I386_SYS_TABLE* val, FILEIO* state_fio)
845 state_fio->StateValue(val->base);
846 state_fio->StateValue(val->limit);
849 void process_state_SEG_DESC(I386_SEG_DESC* val, FILEIO* state_fio)
851 state_fio->StateValue(val->segment);
852 state_fio->StateValue(val->flags);
853 state_fio->StateValue(val->base);
854 state_fio->StateValue(val->limit);
857 void process_state_GPR(I386_GPR* val, FILEIO* state_fio)
859 state_fio->StateArray(val->d, sizeof(val->d), 1);
860 state_fio->StateArray(val->w, sizeof(val->w), 1);
861 state_fio->StateArray(val->b, sizeof(val->b), 1);
864 void process_state_floatx80(floatx80* val, FILEIO* state_fio)
866 state_fio->StateValue(val->high);
867 state_fio->StateValue(val->low);
870 void process_state_XMM_REG(XMM_REG* val, FILEIO* state_fio)
872 state_fio->StateArray(val->b, sizeof(val->b), 1);
873 state_fio->StateArray(val->w, sizeof(val->w), 1);
874 state_fio->StateArray(val->d, sizeof(val->d), 1);
875 state_fio->StateArray(val->q, sizeof(val->q), 1);
876 state_fio->StateArray(val->c, sizeof(val->c), 1);
877 state_fio->StateArray(val->s, sizeof(val->s), 1);
878 state_fio->StateArray(val->i, sizeof(val->i), 1);
879 state_fio->StateArray(val->l, sizeof(val->l), 1);
880 state_fio->StateArray(val->f, sizeof(val->f), 1);
881 state_fio->StateArray(val->f64, sizeof(val->f64), 1);
884 void process_state_vtlb(vtlb_state* val, FILEIO* state_fio)
886 // state_fio->StateValue(val->space);
887 // state_fio->StateValue(val->dynamic);
888 // state_fio->StateValue(val->fixed);
889 state_fio->StateValue(val->dynindex);
890 // state_fio->StateValue(val->pageshift);
891 // state_fio->StateValue(val->addrwidth);
892 if(val->live != NULL) {
893 state_fio->StateArray(val->live, val->fixed + val->dynamic, 1);
895 if(val->fixedpages != NULL) {
896 state_fio->StateArray(val->fixedpages, val->fixed, 1);
898 if(val->table != NULL) {
899 state_fio->StateArray(val->table, (size_t) 1 << (val->addrwidth - val->pageshift), 1);
903 bool I386::process_state(FILEIO* state_fio, bool loading)
905 i386_state *cpustate = (i386_state *)opaque;
907 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
910 if(!state_fio->StateCheckInt32(this_device_id)) {
913 process_state_GPR(&cpustate->reg, state_fio);
914 for(int i = 0; i < array_length(cpustate->sreg); i++) {
915 process_state_SREG(&cpustate->sreg[i], state_fio);
917 state_fio->StateValue(cpustate->eip);
918 state_fio->StateValue(cpustate->pc);
919 state_fio->StateValue(cpustate->prev_eip);
920 state_fio->StateValue(cpustate->prev_pc);
921 state_fio->StateValue(cpustate->eflags);
922 state_fio->StateValue(cpustate->eflags_mask);
923 state_fio->StateValue(cpustate->CF);
924 state_fio->StateValue(cpustate->DF);
925 state_fio->StateValue(cpustate->SF);
926 state_fio->StateValue(cpustate->OF);
927 state_fio->StateValue(cpustate->ZF);
928 state_fio->StateValue(cpustate->PF);
929 state_fio->StateValue(cpustate->AF);
930 state_fio->StateValue(cpustate->IF);
931 state_fio->StateValue(cpustate->TF);
932 state_fio->StateValue(cpustate->IOP1);
933 state_fio->StateValue(cpustate->IOP2);
934 state_fio->StateValue(cpustate->NT);
935 state_fio->StateValue(cpustate->RF);
936 state_fio->StateValue(cpustate->VM);
937 state_fio->StateValue(cpustate->AC);
938 state_fio->StateValue(cpustate->VIF);
939 state_fio->StateValue(cpustate->VIP);
940 state_fio->StateValue(cpustate->ID);
941 state_fio->StateValue(cpustate->CPL);
942 state_fio->StateValue(cpustate->performed_intersegment_jump);
943 state_fio->StateValue(cpustate->delayed_interrupt_enable);
944 state_fio->StateArray(cpustate->cr, sizeof(cpustate->cr), 1);
945 state_fio->StateArray(cpustate->dr, sizeof(cpustate->dr), 1);
946 state_fio->StateArray(cpustate->tr, sizeof(cpustate->tr), 1);
947 process_state_SYS_TABLE(&cpustate->gdtr, state_fio);
948 process_state_SYS_TABLE(&cpustate->idtr, state_fio);
949 process_state_SEG_DESC(&cpustate->task, state_fio);
950 process_state_SEG_DESC(&cpustate->ldtr, state_fio);
951 state_fio->StateValue(cpustate->ext);
952 state_fio->StateValue(cpustate->halted);
953 state_fio->StateValue(cpustate->busreq);
954 state_fio->StateValue(cpustate->shutdown);
955 state_fio->StateValue(cpustate->operand_size);
956 state_fio->StateValue(cpustate->xmm_operand_size);
957 state_fio->StateValue(cpustate->address_size);
958 state_fio->StateValue(cpustate->operand_prefix);
959 state_fio->StateValue(cpustate->address_prefix);
960 state_fio->StateValue(cpustate->segment_prefix);
961 state_fio->StateValue(cpustate->segment_override);
962 //#ifdef USE_DEBUGGER
963 state_fio->StateValue(cpustate->total_cycles);
965 state_fio->StateValue(cpustate->cycles);
966 state_fio->StateValue(cpustate->extra_cycles);
967 state_fio->StateValue(cpustate->base_cycles);
968 state_fio->StateValue(cpustate->opcode);
969 state_fio->StateValue(cpustate->irq_state);
970 state_fio->StateValue(cpustate->a20_mask);
971 state_fio->StateValue(cpustate->cpuid_max_input_value_eax);
972 state_fio->StateValue(cpustate->cpuid_id0);
973 state_fio->StateValue(cpustate->cpuid_id1);
974 state_fio->StateValue(cpustate->cpuid_id2);
975 state_fio->StateValue(cpustate->cpu_version);
976 state_fio->StateValue(cpustate->feature_flags);
977 state_fio->StateValue(cpustate->tsc);
978 state_fio->StateArray(cpustate->perfctr, sizeof(cpustate->perfctr), 1);
979 for(int i = 0; i < array_length(cpustate->x87_reg); i++) {
980 process_state_floatx80(&cpustate->x87_reg[i], state_fio);
982 state_fio->StateValue(cpustate->x87_cw);
983 state_fio->StateValue(cpustate->x87_sw);
984 state_fio->StateValue(cpustate->x87_tw);
985 state_fio->StateValue(cpustate->x87_data_ptr);
986 state_fio->StateValue(cpustate->x87_inst_ptr);
987 state_fio->StateValue(cpustate->x87_opcode);
988 for(int i = 0; i < array_length(cpustate->sse_reg); i++) {
989 process_state_XMM_REG(&cpustate->sse_reg[i], state_fio);
991 state_fio->StateValue(cpustate->mxcsr);
992 state_fio->StateArray(&cpustate->lock_table[0][0], sizeof(cpustate->lock_table), 1);
993 if(cpustate->vtlb != NULL) {
994 process_state_vtlb(cpustate->vtlb, state_fio);
996 state_fio->StateValue(cpustate->smm);
997 state_fio->StateValue(cpustate->smi);
998 state_fio->StateValue(cpustate->smi_latched);
999 state_fio->StateValue(cpustate->nmi_masked);
1000 state_fio->StateValue(cpustate->nmi_latched);
1001 state_fio->StateValue(cpustate->smbase);
1002 // state_fio->StateValue(cpustate->smiact);
1003 state_fio->StateValue(cpustate->lock);
1004 #ifdef DEBUG_MISSING_OPCODE
1005 state_fio->StateArray(cpustate->opcode_bytes, sizeof(cpustate->opcode_bytes), 1);
1006 state_fio->StateValue(cpustate->opcode_pc);
1007 state_fio->StateValue(cpustate->opcode_bytes_length);
1010 //#ifdef USE_DEBUGGER
1013 cpustate->prev_total_cycles = cpustate->total_cycles;