diff options
author | Ian C <ianc@noddybox.co.uk> | 2006-08-20 17:39:42 +0000 |
---|---|---|
committer | Ian C <ianc@noddybox.co.uk> | 2006-08-20 17:39:42 +0000 |
commit | 87ace20633ba711243e336630e2c9a8546516598 (patch) | |
tree | a9c624a08ae8ccc16086781fb009a6709b7a2913 /z80.c | |
parent | 2a5a38a8bd0295b841343062baec242d40267d93 (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.c | 368 |
1 files changed, 368 insertions, 0 deletions
@@ -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 */ |