Пример #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;
	}

    }

}
Пример #2
0
void CDead6800::Step()
{
u8 Opcode;										//current opcode
u8 tmp,ntmp,otmp;								//temp variables used by opcodes
u32 tmp2,tmp3;

CHECK_INTERRUPTS;
if(WaitInterrupt)
	{
	AddCycles(1);
	return;
	}
SavePC = PC;
Opcode = OpRead(PC++);
switch(Opcode)
	{
	#include "Dead6800switch.cpp"
	}
AddCycles(c6800Cycles[Opcode]);
//debug crap
if(Debug == 3)
	{
	char dis[128];

	Disassemble(dis,SavePC);
	message("$%04X: %s D=$%04X X=$%04X S=$%04X CC=$%02X\n",SavePC,dis,D,X,S,CC);
	}
}
Пример #3
0
void CDead63701::Step()
{
u8 Opcode;										//current opcode
u8 tmp,ntmp,otmp;								//temp variables used by opcodes
u32 tmp2,tmp3;

CHECK_INTERRUPTS;
if(WaitInterrupt)
	{
	AddCycles(1);
	return;
	}
SavePC = PC;
Opcode = OpRead(PC++);
switch(Opcode)
	{
	#include "Dead63701switch.cpp"
	#include "../dead6800/Dead6800switch.cpp"
	}
AddCycles(c63701Cycles[Opcode]);
}
Пример #4
0
 virtual void AddMapCycles(unsigned int num) { AddCycles(num); }
Пример #5
0
bool CCpu::SingleStep()
{
    ServiceInterruptRequest();
    
    //Save incoming PC to compare with the outgoing one. If they are identical
    //this indicates a "halt" instruction.
    TUint16 incommingPc = iRegMap.iPC;
    
    //Read the instruction, and decode the op code.
    TUint16 inst = iMemMap[iRegMap.iPC++];
    TUint op = Decode::BasicOpCode(inst);
    
    //All opcodes need to read and/or write operand A.
    TUint16& a = Decode::OperandA(iRegMap, iMemMap, Decode::A(inst));
    
    if(op != Decode::EOpCodeSPECIAL)
    {
        //All basic instructions need to read A and read and/or write B.
        TUint16& b = Decode::OperandB(iRegMap, iMemMap, Decode::B(inst));
        
        switch(op)
        {
            case Decode::EOpCodeSET:
            {
                b = a;
                AddCycles(1);
                break;
            }
                
            case Decode::EOpCodeADD:
            {
                TUint32 u32 = TUint32(b) + TUint32(a);
                b = TUint16(u32 & 0xffff);
                iRegMap.iEX = TUint16(u32 >> 16);
                AddCycles(2);
                break;
            }
                
            case Decode::EOpCodeSUB:
            {
                TUint32 u32 = TUint32(b) - TUint32(a);
                b = TUint16(u32 & 0xffff);
                iRegMap.iEX = TUint16(u32 >> 16);
                AddCycles(2);
                break;
            }
                
            case Decode::EOpCodeMUL:
            {
                TUint32 u32 = TUint32(b) * TUint32(a);
                b = TUint16(u32 & 0xffff);
                iRegMap.iEX = TUint16(u32 >> 16);
                AddCycles(2);
                break;
            }
                
            case Decode::EOpCodeMLI:
            {
                TInt32 i32 = TInt32(b) * TInt32(a);
                b = TUint16(i32 & 0x7fff);
                iRegMap.iEX = TUint16(i32 >> 16);
                AddCycles(2);
                break;
            }
                
            case Decode::EOpCodeDIV:
            {
                if(a == 0)
                {
                    b = 0;
                    iRegMap.iEX = 0;
                }
                else
                {
                    b /= a;
                    iRegMap.iEX = TUint16(((TUint32(b) << 16) / TUint32(a)));
                }
                AddCycles(3);
                break;
            }
                
            case Decode::EOpCodeDVI:
            {
                if(a == 0)
                {
                    b = 0;
                    iRegMap.iEX = 0;
                }
                else
                {
                    TInt32 sa = TInt32(a);
                    TInt32 sb = TInt32(b);
                    b = TUint16(sb / sa);
                    iRegMap.iEX = TUint16((sb << 16) / sa);
                }
                AddCycles(3);
                break;
            }
                
            case Decode::EOpCodeMOD:
            {
                if(a == 0)
                {
                    b = 0;
                } 
                else 
                {
                    b = TUint16(TInt32(b) % TInt32(a));
                }
                AddCycles(3);
                break;
            }
                
            case Decode::EOpCodeMDI:
            {
                if(a == 0)
                {
                    b = 0;
                }
                else
                {
                    b = TUint16(TInt32(b) % TInt32(a));
                }
                AddCycles(3);
                break;
            }
                
            case Decode::EOpCodeAND:
            {
                b &= a;
                AddCycles(1);
                break;
            }
                
            case Decode::EOpCodeBOR:
            {
                b |= a;
                AddCycles(1);
                break;
            }
                
            case Decode::EOpCodeXOR:
            {
                b ^= a;
                AddCycles(1);
                break;
            }
                
            case Decode::EOpCodeSHR:
            {
                b >>= a;
                iRegMap.iEX = TUint16(((TUint32(b) << 16) >> TUint32(a)));
                AddCycles(1);
                break;
            }
                
            case Decode::EOpCodeASR:
            {
                TInt32 sb = TInt32(b);
                b = TUint16(sb >> a);
                iRegMap.iEX = TUint16((TInt32(sb) << 16) >> TUint32(a));
                AddCycles(1);
                break;
            }
                
            case Decode::EOpCodeSHL:
            {
                TUint32 u32 = TUint32(b) << TUint32(a);
                b = TUint16(u32 & 0xffff);
                iRegMap.iEX = TUint16(u32 >> 16);
                AddCycles(1);
                break;
            }

            case Decode::EOpCodeIFB:
            {
                if((b & a) == 0)
                {
                    SkipInstructions();
                }
                AddCycles(2);
                break;
            }
                
            case Decode::EOpCodeIFC:
            {
                if((b & a) != 0)
                {
                    SkipInstructions();
                }
                AddCycles(2);
                break;
            }
                
            case Decode::EOpCodeIFE:
            {
                if(b != a)
                {
                    SkipInstructions();
                }
                AddCycles(2);
                break;
            }
                
            case Decode::EOpCodeIFN:
            {
                if(b == a)
                {
                    SkipInstructions();
                }
                AddCycles(2);
                break;
            }
                
            case Decode::EOpCodeIFG:
            {
                if(b <= a)
                {
                    SkipInstructions();
                }
                AddCycles(2);
                break;
            }
                
            case Decode::EOpCodeIFA:
            {
                if(TInt32(b) <= TInt32(a))
                {
                    SkipInstructions();
                }
                AddCycles(2);
                break;
            }
                
            case Decode::EOpCodeIFL:
            {
                if(b >= a)
                {
                    SkipInstructions();
                }
                AddCycles(2);
                break;
            }
                
            case Decode::EOpCodeIFU:
            {
                if(TInt32(b) >= TInt32(a))
                {
                    SkipInstructions();
                }
                AddCycles(2);
                break;
            }
                
            case Decode::EOpCodeADX:
            {
                TUint32 u32 = TUint32(b) + TUint32(a) + TUint32(iRegMap.iEX);
                b = TUint16(u32 & 0xffff);
                iRegMap.iEX = TUint16(u32 >> 16);
                AddCycles(3);
                break;
            }
                
            case Decode::EOpCodeSBX:
            {
                TUint32 u32 = TUint32(b) - TUint32(a) + TUint32(iRegMap.iEX);
                b = TUint16(u32 & 0xffff);
                iRegMap.iEX = TUint16(u32 >> 16);
                AddCycles(3);
                break;
            }
                
            case Decode::EOpCodeSTI:
            {
                b = a;
                iRegMap.iI++;
                iRegMap.iJ++;
                AddCycles(2);
                break;
            }
                
            case Decode::EOpCodeSTD:
            {
                b = a;
                iRegMap.iI--;
                iRegMap.iJ--;
                AddCycles(2);
                break;
            }
                
            default: assert("Unknown basic op code" && false);
        }
    }
Пример #6
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);
}