blob: ad8b1f597fe39e7cb4fc172bef5a42be78c5cdb8 [file] [log] [blame] [raw]
/* altairz80_cpu.c: MITS Altair CPU (8080 and Z80)
Written by Peter Schorn, 2001
Based on work by Charles E Owen ((c) 1997 - Commercial use prohibited)
Code for Z80 CPU from Frank D. Cringle ((c) 1995 under GNU license)
*/
#include <stdio.h>
#include "altairZ80_defs.h"
/*-------------------------------- definitions for memory space --------*/
uint8 M[MAXMEMSIZE]; /* RAM which is present */
/* two sets of accumulator / flags */
uint16 af[2];
int af_sel;
/* two sets of 16-bit registers */
struct ddregs {
uint16 bc;
uint16 de;
uint16 hl;
} regs[2];
int regs_sel;
uint16 ir;
uint16 ix;
uint16 iy;
uint16 sp;
uint16 pc;
uint16 IFF;
#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)
#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))
/* SetPV and SetPV2 are used to provide correct parity flag semantics for the 8080 in cases
where the Z80 uses the overflow flag
*/
#define SetPV ((cpu_unit.flags & UNIT_CHIP) ? (((cbits >> 6) ^ (cbits >> 5)) & 4) : (parity(sum)))
#define SetPV2(x) ((cpu_unit.flags & UNIT_CHIP) ? (((temp == (x)) << 2)) : (parity(temp)))
/* checkCPU must be invoked whenever a Z80 only instruction is executed */
#define checkCPU if ((cpu_unit.flags & UNIT_CHIP) == 0) { Bad8080OpOccured = 1; break; }
static const uint8 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,
};
#define parity(x) partab[(x)&0xff]
#define POP(x) do { \
register uint32 y = RAM_pp(SP); \
x = y + (RAM_pp(SP) << 8); \
} while (0)
#define JPC(cond) PC = cond ? GetWORD(PC) : PC+2
#define CALLC(cond) { \
if (cond) { \
register uint32 adrr = GetWORD(PC); \
PUSH(PC+2); \
PC = adrr; \
} \
else \
PC += 2; \
}
int32 saved_PC = 0; /* program counter */
int32 SR = 0; /* switch register */
int32 PCX; /* External view of PC */
extern int32 sim_int_char;
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
/* function prototypes */
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
t_stat cpu_reset (DEVICE *dptr);
t_stat cpu_svc (UNIT *uptr);
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
void clear_memory(int32 starting);
extern int32 sio0s(int32 io, int32 data);
extern int32 sio0d(int32 io, int32 data);
extern int32 sio1s(int32 io, int32 data);
extern int32 sio1d(int32 io, int32 data);
extern int32 dsk10(int32 io, int32 data);
extern int32 dsk11(int32 io, int32 data);
extern int32 dsk12(int32 io, int32 data);
extern int32 nulldev(int32 io, int32 data);
extern int32 simh_dev(int32 io, int32 data);
extern int32 markTimeSP;
/* This is the I/O configuration table. There are 255 possible
device addresses, if a device is plugged to a port it's routine
address is here, 'nulldev' means no device is available
*/
struct idev {
int32 (*routine)();
};
struct idev dev_table[256] = {
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 00 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 04 */
{&dsk10}, {&dsk11}, {&dsk12}, {&nulldev}, /* 08 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C */
{&sio0s}, {&sio0d}, {&sio1s}, {&sio1d}, /* 10 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 14 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 18 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1C */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 20 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 24 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 28 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2C */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 30 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 34 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 38 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3C */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 40 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 44 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 48 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 4C */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 50 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 54 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 58 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 5C */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 60 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 64 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 68 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 6C */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 70 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 74 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 78 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 7C */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 80 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 84 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 88 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 8C */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 90 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 94 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 98 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 9C */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* A0 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* A4 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* A8 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* AC */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* B0 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* B4 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* B8 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* BC */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* C0 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* C4 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* C8 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* CC */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D0 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D4 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D8 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* DC */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D0 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* E4 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* E8 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* EC */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* F0 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* F4 */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* F8 */
{&nulldev}, {&nulldev}, {&simh_dev}, {&nulldev} }; /* FC */
/* Altair MITS modified BOOT EPROM, fits in upper 256 byte of memory */
int32 bootrom[bootrom_size] = {
0x21, 0x00, 0x5c, 0x11, 0x13, 0xff, 0x0e, 0xb9, /* ff00-ff07 */
0x1a, 0x77, 0x13, 0x23, 0x0d, 0xc2, 0x08, 0xff, /* ff08-ff0f */
0xc3, 0x00, 0x5c, 0x31, 0xa6, 0x5d, 0xaf, 0xd3, /* ff10-ff17 */
0x08, 0x3e, 0x04, 0xd3, 0x09, 0xc3, 0x18, 0x5c, /* ff18-ff1f */
0xdb, 0x08, 0xe6, 0x02, 0xc2, 0x0d, 0x5c, 0x3e, /* ff20-ff27 */
0x02, 0xd3, 0x09, 0xdb, 0x08, 0xe6, 0x40, 0xc2, /* ff28-ff2f */
0x0d, 0x5c, 0x11, 0x00, 0x00, 0x06, 0x08, 0xc3, /* ff30-ff37 */
0x29, 0x5c, 0x06, 0x00, 0x3e, 0x10, 0xf5, 0xd5, /* ff38-ff3f */
0xc5, 0xd5, 0x11, 0x86, 0x80, 0x21, 0xb9, 0x5c, /* ff40-ff47 */
0xdb, 0x09, 0x1f, 0xda, 0x35, 0x5c, 0xe6, 0x1f, /* ff48-ff4f */
0xb8, 0xc2, 0x35, 0x5c, 0xdb, 0x08, 0xb7, 0xfa, /* ff50-ff57 */
0x41, 0x5c, 0xdb, 0x0a, 0x77, 0x23, 0x1d, 0xca, /* ff58-ff5f */
0x57, 0x5c, 0x1d, 0xdb, 0x0a, 0x77, 0x23, 0xc2, /* ff60-ff67 */
0x41, 0x5c, 0xe1, 0x11, 0xbc, 0x5c, 0x01, 0x80, /* ff68-ff6f */
0x00, 0x1a, 0x77, 0xbe, 0x80, 0x47, 0x13, 0x23, /* ff70-ff77 */
0x0d, 0xc2, 0x5e, 0x5c, 0x1a, 0xfe, 0xff, 0xc2, /* ff78-ff7f */
0x72, 0x5c, 0x13, 0x1a, 0xb8, 0xc1, 0xeb, 0xc2, /* ff80-ff87 */
0xac, 0x5c, 0xf1, 0xf1, 0x2a, 0xba, 0x5c, 0xd5, /* ff88-ff8f */
0x11, 0x00, 0x5c, 0xcd, 0xb3, 0x5c, 0xd1, 0xcd, /* ff90-ff97 */
0xb3, 0x5c, 0xd2, 0xa5, 0x5c, 0x04, 0x04, 0x78, /* ff98-ff9f */
0xfe, 0x20, 0xda, 0x29, 0x5c, 0x06, 0x01, 0xca, /* ffa0-ffa7 */
0x29, 0x5c, 0xdb, 0x08, 0xe6, 0x02, 0xc2, 0x97, /* ffa8-ffaf */
0x5c, 0x3e, 0x01, 0xd3, 0x09, 0xc3, 0x27, 0x5c, /* ffb0-ffb7 */
0x3e, 0x80, 0xd3, 0x08, 0xc3, 0x00, 0x00, 0xd1, /* ffb8-ffbf */
0xf1, 0x3d, 0xc2, 0x2b, 0x5c, 0x76, 0x7a, 0xbc, /* ffc0-ffc7 */
0xc0, 0x7b, 0xbd, 0xc9, 0x00, 0x00, 0x00, 0x00, /* ffc8-ffcf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffd0-ffd7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffd8-ffdf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffe0-ffe7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffe8-ffef */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* fff0-fff7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* fff8-ffff */
};
/* CPU data structures
cpu_dev CPU device descriptor
cpu_unit CPU unit descriptor
cpu_reg CPU register list
cpu_mod CPU modifiers list
*/
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) };
int32 AF_S;
int32 BC_S;
int32 DE_S;
int32 HL_S;
int32 IX_S;
int32 IY_S;
int32 SP_S;
int32 AF1_S;
int32 BC1_S;
int32 DE1_S;
int32 HL1_S;
int32 IFF_S;
int32 INT_S;
REG cpu_reg[] = {
{ HRDATA (PC, saved_PC, 16) },
{ HRDATA (AF, AF_S, 16) },
{ HRDATA (BC, BC_S, 16) },
{ HRDATA (DE, DE_S, 16) },
{ HRDATA (HL, HL_S, 16) },
{ HRDATA (IX, IX_S, 16) },
{ HRDATA (IY, IY_S, 16) },
{ HRDATA (SP, SP_S, 16) },
{ HRDATA (AF1, AF1_S, 16) },
{ HRDATA (BC1, BC1_S, 16) },
{ HRDATA (DE1, DE1_S, 16) },
{ HRDATA (HL1, HL1_S, 16) },
{ FLDATA (IFF, IFF_S, 8) },
{ FLDATA (INT, INT_S, 8) },
{ FLDATA (Z80, cpu_unit.flags, UNIT_V_CHIP), REG_HRO },
{ FLDATA (OPSTOP, cpu_unit.flags, UNIT_V_OPSTOP), REG_HRO },
{ HRDATA (SR, SR, 8) },
{ HRDATA (WRU, sim_int_char, 8) },
{ DRDATA (MARK, markTimeSP, 3), REG_RO },
{ NULL } };
MTAB cpu_mod[] = {
{ UNIT_CHIP, UNIT_CHIP, "Z80", "Z80", NULL },
{ UNIT_CHIP, 0, "8080", "8080", NULL },
{ UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL },
{ UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL },
{ UNIT_MSIZE, 4*KB, NULL, "4K", &cpu_set_size },
{ UNIT_MSIZE, 8*KB, NULL, "8K", &cpu_set_size },
{ UNIT_MSIZE, 12*KB, NULL, "12K", &cpu_set_size },
{ UNIT_MSIZE, 16*KB, NULL, "16K", &cpu_set_size },
{ UNIT_MSIZE, 20*KB, NULL, "20K", &cpu_set_size },
{ UNIT_MSIZE, 24*KB, NULL, "24K", &cpu_set_size },
{ UNIT_MSIZE, 28*KB, NULL, "28K", &cpu_set_size },
{ UNIT_MSIZE, 32*KB, NULL, "32K", &cpu_set_size },
{ UNIT_MSIZE, 48*KB, NULL, "48K", &cpu_set_size },
{ UNIT_MSIZE, 64*KB, NULL, "64K", &cpu_set_size },
{ 0 } };
DEVICE cpu_dev = {
"CPU", &cpu_unit, cpu_reg, cpu_mod,
1, 16, 16, 1, 16, 8,
&cpu_ex, &cpu_dep, &cpu_reset,
NULL, NULL, NULL };
void out(uint32 Port, uint8 Value) {
dev_table[Port].routine(1, Value);
}
int in(uint32 Port) {
return Port == 0xFF ? SR & 0xFF : dev_table[Port].routine(0, 0);
}
inline uint8 GetBYTE(register uint16 a) {
return a < MEMSIZE ? M[a] : 0xff;
}
#define RAM_mm(a) GetBYTE(a--)
#define RAM_pp(a) GetBYTE(a++)
inline void PutBYTE(register uint16 Addr, register uint8 Value) {
if ((Addr < MEMSIZE) && (Addr < bootrom_origin)) {
M[Addr] = Value;
}
/*
else {
printf("R/O M[%x]:=%x\n", Addr, Value);
}
*/
}
#define PutBYTE_pp(a,v) PutBYTE(a++, v)
#define PutBYTE_mm(a,v) PutBYTE(a--, v)
#define mm_PutBYTE(a,v) PutBYTE(--a, v)
inline uint16 GetWORD(register uint16 a) {return (GetBYTE(a) | (GetBYTE((a)+1) << 8));}
inline void PutWORD(register uint16 a, register uint16 v) {
PutBYTE(a, (uint8)(v));
PutBYTE(a+1, v>>8);
}
#define PUSH(x) do { \
mm_PutBYTE(SP, (x) >> 8); \
mm_PutBYTE(SP, x); \
} while (0)
int32 sim_instr (void) {
extern int32 sim_interval;
int32 reason = 0;
register uint32 AF;
register uint32 BC;
register uint32 DE;
register uint32 HL;
register uint32 PC;
register uint32 SP;
register uint32 IX;
register uint32 IY;
register uint32 temp, acu, sum, cbits;
register uint32 op, adr;
int32 BadZ80OpOccured = 0;
int32 Bad8080OpOccured = 0;
pc = saved_PC & ADDRMASK; /* load local PC */
af[af_sel] = AF_S;
regs[regs_sel].bc = BC_S;
regs[regs_sel].de = DE_S;
regs[regs_sel].hl = HL_S;
ix = IX_S;
iy = IY_S;
sp = SP_S;
af[1-af_sel] = AF1_S;
regs[1-regs_sel].bc = BC1_S;
regs[1-regs_sel].de = DE1_S;
regs[1-regs_sel].hl = HL1_S;
IFF = IFF_S;
ir = INT_S;
AF = af[af_sel];
BC = regs[regs_sel].bc;
DE = regs[regs_sel].de;
HL = regs[regs_sel].hl;
PC = pc;
SP = sp;
IX = ix;
IY = iy;
/* Main instruction fetch/decode loop */
while (reason == 0) { /* loop until halted */
if (sim_interval <= 0) { /* check clock queue */
if (reason = sim_process_event ()) {
break;
}
}
if (sim_brk_summ &&
sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
reason = STOP_IBKPT; /* stop simulation */
break;
}
PCX = PC;
sim_interval--;
switch(RAM_pp(PC)) {
case 0x00: /* NOP */
break;
case 0x01: /* LD BC,nnnn */
BC = GetWORD(PC);
PC += 2;
break;
case 0x02: /* LD (BC),A */
PutBYTE(BC, hreg(AF));
break;
case 0x03: /* INC BC */
++BC;
break;
case 0x04: /* INC B */
BC += 0x100;
temp = hreg(BC);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
SetPV2(0x80);
break;
case 0x05: /* DEC B */
BC -= 0x100;
temp = hreg(BC);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
SetPV2(0x7f) | 2;
break;
case 0x06: /* LD B,nn */
Sethreg(BC, RAM_pp(PC));
break;
case 0x07: /* RLCA */
AF = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) |
(AF & 0xc4) | ((AF >> 15) & 1);
break;
case 0x08: /* EX AF,AF' */
checkCPU
af[af_sel] = AF;
af_sel = 1 - af_sel;
AF = af[af_sel];
break;
case 0x09: /* ADD HL,BC */
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) */
Sethreg(AF, GetBYTE(BC));
break;
case 0x0B: /* DEC BC */
--BC;
break;
case 0x0C: /* INC C */
temp = lreg(BC)+1;
Setlreg(BC, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
SetPV2(0x80);
break;
case 0x0D: /* DEC C */
temp = lreg(BC)-1;
Setlreg(BC, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
SetPV2(0x7f) | 2;
break;
case 0x0E: /* LD C,nn */
Setlreg(BC, RAM_pp(PC));
break;
case 0x0F: /* RRCA */
temp = hreg(AF);
sum = temp >> 1;
AF = ((temp & 1) << 15) | (sum << 8) |
(sum & 0x28) | (AF & 0xc4) | (temp & 1);
break;
case 0x10: /* DJNZ dd */
checkCPU
PC += ((BC -= 0x100) & 0xff00) ? (signed char) GetBYTE(PC) + 1 : 1;
break;
case 0x11: /* LD DE,nnnn */
DE = GetWORD(PC);
PC += 2;
break;
case 0x12: /* LD (DE),A */
PutBYTE(DE, hreg(AF));
break;
case 0x13: /* INC DE */
++DE;
break;
case 0x14: /* INC D */
DE += 0x100;
temp = hreg(DE);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
SetPV2(0x80);
break;
case 0x15: /* DEC D */
DE -= 0x100;
temp = hreg(DE);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
SetPV2(0x7f) | 2;
break;
case 0x16: /* LD D,nn */
Sethreg(DE, RAM_pp(PC));
break;
case 0x17: /* RLA */
AF = ((AF << 8) & 0x0100) | ((AF >> 7) & 0x28) | ((AF << 1) & ~0x01ff) |
(AF & 0xc4) | ((AF >> 15) & 1);
break;
case 0x18: /* JR dd */
checkCPU
PC += (1) ? (signed char) GetBYTE(PC) + 1 : 1;
break;
case 0x19: /* ADD HL,DE */
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) */
Sethreg(AF, GetBYTE(DE));
break;
case 0x1B: /* DEC DE */
--DE;
break;
case 0x1C: /* INC E */
temp = lreg(DE)+1;
Setlreg(DE, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
SetPV2(0x80);
break;
case 0x1D: /* DEC E */
temp = lreg(DE)-1;
Setlreg(DE, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
SetPV2(0x7f) | 2;
break;
case 0x1E: /* LD E,nn */
Setlreg(DE, RAM_pp(PC));
break;
case 0x1F: /* RRA */
temp = hreg(AF);
sum = temp >> 1;
AF = ((AF & 1) << 15) | (sum << 8) |
(sum & 0x28) | (AF & 0xc4) | (temp & 1);
break;
case 0x20: /* JR NZ,dd */
checkCPU
PC += (!TSTFLAG(Z)) ? (signed char) GetBYTE(PC) + 1 : 1;
break;
case 0x21: /* LD HL,nnnn */
HL = GetWORD(PC);
PC += 2;
break;
case 0x22: /* LD (nnnn),HL */
temp = GetWORD(PC);
PutWORD(temp, HL);
PC += 2;
break;
case 0x23: /* INC HL */
++HL;
break;
case 0x24: /* INC H */
HL += 0x100;
temp = hreg(HL);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
SetPV2(0x80);
break;
case 0x25: /* DEC H */
HL -= 0x100;
temp = hreg(HL);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
SetPV2(0x7f) | 2;
break;
case 0x26: /* LD H,nn */
Sethreg(HL, RAM_pp(PC));
break;
case 0x27: /* DAA */
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 */
checkCPU
PC += (TSTFLAG(Z)) ? (signed char) GetBYTE(PC) + 1 : 1;
break;
case 0x29: /* ADD HL,HL */
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) */
temp = GetWORD(PC);
HL = GetWORD(temp);
PC += 2;
break;
case 0x2B: /* DEC HL */
--HL;
break;
case 0x2C: /* INC L */
temp = lreg(HL)+1;
Setlreg(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
SetPV2(0x80);
break;
case 0x2D: /* DEC L */
temp = lreg(HL)-1;
Setlreg(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
SetPV2(0x7f) | 2;
break;
case 0x2E: /* LD L,nn */
Setlreg(HL, RAM_pp(PC));
break;
case 0x2F: /* CPL */
AF = (~AF & ~0xff) | (AF & 0xc5) | ((~AF >> 8) & 0x28) | 0x12;
break;
case 0x30: /* JR NC,dd */
checkCPU
PC += (!TSTFLAG(C)) ? (signed char) GetBYTE(PC) + 1 : 1;
break;
case 0x31: /* LD SP,nnnn */
SP = GetWORD(PC);
PC += 2;
break;
case 0x32: /* LD (nnnn),A */
temp = GetWORD(PC);
PutBYTE(temp, hreg(AF));
PC += 2;
break;
case 0x33: /* INC SP */
++SP;
break;
case 0x34: /* INC (HL) */
temp = GetBYTE(HL)+1;
PutBYTE(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
SetPV2(0x80);
break;
case 0x35: /* DEC (HL) */
temp = GetBYTE(HL)-1;
PutBYTE(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
SetPV2(0x7f) | 2;
break;
case 0x36: /* LD (HL),nn */
PutBYTE(HL, RAM_pp(PC));
break;
case 0x37: /* SCF */
AF = (AF&~0x3b)|((AF>>8)&0x28)|1;
break;
case 0x38: /* JR C,dd */
checkCPU
PC += (TSTFLAG(C)) ? (signed char) GetBYTE(PC) + 1 : 1;
break;
case 0x39: /* ADD HL,SP */
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) */
temp = GetWORD(PC);
Sethreg(AF, GetBYTE(temp));
PC += 2;
break;
case 0x3B: /* DEC SP */
--SP;
break;
case 0x3C: /* INC A */
AF += 0x100;
temp = hreg(AF);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) |
SetPV2(0x80);
break;
case 0x3D: /* DEC A */
AF -= 0x100;
temp = hreg(AF);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) |
SetPV2(0x7f) | 2;
break;
case 0x3E: /* LD A,nn */
Sethreg(AF, RAM_pp(PC));
break;
case 0x3F: /* CCF */
AF = (AF&~0x3b)|((AF>>8)&0x28)|((AF&1)<<4)|(~AF&1);
break;
case 0x40: /* LD B,B */
/* nop */
break;
case 0x41: /* LD B,C */
BC = (BC & 255) | ((BC & 255) << 8);
break;
case 0x42: /* LD B,D */
BC = (BC & 255) | (DE & ~255);
break;
case 0x43: /* LD B,E */
BC = (BC & 255) | ((DE & 255) << 8);
break;
case 0x44: /* LD B,H */
BC = (BC & 255) | (HL & ~255);
break;
case 0x45: /* LD B,L */
BC = (BC & 255) | ((HL & 255) << 8);
break;
case 0x46: /* LD B,(HL) */
Sethreg(BC, GetBYTE(HL));
break;
case 0x47: /* LD B,A */
BC = (BC & 255) | (AF & ~255);
break;
case 0x48: /* LD C,B */
BC = (BC & ~255) | ((BC >> 8) & 255);
break;
case 0x49: /* LD C,C */
/* nop */
break;
case 0x4A: /* LD C,D */
BC = (BC & ~255) | ((DE >> 8) & 255);
break;
case 0x4B: /* LD C,E */
BC = (BC & ~255) | (DE & 255);
break;
case 0x4C: /* LD C,H */
BC = (BC & ~255) | ((HL >> 8) & 255);
break;
case 0x4D: /* LD C,L */
BC = (BC & ~255) | (HL & 255);
break;
case 0x4E: /* LD C,(HL) */
Setlreg(BC, GetBYTE(HL));
break;
case 0x4F: /* LD C,A */
BC = (BC & ~255) | ((AF >> 8) & 255);
break;
case 0x50: /* LD D,B */
DE = (DE & 255) | (BC & ~255);
break;
case 0x51: /* LD D,C */
DE = (DE & 255) | ((BC & 255) << 8);
break;
case 0x52: /* LD D,D */
/* nop */
break;
case 0x53: /* LD D,E */
DE = (DE & 255) | ((DE & 255) << 8);
break;
case 0x54: /* LD D,H */
DE = (DE & 255) | (HL & ~255);
break;
case 0x55: /* LD D,L */
DE = (DE & 255) | ((HL & 255) << 8);
break;
case 0x56: /* LD D,(HL) */
Sethreg(DE, GetBYTE(HL));
break;
case 0x57: /* LD D,A */
DE = (DE & 255) | (AF & ~255);
break;
case 0x58: /* LD E,B */
DE = (DE & ~255) | ((BC >> 8) & 255);
break;
case 0x59: /* LD E,C */
DE = (DE & ~255) | (BC & 255);
break;
case 0x5A: /* LD E,D */
DE = (DE & ~255) | ((DE >> 8) & 255);
break;
case 0x5B: /* LD E,E */
/* nop */
break;
case 0x5C: /* LD E,H */
DE = (DE & ~255) | ((HL >> 8) & 255);
break;
case 0x5D: /* LD E,L */
DE = (DE & ~255) | (HL & 255);
break;
case 0x5E: /* LD E,(HL) */
Setlreg(DE, GetBYTE(HL));
break;
case 0x5F: /* LD E,A */
DE = (DE & ~255) | ((AF >> 8) & 255);
break;
case 0x60: /* LD H,B */
HL = (HL & 255) | (BC & ~255);
break;
case 0x61: /* LD H,C */
HL = (HL & 255) | ((BC & 255) << 8);
break;
case 0x62: /* LD H,D */
HL = (HL & 255) | (DE & ~255);
break;
case 0x63: /* LD H,E */
HL = (HL & 255) | ((DE & 255) << 8);
break;
case 0x64: /* LD H,H */
/* nop */
break;
case 0x65: /* LD H,L */
HL = (HL & 255) | ((HL & 255) << 8);
break;
case 0x66: /* LD H,(HL) */
Sethreg(HL, GetBYTE(HL));
break;
case 0x67: /* LD H,A */
HL = (HL & 255) | (AF & ~255);
break;
case 0x68: /* LD L,B */
HL = (HL & ~255) | ((BC >> 8) & 255);
break;
case 0x69: /* LD L,C */
HL = (HL & ~255) | (BC & 255);
break;
case 0x6A: /* LD L,D */
HL = (HL & ~255) | ((DE >> 8) & 255);
break;
case 0x6B: /* LD L,E */
HL = (HL & ~255) | (DE & 255);
break;
case 0x6C: /* LD L,H */
HL = (HL & ~255) | ((HL >> 8) & 255);
break;
case 0x6D: /* LD L,L */
/* nop */
break;
case 0x6E: /* LD L,(HL) */
Setlreg(HL, GetBYTE(HL));
break;
case 0x6F: /* LD L,A */
HL = (HL & ~255) | ((AF >> 8) & 255);
break;
case 0x70: /* LD (HL),B */
PutBYTE(HL, hreg(BC));
break;
case 0x71: /* LD (HL),C */
PutBYTE(HL, lreg(BC));
break;
case 0x72: /* LD (HL),D */
PutBYTE(HL, hreg(DE));
break;
case 0x73: /* LD (HL),E */
PutBYTE(HL, lreg(DE));
break;
case 0x74: /* LD (HL),H */
PutBYTE(HL, hreg(HL));
break;
case 0x75: /* LD (HL),L */
PutBYTE(HL, lreg(HL));
break;
case 0x76: /* HALT */
reason = STOP_HALT;
PC--;
continue;
case 0x77: /* LD (HL),A */
PutBYTE(HL, hreg(AF));
break;
case 0x78: /* LD A,B */
AF = (AF & 255) | (BC & ~255);
break;
case 0x79: /* LD A,C */
AF = (AF & 255) | ((BC & 255) << 8);
break;
case 0x7A: /* LD A,D */
AF = (AF & 255) | (DE & ~255);
break;
case 0x7B: /* LD A,E */
AF = (AF & 255) | ((DE & 255) << 8);
break;
case 0x7C: /* LD A,H */
AF = (AF & 255) | (HL & ~255);
break;
case 0x7D: /* LD A,L */
AF = (AF & 255) | ((HL & 255) << 8);
break;
case 0x7E: /* LD A,(HL) */
Sethreg(AF, GetBYTE(HL));
break;
case 0x7F: /* LD A,A */
/* nop */
break;
case 0x80: /* ADD A,B */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x81: /* ADD A,C */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x82: /* ADD A,D */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x83: /* ADD A,E */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x84: /* ADD A,H */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x85: /* ADD A,L */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x86: /* ADD A,(HL) */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x87: /* ADD A,A */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x88: /* ADC A,B */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x89: /* ADC A,C */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x8A: /* ADC A,D */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x8B: /* ADC A,E */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x8C: /* ADC A,H */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x8D: /* ADC A,L */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x8E: /* ADC A,(HL) */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x8F: /* ADC A,A */
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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0x90: /* SUB B */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x91: /* SUB C */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x92: /* SUB D */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x93: /* SUB E */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x94: /* SUB H */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x95: /* SUB L */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x96: /* SUB (HL) */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x97: /* SUB A */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x98: /* SBC A,B */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x99: /* SBC A,C */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x9A: /* SBC A,D */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x9B: /* SBC A,E */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x9C: /* SBC A,H */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x9D: /* SBC A,L */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x9E: /* SBC A,(HL) */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0x9F: /* SBC A,A */
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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0xA0: /* AND B */
sum = ((AF & (BC)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xA1: /* AND C */
sum = ((AF >> 8) & BC) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xA2: /* AND D */
sum = ((AF & (DE)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xA3: /* AND E */
sum = ((AF >> 8) & DE) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xA4: /* AND H */
sum = ((AF & (HL)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xA5: /* AND L */
sum = ((AF >> 8) & HL) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xA6: /* AND (HL) */
sum = ((AF >> 8) & GetBYTE(HL)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xA7: /* AND A */
sum = ((AF & (AF)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xA8: /* XOR B */
sum = ((AF ^ (BC)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xA9: /* XOR C */
sum = ((AF >> 8) ^ BC) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAA: /* XOR D */
sum = ((AF ^ (DE)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAB: /* XOR E */
sum = ((AF >> 8) ^ DE) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAC: /* XOR H */
sum = ((AF ^ (HL)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAD: /* XOR L */
sum = ((AF >> 8) ^ HL) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAE: /* XOR (HL) */
sum = ((AF >> 8) ^ GetBYTE(HL)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAF: /* XOR A */
sum = ((AF ^ (AF)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB0: /* OR B */
sum = ((AF | (BC)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB1: /* OR C */
sum = ((AF >> 8) | BC) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB2: /* OR D */
sum = ((AF | (DE)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB3: /* OR E */
sum = ((AF >> 8) | DE) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB4: /* OR H */
sum = ((AF | (HL)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB5: /* OR L */
sum = ((AF >> 8) | HL) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB6: /* OR (HL) */
sum = ((AF >> 8) | GetBYTE(HL)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB7: /* OR A */
sum = ((AF | (AF)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB8: /* CP B */
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) |
(SetPV) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xB9: /* CP C */
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) |
(SetPV) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBA: /* CP D */
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) |
(SetPV) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBB: /* CP E */
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) |
(SetPV) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBC: /* CP H */
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) |
(SetPV) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBD: /* CP L */
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) |
(SetPV) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBE: /* CP (HL) */
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) |
(SetPV) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xBF: /* CP A */
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) |
(SetPV) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xC0: /* RET NZ */
if (!TSTFLAG(Z)) POP(PC);
break;
case 0xC1: /* POP BC */
POP(BC);
break;
case 0xC2: /* JP NZ,nnnn */
JPC(!TSTFLAG(Z));
break;
case 0xC3: /* JP nnnn */
JPC(1);
break;
case 0xC4: /* CALL NZ,nnnn */
CALLC(!TSTFLAG(Z));
break;
case 0xC5: /* PUSH BC */
PUSH(BC);
break;
case 0xC6: /* ADD A,nn */
temp = RAM_pp(PC);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0xC7: /* RST 0 */
PUSH(PC); PC = 0;
break;
case 0xC8: /* RET Z */
if (TSTFLAG(Z)) POP(PC);
break;
case 0xC9: /* RET */
POP(PC);
break;
case 0xCA: /* JP Z,nnnn */
JPC(TSTFLAG(Z));
break;
case 0xCB: /* CB prefix */
checkCPU
adr = HL;
switch ((op = GetBYTE(PC)) & 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 */
CALLC(TSTFLAG(Z));
break;
case 0xCD: /* CALL nnnn */
CALLC(1);
break;
case 0xCE: /* ADC A,nn */
temp = RAM_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) |
(SetPV) |
((cbits >> 8) & 1);
break;
case 0xCF: /* RST 8 */
PUSH(PC); PC = 8;
break;
case 0xD0: /* RET NC */
if (!TSTFLAG(C)) POP(PC);
break;
case 0xD1: /* POP DE */
POP(DE);
break;
case 0xD2: /* JP NC,nnnn */
JPC(!TSTFLAG(C));
break;
case 0xD3: /* OUT (nn),A */
out(RAM_pp(PC), hreg(AF));
break;
case 0xD4: /* CALL NC,nnnn */
CALLC(!TSTFLAG(C));
break;
case 0xD5: /* PUSH DE */
PUSH(DE);
break;
case 0xD6: /* SUB nn */
temp = RAM_pp(PC);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = ((sum & 0xff) << 8) | (sum & 0xa8) |
(((sum & 0xff) == 0) << 6) | (cbits & 0x10) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0xD7: /* RST 10H */
PUSH(PC); PC = 0x10;
break;
case 0xD8: /* RET C */
if (TSTFLAG(C)) POP(PC);
break;
case 0xD9: /* EXX */
checkCPU
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 */
JPC(TSTFLAG(C));
break;
case 0xDB: /* IN A,(nn) */
Sethreg(AF, in(RAM_pp(PC)));
break;
case 0xDC: /* CALL C,nnnn */
CALLC(TSTFLAG(C));
break;
case 0xDD: /* DD prefix */
checkCPU
switch (op = RAM_pp(PC)) {
case 0x09: /* ADD IX,BC */
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 */
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 */
IX = GetWORD(PC);
PC += 2;
break;
case 0x22: /* LD (nnnn),IX */
temp = GetWORD(PC);
PutWORD(temp, IX);
PC += 2;
break;
case 0x23: /* INC IX */
++IX;
break;
case 0x24: /* INC IXH */
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 */
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 */
Sethreg(IX, RAM_pp(PC));
break;
case 0x29: /* ADD IX,IX */
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) */
temp = GetWORD(PC);
IX = GetWORD(temp);
PC += 2;
break;
case 0x2B: /* DEC IX */
--IX;
break;
case 0x2C: /* INC IXL */
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 */
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 */
Setlreg(IX, RAM_pp(PC));
break;
case 0x34: /* INC (IX+dd) */
adr = IX + (signed char) RAM_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) */
adr = IX + (signed char) RAM_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 */
adr = IX + (signed char) RAM_pp(PC);
PutBYTE(adr, RAM_pp(PC));
break;
case 0x39: /* ADD IX,SP */
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 */
Sethreg(BC, hreg(IX));
break;
case 0x45: /* LD B,IXL */
Sethreg(BC, lreg(IX));
break;
case 0x46: /* LD B,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
Sethreg(BC, GetBYTE(adr));
break;
case 0x4C: /* LD C,IXH */
Setlreg(BC, hreg(IX));
break;
case 0x4D: /* LD C,IXL */
Setlreg(BC, lreg(IX));
break;
case 0x4E: /* LD C,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
Setlreg(BC, GetBYTE(adr));
break;
case 0x54: /* LD D,IXH */
Sethreg(DE, hreg(IX));
break;
case 0x55: /* LD D,IXL */
Sethreg(DE, lreg(IX));
break;
case 0x56: /* LD D,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
Sethreg(DE, GetBYTE(adr));
break;
case 0x5C: /* LD E,H */
Setlreg(DE, hreg(IX));
break;
case 0x5D: /* LD E,L */
Setlreg(DE, lreg(IX));
break;
case 0x5E: /* LD E,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
Setlreg(DE, GetBYTE(adr));
break;
case 0x60: /* LD IXH,B */
Sethreg(IX, hreg(BC));
break;
case 0x61: /* LD IXH,C */
Sethreg(IX, lreg(BC));
break;
case 0x62: /* LD IXH,D */
Sethreg(IX, hreg(DE));
break;
case 0x63: /* LD IXH,E */
Sethreg(IX, lreg(DE));
break;
case 0x64: /* LD IXH,IXH */
/* nop */
break;
case 0x65: /* LD IXH,IXL */
Sethreg(IX, lreg(IX));
break;
case 0x66: /* LD H,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
Sethreg(HL, GetBYTE(adr));
break;
case 0x67: /* LD IXH,A */
Sethreg(IX, hreg(AF));
break;
case 0x68: /* LD IXL,B */
Setlreg(IX, hreg(BC));
break;
case 0x69: /* LD IXL,C */
Setlreg(IX, lreg(BC));
break;
case 0x6A: /* LD IXL,D */
Setlreg(IX, hreg(DE));
break;
case 0x6B: /* LD IXL,E */
Setlreg(IX, lreg(DE));
break;
case 0x6C: /* LD IXL,IXH */
Setlreg(IX, hreg(IX));
break;
case 0x6D: /* LD IXL,IXL */
/* nop */
break;
case 0x6E: /* LD L,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
Setlreg(HL, GetBYTE(adr));
break;
case 0x6F: /* LD IXL,A */
Setlreg(IX, hreg(AF));
break;
case 0x70: /* LD (IX+dd),B */
adr = IX + (signed char) RAM_pp(PC);
PutBYTE(adr, hreg(BC));
break;
case 0x71: /* LD (IX+dd),C */
adr = IX + (signed char) RAM_pp(PC);
PutBYTE(adr, lreg(BC));
break;
case 0x72: /* LD (IX+dd),D */
adr = IX + (signed char) RAM_pp(PC);
PutBYTE(adr, hreg(DE));
break;
case 0x73: /* LD (IX+dd),E */
adr = IX + (signed char) RAM_pp(PC);
PutBYTE(adr, lreg(DE));
break;
case 0x74: /* LD (IX+dd),H */
adr = IX + (signed char) RAM_pp(PC);
PutBYTE(adr, hreg(HL));
break;
case 0x75: /* LD (IX+dd),L */
adr = IX + (signed char) RAM_pp(PC);
PutBYTE(adr, lreg(HL));
break;
case 0x77: /* LD (IX+dd),A */
adr = IX + (signed char) RAM_pp(PC);
PutBYTE(adr, hreg(AF));
break;
case 0x7C: /* LD A,IXH */
Sethreg(AF, hreg(IX));
break;
case 0x7D: /* LD A,IXL */
Sethreg(AF, lreg(IX));
break;
case 0x7E: /* LD A,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
Sethreg(AF, GetBYTE(adr));
break;
case 0x84: /* ADD A,IXH */
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 */
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) */
adr = IX + (signed char) RAM_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 */
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 */
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) */
adr = IX + (signed char) RAM_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 */
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 */
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) */
adr = IX + (signed char) RAM_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 */
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 */
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) */
adr = IX + (signed char) RAM_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 */
sum = ((AF & (IX)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xA5: /* AND IXL */
sum = ((AF >> 8) & IX) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xA6: /* AND (IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
sum = ((AF >> 8) & GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xAC: /* XOR IXH */
sum = ((AF ^ (IX)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAD: /* XOR IXL */
sum = ((AF >> 8) ^ IX) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAE: /* XOR (IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
sum = ((AF >> 8) ^ GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB4: /* OR IXH */
sum = ((AF | (IX)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB5: /* OR IXL */
sum = ((AF >> 8) | IX) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB6: /* OR (IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
sum = ((AF >> 8) | GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xBC: /* CP IXH */
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 */
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) */
adr = IX + (signed char) RAM_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) RAM_pp(PC);
adr = adr;
switch ((op = GetBYTE(PC)) & 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 */
POP(IX);
break;
case 0xE3: /* EX (SP),IX */
temp = IX; POP(IX); PUSH(temp);
break;
case 0xE5: /* PUSH IX */
PUSH(IX);
break;
case 0xE9: /* JP (IX) */
PC = IX;
break;
case 0xF9: /* LD SP,IX */
SP = IX;
break;
default: /* ignore DD */
BadZ80OpOccured = 1;
PC--;
}
break;
case 0xDE: /* SBC A,nn */
temp = RAM_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) |
(SetPV) | 2 |
((cbits >> 8) & 1);
break;
case 0xDF: /* RST 18H */
PUSH(PC); PC = 0x18;
break;
case 0xE0: /* RET PO */
if (!TSTFLAG(P)) POP(PC);
break;
case 0xE1: /* POP HL */
POP(HL);
break;
case 0xE2: /* JP PO,nnnn */
JPC(!TSTFLAG(P));
break;
case 0xE3: /* EX (SP),HL */
temp = HL; POP(HL); PUSH(temp);
break;
case 0xE4: /* CALL PO,nnnn */
CALLC(!TSTFLAG(P));
break;
case 0xE5: /* PUSH HL */
PUSH(HL);
break;
case 0xE6: /* AND nn */
sum = ((AF >> 8) & RAM_pp(PC)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xE7: /* RST 20H */
PUSH(PC); PC = 0x20;
break;
case 0xE8: /* RET PE */
if (TSTFLAG(P)) POP(PC);
break;
case 0xE9: /* JP (HL) */
PC = HL;
break;
case 0xEA: /* JP PE,nnnn */
JPC(TSTFLAG(P));
break;
case 0xEB: /* EX DE,HL */
temp = HL; HL = DE; DE = temp;
break;
case 0xEC: /* CALL PE,nnnn */
CALLC(TSTFLAG(P));
break;
case 0xED: /* ED prefix */
checkCPU
switch (op = RAM_pp(PC)) {
case 0x40: /* IN B,(C) */
temp = in(lreg(BC));
Sethreg(BC, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x41: /* OUT (C),B */
out(lreg(BC), hreg(BC));
break;
case 0x42: /* SBC HL,BC */
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 */
temp = GetWORD(PC);
PutWORD(temp, BC);
PC += 2;
break;
case 0x44: /* NEG */
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 */
IFF |= IFF >> 1;
POP(PC);
break;
case 0x46: /* IM 0 */
/* interrupt mode 0 */
break;
case 0x47: /* LD I,A */
ir = (ir & 255) | (AF & ~255);
break;
case 0x48: /* IN C,(C) */
temp = in(lreg(BC));
Setlreg(BC, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x49: /* OUT (C),C */
out(lreg(BC), lreg(BC));
break;
case 0x4A: /* ADC HL,BC */
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) */
temp = GetWORD(PC);
BC = GetWORD(temp);
PC += 2;
break;
case 0x4D: /* RETI */
IFF |= IFF >> 1;
POP(PC);
break;
case 0x4F: /* LD R,A */
ir = (ir & ~255) | ((AF >> 8) & 255);
break;
case 0x50: /* IN D,(C) */
temp = in(lreg(BC));
Sethreg(DE, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x51: /* OUT (C),D */
out(lreg(BC), hreg(DE));
break;
case 0x52: /* SBC HL,DE */
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 */
temp = GetWORD(PC);
PutWORD(temp, DE);
PC += 2;
break;
case 0x56: /* IM 1 */
/* interrupt mode 1 */
break;
case 0x57: /* LD A,I */
AF = (AF & 0x29) | (ir & ~255) | ((ir >> 8) & 0x80) | (((ir & ~255) == 0) << 6) | ((IFF & 2) << 1);
break;
case 0x58: /* IN E,(C) */
temp = in(lreg(BC));
Setlreg(DE, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x59: /* OUT (C),E */
out(lreg(BC), lreg(DE));
break;
case 0x5A: /* ADC HL,DE */
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) */
temp = GetWORD(PC);
DE = GetWORD(temp);
PC += 2;
break;
case 0x5E: /* IM 2 */
/* interrupt mode 2 */
break;
case 0x5F: /* LD A,R */
AF = (AF & 0x29) | ((ir & 255) << 8) | (ir & 0x80) | (((ir & 255) == 0) << 6) | ((IFF & 2) << 1);
break;
case 0x60: /* IN H,(C) */
temp = in(lreg(BC));
Sethreg(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x61: /* OUT (C),H */
out(lreg(BC), hreg(HL));
break;
case 0x62: /* SBC HL,HL */
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 */
temp = GetWORD(PC);
PutWORD(temp, HL);
PC += 2;
break;
case 0x67: /* RRD */
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) */
temp = in(lreg(BC));
Setlreg(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x69: /* OUT (C),L */
out(lreg(BC), lreg(HL));
break;
case 0x6A: /* ADC HL,HL */
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) */
temp = GetWORD(PC);
HL = GetWORD(temp);
PC += 2;
break;
case 0x6F: /* RLD */
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) */
temp = in(lreg(BC));
Setlreg(temp, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x71: /* OUT (C),0 */
out(lreg(BC), 0);
break;
case 0x72: /* SBC HL,SP */
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 */
temp = GetWORD(PC);
PutWORD(temp, SP);
PC += 2;
break;
case 0x78: /* IN A,(C) */
temp = in(lreg(BC));
Sethreg(AF, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x79: /* OUT (C),A */
out(lreg(BC), hreg(AF));
break;
case 0x7A: /* ADC HL,SP */
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) */
temp = GetWORD(PC);
SP = GetWORD(temp);
PC += 2;
break;
case 0xA0: /* LDI */
acu = RAM_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 */
acu = hreg(AF);
temp = RAM_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 */
PutBYTE(HL, in(lreg(BC))); ++HL;
SETFLAG(N, 1);
SETFLAG(P, (--BC & 0xffff) != 0);
break;
case 0xA3: /* OUTI */
out(lreg(BC), GetBYTE(HL)); ++HL;
SETFLAG(N, 1);
Sethreg(BC, lreg(BC) - 1);
SETFLAG(Z, lreg(BC) == 0);
break;
case 0xA8: /* LDD */
acu = RAM_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 */
acu = hreg(AF);
temp = RAM_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 */
PutBYTE(HL, in(lreg(BC))); --HL;
SETFLAG(N, 1);
Sethreg(BC, lreg(BC) - 1);
SETFLAG(Z, lreg(BC) == 0);
break;
case 0xAB: /* OUTD */
out(lreg(BC), GetBYTE(HL)); --HL;
SETFLAG(N, 1);
Sethreg(BC, lreg(BC) - 1);
SETFLAG(Z, lreg(BC) == 0);
break;
case 0xB0: /* LDIR */
acu = hreg(AF);
BC &= 0xffff;
do {
acu = RAM_pp(HL);
PutBYTE_pp(DE, acu);
} while (--BC);
acu += hreg(AF);
AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4);
break;
case 0xB1: /* CPIR */
acu = hreg(AF);
BC &= 0xffff;
do {
temp = RAM_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 */
temp = hreg(BC);
do {
PutBYTE(HL, in(lreg(BC))); ++HL;
} while (--temp);
Sethreg(BC, 0);
SETFLAG(N, 1);
SETFLAG(Z, 1);
break;
case 0xB3: /* OTIR */
temp = hreg(BC);
do {
out(lreg(BC), GetBYTE(HL)); ++HL;
} while (--temp);
Sethreg(BC, 0);
SETFLAG(N, 1);
SETFLAG(Z, 1);
break;
case 0xB8: /* LDDR */
BC &= 0xffff;
do {
acu = RAM_mm(HL);
PutBYTE_mm(DE, acu);
} while (--BC);
acu += hreg(AF);
AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4);
break;
case 0xB9: /* CPDR */
acu = hreg(AF);
BC &= 0xffff;
do {
temp = RAM_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 */
temp = hreg(BC);
do {
PutBYTE(HL, in(lreg(BC))); --HL;
} while (--temp);
Sethreg(BC, 0);
SETFLAG(N, 1);
SETFLAG(Z, 1);
break;
case 0xBB: /* OTDR */
temp = hreg(BC);
do {
out(lreg(BC), GetBYTE(HL)); --HL;
} while (--temp);
Sethreg(BC, 0);
SETFLAG(N, 1);
SETFLAG(Z, 1);
break;
default: /* ignore ED and following byte */
BadZ80OpOccured = 1;
}
break;
case 0xEE: /* XOR nn */
sum = ((AF >> 8) ^ RAM_pp(PC)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xEF: /* RST 28H */
PUSH(PC); PC = 0x28;
break;
case 0xF0: /* RET P */
if (!TSTFLAG(S)) POP(PC);
break;
case 0xF1: /* POP AF */
POP(AF);
break;
case 0xF2: /* JP P,nnnn */
JPC(!TSTFLAG(S));
break;
case 0xF3: /* DI */
IFF = 0;
break;
case 0xF4: /* CALL P,nnnn */
CALLC(!TSTFLAG(S));
break;
case 0xF5: /* PUSH AF */
PUSH(AF);
break;
case 0xF6: /* OR nn */
sum = ((AF >> 8) | RAM_pp(PC)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xF7: /* RST 30H */
PUSH(PC); PC = 0x30;
break;
case 0xF8: /* RET M */
if (TSTFLAG(S)) POP(PC);
break;
case 0xF9: /* LD SP,HL */
SP = HL;
break;
case 0xFA: /* JP M,nnnn */
JPC(TSTFLAG(S));
break;
case 0xFB: /* EI */
IFF = 3;
break;
case 0xFC: /* CALL M,nnnn */
CALLC(TSTFLAG(S));
break;
case 0xFD: /* FD prefix */
checkCPU
switch (op = RAM_pp(PC)) {
case 0x09: /* ADD IY,BC */
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 */
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 */
IY = GetWORD(PC);
PC += 2;
break;
case 0x22: /* LD (nnnn),IY */
temp = GetWORD(PC);
PutWORD(temp, IY);
PC += 2;
break;
case 0x23: /* INC IY */
++IY;
break;
case 0x24: /* INC IYH */
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 */
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 */
Sethreg(IY, RAM_pp(PC));
break;
case 0x29: /* ADD IY,IY */
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) */
temp = GetWORD(PC);
IY = GetWORD(temp);
PC += 2;
break;
case 0x2B: /* DEC IY */
--IY;
break;
case 0x2C: /* INC IYL */
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 */
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 */
Setlreg(IY, RAM_pp(PC));
break;
case 0x34: /* INC (IY+dd) */
adr = IY + (signed char) RAM_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) */
adr = IY + (signed char) RAM_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 */
adr = IY + (signed char) RAM_pp(PC);
PutBYTE(adr, RAM_pp(PC));
break;
case 0x39: /* ADD IY,SP */
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 */
Sethreg(BC, hreg(IY));
break;
case 0x45: /* LD B,IYL */
Sethreg(BC, lreg(IY));
break;
case 0x46: /* LD B,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
Sethreg(BC, GetBYTE(adr));
break;
case 0x4C: /* LD C,IYH */
Setlreg(BC, hreg(IY));
break;
case 0x4D: /* LD C,IYL */
Setlreg(BC, lreg(IY));
break;
case 0x4E: /* LD C,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
Setlreg(BC, GetBYTE(adr));
break;
case 0x54: /* LD D,IYH */
Sethreg(DE, hreg(IY));
break;
case 0x55: /* LD D,IYL */
Sethreg(DE, lreg(IY));
break;
case 0x56: /* LD D,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
Sethreg(DE, GetBYTE(adr));
break;
case 0x5C: /* LD E,H */
Setlreg(DE, hreg(IY));
break;
case 0x5D: /* LD E,L */
Setlreg(DE, lreg(IY));
break;
case 0x5E: /* LD E,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
Setlreg(DE, GetBYTE(adr));
break;
case 0x60: /* LD IYH,B */
Sethreg(IY, hreg(BC));
break;
case 0x61: /* LD IYH,C */
Sethreg(IY, lreg(BC));
break;
case 0x62: /* LD IYH,D */
Sethreg(IY, hreg(DE));
break;
case 0x63: /* LD IYH,E */
Sethreg(IY, lreg(DE));
break;
case 0x64: /* LD IYH,IYH */
/* nop */
break;
case 0x65: /* LD IYH,IYL */
Sethreg(IY, lreg(IY));
break;
case 0x66: /* LD H,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
Sethreg(HL, GetBYTE(adr));
break;
case 0x67: /* LD IYH,A */
Sethreg(IY, hreg(AF));
break;
case 0x68: /* LD IYL,B */
Setlreg(IY, hreg(BC));
break;
case 0x69: /* LD IYL,C */
Setlreg(IY, lreg(BC));
break;
case 0x6A: /* LD IYL,D */
Setlreg(IY, hreg(DE));
break;
case 0x6B: /* LD IYL,E */
Setlreg(IY, lreg(DE));
break;
case 0x6C: /* LD IYL,IYH */
Setlreg(IY, hreg(IY));
break;
case 0x6D: /* LD IYL,IYL */
/* nop */
break;
case 0x6E: /* LD L,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
Setlreg(HL, GetBYTE(adr));
break;
case 0x6F: /* LD IYL,A */
Setlreg(IY, hreg(AF));
break;
case 0x70: /* LD (IY+dd),B */
adr = IY + (signed char) RAM_pp(PC);
PutBYTE(adr, hreg(BC));
break;
case 0x71: /* LD (IY+dd),C */
adr = IY + (signed char) RAM_pp(PC);
PutBYTE(adr, lreg(BC));
break;
case 0x72: /* LD (IY+dd),D */
adr = IY + (signed char) RAM_pp(PC);
PutBYTE(adr, hreg(DE));
break;
case 0x73: /* LD (IY+dd),E */
adr = IY + (signed char) RAM_pp(PC);
PutBYTE(adr, lreg(DE));
break;
case 0x74: /* LD (IY+dd),H */
adr = IY + (signed char) RAM_pp(PC);
PutBYTE(adr, hreg(HL));
break;
case 0x75: /* LD (IY+dd),L */
adr = IY + (signed char) RAM_pp(PC);
PutBYTE(adr, lreg(HL));
break;
case 0x77: /* LD (IY+dd),A */
adr = IY + (signed char) RAM_pp(PC);
PutBYTE(adr, hreg(AF));
break;
case 0x7C: /* LD A,IYH */
Sethreg(AF, hreg(IY));
break;
case 0x7D: /* LD A,IYL */
Sethreg(AF, lreg(IY));
break;
case 0x7E: /* LD A,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
Sethreg(AF, GetBYTE(adr));
break;
case 0x84: /* ADD A,IYH */
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 */
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) */
adr = IY + (signed char) RAM_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 */
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 */
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) */
adr = IY + (signed char) RAM_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 */
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 */
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) */
adr = IY + (signed char) RAM_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 */
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 */
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) */
adr = IY + (signed char) RAM_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 */
sum = ((AF & (IY)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xA5: /* AND IYL */
sum = ((AF >> 8) & IY) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xA6: /* AND (IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
sum = ((AF >> 8) & GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xAC: /* XOR IYH */
sum = ((AF ^ (IY)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAD: /* XOR IYL */
sum = ((AF >> 8) ^ IY) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xAE: /* XOR (IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
sum = ((AF >> 8) ^ GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB4: /* OR IYH */
sum = ((AF | (IY)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB5: /* OR IYL */
sum = ((AF >> 8) | IY) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xB6: /* OR (IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
sum = ((AF >> 8) | GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xBC: /* CP IYH */
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 */
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) */
adr = IY + (signed char) RAM_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) RAM_pp(PC);
adr = adr;
switch ((op = GetBYTE(PC)) & 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 */
POP(IY);
break;
case 0xE3: /* EX (SP),IY */
temp = IY; POP(IY); PUSH(temp);
break;
case 0xE5: /* PUSH IY */
PUSH(IY);
break;
case 0xE9: /* JP (IY) */
PC = IY;
break;
case 0xF9: /* LD SP,IY */
SP = IY;
break;
default: /* ignore FD */
BadZ80OpOccured = 1;
PC--;
}
break;
case 0xFE: /* CP nn */
temp = RAM_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) |
(SetPV) | 2 |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0xFF: /* RST 38H */
PUSH(PC); PC = 0x38;
}
if ((BadZ80OpOccured || Bad8080OpOccured) && (cpu_unit.flags & UNIT_OPSTOP)) {
reason = STOP_OPCODE;
}
}
pc = PC;
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;
/* Simulation halted */
saved_PC = (reason == STOP_OPCODE) ? PCX : pc;
AF_S = af[af_sel];
BC_S = regs[regs_sel].bc;
DE_S = regs[regs_sel].de;
HL_S = regs[regs_sel].hl;
IX_S = ix;
IY_S = iy;
SP_S = sp;
AF1_S = af[1-af_sel];
BC1_S = regs[1-regs_sel].bc;
DE1_S = regs[1-regs_sel].de;
HL1_S = regs[1-regs_sel].hl;
IFF_S = IFF;
INT_S = ir;
return reason;
}
void clear_memory(int32 starting) {
int32 i;
for (i = starting; i < MAXMEMSIZE; i++) {
M[i] = 0;
}
for (i = 0; i < bootrom_size; i++) {
M[i + bootrom_origin] = bootrom[i] & 0xFF;
}
}
/* Reset routine */
t_stat cpu_reset (DEVICE *dptr)
{
af[0] = af[1] = 0;
af_sel = 0;
regs[0].bc = regs[0].de = regs[0].hl = 0;
regs_sel = 0;
regs[1].bc = regs[1].de = regs[1].hl = 0;
ir = ix = iy = sp = pc = IFF = 0;
saved_PC = 0;
clear_memory(0);
markTimeSP = 0;
sim_brk_types = sim_brk_dflt = SWMASK ('E');
return SCPE_OK;
}
/* Memory examine */
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
{
if ((addr >= MEMSIZE) && (addr < bootrom_origin)) {
return SCPE_NXM;
}
if (vptr != NULL) {
*vptr = M[addr] & 0xff;
}
return SCPE_OK;
}
/* Memory deposit */
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
{
if ((addr >= MEMSIZE) || (addr >= bootrom_origin)) {
return SCPE_NXM;
}
M[addr] = val & 0xff;
return SCPE_OK;
}
t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc)
{
int32 mc = 0;
t_addr i;
int32 limit;
if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 0xFFF) != 0)) {
return SCPE_ARG;
}
limit = (bootrom_origin < MEMSIZE) ? bootrom_origin : MEMSIZE;
for (i = value; i < limit; i++) {
mc |= M[i];
}
if (mc && (!get_yn ("Really truncate memory [N]?", FALSE))) {
return SCPE_OK;
}
MEMSIZE = value;
clear_memory(value);
return SCPE_OK;
}