Beispiel #1
0
/*non-maskable interrupt*/
int z80ex_nmi(void)
{
	if (z80ex.doing_opcode || z80ex.noint_once || z80ex.prefix) return 0;
	
	if (z80ex.halted) {
		/*so we met an interrupt... stop waiting*/
		PC++;
		z80ex.halted = 0;
	}
	
	z80ex.doing_opcode = 1;
	
	R++; /* accepting interrupt increases R by one */
	/*IFF2=IFF1;*/ /* contrary to zilog z80 docs, IFF2 is not modified on NMI. proved by Slava Tretiak aka restorer */
	IFF1 = 0;

	TSTATES(5); 
	
	z80ex_mwrite_cb(--SP, z80ex.pc.b.h); /* PUSH PC -- high byte */
	TSTATES(3);
		
	z80ex_mwrite_cb(--SP, z80ex.pc.b.l); /* PUSH PC -- low byte */
	TSTATES(3);
	
	PC = 0x0066;
	MEMPTR = PC; /* FIXME: is that really so? */
		
	z80ex.doing_opcode = 0;
	
	return 11; /* NMI always takes 11 t-states */
}
Beispiel #2
0
/*non-maskable interrupt*/
LIB_EXPORT int z80ex_nmi(Z80EX_CONTEXT *cpu)
{
	if(cpu->doing_opcode || cpu->noint_once || cpu->prefix) return(0);	
	
	if(cpu->halted) { PC++; cpu->halted = 0; } /*so we met an interrupt... stop waiting*/
	
	cpu->doing_opcode=1;
	
	R++; /*accepting interrupt increases R by one*/
	/*IFF2=IFF1;*/ /*contrary to zilog z80 docs, IFF2 is not modified on NMI. proved by Slava Tretiak aka restorer*/
	IFF1=0;

	TSTATES(5); 
	
	cpu->mwrite_cb(cpu, --SP, cpu->pc.b.h, cpu->mwrite_cb_user_data); /*PUSH PC -- high byte */
	TSTATES(3);
		
	cpu->mwrite_cb(cpu, --SP, cpu->pc.b.l, cpu->mwrite_cb_user_data); /*PUSH PC -- low byte */
	TSTATES(3);
	
	PC=0x0066;
	MEMPTR=PC; /*FIXME: is that really so?*/
		
	cpu->doing_opcode=0;
	
	return(11); /*NMI always takes 11 t-states*/
}
Beispiel #3
0
/* do one opcode (instruction or prefix) */
int z80ex_step(void)
{
	Z80EX_BYTE opcode, d;
	z80ex_opcode_fn ofn = NULL;
	
	z80ex.doing_opcode = 1;
	z80ex.noint_once = 0;
	z80ex.reset_PV_on_int = 0;
	z80ex.tstate = 0;
	z80ex.op_tstate = 0;
	
	opcode = READ_OP_M1(); 		/* fetch opcode */
	if (z80ex.int_vector_req)
	{
		TSTATES(2); 		/* interrupt eats two extra wait-states */
	}
	R++;				/* R increased by one on every first M1 cycle */

	T_WAIT_UNTIL(4);		/* M1 cycle eats min 4 t-states */

	if (!z80ex.prefix)
		opcodes_base[opcode]();
	else {
		if ((z80ex.prefix | 0x20) == 0xFD && ((opcode | 0x20) == 0xFD || opcode == 0xED)) {
			z80ex.prefix = opcode;
			z80ex.noint_once = 1; /* interrupts are not accepted immediately after prefix */
		} else {
			switch (z80ex.prefix) {
				case 0xDD:
				case 0xFD:
					if (opcode == 0xCB) {	/* FD/DD prefixed CB opcodes */
						d = READ_OP(); /* displacement */
						temp_byte_s = (d & 0x80)? -(((~d) & 0x7f)+1): d;
						opcode = READ_OP();
#ifdef Z80EX_Z180_SUPPORT
						if (Z180_LIKELY(z80ex.z180)) {
							if (unlikely((opcode & 7) != 6 || opcode == 0x36))
								ofn = trapping(z80ex.prefix, 0xCB, opcode, ITC_B3);
							else
								ofn = (z80ex.prefix == 0xDD) ? opcodes_ddcb[opcode] : opcodes_fdcb[opcode];
						} else
#endif
							ofn = (z80ex.prefix == 0xDD) ? opcodes_ddcb[opcode] : opcodes_fdcb[opcode];
					} else { /* FD/DD prefixed base opcodes */
#ifdef Z80EX_Z180_SUPPORT
						if (unlikely(z80ex.z180 && opcodes_ddfd_bad_for_z180[opcode])) {
							ofn = trapping(z80ex.prefix, 0x00, opcode, ITC_B2);
						} else {
#endif
							ofn = (z80ex.prefix == 0xDD) ? opcodes_dd[opcode] : opcodes_fd[opcode];
							if (unlikely(ofn == NULL)) ofn = opcodes_base[opcode]; /* 'mirrored' instructions NOTE: this should NOT happen with Z180! */
#ifdef Z80EX_Z180_SUPPORT
						}
#endif
					}
					break;
								
				case 0xED: /* ED opcodes */
#ifdef Z80EX_ED_TRAPPING_SUPPORT
					if (unlikely(opcode > 0xBB)) {
						/* check if ED-trap emu func accepted the opcode as its own "faked" */
						if (z80ex_ed_cb(opcode)) {
							ofn = opcodes_base[0x00];
							break;
						}
					}
#endif
#ifdef Z80EX_Z180_SUPPORT
					if (Z180_LIKELY(z80ex.z180))
						ofn = opcodes_ed_z180[opcode];
					else
#endif
						ofn = opcodes_ed[opcode];
					if (ofn == NULL) {
#ifdef Z80EX_Z180_SUPPORT
						if (unlikely(z80ex.z180))
							ofn = trapping(0x00, 0xED, opcode, ITC_B2);
						else
#endif
							ofn = opcodes_base[0x00];
					}
					break;
				
				case 0xCB: /* CB opcodes */
#ifdef Z80EX_Z180_SUPPORT
					if (unlikely(z80ex.z180 && (opcode & 0xF8) == 0x30))
						ofn = trapping(0x00, 0xCB, opcode, ITC_B2);
					else
#endif
						ofn = opcodes_cb[opcode];
					break;
					
				default:
					/* this must'nt happen! */
					assert(0);
					break;
			}
		
			ofn();
		
			z80ex.prefix = 0;
		}
	}
		
	z80ex.doing_opcode = 0;
	return z80ex.tstate;
}
Beispiel #4
0
void z80ex_w_states(unsigned w_states)
{
	TSTATES(w_states);
}
Beispiel #5
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;
}
Beispiel #6
0
/* do one opcode (instruction or prefix) */
LIB_EXPORT int z80ex_step(Z80EX_CONTEXT *cpu)
{
	Z80EX_BYTE opcode, d;
	z80ex_opcode_fn ofn=NULL;
	
	cpu->doing_opcode=1;
	cpu->noint_once=0;
	cpu->reset_PV_on_int=0;
	cpu->tstate=0;
	cpu->op_tstate=0;
	
	opcode=READ_OP_M1(); /*fetch opcode*/
	if(cpu->int_vector_req)
	{
		TSTATES(2); /*interrupt eats two extra wait-states*/
	}
	R++; /*R increased by one on every first M1 cycle*/

	T_WAIT_UNTIL(4); /*M1 cycle eats min 4 t-states*/

	if(!cpu->prefix) opcodes_base[opcode](cpu);
	else
	{
		if((cpu->prefix | 0x20) == 0xFD && ((opcode | 0x20) == 0xFD || opcode == 0xED))
		{
			cpu->prefix=opcode;
			cpu->noint_once=1; /*interrupts are not accepted immediately after prefix*/
		}
		else
		{
			switch(cpu->prefix)
			{
				case 0xDD:
				case 0xFD:
					if(opcode == 0xCB)
					{
						d=READ_OP(); /*displacement*/
						temp_byte_s=(d & 0x80)? -(((~d) & 0x7f)+1): d;
						opcode=READ_OP();
						ofn = (cpu->prefix == 0xDD)? opcodes_ddcb[opcode]: opcodes_fdcb[opcode];						
					}
					else
					{
						ofn = (cpu->prefix == 0xDD)? opcodes_dd[opcode]: opcodes_fd[opcode];
						if(ofn == NULL) ofn=opcodes_base[opcode]; /*'mirrored' instructions*/
					}
					break;
								
				case 0xED:
					ofn = opcodes_ed[opcode];
					if(ofn == NULL) ofn=opcodes_base[0x00];
					break;
				
				case 0xCB:
					ofn = opcodes_cb[opcode];
					break;
					
				default:
					/*this must'nt happen!*/
					break;
			}
		
			ofn(cpu);
		
			cpu->prefix=0;
		}
	}
		
	cpu->doing_opcode=0;
	return(cpu->tstate);
}
Beispiel #7
0
LIB_EXPORT void z80ex_w_states(Z80EX_CONTEXT *cpu, unsigned w_states)
{
	TSTATES(w_states);
}