From f295f65db435ab7cb384e44e1dd74dc6d7a34853 Mon Sep 17 00:00:00 2001 From: Ian C Date: Sun, 20 Aug 2006 22:31:42 +0000 Subject: Initial compilable version --- z80_decode.c | 3015 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 1765 insertions(+), 1250 deletions(-) (limited to 'z80_decode.c') diff --git a/z80_decode.c b/z80_decode.c index c323d1f..6bb34f5 100644 --- a/z80_decode.c +++ b/z80_decode.c @@ -28,359 +28,575 @@ Z80 */ +#include + +#include "z80.h" #include "z80_private.h" +static const char ident[]="$Id$"; + +/* ---------------------------------------- TABLES AND INIT +*/ +static const unsigned char partab[256] = { + 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, + 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, + 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, + 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, + 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, + 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, + 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, + 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, + 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, + 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, + 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, + 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, + 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, + 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, + 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, + 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, +}; + +static Z80Byte PSZtable[512]; +static Z80Byte SZtable[512]; +static Z80Byte Ptable[512]; +static Z80Byte Stable[512]; +static Z80Byte Ztable[512]; + + +static int HI; +static int LO; + +/* ---------------------------------------- PRIVATE FUNCTIONS +*/ +void Z80_InitialiseInternals(void) +{ + Z80Word f; + Z80Reg r; + + r.w=0x1234; + + if (r.b[0] == 0x12) + { + HI=0; + LO=1; + } + else if (r.b[1] == 0x12) + { + HI=1; + LO=0; + } + else + { + exit(1); + } + + /* Initialise flag tables + */ + for(f=0;f<256;f++) + { + Z80Byte p,z,s; + int b; + + p=0; + + for(b=0;b<8;b++) + if (f&(1<F=SZtable[w]; \ - if ((REG^w^VAL)&H_Z80) cpu->F|=H_Z80; \ - if ((VAL^REG^0x80)&(REG^w)&0x80) cpu->F|=P_Z80; \ - SETHIDDEN(w); \ - REG=w; \ -} while(0) - - -#define ADC_8_BIT(REG,VAL) \ -do \ -{ \ - Z80Word w; \ - w=(REG+(Z80Word)VAL+CARRY)&0x1ff; \ - cpu->F=SZtable[w]; \ - if ((REG^w^VAL)&H_Z80) cpu->F|=H_Z80; \ - if ((VAL^REG^0x80)&(REG^w)&0x80) cpu->F|=P_Z80; \ - SETHIDDEN(w); \ - REG=w; \ -} while(0) - - -#define SUB_8_BIT(REG,VAL) \ -do \ -{ \ - Z80Word w; \ - w=(REG-(Z80Word)VAL)&0x1ff; \ - cpu->F=SZtable[w]|N_Z80; \ - if ((REG^w^VAL)&H_Z80) cpu->F|=H_Z80; \ - if ((VAL^REG^0x80)&(REG^w)&0x80) cpu->F|=P_Z80; \ - SETHIDDEN(w); \ - REG=w; \ -} while(0) - - -#define CMP_8_BIT(REG,VAL) \ -do \ -{ \ - Z80Word w; \ - w=(REG-(Z80Word)VAL)&0x1ff; \ - cpu->F=SZtable[w]|N_Z80; \ - if ((REG^w^VAL)&H_Z80) cpu->F|=H_Z80; \ - if ((VAL^REG^0x80)&(REG^w)&0x80) cpu->F|=P_Z80; \ - SETHIDDEN(VAL); \ -} while(0) - - -#define SBC_8_BIT(REG,VAL) \ -do \ -{ \ - Z80Word w; \ - w=(REG-(Z80Word)VAL-CARRY)&0x1ff; \ - cpu->F=SZtable[w]|N_Z80; \ - if ((REG^w^VAL)&H_Z80) cpu->F|=H_Z80; \ - if ((VAL^REG^0x80)&(REG^w)&0x80) cpu->F|=P_Z80; \ - SETHIDDEN(w); \ - REG=w; \ -} while(0) - - -#define ADD_16_BIT(REG,VAL) \ -do \ -{ \ - Z80Val w; \ - w=REG+(Z80Val)VAL; \ - cpu->F&=(S_Z80|Z_Z80|V_Z80); \ - if (w>0xffff) cpu->F|=C_Z80; \ - if ((REG^w^VAL)&0x1000) cpu->F|=H_Z80; \ - SETHIDDEN(w>>8); \ - REG=w; \ -} while(0) - - -#define ADC_16_BIT(REG,VAL) \ -do \ -{ \ - Z80Val w; \ - w=REG+(Z80Val)VAL+CARRY; \ - cpu->F&=(S_Z80|Z_Z80|V_Z80); \ - if (w>0xffff) cpu->F|=C_Z80; \ - if ((REG^w^VAL)&0x1000) cpu->F|=H_Z80; \ - SETHIDDEN(w>>8); \ - REG=w; \ -} while(0) - - -#define SBC_16_BIT(REG,VAL) \ -do \ -{ \ - Z80Val w; \ - w=REG-(Z80Val)VAL-CARRY; \ - cpu->F=N_Z80; \ - if (w&0x8000) cpu->F|=S_Z80; \ - if ((w&0xffff)==0) cpu->F|=Z_Z80; \ - if (w>0xffff) cpu->F|=C_Z80; \ - if ((REG^w^VAL)&0x1000) cpu->F|=H_Z80; \ - if ((VAL^REG)&(VAL^w)&0x8000) cpu->F|=P_Z80; \ - SETHIDDEN(w>>8); \ - REG=w; \ -} while(0) - - -#define INC8(REG) \ -do \ -{ \ - REG++; \ - cpu->F=CARRY|SZtable[REG]; \ - if (w&0x80) cpu->F|=P_Z80; \ - if (w&0x0f) cpu->F|=H_Z80; \ -} while(0) - - -#define DEC8(REG) \ -do \ -{ \ - cpu->F=N_Z80|CARRY; \ - if (w&0x80) cpu->F|=P_Z80; \ - if (w&0x0f) cpu->F|=H_Z80; \ - REG--; \ - cpu->F|=SZtable[REG]; \ -} while(0) +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]&=(S_Z80|Z_Z80|V_Z80); + if (w>0xffff) cpu->AF.b[LO]|=C_Z80; + if ((REG^w^VAL)&0x1000) cpu->AF.b[LO]|=H_Z80; + SETHIDDEN(w>>8); + return w; +} + + +static Z80Word SBC16(Z80 *cpu, Z80Word REG, Z80Word VAL) +{ + Z80Val w; + w=REG-(Z80Val)VAL-CARRY; + cpu->AF.b[LO]=N_Z80; + if (w&0x8000) cpu->AF.b[LO]|=S_Z80; + if ((w&0xffff)==0) cpu->AF.b[LO]|=Z_Z80; + if (w>0xffff) cpu->AF.b[LO]|=C_Z80; + if ((REG^w^VAL)&0x1000) cpu->AF.b[LO]|=H_Z80; + if ((VAL^REG)&(VAL^w)&0x8000) cpu->AF.b[LO]|=P_Z80; + SETHIDDEN(w>>8); + return w; +} + + +static Z80Byte INC8(Z80 *cpu, Z80Byte REG) +{ + REG++; + cpu->AF.b[LO]=CARRY|SZtable[REG]; + if (REG&0x80) cpu->AF.b[LO]|=P_Z80; + if (REG&0x0f) cpu->AF.b[LO]|=H_Z80; + return REG; +} + + +static Z80Byte DEC8(Z80 *cpu, Z80Byte REG) +{ + cpu->AF.b[LO]=N_Z80|CARRY; + if (REG&0x80) cpu->AF.b[LO]|=P_Z80; + if (REG&0x0f) cpu->AF.b[LO]|=H_Z80; + REG--; + cpu->AF.b[LO]|=SZtable[REG]; + return REG; +} /* ---------------------------------------- ROTATE AND SHIFT OPS */ -#define RRCA \ -do \ -{ \ - cpu->F=(cpu->F&0xec)|cpu->A&C_Z80; \ - cpu->A=(cpu->A>>1)|(cpu->A<<7); \ - SETHIDDEN(cpu->A); \ -} while(0) - - -#define RRA \ -do \ -{ \ - Z80Byte c; \ - c=CARRY; \ - cpu->F=(cpu->F&0xec)|cpu->A&C_Z80; \ - cpu->A=(cpu->A>>1)|(c<<7); \ - SETHIDDEN(cpu->A); \ -} while(0) - - -#define RRC(REG) \ -do \ -{ \ - Z80Byte c; \ - c=REG&C_Z80; \ - REG=(REG>>1)|(REG<<7); \ - cpu->F=PSZtable[REG]|c; \ - SETHIDDEN(REG); \ -} while(0) - - -#define RR(REG) \ -do \ -{ \ - Z80Byte c; \ - c=REG&C_Z80; \ - REG=(REG>>1)|(CARRY<<7); \ - cpu->F=PSZtable[REG]|c; \ - SETHIDDEN(REG); \ -} while(0) - - -#define RLCA \ -do \ -{ \ - cpu->F=(cpu->F&0xec)|(cpu->A>>7); \ - cpu->A=(cpu->A<<1)|(cpu->A>>7); \ - SETHIDDEN(cpu->A); \ -} while(0) - - -#define RLA \ -do \ -{ \ - Z80Byte c; \ - c=CARRY; \ - cpu->F=(cpu->F&0xec)|(cpu->A>>7); \ - cpu->A=(cpu->A<<1)|c; \ - SETHIDDEN(cpu->A); \ -} while(0) - - -#define RLC(REG) \ -do \ -{ \ - Z80Byte c; \ - c=REG>>7; \ - REG=(REG<<1)|c; \ - cpu->F=PSZtable[REG]|c; \ - SETHIDDEN(REG); \ -} while(0) - - -#define RL(REG) \ -do \ -{ \ - Z80Byte c; \ - c=REG>>7; \ - REG=(REG<<1)|CARRY; \ - cpu->F=PSZtable[REG]|c; \ - SETHIDDEN(REG); \ -} while(0) - - -#define SRL(REG) \ -do \ -{ \ - Z80Byte c; \ - c=REG&Z80_C; \ - REG>>=1; \ - cpu->F=PSZtable[REG]|c; \ - SETHIDDEN(REG); \ -} while(0) - - -#define SRA(REG) \ -do \ -{ \ - Z80Byte c; \ - c=REG&Z80_C; \ - REG=(REG>>1)|(REG&0x80); \ - cpu->F=PSZtable[REG]|c; \ - SETHIDDEN(REG); \ -} while(0) - - -#define SLL(REG) \ -do \ -{ \ - Z80Byte c; \ - c=REG>>7; \ - REG=(REG<<1)|1; \ - cpu->F=PSZtable[REG]|c; \ - SETHIDDEN(REG); \ -} while(0) - - -#define SLA(REG) \ -do \ -{ \ - Z80Byte c; \ - c=REG>>7; \ - REG=REG<<1; \ - cpu->F=PSZtable[REG]|c; \ - SETHIDDEN(REG); \ -} while(0) - - -/* ---------------------------------------- FLOW OPS -*/ -#define CALL(COND) \ -do \ -{ \ - if (COND) \ - { \ - PUSH(cpu->PC+2); \ - cpu->PC=PEEKW(cpu->PC); \ - } \ - else \ - { \ - cpu->PC+=2; \ - } \ -} \ -while(0) - - -#define JP(COND) \ -do \ -{ \ - if (COND) \ - { \ - cpu->PC=PEEKW(cpu->PC); \ - } \ - else \ - { \ - cpu->PC+=2; \ - } \ -} \ -while(0) - - -#define JR(COND) \ -do \ -{ \ - if (COND) \ - { \ - cpu->PC+=(Z80Relative)PEEK(cpu->PC)+1; \ - } \ - else \ - { \ - cpu->PC++; \ - } \ -} \ -while(0) +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; +} /* ---------------------------------------- BOOLEAN OPS */ -#define AND(REG,VAL) \ -do \ -{ \ - REG&=VAL; \ - cpu->F=PSZtable[REG]|H_Z80; \ - SETHIDDEN(REG); \ -} while(0) - - -#define OR(REG,VAL) \ -do \ -{ \ - REG|=VAL; \ - cpu->F=PSZtable[REG]; \ - SETHIDDEN(REG); \ -} while(0) - - -#define XOR(REG,VAL) \ -do \ -{ \ - REG^=VAL; \ - cpu->F=PSZtable[REG]; \ - SETHIDDEN(REG); \ -} while(0) - - -#define BIT(REG,B) \ -do \ -{ \ - cpu->F=CARRY|H_Z80; \ - if (REG&&(1<F|=S_Z80; \ - if (B==5) cpu->F|=B5_Z80; \ - if (B==3) cpu->F|=B3_Z80; \ - } \ - else \ - { \ - cpu->F|=Z_Z80; \ - } \ -} while(0) +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; + } +} + + +/* ---------------------------------------- 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]); +} + /* ---------------------------------------- GENERAL MACROS @@ -392,18 +608,17 @@ do \ #define GETREL (cpu->use_cb_off ? cpu->cb_off : (Z80Relative)FETCH_BYTE) -/* ---------------------------------------- GENERAL UTILS +/* ---------------------------------------- DAA */ /* This code based on the DAA opcode from YAZE, (c) Frank D. Cringle */ static void DAA (Z80 *cpu) { - Z80Word AF; - Z80Word acu,temp,cbits; + Z80Word AF,acu,temp,cbits; - AF=(Z80Word)cpu->A<<8|cpu->F; - acu=cpu->A; + AF=cpu->AF.w; + acu=cpu->AF.b[HI]; temp=acu&0xf; cbits=CARRY; @@ -446,1130 +661,1430 @@ static void DAA (Z80 *cpu) AF = (acu << 8) | (acu & 0xa8) | ((acu == 0) << 6) | (AF & 0x12) | partab[acu] | cbits; - cpu->A=(AF>>8); - cpu->F=(AF&0xff); - SETHIDDEN(cpu->A); + cpu->AF.w=AF; + SETHIDDEN(cpu->AF.b[HI]); } +/* ---------------------------------------- DECODE AND REGISTER SELECTION +*/ -/* ---------------------------------------- HANDLERS FOR CB OPCODES +/* Get the 16 bit register to use according to the bitmask */ -static void DecodeCB(Z80 *cpu, Z80Byte opcode) +static Z80Word *Get16(Z80 *cpu, Z80Byte bm) { - switch(opcode) - { - } + if (bm==0x00) + return &cpu->BC.w; - Z80Byte bmh,bmm,bml; - - /* Split up the opcode into it's bitmasks - */ - bmh=(opcode>>6)&3; - bmm=(opcode>>3)&7; - bml=opcode&7; + if (bm==0x01) + return &cpu->DE.w; - /* Instruction set 00 - */ - if (bmh==0x00) + if (bm==0x02) { - CBOp_00(cpu,opcode,bmh,bmm,bml); - return; - } + if (cpu->shift==0xdd) + return &cpu->IX.w; - /* Instruction set 01 (BIT) - */ - if (bmh==0x01) - { - CBOp_01(cpu,opcode,bmh,bmm,bml); - return; + if (cpu->shift==0xfd) + return &cpu->IY.w; + + return &cpu->HL.w; } - /* Instruction set 10 (RES) and 11 (SET) - */ - CBOp_ResSet(cpu,opcode,bmh,bmm,bml); + return &cpu->SP; } +/* 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; + + if (bm==0x01) + return &cpu->DE.w; + + if (bm==0x02) + return &cpu->HL.w; + + return &cpu->SP; +} -/* ---------------------------------------- OPCODE DECODER +/* Get the 16 bit register to use according to the bitmask, + with AF instead of SP */ -void Z80_Decode(Z80 *cpu, Z80Byte opcode) +static Z80Word *Get16_AF(Z80 *cpu, Z80Byte bm) { - Z80Byte bmh,bmm,bml; + if (bm==0x00) + return &cpu->BC.w; - /* IX/IY shifts - */ - if (opcode==0xdd || opcode==0xfd) + if (bm==0x01) + return &cpu->DE.w; + + if (bm==0x02) { - TSTATE(4); - INC_R; + if (cpu->shift==0xdd) + return &cpu->IX.w; - cpu->shift=opcode; - Z80_Decode(cpu,FETCH_BYTE); - return; + if (cpu->shift==0xfd) + return &cpu->IY.w; + + return &cpu->HL.w; } - /* CB shifts - */ - if (opcode==0xcb) + return &cpu->AF.w; +} + + +/* 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]; + + if (bm==0x00) + return &cpu->BC.b[HI]; + + if (bm==0x01) + return &cpu->BC.b[LO]; + + if (bm==0x02) + return &cpu->DE.b[HI]; + + if (bm==0x03) + return &cpu->DE.b[LO]; + + if (bm==0x04) { - INC_R; + if (cpu->shift==0xdd) + return &cpu->IX.b[HI]; - /* Check for previous IX/IY shift. - */ - if (cpu->shift!=0) - { - cpu->use_cb_off=TRUE; - cpu->cb_off=(Z80Relative)FETCH_BYTE; - } + if (cpu->shift==0xfd) + return &cpu->IY.b[HI]; - DecodeCB(cpu,FETCH_BYTE); - return; + return &cpu->HL.b[HI]; } - /* DE shifts - */ - if (opcode==0xed) + if (bm==0x05) { - INC_R; - DecodeED(cpu,FETCH_BYTE); - return; - } - - *** NEW *** + if (cpu->shift==0xdd) + return &cpu->IX.b[LO]; - INC_R; + if (cpu->shift==0xfd) + return &cpu->IY.b[LO]; - switch(opcode) - { - case 0x00: /* NOP */ - TSTATE(4); - break; - - case 0x01: /* LD BC, nnnn */ - TSTATE(10); - cpu->BC=FETCH_WORD; - break; + return &cpu->HL.b[LO]; + } - case 0x02: - TSTATE(7); - break; + return NULL; +} - case 0x03: - TSTATE(4); - break; - case 0x04: - TSTATE(4); - break; +/* Get the 8 bit register to use according to the bitmask, ignoring the shift. + Returns NULL for (HL) +*/ +static Z80Byte *Get8_HL(Z80 *cpu, Z80Byte bm) +{ + if (bm==0x07) + return &cpu->AF.b[HI]; - case 0x05: - TSTATE(4); - break; + if (bm==0x00) + return &cpu->BC.b[HI]; - case 0x06: - TSTATE(4); - break; + if (bm==0x01) + return &cpu->BC.b[LO]; - case 0x07: - TSTATE(4); - break; + if (bm==0x02) + return &cpu->DE.b[HI]; - case 0x08: - TSTATE(4); - break; + if (bm==0x03) + return &cpu->DE.b[LO]; - case 0x09: - TSTATE(4); - break; + if (bm==0x04) + return &cpu->HL.b[HI]; - case 0x0a: - TSTATE(4); - break; + if (bm==0x05) + return &cpu->HL.b[LO]; - case 0x0b: - TSTATE(4); - break; + return NULL; +} - case 0x0c: - TSTATE(4); - break; - case 0x0d: - TSTATE(4); - break; +/* Get the address pointed to by HL, or the relative one depending on the shift +*/ +static Z80Word GetHL(Z80 *cpu) +{ + if (cpu->shift==0) + return cpu->HL.w; - case 0x0e: - TSTATE(4); - break; + if (cpu->shift==0xdd) + { + TSTATE(8); + return cpu->IX.w+GETREL; + } - case 0x0f: - TSTATE(4); - break; + if (cpu->shift==0xfd) + { + TSTATE(8); + return cpu->IY.w+GETREL; + } - case 0x10: - TSTATE(4); - break; + return 0; +} - case 0x11: - TSTATE(4); - break; - case 0x12: - TSTATE(4); - break; +/* Get the value of HL, IX, IY depending on the shift +*/ +static Z80Word GetHLVal(Z80 *cpu) +{ + if (cpu->shift==0) + return cpu->HL.w; - case 0x13: - TSTATE(4); - break; + if (cpu->shift==0xdd) + return cpu->IX.w; - case 0x14: - TSTATE(4); - break; + if (cpu->shift==0xfd) + return cpu->IY.w; - case 0x15: - TSTATE(4); - break; + return 0; +} - case 0x16: - TSTATE(4); - break; - case 0x17: - TSTATE(4); - break; +/* Get the register (HL, IX, IY) depending on the shift +*/ +static Z80Word* GetHLReg(Z80 *cpu) +{ + if (cpu->shift==0) + return &cpu->HL.w; - case 0x18: - TSTATE(4); - break; + if (cpu->shift==0xdd) + return &cpu->IX.w; - case 0x19: - TSTATE(4); - break; + if (cpu->shift==0xfd) + return &cpu->IY.w; - case 0x1a: - TSTATE(4); - break; + return 0; +} - case 0x1b: - TSTATE(4); - break; - case 0x1c: - TSTATE(4); - break; +/* Get a condition depending on the bitmask +*/ +static Z80Byte GetCond(Z80 *cpu, Z80Byte bm) +{ + if (bm==0x00) /* NZ */ + return !IS_Z; - case 0x1d: - TSTATE(4); - break; + if (bm==0x01) /* Z */ + return IS_Z; - case 0x1e: - TSTATE(4); - break; + if (bm==0x02) /* NC */ + return !IS_C; - case 0x1f: - TSTATE(4); - break; + if (bm==0x03) /* C */ + return IS_C; - case 0x20: - TSTATE(4); - break; + if (bm==0x04) /* PO */ + return !IS_P; - case 0x21: - TSTATE(4); - break; + if (bm==0x05) /* PE */ + return IS_P; - case 0x22: - TSTATE(4); - break; + if (bm==0x06) /* P */ + return !IS_S; - case 0x23: - TSTATE(4); - break; + if (bm==0x07) /* M */ + return IS_S; - case 0x24: - TSTATE(4); - break; + return 0; +} - case 0x25: - TSTATE(4); - break; - case 0x26: - TSTATE(4); - break; +/* ---------------------------------------- HANDLERS FOR ED OPCODES +*/ - case 0x27: - TSTATE(4); - break; - case 0x28: - TSTATE(4); - break; +static void EDOp_01(Z80 *cpu, Z80Byte opcode, + Z80Byte bmh, Z80Byte bmm, Z80Byte bml) +{ + if (bml==0x00) /* IN r,(C) */ + { + Z80Byte *reg; + Z80Byte v; - case 0x29: - TSTATE(4); - break; + TSTATE(12); - case 0x2a: - TSTATE(4); - break; + reg=Get8_HL(cpu,bmm); + v=IN(cpu->BC.w); - case 0x2b: - TSTATE(4); - break; + cpu->AF.b[LO]=(cpu->AF.b[LO]&C_Z80)|PSZtable[v]; + SETHIDDEN(v); - case 0x2c: - TSTATE(4); - break; + if (reg) + *reg=v; - case 0x2d: - TSTATE(4); - break; + return; + } - case 0x2e: - TSTATE(4); - break; + if (bml==0x01) /* OUT r,(C) */ + { + Z80Byte *reg; - case 0x2f: - TSTATE(4); - break; + TSTATE(12); - case 0x30: - TSTATE(4); - break; + reg=Get8_HL(cpu,bmm); + OUT(cpu->BC.w,reg ? *reg:0); - case 0x31: - TSTATE(4); - break; + return; + } - case 0x32: - TSTATE(4); - break; + if (bml==0x02) + { + Z80Word *reg; - case 0x33: - TSTATE(4); - break; + TSTATE(15); - case 0x34: - TSTATE(4); - break; + reg=Get16_HL(cpu,bmm>>1); - case 0x35: - TSTATE(4); - break; + if (bmm&1) /* ADC HL,rr */ + { + cpu->HL.w=ADC16(cpu,cpu->HL.w,*reg); + } + else /* SBC HL,rr */ + { + cpu->HL.w=SBC16(cpu,cpu->HL.w,*reg); + } - case 0x36: - TSTATE(4); - break; + return; + } - case 0x37: - TSTATE(4); - break; + if (bml==0x03) + { + Z80Word a; + Z80Word *reg; - case 0x38: - TSTATE(4); - break; + TSTATE(20); - case 0x39: - TSTATE(4); - break; + a=FETCH_WORD; + reg=Get16_HL(cpu,bmm>>1); - case 0x3a: - TSTATE(4); - break; + if (bmm&1) /* LD rr,(nn) */ + { + *reg=PEEKW(a); + } + else /* LD (nn),rr */ + { + POKEW(a,*reg); + } - case 0x3b: - TSTATE(4); - break; + return; + } - case 0x3c: - TSTATE(4); - break; + if (bml==0x04) /* NEG */ + { + Z80Byte v; - case 0x3d: - TSTATE(4); - break; + TSTATE(8); - case 0x3e: - TSTATE(4); - break; + v=cpu->AF.b[HI]; + cpu->AF.b[HI]=0; - case 0x3f: - TSTATE(4); - break; + SUB8(cpu,v); - case 0x40: - TSTATE(4); - break; + return; + } - case 0x41: - TSTATE(4); - break; + if (bml==0x05) + { + TSTATE(14); - case 0x42: - TSTATE(4); - break; + if (bmm&1) /* RETI */ + { + POP(cpu->PC); + CALLBACK(eZ80_RETI,0); + } + else /* RETN */ + { + cpu->IFF1=cpu->IFF2; + POP(cpu->PC); + } - case 0x43: - TSTATE(4); - break; + return; + } - case 0x44: - TSTATE(4); - break; + if (bml==0x06) /* IM n */ + { + TSTATE(8); - case 0x45: - TSTATE(4); - break; + switch(bmm&0x3) + { + case 0x00: + case 0x01: + cpu->IM=0; + break; + + case 0x02: + cpu->IM=1; + break; + + case 0x03: + cpu->IM=2; + break; + } - case 0x46: - TSTATE(4); - break; + return; + } - case 0x47: - TSTATE(4); - break; + if (bml==0x07) + { + Z80Byte b; - case 0x48: - TSTATE(4); - break; + switch(bmm) + { + case 0x00: /* LD I,A */ + TSTATE(9); + cpu->I=cpu->AF.b[HI]; + break; + case 0x01: /* LD R,A */ + TSTATE(9); + cpu->R=cpu->AF.b[HI]; + break; + case 0x02: /* LD A,I */ + TSTATE(9); + cpu->AF.b[HI]=cpu->I; + break; + case 0x03: /* LD A,R */ + TSTATE(9); + cpu->AF.b[HI]=cpu->R; + break; + case 0x04: /* RRD */ + TSTATE(18); + b=PEEK(cpu->HL.w); + POKE(cpu->HL.w,(b>>4)|(cpu->AF.b[HI]<<4)); + cpu->AF.b[HI]=(cpu->AF.b[HI]&0xF0)|(b&0x0f); + cpu->AF.b[LO]=(cpu->AF.b[LO]&C_Z80)|PSZtable[cpu->AF.b[HI]]; + SETHIDDEN(cpu->AF.b[HI]); + break; + case 0x05: /* RLD */ + TSTATE(18); + b=PEEK(cpu->HL.w); + POKE(cpu->HL.w,(b<<4)|(cpu->AF.b[HI]&0x0f)); + cpu->AF.b[HI]=(cpu->AF.b[HI]&0xF0)|(b>>4); + cpu->AF.b[LO]=(cpu->AF.b[LO]&C_Z80)|PSZtable[cpu->AF.b[HI]]; + SETHIDDEN(cpu->AF.b[HI]); + break; + case 0x06: /* NOP */ + case 0x07: + TSTATE(8); + break; + } - case 0x49: - TSTATE(4); - break; + return; + } +} - case 0x4a: - TSTATE(4); - break; - case 0x4b: - TSTATE(4); - break; +static void EDOp_10(Z80 *cpu, Z80Byte opcode, + Z80Byte bmh, Z80Byte bmm, Z80Byte bml) +{ + if (bml==0x00) + { + switch(bmm) + { + case 0x00: /* NOP */ + case 0x01: + case 0x02: + case 0x03: + TSTATE(8); + CALLBACK(eZ80_EDHook,opcode); + break; + case 0x04: /* LDI */ + TSTATE(16); + LDI(cpu); + break; + case 0x05: /* LDD */ + TSTATE(16); + LDD(cpu); + break; + case 0x06: /* LDIR */ + TSTATE(16); + LDI(cpu); + + if(cpu->BC.w) + { + TSTATE(5); + cpu->PC-=2; + } + break; + case 0x07: /* LDDR */ + TSTATE(16); + LDD(cpu); + + if(cpu->BC.w) + { + TSTATE(5); + cpu->PC-=2; + } + break; + } + } - case 0x4c: - TSTATE(4); - break; + if (bml==0x01) + { + switch(bmm) + { + case 0x00: /* NOP */ + case 0x01: + case 0x02: + case 0x03: + TSTATE(8); + CALLBACK(eZ80_EDHook,opcode); + break; + case 0x04: /* CPI */ + TSTATE(16); + CPI(cpu); + break; + case 0x05: /* CPD */ + TSTATE(16); + CPD(cpu); + break; + case 0x06: /* CPIR */ + TSTATE(16); + CPI(cpu); + + if(cpu->BC.w && !IS_Z) + { + TSTATE(5); + cpu->PC-=2; + } + break; + case 0x07: /* CPDR */ + TSTATE(16); + CPD(cpu); + + if(cpu->BC.w && !IS_Z) + { + TSTATE(5); + cpu->PC-=2; + } + break; + } + } - case 0x4d: - TSTATE(4); - break; + if (bml==0x02) + { + switch(bmm) + { + case 0x00: /* NOP */ + case 0x01: + case 0x02: + case 0x03: + TSTATE(8); + CALLBACK(eZ80_EDHook,opcode); + break; + case 0x04: /* INI */ + TSTATE(16); + INI(cpu); + break; + case 0x05: /* IND */ + TSTATE(16); + IND(cpu); + break; + case 0x06: /* INIR */ + TSTATE(16); + INI(cpu); + + if(cpu->BC.b[HI]) + { + TSTATE(5); + cpu->PC-=2; + } + break; + case 0x07: /* INDR */ + TSTATE(16); + IND(cpu); + + if(cpu->BC.b[HI]) + { + TSTATE(5); + cpu->PC-=2; + } + break; + } + } - case 0x4e: - TSTATE(4); - break; + if (bml==0x03) + { + switch(bmm) + { + case 0x00: /* NOP */ + case 0x01: + case 0x02: + case 0x03: + TSTATE(8); + CALLBACK(eZ80_EDHook,opcode); + break; + case 0x04: /* OUTI */ + TSTATE(16); + OUTI(cpu); + break; + case 0x05: /* OUTD */ + TSTATE(16); + OUTD(cpu); + break; + case 0x06: /* OTIR */ + TSTATE(16); + OUTI(cpu); + + if(cpu->BC.b[HI]) + { + TSTATE(5); + cpu->PC-=2; + } + break; + case 0x07: /* OTDR */ + TSTATE(16); + OUTD(cpu); + + if(cpu->BC.b[HI]) + { + TSTATE(5); + cpu->PC-=2; + } + break; + } + } - case 0x4f: - TSTATE(4); - break; + /* Everything else is a NOP + */ + CALLBACK(eZ80_EDHook,opcode); +} - case 0x50: - TSTATE(4); - break; - case 0x51: - TSTATE(4); - break; +static void DecodeED(Z80 *cpu, Z80Byte opcode) +{ + Z80Byte bmh,bmm,bml; - case 0x52: - TSTATE(4); - break; + /* Split up the opcode into it's bitmasks + */ + bmh=(opcode>>6)&3; + bmm=(opcode>>3)&7; + bml=opcode&7; - case 0x53: - TSTATE(4); - break; + /* Instruction set 01 + */ + if (bmh==0x01) + { + EDOp_01(cpu,opcode,bmh,bmm,bml); + return; + } - case 0x54: - TSTATE(4); - break; + /* Instruction set 10 + */ + if (bmh==0x02) + { + EDOp_10(cpu,opcode,bmh,bmm,bml); + return; + } - case 0x55: - TSTATE(4); - break; + /* All the rest are NOP/invalid + */ + CALLBACK(eZ80_EDHook,opcode); +} - case 0x56: - TSTATE(4); - break; - case 0x57: - TSTATE(4); - break; +/* ---------------------------------------- HANDLERS FOR CB OPCODES +*/ - case 0x58: - TSTATE(4); - break; - case 0x59: - TSTATE(4); - break; +static void CBOp_00(Z80 *cpu, Z80Byte opcode, + Z80Byte bmh, Z80Byte bmm, Z80Byte bml) +{ + static Z80Byte (*op[8])(Z80 *cpu, Z80Byte val)= + { + RLC, + RRC, + RL, + RR, + SLA, + SRA, + SLL, + SRL + }; + Z80Byte *reg; + + reg=Get8(cpu,bml); + + /* If the reg is NULL, this is an (HL) type arg. Also, if this is a + shifted op then the argument is taken from (HL) and also copied to the + register. + */ + if (cpu->shift || !reg) + { + Z80Word a; - case 0x5a: - TSTATE(4); - break; + TSTATE(15); + a=GetHL(cpu); - case 0x5b: - TSTATE(4); - break; + if (cpu->shift && reg) + { + *reg=op[bmm](cpu,PEEK(a)); + POKE(a,*reg); + } + else + POKE(a,op[bmm](cpu,PEEK(a))); + } + else + { + TSTATE(8); + *reg=op[bmm](cpu,*reg); + } +} - case 0x5c: - TSTATE(4); - break; - case 0x5d: - TSTATE(4); - break; +static void CBOp_01(Z80 *cpu, Z80Byte opcode, + Z80Byte bmh, Z80Byte bmm, Z80Byte bml) +{ + Z80Byte *reg; - case 0x5e: - TSTATE(4); - break; + reg=Get8(cpu,bml); - case 0x5f: - TSTATE(4); - break; + /* If the reg is NULL, this is an (HL) type arg. Also, if this is a + shifted op. + */ + if (cpu->shift || !reg) + { + Z80Word a; - case 0x60: - TSTATE(4); - break; + TSTATE(12); + a=GetHL(cpu); + BIT(cpu,PEEK(a),bmm); + } + else + { + TSTATE(8); + BIT(cpu,*reg,bmm); + } +} - case 0x61: - TSTATE(4); - break; - case 0x62: - TSTATE(4); - break; +static void CBOp_ResSet(Z80 *cpu, Z80Byte opcode, + Z80Byte bmh, Z80Byte bmm, Z80Byte bml) +{ + Z80Byte *reg; + int reset; - case 0x63: - TSTATE(4); - break; + reg=Get8(cpu,bml); - case 0x64: - TSTATE(4); - break; + reset=(bmh==0x02); - case 0x65: - TSTATE(4); - break; + /* If the reg is NULL, this is an (HL) type arg. Also, if this is a + shifted op then the argument is taken from (HL) and also copied to the + register. + */ + if (cpu->shift || !reg) + { + Z80Word a; - case 0x66: - TSTATE(4); - break; + TSTATE(15); + a=GetHL(cpu); - case 0x67: - TSTATE(4); - break; + if (reset) + { + CLR(cpu->memory[a],bmm); + } + else + { + SET(cpu->memory[a],bmm); + } - case 0x68: - TSTATE(4); - break; + if (cpu->shift && reg) + { + *reg=cpu->memory[a]; + } + } + else + { + TSTATE(8); + if (reset) + { + CLR(*reg,bmm); + } + else + { + SET(*reg,bmm); + } + } +} - case 0x69: - TSTATE(4); - break; - case 0x6a: - TSTATE(4); - break; +static void DecodeCB(Z80 *cpu, Z80Byte opcode) +{ + Z80Byte bmh,bmm,bml; - case 0x6b: - TSTATE(4); - break; - - case 0x6c: - TSTATE(4); - break; - - case 0x6d: - TSTATE(4); - break; - - case 0x6e: - TSTATE(4); - break; - - case 0x6f: - TSTATE(4); - break; - - case 0x70: - TSTATE(4); - break; - - case 0x71: - TSTATE(4); - break; - - case 0x72: - TSTATE(4); - break; - - case 0x73: - TSTATE(4); - break; - - case 0x74: - TSTATE(4); - break; - - case 0x75: - TSTATE(4); - break; - - case 0x76: - TSTATE(4); - break; - - case 0x77: - TSTATE(4); - break; - - case 0x78: - TSTATE(4); - break; - - case 0x79: - TSTATE(4); - break; - - case 0x7a: - TSTATE(4); - break; - - case 0x7b: - TSTATE(4); - break; - - case 0x7c: - TSTATE(4); - break; - - case 0x7d: - TSTATE(4); - break; - - case 0x7e: - TSTATE(4); - break; - - case 0x7f: - TSTATE(4); - break; - - case 0x80: - TSTATE(4); - break; - - case 0x81: - TSTATE(4); - break; - - case 0x82: - TSTATE(4); - break; - - case 0x83: - TSTATE(4); - break; - - case 0x84: - TSTATE(4); - break; - - case 0x85: - TSTATE(4); - break; - - case 0x86: - TSTATE(4); - break; - - case 0x87: - TSTATE(4); - break; - - case 0x88: - TSTATE(4); - break; - - case 0x89: - TSTATE(4); - break; - - case 0x8a: - TSTATE(4); - break; - - case 0x8b: - TSTATE(4); - break; - - case 0x8c: - TSTATE(4); - break; - - case 0x8d: - TSTATE(4); - break; - - case 0x8e: - TSTATE(4); - break; - - case 0x8f: - TSTATE(4); - break; - - case 0x90: - TSTATE(4); - break; - - case 0x91: - TSTATE(4); - break; - - case 0x92: - TSTATE(4); - break; - - case 0x93: - TSTATE(4); - break; - - case 0x94: - TSTATE(4); - break; - - case 0x95: - TSTATE(4); - break; - - case 0x96: - TSTATE(4); - break; - - case 0x97: - TSTATE(4); - break; - - case 0x98: - TSTATE(4); - break; - - case 0x99: - TSTATE(4); - break; - - case 0x9a: - TSTATE(4); - break; - - case 0x9b: - TSTATE(4); - break; - - case 0x9c: - TSTATE(4); - break; - - case 0x9d: - TSTATE(4); - break; - - case 0x9e: - TSTATE(4); - break; - - case 0x9f: - TSTATE(4); - break; - - case 0xa0: - TSTATE(4); - break; - - case 0xa1: - TSTATE(4); - break; - - case 0xa2: - TSTATE(4); - break; - - case 0xa3: - TSTATE(4); - break; - - case 0xa4: - TSTATE(4); - break; - - case 0xa5: - TSTATE(4); - break; - - case 0xa6: - TSTATE(4); - break; - - case 0xa7: - TSTATE(4); - break; - - case 0xa8: - TSTATE(4); - break; - - case 0xa9: - TSTATE(4); - break; - - case 0xaa: - TSTATE(4); - break; - - case 0xab: - TSTATE(4); - break; - - case 0xac: - TSTATE(4); - break; - - case 0xad: - TSTATE(4); - break; - - case 0xae: - TSTATE(4); - break; - - case 0xaf: - TSTATE(4); - break; - - case 0xb0: - TSTATE(4); - break; - - case 0xb1: - TSTATE(4); - break; - - case 0xb2: - TSTATE(4); - break; + /* Split up the opcode into it's bitmasks + */ + bmh=(opcode>>6)&3; + bmm=(opcode>>3)&7; + bml=opcode&7; - case 0xb3: - TSTATE(4); - break; + /* Instruction set 00 + */ + if (bmh==0x00) + { + CBOp_00(cpu,opcode,bmh,bmm,bml); + return; + } - case 0xb4: - TSTATE(4); - break; + /* Instruction set 01 (BIT) + */ + if (bmh==0x01) + { + CBOp_01(cpu,opcode,bmh,bmm,bml); + return; + } - case 0xb5: - TSTATE(4); - break; + /* Instruction set 10 (RES) and 11 (SET) + */ + CBOp_ResSet(cpu,opcode,bmh,bmm,bml); +} - case 0xb6: - TSTATE(4); - break; - case 0xb7: - TSTATE(4); - break; +/* ---------------------------------------- HANDLERS FOR NORMAL OPCODES +*/ +static void Normal_00(Z80 *cpu, Z80Byte opcode, + Z80Byte bmh, Z80Byte bmm, Z80Byte bml) +{ + Z80Reg tmp; + Z80Byte *bp=NULL; + Z80Word w; - case 0xb8: - TSTATE(4); - break; + if (bml==0x00) + { + switch(bmm) + { + case 0x00: /* NOP */ + TSTATE(4); + break; + case 0x01: /* EX AF,AF' */ + TSTATE(4); + tmp=cpu->AF; + cpu->AF=cpu->AF_; + cpu->AF_=tmp; + break; + case 0x02: /* DJNZ */ + if (--cpu->BC.b[HI]) + { + TSTATE(13); + JR; + } + else + { + TSTATE(8); + NOJR; + } + break; + case 0x03: /* JR */ + TSTATE(12); + JR; + break; + + case 0x04: /* JR cc */ + case 0x05: + case 0x06: + case 0x07: + if (GetCond(cpu,bmm&3)) + { + TSTATE(12); + JR; + } + else + { + TSTATE(7); + NOJR; + } + break; + } - case 0xb9: - TSTATE(4); - break; + return; + } - case 0xba: - TSTATE(4); - break; + if (bml==0x01) + { + if(bmm&1) /* ADD HL,rr */ + { + TSTATE(11); + *GetHLReg(cpu)=ADD16(cpu,*GetHLReg(cpu),*Get16(cpu,bmm>>1)); + } + else /* LD rr,nn */ + { + TSTATE(10); + *Get16(cpu,bmm>>1)=FETCH_WORD; + } - case 0xbb: - TSTATE(4); - break; + return; + } - case 0xbc: - TSTATE(4); - break; + if (bml==0x02) + { + switch(bmm) + { + case 0x00: /* LD (rr),A */ + case 0x02: + TSTATE(7); + POKE(*Get16(cpu,(bmm&2)>>1),cpu->AF.b[HI]); + break; + case 0x01: /* LD A,(rr) */ + case 0x03: + TSTATE(7); + cpu->AF.b[HI]=PEEK(*Get16(cpu,(bmm&2)>>1)); + break; + case 0x04: /* LD (nn),HL */ + TSTATE(16); + w=FETCH_WORD; + POKEW(w,*GetHLReg(cpu)); + break; + case 0x05: /* LD (nn),HL */ + TSTATE(16); + w=FETCH_WORD; + *GetHLReg(cpu)=PEEKW(w); + break; + case 0x06: /* LD (nn),A */ + TSTATE(13); + w=FETCH_WORD; + POKE(w,cpu->AF.b[HI]); + break; + case 0x07: /* LD A,(nn) */ + TSTATE(13); + w=FETCH_WORD; + cpu->AF.b[HI]=PEEK(w); + break; + } - case 0xbd: - TSTATE(4); - break; + return; + } - case 0xbe: - TSTATE(4); - break; + if (bml==0x03) + { + if(bmm&1) /* DEC rr */ + { + TSTATE(6); + (*Get16(cpu,bmm>>1))--; + } + else /* INC rr */ + { + TSTATE(6); + (*Get16(cpu,bmm>>1))++; + } - case 0xbf: - TSTATE(4); - break; + return; + } - case 0xc0: - TSTATE(4); - break; + if (bml==0x04) + { + bp=Get8(cpu,bmm); - case 0xc1: - TSTATE(4); - break; + if(!bp) /* INC (HL) */ + { + Z80Word a; - case 0xc2: + TSTATE(11); + a=GetHL(cpu); + POKE(a,INC8(cpu,PEEK(a))); + } + else /* INC r */ + { TSTATE(4); - break; + *bp=INC8(cpu,*bp); + } - case 0xc3: - TSTATE(4); - break; + return; + } - case 0xc4: - TSTATE(4); - break; + if (bml==0x05) + { + bp=Get8(cpu,bmm); - case 0xc5: - TSTATE(4); - break; + if(!bp) /* INC (HL) */ + { + Z80Word a; - case 0xc6: + TSTATE(11); + a=GetHL(cpu); + POKE(a,DEC8(cpu,PEEK(a))); + } + else /* INC r */ + { TSTATE(4); - break; + *bp=DEC8(cpu,*bp); + } - case 0xc7: - TSTATE(4); - break; + return; + } - case 0xc8: - TSTATE(4); - break; + if (bml==0x06) + { + bp=Get8(cpu,bmm); - case 0xc9: - TSTATE(4); - break; + if(!bp) /* LD (HL),n */ + { + Z80Word a; - case 0xca: - TSTATE(4); - break; + TSTATE(10); + a=GetHL(cpu); + POKE(a,FETCH_BYTE); + } + else /* LD r,n */ + { + TSTATE(7); + *bp=FETCH_BYTE; + } - case 0xcb: - TSTATE(4); - break; + return; + } - case 0xcc: - TSTATE(4); - break; + if (bml==0x07) + { + switch(bmm) + { + case 0x00: /* RLCA */ + TSTATE(4); + RLCA(cpu); + break; + case 0x01: /* RRCA */ + TSTATE(4); + RRCA(cpu); + break; + case 0x02: /* RLA */ + TSTATE(4); + RLA(cpu); + break; + case 0x03: /* RRA */ + TSTATE(4); + RRA(cpu); + break; + case 0x04: /* DAA */ + TSTATE(4); + DAA(cpu); + break; + case 0x05: /* CPL */ + TSTATE(4); + cpu->AF.b[HI]=cpu->AF.b[HI]^0xff; + SETFLAG(H_Z80); + SETFLAG(N_Z80); + break; + case 0x06: /* SCF */ + TSTATE(4); + SETFLAG(C_Z80); + break; + case 0x07: /* CCF */ + TSTATE(4); + if (IS_C) + SETFLAG(H_Z80); + else + CLRFLAG(H_Z80); + + cpu->AF.b[LO]^=C_Z80; + break; + } - case 0xcd: - TSTATE(4); - break; + return; + } +} - case 0xce: - TSTATE(4); - break; - case 0xcf: - TSTATE(4); - break; +static void Normal_01(Z80 *cpu, Z80Byte opcode, + Z80Byte bmh, Z80Byte bmm, Z80Byte bml) +{ + Z80Byte *dest; + Z80Byte *src; - case 0xd0: - TSTATE(4); - break; + dest=Get8(cpu,bmm); + src=Get8(cpu,bml); - case 0xd1: - TSTATE(4); - break; + /* Handle HALT + */ + if (!dest && !src) + { + TSTATE(4); + cpu->PC--; - case 0xd2: - TSTATE(4); - break; + /* Inform user of HALT going high + */ + if (!cpu->halt) + CALLBACK(eZ80_Halt,1); - case 0xd3: - TSTATE(4); - break; + cpu->halt=TRUE; - case 0xd4: - TSTATE(4); - break; + return; + } - case 0xd5: - TSTATE(4); - break; + /* If the src is NULL, then it is an (HL), (IX...) type instruction + */ + if (src) + { + /* If the dest is NULL then it is an (HL) type store + */ + if (!dest) + { + Z80Word a; - case 0xd6: - TSTATE(4); - break; + TSTATE(7); - case 0xd7: - TSTATE(4); - break; + /* Reget the source in case we're shifted. HL is the source when + doing an (HL) style store. + */ + src=Get8_HL(cpu,bml); - case 0xd8: - TSTATE(4); - break; + a=GetHL(cpu); - case 0xd9: + POKE(a,*src); + } + else + { TSTATE(4); - break; + *dest=*src; + } + } + else + { + Z80Word a; - case 0xda: - TSTATE(4); - break; + TSTATE(7); - case 0xdb: - TSTATE(4); - break; + /* Reget the destination in case we're shifted. HL is the dest when + doing an (HL) style read. + */ + dest=Get8_HL(cpu,bmm); - case 0xdc: - TSTATE(4); - break; + a=GetHL(cpu); + *dest=PEEK(a); + } +} - case 0xdd: - TSTATE(4); - break; - case 0xde: - TSTATE(4); - break; +static void Normal_10(Z80 *cpu, Z80Byte opcode, + Z80Byte bmh, Z80Byte bmm, Z80Byte bml) +{ + static void (*op[8])(Z80 *cpu, Z80Byte val)= + { + ADD8, + ADC8, + SUB8, + SBC8, + AND, + XOR, + OR, + CMP8 + }; + + Z80Byte *reg; + + reg=Get8(cpu,bml); + + if (!reg) /* op A,(HL) */ + { + Z80Word a; - case 0xdf: - TSTATE(4); - break; + TSTATE(7); + a=GetHL(cpu); + op[bmm](cpu,PEEK(a)); + } + else /* op A,r */ + { + TSTATE(4); + op[bmm](cpu,*reg); + } +} - case 0xe0: - TSTATE(4); - break; - case 0xe1: - TSTATE(4); - break; +static void Normal_11(Z80 *cpu, Z80Byte opcode, + Z80Byte bmh, Z80Byte bmm, Z80Byte bml) +{ + Z80Reg tmp; - case 0xe2: - TSTATE(4); - break; + if (bml==0x00) /* RET cc */ + { + if (GetCond(cpu,bmm)) + { + TSTATE(11); + POP(cpu->PC); + } + else + { + TSTATE(5); + } - case 0xe3: - TSTATE(4); - break; + return; + } - case 0xe4: - TSTATE(4); - break; + if (bml==0x01) + { + switch(bmm) + { + case 0x00: /* POP rr */ + case 0x02: + case 0x04: + case 0x06: + TSTATE(10); + POP(*Get16_AF(cpu,bmm>>1)); + break; + case 0x01: /* RET */ + TSTATE(10); + POP(cpu->PC); + break; + case 0x03: /* EXX */ + TSTATE(4); + tmp=cpu->BC; + cpu->BC=cpu->BC_; + cpu->BC_=tmp; + tmp=cpu->DE; + cpu->DE=cpu->DE_; + cpu->DE_=tmp; + tmp=cpu->HL; + cpu->HL=cpu->HL_; + cpu->HL_=tmp; + break; + case 0x05: /* JP (HL) */ + TSTATE(4); + cpu->PC=GetHLVal(cpu); + break; + case 0x07: /* LD SP,HL */ + TSTATE(6); + cpu->SP=GetHLVal(cpu); + break; + } - case 0xe5: - TSTATE(4); - break; + return; + } - case 0xe6: - TSTATE(4); - break; + if (bml==0x02) /* JP cc */ + { + TSTATE(10); - case 0xe7: - TSTATE(4); - break; + if (GetCond(cpu,bmm)) + { + JP; + } + else + { + NOJP; + } - case 0xe8: - TSTATE(4); - break; + return; + } - case 0xe9: - TSTATE(4); - break; + if (bml==0x03) + { + Z80Word tmp; + Z80Word *reg; - case 0xea: - TSTATE(4); - break; + switch(bmm) + { + case 0x00: /* JP nn */ + TSTATE(10); + cpu->PC=FETCH_WORD; + break; + case 0x01: /* shift */ + break; + case 0x02: /* OUT (n),a */ + TSTATE(11); + OUT(FETCH_BYTE,cpu->AF.b[HI]); + break; + case 0x03: /* IN A,(n) */ + TSTATE(11); + cpu->AF.b[HI]=IN(FETCH_BYTE); + break; + case 0x04: /* EX (SP),HL */ + TSTATE(19); + reg=GetHLReg(cpu); + tmp=*reg; + *reg=PEEKW(cpu->SP); + POKEW(cpu->SP,tmp); + break; + case 0x05: /* EX DE,HL */ + TSTATE(4); + tmp=cpu->HL.w; + cpu->HL.w=cpu->DE.w; + cpu->DE.w=tmp; + break; + case 0x06: /* DI */ + TSTATE(4); + cpu->IFF1=0; + cpu->IFF2=0; + break; + case 0x07: /* EI */ + TSTATE(4); + cpu->IFF1=1; + cpu->IFF2=1; + break; + } - case 0xeb: - TSTATE(4); - break; + return; + } - case 0xec: - TSTATE(4); - break; + if (bml==0x04) /* CALL cc */ + { + if (GetCond(cpu,bmm)) + { + TSTATE(12); + CALL; + } + else + { + TSTATE(7); + NOCALL; + } - case 0xed: - TSTATE(4); - break; + return; + } - case 0xee: - TSTATE(4); - break; + if (bml==0x05) + { + if (bmm==01) /* CALL nn */ + { + TSTATE(17); + CALL; + } + else + { + if (!(bmm&1)) /* PUSH rr */ + { + TSTATE(11); + PUSH(*Get16_AF(cpu,bmm>>1)); + } - case 0xef: - TSTATE(4); - break; + /* Everything else is a shift */ + } - case 0xf0: - TSTATE(4); - break; + return; + } - case 0xf1: - TSTATE(4); - break; + if (bml==0x06) + { + TSTATE(8); - case 0xf2: - TSTATE(4); - break; + switch(bmm) + { + case 0x00: /* ADD A,n */ + ADD8(cpu,FETCH_BYTE); + break; + case 0x01: /* ADC A,n */ + ADC8(cpu,FETCH_BYTE); + break; + case 0x02: /* SUB A,n */ + SUB8(cpu,FETCH_BYTE); + break; + case 0x03: /* SBC A,n */ + SBC8(cpu,FETCH_BYTE); + break; + case 0x04: /* AND n */ + AND(cpu,FETCH_BYTE); + break; + case 0x05: /* XOR n */ + XOR(cpu,FETCH_BYTE); + break; + case 0x06: /* OR n */ + OR(cpu,FETCH_BYTE); + break; + case 0x07: /* CP n */ + CMP8(cpu,FETCH_BYTE); + break; + } - case 0xf3: - TSTATE(4); - break; + return; + } - case 0xf4: - TSTATE(4); - break; + if (bml==0x07) /* RST nn */ + { + TSTATE(11); + PUSH(cpu->PC); + cpu->PC=bmm*8; + return; + } +} - case 0xf5: - TSTATE(4); - break; - case 0xf6: - TSTATE(4); - break; +/* ---------------------------------------- NORMAL OPCODE DECODER +*/ +void Z80_Decode(Z80 *cpu, Z80Byte opcode) +{ + Z80Byte bmh,bmm,bml; - case 0xf7: - TSTATE(4); - break; + /* IX/IY shifts + */ + if (opcode==0xdd || opcode==0xfd) + { + TSTATE(4); + INC_R; - case 0xf8: - TSTATE(4); - break; + cpu->shift=opcode; + Z80_Decode(cpu,FETCH_BYTE); + return; + } - case 0xf9: - TSTATE(4); - break; + /* CB shifts + */ + if (opcode==0xcb) + { + INC_R; - case 0xfa: - TSTATE(4); - break; + /* Check for previous IX/IY shift. + */ + if (cpu->shift!=0) + { + cpu->use_cb_off=TRUE; + cpu->cb_off=(Z80Relative)FETCH_BYTE; + } - case 0xfb: - TSTATE(4); - break; + DecodeCB(cpu,FETCH_BYTE); + return; + } - case 0xfc: - TSTATE(4); - break; + /* DE shifts + */ + if (opcode==0xed) + { + INC_R; + DecodeED(cpu,FETCH_BYTE); + return; + } - case 0xfd: - TSTATE(4); - break; + /* Split up the opcode into it's bitmasks + */ + bmh=(opcode>>6)&3; + bmm=(opcode>>3)&7; + bml=opcode&7; - case 0xfe: - TSTATE(4); - break; + /* Instruction set 00 + */ + if (bmh==0x00) + { + Normal_00(cpu,opcode,bmh,bmm,bml); + return; + } - case 0xff: - TSTATE(4); - break; + /* Instruction set 01 + */ + if (bmh==0x01) + { + Normal_01(cpu,opcode,bmh,bmm,bml); + return; + } + /* Instruction set 10 + */ + if (bmh==0x02) + { + Normal_10(cpu,opcode,bmh,bmm,bml); + return; } + + /* Instruction set 11 + */ + Normal_11(cpu,opcode,bmh,bmm,bml); } -- cgit v1.2.3