2 Skelton for retropc emulator
5 Author : Takeda.Toshiya
16 #if defined(HAS_UPD7810)
17 #define CPU_MODEL upd7810
18 #elif defined(HAS_UPD7807)
19 #define CPU_MODEL upd7807
20 #elif defined(HAS_UPD7801)
21 #define CPU_MODEL upd7801
22 #elif defined(HAS_UPD78C05)
23 #define CPU_MODEL upd78c05
24 #elif defined(HAS_UPD78C06)
25 #define CPU_MODEL upd78c06
26 #elif defined(HAS_UPD7907)
27 #define CPU_MODEL upd7907
30 /* ----------------------------------------------------------------------------
32 ---------------------------------------------------------------------------- */
37 /*****************************************************************************/
38 /* src/emu/devcpu.h */
40 // CPU interface functions
41 #define CPU_INIT_NAME(name) cpu_init_##name
42 #define CPU_INIT(name) void* CPU_INIT_NAME(name)()
43 #define CPU_INIT_CALL(name) CPU_INIT_NAME(name)()
45 #define CPU_RESET_NAME(name) cpu_reset_##name
46 #define CPU_RESET(name) void CPU_RESET_NAME(name)(upd7810_state *cpustate)
47 #define CPU_RESET_CALL(name) CPU_RESET_NAME(name)(cpustate)
49 #define CPU_EXECUTE_NAME(name) cpu_execute_##name
50 #define CPU_EXECUTE(name) int CPU_EXECUTE_NAME(name)(upd7810_state *cpustate)
51 #define CPU_EXECUTE_CALL(name) CPU_EXECUTE_NAME(name)(cpustate)
53 #define CPU_DISASSEMBLE_NAME(name) cpu_disassemble_##name
54 #define CPU_DISASSEMBLE(name) int CPU_DISASSEMBLE_NAME(name)(_TCHAR *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, symbol_t *first_symbol)
55 #define CPU_DISASSEMBLE_CALL(name) CPU_DISASSEMBLE_NAME(name)(buffer, pc, oprom, oprom, d_debugger->first_symbol)
57 /*****************************************************************************/
58 /* src/emu/didisasm.h */
60 // Disassembler constants
61 const UINT32 DASMFLAG_SUPPORTED = 0x80000000; // are disassembly flags supported?
62 const UINT32 DASMFLAG_STEP_OUT = 0x40000000; // this instruction should be the end of a step out sequence
63 const UINT32 DASMFLAG_STEP_OVER = 0x20000000; // this instruction should be stepped over by setting a breakpoint afterwards
64 const UINT32 DASMFLAG_OVERINSTMASK = 0x18000000; // number of extra instructions to skip when stepping over
65 const UINT32 DASMFLAG_OVERINSTSHIFT = 27; // bits to shift after masking to get the value
66 const UINT32 DASMFLAG_LENGTHMASK = 0x0000ffff; // the low 16-bits contain the actual length
68 /*****************************************************************************/
69 /* src/emu/diexec.h */
74 CLEAR_LINE = 0, // clear (a fired or held) line
75 ASSERT_LINE // assert an interrupt immediately
88 #define fatalerror(...)
93 #include "mame/emu/cpu/upd7810/upd7810.c"
96 #include "mame/emu/cpu/upd7810/7810dasm.c"
101 void UPD7810::initialize()
103 DEVICE::initialize();
104 opaque = CPU_INIT_CALL(upd7810);
106 upd7810_state *cpustate = (upd7810_state *)opaque;
107 #if defined(HAS_UPD7810)
108 cpustate->config.type = TYPE_7810;
109 #elif defined(HAS_UPD7807)
110 cpustate->config.type = TYPE_7807;
111 #elif defined(HAS_UPD7801)
112 cpustate->config.type = TYPE_7801;
113 #elif defined(HAS_UPD78C05)
114 cpustate->config.type = TYPE_78C05;
115 #elif defined(HAS_UPD78C06)
116 cpustate->config.type = TYPE_78C06;
117 #elif defined(HAS_UPD7907)
118 cpustate->config.type = TYPE_78C06;
120 cpustate->program = d_mem;
122 cpustate->outputs_to = (void*)&outputs_to;
123 cpustate->outputs_txd = (void*)&outputs_txd;
126 cpustate->debugger = d_debugger;
127 cpustate->program_stored = d_mem;
128 cpustate->io_stored = d_io;
130 d_debugger->set_context_mem(d_mem);
131 d_debugger->set_context_io(d_io);
135 void UPD7810::release()
140 void UPD7810::reset()
142 upd7810_state *cpustate = (upd7810_state *)opaque;
144 CPU_RESET_CALL(CPU_MODEL);
146 cpustate->program = d_mem;
148 cpustate->outputs_to = (void*)&outputs_to;
149 cpustate->outputs_txd = (void*)&outputs_txd;
152 cpustate->debugger = d_debugger;
153 cpustate->program_stored = d_mem;
154 cpustate->io_stored = d_io;
160 int UPD7810::run(int clock)
162 upd7810_state *cpustate = (upd7810_state *)opaque;
172 // run only one opcode
173 return run_one_opecode();
177 int first_icount = icount;
179 // run cpu while given clocks
180 while(icount > 0 && !busreq) {
181 icount -= run_one_opecode();
183 // if busreq is raised, spin cpu while remained clock
184 if(icount > 0 && busreq) {
186 total_icount += icount;
190 return first_icount - icount;
194 int UPD7810::run_one_opecode()
197 upd7810_state *cpustate = (upd7810_state *)opaque;
198 d_debugger->add_cpu_trace(cpustate->pc.w.l);
200 int passed_icount = CPU_EXECUTE_CALL(upd7810);
202 total_icount += passed_icount;
204 return passed_icount;
207 void UPD7810::write_signal(int id, uint32_t data, uint32_t mask)
209 upd7810_state *cpustate = (upd7810_state *)opaque;
212 case SIG_UPD7810_INTF1:
213 set_irq_line(cpustate, UPD7810_INTF1, (data & mask) ? ASSERT_LINE : CLEAR_LINE);
215 case SIG_UPD7810_INTF2:
216 set_irq_line(cpustate, UPD7810_INTF2, (data & mask) ? ASSERT_LINE : CLEAR_LINE);
218 case SIG_UPD7810_INTF0:
219 set_irq_line(cpustate, UPD7810_INTF0, (data & mask) ? ASSERT_LINE : CLEAR_LINE);
221 case SIG_UPD7810_INTFE1:
222 set_irq_line(cpustate, UPD7810_INTFE1, (data & mask) ? ASSERT_LINE : CLEAR_LINE);
224 case SIG_UPD7810_NMI:
225 set_irq_line(cpustate, INPUT_LINE_NMI, (data & mask) ? ASSERT_LINE : CLEAR_LINE);
228 busreq = ((data & mask) != 0);
233 uint32_t UPD7810::get_pc()
235 upd7810_state *cpustate = (upd7810_state *)opaque;
236 return cpustate->ppc.w.l;
239 uint32_t UPD7810::get_next_pc()
241 upd7810_state *cpustate = (upd7810_state *)opaque;
242 return cpustate->pc.w.l;
246 void UPD7810::write_debug_data8(uint32_t addr, uint32_t data)
249 d_mem->write_data8w(addr, data, &wait);
252 uint32_t UPD7810::read_debug_data8(uint32_t addr)
255 return d_mem->read_data8w(addr, &wait);
258 void UPD7810::write_debug_io8(uint32_t addr, uint32_t data)
261 d_io->write_io8w(addr, data, &wait);
264 uint32_t UPD7810::read_debug_io8(uint32_t addr) {
266 return d_io->read_io8w(addr, &wait);
269 bool UPD7810::write_debug_reg(const _TCHAR *reg, uint32_t data)
271 upd7810_state *cpustate = (upd7810_state *)opaque;
273 if(_tcsicmp(reg, _T("PC")) == 0) {
275 } else if(_tcsicmp(reg, _T("SP")) == 0) {
277 } else if(_tcsicmp(reg, _T("VA")) == 0) {
279 } else if(_tcsicmp(reg, _T("BC")) == 0) {
281 } else if(_tcsicmp(reg, _T("DE")) == 0) {
283 } else if(_tcsicmp(reg, _T("HL")) == 0) {
285 } else if(_tcsicmp(reg, _T("V")) == 0) {
287 } else if(_tcsicmp(reg, _T("A")) == 0) {
289 } else if(_tcsicmp(reg, _T("B")) == 0) {
291 } else if(_tcsicmp(reg, _T("C")) == 0) {
293 } else if(_tcsicmp(reg, _T("D")) == 0) {
295 } else if(_tcsicmp(reg, _T("E")) == 0) {
297 } else if(_tcsicmp(reg, _T("H")) == 0) {
299 } else if(_tcsicmp(reg, _T("L")) == 0) {
301 } else if(_tcsicmp(reg, _T("VA'")) == 0) {
303 } else if(_tcsicmp(reg, _T("BC'")) == 0) {
305 } else if(_tcsicmp(reg, _T("DE'")) == 0) {
307 } else if(_tcsicmp(reg, _T("HL'")) == 0) {
309 } else if(_tcsicmp(reg, _T("V'")) == 0) {
311 } else if(_tcsicmp(reg, _T("A'")) == 0) {
313 } else if(_tcsicmp(reg, _T("B'")) == 0) {
315 } else if(_tcsicmp(reg, _T("C'")) == 0) {
317 } else if(_tcsicmp(reg, _T("D'")) == 0) {
319 } else if(_tcsicmp(reg, _T("E'")) == 0) {
321 } else if(_tcsicmp(reg, _T("H'")) == 0) {
323 } else if(_tcsicmp(reg, _T("L'")) == 0) {
331 void UPD7810::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
334 VA = 0000 BC = 0000 DE = 0000 HL = 0000 PSW= 00 [Z SK HC L1 L0 CY]
335 VA'= 0000 BC'= 0000 DE'= 0000 HL'= 0000 SP = 0000 PC = 0000
336 (BC)= 0000 (DE)=0000 (HL)= 0000 (SP)= 0000 <DI>
337 Clocks = 0 (0) Since Scanline = 0/0 (0/0)
339 upd7810_state *cpustate = (upd7810_state *)opaque;
341 my_stprintf_s(buffer, buffer_len,
342 _T("VA = %04X BC = %04X DE = %04X HL = %04X PSW= %02x [%s %s %s %s %s %s]\nVA'= %04X BC'= %04X DE'= %04X HL'= %04X SP = %04X PC = %04X\n (BC)= %04X (DE)=%04X (HL)= %04X (SP)= %04X <%s>\nClocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
344 (PSW & Z) ? _T("Z") : _T("-"), (PSW & SK) ? _T("SK") : _T("--"), (PSW & HC) ? _T("HC") : _T("--"), (PSW & L1) ? _T("L1") : _T("--"), (PSW & L0) ? _T("L0") : _T("--"), (PSW & CY) ? _T("CY") : _T("--"),
345 VA2, BC2, DE2, HL2, SP, PC,
346 d_mem->read_data16w(BC, &wait), d_mem->read_data16w(DE, &wait), d_mem->read_data16w(HL, &wait), d_mem->read_data16w(SP, &wait),
347 IFF ? _T("EI") : _T("DI"),
348 total_icount, total_icount - prev_total_icount,
349 get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame());
350 prev_total_icount = total_icount;
355 int UPD7810::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
358 uint8_t *opram = oprom;
360 for(int i = 0; i < 8; i++) {
362 oprom[i] = d_mem->read_data8w(pc + i, &wait);
364 return CPU_DISASSEMBLE_CALL(CPU_MODEL) & DASMFLAG_LENGTHMASK;
368 #define STATE_VERSION 4
370 #include "../statesub.h"
372 void UPD7810::decl_state_cpustate()
374 upd7810_state *cpustate = (upd7810_state *)opaque;
376 DECL_STATE_ENTRY_PAIR((cpustate->ppc)); /* previous program counter */
377 DECL_STATE_ENTRY_PAIR((cpustate->pc)); /* program counter */
378 DECL_STATE_ENTRY_PAIR((cpustate->sp)); /* stack pointer */
379 DECL_STATE_ENTRY_UINT8((cpustate->op)); /* opcode */
380 DECL_STATE_ENTRY_UINT8((cpustate->op2)); /* opcode part 2 */
381 DECL_STATE_ENTRY_UINT8((cpustate->iff)); /* interrupt enable flip flop */
382 DECL_STATE_ENTRY_UINT8((cpustate->softi));
383 DECL_STATE_ENTRY_UINT8((cpustate->psw)); /* processor status word */
384 DECL_STATE_ENTRY_PAIR((cpustate->ea)); /* extended accumulator */
385 DECL_STATE_ENTRY_PAIR((cpustate->va)); /* accumulator + vector register */
386 DECL_STATE_ENTRY_PAIR((cpustate->bc)); /* 8bit B and C registers / 16bit BC register */
387 DECL_STATE_ENTRY_PAIR((cpustate->de)); /* 8bit D and E registers / 16bit DE register */
388 DECL_STATE_ENTRY_PAIR((cpustate->hl)); /* 8bit H and L registers / 16bit HL register */
389 DECL_STATE_ENTRY_PAIR((cpustate->ea2)); /* alternate register set */
390 DECL_STATE_ENTRY_PAIR((cpustate->va2));
391 DECL_STATE_ENTRY_PAIR((cpustate->bc2));
392 DECL_STATE_ENTRY_PAIR((cpustate->de2));
393 DECL_STATE_ENTRY_PAIR((cpustate->hl2));
394 DECL_STATE_ENTRY_PAIR((cpustate->cnt)); /* 8 bit timer counter */
395 DECL_STATE_ENTRY_PAIR((cpustate->tm)); /* 8 bit timer 0/1 comparator inputs */
396 DECL_STATE_ENTRY_PAIR((cpustate->ecnt)); /* timer counter register / capture register */
397 DECL_STATE_ENTRY_PAIR((cpustate->etm)); /* timer 0/1 comparator inputs */
398 DECL_STATE_ENTRY_UINT8((cpustate->ma)); /* port A input or output mask */
399 DECL_STATE_ENTRY_UINT8((cpustate->mb)); /* port B input or output mask */
400 DECL_STATE_ENTRY_UINT8((cpustate->mcc)); /* port C control/port select */
401 DECL_STATE_ENTRY_UINT8((cpustate->mc)); /* port C input or output mask */
402 DECL_STATE_ENTRY_UINT8((cpustate->mm)); /* memory mapping */
403 DECL_STATE_ENTRY_UINT8((cpustate->mf)); /* port F input or output mask */
404 DECL_STATE_ENTRY_UINT8((cpustate->tmm)); /* timer 0 and timer 1 operating parameters */
405 DECL_STATE_ENTRY_UINT8((cpustate->etmm)); /* 16-bit multifunction timer/event counter */
406 DECL_STATE_ENTRY_UINT8((cpustate->eom)); /* 16-bit timer/event counter output control */
407 DECL_STATE_ENTRY_UINT8((cpustate->sml)); /* serial interface parameters low */
408 DECL_STATE_ENTRY_UINT8((cpustate->smh)); /* -"- high */
409 DECL_STATE_ENTRY_UINT8((cpustate->anm)); /* analog to digital converter operating parameters */
410 DECL_STATE_ENTRY_UINT8((cpustate->mkl)); /* interrupt mask low */
411 DECL_STATE_ENTRY_UINT8((cpustate->mkh)); /* -"- high */
412 DECL_STATE_ENTRY_UINT8((cpustate->zcm)); /* bias circuitry for ac zero-cross detection */
413 DECL_STATE_ENTRY_UINT8((cpustate->pa_in)); /* port A,B,C,D,F inputs */
414 DECL_STATE_ENTRY_UINT8((cpustate->pb_in));
415 DECL_STATE_ENTRY_UINT8((cpustate->pc_in));
416 DECL_STATE_ENTRY_UINT8((cpustate->pd_in));
417 DECL_STATE_ENTRY_UINT8((cpustate->pf_in));
418 DECL_STATE_ENTRY_UINT8((cpustate->pa_out)); /* port A,B,C,D,F outputs */
419 DECL_STATE_ENTRY_UINT8((cpustate->pb_out));
420 DECL_STATE_ENTRY_UINT8((cpustate->pc_out));
421 DECL_STATE_ENTRY_UINT8((cpustate->pd_out));
422 DECL_STATE_ENTRY_UINT8((cpustate->pf_out));
423 DECL_STATE_ENTRY_UINT8((cpustate->cr0)); /* analog digital conversion register 0 */
424 DECL_STATE_ENTRY_UINT8((cpustate->cr1)); /* analog digital conversion register 1 */
425 DECL_STATE_ENTRY_UINT8((cpustate->cr2)); /* analog digital conversion register 2 */
426 DECL_STATE_ENTRY_UINT8((cpustate->cr3)); /* analog digital conversion register 3 */
427 DECL_STATE_ENTRY_UINT8((cpustate->txb)); /* transmitter buffer */
428 DECL_STATE_ENTRY_UINT8((cpustate->rxb)); /* receiver buffer */
429 DECL_STATE_ENTRY_UINT8((cpustate->txd)); /* port C control line states */
430 DECL_STATE_ENTRY_UINT8((cpustate->rxd));
431 DECL_STATE_ENTRY_UINT8((cpustate->sck));
432 DECL_STATE_ENTRY_UINT8((cpustate->ti));
433 DECL_STATE_ENTRY_UINT8((cpustate->to));
434 DECL_STATE_ENTRY_UINT8((cpustate->ci));
435 DECL_STATE_ENTRY_UINT8((cpustate->co0));
436 DECL_STATE_ENTRY_UINT8((cpustate->co1));
437 DECL_STATE_ENTRY_UINT16((cpustate->irr)); /* interrupt request register */
438 DECL_STATE_ENTRY_UINT16((cpustate->itf)); /* interrupt test flag register */
439 DECL_STATE_ENTRY_INT32((cpustate->int1)); /* keep track of current int1 state. Needed for 7801 irq checking. */
440 DECL_STATE_ENTRY_INT32((cpustate->int2)); /* keep track to current int2 state. Needed for 7801 irq checking. */
442 /* internal helper variables */
443 DECL_STATE_ENTRY_UINT16((cpustate->txs)); /* transmitter shift register */
444 DECL_STATE_ENTRY_UINT16((cpustate->rxs)); /* receiver shift register */
445 DECL_STATE_ENTRY_UINT8((cpustate->txcnt)); /* transmitter shift register bit count */
446 DECL_STATE_ENTRY_UINT8((cpustate->rxcnt)); /* receiver shift register bit count */
447 DECL_STATE_ENTRY_UINT8((cpustate->txbuf)); /* transmitter buffer was written */
448 DECL_STATE_ENTRY_INT32((cpustate->ovc0)); /* overflow counter for timer 0 ((for clock div 12/384) */
449 DECL_STATE_ENTRY_INT32((cpustate->ovc1)); /* overflow counter for timer 0 (for clock div 12/384) */
450 DECL_STATE_ENTRY_INT32((cpustate->ovce)); /* overflow counter for ecnt */
451 DECL_STATE_ENTRY_INT32((cpustate->ovcf)); /* overflow counter for fixed clock div 3 mode */
452 DECL_STATE_ENTRY_INT32((cpustate->ovcs)); /* overflow counter for serial I/O */
453 DECL_STATE_ENTRY_INT32((cpustate->ovcsio));
454 DECL_STATE_ENTRY_UINT8((cpustate->edges)); /* rising/falling edge flag for serial I/O */
455 // const struct opcode_s *opXX; /* opcode table */
456 // const struct opcode_s *op48;
457 // const struct opcode_s *op4C;
458 // const struct opcode_s *op4D;
459 // const struct opcode_s *op60;
460 // const struct opcode_s *op64;
461 // const struct opcode_s *op70;
462 // const struct opcode_s *op74;
463 // void (*handle_timers)(upd7810_state *cpustate, int cycles);
464 // UPD7810_CONFIG config;
465 // device_irq_acknowledge_callback irq_callback;
466 // legacy_cpu_device *device;
470 // void *outputs_txd;
471 //#ifdef USE_DEBUGGER
473 // DEBUGGER *debugger;
474 // DEVICE *program_stored;
475 // DEVICE *io_stored;
477 DECL_STATE_ENTRY_INT32((cpustate->icount));
481 void UPD7810::decl_state()
483 enter_decl_state(STATE_VERSION);
485 decl_state_cpustate();
487 DECL_STATE_ENTRY_UINT64(total_icount);
489 DECL_STATE_ENTRY_INT32(icount);
490 DECL_STATE_ENTRY_BOOL(busreq);
495 void UPD7810::save_state(FILEIO* state_fio)
497 if(state_entry != NULL) {
498 state_entry->save_state(state_fio);
501 // state_fio->FputUint32(STATE_VERSION);
502 // state_fio->FputInt32(this_device_id);
504 // state_fio->Fwrite(opaque, sizeof(upd7810_state), 1);
505 //#ifdef USE_DEBUGGER
506 // state_fio->FputUint64(total_icount);
508 // state_fio->FputInt32(icount);
509 // state_fio->FputBool(busreq);
512 bool UPD7810::load_state(FILEIO* state_fio)
515 if(state_entry != NULL) {
516 mb = state_entry->load_state(state_fio);
518 if(!mb) return false;
520 // if(state_fio->FgetUint32() != STATE_VERSION) {
523 // if(state_fio->FgetInt32() != this_device_id) {
526 // state_fio->Fread(opaque, sizeof(upd7810_state), 1);
528 //total_icount = prev_total_icount = state_fio->FgetUint64();
529 prev_total_icount = total_icount;
531 //icount = state_fio->FgetInt32();
532 //busreq = state_fio->FgetBool();
535 upd7810_state *cpustate = (upd7810_state *)opaque;
536 cpustate->program = d_mem;
538 cpustate->outputs_to = (void*)&outputs_to;
539 cpustate->outputs_txd = (void*)&outputs_txd;
542 cpustate->debugger = d_debugger;
543 cpustate->program_stored = d_mem;
544 cpustate->io_stored = d_io;