simh-testsetgenerator/AltairZ80/altairZ80_cpu.c
Bob Supnik 701f0fe028 Notes For V2.8
1. New Features

1.1 Directory and documentation

- Only common files (SCP and libraries) are in the top level
  directory.  Individual simulator files are in their individual
  directories.
- simh_doc.txt has been split up.  simh_doc.txt now documents
  only SCP.  The individual simulators are documented in separate
  text files in their own directories.
- mingw_build.bat is a batch file for the MINGW/gcc environment
  that will build all the simulators, assuming the root directory
  structure is at c:\sim.
- Makefile is a UNIX make file for the gcc environment that will
  build all the simulators, assuming the root directory is at
  c:\sim.

1.2 SCP

- DO <file name> executes the SCP commands in the specified file.
- Replicated registers in unit structures can now be declared as
  arrays for examine, modify, save, and restore.  Most replicated
  unit registers (for example, mag tape position registers) have
  been changed to arrays.
- The ADD/REMOVE commands have been replaced by SET unit ONLINE
  and SET unit OFFLINE, respectively.
- Register names that are unique within an entire simulator do
  not have to be prefaced with the device name.
- The ATTACH command can attach files read only, either under
  user option (-r), or because the attached file is ready only.
- The SET/SHOW capabilities have been extended.  New forms include:

	SET <dev> param{=value}{ param ...}
	SET <unit> param{=value}{ param ...}
	SHOW <dev> {param param ...}
	SHOW <unit> {param param ...}

- Multiple breakpoints have been implemented.  Breakpoints are
  set/cleared/displayed by:

	BREAK addr_list{[count]}
	NOBREAK addr_list
	SHOW BREAK addr_list

1.3 PDP-11 simulator

- Unibus map implemented, with 22b RP controller (URH70) or 18b
  RP controller (URH11) (in debug).
- All DMA peripherals rewritten to use map.
- Many peripherals modified for source sharing with VAX.
- RQDX3 implemented.
- Bugs fixed in RK11 and RL11 write check.

1.4 PDP-10 simulator

- ITS 1-proceed implemented.
- Bugs fixed in ITS PC sampling and LPMR

1.5 18b PDP simulator

- Interrupts split out to multiple levels to allow easier
  expansion.

1.5 IBM System 3 Simulator

- Written by Charles (Dutch) Owen.

1.6 VAX Simulator (in debug)

- Simulates MicroVAX 3800 (KA655) with 16MB-64MB memory, RQDX3,
  RLV12, TSV11, DZV11, LPV11, PCV11.
- CDROM capability has been added to the RQDX3, to allow testing
  with VMS hobbyist images.

1.7 SDS 940 Simulator (not tested)

- Simulates SDS 940, 16K-64K memory, fixed and moving head
  disk, magtape, line printer, console.

1.8 Altair Z80

- Revised from Charles (Dutch) Owen's original by Peter Schorn.
- MITS 8080 with full Z80 simulation.
- 4K and 8K BASIC packages, Prolog package.

1.9 Interdata

The I4 simulator has been withdrawn for major rework.  Look for
a complete 16b/32b Interdata simulator sometime next year.

2. Release Notes

2.1 SCP

SCP now allows replicated registers in unit structures to be
modelled as arrays.  All replicated register declarations have
been replaced by register array declarations.  As a result,
save files from prior revisions will generate errors after
restoring main memory.

2.2 PDP-11

The Unibus map code is in debug.  The map was implemented primarily
to allow source sharing with the VAX, which requires a DMA map.
DMA devices work correctly with the Unibus map disabled.

The RQDX3 simulator has run a complete RSTS/E SYSGEN, with multiple
drives, and booted the completed system from scratch.

2.3 VAX

The VAX simulator will run the boot code up to the >>> prompt.  It
can successfully process a SHOW DEVICE command.  It runs the HCORE
instruction diagnostic.  It can boot the hobbyist CD through SYSBOOT
and through the date/time dialog and restore the hobbyist CD, using
standalone backup.  On the boot of the restored disk, it gets to the
date/time dialog, and then crashes.

2.4 SDS 940

The SDS 940 is untested, awaiting real code.

2.5 GCC Optimization

At -O2 and above, GCC does not correctly compile the simulators which
use setjmp-longjmp (PDP-11, PDP-10, VAX).  A working hypothesis is
that optimized state maintained in registers is being used in the
setjmp processing routine.  On the PDP-11 and PDP-10, all of this
state has been either made global, or volatile, to encourage GCC to
keep the state up to date in memory.  The VAX is still vulnerable.

3. Work list

3.1 SCP

- Better ENABLE/DISABLE.

3.2 PDP-11 RQDX3

Software mapped mode, RCT read simulation, VMS debug.
2011-04-15 08:33:38 -07:00

3372 lines
97 KiB
C

/* 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;
}