summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2006-08-20 22:31:42 +0000
committerIan C <ianc@noddybox.co.uk>2006-08-20 22:31:42 +0000
commitf295f65db435ab7cb384e44e1dd74dc6d7a34853 (patch)
tree7d9fe765fc9507e6ad800773c51bc5da5d0ae9df
parent87ace20633ba711243e336630e2c9a8546516598 (diff)
Initial compilable version
-rw-r--r--Makefile10
-rw-r--r--emma.c156
-rw-r--r--runall4
-rw-r--r--rundoc4
-rw-r--r--runprelim4
-rw-r--r--z80.c190
-rw-r--r--z80.h9
-rw-r--r--z80_decode.c2981
-rw-r--r--z80_private.h71
9 files changed, 1952 insertions, 1477 deletions
diff --git a/Makefile b/Makefile
index 2cb9ffb..961b9f5 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@
#
# -------------------------------------------------------------------------
#
-# $Id: Makefile,v 1.1.1.1 2006-08-20 17:39:42 ianc Exp $
+# $Id: Makefile,v 1.2 2006-08-20 22:31:42 ianc Exp $
#
# This CFLAGS assumes that gcc is being used.
@@ -29,16 +29,18 @@ CFLAGS = -Wall -Werror -pedantic -ansi -O2 -finline-functions
TARGET = emma
-SOURCE = z80.c \
+SOURCE = z80.c \
+ z80_decode \
emma.c
-OBJECTS = z80.o \
+OBJECTS = z80.o \
+ z80_decode.o \
emma.o
all: $(TARGET) emucpm.hex
$(TARGET): $(OBJECTS)
- ld -o $(TARGET) $(OBJECTS)
+ cc -o $(TARGET) $(OBJECTS)
emucpm.hex: emucpm.z80
tpasm -P Z80 -o intel emucpm.hex emucpm.z80
diff --git a/emma.c b/emma.c
index f2ae2c2..41bdb1a 100644
--- a/emma.c
+++ b/emma.c
@@ -31,7 +31,6 @@ static const char id[]="$Id$";
#include <stdarg.h>
#include "z80.h"
-#include "expr.h"
#define TRUE 1
@@ -41,10 +40,17 @@ static const char id[]="$Id$";
#define LO(w) ((w)&0xff)
#define MK(h,l) (((Z80Word)(h))<<8|(l))
+typedef struct
+{
+ Z80Word address;
+ const char *label;
+} Z80Label;
+
/* ---------------------------------------- GLOBALS
*/
static Z80 *z80;
static Z80Byte mem[0x10000];
+static int memctl[256];
static sig_atomic_t stop=FALSE;
static int quit=FALSE;
@@ -68,6 +74,7 @@ static void Log(const char *format, ...);
static void Run(char *p);
static Z80Word Address(const char *p);
static const char *GetLabel(Z80 *z80, Z80Word addr);
+static const char *Disassemble(Z80Word *addr);
/* ---------------------------------------- SIGNALS
@@ -176,7 +183,7 @@ static void DisplayState(void)
Log("I=%2.2x IM=%2.2x R=%2.2x ",s.I,s.IM,s.R);
Log("IFF1=%2.2x IFF2=%2.2x\n",s.IFF1,s.IFF2);
Log("%4.4x: ",s.PC);
- Log("%s\n",Z80Disassemble(z80,&s.PC));
+ Log("%s\n",Disassemble(&s.PC));
}
@@ -195,12 +202,12 @@ static int StrEq(const char *a, const char *b)
}
-static int Expand(void *client, const char *p, long *res)
+static int Expand(const char *p, long *res)
{
Z80State s;
int ok=TRUE;
- Z80GetState((Z80 *)client,&s);
+ Z80GetState(z80,&s);
if (StrEq(p,"AF"))
*res=s.AF;
@@ -280,21 +287,21 @@ static int Expand(void *client, const char *p, long *res)
n=Address(p+1);
*res=MK(mem[n+1],mem[n]);
}
- else /* Check for labels */
+ else /* Check for labels */
{
- int f;
-
- ok=FALSE;
-
- for(f=0;label && label[f].label;f++)
- {
- if (StrEq(p,label[f].label))
- {
- *res=label[f].address;
- ok=TRUE;
- break;
- }
- }
+ int f;
+
+ ok=FALSE;
+
+ for(f=0;label && label[f].label;f++)
+ {
+ if (StrEq(p,label[f].label))
+ {
+ *res=label[f].address;
+ ok=TRUE;
+ break;
+ }
+ }
}
return ok;
@@ -305,19 +312,29 @@ static Z80Word Address(const char *p)
{
long e=0;
- if (!ExprEval(p,&e,Expand,z80))
- Log("%s\n",ExprError());
+ if (!Expand(p,&e))
+ {
+ e=strtol(p,NULL,0);
+ }
return (Z80Word)e;
}
+static const char *Disassemble(Z80Word *addr)
+{
+ return Z80Disassemble(z80,addr);
+}
+
+
static Z80Val Val(const char *p)
{
long e=0;
- if (!ExprEval(p,&e,Expand,z80))
- Log("%s\n",ExprError());
+ if (!Expand(p,&e))
+ {
+ e=strtol(p,NULL,0);
+ }
return (Z80Val)e;
}
@@ -527,7 +544,7 @@ static void DoDis(int no, const char *arg[])
if ((l=GetLabel(z80,orig)))
Log("*** %s ***\n",l);
- Log("%4.4x: %s\n",orig,Z80Disassemble(z80,&addr));
+ Log("%4.4x: %s\n",orig,Disassemble(&addr));
prev=len;
len-=(addr-orig);
}
@@ -707,6 +724,8 @@ static void DoRun(int no, const char *arg[])
static void DoUntil(int no, const char *arg[])
{
+ Log("No supported\n");
+#if 0
if (no<2)
{
Log("Missing arguments\n");
@@ -744,6 +763,7 @@ static void DoUntil(int no, const char *arg[])
}
stop=FALSE;
+#endif
}
@@ -766,16 +786,23 @@ static void DoSilent(int no, const char *arg[])
static void DoRange(int no, const char *arg[])
{
+ int f;
+
if (no<3)
{
Log("Missing arguments\n");
return;
}
- bottom=Address(arg[1]);
- top=Address(arg[2]);
+ bottom=(Address(arg[1]))/256;
+ top=Address(arg[2])/256;
+
+ for(f=0;f<256;f++)
+ {
+ memctl[f]=(f>=bottom && f<=top);
+ }
- Log("Writable memory between 0x%4.4x and 0x%4.4x\n",bottom,top);
+ Log("Writable memory between 0x%4.4x and 0x%4.4x\n",bottom*256,top*256);
}
@@ -921,77 +948,6 @@ static void Run(char *cmd)
/* ---------------------------------------- MEMORY
*/
-static Z80Byte ReadMem(Z80 *z80, Z80Word addr)
-{
- if (mem_trace)
- Log("PEEK(0x%4.4x)=0x%2.2x\n",addr,mem[addr]);
-
- return mem[addr];
-}
-
-
-static Z80Word ReadMemWord(Z80 *z80, Z80Word addr)
-{
- Z80Word w;
-
- w=MK(mem[addr+1],mem[addr]);
-
- if (mem_trace)
- Log("PEEKW(0x%4.4x)=0x%4.4x\n",addr,w);
-
- return w;
-}
-
-
-static Z80Byte ReadMemDis(Z80 *z80, Z80Word addr)
-{
- return mem[addr];
-}
-
-
-static void WriteMem(Z80 *z80, Z80Word addr, Z80Byte val)
-{
- if (addr>=bottom && addr<=top)
- {
- mem[addr]=val;
-
- if (mem_trace)
- Log("POKE(0x%4.4x)=0x%2.2x\n",addr,mem[addr]);
- }
- else
- {
- if (mem_trace)
- Log("POKE(0x%4.4x)=0x%2.2x [BLOCKED]\n",addr,mem[addr]);
- }
-}
-
-
-static void WriteMemWord(Z80 *z80, Z80Word addr, Z80Word val)
-{
- static const char *block_str[3]={""," [ONE BYTE BLOCKED]"," [BLOCKED]"};
- Z80Byte lo,hi;
- int block=0;
-
- lo=LO(val);
- hi=HI(val);
-
- if (addr>=bottom && addr<=top)
- mem[addr]=lo;
- else
- block++;
-
- addr++;
-
- if (addr>=bottom && addr<=top)
- mem[addr]=hi;
- else
- block++;
-
- if (mem_trace)
- Log("POKEW(0x%4.4x)=0x%4.4x%s\n",addr,val,block_str[block]);
-}
-
-
static Z80Byte ReadPort(Z80 *z80, Z80Word addr)
{
Z80Byte b=0xff;
@@ -1131,9 +1087,11 @@ int main(int argc, char *argv[])
{
const char *autoarg[2]={".","auto"};
char buff[1024];
+ int f;
+
+ for(f=0;f<256;f++) memctl[f]=1;
- z80=Z80Init(WriteMem,ReadMem,WriteMemWord,ReadMemWord,
- WritePort,ReadPort,ReadMemDis);
+ z80=Z80Init(mem,memctl,WritePort,ReadPort);
if (!z80)
{
diff --git a/runall b/runall
new file mode 100644
index 0000000..62f2455
--- /dev/null
+++ b/runall
@@ -0,0 +1,4 @@
+i emucpm.hex
+l zexall.com 0x100
+s
+r 0x100
diff --git a/rundoc b/rundoc
new file mode 100644
index 0000000..7dd9a73
--- /dev/null
+++ b/rundoc
@@ -0,0 +1,4 @@
+i emucpm.hex
+l zexdoc.com 0x100
+s
+r 0x100
diff --git a/runprelim b/runprelim
new file mode 100644
index 0000000..609efd3
--- /dev/null
+++ b/runprelim
@@ -0,0 +1,4 @@
+i emucpm.hex
+l prelim.com 0x100
+s
+r 0x100
diff --git a/z80.c b/z80.c
index 6745fe1..11e466b 100644
--- a/z80.c
+++ b/z80.c
@@ -28,19 +28,14 @@
Z80
*/
+#include <stdlib.h>
+
#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];
+static const char ident_z80_header[]=Z80_H;
+static const char ident_z80_private_header[]=Z80_PRIVATE_H;
/* ---------------------------------------- PRIVATE FUNCTIONS
@@ -48,54 +43,13 @@ static Z80Byte Ztable[512];
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;
- }
+ Z80_InitialiseInternals();
}
static void Z80_CheckInterrupt(Z80 *cpu)
@@ -116,7 +70,7 @@ static void Z80_CheckInterrupt(Z80 *cpu)
TSTATE(2);
cpu->IFF1=0;
cpu->nmi=FALSE;
- PUSH(PC);
+ PUSH(cpu->PC);
cpu->PC=0x66;
}
else if (cpu->IFF1)
@@ -140,12 +94,12 @@ static void Z80_CheckInterrupt(Z80 *cpu)
break;
case 1:
- PUSH(PC);
+ PUSH(cpu->PC);
cpu->PC=0x38;
break;
case 2:
- PUSH(PC);
+ PUSH(cpu->PC);
cpu->PC=(Z80Word)cpu->I*256+cpu->devbyte;
break;
}
@@ -170,7 +124,7 @@ Z80 *Z80Init(Z80Memory memory,
InitTables();
- if (!write_byte || !read_byte || !write_word || !read_word)
+ if (!memory || !memcontrol)
return NULL;
cpu=malloc(sizeof *cpu);
@@ -198,18 +152,17 @@ 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->AF.w=0xffff;
+ cpu->BC.w=0xffff;
+ cpu->DE.w=0xffff;
+ cpu->HL.w=0xffff;
+ cpu->AF_.w=0xffff;
+ cpu->BC_.w=0xffff;
+ cpu->DE_.w=0xffff;
+ cpu->HL_.w=0xffff;
- cpu->IX=0xffff;
- cpu->IY=0xffff;
+ cpu->IX.w=0xffff;
+ cpu->IY.w=0xffff;
cpu->SP=0xffff;
cpu->IFF1=0;
@@ -297,66 +250,57 @@ void Z80Exec(Z80 *cpu)
void Z80GetState(Z80 *cpu, Z80State *state)
{
-#define COPY(a) state->a=cpu->a
- COPY(cycle);
+ state->cycle= cpu->cycle;
- SET_HI(state->AF,cpu->A);
- SET_LO(state->AF,cpu->F);
+ state->AF = cpu->AF.w;
+ state->BC = cpu->BC.w;
+ state->DE = cpu->DE.w;
+ state->HL = cpu->HL.w;
- COPY(BC);
- COPY(DE);
- COPY(HL);
+ state->AF_ = cpu->AF_.w;
+ state->BC_ = cpu->BC_.w;
+ state->DE_ = cpu->DE_.w;
+ state->HL_ = cpu->HL_.w;
- COPY(AF_);
- COPY(BC_);
- COPY(DE_);
- COPY(HL_);
+ state->IX = cpu->IX.w;
+ state->IY = cpu->IY.w;
- COPY(IX);
- COPY(IY);
+ state->SP = cpu->SP;
+ state->PC = cpu->PC;
- COPY(SP);
- COPY(PC);
-
- COPY(IFF1);
- COPY(IFF2);
- COPY(IM);
- COPY(I);
- COPY(R);
-#undef COPY
+ state->IFF1 = cpu->IFF1;
+ state->IFF2 = cpu->IFF2;
+ state->IM = cpu->IM;
+ state->I = cpu->I;
+ state->R = cpu->R;
}
-void Z80SetState(Z80 *cpu, Z80State *state)
+void Z80SetState(Z80 *cpu, const 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
+ cpu->cycle = state->cycle;
+
+ cpu->AF.w = state->AF;
+ cpu->BC.w = state->BC;
+ cpu->DE.w = state->DE;
+ cpu->HL.w = state->HL;
+
+ cpu->AF_.w = state->AF_;
+ cpu->BC_.w = state->BC_;
+ cpu->DE_.w = state->DE_;
+ cpu->HL_.w = state->HL_;
+
+ cpu->IX.w = state->IX;
+ cpu->IY.w = state->IY;
+
+ cpu->SP = state->SP;
+ cpu->PC = state->PC;
+
+ cpu->IFF1 = state->IFF1;
+ cpu->IFF2 = state->IFF2;
+ cpu->IM = state->IM;
+ cpu->I = state->I;
+ cpu->R = state->R;
}
@@ -365,4 +309,16 @@ Z80Val Z80Cycles(Z80 *cpu)
return cpu->cycle;
}
+
+const char *Z80Disassemble(Z80 *cpu, Z80Word *addr)
+{
+#ifdef Z80_DISASSEMBLER_ENABLED
+ (*addr)+=4;
+ return "NO DISASSEMBLER";
+#else
+ (*addr)+=4;
+ return "NO DISASSEMBLER";
+#endif
+}
+
/* END OF FILE */
diff --git a/z80.h b/z80.h
index 814b32d..745ee48 100644
--- a/z80.h
+++ b/z80.h
@@ -33,6 +33,10 @@
/* ---------------------------------------- TYPES
*/
+/* Remove this to disable the disassembler (saving some memory)
+*/
+#define Z80_DISASSEMBLER_ENABLED
+
/* The processor
*/
struct Z80;
@@ -213,6 +217,11 @@ Z80Val Z80Cycles(Z80 *cpu);
void Z80GetState(Z80 *cpu, Z80State *state);
void Z80SetState(Z80 *cpu, const Z80State *state);
+
+/* Simple disassembly. addr is updated on exit.
+*/
+const char *Z80Disassemble(Z80 *cpu, Z80Word *addr);
+
#endif
/* END OF FILE */
diff --git a/z80_decode.c b/z80_decode.c
index c323d1f..6bb34f5 100644
--- a/z80_decode.c
+++ b/z80_decode.c
@@ -28,1549 +28,2064 @@
Z80
*/
-#include "z80_private.h"
+#include <stdlib.h>
-/* ---------------------------------------- ARITHMETIC OPS
-*/
-#define ADD_8_BIT(REG,VAL) \
-do \
-{ \
- Z80Word w; \
- w=REG+(Z80Word)VAL; \
- cpu->F=SZtable[w]; \
- if ((REG^w^VAL)&H_Z80) cpu->F|=H_Z80; \
- if ((VAL^REG^0x80)&(REG^w)&0x80) cpu->F|=P_Z80; \
- SETHIDDEN(w); \
- REG=w; \
-} while(0)
-
-
-#define ADC_8_BIT(REG,VAL) \
-do \
-{ \
- Z80Word w; \
- w=(REG+(Z80Word)VAL+CARRY)&0x1ff; \
- cpu->F=SZtable[w]; \
- if ((REG^w^VAL)&H_Z80) cpu->F|=H_Z80; \
- if ((VAL^REG^0x80)&(REG^w)&0x80) cpu->F|=P_Z80; \
- SETHIDDEN(w); \
- REG=w; \
-} while(0)
-
-
-#define SUB_8_BIT(REG,VAL) \
-do \
-{ \
- Z80Word w; \
- w=(REG-(Z80Word)VAL)&0x1ff; \
- cpu->F=SZtable[w]|N_Z80; \
- if ((REG^w^VAL)&H_Z80) cpu->F|=H_Z80; \
- if ((VAL^REG^0x80)&(REG^w)&0x80) cpu->F|=P_Z80; \
- SETHIDDEN(w); \
- REG=w; \
-} while(0)
-
-
-#define CMP_8_BIT(REG,VAL) \
-do \
-{ \
- Z80Word w; \
- w=(REG-(Z80Word)VAL)&0x1ff; \
- cpu->F=SZtable[w]|N_Z80; \
- if ((REG^w^VAL)&H_Z80) cpu->F|=H_Z80; \
- if ((VAL^REG^0x80)&(REG^w)&0x80) cpu->F|=P_Z80; \
- SETHIDDEN(VAL); \
-} while(0)
-
-
-#define SBC_8_BIT(REG,VAL) \
-do \
-{ \
- Z80Word w; \
- w=(REG-(Z80Word)VAL-CARRY)&0x1ff; \
- cpu->F=SZtable[w]|N_Z80; \
- if ((REG^w^VAL)&H_Z80) cpu->F|=H_Z80; \
- if ((VAL^REG^0x80)&(REG^w)&0x80) cpu->F|=P_Z80; \
- SETHIDDEN(w); \
- REG=w; \
-} while(0)
-
-
-#define ADD_16_BIT(REG,VAL) \
-do \
-{ \
- Z80Val w; \
- w=REG+(Z80Val)VAL; \
- cpu->F&=(S_Z80|Z_Z80|V_Z80); \
- if (w>0xffff) cpu->F|=C_Z80; \
- if ((REG^w^VAL)&0x1000) cpu->F|=H_Z80; \
- SETHIDDEN(w>>8); \
- REG=w; \
-} while(0)
-
-
-#define ADC_16_BIT(REG,VAL) \
-do \
-{ \
- Z80Val w; \
- w=REG+(Z80Val)VAL+CARRY; \
- cpu->F&=(S_Z80|Z_Z80|V_Z80); \
- if (w>0xffff) cpu->F|=C_Z80; \
- if ((REG^w^VAL)&0x1000) cpu->F|=H_Z80; \
- SETHIDDEN(w>>8); \
- REG=w; \
-} while(0)
-
-
-#define SBC_16_BIT(REG,VAL) \
-do \
-{ \
- Z80Val w; \
- w=REG-(Z80Val)VAL-CARRY; \
- cpu->F=N_Z80; \
- if (w&0x8000) cpu->F|=S_Z80; \
- if ((w&0xffff)==0) cpu->F|=Z_Z80; \
- if (w>0xffff) cpu->F|=C_Z80; \
- if ((REG^w^VAL)&0x1000) cpu->F|=H_Z80; \
- if ((VAL^REG)&(VAL^w)&0x8000) cpu->F|=P_Z80; \
- SETHIDDEN(w>>8); \
- REG=w; \
-} while(0)
-
-
-#define INC8(REG) \
-do \
-{ \
- REG++; \
- cpu->F=CARRY|SZtable[REG]; \
- if (w&0x80) cpu->F|=P_Z80; \
- if (w&0x0f) cpu->F|=H_Z80; \
-} while(0)
-
-
-#define DEC8(REG) \
-do \
-{ \
- cpu->F=N_Z80|CARRY; \
- if (w&0x80) cpu->F|=P_Z80; \
- if (w&0x0f) cpu->F|=H_Z80; \
- REG--; \
- cpu->F|=SZtable[REG]; \
-} while(0)
+#include "z80.h"
+#include "z80_private.h"
+static const char ident[]="$Id$";
-/* ---------------------------------------- ROTATE AND SHIFT OPS
+/* ---------------------------------------- TABLES AND INIT
*/
-#define RRCA \
-do \
-{ \
- cpu->F=(cpu->F&0xec)|cpu->A&C_Z80; \
- cpu->A=(cpu->A>>1)|(cpu->A<<7); \
- SETHIDDEN(cpu->A); \
-} while(0)
-
-
-#define RRA \
-do \
-{ \
- Z80Byte c; \
- c=CARRY; \
- cpu->F=(cpu->F&0xec)|cpu->A&C_Z80; \
- cpu->A=(cpu->A>>1)|(c<<7); \
- SETHIDDEN(cpu->A); \
-} while(0)
-
-
-#define RRC(REG) \
-do \
-{ \
- Z80Byte c; \
- c=REG&C_Z80; \
- REG=(REG>>1)|(REG<<7); \
- cpu->F=PSZtable[REG]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define RR(REG) \
-do \
-{ \
- Z80Byte c; \
- c=REG&C_Z80; \
- REG=(REG>>1)|(CARRY<<7); \
- cpu->F=PSZtable[REG]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define RLCA \
-do \
-{ \
- cpu->F=(cpu->F&0xec)|(cpu->A>>7); \
- cpu->A=(cpu->A<<1)|(cpu->A>>7); \
- SETHIDDEN(cpu->A); \
-} while(0)
-
-
-#define RLA \
-do \
-{ \
- Z80Byte c; \
- c=CARRY; \
- cpu->F=(cpu->F&0xec)|(cpu->A>>7); \
- cpu->A=(cpu->A<<1)|c; \
- SETHIDDEN(cpu->A); \
-} while(0)
-
-
-#define RLC(REG) \
-do \
-{ \
- Z80Byte c; \
- c=REG>>7; \
- REG=(REG<<1)|c; \
- cpu->F=PSZtable[REG]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define RL(REG) \
-do \
-{ \
- Z80Byte c; \
- c=REG>>7; \
- REG=(REG<<1)|CARRY; \
- cpu->F=PSZtable[REG]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define SRL(REG) \
-do \
-{ \
- Z80Byte c; \
- c=REG&Z80_C; \
- REG>>=1; \
- cpu->F=PSZtable[REG]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define SRA(REG) \
-do \
-{ \
- Z80Byte c; \
- c=REG&Z80_C; \
- REG=(REG>>1)|(REG&0x80); \
- cpu->F=PSZtable[REG]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define SLL(REG) \
-do \
-{ \
- Z80Byte c; \
- c=REG>>7; \
- REG=(REG<<1)|1; \
- cpu->F=PSZtable[REG]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define SLA(REG) \
-do \
-{ \
- Z80Byte c; \
- c=REG>>7; \
- REG=REG<<1; \
- cpu->F=PSZtable[REG]|c; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-/* ---------------------------------------- FLOW OPS
+static const unsigned char partab[256] = {
+ 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
+ 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
+ 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
+ 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
+ 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
+ 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
+ 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
+ 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
+ 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
+ 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
+ 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
+ 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
+ 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
+ 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
+ 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
+ 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
+};
+
+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;
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
*/
-#define CALL(COND) \
-do \
-{ \
- if (COND) \
- { \
- PUSH(cpu->PC+2); \
- cpu->PC=PEEKW(cpu->PC); \
- } \
- else \
- { \
- cpu->PC+=2; \
- } \
-} \
-while(0)
-
-
-#define JP(COND) \
-do \
-{ \
- if (COND) \
- { \
- cpu->PC=PEEKW(cpu->PC); \
- } \
- else \
- { \
- cpu->PC+=2; \
- } \
-} \
-while(0)
-
-
-#define JR(COND) \
-do \
-{ \
- if (COND) \
- { \
- cpu->PC+=(Z80Relative)PEEK(cpu->PC)+1; \
- } \
- else \
- { \
- cpu->PC++; \
- } \
-} \
-while(0)
+void Z80_InitialiseInternals(void)
+{
+ Z80Word f;
+ Z80Reg r;
+ r.w=0x1234;
-/* ---------------------------------------- BOOLEAN OPS
-*/
-#define AND(REG,VAL) \
-do \
-{ \
- REG&=VAL; \
- cpu->F=PSZtable[REG]|H_Z80; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define OR(REG,VAL) \
-do \
-{ \
- REG|=VAL; \
- cpu->F=PSZtable[REG]; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define XOR(REG,VAL) \
-do \
-{ \
- REG^=VAL; \
- cpu->F=PSZtable[REG]; \
- SETHIDDEN(REG); \
-} while(0)
-
-
-#define BIT(REG,B) \
-do \
-{ \
- cpu->F=CARRY|H_Z80; \
- if (REG&&(1<<B)) \
- { \
- if (B==7) cpu->F|=S_Z80; \
- if (B==5) cpu->F|=B5_Z80; \
- if (B==3) cpu->F|=B3_Z80; \
- } \
- else \
- { \
- cpu->F|=Z_Z80; \
- } \
-} while(0)
+ if (r.b[0] == 0x12)
+ {
+ HI=0;
+ LO=1;
+ }
+ else if (r.b[1] == 0x12)
+ {
+ HI=1;
+ LO=0;
+ }
+ else
+ {
+ exit(1);
+ }
+ /* 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;
+ }
+}
-/* ---------------------------------------- GENERAL MACROS
-*/
-/* Decides whether the offset for IX/IY should be fetched, or used
- from the store for a CB instruction
+/* ---------------------------------------- ARITHMETIC OPS
*/
-#define GETREL (cpu->use_cb_off ? cpu->cb_off : (Z80Relative)FETCH_BYTE)
+static void ADD8(Z80 *cpu, Z80Byte VAL)
+{
+ Z80Word w;
+ w=cpu->AF.b[HI]+(Z80Word)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)&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80;
+ SETHIDDEN(w);
+ cpu->AF.b[HI]=w;
+}
-/* ---------------------------------------- GENERAL UTILS
-*/
+static void ADC8(Z80 *cpu, Z80Byte VAL)
+{
+ Z80Word w;
+ w=(cpu->AF.b[HI]+(Z80Word)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)&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80;
+ SETHIDDEN(w);
+ cpu->AF.b[HI]=w;
+}
-/* This code based on the DAA opcode from YAZE, (c) Frank D. Cringle
-*/
-static void DAA (Z80 *cpu)
+
+static void SUB8(Z80 *cpu, Z80Byte VAL)
{
- Z80Word AF;
- Z80Word acu,temp,cbits;
+ Z80Word w;
+ w=(cpu->AF.b[HI]-(Z80Word)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]^0x80)&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80;
+ SETHIDDEN(w);
+ cpu->AF.b[HI]=w;
+}
- AF=(Z80Word)cpu->A<<8|cpu->F;
- acu=cpu->A;
- temp=acu&0xf;
- cbits=CARRY;
- if (IS_N) /* last operation was a subtract */
- {
- int hd = cbits || acu > 0x99;
- if (IS_H || (temp > 9)) /* adjust low digit */
- {
- if (temp > 5)
- {
- CLR(AF,H_Z80);
- }
+static void CMP8(Z80 *cpu, Z80Byte VAL)
+{
+ Z80Word w;
+ w=(cpu->AF.b[HI]-(Z80Word)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]^0x80)&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80;
+ SETHIDDEN(VAL);
+}
- acu -= 6;
- acu &= 0xff;
- }
- if (hd) /* adjust high digit */
- acu -= 0x160;
- }
- else /* last operation was an add */
- {
- if (IS_H || (temp > 9)) /* adjust low digit */
- {
- if (temp>9)
- {
- SET(AF,H_Z80);
- }
- else
- {
- CLR(AF,H_Z80);
- }
- acu += 6;
- }
- if (cbits || ((acu & 0x1f0) > 0x90)) /* adjust high digit */
- acu += 0x60;
- }
- cbits |= (acu >> 8) & 1;
- acu &= 0xff;
- AF = (acu << 8) | (acu & 0xa8) | ((acu == 0) << 6) |
- (AF & 0x12) | partab[acu] | cbits;
+static void SBC8(Z80 *cpu, Z80Byte VAL)
+{
+ Z80Word w;
+ w=(cpu->AF.b[HI]-(Z80Word)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]^0x80)&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80;
+ SETHIDDEN(w);
+ cpu->AF.b[HI]=w;
+}
+
+
+static Z80Word ADD16(Z80 *cpu, Z80Word REG, Z80Word VAL)
+{
+ 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);
+ return w;
+}
+
- cpu->A=(AF>>8);
- cpu->F=(AF&0xff);
- SETHIDDEN(cpu->A);
+static Z80Word ADC16(Z80 *cpu, Z80Word REG, Z80Word VAL)
+{
+ Z80Val w;
+ w=REG+(Z80Val)VAL+CARRY;
+ 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);
+ return w;
+}
+
+
+static Z80Word SBC16(Z80 *cpu, Z80Word REG, Z80Word VAL)
+{
+ 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 ((REG^w^VAL)&0x1000) cpu->AF.b[LO]|=H_Z80;
+ if ((VAL^REG)&(VAL^w)&0x8000) cpu->AF.b[LO]|=P_Z80;
+ SETHIDDEN(w>>8);
+ return w;
}
+static Z80Byte INC8(Z80 *cpu, Z80Byte REG)
+{
+ REG++;
+ cpu->AF.b[LO]=CARRY|SZtable[REG];
+ if (REG&0x80) cpu->AF.b[LO]|=P_Z80;
+ if (REG&0x0f) cpu->AF.b[LO]|=H_Z80;
+ return REG;
+}
-/* ---------------------------------------- HANDLERS FOR CB OPCODES
+
+static Z80Byte DEC8(Z80 *cpu, Z80Byte REG)
+{
+ cpu->AF.b[LO]=N_Z80|CARRY;
+ if (REG&0x80) cpu->AF.b[LO]|=P_Z80;
+ if (REG&0x0f) cpu->AF.b[LO]|=H_Z80;
+ REG--;
+ cpu->AF.b[LO]|=SZtable[REG];
+ return REG;
+}
+
+
+/* ---------------------------------------- ROTATE AND SHIFT OPS
*/
-static void DecodeCB(Z80 *cpu, Z80Byte opcode)
+static void RRCA(Z80 *cpu)
{
- switch(opcode)
- {
- }
+ cpu->AF.b[LO]=(cpu->AF.b[LO]&0xec)|(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]);
+}
- Z80Byte bmh,bmm,bml;
- /* Split up the opcode into it's bitmasks
- */
- bmh=(opcode>>6)&3;
- bmm=(opcode>>3)&7;
- bml=opcode&7;
+static void RRA(Z80 *cpu)
+{
+ Z80Byte c;
+ c=CARRY;
+ cpu->AF.b[LO]=(cpu->AF.b[LO]&0xec)|(cpu->AF.b[HI]&C_Z80);
+ cpu->AF.b[HI]=(cpu->AF.b[HI]>>1)|(c<<7);
+ SETHIDDEN(cpu->AF.b[HI]);
+}
- /* Instruction set 00
- */
- if (bmh==0x00)
- {
- CBOp_00(cpu,opcode,bmh,bmm,bml);
- return;
- }
- /* Instruction set 01 (BIT)
- */
- if (bmh==0x01)
- {
- CBOp_01(cpu,opcode,bmh,bmm,bml);
- return;
- }
+static Z80Byte RRC(Z80 *cpu, Z80Byte REG)
+{
+ Z80Byte c;
+ c=REG&C_Z80;
+ REG=(REG>>1)|(REG<<7);
+ cpu->AF.b[LO]=PSZtable[REG]|c;
+ SETHIDDEN(REG);
+ return REG;
+}
- /* Instruction set 10 (RES) and 11 (SET)
- */
- CBOp_ResSet(cpu,opcode,bmh,bmm,bml);
+
+static Z80Byte RR(Z80 *cpu, Z80Byte REG)
+{
+ Z80Byte c;
+ c=REG&C_Z80;
+ REG=(REG>>1)|(CARRY<<7);
+ cpu->AF.b[LO]=PSZtable[REG]|c;
+ SETHIDDEN(REG);
+ return REG;
}
+static void RLCA(Z80 *cpu)
+{
+ cpu->AF.b[LO]=(cpu->AF.b[LO]&0xec)|(cpu->AF.b[HI]>>7);
+ cpu->AF.b[HI]=(cpu->AF.b[HI]<<1)|(cpu->AF.b[HI]>>7);
+ SETHIDDEN(cpu->AF.b[HI]);
+}
+
+
+static void RLA(Z80 *cpu)
+{
+ Z80Byte c;
+ c=CARRY;
+ cpu->AF.b[LO]=(cpu->AF.b[LO]&0xec)|(cpu->AF.b[HI]>>7);
+ cpu->AF.b[HI]=(cpu->AF.b[HI]<<1)|c;
+ SETHIDDEN(cpu->AF.b[HI]);
+}
-/* ---------------------------------------- OPCODE DECODER
+static Z80Byte RLC(Z80 *cpu, Z80Byte REG)
+{
+ Z80Byte c;
+ c=REG>>7;
+ REG=(REG<<1)|c;
+ cpu->AF.b[LO]=PSZtable[REG]|c;
+ SETHIDDEN(REG);
+ return REG;
+}
+
+
+static Z80Byte RL(Z80 *cpu, Z80Byte REG)
+{
+ Z80Byte c;
+ c=REG>>7;
+ REG=(REG<<1)|CARRY;
+ cpu->AF.b[LO]=PSZtable[REG]|c;
+ SETHIDDEN(REG);
+ return REG;
+}
+
+
+static Z80Byte SRL(Z80 *cpu, Z80Byte REG)
+{
+ Z80Byte c;
+ c=REG&C_Z80;
+ REG>>=1;
+ cpu->AF.b[LO]=PSZtable[REG]|c;
+ SETHIDDEN(REG);
+ return REG;
+}
+
+
+static Z80Byte SRA(Z80 *cpu, Z80Byte REG)
+{
+ Z80Byte c;
+ c=REG&C_Z80;
+ REG=(REG>>1)|(REG&0x80);
+ cpu->AF.b[LO]=PSZtable[REG]|c;
+ SETHIDDEN(REG);
+ return REG;
+}
+
+
+static Z80Byte SLL(Z80 *cpu, Z80Byte REG)
+{
+ Z80Byte c;
+ c=REG>>7;
+ REG=(REG<<1)|1;
+ cpu->AF.b[LO]=PSZtable[REG]|c;
+ SETHIDDEN(REG);
+ return REG;
+}
+
+
+static Z80Byte SLA(Z80 *cpu, Z80Byte REG)
+{
+ Z80Byte c;
+ c=REG>>7;
+ REG=REG<<1;
+ cpu->AF.b[LO]=PSZtable[REG]|c;
+ SETHIDDEN(REG);
+ return REG;
+}
+
+
+/* ---------------------------------------- BOOLEAN OPS
*/
-void Z80_Decode(Z80 *cpu, Z80Byte opcode)
+static void AND(Z80 *cpu, Z80Byte VAL)
{
- Z80Byte bmh,bmm,bml;
+ cpu->AF.b[HI]&=VAL;
+ cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]]|H_Z80;
+ SETHIDDEN(cpu->AF.b[HI]);
+}
- /* IX/IY shifts
- */
- if (opcode==0xdd || opcode==0xfd)
- {
- TSTATE(4);
- INC_R;
- cpu->shift=opcode;
- Z80_Decode(cpu,FETCH_BYTE);
- return;
- }
+static void OR(Z80 *cpu, Z80Byte VAL)
+{
+ cpu->AF.b[HI]|=VAL;
+ cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]];
+ SETHIDDEN(cpu->AF.b[HI]);
+}
- /* CB shifts
- */
- if (opcode==0xcb)
- {
- INC_R;
- /* Check for previous IX/IY shift.
- */
- if (cpu->shift!=0)
- {
- cpu->use_cb_off=TRUE;
- cpu->cb_off=(Z80Relative)FETCH_BYTE;
- }
+static void XOR(Z80* cpu, Z80Byte VAL)
+{
+ cpu->AF.b[HI]^=VAL;
+ cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]];
+ SETHIDDEN(cpu->AF.b[HI]);
+}
- DecodeCB(cpu,FETCH_BYTE);
- return;
- }
- /* DE shifts
- */
- if (opcode==0xed)
+static void BIT(Z80 *cpu, Z80Byte REG, Z80Byte B)
+{
+ cpu->AF.b[LO]=CARRY|H_Z80;
+ if (REG&&(1<<B))
{
- INC_R;
- DecodeED(cpu,FETCH_BYTE);
- return;
+ if (B==7) cpu->AF.b[LO]|=S_Z80;
+ if (B==5) cpu->AF.b[LO]|=B5_Z80;
+ if (B==3) cpu->AF.b[LO]|=B3_Z80;
}
+ else
+ {
+ cpu->AF.b[LO]|=Z_Z80;
+ }
+}
- *** NEW ***
- INC_R;
+/* ---------------------------------------- BLOCK OPERATIONS
+*/
+static void LDI(Z80 *cpu)
+{
+ Z80Byte b;
- switch(opcode)
- {
- case 0x00: /* NOP */
- TSTATE(4);
- break;
+ b=PEEK(cpu->HL.w);
+ POKE(cpu->DE.w,b);
+ cpu->DE.w++;
+ cpu->HL.w++;
+ cpu->BC.w--;
- case 0x01: /* LD BC, nnnn */
- TSTATE(10);
- cpu->BC=FETCH_WORD;
- break;
+ CLRFLAG(H_Z80);
+ CLRFLAG(N_Z80);
- case 0x02:
- TSTATE(7);
- break;
+ if (cpu->BC.w)
+ SETFLAG(P_Z80);
+ else
+ CLRFLAG(P_Z80);
- case 0x03:
- TSTATE(4);
- break;
+ SETHIDDEN(cpu->AF.b[HI]+b);
+}
- case 0x04:
- TSTATE(4);
- break;
+static void LDD(Z80 *cpu)
+{
+ Z80Byte b;
- case 0x05:
- TSTATE(4);
- break;
+ b=PEEK(cpu->HL.w);
+ POKE(cpu->DE.w,b);
+ cpu->DE.w--;
+ cpu->HL.w--;
+ cpu->BC.w--;
- case 0x06:
- TSTATE(4);
- break;
+ CLRFLAG(H_Z80);
+ CLRFLAG(N_Z80);
- case 0x07:
- TSTATE(4);
- break;
+ if (cpu->BC.w)
+ SETFLAG(P_Z80);
+ else
+ CLRFLAG(P_Z80);
- case 0x08:
- TSTATE(4);
- break;
+ SETHIDDEN(cpu->AF.b[HI]+b);
+}
- case 0x09:
- TSTATE(4);
- break;
+static void CPI(Z80 *cpu)
+{
+ Z80Byte c,b;
- case 0x0a:
- TSTATE(4);
- break;
+ c=CARRY;
+ b=PEEK(cpu->HL.w);
- case 0x0b:
- TSTATE(4);
- break;
+ CMP8(cpu,b);
- case 0x0c:
- TSTATE(4);
- break;
+ if (c)
+ SETFLAG(C_Z80);
+ else
+ CLRFLAG(C_Z80);
- case 0x0d:
- TSTATE(4);
- break;
+ cpu->HL.w++;
+ cpu->BC.w--;
- case 0x0e:
- TSTATE(4);
- break;
+ if (cpu->BC.w)
+ SETFLAG(P_Z80);
+ else
+ CLRFLAG(P_Z80);
+}
- case 0x0f:
- TSTATE(4);
- break;
+static void CPD(Z80 *cpu)
+{
+ Z80Byte c,b;
- case 0x10:
- TSTATE(4);
- break;
+ c=CARRY;
+ b=PEEK(cpu->HL.w);
- case 0x11:
- TSTATE(4);
- break;
+ CMP8(cpu,b);
- case 0x12:
- TSTATE(4);
- break;
+ if (c)
+ SETFLAG(C_Z80);
+ else
+ CLRFLAG(C_Z80);
- case 0x13:
- TSTATE(4);
- break;
+ cpu->HL.w--;
+ cpu->BC.w--;
- case 0x14:
- TSTATE(4);
- break;
+ if (cpu->BC.w)
+ SETFLAG(P_Z80);
+ else
+ CLRFLAG(P_Z80);
+}
- case 0x15:
- TSTATE(4);
- break;
+static void INI(Z80 *cpu)
+{
+ Z80Word w;
+ Z80Byte b;
- case 0x16:
- TSTATE(4);
- break;
+ b=IN(cpu->BC.w);
+ POKE(cpu->HL.w,b);
- case 0x17:
- TSTATE(4);
- break;
+ cpu->BC.b[HI]--;
+ cpu->HL.w++;
- case 0x18:
- TSTATE(4);
- break;
+ cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]];
+ SETHIDDEN(cpu->BC.b[HI]);
- case 0x19:
- TSTATE(4);
- break;
+ w=(((Z80Word)cpu->BC.b[LO])&0xff)+b;
- case 0x1a:
- TSTATE(4);
- break;
+ if (b&0x80)
+ SETFLAG(N_Z80);
- case 0x1b:
- TSTATE(4);
- break;
+ if (w&0x100)
+ {
+ SETFLAG(C_Z80);
+ SETFLAG(H_Z80);
+ }
+ else
+ {
+ CLRFLAG(C_Z80);
+ CLRFLAG(H_Z80);
+ }
+}
- case 0x1c:
- TSTATE(4);
- break;
+static void IND(Z80 *cpu)
+{
+ Z80Word w;
+ Z80Byte b;
- case 0x1d:
- TSTATE(4);
- break;
+ b=IN(cpu->BC.w);
+ POKE(cpu->HL.w,b);
- case 0x1e:
- TSTATE(4);
- break;
+ cpu->BC.b[HI]--;
+ cpu->HL.w--;
- case 0x1f:
- TSTATE(4);
- break;
+ cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]];
+ SETHIDDEN(cpu->BC.b[HI]);
- case 0x20:
- TSTATE(4);
- break;
+ w=(((Z80Word)cpu->BC.b[LO])&0xff)+b;
- case 0x21:
- TSTATE(4);
- break;
+ if (b&0x80)
+ SETFLAG(N_Z80);
- case 0x22:
- TSTATE(4);
- break;
+ if (w&0x100)
+ {
+ SETFLAG(C_Z80);
+ SETFLAG(H_Z80);
+ }
+ else
+ {
+ CLRFLAG(C_Z80);
+ CLRFLAG(H_Z80);
+ }
+}
- case 0x23:
- TSTATE(4);
- break;
+static void OUTI(Z80 *cpu)
+{
+ OUT(cpu->BC.w,PEEK(cpu->HL.w));
- case 0x24:
- TSTATE(4);
- break;
+ cpu->HL.w++;
+ cpu->BC.b[HI]--;
- case 0x25:
- TSTATE(4);
- break;
+ cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]];
+ SETHIDDEN(cpu->BC.b[HI]);
+}
- case 0x26:
- TSTATE(4);
- break;
+static void OUTD(Z80 *cpu)
+{
+ OUT(cpu->BC.w,PEEK(cpu->HL.w));
- case 0x27:
- TSTATE(4);
- break;
+ cpu->HL.w--;
+ cpu->BC.b[HI]--;
- case 0x28:
- TSTATE(4);
- break;
+ cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]];
+ SETFLAG(N_Z80);
+ SETHIDDEN(cpu->BC.b[HI]);
+}
- case 0x29:
- TSTATE(4);
- break;
- case 0x2a:
- TSTATE(4);
- break;
- case 0x2b:
- TSTATE(4);
- break;
+/* ---------------------------------------- GENERAL MACROS
+*/
- case 0x2c:
- TSTATE(4);
- break;
+/* Decides whether the offset for IX/IY should be fetched, or used
+ from the store for a CB instruction
+*/
+#define GETREL (cpu->use_cb_off ? cpu->cb_off : (Z80Relative)FETCH_BYTE)
- case 0x2d:
- TSTATE(4);
- break;
- case 0x2e:
- TSTATE(4);
- break;
+/* ---------------------------------------- DAA
+*/
- case 0x2f:
- TSTATE(4);
- break;
+/* This code based on the DAA opcode from YAZE, (c) Frank D. Cringle
+*/
+static void DAA (Z80 *cpu)
+{
+ Z80Word AF,acu,temp,cbits;
- case 0x30:
- TSTATE(4);
- break;
+ AF=cpu->AF.w;
+ acu=cpu->AF.b[HI];
+ temp=acu&0xf;
+ cbits=CARRY;
- case 0x31:
- TSTATE(4);
- break;
+ if (IS_N) /* last operation was a subtract */
+ {
+ int hd = cbits || acu > 0x99;
+ if (IS_H || (temp > 9)) /* adjust low digit */
+ {
+ if (temp > 5)
+ {
+ CLR(AF,H_Z80);
+ }
- case 0x32:
- TSTATE(4);
- break;
+ acu -= 6;
+ acu &= 0xff;
+ }
+ if (hd) /* adjust high digit */
+ acu -= 0x160;
+ }
+ else /* last operation was an add */
+ {
+ if (IS_H || (temp > 9)) /* adjust low digit */
+ {
+ if (temp>9)
+ {
+ SET(AF,H_Z80);
+ }
+ else
+ {
+ CLR(AF,H_Z80);
+ }
+ acu += 6;
+ }
+ if (cbits || ((acu & 0x1f0) > 0x90)) /* adjust high digit */
+ acu += 0x60;
+ }
- case 0x33:
- TSTATE(4);
- break;
+ cbits |= (acu >> 8) & 1;
+ acu &= 0xff;
+ AF = (acu << 8) | (acu & 0xa8) | ((acu == 0) << 6) |
+ (AF & 0x12) | partab[acu] | cbits;
- case 0x34:
- TSTATE(4);
- break;
+ cpu->AF.w=AF;
+ SETHIDDEN(cpu->AF.b[HI]);
+}
- case 0x35:
- TSTATE(4);
- break;
- case 0x36:
- TSTATE(4);
- break;
+/* ---------------------------------------- DECODE AND REGISTER SELECTION
+*/
- case 0x37:
- TSTATE(4);
- break;
+/* Get the 16 bit register to use according to the bitmask
+*/
+static Z80Word *Get16(Z80 *cpu, Z80Byte bm)
+{
+ if (bm==0x00)
+ return &cpu->BC.w;
- case 0x38:
- TSTATE(4);
- break;
+ if (bm==0x01)
+ return &cpu->DE.w;
- case 0x39:
- TSTATE(4);
- break;
+ if (bm==0x02)
+ {
+ if (cpu->shift==0xdd)
+ return &cpu->IX.w;
- case 0x3a:
- TSTATE(4);
- break;
+ if (cpu->shift==0xfd)
+ return &cpu->IY.w;
- case 0x3b:
- TSTATE(4);
- break;
+ return &cpu->HL.w;
+ }
- case 0x3c:
- TSTATE(4);
- break;
+ return &cpu->SP;
+}
- case 0x3d:
- TSTATE(4);
- break;
- case 0x3e:
- TSTATE(4);
- break;
+/* Get the 16 bit register to use according to the bitmask, ignoring the shift
+*/
+static Z80Word *Get16_HL(Z80 *cpu, Z80Byte bm)
+{
+ if (bm==0x00)
+ return &cpu->BC.w;
- case 0x3f:
- TSTATE(4);
- break;
+ if (bm==0x01)
+ return &cpu->DE.w;
- case 0x40:
- TSTATE(4);
- break;
+ if (bm==0x02)
+ return &cpu->HL.w;
- case 0x41:
- TSTATE(4);
- break;
+ return &cpu->SP;
+}
- case 0x42:
- TSTATE(4);
- break;
- case 0x43:
- TSTATE(4);
- break;
+/* Get the 16 bit register to use according to the bitmask,
+ with AF instead of SP
+*/
+static Z80Word *Get16_AF(Z80 *cpu, Z80Byte bm)
+{
+ if (bm==0x00)
+ return &cpu->BC.w;
- case 0x44:
- TSTATE(4);
- break;
+ if (bm==0x01)
+ return &cpu->DE.w;
- case 0x45:
- TSTATE(4);
- break;
+ if (bm==0x02)
+ {
+ if (cpu->shift==0xdd)
+ return &cpu->IX.w;
- case 0x46:
- TSTATE(4);
- break;
+ if (cpu->shift==0xfd)
+ return &cpu->IY.w;
- case 0x47:
- TSTATE(4);
- break;
+ return &cpu->HL.w;
+ }
- case 0x48:
- TSTATE(4);
- break;
+ return &cpu->AF.w;
+}
- case 0x49:
- TSTATE(4);
- break;
- case 0x4a:
- TSTATE(4);
- break;
+/* Get the 8 bit register to use according to the bitmask .
+ Returns NULL for (HL), (I[XY]+d)
+*/
+static Z80Byte *Get8(Z80 *cpu, Z80Byte bm)
+{
+ if (bm==0x07)
+ return &cpu->AF.b[HI];
- case 0x4b:
- TSTATE(4);
- break;
+ if (bm==0x00)
+ return &cpu->BC.b[HI];
- case 0x4c:
- TSTATE(4);
- break;
+ if (bm==0x01)
+ return &cpu->BC.b[LO];
- case 0x4d:
- TSTATE(4);
- break;
+ if (bm==0x02)
+ return &cpu->DE.b[HI];
- case 0x4e:
- TSTATE(4);
- break;
+ if (bm==0x03)
+ return &cpu->DE.b[LO];
- case 0x4f:
- TSTATE(4);
- break;
+ if (bm==0x04)
+ {
+ if (cpu->shift==0xdd)
+ return &cpu->IX.b[HI];
- case 0x50:
- TSTATE(4);
- break;
+ if (cpu->shift==0xfd)
+ return &cpu->IY.b[HI];
- case 0x51:
- TSTATE(4);
- break;
+ return &cpu->HL.b[HI];
+ }
- case 0x52:
- TSTATE(4);
- break;
+ if (bm==0x05)
+ {
+ if (cpu->shift==0xdd)
+ return &cpu->IX.b[LO];
- case 0x53:
- TSTATE(4);
- break;
+ if (cpu->shift==0xfd)
+ return &cpu->IY.b[LO];
- case 0x54:
- TSTATE(4);
- break;
+ return &cpu->HL.b[LO];
+ }
- case 0x55:
- TSTATE(4);
- break;
+ return NULL;
+}
- case 0x56:
- TSTATE(4);
- break;
- case 0x57:
- TSTATE(4);
- break;
+/* Get the 8 bit register to use according to the bitmask, ignoring the shift.
+ Returns NULL for (HL)
+*/
+static Z80Byte *Get8_HL(Z80 *cpu, Z80Byte bm)
+{
+ if (bm==0x07)
+ return &cpu->AF.b[HI];
- case 0x58:
- TSTATE(4);
- break;
+ if (bm==0x00)
+ return &cpu->BC.b[HI];
- case 0x59:
- TSTATE(4);
- break;
+ if (bm==0x01)
+ return &cpu->BC.b[LO];
- case 0x5a:
- TSTATE(4);
- break;
+ if (bm==0x02)
+ return &cpu->DE.b[HI];
- case 0x5b:
- TSTATE(4);
- break;
+ if (bm==0x03)
+ return &cpu->DE.b[LO];
- case 0x5c:
- TSTATE(4);
- break;
+ if (bm==0x04)
+ return &cpu->HL.b[HI];
- case 0x5d:
- TSTATE(4);
- break;
+ if (bm==0x05)
+ return &cpu->HL.b[LO];
- case 0x5e:
- TSTATE(4);
- break;
+ return NULL;
+}
- case 0x5f:
- TSTATE(4);
- break;
- case 0x60:
- TSTATE(4);
- break;
+/* Get the address pointed to by HL, or the relative one depending on the shift
+*/
+static Z80Word GetHL(Z80 *cpu)
+{
+ if (cpu->shift==0)
+ return cpu->HL.w;
- case 0x61:
- TSTATE(4);
- break;
+ if (cpu->shift==0xdd)
+ {
+ TSTATE(8);
+ return cpu->IX.w+GETREL;
+ }
- case 0x62:
- TSTATE(4);
- break;
+ if (cpu->shift==0xfd)
+ {
+ TSTATE(8);
+ return cpu->IY.w+GETREL;
+ }
- case 0x63:
- TSTATE(4);
- break;
+ return 0;
+}
- case 0x64:
- TSTATE(4);
- break;
- case 0x65:
- TSTATE(4);
- break;
+/* Get the value of HL, IX, IY depending on the shift
+*/
+static Z80Word GetHLVal(Z80 *cpu)
+{
+ if (cpu->shift==0)
+ return cpu->HL.w;
- case 0x66:
- TSTATE(4);
- break;
+ if (cpu->shift==0xdd)
+ return cpu->IX.w;
- case 0x67:
- TSTATE(4);
- break;
+ if (cpu->shift==0xfd)
+ return cpu->IY.w;
- case 0x68:
- TSTATE(4);
- break;
+ return 0;
+}
- case 0x69:
- TSTATE(4);
- break;
- case 0x6a:
- TSTATE(4);
- break;
+/* Get the register (HL, IX, IY) depending on the shift
+*/
+static Z80Word* GetHLReg(Z80 *cpu)
+{
+ if (cpu->shift==0)
+ return &cpu->HL.w;
- case 0x6b:
- TSTATE(4);
- break;
+ if (cpu->shift==0xdd)
+ return &cpu->IX.w;
- case 0x6c:
- TSTATE(4);
- break;
+ if (cpu->shift==0xfd)
+ return &cpu->IY.w;
- case 0x6d:
- TSTATE(4);
- break;
+ return 0;
+}
- case 0x6e:
- TSTATE(4);
- break;
- case 0x6f:
- TSTATE(4);
- break;
+/* Get a condition depending on the bitmask
+*/
+static Z80Byte GetCond(Z80 *cpu, Z80Byte bm)
+{
+ if (bm==0x00) /* NZ */
+ return !IS_Z;
- case 0x70:
- TSTATE(4);
- break;
+ if (bm==0x01) /* Z */
+ return IS_Z;
- case 0x71:
- TSTATE(4);
- break;
+ if (bm==0x02) /* NC */
+ return !IS_C;
- case 0x72:
- TSTATE(4);
- break;
+ if (bm==0x03) /* C */
+ return IS_C;
- case 0x73:
- TSTATE(4);
- break;
+ if (bm==0x04) /* PO */
+ return !IS_P;
- case 0x74:
- TSTATE(4);
- break;
+ if (bm==0x05) /* PE */
+ return IS_P;
- case 0x75:
- TSTATE(4);
- break;
+ if (bm==0x06) /* P */
+ return !IS_S;
- case 0x76:
- TSTATE(4);
- break;
+ if (bm==0x07) /* M */
+ return IS_S;
- case 0x77:
- TSTATE(4);
- break;
+ return 0;
+}
- case 0x78:
- TSTATE(4);
- break;
- case 0x79:
- TSTATE(4);
- break;
+/* ---------------------------------------- HANDLERS FOR ED OPCODES
+*/
- case 0x7a:
- TSTATE(4);
- break;
- case 0x7b:
- TSTATE(4);
- break;
+static void EDOp_01(Z80 *cpu, Z80Byte opcode,
+ Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
+{
+ if (bml==0x00) /* IN r,(C) */
+ {
+ Z80Byte *reg;
+ Z80Byte v;
- case 0x7c:
- TSTATE(4);
- break;
+ TSTATE(12);
- case 0x7d:
- TSTATE(4);
- break;
+ reg=Get8_HL(cpu,bmm);
+ v=IN(cpu->BC.w);
- case 0x7e:
- TSTATE(4);
- break;
+ cpu->AF.b[LO]=(cpu->AF.b[LO]&C_Z80)|PSZtable[v];
+ SETHIDDEN(v);
- case 0x7f:
- TSTATE(4);
- break;
+ if (reg)
+ *reg=v;
- case 0x80:
- TSTATE(4);
- break;
+ return;
+ }
- case 0x81:
- TSTATE(4);
- break;
+ if (bml==0x01) /* OUT r,(C) */
+ {
+ Z80Byte *reg;
- case 0x82:
- TSTATE(4);
- break;
+ TSTATE(12);
- case 0x83:
- TSTATE(4);
- break;
+ reg=Get8_HL(cpu,bmm);
+ OUT(cpu->BC.w,reg ? *reg:0);
- case 0x84:
- TSTATE(4);
- break;
+ return;
+ }
- case 0x85:
- TSTATE(4);
- break;
+ if (bml==0x02)
+ {
+ Z80Word *reg;
- case 0x86:
- TSTATE(4);
- break;
+ TSTATE(15);
- case 0x87:
- TSTATE(4);
- break;
+ reg=Get16_HL(cpu,bmm>>1);
- case 0x88:
- TSTATE(4);
- break;
+ if (bmm&1) /* ADC HL,rr */
+ {
+ cpu->HL.w=ADC16(cpu,cpu->HL.w,*reg);
+ }
+ else /* SBC HL,rr */
+ {
+ cpu->HL.w=SBC16(cpu,cpu->HL.w,*reg);
+ }
- case 0x89:
- TSTATE(4);
- break;
+ return;
+ }
- case 0x8a:
- TSTATE(4);
- break;
+ if (bml==0x03)
+ {
+ Z80Word a;
+ Z80Word *reg;
- case 0x8b:
- TSTATE(4);
- break;
+ TSTATE(20);
- case 0x8c:
- TSTATE(4);
- break;
+ a=FETCH_WORD;
+ reg=Get16_HL(cpu,bmm>>1);
- case 0x8d:
- TSTATE(4);
- break;
+ if (bmm&1) /* LD rr,(nn) */
+ {
+ *reg=PEEKW(a);
+ }
+ else /* LD (nn),rr */
+ {
+ POKEW(a,*reg);
+ }
- case 0x8e:
- TSTATE(4);
- break;
+ return;
+ }
- case 0x8f:
- TSTATE(4);
- break;
+ if (bml==0x04) /* NEG */
+ {
+ Z80Byte v;
- case 0x90:
- TSTATE(4);
- break;
+ TSTATE(8);
- case 0x91:
- TSTATE(4);
- break;
+ v=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
- case 0x92:
- TSTATE(4);
- break;
+ SUB8(cpu,v);
- case 0x93:
- TSTATE(4);
- break;
+ return;
+ }
- case 0x94:
- TSTATE(4);
- break;
+ if (bml==0x05)
+ {
+ TSTATE(14);
- case 0x95:
- TSTATE(4);
- break;
+ if (bmm&1) /* RETI */
+ {
+ POP(cpu->PC);
+ CALLBACK(eZ80_RETI,0);
+ }
+ else /* RETN */
+ {
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ }
- case 0x96:
- TSTATE(4);
- break;
+ return;
+ }
- case 0x97:
- TSTATE(4);
- break;
+ if (bml==0x06) /* IM n */
+ {
+ TSTATE(8);
- case 0x98:
- TSTATE(4);
- break;
+ switch(bmm&0x3)
+ {
+ case 0x00:
+ case 0x01:
+ cpu->IM=0;
+ break;
+
+ case 0x02:
+ cpu->IM=1;
+ break;
+
+ case 0x03:
+ cpu->IM=2;
+ break;
+ }
- case 0x99:
- TSTATE(4);
- break;
+ return;
+ }
- case 0x9a:
- TSTATE(4);
- break;
+ if (bml==0x07)
+ {
+ Z80Byte b;
- case 0x9b:
- TSTATE(4);
- break;
+ switch(bmm)
+ {
+ case 0x00: /* LD I,A */
+ TSTATE(9);
+ cpu->I=cpu->AF.b[HI];
+ break;
+ case 0x01: /* LD R,A */
+ TSTATE(9);
+ cpu->R=cpu->AF.b[HI];
+ break;
+ case 0x02: /* LD A,I */
+ TSTATE(9);
+ cpu->AF.b[HI]=cpu->I;
+ break;
+ case 0x03: /* LD A,R */
+ TSTATE(9);
+ cpu->AF.b[HI]=cpu->R;
+ break;
+ case 0x04: /* RRD */
+ 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]=(cpu->AF.b[LO]&C_Z80)|PSZtable[cpu->AF.b[HI]];
+ SETHIDDEN(cpu->AF.b[HI]);
+ break;
+ case 0x05: /* RLD */
+ 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]=(cpu->AF.b[LO]&C_Z80)|PSZtable[cpu->AF.b[HI]];
+ SETHIDDEN(cpu->AF.b[HI]);
+ break;
+ case 0x06: /* NOP */
+ case 0x07:
+ TSTATE(8);
+ break;
+ }
- case 0x9c:
- TSTATE(4);
- break;
+ return;
+ }
+}
- case 0x9d:
- TSTATE(4);
- break;
- case 0x9e:
- TSTATE(4);
- break;
+static void EDOp_10(Z80 *cpu, Z80Byte opcode,
+ Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
+{
+ if (bml==0x00)
+ {
+ switch(bmm)
+ {
+ case 0x00: /* NOP */
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ TSTATE(8);
+ CALLBACK(eZ80_EDHook,opcode);
+ break;
+ case 0x04: /* LDI */
+ TSTATE(16);
+ LDI(cpu);
+ break;
+ case 0x05: /* LDD */
+ TSTATE(16);
+ LDD(cpu);
+ break;
+ case 0x06: /* LDIR */
+ TSTATE(16);
+ LDI(cpu);
+
+ if(cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+ case 0x07: /* LDDR */
+ TSTATE(16);
+ LDD(cpu);
+
+ if(cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+ }
+ }
- case 0x9f:
- TSTATE(4);
- break;
+ if (bml==0x01)
+ {
+ switch(bmm)
+ {
+ case 0x00: /* NOP */
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ TSTATE(8);
+ CALLBACK(eZ80_EDHook,opcode);
+ break;
+ case 0x04: /* CPI */
+ TSTATE(16);
+ CPI(cpu);
+ break;
+ case 0x05: /* CPD */
+ TSTATE(16);
+ CPD(cpu);
+ break;
+ case 0x06: /* CPIR */
+ TSTATE(16);
+ CPI(cpu);
+
+ if(cpu->BC.w && !IS_Z)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+ case 0x07: /* CPDR */
+ TSTATE(16);
+ CPD(cpu);
+
+ if(cpu->BC.w && !IS_Z)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+ }
+ }
- case 0xa0:
- TSTATE(4);
- break;
+ if (bml==0x02)
+ {
+ switch(bmm)
+ {
+ case 0x00: /* NOP */
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ TSTATE(8);
+ CALLBACK(eZ80_EDHook,opcode);
+ break;
+ case 0x04: /* INI */
+ TSTATE(16);
+ INI(cpu);
+ break;
+ case 0x05: /* IND */
+ TSTATE(16);
+ IND(cpu);
+ break;
+ case 0x06: /* INIR */
+ TSTATE(16);
+ INI(cpu);
+
+ if(cpu->BC.b[HI])
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+ case 0x07: /* INDR */
+ TSTATE(16);
+ IND(cpu);
+
+ if(cpu->BC.b[HI])
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+ }
+ }
- case 0xa1:
- TSTATE(4);
- break;
+ if (bml==0x03)
+ {
+ switch(bmm)
+ {
+ case 0x00: /* NOP */
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ TSTATE(8);
+ CALLBACK(eZ80_EDHook,opcode);
+ break;
+ case 0x04: /* OUTI */
+ TSTATE(16);
+ OUTI(cpu);
+ break;
+ case 0x05: /* OUTD */
+ TSTATE(16);
+ OUTD(cpu);
+ break;
+ case 0x06: /* OTIR */
+ TSTATE(16);
+ OUTI(cpu);
+
+ if(cpu->BC.b[HI])
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+ case 0x07: /* OTDR */
+ TSTATE(16);
+ OUTD(cpu);
+
+ if(cpu->BC.b[HI])
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+ }
+ }
- case 0xa2:
- TSTATE(4);
- break;
+ /* Everything else is a NOP
+ */
+ CALLBACK(eZ80_EDHook,opcode);
+}
- case 0xa3:
- TSTATE(4);
- break;
- case 0xa4:
- TSTATE(4);
- break;
+static void DecodeED(Z80 *cpu, Z80Byte opcode)
+{
+ Z80Byte bmh,bmm,bml;
- case 0xa5:
- TSTATE(4);
- break;
+ /* Split up the opcode into it's bitmasks
+ */
+ bmh=(opcode>>6)&3;
+ bmm=(opcode>>3)&7;
+ bml=opcode&7;
- case 0xa6:
- TSTATE(4);
- break;
+ /* Instruction set 01
+ */
+ if (bmh==0x01)
+ {
+ EDOp_01(cpu,opcode,bmh,bmm,bml);
+ return;
+ }
- case 0xa7:
- TSTATE(4);
- break;
+ /* Instruction set 10
+ */
+ if (bmh==0x02)
+ {
+ EDOp_10(cpu,opcode,bmh,bmm,bml);
+ return;
+ }
- case 0xa8:
- TSTATE(4);
- break;
+ /* All the rest are NOP/invalid
+ */
+ CALLBACK(eZ80_EDHook,opcode);
+}
- case 0xa9:
- TSTATE(4);
- break;
- case 0xaa:
- TSTATE(4);
- break;
+/* ---------------------------------------- HANDLERS FOR CB OPCODES
+*/
- case 0xab:
- TSTATE(4);
- break;
- case 0xac:
- TSTATE(4);
- break;
+static void CBOp_00(Z80 *cpu, Z80Byte opcode,
+ Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
+{
+ static Z80Byte (*op[8])(Z80 *cpu, Z80Byte val)=
+ {
+ RLC,
+ RRC,
+ RL,
+ RR,
+ SLA,
+ SRA,
+ SLL,
+ SRL
+ };
+ Z80Byte *reg;
+
+ reg=Get8(cpu,bml);
+
+ /* If the reg is NULL, this is an (HL) type arg. Also, if this is a
+ shifted op then the argument is taken from (HL) and also copied to the
+ register.
+ */
+ if (cpu->shift || !reg)
+ {
+ Z80Word a;
- case 0xad:
- TSTATE(4);
- break;
+ TSTATE(15);
+ a=GetHL(cpu);
- case 0xae:
- TSTATE(4);
- break;
+ if (cpu->shift && reg)
+ {
+ *reg=op[bmm](cpu,PEEK(a));
+ POKE(a,*reg);
+ }
+ else
+ POKE(a,op[bmm](cpu,PEEK(a)));
+ }
+ else
+ {
+ TSTATE(8);
+ *reg=op[bmm](cpu,*reg);
+ }
+}
- case 0xaf:
- TSTATE(4);
- break;
- case 0xb0:
- TSTATE(4);
- break;
+static void CBOp_01(Z80 *cpu, Z80Byte opcode,
+ Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
+{
+ Z80Byte *reg;
- case 0xb1:
- TSTATE(4);
- break;
+ reg=Get8(cpu,bml);
- case 0xb2:
- TSTATE(4);
- break;
+ /* If the reg is NULL, this is an (HL) type arg. Also, if this is a
+ shifted op.
+ */
+ if (cpu->shift || !reg)
+ {
+ Z80Word a;
- case 0xb3:
- TSTATE(4);
- break;
+ TSTATE(12);
+ a=GetHL(cpu);
+ BIT(cpu,PEEK(a),bmm);
+ }
+ else
+ {
+ TSTATE(8);
+ BIT(cpu,*reg,bmm);
+ }
+}
- case 0xb4:
- TSTATE(4);
- break;
- case 0xb5:
- TSTATE(4);
- break;
+static void CBOp_ResSet(Z80 *cpu, Z80Byte opcode,
+ Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
+{
+ Z80Byte *reg;
+ int reset;
- case 0xb6:
- TSTATE(4);
- break;
+ reg=Get8(cpu,bml);
- case 0xb7:
- TSTATE(4);
- break;
+ reset=(bmh==0x02);
- case 0xb8:
- TSTATE(4);
- break;
+ /* If the reg is NULL, this is an (HL) type arg. Also, if this is a
+ shifted op then the argument is taken from (HL) and also copied to the
+ register.
+ */
+ if (cpu->shift || !reg)
+ {
+ Z80Word a;
- case 0xb9:
- TSTATE(4);
- break;
+ TSTATE(15);
+ a=GetHL(cpu);
- case 0xba:
- TSTATE(4);
- break;
+ if (reset)
+ {
+ CLR(cpu->memory[a],bmm);
+ }
+ else
+ {
+ SET(cpu->memory[a],bmm);
+ }
- case 0xbb:
- TSTATE(4);
- break;
+ if (cpu->shift && reg)
+ {
+ *reg=cpu->memory[a];
+ }
+ }
+ else
+ {
+ TSTATE(8);
+ if (reset)
+ {
+ CLR(*reg,bmm);
+ }
+ else
+ {
+ SET(*reg,bmm);
+ }
+ }
+}
- case 0xbc:
- TSTATE(4);
- break;
- case 0xbd:
- TSTATE(4);
- break;
+static void DecodeCB(Z80 *cpu, Z80Byte opcode)
+{
+ Z80Byte bmh,bmm,bml;
- case 0xbe:
- TSTATE(4);
- break;
+ /* Split up the opcode into it's bitmasks
+ */
+ bmh=(opcode>>6)&3;
+ bmm=(opcode>>3)&7;
+ bml=opcode&7;
- case 0xbf:
- TSTATE(4);
- break;
+ /* Instruction set 00
+ */
+ if (bmh==0x00)
+ {
+ CBOp_00(cpu,opcode,bmh,bmm,bml);
+ return;
+ }
- case 0xc0:
- TSTATE(4);
- break;
+ /* Instruction set 01 (BIT)
+ */
+ if (bmh==0x01)
+ {
+ CBOp_01(cpu,opcode,bmh,bmm,bml);
+ return;
+ }
- case 0xc1:
- TSTATE(4);
- break;
+ /* Instruction set 10 (RES) and 11 (SET)
+ */
+ CBOp_ResSet(cpu,opcode,bmh,bmm,bml);
+}
- case 0xc2:
- TSTATE(4);
- break;
- case 0xc3:
- TSTATE(4);
- break;
+/* ---------------------------------------- HANDLERS FOR NORMAL OPCODES
+*/
+static void Normal_00(Z80 *cpu, Z80Byte opcode,
+ Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
+{
+ Z80Reg tmp;
+ Z80Byte *bp=NULL;
+ Z80Word w;
- case 0xc4:
- TSTATE(4);
- break;
+ if (bml==0x00)
+ {
+ switch(bmm)
+ {
+ case 0x00: /* NOP */
+ TSTATE(4);
+ break;
+ case 0x01: /* EX AF,AF' */
+ TSTATE(4);
+ tmp=cpu->AF;
+ cpu->AF=cpu->AF_;
+ cpu->AF_=tmp;
+ break;
+ case 0x02: /* DJNZ */
+ if (--cpu->BC.b[HI])
+ {
+ TSTATE(13);
+ JR;
+ }
+ else
+ {
+ TSTATE(8);
+ NOJR;
+ }
+ break;
+ case 0x03: /* JR */
+ TSTATE(12);
+ JR;
+ break;
+
+ case 0x04: /* JR cc */
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ if (GetCond(cpu,bmm&3))
+ {
+ TSTATE(12);
+ JR;
+ }
+ else
+ {
+ TSTATE(7);
+ NOJR;
+ }
+ break;
+ }
- case 0xc5:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xc6:
- TSTATE(4);
- break;
+ if (bml==0x01)
+ {
+ if(bmm&1) /* ADD HL,rr */
+ {
+ TSTATE(11);
+ *GetHLReg(cpu)=ADD16(cpu,*GetHLReg(cpu),*Get16(cpu,bmm>>1));
+ }
+ else /* LD rr,nn */
+ {
+ TSTATE(10);
+ *Get16(cpu,bmm>>1)=FETCH_WORD;
+ }
- case 0xc7:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xc8:
- TSTATE(4);
- break;
+ if (bml==0x02)
+ {
+ switch(bmm)
+ {
+ case 0x00: /* LD (rr),A */
+ case 0x02:
+ TSTATE(7);
+ POKE(*Get16(cpu,(bmm&2)>>1),cpu->AF.b[HI]);
+ break;
+ case 0x01: /* LD A,(rr) */
+ case 0x03:
+ TSTATE(7);
+ cpu->AF.b[HI]=PEEK(*Get16(cpu,(bmm&2)>>1));
+ break;
+ case 0x04: /* LD (nn),HL */
+ TSTATE(16);
+ w=FETCH_WORD;
+ POKEW(w,*GetHLReg(cpu));
+ break;
+ case 0x05: /* LD (nn),HL */
+ TSTATE(16);
+ w=FETCH_WORD;
+ *GetHLReg(cpu)=PEEKW(w);
+ break;
+ case 0x06: /* LD (nn),A */
+ TSTATE(13);
+ w=FETCH_WORD;
+ POKE(w,cpu->AF.b[HI]);
+ break;
+ case 0x07: /* LD A,(nn) */
+ TSTATE(13);
+ w=FETCH_WORD;
+ cpu->AF.b[HI]=PEEK(w);
+ break;
+ }
- case 0xc9:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xca:
- TSTATE(4);
- break;
+ if (bml==0x03)
+ {
+ if(bmm&1) /* DEC rr */
+ {
+ TSTATE(6);
+ (*Get16(cpu,bmm>>1))--;
+ }
+ else /* INC rr */
+ {
+ TSTATE(6);
+ (*Get16(cpu,bmm>>1))++;
+ }
- case 0xcb:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xcc:
- TSTATE(4);
- break;
+ if (bml==0x04)
+ {
+ bp=Get8(cpu,bmm);
- case 0xcd:
- TSTATE(4);
- break;
+ if(!bp) /* INC (HL) */
+ {
+ Z80Word a;
- case 0xce:
+ TSTATE(11);
+ a=GetHL(cpu);
+ POKE(a,INC8(cpu,PEEK(a)));
+ }
+ else /* INC r */
+ {
TSTATE(4);
- break;
+ *bp=INC8(cpu,*bp);
+ }
- case 0xcf:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xd0:
- TSTATE(4);
- break;
+ if (bml==0x05)
+ {
+ bp=Get8(cpu,bmm);
- case 0xd1:
- TSTATE(4);
- break;
+ if(!bp) /* INC (HL) */
+ {
+ Z80Word a;
- case 0xd2:
+ TSTATE(11);
+ a=GetHL(cpu);
+ POKE(a,DEC8(cpu,PEEK(a)));
+ }
+ else /* INC r */
+ {
TSTATE(4);
- break;
+ *bp=DEC8(cpu,*bp);
+ }
- case 0xd3:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xd4:
- TSTATE(4);
- break;
+ if (bml==0x06)
+ {
+ bp=Get8(cpu,bmm);
- case 0xd5:
- TSTATE(4);
- break;
+ if(!bp) /* LD (HL),n */
+ {
+ Z80Word a;
- case 0xd6:
- TSTATE(4);
- break;
+ TSTATE(10);
+ a=GetHL(cpu);
+ POKE(a,FETCH_BYTE);
+ }
+ else /* LD r,n */
+ {
+ TSTATE(7);
+ *bp=FETCH_BYTE;
+ }
- case 0xd7:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xd8:
- TSTATE(4);
- break;
+ if (bml==0x07)
+ {
+ switch(bmm)
+ {
+ case 0x00: /* RLCA */
+ TSTATE(4);
+ RLCA(cpu);
+ break;
+ case 0x01: /* RRCA */
+ TSTATE(4);
+ RRCA(cpu);
+ break;
+ case 0x02: /* RLA */
+ TSTATE(4);
+ RLA(cpu);
+ break;
+ case 0x03: /* RRA */
+ TSTATE(4);
+ RRA(cpu);
+ break;
+ case 0x04: /* DAA */
+ TSTATE(4);
+ DAA(cpu);
+ break;
+ case 0x05: /* CPL */
+ TSTATE(4);
+ cpu->AF.b[HI]=cpu->AF.b[HI]^0xff;
+ SETFLAG(H_Z80);
+ SETFLAG(N_Z80);
+ break;
+ case 0x06: /* SCF */
+ TSTATE(4);
+ SETFLAG(C_Z80);
+ break;
+ case 0x07: /* CCF */
+ TSTATE(4);
+ if (IS_C)
+ SETFLAG(H_Z80);
+ else
+ CLRFLAG(H_Z80);
+
+ cpu->AF.b[LO]^=C_Z80;
+ break;
+ }
- case 0xd9:
- TSTATE(4);
- break;
+ return;
+ }
+}
- case 0xda:
- TSTATE(4);
- break;
- case 0xdb:
- TSTATE(4);
- break;
+static void Normal_01(Z80 *cpu, Z80Byte opcode,
+ Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
+{
+ Z80Byte *dest;
+ Z80Byte *src;
- case 0xdc:
- TSTATE(4);
- break;
+ dest=Get8(cpu,bmm);
+ src=Get8(cpu,bml);
- case 0xdd:
- TSTATE(4);
- break;
+ /* Handle HALT
+ */
+ if (!dest && !src)
+ {
+ TSTATE(4);
+ cpu->PC--;
- case 0xde:
- TSTATE(4);
- break;
+ /* Inform user of HALT going high
+ */
+ if (!cpu->halt)
+ CALLBACK(eZ80_Halt,1);
- case 0xdf:
- TSTATE(4);
- break;
+ cpu->halt=TRUE;
- case 0xe0:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xe1:
- TSTATE(4);
- break;
+ /* If the src is NULL, then it is an (HL), (IX...) type instruction
+ */
+ if (src)
+ {
+ /* If the dest is NULL then it is an (HL) type store
+ */
+ if (!dest)
+ {
+ Z80Word a;
- case 0xe2:
- TSTATE(4);
- break;
+ TSTATE(7);
- case 0xe3:
- TSTATE(4);
- break;
+ /* Reget the source in case we're shifted. HL is the source when
+ doing an (HL) style store.
+ */
+ src=Get8_HL(cpu,bml);
- case 0xe4:
- TSTATE(4);
- break;
+ a=GetHL(cpu);
- case 0xe5:
+ POKE(a,*src);
+ }
+ else
+ {
TSTATE(4);
- break;
+ *dest=*src;
+ }
+ }
+ else
+ {
+ Z80Word a;
- case 0xe6:
- TSTATE(4);
- break;
+ TSTATE(7);
- case 0xe7:
- TSTATE(4);
- break;
+ /* Reget the destination in case we're shifted. HL is the dest when
+ doing an (HL) style read.
+ */
+ dest=Get8_HL(cpu,bmm);
- case 0xe8:
- TSTATE(4);
- break;
+ a=GetHL(cpu);
+ *dest=PEEK(a);
+ }
+}
- case 0xe9:
- TSTATE(4);
- break;
- case 0xea:
- TSTATE(4);
- break;
+static void Normal_10(Z80 *cpu, Z80Byte opcode,
+ Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
+{
+ static void (*op[8])(Z80 *cpu, Z80Byte val)=
+ {
+ ADD8,
+ ADC8,
+ SUB8,
+ SBC8,
+ AND,
+ XOR,
+ OR,
+ CMP8
+ };
+
+ Z80Byte *reg;
+
+ reg=Get8(cpu,bml);
+
+ if (!reg) /* op A,(HL) */
+ {
+ Z80Word a;
- case 0xeb:
- TSTATE(4);
- break;
+ TSTATE(7);
+ a=GetHL(cpu);
+ op[bmm](cpu,PEEK(a));
+ }
+ else /* op A,r */
+ {
+ TSTATE(4);
+ op[bmm](cpu,*reg);
+ }
+}
- case 0xec:
- TSTATE(4);
- break;
- case 0xed:
- TSTATE(4);
- break;
+static void Normal_11(Z80 *cpu, Z80Byte opcode,
+ Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
+{
+ Z80Reg tmp;
- case 0xee:
- TSTATE(4);
- break;
+ if (bml==0x00) /* RET cc */
+ {
+ if (GetCond(cpu,bmm))
+ {
+ TSTATE(11);
+ POP(cpu->PC);
+ }
+ else
+ {
+ TSTATE(5);
+ }
- case 0xef:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xf0:
- TSTATE(4);
- break;
+ if (bml==0x01)
+ {
+ switch(bmm)
+ {
+ case 0x00: /* POP rr */
+ case 0x02:
+ case 0x04:
+ case 0x06:
+ TSTATE(10);
+ POP(*Get16_AF(cpu,bmm>>1));
+ break;
+ case 0x01: /* RET */
+ TSTATE(10);
+ POP(cpu->PC);
+ break;
+ case 0x03: /* EXX */
+ TSTATE(4);
+ tmp=cpu->BC;
+ cpu->BC=cpu->BC_;
+ cpu->BC_=tmp;
+ tmp=cpu->DE;
+ cpu->DE=cpu->DE_;
+ cpu->DE_=tmp;
+ tmp=cpu->HL;
+ cpu->HL=cpu->HL_;
+ cpu->HL_=tmp;
+ break;
+ case 0x05: /* JP (HL) */
+ TSTATE(4);
+ cpu->PC=GetHLVal(cpu);
+ break;
+ case 0x07: /* LD SP,HL */
+ TSTATE(6);
+ cpu->SP=GetHLVal(cpu);
+ break;
+ }
- case 0xf1:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xf2:
- TSTATE(4);
- break;
+ if (bml==0x02) /* JP cc */
+ {
+ TSTATE(10);
- case 0xf3:
- TSTATE(4);
- break;
+ if (GetCond(cpu,bmm))
+ {
+ JP;
+ }
+ else
+ {
+ NOJP;
+ }
- case 0xf4:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xf5:
- TSTATE(4);
- break;
+ if (bml==0x03)
+ {
+ Z80Word tmp;
+ Z80Word *reg;
- case 0xf6:
- TSTATE(4);
- break;
+ switch(bmm)
+ {
+ case 0x00: /* JP nn */
+ TSTATE(10);
+ cpu->PC=FETCH_WORD;
+ break;
+ case 0x01: /* shift */
+ break;
+ case 0x02: /* OUT (n),a */
+ TSTATE(11);
+ OUT(FETCH_BYTE,cpu->AF.b[HI]);
+ break;
+ case 0x03: /* IN A,(n) */
+ TSTATE(11);
+ cpu->AF.b[HI]=IN(FETCH_BYTE);
+ break;
+ case 0x04: /* EX (SP),HL */
+ TSTATE(19);
+ reg=GetHLReg(cpu);
+ tmp=*reg;
+ *reg=PEEKW(cpu->SP);
+ POKEW(cpu->SP,tmp);
+ break;
+ case 0x05: /* EX DE,HL */
+ TSTATE(4);
+ tmp=cpu->HL.w;
+ cpu->HL.w=cpu->DE.w;
+ cpu->DE.w=tmp;
+ break;
+ case 0x06: /* DI */
+ TSTATE(4);
+ cpu->IFF1=0;
+ cpu->IFF2=0;
+ break;
+ case 0x07: /* EI */
+ TSTATE(4);
+ cpu->IFF1=1;
+ cpu->IFF2=1;
+ break;
+ }
- case 0xf7:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xf8:
- TSTATE(4);
- break;
+ if (bml==0x04) /* CALL cc */
+ {
+ if (GetCond(cpu,bmm))
+ {
+ TSTATE(12);
+ CALL;
+ }
+ else
+ {
+ TSTATE(7);
+ NOCALL;
+ }
- case 0xf9:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xfa:
- TSTATE(4);
- break;
+ if (bml==0x05)
+ {
+ if (bmm==01) /* CALL nn */
+ {
+ TSTATE(17);
+ CALL;
+ }
+ else
+ {
+ if (!(bmm&1)) /* PUSH rr */
+ {
+ TSTATE(11);
+ PUSH(*Get16_AF(cpu,bmm>>1));
+ }
- case 0xfb:
- TSTATE(4);
- break;
+ /* Everything else is a shift */
+ }
- case 0xfc:
- TSTATE(4);
- break;
+ return;
+ }
- case 0xfd:
- TSTATE(4);
- break;
+ if (bml==0x06)
+ {
+ TSTATE(8);
- case 0xfe:
- TSTATE(4);
- break;
+ switch(bmm)
+ {
+ case 0x00: /* ADD A,n */
+ ADD8(cpu,FETCH_BYTE);
+ break;
+ case 0x01: /* ADC A,n */
+ ADC8(cpu,FETCH_BYTE);
+ break;
+ case 0x02: /* SUB A,n */
+ SUB8(cpu,FETCH_BYTE);
+ break;
+ case 0x03: /* SBC A,n */
+ SBC8(cpu,FETCH_BYTE);
+ break;
+ case 0x04: /* AND n */
+ AND(cpu,FETCH_BYTE);
+ break;
+ case 0x05: /* XOR n */
+ XOR(cpu,FETCH_BYTE);
+ break;
+ case 0x06: /* OR n */
+ OR(cpu,FETCH_BYTE);
+ break;
+ case 0x07: /* CP n */
+ CMP8(cpu,FETCH_BYTE);
+ break;
+ }
- case 0xff:
- TSTATE(4);
- break;
+ return;
+ }
+ if (bml==0x07) /* RST nn */
+ {
+ TSTATE(11);
+ PUSH(cpu->PC);
+ cpu->PC=bmm*8;
+ return;
}
}
+/* ---------------------------------------- NORMAL OPCODE DECODER
+*/
+void Z80_Decode(Z80 *cpu, Z80Byte opcode)
+{
+ Z80Byte bmh,bmm,bml;
+
+ /* IX/IY shifts
+ */
+ if (opcode==0xdd || opcode==0xfd)
+ {
+ TSTATE(4);
+ INC_R;
+
+ cpu->shift=opcode;
+ Z80_Decode(cpu,FETCH_BYTE);
+ return;
+ }
+
+ /* CB shifts
+ */
+ if (opcode==0xcb)
+ {
+ INC_R;
+
+ /* Check for previous IX/IY shift.
+ */
+ if (cpu->shift!=0)
+ {
+ cpu->use_cb_off=TRUE;
+ cpu->cb_off=(Z80Relative)FETCH_BYTE;
+ }
+
+ DecodeCB(cpu,FETCH_BYTE);
+ return;
+ }
+
+ /* DE shifts
+ */
+ if (opcode==0xed)
+ {
+ INC_R;
+ DecodeED(cpu,FETCH_BYTE);
+ return;
+ }
+
+ /* Split up the opcode into it's bitmasks
+ */
+ bmh=(opcode>>6)&3;
+ bmm=(opcode>>3)&7;
+ bml=opcode&7;
+
+ /* Instruction set 00
+ */
+ if (bmh==0x00)
+ {
+ Normal_00(cpu,opcode,bmh,bmm,bml);
+ return;
+ }
+
+ /* Instruction set 01
+ */
+ if (bmh==0x01)
+ {
+ Normal_01(cpu,opcode,bmh,bmm,bml);
+ return;
+ }
+
+ /* Instruction set 10
+ */
+ if (bmh==0x02)
+ {
+ Normal_10(cpu,opcode,bmh,bmm,bml);
+ return;
+ }
+
+ /* Instruction set 11
+ */
+ Normal_11(cpu,opcode,bmh,bmm,bml);
+}
+
+
/* END OF FILE */
diff --git a/z80_private.h b/z80_private.h
index 08dc543..32ce91f 100644
--- a/z80_private.h
+++ b/z80_private.h
@@ -43,25 +43,30 @@
/* ---------------------------------------- TYPES
*/
+typedef union
+{
+ Z80Word w;
+ Z80Byte b[2];
+} Z80Reg;
+
struct Z80
{
Z80Val cycle;
Z80Word PC;
- Z80Byte A;
- Z80Byte F;
- Z80Word BC;
- Z80Word DE;
- Z80Word HL;
+ Z80Reg AF;
+ Z80Reg BC;
+ Z80Reg DE;
+ Z80Reg HL;
- Z80Word AF_;
- Z80Word BC_;
- Z80Word DE_;
- Z80Word HL_;
+ Z80Reg AF_;
+ Z80Reg BC_;
+ Z80Reg DE_;
+ Z80Reg HL_;
- Z80Word IX;
- Z80Word IY;
+ Z80Reg IX;
+ Z80Reg IY;
Z80Word SP;
@@ -136,8 +141,8 @@ struct Z80
#define SET(v,b) v|=b
#define CLR(v,b) v&=~(b)
-#define SETFLAG(f) SET(cpu->F,f)
-#define CLRFLAG(f) CLR(cpu->F,f)
+#define SETFLAG(f) SET(cpu->AF.b[LO],f)
+#define CLRFLAG(f) CLR(cpu->AF.b[LO],f)
#define PEEK(addr) (cpu->memory[addr])
#define PEEKW(addr) (PEEK(addr) | (Z80Word)PEEK(addr+1)<<8)
@@ -148,11 +153,12 @@ struct Z80
{ \
cpu->memory[addr]=val; \
} \
- while (0)(cpu->write(cpu,addr,val))
+ } while (0)
#define POKEW(addr,val) do \
{ \
- POKE(addr,val); \
- POKE(addr+1,val>>8); \
+ Z80Word once=val; \
+ POKE(addr,once); \
+ POKE(addr+1,once>>8); \
} while(0)
#define FETCH_BYTE (cpu->memory[cpu->PC++])
@@ -160,12 +166,12 @@ struct Z80
cpu->memory[cpu->PC-2]| \
((Z80Word)cpu->memory[cpu->PC-1]<<8))
-#define IS_C (cpu->F&C_Z80)
-#define IS_N (cpu->F&N_Z80)
-#define IS_P (cpu->F&P_Z80)
-#define IS_H (cpu->F&H_Z80)
-#define IS_Z (cpu->F&Z_Z80)
-#define IS_S (cpu->F&S_Z80)
+#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)
+#define IS_H (cpu->AF.b[LO]&H_Z80)
+#define IS_Z (cpu->AF.b[LO]&Z_Z80)
+#define IS_S (cpu->AF.b[LO]&S_Z80)
#define CARRY IS_C
@@ -185,9 +191,25 @@ struct Z80
cpu->SP+=2; \
} while(0)
-#define SETHIDDEN(res) cpu->F=(cpu->F&~(B3_Z80|B5_Z80))|\
+#define SETHIDDEN(res) cpu->AF.b[LO]=(cpu->AF.b[LO]&~(B3_Z80|B5_Z80))|\
((res)&(B3_Z80|B5_Z80))
+#define CALL do \
+ { \
+ PUSH(cpu->PC+2); \
+ cpu->PC=PEEKW(cpu->PC); \
+ } while(0)
+#define NOCALL cpu->PC+=2
+#define JP cpu->PC=PEEKW(cpu->PC)
+#define NOJP cpu->PC+=2
+#define JR cpu->PC+=(Z80Relative)PEEK(cpu->PC)+1
+#define NOJR cpu->PC++
+
+#define IN(PORT) (cpu->pread ? cpu->pread(cpu,PORT) : 0)
+#define OUT(PORT,VAL) if (cpu->pwrite) \
+ { \
+ cpu->pwrite(cpu,PORT,VAL); \
+ }
/* ---------------------------------------- FLAG TABLES
@@ -201,7 +223,8 @@ extern Z80Byte Ztable[512];
/* ---------------------------------------- GLOBAL GENERAL OPCODES/ROUTINES
*/
-void Z80_Decode(Z80 *cpu);
+void Z80_Decode(Z80 *cpu, Z80Byte opcode);
+void Z80_InitialiseInternals(void);
#endif