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