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 = 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;
207 int Z80::run(int clock)
210 if(extra_icount > 0) {
211 extra_tmp_count += extra_icount;
216 #ifdef SINGLE_MODE_DMA
222 int passed_icount = max(1, extra_icount);
223 // this is main cpu, icount is not used
224 /*icount = */extra_icount = 0;
225 total_icount += passed_icount;
229 return passed_icount;
231 // run only one opcode
232 //#ifdef USE_DEBUGGER
233 total_icount += extra_icount;
235 icount = -extra_icount;
243 int first_icount = icount;
244 //#ifdef USE_DEBUGGER
245 total_icount += extra_icount;
247 icount -= extra_icount;
255 #ifdef SINGLE_MODE_DMA
261 // run cpu while given clocks
262 while(icount > 0 && !busreq) {
267 // if busreq is raised, spin cpu while remained clock
268 if(icount > 0 && busreq) {
269 //#ifdef USE_DEBUGGER
270 total_icount += icount;
274 return first_icount - icount;
279 void Z80::run_one_opecode()
283 bool now_debugging = d_debugger->now_debugging;
285 d_debugger->check_break_points(PC);
286 if(d_debugger->now_suspended) {
288 d_debugger->now_waiting = true;
289 while(d_debugger->now_debugging && d_debugger->now_suspended) {
292 d_debugger->now_waiting = false;
294 if(d_debugger->now_debugging) {
295 d_mem = d_io = d_debugger;
297 now_debugging = false;
300 after_halt = after_ei = false;
307 F &= ~PF; // reset parity flag after LD A,I or LD A,R
310 #ifdef SINGLE_MODE_DMA
320 if(!d_debugger->now_going) {
321 d_debugger->now_suspended = true;
323 d_mem = d_mem_stored;
328 after_halt = after_ei = false;
332 d_debugger->add_cpu_trace(PC);
333 int first_icount = icount;
335 icount -= extra_icount;
337 total_icount += first_icount - icount;
340 F &= ~PF; // reset parity flag after LD A,I or LD A,R
343 #ifdef SINGLE_MODE_DMA
355 // ei: run next opecode
358 bool now_debugging = d_debugger->now_debugging;
360 d_debugger->check_break_points(PC);
361 if(d_debugger->now_suspended) {
363 d_debugger->now_waiting = true;
364 while(d_debugger->now_debugging && d_debugger->now_suspended) {
367 d_debugger->now_waiting = false;
369 if(d_debugger->now_debugging) {
370 d_mem = d_io = d_debugger;
372 now_debugging = false;
382 F &= ~PF; // reset parity flag after LD A,I or LD A,R
385 #ifdef SINGLE_MODE_DMA
390 if(d_pic != NULL) d_pic->notify_intr_ei();
394 if(!d_debugger->now_going) {
395 d_debugger->now_suspended = true;
397 d_mem = d_mem_stored;
406 d_debugger->add_cpu_trace(PC);
407 int first_icount = icount;
409 icount -= extra_icount;
411 total_icount += first_icount - icount;
414 F &= ~PF; // reset parity flag after LD A,I or LD A,R
417 #ifdef SINGLE_MODE_DMA
422 if(d_pic != NULL) d_pic->notify_intr_ei();
429 icount -= extra_icount;
434 void Z80::check_interrupt()
437 int first_icount = icount;
441 if(intr_req_bit & NMI_REQ_BIT) {
448 intr_req_bit &= ~NMI_REQ_BIT;
450 } else if(has_nsc800) {
451 if((intr_req_bit & 1) && (icr & 1)) {
455 if(d_pic != NULL) { // OK?
456 PCD = WZ = d_pic->get_intr_ack() & 0xffff;
458 PCD = WZ = (PCD & 0xff00) | 0xcd;
460 icount -= cc_op[0xcd] + cc_ex[0xff];
463 } else if((intr_req_bit & 8) && (icr & 8)) {
468 icount -= cc_op[0xff] + cc_ex[0xff];
471 } else if((intr_req_bit & 4) && (icr & 4)) {
476 icount -= cc_op[0xff] + cc_ex[0xff];
479 } else if((intr_req_bit & 2) && (icr & 2)) {
484 icount -= cc_op[0xff] + cc_ex[0xff];
488 } else { // Normal Z80
493 uint32_t vector = 0xcd;
494 if(d_pic != NULL) vector = d_pic->get_intr_ack();
496 // mode 0 (support NOP/JMP/CALL/RST only)
497 switch(vector & 0xff) {
498 case 0x00: break; // NOP
499 case 0xc3: PCD = vector >> 8; break; // JMP
500 case 0xcd: PUSH(pc); PCD = vector >> 8; break; // CALL
501 case 0xc7: PUSH(pc); PCD = 0x0000; break; // RST 00H
502 case 0xcf: PUSH(pc); PCD = 0x0008; break; // RST 08H
503 case 0xd7: PUSH(pc); PCD = 0x0010; break; // RST 10H
504 case 0xdf: PUSH(pc); PCD = 0x0018; break; // RST 18H
505 case 0xe7: PUSH(pc); PCD = 0x0020; break; // RST 20H
506 case 0xef: PUSH(pc); PCD = 0x0028; break; // RST 28H
507 case 0xf7: PUSH(pc); PCD = 0x0030; break; // RST 30H
508 case 0xff: PUSH(pc); PCD = 0x0038; break; // RST 38H
510 icount -= cc_op[vector & 0xff] + cc_ex[0xff];
515 icount -= cc_op[0xff] + cc_ex[0xff];
519 RM16((vector & 0xff) | (I << 8), &pc);
520 icount -= cc_op[0xcd] + cc_ex[0xff];
526 intr_req_bit &= intr_pend_bit;
532 //#ifdef USE_DEBUGGER
533 total_icount += first_icount - icount;
538 void Z80::write_debug_data8(uint32_t addr, uint32_t data)
541 d_mem_stored->write_data8w(addr, data, &wait);
544 uint32_t Z80::read_debug_data8(uint32_t addr)
547 return d_mem_stored->read_data8w(addr, &wait);
550 void Z80::write_debug_io8(uint32_t addr, uint32_t data)
553 d_io_stored->write_io8w(addr, data, &wait);
556 uint32_t Z80::read_debug_io8(uint32_t addr)
559 return d_io_stored->read_io8w(addr, &wait);
564 extern int z80_dasm_main(uint32_t pc, _TCHAR *buffer, size_t buffer_len, symbol_t *first_symbol);
566 extern uint8_t z80_dasm_ops[4];
567 extern int z80_dasm_ptr;
570 int Z80::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
572 for(int i = 0; i < 4; i++) {
574 z80_dasm_ops[i] = d_mem_stored->read_data8w(pc + i, &wait);
576 return z80_dasm_main(pc, buffer, buffer_len, d_debugger->first_symbol);