blob: 559e7741c72573c46104e04f986e58f954c51045 [file] [log] [blame] [raw]
/* altairz80_cpu.c: MITS Altair CPU (8080 and Z80)
Copyright (c) 2002-2004, 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
PETER SCHORN 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 "altairz80_defs.h"
#if !defined (_WIN32)
#include <unistd.h>
#endif
#define PCQ_SIZE 64 /* must be 2**n */
#define PCQ_SIZE_LOG2 6 /* log2 of PCQ_SIZE */
#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 0 /* HALT */
#define STOP_IBKPT 1 /* breakpoint (program counter) */
#define STOP_MEM 2 /* breakpoint (memory access) */
#define STOP_OPCODE 3 /* unknown 8080 or Z80 instruction */
/* two sets of accumulator / flags */
static uint16 af[2];
static int af_sel;
/* two sets of 16-bit registers */
static struct ddregs {
uint16 bc;
uint16 de;
uint16 hl;
} regs[2];
static int regs_sel;
static uint16 ir;
static uint16 ix;
static uint16 iy;
static uint16 sp;
static uint16 pc;
static 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))
#define parity(x) parityTable[(x) & 0xff]
/* SetPV and SetPV2 are used to provide correct parity flag semantics for the 8080 in cases
where the Z80 uses the overflow flag
*/
#define SetPVS(s) ((cpu_unit.flags & UNIT_CHIP) ? (((cbits >> 6) ^ (cbits >> 5)) & 4) : (parity(s)))
#define SetPV (SetPVS(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; \
}
*/
/* checkCPU8080 must be invoked whenever a Z80 only instruction is executed
In case a Z80 instruction is executed on an 8080 the following two cases exist:
1) Trapping is enabled: execution stops
2) Trapping is not enabled: decoding continues with the next byte
*/
#define checkCPU8080 \
if ((cpu_unit.flags & UNIT_CHIP) == 0) { \
if (cpu_unit.flags & UNIT_OPSTOP) { \
reason = STOP_OPCODE; \
goto end_decode; \
} \
else { \
sim_brk_pend = FALSE; \
continue; \
} \
}
/* 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; \
}
#define POP(x) { \
register uint32 y = RAM_pp(SP); \
x = y + (RAM_pp(SP) << 8); \
}
#define JPC(cond) { \
updateTStates(10); \
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; \
updateTStates(17); \
} \
else { \
sim_brk_pend = FALSE; \
PC += 2; \
updateTStates(10); \
} \
}
extern int32 sim_int_char;
extern int32 sio0s (const int32 port, const int32 io, const int32 data);
extern int32 sio0d (const int32 port, const int32 io, const int32 data);
extern int32 sio1s (const int32 port, const int32 io, const int32 data);
extern int32 sio1d (const int32 port, const int32 io, const int32 data);
extern int32 dsk10 (const int32 port, const int32 io, const int32 data);
extern int32 dsk11 (const int32 port, const int32 io, const int32 data);
extern int32 dsk12 (const int32 port, const int32 io, const int32 data);
extern int32 nulldev (const int32 port, const int32 io, const int32 data);
extern int32 hdsk_io (const int32 port, const int32 io, const int32 data);
extern int32 simh_dev (const int32 port, const int32 io, const int32 data);
extern int32 sr_dev (const int32 port, const int32 io, const int32 data);
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);
int32 sim_load(FILE *fileref, char *cptr, char *fnam, int32 flag);
void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Value);
void PutBYTEForced(register uint32 Addr, register uint32 Value);
int32 addressIsInROM(const uint32 Addr);
int32 addressExists(const uint32 Addr);
int32 sim_instr(void);
int32 install_bootrom(void);
void protect(const int32 l, const int32 h);
void printROMMessage(const uint32 cntROM);
uint8 GetBYTEWrapper(register uint32 Addr);
void PutBYTEWrapper(register uint32 Addr, register uint32 Value);
int32 getBankSelect(void);
void setBankSelect(int32 b);
uint32 getCommon(void);
void setCommon(uint32 c);
#if !defined(ALTAIROPT)
static void warnUnsuccessfulWriteAttempt(const uint32 Addr);
static uint8 warnUnsuccessfulReadAttempt(const uint32 Addr);
static t_stat cpu_set_rom (UNIT *uptr, int32 value, char *cptr, void *desc);
static t_stat cpu_set_norom (UNIT *uptr, int32 value, char *cptr, void *desc);
static t_stat cpu_set_altairrom (UNIT *uptr, int32 value, char *cptr, void *desc);
static t_stat cpu_set_warnrom (UNIT *uptr, int32 value, char *cptr, void *desc);
static t_stat cpu_set_banked (UNIT *uptr, int32 value, char *cptr, void *desc);
static t_stat cpu_set_nonbanked (UNIT *uptr, int32 value, char *cptr, void *desc);
#endif
static t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc);
static void prepareMemoryAccessMessage(t_addr loc);
static void checkROMBoundaries(void);
static void reset_memory(void);
static uint32 in(const uint32 Port);
static void out(const uint32 Port, const uint32 Value);
static uint8 GetBYTE(register uint32 Addr);
static void PutBYTE(register uint32 Addr, register uint32 Value);
static uint16 GetWORD(register uint32 a);
static void PutWORD(register uint32 a, register uint32 v);
static t_bool sim_brk_lookup (const t_addr bloc, const int32 btyp);
static void resetCell(const int32 address, const int32 bank);
/* 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 PCX; /* external view of PC */
int32 saved_PC = 0; /* program counter */
static int32 AF_S; /* AF register */
static int32 BC_S; /* BC register */
static int32 DE_S; /* DE register */
static int32 HL_S; /* HL register */
static int32 IX_S; /* IX register */
static int32 IY_S; /* IY register */
static int32 SP_S; /* SP register */
static int32 AF1_S; /* alternate AF register */
static int32 BC1_S; /* alternate BC register */
static int32 DE1_S; /* alternate DE register */
static int32 HL1_S; /* alternate HL register */
static int32 IFF_S; /* interrupt Flip Flop */
static int32 IR_S; /* interrupt (upper)/refresh (lower) register */
int32 SR = 0; /* switch register */
#if !defined(ALTAIROPT)
static int32 bankSelect = 0; /* determines selected memory bank */
static uint32 common = 0xc000; /* addresses >= 'common' are in common memory */
#endif
static uint32 ROMLow = defaultROMLow; /* lowest address of ROM */
static uint32 ROMHigh = defaultROMHigh; /* highest address of ROM */
static uint32 previousCapacity= 0; /* safe for previous memory capacity */
static uint32 clockFrequency = 0; /* in kHz, 0 means as fast as possible */
static uint32 sliceLength = 10; /* length of time-slice for CPU speed */
/* adjustment in milliseonds */
static uint32 executedTStates = 0; /* executed t-states */
static uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
static int32 pcq_p = 0; /* PC queue ptr */
static 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 (IR, IR_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) },
#if defined(ALTAIROPT)
{ HRDATA (ROMLOW, ROMLow, 16), REG_RO },
{ HRDATA (ROMHIGH, ROMHigh, 16), REG_RO },
#else
{ HRDATA (BANK, bankSelect, MAXBANKSLOG2) },
{ HRDATA (COMMON, common, 16) },
{ HRDATA (ROMLOW, ROMLow, 16) },
{ HRDATA (ROMHIGH, ROMHigh, 16) },
#endif
{ DRDATA (CLOCK, clockFrequency, 32) },
{ DRDATA (SLICE, sliceLength, 16) },
{ DRDATA (TSTATES, executedTStates,32), REG_RO },
{ HRDATA (CAPACITY, cpu_unit.capac, 32), REG_RO },
{ HRDATA (PREVCAP, previousCapacity, 32), REG_RO },
{ BRDATA (PCQ, pcq, 16, 16, PCQ_SIZE), REG_RO + REG_CIRC },
{ DRDATA (PCQP, pcq_p, PCQ_SIZE_LOG2), REG_HRO },
{ HRDATA (WRU, sim_int_char, 8) },
{ NULL } };
static 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 },
#if !defined(ALTAIROPT)
{ UNIT_BANKED, UNIT_BANKED, "BANKED", "BANKED", &cpu_set_banked },
{ UNIT_BANKED, 0, "NONBANKED", "NONBANKED", &cpu_set_nonbanked },
{ 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 },
#endif
{ 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, 0,
NULL, NULL, NULL };
/* data structure for IN/OUT instructions */
struct idev {
int32 (*routine)(const int32, const int32, const 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
*/
static const 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 */
};
static INLINE void out(const uint32 Port, const uint32 Value) {
dev_table[Port].routine(Port, 1, Value);
}
static INLINE uint32 in(const uint32 Port) {
return dev_table[Port].routine(Port, 0, 0);
}
/* the following tables precompute some common subexpressions
parityTable[i] 0..255 (number of 1's in i is odd) ? 0 : 4
incTable[i] 0..256! (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0) << 4)
decTable[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0xf) << 4) | 2
cbitsTable[i] 0..511 (i & 0x10) | ((i >> 8) & 1)
cbitsDup8Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | ((i & 0xff) << 8) | (i & 0xa8) |
(((i & 0xff) == 0) << 6)
cbitsDup16Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | (i & 0x28)
cbits2Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | 2
rrcaTable[i] 0..255 ((i & 1) << 15) | ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1)
rraTable[i] 0..255 ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1)
addTable[i] 0..511 ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6)
subTable[i] 0..255 ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | 2
andTable[i] 0..255 (i << 8) | (i & 0xa8) | ((i == 0) << 6) | 0x10 | parityTable[i]
xororTable[i] 0..255 (i << 8) | (i & 0xa8) | ((i == 0) << 6) | parityTable[i]
rotateShiftTable[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i & 0xff]
incZ80Table[i] 0..256! (i & 0xa8) | (((i & 0xff) == 0) << 6) |
(((i & 0xf) == 0) << 4) | ((i == 0x80) << 2)
decZ80Table[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) |
(((i & 0xf) == 0xf) << 4) | ((i == 0x7f) << 2) | 2
cbitsZ80Table[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1)
cbitsZ80DupTable[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) |
((i >> 8) & 1) | (i & 0xa8)
cbits2Z80Table[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2
cbits2Z80DupTable[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 |
(i & 0xa8)
negTable[i] 0..255 (((i & 0x0f) != 0) << 4) | ((i == 0x80) << 2) | 2 | (i != 0)
rrdrldTable[i] 0..255 (i << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i]
cpTable[i] 0..255 (i & 0x80) | (((i & 0xff) == 0) << 6)
*/
/* parityTable[i] = (number of 1's in i is odd) ? 0 : 4, i = 0..255 */
static const uint8 parityTable[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,
};
/* incTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0) << 4), i = 0..256 */
static const uint8 incTable[257] = {
80, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40,
48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40,
16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40,
48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40,
144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136,
144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136,
176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168,
176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168,
144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136,
144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136,
176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168,
176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 80
};
/* decTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0xf) << 4) | 2, i = 0..255 */
static const uint8 decTable[256] = {
66, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26,
2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26,
34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58,
34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58,
2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26,
2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26,
34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58,
34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58,
130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154,
130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154,
162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186,
162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186,
130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154,
130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154,
162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186,
162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186,
};
/* cbitsTable[i] = (i & 0x10) | ((i >> 8) & 1), i = 0..511 */
static const uint8 cbitsTable[512] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
};
/* cbitsDup8Table[i] = (i & 0x10) | ((i >> 8) & 1) | ((i & 0xff) << 8) | (i & 0xa8) |
(((i & 0xff) == 0) << 6), i = 0..511 */
static const uint16 cbitsDup8Table[512] = {
0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700,
0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08,
0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710,
0x1818,0x1918,0x1a18,0x1b18,0x1c18,0x1d18,0x1e18,0x1f18,
0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720,
0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28,
0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,0x3630,0x3730,
0x3838,0x3938,0x3a38,0x3b38,0x3c38,0x3d38,0x3e38,0x3f38,
0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700,
0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08,
0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710,
0x5818,0x5918,0x5a18,0x5b18,0x5c18,0x5d18,0x5e18,0x5f18,
0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720,
0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28,
0x7030,0x7130,0x7230,0x7330,0x7430,0x7530,0x7630,0x7730,
0x7838,0x7938,0x7a38,0x7b38,0x7c38,0x7d38,0x7e38,0x7f38,
0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780,
0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88,
0x9090,0x9190,0x9290,0x9390,0x9490,0x9590,0x9690,0x9790,
0x9898,0x9998,0x9a98,0x9b98,0x9c98,0x9d98,0x9e98,0x9f98,
0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0,
0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8,
0xb0b0,0xb1b0,0xb2b0,0xb3b0,0xb4b0,0xb5b0,0xb6b0,0xb7b0,
0xb8b8,0xb9b8,0xbab8,0xbbb8,0xbcb8,0xbdb8,0xbeb8,0xbfb8,
0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780,
0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88,
0xd090,0xd190,0xd290,0xd390,0xd490,0xd590,0xd690,0xd790,
0xd898,0xd998,0xda98,0xdb98,0xdc98,0xdd98,0xde98,0xdf98,
0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0,
0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8,
0xf0b0,0xf1b0,0xf2b0,0xf3b0,0xf4b0,0xf5b0,0xf6b0,0xf7b0,
0xf8b8,0xf9b8,0xfab8,0xfbb8,0xfcb8,0xfdb8,0xfeb8,0xffb8,
0x0041,0x0101,0x0201,0x0301,0x0401,0x0501,0x0601,0x0701,
0x0809,0x0909,0x0a09,0x0b09,0x0c09,0x0d09,0x0e09,0x0f09,
0x1011,0x1111,0x1211,0x1311,0x1411,0x1511,0x1611,0x1711,
0x1819,0x1919,0x1a19,0x1b19,0x1c19,0x1d19,0x1e19,0x1f19,
0x2021,0x2121,0x2221,0x2321,0x2421,0x2521,0x2621,0x2721,
0x2829,0x2929,0x2a29,0x2b29,0x2c29,0x2d29,0x2e29,0x2f29,
0x3031,0x3131,0x3231,0x3331,0x3431,0x3531,0x3631,0x3731,
0x3839,0x3939,0x3a39,0x3b39,0x3c39,0x3d39,0x3e39,0x3f39,
0x4001,0x4101,0x4201,0x4301,0x4401,0x4501,0x4601,0x4701,
0x4809,0x4909,0x4a09,0x4b09,0x4c09,0x4d09,0x4e09,0x4f09,
0x5011,0x5111,0x5211,0x5311,0x5411,0x5511,0x5611,0x5711,
0x5819,0x5919,0x5a19,0x5b19,0x5c19,0x5d19,0x5e19,0x5f19,
0x6021,0x6121,0x6221,0x6321,0x6421,0x6521,0x6621,0x6721,
0x6829,0x6929,0x6a29,0x6b29,0x6c29,0x6d29,0x6e29,0x6f29,
0x7031,0x7131,0x7231,0x7331,0x7431,0x7531,0x7631,0x7731,
0x7839,0x7939,0x7a39,0x7b39,0x7c39,0x7d39,0x7e39,0x7f39,
0x8081,0x8181,0x8281,0x8381,0x8481,0x8581,0x8681,0x8781,
0x8889,0x8989,0x8a89,0x8b89,0x8c89,0x8d89,0x8e89,0x8f89,
0x9091,0x9191,0x9291,0x9391,0x9491,0x9591,0x9691,0x9791,
0x9899,0x9999,0x9a99,0x9b99,0x9c99,0x9d99,0x9e99,0x9f99,
0xa0a1,0xa1a1,0xa2a1,0xa3a1,0xa4a1,0xa5a1,0xa6a1,0xa7a1,
0xa8a9,0xa9a9,0xaaa9,0xaba9,0xaca9,0xada9,0xaea9,0xafa9,
0xb0b1,0xb1b1,0xb2b1,0xb3b1,0xb4b1,0xb5b1,0xb6b1,0xb7b1,
0xb8b9,0xb9b9,0xbab9,0xbbb9,0xbcb9,0xbdb9,0xbeb9,0xbfb9,
0xc081,0xc181,0xc281,0xc381,0xc481,0xc581,0xc681,0xc781,
0xc889,0xc989,0xca89,0xcb89,0xcc89,0xcd89,0xce89,0xcf89,
0xd091,0xd191,0xd291,0xd391,0xd491,0xd591,0xd691,0xd791,
0xd899,0xd999,0xda99,0xdb99,0xdc99,0xdd99,0xde99,0xdf99,
0xe0a1,0xe1a1,0xe2a1,0xe3a1,0xe4a1,0xe5a1,0xe6a1,0xe7a1,
0xe8a9,0xe9a9,0xeaa9,0xeba9,0xeca9,0xeda9,0xeea9,0xefa9,
0xf0b1,0xf1b1,0xf2b1,0xf3b1,0xf4b1,0xf5b1,0xf6b1,0xf7b1,
0xf8b9,0xf9b9,0xfab9,0xfbb9,0xfcb9,0xfdb9,0xfeb9,0xffb9,
};
/* cbitsDup16Table[i] = (i & 0x10) | ((i >> 8) & 1) | (i & 0x28), i = 0..511 */
static const uint8 cbitsDup16Table[512] = {
0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24,
32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40,
48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56,
0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24,
32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40,
48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56,
0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24,
32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40,
48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56,
0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24,
32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40,
48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56,
1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9,
17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25,
33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41,
49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57,
1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9,
17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25,
33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41,
49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57,
1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9,
17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25,
33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41,
49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57,
1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9,
17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25,
33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41,
49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57,
};
/* cbits2Table[i] = (i & 0x10) | ((i >> 8) & 1) | 2, i = 0..511 */
static const uint8 cbits2Table[512] = {
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
};
/* rrcaTable[i] = ((i & 1) << 15) | ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1), i = 0..255 */
static const uint16 rrcaTable[256] = {
0x0000,0x8001,0x0100,0x8101,0x0200,0x8201,0x0300,0x8301,
0x0400,0x8401,0x0500,0x8501,0x0600,0x8601,0x0700,0x8701,
0x0808,0x8809,0x0908,0x8909,0x0a08,0x8a09,0x0b08,0x8b09,
0x0c08,0x8c09,0x0d08,0x8d09,0x0e08,0x8e09,0x0f08,0x8f09,
0x1000,0x9001,0x1100,0x9101,0x1200,0x9201,0x1300,0x9301,
0x1400,0x9401,0x1500,0x9501,0x1600,0x9601,0x1700,0x9701,
0x1808,0x9809,0x1908,0x9909,0x1a08,0x9a09,0x1b08,0x9b09,
0x1c08,0x9c09,0x1d08,0x9d09,0x1e08,0x9e09,0x1f08,0x9f09,
0x2020,0xa021,0x2120,0xa121,0x2220,0xa221,0x2320,0xa321,
0x2420,0xa421,0x2520,0xa521,0x2620,0xa621,0x2720,0xa721,
0x2828,0xa829,0x2928,0xa929,0x2a28,0xaa29,0x2b28,0xab29,
0x2c28,0xac29,0x2d28,0xad29,0x2e28,0xae29,0x2f28,0xaf29,
0x3020,0xb021,0x3120,0xb121,0x3220,0xb221,0x3320,0xb321,
0x3420,0xb421,0x3520,0xb521,0x3620,0xb621,0x3720,0xb721,
0x3828,0xb829,0x3928,0xb929,0x3a28,0xba29,0x3b28,0xbb29,
0x3c28,0xbc29,0x3d28,0xbd29,0x3e28,0xbe29,0x3f28,0xbf29,
0x4000,0xc001,0x4100,0xc101,0x4200,0xc201,0x4300,0xc301,
0x4400,0xc401,0x4500,0xc501,0x4600,0xc601,0x4700,0xc701,
0x4808,0xc809,0x4908,0xc909,0x4a08,0xca09,0x4b08,0xcb09,
0x4c08,0xcc09,0x4d08,0xcd09,0x4e08,0xce09,0x4f08,0xcf09,
0x5000,0xd001,0x5100,0xd101,0x5200,0xd201,0x5300,0xd301,
0x5400,0xd401,0x5500,0xd501,0x5600,0xd601,0x5700,0xd701,
0x5808,0xd809,0x5908,0xd909,0x5a08,0xda09,0x5b08,0xdb09,
0x5c08,0xdc09,0x5d08,0xdd09,0x5e08,0xde09,0x5f08,0xdf09,
0x6020,0xe021,0x6120,0xe121,0x6220,0xe221,0x6320,0xe321,
0x6420,0xe421,0x6520,0xe521,0x6620,0xe621,0x6720,0xe721,
0x6828,0xe829,0x6928,0xe929,0x6a28,0xea29,0x6b28,0xeb29,
0x6c28,0xec29,0x6d28,0xed29,0x6e28,0xee29,0x6f28,0xef29,
0x7020,0xf021,0x7120,0xf121,0x7220,0xf221,0x7320,0xf321,
0x7420,0xf421,0x7520,0xf521,0x7620,0xf621,0x7720,0xf721,
0x7828,0xf829,0x7928,0xf929,0x7a28,0xfa29,0x7b28,0xfb29,
0x7c28,0xfc29,0x7d28,0xfd29,0x7e28,0xfe29,0x7f28,0xff29,
};
/* rraTable[i] = ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1), i = 0..255 */
static const uint16 rraTable[256] = {
0x0000,0x0001,0x0100,0x0101,0x0200,0x0201,0x0300,0x0301,
0x0400,0x0401,0x0500,0x0501,0x0600,0x0601,0x0700,0x0701,
0x0808,0x0809,0x0908,0x0909,0x0a08,0x0a09,0x0b08,0x0b09,
0x0c08,0x0c09,0x0d08,0x0d09,0x0e08,0x0e09,0x0f08,0x0f09,
0x1000,0x1001,0x1100,0x1101,0x1200,0x1201,0x1300,0x1301,
0x1400,0x1401,0x1500,0x1501,0x1600,0x1601,0x1700,0x1701,
0x1808,0x1809,0x1908,0x1909,0x1a08,0x1a09,0x1b08,0x1b09,
0x1c08,0x1c09,0x1d08,0x1d09,0x1e08,0x1e09,0x1f08,0x1f09,
0x2020,0x2021,0x2120,0x2121,0x2220,0x2221,0x2320,0x2321,
0x2420,0x2421,0x2520,0x2521,0x2620,0x2621,0x2720,0x2721,
0x2828,0x2829,0x2928,0x2929,0x2a28,0x2a29,0x2b28,0x2b29,
0x2c28,0x2c29,0x2d28,0x2d29,0x2e28,0x2e29,0x2f28,0x2f29,
0x3020,0x3021,0x3120,0x3121,0x3220,0x3221,0x3320,0x3321,
0x3420,0x3421,0x3520,0x3521,0x3620,0x3621,0x3720,0x3721,
0x3828,0x3829,0x3928,0x3929,0x3a28,0x3a29,0x3b28,0x3b29,
0x3c28,0x3c29,0x3d28,0x3d29,0x3e28,0x3e29,0x3f28,0x3f29,
0x4000,0x4001,0x4100,0x4101,0x4200,0x4201,0x4300,0x4301,
0x4400,0x4401,0x4500,0x4501,0x4600,0x4601,0x4700,0x4701,
0x4808,0x4809,0x4908,0x4909,0x4a08,0x4a09,0x4b08,0x4b09,
0x4c08,0x4c09,0x4d08,0x4d09,0x4e08,0x4e09,0x4f08,0x4f09,
0x5000,0x5001,0x5100,0x5101,0x5200,0x5201,0x5300,0x5301,
0x5400,0x5401,0x5500,0x5501,0x5600,0x5601,0x5700,0x5701,
0x5808,0x5809,0x5908,0x5909,0x5a08,0x5a09,0x5b08,0x5b09,
0x5c08,0x5c09,0x5d08,0x5d09,0x5e08,0x5e09,0x5f08,0x5f09,
0x6020,0x6021,0x6120,0x6121,0x6220,0x6221,0x6320,0x6321,
0x6420,0x6421,0x6520,0x6521,0x6620,0x6621,0x6720,0x6721,
0x6828,0x6829,0x6928,0x6929,0x6a28,0x6a29,0x6b28,0x6b29,
0x6c28,0x6c29,0x6d28,0x6d29,0x6e28,0x6e29,0x6f28,0x6f29,
0x7020,0x7021,0x7120,0x7121,0x7220,0x7221,0x7320,0x7321,
0x7420,0x7421,0x7520,0x7521,0x7620,0x7621,0x7720,0x7721,
0x7828,0x7829,0x7928,0x7929,0x7a28,0x7a29,0x7b28,0x7b29,
0x7c28,0x7c29,0x7d28,0x7d29,0x7e28,0x7e29,0x7f28,0x7f29,
};
/* addTable[i] = ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6), i = 0..511 */
static const uint16 addTable[512] = {
0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700,
0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08,
0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700,
0x1808,0x1908,0x1a08,0x1b08,0x1c08,0x1d08,0x1e08,0x1f08,
0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720,
0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28,
0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,0x3620,0x3720,
0x3828,0x3928,0x3a28,0x3b28,0x3c28,0x3d28,0x3e28,0x3f28,
0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700,
0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08,
0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700,
0x5808,0x5908,0x5a08,0x5b08,0x5c08,0x5d08,0x5e08,0x5f08,
0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720,
0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28,
0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,0x7620,0x7720,
0x7828,0x7928,0x7a28,0x7b28,0x7c28,0x7d28,0x7e28,0x7f28,
0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780,
0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88,
0x9080,0x9180,0x9280,0x9380,0x9480,0x9580,0x9680,0x9780,
0x9888,0x9988,0x9a88,0x9b88,0x9c88,0x9d88,0x9e88,0x9f88,
0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0,
0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8,
0xb0a0,0xb1a0,0xb2a0,0xb3a0,0xb4a0,0xb5a0,0xb6a0,0xb7a0,
0xb8a8,0xb9a8,0xbaa8,0xbba8,0xbca8,0xbda8,0xbea8,0xbfa8,
0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780,
0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88,
0xd080,0xd180,0xd280,0xd380,0xd480,0xd580,0xd680,0xd780,
0xd888,0xd988,0xda88,0xdb88,0xdc88,0xdd88,0xde88,0xdf88,
0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0,
0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8,
0xf0a0,0xf1a0,0xf2a0,0xf3a0,0xf4a0,0xf5a0,0xf6a0,0xf7a0,
0xf8a8,0xf9a8,0xfaa8,0xfba8,0xfca8,0xfda8,0xfea8,0xffa8,
0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700,
0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08,
0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700,
0x1808,0x1908,0x1a08,0x1b08,0x1c08,0x1d08,0x1e08,0x1f08,
0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720,
0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28,
0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,0x3620,0x3720,
0x3828,0x3928,0x3a28,0x3b28,0x3c28,0x3d28,0x3e28,0x3f28,
0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700,
0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08,
0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700,
0x5808,0x5908,0x5a08,0x5b08,0x5c08,0x5d08,0x5e08,0x5f08,
0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720,
0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28,
0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,0x7620,0x7720,
0x7828,0x7928,0x7a28,0x7b28,0x7c28,0x7d28,0x7e28,0x7f28,
0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780,
0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88,
0x9080,0x9180,0x9280,0x9380,0x9480,0x9580,0x9680,0x9780,
0x9888,0x9988,0x9a88,0x9b88,0x9c88,0x9d88,0x9e88,0x9f88,
0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0,
0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8,
0xb0a0,0xb1a0,0xb2a0,0xb3a0,0xb4a0,0xb5a0,0xb6a0,0xb7a0,
0xb8a8,0xb9a8,0xbaa8,0xbba8,0xbca8,0xbda8,0xbea8,0xbfa8,
0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780,
0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88,
0xd080,0xd180,0xd280,0xd380,0xd480,0xd580,0xd680,0xd780,
0xd888,0xd988,0xda88,0xdb88,0xdc88,0xdd88,0xde88,0xdf88,
0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0,
0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8,
0xf0a0,0xf1a0,0xf2a0,0xf3a0,0xf4a0,0xf5a0,0xf6a0,0xf7a0,
0xf8a8,0xf9a8,0xfaa8,0xfba8,0xfca8,0xfda8,0xfea8,0xffa8,
};
/* subTable[i] = ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | 2, i = 0..255 */
static const uint16 subTable[256] = {
0x0042,0x0102,0x0202,0x0302,0x0402,0x0502,0x0602,0x0702,
0x080a,0x090a,0x0a0a,0x0b0a,0x0c0a,0x0d0a,0x0e0a,0x0f0a,
0x1002,0x1102,0x1202,0x1302,0x1402,0x1502,0x1602,0x1702,
0x180a,0x190a,0x1a0a,0x1b0a,0x1c0a,0x1d0a,0x1e0a,0x1f0a,
0x2022,0x2122,0x2222,0x2322,0x2422,0x2522,0x2622,0x2722,
0x282a,0x292a,0x2a2a,0x2b2a,0x2c2a,0x2d2a,0x2e2a,0x2f2a,
0x3022,0x3122,0x3222,0x3322,0x3422,0x3522,0x3622,0x3722,
0x382a,0x392a,0x3a2a,0x3b2a,0x3c2a,0x3d2a,0x3e2a,0x3f2a,
0x4002,0x4102,0x4202,0x4302,0x4402,0x4502,0x4602,0x4702,
0x480a,0x490a,0x4a0a,0x4b0a,0x4c0a,0x4d0a,0x4e0a,0x4f0a,
0x5002,0x5102,0x5202,0x5302,0x5402,0x5502,0x5602,0x5702,
0x580a,0x590a,0x5a0a,0x5b0a,0x5c0a,0x5d0a,0x5e0a,0x5f0a,
0x6022,0x6122,0x6222,0x6322,0x6422,0x6522,0x6622,0x6722,
0x682a,0x692a,0x6a2a,0x6b2a,0x6c2a,0x6d2a,0x6e2a,0x6f2a,
0x7022,0x7122,0x7222,0x7322,0x7422,0x7522,0x7622,0x7722,
0x782a,0x792a,0x7a2a,0x7b2a,0x7c2a,0x7d2a,0x7e2a,0x7f2a,
0x8082,0x8182,0x8282,0x8382,0x8482,0x8582,0x8682,0x8782,
0x888a,0x898a,0x8a8a,0x8b8a,0x8c8a,0x8d8a,0x8e8a,0x8f8a,
0x9082,0x9182,0x9282,0x9382,0x9482,0x9582,0x9682,0x9782,
0x988a,0x998a,0x9a8a,0x9b8a,0x9c8a,0x9d8a,0x9e8a,0x9f8a,
0xa0a2,0xa1a2,0xa2a2,0xa3a2,0xa4a2,0xa5a2,0xa6a2,0xa7a2,
0xa8aa,0xa9aa,0xaaaa,0xabaa,0xacaa,0xadaa,0xaeaa,0xafaa,
0xb0a2,0xb1a2,0xb2a2,0xb3a2,0xb4a2,0xb5a2,0xb6a2,0xb7a2,
0xb8aa,0xb9aa,0xbaaa,0xbbaa,0xbcaa,0xbdaa,0xbeaa,0xbfaa,
0xc082,0xc182,0xc282,0xc382,0xc482,0xc582,0xc682,0xc782,
0xc88a,0xc98a,0xca8a,0xcb8a,0xcc8a,0xcd8a,0xce8a,0xcf8a,
0xd082,0xd182,0xd282,0xd382,0xd482,0xd582,0xd682,0xd782,
0xd88a,0xd98a,0xda8a,0xdb8a,0xdc8a,0xdd8a,0xde8a,0xdf8a,
0xe0a2,0xe1a2,0xe2a2,0xe3a2,0xe4a2,0xe5a2,0xe6a2,0xe7a2,
0xe8aa,0xe9aa,0xeaaa,0xebaa,0xecaa,0xedaa,0xeeaa,0xefaa,
0xf0a2,0xf1a2,0xf2a2,0xf3a2,0xf4a2,0xf5a2,0xf6a2,0xf7a2,
0xf8aa,0xf9aa,0xfaaa,0xfbaa,0xfcaa,0xfdaa,0xfeaa,0xffaa,
};
/* andTable[i] = (i << 8) | (i & 0xa8) | ((i == 0) << 6) | 0x10 | parityTable[i], i = 0..255 */
static const uint16 andTable[256] = {
0x0054,0x0110,0x0210,0x0314,0x0410,0x0514,0x0614,0x0710,
0x0818,0x091c,0x0a1c,0x0b18,0x0c1c,0x0d18,0x0e18,0x0f1c,
0x1010,0x1114,0x1214,0x1310,0x1414,0x1510,0x1610,0x1714,
0x181c,0x1918,0x1a18,0x1b1c,0x1c18,0x1d1c,0x1e1c,0x1f18,
0x2030,0x2134,0x2234,0x2330,0x2434,0x2530,0x2630,0x2734,
0x283c,0x2938,0x2a38,0x2b3c,0x2c38,0x2d3c,0x2e3c,0x2f38,
0x3034,0x3130,0x3230,0x3334,0x3430,0x3534,0x3634,0x3730,
0x3838,0x393c,0x3a3c,0x3b38,0x3c3c,0x3d38,0x3e38,0x3f3c,
0x4010,0x4114,0x4214,0x4310,0x4414,0x4510,0x4610,0x4714,
0x481c,0x4918,0x4a18,0x4b1c,0x4c18,0x4d1c,0x4e1c,0x4f18,
0x5014,0x5110,0x5210,0x5314,0x5410,0x5514,0x5614,0x5710,
0x5818,0x591c,0x5a1c,0x5b18,0x5c1c,0x5d18,0x5e18,0x5f1c,
0x6034,0x6130,0x6230,0x6334,0x6430,0x6534,0x6634,0x6730,
0x6838,0x693c,0x6a3c,0x6b38,0x6c3c,0x6d38,0x6e38,0x6f3c,
0x7030,0x7134,0x7234,0x7330,0x7434,0x7530,0x7630,0x7734,
0x783c,0x7938,0x7a38,0x7b3c,0x7c38,0x7d3c,0x7e3c,0x7f38,
0x8090,0x8194,0x8294,0x8390,0x8494,0x8590,0x8690,0x8794,
0x889c,0x8998,0x8a98,0x8b9c,0x8c98,0x8d9c,0x8e9c,0x8f98,
0x9094,0x9190,0x9290,0x9394,0x9490,0x9594,0x9694,0x9790,
0x9898,0x999c,0x9a9c,0x9b98,0x9c9c,0x9d98,0x9e98,0x9f9c,
0xa0b4,0xa1b0,0xa2b0,0xa3b4,0xa4b0,0xa5b4,0xa6b4,0xa7b0,
0xa8b8,0xa9bc,0xaabc,0xabb8,0xacbc,0xadb8,0xaeb8,0xafbc,
0xb0b0,0xb1b4,0xb2b4,0xb3b0,0xb4b4,0xb5b0,0xb6b0,0xb7b4,
0xb8bc,0xb9b8,0xbab8,0xbbbc,0xbcb8,0xbdbc,0xbebc,0xbfb8,
0xc094,0xc190,0xc290,0xc394,0xc490,0xc594,0xc694,0xc790,
0xc898,0xc99c,0xca9c,0xcb98,0xcc9c,0xcd98,0xce98,0xcf9c,
0xd090,0xd194,0xd294,0xd390,0xd494,0xd590,0xd690,0xd794,
0xd89c,0xd998,0xda98,0xdb9c,0xdc98,0xdd9c,0xde9c,0xdf98,
0xe0b0,0xe1b4,0xe2b4,0xe3b0,0xe4b4,0xe5b0,0xe6b0,0xe7b4,
0xe8bc,0xe9b8,0xeab8,0xebbc,0xecb8,0xedbc,0xeebc,0xefb8,
0xf0b4,0xf1b0,0xf2b0,0xf3b4,0xf4b0,0xf5b4,0xf6b4,0xf7b0,
0xf8b8,0xf9bc,0xfabc,0xfbb8,0xfcbc,0xfdb8,0xfeb8,0xffbc,
};
/* xororTable[i] = (i << 8) | (i & 0xa8) | ((i == 0) << 6) | parityTable[i], i = 0..255 */
static const uint16 xororTable[256] = {
0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700,
0x0808,0x090c,0x0a0c,0x0b08,0x0c0c,0x0d08,0x0e08,0x0f0c,
0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704,
0x180c,0x1908,0x1a08,0x1b0c,0x1c08,0x1d0c,0x1e0c,0x1f08,
0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724,
0x282c,0x2928,0x2a28,0x2b2c,0x2c28,0x2d2c,0x2e2c,0x2f28,
0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720,
0x3828,0x392c,0x3a2c,0x3b28,0x3c2c,0x3d28,0x3e28,0x3f2c,
0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704,
0x480c,0x4908,0x4a08,0x4b0c,0x4c08,0x4d0c,0x4e0c,0x4f08,
0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700,
0x5808,0x590c,0x5a0c,0x5b08,0x5c0c,0x5d08,0x5e08,0x5f0c,
0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720,
0x6828,0x692c,0x6a2c,0x6b28,0x6c2c,0x6d28,0x6e28,0x6f2c,
0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724,
0x782c,0x7928,0x7a28,0x7b2c,0x7c28,0x7d2c,0x7e2c,0x7f28,
0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784,
0x888c,0x8988,0x8a88,0x8b8c,0x8c88,0x8d8c,0x8e8c,0x8f88,
0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780,
0x9888,0x998c,0x9a8c,0x9b88,0x9c8c,0x9d88,0x9e88,0x9f8c,
0xa0a4,0xa1a0,0xa2a0,0xa3a4,0xa4a0,0xa5a4,0xa6a4,0xa7a0,
0xa8a8,0xa9ac,0xaaac,0xaba8,0xacac,0xada8,0xaea8,0xafac,
0xb0a0,0xb1a4,0xb2a4,0xb3a0,0xb4a4,0xb5a0,0xb6a0,0xb7a4,
0xb8ac,0xb9a8,0xbaa8,0xbbac,0xbca8,0xbdac,0xbeac,0xbfa8,
0xc084,0xc180,0xc280,0xc384,0xc480,0xc584,0xc684,0xc780,
0xc888,0xc98c,0xca8c,0xcb88,0xcc8c,0xcd88,0xce88,0xcf8c,
0xd080,0xd184,0xd284,0xd380,0xd484,0xd580,0xd680,0xd784,
0xd88c,0xd988,0xda88,0xdb8c,0xdc88,0xdd8c,0xde8c,0xdf88,
0xe0a0,0xe1a4,0xe2a4,0xe3a0,0xe4a4,0xe5a0,0xe6a0,0xe7a4,
0xe8ac,0xe9a8,0xeaa8,0xebac,0xeca8,0xedac,0xeeac,0xefa8,
0xf0a4,0xf1a0,0xf2a0,0xf3a4,0xf4a0,0xf5a4,0xf6a4,0xf7a0,
0xf8a8,0xf9ac,0xfaac,0xfba8,0xfcac,0xfda8,0xfea8,0xffac,
};
/* rotateShiftTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i & 0xff], i = 0..255 */
static const uint8 rotateShiftTable[256] = {
68, 0, 0, 4, 0, 4, 4, 0, 8, 12, 12, 8, 12, 8, 8, 12,
0, 4, 4, 0, 4, 0, 0, 4, 12, 8, 8, 12, 8, 12, 12, 8,
32, 36, 36, 32, 36, 32, 32, 36, 44, 40, 40, 44, 40, 44, 44, 40,
36, 32, 32, 36, 32, 36, 36, 32, 40, 44, 44, 40, 44, 40, 40, 44,
0, 4, 4, 0, 4, 0, 0, 4, 12, 8, 8, 12, 8, 12, 12, 8,
4, 0, 0, 4, 0, 4, 4, 0, 8, 12, 12, 8, 12, 8, 8, 12,
36, 32, 32, 36, 32, 36, 36, 32, 40, 44, 44, 40, 44, 40, 40, 44,
32, 36, 36, 32, 36, 32, 32, 36, 44, 40, 40, 44, 40, 44, 44, 40,
128,132,132,128,132,128,128,132,140,136,136,140,136,140,140,136,
132,128,128,132,128,132,132,128,136,140,140,136,140,136,136,140,
164,160,160,164,160,164,164,160,168,172,172,168,172,168,168,172,
160,164,164,160,164,160,160,164,172,168,168,172,168,172,172,168,
132,128,128,132,128,132,132,128,136,140,140,136,140,136,136,140,
128,132,132,128,132,128,128,132,140,136,136,140,136,140,140,136,
160,164,164,160,164,160,160,164,172,168,168,172,168,172,172,168,
164,160,160,164,160,164,164,160,168,172,172,168,172,168,168,172,
};
/* incZ80Table[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) |
(((i & 0xf) == 0) << 4) | ((i == 0x80) << 2), i = 0..256 */
static const uint8 incZ80Table[257] = {
80, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40,
48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40,
16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40,
48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40,
148,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136,
144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136,
176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168,
176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168,
144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136,
144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136,
176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168,
176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 80,
};
/* decZ80Table[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) |
(((i & 0xf) == 0xf) << 4) | ((i == 0x7f) << 2) | 2, i = 0..255 */
static const uint8 decZ80Table[256] = {
66, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26,
2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26,
34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58,
34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58,
2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26,
2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26,
34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58,
34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 62,
130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154,
130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154,
162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186,
162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186,
130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154,
130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154,
162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186,
162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186,
};
/* cbitsZ80Table[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1), i = 0..511 */
static const uint8 cbitsZ80Table[512] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
};
/* cbitsZ80DupTable[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) |
((i >> 8) & 1) | (i & 0xa8), i = 0..511 */
static const uint8 cbitsZ80DupTable[512] = {
0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24,
32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40,
48, 48, 48, 48, 48, 48, 48, 48, 56, 56, 56, 56, 56, 56, 56, 56,
0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24,
32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40,
48, 48, 48, 48, 48, 48, 48, 48, 56, 56, 56, 56, 56, 56, 56, 56,
132,132,132,132,132,132,132,132,140,140,140,140,140,140,140,140,
148,148,148,148,148,148,148,148,156,156,156,156,156,156,156,156,
164,164,164,164,164,164,164,164,172,172,172,172,172,172,172,172,
180,180,180,180,180,180,180,180,188,188,188,188,188,188,188,188,
132,132,132,132,132,132,132,132,140,140,140,140,140,140,140,140,
148,148,148,148,148,148,148,148,156,156,156,156,156,156,156,156,
164,164,164,164,164,164,164,164,172,172,172,172,172,172,172,172,
180,180,180,180,180,180,180,180,188,188,188,188,188,188,188,188,
5, 5, 5, 5, 5, 5, 5, 5, 13, 13, 13, 13, 13, 13, 13, 13,
21, 21, 21, 21, 21, 21, 21, 21, 29, 29, 29, 29, 29, 29, 29, 29,
37, 37, 37, 37, 37, 37, 37, 37, 45, 45, 45, 45, 45, 45, 45, 45,
53, 53, 53, 53, 53, 53, 53, 53, 61, 61, 61, 61, 61, 61, 61, 61,
5, 5, 5, 5, 5, 5, 5, 5, 13, 13, 13, 13, 13, 13, 13, 13,
21, 21, 21, 21, 21, 21, 21, 21, 29, 29, 29, 29, 29, 29, 29, 29,
37, 37, 37, 37, 37, 37, 37, 37, 45, 45, 45, 45, 45, 45, 45, 45,
53, 53, 53, 53, 53, 53, 53, 53, 61, 61, 61, 61, 61, 61, 61, 61,
129,129,129,129,129,129,129,129,137,137,137,137,137,137,137,137,
145,145,145,145,145,145,145,145,153,153,153,153,153,153,153,153,
161,161,161,161,161,161,161,161,169,169,169,169,169,169,169,169,
177,177,177,177,177,177,177,177,185,185,185,185,185,185,185,185,
129,129,129,129,129,129,129,129,137,137,137,137,137,137,137,137,
145,145,145,145,145,145,145,145,153,153,153,153,153,153,153,153,
161,161,161,161,161,161,161,161,169,169,169,169,169,169,169,169,
177,177,177,177,177,177,177,177,185,185,185,185,185,185,185,185,
};
/* cbits2Z80Table[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2, i = 0..511 */
static const uint8 cbits2Z80Table[512] = {
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
};
/* cbits2Z80DupTable[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 |
(i & 0xa8), i = 0..511 */
static const uint8 cbits2Z80DupTable[512] = {
2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10,
18, 18, 18, 18, 18, 18, 18, 18, 26, 26, 26, 26, 26, 26, 26, 26,
34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 42,
50, 50, 50, 50, 50, 50, 50, 50, 58, 58, 58, 58, 58, 58, 58, 58,
2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10,
18, 18, 18, 18, 18, 18, 18, 18, 26, 26, 26, 26, 26, 26, 26, 26,
34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 42,
50, 50, 50, 50, 50, 50, 50, 50, 58, 58, 58, 58, 58, 58, 58, 58,
134,134,134,134,134,134,134,134,142,142,142,142,142,142,142,142,
150,150,150,150,150,150,150,150,158,158,158,158,158,158,158,158,
166,166,166,166,166,166,166,166,174,174,174,174,174,174,174,174,
182,182,182,182,182,182,182,182,190,190,190,190,190,190,190,190,
134,134,134,134,134,134,134,134,142,142,142,142,142,142,142,142,
150,150,150,150,150,150,150,150,158,158,158,158,158,158,158,158,
166,166,166,166,166,166,166,166,174,174,174,174,174,174,174,174,
182,182,182,182,182,182,182,182,190,190,190,190,190,190,190,190,
7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 15,
23, 23, 23, 23, 23, 23, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31,
39, 39, 39, 39, 39, 39, 39, 39, 47, 47, 47, 47, 47, 47, 47, 47,
55, 55, 55, 55, 55, 55, 55, 55, 63, 63, 63, 63, 63, 63, 63, 63,
7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 15,
23, 23, 23, 23, 23, 23, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31,
39, 39, 39, 39, 39, 39, 39, 39, 47, 47, 47, 47, 47, 47, 47, 47,
55, 55, 55, 55, 55, 55, 55, 55, 63, 63, 63, 63, 63, 63, 63, 63,
131,131,131,131,131,131,131,131,139,139,139,139,139,139,139,139,
147,147,147,147,147,147,147,147,155,155,155,155,155,155,155,155,
163,163,163,163,163,163,163,163,171,171,171,171,171,171,171,171,
179,179,179,179,179,179,179,179,187,187,187,187,187,187,187,187,
131,131,131,131,131,131,131,131,139,139,139,139,139,139,139,139,
147,147,147,147,147,147,147,147,155,155,155,155,155,155,155,155,
163,163,163,163,163,163,163,163,171,171,171,171,171,171,171,171,
179,179,179,179,179,179,179,179,187,187,187,187,187,187,187,187,
};
/* negTable[i] = (((i & 0x0f) != 0) << 4) | ((i == 0x80) << 2) | 2 | (i != 0), i = 0..255 */
static const uint8 negTable[256] = {
2,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
7,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
};
/* rrdrldTable[i] = (i << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i], i = 0..255 */
static const uint16 rrdrldTable[256] = {
0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700,
0x0808,0x090c,0x0a0c,0x0b08,0x0c0c,0x0d08,0x0e08,0x0f0c,
0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704,
0x180c,0x1908,0x1a08,0x1b0c,0x1c08,0x1d0c,0x1e0c,0x1f08,
0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724,
0x282c,0x2928,0x2a28,0x2b2c,0x2c28,0x2d2c,0x2e2c,0x2f28,
0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720,
0x3828,0x392c,0x3a2c,0x3b28,0x3c2c,0x3d28,0x3e28,0x3f2c,
0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704,
0x480c,0x4908,0x4a08,0x4b0c,0x4c08,0x4d0c,0x4e0c,0x4f08,
0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700,
0x5808,0x590c,0x5a0c,0x5b08,0x5c0c,0x5d08,0x5e08,0x5f0c,
0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720,
0x6828,0x692c,0x6a2c,0x6b28,0x6c2c,0x6d28,0x6e28,0x6f2c,
0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724,
0x782c,0x7928,0x7a28,0x7b2c,0x7c28,0x7d2c,0x7e2c,0x7f28,
0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784,
0x888c,0x8988,0x8a88,0x8b8c,0x8c88,0x8d8c,0x8e8c,0x8f88,
0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780,
0x9888,0x998c,0x9a8c,0x9b88,0x9c8c,0x9d88,0x9e88,0x9f8c,
0xa0a4,0xa1a0,0xa2a0,0xa3a4,0xa4a0,0xa5a4,0xa6a4,0xa7a0,
0xa8a8,0xa9ac,0xaaac,0xaba8,0xacac,0xada8,0xaea8,0xafac,
0xb0a0,0xb1a4,0xb2a4,0xb3a0,0xb4a4,0xb5a0,0xb6a0,0xb7a4,
0xb8ac,0xb9a8,0xbaa8,0xbbac,0xbca8,0xbdac,0xbeac,0xbfa8,
0xc084,0xc180,0xc280,0xc384,0xc480,0xc584,0xc684,0xc780,
0xc888,0xc98c,0xca8c,0xcb88,0xcc8c,0xcd88,0xce88,0xcf8c,
0xd080,0xd184,0xd284,0xd380,0xd484,0xd580,0xd680,0xd784,
0xd88c,0xd988,0xda88,0xdb8c,0xdc88,0xdd8c,0xde8c,0xdf88,
0xe0a0,0xe1a4,0xe2a4,0xe3a0,0xe4a4,0xe5a0,0xe6a0,0xe7a4,
0xe8ac,0xe9a8,0xeaa8,0xebac,0xeca8,0xedac,0xeeac,0xefa8,
0xf0a4,0xf1a0,0xf2a0,0xf3a4,0xf4a0,0xf5a4,0xf6a4,0xf7a0,
0xf8a8,0xf9ac,0xfaac,0xfba8,0xfcac,0xfda8,0xfea8,0xffac,
};
/* cpTable[i] = (i & 0x80) | (((i & 0xff) == 0) << 6), i = 0..255 */
static const uint8 cpTable[256] = {
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
};
/* remove comments to generate table contents
static void altairz80_init(void);
void (*sim_vm_init) (void) = &altairz80_init;
static void altairz80_init(void) {
*/
/* parityTable */
/*
uint32 i, v;
for (i = 0; i < 256; i++) {
v = ((i & 1) + ((i & 2) >> 1) + ((i & 4) >> 2) + ((i & 8) >> 3) +
((i & 16) >> 4) + ((i & 32) >> 5) + ((i & 64) >> 6) + ((i & 128) >> 7)) % 2 ? 0 : 4;
printf("%1d,", v);
if ( ((i+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* incTable */
/*
uint32 temp, v;
for (temp = 0; temp <= 256; temp++) {
v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | (((temp & 0xf) == 0) << 4);
printf("%3d,", v);
if ( ((temp+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* decTable */
/*
uint32 temp, v;
for (temp = 0; temp < 256; temp++) {
v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | (((temp & 0xf) == 0xf) << 4) | 2;
printf("%3d,", v);
if ( ((temp+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* cbitsTable */
/*
uint32 cbits, v;
for (cbits = 0; cbits < 512; cbits++) {
v = (cbits & 0x10) | ((cbits >> 8) & 1);
printf("%2d,", v);
if ( ((cbits+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* cbitsDup8Table */
/*
uint32 cbits, v;
for (cbits = 0; cbits < 512; cbits++) {
v = (cbits & 0x10) | ((cbits >> 8) & 1) | ((cbits & 0xff) << 8) | (cbits & 0xa8) | (((cbits & 0xff) == 0) << 6);
printf("0x%04x,", v);
if ( ((cbits+1) & 0x7) == 0) {
printf("\n");
}
}
*/
/* cbitsDup16Table */
/*
uint32 cbits, v;
for (cbits = 0; cbits < 512; cbits++) {
v = (cbits & 0x10) | ((cbits >> 8) & 1) | (cbits & 0x28);
printf("%2d,", v);
if ( ((cbits+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* cbits2Table */
/*
uint32 cbits, v;
for (cbits = 0; cbits < 512; cbits++) {
v = (cbits & 0x10) | ((cbits >> 8) & 1) | 2;
printf("%2d,", v);
if ( ((cbits+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* rrcaTable */
/*
uint32 temp, sum, v;
for (temp = 0; temp < 256; temp++) {
sum = temp >> 1;
v = ((temp & 1) << 15) | (sum << 8) | (sum & 0x28) | (temp & 1);
printf("0x%04x,", v);
if ( ((temp+1) & 0x7) == 0) {
printf("\n");
}
}
*/
/* rraTable */
/*
uint32 temp, sum, v;
for (temp = 0; temp < 256; temp++) {
sum = temp >> 1;
v = (sum << 8) | (sum & 0x28) | (temp & 1);
printf("0x%04x,", v);
if ( ((temp+1) & 0x7) == 0) {
printf("\n");
}
}
*/
/* addTable */
/*
uint32 sum, v;
for (sum = 0; sum < 512; sum++) {
v = ((sum & 0xff) << 8) | (sum & 0xa8) | (((sum & 0xff) == 0) << 6);
printf("0x%04x,", v);
if ( ((sum+1) & 0x7) == 0) {
printf("\n");
}
}
*/
/* subTable */
/*
uint32 sum, v;
for (sum = 0; sum < 256; sum++) {
v = ((sum & 0xff) << 8) | (sum & 0xa8) | (((sum & 0xff) == 0) << 6) | 2;
printf("0x%04x,", v);
if ( ((sum+1) & 0x7) == 0) {
printf("\n");
}
}
*/
/* andTable */
/*
uint32 sum, v;
for (sum = 0; sum < 256; sum++) {
v = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | 0x10 | parityTable[sum];
printf("0x%04x,", v);
if ( ((sum+1) & 0x7) == 0) {
printf("\n");
}
}
*/
/* xororTable */
/*
uint32 sum, v;
for (sum = 0; sum < 256; sum++) {
v = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | parityTable[sum];
printf("0x%04x,", v);
if ( ((sum+1) & 0x7) == 0) {
printf("\n");
}
}
*/
/* rotateShiftTable */
/*
uint32 temp, v;
for (temp = 0; temp < 256; temp++) {
v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | parity(temp);
printf("%3d,", v);
if ( ((temp+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* incZ80Table */
/*
uint32 temp, v;
for (temp = 0; temp < 256; temp++) {
v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0) << 4) | ((temp == 0x80) << 2);
printf("%3d,", v);
if ( ((temp+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* decZ80Table */
/*
uint32 temp, v;
for (temp = 0; temp < 256; temp++) {
v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) |
(((temp & 0xf) == 0xf) << 4) | ((temp == 0x7f) << 2) | 2;
printf("%3d,", v);
if ( ((temp+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* cbitsZ80Table */
/*
uint32 cbits, v;
for (cbits = 0; cbits < 512; cbits++) {
v = (cbits & 0x10) | (((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1);
printf("%2d,", v);
if ( ((cbits+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* cbitsZ80DupTable */
/*
uint32 cbits, v;
for (cbits = 0; cbits < 512; cbits++) {
v = (cbits & 0x10) | (((cbits >> 6) ^ (cbits >> 5)) & 4) |
((cbits >> 8) & 1) | (cbits & 0xa8);
printf("%3d,", v);
if ( ((cbits+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* cbits2Z80Table */
/*
uint32 cbits, v;
for (cbits = 0; cbits < 512; cbits++) {
v = (((cbits >> 6) ^ (cbits >> 5)) & 4) | (cbits & 0x10) | 2 | ((cbits >> 8) & 1);
printf("%2d,", v);
if ( ((cbits+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* cbits2Z80DupTable */
/*
uint32 cbits, v;
for (cbits = 0; cbits < 512; cbits++) {
v = (((cbits >> 6) ^ (cbits >> 5)) & 4) | (cbits & 0x10) | 2 | ((cbits >> 8) & 1) |
(cbits & 0xa8);
printf("%3d,", v);
if ( ((cbits+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* negTable */
/*
uint32 temp, v;
for (temp = 0; temp < 256; temp++) {
v = (((temp & 0x0f) != 0) << 4) | ((temp == 0x80) << 2) | 2 | (temp != 0);
printf("%2d,", v);
if ( ((temp+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* rrdrldTable */
/*
uint32 acu, v;
for (acu = 0; acu < 256; acu++) {
v = (acu << 8) | (acu & 0xa8) | (((acu & 0xff) == 0) << 6) | parityTable[acu];
printf("0x%04x,", v);
if ( ((acu+1) & 0x7) == 0) {
printf("\n");
}
}
*/
/* cpTable */
/*
uint32 sum, v;
for (sum = 0; sum < 256; sum++) {
v = (sum & 0x80) | (((sum & 0xff) == 0) << 6);
printf("%3d,", v);
if ( ((sum+1) & 0xf) == 0) {
printf("\n");
}
}
*/
/* remove comments to generate table contents
}
*/
/* Memory management. Two options available:
1) All features (ROM checking, ROM boundaries definable at run time, banked memory)
2) Bare bones (faster, no checking, no banked memory) - define ALTAIROPT
*/
static int32 lowProtect;
static int32 highProtect;
static int32 isProtected = FALSE;
void protect(const int32 l, const int32 h) {
isProtected = TRUE;
lowProtect = l;
highProtect = h;
}
#if defined(ALTAIROPT)
static uint8 M[MAXMEMSIZE]; /* RAM which is present */
/* determine whether Addr points to Read Only Memory */
INLINE int32 addressIsInROM(const uint32 Addr) {
return FALSE;
}
/* determine whether Addr points to a valid memory address */
INLINE int32 addressExists(const uint32 Addr) {
return TRUE;
}
#if defined(ALTAIROPTMACRO)
#define GetBYTE(Addr) M[(Addr) & ADDRMASK]
#define PutBYTE(Addr, Value) M[(Addr) & ADDRMASK] = Value;
#define PutWORD(Addr, Value) \
M[(Addr) & ADDRMASK] = Value; \
M[((Addr) + 1) & ADDRMASK] = Value >> 8;
#else
static INLINE uint8 GetBYTE(register uint32 Addr) {
return M[Addr & ADDRMASK];
}
static INLINE void PutBYTE(register uint32 Addr, register uint32 Value) {
M[Addr & ADDRMASK] = Value;
}
static INLINE void PutWORD(register uint32 Addr, register uint32 Value) {
M[Addr & ADDRMASK] = Value;
M[(Addr + 1) & ADDRMASK] = Value >> 8;
}
#endif
INLINE void PutBYTEForced(register uint32 Addr, register uint32 Value) {
M[Addr & ADDRMASK] = Value;
}
void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Value) {
M[Addr & ADDRMASK] = Value;
}
int32 install_bootrom(void) {
extern int32 bootrom[bootrom_size];
int32 i, cnt = 0;
for (i = 0; i < bootrom_size; i++) {
if (M[i + defaultROMLow] != (bootrom[i] & 0xff)) {
cnt++;
M[i + defaultROMLow] = bootrom[i] & 0xff;
}
}
return cnt;
}
static void resetCell(const int32 address, const int32 bank) {
if (!(isProtected && (lowProtect <= address) && (address <= highProtect))) {
M[address] = 0;
}
}
/* memory examine */
t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) {
*vptr = M[addr & ADDRMASK];
return SCPE_OK;
}
/* memory deposit */
t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw) {
M[addr & ADDRMASK] = val & 0xff;
return SCPE_OK;
}
int32 getBankSelect(void) {
return 0;
}
void setBankSelect(int32 b) {
}
uint32 getCommon(void) {
return 0;
}
void setCommon(uint32 c) {
}
#else
static uint8 M[MAXMEMSIZE][MAXBANKS]; /* RAM which is present */
static void warnUnsuccessfulWriteAttempt(const uint32 Addr) {
if (cpu_unit.flags & UNIT_WARNROM) {
if (addressIsInROM(Addr)) {
message2("Attempt to write to ROM " AddressFormat ".", Addr);
}
else {
message2("Attempt to write to non existing memory " AddressFormat ".", Addr);
}
}
}
static uint8 warnUnsuccessfulReadAttempt(const uint32 Addr) {
if (cpu_unit.flags & UNIT_WARNROM) {
message2("Attempt to read from non existing memory " AddressFormat ".", Addr);
}
return 0xff;
}
/* determine whether Addr points to Read Only Memory */
int32 addressIsInROM(const uint32 Addr) {
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(const uint32 Addr) {
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) );
}
static 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);
}
}
static 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);
}
}
}
static 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);
}
}
}
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;
}
}
void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Value) {
M[Addr & ADDRMASK][Bank & BANKMASK] = Value;
}
int32 install_bootrom(void) {
extern int32 bootrom[bootrom_size];
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;
}
static void resetCell(const int32 address, const int32 bank) {
if (!(isProtected && (bank == 0) && (lowProtect <= address) && (address <= highProtect))) {
M[address][bank] = 0;
}
}
/* memory examine */
t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) {
*vptr = M[addr & ADDRMASK][(addr >> 16) & BANKMASK];
return SCPE_OK;
}
/* memory deposit */
t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw) {
M[addr & ADDRMASK][(addr >> 16) & BANKMASK] = val & 0xff;
return SCPE_OK;
}
int32 getBankSelect(void) {
return bankSelect;
}
void setBankSelect(int32 b) {
bankSelect = b;
}
uint32 getCommon(void) {
return common;
}
void setCommon(uint32 c) {
common = c;
}
#endif
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);
}
#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)
static INLINE uint16 GetWORD(register uint32 a) {
return GetBYTE(a) | (GetBYTE(a + 1) << 8);
}
#define MASK_BRK (TRUE + 1)
/* 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
*/
static int32 sim_brk_lookup (const t_addr loc, const int32 btyp) {
extern t_bool sim_brk_pend;
extern t_addr sim_brk_ploc;
extern char *sim_brk_act;
BRKTAB *bp;
if ((bp = sim_brk_fnd (loc)) && /* entry in table? */
(btyp & bp -> typ) && /* type match? */
(!sim_brk_pend || (loc != sim_brk_ploc)) && /* new location? */
(--(bp -> cnt) <= 0)) { /* count reach 0? */
bp -> cnt = 0; /* reset count */
sim_brk_ploc = loc; /* save location */
sim_brk_act = bp -> act; /* set up actions */
sim_brk_pend = TRUE; /* don't do twice */
return TRUE;
}
return (sim_brk_pend && (loc == sim_brk_ploc)) ? MASK_BRK : FALSE;
}
static void prepareMemoryAccessMessage(t_addr loc) {
extern char memoryAccessMessage[];
sprintf(memoryAccessMessage, "Memory access breakpoint [%04xh]", loc);
}
#define PUSH(x) { \
mm_PutBYTE(SP, (x) >> 8); \
mm_PutBYTE(SP, x); \
}
#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))
#define updateTStates(n) \
tStates += n; \
if (sim_step) { \
if (sim_switches & SWMASK ('T')) { sim_step -= n; } else { sim_step--; } \
if (sim_step <= 0) { reason = SCPE_STOP; goto end_decode; } \
}
int32 sim_instr (void) {
extern int32 sim_switches;
extern int32 sim_step;
extern int32 sim_interval;
extern t_bool sim_brk_pend;
extern int32 timerInterrupt;
extern int32 timerInterruptHandler;
extern uint32 sim_os_msec(void);
extern t_bool rtc_avail;
extern int32 sim_brk_summ;
int32 reason = 0;
register uint32 specialProcessing;
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 = 0;
register uint32 acu = 0;
register uint32 sum;
register uint32 cbits;
register uint32 op;
register uint32 adr;
/* tStates contains the number of t-states executed. One t-state is executed
in one microsecond on a 1MHz CPU. tStates is used for real-time simulations. */
register uint32 tStates;
uint32 tStatesInSlice; /* number of t-states in 10 mSec time-slice */
uint32 startTime;
int32 br1, br2, tStateModifier = FALSE;
sim_cancel_step ();
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 = IR_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;
specialProcessing = clockFrequency | timerInterrupt | sim_brk_summ;
tStates = 0;
if (rtc_avail) {
startTime = sim_os_msec();
tStatesInSlice = sliceLength*clockFrequency;
}
else { /* make sure that sim_os_msec() is not called later */
clockFrequency = startTime = tStatesInSlice = 0;
}
/* main instruction fetch/decode loop */
while (TRUE) { /* loop until halted */
if (sim_interval <= 0) { /* check clock queue */
if ( (reason = sim_process_event()) ) {
break;
}
else {
specialProcessing = clockFrequency | timerInterrupt | sim_brk_summ;
}
}
if (specialProcessing) { /* quick check for special processing */
if (clockFrequency && (tStates >= tStatesInSlice)) {
/* clockFrequency != 0 implies that real time clock is available */
startTime += sliceLength;
tStates -= tStatesInSlice;
#if defined (_WIN32)
while (sim_os_msec() <= startTime) {} /* poor man's sleep */
#else
{
uint32 now;
if (startTime > (now = sim_os_msec())) {
usleep(1000 * (startTime - now));
}
}
#endif
}
if (timerInterrupt && (IFF & 1)) {
timerInterrupt = FALSE;
specialProcessing = clockFrequency | sim_brk_summ;
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 */
updateTStates(4);
sim_brk_pend = FALSE;
break;
case 0x01: /* LD BC,nnnn */
updateTStates(10);
sim_brk_pend = FALSE;
BC = GetWORD(PC);
PC += 2;
break;
case 0x02: /* LD (BC),A */
updateTStates(7);
CheckBreakByte(BC)
PutBYTE(BC, hreg(AF));
break;
case 0x03: /* INC BC */
updateTStates(6);
sim_brk_pend = FALSE;
++BC;
break;
case 0x04: /* INC B */
updateTStates(4);
sim_brk_pend = FALSE;
BC += 0x100;
temp = hreg(BC);
AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); /* SetPV2 uses temp */
break;
case 0x05: /* DEC B */
updateTStates(4);
sim_brk_pend = FALSE;
BC -= 0x100;
temp = hreg(BC);
AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); /* SetPV2 uses temp */
break;
case 0x06: /* LD B,nn */
updateTStates(7);
sim_brk_pend = FALSE;
Sethreg(BC, RAM_pp(PC));
break;
case 0x07: /* RLCA */
updateTStates(4);
sim_brk_pend = FALSE;
AF = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) |
(AF & 0xc4) | ((AF >> 15) & 1);
break;
case 0x08: /* EX AF,AF' */
updateTStates(4);
sim_brk_pend = FALSE;
checkCPU8080;
af[af_sel] = AF;
af_sel = 1 - af_sel;
AF = af[af_sel];
break;
case 0x09: /* ADD HL,BC */
updateTStates(11);
sim_brk_pend = FALSE;
HL &= ADDRMASK;
BC &= ADDRMASK;
sum = HL + BC;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ BC ^ sum) >> 8];
HL = sum;
break;
case 0x0a: /* LD A,(BC) */
updateTStates(7);
CheckBreakByte(BC)
Sethreg(AF, GetBYTE(BC));
break;
case 0x0b: /* DEC BC */
updateTStates(6);
sim_brk_pend = FALSE;
--BC;
break;
case 0x0c: /* INC C */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(BC) + 1;
Setlreg(BC, temp);
AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80);
break;
case 0x0d: /* DEC C */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(BC) - 1;
Setlreg(BC, temp);
AF = (AF & ~0xfe) | decTable[temp & 0xff] | SetPV2(0x7f);
break;
case 0x0e: /* LD C,nn */
updateTStates(7);
sim_brk_pend = FALSE;
Setlreg(BC, RAM_pp(PC));
break;
case 0x0f: /* RRCA */
updateTStates(4);
sim_brk_pend = FALSE;
AF = (AF & 0xc4) | rrcaTable[hreg(AF)];
break;
case 0x10: /* DJNZ dd */
sim_brk_pend = FALSE;
checkCPU8080;
if ((BC -= 0x100) & 0xff00) {
PCQ_ENTRY(PC - 1);
PC += (signed char) GetBYTE(PC) + 1;
updateTStates(13);
}
else {
PC++;
updateTStates(8);
}
break;
case 0x11: /* LD DE,nnnn */
updateTStates(10);
sim_brk_pend = FALSE;
DE = GetWORD(PC);
PC += 2;
break;
case 0x12: /* LD (DE),A */
updateTStates(7);
CheckBreakByte(DE)
PutBYTE(DE, hreg(AF));
break;
case 0x13: /* INC DE */
updateTStates(6);
sim_brk_pend = FALSE;
++DE;
break;
case 0x14: /* INC D */
updateTStates(4);
sim_brk_pend = FALSE;
DE += 0x100;
temp = hreg(DE);
AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); /* SetPV2 uses temp */
break;
case 0x15: /* DEC D */
updateTStates(4);
sim_brk_pend = FALSE;
DE -= 0x100;
temp = hreg(DE);
AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); /* SetPV2 uses temp */
break;
case 0x16: /* LD D,nn */
updateTStates(7);
sim_brk_pend = FALSE;
Sethreg(DE, RAM_pp(PC));
break;
case 0x17: /* RLA */
updateTStates(4);
sim_brk_pend = FALSE;
AF = ((AF << 8) & 0x0100) | ((AF >> 7) & 0x28) | ((AF << 1) & ~0x01ff) |
(AF & 0xc4) | ((AF >> 15) & 1);
break;
case 0x18: /* JR dd */
updateTStates(12);
sim_brk_pend = FALSE;
checkCPU8080;
PCQ_ENTRY(PC - 1);
PC += (signed char) GetBYTE(PC) + 1;
break;
case 0x19: /* ADD HL,DE */
updateTStates(11);
sim_brk_pend = FALSE;
HL &= ADDRMASK;
DE &= ADDRMASK;
sum = HL + DE;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ DE ^ sum) >> 8];
HL = sum;
break;
case 0x1a: /* LD A,(DE) */
updateTStates(7);
CheckBreakByte(DE)
Sethreg(AF, GetBYTE(DE));
break;
case 0x1b: /* DEC DE */
updateTStates(6);
sim_brk_pend = FALSE;
--DE;
break;
case 0x1c: /* INC E */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(DE) + 1;
Setlreg(DE, temp);
AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80);
break;
case 0x1d: /* DEC E */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(DE) - 1;
Setlreg(DE, temp);
AF = (AF & ~0xfe) | decTable[temp & 0xff] | SetPV2(0x7f);
break;
case 0x1e: /* LD E,nn */
updateTStates(7);
sim_brk_pend = FALSE;
Setlreg(DE, RAM_pp(PC));
break;
case 0x1f: /* RRA */
updateTStates(4);
sim_brk_pend = FALSE;
AF = ((AF & 1) << 15) | (AF & 0xc4) | rraTable[hreg(AF)];
break;
case 0x20: /* JR NZ,dd */
sim_brk_pend = FALSE;
checkCPU8080;
if (TSTFLAG(Z)) {
PC++;
updateTStates(7);
}
else {
PCQ_ENTRY(PC - 1);
PC += (signed char) GetBYTE(PC) + 1;
updateTStates(12);
}
break;
case 0x21: /* LD HL,nnnn */
updateTStates(10);
sim_brk_pend = FALSE;
HL = GetWORD(PC);
PC += 2;
break;
case 0x22: /* LD (nnnn),HL */
updateTStates(16);
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, HL);
PC += 2;
break;
case 0x23: /* INC HL */
updateTStates(6);
sim_brk_pend = FALSE;
++HL;
break;
case 0x24: /* INC H */
updateTStates(4);
sim_brk_pend = FALSE;
HL += 0x100;
temp = hreg(HL);
AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); /* SetPV2 uses temp */
break;
case 0x25: /* DEC H */
updateTStates(4);
sim_brk_pend = FALSE;
HL -= 0x100;
temp = hreg(HL);
AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); /* SetPV2 uses temp */
break;
case 0x26: /* LD H,nn */
updateTStates(7);
sim_brk_pend = FALSE;
Sethreg(HL, RAM_pp(PC));
break;
case 0x27: /* DAA */
updateTStates(4);
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;
}
}
AF = (AF & 0x12) | rrdrldTable[acu & 0xff] | ((acu >> 8) & 1) | 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;
updateTStates(12);
}
else {
PC++;
updateTStates(7);
}
break;
case 0x29: /* ADD HL,HL */
updateTStates(11);
sim_brk_pend = FALSE;
HL &= ADDRMASK;
sum = HL + HL;
AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8];
HL = sum;
break;
case 0x2a: /* LD HL,(nnnn) */
updateTStates(16);
temp = GetWORD(PC);
CheckBreakWord(temp);
HL = GetWORD(temp);
PC += 2;
break;
case 0x2b: /* DEC HL */
updateTStates(6);
sim_brk_pend = FALSE;
--HL;
break;
case 0x2c: /* INC L */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(HL) + 1;
Setlreg(HL, temp);
AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80);
break;
case 0x2d: /* DEC L */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(HL) - 1;
Setlreg(HL, temp);
AF = (AF & ~0xfe) | decTable[temp & 0xff] | SetPV2(0x7f);
break;
case 0x2e: /* LD L,nn */
updateTStates(7);
sim_brk_pend = FALSE;
Setlreg(HL, RAM_pp(PC));
break;
case 0x2f: /* CPL */
updateTStates(4);
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++;
updateTStates(7);
}
else {
PCQ_ENTRY(PC - 1);
PC += (signed char) GetBYTE(PC) + 1;
updateTStates(12);
}
break;
case 0x31: /* LD SP,nnnn */
updateTStates(10);
sim_brk_pend = FALSE;
SP = GetWORD(PC);
PC += 2;
break;
case 0x32: /* LD (nnnn),A */
updateTStates(13);
temp = GetWORD(PC);
CheckBreakByte(temp);
PutBYTE(temp, hreg(AF));
PC += 2;
break;
case 0x33: /* INC SP */
updateTStates(6);
sim_brk_pend = FALSE;
++SP;
break;
case 0x34: /* INC (HL) */
updateTStates(11);
CheckBreakByte(HL);
temp = GetBYTE(HL) + 1;
PutBYTE(HL, temp);
AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80);
break;
case 0x35: /* DEC (HL) */
updateTStates(11);
CheckBreakByte(HL);
temp = GetBYTE(HL) - 1;
PutBYTE(HL, temp);
AF = (AF & ~0xfe) | decTable[temp & 0xff] | SetPV2(0x7f);
break;
case 0x36: /* LD (HL),nn */
updateTStates(10);
CheckBreakByte(HL);
PutBYTE(HL, RAM_pp(PC));
break;
case 0x37: /* SCF */
updateTStates(4);
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;
updateTStates(12);
}
else {
PC++;
updateTStates(7);
}
break;
case 0x39: /* ADD HL,SP */
updateTStates(11);
sim_brk_pend = FALSE;
HL &= ADDRMASK;
SP &= ADDRMASK;
sum = HL + SP;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ SP ^ sum) >> 8];
HL = sum;
break;
case 0x3a: /* LD A,(nnnn) */
updateTStates(13);
temp = GetWORD(PC);
CheckBreakByte(temp);
Sethreg(AF, GetBYTE(temp));
PC += 2;
break;
case 0x3b: /* DEC SP */
updateTStates(6);
sim_brk_pend = FALSE;
--SP;
break;
case 0x3c: /* INC A */
updateTStates(4);
sim_brk_pend = FALSE;
AF += 0x100;
temp = hreg(AF);
AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); /* SetPV2 uses temp */
break;
case 0x3d: /* DEC A */
updateTStates(4);
sim_brk_pend = FALSE;
AF -= 0x100;
temp = hreg(AF);
AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); /* SetPV2 uses temp */
break;
case 0x3e: /* LD A,nn */
updateTStates(7);
sim_brk_pend = FALSE;
Sethreg(AF, RAM_pp(PC));
break;
case 0x3f: /* CCF */
updateTStates(4);
sim_brk_pend = FALSE;
AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) | ((AF & 1) << 4) | (~AF & 1);
break;
case 0x40: /* LD B,B */
updateTStates(4);
sim_brk_pend = FALSE; /* nop */
break;
case 0x41: /* LD B,C */
updateTStates(4);
sim_brk_pend = FALSE;
BC = (BC & 0xff) | ((BC & 0xff) << 8);
break;
case 0x42: /* LD B,D */
updateTStates(4);
sim_brk_pend = FALSE;
BC = (BC & 0xff) | (DE & ~0xff);
break;
case 0x43: /* LD B,E */
updateTStates(4);
sim_brk_pend = FALSE;
BC = (BC & 0xff) | ((DE & 0xff) << 8);
break;
case 0x44: /* LD B,H */
updateTStates(4);
sim_brk_pend = FALSE;
BC = (BC & 0xff) | (HL & ~0xff);
break;
case 0x45: /* LD B,L */
updateTStates(4);
sim_brk_pend = FALSE;
BC = (BC & 0xff) | ((HL & 0xff) << 8);
break;
case 0x46: /* LD B,(HL) */
updateTStates(7);
CheckBreakByte(HL);
Sethreg(BC, GetBYTE(HL));
break;
case 0x47: /* LD B,A */
updateTStates(4);
sim_brk_pend = FALSE;
BC = (BC & 0xff) | (AF & ~0xff);
break;
case 0x48: /* LD C,B */
updateTStates(4);
sim_brk_pend = FALSE;
BC = (BC & ~0xff) | ((BC >> 8) & 0xff);
break;
case 0x49: /* LD C,C */
updateTStates(4);
sim_brk_pend = FALSE; /* nop */
break;
case 0x4a: /* LD C,D */
updateTStates(4);
sim_brk_pend = FALSE;
BC = (BC & ~0xff) | ((DE >> 8) & 0xff);
break;
case 0x4b: /* LD C,E */
updateTStates(4);
sim_brk_pend = FALSE;
BC = (BC & ~0xff) | (DE & 0xff);
break;
case 0x4c: /* LD C,H */
updateTStates(4);
sim_brk_pend = FALSE;
BC = (BC & ~0xff) | ((HL >> 8) & 0xff);
break;
case 0x4d: /* LD C,L */
updateTStates(4);
sim_brk_pend = FALSE;
BC = (BC & ~0xff) | (HL & 0xff);
break;
case 0x4e: /* LD C,(HL) */
updateTStates(7);
CheckBreakByte(HL);
Setlreg(BC, GetBYTE(HL));
break;
case 0x4f: /* LD C,A */
updateTStates(4);
sim_brk_pend = FALSE;
BC = (BC & ~0xff) | ((AF >> 8) & 0xff);
break;
case 0x50: /* LD D,B */
updateTStates(4);
sim_brk_pend = FALSE;
DE = (DE & 0xff) | (BC & ~0xff);
break;
case 0x51: /* LD D,C */
updateTStates(4);
sim_brk_pend = FALSE;
DE = (DE & 0xff) | ((BC & 0xff) << 8);
break;
case 0x52: /* LD D,D */
updateTStates(4);
sim_brk_pend = FALSE; /* nop */
break;
case 0x53: /* LD D,E */
updateTStates(4);
sim_brk_pend = FALSE;
DE = (DE & 0xff) | ((DE & 0xff) << 8);
break;
case 0x54: /* LD D,H */
updateTStates(4);
sim_brk_pend = FALSE;
DE = (DE & 0xff) | (HL & ~0xff);
break;
case 0x55: /* LD D,L */
updateTStates(4);
sim_brk_pend = FALSE;
DE = (DE & 0xff) | ((HL & 0xff) << 8);
break;
case 0x56: /* LD D,(HL) */
updateTStates(7);
CheckBreakByte(HL);
Sethreg(DE, GetBYTE(HL));
break;
case 0x57: /* LD D,A */
updateTStates(4);
sim_brk_pend = FALSE;
DE = (DE & 0xff) | (AF & ~0xff);
break;
case 0x58: /* LD E,B */
updateTStates(4);
sim_brk_pend = FALSE;
DE = (DE & ~0xff) | ((BC >> 8) & 0xff);
break;
case 0x59: /* LD E,C */
updateTStates(4);
sim_brk_pend = FALSE;
DE = (DE & ~0xff) | (BC & 0xff);
break;
case 0x5a: /* LD E,D */
updateTStates(4);
sim_brk_pend = FALSE;
DE = (DE & ~0xff) | ((DE >> 8) & 0xff);
break;
case 0x5b: /* LD E,E */
updateTStates(4);
sim_brk_pend = FALSE; /* nop */
break;
case 0x5c: /* LD E,H */
updateTStates(4);
sim_brk_pend = FALSE;
DE = (DE & ~0xff) | ((HL >> 8) & 0xff);
break;
case 0x5d: /* LD E,L */
updateTStates(4);
sim_brk_pend = FALSE;
DE = (DE & ~0xff) | (HL & 0xff);
break;
case 0x5e: /* LD E,(HL) */
updateTStates(7);
CheckBreakByte(HL);
Setlreg(DE, GetBYTE(HL));
break;
case 0x5f: /* LD E,A */
updateTStates(4);
sim_brk_pend = FALSE;
DE = (DE & ~0xff) | ((AF >> 8) & 0xff);
break;
case 0x60: /* LD H,B */
updateTStates(4);
sim_brk_pend = FALSE;
HL = (HL & 0xff) | (BC & ~0xff);
break;
case 0x61: /* LD H,C */
updateTStates(4);
sim_brk_pend = FALSE;
HL = (HL & 0xff) | ((BC & 0xff) << 8);
break;
case 0x62: /* LD H,D */
updateTStates(4);
sim_brk_pend = FALSE;
HL = (HL & 0xff) | (DE & ~0xff);
break;
case 0x63: /* LD H,E */
updateTStates(4);
sim_brk_pend = FALSE;
HL = (HL & 0xff) | ((DE & 0xff) << 8);
break;
case 0x64: /* LD H,H */
updateTStates(4);
sim_brk_pend = FALSE; /* nop */
break;
case 0x65: /* LD H,L */
updateTStates(4);
sim_brk_pend = FALSE;
HL = (HL & 0xff) | ((HL & 0xff) << 8);
break;
case 0x66: /* LD H,(HL) */
updateTStates(7);
CheckBreakByte(HL);
Sethreg(HL, GetBYTE(HL));
break;
case 0x67: /* LD H,A */
updateTStates(4);
sim_brk_pend = FALSE;
HL = (HL & 0xff) | (AF & ~0xff);
break;
case 0x68: /* LD L,B */
updateTStates(4);
sim_brk_pend = FALSE;
HL = (HL & ~0xff) | ((BC >> 8) & 0xff);
break;
case 0x69: /* LD L,C */
updateTStates(4);
sim_brk_pend = FALSE;
HL = (HL & ~0xff) | (BC & 0xff);
break;
case 0x6a: /* LD L,D */
updateTStates(4);
sim_brk_pend = FALSE;
HL = (HL & ~0xff) | ((DE >> 8) & 0xff);
break;
case 0x6b: /* LD L,E */
updateTStates(4);
sim_brk_pend = FALSE;
HL = (HL & ~0xff) | (DE & 0xff);
break;
case 0x6c: /* LD L,H */
updateTStates(4);
sim_brk_pend = FALSE;
HL = (HL & ~0xff) | ((HL >> 8) & 0xff);
break;
case 0x6d: /* LD L,L */
updateTStates(4);
sim_brk_pend = FALSE; /* nop */
break;
case 0x6e: /* LD L,(HL) */
updateTStates(7);
CheckBreakByte(HL);
Setlreg(HL, GetBYTE(HL));
break;
case 0x6f: /* LD L,A */
updateTStates(4);
sim_brk_pend = FALSE;
HL = (HL & ~0xff) | ((AF >> 8) & 0xff);
break;
case 0x70: /* LD (HL),B */
updateTStates(7);
CheckBreakByte(HL);
PutBYTE(HL, hreg(BC));
break;
case 0x71: /* LD (HL),C */
updateTStates(7);
CheckBreakByte(HL);
PutBYTE(HL, lreg(BC));
break;
case 0x72: /* LD (HL),D */
updateTStates(7);
CheckBreakByte(HL);
PutBYTE(HL, hreg(DE));
break;
case 0x73: /* LD (HL),E */
updateTStates(7);
CheckBreakByte(HL);
PutBYTE(HL, lreg(DE));
break;
case 0x74: /* LD (HL),H */
updateTStates(7);
CheckBreakByte(HL);
PutBYTE(HL, hreg(HL));
break;
case 0x75: /* LD (HL),L */
updateTStates(7);
CheckBreakByte(HL);
PutBYTE(HL, lreg(HL));
break;
case 0x76: /* HALT */
updateTStates(4);
sim_brk_pend = FALSE;
reason = STOP_HALT;
PC--;
goto end_decode;
case 0x77: /* LD (HL),A */
updateTStates(7);
CheckBreakByte(HL);
PutBYTE(HL, hreg(AF));
break;
case 0x78: /* LD A,B */
updateTStates(4);
sim_brk_pend = FALSE;
AF = (AF & 0xff) | (BC & ~0xff);
break;
case 0x79: /* LD A,C */
updateTStates(4);
sim_brk_pend = FALSE;
AF = (AF & 0xff) | ((BC & 0xff) << 8);
break;
case 0x7a: /* LD A,D */
updateTStates(4);
sim_brk_pend = FALSE;
AF = (AF & 0xff) | (DE & ~0xff);
break;
case 0x7b: /* LD A,E */
updateTStates(4);
sim_brk_pend = FALSE;
AF = (AF & 0xff) | ((DE & 0xff) << 8);
break;
case 0x7c: /* LD A,H */
updateTStates(4);
sim_brk_pend = FALSE;
AF = (AF & 0xff) | (HL & ~0xff);
break;
case 0x7d: /* LD A,L */
updateTStates(4);
sim_brk_pend = FALSE;
AF = (AF & 0xff) | ((HL & 0xff) << 8);
break;
case 0x7e: /* LD A,(HL) */
updateTStates(7);
CheckBreakByte(HL);
Sethreg(AF, GetBYTE(HL));
break;
case 0x7f: /* LD A,A */
updateTStates(4);
sim_brk_pend = FALSE; /* nop */
break;
case 0x80: /* ADD A,B */
updateTStates(4);
sim_brk_pend = FALSE;
temp = hreg(BC);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x81: /* ADD A,C */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(BC);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x82: /* ADD A,D */
updateTStates(4);
sim_brk_pend = FALSE;
temp = hreg(DE);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x83: /* ADD A,E */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(DE);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x84: /* ADD A,H */
updateTStates(4);
sim_brk_pend = FALSE;
temp = hreg(HL);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x85: /* ADD A,L */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(HL);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x86: /* ADD A,(HL) */
updateTStates(7);
CheckBreakByte(HL);
temp = GetBYTE(HL);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x87: /* ADD A,A */
updateTStates(4);
sim_brk_pend = FALSE;
cbits = 2 * hreg(AF);
AF = cbitsDup8Table[cbits] | (SetPVS(cbits));
break;
case 0x88: /* ADC A,B */
updateTStates(4);
sim_brk_pend = FALSE;
temp = hreg(BC);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x89: /* ADC A,C */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(BC);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x8a: /* ADC A,D */
updateTStates(4);
sim_brk_pend = FALSE;
temp = hreg(DE);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x8b: /* ADC A,E */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(DE);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x8c: /* ADC A,H */
updateTStates(4);
sim_brk_pend = FALSE;
temp = hreg(HL);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x8d: /* ADC A,L */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(HL);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x8e: /* ADC A,(HL) */
updateTStates(7);
CheckBreakByte(HL);
temp = GetBYTE(HL);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0x8f: /* ADC A,A */
updateTStates(4);
sim_brk_pend = FALSE;
cbits = 2 * hreg(AF) + TSTFLAG(C);
AF = cbitsDup8Table[cbits] | (SetPVS(cbits));
break;
case 0x90: /* SUB B */
updateTStates(4);
sim_brk_pend = FALSE;
temp = hreg(BC);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x91: /* SUB C */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(BC);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x92: /* SUB D */
updateTStates(4);
sim_brk_pend = FALSE;
temp = hreg(DE);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x93: /* SUB E */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(DE);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x94: /* SUB H */
updateTStates(4);
sim_brk_pend = FALSE;
temp = hreg(HL);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x95: /* SUB L */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(HL);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x96: /* SUB (HL) */
updateTStates(7);
CheckBreakByte(HL);
temp = GetBYTE(HL);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x97: /* SUB A */
updateTStates(4);
sim_brk_pend = FALSE;
AF = cpu_unit.flags & UNIT_CHIP ? 0x42 : 0x46;
break;
case 0x98: /* SBC A,B */
updateTStates(4);
sim_brk_pend = FALSE;
temp = hreg(BC);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x99: /* SBC A,C */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(BC);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x9a: /* SBC A,D */
updateTStates(4);
sim_brk_pend = FALSE;
temp = hreg(DE);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x9b: /* SBC A,E */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(DE);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x9c: /* SBC A,H */
updateTStates(4);
sim_brk_pend = FALSE;
temp = hreg(HL);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x9d: /* SBC A,L */
updateTStates(4);
sim_brk_pend = FALSE;
temp = lreg(HL);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x9e: /* SBC A,(HL) */
updateTStates(7);
CheckBreakByte(HL);
temp = GetBYTE(HL);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0x9f: /* SBC A,A */
updateTStates(4);
sim_brk_pend = FALSE;
cbits = -TSTFLAG(C);
AF = subTable[cbits & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPVS(cbits));
break;
case 0xa0: /* AND B */
updateTStates(4);
sim_brk_pend = FALSE;
AF = andTable[((AF & BC) >> 8) & 0xff];
break;
case 0xa1: /* AND C */
updateTStates(4);
sim_brk_pend = FALSE;
AF = andTable[((AF >> 8) & BC) & 0xff];
break;
case 0xa2: /* AND D */
updateTStates(4);
sim_brk_pend = FALSE;
AF = andTable[((AF & DE) >> 8) & 0xff];
break;
case 0xa3: /* AND E */
updateTStates(4);
sim_brk_pend = FALSE;
AF = andTable[((AF >> 8) & DE) & 0xff];
break;
case 0xa4: /* AND H */
updateTStates(4);
sim_brk_pend = FALSE;
AF = andTable[((AF & HL) >> 8) & 0xff];
break;
case 0xa5: /* AND L */
updateTStates(4);
sim_brk_pend = FALSE;
AF = andTable[((AF >> 8) & HL) & 0xff];
break;
case 0xa6: /* AND (HL) */
updateTStates(7);
CheckBreakByte(HL);
AF = andTable[((AF >> 8) & GetBYTE(HL)) & 0xff];
break;
case 0xa7: /* AND A */
updateTStates(4);
sim_brk_pend = FALSE;
AF = andTable[(AF >> 8) & 0xff];
break;
case 0xa8: /* XOR B */
updateTStates(4);
sim_brk_pend = FALSE;
AF = xororTable[((AF ^ BC) >> 8) & 0xff];
break;
case 0xa9: /* XOR C */
updateTStates(4);
sim_brk_pend = FALSE;
AF = xororTable[((AF >> 8) ^ BC) & 0xff];
break;
case 0xaa: /* XOR D */
updateTStates(4);
sim_brk_pend = FALSE;
AF = xororTable[((AF ^ DE) >> 8) & 0xff];
break;
case 0xab: /* XOR E */
updateTStates(4);
sim_brk_pend = FALSE;
AF = xororTable[((AF >> 8) ^ DE) & 0xff];
break;
case 0xac: /* XOR H */
updateTStates(4);
sim_brk_pend = FALSE;
AF = xororTable[((AF ^ HL) >> 8) & 0xff];
break;
case 0xad: /* XOR L */
updateTStates(4);
sim_brk_pend = FALSE;
AF = xororTable[((AF >> 8) ^ HL) & 0xff];
break;
case 0xae: /* XOR (HL) */
updateTStates(7);
CheckBreakByte(HL);
AF = xororTable[((AF >> 8) ^ GetBYTE(HL)) & 0xff];
break;
case 0xaf: /* XOR A */
updateTStates(4);
sim_brk_pend = FALSE;
AF = 0x44;
break;
case 0xb0: /* OR B */
updateTStates(4);
sim_brk_pend = FALSE;
AF = xororTable[((AF | BC) >> 8) & 0xff];
break;
case 0xb1: /* OR C */
updateTStates(4);
sim_brk_pend = FALSE;
AF = xororTable[((AF >> 8) | BC) & 0xff];
break;
case 0xb2: /* OR D */
updateTStates(4);
sim_brk_pend = FALSE;
AF = xororTable[((AF | DE) >> 8) & 0xff];
break;
case 0xb3: /* OR E */
updateTStates(4);
sim_brk_pend = FALSE;
AF = xororTable[((AF >> 8) | DE) & 0xff];
break;
case 0xb4: /* OR H */
updateTStates(4);
sim_brk_pend = FALSE;
AF = xororTable[((AF | HL) >> 8) & 0xff];
break;
case 0xb5: /* OR L */
updateTStates(4);
sim_brk_pend = FALSE;
AF = xororTable[((AF >> 8) | HL) & 0xff];
break;
case 0xb6: /* OR (HL) */
updateTStates(7);
CheckBreakByte(HL);
AF = xororTable[((AF >> 8) | GetBYTE(HL)) & 0xff];
break;
case 0xb7: /* OR A */
updateTStates(4);
sim_brk_pend = FALSE;
AF = xororTable[(AF >> 8) & 0xff];
break;
case 0xb8: /* CP B */
updateTStates(4);
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) | cpTable[sum & 0xff] | (temp & 0x28) |
(SetPV) | cbits2Table[cbits & 0x1ff];
break;
case 0xb9: /* CP C */
updateTStates(4);
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) | cpTable[sum & 0xff] | (temp & 0x28) |
(SetPV) | cbits2Table[cbits & 0x1ff];
break;
case 0xba: /* CP D */
updateTStates(4);
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) | cpTable[sum & 0xff] | (temp & 0x28) |
(SetPV) | cbits2Table[cbits & 0x1ff];
break;
case 0xbb: /* CP E */
updateTStates(4);
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) | cpTable[sum & 0xff] | (temp & 0x28) |
(SetPV) | cbits2Table[cbits & 0x1ff];
break;
case 0xbc: /* CP H */
updateTStates(4);
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) | cpTable[sum & 0xff] | (temp & 0x28) |
(SetPV) | cbits2Table[cbits & 0x1ff];
break;
case 0xbd: /* CP L */
updateTStates(4);
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) | cpTable[sum & 0xff] | (temp & 0x28) |
(SetPV) | cbits2Table[cbits & 0x1ff];
break;
case 0xbe: /* CP (HL) */
updateTStates(7);
CheckBreakByte(HL);
temp = GetBYTE(HL);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
(SetPV) | cbits2Table[cbits & 0x1ff];
break;
case 0xbf: /* CP A */
updateTStates(4);
sim_brk_pend = FALSE;
Setlreg(AF, (hreg(AF) & 0x28) | (cpu_unit.flags & UNIT_CHIP ? 0x42 : 0x46));
break;
case 0xc0: /* RET NZ */
if (TSTFLAG(Z)) {
sim_brk_pend = FALSE;
updateTStates(5);
}
else {
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
updateTStates(11);
}
break;
case 0xc1: /* POP BC */
updateTStates(10);
CheckBreakWord(SP);
POP(BC);
break;
case 0xc2: /* JP NZ,nnnn */
sim_brk_pend = FALSE;
JPC(!TSTFLAG(Z)); /* also updates tStates */
break;
case 0xc3: /* JP nnnn */
sim_brk_pend = FALSE;
JPC(1); /* also updates tStates */
break;
case 0xc4: /* CALL NZ,nnnn */
CALLC(!TSTFLAG(Z)); /* also updates tStates */
break;
case 0xc5: /* PUSH BC */
updateTStates(11);
CheckBreakWord(SP - 2);
PUSH(BC);
break;
case 0xc6: /* ADD A,nn */
updateTStates(7);
sim_brk_pend = FALSE;
temp = RAM_pp(PC);
acu = hreg(AF);
sum = acu + temp;
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0xc7: /* RST 0 */
updateTStates(11);
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);
updateTStates(11);
}
else {
sim_brk_pend = FALSE;
updateTStates(5);
}
break;
case 0xc9: /* RET */
updateTStates(10);
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
break;
case 0xca: /* JP Z,nnnn */
sim_brk_pend = FALSE;
JPC(TSTFLAG(Z)); /* also updates tStates */
break;
case 0xcb: /* CB prefix */
checkCPU8080;
adr = HL;
switch ((op = GetBYTE(PC)) & 7) {
case 0:
sim_brk_pend = tStateModifier = FALSE;
++PC;
acu = hreg(BC);
updateTStates(8);
break;
case 1:
sim_brk_pend = tStateModifier = FALSE;
++PC;
acu = lreg(BC);
updateTStates(8);
break;
case 2:
sim_brk_pend = tStateModifier = FALSE;
++PC;
acu = hreg(DE);
updateTStates(8);
break;
case 3:
sim_brk_pend = tStateModifier = FALSE;
++PC;
acu = lreg(DE);
updateTStates(8);
break;
case 4:
sim_brk_pend = tStateModifier = FALSE;
++PC;
acu = hreg(HL);
updateTStates(8);
break;
case 5:
sim_brk_pend = tStateModifier = FALSE;
++PC;
acu = lreg(HL);
updateTStates(8);
break;
case 6:
CheckBreakByte(adr);
++PC;
acu = GetBYTE(adr);
tStateModifier = TRUE;
updateTStates(15);
break;
case 7:
sim_brk_pend = tStateModifier = FALSE;
++PC;
acu = hreg(AF);
updateTStates(8);
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) | rotateShiftTable[temp & 0xff] | !!cbits;
}
break;
case 0x40: /* BIT */
if (tStateModifier) {
tStates -= 3;
}
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)); /* also updates tStates */
break;
case 0xcd: /* CALL nnnn */
CALLC(1); /* also updates tStates */
break;
case 0xce: /* ADC A,nn */
updateTStates(7);
sim_brk_pend = FALSE;
temp = RAM_pp(PC);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = addTable[sum] | cbitsTable[cbits] | (SetPV);
break;
case 0xcf: /* RST 8 */
updateTStates(11);
CheckBreakWord(SP - 2);
PUSH(PC);
PCQ_ENTRY(PC - 1);
PC = 8;
break;
case 0xd0: /* RET NC */
if (TSTFLAG(C)) {
sim_brk_pend = FALSE;
updateTStates(5);
}
else {
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
updateTStates(11);
}
break;
case 0xd1: /* POP DE */
updateTStates(10);
CheckBreakWord(SP);
POP(DE);
break;
case 0xd2: /* JP NC,nnnn */
sim_brk_pend = FALSE;
JPC(!TSTFLAG(C)); /* also updates tStates */
break;
case 0xd3: /* OUT (nn),A */
updateTStates(11);
sim_brk_pend = FALSE;
out(RAM_pp(PC), hreg(AF));
break;
case 0xd4: /* CALL NC,nnnn */
CALLC(!TSTFLAG(C)); /* also updates tStates */
break;
case 0xd5: /* PUSH DE */
updateTStates(11);
CheckBreakWord(SP - 2);
PUSH(DE);
break;
case 0xd6: /* SUB nn */
updateTStates(7);
sim_brk_pend = FALSE;
temp = RAM_pp(PC);
acu = hreg(AF);
sum = acu - temp;
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0xd7: /* RST 10H */
updateTStates(11);
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);
updateTStates(11);
}
else {
sim_brk_pend = FALSE;
updateTStates(5);
}
break;
case 0xd9: /* EXX */
updateTStates(4);
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)); /* also updates tStates */
break;
case 0xdb: /* IN A,(nn) */
updateTStates(11);
sim_brk_pend = FALSE;
Sethreg(AF, in(RAM_pp(PC)));
break;
case 0xdc: /* CALL C,nnnn */
CALLC(TSTFLAG(C)); /* also updates tStates */
break;
case 0xdd: /* DD prefix */
checkCPU8080;
switch (op = RAM_pp(PC)) {
case 0x09: /* ADD IX,BC */
updateTStates(15);
sim_brk_pend = FALSE;
IX &= ADDRMASK;
BC &= ADDRMASK;
sum = IX + BC;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ BC ^ sum) >> 8];
IX = sum;
break;
case 0x19: /* ADD IX,DE */
updateTStates(15);
sim_brk_pend = FALSE;
IX &= ADDRMASK;
DE &= ADDRMASK;
sum = IX + DE;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ DE ^ sum) >> 8];
IX = sum;
break;
case 0x21: /* LD IX,nnnn */
updateTStates(14);
sim_brk_pend = FALSE;
IX = GetWORD(PC);
PC += 2;
break;
case 0x22: /* LD (nnnn),IX */
updateTStates(20);
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, IX);
PC += 2;
break;
case 0x23: /* INC IX */
updateTStates(10);
sim_brk_pend = FALSE;
++IX;
break;
case 0x24: /* INC IXH */
updateTStates(9);
sim_brk_pend = FALSE;
IX += 0x100;
AF = (AF & ~0xfe) | incZ80Table[hreg(IX)];
break;
case 0x25: /* DEC IXH */
updateTStates(9);
sim_brk_pend = FALSE;
IX -= 0x100;
AF = (AF & ~0xfe) | decZ80Table[hreg(IX)];
break;
case 0x26: /* LD IXH,nn */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IX, RAM_pp(PC));
break;
case 0x29: /* ADD IX,IX */
updateTStates(15);
sim_brk_pend = FALSE;
IX &= ADDRMASK;
sum = IX + IX;
AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8];
IX = sum;
break;
case 0x2a: /* LD IX,(nnnn) */
updateTStates(20);
temp = GetWORD(PC);
CheckBreakWord(temp);
IX = GetWORD(temp);
PC += 2;
break;
case 0x2b: /* DEC IX */
updateTStates(10);
sim_brk_pend = FALSE;
--IX;
break;
case 0x2c: /* INC IXL */
updateTStates(9);
sim_brk_pend = FALSE;
temp = lreg(IX) + 1;
Setlreg(IX, temp);
AF = (AF & ~0xfe) | incZ80Table[temp];
break;
case 0x2d: /* DEC IXL */
updateTStates(9);
sim_brk_pend = FALSE;
temp = lreg(IX) - 1;
Setlreg(IX, temp);
AF = (AF & ~0xfe) | decZ80Table[temp & 0xff];
break;
case 0x2e: /* LD IXL,nn */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IX, RAM_pp(PC));
break;
case 0x34: /* INC (IX+dd) */
updateTStates(23);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr) + 1;
PutBYTE(adr, temp);
AF = (AF & ~0xfe) | incZ80Table[temp];
break;
case 0x35: /* DEC (IX+dd) */
updateTStates(23);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr) - 1;
PutBYTE(adr, temp);
AF = (AF & ~0xfe) | decZ80Table[temp & 0xff];
break;
case 0x36: /* LD (IX+dd),nn */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, RAM_pp(PC));
break;
case 0x39: /* ADD IX,SP */
updateTStates(15);
sim_brk_pend = FALSE;
IX &= ADDRMASK;
SP &= ADDRMASK;
sum = IX + SP;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ SP ^ sum) >> 8];
IX = sum;
break;
case 0x44: /* LD B,IXH */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(BC, hreg(IX));
break;
case 0x45: /* LD B,IXL */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(BC, lreg(IX));
break;
case 0x46: /* LD B,(IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(BC, GetBYTE(adr));
break;
case 0x4c: /* LD C,IXH */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(BC, hreg(IX));
break;
case 0x4d: /* LD C,IXL */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(BC, lreg(IX));
break;
case 0x4e: /* LD C,(IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Setlreg(BC, GetBYTE(adr));
break;
case 0x54: /* LD D,IXH */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(DE, hreg(IX));
break;
case 0x55: /* LD D,IXL */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(DE, lreg(IX));
break;
case 0x56: /* LD D,(IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(DE, GetBYTE(adr));
break;
case 0x5c: /* LD E,IXH */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(DE, hreg(IX));
break;
case 0x5d: /* LD E,IXL */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(DE, lreg(IX));
break;
case 0x5e: /* LD E,(IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Setlreg(DE, GetBYTE(adr));
break;
case 0x60: /* LD IXH,B */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IX, hreg(BC));
break;
case 0x61: /* LD IXH,C */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IX, lreg(BC));
break;
case 0x62: /* LD IXH,D */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IX, hreg(DE));
break;
case 0x63: /* LD IXH,E */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IX, lreg(DE));
break;
case 0x64: /* LD IXH,IXH */
updateTStates(9);
sim_brk_pend = FALSE; /* nop */
break;
case 0x65: /* LD IXH,IXL */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IX, lreg(IX));
break;
case 0x66: /* LD H,(IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(HL, GetBYTE(adr));
break;
case 0x67: /* LD IXH,A */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IX, hreg(AF));
break;
case 0x68: /* LD IXL,B */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IX, hreg(BC));
break;
case 0x69: /* LD IXL,C */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IX, lreg(BC));
break;
case 0x6a: /* LD IXL,D */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IX, hreg(DE));
break;
case 0x6b: /* LD IXL,E */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IX, lreg(DE));
break;
case 0x6c: /* LD IXL,IXH */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IX, hreg(IX));
break;
case 0x6d: /* LD IXL,IXL */
updateTStates(9);
sim_brk_pend = FALSE; /* nop */
break;
case 0x6e: /* LD L,(IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Setlreg(HL, GetBYTE(adr));
break;
case 0x6f: /* LD IXL,A */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IX, hreg(AF));
break;
case 0x70: /* LD (IX+dd),B */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(BC));
break;
case 0x71: /* LD (IX+dd),C */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, lreg(BC));
break;
case 0x72: /* LD (IX+dd),D */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(DE));
break;
case 0x73: /* LD (IX+dd),E */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, lreg(DE));
break;
case 0x74: /* LD (IX+dd),H */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(HL));
break;
case 0x75: /* LD (IX+dd),L */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, lreg(HL));
break;
case 0x77: /* LD (IX+dd),A */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(AF));
break;
case 0x7c: /* LD A,IXH */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(AF, hreg(IX));
break;
case 0x7d: /* LD A,IXL */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(AF, lreg(IX));
break;
case 0x7e: /* LD A,(IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(AF, GetBYTE(adr));
break;
case 0x84: /* ADD A,IXH */
updateTStates(9);
sim_brk_pend = FALSE;
temp = hreg(IX);
acu = hreg(AF);
sum = acu + temp;
AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum];
break;
case 0x85: /* ADD A,IXL */
updateTStates(9);
sim_brk_pend = FALSE;
temp = lreg(IX);
acu = hreg(AF);
sum = acu + temp;
AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum];
break;
case 0x86: /* ADD A,(IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu + temp;
AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum];
break;
case 0x8c: /* ADC A,IXH */
updateTStates(9);
sim_brk_pend = FALSE;
temp = hreg(IX);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum];
break;
case 0x8d: /* ADC A,IXL */
updateTStates(9);
sim_brk_pend = FALSE;
temp = lreg(IX);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum];
break;
case 0x8e: /* ADC A,(IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum];
break;
case 0x96: /* SUB (IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu - temp;
AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
break;
case 0x94: /* SUB IXH */
SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */
case 0x9c: /* SBC A,IXH */
updateTStates(9);
sim_brk_pend = FALSE;
temp = hreg(IX);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
break;
case 0x95: /* SUB IXL */
SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */
case 0x9d: /* SBC A,IXL */
updateTStates(9);
sim_brk_pend = FALSE;
temp = lreg(IX);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
break;
case 0x9e: /* SBC A,(IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
break;
case 0xa4: /* AND IXH */
updateTStates(9);
sim_brk_pend = FALSE;
AF = andTable[((AF & IX) >> 8) & 0xff];
break;
case 0xa5: /* AND IXL */
updateTStates(9);
sim_brk_pend = FALSE;
AF = andTable[((AF >> 8) & IX) & 0xff];
break;
case 0xa6: /* AND (IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
AF = andTable[((AF >> 8) & GetBYTE(adr)) & 0xff];
break;
case 0xac: /* XOR IXH */
updateTStates(9);
sim_brk_pend = FALSE;
AF = xororTable[((AF ^ IX) >> 8) & 0xff];
break;
case 0xad: /* XOR IXL */
updateTStates(9);
sim_brk_pend = FALSE;
AF = xororTable[((AF >> 8) ^ IX) & 0xff];
break;
case 0xae: /* XOR (IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
AF = xororTable[((AF >> 8) ^ GetBYTE(adr)) & 0xff];
break;
case 0xb4: /* OR IXH */
updateTStates(9);
sim_brk_pend = FALSE;
AF = xororTable[((AF | IX) >> 8) & 0xff];
break;
case 0xb5: /* OR IXL */
updateTStates(9);
sim_brk_pend = FALSE;
AF = xororTable[((AF >> 8) | IX) & 0xff];
break;
case 0xb6: /* OR (IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
AF = xororTable[((AF >> 8) | GetBYTE(adr)) & 0xff];
break;
case 0xbc: /* CP IXH */
updateTStates(9);
sim_brk_pend = FALSE;
temp = hreg(IX);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
break;
case 0xbd: /* CP IXL */
updateTStates(9);
sim_brk_pend = FALSE;
temp = lreg(IX);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
break;
case 0xbe: /* CP (IX+dd) */
updateTStates(19);
adr = IX + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
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 */
updateTStates(23);
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) | rotateShiftTable[temp & 0xff] | !!cbits;
}
break;
case 0x40: /* BIT */
updateTStates(20);
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 */
updateTStates(23);
temp = acu & ~(1 << ((op >> 3) & 7));
break;
case 0xc0: /* SET */
updateTStates(23);
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 */
updateTStates(14);
CheckBreakWord(SP);
POP(IX);
break;
case 0xe3: /* EX (SP),IX */
updateTStates(23);
CheckBreakWord(SP);
temp = IX;
POP(IX);
PUSH(temp);
break;
case 0xe5: /* PUSH IX */
updateTStates(15);
CheckBreakWord(SP - 2);
PUSH(IX);
break;
case 0xe9: /* JP (IX) */
updateTStates(8);
sim_brk_pend = FALSE;
PCQ_ENTRY(PC - 2);
PC = IX;
break;
case 0xf9: /* LD SP,IX */
updateTStates(10);
sim_brk_pend = FALSE;
SP = IX;
break;
default: /* ignore DD */
sim_brk_pend = FALSE;
checkCPUZ80;
PC--;
}
break;
case 0xde: /* SBC A,nn */
updateTStates(7);
sim_brk_pend = FALSE;
temp = RAM_pp(PC);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
cbits = acu ^ temp ^ sum;
AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV);
break;
case 0xdf: /* RST 18H */
updateTStates(11);
CheckBreakWord(SP - 2);
PUSH(PC);
PCQ_ENTRY(PC - 1);
PC = 0x18;
break;
case 0xe0: /* RET PO */
if (TSTFLAG(P)) {
sim_brk_pend = FALSE;
updateTStates(5);
}
else {
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
updateTStates(11);
}
break;
case 0xe1: /* POP HL */
updateTStates(10);
CheckBreakWord(SP);
POP(HL);
break;
case 0xe2: /* JP PO,nnnn */
sim_brk_pend = FALSE;
JPC(!TSTFLAG(P)); /* also updates tStates */
break;
case 0xe3: /* EX (SP),HL */
updateTStates(19);
CheckBreakWord(SP);
temp = HL;
POP(HL);
PUSH(temp);
break;
case 0xe4: /* CALL PO,nnnn */
CALLC(!TSTFLAG(P)); /* also updates tStates */
break;
case 0xe5: /* PUSH HL */
updateTStates(11);
CheckBreakWord(SP - 2);
PUSH(HL);
break;
case 0xe6: /* AND nn */
updateTStates(7);
sim_brk_pend = FALSE;
AF = andTable[((AF >> 8) & RAM_pp(PC)) & 0xff];
break;
case 0xe7: /* RST 20H */
updateTStates(11);
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);
updateTStates(11);
}
else {
sim_brk_pend = FALSE;
updateTStates(5);
}
break;
case 0xe9: /* JP (HL) */
updateTStates(4);
sim_brk_pend = FALSE;
PCQ_ENTRY(PC - 1);
PC = HL;
break;
case 0xea: /* JP PE,nnnn */
sim_brk_pend = FALSE;
JPC(TSTFLAG(P)); /* also updates tStates */
break;
case 0xeb: /* EX DE,HL */
updateTStates(4);
sim_brk_pend = FALSE;
temp = HL;
HL = DE;
DE = temp;
break;
case 0xec: /* CALL PE,nnnn */
CALLC(TSTFLAG(P)); /* also updates tStates */
break;
case 0xed: /* ED prefix */
checkCPU8080;
switch (op = RAM_pp(PC)) {
case 0x40: /* IN B,(C) */
updateTStates(12);
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Sethreg(BC, temp);
AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff];
break;
case 0x41: /* OUT (C),B */
updateTStates(12);
sim_brk_pend = FALSE;
out(lreg(BC), hreg(BC));
break;
case 0x42: /* SBC HL,BC */
updateTStates(15);
sim_brk_pend = FALSE;
HL &= ADDRMASK;
BC &= ADDRMASK;
sum = HL - BC - TSTFLAG(C);
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) |
cbits2Z80Table[((HL ^ BC ^ sum) >> 8) & 0x1ff];
HL = sum;
break;
case 0x43: /* LD (nnnn),BC */
updateTStates(20);
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, BC);
PC += 2;
break;
case 0x44: /* NEG */
case 0x4C: /* NEG, unofficial */
case 0x54: /* NEG, unofficial */
case 0x5C: /* NEG, unofficial */
case 0x64: /* NEG, unofficial */
case 0x6C: /* NEG, unofficial */
case 0x74: /* NEG, unofficial */
case 0x7C: /* NEG, unofficial */
updateTStates(8);
sim_brk_pend = FALSE;
temp = hreg(AF);
AF = ((~(AF & 0xff00) + 1) & 0xff00); /* AF = (-(AF & 0xff00) & 0xff00); */
AF |= ((AF >> 8) & 0xa8) | (((AF & 0xff00) == 0) << 6) | negTable[temp];
break;
case 0x45: /* RETN */
case 0x55: /* RETN, unofficial */
case 0x5D: /* RETN, unofficial */
case 0x65: /* RETN, unofficial */
case 0x6D: /* RETN, unofficial */
case 0x75: /* RETN, unofficial */
case 0x7D: /* RETN, unofficial */
updateTStates(14);
IFF |= IFF >> 1;
CheckBreakWord(SP);
PCQ_ENTRY(PC - 2);
POP(PC);
break;
case 0x46: /* IM 0 */
updateTStates(8);
sim_brk_pend = FALSE;
/* interrupt mode 0 */
break;
case 0x47: /* LD I,A */
updateTStates(9);
sim_brk_pend = FALSE;
ir = (ir & 0xff) | (AF & ~0xff);
break;
case 0x48: /* IN C,(C) */
updateTStates(12);
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Setlreg(BC, temp);
AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff];
break;
case 0x49: /* OUT (C),C */
updateTStates(12);
sim_brk_pend = FALSE;
out(lreg(BC), lreg(BC));
break;
case 0x4a: /* ADC HL,BC */
updateTStates(15);
sim_brk_pend = FALSE;
HL &= ADDRMASK;
BC &= ADDRMASK;
sum = HL + BC + TSTFLAG(C);
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) |
cbitsZ80Table[(HL ^ BC ^ sum) >> 8];
HL = sum;
break;
case 0x4b: /* LD BC,(nnnn) */
updateTStates(20);
temp = GetWORD(PC);
CheckBreakWord(temp);
BC = GetWORD(temp);
PC += 2;
break;
case 0x4d: /* RETI */
updateTStates(14);
IFF |= IFF >> 1;
CheckBreakWord(SP);
PCQ_ENTRY(PC - 2);
POP(PC);
break;
case 0x4f: /* LD R,A */
updateTStates(9);
sim_brk_pend = FALSE;
ir = (ir & ~0xff) | ((AF >> 8) & 0xff);
break;
case 0x50: /* IN D,(C) */
updateTStates(12);
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Sethreg(DE, temp);
AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff];
break;
case 0x51: /* OUT (C),D */
updateTStates(12);
sim_brk_pend = FALSE;
out(lreg(BC), hreg(DE));
break;
case 0x52: /* SBC HL,DE */
updateTStates(15);
sim_brk_pend = FALSE;
HL &= ADDRMASK;
DE &= ADDRMASK;
sum = HL - DE - TSTFLAG(C);
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) |
cbits2Z80Table[((HL ^ DE ^ sum) >> 8) & 0x1ff];
HL = sum;
break;
case 0x53: /* LD (nnnn),DE */
updateTStates(20);
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, DE);
PC += 2;
break;
case 0x56: /* IM 1 */
updateTStates(8);
sim_brk_pend = FALSE;
/* interrupt mode 1 */
break;
case 0x57: /* LD A,I */
updateTStates(9);
sim_brk_pend = FALSE;
AF = (AF & 0x29) | (ir & ~0xff) | ((ir >> 8) & 0x80) | (((ir & ~0xff) == 0) << 6) | ((IFF & 2) << 1);
break;
case 0x58: /* IN E,(C) */
updateTStates(12);
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Setlreg(DE, temp);
AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff];
break;
case 0x59: /* OUT (C),E */
updateTStates(12);
sim_brk_pend = FALSE;
out(lreg(BC), lreg(DE));
break;
case 0x5a: /* ADC HL,DE */
updateTStates(15);
sim_brk_pend = FALSE;
HL &= ADDRMASK;
DE &= ADDRMASK;
sum = HL + DE + TSTFLAG(C);
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) |
cbitsZ80Table[(HL ^ DE ^ sum) >> 8];
HL = sum;
break;
case 0x5b: /* LD DE,(nnnn) */
updateTStates(20);
temp = GetWORD(PC);
CheckBreakWord(temp);
DE = GetWORD(temp);
PC += 2;
break;
case 0x5e: /* IM 2 */
updateTStates(8);
sim_brk_pend = FALSE;
/* interrupt mode 2 */
break;
case 0x5f: /* LD A,R */
updateTStates(9);
sim_brk_pend = FALSE;
AF = (AF & 0x29) | ((ir & 0xff) << 8) | (ir & 0x80) |
(((ir & 0xff) == 0) << 6) | ((IFF & 2) << 1);
break;
case 0x60: /* IN H,(C) */
updateTStates(12);
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Sethreg(HL, temp);
AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff];
break;
case 0x61: /* OUT (C),H */
updateTStates(12);
sim_brk_pend = FALSE;
out(lreg(BC), hreg(HL));
break;
case 0x62: /* SBC HL,HL */
updateTStates(15);
sim_brk_pend = FALSE;
HL &= ADDRMASK;
sum = HL - HL - TSTFLAG(C);
AF = (AF & ~0xff) | (((sum & ADDRMASK) == 0) << 6) |
cbits2Z80DupTable[(sum >> 8) & 0x1ff];
HL = sum;
break;
case 0x63: /* LD (nnnn),HL */
updateTStates(20);
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, HL);
PC += 2;
break;
case 0x67: /* RRD */
updateTStates(18);
sim_brk_pend = FALSE;
temp = GetBYTE(HL);
acu = hreg(AF);
PutBYTE(HL, hdig(temp) | (ldig(acu) << 4));
AF = rrdrldTable[(acu & 0xf0) | ldig(temp)] | (AF & 1);
break;
case 0x68: /* IN L,(C) */
updateTStates(12);
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Setlreg(HL, temp);
AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff];
break;
case 0x69: /* OUT (C),L */
updateTStates(12);
sim_brk_pend = FALSE;
out(lreg(BC), lreg(HL));
break;
case 0x6a: /* ADC HL,HL */
updateTStates(15);
sim_brk_pend = FALSE;
HL &= ADDRMASK;
sum = HL + HL + TSTFLAG(C);
AF = (AF & ~0xff) | (((sum & ADDRMASK) == 0) << 6) |
cbitsZ80DupTable[sum >> 8];
HL = sum;
break;
case 0x6b: /* LD HL,(nnnn) */
updateTStates(20);
temp = GetWORD(PC);
CheckBreakWord(temp);
HL = GetWORD(temp);
PC += 2;
break;
case 0x6f: /* RLD */
updateTStates(18);
sim_brk_pend = FALSE;
temp = GetBYTE(HL);
acu = hreg(AF);
PutBYTE(HL, (ldig(temp) << 4) | ldig(acu));
AF = rrdrldTable[(acu & 0xf0) | hdig(temp)] | (AF & 1);
break;
case 0x70: /* IN (C) */
updateTStates(12);
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Setlreg(temp, temp);
AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff];
break;
case 0x71: /* OUT (C),0 */
updateTStates(12);
sim_brk_pend = FALSE;
out(lreg(BC), 0);
break;
case 0x72: /* SBC HL,SP */
updateTStates(15);
sim_brk_pend = FALSE;
HL &= ADDRMASK;
SP &= ADDRMASK;
sum = HL - SP - TSTFLAG(C);
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) |
cbits2Z80Table[((HL ^ SP ^ sum) >> 8) & 0x1ff];
HL = sum;
break;
case 0x73: /* LD (nnnn),SP */
updateTStates(20);
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, SP);
PC += 2;
break;
case 0x78: /* IN A,(C) */
updateTStates(12);
sim_brk_pend = FALSE;
temp = in(lreg(BC));
Sethreg(AF, temp);
AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff];
break;
case 0x79: /* OUT (C),A */
updateTStates(12);
sim_brk_pend = FALSE;
out(lreg(BC), hreg(AF));
break;
case 0x7a: /* ADC HL,SP */
updateTStates(15);
sim_brk_pend = FALSE;
HL &= ADDRMASK;
SP &= ADDRMASK;
sum = HL + SP + TSTFLAG(C);
AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) |
cbitsZ80Table[(HL ^ SP ^ sum) >> 8];
HL = sum;
break;
case 0x7b: /* LD SP,(nnnn) */
updateTStates(20);
temp = GetWORD(PC);
CheckBreakWord(temp);
SP = GetWORD(temp);
PC += 2;
break;
case 0xa0: /* LDI */
updateTStates(16);
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 */
updateTStates(16);
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 */
updateTStates(16);
CheckBreakByte(HL);
PutBYTE(HL, in(lreg(BC)));
++HL;
SETFLAG(N, 1);
SETFLAG(P, (--BC & ADDRMASK) != 0);
break;
case 0xa3: /* OUTI */
updateTStates(16);
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 */
updateTStates(16);
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 */
updateTStates(16);
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 */
updateTStates(16);
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 */
updateTStates(16);
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 */
tStates -= 5;
acu = hreg(AF);
BC &= ADDRMASK;
do {
updateTStates(21);
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 */
tStates -= 5;
acu = hreg(AF);
BC &= ADDRMASK;
do {
updateTStates(21);
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 */
tStates -= 5;
temp = hreg(BC);
do {
updateTStates(21);
CheckBreakByte(HL);
PutBYTE(HL, in(lreg(BC)));
++HL;
} while (--temp);
Sethreg(BC, 0);
SETFLAG(N, 1);
SETFLAG(Z, 1);
break;
case 0xb3: /* OTIR */
tStates -= 5;
temp = hreg(BC);
do {
updateTStates(21);
CheckBreakByte(HL);
out(lreg(BC), GetBYTE(HL));
++HL;
} while (--temp);
Sethreg(BC, 0);
SETFLAG(N, 1);
SETFLAG(Z, 1);
break;
case 0xb8: /* LDDR */
tStates -= 5;
BC &= ADDRMASK;
do {
updateTStates(21);
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 */
tStates -= 5;
acu = hreg(AF);
BC &= ADDRMASK;
do {
updateTStates(21);
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 */
tStates -= 5;
temp = hreg(BC);
do {
updateTStates(21);
CheckBreakByte(HL);
PutBYTE(HL, in(lreg(BC)));
--HL;
} while (--temp);
Sethreg(BC, 0);
SETFLAG(N, 1);
SETFLAG(Z, 1);
break;
case 0xbb: /* OTDR */
tStates -= 5;
temp = hreg(BC);
do {
updateTStates(21);
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 */
updateTStates(7);
sim_brk_pend = FALSE;
AF = xororTable[((AF >> 8) ^ RAM_pp(PC)) & 0xff];
break;
case 0xef: /* RST 28H */
updateTStates(11);
CheckBreakWord(SP - 2);
PUSH(PC);
PCQ_ENTRY(PC - 1);
PC = 0x28;
break;
case 0xf0: /* RET P */
if (TSTFLAG(S)) {
sim_brk_pend = FALSE;
updateTStates(5);
}
else {
CheckBreakWord(SP);
PCQ_ENTRY(PC - 1);
POP(PC);
updateTStates(11);
}
break;
case 0xf1: /* POP AF */
updateTStates(10);
CheckBreakWord(SP);
POP(AF);
break;
case 0xf2: /* JP P,nnnn */
sim_brk_pend = FALSE;
JPC(!TSTFLAG(S)); /* also updates tStates */
break;
case 0xf3: /* DI */
updateTStates(4);
sim_brk_pend = FALSE;
IFF = 0;
break;
case 0xf4: /* CALL P,nnnn */
CALLC(!TSTFLAG(S)); /* also updates tStates */
break;
case 0xf5: /* PUSH AF */
updateTStates(11);
CheckBreakWord(SP - 2);
PUSH(AF);
break;
case 0xf6: /* OR nn */
updateTStates(7);
sim_brk_pend = FALSE;
AF = xororTable[((AF >> 8) | RAM_pp(PC)) & 0xff];
break;
case 0xf7: /* RST 30H */
updateTStates(11);
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);
updateTStates(11);
}
else {
sim_brk_pend = FALSE;
updateTStates(5);
}
break;
case 0xf9: /* LD SP,HL */
updateTStates(6);
sim_brk_pend = FALSE;
SP = HL;
break;
case 0xfa: /* JP M,nnnn */
sim_brk_pend = FALSE;
JPC(TSTFLAG(S)); /* also updates tStates */
break;
case 0xfb: /* EI */
updateTStates(4);
sim_brk_pend = FALSE;
IFF = 3;
break;
case 0xfc: /* CALL M,nnnn */
CALLC(TSTFLAG(S)); /* also updates tStates */
break;
case 0xfd: /* FD prefix */
checkCPU8080;
switch (op = RAM_pp(PC)) {
case 0x09: /* ADD IY,BC */
updateTStates(15);
sim_brk_pend = FALSE;
IY &= ADDRMASK;
BC &= ADDRMASK;
sum = IY + BC;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ BC ^ sum) >> 8];
IY = sum;
break;
case 0x19: /* ADD IY,DE */
updateTStates(15);
sim_brk_pend = FALSE;
IY &= ADDRMASK;
DE &= ADDRMASK;
sum = IY + DE;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ DE ^ sum) >> 8];
IY = sum;
break;
case 0x21: /* LD IY,nnnn */
updateTStates(14);
sim_brk_pend = FALSE;
IY = GetWORD(PC);
PC += 2;
break;
case 0x22: /* LD (nnnn),IY */
updateTStates(20);
temp = GetWORD(PC);
CheckBreakWord(temp);
PutWORD(temp, IY);
PC += 2;
break;
case 0x23: /* INC IY */
updateTStates(10);
sim_brk_pend = FALSE;
++IY;
break;
case 0x24: /* INC IYH */
updateTStates(9);
sim_brk_pend = FALSE;
IY += 0x100;
AF = (AF & ~0xfe) | incZ80Table[hreg(IY)];
break;
case 0x25: /* DEC IYH */
updateTStates(9);
sim_brk_pend = FALSE;
IY -= 0x100;
AF = (AF & ~0xfe) | decZ80Table[hreg(IY)];
break;
case 0x26: /* LD IYH,nn */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IY, RAM_pp(PC));
break;
case 0x29: /* ADD IY,IY */
updateTStates(15);
sim_brk_pend = FALSE;
IY &= ADDRMASK;
sum = IY + IY;
AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8];
IY = sum;
break;
case 0x2a: /* LD IY,(nnnn) */
updateTStates(20);
temp = GetWORD(PC);
CheckBreakWord(temp);
IY = GetWORD(temp);
PC += 2;
break;
case 0x2b: /* DEC IY */
updateTStates(10);
sim_brk_pend = FALSE;
--IY;
break;
case 0x2c: /* INC IYL */
updateTStates(9);
sim_brk_pend = FALSE;
temp = lreg(IY) + 1;
Setlreg(IY, temp);
AF = (AF & ~0xfe) | incZ80Table[temp];
break;
case 0x2d: /* DEC IYL */
updateTStates(9);
sim_brk_pend = FALSE;
temp = lreg(IY) - 1;
Setlreg(IY, temp);
AF = (AF & ~0xfe) | decZ80Table[temp & 0xff];
break;
case 0x2e: /* LD IYL,nn */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IY, RAM_pp(PC));
break;
case 0x34: /* INC (IY+dd) */
updateTStates(23);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr) + 1;
PutBYTE(adr, temp);
AF = (AF & ~0xfe) | incZ80Table[temp];
break;
case 0x35: /* DEC (IY+dd) */
updateTStates(23);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr) - 1;
PutBYTE(adr, temp);
AF = (AF & ~0xfe) | decZ80Table[temp & 0xff];
break;
case 0x36: /* LD (IY+dd),nn */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, RAM_pp(PC));
break;
case 0x39: /* ADD IY,SP */
updateTStates(15);
sim_brk_pend = FALSE;
IY &= ADDRMASK;
SP &= ADDRMASK;
sum = IY + SP;
AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ SP ^ sum) >> 8];
IY = sum;
break;
case 0x44: /* LD B,IYH */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(BC, hreg(IY));
break;
case 0x45: /* LD B,IYL */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(BC, lreg(IY));
break;
case 0x46: /* LD B,(IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(BC, GetBYTE(adr));
break;
case 0x4c: /* LD C,IYH */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(BC, hreg(IY));
break;
case 0x4d: /* LD C,IYL */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(BC, lreg(IY));
break;
case 0x4e: /* LD C,(IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Setlreg(BC, GetBYTE(adr));
break;
case 0x54: /* LD D,IYH */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(DE, hreg(IY));
break;
case 0x55: /* LD D,IYL */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(DE, lreg(IY));
break;
case 0x56: /* LD D,(IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(DE, GetBYTE(adr));
break;
case 0x5c: /* LD E,IYH */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(DE, hreg(IY));
break;
case 0x5d: /* LD E,IYL */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(DE, lreg(IY));
break;
case 0x5e: /* LD E,(IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Setlreg(DE, GetBYTE(adr));
break;
case 0x60: /* LD IYH,B */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IY, hreg(BC));
break;
case 0x61: /* LD IYH,C */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IY, lreg(BC));
break;
case 0x62: /* LD IYH,D */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IY, hreg(DE));
break;
case 0x63: /* LD IYH,E */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IY, lreg(DE));
break;
case 0x64: /* LD IYH,IYH */
updateTStates(9);
sim_brk_pend = FALSE; /* nop */
break;
case 0x65: /* LD IYH,IYL */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IY, lreg(IY));
break;
case 0x66: /* LD H,(IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(HL, GetBYTE(adr));
break;
case 0x67: /* LD IYH,A */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(IY, hreg(AF));
break;
case 0x68: /* LD IYL,B */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IY, hreg(BC));
break;
case 0x69: /* LD IYL,C */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IY, lreg(BC));
break;
case 0x6a: /* LD IYL,D */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IY, hreg(DE));
break;
case 0x6b: /* LD IYL,E */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IY, lreg(DE));
break;
case 0x6c: /* LD IYL,IYH */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IY, hreg(IY));
break;
case 0x6d: /* LD IYL,IYL */
updateTStates(9);
sim_brk_pend = FALSE; /* nop */
break;
case 0x6e: /* LD L,(IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Setlreg(HL, GetBYTE(adr));
break;
case 0x6f: /* LD IYL,A */
updateTStates(9);
sim_brk_pend = FALSE;
Setlreg(IY, hreg(AF));
break;
case 0x70: /* LD (IY+dd),B */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(BC));
break;
case 0x71: /* LD (IY+dd),C */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, lreg(BC));
break;
case 0x72: /* LD (IY+dd),D */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(DE));
break;
case 0x73: /* LD (IY+dd),E */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, lreg(DE));
break;
case 0x74: /* LD (IY+dd),H */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(HL));
break;
case 0x75: /* LD (IY+dd),L */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, lreg(HL));
break;
case 0x77: /* LD (IY+dd),A */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
PutBYTE(adr, hreg(AF));
break;
case 0x7c: /* LD A,IYH */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(AF, hreg(IY));
break;
case 0x7d: /* LD A,IYL */
updateTStates(9);
sim_brk_pend = FALSE;
Sethreg(AF, lreg(IY));
break;
case 0x7e: /* LD A,(IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
Sethreg(AF, GetBYTE(adr));
break;
case 0x84: /* ADD A,IYH */
updateTStates(9);
sim_brk_pend = FALSE;
temp = hreg(IY);
acu = hreg(AF);
sum = acu + temp;
AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum];
break;
case 0x85: /* ADD A,IYL */
updateTStates(9);
sim_brk_pend = FALSE;
temp = lreg(IY);
acu = hreg(AF);
sum = acu + temp;
AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum];
break;
case 0x86: /* ADD A,(IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu + temp;
AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum];
break;
case 0x8c: /* ADC A,IYH */
updateTStates(9);
sim_brk_pend = FALSE;
temp = hreg(IY);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum];
break;
case 0x8d: /* ADC A,IYL */
updateTStates(9);
sim_brk_pend = FALSE;
temp = lreg(IY);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum];
break;
case 0x8e: /* ADC A,(IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu + temp + TSTFLAG(C);
AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum];
break;
case 0x96: /* SUB (IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu - temp;
AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
break;
case 0x94: /* SUB IYH */
SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */
case 0x9c: /* SBC A,IYH */
updateTStates(9);
sim_brk_pend = FALSE;
temp = hreg(IY);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
break;
case 0x95: /* SUB IYL */
SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */
case 0x9d: /* SBC A,IYL */
updateTStates(9);
sim_brk_pend = FALSE;
temp = lreg(IY);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
break;
case 0x9e: /* SBC A,(IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr);
acu = hreg(AF);
sum = acu - temp - TSTFLAG(C);
AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
break;
case 0xa4: /* AND IYH */
updateTStates(9);
sim_brk_pend = FALSE;
AF = andTable[((AF & IY) >> 8) & 0xff];
break;
case 0xa5: /* AND IYL */
updateTStates(9);
sim_brk_pend = FALSE;
AF = andTable[((AF >> 8) & IY) & 0xff];
break;
case 0xa6: /* AND (IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
AF = andTable[((AF >> 8) & GetBYTE(adr)) & 0xff];
break;
case 0xac: /* XOR IYH */
updateTStates(9);
sim_brk_pend = FALSE;
AF = xororTable[((AF ^ IY) >> 8) & 0xff];
break;
case 0xad: /* XOR IYL */
updateTStates(9);
sim_brk_pend = FALSE;
AF = xororTable[((AF >> 8) ^ IY) & 0xff];
break;
case 0xae: /* XOR (IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
AF = xororTable[((AF >> 8) ^ GetBYTE(adr)) & 0xff];
break;
case 0xb4: /* OR IYH */
updateTStates(9);
sim_brk_pend = FALSE;
AF = xororTable[((AF | IY) >> 8) & 0xff];
break;
case 0xb5: /* OR IYL */
updateTStates(9);
sim_brk_pend = FALSE;
AF = xororTable[((AF >> 8) | IY) & 0xff];
break;
case 0xb6: /* OR (IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
AF = xororTable[((AF >> 8) | GetBYTE(adr)) & 0xff];
break;
case 0xbc: /* CP IYH */
updateTStates(9);
sim_brk_pend = FALSE;
temp = hreg(IY);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
break;
case 0xbd: /* CP IYL */
updateTStates(9);
sim_brk_pend = FALSE;
temp = lreg(IY);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
break;
case 0xbe: /* CP (IY+dd) */
updateTStates(19);
adr = IY + (signed char) RAM_pp(PC);
CheckBreakByte(adr);
temp = GetBYTE(adr);
AF = (AF & ~0x28) | (temp & 0x28);
acu = hreg(AF);
sum = acu - temp;
AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) |
cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff];
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 */
updateTStates(23);
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) | rotateShiftTable[temp & 0xff] | !!cbits;
}
break;
case 0x40: /* BIT */
updateTStates(20);
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 */
updateTStates(23);
temp = acu & ~(1 << ((op >> 3) & 7));
break;
case 0xc0: /* SET */
updateTStates(23);
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 */
updateTStates(14);
CheckBreakWord(SP);
POP(IY);
break;
case 0xe3: /* EX (SP),IY */
updateTStates(23);
CheckBreakWord(SP);
temp = IY;
POP(IY);
PUSH(temp);
break;
case 0xe5: /* PUSH IY */
updateTStates(15);
CheckBreakWord(SP - 2);
PUSH(IY);
break;
case 0xe9: /* JP (IY) */
updateTStates(8);
sim_brk_pend = FALSE;
PCQ_ENTRY(PC - 2);
PC = IY;
break;
case 0xf9: /* LD SP,IY */
updateTStates(10);
sim_brk_pend = FALSE;
SP = IY;
break;
default: /* ignore FD */
sim_brk_pend = FALSE;
checkCPUZ80;
PC--;
}
break;
case 0xfe: /* CP nn */
updateTStates(7);
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) | cpTable[sum & 0xff] | (temp & 0x28) |
(SetPV) | cbits2Table[cbits & 0x1ff];
break;
case 0xff: /* RST 38H */
updateTStates(11);
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;
IR_S = ir;
executedTStates = tStates;
return reason;
}
static 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;
}
void printROMMessage(const uint32 cntROM) {
if (cntROM) {
printf("Warning: %d bytes written to ROM [%04X - %04X].\n", cntROM, ROMLow, ROMHigh);
}
}
/* reset routine */
t_stat cpu_reset(DEVICE *dptr) {
extern int32 sim_brk_types, sim_brk_dflt; /* breakpoint info */
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;
IR_S = IX_S = IY_S = SP_S = 0;
IFF_S = 3;
setBankSelect(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;
}
static 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;
}
}
}
#if !defined(ALTAIROPT)
static t_stat cpu_set_rom(UNIT *uptr, int32 value, char *cptr, void *desc) {
checkROMBoundaries();
return SCPE_OK;
}
static 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;
}
static 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;
}
static 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 no ROM - no warning to be expected.\n");
}
return SCPE_OK;
}
static 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 != (MAXBANKS * MAXMEMSIZE)) {
previousCapacity = MEMSIZE;
}
MEMSIZE = MAXBANKS * MAXMEMSIZE;
cpu_dev.awidth = 16 + MAXBANKSLOG2;
return SCPE_OK;
}
static t_stat cpu_set_nonbanked(UNIT *uptr, int32 value, char *cptr, void *desc) {
if (MEMSIZE == (MAXBANKS * MAXMEMSIZE)) {
MEMSIZE = previousCapacity ? previousCapacity : 64*KB;
}
cpu_dev.awidth = 16;
return SCPE_OK;
}
#endif
static t_stat cpu_set_size(UNIT *uptr, int32 value, char *cptr, void *desc) {
if (cpu_unit.flags & UNIT_BANKED) {
printf("\"SET CPU NONBANKED\" also executed.\n");
cpu_unit.flags &= ~UNIT_BANKED;
}
MEMSIZE = value;
cpu_dev.awidth = 16;
reset_memory();
return SCPE_OK;
}
/* This is the binary loader. The input file is considered to be
a string of literal bytes with no format special format. The
load starts at the current value of the PC. ROM/NOROM and
ALTAIRROM/NOALTAIRROM settings are ignored.
*/
int32 sim_load(FILE *fileref, char *cptr, char *fnam, int32 flag) {
int32 i, addr = 0, cnt = 0, org, cntROM = 0, cntNonExist = 0;
t_addr j, lo, hi;
char *result;
t_stat status;
if (flag) {
result = get_range(NULL, cptr, &lo, &hi, 16, ADDRMASK, 0);
if (result == NULL) {
return SCPE_ARG;
}
for (j = lo; j <= hi; j++) {
if (putc(GetBYTE(j), fileref) == EOF) {
return SCPE_IOERR;
}
}
printf("%d byte%s dumped [%x - %x].\n", hi + 1 - lo, hi == lo ? "" : "s", lo, hi);
}
else {
if (*cptr == 0) {
addr = saved_PC;
}
else {
addr = get_uint(cptr, 16, ADDRMASK, &status);
if (status != SCPE_OK) {
return status;
}
}
org = addr;
while ((addr < MAXMEMSIZE) && ((i = getc(fileref)) != EOF)) {
PutBYTEForced(addr, i);
if (addressIsInROM(addr)) {
cntROM++;
}
if (!addressExists(addr)) {
cntNonExist++;
}
addr++;
cnt++;
} /* end while */
printf("%d bytes [%d page%s] loaded at %x.\n", cnt, (cnt + 255) >> 8,
((cnt + 255) >> 8) == 1 ? "" : "s", org);
printROMMessage(cntROM);
if (cntNonExist) {
printf("Warning: %d bytes written to non-existing memory (for this configuration).\n", cntNonExist);
}
}
return SCPE_OK;
}