2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
12 #include "../debugger.h"
15 /* ----------------------------------------------------------------------------
17 ---------------------------------------------------------------------------- */
19 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
20 #pragma warning( disable : 4018 )
21 #pragma warning( disable : 4146 )
22 #pragma warning( disable : 4244 )
23 #pragma warning( disable : 4996 )
27 #define CPU_MODEL i8086
28 #elif defined(HAS_I88)
29 #define CPU_MODEL i8088
30 #elif defined(HAS_I186)
31 #define CPU_MODEL i80186
32 #elif defined(HAS_V30)
34 #elif defined(HAS_I286)
35 #define CPU_MODEL i80286
38 #ifndef __BIG_ENDIAN__
48 /*****************************************************************************/
49 /* src/emu/devcpu.h */
51 // CPU interface functions
52 #define CPU_INIT_NAME(name) cpu_init_##name
53 #define CPU_INIT(name) void* CPU_INIT_NAME(name)()
54 #define CPU_INIT_CALL(name) CPU_INIT_NAME(name)()
56 #define CPU_RESET_NAME(name) cpu_reset_##name
57 #define CPU_RESET(name) void CPU_RESET_NAME(name)(cpu_state *cpustate)
58 #define CPU_RESET_CALL(name) CPU_RESET_NAME(name)(cpustate)
60 #define CPU_EXECUTE_NAME(name) cpu_execute_##name
61 #define CPU_EXECUTE(name) int CPU_EXECUTE_NAME(name)(cpu_state *cpustate, int icount)
62 #define CPU_EXECUTE_CALL(name) CPU_EXECUTE_NAME(name)(cpustate, icount)
64 #define CPU_DISASSEMBLE_NAME(name) cpu_disassemble_##name
65 #define CPU_DISASSEMBLE(name) int CPU_DISASSEMBLE_NAME(name)(_TCHAR *buffer, offs_t eip, const UINT8 *oprom)
66 #define CPU_DISASSEMBLE_CALL(name) CPU_DISASSEMBLE_NAME(name)(buffer, eip, oprom)
68 /*****************************************************************************/
69 /* src/emu/didisasm.h */
71 // Disassembler constants
72 const UINT32 DASMFLAG_SUPPORTED = 0x80000000; // are disassembly flags supported?
73 const UINT32 DASMFLAG_STEP_OUT = 0x40000000; // this instruction should be the end of a step out sequence
74 const UINT32 DASMFLAG_STEP_OVER = 0x20000000; // this instruction should be stepped over by setting a breakpoint afterwards
75 const UINT32 DASMFLAG_OVERINSTMASK = 0x18000000; // number of extra instructions to skip when stepping over
76 const UINT32 DASMFLAG_OVERINSTSHIFT = 27; // bits to shift after masking to get the value
77 const UINT32 DASMFLAG_LENGTHMASK = 0x0000ffff; // the low 16-bits contain the actual length
79 /*****************************************************************************/
80 /* src/emu/diexec.h */
85 CLEAR_LINE = 0, // clear (a fired or held) line
86 ASSERT_LINE, // assert an interrupt immediately
87 HOLD_LINE, // hold interrupt line until acknowledged
88 PULSE_LINE // pulse interrupt line instantaneously (only for NMI, RESET)
97 /*****************************************************************************/
98 /* src/emu/emucore.h */
100 // constants for expression endianness
107 // declare native endianness to be one or the other
109 const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_LITTLE;
111 const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_BIG;
113 // endian-based value: first value is if 'endian' is little-endian, second is if 'endian' is big-endian
114 #define ENDIAN_VALUE_LE_BE(endian,leval,beval) (((endian) == ENDIANNESS_LITTLE) ? (leval) : (beval))
115 // endian-based value: first value is if native endianness is little-endian, second is if native is big-endian
116 #define NATIVE_ENDIAN_VALUE_LE_BE(leval,beval) ENDIAN_VALUE_LE_BE(ENDIANNESS_NATIVE, leval, beval)
117 // endian-based value: first value is if 'endian' matches native, second is if 'endian' doesn't match native
118 #define ENDIAN_VALUE_NE_NNE(endian,leval,beval) (((endian) == ENDIANNESS_NATIVE) ? (neval) : (nneval))
120 /*****************************************************************************/
121 /* src/emu/memory.h */
123 // offsets and addresses are 32-bit (for now...)
124 typedef UINT32 offs_t;
126 /*****************************************************************************/
127 /* src/osd/osdcomm.h */
129 /* Highly useful macro for compile-time knowledge of an array size */
130 #define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
132 #if defined(HAS_I86) || defined(HAS_I88) || defined(HAS_I186) || defined(HAS_V30)
133 #define cpu_state i8086_state
134 #include "../mame/emu/cpu/i86/i86.c"
135 #elif defined(HAS_I286)
136 #define cpu_state i80286_state
137 #include "../mame/emu/cpu/i86/i286.c"
141 #include "../mame/emu/cpu/nec/necdasm.c"
143 #include "../mame/emu/cpu/i386/i386dasm.c"
147 void I286::initialize()
149 opaque = CPU_INIT_CALL(CPU_MODEL);
151 cpu_state *cpustate = (cpu_state *)opaque;
152 cpustate->pic = d_pic;
153 cpustate->program = d_mem;
155 #ifdef I86_PSEUDO_BIOS
156 cpustate->bios = d_bios;
158 #ifdef SINGLE_MODE_DMA
159 cpustate->dma = d_dma;
163 cpustate->debugger = d_debugger;
164 cpustate->program_stored = d_mem;
165 cpustate->io_stored = d_io;
167 d_debugger->set_context_mem(d_mem);
168 d_debugger->set_context_io(d_io);
179 cpu_state *cpustate = (cpu_state *)opaque;
180 int busreq = cpustate->busreq;
182 CPU_RESET_CALL(CPU_MODEL);
184 cpustate->pic = d_pic;
185 cpustate->program = d_mem;
187 #ifdef I86_PSEUDO_BIOS
188 cpustate->bios = d_bios;
190 #ifdef SINGLE_MODE_DMA
191 cpustate->dma = d_dma;
195 cpustate->debugger = d_debugger;
196 cpustate->program_stored = d_mem;
197 cpustate->io_stored = d_io;
199 cpustate->busreq = busreq;
202 int I286::run(int icount)
204 cpu_state *cpustate = (cpu_state *)opaque;
206 // ugly patch for PC/JX hardware diagnostics :-(
208 if(cpustate->pc == 0xff040) cpustate->pc = 0xff04a;
209 if(cpustate->pc == 0xff17d) cpustate->pc = 0xff18f;
212 if(cpustate->pc == 0xfa909) { cpustate->regs.b[BH] = read_port_byte(0xa1); cpustate->pc = 0xfa97c; }
213 if(cpustate->pc == 0xff6e1) { cpustate->regs.b[AL] = 0x0d; cpustate->pc += 2; }
216 return CPU_EXECUTE_CALL(CPU_MODEL);
219 void I286::write_signal(int id, uint32_t data, uint32_t mask)
221 cpu_state *cpustate = (cpu_state *)opaque;
223 if(id == SIG_CPU_NMI) {
224 set_irq_line(cpustate, INPUT_LINE_NMI, (data & mask) ? HOLD_LINE : CLEAR_LINE);
225 } else if(id == SIG_CPU_IRQ) {
226 set_irq_line(cpustate, INPUT_LINE_IRQ, (data & mask) ? HOLD_LINE : CLEAR_LINE);
227 } else if(id == SIG_CPU_BUSREQ) {
228 cpustate->busreq = (data & mask) ? 1 : 0;
229 } else if(id == SIG_I86_TEST) {
230 cpustate->test_state = (data & mask) ? 1 : 0;
232 } else if(id == SIG_I286_A20) {
233 i80286_set_a20_line(cpustate, data & mask);
238 void I286::set_intr_line(bool line, bool pending, uint32_t bit)
240 cpu_state *cpustate = (cpu_state *)opaque;
241 set_irq_line(cpustate, INPUT_LINE_IRQ, line ? HOLD_LINE : CLEAR_LINE);
244 void I286::set_extra_clock(int icount)
246 cpu_state *cpustate = (cpu_state *)opaque;
247 cpustate->extra_cycles += icount;
250 int I286::get_extra_clock()
252 cpu_state *cpustate = (cpu_state *)opaque;
253 return cpustate->extra_cycles;
256 uint32_t I286::get_pc()
258 cpu_state *cpustate = (cpu_state *)opaque;
259 return cpustate->prevpc;
262 uint32_t I286::get_next_pc()
264 cpu_state *cpustate = (cpu_state *)opaque;
269 void I286::write_debug_data8(uint32_t addr, uint32_t data)
272 d_mem->write_data8w(addr, data, &wait);
275 uint32_t I286::read_debug_data8(uint32_t addr)
278 return d_mem->read_data8w(addr, &wait);
281 void I286::write_debug_data16(uint32_t addr, uint32_t data)
284 d_mem->write_data16w(addr, data, &wait);
287 uint32_t I286::read_debug_data16(uint32_t addr)
290 return d_mem->read_data16w(addr, &wait);
293 void I286::write_debug_io8(uint32_t addr, uint32_t data)
296 d_io->write_io8w(addr, data, &wait);
299 uint32_t I286::read_debug_io8(uint32_t addr) {
301 return d_io->read_io8w(addr, &wait);
304 void I286::write_debug_io16(uint32_t addr, uint32_t data)
307 d_io->write_io16w(addr, data, &wait);
310 uint32_t I286::read_debug_io16(uint32_t addr) {
312 return d_io->read_io16w(addr, &wait);
315 bool I286::write_debug_reg(const _TCHAR *reg, uint32_t data)
317 cpu_state *cpustate = (cpu_state *)opaque;
318 if(_tcsicmp(reg, _T("IP")) == 0) {
319 cpustate->pc = ((data & 0xffff) + cpustate->base[CS]) & AMASK;
320 CHANGE_PC(cpustate->pc);
321 } else if(_tcsicmp(reg, _T("AX")) == 0) {
322 cpustate->regs.w[AX] = data;
323 } else if(_tcsicmp(reg, _T("BX")) == 0) {
324 cpustate->regs.w[BX] = data;
325 } else if(_tcsicmp(reg, _T("CX")) == 0) {
326 cpustate->regs.w[CX] = data;
327 } else if(_tcsicmp(reg, _T("DX")) == 0) {
328 cpustate->regs.w[DX] = data;
329 } else if(_tcsicmp(reg, _T("SP")) == 0) {
330 cpustate->regs.w[SP] = data;
331 } else if(_tcsicmp(reg, _T("BP")) == 0) {
332 cpustate->regs.w[BP] = data;
333 } else if(_tcsicmp(reg, _T("SI")) == 0) {
334 cpustate->regs.w[SI] = data;
335 } else if(_tcsicmp(reg, _T("DI")) == 0) {
336 cpustate->regs.w[DI] = data;
337 } else if(_tcsicmp(reg, _T("AL")) == 0) {
338 cpustate->regs.b[AL] = data;
339 } else if(_tcsicmp(reg, _T("AH")) == 0) {
340 cpustate->regs.b[AH] = data;
341 } else if(_tcsicmp(reg, _T("BL")) == 0) {
342 cpustate->regs.b[BL] = data;
343 } else if(_tcsicmp(reg, _T("BH")) == 0) {
344 cpustate->regs.b[BH] = data;
345 } else if(_tcsicmp(reg, _T("CL")) == 0) {
346 cpustate->regs.b[CL] = data;
347 } else if(_tcsicmp(reg, _T("CH")) == 0) {
348 cpustate->regs.b[CH] = data;
349 } else if(_tcsicmp(reg, _T("DL")) == 0) {
350 cpustate->regs.b[DL] = data;
351 } else if(_tcsicmp(reg, _T("DH")) == 0) {
352 cpustate->regs.b[DH] = data;
359 void I286::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
361 cpu_state *cpustate = (cpu_state *)opaque;
362 my_stprintf_s(buffer, buffer_len,
363 _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]\nClocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
364 cpustate->regs.w[AX], cpustate->regs.w[BX], cpustate->regs.w[CX], cpustate->regs.w[DX], cpustate->regs.w[SP], cpustate->regs.w[BP], cpustate->regs.w[SI], cpustate->regs.w[DI],
365 cpustate->sregs[DS], cpustate->sregs[ES], cpustate->sregs[SS], cpustate->sregs[CS], cpustate->pc - cpustate->base[CS],
366 OF ? _T('O') : _T('-'), DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
367 SF ? _T('S') : _T('-'), ZF ? _T('Z') : _T('-'), AF ? _T('A') : _T('-'), PF ? _T('P') : _T('-'), CF ? _T('C') : _T('-'),
368 cpustate->total_icount, cpustate->total_icount - cpustate->prev_total_icount,
369 get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame());
370 cpustate->prev_total_icount = cpustate->total_icount;
373 int I286::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
375 cpu_state *cpustate = (cpu_state *)opaque;
376 UINT64 eip = pc - cpustate->base[CS];
378 for(int i = 0; i < 16; i++) {
380 ops[i] = d_mem->read_data8w(pc + i, &wait);
385 return CPU_DISASSEMBLE_CALL(nec_generic) & DASMFLAG_LENGTHMASK;
387 return CPU_DISASSEMBLE_CALL(x86_16) & DASMFLAG_LENGTHMASK;
393 void I286::set_address_mask(uint32_t mask)
395 cpu_state *cpustate = (cpu_state *)opaque;
396 cpustate->amask = mask;
399 uint32_t I286::get_address_mask()
401 cpu_state *cpustate = (cpu_state *)opaque;
402 return cpustate->amask;
405 void I286::set_shutdown_flag(int shutdown)
407 cpu_state *cpustate = (cpu_state *)opaque;
408 cpustate->shutdown = shutdown;
411 int I286::get_shutdown_flag()
413 cpu_state *cpustate = (cpu_state *)opaque;
414 return cpustate->shutdown;
418 #define STATE_VERSION 4
420 bool I286::process_state(FILEIO* state_fio, bool loading)
422 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
425 if(!state_fio->StateCheckInt32(this_device_id)) {
428 state_fio->StateBuffer(opaque, sizeof(cpu_state), 1);
432 cpu_state *cpustate = (cpu_state *)opaque;
433 cpustate->pic = d_pic;
434 cpustate->program = d_mem;
436 #ifdef I86_PSEUDO_BIOS
437 cpustate->bios = d_bios;
439 #ifdef SINGLE_MODE_DMA
440 cpustate->dma = d_dma;
444 cpustate->debugger = d_debugger;
445 cpustate->program_stored = d_mem;
446 cpustate->io_stored = d_io;
447 cpustate->prev_total_icount = cpustate->total_icount;
453 bool I286::process_state(FILEIO* state_fio, bool loading)
455 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
458 if(!state_fio->StateCheckInt32(this_device_id)) {
461 state_fio->StateBuffer(opaque, sizeof(cpu_state), 1);
465 cpu_state *cpustate = (cpu_state *)opaque;
466 cpustate->pic = d_pic;
467 cpustate->program = d_mem;
469 #ifdef I86_PSEUDO_BIOS
470 cpustate->bios = d_bios;
472 #ifdef SINGLE_MODE_DMA
473 cpustate->dma = d_dma;
477 cpustate->debugger = d_debugger;
478 cpustate->program_stored = d_mem;
479 cpustate->io_stored = d_io;
480 cpustate->prev_total_icount = cpustate->total_icount;