int TraceCpuStep(Z80EX_CONTEXT *cpu) { CpuTrace_Log(); cpuTrace_intReq = 0; cpuTrace_dT = z80ex_step(cpu); return cpuTrace_dT; }
static void xep128_emulation ( void ) { emu_timekeeping_check(); for (;;) { int t; if (XEMU_UNLIKELY(paused && !z80ex.prefix)) { /* Paused is non-zero for special cases, like pausing emulator :) or single-step execution mode We only do this if z80ex.prefix is non-zero, ie not in the "middle" of a prefixed Z80 opcode or so ... */ __emu_one_frame(312, 0); // keep UI stuffs (and some timing) intact ... with a faked about 312 scanline (normal frame) timing needed ... return; } if (XEMU_UNLIKELY(nmi_pending)) { t = z80ex_nmi(); DEBUG("NMI: %d" NL, t); if (t) nmi_pending = 0; } else t = 0; //if (XEMU_UNLIKELY((dave_int_read & 0xAA) && t == 0)) { if ((dave_int_read & 0xAA) && t == 0) { t = z80ex_int(); if (t) DEBUG("CPU: int and accepted = %d" NL, t); } else t = 0; if (XEMU_LIKELY(!t)) t = z80ex_step(); cpu_cycles_for_dave_sync += t; //DEBUG("DAVE: SYNC: CPU cycles = %d, Dave sync val = %d, limit = %d" NL, t, cpu_cycles_for_dave_sync, cpu_cycles_per_dave_tick); while (cpu_cycles_for_dave_sync >= cpu_cycles_per_dave_tick) { dave_tick(); cpu_cycles_for_dave_sync -= cpu_cycles_per_dave_tick; } balancer += t * SCALER; //DEBUG("%s [balance=%f t=%d]" NL, buffer, balancer, t); while (balancer >= 0.5) { nick_render_slot(); balancer -= 1.0; if (XEMU_UNLIKELY(emu_one_frame_rasters != -1)) { __emu_one_frame( emu_one_frame_rasters, emu_one_frame_frameskip ); emu_one_frame_rasters = -1; return; } } //DEBUG("[balance=%f t=%d]" NL, balancer, t); } }
// main cycle void zx_life( int *running ) { while ( *running ) { while ( zxcpu_tstates_main < zxcpu_tstates_frame ) { if ((zxcpu_tstates_main >= zxcpu_int_start) && (zxcpu_tstates_main < zxcpu_int_end)) zxcpu_tstates_main += z80ex_int(zxcpu); zxcpu_tstates_main += z80ex_step(zxcpu); } if ( !zx_frame_new ) zx_frame_end(); zx_frame_new = 0; //zxcpu_tstates_main %= zxcpu_tstates_frame; while ( zxcpu_tstates_main >= zxcpu_tstates_frame ) \ zxcpu_tstates_main -= zxcpu_tstates_frame; } }
uint32_t Z80CPUBase::execute(uint32_t instructions) { if (m_context == 0) return 0; uint32_t Tstates = 0; while((instructions > 0) && (!m_isHalted)) { if (m_intPending) { if (z80ex_int(m_context) != 0) { m_intPending = false; } } Tstates += z80ex_step(m_context); instructions--; } return Tstates; }
int main() { Z80EX_CONTEXT *cpu; MACHINE machine; load("a.bin", machine.mem, 0xffff); cpu = z80ex_create( read_memory, &machine, write_memory, &machine, read_port, &machine, write_port, &machine, interrupt_vector_read, &machine ); for(int i = 0; i < 64; i++) { z80ex_step(cpu); } return 0; }
/*maskable interrupt*/ int z80ex_int(void) { Z80EX_WORD inttemp; Z80EX_BYTE iv; unsigned long tt; /* If the INT line is low and IFF1 is set, and there's no opcode executing just now, a maskable interrupt is accepted, whether or not the last INT routine has finished */ if ( !IFF1 || z80ex.noint_once || z80ex.doing_opcode || z80ex.prefix #ifdef Z80EX_Z180_SUPPORT || z80ex.internal_int_disable #endif ) return 0; z80ex.tstate = 0; z80ex.op_tstate = 0; if (z80ex.halted) { /* so we met an interrupt... stop waiting */ PC++; z80ex.halted = 0; } /* When an INT is accepted, both IFF1 and IFF2 are cleared, preventing another interrupt from occurring which would end up as an infinite loop */ IFF1 = IFF2 = 0; /* original (NMOS) zilog z80 bug: */ /* If a LD A,I or LD A,R (which copy IFF2 to the P/V flag) is interrupted, then the P/V flag is reset, even if interrupts were enabled beforehand. */ /* (this bug was fixed in CMOS version of z80) */ if (z80ex.reset_PV_on_int) { F = (F & ~FLAG_P); } z80ex.reset_PV_on_int = 0; z80ex.int_vector_req = 1; z80ex.doing_opcode = 1; switch (IM) { case IM0: /* note: there's no need to do R++ and WAITs here, it'll be handled by z80ex_step */ tt = z80ex_step(); while(z80ex.prefix) { /* this is not the end? */ tt+=z80ex_step(); } z80ex.tstate = tt; break; case IM1: R++; TSTATES(2); /* two extra wait-states */ /* An RST 38h is executed, no matter what value is put on the bus or what value the I register has. 13 t-states (2 extra + 11 for RST). */ opcodes_base[0xff](); /* RST 38 */ break; case IM2: R++; /* takes 19 clock periods to complete (seven to fetch the lower eight bits from the interrupting device, six to save the program counter, and six to obtain the jump address) */ iv=READ_OP(); T_WAIT_UNTIL(7); inttemp = (0x100 * I) + iv; PUSH(PC, 7, 10); READ_MEM(PCL, inttemp++, 13); READ_MEM(PCH, inttemp, 16); MEMPTR = PC; T_WAIT_UNTIL(19); break; } z80ex.doing_opcode = 0; z80ex.int_vector_req = 0; return z80ex.tstate; }