Exemple #1
0
int TraceCpuStep(Z80EX_CONTEXT *cpu)
{
	CpuTrace_Log();
	cpuTrace_intReq = 0;
	cpuTrace_dT = z80ex_step(cpu);
	return cpuTrace_dT;
}
Exemple #2
0
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);
	}
}
Exemple #3
0
// 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;
    }
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
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;
}