From 87ace20633ba711243e336630e2c9a8546516598 Mon Sep 17 00:00:00 2001 From: Ian C Date: Sun, 20 Aug 2006 17:39:42 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r2, which included commits to RCS files with non-trunk default branches. --- z80.c | 368 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 z80.c (limited to 'z80.c') 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 + + 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<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;fcallback[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;fcallback[reason][f]) + { + cpu->callback[reason][f]=callback; + return TRUE; + } + + return FALSE; +} + + +void Z80RemoveCallback(Z80 *cpu, Z80CallbackReason reason, Z80Callback callback) +{ + int f; + + for(f=0;fcallback[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 */ -- cgit v1.2.3