Esempio n. 1
0
/*====================================================================
  void Z80Interrupt( Z80 *regs, word ivec )
 ===================================================================*/
void
Z80Interrupt (Z80 * regs, word ivec)
{
  word intaddress;

  /* unhalt the computer */
  if (regs->halted == 1)
    regs->halted = 0;

  if (regs->IFF1)
    {
      PUSH (PC);
      regs->IFF1 = 0;
      switch (regs->IM)
	{
	case 0:
	  r_PC = 0x0038;
	  AddCycles (12);
	  break;
	case 1:
	  r_PC = 0x0038;
	  AddCycles (13);
	  break;
	case 2:
	  intaddress = (((regs->I & 0xFF) << 8) | 0xFF);
	  regs->PC.B.l = Z80ReadMem (intaddress);
	  regs->PC.B.h = Z80ReadMem (intaddress + 1);
	  AddCycles (19);
	  break;
	}

    }

}
Esempio n. 2
0
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 Copyright (c) 2000-2002 Santiago Romero Iglesias  (for ASpectrum)
 Copyright (c) 2004 rlyeh  (adapted for fzx32, also used by GP2Xpectrum)
 Copyright (c) 2006-2009 Metalbrain  (modifications for GP2Xpectrum)
 some small parts may be taken from or inspired by FUSE's equivalent file, which is
 Copyright (c) 1999-2003 Philip Kendall

 =====================================================================*/

/* 15 clock cycles minimum = FD/DD CB xx opcode = 4 + 4 + 3 + 4 */

tmpreg.W = REGISTER.W + (offset) Z80ReadMem (r_PC);
r_PC++;
opcode = Z80ReadMem (r_PC);contend_read_x2(r_PC);
r_PC++;
r_meml = Z80ReadMem (tmpreg.W);contend_read(tmpreg.W);
r_memh = tmpreg.W>>8;


switch (opcode & 0xf8)
  {
  case RLC_xIXY & 0xf8:
    RLC (r_meml);
    Z80WriteMem (tmpreg.W, r_meml, regs);
    break;
  case RRC_xIXY & 0xf8:
    RRC (r_meml);
Esempio n. 3
0
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 Copyright (c) 2000-2002 Santiago Romero Iglesias  (for ASpectrum)
 Copyright (c) 2004 rlyeh  (adapted for fzx32, also used by GP2Xpectrum)
 Copyright (c) 2006-2007 Metalbrain  (modifications for GP2Xpectrum)
 some small parts may be taken from or inspired by FUSE's equivalent file, which is
 Copyright (c) 1999-2006 Philip Kendall
 
 =====================================================================*/

/* 8 clock cycles minimum = CB opcode = 4+4 */

opcode = Z80ReadMem (r_PC);
AddCycles(1);
r_PC++;

switch (opcode)
  {

  case RLC_B:
    RLC (r_B);
    break;
  case RLC_C:
    RLC (r_C);
    break;
  case RLC_D:
    RLC (r_D);
    break;
Esempio n. 4
0
/*====================================================================
  byte Z80MemRead( register word address )

  This function reads from the given memory address. It is not inlined,
  and it's written for debugging purposes.
 ===================================================================*/
byte
Z80MemRead (register word address, Z80 * regs)
{
	  return (Z80ReadMem (address));
}
Esempio n. 5
0
/*====================================================================
  word Z80Run( Z80 *regs, int numopcodes )

  This function does the whole Z80 simulation. It consists on a
  for(;;) loop (as stated on Marat's Fayzullin HOWTO -How to
  Write a Computer Emulator-) which fetchs the next opcode,
  interprets it (using a switch statement) and then it's
  executed in the right CASE: of that switch. I've put the different
  case statements into C files included here with #include to
  make this more readable (and programming easier! :).

  This function will change regs->ICount register and will execute
  an interrupt when it reaches 0 (or <0). You can then do anything
  related to your machine emulation here, using the Z80Hardware()
  function. This function must be filled by yourself: put there
  the code related to the emulated machine hardware, such as
  screen redrawing, sound playing and so on. This functions can
  return an special value to make Z80Run stop the emulation (and
  return to the caller): that's INT_QUIT. If there is time to
  execute an interrupt, please return INT_IRQ or INT_NMI. Return
  INT_NOINT if there is no time for an interrupt :) .

  Z80Execute() will change PC and all the z80 registers acording
  to the executed opcode, and those values will be returned when
  a INT_QUIT is received.

  Pass as numcycles the number of clock cycle you want to execute
  z80 opcodes for or < 0 (negative) to execute "infinite" opcodes.
 ===================================================================*/
word
ExecZ80 (Z80 * regs, int numcycles)
{
  /* opcode and temp variables */
  register byte opcode;
  eword tmpreg, ops, mread, tmpreg2;
  unsigned long tempdword;
  register int loop;
  unsigned short tempword;

  /* emulate <numcycles> cycles */
  loop = (regs->ICount - numcycles);

  /* this is the emulation main loop */
  while (regs->ICount > loop)
    {
#ifdef DEBUG
      /* test if we have reached the trap address */
      if (regs->PC.W == regs->TrapAddress && regs->dobreak != 0)
	return (regs->PC.W);
#endif

      if (regs->halted == 1)
	{
	  r_PC--;
	  AddCycles (4);
	}

      /* read the opcode from memory (pointed by PC) */
      opcode = Z80ReadMem (regs->PC.W);
      regs->PC.W++;

      /* increment the R register and decode the instruction */
      AddR (1);
      switch (opcode)
	{
#include "opcodes.h"
	case PREFIX_CB:
	  AddR (1);
#include "op_cb.h"
	  break;
	case PREFIX_ED:
	  AddR (1);
#include "op_ed.h"
	  break;
	case PREFIX_DD:
	case PREFIX_FD:
	  AddR (1);
	  if (opcode == PREFIX_DD)
	    {
#define REGISTER regs->IX
	      regs->we_are_on_ddfd = WE_ARE_ON_DD;
#include "op_dd_fd.h"


#undef  REGISTER
	    }
	  else
	    {
#define REGISTER regs->IY
	      regs->we_are_on_ddfd = WE_ARE_ON_FD;
#include "op_dd_fd.h"
#undef  REGISTER
	    }
	  regs->we_are_on_ddfd = 0;
	  break;
	}

      /* patch ROM loading routine */
      // address contributed by Ignacio Burgue�o :)
//     if( r_PC == 0x0569 )
      if (r_PC >= 0x0556 && r_PC <= 0x056c)
	      Z80Patch (regs);

      /* check if it's time to do other hardware emulation */
      if (regs->ICount <= 0) {
//	if (regs->petint==1) {
	  regs->petint=0;
/*	  tmpreg.W = Z80Hardware (regs); */ //Z80Hardware alwais return INT_NOINT
	  regs->ICount += regs->IPeriod;
	  loop = regs->ICount + loop;

	  /* check if we must exit the emulation or there is an INT */
/*	  if (tmpreg.W == INT_QUIT)
	    return (regs->PC.W);
	  if (tmpreg.W != INT_NOINT) */   
	    Z80Interrupt (regs, tmpreg.W);
	}
  }

  return (regs->PC.W);
}