/**
** Supermodel
** A Sega Model 3 Arcade Emulator.
** Copyright 2011 Bart Trzynadlowski, Nik Henson
**
** This file is part of Supermodel.
**
** Supermodel is free software: you can redistribute it and/or modify it under
** the terms of the GNU General Public License as published by the Free
** Software Foundation, either version 3 of the License, or (at your option)
** any later version.
**
** Supermodel is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
** more details.
**
** You should have received a copy of the GNU General Public License along
** with Supermodel. If not, see .
**/
/*
* Z80.cpp
*
* Z80 instruction set simulator.
* Copyright (C) 1995 Frank D. Cringle.
* Adapted for use in Supermodel by Bart Trzynadlowski (July 15, 2011).
*
* Please see Z80.h for a discussion of known inaccuracies.
*/
#include "Z80.h" // must include this first to define CZ80
#include // for NULL
#include "Supermodel.h"
#include "Debugger/CPU/Z80Debug.h"
/******************************************************************************
Internal Helper Macros
******************************************************************************/
// Address space access
#define GetBYTE(a) ( Bus->Read8(a&0xFFFF) )
#define GetBYTE_pp(a) ( Bus->Read8(((a)++)&0xFFFF) )
#define GetBYTE_mm(a) ( Bus->Read8(((a)--)&0xFFFF) )
#define mm_GetBYTE(a) ( Bus->Read8((--(a))&0xFFFF) )
#define PutBYTE(a,v) Bus->Write8((a)&0xFFFF,v)
#define PutBYTE_pp(a,v) Bus->Write8(((a)++)&0xFFFF,v)
#define PutBYTE_mm(a,v) Bus->Write8(((a)--)&0xFFFF,v)
#define mm_PutBYTE(a,v) Bus->Write8((--(a))&0xFFFF,v)
#define GetWORD(a) (Bus->Read8((a)&0xFFFF) | (Bus->Read8(((a)+1)&0xFFFF)<<8))
#define PutWORD(a, v) \
do \
{ \
PutBYTE((a),(v)&0xFF); \
PutBYTE((a)+1,((v)>>8)); \
} while (0)
#define OUTPUT(a,v) Bus->IOWrite8((a)&0xFF,v)
#define INPUT(a) ( Bus->IORead8((a)&0xFF) )
// Flags
#define FLAG_C 1
#define FLAG_N 2
#define FLAG_P 4
#define FLAG_H 16
#define FLAG_Z 64
#define FLAG_S 128
#define SETFLAG(f,c) AF = (c) ? AF | FLAG_ ## f : AF & ~FLAG_ ## f
#define TSTFLAG(f) ((AF & FLAG_ ## f) != 0)
// Piecewise register access
#define ldig(x) ((x) & 0xf)
#define hdig(x) (((x)>>4)&0xf)
#define lreg(x) ((x)&0xff)
#define hreg(x) (((x)>>8)&0xff)
#define Setlreg(x, v) x = (((x)&0xff00) | ((v)&0xff))
#define Sethreg(x, v) x = (((x)&0xff) | (((v)&0xff) << 8))
// Parity bit calculation
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,
};
// Instruction cycle tables
static const unsigned char cycleTables[5][256] = {
{
// Table 0: single byte instructions
4,10,7,6,4,4,7,4,4,11,7,6,4,4,7,4,
8,10,7,6,4,4,7,4,12,11,7,6,4,4,7,4,
7,10,16,6,4,4,7,4,7,11,16,6,4,4,7,4,
7,10,13,6,11,11,10,4,7,11,13,6,4,4,7,4,
4,4,4,4,4,4,7,4,4,4,4,4,4,4,7,4,
4,4,4,4,4,4,7,4,4,4,4,4,4,4,7,4,
4,4,4,4,4,4,7,4,4,4,4,4,4,4,7,4,
7,7,7,7,7,7,4,7,4,4,4,4,4,4,7,4,
4,4,4,4,4,4,7,4,4,4,4,4,4,4,7,4,
4,4,4,4,4,4,7,4,4,4,4,4,4,4,7,4,
4,4,4,4,4,4,7,4,4,4,4,4,4,4,7,4,
4,4,4,4,4,4,7,4,4,4,4,4,4,4,7,4,
5,10,10,10,10,11,7,11,5,10,10,0,10,17,7,11,
5,10,10,11,10,11,7,11,5,4,10,11,10,0,7,11,
5,10,10,19,10,11,7,11,5,4,10,4,10,0,7,11,
5,10,10,4,10,11,7,11,5,6,10,4,10,0,7,11
}, {
// Table 1: two byte instructions of form CB-XX
8,8,8,8,8,8,15,8,8,8,8,8,8,8,15,8,
8,8,8,8,8,8,15,8,8,8,8,8,8,8,15,8,
8,8,8,8,8,8,15,8,8,8,8,8,8,8,15,8,
8,8,8,8,8,8,15,8,8,8,8,8,8,8,15,8,
8,8,8,8,8,8,12,8,8,8,8,8,8,8,12,8,
8,8,8,8,8,8,12,8,8,8,8,8,8,8,12,8,
8,8,8,8,8,8,12,8,8,8,8,8,8,8,12,8,
8,8,8,8,8,8,12,8,8,8,8,8,8,8,12,8,
8,8,8,8,8,8,15,8,8,8,8,8,8,8,15,8,
8,8,8,8,8,8,15,8,8,8,8,8,8,8,15,8,
8,8,8,8,8,8,15,8,8,8,8,8,8,8,15,8,
8,8,8,8,8,8,15,8,8,8,8,8,8,8,15,8,
8,8,8,8,8,8,15,8,8,8,8,8,8,8,15,8,
8,8,8,8,8,8,15,8,8,8,8,8,8,8,15,8,
8,8,8,8,8,8,15,8,8,8,8,8,8,8,15,8,
8,8,8,8,8,8,15,8,8,8,8,8,8,8,15,8
}, {
// Table 2: two byte instructions of form ED-XX
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,12,15,20,8,14,8,9,12,12,15,20,0,14,0,9,
12,12,15,20,0,0,8,9,12,12,15,20,0,0,8,9,
12,12,15,20,0,0,0,18,12,12,15,20,0,0,0,18,
12,0,15,20,0,0,0,0,12,12,15,20,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
16,16,16,16,0,0,0,0,16,16,16,16,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
}, {
// Table 3: two byte instructions of form DD-XX or FD-XX
0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,
0,14,20,10,9,9,9,0,0,15,20,10,9,9,9,0,
0,0,0,0,23,23,19,0,0,15,0,0,0,0,0,0,
0,0,0,0,9,9,19,0,0,0,0,0,9,9,19,0,
0,0,0,0,9,9,19,0,0,0,0,0,9,9,19,0,
9,9,9,9,9,9,19,9,9,9,9,9,9,9,19,9,
19,19,19,19,19,19,19,19,0,0,0,0,9,9,19,0,
0,0,0,0,9,9,19,0,0,0,0,0,9,9,19,0,
0,0,0,0,9,9,19,0,0,0,0,0,9,9,19,0,
0,0,0,0,9,9,19,0,0,0,0,0,9,9,19,0,
0,0,0,0,9,9,19,0,0,0,0,0,9,9,19,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,14,0,23,0,15,0,0,0,8,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0
}, {
// Table 4: three byte instructions of form DD-CB-XX or FD-CB-XX
0,0,0,0,0,0,23,0,0,0,0,0,0,0,23,0,
0,0,0,0,0,0,23,0,0,0,0,0,0,0,23,0,
0,0,0,0,0,0,23,0,0,0,0,0,0,0,23,0,
0,0,0,0,0,0,23,0,0,0,0,0,0,0,23,0,
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
0,0,0,0,0,0,23,0,0,0,0,0,0,0,23,0,
0,0,0,0,0,0,23,0,0,0,0,0,0,0,23,0,
0,0,0,0,0,0,23,0,0,0,0,0,0,0,23,0,
0,0,0,0,0,0,23,0,0,0,0,0,0,0,23,0,
0,0,0,0,0,0,23,0,0,0,0,0,0,0,23,0,
0,0,0,0,0,0,23,0,0,0,0,0,0,0,23,0,
0,0,0,0,0,0,23,0,0,0,0,0,0,0,23,0,
0,0,0,0,0,0,23,0,0,0,0,0,0,0,23,0
}
};
#define parity(x) partab[(x)&0xff]
// Stack
#define POP(x) \
do \
{ \
unsigned int y = GetBYTE_pp(SP); \
x = y + (GetBYTE_pp(SP) << 8); \
} while (0)
#define PUSH(x) \
do \
{ \
mm_PutBYTE(SP,((x)>>8)); \
mm_PutBYTE(SP,(x)&0xFF); \
} while (0)
// Branching
#define Jpc(cond) pc = cond ? GetWORD(pc) : pc+2
#define CALLC(cond) \
{ \
if (cond) \
{ \
unsigned int adrr = GetWORD(pc); \
PUSH(pc+2); \
pc = adrr; \
} \
else \
pc += 2; \
}
/*******************************************************************************
Functions
*******************************************************************************/
int CZ80::Run(int numCycles)
{
#ifdef SUPERMODEL_DEBUGGER
// If debugging enabled, don't optimize access to registers as they need to be accesible to debugger during execution
#define AF af[af_sel]
#define BC regs[regs_sel].bc
#define DE regs[regs_sel].de
#define HL regs[regs_sel].hl
#define SP sp
#define IX ix
#define IY iy
#else
// Optimization: copy registers into native word-sized local variables
unsigned int AF = af[af_sel];
unsigned int BC = regs[regs_sel].bc;
unsigned int DE = regs[regs_sel].de;
unsigned int HL = regs[regs_sel].hl;
unsigned int SP = sp;
unsigned int IX = ix;
unsigned int IY = iy;
#endif
unsigned int temp = 0;
unsigned int acu = 0;
unsigned int sum = 0;
unsigned int cbits = 0;
unsigned int op = 0;
unsigned int adr = 0;
int cycles = numCycles;
#ifdef SUPERMODEL_DEBUGGER
if (Debug != NULL)
{
Debug->CPUActive();
lastCycles += numCycles;
}
#endif // SUPERMODEL_DEBUGGER
while (cycles > 0)
{
op = GetBYTE_pp(pc);
#ifdef SUPERMODEL_DEBUGGER
if (Debug != NULL)
{
while (Debug->CPUExecute(pc - 1, op, lastCycles - cycles))
op = GetBYTE_pp(pc);
lastCycles = cycles;
}
#endif // SUPERMODEL_DEBUGGER
switch(op) {
case 0x00: /* NOP */
cycles -= cycleTables[0][0x00];
break;
case 0x01: /* LD BC,nnnn */
cycles -= cycleTables[0][0x01];
BC = GetWORD(pc);
pc += 2;
break;
case 0x02: /* LD (BC),A */
cycles -= cycleTables[0][0x02];
PutBYTE(BC, hreg(AF));
break;
case 0x03: /* INC BC */
cycles -= cycleTables[0][0x03];
++BC;
break;
case 0x04: /* INC B */
cycles -= cycleTables[0][0x04];
BC += 0x100;
temp = hreg(BC);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x05: /* DEC B */
cycles -= cycleTables[0][0x05];
BC -= 0x100;
temp = hreg(BC);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x06: /* LD B,nn */
cycles -= cycleTables[0][0x06];
Sethreg(BC, GetBYTE_pp(pc));
break;
case 0x07: /* RLCA */
cycles -= cycleTables[0][0x07];
AF = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) |
(AF & 0xc4) | ((AF >> 15) & 1);
break;
case 0x08: /* EX AF,AF' */
cycles -= cycleTables[0][0x08];
af[af_sel] = AF;
af_sel = 1 - af_sel;
AF = af[af_sel];
break;
case 0x09: /* ADD HL,BC */
cycles -= cycleTables[0][0x09];
HL &= 0xffff;
BC &= 0xffff;
sum = HL + BC;
cbits = (HL ^ BC ^ sum) >> 8;
HL = sum;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x0A: /* LD A,(BC) */
cycles -= cycleTables[0][0x0A];
Sethreg(AF, GetBYTE(BC));
break;
case 0x0B: /* DEC BC */
cycles -= cycleTables[0][0x0B];
--BC;
break;
case 0x0C: /* INC C */
cycles -= cycleTables[0][0x0C];
temp = lreg(BC)+1;
Setlreg(BC, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x0D: /* DEC C */
cycles -= cycleTables[0][0x0D];
temp = lreg(BC)-1;
Setlreg(BC, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x0E: /* LD C,nn */
cycles -= cycleTables[0][0x0E];
Setlreg(BC, GetBYTE_pp(pc));
break;
case 0x0F: /* RRCA */
cycles -= cycleTables[0][0x0F];
temp = hreg(AF);
sum = temp >> 1;
AF = ((temp & 1) << 15) | (sum << 8) |
(sum & 0x28) | (AF & 0xc4) | (temp & 1);
break;
case 0x10: /* DJNZ dd */
cycles -= cycleTables[0][0x10];
pc += ((BC -= 0x100) & 0xff00) ? (signed char) GetBYTE(pc) + 1 : 1;
break;
case 0x11: /* LD DE,nnnn */
cycles -= cycleTables[0][0x11];
DE = GetWORD(pc);
pc += 2;
break;
case 0x12: /* LD (DE),A */
cycles -= cycleTables[0][0x12];
PutBYTE(DE, hreg(AF));
break;
case 0x13: /* INC DE */
cycles -= cycleTables[0][0x13];
++DE;
break;
case 0x14: /* INC D */
cycles -= cycleTables[0][0x14];
DE += 0x100;
temp = hreg(DE);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x15: /* DEC D */
cycles -= cycleTables[0][0x15];
DE -= 0x100;
temp = hreg(DE);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x16: /* LD D,nn */
cycles -= cycleTables[0][0x16];
Sethreg(DE, GetBYTE_pp(pc));
break;
case 0x17: /* RLA */
cycles -= cycleTables[0][0x17];
AF = ((AF << 8) & 0x0100) | ((AF >> 7) & 0x28) | ((AF << 1) & ~0x01ff) |
(AF & 0xc4) | ((AF >> 15) & 1);
break;
case 0x18: /* JR dd */
cycles -= cycleTables[0][0x18];
pc += (1) ? (signed char) GetBYTE(pc) + 1 : 1;
break;
case 0x19: /* ADD HL,DE */
cycles -= cycleTables[0][0x19];
HL &= 0xffff;
DE &= 0xffff;
sum = HL + DE;
cbits = (HL ^ DE ^ sum) >> 8;
HL = sum;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x1A: /* LD A,(DE) */
cycles -= cycleTables[0][0x1A];
Sethreg(AF, GetBYTE(DE));
break;
case 0x1B: /* DEC DE */
cycles -= cycleTables[0][0x1B];
--DE;
break;
case 0x1C: /* INC E */
cycles -= cycleTables[0][0x1C];
temp = lreg(DE)+1;
Setlreg(DE, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x1D: /* DEC E */
cycles -= cycleTables[0][0x1D];
temp = lreg(DE)-1;
Setlreg(DE, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x1E: /* LD E,nn */
cycles -= cycleTables[0][0x1E];
Setlreg(DE, GetBYTE_pp(pc));
break;
case 0x1F: /* RRA */
cycles -= cycleTables[0][0x1F];
temp = hreg(AF);
sum = temp >> 1;
AF = ((AF & 1) << 15) | (sum << 8) |
(sum & 0x28) | (AF & 0xc4) | (temp & 1);
break;
case 0x20: /* JR NZ,dd */
cycles -= cycleTables[0][0x20];
pc += (!TSTFLAG(Z)) ? (signed char) GetBYTE(pc) + 1 : 1;
break;
case 0x21: /* LD HL,nnnn */
cycles -= cycleTables[0][0x21];
HL = GetWORD(pc);
pc += 2;
break;
case 0x22: /* LD (nnnn),HL */
cycles -= cycleTables[0][0x22];
temp = GetWORD(pc);
PutWORD(temp, HL);
pc += 2;
break;
case 0x23: /* INC HL */
cycles -= cycleTables[0][0x23];
++HL;
break;
case 0x24: /* INC H */
cycles -= cycleTables[0][0x24];
HL += 0x100;
temp = hreg(HL);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x25: /* DEC H */
cycles -= cycleTables[0][0x25];
HL -= 0x100;
temp = hreg(HL);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x26: /* LD H,nn */
cycles -= cycleTables[0][0x26];
Sethreg(HL, GetBYTE_pp(pc));
break;
case 0x27: /* DAA */
cycles -= cycleTables[0][0x27];
acu = hreg(AF);
temp = ldig(acu);
cbits = TSTFLAG(C);
if (TSTFLAG(N)) { /* last operation was a subtract */
int hd = cbits || acu > 0x99;
if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */
if (temp > 5)
SETFLAG(H, 0);
acu -= 6;
acu &= 0xff;
}
if (hd) /* adjust high digit */
acu -= 0x160;
}
else { /* last operation was an add */
if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */
SETFLAG(H, (temp > 9));
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;
break;
case 0x28: /* JR Z,dd */
cycles -= cycleTables[0][0x28];
pc += (TSTFLAG(Z)) ? (signed char) GetBYTE(pc) + 1 : 1;
break;
case 0x29: /* ADD HL,HL */
cycles -= cycleTables[0][0x29];
HL &= 0xffff;
sum = HL + HL;
cbits = (HL ^ HL ^ sum) >> 8;
HL = sum;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x2A: /* LD HL,(nnnn) */
cycles -= cycleTables[0][0x2A];
temp = GetWORD(pc);
HL = GetWORD(temp);
pc += 2;
break;
case 0x2B: /* DEC HL */
cycles -= cycleTables[0][0x2B];
--HL;
break;
case 0x2C: /* INC L */
cycles -= cycleTables[0][0x2C];
temp = lreg(HL)+1;
Setlreg(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x2D: /* DEC L */
cycles -= cycleTables[0][0x2D];
temp = lreg(HL)-1;
Setlreg(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x2E: /* LD L,nn */
cycles -= cycleTables[0][0x2E];
Setlreg(HL, GetBYTE_pp(pc));
break;
case 0x2F: /* CPL */
cycles -= cycleTables[0][0x2F];
AF = (~AF & ~0xff) | (AF & 0xc5) | ((~AF >> 8) & 0x28) | 0x12;
break;
case 0x30: /* JR NC,dd */
cycles -= cycleTables[0][0x30];
pc += (!TSTFLAG(C)) ? (signed char) GetBYTE(pc) + 1 : 1;
break;
case 0x31: /* LD SP,nnnn */
cycles -= cycleTables[0][0x31];
SP = GetWORD(pc);
pc += 2;
break;
case 0x32: /* LD (nnnn),A */
cycles -= cycleTables[0][0x32];
temp = GetWORD(pc);
PutBYTE(temp, hreg(AF));
pc += 2;
break;
case 0x33: /* INC SP */
cycles -= cycleTables[0][0x33];
++SP;
break;
case 0x34: /* INC (HL) */
cycles -= cycleTables[0][0x34];
temp = GetBYTE(HL)+1;
PutBYTE(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x35: /* DEC (HL) */
cycles -= cycleTables[0][0x35];
temp = GetBYTE(HL)-1;
PutBYTE(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x36: /* LD (HL),nn */
cycles -= cycleTables[0][0x36];
PutBYTE(HL, GetBYTE_pp(pc));
break;
case 0x37: /* SCF */
cycles -= cycleTables[0][0x37];
AF = (AF&~0x3b)|((AF>>8)&0x28)|1;
break;
case 0x38: /* JR C,dd */
cycles -= cycleTables[0][0x38];
pc += (TSTFLAG(C)) ? (signed char) GetBYTE(pc) + 1 : 1;
break;
case 0x39: /* ADD HL,SP */
cycles -= cycleTables[0][0x39];
HL &= 0xffff;
SP &= 0xffff;
sum = HL + SP;
cbits = (HL ^ SP ^ sum) >> 8;
HL = sum;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x3A: /* LD A,(nnnn) */
cycles -= cycleTables[0][0x3A];
temp = GetWORD(pc);
Sethreg(AF, GetBYTE(temp));
pc += 2;
break;
case 0x3B: /* DEC SP */
cycles -= cycleTables[0][0x3B];
--SP;
break;
case 0x3C: /* INC A */
cycles -= cycleTables[0][0x3C];
AF += 0x100;
temp = hreg(AF);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x3D: /* DEC A */
cycles -= cycleTables[0][0x3D];
AF -= 0x100;
temp = hreg(AF);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x3E: /* LD A,nn */
cycles -= cycleTables[0][0x3E];
Sethreg(AF, GetBYTE_pp(pc));
break;
case 0x3F: /* CCF */
cycles -= cycleTables[0][0x3F];
AF = (AF&~0x3b)|((AF>>8)&0x28)|((AF&1)<<4)|(~AF&1);
break;
case 0x40: /* LD B,B */
cycles -= cycleTables[0][0x40];
/* nop */
break;
case 0x41: /* LD B,C */
cycles -= cycleTables[0][0x41];
BC = (BC & 255) | ((BC & 255) << 8);
break;
case 0x42: /* LD B,D */
cycles -= cycleTables[0][0x42];
BC = (BC & 255) | (DE & ~255);
break;
case 0x43: /* LD B,E */
cycles -= cycleTables[0][0x43];
BC = (BC & 255) | ((DE & 255) << 8);
break;
case 0x44: /* LD B,H */
cycles -= cycleTables[0][0x44];
BC = (BC & 255) | (HL & ~255);
break;
case 0x45: /* LD B,L */
cycles -= cycleTables[0][0x45];
BC = (BC & 255) | ((HL & 255) << 8);
break;
case 0x46: /* LD B,(HL) */
cycles -= cycleTables[0][0x46];
Sethreg(BC, GetBYTE(HL));
break;
case 0x47: /* LD B,A */
cycles -= cycleTables[0][0x47];
BC = (BC & 255) | (AF & ~255);
break;
case 0x48: /* LD C,B */
cycles -= cycleTables[0][0x48];
BC = (BC & ~255) | ((BC >> 8) & 255);
break;
case 0x49: /* LD C,C */
cycles -= cycleTables[0][0x49];
/* nop */
break;
case 0x4A: /* LD C,D */
cycles -= cycleTables[0][0x4A];
BC = (BC & ~255) | ((DE >> 8) & 255);
break;
case 0x4B: /* LD C,E */
cycles -= cycleTables[0][0x4B];
BC = (BC & ~255) | (DE & 255);
break;
case 0x4C: /* LD C,H */
cycles -= cycleTables[0][0x4C];
BC = (BC & ~255) | ((HL >> 8) & 255);
break;
case 0x4D: /* LD C,L */
cycles -= cycleTables[0][0x4D];
BC = (BC & ~255) | (HL & 255);
break;
case 0x4E: /* LD C,(HL) */
cycles -= cycleTables[0][0x4E];
Setlreg(BC, GetBYTE(HL));
break;
case 0x4F: /* LD C,A */
cycles -= cycleTables[0][0x4F];
BC = (BC & ~255) | ((AF >> 8) & 255);
break;
case 0x50: /* LD D,B */
cycles -= cycleTables[0][0x50];
DE = (DE & 255) | (BC & ~255);
break;
case 0x51: /* LD D,C */
cycles -= cycleTables[0][0x51];
DE = (DE & 255) | ((BC & 255) << 8);
break;
case 0x52: /* LD D,D */
cycles -= cycleTables[0][0x52];
/* nop */
break;
case 0x53: /* LD D,E */
cycles -= cycleTables[0][0x53];
DE = (DE & 255) | ((DE & 255) << 8);
break;
case 0x54: /* LD D,H */
cycles -= cycleTables[0][0x54];
DE = (DE & 255) | (HL & ~255);
break;
case 0x55: /* LD D,L */
cycles -= cycleTables[0][0x55];
DE = (DE & 255) | ((HL & 255) << 8);
break;
case 0x56: /* LD D,(HL) */
cycles -= cycleTables[0][0x56];
Sethreg(DE, GetBYTE(HL));
break;
case 0x57: /* LD D,A */
cycles -= cycleTables[0][0x57];
DE = (DE & 255) | (AF & ~255);
break;
case 0x58: /* LD E,B */
cycles -= cycleTables[0][0x58];
DE = (DE & ~255) | ((BC >> 8) & 255);
break;
case 0x59: /* LD E,C */
cycles -= cycleTables[0][0x59];
DE = (DE & ~255) | (BC & 255);
break;
case 0x5A: /* LD E,D */
cycles -= cycleTables[0][0x5A];
DE = (DE & ~255) | ((DE >> 8) & 255);
break;
case 0x5B: /* LD E,E */
cycles -= cycleTables[0][0x5B];
/* nop */
break;
case 0x5C: /* LD E,H */
cycles -= cycleTables[0][0x5C];
DE = (DE & ~255) | ((HL >> 8) & 255);
break;
case 0x5D: /* LD E,L */
cycles -= cycleTables[0][0x5D];
DE = (DE & ~255) | (HL & 255);
break;
case 0x5E: /* LD E,(HL) */
cycles -= cycleTables[0][0x5E];
Setlreg(DE, GetBYTE(HL));
break;
case 0x5F: /* LD E,A */
cycles -= cycleTables[0][0x5F];
DE = (DE & ~255) | ((AF >> 8) & 255);
break;
case 0x60: /* LD H,B */
cycles -= cycleTables[0][0x60];
HL = (HL & 255) | (BC & ~255);
break;
case 0x61: /* LD H,C */
cycles -= cycleTables[0][0x61];
HL = (HL & 255) | ((BC & 255) << 8);
break;
case 0x62: /* LD H,D */
cycles -= cycleTables[0][0x62];
HL = (HL & 255) | (DE & ~255);
break;
case 0x63: /* LD H,E */
cycles -= cycleTables[0][0x63];
HL = (HL & 255) | ((DE & 255) << 8);
break;
case 0x64: /* LD H,H */
cycles -= cycleTables[0][0x64];
/* nop */
break;
case 0x65: /* LD H,L */
cycles -= cycleTables[0][0x65];
HL = (HL & 255) | ((HL & 255) << 8);
break;
case 0x66: /* LD H,(HL) */
cycles -= cycleTables[0][0x66];
Sethreg(HL, GetBYTE(HL));
break;
case 0x67: /* LD H,A */
cycles -= cycleTables[0][0x67];
HL = (HL & 255) | (AF & ~255);
break;
case 0x68: /* LD L,B */
cycles -= cycleTables[0][0x68];
HL = (HL & ~255) | ((BC >> 8) & 255);
break;
case 0x69: /* LD L,C */
cycles -= cycleTables[0][0x69];
HL = (HL & ~255) | (BC & 255);
break;
case 0x6A: /* LD L,D */
cycles -= cycleTables[0][0x6A];
HL = (HL & ~255) | ((DE >> 8) & 255);
break;
case 0x6B: /* LD L,E */
cycles -= cycleTables[0][0x6B];
HL = (HL & ~255) | (DE & 255);
break;
case 0x6C: /* LD L,H */
cycles -= cycleTables[0][0x6C];
HL = (HL & ~255) | ((HL >> 8) & 255);
break;
case 0x6D: /* LD L,L */
cycles -= cycleTables[0][0x6D];
/* nop */
break;
case 0x6E: /* LD L,(HL) */
cycles -= cycleTables[0][0x6E];
Setlreg(HL, GetBYTE(HL));
break;
case 0x6F: /* LD L,A */
cycles -= cycleTables[0][0x6F];
HL = (HL & ~255) | ((AF >> 8) & 255);
break;
case 0x70: /* LD (HL),B */
cycles -= cycleTables[0][0x70];
PutBYTE(HL, hreg(BC));
break;
case 0x71: /* LD (HL),C */
cycles -= cycleTables[0][0x71];
PutBYTE(HL, lreg(BC));
break;
case 0x72: /* LD (HL),D */
cycles -= cycleTables[0][0x72];
PutBYTE(HL, hreg(DE));
break;
case 0x73: /* LD (HL),E */
cycles -= cycleTables[0][0x73];
PutBYTE(HL, lreg(DE));
break;
case 0x74: /* LD (HL),H */
cycles -= cycleTables[0][0x74];
PutBYTE(HL, hreg(HL));
break;
case 0x75: /* LD (HL),L */
cycles -= cycleTables[0][0x75];
PutBYTE(HL, lreg(HL));
break;
case 0x76: /* HALT */
cycles -= cycleTables[0][0x76];
// ErrorLog("Z80 encountered an unemulated instruction at 0x%04X", (pc-1)&0xFFFF);
goto HALTExit;
case 0x77: /* LD (HL),A */
cycles -= cycleTables[0][0x77];
PutBYTE(HL, hreg(AF));
break;
case 0x78: /* LD A,B */
cycles -= cycleTables[0][0x78];
AF = (AF & 255) | (BC & ~255);
break;
case 0x79: /* LD A,C */
cycles -= cycleTables[0][0x79];
AF = (AF & 255) | ((BC & 255) << 8);
break;
case 0x7A: /* LD A,D */
cycles -= cycleTables[0][0x7A];
AF = (AF & 255) | (DE & ~255);
break;
case 0x7B: /* LD A,E */
cycles -= cycleTables[0][0x7B];
AF = (AF & 255) | ((DE & 255) << 8);
break;
case 0x7C: /* LD A,H */
cycles -= cycleTables[0][0x7C];
AF = (AF & 255) | (HL & ~255);
break;
case 0x7D: /* LD A,L */
cycles -= cycleTables[0][0x7D];
AF = (AF & 255) | ((HL & 255) << 8);
break;
case 0x7E: /* LD A,(HL) */
cycles -= cycleTables[0][0x7E];
Sethreg(AF, GetBYTE(HL));
break;
case 0x7F: /* LD A,A */
cycles -= cycleTables[0][0x7F];
/* nop */
break;
case 0x80: /* ADD A,B */
cycles -= cycleTables[0][0x80];
temp = hreg(BC);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x81: /* ADD A,C */
cycles -= cycleTables[0][0x81];
temp = lreg(BC);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x82: /* ADD A,D */
cycles -= cycleTables[0][0x82];
temp = hreg(DE);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x83: /* ADD A,E */
cycles -= cycleTables[0][0x83];
temp = lreg(DE);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x84: /* ADD A,H */
cycles -= cycleTables[0][0x84];
temp = hreg(HL);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x85: /* ADD A,L */
cycles -= cycleTables[0][0x85];
temp = lreg(HL);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x86: /* ADD A,(HL) */
cycles -= cycleTables[0][0x86];
temp = GetBYTE(HL);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x87: /* ADD A,A */
cycles -= cycleTables[0][0x87];
temp = hreg(AF);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x88: /* ADC A,B */
cycles -= cycleTables[0][0x88];
temp = hreg(BC);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x89: /* ADC A,C */
cycles -= cycleTables[0][0x89];
temp = lreg(BC);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x8A: /* ADC A,D */
cycles -= cycleTables[0][0x8A];
temp = hreg(DE);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x8B: /* ADC A,E */
cycles -= cycleTables[0][0x8B];
temp = lreg(DE);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x8C: /* ADC A,H */
cycles -= cycleTables[0][0x8C];
temp = hreg(HL);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x8D: /* ADC A,L */
cycles -= cycleTables[0][0x8D];
temp = lreg(HL);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x8E: /* ADC A,(HL) */
cycles -= cycleTables[0][0x8E];
temp = GetBYTE(HL);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x8F: /* ADC A,A */
cycles -= cycleTables[0][0x8F];
temp = hreg(AF);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x90: /* SUB B */
cycles -= cycleTables[0][0x90];
temp = hreg(BC);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x91: /* SUB C */
cycles -= cycleTables[0][0x91];
temp = lreg(BC);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x92: /* SUB D */
cycles -= cycleTables[0][0x92];
temp = hreg(DE);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x93: /* SUB E */
cycles -= cycleTables[0][0x93];
temp = lreg(DE);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x94: /* SUB H */
cycles -= cycleTables[0][0x94];
temp = hreg(HL);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x95: /* SUB L */
cycles -= cycleTables[0][0x95];
temp = lreg(HL);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x96: /* SUB (HL) */
cycles -= cycleTables[0][0x96];
temp = GetBYTE(HL);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x97: /* SUB A */
cycles -= cycleTables[0][0x97];
temp = hreg(AF);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x98: /* SBC A,B */
cycles -= cycleTables[0][0x98];
temp = hreg(BC);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x99: /* SBC A,C */
cycles -= cycleTables[0][0x99];
temp = lreg(BC);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x9A: /* SBC A,D */
cycles -= cycleTables[0][0x9A];
temp = hreg(DE);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x9B: /* SBC A,E */
cycles -= cycleTables[0][0x9B];
temp = lreg(DE);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x9C: /* SBC A,H */
cycles -= cycleTables[0][0x9C];
temp = hreg(HL);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x9D: /* SBC A,L */
cycles -= cycleTables[0][0x9D];
temp = lreg(HL);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x9E: /* SBC A,(HL) */
cycles -= cycleTables[0][0x9E];
temp = GetBYTE(HL);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x9F: /* SBC A,A */
cycles -= cycleTables[0][0x9F];
temp = hreg(AF);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0xA0: /* AND B */
cycles -= cycleTables[0][0xA0];
sum = ((AF & (BC)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xA1: /* AND C */
cycles -= cycleTables[0][0xA1];
sum = ((AF >> 8) & BC) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xA2: /* AND D */
cycles -= cycleTables[0][0xA2];
sum = ((AF & (DE)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xA3: /* AND E */
cycles -= cycleTables[0][0xA3];
sum = ((AF >> 8) & DE) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xA4: /* AND H */
cycles -= cycleTables[0][0xA4];
sum = ((AF & (HL)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xA5: /* AND L */
cycles -= cycleTables[0][0xA5];
sum = ((AF >> 8) & HL) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xA6: /* AND (HL) */
cycles -= cycleTables[0][0xA6];
sum = ((AF >> 8) & GetBYTE(HL)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xA7: /* AND A */
cycles -= cycleTables[0][0xA7];
sum = ((AF & (AF)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xA8: /* XOR B */
cycles -= cycleTables[0][0xA8];
sum = ((AF ^ (BC)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xA9: /* XOR C */
cycles -= cycleTables[0][0xA9];
sum = ((AF >> 8) ^ BC) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAA: /* XOR D */
cycles -= cycleTables[0][0xAA];
sum = ((AF ^ (DE)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAB: /* XOR E */
cycles -= cycleTables[0][0xAB];
sum = ((AF >> 8) ^ DE) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAC: /* XOR H */
cycles -= cycleTables[0][0xAC];
sum = ((AF ^ (HL)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAD: /* XOR L */
cycles -= cycleTables[0][0xAD];
sum = ((AF >> 8) ^ HL) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAE: /* XOR (HL) */
cycles -= cycleTables[0][0xAE];
sum = ((AF >> 8) ^ GetBYTE(HL)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAF: /* XOR A */
cycles -= cycleTables[0][0xAF];
sum = ((AF ^ (AF)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB0: /* OR B */
cycles -= cycleTables[0][0xB0];
sum = ((AF | (BC)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB1: /* OR C */
cycles -= cycleTables[0][0xB1];
sum = ((AF >> 8) | BC) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB2: /* OR D */
cycles -= cycleTables[0][0xB2];
sum = ((AF | (DE)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB3: /* OR E */
cycles -= cycleTables[0][0xB3];
sum = ((AF >> 8) | DE) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB4: /* OR H */
cycles -= cycleTables[0][0xB4];
sum = ((AF | (HL)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB5: /* OR L */
cycles -= cycleTables[0][0xB5];
sum = ((AF >> 8) | HL) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB6: /* OR (HL) */
cycles -= cycleTables[0][0xB6];
sum = ((AF >> 8) | GetBYTE(HL)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB7: /* OR A */
cycles -= cycleTables[0][0xB7];
sum = ((AF | (AF)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB8: /* CP B */
cycles -= cycleTables[0][0xB8];
temp = hreg(BC);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xB9: /* CP C */
cycles -= cycleTables[0][0xB9];
temp = lreg(BC);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBA: /* CP D */
cycles -= cycleTables[0][0xBA];
temp = hreg(DE);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBB: /* CP E */
cycles -= cycleTables[0][0xBB];
temp = lreg(DE);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBC: /* CP H */
cycles -= cycleTables[0][0xBC];
temp = hreg(HL);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBD: /* CP L */
cycles -= cycleTables[0][0xBD];
temp = lreg(HL);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBE: /* CP (HL) */
cycles -= cycleTables[0][0xBE];
temp = GetBYTE(HL);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBF: /* CP A */
cycles -= cycleTables[0][0xBF];
temp = hreg(AF);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xC0: /* RET NZ */
cycles -= cycleTables[0][0xC0];
if (!TSTFLAG(Z)) POP(pc);
break;
case 0xC1: /* POP BC */
cycles -= cycleTables[0][0xC1];
POP(BC);
break;
case 0xC2: /* JP NZ,nnnn */
cycles -= cycleTables[0][0xC2];
Jpc(!TSTFLAG(Z));
break;
case 0xC3: /* JP nnnn */
cycles -= cycleTables[0][0xC3];
Jpc(1);
break;
case 0xC4: /* CALL NZ,nnnn */
cycles -= cycleTables[0][0xC4];
CALLC(!TSTFLAG(Z));
break;
case 0xC5: /* PUSH BC */
cycles -= cycleTables[0][0xC5];
PUSH(BC);
break;
case 0xC6: /* ADD A,nn */
cycles -= cycleTables[0][0xC6];
temp = GetBYTE_pp(pc);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0xC7: /* RST 0 */
cycles -= cycleTables[0][0xC7];
PUSH(pc); pc = 0;
break;
case 0xC8: /* RET Z */
cycles -= cycleTables[0][0xC8];
if (TSTFLAG(Z)) POP(pc);
break;
case 0xC9: /* RET */
cycles -= cycleTables[0][0xC9];
POP(pc);
break;
case 0xCA: /* JP Z,nnnn */
cycles -= cycleTables[0][0xCA];
Jpc(TSTFLAG(Z));
break;
case 0xCB: /* CB prefix */
adr = HL;
op = GetBYTE(pc);
cycles -= cycleTables[1][op];
switch (op & 7) {
case 0: ++pc; acu = hreg(BC); break;
case 1: ++pc; acu = lreg(BC); break;
case 2: ++pc; acu = hreg(DE); break;
case 3: ++pc; acu = lreg(DE); break;
case 4: ++pc; acu = hreg(HL); break;
case 5: ++pc; acu = lreg(HL); break;
case 6: ++pc; acu = GetBYTE(adr); break;
case 7: ++pc; acu = hreg(AF); break;
}
switch (op & 0xc0) {
case 0x00: /* shift/rotate */
switch (op & 0x38) {
case 0x00: /* RLC */
temp = (acu << 1) | (acu >> 7);
cbits = temp & 1;
goto cbshflg1;
case 0x08: /* RRC */
temp = (acu >> 1) | (acu << 7);
cbits = temp & 0x80;
goto cbshflg1;
case 0x10: /* RL */
temp = (acu << 1) | TSTFLAG(C);
cbits = acu & 0x80;
goto cbshflg1;
case 0x18: /* RR */
temp = (acu >> 1) | (TSTFLAG(C) << 7);
cbits = acu & 1;
goto cbshflg1;
case 0x20: /* SLA */
temp = acu << 1;
cbits = acu & 0x80;
goto cbshflg1;
case 0x28: /* SRA */
temp = (acu >> 1) | (acu & 0x80);
cbits = acu & 1;
goto cbshflg1;
case 0x30: /* SLIA */
temp = (acu << 1) | 1;
cbits = acu & 0x80;
goto cbshflg1;
case 0x38: /* SRL */
temp = acu >> 1;
cbits = acu & 1;
cbshflg1:
AF = (AF & ~0xff) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp) | !!cbits;
}
break;
case 0x40: /* BIT */
if (acu & (1 << ((op >> 3) & 7)))
AF = (AF & ~0xfe) | 0x10 |
(((op & 0x38) == 0x38) << 7);
else
AF = (AF & ~0xfe) | 0x54;
if ((op&7) != 6)
AF |= (acu & 0x28);
temp = acu;
break;
case 0x80: /* RES */
temp = acu & ~(1 << ((op >> 3) & 7));
break;
case 0xc0: /* SET */
temp = acu | (1 << ((op >> 3) & 7));
break;
}
switch (op & 7) {
case 0: Sethreg(BC, temp); break;
case 1: Setlreg(BC, temp); break;
case 2: Sethreg(DE, temp); break;
case 3: Setlreg(DE, temp); break;
case 4: Sethreg(HL, temp); break;
case 5: Setlreg(HL, temp); break;
case 6: PutBYTE(adr, temp); break;
case 7: Sethreg(AF, temp); break;
}
break;
case 0xCC: /* CALL Z,nnnn */
cycles -= cycleTables[0][0xCC];
CALLC(TSTFLAG(Z));
break;
case 0xCD: /* CALL nnnn */
cycles -= cycleTables[0][0xCD];
CALLC(1);
break;
case 0xCE: /* ADC A,nn */
cycles -= cycleTables[0][0xCE];
temp = GetBYTE_pp(pc);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0xCF: /* RST 8 */
cycles -= cycleTables[0][0xCF];
PUSH(pc); pc = 8;
break;
case 0xD0: /* RET NC */
cycles -= cycleTables[0][0xD0];
if (!TSTFLAG(C)) POP(pc);
break;
case 0xD1: /* POP DE */
cycles -= cycleTables[0][0xD1];
POP(DE);
break;
case 0xD2: /* JP NC,nnnn */
cycles -= cycleTables[0][0xD2];
Jpc(!TSTFLAG(C));
break;
case 0xD3: /* OUT (nn),A */
cycles -= cycleTables[0][0xD3];
OUTPUT(GetBYTE_pp(pc), hreg(AF));
break;
case 0xD4: /* CALL NC,nnnn */
cycles -= cycleTables[0][0xD4];
CALLC(!TSTFLAG(C));
break;
case 0xD5: /* PUSH DE */
cycles -= cycleTables[0][0xD5];
PUSH(DE);
break;
case 0xD6: /* SUB nn */
cycles -= cycleTables[0][0xD6];
temp = GetBYTE_pp(pc);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0xD7: /* RST 10H */
cycles -= cycleTables[0][0xD7];
PUSH(pc); pc = 0x10;
break;
case 0xD8: /* RET C */
cycles -= cycleTables[0][0xD8];
if (TSTFLAG(C)) POP(pc);
break;
case 0xD9: /* EXX */
cycles -= cycleTables[0][0xD9];
regs[regs_sel].bc = BC;
regs[regs_sel].de = DE;
regs[regs_sel].hl = HL;
regs_sel = 1 - regs_sel;
BC = regs[regs_sel].bc;
DE = regs[regs_sel].de;
HL = regs[regs_sel].hl;
break;
case 0xDA: /* JP C,nnnn */
cycles -= cycleTables[0][0xDA];
Jpc(TSTFLAG(C));
break;
case 0xDB: /* IN A,(nn) */
cycles -= cycleTables[0][0xDB];
Sethreg(AF, INPUT(GetBYTE_pp(pc)));
break;
case 0xDC: /* CALL C,nnnn */
cycles -= cycleTables[0][0xDC];
CALLC(TSTFLAG(C));
break;
case 0xDD: /* DD prefix */
op = GetBYTE_pp(pc);
switch (op) {
case 0x09: /* ADD IX,BC */
cycles -= cycleTables[3][0x09];
IX &= 0xffff;
BC &= 0xffff;
sum = IX + BC;
cbits = (IX ^ BC ^ sum) >> 8;
IX = sum;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x19: /* ADD IX,DE */
cycles -= cycleTables[3][0x19];
IX &= 0xffff;
DE &= 0xffff;
sum = IX + DE;
cbits = (IX ^ DE ^ sum) >> 8;
IX = sum;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x21: /* LD IX,nnnn */
cycles -= cycleTables[3][0x21];
IX = GetWORD(pc);
pc += 2;
break;
case 0x22: /* LD (nnnn),IX */
cycles -= cycleTables[3][0x22];
temp = GetWORD(pc);
PutWORD(temp, IX);
pc += 2;
break;
case 0x23: /* INC IX */
cycles -= cycleTables[3][0x23];
++IX;
break;
case 0x24: /* INC IXH */
cycles -= cycleTables[3][0x24];
IX += 0x100;
temp = hreg(IX);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x25: /* DEC IXH */
cycles -= cycleTables[3][0x25];
IX -= 0x100;
temp = hreg(IX);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x26: /* LD IXH,nn */
cycles -= cycleTables[3][0x26];
Sethreg(IX, GetBYTE_pp(pc));
break;
case 0x29: /* ADD IX,IX */
cycles -= cycleTables[3][0x29];
IX &= 0xffff;
sum = IX + IX;
cbits = (IX ^ IX ^ sum) >> 8;
IX = sum;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x2A: /* LD IX,(nnnn) */
cycles -= cycleTables[3][0x2A];
temp = GetWORD(pc);
IX = GetWORD(temp);
pc += 2;
break;
case 0x2B: /* DEC IX */
cycles -= cycleTables[3][0x2B];
--IX;
break;
case 0x2C: /* INC IXL */
cycles -= cycleTables[3][0x2C];
temp = lreg(IX)+1;
Setlreg(IX, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x2D: /* DEC IXL */
cycles -= cycleTables[3][0x2D];
temp = lreg(IX)-1;
Setlreg(IX, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x2E: /* LD IXL,nn */
cycles -= cycleTables[3][0x2E];
Setlreg(IX, GetBYTE_pp(pc));
break;
case 0x34: /* INC (IX+dd) */
cycles -= cycleTables[3][0x34];
adr = IX + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr)+1;
PutBYTE(adr, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x35: /* DEC (IX+dd) */
cycles -= cycleTables[3][0x35];
adr = IX + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr)-1;
PutBYTE(adr, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x36: /* LD (IX+dd),nn */
cycles -= cycleTables[3][0x36];
adr = IX + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, GetBYTE_pp(pc));
break;
case 0x39: /* ADD IX,SP */
cycles -= cycleTables[3][0x39];
IX &= 0xffff;
SP &= 0xffff;
sum = IX + SP;
cbits = (IX ^ SP ^ sum) >> 8;
IX = sum;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x44: /* LD B,IXH */
cycles -= cycleTables[3][0x44];
Sethreg(BC, hreg(IX));
break;
case 0x45: /* LD B,IXL */
cycles -= cycleTables[3][0x45];
Sethreg(BC, lreg(IX));
break;
case 0x46: /* LD B,(IX+dd) */
cycles -= cycleTables[3][0x46];
adr = IX + (signed char) GetBYTE_pp(pc);
Sethreg(BC, GetBYTE(adr));
break;
case 0x4C: /* LD C,IXH */
cycles -= cycleTables[3][0x4C];
Setlreg(BC, hreg(IX));
break;
case 0x4D: /* LD C,IXL */
cycles -= cycleTables[3][0x4D];
Setlreg(BC, lreg(IX));
break;
case 0x4E: /* LD C,(IX+dd) */
cycles -= cycleTables[3][0x4E];
adr = IX + (signed char) GetBYTE_pp(pc);
Setlreg(BC, GetBYTE(adr));
break;
case 0x54: /* LD D,IXH */
cycles -= cycleTables[3][0x54];
Sethreg(DE, hreg(IX));
break;
case 0x55: /* LD D,IXL */
cycles -= cycleTables[3][0x55];
Sethreg(DE, lreg(IX));
break;
case 0x56: /* LD D,(IX+dd) */
cycles -= cycleTables[3][0x56];
adr = IX + (signed char) GetBYTE_pp(pc);
Sethreg(DE, GetBYTE(adr));
break;
case 0x5C: /* LD E,H */
cycles -= cycleTables[3][0x5C];
Setlreg(DE, hreg(IX));
break;
case 0x5D: /* LD E,L */
cycles -= cycleTables[3][0x5D];
Setlreg(DE, lreg(IX));
break;
case 0x5E: /* LD E,(IX+dd) */
cycles -= cycleTables[3][0x5E];
adr = IX + (signed char) GetBYTE_pp(pc);
Setlreg(DE, GetBYTE(adr));
break;
case 0x60: /* LD IXH,B */
cycles -= cycleTables[3][0x60];
Sethreg(IX, hreg(BC));
break;
case 0x61: /* LD IXH,C */
cycles -= cycleTables[3][0x61];
Sethreg(IX, lreg(BC));
break;
case 0x62: /* LD IXH,D */
cycles -= cycleTables[3][0x62];
Sethreg(IX, hreg(DE));
break;
case 0x63: /* LD IXH,E */
cycles -= cycleTables[3][0x63];
Sethreg(IX, lreg(DE));
break;
case 0x64: /* LD IXH,IXH */
cycles -= cycleTables[3][0x64];
/* nop */
break;
case 0x65: /* LD IXH,IXL */
cycles -= cycleTables[3][0x65];
Sethreg(IX, lreg(IX));
break;
case 0x66: /* LD H,(IX+dd) */
cycles -= cycleTables[3][0x66];
adr = IX + (signed char) GetBYTE_pp(pc);
Sethreg(HL, GetBYTE(adr));
break;
case 0x67: /* LD IXH,A */
cycles -= cycleTables[3][0x67];
Sethreg(IX, hreg(AF));
break;
case 0x68: /* LD IXL,B */
cycles -= cycleTables[3][0x68];
Setlreg(IX, hreg(BC));
break;
case 0x69: /* LD IXL,C */
cycles -= cycleTables[3][0x69];
Setlreg(IX, lreg(BC));
break;
case 0x6A: /* LD IXL,D */
cycles -= cycleTables[3][0x6A];
Setlreg(IX, hreg(DE));
break;
case 0x6B: /* LD IXL,E */
cycles -= cycleTables[3][0x6B];
Setlreg(IX, lreg(DE));
break;
case 0x6C: /* LD IXL,IXH */
cycles -= cycleTables[3][0x6C];
Setlreg(IX, hreg(IX));
break;
case 0x6D: /* LD IXL,IXL */
cycles -= cycleTables[3][0x6D];
/* nop */
break;
case 0x6E: /* LD L,(IX+dd) */
cycles -= cycleTables[3][0x6E];
adr = IX + (signed char) GetBYTE_pp(pc);
Setlreg(HL, GetBYTE(adr));
break;
case 0x6F: /* LD IXL,A */
cycles -= cycleTables[3][0x6F];
Setlreg(IX, hreg(AF));
break;
case 0x70: /* LD (IX+dd),B */
cycles -= cycleTables[3][0x70];
adr = IX + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, hreg(BC));
break;
case 0x71: /* LD (IX+dd),C */
cycles -= cycleTables[3][0x71];
adr = IX + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, lreg(BC));
break;
case 0x72: /* LD (IX+dd),D */
cycles -= cycleTables[3][0x72];
adr = IX + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, hreg(DE));
break;
case 0x73: /* LD (IX+dd),E */
cycles -= cycleTables[3][0x73];
adr = IX + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, lreg(DE));
break;
case 0x74: /* LD (IX+dd),H */
cycles -= cycleTables[3][0x74];
adr = IX + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, hreg(HL));
break;
case 0x75: /* LD (IX+dd),L */
cycles -= cycleTables[3][0x75];
adr = IX + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, lreg(HL));
break;
case 0x77: /* LD (IX+dd),A */
cycles -= cycleTables[3][0x77];
adr = IX + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, hreg(AF));
break;
case 0x7C: /* LD A,IXH */
cycles -= cycleTables[3][0x7C];
Sethreg(AF, hreg(IX));
break;
case 0x7D: /* LD A,IXL */
cycles -= cycleTables[3][0x7D];
Sethreg(AF, lreg(IX));
break;
case 0x7E: /* LD A,(IX+dd) */
cycles -= cycleTables[3][0x7E];
adr = IX + (signed char) GetBYTE_pp(pc);
Sethreg(AF, GetBYTE(adr));
break;
case 0x84: /* ADD A,IXH */
cycles -= cycleTables[3][0x84];
temp = hreg(IX);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x85: /* ADD A,IXL */
cycles -= cycleTables[3][0x85];
temp = lreg(IX);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x86: /* ADD A,(IX+dd) */
cycles -= cycleTables[3][0x86];
adr = IX + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x8C: /* ADC A,IXH */
cycles -= cycleTables[3][0x8C];
temp = hreg(IX);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x8D: /* ADC A,IXL */
cycles -= cycleTables[3][0x8D];
temp = lreg(IX);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x8E: /* ADC A,(IX+dd) */
cycles -= cycleTables[3][0x8E];
adr = IX + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x94: /* SUB IXH */
cycles -= cycleTables[3][0x94];
temp = hreg(IX);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x95: /* SUB IXL */
cycles -= cycleTables[3][0x95];
temp = lreg(IX);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x96: /* SUB (IX+dd) */
cycles -= cycleTables[3][0x96];
adr = IX + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x9C: /* SBC A,IXH */
cycles -= cycleTables[3][0x9C];
temp = hreg(IX);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x9D: /* SBC A,IXL */
cycles -= cycleTables[3][0x9D];
temp = lreg(IX);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x9E: /* SBC A,(IX+dd) */
cycles -= cycleTables[3][0x9E];
adr = IX + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0xA4: /* AND IXH */
cycles -= cycleTables[3][0xA4];
sum = ((AF & (IX)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xA5: /* AND IXL */
cycles -= cycleTables[3][0xA5];
sum = ((AF >> 8) & IX) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xA6: /* AND (IX+dd) */
cycles -= cycleTables[3][0xA6];
adr = IX + (signed char) GetBYTE_pp(pc);
sum = ((AF >> 8) & GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xAC: /* XOR IXH */
cycles -= cycleTables[3][0xAC];
sum = ((AF ^ (IX)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAD: /* XOR IXL */
cycles -= cycleTables[3][0xAD];
sum = ((AF >> 8) ^ IX) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAE: /* XOR (IX+dd) */
cycles -= cycleTables[3][0xAE];
adr = IX + (signed char) GetBYTE_pp(pc);
sum = ((AF >> 8) ^ GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB4: /* OR IXH */
cycles -= cycleTables[3][0xB4];
sum = ((AF | (IX)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB5: /* OR IXL */
cycles -= cycleTables[3][0xB5];
sum = ((AF >> 8) | IX) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB6: /* OR (IX+dd) */
cycles -= cycleTables[3][0xB6];
adr = IX + (signed char) GetBYTE_pp(pc);
sum = ((AF >> 8) | GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xBC: /* CP IXH */
cycles -= cycleTables[3][0xBC];
temp = hreg(IX);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBD: /* CP IXL */
cycles -= cycleTables[3][0xBD];
temp = lreg(IX);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBE: /* CP (IX+dd) */
cycles -= cycleTables[3][0xBE];
adr = IX + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xCB: /* CB prefix */
adr = IX + (signed char) GetBYTE_pp(pc);
adr = adr;
op = GetBYTE(pc);
cycles -= cycleTables[4][op];
switch (op & 7) {
case 0: ++pc; acu = hreg(BC); break;
case 1: ++pc; acu = lreg(BC); break;
case 2: ++pc; acu = hreg(DE); break;
case 3: ++pc; acu = lreg(DE); break;
case 4: ++pc; acu = hreg(HL); break;
case 5: ++pc; acu = lreg(HL); break;
case 6: ++pc; acu = GetBYTE(adr); break;
case 7: ++pc; acu = hreg(AF); break;
}
switch (op & 0xc0) {
case 0x00: /* shift/rotate */
switch (op & 0x38) {
case 0x00: /* RLC */
temp = (acu << 1) | (acu >> 7);
cbits = temp & 1;
goto cbshflg2;
case 0x08: /* RRC */
temp = (acu >> 1) | (acu << 7);
cbits = temp & 0x80;
goto cbshflg2;
case 0x10: /* RL */
temp = (acu << 1) | TSTFLAG(C);
cbits = acu & 0x80;
goto cbshflg2;
case 0x18: /* RR */
temp = (acu >> 1) | (TSTFLAG(C) << 7);
cbits = acu & 1;
goto cbshflg2;
case 0x20: /* SLA */
temp = acu << 1;
cbits = acu & 0x80;
goto cbshflg2;
case 0x28: /* SRA */
temp = (acu >> 1) | (acu & 0x80);
cbits = acu & 1;
goto cbshflg2;
case 0x30: /* SLIA */
temp = (acu << 1) | 1;
cbits = acu & 0x80;
goto cbshflg2;
case 0x38: /* SRL */
temp = acu >> 1;
cbits = acu & 1;
cbshflg2:
AF = (AF & ~0xff) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp) | !!cbits;
}
break;
case 0x40: /* BIT */
if (acu & (1 << ((op >> 3) & 7)))
AF = (AF & ~0xfe) | 0x10 |
(((op & 0x38) == 0x38) << 7);
else
AF = (AF & ~0xfe) | 0x54;
if ((op&7) != 6)
AF |= (acu & 0x28);
temp = acu;
break;
case 0x80: /* RES */
temp = acu & ~(1 << ((op >> 3) & 7));
break;
case 0xc0: /* SET */
temp = acu | (1 << ((op >> 3) & 7));
break;
}
switch (op & 7) {
case 0: Sethreg(BC, temp); break;
case 1: Setlreg(BC, temp); break;
case 2: Sethreg(DE, temp); break;
case 3: Setlreg(DE, temp); break;
case 4: Sethreg(HL, temp); break;
case 5: Setlreg(HL, temp); break;
case 6: PutBYTE(adr, temp); break;
case 7: Sethreg(AF, temp); break;
}
break;
case 0xE1: /* POP IX */
cycles -= cycleTables[3][0xE1];
POP(IX);
break;
case 0xE3: /* EX (SP),IX */
cycles -= cycleTables[3][0xE3];
temp = IX; POP(IX); PUSH(temp);
break;
case 0xE5: /* PUSH IX */
cycles -= cycleTables[3][0xE5];
PUSH(IX);
break;
case 0xE9: /* JP (IX) */
cycles -= cycleTables[3][0xE9];
pc = IX;
break;
case 0xF9: /* LD SP,IX */
cycles -= cycleTables[3][0xF9];
SP = IX;
break;
default: pc--; /* ignore DD */
}
break;
case 0xDE: /* SBC A,nn */
cycles -= cycleTables[0][0xDE];
temp = GetBYTE_pp(pc);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0xDF: /* RST 18H */
cycles -= cycleTables[0][0xDF];
PUSH(pc); pc = 0x18;
break;
case 0xE0: /* RET PO */
cycles -= cycleTables[0][0xE0];
if (!TSTFLAG(P)) POP(pc);
break;
case 0xE1: /* POP HL */
cycles -= cycleTables[0][0xE1];
POP(HL);
break;
case 0xE2: /* JP PO,nnnn */
cycles -= cycleTables[0][0xE2];
Jpc(!TSTFLAG(P));
break;
case 0xE3: /* EX (SP),HL */
cycles -= cycleTables[0][0xE3];
temp = HL; POP(HL); PUSH(temp);
break;
case 0xE4: /* CALL PO,nnnn */
cycles -= cycleTables[0][0xE4];
CALLC(!TSTFLAG(P));
break;
case 0xE5: /* PUSH HL */
cycles -= cycleTables[0][0xE5];
PUSH(HL);
break;
case 0xE6: /* AND nn */
cycles -= cycleTables[0][0xE6];
sum = ((AF >> 8) & GetBYTE_pp(pc)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xE7: /* RST 20H */
cycles -= cycleTables[0][0xE7];
PUSH(pc); pc = 0x20;
break;
case 0xE8: /* RET PE */
cycles -= cycleTables[0][0xE8];
if (TSTFLAG(P)) POP(pc);
break;
case 0xE9: /* JP (HL) */
cycles -= cycleTables[0][0xE9];
pc = HL;
break;
case 0xEA: /* JP PE,nnnn */
cycles -= cycleTables[0][0xEA];
Jpc(TSTFLAG(P));
break;
case 0xEB: /* EX DE,HL */
cycles -= cycleTables[0][0xEB];
temp = HL; HL = DE; DE = temp;
break;
case 0xEC: /* CALL PE,nnnn */
cycles -= cycleTables[0][0xEC];
CALLC(TSTFLAG(P));
break;
case 0xED: /* ED prefix */
op = GetBYTE_pp(pc);
switch (op) {
case 0x40: /* IN B,(C) */
cycles -= cycleTables[2][0x40];
temp = INPUT(lreg(BC));
Sethreg(BC, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x41: /* OUT (C),B */
cycles -= cycleTables[2][0x41];
OUTPUT(lreg(BC), hreg(BC));
break;
case 0x42: /* SBC HL,BC */
cycles -= cycleTables[2][0x42];
HL &= 0xffff;
BC &= 0xffff;
sum = HL - BC - TSTFLAG(C);
cbits = (HL ^ BC ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & 0xffff) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | 2 | ((cbits >> 8) & 1);
break;
case 0x43: /* LD (nnnn),BC */
cycles -= cycleTables[2][0x43];
temp = GetWORD(pc);
PutWORD(temp, BC);
pc += 2;
break;
case 0x44: /* NEG */
cycles -= cycleTables[2][0x44];
temp = hreg(AF);
AF = (-(AF & 0xff00) & 0xff00);
AF |= ((AF >> 8) & 0xa8) | (((AF & 0xff00) == 0) << 6) |
(((temp & 0x0f) != 0) << 4) | ((temp == 0x80) << 2) |
2 | (temp != 0);
break;
case 0x45: /* RETN */
cycles -= cycleTables[2][0x45];
iff |= iff >> 1;
POP(pc);
break;
case 0x46: /* IM 0 */
cycles -= cycleTables[2][0x46];
im = 0; // interrupt mode 0
break;
case 0x47: /* LD I,A */
cycles -= cycleTables[2][0x47];
ir = (ir & 255) | (AF & ~255);
break;
case 0x48: /* IN C,(C) */
cycles -= cycleTables[2][0x48];
temp = INPUT(lreg(BC));
Setlreg(BC, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x49: /* OUT (C),C */
cycles -= cycleTables[2][0x49];
OUTPUT(lreg(BC), lreg(BC));
break;
case 0x4A: /* ADC HL,BC */
cycles -= cycleTables[2][0x4A];
HL &= 0xffff;
BC &= 0xffff;
sum = HL + BC + TSTFLAG(C);
cbits = (HL ^ BC ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & 0xffff) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x4B: /* LD BC,(nnnn) */
cycles -= cycleTables[2][0x4B];
temp = GetWORD(pc);
BC = GetWORD(temp);
pc += 2;
break;
case 0x4D: /* RETI */
cycles -= cycleTables[2][0x4D];
iff |= iff >> 1;
POP(pc);
break;
case 0x4F: /* LD R,A */
cycles -= cycleTables[2][0x4F];
ir = (ir & ~255) | ((AF >> 8) & 255);
break;
case 0x50: /* IN D,(C) */
cycles -= cycleTables[2][0x50];
temp = INPUT(lreg(BC));
Sethreg(DE, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x51: /* OUT (C),D */
cycles -= cycleTables[2][0x51];
OUTPUT(lreg(BC), hreg(DE));
break;
case 0x52: /* SBC HL,DE */
cycles -= cycleTables[2][0x52];
HL &= 0xffff;
DE &= 0xffff;
sum = HL - DE - TSTFLAG(C);
cbits = (HL ^ DE ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & 0xffff) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | 2 | ((cbits >> 8) & 1);
break;
case 0x53: /* LD (nnnn),DE */
cycles -= cycleTables[2][0x53];
temp = GetWORD(pc);
PutWORD(temp, DE);
pc += 2;
break;
case 0x56: /* IM 1 */
cycles -= cycleTables[2][0x56];
im = 1; // interrupt mode 1
break;
case 0x57: /* LD A,I */
cycles -= cycleTables[2][0x57];
AF = (AF & 0x29) | (ir & ~255) | ((ir >> 8) & 0x80) | (((ir & ~255) == 0) << 6) | ((iff & 2) << 1);
break;
case 0x58: /* IN E,(C) */
cycles -= cycleTables[2][0x58];
temp = INPUT(lreg(BC));
Setlreg(DE, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x59: /* OUT (C),E */
cycles -= cycleTables[2][0x59];
OUTPUT(lreg(BC), lreg(DE));
break;
case 0x5A: /* ADC HL,DE */
cycles -= cycleTables[2][0x5A];
HL &= 0xffff;
DE &= 0xffff;
sum = HL + DE + TSTFLAG(C);
cbits = (HL ^ DE ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & 0xffff) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x5B: /* LD DE,(nnnn) */
cycles -= cycleTables[2][0x5B];
temp = GetWORD(pc);
DE = GetWORD(temp);
pc += 2;
break;
case 0x5E: /* IM 2 */
cycles -= cycleTables[2][0x5E];
im = 2; // interrupt mode 2
break;
case 0x5F: /* LD A,R */
cycles -= cycleTables[2][0x5F];
AF = (AF & 0x29) | ((ir & 255) << 8) | (ir & 0x80) | (((ir & 255) == 0) << 6) | ((iff & 2) << 1);
break;
case 0x60: /* IN H,(C) */
cycles -= cycleTables[2][0x60];
temp = INPUT(lreg(BC));
Sethreg(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x61: /* OUT (C),H */
cycles -= cycleTables[2][0x61];
OUTPUT(lreg(BC), hreg(HL));
break;
case 0x62: /* SBC HL,HL */
cycles -= cycleTables[2][0x62];
HL &= 0xffff;
sum = HL - HL - TSTFLAG(C);
cbits = (HL ^ HL ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & 0xffff) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | 2 | ((cbits >> 8) & 1);
break;
case 0x63: /* LD (nnnn),HL */
cycles -= cycleTables[2][0x63];
temp = GetWORD(pc);
PutWORD(temp, HL);
pc += 2;
break;
case 0x67: /* RRD */
cycles -= cycleTables[2][0x67];
temp = GetBYTE(HL);
acu = hreg(AF);
PutBYTE(HL, hdig(temp) | (ldig(acu) << 4));
acu = (acu & 0xf0) | ldig(temp);
AF = (acu << 8) | (acu & 0xa8) | (((acu & 0xff) == 0) << 6) |
partab[acu] | (AF & 1);
break;
case 0x68: /* IN L,(C) */
cycles -= cycleTables[2][0x68];
temp = INPUT(lreg(BC));
Setlreg(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x69: /* OUT (C),L */
cycles -= cycleTables[2][0x69];
OUTPUT(lreg(BC), lreg(HL));
break;
case 0x6A: /* ADC HL,HL */
cycles -= cycleTables[2][0x6A];
HL &= 0xffff;
sum = HL + HL + TSTFLAG(C);
cbits = (HL ^ HL ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & 0xffff) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x6B: /* LD HL,(nnnn) */
cycles -= cycleTables[2][0x6B];
temp = GetWORD(pc);
HL = GetWORD(temp);
pc += 2;
break;
case 0x6F: /* RLD */
cycles -= cycleTables[2][0x6F];
temp = GetBYTE(HL);
acu = hreg(AF);
PutBYTE(HL, (ldig(temp) << 4) | ldig(acu));
acu = (acu & 0xf0) | hdig(temp);
AF = (acu << 8) | (acu & 0xa8) | (((acu & 0xff) == 0) << 6) |
partab[acu] | (AF & 1);
break;
case 0x70: /* IN (C) */
cycles -= cycleTables[2][0x70];
temp = INPUT(lreg(BC));
Setlreg(temp, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x71: /* OUT (C),0 */
cycles -= cycleTables[2][0x71];
OUTPUT(lreg(BC), lreg(0));
break;
case 0x72: /* SBC HL,SP */
cycles -= cycleTables[2][0x72];
HL &= 0xffff;
SP &= 0xffff;
sum = HL - SP - TSTFLAG(C);
cbits = (HL ^ SP ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & 0xffff) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | 2 | ((cbits >> 8) & 1);
break;
case 0x73: /* LD (nnnn),SP */
cycles -= cycleTables[2][0x73];
temp = GetWORD(pc);
PutWORD(temp, SP);
pc += 2;
break;
case 0x78: /* IN A,(C) */
cycles -= cycleTables[2][0x78];
temp = INPUT(lreg(BC));
Sethreg(AF, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x79: /* OUT (C),A */
cycles -= cycleTables[2][0x79];
OUTPUT(lreg(BC), hreg(AF));
break;
case 0x7A: /* ADC HL,SP */
cycles -= cycleTables[2][0x7A];
HL &= 0xffff;
SP &= 0xffff;
sum = HL + SP + TSTFLAG(C);
cbits = (HL ^ SP ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & 0xffff) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x7B: /* LD SP,(nnnn) */
cycles -= cycleTables[2][0x7B];
temp = GetWORD(pc);
SP = GetWORD(temp);
pc += 2;
break;
case 0xA0: /* LDI */
cycles -= cycleTables[2][0xA0];
acu = GetBYTE_pp(HL);
PutBYTE_pp(DE, acu);
acu += hreg(AF);
AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) |
(((--BC & 0xffff) != 0) << 2);
break;
case 0xA1: /* CPI */
cycles -= cycleTables[2][0xA1];
acu = hreg(AF);
temp = GetBYTE_pp(HL);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) |
(((sum - ((cbits&16)>>4))&2) << 4) | (cbits & 16) |
((sum - ((cbits >> 4) & 1)) & 8) |
((--BC & 0xffff) != 0) << 2 | 2;
if ((sum & 15) == 8 && (cbits & 16) != 0)
AF &= ~8;
break;
case 0xA2: /* INI */
cycles -= cycleTables[2][0xA2];
PutBYTE(HL, INPUT(lreg(BC))); ++HL;
SETFLAG(N, 1);
SETFLAG(P, (--BC & 0xffff) != 0);
break;
case 0xA3: /* OUTI */
cycles -= cycleTables[2][0xA3];
OUTPUT(lreg(BC), GetBYTE(HL)); ++HL;
SETFLAG(N, 1);
Sethreg(BC, hreg(BC) - 1);
SETFLAG(Z, hreg(BC) == 0);
break;
case 0xA8: /* LDD */
cycles -= cycleTables[2][0xA8];
acu = GetBYTE_mm(HL);
PutBYTE_mm(DE, acu);
acu += hreg(AF);
AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) |
(((--BC & 0xffff) != 0) << 2);
break;
case 0xA9: /* CPD */
cycles -= cycleTables[2][0xA9];
acu = hreg(AF);
temp = GetBYTE_mm(HL);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) |
(((sum - ((cbits&16)>>4))&2) << 4) | (cbits & 16) |
((sum - ((cbits >> 4) & 1)) & 8) |
((--BC & 0xffff) != 0) << 2 | 2;
if ((sum & 15) == 8 && (cbits & 16) != 0)
AF &= ~8;
break;
case 0xAA: /* IND */
cycles -= cycleTables[2][0xAA];
PutBYTE(HL, INPUT(lreg(BC))); --HL;
SETFLAG(N, 1);
Sethreg(BC, lreg(BC) - 1);
SETFLAG(Z, lreg(BC) == 0);
break;
case 0xAB: /* OUTD */
cycles -= cycleTables[2][0xAB];
OUTPUT(lreg(BC), GetBYTE(HL)); --HL;
SETFLAG(N, 1);
Sethreg(BC, hreg(BC) - 1);
SETFLAG(Z, hreg(BC) == 0);
break;
case 0xB0: /* LDIR */
cycles -= cycleTables[2][0xB0];
acu = hreg(AF);
BC &= 0xffff;
if (BC == 0)
BC = 0x10000;
do {
acu = GetBYTE_pp(HL);
PutBYTE_pp(DE, acu);
} while (--BC);
acu += hreg(AF);
AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4);
break;
case 0xB1: /* CPIR */
cycles -= cycleTables[2][0xB1];
acu = hreg(AF);
BC &= 0xffff;
if (BC == 0)
BC = 0x10000;
do {
temp = GetBYTE_pp(HL);
op = --BC != 0;
sum = acu - temp;
} while (op && sum != 0);
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) |
(((sum - ((cbits&16)>>4))&2) << 4) |
(cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) |
op << 2 | 2;
if ((sum & 15) == 8 && (cbits & 16) != 0)
AF &= ~8;
break;
case 0xB2: /* INIR */
cycles -= cycleTables[2][0xB2];
temp = hreg(BC);
do {
PutBYTE(HL, INPUT(lreg(BC))); ++HL;
} while (--temp);
Sethreg(BC, 0);
SETFLAG(N, 1);
SETFLAG(Z, 1);
break;
case 0xB3: /* OTIR */
cycles -= cycleTables[2][0xB3];
temp = hreg(BC);
do {
OUTPUT(lreg(BC), GetBYTE(HL)); ++HL;
} while (--temp);
Sethreg(BC, 0);
SETFLAG(N, 1);
SETFLAG(Z, 1);
break;
case 0xB8: /* LDDR */
cycles -= cycleTables[2][0xB8];
BC &= 0xffff;
if (BC == 0)
BC = 0x10000;
do {
acu = GetBYTE_mm(HL);
PutBYTE_mm(DE, acu);
} while (--BC);
acu += hreg(AF);
AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4);
break;
case 0xB9: /* CPDR */
cycles -= cycleTables[2][0xB9];
acu = hreg(AF);
BC &= 0xffff;
if (BC == 0)
BC = 0x10000;
do {
temp = GetBYTE_mm(HL);
op = --BC != 0;
sum = acu - temp;
} while (op && sum != 0);
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) |
(((sum - ((cbits&16)>>4))&2) << 4) |
(cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) |
op << 2 | 2;
if ((sum & 15) == 8 && (cbits & 16) != 0)
AF &= ~8;
break;
case 0xBA: /* INDR */
cycles -= cycleTables[2][0xBA];
temp = hreg(BC);
do {
PutBYTE(HL, INPUT(lreg(BC))); --HL;
} while (--temp);
Sethreg(BC, 0);
SETFLAG(N, 1);
SETFLAG(Z, 1);
break;
case 0xBB: /* OTDR */
cycles -= cycleTables[2][0xBB];
temp = hreg(BC);
do {
OUTPUT(lreg(BC), GetBYTE(HL)); --HL;
} while (--temp);
Sethreg(BC, 0);
SETFLAG(N, 1);
SETFLAG(Z, 1);
break;
default: if (0x40 <= op && op <= 0x7f) pc--; /* ignore ED */
}
break;
case 0xEE: /* XOR nn */
cycles -= cycleTables[0][0xEE];
sum = ((AF >> 8) ^ GetBYTE_pp(pc)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xEF: /* RST 28H */
cycles -= cycleTables[0][0xEF];
PUSH(pc); pc = 0x28;
break;
case 0xF0: /* RET P */
cycles -= cycleTables[0][0xF0];
if (!TSTFLAG(S)) POP(pc);
break;
case 0xF1: /* POP AF */
cycles -= cycleTables[0][0xF1];
POP(AF);
break;
case 0xF2: /* JP P,nnnn */
cycles -= cycleTables[0][0xF2];
Jpc(!TSTFLAG(S));
break;
case 0xF3: /* DI */
cycles -= cycleTables[0][0xF3];
iff = 0;
break;
case 0xF4: /* CALL P,nnnn */
cycles -= cycleTables[0][0xF4];
CALLC(!TSTFLAG(S));
break;
case 0xF5: /* PUSH AF */
cycles -= cycleTables[0][0xF5];
PUSH(AF);
break;
case 0xF6: /* OR nn */
cycles -= cycleTables[0][0xF6];
sum = ((AF >> 8) | GetBYTE_pp(pc)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xF7: /* RST 30H */
cycles -= cycleTables[0][0xF7];
PUSH(pc); pc = 0x30;
break;
case 0xF8: /* RET M */
cycles -= cycleTables[0][0xF8];
if (TSTFLAG(S)) POP(pc);
break;
case 0xF9: /* LD SP,HL */
cycles -= cycleTables[0][0xF9];
SP = HL;
break;
case 0xFA: /* JP M,nnnn */
cycles -= cycleTables[0][0xFA];
Jpc(TSTFLAG(S));
break;
case 0xFB: /* EI */
cycles -= cycleTables[0][0xFB];
iff = 3;
break;
case 0xFC: /* CALL M,nnnn */
cycles -= cycleTables[0][0xFC];
CALLC(TSTFLAG(S));
break;
case 0xFD: /* FD prefix */
op = GetBYTE_pp(pc);
switch (op) {
case 0x09: /* ADD IY,BC */
cycles -= cycleTables[3][0x09];
IY &= 0xffff;
BC &= 0xffff;
sum = IY + BC;
cbits = (IY ^ BC ^ sum) >> 8;
IY = sum;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x19: /* ADD IY,DE */
cycles -= cycleTables[3][0x19];
IY &= 0xffff;
DE &= 0xffff;
sum = IY + DE;
cbits = (IY ^ DE ^ sum) >> 8;
IY = sum;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x21: /* LD IY,nnnn */
cycles -= cycleTables[3][0x21];
IY = GetWORD(pc);
pc += 2;
break;
case 0x22: /* LD (nnnn),IY */
cycles -= cycleTables[3][0x22];
temp = GetWORD(pc);
PutWORD(temp, IY);
pc += 2;
break;
case 0x23: /* INC IY */
cycles -= cycleTables[3][0x23];
++IY;
break;
case 0x24: /* INC IYH */
cycles -= cycleTables[3][0x24];
IY += 0x100;
temp = hreg(IY);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x25: /* DEC IYH */
cycles -= cycleTables[3][0x25];
IY -= 0x100;
temp = hreg(IY);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x26: /* LD IYH,nn */
cycles -= cycleTables[3][0x26];
Sethreg(IY, GetBYTE_pp(pc));
break;
case 0x29: /* ADD IY,IY */
cycles -= cycleTables[3][0x29];
IY &= 0xffff;
sum = IY + IY;
cbits = (IY ^ IY ^ sum) >> 8;
IY = sum;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x2A: /* LD IY,(nnnn) */
cycles -= cycleTables[3][0x2A];
temp = GetWORD(pc);
IY = GetWORD(temp);
pc += 2;
break;
case 0x2B: /* DEC IY */
cycles -= cycleTables[3][0x2B];
--IY;
break;
case 0x2C: /* INC IYL */
cycles -= cycleTables[3][0x2C];
temp = lreg(IY)+1;
Setlreg(IY, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x2D: /* DEC IYL */
cycles -= cycleTables[3][0x2D];
temp = lreg(IY)-1;
Setlreg(IY, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x2E: /* LD IYL,nn */
cycles -= cycleTables[3][0x2E];
Setlreg(IY, GetBYTE_pp(pc));
break;
case 0x34: /* INC (IY+dd) */
cycles -= cycleTables[3][0x34];
adr = IY + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr)+1;
PutBYTE(adr, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
((temp == 0x80) << 2);
break;
case 0x35: /* DEC (IY+dd) */
cycles -= cycleTables[3][0x35];
adr = IY + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr)-1;
PutBYTE(adr, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
((temp == 0x7f) << 2) | 2;
break;
case 0x36: /* LD (IY+dd),nn */
cycles -= cycleTables[3][0x36];
adr = IY + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, GetBYTE_pp(pc));
break;
case 0x39: /* ADD IY,SP */
cycles -= cycleTables[3][0x39];
IY &= 0xffff;
SP &= 0xffff;
sum = IY + SP;
cbits = (IY ^ SP ^ sum) >> 8;
IY = sum;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x44: /* LD B,IYH */
cycles -= cycleTables[3][0x44];
Sethreg(BC, hreg(IY));
break;
case 0x45: /* LD B,IYL */
cycles -= cycleTables[3][0x45];
Sethreg(BC, lreg(IY));
break;
case 0x46: /* LD B,(IY+dd) */
cycles -= cycleTables[3][0x46];
adr = IY + (signed char) GetBYTE_pp(pc);
Sethreg(BC, GetBYTE(adr));
break;
case 0x4C: /* LD C,IYH */
cycles -= cycleTables[3][0x4C];
Setlreg(BC, hreg(IY));
break;
case 0x4D: /* LD C,IYL */
cycles -= cycleTables[3][0x4D];
Setlreg(BC, lreg(IY));
break;
case 0x4E: /* LD C,(IY+dd) */
cycles -= cycleTables[3][0x4E];
adr = IY + (signed char) GetBYTE_pp(pc);
Setlreg(BC, GetBYTE(adr));
break;
case 0x54: /* LD D,IYH */
cycles -= cycleTables[3][0x54];
Sethreg(DE, hreg(IY));
break;
case 0x55: /* LD D,IYL */
cycles -= cycleTables[3][0x55];
Sethreg(DE, lreg(IY));
break;
case 0x56: /* LD D,(IY+dd) */
cycles -= cycleTables[3][0x56];
adr = IY + (signed char) GetBYTE_pp(pc);
Sethreg(DE, GetBYTE(adr));
break;
case 0x5C: /* LD E,H */
cycles -= cycleTables[3][0x5C];
Setlreg(DE, hreg(IY));
break;
case 0x5D: /* LD E,L */
cycles -= cycleTables[3][0x5D];
Setlreg(DE, lreg(IY));
break;
case 0x5E: /* LD E,(IY+dd) */
cycles -= cycleTables[3][0x5E];
adr = IY + (signed char) GetBYTE_pp(pc);
Setlreg(DE, GetBYTE(adr));
break;
case 0x60: /* LD IYH,B */
cycles -= cycleTables[3][0x60];
Sethreg(IY, hreg(BC));
break;
case 0x61: /* LD IYH,C */
cycles -= cycleTables[3][0x61];
Sethreg(IY, lreg(BC));
break;
case 0x62: /* LD IYH,D */
cycles -= cycleTables[3][0x62];
Sethreg(IY, hreg(DE));
break;
case 0x63: /* LD IYH,E */
cycles -= cycleTables[3][0x63];
Sethreg(IY, lreg(DE));
break;
case 0x64: /* LD IYH,IYH */
cycles -= cycleTables[3][0x64];
/* nop */
break;
case 0x65: /* LD IYH,IYL */
cycles -= cycleTables[3][0x65];
Sethreg(IY, lreg(IY));
break;
case 0x66: /* LD H,(IY+dd) */
cycles -= cycleTables[3][0x66];
adr = IY + (signed char) GetBYTE_pp(pc);
Sethreg(HL, GetBYTE(adr));
break;
case 0x67: /* LD IYH,A */
cycles -= cycleTables[3][0x67];
Sethreg(IY, hreg(AF));
break;
case 0x68: /* LD IYL,B */
cycles -= cycleTables[3][0x68];
Setlreg(IY, hreg(BC));
break;
case 0x69: /* LD IYL,C */
cycles -= cycleTables[3][0x69];
Setlreg(IY, lreg(BC));
break;
case 0x6A: /* LD IYL,D */
cycles -= cycleTables[3][0x6A];
Setlreg(IY, hreg(DE));
break;
case 0x6B: /* LD IYL,E */
cycles -= cycleTables[3][0x6B];
Setlreg(IY, lreg(DE));
break;
case 0x6C: /* LD IYL,IYH */
cycles -= cycleTables[3][0x6C];
Setlreg(IY, hreg(IY));
break;
case 0x6D: /* LD IYL,IYL */
cycles -= cycleTables[3][0x6D];
/* nop */
break;
case 0x6E: /* LD L,(IY+dd) */
cycles -= cycleTables[3][0x6E];
adr = IY + (signed char) GetBYTE_pp(pc);
Setlreg(HL, GetBYTE(adr));
break;
case 0x6F: /* LD IYL,A */
cycles -= cycleTables[3][0x6F];
Setlreg(IY, hreg(AF));
break;
case 0x70: /* LD (IY+dd),B */
cycles -= cycleTables[3][0x70];
adr = IY + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, hreg(BC));
break;
case 0x71: /* LD (IY+dd),C */
cycles -= cycleTables[3][0x71];
adr = IY + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, lreg(BC));
break;
case 0x72: /* LD (IY+dd),D */
cycles -= cycleTables[3][0x72];
adr = IY + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, hreg(DE));
break;
case 0x73: /* LD (IY+dd),E */
cycles -= cycleTables[3][0x73];
adr = IY + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, lreg(DE));
break;
case 0x74: /* LD (IY+dd),H */
cycles -= cycleTables[3][0x74];
adr = IY + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, hreg(HL));
break;
case 0x75: /* LD (IY+dd),L */
cycles -= cycleTables[3][0x75];
adr = IY + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, lreg(HL));
break;
case 0x77: /* LD (IY+dd),A */
cycles -= cycleTables[3][0x77];
adr = IY + (signed char) GetBYTE_pp(pc);
PutBYTE(adr, hreg(AF));
break;
case 0x7C: /* LD A,IYH */
cycles -= cycleTables[3][0x7C];
Sethreg(AF, hreg(IY));
break;
case 0x7D: /* LD A,IYL */
cycles -= cycleTables[3][0x7D];
Sethreg(AF, lreg(IY));
break;
case 0x7E: /* LD A,(IY+dd) */
cycles -= cycleTables[3][0x7E];
adr = IY + (signed char) GetBYTE_pp(pc);
Sethreg(AF, GetBYTE(adr));
break;
case 0x84: /* ADD A,IYH */
cycles -= cycleTables[3][0x84];
temp = hreg(IY);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x85: /* ADD A,IYL */
cycles -= cycleTables[3][0x85];
temp = lreg(IY);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x86: /* ADD A,(IY+dd) */
cycles -= cycleTables[3][0x86];
adr = IY + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x8C: /* ADC A,IYH */
cycles -= cycleTables[3][0x8C];
temp = hreg(IY);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x8D: /* ADC A,IYL */
cycles -= cycleTables[3][0x8D];
temp = lreg(IY);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x8E: /* ADC A,(IY+dd) */
cycles -= cycleTables[3][0x8E];
adr = IY + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
break;
case 0x94: /* SUB IYH */
cycles -= cycleTables[3][0x94];
temp = hreg(IY);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x95: /* SUB IYL */
cycles -= cycleTables[3][0x95];
temp = lreg(IY);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x96: /* SUB (IY+dd) */
cycles -= cycleTables[3][0x96];
adr = IY + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x9C: /* SBC A,IYH */
cycles -= cycleTables[3][0x9C];
temp = hreg(IY);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x9D: /* SBC A,IYL */
cycles -= cycleTables[3][0x9D];
temp = lreg(IY);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0x9E: /* SBC A,(IY+dd) */
cycles -= cycleTables[3][0x9E];
adr = IY + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
((cbits >> 8) & 1);
break;
case 0xA4: /* AND IYH */
cycles -= cycleTables[3][0xA4];
sum = ((AF & (IY)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xA5: /* AND IYL */
cycles -= cycleTables[3][0xA5];
sum = ((AF >> 8) & IY) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xA6: /* AND (IY+dd) */
cycles -= cycleTables[3][0xA6];
adr = IY + (signed char) GetBYTE_pp(pc);
sum = ((AF >> 8) & GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xAC: /* XOR IYH */
cycles -= cycleTables[3][0xAC];
sum = ((AF ^ (IY)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAD: /* XOR IYL */
cycles -= cycleTables[3][0xAD];
sum = ((AF >> 8) ^ IY) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAE: /* XOR (IY+dd) */
cycles -= cycleTables[3][0xAE];
adr = IY + (signed char) GetBYTE_pp(pc);
sum = ((AF >> 8) ^ GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB4: /* OR IYH */
cycles -= cycleTables[3][0xB4];
sum = ((AF | (IY)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB5: /* OR IYL */
cycles -= cycleTables[3][0xB5];
sum = ((AF >> 8) | IY) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB6: /* OR (IY+dd) */
cycles -= cycleTables[3][0xB6];
adr = IY + (signed char) GetBYTE_pp(pc);
sum = ((AF >> 8) | GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xBC: /* CP IYH */
cycles -= cycleTables[3][0xBC];
temp = hreg(IY);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBD: /* CP IYL */
cycles -= cycleTables[3][0xBD];
temp = lreg(IY);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBE: /* CP (IY+dd) */
cycles -= cycleTables[3][0xBE];
adr = IY + (signed char) GetBYTE_pp(pc);
temp = GetBYTE(adr);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xCB: /* CB prefix */
adr = IY + (signed char) GetBYTE_pp(pc);
//adr = adr;
op = GetBYTE(pc);
cycles -= cycleTables[4][op];
switch (op & 7) {
case 0: ++pc; acu = hreg(BC); break;
case 1: ++pc; acu = lreg(BC); break;
case 2: ++pc; acu = hreg(DE); break;
case 3: ++pc; acu = lreg(DE); break;
case 4: ++pc; acu = hreg(HL); break;
case 5: ++pc; acu = lreg(HL); break;
case 6: ++pc; acu = GetBYTE(adr); break;
case 7: ++pc; acu = hreg(AF); break;
}
switch (op & 0xc0) {
case 0x00: /* shift/rotate */
switch (op & 0x38) {
case 0x00: /* RLC */
temp = (acu << 1) | (acu >> 7);
cbits = temp & 1;
goto cbshflg3;
case 0x08: /* RRC */
temp = (acu >> 1) | (acu << 7);
cbits = temp & 0x80;
goto cbshflg3;
case 0x10: /* RL */
temp = (acu << 1) | TSTFLAG(C);
cbits = acu & 0x80;
goto cbshflg3;
case 0x18: /* RR */
temp = (acu >> 1) | (TSTFLAG(C) << 7);
cbits = acu & 1;
goto cbshflg3;
case 0x20: /* SLA */
temp = acu << 1;
cbits = acu & 0x80;
goto cbshflg3;
case 0x28: /* SRA */
temp = (acu >> 1) | (acu & 0x80);
cbits = acu & 1;
goto cbshflg3;
case 0x30: /* SLIA */
temp = (acu << 1) | 1;
cbits = acu & 0x80;
goto cbshflg3;
case 0x38: /* SRL */
temp = acu >> 1;
cbits = acu & 1;
cbshflg3:
AF = (AF & ~0xff) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp) | !!cbits;
}
break;
case 0x40: /* BIT */
if (acu & (1 << ((op >> 3) & 7)))
AF = (AF & ~0xfe) | 0x10 |
(((op & 0x38) == 0x38) << 7);
else
AF = (AF & ~0xfe) | 0x54;
if ((op&7) != 6)
AF |= (acu & 0x28);
temp = acu;
break;
case 0x80: /* RES */
temp = acu & ~(1 << ((op >> 3) & 7));
break;
case 0xc0: /* SET */
temp = acu | (1 << ((op >> 3) & 7));
break;
}
switch (op & 7) {
case 0: Sethreg(BC, temp); break;
case 1: Setlreg(BC, temp); break;
case 2: Sethreg(DE, temp); break;
case 3: Setlreg(DE, temp); break;
case 4: Sethreg(HL, temp); break;
case 5: Setlreg(HL, temp); break;
case 6: PutBYTE(adr, temp); break;
case 7: Sethreg(AF, temp); break;
}
break;
case 0xE1: /* POP IY */
cycles -= cycleTables[3][0xE1];
POP(IY);
break;
case 0xE3: /* EX (SP),IY */
cycles -= cycleTables[3][0xE3];
temp = IY; POP(IY); PUSH(temp);
break;
case 0xE5: /* PUSH IY */
cycles -= cycleTables[3][0xE5];
PUSH(IY);
break;
case 0xE9: /* JP (IY) */
cycles -= cycleTables[3][0xE9];
pc = IY;
break;
case 0xF9: /* LD SP,IY */
cycles -= cycleTables[3][0xF9];
SP = IY;
break;
default: pc--; /* ignore DD */
}
break;
case 0xFE: /* CP nn */
cycles -= cycleTables[0][0xFE];
temp = GetBYTE_pp(pc);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | (sum & 0x80) |
(((sum & 0xff) == 0) << 6) | (temp & 0x28) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xFF: /* RST 38H */
cycles -= cycleTables[0][0xFF];
PUSH(pc); pc = 0x38;
break;
}
// Interrupts
if (nmiTrigger) // NMI triggered (higher priority than INT)
{
/*
* NMI sequence:
*
* - Push pc on stack
* - Set pc to NMI vector (0x0066)
* - Copy IFF1 to IFF2 (save interrupt enable status)
* - Clear IFF1 (disable interrupts)
* - Un-halt CPU (if in HALT state)
*/
#ifdef SUPERMODEL_DEBUGGER
if (Debug != NULL)
Debug->CPUException(Z80_EX_NMI);
#endif // SUPERMODEL_DEBUGGER
PUSH(pc);
pc = 0x0066;
iff = (iff&~2) | ((iff&1)<<1);
iff &= ~1;
nmiTrigger = false; // clear NMI
// TODO: if in HALTed state, un-halt
}
else if (intLine) // INT asserted
{
// If interrupts are enabled (IFF1 != 0)
if ((iff&1))
{
int v;
/*
* INT sequence:
*
* - Disable interrupts (clear IFF1 and IFF2)
* - Push pc on stack
* - Un-halt CPU (if in HALT state)
* - Set pc to vector (which depends on mode)
*
* If no callback is provided when required, nothing happens and
* the interrupt line is cleared. Otherwise, callbacks are
* responsible for clearing the lines themselves.
*/
// TODO: if in HALTed state, un-halt
switch (im) // interrupt mode (0, 1, or 2 only!)
{
case 0:
/*
* Mode 0:
*
* Fetches up 3 bytes from bus and executes them directly.
* Usually, this will just be an RST instruction, so this is
* all that we accept here.
*/
if (NULL != INTCallback)
{
v = INTCallback(this);
#ifdef SUPERMODEL_DEBUGGER
if (Debug != NULL)
Debug->CPUException(v);
#endif // SUPERMODEL_DEBUGGER
switch (v)
{
case Z80_INT_RST_00: v = 0x0000; break;
case Z80_INT_RST_08: v = 0x0008; break;
case Z80_INT_RST_10: v = 0x0010; break;
case Z80_INT_RST_18: v = 0x0018; break;
case Z80_INT_RST_20: v = 0x0020; break;
case Z80_INT_RST_28: v = 0x0028; break;
case Z80_INT_RST_30: v = 0x0030; break;
case Z80_INT_RST_38: v = 0x0038; break;
default: v = -1; break; // invalid, do nothing
}
if (v >= 0) // valid vector
{
PUSH(pc);
pc = (UINT16) v;
iff = 0;
}
}
else // if no callback, do nothing, clear INT line
intLine = false;
break;
case 1:
/*
* Mode 1:
*
* Vector is 0x0038.
*/
#ifdef SUPERMODEL_DEBUGGER
if (Debug != NULL)
Debug->CPUException(Z80_IM1_IRQ);
#endif // SUPERMODEL_DEBUGGER
PUSH(pc);
pc = 0x0038;
iff = 0;
if (NULL != INTCallback)
INTCallback(this);
else // no callback, clear INT line automatically
intLine = false;
break;
case 2:
/*
* Mode 2:
*
* A 16-bit address is formed by concatenating the I register
* and 8 bits read from the bus (with bit 0 cleared). The final
* 16-bit vector is read from this address.
*/
#ifdef SUPERMODEL_DEBUGGER
if (Debug != NULL)
Debug->CPUException(Z80_IM2_VECTOR);
#endif // SUPERMODEL_DEBUGGER
if (NULL != INTCallback)
{
v = INTCallback(this);
v = (ir&0xFF00) | (v&0xFE);
PUSH(pc);
pc = GetWORD(v);
iff = 0;
}
else // if no callback, do nothing, clear INT line
intLine = false;
break;
default: // should never happen (nothing will be done)
intLine = false;
break;
}
}
}
} // end while
// write registers back to context
HALTExit:
#ifdef SUPERMODEL_DEBUGGER
if (Debug != NULL)
{
Debug->CPUInactive();
lastCycles -= cycles;
}
#else
// Save local copies of Z80 registers back to context
af[af_sel] = AF;
regs[regs_sel].bc = BC;
regs[regs_sel].de = DE;
regs[regs_sel].hl = HL;
ix = IX;
iy = IY;
sp = SP;
#endif // SUPERMODEL_DEBUGGER
// Return number of cycles actually executed
return numCycles - cycles;
}
void CZ80::TriggerNMI(void)
{
nmiTrigger = true;
}
void CZ80::SetINT(bool state)
{
intLine = state;
}
UINT16 CZ80::GetPC(void)
{
return pc;
}
#ifdef SUPERMODEL_DEBUGGER
UINT8 CZ80::GetReg8(unsigned reg8)
{
switch (reg8)
{
case Z80_REG8_IFF: return iff;
case Z80_REG8_IM: return im;
case Z80_REG8_I: return ir>>8;
case Z80_REG8_R: return ir&0xFF;
case Z80_REG8_A: return af[0]>>8;
case Z80_REG8_F: return af[0]&0xFF;
case Z80_REG8_B: return regs[0].bc>>8;
case Z80_REG8_C: return regs[0].bc&0xFF;
case Z80_REG8_D: return regs[0].de>>8;
case Z80_REG8_E: return regs[0].de&0xFF;
case Z80_REG8_H: return regs[0].hl>>8;
case Z80_REG8_L: return regs[0].hl&0xFF;
default: return 0;
}
}
bool CZ80::SetReg8(unsigned reg8, UINT8 value)
{
switch (reg8)
{
case Z80_REG8_IFF: iff = value; return true;
case Z80_REG8_IM: im = value; return true;
case Z80_REG8_I: ir |= value<<8; return true;
case Z80_REG8_R: ir |= value; return true;
case Z80_REG8_A: af[0] |= value<<8; return true;
case Z80_REG8_F: af[0] |= value; return true;
case Z80_REG8_B: regs[0].bc |= value<<8; return true;
case Z80_REG8_C: regs[0].bc |= value; return true;
case Z80_REG8_D: regs[0].de |= value<<8; return true;
case Z80_REG8_E: regs[0].de |= value; return true;
case Z80_REG8_H: regs[0].hl |= value<<8; return true;
case Z80_REG8_L: regs[0].hl |= value; return true;
default: return false;
}
}
UINT16 CZ80::GetReg16(unsigned reg16)
{
switch (reg16)
{
case Z80_REG16_SP: return sp;
case Z80_REG16_PC: return pc;
case Z80_REG16_IR: return ir;
case Z80_REG16_AF: return af[0];
case Z80_REG16_BC: return regs[0].bc;
case Z80_REG16_DE: return regs[0].de;
case Z80_REG16_HL: return regs[0].hl;
case Z80_REG16_IX: return ix;
case Z80_REG16_IY: return iy;
case Z80_REG16_AF_: return af[1];
case Z80_REG16_BC_: return regs[1].bc;
case Z80_REG16_DE_: return regs[1].de;
case Z80_REG16_HL_: return regs[1].hl;
default: return 0;
}
}
bool CZ80::SetReg16(unsigned reg16, UINT16 value)
{
switch (reg16)
{
case Z80_REG16_SP: sp = value; return true;
case Z80_REG16_PC: pc = value; return true;
case Z80_REG16_IR: ir = value; return true;
case Z80_REG16_AF: af[0] = value; return true;
case Z80_REG16_BC: regs[0].bc = value; return true;
case Z80_REG16_DE: regs[0].de = value; return true;
case Z80_REG16_HL: regs[0].hl = value; return true;
case Z80_REG16_IX: ix = value; return true;
case Z80_REG16_IY: iy = value; return true;
case Z80_REG16_AF_: af[1] = value; return true;
case Z80_REG16_BC_: regs[1].bc = value; return true;
case Z80_REG16_DE_: regs[1].de = value; return true;
case Z80_REG16_HL_: regs[1].hl = value; return true;
default: return false;
}
}
#endif // SUPERMODEL_DEBUGGER
void CZ80::Reset(void)
{
pc = 0x0000;
sp = 0xF000;
af[0] = 0x0000;
af[1] = 0x0000;
regs[0].bc = 0x0000;
regs[0].de = 0x0000;
regs[0].hl = 0x0000;
regs[1].bc = 0x0000;
regs[1].de = 0x0000;
regs[1].hl = 0x0000;
ix = 0x0000;
iy = 0x0000;
ir = 0x0000;
iff = 0;
im = 0;
af_sel = 0;
regs_sel = 0;
intLine = false;
nmiTrigger = false;
#ifdef SUPERMODEL_DEBUGGER
lastCycles = 0;
#endif // SUPERMODEL_DEBUGGER
}
void CZ80::SaveState(CBlockFile *StateFile, const char *name)
{
StateFile->NewBlock(name, __FILE__);
for (int i = 0; i < 2; i++)
{
StateFile->Write(®s[i].bc, sizeof(regs[i].bc));
StateFile->Write(®s[i].de, sizeof(regs[i].de));
StateFile->Write(®s[i].hl, sizeof(regs[i].hl));
}
StateFile->Write(af, sizeof(af));
StateFile->Write(&ir, sizeof(ir));
StateFile->Write(&ix, sizeof(ix));
StateFile->Write(&iy, sizeof(iy));
StateFile->Write(&sp, sizeof(sp));
StateFile->Write(&pc, sizeof(pc));
StateFile->Write(&iff, sizeof(iff));
StateFile->Write(&im, sizeof(im));
StateFile->Write(®s_sel, sizeof(regs_sel));
StateFile->Write(&af_sel, sizeof(af_sel));
StateFile->Write(&nmiTrigger, sizeof(nmiTrigger));
StateFile->Write(&intLine, sizeof(intLine));
}
void CZ80::LoadState(CBlockFile *StateFile, const char *name)
{
if (OKAY != StateFile->FindBlock(name))
{
ErrorLog("Unable to load Z80 state. Save state file is corrupt.");
return;
}
for (int i = 0; i < 2; i++)
{
StateFile->Read(®s[i].bc, sizeof(regs[i].bc));
StateFile->Read(®s[i].de, sizeof(regs[i].de));
StateFile->Read(®s[i].hl, sizeof(regs[i].hl));
}
StateFile->Read(af, sizeof(af));
StateFile->Read(&ir, sizeof(ir));
StateFile->Read(&ix, sizeof(ix));
StateFile->Read(&iy, sizeof(iy));
StateFile->Read(&sp, sizeof(sp));
StateFile->Read(&pc, sizeof(pc));
StateFile->Read(&iff, sizeof(iff));
StateFile->Read(&im, sizeof(im));
StateFile->Read(®s_sel, sizeof(regs_sel));
StateFile->Read(&af_sel, sizeof(af_sel));
StateFile->Read(&nmiTrigger, sizeof(nmiTrigger));
StateFile->Read(&intLine, sizeof(intLine));
}
void CZ80::Init(IBus *BusPtr, int (*INTF)(CZ80 *Z80))
{
Bus = BusPtr;
INTCallback = INTF;
}
#ifdef SUPERMODEL_DEBUGGER
void CZ80::AttachDebugger(Debugger::CZ80Debug *DebugPtr)
{
if (Debug != NULL)
DetachDebugger();
Debug = DebugPtr;
Bus = Debug->AttachBus(Bus);
}
void CZ80::DetachDebugger()
{
if (Debug == NULL)
return;
Bus = Debug->DetachBus();
Debug = NULL;
}
#endif //SUPERMODEL_DEBUGGER
CZ80::CZ80(void)
{
INTCallback = NULL; // so we can later check to see if one has been installed
Bus = NULL;
#ifdef SUPERMODEL_DEBUGGER
Debug = NULL;
#endif //SUPERMODEL_DEBUGGER
}
CZ80::~CZ80(void)
{
INTCallback = NULL;
Bus = NULL;
#ifdef SUPERMODEL_DEBUGGER
Debug = NULL;
#endif //SUPERMODEL_DEBUGGER
}