summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2006-08-25 23:28:49 +0000
committerIan C <ianc@noddybox.co.uk>2006-08-25 23:28:49 +0000
commit458ae07fcde77592e06927f0dddcd12c8d242b29 (patch)
tree23a7c741e02a287df2b802184095dec9d6b4817a
parent0034381aac6413def6960c7e4a1f8b84b5538549 (diff)
Devolopment checkin. Compiles, but doesn't pass tests.
-rw-r--r--Makefile11
-rw-r--r--emma.c2
-rw-r--r--runtest2
-rw-r--r--test.z8017
-rw-r--r--z80.c26
-rw-r--r--z80_decode.c3693
-rw-r--r--z80_private.h32
7 files changed, 2109 insertions, 1674 deletions
diff --git a/Makefile b/Makefile
index 6031150..a77cfcd 100644
--- a/Makefile
+++ b/Makefile
@@ -18,14 +18,14 @@
#
# -------------------------------------------------------------------------
#
-# $Id: Makefile,v 1.4 2006-08-21 22:14:41 ianc Exp $
+# $Id: Makefile,v 1.5 2006-08-25 23:28:49 ianc Exp $
#
# This CFLAGS assumes that gcc is being used.
# Simply comment out if not, and replace as needed.
# Other CFLAGS lines *are* required.
#
-CFLAGS = -Wall -Werror -pedantic -ansi -O2 -finline-functions
+CFLAGS = -g -Wall -Werror -pedantic -ansi -O2 -finline-functions
# Remove this to disable the disassembler (saving some memory)
#
@@ -46,16 +46,19 @@ OBJECTS = z80.o \
expr.o \
emma.o
-all: $(TARGET) emucpm.hex
+all: $(TARGET) emucpm.hex test.hex
$(TARGET): $(OBJECTS)
cc -o $(TARGET) $(OBJECTS)
+test.hex: test.z80
+ tpasm -P Z80 -o intel test.hex test.z80
+
emucpm.hex: emucpm.z80
tpasm -P Z80 -o intel emucpm.hex emucpm.z80
clean:
- rm -f $(TARGET) $(OBJECTS) core $(TARGET).exe emucpm.hex
+ rm -f $(TARGET) $(OBJECTS) core $(TARGET).exe emucpm.hex test.hex
depend:
makedepend -- $(CFLAGS) -- $(SOURCE)
diff --git a/emma.c b/emma.c
index 21c640e..f8f0932 100644
--- a/emma.c
+++ b/emma.c
@@ -182,7 +182,7 @@ static void DisplayState(void)
Log("BC=%4.4x DE=%4.4x HL=%4.4x ",s.BC,s.DE,s.HL);
Log("IX=%4.4x IY=%4.4x SP=%4.4x\n",s.IX,s.IY,s.SP);
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("IFF1=%2.2x IFF2=%2.2x CYCLES=%lu\n",s.IFF1,s.IFF2,s.cycle);
Log("%4.4x: ",s.PC);
Log("%s\n",Disassemble(&s.PC));
}
diff --git a/runtest b/runtest
new file mode 100644
index 0000000..4572c47
--- /dev/null
+++ b/runtest
@@ -0,0 +1,2 @@
+i test.hex
+n
diff --git a/test.z80 b/test.z80
new file mode 100644
index 0000000..f43eea0
--- /dev/null
+++ b/test.z80
@@ -0,0 +1,17 @@
+;
+; Odd random tests
+;
+ org 0
+
+ ld hl,$1234
+ push hl
+ pop af
+ ld bc,$5678
+ ld de,$9abc
+ ld hl,$def0
+ ld ix,$dead
+ ld iy,$beef
+
+loop:
+ inc b
+ jp loop
diff --git a/z80.c b/z80.c
index 0b74bf5..6986c96 100644
--- a/z80.c
+++ b/z80.c
@@ -157,10 +157,10 @@ void Z80Reset(Z80 *cpu)
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->AF_=0xffff;
+ cpu->BC_=0xffff;
+ cpu->DE_=0xffff;
+ cpu->HL_=0xffff;
cpu->IX.w=0xffff;
cpu->IY.w=0xffff;
@@ -228,8 +228,6 @@ int Z80SingleStep(Z80 *cpu)
{
cpu->last_cb=TRUE;
cpu->shift=0;
- cpu->use_cb_off=FALSE;
- cpu->cb_off=0;
Z80_CheckInterrupt(cpu);
@@ -258,10 +256,10 @@ void Z80GetState(Z80 *cpu, Z80State *state)
state->DE = cpu->DE.w;
state->HL = cpu->HL.w;
- state->AF_ = cpu->AF_.w;
- state->BC_ = cpu->BC_.w;
- state->DE_ = cpu->DE_.w;
- state->HL_ = cpu->HL_.w;
+ state->AF_ = cpu->AF_;
+ state->BC_ = cpu->BC_;
+ state->DE_ = cpu->DE_;
+ state->HL_ = cpu->HL_;
state->IX = cpu->IX.w;
state->IY = cpu->IY.w;
@@ -286,10 +284,10 @@ void Z80SetState(Z80 *cpu, const Z80State *state)
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->AF_ = state->AF_;
+ cpu->BC_ = state->BC_;
+ cpu->DE_ = state->DE_;
+ cpu->HL_ = state->HL_;
cpu->IX.w = state->IX;
cpu->IY.w = state->IY;
diff --git a/z80_decode.c b/z80_decode.c
index c5688c8..5b8207d 100644
--- a/z80_decode.c
+++ b/z80_decode.c
@@ -25,8 +25,6 @@
$Id$
- Z80
-
*/
#include <stdlib.h>
@@ -66,7 +64,7 @@ static Z80Byte Ztable[512];
static int HI;
static int LO;
-/* ---------------------------------------- PRIVATE FUNCTIONS
+/* ---------------------------------------- MISC FUNCTIONS
*/
void Z80_InitialiseInternals(void)
{
@@ -132,484 +130,827 @@ void Z80_InitialiseInternals(void)
}
}
-
-/* ---------------------------------------- ARITHMETIC OPS
-*/
-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;
-}
-
-
-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;
-}
-
-
-static void SUB8(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(w);
- cpu->AF.b[HI]=w;
-}
-
-
-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);
-}
-
-
-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;
-}
-
-
-static Z80Word ADC16(Z80 *cpu, Z80Word REG, Z80Word VAL)
-{
- Z80Val w;
- w=REG+(Z80Val)VAL+CARRY;
- cpu->AF.b[LO]=0;
- if ((w&0xffff)==0) cpu->AF.b[LO]=Z_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);
- return w;
-}
-
-
-static Z80Word SBC16(Z80 *cpu, Z80Word REG, Z80Word VAL)
+static Z80Word FPEEKW(Z80 *cpu, Z80Word addr)
{
- Z80Val w;
- w=REG-(Z80Val)VAL-CARRY;
- cpu->AF.b[LO]=N_Z80;
- if ((w&0xffff)==0) cpu->AF.b[LO]=Z_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)&(VAL^w)&0x8000) cpu->AF.b[LO]|=P_Z80;
- if ((REG^w^VAL)&0x1000) cpu->AF.b[LO]|=H_Z80;
- SETHIDDEN(w>>8);
- return w;
+ return (PEEK(addr) | (Z80Word)PEEK(addr+1)<<8);
}
-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;
-}
+/* ---------------------------------------- GENERAL MACROS
+*/
+#define SWAP(A,B) \
+do { \
+ Z80Word swap_tmp; \
+ swap_tmp=A; \
+ A=B; \
+ B=swap_tmp; \
+} while(0)
-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;
-}
+/* ---------------------------------------- ARITHMETIC OPS
+*/
+#define ADD8(ONCE) \
+do { \
+ Z80Byte VAL=ONCE; \
+ 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; \
+} while(0)
+
+
+#define ADC8(ONCE) \
+do { \
+ Z80Byte VAL=ONCE; \
+ 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; \
+} while(0)
+
+
+#define SUB8(ONCE) \
+do { \
+ Z80Byte VAL=ONCE; \
+ 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; \
+} while(0)
+
+
+#define CMP8(ONCE) \
+do { \
+ Z80Byte VAL=ONCE; \
+ 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); \
+} while(0)
+
+
+#define SBC8(ONCE) \
+do { \
+ Z80Byte VAL=ONCE; \
+ 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; \
+} 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>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&0xffff)==0) cpu->AF.b[LO]=Z_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)&(VAL^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) cpu->AF.b[LO]|=H_Z80; \
+} while(0)
+
+
+#define DEC8(REG) \
+do { \
+ 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]; \
+} while(0)
/* ---------------------------------------- ROTATE AND SHIFT OPS
*/
-static void RRCA(Z80 *cpu)
-{
- 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]);
-}
-
-
-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]);
-}
-
-
-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;
-}
-
-
-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]);
-}
-
-
-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;
-}
+#define RRCA \
+do { \
+ 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]); \
+} while(0)
+
+
+#define RRA \
+do { \
+ 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]); \
+} 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]&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]); \
+} while(0)
+
+
+#define RLA \
+do { \
+ 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]); \
+} 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
*/
-static void AND(Z80 *cpu, Z80Byte VAL)
-{
- cpu->AF.b[HI]&=VAL;
- cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]]|H_Z80;
- SETHIDDEN(cpu->AF.b[HI]);
-}
-
-
-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]);
-}
-
-
-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]);
-}
-
-
-static void BIT(Z80 *cpu, Z80Byte REG, Z80Byte B)
-{
- cpu->AF.b[LO]=CARRY|H_Z80;
- if (REG&&(1<<B))
- {
- 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;
- }
-}
-
+#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) 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; \
+ } \
+} while(0)
+
+#define RES CLR
+
+
+/* ---------------------------------------- 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
*/
-static void LDI(Z80 *cpu)
-{
- 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);
-}
-
-static void LDD(Z80 *cpu)
-{
- 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);
-}
-
-static void CPI(Z80 *cpu)
-{
- Z80Byte c,b;
-
- c=CARRY;
- b=PEEK(cpu->HL.w);
-
- CMP8(cpu,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);
-}
-
-static void CPD(Z80 *cpu)
-{
- Z80Byte c,b;
-
- c=CARRY;
- b=PEEK(cpu->HL.w);
-
- CMP8(cpu,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);
-}
-
-static void INI(Z80 *cpu)
-{
- 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);
- }
-}
-
-static void IND(Z80 *cpu)
-{
- 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);
- }
-}
-
-static void OUTI(Z80 *cpu)
-{
- 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]);
-}
-
-static void OUTD(Z80 *cpu)
-{
- 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]);
-}
-
-
+#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
+*/
-/* ---------------------------------------- GENERAL MACROS
+#define LD_BLOCK(BASE,DEST) \
+ 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); \
+ DEST=cpu->memory[*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(cpu->memory[*HL+off]); \
+ break; \
+ \
+ case BASE+7: /* OP A,A */ \
+ TSTATE(4); \
+ OP(cpu->AF.b[HI]); \
+ break;
+
+
+/* ---------------------------------------- CB OPCODE SHORT-HAND BLOCKS
*/
-/* Decides whether the offset for IX/IY should be fetched, or used
- from the store for a CB instruction
+#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(cpu->memory[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(cpu->memory[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 GETREL (cpu->use_cb_off ? cpu->cb_off : (Z80Relative)FETCH_BYTE)
+#define SHIFTED_CB_ALU_BLOCK(BASE,OP) \
+ case BASE: /* OP B */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr]); \
+ cpu->BC.b[HI]=cpu->memory[addr]; \
+ break; \
+ \
+ case BASE+1: /* OP C */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr]); \
+ cpu->BC.b[LO]=cpu->memory[addr]; \
+ break; \
+ \
+ case BASE+2: /* OP D */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr]); \
+ cpu->DE.b[HI]=cpu->memory[addr]; \
+ break; \
+ \
+ case BASE+3: /* OP E */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr]); \
+ cpu->DE.b[LO]=cpu->memory[addr]; \
+ break; \
+ \
+ case BASE+4: /* OP H */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr]); \
+ cpu->HL.b[HI]=cpu->memory[addr]; \
+ break; \
+ \
+ case BASE+5: /* OP L */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr]); \
+ cpu->HL.b[LO]=cpu->memory[addr]; \
+ break; \
+ \
+ case BASE+6: /* OP (HL) */ \
+ TSTATE(15); \
+ OP(cpu->memory[addr]); \
+ break; \
+ \
+ case BASE+7: /* OP A */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr]); \
+ cpu->AF.b[HI]=cpu->memory[addr]; \
+ break;
+
+#define SHIFTED_CB_BITMANIP_BLOCK(BASE,OP,BIT_NO) \
+ case BASE: /* OP B */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr],BIT_NO); \
+ cpu->BC.b[HI]=cpu->memory[addr]; \
+ break; \
+ \
+ case BASE+1: /* OP C */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr],BIT_NO); \
+ cpu->BC.b[LO]=cpu->memory[addr]; \
+ break; \
+ \
+ case BASE+2: /* OP D */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr],BIT_NO); \
+ cpu->DE.b[HI]=cpu->memory[addr]; \
+ break; \
+ \
+ case BASE+3: /* OP E */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr],BIT_NO); \
+ cpu->DE.b[LO]=cpu->memory[addr]; \
+ break; \
+ \
+ case BASE+4: /* OP H */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr],BIT_NO); \
+ cpu->HL.b[HI]=cpu->memory[addr]; \
+ break; \
+ \
+ case BASE+5: /* OP L */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr],BIT_NO); \
+ cpu->HL.b[LO]=cpu->memory[addr]; \
+ break; \
+ \
+ case BASE+6: /* OP (HL) */ \
+ TSTATE(12); \
+ OP(cpu->memory[addr],BIT_NO); \
+ break; \
+ \
+ case BASE+7: /* OP A */ \
+ TSTATE(8); \
+ OP(cpu->memory[addr],BIT_NO); \
+ cpu->AF.b[HI]=cpu->memory[addr]; \
+ break;
/* ---------------------------------------- DAA
*/
@@ -669,1425 +1010,1495 @@ static void DAA (Z80 *cpu)
}
-/* ---------------------------------------- DECODE AND REGISTER SELECTION
-*/
-
-/* Get the 16 bit register to use according to the bitmask
+/* ---------------------------------------- HANDLERS FOR ED OPCODES
*/
-static Z80Word *Get16(Z80 *cpu, Z80Byte bm)
+static void DecodeED(Z80 *cpu, Z80Byte opcode)
{
- if (bm==0x00)
- return &cpu->BC.w;
+ switch(opcode)
+ {
+ case 0x40: /* IN B,(C) */
+ TSTATE(12);
- if (bm==0x01)
- return &cpu->DE.w;
+ if (cpu->pread)
+ {
+ cpu->BC.b[HI]=cpu->pread(cpu,cpu->BC.w);
+ }
+ else
+ {
+ cpu->BC.b[HI]=0;
+ }
- if (bm==0x02)
- {
- if (cpu->shift==0xdd)
- return &cpu->IX.w;
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->BC.b[HI]];
+ SETHIDDEN(cpu->BC.b[HI]);
+ break;
- if (cpu->shift==0xfd)
- return &cpu->IY.w;
+ case 0x41: /* OUT (C),B */
+ TSTATE(12);
+ if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->BC.b[HI]);
+ break;
- return &cpu->HL.w;
- }
+ case 0x42: /* SBC HL,BC */
+ TSTATE(15);
+ SBC16(cpu->HL.w,cpu->BC.w);
+ break;
- return &cpu->SP;
-}
+ case 0x43: /* LD (nnnn),BC */
+ TSTATE(20);
+ POKEW(FETCH_WORD,cpu->BC.w);
+ break;
+ case 0x44: /* NEG */
+ {
+ Z80Byte b;
-/* 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;
+ TSTATE(8);
- if (bm==0x01)
- return &cpu->DE.w;
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
- if (bm==0x02)
- return &cpu->HL.w;
+ case 0x45: /* RETN */
+ TSTATE(14);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
- return &cpu->SP;
-}
+ case 0x46: /* IM 0 */
+ TSTATE(8);
+ cpu->IM=0;
+ break;
+ case 0x47: /* LD I,A */
+ TSTATE(9);
+ cpu->I=cpu->AF.b[HI];
+ 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 0x48: /* IN C,(C) */
+ TSTATE(12);
- if (bm==0x01)
- return &cpu->DE.w;
+ if (cpu->pread)
+ {
+ cpu->BC.b[LO]=cpu->pread(cpu,cpu->BC.w);
+ }
+ else
+ {
+ cpu->BC.b[LO]=0;
+ }
- if (bm==0x02)
- {
- if (cpu->shift==0xdd)
- return &cpu->IX.w;
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->BC.b[LO]];
+ SETHIDDEN(cpu->BC.b[LO]);
+ break;
- if (cpu->shift==0xfd)
- return &cpu->IY.w;
+ case 0x49: /* OUT (C),C */
+ TSTATE(12);
+ if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->BC.b[LO]);
+ break;
- return &cpu->HL.w;
- }
+ case 0x4a: /* ADC HL,BC */
+ TSTATE(15);
+ ADC16(cpu->HL.w,cpu->BC.w);
+ break;
- return &cpu->AF.w;
-}
+ case 0x4b: /* LD BC,(nnnn) */
+ TSTATE(20);
+ cpu->BC.w=PEEKW(FETCH_WORD);
+ break;
+ case 0x4c: /* NEG */
+ {
+ Z80Byte b;
-/* 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];
+ TSTATE(8);
- if (bm==0x00)
- return &cpu->BC.b[HI];
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
- if (bm==0x01)
- return &cpu->BC.b[LO];
+ case 0x4d: /* RETI */
+ TSTATE(14);
+ CALLBACK(eZ80_RETI,0);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
- if (bm==0x02)
- return &cpu->DE.b[HI];
+ case 0x4e: /* IM 0/1 */
+ TSTATE(8);
+ cpu->IM=0;
+ break;
- if (bm==0x03)
- return &cpu->DE.b[LO];
+ case 0x4f: /* LD R,A */
+ TSTATE(9);
+ cpu->R=cpu->AF.b[HI];
+ break;
- if (bm==0x04)
- {
- if (cpu->shift==0xdd)
- return &cpu->IX.b[HI];
+ case 0x50: /* IN D,(C) */
+ TSTATE(12);
- if (cpu->shift==0xfd)
- return &cpu->IY.b[HI];
+ if (cpu->pread)
+ {
+ cpu->DE.b[HI]=cpu->pread(cpu,cpu->BC.w);
+ }
+ else
+ {
+ cpu->DE.b[HI]=0;
+ }
- return &cpu->HL.b[HI];
- }
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->DE.b[HI]];
+ SETHIDDEN(cpu->BC.b[HI]);
+ break;
- if (bm==0x05)
- {
- if (cpu->shift==0xdd)
- return &cpu->IX.b[LO];
+ case 0x51: /* OUT (C),D */
+ TSTATE(12);
+ if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->DE.b[HI]);
+ break;
- if (cpu->shift==0xfd)
- return &cpu->IY.b[LO];
+ case 0x52: /* SBC HL,DE */
+ TSTATE(15);
+ SBC16(cpu->HL.w,cpu->DE.w);
+ break;
- return &cpu->HL.b[LO];
- }
+ case 0x53: /* LD (nnnn),DE */
+ TSTATE(20);
+ POKEW(FETCH_WORD,cpu->DE.w);
+ break;
- return NULL;
-}
+ case 0x54: /* NEG */
+ {
+ Z80Byte b;
+ TSTATE(8);
-/* 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];
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
- if (bm==0x00)
- return &cpu->BC.b[HI];
+ case 0x55: /* RETN */
+ TSTATE(14);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
- if (bm==0x01)
- return &cpu->BC.b[LO];
+ case 0x56: /* IM 1 */
+ TSTATE(8);
+ cpu->IM=1;
+ break;
- if (bm==0x02)
- return &cpu->DE.b[HI];
+ case 0x57: /* LD A,I */
+ TSTATE(9);
+ cpu->AF.b[HI]=cpu->I;
+ break;
- if (bm==0x03)
- return &cpu->DE.b[LO];
+ case 0x58: /* IN E,(C) */
+ TSTATE(12);
- if (bm==0x04)
- return &cpu->HL.b[HI];
+ if (cpu->pread)
+ {
+ cpu->DE.b[LO]=cpu->pread(cpu,cpu->BC.w);
+ }
+ else
+ {
+ cpu->BC.b[LO]=0;
+ }
- if (bm==0x05)
- return &cpu->HL.b[LO];
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->DE.b[LO]];
+ SETHIDDEN(cpu->DE.b[LO]);
+ break;
- return NULL;
-}
+ 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;
-/* 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 0x5b: /* LD DE,(nnnn) */
+ TSTATE(20);
+ cpu->DE.w=PEEKW(FETCH_WORD);
+ break;
- if (cpu->shift==0xdd)
- {
- TSTATE(8);
- return cpu->IX.w+GETREL;
- }
+ case 0x5c: /* NEG */
+ {
+ Z80Byte b;
- if (cpu->shift==0xfd)
- {
- TSTATE(8);
- return cpu->IY.w+GETREL;
- }
+ TSTATE(8);
- return 0;
-}
+ 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;
-/* 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 0x5e: /* IM 2 */
+ TSTATE(8);
+ cpu->IM=2;
+ break;
- if (cpu->shift==0xdd)
- return cpu->IX.w;
+ case 0x5f: /* LD A,R */
+ TSTATE(9);
+ cpu->AF.b[HI]=cpu->R;
+ break;
- if (cpu->shift==0xfd)
- return cpu->IY.w;
+ case 0x60: /* IN H,(C) */
+ TSTATE(12);
- return 0;
-}
+ 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;
-/* Get the register (HL, IX, IY) depending on the shift
-*/
-static Z80Word* GetHLReg(Z80 *cpu)
-{
- if (cpu->shift==0)
- return &cpu->HL.w;
+ case 0x61: /* OUT (C),H */
+ TSTATE(12);
+ if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->HL.b[HI]);
+ break;
- if (cpu->shift==0xdd)
- return &cpu->IX.w;
+ case 0x62: /* SBC HL,HL */
+ TSTATE(15);
+ SBC16(cpu->HL.w,cpu->HL.w);
+ break;
- if (cpu->shift==0xfd)
- return &cpu->IY.w;
+ case 0x63: /* LD (nnnn),HL */
+ TSTATE(20);
+ POKEW(FETCH_WORD,cpu->HL.w);
+ break;
- return 0;
-}
+ case 0x64: /* NEG */
+ {
+ Z80Byte b;
+ TSTATE(8);
-/* Get a condition depending on the bitmask
-*/
-static Z80Byte GetCond(Z80 *cpu, Z80Byte bm)
-{
- if (bm==0x00) /* NZ */
- return !IS_Z;
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
- if (bm==0x01) /* Z */
- return IS_Z;
+ case 0x65: /* RETN */
+ TSTATE(14);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
- if (bm==0x02) /* NC */
- return !IS_C;
+ case 0x66: /* IM 0 */
+ TSTATE(8);
+ cpu->IM=0;
+ break;
- if (bm==0x03) /* C */
- return IS_C;
+ case 0x67: /* RRD */
+ {
+ Z80Byte b;
- if (bm==0x04) /* PO */
- return !IS_P;
+ TSTATE(18);
- if (bm==0x05) /* PE */
- return IS_P;
+ b=PEEK(cpu->HL.w);
- if (bm==0x06) /* P */
- return !IS_S;
+ POKE(cpu->HL.w,(b>>4)|(cpu->AF.b[HI]<<4));
+ cpu->AF.b[HI]=(cpu->AF.b[HI]&0xf0)|(b&0x0f);
- if (bm==0x07) /* M */
- return IS_S;
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->AF.b[HI]];
+ SETHIDDEN(cpu->AF.b[HI]);
+ break;
+ }
- return 0;
-}
+ 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;
+ }
-/* ---------------------------------------- HANDLERS FOR ED OPCODES
-*/
+ 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;
-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 0x6a: /* ADC HL,HL */
+ TSTATE(15);
+ ADC16(cpu->HL.w,cpu->HL.w);
+ break;
- TSTATE(12);
+ case 0x6b: /* LD HL,(nnnn) */
+ TSTATE(20);
+ cpu->HL.w=PEEKW(FETCH_WORD);
+ break;
- reg=Get8_HL(cpu,bmm);
- v=IN(cpu->BC.w);
+ case 0x6c: /* NEG */
+ {
+ Z80Byte b;
- cpu->AF.b[LO]=(cpu->AF.b[LO]&C_Z80)|PSZtable[v];
- SETHIDDEN(v);
+ TSTATE(8);
- if (reg)
- *reg=v;
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
- return;
- }
+ case 0x6d: /* RETN */
+ TSTATE(14);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
- if (bml==0x01) /* OUT r,(C) */
- {
- Z80Byte *reg;
+ case 0x6e: /* IM 0/1 */
+ TSTATE(8);
+ cpu->IM=0;
+ break;
- TSTATE(12);
+ case 0x6f: /* RLD */
+ {
+ Z80Byte b;
- reg=Get8_HL(cpu,bmm);
- OUT(cpu->BC.w,reg ? *reg:0);
+ TSTATE(18);
- return;
- }
+ b=PEEK(cpu->HL.w);
- if (bml==0x02)
- {
- Z80Word *reg;
+ POKE(cpu->HL.w,(b<<4)|(cpu->AF.b[HI]&0x0f));
+ cpu->AF.b[HI]=(cpu->AF.b[HI]&0xf0)|(b>>4);
- TSTATE(15);
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->AF.b[HI]];
+ SETHIDDEN(cpu->AF.b[HI]);
+ break;
+ }
- reg=Get16_HL(cpu,bmm>>1);
+ case 0x70: /* IN (C) */
+ {
+ Z80Byte b;
- 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);
- }
+ TSTATE(12);
- return;
- }
+ if (cpu->pread)
+ {
+ b=cpu->pread(cpu,cpu->BC.w);
+ }
+ else
+ {
+ b=0;
+ }
- if (bml==0x03)
- {
- Z80Word a;
- Z80Word *reg;
+ cpu->AF.b[LO]=CARRY|PSZtable[b];
+ SETHIDDEN(b);
+ break;
+ }
- TSTATE(20);
+ case 0x71: /* OUT (C) */
+ TSTATE(12);
+ if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,0);
+ break;
- a=FETCH_WORD;
- reg=Get16_HL(cpu,bmm>>1);
+ case 0x72: /* SBC HL,SP */
+ TSTATE(15);
+ SBC16(cpu->HL.w,cpu->SP);
+ break;
- if (bmm&1) /* LD rr,(nn) */
- {
- *reg=PEEKW(a);
- }
- else /* LD (nn),rr */
- {
- POKEW(a,*reg);
- }
+ case 0x73: /* LD (nnnn),SP */
+ TSTATE(20);
+ POKEW(FETCH_WORD,cpu->SP);
+ break;
- return;
- }
+ case 0x74: /* NEG */
+ {
+ Z80Byte b;
- if (bml==0x04) /* NEG */
- {
- Z80Byte v;
+ TSTATE(8);
- TSTATE(8);
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
- v=cpu->AF.b[HI];
- cpu->AF.b[HI]=0;
+ case 0x75: /* RETN */
+ TSTATE(14);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
- SUB8(cpu,v);
+ case 0x76: /* IM 1 */
+ TSTATE(8);
+ cpu->IM=1;
+ break;
- return;
- }
+ case 0x77: /* NOP */
+ TSTATE(8);
+ CALLBACK(eZ80_EDHook,opcode);
+ break;
- if (bml==0x05)
- {
- TSTATE(14);
+ case 0x78: /* IN A,(C) */
+ TSTATE(12);
- if (bmm&1) /* RETI */
- {
- POP(cpu->PC);
- CALLBACK(eZ80_RETI,0);
- }
- else /* RETN */
- {
+ 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;
- return;
- }
+ case 0xb1: /* CPIR */
+ TSTATE(16);
+ CPI;
+ if (cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
- if (bml==0x06) /* IM n */
- {
- TSTATE(8);
+ case 0xb2: /* INIR */
+ TSTATE(16);
+ INI;
+ if (cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ 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 0xb3: /* OTIR */
+ TSTATE(16);
+ OUTI;
+ if (cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
- return;
- }
+ case 0xb8: /* LDDR */
+ TSTATE(16);
+ LDD;
+ if (cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
- if (bml==0x07)
- {
- Z80Byte b;
+ case 0xb9: /* CPDR */
+ TSTATE(16);
+ CPD;
+ if (cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ 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 0xba: /* INDR */
+ TSTATE(16);
+ IND;
+ if (cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
- return;
+ 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;
}
}
-static void EDOp_10(Z80 *cpu, Z80Byte opcode,
- Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
+/* ---------------------------------------- HANDLERS FOR CB OPCODES
+*/
+static void DecodeCB(Z80 *cpu, Z80Byte opcode)
{
- 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;
- }
- }
-
- 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;
- }
+ 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,RES,0)
+ CB_BITMANIP_BLOCK(0x88,RES,1)
+ CB_BITMANIP_BLOCK(0x90,RES,2)
+ CB_BITMANIP_BLOCK(0x98,RES,3)
+ CB_BITMANIP_BLOCK(0xa0,RES,4)
+ CB_BITMANIP_BLOCK(0xa8,RES,5)
+ CB_BITMANIP_BLOCK(0xb0,RES,6)
+ CB_BITMANIP_BLOCK(0xb8,RES,7)
+
+ CB_BITMANIP_BLOCK(0xc0,SET,0)
+ CB_BITMANIP_BLOCK(0xc8,SET,1)
+ CB_BITMANIP_BLOCK(0xd0,SET,2)
+ CB_BITMANIP_BLOCK(0xd8,SET,3)
+ CB_BITMANIP_BLOCK(0xe0,SET,4)
+ CB_BITMANIP_BLOCK(0xe8,SET,5)
+ CB_BITMANIP_BLOCK(0xf0,SET,6)
+ CB_BITMANIP_BLOCK(0xf8,SET,7)
}
+}
- 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;
- }
- }
- 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;
- }
- }
+static void ShiftedDecodeCB(Z80 *cpu, Z80Byte opcode, Z80Relative offset)
+{
+ Z80Word addr;
- /* Everything else is a NOP
+ /* See if we've come here from a IX/IY shift.
*/
- CALLBACK(eZ80_EDHook,opcode);
+ 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,RES,0)
+ SHIFTED_CB_BITMANIP_BLOCK(0x88,RES,1)
+ SHIFTED_CB_BITMANIP_BLOCK(0x90,RES,2)
+ SHIFTED_CB_BITMANIP_BLOCK(0x98,RES,3)
+ SHIFTED_CB_BITMANIP_BLOCK(0xa0,RES,4)
+ SHIFTED_CB_BITMANIP_BLOCK(0xa8,RES,5)
+ SHIFTED_CB_BITMANIP_BLOCK(0xb0,RES,6)
+ SHIFTED_CB_BITMANIP_BLOCK(0xb8,RES,7)
+
+ SHIFTED_CB_BITMANIP_BLOCK(0xc0,SET,0)
+ SHIFTED_CB_BITMANIP_BLOCK(0xc8,SET,1)
+ SHIFTED_CB_BITMANIP_BLOCK(0xd0,SET,2)
+ SHIFTED_CB_BITMANIP_BLOCK(0xd8,SET,3)
+ SHIFTED_CB_BITMANIP_BLOCK(0xe0,SET,4)
+ SHIFTED_CB_BITMANIP_BLOCK(0xe8,SET,5)
+ SHIFTED_CB_BITMANIP_BLOCK(0xf0,SET,6)
+ SHIFTED_CB_BITMANIP_BLOCK(0xf8,SET,7)
+ }
}
-static void DecodeED(Z80 *cpu, Z80Byte opcode)
+/* ---------------------------------------- NORMAL OPCODE DECODER
+*/
+void Z80_Decode(Z80 *cpu, Z80Byte opcode)
{
- Z80Byte bmh,bmm,bml;
+ Z80Word *HL;
+ Z80Byte *H;
+ Z80Byte *L;
+ Z80Relative off;
- /* Split up the opcode into it's bitmasks
+ /* See if we've come here from a IX/IY shift
*/
- bmh=(opcode>>6)&3;
- bmm=(opcode>>3)&7;
- bml=opcode&7;
+ 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;
- /* Instruction set 01
- */
- if (bmh==0x01)
- {
- EDOp_01(cpu,opcode,bmh,bmm,bml);
- return;
- }
+ case 0x01: /* LD BC,nnnn */
+ TSTATE(10);
+ cpu->BC.w=FETCH_WORD;
+ break;
- /* Instruction set 10
- */
- if (bmh==0x02)
- {
- EDOp_10(cpu,opcode,bmh,bmm,bml);
- return;
- }
+ case 0x02: /* LD (BC),A */
+ TSTATE(7);
+ POKE(cpu->BC.w,cpu->AF.b[HI]);
+ break;
- /* All the rest are NOP/invalid
- */
- CALLBACK(eZ80_EDHook,opcode);
-}
+ case 0x03: /* INC BC */
+ TSTATE(6);
+ cpu->BC.w++;
+ break;
+ case 0x04: /* INC B */
+ TSTATE(4);
+ INC8(cpu->BC.b[HI]);
+ break;
-/* ---------------------------------------- HANDLERS FOR CB OPCODES
-*/
+ 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;
-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 0x07: /* RLCA */
+ TSTATE(4);
+ RLCA;
+ break;
- TSTATE(15);
- a=GetHL(cpu);
+ case 0x08: /* EX AF,AF' */
+ TSTATE(4);
+ SWAP(cpu->AF.w,cpu->AF_);
+ 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 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;
-static void CBOp_01(Z80 *cpu, Z80Byte opcode,
- Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
-{
- Z80Byte *reg;
+ case 0x0b: /* DEC BC */
+ TSTATE(6);
+ cpu->BC.w--;
+ break;
- reg=Get8(cpu,bml);
+ case 0x0c: /* INC C */
+ TSTATE(4);
+ INC8(cpu->BC.b[LO]);
+ 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 0x0d: /* DEC C */
+ TSTATE(4);
+ DEC8(cpu->BC.b[LO]);
+ break;
- TSTATE(12);
- a=GetHL(cpu);
- BIT(cpu,PEEK(a),bmm);
- }
- else
- {
- TSTATE(8);
- BIT(cpu,*reg,bmm);
- }
-}
+ case 0x0e: /* LD C,n */
+ TSTATE(7);
+ cpu->BC.b[LO]=FETCH_BYTE;
+ break;
+ case 0x0f: /* RRCA */
+ TSTATE(4);
+ RRCA;
+ break;
-static void CBOp_ResSet(Z80 *cpu, Z80Byte opcode,
- Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
-{
- Z80Byte *reg;
- int reset;
+ case 0x10: /* DJNZ */
+ if (--(cpu->BC.b[HI]))
+ {
+ TSTATE(13);
+ JR;
+ }
+ else
+ {
+ TSTATE(8);
+ NOJR;
+ }
+ break;
- reg=Get8(cpu,bml);
+ case 0x11: /* LD DE,nnnn */
+ TSTATE(10);
+ cpu->DE.w=FETCH_WORD;
+ break;
- reset=(bmh==0x02);
+ case 0x12: /* LD (DE),A */
+ TSTATE(7);
+ POKE(cpu->DE.w,cpu->AF.b[HI]);
+ 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 0x13: /* INC DE */
+ TSTATE(6);
+ cpu->DE.w++;
+ break;
- TSTATE(15);
- a=GetHL(cpu);
+ case 0x14: /* INC D */
+ TSTATE(4);
+ INC8(cpu->DE.b[HI]);
+ break;
- if (reset)
- {
- CLR(cpu->memory[a],bmm);
- }
- else
- {
- SET(cpu->memory[a],bmm);
- }
+ case 0x15: /* DEC D */
+ TSTATE(4);
+ DEC8(cpu->DE.b[HI]);
+ break;
- if (cpu->shift && reg)
- {
- *reg=cpu->memory[a];
- }
- }
- else
- {
- TSTATE(8);
- if (reset)
- {
- CLR(*reg,bmm);
- }
- else
- {
- SET(*reg,bmm);
- }
- }
-}
+ case 0x16: /* LD D,n */
+ TSTATE(7);
+ cpu->DE.b[HI]=FETCH_BYTE;
+ break;
+ case 0x17: /* RLA */
+ TSTATE(4);
+ RLA;
+ break;
-static void DecodeCB(Z80 *cpu, Z80Byte opcode)
-{
- Z80Byte bmh,bmm,bml;
+ case 0x18: /* JR d */
+ TSTATE(12);
+ JR;
+ break;
- /* Split up the opcode into it's bitmasks
- */
- bmh=(opcode>>6)&3;
- bmm=(opcode>>3)&7;
- bml=opcode&7;
+ case 0x19: /* ADD HL,DE */
+ TSTATE(11);
+ ADD16(*HL,cpu->DE.w);
+ break;
- /* Instruction set 00
- */
- if (bmh==0x00)
- {
- CBOp_00(cpu,opcode,bmh,bmm,bml);
- return;
- }
+ case 0x1a: /* LD A,(DE) */
+ TSTATE(7);
+ cpu->AF.b[HI]=PEEK(cpu->DE.w);
+ break;
- /* Instruction set 01 (BIT)
- */
- if (bmh==0x01)
- {
- CBOp_01(cpu,opcode,bmh,bmm,bml);
- return;
- }
+ case 0x1b: /* DEC DE */
+ TSTATE(6);
+ cpu->DE.w--;
+ break;
- /* Instruction set 10 (RES) and 11 (SET)
- */
- CBOp_ResSet(cpu,opcode,bmh,bmm,bml);
-}
+ case 0x1c: /* INC E */
+ TSTATE(4);
+ INC8(cpu->DE.b[LO]);
+ break;
+ case 0x1d: /* DEC E */
+ TSTATE(4);
+ DEC8(cpu->DE.b[LO]);
+ 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 0x1e: /* LD E,n */
+ TSTATE(7);
+ cpu->DE.b[LO]=FETCH_BYTE;
+ 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 0x1f: /* RRA */
+ TSTATE(4);
+ RRA;
+ break;
- return;
- }
+ case 0x20: /* JR NZ,e */
+ JR_COND(!IS_Z);
+ 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 */
- {
+ case 0x21: /* LD HL,nnnn */
TSTATE(10);
- *Get16(cpu,bmm>>1)=FETCH_WORD;
- }
+ *HL=FETCH_WORD;
+ break;
- return;
- }
+ case 0x22: /* LD (nnnn),HL */
+ TSTATE(16);
+ POKEW(FETCH_WORD,*HL);
+ 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 0x23: /* INC HL */
+ TSTATE(6);
+ (*HL)++;
+ break;
- return;
- }
+ case 0x24: /* INC H */
+ TSTATE(4);
+ INC8(*H);
+ 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 0x25: /* DEC H */
+ TSTATE(4);
+ DEC8(*H);
+ break;
- return;
- }
+ case 0x26: /* LD H,n */
+ TSTATE(7);
+ *H=FETCH_BYTE;
+ break;
- if (bml==0x04)
- {
- bp=Get8(cpu,bmm);
+ case 0x27: /* DAA */
+ TSTATE(4);
+ DAA(cpu);
+ break;
- if(!bp) /* INC (HL) */
- {
- Z80Word a;
+ case 0x28: /* JR Z,d */
+ JR_COND(IS_Z);
+ break;
+ case 0x29: /* ADD HL,HL */
TSTATE(11);
- a=GetHL(cpu);
- POKE(a,INC8(cpu,PEEK(a)));
- }
- else /* INC r */
- {
+ ADD16(*HL,cpu->HL.w);
+ 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);
- *bp=INC8(cpu,*bp);
- }
+ INC8(*L);
+ break;
- return;
- }
+ case 0x2d: /* DEC L */
+ TSTATE(4);
+ DEC8(*L);
+ break;
- if (bml==0x05)
- {
- bp=Get8(cpu,bmm);
+ case 0x2e: /* LD L,n */
+ TSTATE(7);
+ *L=FETCH_BYTE;
+ break;
- if(!bp) /* INC (HL) */
- {
- Z80Word a;
+ case 0x2f: /* RRA */
+ TSTATE(4);
+ RRA;
+ 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);
+ POKEW(FETCH_WORD,cpu->AF.b[HI]);
+ break;
+ case 0x33: /* INC SP */
+ TSTATE(6);
+ cpu->SP++;
+ break;
+
+ case 0x34: /* INC (HL) */
TSTATE(11);
- a=GetHL(cpu);
- POKE(a,DEC8(cpu,PEEK(a)));
- }
- else /* INC r */
- {
+ OFFSET(off);
+ INC8(cpu->memory[*HL+off]);
+ break;
+
+ case 0x35: /* DEC (HL) */
+ TSTATE(11);
+ OFFSET(off);
+ DEC8(cpu->memory[*HL+off]);
+ break;
+
+ case 0x36: /* LD (HL),n */
+ TSTATE(10);
+ OFFSET(off);
+ cpu->memory[*HL+off]=FETCH_BYTE;
+ break;
+
+ case 0x37: /* SCF */
TSTATE(4);
- *bp=DEC8(cpu,*bp);
- }
+ SETFLAG(C_Z80);
+ break;
- return;
- }
+ case 0x38: /* JR C,d */
+ JR_COND(IS_C);
+ break;
- if (bml==0x06)
- {
- bp=Get8(cpu,bmm);
+ case 0x39: /* ADD HL,SP */
+ TSTATE(11);
+ ADD16(*HL,cpu->SP);
+ break;
- if(!bp) /* LD (HL),n */
- {
- Z80Word a;
+ case 0x3a: /* LD A,(nnnn) */
+ TSTATE(13);
+ cpu->AF.b[HI]=cpu->memory[FETCH_WORD];
+ break;
- TSTATE(10);
- a=GetHL(cpu);
- POKE(a,FETCH_BYTE);
- }
- else /* LD r,n */
- {
+ 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);
- *bp=FETCH_BYTE;
- }
+ cpu->AF.b[HI]=FETCH_BYTE;
+ break;
- return;
- }
+ case 0x3f: /* CCF */
+ TSTATE(4);
+ cpu->AF.b[LO]^=C_Z80;
+ 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;
- }
+ LD_BLOCK(0x40,cpu->BC.b[HI])
+ LD_BLOCK(0x48,cpu->BC.b[LO])
+ LD_BLOCK(0x50,cpu->DE.b[HI])
+ LD_BLOCK(0x58,cpu->DE.b[LO])
+ LD_BLOCK(0x60,*H)
+ LD_BLOCK(0x68,*L)
- return;
- }
-}
+ case 0x70: /* LD (HL),B */
+ TSTATE(7);
+ OFFSET(off);
+ cpu->memory[*HL+off]=cpu->BC.b[HI];
+ break;
+ case 0x71: /* LD (HL),C */
+ TSTATE(7);
+ OFFSET(off);
+ cpu->memory[*HL+off]=cpu->BC.b[LO];
+ break;
-static void Normal_01(Z80 *cpu, Z80Byte opcode,
- Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
-{
- Z80Byte *dest;
- Z80Byte *src;
+ case 0x72: /* LD (HL),D */
+ TSTATE(7);
+ OFFSET(off);
+ cpu->memory[*HL+off]=cpu->DE.b[HI];
+ break;
- dest=Get8(cpu,bmm);
- src=Get8(cpu,bml);
+ case 0x73: /* LD (HL),E */
+ TSTATE(7);
+ OFFSET(off);
+ cpu->memory[*HL+off]=cpu->DE.b[LO];
+ break;
- /* Handle HALT
- */
- if (!dest && !src)
- {
- TSTATE(4);
- cpu->PC--;
+ case 0x74: /* LD (HL),H */
+ TSTATE(7);
+ OFFSET(off);
+ cpu->memory[*HL+off]=cpu->HL.b[HI];
+ break;
- /* Inform user of HALT going high
- */
- if (!cpu->halt)
- CALLBACK(eZ80_Halt,1);
+ case 0x75: /* LD (HL),L */
+ TSTATE(7);
+ OFFSET(off);
+ cpu->memory[*HL+off]=cpu->HL.b[LO];
+ break;
- cpu->halt=TRUE;
+ case 0x76: /* HALT */
+ TSTATE(4);
+ cpu->PC--;
- return;
- }
+ if (!cpu->halt)
+ CALLBACK(eZ80_Halt,1);
- /* 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;
+ cpu->halt=TRUE;
+ break;
+ case 0x77: /* LD (HL),A */
TSTATE(7);
+ OFFSET(off);
+ cpu->memory[*HL+off]=cpu->AF.b[HI];
+ break;
+
+ LD_BLOCK(0x78,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;
- /* Reget the source in case we're shifted. HL is the source when
- doing an (HL) style store.
+ 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.
*/
- src=Get8_HL(cpu,bml);
+ if (cpu->shift!=0)
+ {
+ Z80Relative cb_offset;
- a=GetHL(cpu);
+ TSTATE(4); /* Wild stab in the dark! */
+ cb_offset=FETCH_BYTE;
+ ShiftedDecodeCB(cpu,FETCH_BYTE,cb_offset);
+ }
+ else
+ {
+ DecodeCB(cpu,FETCH_BYTE);
+ }
+ break;
- POKE(a,*src);
- }
- else
- {
- TSTATE(4);
- *dest=*src;
- }
- }
- else
- {
- Z80Word a;
+ case 0xcc: /* CALL Z,nnnn */
+ CALL_COND(IS_Z);
+ break;
- TSTATE(7);
+ case 0xcd: /* CALL nnnn */
+ CALL_COND(1);
+ 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 0xce: /* ADC A,n */
+ ADC8(FETCH_BYTE);
+ break;
- a=GetHL(cpu);
- *dest=PEEK(a);
- }
-}
+ case 0xcf: /* RST 8 */
+ RST(8);
+ break;
+ case 0xd0: /* RET NC */
+ RET_COND(!IS_C);
+ 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 0xd1: /* POP DE */
+ TSTATE(10);
+ POP(cpu->DE.w);
+ break;
- TSTATE(7);
- a=GetHL(cpu);
- op[bmm](cpu,PEEK(a));
- }
- else /* op A,r */
- {
- TSTATE(4);
- op[bmm](cpu,*reg);
- }
-}
+ 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;
-static void Normal_11(Z80 *cpu, Z80Byte opcode,
- Z80Byte bmh, Z80Byte bmm, Z80Byte bml)
-{
- Z80Reg tmp;
+ case 0xd4: /* CALL NC,nnnn */
+ CALL_COND(!IS_C);
+ break;
- if (bml==0x00) /* RET cc */
- {
- if (GetCond(cpu,bmm))
- {
+ case 0xd5: /* PUSH DE */
TSTATE(11);
- POP(cpu->PC);
- }
- else
- {
- TSTATE(5);
- }
+ PUSH(cpu->DE.w);
+ break;
- return;
- }
+ case 0xd6: /* SUB A,n */
+ TSTATE(7);
+ SUB8(FETCH_BYTE);
+ 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 0xd7: /* RST 10 */
+ RST(0x10);
+ break;
- return;
- }
+ case 0xd8: /* RET C */
+ RET_COND(IS_C);
+ break;
- if (bml==0x02) /* JP cc */
- {
- TSTATE(10);
+ case 0xd9: /* EXX */
+ TSTATE(4);
+ SWAP(cpu->BC.w,cpu->BC_);
+ SWAP(cpu->DE.w,cpu->DE_);
+ SWAP(cpu->HL.w,cpu->HL_);
+ break;
- if (GetCond(cpu,bmm))
- {
- JP;
- }
- else
- {
- NOJP;
- }
+ case 0xda: /* JP C,nnnn */
+ JP_COND(IS_C);
+ break;
- return;
- }
+ case 0xdb: /* IN A,(n) */
+ TSTATE(11);
+ if (cpu->pread)
+ cpu->AF.b[HI]=cpu->pread(cpu,FETCH_BYTE);
+ else
+ cpu->PC++;
+ break;
- if (bml==0x03)
- {
- Z80Word tmp;
- Z80Word *reg;
+ case 0xdc: /* CALL C,nnnn */
+ CALL_COND(IS_C);
+ 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 0xdd: /* DD PREFIX */
+ TSTATE(4);
+ INC_R;
- return;
- }
+ cpu->shift=opcode;
+ Z80_Decode(cpu,FETCH_BYTE);
+ break;
- if (bml==0x04) /* CALL cc */
- {
- if (GetCond(cpu,bmm))
- {
- TSTATE(12);
- CALL;
- }
- else
- {
+ case 0xde: /* SBC A,n */
TSTATE(7);
- NOCALL;
- }
+ SBC8(FETCH_BYTE);
+ break;
- return;
- }
+ case 0xdf: /* RST 18 */
+ RST(0x18);
+ break;
- if (bml==0x05)
- {
- if (bmm==01) /* CALL nn */
- {
- TSTATE(17);
- CALL;
- }
- else
- {
- if (!(bmm&1)) /* PUSH rr */
+ 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 */
{
- TSTATE(11);
- PUSH(*Get16_AF(cpu,bmm>>1));
+ Z80Word tmp;
+ TSTATE(19);
+ POP(tmp);
+ PUSH(*HL);
+ *HL=tmp;
}
+ break;
- /* Everything else is a shift */
- }
+ case 0xe4: /* CALL PO,nnnn */
+ CALL_COND(!IS_P);
+ break;
- return;
- }
+ case 0xe5: /* PUSH HL */
+ TSTATE(10);
+ PUSH(*HL);
+ break;
- if (bml==0x06)
- {
- TSTATE(8);
+ case 0xe6: /* AND A,n */
+ TSTATE(7);
+ AND(FETCH_BYTE);
+ 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 0xe7: /* RST 20 */
+ RST(0x20);
+ break;
- return;
- }
+ case 0xe8: /* RET PE */
+ RET_COND(IS_P);
+ break;
- if (bml==0x07) /* RST nn */
- {
- TSTATE(11);
- PUSH(cpu->PC);
- cpu->PC=bmm*8;
- return;
- }
-}
+ case 0xe9: /* JP (HL) */
+ TSTATE(4);
+ cpu->PC=*HL;
+ break;
+ case 0xea: /* JP PE,nnnn */
+ JP_COND(IS_P);
+ break;
-/* ---------------------------------------- NORMAL OPCODE DECODER
-*/
-void Z80_Decode(Z80 *cpu, Z80Byte opcode)
-{
- Z80Byte bmh,bmm,bml;
+ case 0xeb: /* EX DE,HL */
+ TSTATE(4);
+ SWAP(cpu->DE.w,*HL);
+ break;
- /* IX/IY shifts
- */
- if (opcode==0xdd || opcode==0xfd)
- {
- TSTATE(4);
- INC_R;
+ case 0xec: /* CALL PE,nnnn */
+ CALL_COND(IS_P);
+ break;
- cpu->shift=opcode;
- Z80_Decode(cpu,FETCH_BYTE);
- return;
- }
+ case 0xed: /* ED PREFIX */
+ INC_R;
+ DecodeED(cpu,FETCH_BYTE);
+ break;
- /* CB shifts
- */
- if (opcode==0xcb)
- {
- INC_R;
+ case 0xee: /* XOR A,n */
+ TSTATE(7);
+ XOR(FETCH_BYTE);
+ break;
- /* Check for previous IX/IY shift.
- */
- if (cpu->shift!=0)
- {
- cpu->use_cb_off=TRUE;
- cpu->cb_off=(Z80Relative)FETCH_BYTE;
- }
+ case 0xef: /* RST 28 */
+ RST(0x28);
+ break;
- DecodeCB(cpu,FETCH_BYTE);
- return;
- }
+ case 0xf0: /* RET P */
+ RET_COND(!IS_S);
+ break;
- /* DE shifts
- */
- if (opcode==0xed)
- {
- INC_R;
- DecodeED(cpu,FETCH_BYTE);
- return;
- }
+ case 0xf1: /* POP AF */
+ TSTATE(10);
+ POP(cpu->AF.w);
+ break;
- /* Split up the opcode into it's bitmasks
- */
- bmh=(opcode>>6)&3;
- bmm=(opcode>>3)&7;
- bml=opcode&7;
+ case 0xf2: /* JP P,nnnn */
+ JP_COND(!IS_S);
+ break;
- /* Instruction set 00
- */
- if (bmh==0x00)
- {
- Normal_00(cpu,opcode,bmh,bmm,bml);
- return;
- }
+ case 0xf3: /* DI */
+ TSTATE(4);
+ cpu->IFF1=0;
+ cpu->IFF2=0;
+ break;
- /* Instruction set 01
- */
- if (bmh==0x01)
- {
- Normal_01(cpu,opcode,bmh,bmm,bml);
- return;
- }
+ case 0xf4: /* CALL P,nnnn */
+ CALL_COND(!IS_S);
+ break;
- /* Instruction set 10
- */
- if (bmh==0x02)
- {
- Normal_10(cpu,opcode,bmh,bmm,bml);
- return;
- }
+ case 0xf5: /* PUSH AF */
+ TSTATE(10);
+ PUSH(cpu->AF.w);
+ break;
- /* Instruction set 11
- */
- Normal_11(cpu,opcode,bmh,bmm,bml);
+ 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;
+
+ }
}
diff --git a/z80_private.h b/z80_private.h
index ae0ec8c..26adbbb 100644
--- a/z80_private.h
+++ b/z80_private.h
@@ -60,10 +60,10 @@ struct Z80
Z80Reg DE;
Z80Reg HL;
- Z80Reg AF_;
- Z80Reg BC_;
- Z80Reg DE_;
- Z80Reg HL_;
+ Z80Word AF_;
+ Z80Word BC_;
+ Z80Word DE_;
+ Z80Word HL_;
Z80Reg IX;
Z80Reg IY;
@@ -77,9 +77,6 @@ struct Z80
Z80Byte R;
int halt;
- int use_cb_off;
- Z80Relative cb_off;
-
Z80Byte shift;
int raise;
@@ -145,7 +142,7 @@ struct Z80
#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)
+#define PEEKW(addr) FPEEKW(cpu,addr)
#define POKE(addr,val) do \
{ \
@@ -157,8 +154,9 @@ struct Z80
#define POKEW(addr,val) do \
{ \
Z80Word once=val; \
- POKE(addr,once); \
- POKE(addr+1,once>>8); \
+ Z80Word once_addr=addr; \
+ POKE(once_addr,once); \
+ POKE(once_addr+1,once>>8); \
} while(0)
#define FETCH_BYTE (cpu->memory[cpu->PC++])
@@ -175,6 +173,9 @@ struct Z80
#define CARRY IS_C
+#define IS_IX_IY (cpu->shift==0xdd || cpu->shift==0xfd)
+#define OFFSET(off) off=(IS_IX_IY ? (Z80Relative)FETCH_BYTE:0)
+
#define TSTATE(n) cpu->cycle+=n
#define ADD_R(v) cpu->R=((cpu->R&0x80)|((cpu->R+(v))&0x7f))
@@ -205,11 +206,14 @@ struct Z80
#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) \
+#define OUT(P,V) do \
{ \
- cpu->pwrite(cpu,PORT,VAL); \
- }
+ if (cpu->pwrite) \
+ cpu->pwrite(cpu,P,V); \
+ } while(0)
+
+#define IN(P) (cpu->pread?cpu->pread(cpu,P):0)
+
/* ---------------------------------------- FLAG TABLES