summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/spec.h2
-rw-r--r--include/z80.h115
-rw-r--r--include/z80_decode.c2522
-rw-r--r--include/z80_private.h122
4 files changed, 138 insertions, 2623 deletions
diff --git a/include/spec.h b/include/spec.h
index bcb587c..35ed5ed 100644
--- a/include/spec.h
+++ b/include/spec.h
@@ -2,7 +2,7 @@
dsspec - Nintendo DS Sinclair Spectrum 48K emulator.
- Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.co.uk)
+ Copyright (C) 2006 Ian Cowburn (ianc@noddybox.demon.co.uk)
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
diff --git a/include/z80.h b/include/z80.h
index 0b7424b..000b950 100644
--- a/include/z80.h
+++ b/include/z80.h
@@ -27,14 +27,13 @@
#ifndef Z80_H
#define Z80_H "$Id$"
-/* ---------------------------------------- TYPES
+/* Configuration
*/
+#include "z80_config.h"
-/* The processor
-*/
-struct Z80;
-typedef struct Z80 Z80;
+/* ---------------------------------------- TYPES
+*/
/* Large unsigned type
*/
@@ -56,6 +55,53 @@ typedef signed char Z80Relative;
typedef unsigned short Z80Word;
+/* A Z80 16-bit register. To access the HI/LO component use the indexes
+ Z80_HI_WORD and Z80_LO_WORD which will be initialised once Z80Init has been
+ called.
+*/
+typedef union
+{
+ Z80Word w;
+ Z80Byte b[2];
+} Z80Reg;
+
+extern int Z80_HI_WORD;
+extern int Z80_LO_WORD;
+
+
+/* The processor
+*/
+struct Z80Private;
+
+typedef struct
+{
+ Z80Word PC;
+
+ Z80Reg AF;
+ Z80Reg BC;
+ Z80Reg DE;
+ Z80Reg HL;
+
+ Z80Word AF_;
+ Z80Word BC_;
+ Z80Word DE_;
+ Z80Word HL_;
+
+ Z80Reg IX;
+ Z80Reg IY;
+
+ Z80Word SP;
+
+ Z80Byte IFF1;
+ Z80Byte IFF2;
+ Z80Byte IM;
+ Z80Byte I;
+ Z80Byte R;
+
+ struct Z80Private *priv;
+} Z80;
+
+
/* Interfaces used to handle memory
*/
typedef Z80Byte (*Z80ReadMemory)(Z80 *cpu, Z80Word address);
@@ -95,36 +141,6 @@ typedef enum
} Z80CallbackReason;
-/* Get/settable state of the Z80
-*/
-typedef struct
-{
- Z80Word PC;
- Z80Word SP;
-
- Z80Val cycle;
-
- Z80Word AF;
- Z80Word BC;
- Z80Word DE;
- Z80Word HL;
-
- Z80Word AF_; /* Alternate registers */
- Z80Word BC_;
- Z80Word DE_;
- Z80Word HL_;
-
- Z80Word IX;
- Z80Word IY;
-
- Z80Byte IFF1;
- Z80Byte IFF2;
- Z80Byte IM;
- Z80Byte I;
- Z80Byte R;
-} Z80State;
-
-
/* Flags in the F register
*/
typedef enum
@@ -157,11 +173,16 @@ typedef struct
/* Initialises the processor.
*/
+#ifdef ENABLE_ARRAY_MEMORY
+Z80 *Z80Init(Z80ReadPort read_port,
+ Z80WritePort write_port);
+#else
Z80 *Z80Init(Z80ReadMemory read_memory,
Z80WriteMemory write_memory,
Z80ReadPort read_port,
Z80WritePort write_port,
Z80ReadMemory read_for_disassem);
+#endif
/* Resets the processor.
@@ -169,21 +190,6 @@ Z80 *Z80Init(Z80ReadMemory read_memory,
void Z80Reset(Z80 *cpu);
-/* Sets the PC
-*/
-void Z80SetPC(Z80 *cpu, Z80Word PC);
-
-
-/* Gets the PC
-*/
-Z80Word Z80GetPC(Z80 *cpu);
-
-
-/* Sets the cycle count to the specified count
-*/
-void Z80ResetCycles(Z80 *cpu, Z80Val cycles);
-
-
/* Lodge a callback to be invoked after special events. Returns FALSE
if the callback couldn't be lodged (there is a max of 10 callbacks per
reason).
@@ -223,11 +229,10 @@ int Z80SingleStep(Z80 *cpu);
void Z80Exec(Z80 *cpu);
-/* Interrogate the state of the Z80
+/* Manipulate the cylce count of the Z80
*/
Z80Val Z80Cycles(Z80 *cpu);
-void Z80GetState(Z80 *cpu, Z80State *state);
-void Z80SetState(Z80 *cpu, const Z80State *state);
+void Z80ResetCycles(Z80 *cpu, Z80Val cycles);
/* Set address to label mappings for the disassembler
@@ -235,8 +240,8 @@ void Z80SetState(Z80 *cpu, const Z80State *state);
void Z80SetLabels(Z80Label labels[]);
-/* Simple disassembly of memory accessed through read_for_disassem.
- addr is updated on exit.
+/* Simple disassembly of memory accessed through read_for_disassem, or
+ Z80_MEMORY as appropriate. addr is updated on exit.
*/
const char *Z80Disassemble(Z80 *cpu, Z80Word *addr);
diff --git a/include/z80_decode.c b/include/z80_decode.c
deleted file mode 100644
index ced7fbd..0000000
--- a/include/z80_decode.c
+++ /dev/null
@@ -1,2522 +0,0 @@
-/*
-
- z80 - Z80 Emulator
-
- Copyright (C) 2006 Ian Cowburn <ianc@noddybox.co.uk>
-
- 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$
-
-*/
-#include <stdlib.h>
-#include <limits.h>
-
-#include "z80.h"
-#include "z80_private.h"
-
-static const char ident[]="$Id$";
-
-/* ---------------------------------------- TABLES AND INIT
-*/
-static Z80Byte PSZtable[512];
-static Z80Byte SZtable[512];
-static Z80Byte Ptable[512];
-static Z80Byte Stable[512];
-static Z80Byte Ztable[512];
-
-
-static int HI;
-static int LO;
-
-/* ---------------------------------------- MISC FUNCTIONS
-*/
-void Z80_InitialiseInternals(void)
-{
- Z80Word f;
- Z80Reg r;
-
- /* Check endianness
- */
- r.w=0x1234;
-
- if (r.b[0] == 0x12)
- {
- HI=0;
- LO=1;
- }
- else if (r.b[1] == 0x12)
- {
- HI=1;
- LO=0;
- }
- else
- {
- exit(1);
- }
-
- /* Check variable sizes
- */
- if (CHAR_BIT!=8 || sizeof(Z80Word)!=2)
- {
- exit(2);
- }
-
- /* 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 Z80Word FPEEKW(Z80 *cpu, Z80Word addr)
-{
- return (PEEK(addr) | (Z80Word)PEEK(addr+1)<<8);
-}
-
-
-static void FPOKEW(Z80 *cpu, Z80Word addr, Z80Word val)
-{
- cpu->mwrite(cpu,addr,val);
- cpu->mwrite(cpu,addr+1,val>>8);
-}
-
-
-/* ---------------------------------------- GENERAL MACROS
-*/
-#define SWAP(A,B) \
-do { \
- unsigned swap_tmp; \
- swap_tmp=A; \
- A=B; \
- B=swap_tmp; \
-} while(0)
-
-
-/* ---------------------------------------- ARITHMETIC OPS
-*/
-#define ADD8(ONCE) \
-do { \
- Z80Byte VAL=ONCE; \
- unsigned w; \
- w=cpu->AF.b[HI]+(unsigned)VAL; \
- cpu->AF.b[LO]=SZtable[w]; \
- if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \
- if ((VAL^cpu->AF.b[HI]^0x80)&(VAL^w)&0x80) cpu->AF.b[LO]|=P_Z80; \
- SETHIDDEN(w); \
- cpu->AF.b[HI]=w; \
-} while(0)
-
-
-#define ADC8(ONCE) \
-do { \
- Z80Byte VAL=ONCE; \
- unsigned w; \
- w=(cpu->AF.b[HI]+(unsigned)VAL+CARRY)&0x1ff; \
- cpu->AF.b[LO]=SZtable[w]; \
- if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \
- if ((VAL^cpu->AF.b[HI]^0x80)&(VAL^w)&0x80) cpu->AF.b[LO]|=P_Z80; \
- SETHIDDEN(w); \
- cpu->AF.b[HI]=w; \
-} while(0)
-
-
-#define SUB8(ONCE) \
-do { \
- Z80Byte VAL=ONCE; \
- unsigned w; \
- w=(cpu->AF.b[HI]-(unsigned)VAL)&0x1ff; \
- cpu->AF.b[LO]=SZtable[w]|N_Z80; \
- if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \
- if ((VAL^cpu->AF.b[HI])&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80; \
- SETHIDDEN(w); \
- cpu->AF.b[HI]=w; \
-} while(0)
-
-
-#define CMP8(ONCE) \
-do { \
- Z80Byte VAL=ONCE; \
- unsigned w; \
- w=(cpu->AF.b[HI]-(unsigned)VAL)&0x1ff; \
- cpu->AF.b[LO]=SZtable[w]|N_Z80; \
- if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \
- if ((VAL^cpu->AF.b[HI])&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80; \
- SETHIDDEN(VAL); \
-} while(0)
-
-
-#define SBC8(ONCE) \
-do { \
- Z80Byte VAL=ONCE; \
- unsigned w; \
- w=(cpu->AF.b[HI]-(unsigned)VAL-CARRY)&0x1ff; \
- cpu->AF.b[LO]=SZtable[w]|N_Z80; \
- if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \
- if ((VAL^cpu->AF.b[HI])&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80; \
- SETHIDDEN(w); \
- cpu->AF.b[HI]=w; \
-} while(0)
-
-
-#define ADD16(REG,ONCE) \
-do { \
- Z80Word VAL=ONCE; \
- Z80Val w; \
- w=(REG)+(Z80Val)VAL; \
- cpu->AF.b[LO]&=(S_Z80|Z_Z80|V_Z80); \
- if (w>0xffff) cpu->AF.b[LO]|=C_Z80; \
- if (((REG)^w^VAL)&0x1000) cpu->AF.b[LO]|=H_Z80; \
- SETHIDDEN(w>>8); \
- (REG)=w; \
-} while(0)
-
-
-#define ADC16(REG, ONCE) \
-do { \
- Z80Word VAL=ONCE; \
- Z80Val w; \
- w=(REG)+(Z80Val)VAL+CARRY; \
- cpu->AF.b[LO]=0; \
- if ((w&0xffff)==0) cpu->AF.b[LO]=Z_Z80; \
- if (w&0x8000) cpu->AF.b[LO]|=S_Z80; \
- if (w>0xffff) cpu->AF.b[LO]|=C_Z80; \
- if ((VAL^(REG)^0x8000)&((REG)^w)&0x8000) cpu->AF.b[LO]|=P_Z80; \
- if (((REG)^w^VAL)&0x1000) cpu->AF.b[LO]|=H_Z80; \
- SETHIDDEN(w>>8); \
- (REG)=w; \
-} while(0)
-
-
-#define SBC16(REG, ONCE) \
-do { \
- Z80Word VAL=ONCE; \
- Z80Val w; \
- w=(REG)-(Z80Val)VAL-CARRY; \
- cpu->AF.b[LO]=N_Z80; \
- if (w&0x8000) cpu->AF.b[LO]|=S_Z80; \
- if ((w&0xffff)==0) cpu->AF.b[LO]|=Z_Z80; \
- if (w>0xffff) cpu->AF.b[LO]|=C_Z80; \
- if ((VAL^(REG))&((REG)^w)&0x8000) cpu->AF.b[LO]|=P_Z80; \
- if (((REG)^w^VAL)&0x1000) cpu->AF.b[LO]|=H_Z80; \
- SETHIDDEN(w>>8); \
- (REG)=w; \
-} while(0)
-
-
-#define INC8(REG) \
-do { \
- (REG)++; \
- cpu->AF.b[LO]=CARRY|SZtable[(REG)]; \
- if ((REG)==0x80) cpu->AF.b[LO]|=P_Z80; \
- if (((REG)&0x0f)==0) cpu->AF.b[LO]|=H_Z80; \
-} while(0)
-
-
-#define DEC8(REG) \
-do { \
- (REG)--; \
- cpu->AF.b[LO]=N_Z80|CARRY; \
- if ((REG)==0x7f) cpu->AF.b[LO]|=P_Z80; \
- if (((REG)&0x0f)==0x0f) cpu->AF.b[LO]|=H_Z80; \
- cpu->AF.b[LO]|=SZtable[(REG)]; \
-} while(0)
-
-
-#define OP_ON_MEM(OP,addr) \
-do { \
- Z80Byte memop=cpu->mread(cpu,addr); \
- OP(memop); \
- cpu->mwrite(cpu,addr,memop); \
-} while(0)
-
-
-#define OP_ON_MEM_WITH_ARG(OP,addr,arg) \
-do { \
- Z80Byte memop=cpu->mread(cpu,addr); \
- OP(memop,arg); \
- cpu->mwrite(cpu,addr,memop); \
-} while(0)
-
-
-#define OP_ON_MEM_WITH_COPY(OP,addr,copy) \
-do { \
- Z80Byte memop=cpu->mread(cpu,addr); \
- OP(memop); \
- copy=memop; \
- cpu->mwrite(cpu,addr,memop); \
-} while(0)
-
-
-#define OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,arg,copy) \
-do { \
- Z80Byte memop=cpu->mread(cpu,addr); \
- OP(memop,arg); \
- copy=memop; \
- cpu->mwrite(cpu,addr,memop); \
-} while(0)
-
-
-/* ---------------------------------------- ROTATE AND SHIFT OPS
-*/
-#define RRCA \
-do { \
- cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))|(cpu->AF.b[HI]&C_Z80); \
- cpu->AF.b[HI]=(cpu->AF.b[HI]>>1)|(cpu->AF.b[HI]<<7); \
- SETHIDDEN(cpu->AF.b[HI]); \
-} while(0)
-
-
-#define RRA \
-do { \
- Z80Byte c; \
- c=CARRY; \
- cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))|(cpu->AF.b[HI]&C_Z80); \
- cpu->AF.b[HI]=(cpu->AF.b[HI]>>1)|(c<<7); \
- SETHIDDEN(cpu->AF.b[HI]); \
-} while(0)
-
-
-#define RRC(REG) \
-do { \
- Z80Byte c; \
- c=(REG)&C_Z80; \
- (REG)=((REG)>>1)|((REG)<<7); \
- cpu->AF.b[LO]=PSZtable[(REG)]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define RR(REG) \
-do { \
- Z80Byte c; \
- c=(REG)&C_Z80; \
- (REG)=((REG)>>1)|(CARRY<<7); \
- cpu->AF.b[LO]=PSZtable[(REG)]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define RLCA \
-do { \
- cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))|(cpu->AF.b[HI]>>7); \
- cpu->AF.b[HI]=(cpu->AF.b[HI]<<1)|(cpu->AF.b[HI]>>7); \
- SETHIDDEN(cpu->AF.b[HI]); \
-} while(0)
-
-
-#define RLA \
-do { \
- Z80Byte c; \
- c=CARRY; \
- cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))|(cpu->AF.b[HI]>>7); \
- cpu->AF.b[HI]=(cpu->AF.b[HI]<<1)|c; \
- SETHIDDEN(cpu->AF.b[HI]); \
-} while(0)
-
-
-#define RLC(REG) \
-do { \
- Z80Byte c; \
- c=(REG)>>7; \
- (REG)=((REG)<<1)|c; \
- cpu->AF.b[LO]=PSZtable[(REG)]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define RL(REG) \
-do { \
- Z80Byte c; \
- c=(REG)>>7; \
- (REG)=((REG)<<1)|CARRY; \
- cpu->AF.b[LO]=PSZtable[(REG)]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define SRL(REG) \
-do { \
- Z80Byte c; \
- c=(REG)&C_Z80; \
- (REG)>>=1; \
- cpu->AF.b[LO]=PSZtable[(REG)]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define SRA(REG) \
-do { \
- Z80Byte c; \
- c=(REG)&C_Z80; \
- (REG)=((REG)>>1)|((REG)&0x80); \
- cpu->AF.b[LO]=PSZtable[(REG)]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define SLL(REG) \
-do { \
- Z80Byte c; \
- c=(REG)>>7; \
- (REG)=((REG)<<1)|1; \
- cpu->AF.b[LO]=PSZtable[(REG)]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define SLA(REG) \
-do { \
- Z80Byte c; \
- c=(REG)>>7; \
- (REG)=(REG)<<1; \
- cpu->AF.b[LO]=PSZtable[(REG)]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-/* ---------------------------------------- BOOLEAN OPS
-*/
-#define AND(VAL) \
-do { \
- cpu->AF.b[HI]&=VAL; \
- cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]]|H_Z80; \
- SETHIDDEN(cpu->AF.b[HI]); \
-} while(0)
-
-
-#define OR(VAL) \
-do { \
- cpu->AF.b[HI]|=VAL; \
- cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]]; \
- SETHIDDEN(cpu->AF.b[HI]); \
-} while(0)
-
-
-#define XOR(VAL) \
-do { \
- cpu->AF.b[HI]^=VAL; \
- cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]]; \
- SETHIDDEN(cpu->AF.b[HI]); \
-} while(0)
-
-
-#define BIT(REG,B) \
-do { \
- cpu->AF.b[LO]=CARRY|H_Z80; \
- if ((REG)&(1<<B)) \
- { \
- if (B==7 && (REG&S_Z80)) cpu->AF.b[LO]|=S_Z80; \
- if (B==5 && (REG&B5_Z80)) cpu->AF.b[LO]|=B5_Z80; \
- if (B==3 && (REG&B3_Z80)) cpu->AF.b[LO]|=B3_Z80; \
- } \
- else \
- { \
- cpu->AF.b[LO]|=Z_Z80; \
- cpu->AF.b[LO]|=P_Z80; \
- } \
-} while(0)
-
-#define BIT_SET(REG,B) (REG)|=(1<<B)
-#define BIT_RES(REG,B) (REG)&=~(1<<B)
-
-
-/* ---------------------------------------- JUMP OPERATIONS
-*/
-#define JR_COND(COND) \
-do { \
- if (COND) \
- { \
- TSTATE(12); \
- JR; \
- } \
- else \
- { \
- TSTATE(7); \
- NOJR; \
- } \
-} while(0)
-
-
-#define JP_COND(COND) \
-do { \
- TSTATE(10); \
- if (COND) \
- { \
- JP; \
- } \
- else \
- { \
- NOJP; \
- } \
-} while(0)
-
-
-#define CALL_COND(COND) \
-do { \
- if (COND) \
- { \
- TSTATE(17); \
- CALL; \
- } \
- else \
- { \
- TSTATE(10); \
- NOCALL; \
- } \
-} while(0)
-
-
-#define RET_COND(COND) \
-do { \
- if (COND) \
- { \
- TSTATE(11); \
- POP(cpu->PC); \
- } \
- else \
- { \
- TSTATE(5); \
- } \
-} while(0)
-
-
-#define RST(ADDR) \
- TSTATE(11); \
- PUSH(cpu->PC); \
- cpu->PC=ADDR
-
-/* ---------------------------------------- BLOCK OPERATIONS
-*/
-#define LDI \
-do { \
- Z80Byte b; \
- \
- b=PEEK(cpu->HL.w); \
- POKE(cpu->DE.w,b); \
- cpu->DE.w++; \
- cpu->HL.w++; \
- cpu->BC.w--; \
- \
- CLRFLAG(H_Z80); \
- CLRFLAG(N_Z80); \
- \
- if (cpu->BC.w) \
- SETFLAG(P_Z80); \
- else \
- CLRFLAG(P_Z80); \
- \
- SETHIDDEN(cpu->AF.b[HI]+b); \
-} while(0)
-
-#define LDD \
-do { \
- Z80Byte b; \
- \
- b=PEEK(cpu->HL.w); \
- POKE(cpu->DE.w,b); \
- cpu->DE.w--; \
- cpu->HL.w--; \
- cpu->BC.w--; \
- \
- CLRFLAG(H_Z80); \
- CLRFLAG(N_Z80); \
- \
- if (cpu->BC.w) \
- SETFLAG(P_Z80); \
- else \
- CLRFLAG(P_Z80); \
- \
- SETHIDDEN(cpu->AF.b[HI]+b); \
-} while(0)
-
-#define CPI \
-do { \
- Z80Byte c,b; \
- \
- c=CARRY; \
- b=PEEK(cpu->HL.w); \
- \
- CMP8(b); \
- \
- if (c) \
- SETFLAG(C_Z80); \
- else \
- CLRFLAG(C_Z80); \
- \
- cpu->HL.w++; \
- cpu->BC.w--; \
- \
- if (cpu->BC.w) \
- SETFLAG(P_Z80); \
- else \
- CLRFLAG(P_Z80); \
-} while(0)
-
-#define CPD \
-do { \
- Z80Byte c,b; \
- \
- c=CARRY; \
- b=PEEK(cpu->HL.w); \
- \
- CMP8(b); \
- \
- if (c) \
- SETFLAG(C_Z80); \
- else \
- CLRFLAG(C_Z80); \
- \
- cpu->HL.w--; \
- cpu->BC.w--; \
- \
- if (cpu->BC.w) \
- SETFLAG(P_Z80); \
- else \
- CLRFLAG(P_Z80); \
-} while(0)
-
-#define INI \
-do { \
- Z80Word w; \
- Z80Byte b; \
- \
- b=IN(cpu->BC.w); \
- POKE(cpu->HL.w,b); \
- \
- cpu->BC.b[HI]--; \
- cpu->HL.w++; \
- \
- cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]]; \
- SETHIDDEN(cpu->BC.b[HI]); \
- \
- w=(((Z80Word)cpu->BC.b[LO])&0xff)+b; \
- \
- if (b&0x80) \
- SETFLAG(N_Z80); \
- \
- if (w&0x100) \
- { \
- SETFLAG(C_Z80); \
- SETFLAG(H_Z80); \
- } \
- else \
- { \
- CLRFLAG(C_Z80); \
- CLRFLAG(H_Z80); \
- } \
-} while(0)
-
-#define IND \
-do { \
- Z80Word w; \
- Z80Byte b; \
- \
- b=IN(cpu->BC.w); \
- POKE(cpu->HL.w,b); \
- \
- cpu->BC.b[HI]--; \
- cpu->HL.w--; \
- \
- cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]]; \
- SETHIDDEN(cpu->BC.b[HI]); \
- \
- w=(((Z80Word)cpu->BC.b[LO])&0xff)+b; \
- \
- if (b&0x80) \
- SETFLAG(N_Z80); \
- \
- if (w&0x100) \
- { \
- SETFLAG(C_Z80); \
- SETFLAG(H_Z80); \
- } \
- else \
- { \
- CLRFLAG(C_Z80); \
- CLRFLAG(H_Z80); \
- } \
-} while(0) \
-
-#define OUTI \
-do { \
- OUT(cpu->BC.w,PEEK(cpu->HL.w)); \
- \
- cpu->HL.w++; \
- cpu->BC.b[HI]--; \
- \
- cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]]; \
- SETHIDDEN(cpu->BC.b[HI]); \
-} while(0)
-
-#define OUTD \
-do { \
- OUT(cpu->BC.w,PEEK(cpu->HL.w)); \
- \
- cpu->HL.w--; \
- cpu->BC.b[HI]--; \
- \
- cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]]; \
- SETFLAG(N_Z80); \
- SETHIDDEN(cpu->BC.b[HI]); \
-} while(0)
-
-
-/* ---------------------------------------- BASE OPCODE SHORT-HAND BLOCKS
-*/
-
-#define LD_BLOCK(BASE,DEST,DEST2) \
- case BASE: /* LD DEST,B */ \
- TSTATE(4); \
- DEST=cpu->BC.b[HI]; \
- break; \
- \
- case BASE+1: /* LD DEST,C */ \
- TSTATE(4); \
- DEST=cpu->BC.b[LO]; \
- break; \
- \
- case BASE+2: /* LD DEST,D */ \
- TSTATE(4); \
- DEST=cpu->DE.b[HI]; \
- break; \
- \
- case BASE+3: /* LD DEST,E */ \
- TSTATE(4); \
- DEST=cpu->DE.b[LO]; \
- break; \
- \
- case BASE+4: /* LD DEST,H */ \
- TSTATE(4); \
- DEST=*H; \
- break; \
- \
- case BASE+5: /* LD DEST,L */ \
- TSTATE(4); \
- DEST=*L; \
- break; \
- \
- case BASE+6: /* LD DEST,(HL) */ \
- TSTATE(7); \
- OFFSET(off); \
- DEST2=cpu->mread(cpu,*HL+off); \
- break; \
- \
- case BASE+7: /* LD DEST,A */ \
- TSTATE(4); \
- DEST=cpu->AF.b[HI]; \
- break;
-
-#define ALU_BLOCK(BASE,OP) \
- case BASE: /* OP A,B */ \
- TSTATE(4); \
- OP(cpu->BC.b[HI]); \
- break; \
- \
- case BASE+1: /* OP A,C */ \
- TSTATE(4); \
- OP(cpu->BC.b[LO]); \
- break; \
- \
- case BASE+2: /* OP A,D */ \
- TSTATE(4); \
- OP(cpu->DE.b[HI]); \
- break; \
- \
- case BASE+3: /* OP A,E */ \
- TSTATE(4); \
- OP(cpu->DE.b[LO]); \
- break; \
- \
- case BASE+4: /* OP A,H */ \
- TSTATE(4); \
- OP(*H); \
- break; \
- \
- case BASE+5: /* OP A,L */ \
- TSTATE(4); \
- OP(*L); \
- break; \
- \
- case BASE+6: /* OP A,(HL) */ \
- TSTATE(7); \
- OFFSET(off); \
- OP_ON_MEM(OP,*HL+off); \
- break; \
- \
- case BASE+7: /* OP A,A */ \
- TSTATE(4); \
- OP(cpu->AF.b[HI]); \
- break;
-
-
-/* ---------------------------------------- CB OPCODE SHORT-HAND BLOCKS
-*/
-
-#define CB_ALU_BLOCK(BASE,OP) \
- case BASE: /* OP B */ \
- TSTATE(8); \
- OP(cpu->BC.b[HI]); \
- break; \
- \
- case BASE+1: /* OP C */ \
- TSTATE(8); \
- OP(cpu->BC.b[LO]); \
- break; \
- \
- case BASE+2: /* OP D */ \
- TSTATE(8); \
- OP(cpu->DE.b[HI]); \
- break; \
- \
- case BASE+3: /* OP E */ \
- TSTATE(8); \
- OP(cpu->DE.b[LO]); \
- break; \
- \
- case BASE+4: /* OP H */ \
- TSTATE(8); \
- OP(cpu->HL.b[HI]); \
- break; \
- \
- case BASE+5: /* OP L */ \
- TSTATE(8); \
- OP(cpu->HL.b[LO]); \
- break; \
- \
- case BASE+6: /* OP (HL) */ \
- TSTATE(15); \
- OP_ON_MEM(OP,cpu->HL.w); \
- break; \
- \
- case BASE+7: /* OP A */ \
- TSTATE(8); \
- OP(cpu->AF.b[HI]); \
- break;
-
-#define CB_BITMANIP_BLOCK(BASE,OP,BIT_NO) \
- case BASE: /* OP B */ \
- TSTATE(8); \
- OP(cpu->BC.b[HI],BIT_NO); \
- break; \
- \
- case BASE+1: /* OP C */ \
- TSTATE(8); \
- OP(cpu->BC.b[LO],BIT_NO); \
- break; \
- \
- case BASE+2: /* OP D */ \
- TSTATE(8); \
- OP(cpu->DE.b[HI],BIT_NO); \
- break; \
- \
- case BASE+3: /* OP E */ \
- TSTATE(8); \
- OP(cpu->DE.b[LO],BIT_NO); \
- break; \
- \
- case BASE+4: /* OP H */ \
- TSTATE(8); \
- OP(cpu->HL.b[HI],BIT_NO); \
- break; \
- \
- case BASE+5: /* OP L */ \
- TSTATE(8); \
- OP(cpu->HL.b[LO],BIT_NO); \
- break; \
- \
- case BASE+6: /* OP (HL) */ \
- TSTATE(12); \
- OP_ON_MEM_WITH_ARG(OP,cpu->HL.w,BIT_NO); \
- break; \
- \
- case BASE+7: /* OP A */ \
- TSTATE(8); \
- OP(cpu->AF.b[HI],BIT_NO); \
- break;
-
-/* ---------------------------------------- SHIFTED CB OPCODE SHORT-HAND BLOCKS
-*/
-
-#define SHIFTED_CB_ALU_BLOCK(BASE,OP) \
- case BASE: /* OP B */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_COPY(OP,addr,cpu->BC.b[HI]); \
- break; \
- \
- case BASE+1: /* OP C */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_COPY(OP,addr,cpu->BC.b[LO]); \
- break; \
- \
- case BASE+2: /* OP D */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_COPY(OP,addr,cpu->DE.b[HI]); \
- break; \
- \
- case BASE+3: /* OP E */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_COPY(OP,addr,cpu->DE.b[LO]); \
- break; \
- \
- case BASE+4: /* OP H */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_COPY(OP,addr,cpu->HL.b[HI]); \
- break; \
- \
- case BASE+5: /* OP L */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_COPY(OP,addr,cpu->HL.b[LO]); \
- break; \
- \
- case BASE+6: /* OP (HL) */ \
- TSTATE(15); \
- OP_ON_MEM(OP,addr); \
- break; \
- \
- case BASE+7: /* OP A */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_COPY(OP,addr,cpu->AF.b[HI]); \
- break;
-
-#define SHIFTED_CB_BITMANIP_BLOCK(BASE,OP,BIT_NO) \
- case BASE: /* OP B */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->BC.b[HI]); \
- break; \
- \
- case BASE+1: /* OP C */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->BC.b[LO]); \
- break; \
- \
- case BASE+2: /* OP D */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->DE.b[HI]); \
- break; \
- \
- case BASE+3: /* OP E */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->DE.b[LO]); \
- break; \
- \
- case BASE+4: /* OP H */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->HL.b[HI]); \
- break; \
- \
- case BASE+5: /* OP L */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->HL.b[LO]); \
- break; \
- \
- case BASE+6: /* OP (HL) */ \
- TSTATE(12); \
- OP_ON_MEM_WITH_ARG(OP,addr,BIT_NO); \
- break; \
- \
- case BASE+7: /* OP A */ \
- TSTATE(8); \
- OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->AF.b[HI]); \
- break;
-
-/* ---------------------------------------- DAA
-*/
-
-/* This alogrithm is based on info from
- http://www.worldofspectrum.org/faq/reference/z80reference.htm
-*/
-static void DAA (Z80 *cpu)
-{
- Z80Byte add=0;
- Z80Byte carry=0;
- Z80Byte nf=cpu->AF.b[LO]&N_Z80;
- Z80Byte acc=cpu->AF.b[HI];
-
- if (acc>0x99 || IS_C)
- {
- add|=0x60;
- carry=C_Z80;
- }
-
- if ((acc&0xf)>0x9 || IS_H)
- {
- add|=0x06;
- }
-
- if (nf)
- {
- cpu->AF.b[HI]-=add;
- }
- else
- {
- cpu->AF.b[HI]+=add;
- }
-
- cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]]
- | carry
- | nf
- | ((acc^cpu->AF.b[HI])&H_Z80)
- | (cpu->AF.b[HI]&(B3_Z80|B5_Z80));
-}
-
-/* ---------------------------------------- HANDLERS FOR ED OPCODES
-*/
-static void DecodeED(Z80 *cpu, Z80Byte opcode)
-{
- switch(opcode)
- {
- case 0x40: /* IN B,(C) */
- TSTATE(12);
-
- if (cpu->pread)
- {
- cpu->BC.b[HI]=cpu->pread(cpu,cpu->BC.w);
- }
- else
- {
- cpu->BC.b[HI]=0;
- }
-
- cpu->AF.b[LO]=CARRY|PSZtable[cpu->BC.b[HI]];
- SETHIDDEN(cpu->BC.b[HI]);
- break;
-
- case 0x41: /* OUT (C),B */
- TSTATE(12);
- if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->BC.b[HI]);
- break;
-
- case 0x42: /* SBC HL,BC */
- TSTATE(15);
- SBC16(cpu->HL.w,cpu->BC.w);
- break;
-
- case 0x43: /* LD (nnnn),BC */
- TSTATE(20);
- POKEW(FETCH_WORD,cpu->BC.w);
- break;
-
- case 0x44: /* NEG */
- {
- Z80Byte b;
-
- TSTATE(8);
-
- b=cpu->AF.b[HI];
- cpu->AF.b[HI]=0;
- SUB8(b);
- break;
- }
-
- case 0x45: /* RETN */
- TSTATE(14);
- cpu->IFF1=cpu->IFF2;
- POP(cpu->PC);
- break;
-
- case 0x46: /* IM 0 */
- TSTATE(8);
- cpu->IM=0;
- break;
-
- case 0x47: /* LD I,A */
- TSTATE(9);
- cpu->I=cpu->AF.b[HI];
- break;
-
- case 0x48: /* IN C,(C) */
- TSTATE(12);
-
- if (cpu->pread)
- {
- cpu->BC.b[LO]=cpu->pread(cpu,cpu->BC.w);
- }
- else
- {
- cpu->BC.b[LO]=0;
- }
-
- cpu->AF.b[LO]=CARRY|PSZtable[cpu->BC.b[LO]];
- SETHIDDEN(cpu->BC.b[LO]);
- break;
-
- case 0x49: /* OUT (C),C */
- TSTATE(12);
- if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->BC.b[LO]);
- break;
-
- case 0x4a: /* ADC HL,BC */
- TSTATE(15);
- ADC16(cpu->HL.w,cpu->BC.w);
- break;
-
- case 0x4b: /* LD BC,(nnnn) */
- TSTATE(20);
- cpu->BC.w=PEEKW(FETCH_WORD);
- break;
-
- case 0x4c: /* NEG */
- {
- Z80Byte b;
-
- TSTATE(8);
-
- b=cpu->AF.b[HI];
- cpu->AF.b[HI]=0;
- SUB8(b);
- break;
- }
-
- case 0x4d: /* RETI */
- TSTATE(14);
- CALLBACK(eZ80_RETI,0);
- cpu->IFF1=cpu->IFF2;
- POP(cpu->PC);
- break;
-
- case 0x4e: /* IM 0/1 */
- TSTATE(8);
- cpu->IM=0;
- break;
-
- case 0x4f: /* LD R,A */
- TSTATE(9);
- cpu->R=cpu->AF.b[HI];
- break;
-
- case 0x50: /* IN D,(C) */
- TSTATE(12);
-
- if (cpu->pread)
- {
- cpu->DE.b[HI]=cpu->pread(cpu,cpu->BC.w);
- }
- else
- {
- cpu->DE.b[HI]=0;
- }
-
- cpu->AF.b[LO]=CARRY|PSZtable[cpu->DE.b[HI]];
- SETHIDDEN(cpu->BC.b[HI]);
- break;
-
- case 0x51: /* OUT (C),D */
- TSTATE(12);
- if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->DE.b[HI]);
- break;
-
- case 0x52: /* SBC HL,DE */
- TSTATE(15);
- SBC16(cpu->HL.w,cpu->DE.w);
- break;
-
- case 0x53: /* LD (nnnn),DE */
- TSTATE(20);
- POKEW(FETCH_WORD,cpu->DE.w);
- break;
-
- case 0x54: /* NEG */
- {
- Z80Byte b;
-
- TSTATE(8);
-
- b=cpu->AF.b[HI];
- cpu->AF.b[HI]=0;
- SUB8(b);
- break;
- }
-
- case 0x55: /* RETN */
- TSTATE(14);
- cpu->IFF1=cpu->IFF2;
- POP(cpu->PC);
- break;
-
- case 0x56: /* IM 1 */
- TSTATE(8);
- cpu->IM=1;
- break;
-
- case 0x57: /* LD A,I */
- TSTATE(9);
- cpu->AF.b[HI]=cpu->I;
- break;
-
- case 0x58: /* IN E,(C) */
- TSTATE(12);
-
- if (cpu->pread)
- {
- cpu->DE.b[LO]=cpu->pread(cpu,cpu->BC.w);
- }
- else
- {
- cpu->BC.b[LO]=0;
- }
-
- cpu->AF.b[LO]=CARRY|PSZtable[cpu->DE.b[LO]];
- SETHIDDEN(cpu->DE.b[LO]);
- break;
-
- case 0x59: /* OUT (C),E */
- TSTATE(12);
- if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->DE.b[LO]);
- break;
-
- case 0x5a: /* ADC HL,DE */
- TSTATE(15);
- ADC16(cpu->HL.w,cpu->DE.w);
- break;
-
- case 0x5b: /* LD DE,(nnnn) */
- TSTATE(20);
- cpu->DE.w=PEEKW(FETCH_WORD);
- break;
-
- case 0x5c: /* NEG */
- {
- Z80Byte b;
-
- TSTATE(8);
-
- b=cpu->AF.b[HI];
- cpu->AF.b[HI]=0;
- SUB8(b);
- break;
- }
-
- case 0x5d: /* RETN */
- TSTATE(14);
- cpu->IFF1=cpu->IFF2;
- POP(cpu->PC);
- break;
-
- case 0x5e: /* IM 2 */
- TSTATE(8);
- cpu->IM=2;
- break;
-
- case 0x5f: /* LD A,R */
- TSTATE(9);
- cpu->AF.b[HI]=cpu->R;
- break;
-
- case 0x60: /* IN H,(C) */
- TSTATE(12);
-
- if (cpu->pread)
- {
- cpu->HL.b[HI]=cpu->pread(cpu,cpu->BC.w);
- }
- else
- {
- cpu->HL.b[HI]=0;
- }
-
- cpu->AF.b[LO]=CARRY|PSZtable[cpu->HL.b[HI]];
- SETHIDDEN(cpu->HL.b[HI]);
- break;
-
- case 0x61: /* OUT (C),H */
- TSTATE(12);
- if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->HL.b[HI]);
- break;
-
- case 0x62: /* SBC HL,HL */
- TSTATE(15);
- SBC16(cpu->HL.w,cpu->HL.w);
- break;
-
- case 0x63: /* LD (nnnn),HL */
- TSTATE(20);
- POKEW(FETCH_WORD,cpu->HL.w);
- break;
-
- case 0x64: /* NEG */
- {
- Z80Byte b;
-
- TSTATE(8);
-
- b=cpu->AF.b[HI];
- cpu->AF.b[HI]=0;
- SUB8(b);
- break;
- }
-
- case 0x65: /* RETN */
- TSTATE(14);
- cpu->IFF1=cpu->IFF2;
- POP(cpu->PC);
- break;
-
- case 0x66: /* IM 0 */
- TSTATE(8);
- cpu->IM=0;
- break;
-
- case 0x67: /* RRD */
- {
- Z80Byte b;
-
- TSTATE(18);
-
- b=PEEK(cpu->HL.w);
-
- POKE(cpu->HL.w,(b>>4)|(cpu->AF.b[HI]<<4));
- cpu->AF.b[HI]=(cpu->AF.b[HI]&0xf0)|(b&0x0f);
-
- cpu->AF.b[LO]=CARRY|PSZtable[cpu->AF.b[HI]];
- SETHIDDEN(cpu->AF.b[HI]);
- break;
- }
-
- case 0x68: /* IN L,(C) */
- TSTATE(12);
-
- if (cpu->pread)
- {
- cpu->HL.b[LO]=cpu->pread(cpu,cpu->BC.w);
- }
- else
- {
- cpu->HL.b[LO]=0;
- }
-
- cpu->AF.b[LO]=CARRY|PSZtable[cpu->HL.b[LO]];
- SETHIDDEN(cpu->HL.b[LO]);
- break;
-
- case 0x69: /* OUT (C),L */
- TSTATE(12);
- if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->HL.b[LO]);
- break;
-
- case 0x6a: /* ADC HL,HL */
- TSTATE(15);
- ADC16(cpu->HL.w,cpu->HL.w);
- break;
-
- case 0x6b: /* LD HL,(nnnn) */
- TSTATE(20);
- cpu->HL.w=PEEKW(FETCH_WORD);
- break;
-
- case 0x6c: /* NEG */
- {
- Z80Byte b;
-
- TSTATE(8);
-
- b=cpu->AF.b[HI];
- cpu->AF.b[HI]=0;
- SUB8(b);
- break;
- }
-
- case 0x6d: /* RETN */
- TSTATE(14);
- cpu->IFF1=cpu->IFF2;
- POP(cpu->PC);
- break;
-
- case 0x6e: /* IM 0/1 */
- TSTATE(8);
- cpu->IM=0;
- break;
-
- case 0x6f: /* RLD */
- {
- Z80Byte b;
-
- TSTATE(18);
-
- b=PEEK(cpu->HL.w);
-
- POKE(cpu->HL.w,(b<<4)|(cpu->AF.b[HI]&0x0f));
- cpu->AF.b[HI]=(cpu->AF.b[HI]&0xf0)|(b>>4);
-
- cpu->AF.b[LO]=CARRY|PSZtable[cpu->AF.b[HI]];
- SETHIDDEN(cpu->AF.b[HI]);
- break;
- }
-
- case 0x70: /* IN (C) */
- {
- Z80Byte b;
-
- TSTATE(12);
-
- if (cpu->pread)
- {
- b=cpu->pread(cpu,cpu->BC.w);
- }
- else
- {
- b=0;
- }
-
- cpu->AF.b[LO]=CARRY|PSZtable[b];
- SETHIDDEN(b);
- break;
- }
-
- case 0x71: /* OUT (C) */
- TSTATE(12);
- if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,0);
- break;
-
- case 0x72: /* SBC HL,SP */
- TSTATE(15);
- SBC16(cpu->HL.w,cpu->SP);
- break;
-
- case 0x73: /* LD (nnnn),SP */
- TSTATE(20);
- POKEW(FETCH_WORD,cpu->SP);
- break;
-
- case 0x74: /* NEG */
- {
- Z80Byte b;
-
- TSTATE(8);
-
- b=cpu->AF.b[HI];
- cpu->AF.b[HI]=0;
- SUB8(b);
- break;
- }
-
- case 0x75: /* RETN */
- TSTATE(14);
- cpu->IFF1=cpu->IFF2;
- POP(cpu->PC);
- break;
-
- case 0x76: /* IM 1 */
- TSTATE(8);
- cpu->IM=1;
- break;
-
- case 0x77: /* NOP */
- TSTATE(8);
- CALLBACK(eZ80_EDHook,opcode);
- break;
-
- case 0x78: /* IN A,(C) */
- TSTATE(12);
-
- if (cpu->pread)
- {
- cpu->AF.b[HI]=cpu->pread(cpu,cpu->BC.w);
- }
- else
- {
- cpu->AF.b[HI]=0;
- }
-
- cpu->AF.b[LO]=CARRY|PSZtable[cpu->AF.b[HI]];
- SETHIDDEN(cpu->AF.b[HI]);
- break;
-
- case 0x79: /* OUT (C),A */
- TSTATE(12);
- if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->AF.b[HI]);
- break;
-
- case 0x7a: /* ADC HL,SP */
- TSTATE(15);
- ADC16(cpu->HL.w,cpu->SP);
- break;
-
- case 0x7b: /* LD SP,(nnnn) */
- TSTATE(20);
- cpu->SP=PEEKW(FETCH_WORD);
- break;
-
- case 0x7c: /* NEG */
- {
- Z80Byte b;
-
- TSTATE(8);
-
- b=cpu->AF.b[HI];
- cpu->AF.b[HI]=0;
- SUB8(b);
- break;
- }
-
- case 0x7d: /* RETN */
- TSTATE(14);
- cpu->IFF1=cpu->IFF2;
- POP(cpu->PC);
- break;
-
- case 0x7e: /* IM 2 */
- TSTATE(8);
- cpu->IM=2;
- break;
-
- case 0x7f: /* NOP */
- TSTATE(8);
- CALLBACK(eZ80_EDHook,opcode);
- break;
-
- case 0xa0: /* LDI */
- TSTATE(16);
- LDI;
- break;
-
- case 0xa1: /* CPI */
- TSTATE(16);
- CPI;
- break;
-
- case 0xa2: /* INI */
- TSTATE(16);
- INI;
- break;
-
- case 0xa3: /* OUTI */
- TSTATE(16);
- OUTI;
- break;
-
- case 0xa8: /* LDD */
- TSTATE(16);
- LDD;
- break;
-
- case 0xa9: /* CPD */
- TSTATE(16);
- CPD;
- break;
-
- case 0xaa: /* IND */
- TSTATE(16);
- IND;
- break;
-
- case 0xab: /* OUTD */
- TSTATE(16);
- OUTD;
- break;
-
- case 0xb0: /* LDIR */
- TSTATE(16);
- LDI;
- if (cpu->BC.w)
- {
- TSTATE(5);
- cpu->PC-=2;
- }
- break;
-
- case 0xb1: /* CPIR */
- TSTATE(16);
- CPI;
- if (cpu->BC.w && !IS_Z)
- {
- TSTATE(5);
- cpu->PC-=2;
- }
- break;
-
- case 0xb2: /* INIR */
- TSTATE(16);
- INI;
- if (cpu->BC.w)
- {
- TSTATE(5);
- cpu->PC-=2;
- }
- break;
-
- case 0xb3: /* OTIR */
- TSTATE(16);
- OUTI;
- if (cpu->BC.w)
- {
- TSTATE(5);
- cpu->PC-=2;
- }
- break;
-
- case 0xb8: /* LDDR */
- TSTATE(16);
- LDD;
- if (cpu->BC.w)
- {
- TSTATE(5);
- cpu->PC-=2;
- }
- break;
-
- case 0xb9: /* CPDR */
- TSTATE(16);
- CPD;
- if (cpu->BC.w && !IS_Z)
- {
- TSTATE(5);
- cpu->PC-=2;
- }
- break;
-
- case 0xba: /* INDR */
- TSTATE(16);
- IND;
- if (cpu->BC.w)
- {
- TSTATE(5);
- cpu->PC-=2;
- }
- break;
-
- case 0xbb: /* OTDR */
- TSTATE(16);
- OUTD;
- if (cpu->BC.w)
- {
- TSTATE(5);
- cpu->PC-=2;
- }
- break;
-
- /* All the rest are NOP/invalid
- */
- default:
- TSTATE(8);
- CALLBACK(eZ80_EDHook,opcode);
- break;
- }
-}
-
-
-/* ---------------------------------------- HANDLERS FOR CB OPCODES
-*/
-static void DecodeCB(Z80 *cpu, Z80Byte opcode)
-{
- switch(opcode)
- {
- CB_ALU_BLOCK(0x00,RLC)
- CB_ALU_BLOCK(0x08,RRC)
- CB_ALU_BLOCK(0x10,RL)
- CB_ALU_BLOCK(0x18,RR)
- CB_ALU_BLOCK(0x20,SLA)
- CB_ALU_BLOCK(0x28,SRA)
- CB_ALU_BLOCK(0x30,SLL)
- CB_ALU_BLOCK(0x38,SRL)
-
- CB_BITMANIP_BLOCK(0x40,BIT,0)
- CB_BITMANIP_BLOCK(0x48,BIT,1)
- CB_BITMANIP_BLOCK(0x50,BIT,2)
- CB_BITMANIP_BLOCK(0x58,BIT,3)
- CB_BITMANIP_BLOCK(0x60,BIT,4)
- CB_BITMANIP_BLOCK(0x68,BIT,5)
- CB_BITMANIP_BLOCK(0x70,BIT,6)
- CB_BITMANIP_BLOCK(0x78,BIT,7)
-
- CB_BITMANIP_BLOCK(0x80,BIT_RES,0)
- CB_BITMANIP_BLOCK(0x88,BIT_RES,1)
- CB_BITMANIP_BLOCK(0x90,BIT_RES,2)
- CB_BITMANIP_BLOCK(0x98,BIT_RES,3)
- CB_BITMANIP_BLOCK(0xa0,BIT_RES,4)
- CB_BITMANIP_BLOCK(0xa8,BIT_RES,5)
- CB_BITMANIP_BLOCK(0xb0,BIT_RES,6)
- CB_BITMANIP_BLOCK(0xb8,BIT_RES,7)
-
- CB_BITMANIP_BLOCK(0xc0,BIT_SET,0)
- CB_BITMANIP_BLOCK(0xc8,BIT_SET,1)
- CB_BITMANIP_BLOCK(0xd0,BIT_SET,2)
- CB_BITMANIP_BLOCK(0xd8,BIT_SET,3)
- CB_BITMANIP_BLOCK(0xe0,BIT_SET,4)
- CB_BITMANIP_BLOCK(0xe8,BIT_SET,5)
- CB_BITMANIP_BLOCK(0xf0,BIT_SET,6)
- CB_BITMANIP_BLOCK(0xf8,BIT_SET,7)
- }
-}
-
-
-static void ShiftedDecodeCB(Z80 *cpu, Z80Byte opcode, Z80Relative offset)
-{
- Z80Word addr;
-
- /* See if we've come here from a IX/IY shift.
- */
- switch (cpu->shift)
- {
- case 0xdd:
- addr=cpu->IX.w+offset;
- break;
- case 0xfd:
- addr=cpu->IY.w+offset;
- break;
- default:
- addr=cpu->HL.w; /* Play safe... */
- break;
- }
-
- switch(opcode)
- {
- SHIFTED_CB_ALU_BLOCK(0x00,RLC)
- SHIFTED_CB_ALU_BLOCK(0x08,RRC)
- SHIFTED_CB_ALU_BLOCK(0x10,RL)
- SHIFTED_CB_ALU_BLOCK(0x18,RR)
- SHIFTED_CB_ALU_BLOCK(0x20,SLA)
- SHIFTED_CB_ALU_BLOCK(0x28,SRA)
- SHIFTED_CB_ALU_BLOCK(0x30,SLL)
- SHIFTED_CB_ALU_BLOCK(0x38,SRL)
-
- SHIFTED_CB_BITMANIP_BLOCK(0x40,BIT,0)
- SHIFTED_CB_BITMANIP_BLOCK(0x48,BIT,1)
- SHIFTED_CB_BITMANIP_BLOCK(0x50,BIT,2)
- SHIFTED_CB_BITMANIP_BLOCK(0x58,BIT,3)
- SHIFTED_CB_BITMANIP_BLOCK(0x60,BIT,4)
- SHIFTED_CB_BITMANIP_BLOCK(0x68,BIT,5)
- SHIFTED_CB_BITMANIP_BLOCK(0x70,BIT,6)
- SHIFTED_CB_BITMANIP_BLOCK(0x78,BIT,7)
-
- SHIFTED_CB_BITMANIP_BLOCK(0x80,BIT_RES,0)
- SHIFTED_CB_BITMANIP_BLOCK(0x88,BIT_RES,1)
- SHIFTED_CB_BITMANIP_BLOCK(0x90,BIT_RES,2)
- SHIFTED_CB_BITMANIP_BLOCK(0x98,BIT_RES,3)
- SHIFTED_CB_BITMANIP_BLOCK(0xa0,BIT_RES,4)
- SHIFTED_CB_BITMANIP_BLOCK(0xa8,BIT_RES,5)
- SHIFTED_CB_BITMANIP_BLOCK(0xb0,BIT_RES,6)
- SHIFTED_CB_BITMANIP_BLOCK(0xb8,BIT_RES,7)
-
- SHIFTED_CB_BITMANIP_BLOCK(0xc0,BIT_SET,0)
- SHIFTED_CB_BITMANIP_BLOCK(0xc8,BIT_SET,1)
- SHIFTED_CB_BITMANIP_BLOCK(0xd0,BIT_SET,2)
- SHIFTED_CB_BITMANIP_BLOCK(0xd8,BIT_SET,3)
- SHIFTED_CB_BITMANIP_BLOCK(0xe0,BIT_SET,4)
- SHIFTED_CB_BITMANIP_BLOCK(0xe8,BIT_SET,5)
- SHIFTED_CB_BITMANIP_BLOCK(0xf0,BIT_SET,6)
- SHIFTED_CB_BITMANIP_BLOCK(0xf8,BIT_SET,7)
- }
-}
-
-
-/* ---------------------------------------- NORMAL OPCODE DECODER
-*/
-void Z80_Decode(Z80 *cpu, Z80Byte opcode)
-{
- Z80Word *HL;
- Z80Byte *H;
- Z80Byte *L;
- Z80Relative off;
-
- /* See if we've come here from a IX/IY shift
- */
- switch (cpu->shift)
- {
- case 0xdd:
- HL=&(cpu->IX.w);
- L=cpu->IX.b+LO;
- H=cpu->IX.b+HI;
- break;
- case 0xfd:
- HL=&(cpu->IY.w);
- L=cpu->IY.b+LO;
- H=cpu->IY.b+HI;
- break;
- default:
- HL=&(cpu->HL.w);
- L=cpu->HL.b+LO;
- H=cpu->HL.b+HI;
- break;
- }
-
- switch(opcode)
- {
- case 0x00: /* NOP */
- TSTATE(4);
- break;
-
- case 0x01: /* LD BC,nnnn */
- TSTATE(10);
- cpu->BC.w=FETCH_WORD;
- break;
-
- case 0x02: /* LD (BC),A */
- TSTATE(7);
- POKE(cpu->BC.w,cpu->AF.b[HI]);
- break;
-
- case 0x03: /* INC BC */
- TSTATE(6);
- cpu->BC.w++;
- break;
-
- case 0x04: /* INC B */
- TSTATE(4);
- INC8(cpu->BC.b[HI]);
- break;
-
- case 0x05: /* DEC B */
- TSTATE(4);
- DEC8(cpu->BC.b[HI]);
- break;
-
- case 0x06: /* LD B,n */
- TSTATE(7);
- cpu->BC.b[HI]=FETCH_BYTE;
- break;
-
- case 0x07: /* RLCA */
- TSTATE(4);
- RLCA;
- break;
-
- case 0x08: /* EX AF,AF' */
- TSTATE(4);
- SWAP(cpu->AF.w,cpu->AF_);
- break;
-
- case 0x09: /* ADD HL,BC */
- TSTATE(11);
- ADD16(*HL,cpu->BC.w);
- break;
-
- case 0x0a: /* LD A,(BC) */
- TSTATE(7);
- cpu->AF.b[HI]=PEEK(cpu->BC.w);
- break;
-
- case 0x0b: /* DEC BC */
- TSTATE(6);
- cpu->BC.w--;
- break;
-
- case 0x0c: /* INC C */
- TSTATE(4);
- INC8(cpu->BC.b[LO]);
- break;
-
- case 0x0d: /* DEC C */
- TSTATE(4);
- DEC8(cpu->BC.b[LO]);
- break;
-
- case 0x0e: /* LD C,n */
- TSTATE(7);
- cpu->BC.b[LO]=FETCH_BYTE;
- break;
-
- case 0x0f: /* RRCA */
- TSTATE(4);
- RRCA;
- break;
-
- case 0x10: /* DJNZ */
- if (--(cpu->BC.b[HI]))
- {
- TSTATE(13);
- JR;
- }
- else
- {
- TSTATE(8);
- NOJR;
- }
- break;
-
- case 0x11: /* LD DE,nnnn */
- TSTATE(10);
- cpu->DE.w=FETCH_WORD;
- break;
-
- case 0x12: /* LD (DE),A */
- TSTATE(7);
- POKE(cpu->DE.w,cpu->AF.b[HI]);
- break;
-
- case 0x13: /* INC DE */
- TSTATE(6);
- cpu->DE.w++;
- break;
-
- case 0x14: /* INC D */
- TSTATE(4);
- INC8(cpu->DE.b[HI]);
- break;
-
- case 0x15: /* DEC D */
- TSTATE(4);
- DEC8(cpu->DE.b[HI]);
- break;
-
- case 0x16: /* LD D,n */
- TSTATE(7);
- cpu->DE.b[HI]=FETCH_BYTE;
- break;
-
- case 0x17: /* RLA */
- TSTATE(4);
- RLA;
- break;
-
- case 0x18: /* JR d */
- TSTATE(12);
- JR;
- break;
-
- case 0x19: /* ADD HL,DE */
- TSTATE(11);
- ADD16(*HL,cpu->DE.w);
- break;
-
- case 0x1a: /* LD A,(DE) */
- TSTATE(7);
- cpu->AF.b[HI]=PEEK(cpu->DE.w);
- break;
-
- case 0x1b: /* DEC DE */
- TSTATE(6);
- cpu->DE.w--;
- break;
-
- case 0x1c: /* INC E */
- TSTATE(4);
- INC8(cpu->DE.b[LO]);
- break;
-
- case 0x1d: /* DEC E */
- TSTATE(4);
- DEC8(cpu->DE.b[LO]);
- break;
-
- case 0x1e: /* LD E,n */
- TSTATE(7);
- cpu->DE.b[LO]=FETCH_BYTE;
- break;
-
- case 0x1f: /* RRA */
- TSTATE(4);
- RRA;
- break;
-
- case 0x20: /* JR NZ,e */
- JR_COND(!IS_Z);
- break;
-
- case 0x21: /* LD HL,nnnn */
- TSTATE(10);
- *HL=FETCH_WORD;
- break;
-
- case 0x22: /* LD (nnnn),HL */
- TSTATE(16);
- POKEW(FETCH_WORD,*HL);
- break;
-
- case 0x23: /* INC HL */
- TSTATE(6);
- (*HL)++;
- break;
-
- case 0x24: /* INC H */
- TSTATE(4);
- INC8(*H);
- break;
-
- case 0x25: /* DEC H */
- TSTATE(4);
- DEC8(*H);
- break;
-
- case 0x26: /* LD H,n */
- TSTATE(7);
- *H=FETCH_BYTE;
- break;
-
- case 0x27: /* DAA */
- TSTATE(4);
- DAA(cpu);
- break;
-
- case 0x28: /* JR Z,d */
- JR_COND(IS_Z);
- break;
-
- case 0x29: /* ADD HL,HL */
- TSTATE(11);
- ADD16(*HL,*HL);
- break;
-
- case 0x2a: /* LD HL,(nnnn) */
- TSTATE(7);
- *HL=PEEKW(FETCH_WORD);
- break;
-
- case 0x2b: /* DEC HL */
- TSTATE(6);
- (*HL)--;
- break;
-
- case 0x2c: /* INC L */
- TSTATE(4);
- INC8(*L);
- break;
-
- case 0x2d: /* DEC L */
- TSTATE(4);
- DEC8(*L);
- break;
-
- case 0x2e: /* LD L,n */
- TSTATE(7);
- *L=FETCH_BYTE;
- break;
-
- case 0x2f: /* CPL */
- TSTATE(4);
- cpu->AF.b[HI]^=0xff;
- SETFLAG(H_Z80);
- SETFLAG(N_Z80);
- SETHIDDEN(cpu->AF.b[HI]);
- break;
-
- case 0x30: /* JR NC,d */
- JR_COND(!IS_C);
- break;
-
- case 0x31: /* LD SP,nnnn */
- TSTATE(10);
- cpu->SP=FETCH_WORD;
- break;
-
- case 0x32: /* LD (nnnn),A */
- TSTATE(13);
- POKE(FETCH_WORD,cpu->AF.b[HI]);
- break;
-
- case 0x33: /* INC SP */
- TSTATE(6);
- cpu->SP++;
- break;
-
- case 0x34: /* INC (HL) */
- TSTATE(11);
- OFFSET(off);
- OP_ON_MEM(INC8,*HL+off);
- break;
-
- case 0x35: /* DEC (HL) */
- TSTATE(11);
- OFFSET(off);
- OP_ON_MEM(DEC8,*HL+off);
- break;
-
- case 0x36: /* LD (HL),n */
- TSTATE(10);
- OFFSET(off);
- cpu->mwrite(cpu,*HL+off,FETCH_BYTE);
- break;
-
- case 0x37: /* SCF */
- TSTATE(4);
- cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))
- | C_Z80
- | (cpu->AF.b[HI]&(B3_Z80|B5_Z80));
- break;
-
- case 0x38: /* JR C,d */
- JR_COND(IS_C);
- break;
-
- case 0x39: /* ADD HL,SP */
- TSTATE(11);
- ADD16(*HL,cpu->SP);
- break;
-
- case 0x3a: /* LD A,(nnnn) */
- TSTATE(13);
- cpu->AF.b[HI]=cpu->mread(cpu,FETCH_WORD);
- break;
-
- case 0x3b: /* DEC SP */
- TSTATE(6);
- cpu->SP--;
- break;
-
- case 0x3c: /* INC A */
- TSTATE(4);
- INC8(cpu->AF.b[HI]);
- break;
-
- case 0x3d: /* DEC A */
- TSTATE(4);
- DEC8(cpu->AF.b[HI]);
- break;
-
- case 0x3e: /* LD A,n */
- TSTATE(7);
- cpu->AF.b[HI]=FETCH_BYTE;
- break;
-
- case 0x3f: /* CCF */
- TSTATE(4);
-
- if (CARRY)
- SETFLAG(H_Z80);
- else
- CLRFLAG(H_Z80);
-
- cpu->AF.b[LO]^=C_Z80;
- SETHIDDEN(cpu->AF.b[HI]);
- break;
-
- LD_BLOCK(0x40,cpu->BC.b[HI],cpu->BC.b[HI])
- LD_BLOCK(0x48,cpu->BC.b[LO],cpu->BC.b[LO])
- LD_BLOCK(0x50,cpu->DE.b[HI],cpu->DE.b[HI])
- LD_BLOCK(0x58,cpu->DE.b[LO],cpu->DE.b[LO])
- LD_BLOCK(0x60,*H,cpu->HL.b[HI])
- LD_BLOCK(0x68,*L,cpu->HL.b[LO])
-
- case 0x70: /* LD (HL),B */
- TSTATE(7);
- OFFSET(off);
- cpu->mwrite(cpu,*HL+off,cpu->BC.b[HI]);
- break;
-
- case 0x71: /* LD (HL),C */
- TSTATE(7);
- OFFSET(off);
- cpu->mwrite(cpu,*HL+off,cpu->BC.b[LO]);
- break;
-
- case 0x72: /* LD (HL),D */
- TSTATE(7);
- OFFSET(off);
- cpu->mwrite(cpu,*HL+off,cpu->DE.b[HI]);
- break;
-
- case 0x73: /* LD (HL),E */
- TSTATE(7);
- OFFSET(off);
- cpu->mwrite(cpu,*HL+off,cpu->DE.b[LO]);
- break;
-
- case 0x74: /* LD (HL),H */
- TSTATE(7);
- OFFSET(off);
- cpu->mwrite(cpu,*HL+off,cpu->HL.b[HI]);
- break;
-
- case 0x75: /* LD (HL),L */
- TSTATE(7);
- OFFSET(off);
- cpu->mwrite(cpu,*HL+off,cpu->HL.b[LO]);
- break;
-
- case 0x76: /* HALT */
- TSTATE(4);
- cpu->PC--;
-
- if (!cpu->halt)
- CALLBACK(eZ80_Halt,1);
-
- cpu->halt=TRUE;
- break;
-
- case 0x77: /* LD (HL),A */
- TSTATE(7);
- OFFSET(off);
- cpu->mwrite(cpu,*HL+off,cpu->AF.b[HI]);
- break;
-
- LD_BLOCK(0x78,cpu->AF.b[HI],cpu->AF.b[HI])
-
- ALU_BLOCK(0x80,ADD8)
- ALU_BLOCK(0x88,ADC8)
- ALU_BLOCK(0x90,SUB8)
- ALU_BLOCK(0x98,SBC8)
- ALU_BLOCK(0xa0,AND)
- ALU_BLOCK(0xa8,XOR)
- ALU_BLOCK(0xb0,OR)
- ALU_BLOCK(0xb8,CMP8)
-
- case 0xc0: /* RET NZ */
- RET_COND(!IS_Z);
- break;
-
- case 0xc1: /* POP BC */
- TSTATE(10);
- POP(cpu->BC.w);
- break;
-
- case 0xc2: /* JP NZ,nnnn */
- JP_COND(!IS_Z);
- break;
-
- case 0xc3: /* JP nnnn */
- JP_COND(1);
- break;
-
- case 0xc4: /* CALL NZ,nnnn */
- CALL_COND(!IS_Z);
- break;
-
- case 0xc5: /* PUSH BC */
- TSTATE(10);
- PUSH(cpu->BC.w);
- break;
-
- case 0xc6: /* ADD A,n */
- TSTATE(7);
- ADD8(FETCH_BYTE);
- break;
-
- case 0xc7: /* RST 0 */
- RST(0);
- break;
-
- case 0xc8: /* RET Z */
- RET_COND(IS_Z);
- break;
-
- case 0xc9: /* RET */
- TSTATE(10);
- POP(cpu->PC);
- break;
-
- case 0xca: /* JP Z,nnnn */
- JP_COND(IS_Z);
- break;
-
- case 0xcb: /* CB PREFIX */
- INC_R;
-
- /* Check for previous IX/IY shift.
- */
- if (cpu->shift!=0)
- {
- Z80Relative cb_offset;
-
- TSTATE(4); /* Wild stab in the dark! */
- cb_offset=FETCH_BYTE;
- ShiftedDecodeCB(cpu,FETCH_BYTE,cb_offset);
- }
- else
- {
- DecodeCB(cpu,FETCH_BYTE);
- }
- break;
-
- case 0xcc: /* CALL Z,nnnn */
- CALL_COND(IS_Z);
- break;
-
- case 0xcd: /* CALL nnnn */
- CALL_COND(1);
- break;
-
- case 0xce: /* ADC A,n */
- ADC8(FETCH_BYTE);
- break;
-
- case 0xcf: /* RST 8 */
- RST(8);
- break;
-
- case 0xd0: /* RET NC */
- RET_COND(!IS_C);
- break;
-
- case 0xd1: /* POP DE */
- TSTATE(10);
- POP(cpu->DE.w);
- break;
-
- case 0xd2: /* JP NC,nnnn */
- JP_COND(!IS_C);
- break;
-
- case 0xd3: /* OUT (n),A */
- TSTATE(11);
- if (cpu->pwrite)
- cpu->pwrite(cpu,FETCH_BYTE,cpu->AF.b[HI]);
- else
- cpu->PC++;
- break;
-
- case 0xd4: /* CALL NC,nnnn */
- CALL_COND(!IS_C);
- break;
-
- case 0xd5: /* PUSH DE */
- TSTATE(11);
- PUSH(cpu->DE.w);
- break;
-
- case 0xd6: /* SUB A,n */
- TSTATE(7);
- SUB8(FETCH_BYTE);
- break;
-
- case 0xd7: /* RST 10 */
- RST(0x10);
- break;
-
- case 0xd8: /* RET C */
- RET_COND(IS_C);
- break;
-
- case 0xd9: /* EXX */
- TSTATE(4);
- SWAP(cpu->BC.w,cpu->BC_);
- SWAP(cpu->DE.w,cpu->DE_);
- SWAP(cpu->HL.w,cpu->HL_);
- break;
-
- case 0xda: /* JP C,nnnn */
- JP_COND(IS_C);
- break;
-
- case 0xdb: /* IN A,(n) */
- TSTATE(11);
- if (cpu->pread)
- {
- Z80Word port;
-
- port=FETCH_BYTE;
- port|=(Z80Word)cpu->AF.b[HI]<<8;
- cpu->AF.b[HI]=cpu->pread(cpu,port);
- }
- else
- cpu->PC++;
- break;
-
- case 0xdc: /* CALL C,nnnn */
- CALL_COND(IS_C);
- break;
-
- case 0xdd: /* DD PREFIX */
- TSTATE(4);
- INC_R;
-
- cpu->shift=opcode;
- Z80_Decode(cpu,FETCH_BYTE);
- break;
-
- case 0xde: /* SBC A,n */
- TSTATE(7);
- SBC8(FETCH_BYTE);
- break;
-
- case 0xdf: /* RST 18 */
- RST(0x18);
- break;
-
- case 0xe0: /* RET PO */
- RET_COND(!IS_P);
- break;
-
- case 0xe1: /* POP HL */
- TSTATE(10);
- POP(*HL);
- break;
-
- case 0xe2: /* JP PO,nnnn */
- JP_COND(!IS_P);
- break;
-
- case 0xe3: /* EX (SP),HL */
- {
- Z80Word tmp;
- TSTATE(19);
- POP(tmp);
- PUSH(*HL);
- *HL=tmp;
- }
- break;
-
- case 0xe4: /* CALL PO,nnnn */
- CALL_COND(!IS_P);
- break;
-
- case 0xe5: /* PUSH HL */
- TSTATE(10);
- PUSH(*HL);
- break;
-
- case 0xe6: /* AND A,n */
- TSTATE(7);
- AND(FETCH_BYTE);
- break;
-
- case 0xe7: /* RST 20 */
- RST(0x20);
- break;
-
- case 0xe8: /* RET PE */
- RET_COND(IS_P);
- break;
-
- case 0xe9: /* JP (HL) */
- TSTATE(4);
- cpu->PC=*HL;
- break;
-
- case 0xea: /* JP PE,nnnn */
- JP_COND(IS_P);
- break;
-
- case 0xeb: /* EX DE,HL */
- TSTATE(4);
- SWAP(cpu->DE.w,*HL);
- break;
-
- case 0xec: /* CALL PE,nnnn */
- CALL_COND(IS_P);
- break;
-
- case 0xed: /* ED PREFIX */
- INC_R;
- DecodeED(cpu,FETCH_BYTE);
- break;
-
- case 0xee: /* XOR A,n */
- TSTATE(7);
- XOR(FETCH_BYTE);
- break;
-
- case 0xef: /* RST 28 */
- RST(0x28);
- break;
-
- case 0xf0: /* RET P */
- RET_COND(!IS_S);
- break;
-
- case 0xf1: /* POP AF */
- TSTATE(10);
- POP(cpu->AF.w);
- break;
-
- case 0xf2: /* JP P,nnnn */
- JP_COND(!IS_S);
- break;
-
- case 0xf3: /* DI */
- TSTATE(4);
- cpu->IFF1=0;
- cpu->IFF2=0;
- break;
-
- case 0xf4: /* CALL P,nnnn */
- CALL_COND(!IS_S);
- break;
-
- case 0xf5: /* PUSH AF */
- TSTATE(10);
- PUSH(cpu->AF.w);
- break;
-
- case 0xf6: /* OR A,n */
- TSTATE(7);
- OR(FETCH_BYTE);
- break;
-
- case 0xf7: /* RST 30 */
- RST(0x30);
- break;
-
- case 0xf8: /* RET M */
- RET_COND(IS_S);
- break;
-
- case 0xf9: /* LD SP,HL */
- TSTATE(6);
- cpu->SP=*HL;
- break;
-
- case 0xfa: /* JP M,nnnn */
- JP_COND(IS_S);
- break;
-
- case 0xfb: /* EI */
- TSTATE(4);
- cpu->IFF1=1;
- cpu->IFF2=1;
- break;
-
- case 0xfc: /* CALL M,nnnn */
- CALL_COND(IS_S);
- break;
-
- case 0xfd: /* FD PREFIX */
- TSTATE(4);
- INC_R;
-
- cpu->shift=opcode;
- Z80_Decode(cpu,FETCH_BYTE);
- break;
-
- case 0xfe: /* CP A,n */
- TSTATE(7);
- CMP8(FETCH_BYTE);
- break;
-
- case 0xff: /* RST 38 */
- RST(0x38);
- break;
-
- }
-}
-
-
-/* END OF FILE */
diff --git a/include/z80_private.h b/include/z80_private.h
index 4a19324..dc4f6b9 100644
--- a/include/z80_private.h
+++ b/include/z80_private.h
@@ -2,7 +2,7 @@
z80 - Z80 emulation
- Copyright (C) 2006 Ian Cowburn (ianc@noddybox.demon.co.uk)
+ Copyright (C) 2006 Ian Cowburn (ianc@noddybox.co.uk)
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
@@ -29,6 +29,8 @@
#ifndef Z80_PRIVATE_H
#define Z80_PRIVATE_H "$Id$"
+#include "z80_config.h"
+
#ifndef TRUE
#define TRUE 1
#endif
@@ -43,40 +45,10 @@
/* ---------------------------------------- TYPES
*/
-typedef signed short sword;
-
-typedef union
-{
- Z80Word w;
- Z80Byte b[2];
-} Z80Reg;
-
-struct Z80
+struct Z80Private
{
Z80Val cycle;
- Z80Word PC;
-
- Z80Reg AF;
- Z80Reg BC;
- Z80Reg DE;
- Z80Reg HL;
-
- Z80Word AF_;
- Z80Word BC_;
- Z80Word DE_;
- Z80Word HL_;
-
- Z80Reg IX;
- Z80Reg IY;
-
- Z80Word SP;
-
- Z80Byte IFF1;
- Z80Byte IFF2;
- Z80Byte IM;
- Z80Byte I;
- Z80Byte R;
int halt;
Z80Byte shift;
@@ -85,10 +57,12 @@ struct Z80
Z80Byte devbyte;
int nmi;
+#ifndef ENABLE_ARRAY_MEMORY
Z80ReadMemory disread;
Z80ReadMemory mread;
Z80WriteMemory mwrite;
+#endif
Z80ReadPort pread;
Z80WritePort pwrite;
@@ -98,6 +72,16 @@ struct Z80
int last_cb;
};
+#define PRIV cpu->priv
+
+
+/* ---------------------------------------- ARRAY MEMORY
+*/
+
+#ifdef ENABLE_ARRAY_MEMORY
+extern Z80Byte Z80_MEMORY[];
+#endif
+
/* ---------------------------------------- MACROS
*/
@@ -114,9 +98,9 @@ struct Z80
int f; \
\
for(f=0;f<MAX_PER_CALLBACK;f++) \
- if (cpu->callback[r][f]) \
- cpu->last_cb &= \
- cpu->callback[r][f](cpu,d); \
+ if (PRIV->callback[r][f]) \
+ PRIV->last_cb &= \
+ PRIV->callback[r][f](cpu,d);\
} while(0)
/* Flag register
@@ -139,15 +123,50 @@ struct Z80
#define SETFLAG(f) SET(cpu->AF.b[LO],f)
#define CLRFLAG(f) CLR(cpu->AF.b[LO],f)
-#define PEEK(addr) (cpu->mread(cpu,addr))
+#ifdef ENABLE_ARRAY_MEMORY
+
+#define PEEK(addr) Z80_MEMORY[addr]
+
+static inline Z80Word PEEKW(Z80Word addr)
+{
+ return (PEEK(addr) | (Z80Word)PEEK(addr+1)<<8);
+}
+
+#define POKE(addr,val) do \
+ { \
+ Z80Word ba=addr; \
+ if (ba>=RAMBOT && ba<=RAMTOP) \
+ Z80_MEMORY[ba]=val; \
+ } while(0)
+
+#define POKEW(addr,val) do \
+ { \
+ Z80Word wa=addr; \
+ Z80Word wv=val; \
+ POKE(wa,wv); \
+ POKE(wa+1,wv>>8); \
+ } while(0)
+
+
+#define FETCH_BYTE (Z80_MEMORY[cpu->PC++])
+#define FETCH_WORD (cpu->PC+=2, \
+ Z80_MEMORY[cpu->PC-2]| \
+ ((Z80Word)Z80_MEMORY[cpu->PC-1]<<8))
+
+#else
+
+#define PEEK(addr) (PRIV->mread(cpu,addr))
#define PEEKW(addr) FPEEKW(cpu,addr)
-#define POKE(addr,val) cpu->mwrite(cpu,addr,val)
+#define POKE(addr,val) PRIV->mwrite(cpu,addr,val)
#define POKEW(addr,val) FPOKEW(cpu,addr,val)
-#define FETCH_BYTE (cpu->mread(cpu,cpu->PC++))
+#define FETCH_BYTE (PRIV->mread(cpu,cpu->PC++))
#define FETCH_WORD (cpu->PC+=2,FPEEKW(cpu,cpu->PC-2))
+#endif
+
+
#define IS_C (cpu->AF.b[LO]&C_Z80)
#define IS_N (cpu->AF.b[LO]&N_Z80)
#define IS_P (cpu->AF.b[LO]&P_Z80)
@@ -157,21 +176,34 @@ struct Z80
#define CARRY IS_C
-#define IS_IX_IY (cpu->shift==0xdd || cpu->shift==0xfd)
+#define IS_IX_IY (PRIV->shift==0xdd || PRIV->shift==0xfd)
#define OFFSET(off) off=(IS_IX_IY ? (Z80Relative)FETCH_BYTE:0)
-#define TSTATE(n) cpu->cycle+=n
+#define TSTATE(n) PRIV->cycle+=n
#define ADD_R(v) cpu->R=((cpu->R&0x80)|((cpu->R+(v))&0x7f))
#define INC_R ADD_R(1)
+#ifdef ENABLE_ARRAY_MEMORY
+
+#define PUSH(REG) do \
+ { \
+ Z80Word pv=REG; \
+ cpu->SP-=2; \
+ POKE(cpu->SP,pv); \
+ POKE(cpu->SP+1,pv>>8); \
+ } while(0)
+
+#else
+
#define PUSH(REG) do \
{ \
Z80Word pushv=REG; \
cpu->SP-=2; \
- cpu->mwrite(cpu,cpu->SP,pushv); \
- cpu->mwrite(cpu,cpu->SP+1,pushv>>8);\
+ PRIV->mwrite(cpu,cpu->SP,pushv); \
+ PRIV->mwrite(cpu,cpu->SP+1,pushv>>8);\
} while(0)
+#endif
#define POP(REG) do \
{ \
@@ -197,11 +229,11 @@ struct Z80
#define OUT(P,V) do \
{ \
- if (cpu->pwrite) \
- cpu->pwrite(cpu,P,V); \
+ if (PRIV->pwrite) \
+ PRIV->pwrite(cpu,P,V); \
} while(0)
-#define IN(P) (cpu->pread?cpu->pread(cpu,P):0)
+#define IN(P) (PRIV->pread?PRIV->pread(cpu,P):0)