2 Skelton for retropc emulator
5 Author : Takeda.Toshiya
18 #ifndef CPU_START_ADDR
19 #define CPU_START_ADDR 0
22 #define NMI_REQ_BIT 0x80000000
91 // opecode definitions
93 #define ENTER_HALT() do { \
98 #define LEAVE_HALT() do { \
100 after_halt = false; \
106 #define POP(DR) do { \
111 #define PUSH(SR) do { \
117 Z80::Z80(VM_TEMPLATE* parent_vm, EMU* parent_emu) : Z80_BASE(parent_vm, parent_emu)
122 #ifdef Z80_PSEUDO_BIOS
123 has_pseudo_bios = true;
125 #ifdef SINGLE_MODE_DMA
126 has_single_mode_dma = true;
128 #ifdef Z80_MEMORY_WAIT
129 has_memory_wait = true;
134 #ifdef HAS_LDAIR_QUIRK
135 has_ldair_quirk = true;
143 void Z80::initialize()
145 Z80_BASE::initialize();
147 d_mem_stored = d_mem;
149 d_debugger->set_context_mem(d_mem);
150 d_debugger->set_context_io(d_io);
156 PCD = CPU_START_ADDR;
158 AFD = BCD = DED = HLD = 0;
159 IXD = IYD = 0xffff; /* IX and IY are FFFF after a reset! */
160 F = ZF; /* Zero flag is set */
163 af2.d = bc2.d = de2.d = hl2.d = 0;
166 im = iff1 = iff2 = icr = 0;
168 after_ei = after_ldair = false;
169 intr_req_bit = intr_pend_bit = 0;
171 icount = extra_icount = busreq_icount = 0;
174 void Z80::debugger_hook(void)
177 bool now_debugging = d_debugger->now_debugging;
179 d_debugger->check_break_points(PC);
180 if(d_debugger->now_suspended) {
182 d_debugger->now_waiting = true;
183 while(d_debugger->now_debugging && d_debugger->now_suspended) {
186 d_debugger->now_waiting = false;
188 if(d_debugger->now_debugging) {
191 now_debugging = false;
194 //d_debugger->add_cpu_trace(PC);
195 int first_icount = icount;
198 if(!d_debugger->now_going) {
199 d_debugger->now_suspended = true;
201 d_mem = d_mem_stored;
208 int Z80::run(int clock)
211 if(extra_icount > 0) {
212 extra_tmp_count += extra_icount;
215 // this is primary cpu
218 #ifdef SINGLE_MODE_DMA
224 int passed_icount = max(1, extra_icount);
225 // this is main cpu, icount is not used
226 /*icount = */extra_icount = 0;
227 total_icount += passed_icount;
231 return passed_icount;
233 // run only one opcode
234 if((extra_icount += busreq_icount) > 0) {
236 update_extra_event(extra_icount);
238 total_icount += extra_icount;
240 icount = -extra_icount;
241 extra_icount = busreq_icount = 0;
248 int first_icount = icount;
249 //#ifdef USE_DEBUGGER
250 total_icount += extra_icount;
252 icount -= extra_icount;
260 #ifdef SINGLE_MODE_DMA
266 // run cpu while given clocks
267 while(icount > 0 && !busreq) {
272 // if busreq is raised, spin cpu while remained clock
273 if(icount > 0 && busreq) {
274 //#ifdef USE_DEBUGGER
275 total_icount += icount;
279 return first_icount - icount;
284 void Z80::run_one_opecode()
288 bool now_debugging = d_debugger->now_debugging;
290 d_debugger->check_break_points(PC);
291 if(d_debugger->now_suspended) {
292 d_debugger->now_waiting = true;
293 emu->start_waiting_in_debugger();
294 while(d_debugger->now_debugging && d_debugger->now_suspended) {
295 emu->process_waiting_in_debugger();
297 emu->finish_waiting_in_debugger();
298 d_debugger->now_waiting = false;
300 if(d_debugger->now_debugging) {
301 d_mem = d_io = d_debugger;
303 now_debugging = false;
306 after_halt = after_ei = false;
313 F &= ~PF; // reset parity flag after LD A,I or LD A,R
316 #ifdef SINGLE_MODE_DMA
326 if(!d_debugger->now_going) {
327 d_debugger->now_suspended = true;
329 d_mem = d_mem_stored;
334 after_halt = after_ei = false;
338 d_debugger->add_cpu_trace(PC);
339 int first_icount = icount;
341 icount -= extra_icount;
343 total_icount += first_icount - icount;
346 F &= ~PF; // reset parity flag after LD A,I or LD A,R
349 #ifdef SINGLE_MODE_DMA
361 // ei: run next opecode
364 bool now_debugging = d_debugger->now_debugging;
366 d_debugger->check_break_points(PC);
367 if(d_debugger->now_suspended) {
368 d_debugger->now_waiting = true;
369 emu->start_waiting_in_debugger();
370 while(d_debugger->now_debugging && d_debugger->now_suspended) {
371 emu->process_waiting_in_debugger();
373 emu->finish_waiting_in_debugger();
374 d_debugger->now_waiting = false;
376 if(d_debugger->now_debugging) {
377 d_mem = d_io = d_debugger;
379 now_debugging = false;
389 F &= ~PF; // reset parity flag after LD A,I or LD A,R
392 #ifdef SINGLE_MODE_DMA
397 if(d_pic != NULL) d_pic->notify_intr_ei();
401 if(!d_debugger->now_going) {
402 d_debugger->now_suspended = true;
404 d_mem = d_mem_stored;
413 d_debugger->add_cpu_trace(PC);
414 int first_icount = icount;
416 icount -= extra_icount;
418 total_icount += first_icount - icount;
421 F &= ~PF; // reset parity flag after LD A,I or LD A,R
424 #ifdef SINGLE_MODE_DMA
429 if(d_pic != NULL) d_pic->notify_intr_ei();
436 icount -= extra_icount;
441 void Z80::check_interrupt()
444 int first_icount = icount;
448 if(intr_req_bit & NMI_REQ_BIT) {
455 intr_req_bit &= ~NMI_REQ_BIT;
457 } else if(has_nsc800) {
458 if((intr_req_bit & 1) && (icr & 1)) {
462 if(d_pic != NULL) { // OK?
463 PCD = WZ = d_pic->get_intr_ack() & 0xffff;
465 PCD = WZ = (PCD & 0xff00) | 0xcd;
467 icount -= cc_op[0xcd] + cc_ex[0xff];
470 } else if((intr_req_bit & 8) && (icr & 8)) {
475 icount -= cc_op[0xff] + cc_ex[0xff];
478 } else if((intr_req_bit & 4) && (icr & 4)) {
483 icount -= cc_op[0xff] + cc_ex[0xff];
486 } else if((intr_req_bit & 2) && (icr & 2)) {
491 icount -= cc_op[0xff] + cc_ex[0xff];
495 } else { // Normal Z80
500 uint32_t vector = 0xcd;
501 if(d_pic != NULL) vector = d_pic->get_intr_ack();
503 // mode 0 (support NOP/JMP/CALL/RST only)
504 switch(vector & 0xff) {
505 case 0x00: break; // NOP
506 case 0xc3: PCD = vector >> 8; break; // JMP
507 case 0xcd: PUSH(pc); PCD = vector >> 8; break; // CALL
508 case 0xc7: PUSH(pc); PCD = 0x0000; break; // RST 00H
509 case 0xcf: PUSH(pc); PCD = 0x0008; break; // RST 08H
510 case 0xd7: PUSH(pc); PCD = 0x0010; break; // RST 10H
511 case 0xdf: PUSH(pc); PCD = 0x0018; break; // RST 18H
512 case 0xe7: PUSH(pc); PCD = 0x0020; break; // RST 20H
513 case 0xef: PUSH(pc); PCD = 0x0028; break; // RST 28H
514 case 0xf7: PUSH(pc); PCD = 0x0030; break; // RST 30H
515 case 0xff: PUSH(pc); PCD = 0x0038; break; // RST 38H
517 icount -= cc_op[vector & 0xff] + cc_ex[0xff];
522 icount -= cc_op[0xff] + cc_ex[0xff];
526 RM16((vector & 0xff) | (I << 8), &pc);
527 icount -= cc_op[0xcd] + cc_ex[0xff];
533 intr_req_bit &= intr_pend_bit;
539 //#ifdef USE_DEBUGGER
540 total_icount += first_icount - icount;
545 void Z80::write_debug_data8(uint32_t addr, uint32_t data)
548 d_mem_stored->write_data8w(addr, data, &wait);
551 uint32_t Z80::read_debug_data8(uint32_t addr)
554 return d_mem_stored->read_data8w(addr, &wait);
557 void Z80::write_debug_io8(uint32_t addr, uint32_t data)
560 d_io_stored->write_io8w(addr, data, &wait);
563 uint32_t Z80::read_debug_io8(uint32_t addr)
566 return d_io_stored->read_io8w(addr, &wait);
571 extern int z80_dasm_main(uint32_t pc, _TCHAR *buffer, size_t buffer_len, symbol_t *first_symbol);
573 extern uint8_t z80_dasm_ops[4];
574 extern int z80_dasm_ptr;
577 int Z80::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
579 for(int i = 0; i < 4; i++) {
581 z80_dasm_ops[i] = d_mem_stored->read_data8w(pc + i, &wait);
583 return z80_dasm_main(pc, buffer, buffer_len, d_debugger->first_symbol);