summaryrefslogtreecommitdiff
path: root/z80.c
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2006-08-20 17:39:42 +0000
committerIan C <ianc@noddybox.co.uk>2006-08-20 17:39:42 +0000
commit87ace20633ba711243e336630e2c9a8546516598 (patch)
treea9c624a08ae8ccc16086781fb009a6709b7a2913 /z80.c
parent2a5a38a8bd0295b841343062baec242d40267d93 (diff)
This commit was generated by cvs2svn to compensate for changes in r2,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'z80.c')
-rw-r--r--z80.c368
1 files changed, 368 insertions, 0 deletions
diff --git a/z80.c b/z80.c
new file mode 100644
index 0000000..6745fe1
--- /dev/null
+++ b/z80.c
@@ -0,0 +1,368 @@
+/*
+
+ z80 - Z80 Emulator
+
+ Copyright (C) 2006 Ian Cowburn <ianc@noddybox.co.uk>
+
+ Some of the opcode routines are based on the Z80 emulation from YAZE,
+ Copyright (c) 1995 Frank D. Cringle.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ $Id$
+
+ Z80
+
+*/
+#include "z80.h"
+#include "z80_private.h"
+
+static const char ident[]="$Id$";
+
+
+/* ---------------------------------------- LIBRARY VARIABLES
+*/
+static Z80Byte PSZtable[512];
+static Z80Byte SZtable[512];
+static Z80Byte Ptable[512];
+static Z80Byte Stable[512];
+static Z80Byte Ztable[512];
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+static void InitTables()
+{
+ static int init=FALSE;
+ Z80Reg r;
+ Z80Word f;
+
+ if (init)
+ return;
+
+ init=TRUE;
+
+ /* Initialise flag tables
+ */
+ for(f=0;f<256;f++)
+ {
+ Z80Byte p,z,s;
+ int b;
+
+ p=0;
+
+ for(b=0;b<8;b++)
+ if (f&(1<<b))
+ p++;
+
+ if (p&1)
+ p=0;
+ else
+ p=P_Z80;
+
+ if (f)
+ z=0;
+ else
+ z=Z_Z80;
+
+ if (f&0x80)
+ s=S_Z80;
+ else
+ s=0;
+
+ Ptable[f]=p;
+ Stable[f]=s;
+ Ztable[f]=z;
+ SZtable[f]=z|s;
+ PSZtable[f]=z|s|p;
+
+ Ptable[f+256]=Ptable[f]|C_Z80;
+ Stable[f+256]=Stable[f]|C_Z80;
+ Ztable[f+256]=Ztable[f]|C_Z80;
+ SZtable[f+256]=SZtable[f]|C_Z80;
+ PSZtable[f+256]=PSZtable[f]|C_Z80;
+ }
+}
+
+static void Z80_CheckInterrupt(Z80 *cpu)
+{
+ /* Check interrupts
+ */
+ if (cpu->raise)
+ {
+ if (cpu->nmi)
+ {
+ if (cpu->halt)
+ {
+ cpu->halt=FALSE;
+ CALLBACK(eZ80_Halt,0);
+ cpu->PC++;
+ }
+
+ TSTATE(2);
+ cpu->IFF1=0;
+ cpu->nmi=FALSE;
+ PUSH(PC);
+ cpu->PC=0x66;
+ }
+ else if (cpu->IFF1)
+ {
+ if (cpu->halt)
+ {
+ cpu->halt=FALSE;
+ CALLBACK(eZ80_Halt,0);
+ cpu->PC++;
+ }
+
+ TSTATE(2);
+
+ switch(cpu->IM)
+ {
+ default:
+ case 0:
+ INC_R;
+ Z80_Decode(cpu,cpu->devbyte);
+ return;
+ break;
+
+ case 1:
+ PUSH(PC);
+ cpu->PC=0x38;
+ break;
+
+ case 2:
+ PUSH(PC);
+ cpu->PC=(Z80Word)cpu->I*256+cpu->devbyte;
+ break;
+ }
+ }
+
+ cpu->raise=FALSE;
+ }
+}
+
+
+/* ---------------------------------------- INTERFACES
+*/
+
+Z80 *Z80Init(Z80Memory memory,
+ Z80MemoryControl memcontrol,
+ Z80WritePort write_port,
+ Z80ReadPort read_port)
+{
+ Z80 *cpu;
+ int f;
+ int r;
+
+ InitTables();
+
+ if (!write_byte || !read_byte || !write_word || !read_word)
+ return NULL;
+
+ cpu=malloc(sizeof *cpu);
+
+ if (cpu)
+ {
+ cpu->memory=memory;
+ cpu->memctrl=memcontrol;
+ cpu->pread=read_port;
+ cpu->pwrite=write_port;
+
+ for(f=0;f<eZ80_NO_CALLBACK;f++)
+ for(r=0;r<MAX_PER_CALLBACK;r++)
+ cpu->callback[f][r]=NULL;
+
+ Z80Reset(cpu);
+ }
+
+ return cpu;
+}
+
+
+void Z80Reset(Z80 *cpu)
+{
+ cpu->cycle=0;
+ cpu->PC=0;
+
+ cpu->A=0xff;
+ cpu->F=0xff;
+ cpu->BC=0xffff;
+ cpu->DE=0xffff;
+ cpu->HL=0xffff;
+ cpu->AF_=0xffff;
+ cpu->BC_=0xffff;
+ cpu->DE_=0xffff;
+ cpu->HL_=0xffff;
+
+ cpu->IX=0xffff;
+ cpu->IY=0xffff;
+
+ cpu->SP=0xffff;
+ cpu->IFF1=0;
+ cpu->IFF2=0;
+ cpu->IM=0;
+ cpu->I=0;
+ cpu->R=0;
+ cpu->halt=0;
+
+ cpu->raise=FALSE;
+ cpu->nmi=FALSE;
+}
+
+
+void Z80ResetCycles(Z80 *cpu, Z80Val cycles)
+{
+ cpu->cycle=cycles;
+}
+
+
+int Z80LodgeCallback(Z80 *cpu, Z80CallbackReason reason, Z80Callback callback)
+{
+ int f;
+
+ for(f=0;f<MAX_PER_CALLBACK;f++)
+ if (!cpu->callback[reason][f])
+ {
+ cpu->callback[reason][f]=callback;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+void Z80RemoveCallback(Z80 *cpu, Z80CallbackReason reason, Z80Callback callback)
+{
+ int f;
+
+ for(f=0;f<MAX_PER_CALLBACK;f++)
+ if (cpu->callback[reason][f]==callback)
+ cpu->callback[reason][f]=NULL;
+}
+
+
+void Z80Interrupt(Z80 *cpu, Z80Byte devbyte)
+{
+ cpu->raise=TRUE;
+ cpu->devbyte=devbyte;
+ cpu->nmi=FALSE;
+}
+
+
+void Z80NMI(Z80 *cpu)
+{
+ cpu->raise=TRUE;
+ cpu->nmi=TRUE;
+}
+
+
+int Z80SingleStep(Z80 *cpu)
+{
+ cpu->last_cb=TRUE;
+ cpu->shift=0;
+ cpu->use_cb_off=FALSE;
+ cpu->cb_off=0;
+
+ Z80_CheckInterrupt(cpu);
+
+ CALLBACK(eZ80_Instruction,cpu->cycle);
+
+ INC_R;
+
+ Z80_Decode(cpu,cpu->memory[cpu->PC++]);
+
+ return cpu->last_cb;
+}
+
+
+void Z80Exec(Z80 *cpu)
+{
+ while (Z80SingleStep(cpu));
+}
+
+
+void Z80GetState(Z80 *cpu, Z80State *state)
+{
+#define COPY(a) state->a=cpu->a
+ COPY(cycle);
+
+ SET_HI(state->AF,cpu->A);
+ SET_LO(state->AF,cpu->F);
+
+ COPY(BC);
+ COPY(DE);
+ COPY(HL);
+
+ COPY(AF_);
+ COPY(BC_);
+ COPY(DE_);
+ COPY(HL_);
+
+ COPY(IX);
+ COPY(IY);
+
+ COPY(SP);
+ COPY(PC);
+
+ COPY(IFF1);
+ COPY(IFF2);
+ COPY(IM);
+ COPY(I);
+ COPY(R);
+#undef COPY
+}
+
+
+void Z80SetState(Z80 *cpu, Z80State *state)
+{
+#define COPY(a) cpu->a=state->a
+ COPY(cycle);
+
+ cpu->A=GET_HI(state->AF);
+ cpu->F=GET_LO(state->AF);
+
+ COPY(AF);
+ COPY(BC);
+ COPY(DE);
+ COPY(HL);
+
+ COPY(AF_);
+ COPY(BC_);
+ COPY(DE_);
+ COPY(HL_);
+
+ COPY(IX);
+ COPY(IY);
+
+ COPY(SP);
+ COPY(PC);
+
+ COPY(IFF1);
+ COPY(IFF2);
+ COPY(IM);
+ COPY(I);
+ COPY(R);
+#undef COPY
+}
+
+
+Z80Val Z80Cycles(Z80 *cpu)
+{
+ return cpu->cycle;
+}
+
+/* END OF FILE */