blob: 2bae2eff6d4870a0d9b7b40c96a27c91c2a309cf [file] [log] [blame] [raw]
/* altairz80_cpu.c: MITS Altair CPU (8080 and Z80)
Copyright (c) 2002, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Peter Schorn shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Peter Schorn.
Based on work by Charles E Owen (c) 1997
Code for Z80 CPU from Frank D. Cringle ((c) 1995 under GNU license)
*/
#include <stdio.h>
#include "altairz80_defs.h"
#define PCQ_SIZE 64 /* must be 2**n */
#define PCQ_MASK (PCQ_SIZE - 1)
#define PCQ_ENTRY(PC) pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC
/* Simulator stop codes */
#define STOP_HALT 2 /* HALT */
#define STOP_IBKPT 3 /* breakpoint (program counter) */
#define STOP_MEM 4 /* breakpoint (memory access) */
#define STOP_OPCODE 5 /* unknown 8080 or Z80 instruction */
/*-------------------------------- definitions for memory space --------------------*/
uint8 M[MAXMEMSIZE][MAXBANKS]; /* 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)))
/* checkCPU8080 must be invoked whenever a Z80 only instruction is executed */
#define checkCPU8080 \
if (((cpu_unit.flags & UNIT_CHIP) == 0) && (cpu_unit.flags & UNIT_OPSTOP)) { \
reason = STOP_OPCODE; \
goto end_decode; \
}
/* checkCPUZ80 must be invoked whenever a non Z80 instruction is executed */
#define checkCPUZ80 \
if (cpu_unit.flags & UNIT_OPSTOP) { \
reason = STOP_OPCODE; \
goto end_decode; \
}
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) { \
if (cond) { \
PCQ_ENTRY(PC - 1); \
PC = GetWORD(PC); \
} \
else { \
PC += 2; \
} \
}
#define CALLC(cond) { \
if (cond) { \
register uint32 adrr = GetWORD(PC); \
CheckBreakWord(SP - 2); \
PUSH(PC + 2); \
PCQ_ENTRY(PC - 1); \
PC = adrr; \
} \
else { \
sim_brk_pend = FALSE; \
PC += 2; \
} \
}
int32 saved_PC = 0; /* program counter */
int32 SR = 0; /* switch register */
int32 PCX; /* External view of PC */
int32 bankSelect = 0; /* determines selected memory bank */
uint32 common = 0xc000; /* addresses >= 'common' are in common memory */
uint32 ROMLow = defaultROMLow; /* lowest address of ROM */
uint32 ROMHigh = defaultROMHigh; /* highest address of ROM */
extern int32 sim_int_char;
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
extern int32 sio0s (int32 port, int32 io, int32 data);
extern int32 sio0d (int32 port, int32 io, int32 data);
extern int32 sio1s (int32 port, int32 io, int32 data);
extern int32 sio1d (int32 port, int32 io, int32 data);
extern int32 dsk10 (int32 port, int32 io, int32 data);
extern int32 dsk11 (int32 port, int32 io, int32 data);
extern int32 dsk12 (int32 port, int32 io, int32 data);
extern int32 nulldev (int32 port, int32 io, int32 data);
extern int32 hdsk_io (int32 port, int32 io, int32 data);
extern int32 simh_dev (int32 port, int32 io, int32 data);
extern int32 sr_dev (int32 port, int32 io, int32 data);
extern int32 bootrom[bootrom_size];
extern char memoryAccessMessage[];
extern char messageBuffer[];
extern void printMessage(void);
/* 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_set_size(UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_set_banked(UNIT *uptr, int32 value, char *cptr, void *desc);
t_stat cpu_set_rom(UNIT *uptr, int32 value, char *cptr, void *desc);
t_stat cpu_set_norom(UNIT *uptr, int32 value, char *cptr, void *desc);
t_stat cpu_set_altairrom(UNIT *uptr, int32 value, char *cptr, void *desc);
uint32 in(uint32 Port);
void out(uint32 Port, uint32 Value);
uint8 GetBYTE(register uint32 Addr);
void PutBYTE(register uint32 Addr, register uint32 Value);
void PutBYTEForced(register uint32 Addr, register uint32 Value);
int32 addressIsInROM(uint32 Addr);
int32 addressExists(uint32 Addr);
uint16 GetWORD(register uint32 a);
void PutWORD(register uint32 a, register uint32 v);
int32 sim_instr(void);
int32 install_bootrom(void);
void reset_memory(void);
t_bool sim_brk_lookup (t_addr bloc, int32 btyp);
void prepareMemoryAccessMessage(t_addr loc);
void checkROMBoundaries(void);
void warnUnsuccessfulWriteAttempt(uint32 Addr);
uint8 warnUnsuccessfulReadAttempt(uint32 Addr);
t_stat cpu_set_warnrom(UNIT *uptr, int32 value, char *cptr, void *desc);
void protect(int32 l, int32 h);
void resetCell(int32 address, int32 bank);
#ifndef NO_INLINE
/* in case of using inline we need to ensure that the GetBYTE and PutBYTE
are accessible externally */
uint8 GetBYTEWrapper(register uint32 Addr);
void PutBYTEWrapper(register uint32 Addr, register uint32 Value);
#endif
/* 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 + UNIT_ROM + UNIT_ALTAIRROM, 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;
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
int32 pcq_p = 0; /* PC queue ptr */
REG *pcq_r = NULL; /* PC queue reg ptr */
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) },
{ GRDATA (IFF, IFF_S, 2, 2, 0) },
{ 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 (BANK, bankSelect, MAXBANKSLOG2) },
{ HRDATA (COMMON, common, 16) },
{ HRDATA (ROMLOW, ROMLow, 16) },
{ HRDATA (ROMHIGH, ROMHigh, 16) },
{ HRDATA (CAPACITY, cpu_unit.capac, 17), REG_RO },
{ BRDATA (PCQ, pcq, 16, 16, PCQ_SIZE), REG_RO + REG_CIRC },
{ DRDATA (PCQP, pcq_p, 6), REG_HRO },
{ HRDATA (WRU, sim_int_char, 8) },
{ 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_BANKED, UNIT_BANKED, "BANKED", "BANKED", &cpu_set_banked },
{ UNIT_BANKED, 0, "NONBANKED", "NONBANKED", NULL },
{ UNIT_ROM, UNIT_ROM, "ROM", "ROM", &cpu_set_rom },
{ UNIT_ROM, 0, "NOROM", "NOROM", &cpu_set_norom },
{ UNIT_ALTAIRROM, UNIT_ALTAIRROM, "ALTAIRROM", "ALTAIRROM", &cpu_set_altairrom },
{ UNIT_ALTAIRROM, 0, "NOALTAIRROM", "NOALTAIRROM", NULL },
{ UNIT_WARNROM, UNIT_WARNROM, "WARNROM", "WARNROM", &cpu_set_warnrom },
{ UNIT_WARNROM, 0, "NOWARNROM", "NOWARNROM", 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, 36 * KB, NULL, "36K", &cpu_set_size },
{ UNIT_MSIZE, 40 * KB, NULL, "40K", &cpu_set_size },
{ UNIT_MSIZE, 44 * KB, NULL, "44K", &cpu_set_size },
{ UNIT_MSIZE, 48 * KB, NULL, "48K", &cpu_set_size },
{ UNIT_MSIZE, 52 * KB, NULL, "52K", &cpu_set_size },
{ UNIT_MSIZE, 56 * KB, NULL, "56K", &cpu_set_size },
{ UNIT_MSIZE, 60 * KB, NULL, "60K", &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, NULL, 0 };
/* data structure for IN/OUT instructions */
struct idev {
int32 (*routine)(int32, int32, int32);
};
/* 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 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 */
{&sio0s}, {&sio0d}, {&sio0s}, {&sio0d}, /* 14 */
{&sio0s}, {&sio0d}, {&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}, {&hdsk_io}, {&simh_dev}, {&sr_dev} }; /* FC */
INLINE void out(uint32 Port, uint32 Value) {
dev_table[Port].routine(Port, 1, Value);
}
INLINE uint32 in(uint32 Port) {
return dev_table[Port].routine(Port, 0, 0);
}
void warnUnsuccessfulWriteAttempt(uint32 Addr) {
if (cpu_unit.flags & UNIT_WARNROM) {
if (addressIsInROM(Addr)) {
message2("Attempt to write to ROM " AddressFormat ".\n", Addr);
}
else {
message2("Attempt to write to non existing memory " AddressFormat ".\n", Addr);
}
}
}
uint8 warnUnsuccessfulReadAttempt(uint32 Addr) {
if (cpu_unit.flags & UNIT_WARNROM) {
message2("Attempt to read from non existing memory " AddressFormat ".\n", Addr);
}
return 0xff;
}
/* Determine whether Addr points to Read Only Memory */
int32 addressIsInROM(uint32 Addr) {
Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */
return (cpu_unit.flags & UNIT_ROM) && ( /* must have ROM enabled */
/* in banked case we have standard Altair ROM */
((cpu_unit.flags & UNIT_BANKED) && (defaultROMLow <= Addr)) ||
/* in non-banked case we check the bounds of the ROM */
(((cpu_unit.flags & UNIT_BANKED) == 0) && (ROMLow <= Addr) && (Addr <= ROMHigh)));
}
/* Determine whether Addr points to a valid memory address */
int32 addressExists(uint32 Addr) {
Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */
return (cpu_unit.flags & UNIT_BANKED) || (Addr < MEMSIZE) ||
((cpu_unit.flags & UNIT_BANKED) == 0) && (cpu_unit.flags & UNIT_ROM)
&& (ROMLow <= Addr) && (Addr <= ROMHigh);
}
INLINE uint8 GetBYTE(register uint32 Addr) {
Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */
if (cpu_unit.flags & UNIT_BANKED) { /* banked memory case */
/* if Addr below "common" take from selected bank, otherwise from bank 0 */
return Addr < common ? M[Addr][bankSelect] : M[Addr][0];
}
else { /* non-banked memory case */
return ((Addr < MEMSIZE) ||
(cpu_unit.flags & UNIT_ROM) && (ROMLow <= Addr) && (Addr <= ROMHigh)) ?
M[Addr][0] : warnUnsuccessfulReadAttempt(Addr);
}
}
INLINE void PutBYTE(register uint32 Addr, register uint32 Value) {
Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */
if (cpu_unit.flags & UNIT_BANKED) {
if (Addr < common) {
M[Addr][bankSelect] = Value;
}
else if ((Addr < defaultROMLow) || ((cpu_unit.flags & UNIT_ROM) == 0)) {
M[Addr][0] = Value;
}
else {
warnUnsuccessfulWriteAttempt(Addr);
}
}
else {
if ((Addr < MEMSIZE) && ((Addr < ROMLow) || (Addr > ROMHigh) || ((cpu_unit.flags & UNIT_ROM) == 0))) {
M[Addr][0] = Value;
}
else {
warnUnsuccessfulWriteAttempt(Addr);
}
}
}
void PutBYTEForced(register uint32 Addr, register uint32 Value) {
Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */
if ((cpu_unit.flags & UNIT_BANKED) && (Addr < common)) {
M[Addr][bankSelect] = Value;
}
else {
M[Addr][0] = Value;
}
}
INLINE void PutWORD(register uint32 Addr, register uint32 Value) {
Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */
if (cpu_unit.flags & UNIT_BANKED) {
if (Addr < common) {
M[Addr][bankSelect] = Value;
}
else if ((Addr < defaultROMLow) || ((cpu_unit.flags & UNIT_ROM) == 0)) {
M[Addr][0] = Value;
}
else {
warnUnsuccessfulWriteAttempt(Addr);
}
Addr = (Addr + 1) & ADDRMASK;
if (Addr < common) {
M[Addr][bankSelect] = Value >> 8;
}
else if ((Addr < defaultROMLow) || ((cpu_unit.flags & UNIT_ROM) == 0)) {
M[Addr][0] = Value >> 8;
}
else {
warnUnsuccessfulWriteAttempt(Addr);
}
}
else {
if ((Addr < MEMSIZE) && ((Addr < ROMLow) || (Addr > ROMHigh) || ((cpu_unit.flags & UNIT_ROM) == 0))) {
M[Addr][0] = Value;
}
else {
warnUnsuccessfulWriteAttempt(Addr);
}
Addr = (Addr + 1) & ADDRMASK;
if ((Addr < MEMSIZE) && ((Addr < ROMLow) || (Addr > ROMHigh) || ((cpu_unit.flags & UNIT_ROM) == 0))) {
M[Addr][0] = Value >> 8;
}
else {
warnUnsuccessfulWriteAttempt(Addr);
}
}
}
#ifndef NO_INLINE
uint8 GetBYTEWrapper(register uint32 Addr) { /* make sure that non-inlined version exists */
return GetBYTE(Addr);
}
void PutBYTEWrapper(register uint32 Addr, register uint32 Value) {
PutBYTE(Addr, Value);
}
#endif
#define RAM_mm(a) GetBYTE(a--)
#define RAM_pp(a) GetBYTE(a++)
#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 uint32 a) {
return GetBYTE(a) | (GetBYTE(a + 1) << 8);
}
#define MASK_BRK (TRUE+1)
/* repeated from scp.c */
struct brktab {
t_addr addr;
int32 typ;
int32 cnt;
char *act;
};
typedef struct brktab BRKTAB;
/* this is a modified version of sim_brk_test with two differences:
1) is does not set sim_brk_pend to FALSE (this if left to the instruction decode)
2) it returns MASK_BRK if a breakpoint is found but should be ignored
*/
int32 sim_brk_lookup (t_addr loc, int32 btyp) {
extern BRKTAB *sim_brk_fnd (t_addr loc);
extern t_bool sim_brk_pend;
extern t_addr sim_brk_ploc;
BRKTAB *bp;
if ((bp = sim_brk_fnd (loc)) &&
(btyp & bp -> typ) &&
(!sim_brk_pend || (loc != sim_brk_ploc)) &&
(--(bp -> cnt) <= 0)) {
bp -> cnt = 0;
sim_brk_ploc = loc;
sim_brk_pend = TRUE;
return TRUE;
}
return (sim_brk_pend && (loc == sim_brk_ploc)) ? MASK_BRK : FALSE;
}
void prepareMemoryAccessMessage(t_addr loc) {
sprintf(memoryAccessMessage, "Memory access breakpoint [%04xh]", loc);
}
#define PUSH(x) do { \
mm_PutBYTE(SP, (x) >> 8); \
mm_PutBYTE(SP, x); \
} while (0)
#define CheckBreakByte(a) \
if (sim_brk_summ && sim_brk_test(a, SWMASK('M'))) { \
reason = STOP_MEM; \
prepareMemoryAccessMessage(a); \
goto end_decode; \
}
#define CheckBreakTwoBytesExtended(a1, a2, iCode) \
if (sim_brk_summ) { \
br1 = sim_brk_lookup(a1, SWMASK('M')); \
br2 = br1 ? FALSE : sim_brk_lookup(a2, SWMASK('M')); \
if ((br1 == MASK_BRK) || (br2 == MASK_BRK)) { \
sim_brk_pend = FALSE; \
} \
else if (br1 || br2) { \
reason = STOP_MEM; \
if (br1) { \
prepareMemoryAccessMessage(a1); \
} \
else { \
prepareMemoryAccessMessage(a2); \
} \
iCode; \
goto end_decode; \
} \
else { \
sim_brk_pend = FALSE; \
} \
}
#define CheckBreakTwoBytes(a1, a2) CheckBreakTwoBytesExtended(a1, a2,;)
#define CheckBreakWord(a) CheckBreakTwoBytes(a, (a+1))
int32 sim_instr (void) {
extern int32 sim_interval;
extern t_bool sim_brk_pend;
extern int32 timerInterrupt;
extern int32 timerInterruptHandler;
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 br1, br2;
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 (TRUE) { /* loop until halted */
if (sim_interval <= 0) { /* check clock queue */
if (reason = sim_process_event()) {
break;
}
}
if (timerInterrupt && (IFF & 1)) {
timerInterrupt = FALSE;
IFF = 0; /* disable interrupts */
CheckBreakTwoBytesExtended(SP - 2, SP - 1, (timerInterrupt = TRUE, IFF |= 1));
PUSH(PC);
PCQ_ENTRY(PC - 1);
PC = timerInterruptHandler & ADDRMASK;
}
if (sim_brk_summ && (sim_brk_lookup(PC, SWMASK('E')) == TRUE)) { /* breakpoint? */
reason = STOP_IBKPT; /* stop simulation */
break;
}
PCX = PC;
sim_interval--;
/* make sure that each instructions properly sets sim_brk_pend:
1) Either directly to FALSE if no memory access takes place or
2) through a call to a Check... routine
*/
switch(RAM_pp(PC)) {
case 0x00: /* NOP */
sim_brk_pend = FALSE;
break;
case 0x01: /* LD BC,nnnn */
sim_brk_pend = FALSE;
BC = GetWORD(PC);
PC += 2;
break;
case 0x02: /* LD (BC),A */
CheckBreakByte(BC)
PutBYTE(BC, hreg(AF));
break;
case 0x03: /* INC BC */
sim_brk_pend = FALSE;
++BC;
break;
case 0x04: /* INC B */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
Sethreg(BC, RAM_pp(PC));
break;
case 0x07: /* RLCA */
sim_brk_pend = FALSE;
AF = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) |
(AF & 0xc4) | ((AF >> 15) & 1);
break;
case 0x08: /* EX AF,AF' */
sim_brk_pend = FALSE;
checkCPU8080;
af[af_sel] = AF;
af_sel = 1 - af_sel;
AF = af[af_sel];
break;
case 0x09: /* ADD HL,BC */
sim_brk_pend = FALSE;
HL &= ADDRMASK;
BC &= ADDRMASK;
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) */
CheckBreakByte(BC)
Sethreg(AF, GetBYTE(BC));
break;
case 0x0b: /* DEC BC */
sim_brk_pend = FALSE;
--BC;
break;
case 0x0c: /* INC C */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
Setlreg(BC, RAM_pp(PC));
break;
case 0x0f: /* RRCA */
sim_brk_pend = FALSE;
temp = hreg(AF);
sum = temp >> 1;
AF = ((temp & 1) << 15) | (sum << 8) |
(sum & 0x28) | (AF & 0xc4) | (temp & 1);
break;
case 0x10: /* DJNZ dd */
sim_brk_pend = FALSE;
checkCPU8080;
if ((BC -= 0x100) & 0xff00) {
PCQ_ENTRY(PC - 1);
PC += (signed char) GetBYTE(PC) + 1;
}
else {
PC++;
}
break;
case 0x11: /* LD DE,nnnn */
sim_brk_pend = FALSE;
DE = GetWORD(PC);
PC += 2;
break;
case 0x12: /* LD (DE),A */
CheckBreakByte(DE)
PutBYTE(DE, hreg(AF));
break;
case 0x13: /* INC DE */
sim_brk_pend = FALSE;
++DE;
break;
case 0x14: /* INC D */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
Sethreg(DE, RAM_pp(PC));
break;
case 0x17: /* RLA */
sim_brk_pend = FALSE;
AF = ((AF << 8) & 0x0100) | ((AF >> 7) & 0x28) | ((AF << 1) & ~0x01ff) |
(AF & 0xc4) | ((AF >> 15) & 1);
break;
case 0x18: /* JR dd */
sim_brk_pend = FALSE;
checkCPU8080;
PCQ_ENTRY(PC - 1);
PC += (signed char) GetBYTE(PC) + 1;
break;
case 0x19: /* ADD HL,DE */
sim_brk_pend = FALSE;
HL &= ADDRMASK;
DE &= ADDRMASK;
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) */
CheckBreakByte(DE)
Sethreg(AF, GetBYTE(DE));
break;
case 0x1b: /* DEC DE */
sim_brk_pend = FALSE;
--DE;
break;
case 0x1c: /* INC E */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
Setlreg(DE, RAM_pp(PC));
break;
case 0x1f: /* RRA */
sim_brk_pend = FALSE;
temp = hreg(AF);
sum = temp >> 1;
AF = ((AF & 1) << 15) | (sum << 8) |
(sum & 0x28) | (AF & 0xc4) | (temp & 1);
break;
case 0x20: /* JR NZ,dd */
sim_brk_pend = FALSE;
checkCPU8080;
if (TSTFLAG(Z)) {
PC++;
}
else {
PCQ_ENTRY(PC - 1);
PC += (signed char) GetBYTE(PC) + 1;
}
break;
case 0x21: /* LD HL,nnnn */
sim_brk_pend = FALSE;
HL = GetWORD(PC);
PC += 2;
break;
case 0x22: /* LD (nnnn),HL */
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, HL);
PC += 2;
break;
case 0x23: /* INC HL */
sim_brk_pend = FALSE;
++HL;
break;
case 0x24: /* INC H */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
Sethreg(HL, RAM_pp(PC));
break;
case 0x27: /* DAA */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
checkCPU8080;
if (TSTFLAG(Z)) {
PCQ_ENTRY(PC - 1);
PC += (signed char) GetBYTE(PC) + 1;
}
else {
PC++;
}
break;
case 0x29: /* ADD HL,HL */
sim_brk_pend = FALSE;
HL &= ADDRMASK;
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);
CheckBreakWord(temp);
HL = GetWORD(temp);
PC += 2;
break;
case 0x2b: /* DEC HL */
sim_brk_pend = FALSE;
--HL;
break;
case 0x2c: /* INC L */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
Setlreg(HL, RAM_pp(PC));
break;
case 0x2f: /* CPL */
sim_brk_pend = FALSE;
AF = (~AF & ~0xff) | (AF & 0xc5) | ((~AF >> 8) & 0x28) | 0x12;
break;
case 0x30: /* JR NC,dd */
sim_brk_pend = FALSE;
checkCPU8080;
if (TSTFLAG(C)) {
PC++;
}
else {
PCQ_ENTRY(PC - 1);
PC += (signed char) GetBYTE(PC) + 1;
}
break;
case 0x31: /* LD SP,nnnn */
sim_brk_pend = FALSE;
SP = GetWORD(PC);
PC += 2;
break;
case 0x32: /* LD (nnnn),A */
temp = GetWORD(PC);
CheckBreakByte(temp);
PutBYTE(temp, hreg(AF));
PC += 2;
break;
case 0x33: /* INC SP */
sim_brk_pend = FALSE;
++SP;
break;
case 0x34: /* INC (HL) */
CheckBreakByte(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) */
CheckBreakByte(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 */
CheckBreakByte(HL);
PutBYTE(HL, RAM_pp(PC));
break;
case 0x37: /* SCF */
sim_brk_pend = FALSE;
AF = (AF & ~0x3b) | ((AF>>8) & 0x28) | 1;
break;
case 0x38: /* JR C,dd */
sim_brk_pend = FALSE;
checkCPU8080;
if (TSTFLAG(C)) {
PCQ_ENTRY(PC - 1);
PC += (signed char) GetBYTE(PC) + 1;
}
else {
PC++;
}
break;
case 0x39: /* ADD HL,SP */
sim_brk_pend = FALSE;
HL &= ADDRMASK;
SP &= ADDRMASK;
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);
CheckBreakByte(temp);
Sethreg(AF, GetBYTE(temp));
PC += 2;
break;
case 0x3b: /* DEC SP */
sim_brk_pend = FALSE;
--SP;
break;
case 0x3c: /* INC A */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
Sethreg(AF, RAM_pp(PC));
break;
case 0x3f: /* CCF */
sim_brk_pend = FALSE;
AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) |
((AF & 1) << 4) | (~AF & 1);
break;
case 0x40: /* LD B,B */
sim_brk_pend = FALSE;
/* nop */
break;
case 0x41: /* LD B,C */
sim_brk_pend = FALSE;
BC = (BC & 255) | ((BC & 255) << 8);
break;
case 0x42: /* LD B,D */
sim_brk_pend = FALSE;
BC = (BC & 255) | (DE & ~255);
break;
case 0x43: /* LD B,E */
sim_brk_pend = FALSE;
BC = (BC & 255) | ((DE & 255) << 8);
break;
case 0x44: /* LD B,H */
sim_brk_pend = FALSE;
BC = (BC & 255) | (HL & ~255);
break;
case 0x45: /* LD B,L */
sim_brk_pend = FALSE;
BC = (BC & 255) | ((HL & 255) << 8);
break;
case 0x46: /* LD B,(HL) */
CheckBreakByte(HL);
Sethreg(BC, GetBYTE(HL));
break;
case 0x47: /* LD B,A */
sim_brk_pend = FALSE;
BC = (BC & 255) | (AF & ~255);
break;
case 0x48: /* LD C,B */
sim_brk_pend = FALSE;
BC = (BC & ~255) | ((BC >> 8) & 255);
break;
case 0x49: /* LD C,C */
sim_brk_pend = FALSE;
/* nop */
break;
case 0x4a: /* LD C,D */
sim_brk_pend = FALSE;
BC = (BC & ~255) | ((DE >> 8) & 255);
break;
case 0x4b: /* LD C,E */
sim_brk_pend = FALSE;
BC = (BC & ~255) | (DE & 255);
break;
case 0x4c: /* LD C,H */
sim_brk_pend = FALSE;
BC = (BC & ~255) | ((HL >> 8) & 255);
break;
case 0x4d: /* LD C,L */
sim_brk_pend = FALSE;
BC = (BC & ~255) | (HL & 255);
break;
case 0x4e: /* LD C,(HL) */
CheckBreakByte(HL);
Setlreg(BC, GetBYTE(HL));
break;
case 0x4f: /* LD C,A */
sim_brk_pend = FALSE;
BC = (BC & ~255) | ((AF >> 8) & 255);
break;
case 0x50: /* LD D,B */
sim_brk_pend = FALSE;
DE = (DE & 255) | (BC & ~255);
break;
case 0x51: /* LD D,C */
sim_brk_pend = FALSE;
DE = (DE & 255) | ((BC & 255) << 8);
break;
case 0x52: /* LD D,D */
sim_brk_pend = FALSE;
/* nop */
break;
case 0x53: /* LD D,E */
sim_brk_pend = FALSE;
DE = (DE & 255) | ((DE & 255) << 8);
break;
case 0x54: /* LD D,H */
sim_brk_pend = FALSE;
DE = (DE & 255) | (HL & ~255);
break;
case 0x55: /* LD D,L */
sim_brk_pend = FALSE;
DE = (DE & 255) | ((HL & 255) << 8);
break;
case 0x56: /* LD D,(HL) */
CheckBreakByte(HL);
Sethreg(DE, GetBYTE(HL));
break;
case 0x57: /* LD D,A */
sim_brk_pend = FALSE;
DE = (DE & 255) | (AF & ~255);
break;
case 0x58: /* LD E,B */
sim_brk_pend = FALSE;
DE = (DE & ~255) | ((BC >> 8) & 255);
break;
case 0x59: /* LD E,C */
sim_brk_pend = FALSE;
DE = (DE & ~255) | (BC & 255);
break;
case 0x5a: /* LD E,D */
sim_brk_pend = FALSE;
DE = (DE & ~255) | ((DE >> 8) & 255);
break;
case 0x5b: /* LD E,E */
sim_brk_pend = FALSE;
/* nop */
break;
case 0x5c: /* LD E,H */
sim_brk_pend = FALSE;
DE = (DE & ~255) | ((HL >> 8) & 255);
break;
case 0x5d: /* LD E,L */
sim_brk_pend = FALSE;
DE = (DE & ~255) | (HL & 255);
break;
case 0x5e: /* LD E,(HL) */
CheckBreakByte(HL);
Setlreg(DE, GetBYTE(HL));
break;
case 0x5f: /* LD E,A */
sim_brk_pend = FALSE;
DE = (DE & ~255) | ((AF >> 8) & 255);
break;
case 0x60: /* LD H,B */
sim_brk_pend = FALSE;
HL = (HL & 255) | (BC & ~255);
break;
case 0x61: /* LD H,C */
sim_brk_pend = FALSE;
HL = (HL & 255) | ((BC & 255) << 8);
break;
case 0x62: /* LD H,D */
sim_brk_pend = FALSE;
HL = (HL & 255) | (DE & ~255);
break;
case 0x63: /* LD H,E */
sim_brk_pend = FALSE;
HL = (HL & 255) | ((DE & 255) << 8);
break;
case 0x64: /* LD H,H */
sim_brk_pend = FALSE;
/* nop */
break;
case 0x65: /* LD H,L */
sim_brk_pend = FALSE;
HL = (HL & 255) | ((HL & 255) << 8);
break;
case 0x66: /* LD H,(HL) */
CheckBreakByte(HL);
Sethreg(HL, GetBYTE(HL));
break;
case 0x67: /* LD H,A */
sim_brk_pend = FALSE;
HL = (HL & 255) | (AF & ~255);
break;
case 0x68: /* LD L,B */
sim_brk_pend = FALSE;
HL = (HL & ~255) | ((BC >> 8) & 255);
break;
case 0x69: /* LD L,C */
sim_brk_pend = FALSE;
HL = (HL & ~255) | (BC & 255);
break;
case 0x6a: /* LD L,D */
sim_brk_pend = FALSE;
HL = (HL & ~255) | ((DE >> 8) & 255);
break;
case 0x6b: /* LD L,E */
sim_brk_pend = FALSE;
HL = (HL & ~255) | (DE & 255);
break;
case 0x6c: /* LD L,H */
sim_brk_pend = FALSE;
HL = (HL & ~255) | ((HL >> 8) & 255);
break;
case 0x6d: /* LD L,L */
sim_brk_pend = FALSE;
/* nop */
break;
case 0x6e: /* LD L,(HL) */
CheckBreakByte(HL);
Setlreg(HL, GetBYTE(HL));
break;
case 0x6f: /* LD L,A */
sim_brk_pend = FALSE;
HL = (HL & ~255) | ((AF >> 8) & 255);
break;
case 0x70: /* LD (HL),B */
CheckBreakByte(HL);
PutBYTE(HL, hreg(BC));
break;
case 0x71: /* LD (HL),C */
CheckBreakByte(HL);
PutBYTE(HL, lreg(BC));
break;
case 0x72: /* LD (HL),D */
CheckBreakByte(HL);
PutBYTE(HL, hreg(DE));
break;
case 0x73: /* LD (HL),E */
CheckBreakByte(HL);
PutBYTE(HL, lreg(DE));
break;
case 0x74: /* LD (HL),H */
CheckBreakByte(HL);
PutBYTE(HL, hreg(HL));
break;
case 0x75: /* LD (HL),L */
CheckBreakByte(HL);
PutBYTE(HL, lreg(HL));
break;
case 0x76: /* HALT */
sim_brk_pend = FALSE;
reason = STOP_HALT;
PC--;
goto end_decode;
case 0x77: /* LD (HL),A */
CheckBreakByte(HL);
PutBYTE(HL, hreg(AF));
break;
case 0x78: /* LD A,B */
sim_brk_pend = FALSE;
AF = (AF & 255) | (BC & ~255);
break;
case 0x79: /* LD A,C */
sim_brk_pend = FALSE;
AF = (AF & 255) | ((BC & 255) << 8);
break;
case 0x7a: /* LD A,D */
sim_brk_pend = FALSE;
AF = (AF & 255) | (DE & ~255);
break;
case 0x7b: /* LD A,E */
sim_brk_pend = FALSE;
AF = (AF & 255) | ((DE & 255) << 8);
break;
case 0x7c: /* LD A,H */
sim_brk_pend = FALSE;
AF = (AF & 255) | (HL & ~255);
break;
case 0x7d: /* LD A,L */
sim_brk_pend = FALSE;
AF = (AF & 255) | ((HL & 255) << 8);
break;
case 0x7e: /* LD A,(HL) */
CheckBreakByte(HL);
Sethreg(AF, GetBYTE(HL));
break;
case 0x7f: /* LD A,A */
sim_brk_pend = FALSE;
/* nop */
break;
case 0x80: /* ADD A,B */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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) */
CheckBreakByte(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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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) */
CheckBreakByte(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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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) */
CheckBreakByte(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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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) */
CheckBreakByte(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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
sum = ((AF & (BC)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xa1: /* AND C */
sim_brk_pend = FALSE;
sum = ((AF >> 8) & BC) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xa2: /* AND D */
sim_brk_pend = FALSE;
sum = ((AF & (DE)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xa3: /* AND E */
sim_brk_pend = FALSE;
sum = ((AF >> 8) & DE) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xa4: /* AND H */
sim_brk_pend = FALSE;
sum = ((AF & (HL)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xa5: /* AND L */
sim_brk_pend = FALSE;
sum = ((AF >> 8) & HL) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xa6: /* AND (HL) */
CheckBreakByte(HL);
sum = ((AF >> 8) & GetBYTE(HL)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xa7: /* AND A */
sim_brk_pend = FALSE;
sum = ((AF & (AF)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xa8: /* XOR B */
sim_brk_pend = FALSE;
sum = ((AF ^ (BC)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xa9: /* XOR C */
sim_brk_pend = FALSE;
sum = ((AF >> 8) ^ BC) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xaa: /* XOR D */
sim_brk_pend = FALSE;
sum = ((AF ^ (DE)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xab: /* XOR E */
sim_brk_pend = FALSE;
sum = ((AF >> 8) ^ DE) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xac: /* XOR H */
sim_brk_pend = FALSE;
sum = ((AF ^ (HL)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xad: /* XOR L */
sim_brk_pend = FALSE;
sum = ((AF >> 8) ^ HL) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xae: /* XOR (HL) */
CheckBreakByte(HL);
sum = ((AF >> 8) ^ GetBYTE(HL)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xaf: /* XOR A */
sim_brk_pend = FALSE;
sum = ((AF ^ (AF)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xb0: /* OR B */
sim_brk_pend = FALSE;
sum = ((AF | (BC)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xb1: /* OR C */
sim_brk_pend = FALSE;
sum = ((AF >> 8) | BC) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xb2: /* OR D */
sim_brk_pend = FALSE;
sum = ((AF | (DE)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xb3: /* OR E */
sim_brk_pend = FALSE;
sum = ((AF >> 8) | DE) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xb4: /* OR H */
sim_brk_pend = FALSE;
sum = ((AF | (HL)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xb5: /* OR L */
sim_brk_pend = FALSE;
sum = ((AF >> 8) | HL) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xb6: /* OR (HL) */
CheckBreakByte(HL);
sum = ((AF >> 8) | GetBYTE(HL)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xb7: /* OR A */
sim_brk_pend = FALSE;
sum = ((AF | (AF)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xb8: /* CP B */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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) */
CheckBreakByte(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 */
sim_brk_pend = FALSE;
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)) {
sim_brk_pend = FALSE;
}
else {
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
}
break;
case 0xc1: /* POP BC */
CheckBreakWord(SP);
POP(BC);
break;
case 0xc2: /* JP NZ,nnnn */
sim_brk_pend = FALSE;
JPC(!TSTFLAG(Z));
break;
case 0xc3: /* JP nnnn */
sim_brk_pend = FALSE;
JPC(1);
break;
case 0xc4: /* CALL NZ,nnnn */
CALLC(!TSTFLAG(Z));
break;
case 0xc5: /* PUSH BC */
CheckBreakWord(SP - 2);
PUSH(BC);
break;
case 0xc6: /* ADD A,nn */
sim_brk_pend = FALSE;
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 */
CheckBreakWord(SP - 2);
PUSH(PC); PCQ_ENTRY(PC - 1); PC = 0;
break;
case 0xc8: /* RET Z */
if (TSTFLAG(Z)) {
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
}
else {
sim_brk_pend = FALSE;
}
break;
case 0xc9: /* RET */
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
break;
case 0xca: /* JP Z,nnnn */
sim_brk_pend = FALSE;
JPC(TSTFLAG(Z));
break;
case 0xcb: /* CB prefix */
checkCPU8080;
adr = HL;
switch ((op = GetBYTE(PC)) & 7) {
case 0: sim_brk_pend = FALSE; ++PC; acu = hreg(BC); break;
case 1: sim_brk_pend = FALSE; ++PC; acu = lreg(BC); break;
case 2: sim_brk_pend = FALSE; ++PC; acu = hreg(DE); break;
case 3: sim_brk_pend = FALSE; ++PC; acu = lreg(DE); break;
case 4: sim_brk_pend = FALSE; ++PC; acu = hreg(HL); break;
case 5: sim_brk_pend = FALSE; ++PC; acu = lreg(HL); break;
case 6: CheckBreakByte(adr); ++PC; acu = GetBYTE(adr); break;
case 7: sim_brk_pend = FALSE; ++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 */
sim_brk_pend = FALSE;
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 */
CheckBreakWord(SP - 2);
PUSH(PC); PCQ_ENTRY(PC - 1); PC = 8;
break;
case 0xd0: /* RET NC */
if (TSTFLAG(C)) {
sim_brk_pend = FALSE;
}
else {
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
}
break;
case 0xd1: /* POP DE */
CheckBreakWord(SP);
POP(DE);
break;
case 0xd2: /* JP NC,nnnn */
sim_brk_pend = FALSE;
JPC(!TSTFLAG(C));
break;
case 0xd3: /* OUT (nn),A */
sim_brk_pend = FALSE;
out(RAM_pp(PC), hreg(AF));
break;
case 0xd4: /* CALL NC,nnnn */
CALLC(!TSTFLAG(C));
break;
case 0xd5: /* PUSH DE */
CheckBreakWord(SP - 2);
PUSH(DE);
break;
case 0xd6: /* SUB nn */
sim_brk_pend = FALSE;
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 */
CheckBreakWord(SP - 2);
PUSH(PC); PCQ_ENTRY(PC - 1); PC = 0x10;
break;
case 0xd8: /* RET C */
if (TSTFLAG(C)) {
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
}
else {
sim_brk_pend = FALSE;
}
break;
case 0xd9: /* EXX */
sim_brk_pend = FALSE;
checkCPU8080;
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 */
sim_brk_pend = FALSE;
JPC(TSTFLAG(C));
break;
case 0xdb: /* IN A,(nn) */
sim_brk_pend = FALSE;
Sethreg(AF, in(RAM_pp(PC)));
break;
case 0xdc: /* CALL C,nnnn */
CALLC(TSTFLAG(C));
break;
case 0xdd: /* DD prefix */
checkCPU8080;
switch (op = RAM_pp(PC)) {
case 0x09: /* ADD IX,BC */
sim_brk_pend = FALSE;
IX &= ADDRMASK;
BC &= ADDRMASK;
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 */
sim_brk_pend = FALSE;
IX &= ADDRMASK;
DE &= ADDRMASK;
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 */
sim_brk_pend = FALSE;
IX = GetWORD(PC);
PC += 2;
break;
case 0x22: /* LD (nnnn),IX */
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, IX);
PC += 2;
break;
case 0x23: /* INC IX */
sim_brk_pend = FALSE;
++IX;
break;
case 0x24: /* INC IXH */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
Sethreg(IX, RAM_pp(PC));
break;
case 0x29: /* ADD IX,IX */
sim_brk_pend = FALSE;
IX &= ADDRMASK;
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);
CheckBreakWord(temp);
IX = GetWORD(temp);
PC += 2;
break;
case 0x2b: /* DEC IX */
sim_brk_pend = FALSE;
--IX;
break;
case 0x2c: /* INC IXL */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
Setlreg(IX, RAM_pp(PC));
break;
case 0x34: /* INC (IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
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);
CheckBreakByte(adr);
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);
CheckBreakByte(adr);
PutBYTE(adr, RAM_pp(PC));
break;
case 0x39: /* ADD IX,SP */
sim_brk_pend = FALSE;
IX &= ADDRMASK;
SP &= ADDRMASK;
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 */
sim_brk_pend = FALSE;
Sethreg(BC, hreg(IX));
break;
case 0x45: /* LD B,IXL */
sim_brk_pend = FALSE;
Sethreg(BC, lreg(IX));
break;
case 0x46: /* LD B,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(BC, GetBYTE(adr));
break;
case 0x4c: /* LD C,IXH */
sim_brk_pend = FALSE;
Setlreg(BC, hreg(IX));
break;
case 0x4d: /* LD C,IXL */
sim_brk_pend = FALSE;
Setlreg(BC, lreg(IX));
break;
case 0x4e: /* LD C,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Setlreg(BC, GetBYTE(adr));
break;
case 0x54: /* LD D,IXH */
sim_brk_pend = FALSE;
Sethreg(DE, hreg(IX));
break;
case 0x55: /* LD D,IXL */
sim_brk_pend = FALSE;
Sethreg(DE, lreg(IX));
break;
case 0x56: /* LD D,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(DE, GetBYTE(adr));
break;
case 0x5c: /* LD E,H */
sim_brk_pend = FALSE;
Setlreg(DE, hreg(IX));
break;
case 0x5d: /* LD E,L */
sim_brk_pend = FALSE;
Setlreg(DE, lreg(IX));
break;
case 0x5e: /* LD E,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Setlreg(DE, GetBYTE(adr));
break;
case 0x60: /* LD IXH,B */
sim_brk_pend = FALSE;
Sethreg(IX, hreg(BC));
break;
case 0x61: /* LD IXH,C */
sim_brk_pend = FALSE;
Sethreg(IX, lreg(BC));
break;
case 0x62: /* LD IXH,D */
sim_brk_pend = FALSE;
Sethreg(IX, hreg(DE));
break;
case 0x63: /* LD IXH,E */
sim_brk_pend = FALSE;
Sethreg(IX, lreg(DE));
break;
case 0x64: /* LD IXH,IXH */
sim_brk_pend = FALSE;
/* nop */
break;
case 0x65: /* LD IXH,IXL */
sim_brk_pend = FALSE;
Sethreg(IX, lreg(IX));
break;
case 0x66: /* LD H,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(HL, GetBYTE(adr));
break;
case 0x67: /* LD IXH,A */
sim_brk_pend = FALSE;
Sethreg(IX, hreg(AF));
break;
case 0x68: /* LD IXL,B */
sim_brk_pend = FALSE;
Setlreg(IX, hreg(BC));
break;
case 0x69: /* LD IXL,C */
sim_brk_pend = FALSE;
Setlreg(IX, lreg(BC));
break;
case 0x6a: /* LD IXL,D */
sim_brk_pend = FALSE;
Setlreg(IX, hreg(DE));
break;
case 0x6b: /* LD IXL,E */
sim_brk_pend = FALSE;
Setlreg(IX, lreg(DE));
break;
case 0x6c: /* LD IXL,IXH */
sim_brk_pend = FALSE;
Setlreg(IX, hreg(IX));
break;
case 0x6d: /* LD IXL,IXL */
sim_brk_pend = FALSE;
/* nop */
break;
case 0x6e: /* LD L,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Setlreg(HL, GetBYTE(adr));
break;
case 0x6f: /* LD IXL,A */
sim_brk_pend = FALSE;
Setlreg(IX, hreg(AF));
break;
case 0x70: /* LD (IX+dd),B */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(BC));
break;
case 0x71: /* LD (IX+dd),C */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, lreg(BC));
break;
case 0x72: /* LD (IX+dd),D */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(DE));
break;
case 0x73: /* LD (IX+dd),E */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, lreg(DE));
break;
case 0x74: /* LD (IX+dd),H */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(HL));
break;
case 0x75: /* LD (IX+dd),L */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, lreg(HL));
break;
case 0x77: /* LD (IX+dd),A */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(AF));
break;
case 0x7c: /* LD A,IXH */
sim_brk_pend = FALSE;
Sethreg(AF, hreg(IX));
break;
case 0x7d: /* LD A,IXL */
sim_brk_pend = FALSE;
Sethreg(AF, lreg(IX));
break;
case 0x7e: /* LD A,(IX+dd) */
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(AF, GetBYTE(adr));
break;
case 0x84: /* ADD A,IXH */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
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 */
sim_brk_pend = FALSE;
sum = ((AF & (IX)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xa5: /* AND IXL */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
sum = ((AF >> 8) & GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xac: /* XOR IXH */
sim_brk_pend = FALSE;
sum = ((AF ^ (IX)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xad: /* XOR IXL */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
sum = ((AF >> 8) ^ GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xb4: /* OR IXH */
sim_brk_pend = FALSE;
sum = ((AF | (IX)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xb5: /* OR IXL */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
sum = ((AF >> 8) | GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xbc: /* CP IXH */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
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);
switch ((op = GetBYTE(PC)) & 7) {
case 0: sim_brk_pend = FALSE; ++PC; acu = hreg(BC); break;
case 1: sim_brk_pend = FALSE; ++PC; acu = lreg(BC); break;
case 2: sim_brk_pend = FALSE; ++PC; acu = hreg(DE); break;
case 3: sim_brk_pend = FALSE; ++PC; acu = lreg(DE); break;
case 4: sim_brk_pend = FALSE; ++PC; acu = hreg(HL); break;
case 5: sim_brk_pend = FALSE; ++PC; acu = lreg(HL); break;
case 6: CheckBreakByte(adr); ++PC; acu = GetBYTE(adr); break;
case 7: sim_brk_pend = FALSE; ++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 */
CheckBreakWord(SP);
POP(IX);
break;
case 0xe3: /* EX (SP),IX */
CheckBreakWord(SP);
temp = IX; POP(IX); PUSH(temp);
break;
case 0xe5: /* PUSH IX */
CheckBreakWord(SP - 2);
PUSH(IX);
break;
case 0xe9: /* JP (IX) */
sim_brk_pend = FALSE;
PCQ_ENTRY(PC - 2);
PC = IX;
break;
case 0xf9: /* LD SP,IX */
sim_brk_pend = FALSE;
SP = IX;
break;
default: /* ignore DD */
sim_brk_pend = FALSE;
checkCPUZ80;
PC--;
}
break;
case 0xde: /* SBC A,nn */
sim_brk_pend = FALSE;
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 */
CheckBreakWord(SP - 2);
PUSH(PC); PCQ_ENTRY(PC - 1); PC = 0x18;
break;
case 0xe0: /* RET PO */
if (TSTFLAG(P)) {
sim_brk_pend = FALSE;
}
else {
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
}
break;
case 0xe1: /* POP HL */
CheckBreakWord(SP);
POP(HL);
break;
case 0xe2: /* JP PO,nnnn */
sim_brk_pend = FALSE;
JPC(!TSTFLAG(P));
break;
case 0xe3: /* EX (SP),HL */
CheckBreakWord(SP);
temp = HL; POP(HL); PUSH(temp);
break;
case 0xe4: /* CALL PO,nnnn */
CALLC(!TSTFLAG(P));
break;
case 0xe5: /* PUSH HL */
CheckBreakWord(SP - 2);
PUSH(HL);
break;
case 0xe6: /* AND nn */
sim_brk_pend = FALSE;
sum = ((AF >> 8) & RAM_pp(PC)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xe7: /* RST 20H */
CheckBreakWord(SP - 2);
PUSH(PC); PCQ_ENTRY(PC - 1); PC = 0x20;
break;
case 0xe8: /* RET PE */
if (TSTFLAG(P)) {
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
}
else {
sim_brk_pend = FALSE;
}
break;
case 0xe9: /* JP (HL) */
sim_brk_pend = FALSE;
PCQ_ENTRY(PC - 1);
PC = HL;
break;
case 0xea: /* JP PE,nnnn */
sim_brk_pend = FALSE;
JPC(TSTFLAG(P));
break;
case 0xeb: /* EX DE,HL */
sim_brk_pend = FALSE;
temp = HL; HL = DE; DE = temp;
break;
case 0xec: /* CALL PE,nnnn */
CALLC(TSTFLAG(P));
break;
case 0xed: /* ED prefix */
checkCPU8080;
switch (op = RAM_pp(PC)) {
case 0x40: /* IN B,(C) */
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Sethreg(BC, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x41: /* OUT (C),B */
sim_brk_pend = FALSE;
out(lreg(BC), hreg(BC));
break;
case 0x42: /* SBC HL,BC */
sim_brk_pend = FALSE;
HL &= ADDRMASK;
BC &= ADDRMASK;
sum = HL - BC - TSTFLAG(C);
cbits = (HL ^ BC ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & ADDRMASK) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | 2 | ((cbits >> 8) & 1);
break;
case 0x43: /* LD (nnnn),BC */
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, BC);
PC += 2;
break;
case 0x44: /* NEG */
sim_brk_pend = FALSE;
temp = hreg(AF);
AF = ((~(AF & 0xff00) + 1) & 0xff00); /* 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;
CheckBreakWord(SP);
PCQ_ENTRY(PC - 2);
POP(PC);
break;
case 0x46: /* IM 0 */
sim_brk_pend = FALSE;
/* interrupt mode 0 */
break;
case 0x47: /* LD I,A */
sim_brk_pend = FALSE;
ir = (ir & 255) | (AF & ~255);
break;
case 0x48: /* IN C,(C) */
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Setlreg(BC, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x49: /* OUT (C),C */
sim_brk_pend = FALSE;
out(lreg(BC), lreg(BC));
break;
case 0x4a: /* ADC HL,BC */
sim_brk_pend = FALSE;
HL &= ADDRMASK;
BC &= ADDRMASK;
sum = HL + BC + TSTFLAG(C);
cbits = (HL ^ BC ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & ADDRMASK) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x4b: /* LD BC,(nnnn) */
temp = GetWORD(PC);
CheckBreakWord(temp);
BC = GetWORD(temp);
PC += 2;
break;
case 0x4d: /* RETI */
IFF |= IFF >> 1;
CheckBreakWord(SP);
PCQ_ENTRY(PC - 2);
POP(PC);
break;
case 0x4f: /* LD R,A */
sim_brk_pend = FALSE;
ir = (ir & ~255) | ((AF >> 8) & 255);
break;
case 0x50: /* IN D,(C) */
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Sethreg(DE, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x51: /* OUT (C),D */
sim_brk_pend = FALSE;
out(lreg(BC), hreg(DE));
break;
case 0x52: /* SBC HL,DE */
sim_brk_pend = FALSE;
HL &= ADDRMASK;
DE &= ADDRMASK;
sum = HL - DE - TSTFLAG(C);
cbits = (HL ^ DE ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & ADDRMASK) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | 2 | ((cbits >> 8) & 1);
break;
case 0x53: /* LD (nnnn),DE */
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, DE);
PC += 2;
break;
case 0x56: /* IM 1 */
sim_brk_pend = FALSE;
/* interrupt mode 1 */
break;
case 0x57: /* LD A,I */
sim_brk_pend = FALSE;
AF = (AF & 0x29) | (ir & ~255) | ((ir >> 8) & 0x80) | (((ir & ~255) == 0) << 6) | ((IFF & 2) << 1);
break;
case 0x58: /* IN E,(C) */
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Setlreg(DE, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x59: /* OUT (C),E */
sim_brk_pend = FALSE;
out(lreg(BC), lreg(DE));
break;
case 0x5a: /* ADC HL,DE */
sim_brk_pend = FALSE;
HL &= ADDRMASK;
DE &= ADDRMASK;
sum = HL + DE + TSTFLAG(C);
cbits = (HL ^ DE ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & ADDRMASK) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x5b: /* LD DE,(nnnn) */
temp = GetWORD(PC);
CheckBreakWord(temp);
DE = GetWORD(temp);
PC += 2;
break;
case 0x5e: /* IM 2 */
sim_brk_pend = FALSE;
/* interrupt mode 2 */
break;
case 0x5f: /* LD A,R */
sim_brk_pend = FALSE;
AF = (AF & 0x29) | ((ir & 255) << 8) | (ir & 0x80) | (((ir & 255) == 0) << 6) | ((IFF & 2) << 1);
break;
case 0x60: /* IN H,(C) */
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Sethreg(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x61: /* OUT (C),H */
sim_brk_pend = FALSE;
out(lreg(BC), hreg(HL));
break;
case 0x62: /* SBC HL,HL */
sim_brk_pend = FALSE;
HL &= ADDRMASK;
sum = HL - HL - TSTFLAG(C);
cbits = (HL ^ HL ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & ADDRMASK) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | 2 | ((cbits >> 8) & 1);
break;
case 0x63: /* LD (nnnn),HL */
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, HL);
PC += 2;
break;
case 0x67: /* RRD */
sim_brk_pend = FALSE;
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) */
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Setlreg(HL, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x69: /* OUT (C),L */
sim_brk_pend = FALSE;
out(lreg(BC), lreg(HL));
break;
case 0x6a: /* ADC HL,HL */
sim_brk_pend = FALSE;
HL &= ADDRMASK;
sum = HL + HL + TSTFLAG(C);
cbits = (HL ^ HL ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & ADDRMASK) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x6b: /* LD HL,(nnnn) */
temp = GetWORD(PC);
CheckBreakWord(temp);
HL = GetWORD(temp);
PC += 2;
break;
case 0x6f: /* RLD */
sim_brk_pend = FALSE;
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) */
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Setlreg(temp, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x71: /* OUT (C),0 */
sim_brk_pend = FALSE;
out(lreg(BC), 0);
break;
case 0x72: /* SBC HL,SP */
sim_brk_pend = FALSE;
HL &= ADDRMASK;
SP &= ADDRMASK;
sum = HL - SP - TSTFLAG(C);
cbits = (HL ^ SP ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & ADDRMASK) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | 2 | ((cbits >> 8) & 1);
break;
case 0x73: /* LD (nnnn),SP */
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, SP);
PC += 2;
break;
case 0x78: /* IN A,(C) */
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Sethreg(AF, temp);
AF = (AF & ~0xfe) | (temp & 0xa8) |
(((temp & 0xff) == 0) << 6) |
parity(temp);
break;
case 0x79: /* OUT (C),A */
sim_brk_pend = FALSE;
out(lreg(BC), hreg(AF));
break;
case 0x7a: /* ADC HL,SP */
sim_brk_pend = FALSE;
HL &= ADDRMASK;
SP &= ADDRMASK;
sum = HL + SP + TSTFLAG(C);
cbits = (HL ^ SP ^ sum) >> 8;
HL = sum;
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) |
(((sum & ADDRMASK) == 0) << 6) |
(((cbits >> 6) ^ (cbits >> 5)) & 4) |
(cbits & 0x10) | ((cbits >> 8) & 1);
break;
case 0x7b: /* LD SP,(nnnn) */
temp = GetWORD(PC);
CheckBreakWord(temp);
SP = GetWORD(temp);
PC += 2;
break;
case 0xa0: /* LDI */
CheckBreakTwoBytes(HL, DE);
acu = RAM_pp(HL);
PutBYTE_pp(DE, acu);
acu += hreg(AF);
AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) |
(((--BC & ADDRMASK) != 0) << 2);
break;
case 0xa1: /* CPI */
CheckBreakByte(HL);
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 & ADDRMASK) != 0) << 2 | 2;
if ((sum & 15) == 8 && (cbits & 16) != 0) {
AF &= ~8;
}
break;
case 0xa2: /* INI */
CheckBreakByte(HL);
PutBYTE(HL, in(lreg(BC))); ++HL;
SETFLAG(N, 1);
SETFLAG(P, (--BC & ADDRMASK) != 0);
break;
case 0xa3: /* OUTI */
CheckBreakByte(HL);
out(lreg(BC), GetBYTE(HL)); ++HL;
SETFLAG(N, 1);
Sethreg(BC, lreg(BC) - 1);
SETFLAG(Z, lreg(BC) == 0);
break;
case 0xa8: /* LDD */
CheckBreakTwoBytes(HL, DE);
acu = RAM_mm(HL);
PutBYTE_mm(DE, acu);
acu += hreg(AF);
AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) |
(((--BC & ADDRMASK) != 0) << 2);
break;
case 0xa9: /* CPD */
CheckBreakByte(HL);
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 & ADDRMASK) != 0) << 2 | 2;
if ((sum & 15) == 8 && (cbits & 16) != 0) {
AF &= ~8;
}
break;
case 0xaa: /* IND */
CheckBreakByte(HL);
PutBYTE(HL, in(lreg(BC))); --HL;
SETFLAG(N, 1);
Sethreg(BC, lreg(BC) - 1);
SETFLAG(Z, lreg(BC) == 0);
break;
case 0xab: /* OUTD */
CheckBreakByte(HL);
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 &= ADDRMASK;
do {
CheckBreakTwoBytes(HL, DE);
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 &= ADDRMASK;
do {
CheckBreakByte(HL);
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 {
CheckBreakByte(HL);
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 {
CheckBreakByte(HL);
out(lreg(BC), GetBYTE(HL)); ++HL;
} while (--temp);
Sethreg(BC, 0);
SETFLAG(N, 1);
SETFLAG(Z, 1);
break;
case 0xb8: /* LDDR */
BC &= ADDRMASK;
do {
CheckBreakTwoBytes(HL, DE);
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 &= ADDRMASK;
do {
CheckBreakByte(HL);
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 {
CheckBreakByte(HL);
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 {
CheckBreakByte(HL);
out(lreg(BC), GetBYTE(HL)); --HL;
} while (--temp);
Sethreg(BC, 0);
SETFLAG(N, 1);
SETFLAG(Z, 1);
break;
default: /* ignore ED and following byte */
sim_brk_pend = FALSE;
checkCPUZ80;
}
break;
case 0xee: /* XOR nn */
sim_brk_pend = FALSE;
sum = ((AF >> 8) ^ RAM_pp(PC)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xef: /* RST 28H */
CheckBreakWord(SP - 2);
PUSH(PC); PCQ_ENTRY(PC - 1); PC = 0x28;
break;
case 0xf0: /* RET P */
if (TSTFLAG(S)) {
sim_brk_pend = FALSE;
}
else {
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
}
break;
case 0xf1: /* POP AF */
CheckBreakWord(SP);
POP(AF);
break;
case 0xf2: /* JP P,nnnn */
sim_brk_pend = FALSE;
JPC(!TSTFLAG(S));
break;
case 0xf3: /* DI */
sim_brk_pend = FALSE;
IFF = 0;
break;
case 0xf4: /* CALL P,nnnn */
CALLC(!TSTFLAG(S));
break;
case 0xf5: /* PUSH AF */
CheckBreakWord(SP - 2);
PUSH(AF);
break;
case 0xf6: /* OR nn */
sim_brk_pend = FALSE;
sum = ((AF >> 8) | RAM_pp(PC)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xf7: /* RST 30H */
CheckBreakWord(SP - 2);
PUSH(PC); PCQ_ENTRY(PC - 1); PC = 0x30;
break;
case 0xf8: /* RET M */
if (TSTFLAG(S)) {
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
}
else {
sim_brk_pend = FALSE;
}
break;
case 0xf9: /* LD SP,HL */
sim_brk_pend = FALSE;
SP = HL;
break;
case 0xfa: /* JP M,nnnn */
sim_brk_pend = FALSE;
JPC(TSTFLAG(S));
break;
case 0xfb: /* EI */
sim_brk_pend = FALSE;
IFF = 3;
break;
case 0xfc: /* CALL M,nnnn */
CALLC(TSTFLAG(S));
break;
case 0xfd: /* FD prefix */
checkCPU8080;
switch (op = RAM_pp(PC)) {
case 0x09: /* ADD IY,BC */
sim_brk_pend = FALSE;
IY &= ADDRMASK;
BC &= ADDRMASK;
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 */
sim_brk_pend = FALSE;
IY &= ADDRMASK;
DE &= ADDRMASK;
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 */
sim_brk_pend = FALSE;
IY = GetWORD(PC);
PC += 2;
break;
case 0x22: /* LD (nnnn),IY */
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, IY);
PC += 2;
break;
case 0x23: /* INC IY */
sim_brk_pend = FALSE;
++IY;
break;
case 0x24: /* INC IYH */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
Sethreg(IY, RAM_pp(PC));
break;
case 0x29: /* ADD IY,IY */
sim_brk_pend = FALSE;
IY &= ADDRMASK;
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);
CheckBreakWord(temp);
IY = GetWORD(temp);
PC += 2;
break;
case 0x2b: /* DEC IY */
sim_brk_pend = FALSE;
--IY;
break;
case 0x2c: /* INC IYL */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
Setlreg(IY, RAM_pp(PC));
break;
case 0x34: /* INC (IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
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);
CheckBreakByte(adr);
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);
CheckBreakByte(adr);
PutBYTE(adr, RAM_pp(PC));
break;
case 0x39: /* ADD IY,SP */
sim_brk_pend = FALSE;
IY &= ADDRMASK;
SP &= ADDRMASK;
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 */
sim_brk_pend = FALSE;
Sethreg(BC, hreg(IY));
break;
case 0x45: /* LD B,IYL */
sim_brk_pend = FALSE;
Sethreg(BC, lreg(IY));
break;
case 0x46: /* LD B,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(BC, GetBYTE(adr));
break;
case 0x4c: /* LD C,IYH */
sim_brk_pend = FALSE;
Setlreg(BC, hreg(IY));
break;
case 0x4d: /* LD C,IYL */
sim_brk_pend = FALSE;
Setlreg(BC, lreg(IY));
break;
case 0x4e: /* LD C,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Setlreg(BC, GetBYTE(adr));
break;
case 0x54: /* LD D,IYH */
sim_brk_pend = FALSE;
Sethreg(DE, hreg(IY));
break;
case 0x55: /* LD D,IYL */
sim_brk_pend = FALSE;
Sethreg(DE, lreg(IY));
break;
case 0x56: /* LD D,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(DE, GetBYTE(adr));
break;
case 0x5c: /* LD E,H */
sim_brk_pend = FALSE;
Setlreg(DE, hreg(IY));
break;
case 0x5d: /* LD E,L */
sim_brk_pend = FALSE;
Setlreg(DE, lreg(IY));
break;
case 0x5e: /* LD E,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Setlreg(DE, GetBYTE(adr));
break;
case 0x60: /* LD IYH,B */
sim_brk_pend = FALSE;
Sethreg(IY, hreg(BC));
break;
case 0x61: /* LD IYH,C */
sim_brk_pend = FALSE;
Sethreg(IY, lreg(BC));
break;
case 0x62: /* LD IYH,D */
sim_brk_pend = FALSE;
Sethreg(IY, hreg(DE));
break;
case 0x63: /* LD IYH,E */
sim_brk_pend = FALSE;
Sethreg(IY, lreg(DE));
break;
case 0x64: /* LD IYH,IYH */
sim_brk_pend = FALSE;
/* nop */
break;
case 0x65: /* LD IYH,IYL */
sim_brk_pend = FALSE;
Sethreg(IY, lreg(IY));
break;
case 0x66: /* LD H,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(HL, GetBYTE(adr));
break;
case 0x67: /* LD IYH,A */
sim_brk_pend = FALSE;
Sethreg(IY, hreg(AF));
break;
case 0x68: /* LD IYL,B */
sim_brk_pend = FALSE;
Setlreg(IY, hreg(BC));
break;
case 0x69: /* LD IYL,C */
sim_brk_pend = FALSE;
Setlreg(IY, lreg(BC));
break;
case 0x6a: /* LD IYL,D */
sim_brk_pend = FALSE;
Setlreg(IY, hreg(DE));
break;
case 0x6b: /* LD IYL,E */
sim_brk_pend = FALSE;
Setlreg(IY, lreg(DE));
break;
case 0x6c: /* LD IYL,IYH */
sim_brk_pend = FALSE;
Setlreg(IY, hreg(IY));
break;
case 0x6d: /* LD IYL,IYL */
sim_brk_pend = FALSE;
/* nop */
break;
case 0x6e: /* LD L,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Setlreg(HL, GetBYTE(adr));
break;
case 0x6f: /* LD IYL,A */
sim_brk_pend = FALSE;
Setlreg(IY, hreg(AF));
break;
case 0x70: /* LD (IY+dd),B */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(BC));
break;
case 0x71: /* LD (IY+dd),C */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, lreg(BC));
break;
case 0x72: /* LD (IY+dd),D */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(DE));
break;
case 0x73: /* LD (IY+dd),E */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, lreg(DE));
break;
case 0x74: /* LD (IY+dd),H */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(HL));
break;
case 0x75: /* LD (IY+dd),L */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, lreg(HL));
break;
case 0x77: /* LD (IY+dd),A */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(AF));
break;
case 0x7c: /* LD A,IYH */
sim_brk_pend = FALSE;
Sethreg(AF, hreg(IY));
break;
case 0x7d: /* LD A,IYL */
sim_brk_pend = FALSE;
Sethreg(AF, lreg(IY));
break;
case 0x7e: /* LD A,(IY+dd) */
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(AF, GetBYTE(adr));
break;
case 0x84: /* ADD A,IYH */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
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 */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
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 */
sim_brk_pend = FALSE;
sum = ((AF & (IY)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) |
((sum == 0) << 6) | 0x10 | partab[sum];
break;
case 0xa5: /* AND IYL */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
sum = ((AF >> 8) & GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | 0x10 |
((sum == 0) << 6) | partab[sum];
break;
case 0xac: /* XOR IYH */
sim_brk_pend = FALSE;
sum = ((AF ^ (IY)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xad: /* XOR IYL */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
sum = ((AF >> 8) ^ GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xb4: /* OR IYH */
sim_brk_pend = FALSE;
sum = ((AF | (IY)) >> 8) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xb5: /* OR IYL */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
sum = ((AF >> 8) | GetBYTE(adr)) & 0xff;
AF = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | partab[sum];
break;
case 0xbc: /* CP IYH */
sim_brk_pend = FALSE;
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 */
sim_brk_pend = FALSE;
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);
CheckBreakByte(adr);
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);
switch ((op = GetBYTE(PC)) & 7) {
case 0: sim_brk_pend = FALSE; ++PC; acu = hreg(BC); break;
case 1: sim_brk_pend = FALSE; ++PC; acu = lreg(BC); break;
case 2: sim_brk_pend = FALSE; ++PC; acu = hreg(DE); break;
case 3: sim_brk_pend = FALSE; ++PC; acu = lreg(DE); break;
case 4: sim_brk_pend = FALSE; ++PC; acu = hreg(HL); break;
case 5: sim_brk_pend = FALSE; ++PC; acu = lreg(HL); break;
case 6: CheckBreakByte(adr); ++PC; acu = GetBYTE(adr); break;
case 7: sim_brk_pend = FALSE; ++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 */
CheckBreakWord(SP);
POP(IY);
break;
case 0xe3: /* EX (SP),IY */
CheckBreakWord(SP);
temp = IY; POP(IY); PUSH(temp);
break;
case 0xe5: /* PUSH IY */
CheckBreakWord(SP - 2);
PUSH(IY);
break;
case 0xe9: /* JP (IY) */
sim_brk_pend = FALSE;
PCQ_ENTRY(PC - 2);
PC = IY;
break;
case 0xf9: /* LD SP,IY */
sim_brk_pend = FALSE;
SP = IY;
break;
default: /* ignore FD */
sim_brk_pend = FALSE;
checkCPUZ80;
PC--;
}
break;
case 0xfe: /* CP nn */
sim_brk_pend = FALSE;
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 */
CheckBreakWord(SP - 2);
PUSH(PC); PCQ_ENTRY(PC - 1); PC = 0x38;
}
}
end_decode:
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) || (reason == STOP_MEM)) ? PCX : pc;
pcq_r -> qptr = pcq_p; /* update pc q ptr */
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;
}
int32 install_bootrom(void) {
int32 i, cnt = 0;
for (i = 0; i < bootrom_size; i++) {
if (M[i + defaultROMLow][0] != (bootrom[i] & 0xff)) {
cnt++;
M[i + defaultROMLow][0] = bootrom[i] & 0xff;
}
}
return cnt;
}
int32 lowProtect;
int32 highProtect;
int32 isProtected = FALSE;
void protect(int32 l, int32 h) {
isProtected = TRUE;
lowProtect = l;
highProtect = h;
}
void resetCell(int32 address, int32 bank) {
if (!(isProtected && (bank == 0) && (lowProtect <= address) && (address <= highProtect))) {
M[address][bank] = 0;
}
}
void reset_memory(void) {
uint32 i, j;
checkROMBoundaries();
if (cpu_unit.flags & UNIT_BANKED) {
for (i = 0; i < MAXMEMSIZE; i++) {
for (j = 0; j < MAXBANKS; j++) {
resetCell(i, j);
}
}
}
else if (cpu_unit.flags & UNIT_ROM) {
for (i = 0; i < ROMLow; i++) {
resetCell(i, 0);
}
for (i = ROMHigh+1; i < MAXMEMSIZE; i++) {
resetCell(i, 0);
}
}
else {
for (i = 0; i < MAXMEMSIZE; i++) {
resetCell(i, 0);
}
}
if (cpu_unit.flags & (UNIT_ALTAIRROM | UNIT_BANKED)) {
install_bootrom();
}
isProtected = FALSE;
}
/* Reset routine */
t_stat cpu_reset(DEVICE *dptr) {
int32 i;
AF_S = AF1_S = 0;
af_sel = 0;
BC_S = DE_S = HL_S = 0;
regs_sel = 0;
BC1_S = DE1_S = HL1_S = 0;
INT_S = IX_S = IY_S = SP_S = 0;
IFF_S = 3;
bankSelect = 0;
reset_memory();
sim_brk_types = (SWMASK('E') | SWMASK('M'));
sim_brk_dflt = SWMASK('E');
for (i = 0; i < PCQ_SIZE; i++) {
pcq[i] = 0;
}
pcq_p = 0;
pcq_r = find_reg("PCQ", NULL, dptr);
if (pcq_r) {
pcq_r -> qptr = 0;
}
else {
return SCPE_IERR;
}
return SCPE_OK;
}
/* Memory examine */
t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) {
if (addressExists(addr)) {
if (vptr != NULL) {
*vptr = GetBYTE(addr) & 0xff;
}
return SCPE_OK;
}
else {
return SCPE_NXM;
}
}
/* Memory deposit */
t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw) {
if (addressExists(addr) && (!addressIsInROM(addr))) {
PutBYTE(addr, val & 0xff);
return SCPE_OK;
}
else {
return SCPE_NXM;
}
}
void checkROMBoundaries(void) {
uint32 temp;
if (ROMLow > ROMHigh) {
printf("ROMLOW [%04X] must be less than or equal to ROMHIGH [%04X]. Values exchanged.\n",
ROMLow, ROMHigh);
temp = ROMLow;
ROMLow = ROMHigh;
ROMHigh = temp;
}
if (cpu_unit.flags & UNIT_ALTAIRROM) {
if (defaultROMLow < ROMLow) {
printf("ROMLOW [%04X] reset to %04X since Altair ROM was desired.\n", ROMLow, defaultROMLow);
ROMLow = defaultROMLow;
}
if (ROMHigh < defaultROMHigh) {
printf("ROMHIGH [%04X] reset to %04X since Altair ROM was desired.\n", ROMHigh, defaultROMHigh);
ROMHigh = defaultROMHigh;
}
}
}
t_stat cpu_set_rom(UNIT *uptr, int32 value, char *cptr, void *desc) {
checkROMBoundaries();
return SCPE_OK;
}
t_stat cpu_set_norom(UNIT *uptr, int32 value, char *cptr, void *desc) {
if (cpu_unit.flags & UNIT_ALTAIRROM) {
printf("\"SET CPU NOALTAIRROM\" also executed.\n");
cpu_unit.flags &= ~UNIT_ALTAIRROM;
}
return SCPE_OK;
}
t_stat cpu_set_altairrom(UNIT *uptr, int32 value, char *cptr, void *desc) {
install_bootrom();
if (ROMLow != defaultROMLow) {
printf("\"D ROMLOW %04X\" also executed.\n", defaultROMLow);
ROMLow = defaultROMLow;
}
if (ROMHigh != defaultROMHigh) {
printf("\"D ROMHIGH %04X\" also executed.\n", defaultROMHigh);
ROMHigh = defaultROMHigh;
}
if (!(cpu_unit.flags & UNIT_ROM)) {
printf("\"SET CPU ROM\" also executed.\n");
cpu_unit.flags |= UNIT_ROM;
}
return SCPE_OK;
}
t_stat cpu_set_warnrom(UNIT *uptr, int32 value, char *cptr, void *desc) {
if ((!(cpu_unit.flags & UNIT_ROM)) && (MEMSIZE == 64*KB)) {
printf("CPU has currently 64 Kb available for writing.\n");
}
return SCPE_OK;
}
t_stat cpu_set_banked(UNIT *uptr, int32 value, char *cptr, void *desc) {
if (common > defaultROMLow) {
printf("Warning: COMMON [%04X] must not be greater than %04X. Reset to %04X.\n",
common, defaultROMLow, defaultROMLow);
common = defaultROMLow;
}
if (MEMSIZE < MAXMEMSIZE) {
printf("\"SET CPU 64K\" also executed.\n");
MEMSIZE = MAXMEMSIZE;
reset_memory();
}
return SCPE_OK;
}
t_stat cpu_set_size(UNIT *uptr, int32 value, char *cptr, void *desc) {
if ((cpu_unit.flags & UNIT_BANKED) && (value < MAXMEMSIZE)) {
printf("\"SET CPU NONBANKED\" also executed.\n");
cpu_unit.flags &= ~UNIT_BANKED;
}
if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 0xfff) != 0)) {
return SCPE_ARG;
}
MEMSIZE = value;
reset_memory();
return SCPE_OK;
}