From 458ae07fcde77592e06927f0dddcd12c8d242b29 Mon Sep 17 00:00:00 2001 From: Ian C Date: Fri, 25 Aug 2006 23:28:49 +0000 Subject: Devolopment checkin. Compiles, but doesn't pass tests. --- Makefile | 11 +- emma.c | 2 +- runtest | 2 + test.z80 | 17 + z80.c | 26 +- z80_decode.c | 3693 ++++++++++++++++++++++++++++++++------------------------- z80_private.h | 32 +- 7 files changed, 2109 insertions(+), 1674 deletions(-) create mode 100644 runtest create mode 100644 test.z80 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 @@ -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) +static Z80Word FPEEKW(Z80 *cpu, Z80Word addr) { - 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) -{ - 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<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<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; - /* Reget the source in case we're shifted. HL is the source when - doing an (HL) style store. + case 0xc4: /* CALL NZ,nnnn */ + CALL_COND(!IS_Z); + break; + + case 0xc5: /* PUSH BC */ + TSTATE(10); + PUSH(cpu->BC.w); + break; + + case 0xc6: /* ADD A,n */ + TSTATE(7); + ADD8(FETCH_BYTE); + break; + + case 0xc7: /* RST 0 */ + RST(0); + break; + + case 0xc8: /* RET Z */ + RET_COND(IS_Z); + break; + + case 0xc9: /* RET */ + TSTATE(10); + POP(cpu->PC); + break; + + case 0xca: /* JP Z,nnnn */ + JP_COND(IS_Z); + break; + + case 0xcb: /* CB PREFIX */ + INC_R; + + /* Check for previous IX/IY shift. */ - 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 -- cgit v1.2.3