2 Skelton for retropc emulator
4 Origin : MAME i386 core
5 Author : Takeda.Toshiya
8 [ i386/i486/Pentium/MediaGX ]
16 /* ----------------------------------------------------------------------------
18 ---------------------------------------------------------------------------- */
20 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
21 #pragma warning( disable : 4018 )
22 #pragma warning( disable : 4065 )
23 #pragma warning( disable : 4146 )
24 #pragma warning( disable : 4244 )
25 #pragma warning( disable : 4996 )
29 #define CPU_MODEL i386
30 #elif defined(HAS_I486)
31 #define CPU_MODEL i486
32 #elif defined(HAS_PENTIUM)
33 #define CPU_MODEL pentium
34 #elif defined(HAS_MEDIAGX)
35 #define CPU_MODEL mediagx
36 #elif defined(HAS_PENTIUM_PRO)
37 #define CPU_MODEL pentium_pro
38 #elif defined(HAS_PENTIUM_MMX)
39 #define CPU_MODEL pentium_mmx
40 #elif defined(HAS_PENTIUM2)
41 #define CPU_MODEL pentium2
42 #elif defined(HAS_PENTIUM3)
43 #define CPU_MODEL pentium3
44 #elif defined(HAS_PENTIUM4)
45 #define CPU_MODEL pentium4
48 #ifndef __BIG_ENDIAN__
56 #define U64(v) UINT64(v)
58 #define fatalerror(...) exit(1)
60 #define popmessage(...)
62 /*****************************************************************************/
63 /* src/emu/devcpu.h */
65 // CPU interface functions
66 #define CPU_INIT_NAME(name) cpu_init_##name
67 #define CPU_INIT(name) void* CPU_INIT_NAME(name)()
68 #define CPU_INIT_CALL(name) CPU_INIT_NAME(name)()
70 #define CPU_RESET_NAME(name) cpu_reset_##name
71 #define CPU_RESET(name) void CPU_RESET_NAME(name)(i386_state *cpustate)
72 #define CPU_RESET_CALL(name) CPU_RESET_NAME(name)(cpustate)
74 #define CPU_EXECUTE_NAME(name) cpu_execute_##name
75 #define CPU_EXECUTE(name) int CPU_EXECUTE_NAME(name)(i386_state *cpustate, int cycles)
76 #define CPU_EXECUTE_CALL(name) CPU_EXECUTE_NAME(name)(cpustate, cycles)
78 #define CPU_TRANSLATE_NAME(name) cpu_translate_##name
79 #define CPU_TRANSLATE(name) int CPU_TRANSLATE_NAME(name)(void *cpudevice, address_spacenum space, int intention, offs_t *address)
80 #define CPU_TRANSLATE_CALL(name) CPU_TRANSLATE_NAME(name)(cpudevice, space, intention, address)
82 #define CPU_DISASSEMBLE_NAME(name) cpu_disassemble_##name
83 #define CPU_DISASSEMBLE(name) int CPU_DISASSEMBLE_NAME(name)(char *buffer, offs_t eip, const UINT8 *oprom)
84 #define CPU_DISASSEMBLE_CALL(name) CPU_DISASSEMBLE_NAME(name)(buffer, eip, oprom)
86 /*****************************************************************************/
87 /* src/emu/didisasm.h */
89 // Disassembler constants
90 const UINT32 DASMFLAG_SUPPORTED = 0x80000000; // are disassembly flags supported?
91 const UINT32 DASMFLAG_STEP_OUT = 0x40000000; // this instruction should be the end of a step out sequence
92 const UINT32 DASMFLAG_STEP_OVER = 0x20000000; // this instruction should be stepped over by setting a breakpoint afterwards
93 const UINT32 DASMFLAG_OVERINSTMASK = 0x18000000; // number of extra instructions to skip when stepping over
94 const UINT32 DASMFLAG_OVERINSTSHIFT = 27; // bits to shift after masking to get the value
95 const UINT32 DASMFLAG_LENGTHMASK = 0x0000ffff; // the low 16-bits contain the actual length
97 /*****************************************************************************/
98 /* src/emu/diexec.h */
103 CLEAR_LINE = 0, // clear (a fired or held) line
104 ASSERT_LINE, // assert an interrupt immediately
105 HOLD_LINE, // hold interrupt line until acknowledged
106 PULSE_LINE // pulse interrupt line instantaneously (only for NMI, RESET)
115 /*****************************************************************************/
116 /* src/emu/dimemory.h */
118 // Translation intentions
119 const int TRANSLATE_TYPE_MASK = 0x03; // read write or fetch
120 const int TRANSLATE_USER_MASK = 0x04; // user mode or fully privileged
121 const int TRANSLATE_DEBUG_MASK = 0x08; // debug mode (no side effects)
123 const int TRANSLATE_READ = 0; // translate for read
124 const int TRANSLATE_WRITE = 1; // translate for write
125 const int TRANSLATE_FETCH = 2; // translate for instruction fetch
126 const int TRANSLATE_READ_USER = (TRANSLATE_READ | TRANSLATE_USER_MASK);
127 const int TRANSLATE_WRITE_USER = (TRANSLATE_WRITE | TRANSLATE_USER_MASK);
128 const int TRANSLATE_FETCH_USER = (TRANSLATE_FETCH | TRANSLATE_USER_MASK);
129 const int TRANSLATE_READ_DEBUG = (TRANSLATE_READ | TRANSLATE_DEBUG_MASK);
130 const int TRANSLATE_WRITE_DEBUG = (TRANSLATE_WRITE | TRANSLATE_DEBUG_MASK);
131 const int TRANSLATE_FETCH_DEBUG = (TRANSLATE_FETCH | TRANSLATE_DEBUG_MASK);
133 /*****************************************************************************/
134 /* src/emu/emucore.h */
136 // constants for expression endianness
143 // declare native endianness to be one or the other
145 const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_LITTLE;
147 const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_BIG;
149 // endian-based value: first value is if 'endian' is little-endian, second is if 'endian' is big-endian
150 #define ENDIAN_VALUE_LE_BE(endian,leval,beval) (((endian) == ENDIANNESS_LITTLE) ? (leval) : (beval))
151 // endian-based value: first value is if native endianness is little-endian, second is if native is big-endian
152 #define NATIVE_ENDIAN_VALUE_LE_BE(leval,beval) ENDIAN_VALUE_LE_BE(ENDIANNESS_NATIVE, leval, beval)
153 // endian-based value: first value is if 'endian' matches native, second is if 'endian' doesn't match native
154 #define ENDIAN_VALUE_NE_NNE(endian,leval,beval) (((endian) == ENDIANNESS_NATIVE) ? (neval) : (nneval))
156 /*****************************************************************************/
157 /* src/emu/memory.h */
160 enum address_spacenum
162 AS_0, // first address space
163 AS_1, // second address space
164 AS_2, // third address space
165 AS_3, // fourth address space
166 ADDRESS_SPACES, // maximum number of address spaces
168 // alternate address space names for common use
169 AS_PROGRAM = AS_0, // program address space
170 AS_DATA = AS_1, // data address space
171 AS_IO = AS_2 // I/O address space
174 // offsets and addresses are 32-bit (for now...)
175 typedef UINT32 offs_t;
177 /*****************************************************************************/
178 /* src/osd/osdcomm.h */
180 /* Highly useful macro for compile-time knowledge of an array size */
181 #define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
183 #ifdef I386_BIOS_CALL
184 #define BIOS_INT(num) if(cpustate->bios != NULL) { \
185 uint16 regs[8], sregs[4]; \
186 regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
187 regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
188 sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
189 sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
190 int32 ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \
191 if(cpustate->bios->bios_int_i86(num, regs, sregs, &ZeroFlag, &CarryFlag)) { \
192 REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
193 REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
194 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
198 #define BIOS_CALL(address) if(cpustate->bios != NULL) { \
199 uint16 regs[8], sregs[4]; \
200 regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
201 regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
202 sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
203 sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
204 int32 ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \
205 if(cpustate->bios->bios_call_i86(address, regs, sregs, &ZeroFlag, &CarryFlag)) { \
206 REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
207 REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
208 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
214 static CPU_TRANSLATE(i386);
216 #include "mame/lib/softfloat/softfloat.c"
217 #include "mame/emu/cpu/vtlb.c"
218 #include "mame/emu/cpu/i386/i386.c"
220 #include "mame/emu/cpu/i386/i386dasm.c"
223 void I386::initialize()
225 opaque = CPU_INIT_CALL(CPU_MODEL);
227 i386_state *cpustate = (i386_state *)opaque;
228 cpustate->pic = d_pic;
229 cpustate->program = d_mem;
231 #ifdef I386_BIOS_CALL
232 cpustate->bios = d_bios;
234 #ifdef SINGLE_MODE_DMA
235 cpustate->dma = d_dma;
239 cpustate->debugger = d_debugger;
240 cpustate->program_stored = d_mem;
241 cpustate->io_stored = d_io;
243 d_debugger->set_context_mem(d_mem);
244 d_debugger->set_context_io(d_io);
246 cpustate->shutdown = 0;
251 i386_state *cpustate = (i386_state *)opaque;
252 vtlb_free(cpustate->vtlb);
258 i386_state *cpustate = (i386_state *)opaque;
259 CPU_RESET_CALL(CPU_MODEL);
262 int I386::run(int cycles)
264 i386_state *cpustate = (i386_state *)opaque;
265 return CPU_EXECUTE_CALL(i386);
268 void I386::write_signal(int id, uint32 data, uint32 mask)
270 i386_state *cpustate = (i386_state *)opaque;
272 if(id == SIG_CPU_NMI) {
273 i386_set_irq_line(cpustate, INPUT_LINE_NMI, (data & mask) ? HOLD_LINE : CLEAR_LINE);
274 } else if(id == SIG_CPU_IRQ) {
275 i386_set_irq_line(cpustate, INPUT_LINE_IRQ, (data & mask) ? HOLD_LINE : CLEAR_LINE);
276 } else if(id == SIG_CPU_BUSREQ) {
277 cpustate->busreq = (data & mask) ? 1 : 0;
278 } else if(id == SIG_I386_A20) {
279 i386_set_a20_line(cpustate, data & mask);
283 void I386::set_intr_line(bool line, bool pending, uint32 bit)
285 i386_state *cpustate = (i386_state *)opaque;
286 i386_set_irq_line(cpustate, INPUT_LINE_IRQ, line ? HOLD_LINE : CLEAR_LINE);
289 void I386::set_extra_clock(int cycles)
291 i386_state *cpustate = (i386_state *)opaque;
292 cpustate->extra_cycles += cycles;
295 int I386::get_extra_clock()
297 i386_state *cpustate = (i386_state *)opaque;
298 return cpustate->extra_cycles;
301 uint32 I386::get_pc()
303 i386_state *cpustate = (i386_state *)opaque;
304 return cpustate->prev_pc;
307 uint32 I386::get_next_pc()
309 i386_state *cpustate = (i386_state *)opaque;
314 void I386::debug_write_data8(uint32 addr, uint32 data)
317 d_mem->write_data8w(addr, data, &wait);
320 uint32 I386::debug_read_data8(uint32 addr)
323 return d_mem->read_data8w(addr, &wait);
326 void I386::debug_write_data16(uint32 addr, uint32 data)
329 d_mem->write_data16w(addr, data, &wait);
332 uint32 I386::debug_read_data16(uint32 addr)
335 return d_mem->read_data16w(addr, &wait);
338 void I386::debug_write_data32(uint32 addr, uint32 data)
341 d_mem->write_data32w(addr, data, &wait);
344 uint32 I386::debug_read_data32(uint32 addr)
347 return d_mem->read_data32w(addr, &wait);
350 void I386::debug_write_io8(uint32 addr, uint32 data)
353 d_io->write_io8w(addr, data, &wait);
356 uint32 I386::debug_read_io8(uint32 addr) {
358 return d_io->read_io8w(addr, &wait);
361 void I386::debug_write_io16(uint32 addr, uint32 data)
364 d_io->write_io16w(addr, data, &wait);
367 uint32 I386::debug_read_io16(uint32 addr) {
369 return d_io->read_io16w(addr, &wait);
372 void I386::debug_write_io32(uint32 addr, uint32 data)
375 d_io->write_io32w(addr, data, &wait);
378 uint32 I386::debug_read_io32(uint32 addr) {
380 return d_io->read_io32w(addr, &wait);
383 bool I386::debug_write_reg(_TCHAR *reg, uint32 data)
385 i386_state *cpustate = (i386_state *)opaque;
386 if(_tcsicmp(reg, _T("IP")) == 0) {
387 cpustate->eip = data & 0xffff;
388 CHANGE_PC(cpustate, cpustate->eip);
389 } else if(_tcsicmp(reg, _T("AX")) == 0) {
391 } else if(_tcsicmp(reg, _T("BX")) == 0) {
393 } else if(_tcsicmp(reg, _T("CX")) == 0) {
395 } else if(_tcsicmp(reg, _T("DX")) == 0) {
397 } else if(_tcsicmp(reg, _T("SP")) == 0) {
399 } else if(_tcsicmp(reg, _T("BP")) == 0) {
401 } else if(_tcsicmp(reg, _T("SI")) == 0) {
403 } else if(_tcsicmp(reg, _T("DI")) == 0) {
405 } else if(_tcsicmp(reg, _T("AL")) == 0) {
407 } else if(_tcsicmp(reg, _T("AH")) == 0) {
409 } else if(_tcsicmp(reg, _T("BL")) == 0) {
411 } else if(_tcsicmp(reg, _T("BH")) == 0) {
413 } else if(_tcsicmp(reg, _T("CL")) == 0) {
415 } else if(_tcsicmp(reg, _T("CH")) == 0) {
417 } else if(_tcsicmp(reg, _T("DL")) == 0) {
419 } else if(_tcsicmp(reg, _T("DH")) == 0) {
427 void I386::debug_regs_info(_TCHAR *buffer, size_t buffer_len)
429 i386_state *cpustate = (i386_state *)opaque;
430 _stprintf_s(buffer, buffer_len,
431 _T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\nDS=%04X ES=%04X SS=%04X CS=%04X IP=%04X FLAG=[%c%c%c%c%c%c%c%c%c]"),
432 REG16(AX), REG16(BX), REG16(CX), REG16(DX), REG16(SP), REG16(BP), REG16(SI), REG16(DI),
433 cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->eip,
434 cpustate->OF ? _T('O') : _T('-'), cpustate->DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
435 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('-'));
438 int I386::debug_dasm(uint32 pc, _TCHAR *buffer, size_t buffer_len)
440 i386_state *cpustate = (i386_state *)opaque;
441 UINT64 eip = cpustate->eip;
443 for(int i = 0; i < 16; i++) {
445 ops[i] = d_mem->read_data8w(pc + i, &wait);
449 if(cpustate->operand_size) {
450 return CPU_DISASSEMBLE_CALL(x86_32) & DASMFLAG_LENGTHMASK;
452 return CPU_DISASSEMBLE_CALL(x86_16) & DASMFLAG_LENGTHMASK;
457 void I386::set_address_mask(uint32 mask)
459 i386_state *cpustate = (i386_state *)opaque;
460 cpustate->a20_mask = mask;
463 uint32 I386::get_address_mask()
465 i386_state *cpustate = (i386_state *)opaque;
466 return cpustate->a20_mask;
469 void I386::set_shutdown_flag(int shutdown)
471 i386_state *cpustate = (i386_state *)opaque;
472 cpustate->shutdown = shutdown;
475 int I386::get_shutdown_flag()
477 i386_state *cpustate = (i386_state *)opaque;
478 return cpustate->shutdown;
482 #define STATE_VERSION 1
484 void I386::save_state(FILEIO* state_fio)
486 state_fio->FputUint32(STATE_VERSION);
487 state_fio->FputInt32(this_device_id);
489 state_fio->Fwrite(opaque, sizeof(i386_state), 1);
492 bool I386::load_state(FILEIO* state_fio)
494 if(state_fio->FgetUint32() != STATE_VERSION) {
497 if(state_fio->FgetInt32() != this_device_id) {
500 state_fio->Fread(opaque, sizeof(i386_state), 1);
503 i386_state *cpustate = (i386_state *)opaque;
504 cpustate->pic = d_pic;
505 cpustate->program = d_mem;
508 cpustate->bios = d_bios;
510 #ifdef SINGLE_MODE_DMA
511 cpustate->dma = d_dma;
515 cpustate->debugger = d_debugger;
516 cpustate->program_stored = d_mem;
517 cpustate->io_stored = d_io;