Added preliminary Zilog Z8 CPU core for MESS.
This commit is contained in:
parent
f09c9059f9
commit
1c56a127d5
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -492,6 +492,10 @@ src/emu/cpu/z180/z180op.c svneol=native#text/plain
|
||||
src/emu/cpu/z180/z180ops.h svneol=native#text/plain
|
||||
src/emu/cpu/z180/z180tbl.h svneol=native#text/plain
|
||||
src/emu/cpu/z180/z180xy.c svneol=native#text/plain
|
||||
src/emu/cpu/z8/z8.c svneol=native#text/plain
|
||||
src/emu/cpu/z8/z8.h svneol=native#text/plain
|
||||
src/emu/cpu/z8/z8dasm.c svneol=native#text/plain
|
||||
src/emu/cpu/z8/z8ops.c svneol=native#text/plain
|
||||
src/emu/cpu/z80/z80.c svneol=native#text/plain
|
||||
src/emu/cpu/z80/z80.h svneol=native#text/plain
|
||||
src/emu/cpu/z80/z80daisy.c svneol=native#text/plain
|
||||
|
@ -1577,6 +1577,22 @@ $(CPUOBJ)/z8000/z8000.o: $(CPUSRC)/z8000/z8000.c \
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------
|
||||
# Zilog Z8
|
||||
#-------------------------------------------------
|
||||
|
||||
ifneq ($(filter Z8,$(CPUS)),)
|
||||
OBJDIRS += $(CPUOBJ)/z8
|
||||
CPUOBJS += $(CPUOBJ)/z8/z8.o
|
||||
DASMOBJS += $(CPUOBJ)/z8/z8dasm.o
|
||||
endif
|
||||
|
||||
$(CPUOBJ)/z8/z8.o: $(CPUSRC)/z8/z8.c \
|
||||
$(CPUSRC)/z8/z8ops.c \
|
||||
$(CPUSRC)/z8/z8.h
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------
|
||||
# Argonaut SuperFX
|
||||
#-------------------------------------------------
|
||||
|
948
src/emu/cpu/z8/z8.c
Normal file
948
src/emu/cpu/z8/z8.c
Normal file
@ -0,0 +1,948 @@
|
||||
/**********************************************************************
|
||||
|
||||
Zilog Z8 Single-Chip MCU emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
/*
|
||||
|
||||
TODO:
|
||||
|
||||
- strobed I/O
|
||||
- interrupts
|
||||
- expose register file to disassembler
|
||||
- decimal adjust instruction
|
||||
- timer Tin/Tout modes
|
||||
- serial
|
||||
- instruction pipeline
|
||||
|
||||
*/
|
||||
|
||||
#include "driver.h"
|
||||
#include "debugger.h"
|
||||
#include "z8.h"
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
|
||||
enum
|
||||
{
|
||||
Z8_REGISTER_P0 = 0,
|
||||
Z8_REGISTER_P1,
|
||||
Z8_REGISTER_P2,
|
||||
Z8_REGISTER_P3,
|
||||
Z8_REGISTER_SIO = 0xf0,
|
||||
Z8_REGISTER_TMR,
|
||||
Z8_REGISTER_T1,
|
||||
Z8_REGISTER_PRE1,
|
||||
Z8_REGISTER_T0,
|
||||
Z8_REGISTER_PRE0,
|
||||
Z8_REGISTER_P2M,
|
||||
Z8_REGISTER_P3M,
|
||||
Z8_REGISTER_P01M,
|
||||
Z8_REGISTER_IPR,
|
||||
Z8_REGISTER_IRQ,
|
||||
Z8_REGISTER_IMR,
|
||||
Z8_REGISTER_FLAGS,
|
||||
Z8_REGISTER_RP,
|
||||
Z8_REGISTER_SPH,
|
||||
Z8_REGISTER_SPL
|
||||
};
|
||||
|
||||
#define Z8_P3_DAV0 0x04 /* not supported */
|
||||
#define Z8_P3_DAV1 0x08 /* not supported */
|
||||
#define Z8_P3_DAV2 0x02 /* not supported */
|
||||
#define Z8_P3_RDY0 0x20 /* not supported */
|
||||
#define Z8_P3_RDY1 0x10 /* not supported */
|
||||
#define Z8_P3_RDY2 0x40 /* not supported */
|
||||
#define Z8_P3_IRQ0 0x04 /* not supported */
|
||||
#define Z8_P3_IRQ1 0x08 /* not supported */
|
||||
#define Z8_P3_IRQ2 0x02 /* not supported */
|
||||
#define Z8_P3_IRQ3 0x01 /* not supported */
|
||||
#define Z8_P3_DI 0x01 /* not supported */
|
||||
#define Z8_P3_DO 0x80 /* not supported */
|
||||
#define Z8_P3_TIN 0x02 /* not supported */
|
||||
#define Z8_P3_TOUT 0x40 /* not supported */
|
||||
#define Z8_P3_DM 0x10 /* not supported */
|
||||
|
||||
#define Z8_PRE0_COUNT_MODULO_N 0x01
|
||||
|
||||
#define Z8_PRE1_COUNT_MODULO_N 0x01
|
||||
#define Z8_PRE1_INTERNAL_CLOCK 0x02
|
||||
|
||||
#define Z8_TMR_LOAD_T0 0x01
|
||||
#define Z8_TMR_ENABLE_T0 0x02
|
||||
#define Z8_TMR_LOAD_T1 0x04
|
||||
#define Z8_TMR_ENABLE_T1 0x08
|
||||
#define Z8_TMR_TIN_MASK 0x30 /* not supported */
|
||||
#define Z8_TMR_TIN_EXTERNAL_CLK 0x00 /* not supported */
|
||||
#define Z8_TMR_TIN_GATE 0x10 /* not supported */
|
||||
#define Z8_TMR_TIN_TRIGGER 0x20 /* not supported */
|
||||
#define Z8_TMR_TIN_RETRIGGER 0x30 /* not supported */
|
||||
#define Z8_TMR_TOUT_MASK 0xc0 /* not supported */
|
||||
#define Z8_TMR_TOUT_OFF 0x00 /* not supported */
|
||||
#define Z8_TMR_TOUT_T0 0x40 /* not supported */
|
||||
#define Z8_TMR_TOUT_T1 0x80 /* not supported */
|
||||
#define Z8_TMR_TOUT_INTERNAL_CLK 0xc0 /* not supported */
|
||||
|
||||
#define Z8_P01M_P0L_MODE_MASK 0x03
|
||||
#define Z8_P01M_P0L_MODE_OUTPUT 0x00
|
||||
#define Z8_P01M_P0L_MODE_INPUT 0x01
|
||||
#define Z8_P01M_P0L_MODE_A8_A11 0x02 /* not supported */
|
||||
#define Z8_P01M_INTERNAL_STACK 0x04
|
||||
#define Z8_P01M_P1_MODE_MASK 0x18
|
||||
#define Z8_P01M_P1_MODE_OUTPUT 0x00
|
||||
#define Z8_P01M_P1_MODE_INPUT 0x08
|
||||
#define Z8_P01M_P1_MODE_AD0_AD7 0x10 /* not supported */
|
||||
#define Z8_P01M_P1_MODE_HI_Z 0x18 /* not supported */
|
||||
#define Z8_P01M_EXTENDED_TIMING 0x20 /* not supported */
|
||||
#define Z8_P01M_P0H_MODE_MASK 0xc0
|
||||
#define Z8_P01M_P0H_MODE_OUTPUT 0x00
|
||||
#define Z8_P01M_P0H_MODE_INPUT 0x40
|
||||
#define Z8_P01M_P0H_MODE_A12_A15 0x80 /* not supported */
|
||||
|
||||
#define Z8_P3M_P2_ACTIVE_PULLUPS 0x01 /* not supported */
|
||||
#define Z8_P3M_P0_STROBED 0x04 /* not supported */
|
||||
#define Z8_P3M_P33_P34_MASK 0x18
|
||||
#define Z8_P3M_P33_P34_INPUT_OUTPUT 0x00
|
||||
#define Z8_P3M_P33_P34_INPUT_DM 0x08 /* not supported */
|
||||
#define Z8_P3M_P33_P34_INPUT_DM_2 0x10 /* not supported */
|
||||
#define Z8_P3M_P33_P34_DAV1_RDY1 0x18 /* not supported */
|
||||
#define Z8_P3M_P2_STROBED 0x20 /* not supported */
|
||||
#define Z8_P3M_P3_SERIAL 0x40 /* not supported */
|
||||
#define Z8_P3M_PARITY 0x80 /* not supported */
|
||||
|
||||
#define Z8_IMR_ENABLE 0x80 /* not supported */
|
||||
#define Z8_IMR_RAM_PROTECT 0x40 /* not supported */
|
||||
#define Z8_IMR_ENABLE_IRQ5 0x20 /* not supported */
|
||||
#define Z8_IMR_ENABLE_IRQ4 0x10 /* not supported */
|
||||
#define Z8_IMR_ENABLE_IRQ3 0x08 /* not supported */
|
||||
#define Z8_IMR_ENABLE_IRQ2 0x04 /* not supported */
|
||||
#define Z8_IMR_ENABLE_IRQ1 0x02 /* not supported */
|
||||
#define Z8_IMR_ENABLE_IRQ0 0x01 /* not supported */
|
||||
|
||||
#define Z8_FLAGS_F1 0x01
|
||||
#define Z8_FLAGS_F2 0x02
|
||||
#define Z8_FLAGS_H 0x04
|
||||
#define Z8_FLAGS_D 0x08
|
||||
#define Z8_FLAGS_V 0x10
|
||||
#define Z8_FLAGS_S 0x20
|
||||
#define Z8_FLAGS_Z 0x40
|
||||
#define Z8_FLAGS_C 0x80
|
||||
|
||||
enum
|
||||
{
|
||||
CC_F = 0, CC_LT, CC_LE, CC_ULE, CC_OV, CC_MI, CC_Z, CC_C,
|
||||
CC_T, CC_GE, CC_GT, CC_UGT, CC_NOV, CC_PL, CC_NZ, CC_NC
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
MACROS
|
||||
***************************************************************************/
|
||||
|
||||
#define P01M cpustate->r[Z8_REGISTER_P01M]
|
||||
#define P2M cpustate->r[Z8_REGISTER_P2M]
|
||||
#define P3M cpustate->r[Z8_REGISTER_P3M]
|
||||
#define T0 cpustate->r[Z8_REGISTER_T0]
|
||||
#define T1 cpustate->r[Z8_REGISTER_T1]
|
||||
#define PRE0 cpustate->r[Z8_REGISTER_PRE0]
|
||||
#define PRE1 cpustate->r[Z8_REGISTER_PRE1]
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
typedef struct _z8_state z8_state;
|
||||
struct _z8_state
|
||||
{
|
||||
const address_space *program;
|
||||
const address_space *data;
|
||||
const address_space *io;
|
||||
|
||||
/* registers */
|
||||
UINT16 pc; /* program counter */
|
||||
UINT8 r[256]; /* register file */
|
||||
UINT8 input[4]; /* port input latches */
|
||||
UINT8 output[4]; /* port output latches */
|
||||
UINT8 t0; /* timer 0 current count */
|
||||
UINT8 t1; /* timer 1 current count */
|
||||
|
||||
/* fake registers */
|
||||
UINT16 fake_sp; /* fake stack pointer */
|
||||
UINT8 fake_r[16]; /* fake working registers */
|
||||
|
||||
/* interrupts */
|
||||
int irq[6]; /* interrupts */
|
||||
|
||||
/* execution logic */
|
||||
int clock; /* clock */
|
||||
int icount; /* instruction counter */
|
||||
|
||||
cpu_state_table state_table;
|
||||
|
||||
/* timers */
|
||||
emu_timer *t0_timer;
|
||||
emu_timer *t1_timer;
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
CPU STATE DESCRIPTION
|
||||
***************************************************************************/
|
||||
|
||||
#define Z8_STATE_ENTRY(_name, _format, _member, _datamask, _flags) \
|
||||
CPU_STATE_ENTRY(Z8_##_name, #_name, _format, z8_state, _member, _datamask, ~0, _flags)
|
||||
|
||||
static const cpu_state_entry state_array[] =
|
||||
{
|
||||
Z8_STATE_ENTRY(PC, "%04X", pc, 0xffff, 0)
|
||||
Z8_STATE_ENTRY(GENPC, "%04X", pc, 0xffff, CPUSTATE_NOSHOW)
|
||||
Z8_STATE_ENTRY(SP, "%04X", fake_sp, 0xffff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(GENSP, "%04X", fake_sp, 0xffff, CPUSTATE_NOSHOW | CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(RP, "%02X", r[Z8_REGISTER_RP], 0xff, 0)
|
||||
Z8_STATE_ENTRY(T0, "%02X", t0, 0xff, 0)
|
||||
Z8_STATE_ENTRY(T1, "%02X", t1, 0xff, 0)
|
||||
|
||||
Z8_STATE_ENTRY(R0, "%02X", fake_r[0], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R1, "%02X", fake_r[1], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R2, "%02X", fake_r[2], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R3, "%02X", fake_r[3], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R4, "%02X", fake_r[4], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R5, "%02X", fake_r[5], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R6, "%02X", fake_r[6], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R7, "%02X", fake_r[7], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R8, "%02X", fake_r[8], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R9, "%02X", fake_r[9], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R10, "%02X", fake_r[10], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R11, "%02X", fake_r[11], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R12, "%02X", fake_r[12], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R13, "%02X", fake_r[13], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R14, "%02X", fake_r[14], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
Z8_STATE_ENTRY(R15, "%02X", fake_r[15], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
|
||||
};
|
||||
|
||||
static const cpu_state_table state_table_template =
|
||||
{
|
||||
NULL, /* pointer to the base of state (offsets are relative to this) */
|
||||
0, /* subtype this table refers to */
|
||||
ARRAY_LENGTH(state_array), /* number of entries */
|
||||
state_array /* array of entries */
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
INLINE FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
INLINE z8_state *get_safe_token(const device_config *device)
|
||||
{
|
||||
assert(device != NULL);
|
||||
assert(device->token != NULL);
|
||||
assert(device->type == CPU);
|
||||
assert((cpu_get_type(device) == CPU_Z8601) ||
|
||||
(cpu_get_type(device) == CPU_UB8830D) ||
|
||||
(cpu_get_type(device) == CPU_Z8611));
|
||||
return (z8_state *)device->token;
|
||||
}
|
||||
|
||||
INLINE UINT8 fetch(z8_state *cpustate)
|
||||
{
|
||||
UINT8 data = memory_decrypted_read_byte(cpustate->program, cpustate->pc);
|
||||
|
||||
cpustate->pc++;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
INLINE UINT8 register_read(z8_state *cpustate, UINT8 offset)
|
||||
{
|
||||
UINT8 data = 0xff;
|
||||
UINT8 mask = 0;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case Z8_REGISTER_P0:
|
||||
switch (P01M & Z8_P01M_P0L_MODE_MASK)
|
||||
{
|
||||
case Z8_P01M_P0L_MODE_OUTPUT: data = cpustate->output[offset] & 0x0f; break;
|
||||
case Z8_P01M_P0L_MODE_INPUT: mask = 0x0f; break;
|
||||
default: /* A8...A11 */ data = 0x0f; break;
|
||||
}
|
||||
|
||||
switch (P01M & Z8_P01M_P0H_MODE_MASK)
|
||||
{
|
||||
case Z8_P01M_P0H_MODE_OUTPUT: data |= cpustate->output[offset] & 0xf0; break;
|
||||
case Z8_P01M_P0H_MODE_INPUT: mask |= 0xf0; break;
|
||||
default: /* A12...A15 */ data |= 0xf0; break;
|
||||
}
|
||||
|
||||
if (!(P3M & Z8_P3M_P0_STROBED))
|
||||
{
|
||||
if (mask) cpustate->input[offset] = memory_read_byte_8be(cpustate->io, offset);
|
||||
}
|
||||
|
||||
data |= cpustate->input[offset] & mask;
|
||||
break;
|
||||
|
||||
case Z8_REGISTER_P1:
|
||||
switch (P01M & Z8_P01M_P1_MODE_MASK)
|
||||
{
|
||||
case Z8_P01M_P1_MODE_OUTPUT: data = cpustate->output[offset]; break;
|
||||
case Z8_P01M_P1_MODE_INPUT: mask = 0xff; break;
|
||||
default: /* AD0..AD7 */ data = 0xff; break;
|
||||
}
|
||||
|
||||
if ((P3M & Z8_P3M_P33_P34_MASK) != Z8_P3M_P33_P34_DAV1_RDY1)
|
||||
{
|
||||
if (mask) cpustate->input[offset] = memory_read_byte_8be(cpustate->io, offset);
|
||||
}
|
||||
|
||||
data |= cpustate->input[offset] & mask;
|
||||
break;
|
||||
|
||||
case Z8_REGISTER_P2:
|
||||
mask = cpustate->r[Z8_REGISTER_P2M];
|
||||
|
||||
if (!(P3M & Z8_P3M_P2_STROBED))
|
||||
{
|
||||
if (mask) cpustate->input[offset] = memory_read_byte_8be(cpustate->io, offset);
|
||||
}
|
||||
|
||||
data = (cpustate->input[offset] & mask) | (cpustate->output[offset] & ~mask);
|
||||
break;
|
||||
|
||||
case Z8_REGISTER_P3:
|
||||
// TODO: special port 3 modes
|
||||
if (!(P3M & 0x7c))
|
||||
{
|
||||
mask = 0x0f;
|
||||
}
|
||||
|
||||
if (mask) cpustate->input[offset] = memory_read_byte_8be(cpustate->io, offset);
|
||||
|
||||
data = (cpustate->input[offset] & mask) | (cpustate->output[offset] & ~mask);
|
||||
break;
|
||||
|
||||
case Z8_REGISTER_T0:
|
||||
data = cpustate->t0;
|
||||
break;
|
||||
|
||||
case Z8_REGISTER_T1:
|
||||
data = cpustate->t1;
|
||||
break;
|
||||
|
||||
case Z8_REGISTER_PRE1:
|
||||
case Z8_REGISTER_PRE0:
|
||||
case Z8_REGISTER_P2M:
|
||||
case Z8_REGISTER_P3M:
|
||||
case Z8_REGISTER_P01M:
|
||||
case Z8_REGISTER_IPR:
|
||||
/* write only */
|
||||
break;
|
||||
|
||||
default:
|
||||
data = cpustate->r[offset];
|
||||
break;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
INLINE UINT16 register_pair_read(z8_state *cpustate, UINT8 offset)
|
||||
{
|
||||
return (register_read(cpustate, offset) << 8) | register_read(cpustate, offset + 1);
|
||||
}
|
||||
|
||||
INLINE void register_write(z8_state *cpustate, UINT8 offset, UINT8 data)
|
||||
{
|
||||
UINT8 mask = 0;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case Z8_REGISTER_P0:
|
||||
cpustate->output[offset] = data;
|
||||
if ((P01M & Z8_P01M_P0L_MODE_MASK) == Z8_P01M_P0L_MODE_OUTPUT) mask |= 0x0f;
|
||||
if ((P01M & Z8_P01M_P0H_MODE_MASK) == Z8_P01M_P0H_MODE_OUTPUT) mask |= 0xf0;
|
||||
if (mask) memory_write_byte_8be(cpustate->io, offset, data & mask);
|
||||
break;
|
||||
|
||||
case Z8_REGISTER_P1:
|
||||
cpustate->output[offset] = data;
|
||||
if ((P01M & Z8_P01M_P1_MODE_MASK) == Z8_P01M_P1_MODE_OUTPUT) mask = 0xff;
|
||||
if (mask) memory_write_byte_8be(cpustate->io, offset, data & mask);
|
||||
break;
|
||||
|
||||
case Z8_REGISTER_P2:
|
||||
cpustate->output[offset] = data;
|
||||
mask = cpustate->r[Z8_REGISTER_P2M] ^ 0xff;
|
||||
if (mask) memory_write_byte_8be(cpustate->io, offset, data & mask);
|
||||
break;
|
||||
|
||||
case Z8_REGISTER_P3:
|
||||
cpustate->output[offset] = data;
|
||||
|
||||
// TODO: special port 3 modes
|
||||
if (!(P3M & 0x7c))
|
||||
{
|
||||
mask = 0xf0;
|
||||
}
|
||||
|
||||
if (mask) memory_write_byte_8be(cpustate->io, offset, data & mask);
|
||||
break;
|
||||
|
||||
case Z8_REGISTER_SIO:
|
||||
break;
|
||||
|
||||
case Z8_REGISTER_TMR:
|
||||
if (data & Z8_TMR_LOAD_T0)
|
||||
{
|
||||
cpustate->t0 = T0;
|
||||
timer_adjust_periodic(cpustate->t0_timer, attotime_zero, 0, ATTOTIME_IN_HZ(cpustate->clock / 2 / 4 / ((PRE0 >> 2) + 1)));
|
||||
}
|
||||
|
||||
timer_enable(cpustate->t0_timer, data & Z8_TMR_ENABLE_T0);
|
||||
|
||||
if (data & Z8_TMR_LOAD_T1)
|
||||
{
|
||||
cpustate->t1 = T1;
|
||||
timer_adjust_periodic(cpustate->t1_timer, attotime_zero, 0, ATTOTIME_IN_HZ(cpustate->clock / 2 / 4 / ((PRE1 >> 2) + 1)));
|
||||
}
|
||||
|
||||
timer_enable(cpustate->t1_timer, data & Z8_TMR_ENABLE_T1);
|
||||
break;
|
||||
|
||||
case Z8_REGISTER_P2M:
|
||||
break;
|
||||
case Z8_REGISTER_P3M:
|
||||
break;
|
||||
case Z8_REGISTER_P01M:
|
||||
break;
|
||||
case Z8_REGISTER_IPR:
|
||||
break;
|
||||
case Z8_REGISTER_IRQ:
|
||||
break;
|
||||
case Z8_REGISTER_IMR:
|
||||
break;
|
||||
case Z8_REGISTER_FLAGS:
|
||||
break;
|
||||
case Z8_REGISTER_RP:
|
||||
break;
|
||||
case Z8_REGISTER_SPH:
|
||||
break;
|
||||
case Z8_REGISTER_SPL:
|
||||
break;
|
||||
default:
|
||||
// TODO ignore missing registers
|
||||
break;
|
||||
}
|
||||
|
||||
cpustate->r[offset] = data;
|
||||
}
|
||||
|
||||
INLINE void register_pair_write(z8_state *cpustate, UINT8 offset, UINT16 data)
|
||||
{
|
||||
register_write(cpustate, offset, data >> 8);
|
||||
register_write(cpustate, offset + 1, data & 0xff);
|
||||
}
|
||||
|
||||
INLINE UINT8 get_working_register(z8_state *cpustate, int offset)
|
||||
{
|
||||
return (cpustate->r[Z8_REGISTER_RP] & 0xf0) | (offset & 0x0f);
|
||||
}
|
||||
|
||||
INLINE UINT8 get_register(z8_state *cpustate, UINT8 offset)
|
||||
{
|
||||
if ((offset & 0xf0) == 0xe0)
|
||||
return get_working_register(cpustate, offset & 0x0f);
|
||||
else
|
||||
return offset;
|
||||
}
|
||||
|
||||
INLINE UINT8 get_intermediate_register(z8_state *cpustate, int offset)
|
||||
{
|
||||
return register_read(cpustate, get_register(cpustate, offset));
|
||||
}
|
||||
|
||||
INLINE void stack_push_byte(z8_state *cpustate, UINT8 src)
|
||||
{
|
||||
if (register_read(cpustate, Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK)
|
||||
{
|
||||
/* SP <- SP - 1 */
|
||||
UINT8 sp = register_read(cpustate, Z8_REGISTER_SPL) - 1;
|
||||
register_write(cpustate, Z8_REGISTER_SPL, sp);
|
||||
|
||||
/* @SP <- src */
|
||||
register_write(cpustate, sp, src);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SP <- SP - 1 */
|
||||
UINT16 sp = register_pair_read(cpustate, Z8_REGISTER_SPH) - 1;
|
||||
register_pair_write(cpustate, Z8_REGISTER_SPH, sp);
|
||||
|
||||
/* @SP <- src */
|
||||
memory_write_byte(cpustate->data, sp, src);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void stack_push_word(z8_state *cpustate, UINT16 src)
|
||||
{
|
||||
if (register_read(cpustate, Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK)
|
||||
{
|
||||
/* SP <- SP - 2 */
|
||||
UINT8 sp = register_read(cpustate, Z8_REGISTER_SPL) - 2;
|
||||
register_write(cpustate, Z8_REGISTER_SPL, sp);
|
||||
|
||||
/* @SP <- src */
|
||||
register_pair_write(cpustate, sp, src);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SP <- SP - 2 */
|
||||
UINT16 sp = register_pair_read(cpustate, Z8_REGISTER_SPH) - 2;
|
||||
register_pair_write(cpustate, Z8_REGISTER_SPH, sp);
|
||||
|
||||
/* @SP <- src */
|
||||
memory_write_word_8le(cpustate->data, sp, src);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE UINT8 stack_pop_byte(z8_state *cpustate)
|
||||
{
|
||||
if (register_read(cpustate, Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK)
|
||||
{
|
||||
/* SP <- SP + 1 */
|
||||
UINT8 sp = register_read(cpustate, Z8_REGISTER_SPL) + 1;
|
||||
register_write(cpustate, Z8_REGISTER_SPL, sp);
|
||||
|
||||
/* @SP <- src */
|
||||
return register_read(cpustate, sp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SP <- SP + 1 */
|
||||
UINT16 sp = register_pair_read(cpustate, Z8_REGISTER_SPH) + 1;
|
||||
register_pair_write(cpustate, Z8_REGISTER_SPH, sp);
|
||||
|
||||
/* @SP <- src */
|
||||
return memory_read_byte(cpustate->data, sp);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE UINT16 stack_pop_word(z8_state *cpustate)
|
||||
{
|
||||
if (register_read(cpustate, Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK)
|
||||
{
|
||||
/* SP <- SP + 2 */
|
||||
UINT8 sp = register_read(cpustate, Z8_REGISTER_SPL) + 2;
|
||||
register_write(cpustate, Z8_REGISTER_SPL, sp);
|
||||
|
||||
/* @SP <- src */
|
||||
return register_read(cpustate, sp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SP <- SP + 2 */
|
||||
UINT16 sp = register_pair_read(cpustate, Z8_REGISTER_SPH) + 2;
|
||||
register_pair_write(cpustate, Z8_REGISTER_SPH, sp);
|
||||
|
||||
/* @SP <- src */
|
||||
return memory_read_word_8le(cpustate->data, sp);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void set_flag(z8_state *cpustate, UINT8 flag, int state)
|
||||
{
|
||||
if (state)
|
||||
cpustate->r[Z8_REGISTER_FLAGS] |= flag;
|
||||
else
|
||||
cpustate->r[Z8_REGISTER_FLAGS] &= ~flag;
|
||||
}
|
||||
|
||||
#define set_flag_h(state) set_flag(cpustate, Z8_FLAGS_H, state);
|
||||
#define set_flag_d(state) set_flag(cpustate, Z8_FLAGS_D, state);
|
||||
#define set_flag_v(state) set_flag(cpustate, Z8_FLAGS_V, state);
|
||||
#define set_flag_s(state) set_flag(cpustate, Z8_FLAGS_S, state);
|
||||
#define set_flag_z(state) set_flag(cpustate, Z8_FLAGS_Z, state);
|
||||
#define set_flag_c(state) set_flag(cpustate, Z8_FLAGS_C, state);
|
||||
|
||||
/***************************************************************************
|
||||
OPCODE HANDLERS
|
||||
***************************************************************************/
|
||||
|
||||
#define INSTRUCTION(mnemonic) INLINE void (mnemonic)(z8_state *cpustate, UINT8 opcode, int *cycles)
|
||||
|
||||
INSTRUCTION( illegal )
|
||||
{
|
||||
logerror("Z8: PC = %04x, Illegal opcode = %02x\n", cpustate->pc - 1, opcode);
|
||||
}
|
||||
|
||||
#include "z8ops.c"
|
||||
|
||||
/***************************************************************************
|
||||
OPCODE TABLES
|
||||
***************************************************************************/
|
||||
|
||||
typedef void (*z8_opcode_func) (z8_state *cpustate, UINT8 opcode, int *cycles);
|
||||
|
||||
typedef struct _z8_opcode_map z8_opcode_map;
|
||||
struct _z8_opcode_map
|
||||
{
|
||||
z8_opcode_func function;
|
||||
int execution_cycles;
|
||||
int pipeline_cycles;
|
||||
};
|
||||
|
||||
static const z8_opcode_map Z8601_OPCODE_MAP[] =
|
||||
{
|
||||
{ dec_R1, 6, 5 }, { dec_IR1, 6, 5 }, { add_r1_r2, 10, 5 }, { add_r1_Ir2, 10, 5 }, { add_R2_R1, 10, 5 }, { add_IR2_R1, 10, 5 }, { add_R1_IM, 10, 5 }, { add_IR1_IM, 10, 5 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
|
||||
|
||||
{ rlc_R1, 6, 5 }, { rlc_IR1, 6, 5 }, { adc_r1_r2, 6, 5 }, { adc_r1_Ir2, 6, 5 }, { adc_R2_R1, 10, 5 }, { adc_IR2_R1, 10, 5 }, { adc_R1_IM, 10, 5 }, { adc_IR1_IM, 10, 5 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
|
||||
|
||||
{ inc_R1, 6, 5 }, { inc_IR1, 6, 5 }, { sub_r1_r2, 6, 5 }, { sub_r1_Ir2, 6, 5 }, { sub_R2_R1, 10, 5 }, { sub_IR2_R1, 10, 5 }, { sub_R1_IM, 10, 5 }, { sub_IR1_IM, 10, 5 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
|
||||
|
||||
{ jp_IRR1, 8, 0 }, { srp_IM, 6, 1 }, { sbc_r1_r2, 6, 5 }, { sbc_r1_Ir2, 6, 5 }, { sbc_R2_R1, 10, 5 }, { sbc_IR2_R1, 10, 5 }, { sbc_R1_IM, 10, 5 }, { sbc_IR1_IM, 10, 5 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
|
||||
|
||||
{ da_R1, 8, 5 }, { da_IR1, 8, 5 }, { or_r1_r2, 6, 5 }, { or_r1_Ir2, 6, 5 }, { or_R2_R1, 10, 5 }, { or_IR2_R1, 10, 5 }, { or_R1_IM, 10, 5 }, { or_IR1_IM, 10, 5 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
|
||||
|
||||
{ pop_R1, 10, 5 }, { pop_IR1, 10, 5 }, { and_r1_r2, 6, 5 }, { and_r1_Ir2, 6, 5 }, { and_R2_R1, 10, 5 }, { and_IR2_R1, 10, 5 }, { and_R1_IM, 10, 5 }, { and_IR1_IM, 10, 5 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
|
||||
|
||||
{ com_R1, 6, 5 }, { com_IR1, 6, 5 }, { tcm_r1_r2, 6, 5 }, { tcm_r1_Ir2, 6, 5 }, { tcm_R2_R1, 10, 5 }, { tcm_IR2_R1, 10, 5 }, { tcm_R1_IM, 10, 5 }, { tcm_IR1_IM, 10, 5 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
|
||||
|
||||
{ push_R2, 10, 1 }, { push_IR2, 12, 1 },{ tm_r1_r2, 6, 5 }, { tm_r1_Ir2, 6, 5 }, { tm_R2_R1, 10, 5 }, { tm_IR2_R1, 10, 5 }, { tm_R1_IM, 10, 5 }, { tm_IR1_IM, 10, 5 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
|
||||
|
||||
{ decw_RR1, 10, 5 },{ decw_IR1, 10, 5 },{ lde_r1_Irr2, 12, 0 }, { ldei_Ir1_Irr2, 18, 0 },{ illegal, 0, 0 }, { illegal, 0, 0 }, { illegal, 0, 0 }, { illegal, 0, 0 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { di, 6, 1 },
|
||||
|
||||
{ rl_R1, 6, 5 }, { rl_IR1, 6, 5 }, { lde_r2_Irr1, 12, 0 }, { ldei_Ir2_Irr1, 18, 0 },{ illegal, 0, 0 }, { illegal, 0, 0 }, { illegal, 0, 0 }, { illegal, 0, 0 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { ei, 6, 1 },
|
||||
|
||||
{ incw_RR1, 10, 5 },{ incw_IR1, 10, 5 },{ cp_r1_r2, 6, 5 }, { cp_r1_Ir2, 6, 5 }, { cp_R2_R1, 10, 5 }, { cp_IR2_R1, 10, 5 }, { cp_R1_IM, 10, 5 }, { cp_IR1_IM, 10, 5 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { ret, 14, 0 },
|
||||
|
||||
{ clr_R1, 6, 5 }, { clr_IR1, 6, 5 }, { xor_r1_r2, 6, 5 }, { xor_r1_Ir2, 6, 5 }, { xor_R2_R1, 10, 5 }, { xor_IR2_R1, 10, 5 }, { xor_R1_IM, 10, 5 }, { xor_IR1_IM, 10, 5 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { iret, 16, 0 },
|
||||
|
||||
{ rrc_R1, 6, 5 }, { rrc_IR1, 6, 5 }, { ldc_r1_Irr2, 12, 0 }, { ldci_Ir1_Irr2, 18, 0 },{ illegal, 0, 0 }, { illegal, 0, 0 }, { illegal, 0, 0 }, { ld_r1_x_R2, 10, 5 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { rcf, 6, 5 },
|
||||
|
||||
{ sra_R1, 6, 5 }, { sra_IR1, 6, 5 }, { ldc_r2_Irr1, 12, 0 }, { ldci_Ir2_Irr1, 18, 0 },{ call_IRR1, 20, 0 }, { illegal, 0, 0 }, { call_DA, 20, 0 }, { ld_r2_x_R1, 10, 5 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { scf, 6, 5 },
|
||||
|
||||
{ rr_R1, 6, 5 }, { rr_IR1, 6, 5 }, { illegal, 0, 0 }, { ld_r1_Ir2, 6, 5 }, { ld_R2_R1, 10, 5 }, { ld_IR2_R1, 10, 5 }, { ld_R1_IM, 10, 5 }, { ld_IR1_IM, 10, 5 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { ccf, 6, 5 },
|
||||
|
||||
{ swap_R1, 8, 5 }, { swap_IR1, 8, 5 }, { illegal, 0, 0 }, { ld_Ir1_r2, 6, 5 }, { illegal, 0, 0 }, { ld_R2_IR1, 10, 5 }, { illegal, 0, 0 }, { illegal, 0, 0 },
|
||||
{ ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { nop, 6, 0 },
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
TIMER CALLBACKS
|
||||
***************************************************************************/
|
||||
|
||||
static TIMER_CALLBACK( t0_tick )
|
||||
{
|
||||
z8_state *cpustate = (z8_state *)ptr;
|
||||
|
||||
cpustate->t0--;
|
||||
|
||||
if (cpustate->t0 == 0)
|
||||
{
|
||||
cpustate->t0 = T0;
|
||||
timer_adjust_periodic(cpustate->t0_timer, attotime_zero, 0, ATTOTIME_IN_HZ(cpustate->clock / 2 / 4 / ((PRE0 >> 2) + 1)));
|
||||
timer_enable(cpustate->t0_timer, PRE0 & Z8_PRE0_COUNT_MODULO_N);
|
||||
cpustate->irq[4] = ASSERT_LINE;
|
||||
}
|
||||
}
|
||||
|
||||
static TIMER_CALLBACK( t1_tick )
|
||||
{
|
||||
z8_state *cpustate = (z8_state *)ptr;
|
||||
|
||||
cpustate->t1--;
|
||||
|
||||
if (cpustate->t1 == 0)
|
||||
{
|
||||
cpustate->t1 = T1;
|
||||
timer_adjust_periodic(cpustate->t1_timer, attotime_zero, 0, ATTOTIME_IN_HZ(cpustate->clock / 2 / 4 / ((PRE1 >> 2) + 1)));
|
||||
timer_enable(cpustate->t1_timer, PRE1 & Z8_PRE0_COUNT_MODULO_N);
|
||||
cpustate->irq[5] = ASSERT_LINE;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
INITIALIZATION
|
||||
***************************************************************************/
|
||||
|
||||
static CPU_INIT( z8 )
|
||||
{
|
||||
z8_state *cpustate = get_safe_token(device);
|
||||
|
||||
/* set up the state table */
|
||||
cpustate->state_table = state_table_template;
|
||||
cpustate->state_table.baseptr = cpustate;
|
||||
cpustate->state_table.subtypemask = 1;
|
||||
|
||||
cpustate->clock = device->clock;
|
||||
|
||||
/* find address spaces */
|
||||
cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM);
|
||||
cpustate->data = memory_find_address_space(device, ADDRESS_SPACE_DATA);
|
||||
cpustate->io = memory_find_address_space(device, ADDRESS_SPACE_IO);
|
||||
|
||||
/* allocate timers */
|
||||
cpustate->t0_timer = timer_alloc(device->machine, t0_tick, cpustate);
|
||||
cpustate->t1_timer = timer_alloc(device->machine, t1_tick, cpustate);
|
||||
|
||||
/* register for state saving */
|
||||
state_save_register_device_item(device, 0, cpustate->pc);
|
||||
state_save_register_device_item_array(device, 0, cpustate->r);
|
||||
state_save_register_device_item_array(device, 0, cpustate->input);
|
||||
state_save_register_device_item_array(device, 0, cpustate->output);
|
||||
state_save_register_device_item_array(device, 0, cpustate->irq);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
EXECUTION
|
||||
***************************************************************************/
|
||||
|
||||
static CPU_EXECUTE( z8 )
|
||||
{
|
||||
z8_state *cpustate = get_safe_token(device);
|
||||
|
||||
cpustate->icount = cycles;
|
||||
|
||||
do
|
||||
{
|
||||
UINT8 opcode;
|
||||
int cycles;
|
||||
|
||||
debugger_instruction_hook(device, cpustate->pc);
|
||||
|
||||
/* TODO: sample interrupts */
|
||||
cpustate->input[3] = memory_read_byte_8be(cpustate->io, 3);
|
||||
|
||||
/* fetch opcode */
|
||||
opcode = fetch(cpustate);
|
||||
cycles = Z8601_OPCODE_MAP[opcode].execution_cycles;
|
||||
|
||||
/* execute instruction */
|
||||
(*(Z8601_OPCODE_MAP[opcode].function))(cpustate, opcode, &cycles);
|
||||
|
||||
cpustate->icount -= cycles;
|
||||
}
|
||||
while (cpustate->icount > 0);
|
||||
|
||||
return cycles - cpustate->icount;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
RESET
|
||||
***************************************************************************/
|
||||
|
||||
static CPU_RESET( z8 )
|
||||
{
|
||||
z8_state *cpustate = get_safe_token(device);
|
||||
|
||||
cpustate->pc = 0x000c;
|
||||
|
||||
register_write(cpustate, Z8_REGISTER_TMR, 0x00);
|
||||
register_write(cpustate, Z8_REGISTER_PRE1, register_read(cpustate, Z8_REGISTER_PRE1) & 0xfc);
|
||||
register_write(cpustate, Z8_REGISTER_PRE0, register_read(cpustate, Z8_REGISTER_PRE0) & 0xfe);
|
||||
register_write(cpustate, Z8_REGISTER_P2M, 0xff);
|
||||
register_write(cpustate, Z8_REGISTER_P3M, 0x00);
|
||||
register_write(cpustate, Z8_REGISTER_P01M, 0x4d);
|
||||
register_write(cpustate, Z8_REGISTER_IRQ, 0x00);
|
||||
register_write(cpustate, Z8_REGISTER_RP, 0x00);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
ADDRESS MAPS
|
||||
***************************************************************************/
|
||||
|
||||
static ADDRESS_MAP_START( program_2kb, ADDRESS_SPACE_PROGRAM, 8 )
|
||||
AM_RANGE(0x0000, 0x07ff) AM_ROM
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( program_4kb, ADDRESS_SPACE_PROGRAM, 8 )
|
||||
AM_RANGE(0x0000, 0x0fff) AM_ROM
|
||||
ADDRESS_MAP_END
|
||||
|
||||
/**************************************************************************
|
||||
* STATE IMPORT/EXPORT
|
||||
**************************************************************************/
|
||||
|
||||
static CPU_IMPORT_STATE( z8 )
|
||||
{
|
||||
z8_state *cpustate = get_safe_token(device);
|
||||
|
||||
switch (entry->index)
|
||||
{
|
||||
case Z8_SP:
|
||||
case Z8_GENSP:
|
||||
cpustate->r[Z8_REGISTER_SPH] = cpustate->fake_sp >> 8;
|
||||
cpustate->r[Z8_REGISTER_SPL] = cpustate->fake_sp & 0xff;
|
||||
break;
|
||||
|
||||
case Z8_R0: case Z8_R1: case Z8_R2: case Z8_R3: case Z8_R4: case Z8_R5: case Z8_R6: case Z8_R7: case Z8_R8: case Z8_R9: case Z8_R10: case Z8_R11: case Z8_R12: case Z8_R13: case Z8_R14: case Z8_R15:
|
||||
cpustate->r[cpustate->r[Z8_REGISTER_RP] + (entry->index - Z8_R0)] = cpustate->fake_r[entry->index - Z8_R0];
|
||||
break;
|
||||
|
||||
default:
|
||||
fatalerror("CPU_IMPORT_STATE(z8) called for unexpected value\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static CPU_EXPORT_STATE( z8 )
|
||||
{
|
||||
z8_state *cpustate = get_safe_token(device);
|
||||
|
||||
switch (entry->index)
|
||||
{
|
||||
case Z8_SP:
|
||||
case Z8_GENSP:
|
||||
cpustate->fake_sp = (cpustate->r[Z8_REGISTER_SPH] << 8) | cpustate->r[Z8_REGISTER_SPL];
|
||||
break;
|
||||
|
||||
case Z8_R0: case Z8_R1: case Z8_R2: case Z8_R3: case Z8_R4: case Z8_R5: case Z8_R6: case Z8_R7: case Z8_R8: case Z8_R9: case Z8_R10: case Z8_R11: case Z8_R12: case Z8_R13: case Z8_R14: case Z8_R15:
|
||||
cpustate->fake_r[entry->index - Z8_R0] = cpustate->r[cpustate->r[Z8_REGISTER_RP] + (entry->index - Z8_R0)];
|
||||
break;
|
||||
|
||||
default:
|
||||
fatalerror("CPU_EXPORT_STATE(z8) called for unexpected value\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
GENERAL CONTEXT ACCESS
|
||||
***************************************************************************/
|
||||
|
||||
static CPU_SET_INFO( z8 )
|
||||
{
|
||||
z8_state *cpustate = get_safe_token(device);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ0: cpustate->irq[0] = info->i; break;
|
||||
case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ1: cpustate->irq[1] = info->i; break;
|
||||
case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ2: cpustate->irq[2] = info->i; break;
|
||||
case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ3: cpustate->irq[3] = info->i; break;
|
||||
}
|
||||
}
|
||||
|
||||
static CPU_GET_INFO( z8 )
|
||||
{
|
||||
z8_state *cpustate = (device != NULL && device->token != NULL) ? get_safe_token(device) : NULL;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
/* --- the following bits of info are returned as 64-bit signed integers --- */
|
||||
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(z8_state); break;
|
||||
case CPUINFO_INT_INPUT_LINES: info->i = 4; break;
|
||||
case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
|
||||
case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
|
||||
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
|
||||
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 2; break;
|
||||
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
|
||||
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 3; break;
|
||||
case CPUINFO_INT_MIN_CYCLES: info->i = 6; break;
|
||||
case CPUINFO_INT_MAX_CYCLES: info->i = 20; break;
|
||||
|
||||
case CPUINFO_INT_DATABUS_WIDTH_PROGRAM: info->i = 8; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH_PROGRAM: info->i = 16; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT_PROGRAM: info->i = 0; break;
|
||||
case CPUINFO_INT_DATABUS_WIDTH_DATA: info->i = 8; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH_DATA: info->i = 16; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT_DATA: info->i = 0; break;
|
||||
case CPUINFO_INT_DATABUS_WIDTH_IO: info->i = 8; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH_IO: info->i = 2; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT_IO: info->i = 0; break;
|
||||
|
||||
/* --- the following bits of info are returned as pointers to functions --- */
|
||||
case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(z8); break;
|
||||
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(z8); break;
|
||||
case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(z8); break;
|
||||
case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(z8); break;
|
||||
case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(z8); break;
|
||||
case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(z8); break;
|
||||
case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(z8); break;
|
||||
|
||||
/* --- the following bits of info are returned as pointers --- */
|
||||
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
|
||||
case CPUINFO_PTR_STATE_TABLE: info->state_table = &cpustate->state_table; break;
|
||||
|
||||
/* --- the following bits of info are returned as NULL-terminated strings --- */
|
||||
case DEVINFO_STR_NAME: strcpy(info->s, "Z8"); break;
|
||||
case DEVINFO_STR_FAMILY: strcpy(info->s, "Zilog Z8"); break;
|
||||
case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
|
||||
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
|
||||
case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright MESS Team"); break;
|
||||
|
||||
case CPUINFO_STR_FLAGS: sprintf(info->s,
|
||||
"%c%c%c%c%c%c",
|
||||
cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_C ? 'C' : '.',
|
||||
cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_Z ? 'Z' : '.',
|
||||
cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_S ? 'S' : '.',
|
||||
cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_V ? 'V' : '.',
|
||||
cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_D ? 'D' : '.',
|
||||
cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_H ? 'H' : '.'); break;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
CPU-SPECIFIC CONTEXT ACCESS
|
||||
***************************************************************************/
|
||||
|
||||
CPU_GET_INFO( z8601 )
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
/* --- the following bits of info are returned as pointers --- */
|
||||
case CPUINFO_PTR_INTERNAL_MEMORY_MAP_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_2kb); break;
|
||||
|
||||
/* --- the following bits of info are returned as NULL-terminated strings --- */
|
||||
case DEVINFO_STR_NAME: strcpy(info->s, "Z8601"); break;
|
||||
|
||||
default: CPU_GET_INFO_CALL(z8); break;
|
||||
}
|
||||
}
|
||||
|
||||
CPU_GET_INFO( ub8830d )
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
/* --- the following bits of info are returned as pointers --- */
|
||||
case CPUINFO_PTR_INTERNAL_MEMORY_MAP_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_2kb); break;
|
||||
|
||||
/* --- the following bits of info are returned as NULL-terminated strings --- */
|
||||
case DEVINFO_STR_NAME: strcpy(info->s, "UB8830D"); break;
|
||||
|
||||
default: CPU_GET_INFO_CALL(z8); break;
|
||||
}
|
||||
}
|
||||
|
||||
CPU_GET_INFO( z8611 )
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
/* --- the following bits of info are returned as pointers --- */
|
||||
case CPUINFO_PTR_INTERNAL_MEMORY_MAP_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_4kb); break;
|
||||
|
||||
/* --- the following bits of info are returned as NULL-terminated strings --- */
|
||||
case DEVINFO_STR_NAME: strcpy(info->s, "Z8611"); break;
|
||||
|
||||
default: CPU_GET_INFO_CALL(z8); break;
|
||||
}
|
||||
}
|
41
src/emu/cpu/z8/z8.h
Normal file
41
src/emu/cpu/z8/z8.h
Normal file
@ -0,0 +1,41 @@
|
||||
/**********************************************************************
|
||||
|
||||
Zilog Z8 Single-Chip MCU emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __Z8_H__
|
||||
#define __Z8_H__
|
||||
|
||||
#include "cpuintrf.h"
|
||||
|
||||
enum
|
||||
{
|
||||
Z8_PC, Z8_SP, Z8_RP, Z8_T0, Z8_T1,
|
||||
|
||||
Z8_R0, Z8_R1, Z8_R2, Z8_R3, Z8_R4, Z8_R5, Z8_R6, Z8_R7, Z8_R8, Z8_R9, Z8_R10, Z8_R11, Z8_R12, Z8_R13, Z8_R14, Z8_R15,
|
||||
|
||||
Z8_GENPC = REG_GENPC,
|
||||
Z8_GENSP = REG_GENSP
|
||||
};
|
||||
|
||||
/* Zilog Z8601 */
|
||||
CPU_GET_INFO( z8601 );
|
||||
#define CPU_Z8601 CPU_GET_INFO_NAME( z8601 )
|
||||
|
||||
/* VEB Mikroelektronik Erfurt UB8830D MME */
|
||||
CPU_GET_INFO( ub8830d );
|
||||
#define CPU_UB8830D CPU_GET_INFO_NAME( ub8830d )
|
||||
|
||||
/* Zilog Z8611 */
|
||||
CPU_GET_INFO( z8611 );
|
||||
#define CPU_Z8611 CPU_GET_INFO_NAME( z8611 )
|
||||
|
||||
CPU_DISASSEMBLE( z8 );
|
||||
|
||||
#endif
|
378
src/emu/cpu/z8/z8dasm.c
Normal file
378
src/emu/cpu/z8/z8dasm.c
Normal file
@ -0,0 +1,378 @@
|
||||
#include "cpuintrf.h"
|
||||
#include "debugger.h"
|
||||
#include "z8.h"
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
|
||||
static const char* REGISTER_NAME[256] =
|
||||
{
|
||||
"P0", "P1", "P2", "P3", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"SIO", "TMR", "T1", "PRE1", "T0", "PRE0", "P2M", "P3M", "P01M", "IPR", "IRQ", "IMR", "FLAGS", "RP", "SPH", "SPL"
|
||||
};
|
||||
|
||||
static const char* CONDITION_CODE[16] =
|
||||
{
|
||||
"F", "LT", "LE", "ULE", "OV", "MI", "Z", "C",
|
||||
"", "GE", "GT", "UGT", "NOV", "PL", "NZ", "NC"
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
MACROS
|
||||
***************************************************************************/
|
||||
|
||||
#define r "R%u"
|
||||
#define Ir "@R%u"
|
||||
#define R "%02Xh"
|
||||
#define RR "%02Xh"
|
||||
#define IR "@%02Xh"
|
||||
#define Irr "@RR%u"
|
||||
#define IRR "@%02Xh"
|
||||
#define IM "#%02Xh"
|
||||
#define X "%02Xh(R%u)"
|
||||
#define DA "%04Xh"
|
||||
#define RA "%04Xh"
|
||||
|
||||
#define B0 oprom[0]
|
||||
#define B1 oprom[1]
|
||||
#define B0H (B0 >> 4)
|
||||
#define B0L (B0 & 0x0f)
|
||||
#define OPH (opcode >> 4)
|
||||
|
||||
#define ARG(_formatting, _value) { if (argc) dst += sprintf(dst, ", "); dst += sprintf(dst, _formatting, _value); argc++; }
|
||||
|
||||
#define arg_name(_value) ARG("%s", REGISTER_NAME[_value])
|
||||
#define arg_cc ARG("%s", CONDITION_CODE[OPH])
|
||||
#define arg_r(_value) ARG(r, _value)
|
||||
#define arg_Ir(_value) ARG(Ir, _value)
|
||||
#define arg_Irr(_value) ARG(Irr, _value & 0x0f)
|
||||
#define arg_R(_value) if ((_value & 0xf0) == 0xe0) ARG(r, _value & 0x0f) else if ((_value < 4) || (_value >= 0xf0)) arg_name(_value) else ARG(R, _value)
|
||||
#define arg_RR(_value) if ((_value & 0xf0) == 0xe0) ARG(r, _value & 0x0f) else ARG(R, _value)
|
||||
#define arg_IR(_value) if ((_value & 0xf0) == 0xe0) ARG(Ir, _value & 0x0f) else ARG(IR, _value)
|
||||
#define arg_IRR(_value) if ((_value & 0xf0) == 0xe0) ARG(Irr, _value & 0x0f) else ARG(IRR, _value)
|
||||
#define arg_IM(_value) ARG(IM, _value)
|
||||
#define arg_RA ARG(RA, pc + (INT8)B0 + 2)
|
||||
#define arg_DA ARG(DA, B0 << 8 | B1)
|
||||
#define arg_X(_value1, _value2) { if (argc) dst += sprintf(dst, ", "); dst += sprintf(dst, X, _value1, _value2); argc++; }
|
||||
|
||||
#define illegal dst += sprintf(dst, "Illegal")
|
||||
#define mnemonic(_mnemonic) dst += sprintf(dst, "%-5s", _mnemonic)
|
||||
#define bytes(_count) oprom += (_count - 1)
|
||||
#define step_over flags = DASMFLAG_STEP_OVER
|
||||
#define step_out flags = DASMFLAG_STEP_OUT
|
||||
|
||||
/***************************************************************************
|
||||
DISASSEMBLER
|
||||
***************************************************************************/
|
||||
|
||||
CPU_DISASSEMBLE( z8 )
|
||||
{
|
||||
const UINT8 *startrom = oprom;
|
||||
UINT32 flags = 0;
|
||||
UINT8 opcode = *oprom++;
|
||||
char *dst = buffer;
|
||||
int argc = 0;
|
||||
|
||||
switch (pc)
|
||||
{
|
||||
case 0x0000:
|
||||
case 0x0002:
|
||||
case 0x0004:
|
||||
case 0x0006:
|
||||
case 0x0008:
|
||||
case 0x000a:
|
||||
sprintf(buffer, "IRQ%u Vector %04Xh", pc / 2, opcode << 8 | *oprom++); break;
|
||||
default:
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x00: mnemonic("DEC"); arg_R(B0); bytes(2); break;
|
||||
case 0x01: mnemonic("DEC"); arg_IR(B0); bytes(2); break;
|
||||
case 0x02: mnemonic("ADD"); arg_r(B0H); arg_r(B0L); bytes(2); break;
|
||||
case 0x03: mnemonic("ADD"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
|
||||
case 0x04: mnemonic("ADD"); arg_R(B0); arg_R(B1); bytes(3); break;
|
||||
case 0x05: mnemonic("ADD"); arg_R(B0); arg_IR(B1); bytes(3); break;
|
||||
case 0x06: mnemonic("ADD"); arg_R(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x07: mnemonic("ADD"); arg_IR(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x08: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0x09: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0x0a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0x0b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0x0c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0x0d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0x0e: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0x0f: illegal; break;
|
||||
|
||||
case 0x10: mnemonic("RLC"); arg_R(B0); bytes(2); break;
|
||||
case 0x11: mnemonic("RLC"); arg_IR(B0); bytes(2); break;
|
||||
case 0x12: mnemonic("ADC"); arg_r(B0H); arg_r(B0L); bytes(2); break;
|
||||
case 0x13: mnemonic("ADC"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
|
||||
case 0x14: mnemonic("ADC"); arg_R(B0); arg_R(B1); bytes(3); break;
|
||||
case 0x15: mnemonic("ADC"); arg_R(B0); arg_IR(B1); bytes(3); break;
|
||||
case 0x16: mnemonic("ADC"); arg_R(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x17: mnemonic("ADC"); arg_IR(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x18: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0x19: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0x1a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0x1b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0x1c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0x1d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0x1e: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0x1f: illegal; break;
|
||||
|
||||
case 0x20: mnemonic("INC"); arg_R(B0); bytes(2); break;
|
||||
case 0x21: mnemonic("INC"); arg_IR(B0); bytes(2); break;
|
||||
case 0x22: mnemonic("SUB"); arg_r(B0H); arg_r(B0L); bytes(2); break;
|
||||
case 0x23: mnemonic("SUB"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
|
||||
case 0x24: mnemonic("SUB"); arg_R(B0); arg_R(B1); bytes(3); break;
|
||||
case 0x25: mnemonic("SUB"); arg_R(B0); arg_IR(B1); bytes(3); break;
|
||||
case 0x26: mnemonic("SUB"); arg_R(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x27: mnemonic("SUB"); arg_IR(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x28: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0x29: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0x2a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0x2b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0x2c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0x2d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0x2e: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0x2f: illegal; break;
|
||||
|
||||
case 0x30: mnemonic("JP"); arg_IRR(B0); bytes(2); break;
|
||||
case 0x31: mnemonic("SRP"); arg_IM(*oprom++); break;
|
||||
case 0x32: mnemonic("SBC"); arg_r(B0H); arg_r(B0L); bytes(2); break;
|
||||
case 0x33: mnemonic("SBC"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
|
||||
case 0x34: mnemonic("SBC"); arg_R(B0); arg_R(B1); bytes(3); break;
|
||||
case 0x35: mnemonic("SBC"); arg_R(B0); arg_IR(B1); bytes(3); break;
|
||||
case 0x36: mnemonic("SBC"); arg_R(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x37: mnemonic("SBC"); arg_IR(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x38: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0x39: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0x3a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0x3b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0x3c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0x3d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0x3e: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0x3f: illegal; break;
|
||||
|
||||
case 0x40: mnemonic("DA"); arg_R(B0); bytes(2); break;
|
||||
case 0x41: mnemonic("DA"); arg_IR(B0); bytes(2); break;
|
||||
case 0x42: mnemonic("OR"); arg_r(B0H); arg_r(B0L); bytes(2); break;
|
||||
case 0x43: mnemonic("OR"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
|
||||
case 0x44: mnemonic("OR"); arg_R(B0); arg_R(B1); bytes(3); break;
|
||||
case 0x45: mnemonic("OR"); arg_R(B0); arg_IR(B1); bytes(3); break;
|
||||
case 0x46: mnemonic("OR"); arg_R(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x47: mnemonic("OR"); arg_IR(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x48: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0x49: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0x4a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0x4b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0x4c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0x4d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0x4e: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0x4f: illegal; /* mnemonic("WDH"); */ break;
|
||||
|
||||
case 0x50: mnemonic("POP"); arg_R(B0); bytes(2); break;
|
||||
case 0x51: mnemonic("POP"); arg_IR(B0); bytes(2); break;
|
||||
case 0x52: mnemonic("AND"); arg_r(B0H); arg_r(B0L); bytes(2); break;
|
||||
case 0x53: mnemonic("AND"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
|
||||
case 0x54: mnemonic("AND"); arg_R(B0); arg_R(B1); bytes(3); break;
|
||||
case 0x55: mnemonic("AND"); arg_R(B0); arg_IR(B1); bytes(3); break;
|
||||
case 0x56: mnemonic("AND"); arg_R(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x57: mnemonic("AND"); arg_IR(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x58: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0x59: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0x5a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0x5b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0x5c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0x5d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0x5e: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0x5f: illegal; /* mnemonic("WDT"); */ break;
|
||||
|
||||
case 0x60: mnemonic("COM"); arg_R(B0); bytes(2); break;
|
||||
case 0x61: mnemonic("COM"); arg_IR(B0); bytes(2); break;
|
||||
case 0x62: mnemonic("TCM"); arg_r(B0H); arg_r(B0L); bytes(2); break;
|
||||
case 0x63: mnemonic("TCM"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
|
||||
case 0x64: mnemonic("TCM"); arg_R(B0); arg_R(B1); bytes(3); break;
|
||||
case 0x65: mnemonic("TCM"); arg_R(B0); arg_IR(B1); bytes(3); break;
|
||||
case 0x66: mnemonic("TCM"); arg_R(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x67: mnemonic("TCM"); arg_IR(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x68: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0x69: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0x6a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0x6b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0x6c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0x6d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0x6e: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0x6f: illegal; /* mnemonic("STOP"); */ break;
|
||||
|
||||
case 0x70: mnemonic("PUSH"); arg_R(B0); bytes(2); break;
|
||||
case 0x71: mnemonic("PUSH"); arg_IR(B0); bytes(2); break;
|
||||
case 0x72: mnemonic("TM"); arg_r(B0H); arg_r(B0L); bytes(2); break;
|
||||
case 0x73: mnemonic("TM"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
|
||||
case 0x74: mnemonic("TM"); arg_R(B0); arg_R(B1); bytes(3); break;
|
||||
case 0x75: mnemonic("TM"); arg_R(B0); arg_IR(B1); bytes(3); break;
|
||||
case 0x76: mnemonic("TM"); arg_R(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x77: mnemonic("TM"); arg_IR(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0x78: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0x79: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0x7a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0x7b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0x7c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0x7d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0x7e: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0x7f: illegal; /* mnemonic("HALT"); */ break;
|
||||
|
||||
case 0x80: mnemonic("DECW"); arg_RR(*oprom++); break;
|
||||
case 0x81: mnemonic("DECW"); arg_IR(B0); bytes(2); break;
|
||||
case 0x82: mnemonic("LDE"); arg_r(B0H); arg_Irr(B0L); bytes(2); break;
|
||||
case 0x83: mnemonic("LDEI"); arg_Ir(B0H); arg_Irr(B0L); bytes(2); break;
|
||||
case 0x84: illegal; break;
|
||||
case 0x85: illegal; break;
|
||||
case 0x86: illegal; break;
|
||||
case 0x87: illegal; break;
|
||||
case 0x88: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0x89: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0x8a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0x8b: mnemonic("JR"); arg_RA; bytes(2); break;
|
||||
case 0x8c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0x8d: mnemonic("JP"); arg_DA; bytes(3); break;
|
||||
case 0x8e: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0x8f: mnemonic("DI"); break;
|
||||
|
||||
case 0x90: mnemonic("RL"); arg_R(B0); bytes(2); break;
|
||||
case 0x91: mnemonic("RL"); arg_IR(B0); bytes(2); break;
|
||||
case 0x92: mnemonic("LDE"); arg_r(B0L); arg_Irr(B0H); bytes(2); break;
|
||||
case 0x93: mnemonic("LDEI"); arg_Ir(B0L); arg_Irr(B0H); bytes(2); break;
|
||||
case 0x94: illegal; break;
|
||||
case 0x95: illegal; break;
|
||||
case 0x96: illegal; break;
|
||||
case 0x97: illegal; break;
|
||||
case 0x98: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0x99: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0x9a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0x9b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0x9c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0x9d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0x9e: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0x9f: mnemonic("EI"); break;
|
||||
|
||||
case 0xa0: mnemonic("INCW"); arg_RR(B0); bytes(2); break;
|
||||
case 0xa1: mnemonic("INCW"); arg_IR(B0); bytes(2); break;
|
||||
case 0xa2: mnemonic("CP"); arg_r(B0H); arg_r(B0L); bytes(2); break;
|
||||
case 0xa3: mnemonic("CP"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
|
||||
case 0xa4: mnemonic("CP"); arg_R(B0); arg_R(B1); bytes(3); break;
|
||||
case 0xa5: mnemonic("CP"); arg_R(B0); arg_IR(B1); bytes(3); break;
|
||||
case 0xa6: mnemonic("CP"); arg_R(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0xa7: mnemonic("CP"); arg_IR(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0xa8: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0xa9: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0xaa: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0xab: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0xac: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0xad: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0xae: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0xaf: mnemonic("RET"); step_out; break;
|
||||
|
||||
case 0xb0: mnemonic("CLR"); arg_R(B0); bytes(2); break;
|
||||
case 0xb1: mnemonic("XOR"); arg_IR(B0); bytes(2); break;
|
||||
case 0xb2: mnemonic("XOR"); arg_r(B0H); arg_r(B0L); bytes(2); break;
|
||||
case 0xb3: mnemonic("XOR"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
|
||||
case 0xb4: mnemonic("XOR"); arg_R(B0); arg_R(B1); bytes(3); break;
|
||||
case 0xb5: mnemonic("XOR"); arg_R(B0); arg_IR(B1); bytes(3); break;
|
||||
case 0xb6: mnemonic("XOR"); arg_R(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0xb7: mnemonic("XOR"); arg_IR(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0xb8: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0xb9: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0xba: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0xbb: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0xbc: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0xbd: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0xbe: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0xbf: mnemonic("IRET"); step_out; break;
|
||||
|
||||
case 0xc0: mnemonic("RRC"); arg_R(B0); bytes(2); break;
|
||||
case 0xc1: mnemonic("RRC"); arg_IR(B0); bytes(2); break;
|
||||
case 0xc2: mnemonic("LDC"); arg_r(B0H); arg_Irr(B0L); bytes(2); break;
|
||||
case 0xc3: mnemonic("LDCI"); arg_Ir(B0H); arg_Irr(B0L); bytes(2); break;
|
||||
case 0xc4: illegal; break;
|
||||
case 0xc5: illegal; break;
|
||||
case 0xc6: illegal; break;
|
||||
case 0xc7: mnemonic("LD"); arg_r(B0H); arg_X(B1, B0L); bytes(3); break;
|
||||
case 0xc8: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0xc9: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0xca: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0xcb: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0xcc: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0xcd: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0xce: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0xcf: mnemonic("RCF"); break;
|
||||
|
||||
case 0xd0: mnemonic("SRA"); arg_R(B0); bytes(2); break;
|
||||
case 0xd1: mnemonic("SRA"); arg_IR(B0); bytes(2); break;
|
||||
case 0xd2: mnemonic("LDC"); arg_Irr(B0L); arg_r(B0H); bytes(2); break;
|
||||
case 0xd3: mnemonic("LDCI"); arg_Irr(B0L); arg_Ir(B0H); bytes(2); break;
|
||||
case 0xd4: mnemonic("CALL"); arg_IRR(B0); bytes(2); step_over; break;
|
||||
case 0xd5: illegal; break;
|
||||
case 0xd6: mnemonic("CALL"); arg_DA; bytes(3); step_over; break;
|
||||
case 0xd7: mnemonic("LD"); arg_r(B0L); arg_X(B1, B0H); bytes(3); break;
|
||||
case 0xd8: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0xd9: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0xda: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0xdb: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0xdc: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0xdd: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0xde: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0xdf: mnemonic("SCF"); break;
|
||||
|
||||
case 0xe0: mnemonic("RR"); arg_R(B0); bytes(2); break;
|
||||
case 0xe1: mnemonic("RR"); arg_IR(B0); bytes(2); break;
|
||||
case 0xe2: illegal; break;
|
||||
case 0xe3: mnemonic("LD"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
|
||||
case 0xe4: mnemonic("LD"); arg_R(B0); arg_R(B1); bytes(3); break;
|
||||
case 0xe5: mnemonic("LD"); arg_R(B0); arg_IR(B1); bytes(3); break;
|
||||
case 0xe6: mnemonic("LD"); arg_R(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0xe7: mnemonic("LD"); arg_IR(B0); arg_IM(B1); bytes(3); break;
|
||||
case 0xe8: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0xe9: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0xea: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0xeb: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0xec: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0xed: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0xee: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0xef: mnemonic("CCF"); break;
|
||||
|
||||
case 0xf0: mnemonic("SWAP"); arg_R(B0); bytes(2); break;
|
||||
case 0xf1: mnemonic("SWAP"); arg_IR(B0); bytes(2); break;
|
||||
case 0xf2: illegal; break;
|
||||
case 0xf3: mnemonic("LD"); arg_Ir(B0H); arg_r(B0L); bytes(2); break;
|
||||
case 0xf4: illegal; break;
|
||||
case 0xf5: mnemonic("LD"); arg_IR(B0); arg_R(B1); bytes(3); break;
|
||||
case 0xf6: illegal; break;
|
||||
case 0xf7: illegal; break;
|
||||
case 0xf8: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
|
||||
case 0xf9: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
|
||||
case 0xfa: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
|
||||
case 0xfb: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
|
||||
case 0xfc: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
|
||||
case 0xfd: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
|
||||
case 0xfe: mnemonic("INC"); arg_r(OPH); break;
|
||||
case 0xff: mnemonic("NOP"); break;
|
||||
}
|
||||
}
|
||||
|
||||
return (oprom - startrom) | flags | DASMFLAG_SUPPORTED;
|
||||
}
|
746
src/emu/cpu/z8/z8ops.c
Normal file
746
src/emu/cpu/z8/z8ops.c
Normal file
@ -0,0 +1,746 @@
|
||||
/**********************************************************************
|
||||
|
||||
Zilog Z8 Single-Chip MCU emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
MACROS
|
||||
***************************************************************************/
|
||||
|
||||
#define read(_reg) register_read(cpustate, _reg)
|
||||
#define r(_data) get_working_register(cpustate, _data)
|
||||
#define Ir(_data) get_intermediate_register(cpustate, get_working_register(cpustate, _data))
|
||||
#define R get_register(cpustate, fetch(cpustate))
|
||||
#define IR get_intermediate_register(cpustate, get_register(cpustate, fetch(cpustate)))
|
||||
#define RR get_intermediate_register(cpustate, get_register(cpustate, fetch(cpustate)))
|
||||
#define IM fetch(cpustate)
|
||||
#define flag(_flag) ((cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS##_##_flag) ? 1 : 0)
|
||||
|
||||
#define mode_r1_r2(_func) \
|
||||
UINT8 dst_src = fetch(cpustate);\
|
||||
UINT8 dst = r(dst_src >> 4);\
|
||||
UINT8 src = read(r(dst_src & 0x0f));\
|
||||
_func(cpustate, dst, src);
|
||||
|
||||
#define mode_r1_Ir2(_func) \
|
||||
UINT8 dst_src = fetch(cpustate);\
|
||||
UINT8 dst = r(dst_src >> 4);\
|
||||
UINT8 src = read(Ir(dst_src & 0x0f));\
|
||||
_func(cpustate, dst, src);
|
||||
|
||||
#define mode_R2_R1(_func) \
|
||||
UINT8 src = read(R);\
|
||||
UINT8 dst = R;\
|
||||
_func(cpustate, dst, src);
|
||||
|
||||
#define mode_IR2_R1(_func) \
|
||||
UINT8 src = read(R);\
|
||||
UINT8 dst = IR;\
|
||||
_func(cpustate, dst, src);
|
||||
|
||||
#define mode_R1_IM(_func) \
|
||||
UINT8 dst = R;\
|
||||
UINT8 src = IM;\
|
||||
_func(cpustate, dst, src);
|
||||
|
||||
#define mode_IR1_IM(_func) \
|
||||
UINT8 dst = IR;\
|
||||
UINT8 src = IM;\
|
||||
_func(cpustate, dst, src);
|
||||
|
||||
#define mode_r1(_func) \
|
||||
UINT8 dst = r(opcode >> 4);\
|
||||
_func(cpustate, dst);
|
||||
|
||||
#define mode_R1(_func) \
|
||||
UINT8 dst = R;\
|
||||
_func(cpustate, dst);
|
||||
|
||||
#define mode_RR1(_func) \
|
||||
UINT8 dst = R;\
|
||||
_func(cpustate, dst);
|
||||
|
||||
#define mode_IR1(_func) \
|
||||
UINT8 dst = IR;\
|
||||
_func(cpustate, dst);
|
||||
|
||||
#define mode_r1_IM(_func) \
|
||||
UINT8 dst = r(opcode >> 4);\
|
||||
UINT8 src = IM;\
|
||||
_func(cpustate, dst, src);
|
||||
|
||||
#define mode_r1_R2(_func) \
|
||||
UINT8 dst = r(opcode >> 4);\
|
||||
UINT8 src = read(R);\
|
||||
_func(cpustate, dst, src);
|
||||
|
||||
#define mode_r2_R1(_func) \
|
||||
UINT8 src = read(r(opcode >> 4));\
|
||||
UINT8 dst = R;\
|
||||
_func(cpustate, dst, src);
|
||||
|
||||
#define mode_Ir1_r2(_func) \
|
||||
UINT8 dst_src = fetch(cpustate);\
|
||||
UINT8 dst = Ir(dst_src >> 4);\
|
||||
UINT8 src = read(r(dst_src & 0x0f));\
|
||||
_func(cpustate, dst, src);
|
||||
|
||||
#define mode_R2_IR1(_func) \
|
||||
UINT8 src = read(R);\
|
||||
UINT8 dst = IR;\
|
||||
_func(cpustate, dst, src);
|
||||
|
||||
#define mode_r1_x_R2(_func) \
|
||||
UINT8 dst_src = fetch(cpustate);\
|
||||
UINT8 dst = r(dst_src >> 4);\
|
||||
UINT8 src = read(read(r(dst_src & 0x0f)) + R);\
|
||||
_func(cpustate, dst, src);
|
||||
|
||||
#define mode_r2_x_R1(_func) \
|
||||
UINT8 dst_src = fetch(cpustate);\
|
||||
UINT8 dst = R + read(r(dst_src & 0x0f));\
|
||||
UINT8 src = read(r(dst_src >> 4));\
|
||||
_func(cpustate, dst, src);
|
||||
|
||||
/***************************************************************************
|
||||
LOAD INSTRUCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
static void clear(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
/* dst <- 0 */
|
||||
register_write(cpustate, dst, 0);
|
||||
}
|
||||
|
||||
INSTRUCTION( clr_R1 ) { mode_R1(clear) }
|
||||
INSTRUCTION( clr_IR1 ) { mode_IR1(clear) }
|
||||
|
||||
static void load(z8_state *cpustate, UINT8 dst, UINT8 src)
|
||||
{
|
||||
/* dst <- src */
|
||||
register_write(cpustate, dst, src);
|
||||
}
|
||||
|
||||
INSTRUCTION( ld_r1_IM ) { mode_r1_IM(load) }
|
||||
INSTRUCTION( ld_r1_R2 ) { mode_r1_R2(load) }
|
||||
INSTRUCTION( ld_r2_R1 ) { mode_r2_R1(load) }
|
||||
INSTRUCTION( ld_Ir1_r2 ) { mode_Ir1_r2(load) }
|
||||
INSTRUCTION( ld_R2_IR1 ) { mode_R2_IR1(load) }
|
||||
INSTRUCTION( ld_r1_x_R2 ) { mode_r1_x_R2(load) }
|
||||
INSTRUCTION( ld_r2_x_R1 ) { mode_r2_x_R1(load) }
|
||||
|
||||
INSTRUCTION( ld_r1_r2 ) { mode_r1_r2(load) }
|
||||
INSTRUCTION( ld_r1_Ir2 ) { mode_r1_Ir2(load) }
|
||||
INSTRUCTION( ld_R2_R1 ) { mode_R2_R1(load) }
|
||||
INSTRUCTION( ld_IR2_R1 ) { mode_IR2_R1(load) }
|
||||
INSTRUCTION( ld_R1_IM ) { mode_R1_IM(load) }
|
||||
INSTRUCTION( ld_IR1_IM ) { mode_IR1_IM(load) }
|
||||
|
||||
static void load_from_memory(z8_state *cpustate, const address_space *space)
|
||||
{
|
||||
UINT8 operands = fetch(cpustate);
|
||||
UINT8 dst = get_working_register(cpustate, operands >> 4);
|
||||
UINT8 src = get_working_register(cpustate, operands & 0x0f);
|
||||
|
||||
UINT16 address = register_pair_read(cpustate, src);
|
||||
UINT8 data = memory_decrypted_read_byte(cpustate->program, address);
|
||||
|
||||
register_write(cpustate, dst, data);
|
||||
}
|
||||
|
||||
static void load_to_memory(z8_state *cpustate, const address_space *space)
|
||||
{
|
||||
UINT8 operands = fetch(cpustate);
|
||||
UINT8 src = get_working_register(cpustate, operands >> 4);
|
||||
UINT8 dst = get_working_register(cpustate, operands & 0x0f);
|
||||
|
||||
UINT16 address = register_pair_read(cpustate, dst);
|
||||
UINT8 data = register_read(cpustate, src);
|
||||
|
||||
memory_write_byte(cpustate->program, address, data);
|
||||
}
|
||||
|
||||
static void load_from_memory_autoinc(z8_state *cpustate, const address_space *space)
|
||||
{
|
||||
UINT8 operands = fetch(cpustate);
|
||||
UINT8 dst = get_working_register(cpustate, operands >> 4);
|
||||
UINT8 real_dst = get_intermediate_register(cpustate, dst);
|
||||
UINT8 src = get_working_register(cpustate, operands & 0x0f);
|
||||
|
||||
UINT16 address = register_pair_read(cpustate, src);
|
||||
UINT8 data = memory_decrypted_read_byte(cpustate->program, address);
|
||||
|
||||
register_write(cpustate, real_dst, data);
|
||||
|
||||
register_write(cpustate, dst, real_dst + 1);
|
||||
register_pair_write(cpustate, src, address + 1);
|
||||
}
|
||||
|
||||
static void load_to_memory_autoinc(z8_state *cpustate, const address_space *space)
|
||||
{
|
||||
UINT8 operands = fetch(cpustate);
|
||||
UINT8 src = get_working_register(cpustate, operands >> 4);
|
||||
UINT8 dst = get_working_register(cpustate, operands & 0x0f);
|
||||
UINT8 real_src = get_intermediate_register(cpustate, src);
|
||||
|
||||
UINT16 address = register_pair_read(cpustate, dst);
|
||||
UINT8 data = register_read(cpustate, real_src);
|
||||
|
||||
memory_write_byte(cpustate->program, address, data);
|
||||
|
||||
register_pair_write(cpustate, dst, address + 1);
|
||||
register_write(cpustate, src, real_src + 1);
|
||||
}
|
||||
|
||||
INSTRUCTION( ldc_r1_Irr2 ) { load_from_memory(cpustate, cpustate->program); }
|
||||
INSTRUCTION( ldc_r2_Irr1 ) { load_to_memory(cpustate, cpustate->program); }
|
||||
INSTRUCTION( ldci_Ir1_Irr2 ) { load_from_memory_autoinc(cpustate, cpustate->program); }
|
||||
INSTRUCTION( ldci_Ir2_Irr1 ) { load_to_memory_autoinc(cpustate, cpustate->program); }
|
||||
INSTRUCTION( lde_r1_Irr2 ) { load_from_memory(cpustate, cpustate->data); }
|
||||
INSTRUCTION( lde_r2_Irr1 ) { load_to_memory(cpustate, cpustate->data); }
|
||||
INSTRUCTION( ldei_Ir1_Irr2 ) { load_from_memory_autoinc(cpustate, cpustate->data); }
|
||||
INSTRUCTION( ldei_Ir2_Irr1 ) { load_to_memory_autoinc(cpustate, cpustate->data); }
|
||||
|
||||
static void pop(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
/* dst <- @SP
|
||||
SP <- SP + 1 */
|
||||
register_write(cpustate, dst, stack_pop_byte(cpustate));
|
||||
}
|
||||
|
||||
INSTRUCTION( pop_R1 ) { mode_R1(pop) }
|
||||
INSTRUCTION( pop_IR1 ) { mode_IR1(pop) }
|
||||
|
||||
static void push(z8_state *cpustate, UINT8 src)
|
||||
{
|
||||
/* SP <- SP - 1
|
||||
@SP <- src */
|
||||
stack_push_byte(cpustate, read(src));
|
||||
}
|
||||
|
||||
INSTRUCTION( push_R2 ) { mode_R1(push) }
|
||||
INSTRUCTION( push_IR2 ) { mode_IR1(push) }
|
||||
|
||||
/***************************************************************************
|
||||
ARITHMETIC INSTRUCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
static void add_carry(z8_state *cpustate, UINT8 dst, INT8 src)
|
||||
{
|
||||
/* dst <- dst + src + C */
|
||||
UINT8 data = register_read(cpustate, dst);
|
||||
UINT16 new_data = data + src + flag(C);
|
||||
|
||||
set_flag_c(new_data & 0x100);
|
||||
set_flag_z(new_data == 0);
|
||||
set_flag_s(new_data & 0x80);
|
||||
set_flag_v(((data & 0x80) == (src & 0x80)) && ((new_data & 0x80) != (src & 0x80)));
|
||||
set_flag_d(0);
|
||||
set_flag_h(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10));
|
||||
|
||||
register_write(cpustate, dst, new_data & 0xff);
|
||||
}
|
||||
|
||||
INSTRUCTION( adc_r1_r2 ) { mode_r1_r2(add_carry) }
|
||||
INSTRUCTION( adc_r1_Ir2 ) { mode_r1_Ir2(add_carry) }
|
||||
INSTRUCTION( adc_R2_R1 ) { mode_R2_R1(add_carry) }
|
||||
INSTRUCTION( adc_IR2_R1 ) { mode_IR2_R1(add_carry) }
|
||||
INSTRUCTION( adc_R1_IM ) { mode_R1_IM(add_carry) }
|
||||
INSTRUCTION( adc_IR1_IM ) { mode_IR1_IM(add_carry) }
|
||||
|
||||
static void add(z8_state *cpustate, UINT8 dst, INT8 src)
|
||||
{
|
||||
/* dst <- dst + src */
|
||||
UINT8 data = register_read(cpustate, dst);
|
||||
UINT16 new_data = data + src;
|
||||
|
||||
set_flag_c(new_data & 0x100);
|
||||
set_flag_z(new_data == 0);
|
||||
set_flag_s(new_data & 0x80);
|
||||
set_flag_v(((data & 0x80) == (src & 0x80)) && ((new_data & 0x80) != (src & 0x80)));
|
||||
set_flag_d(0);
|
||||
set_flag_h(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10));
|
||||
|
||||
register_write(cpustate, dst, new_data & 0xff);
|
||||
}
|
||||
|
||||
INSTRUCTION( add_r1_r2 ) { mode_r1_r2(add) }
|
||||
INSTRUCTION( add_r1_Ir2 ) { mode_r1_Ir2(add) }
|
||||
INSTRUCTION( add_R2_R1 ) { mode_R2_R1(add) }
|
||||
INSTRUCTION( add_IR2_R1 ) { mode_IR2_R1(add) }
|
||||
INSTRUCTION( add_R1_IM ) { mode_R1_IM(add) }
|
||||
INSTRUCTION( add_IR1_IM ) { mode_IR1_IM(add) }
|
||||
|
||||
static void compare(z8_state *cpustate, UINT8 dst, UINT8 src)
|
||||
{
|
||||
/* dst - src */
|
||||
UINT8 data = register_read(cpustate, dst);
|
||||
UINT16 new_data = data - src;
|
||||
|
||||
set_flag_c(!(new_data & 0x100));
|
||||
set_flag_z(new_data == 0);
|
||||
set_flag_s(new_data & 0x80);
|
||||
set_flag_v(((data & 0x80) != (src & 0x80)) && ((new_data & 0x80) == (src & 0x80)));
|
||||
}
|
||||
|
||||
INSTRUCTION( cp_r1_r2 ) { mode_r1_r2(compare) }
|
||||
INSTRUCTION( cp_r1_Ir2 ) { mode_r1_Ir2(compare) }
|
||||
INSTRUCTION( cp_R2_R1 ) { mode_R2_R1(compare) }
|
||||
INSTRUCTION( cp_IR2_R1 ) { mode_IR2_R1(compare) }
|
||||
INSTRUCTION( cp_R1_IM ) { mode_R1_IM(compare) }
|
||||
INSTRUCTION( cp_IR1_IM ) { mode_IR1_IM(compare) }
|
||||
|
||||
static void decimal_adjust(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
}
|
||||
|
||||
INSTRUCTION( da_R1 ) { mode_R1(decimal_adjust) }
|
||||
INSTRUCTION( da_IR1 ) { mode_IR1(decimal_adjust) }
|
||||
|
||||
static void decrement(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
/* dst <- dst - 1 */
|
||||
UINT8 data = register_read(cpustate, dst) - 1;
|
||||
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(data & 0x80);
|
||||
set_flag_v(data == 0x7f);
|
||||
|
||||
register_write(cpustate, dst, data);
|
||||
}
|
||||
|
||||
INSTRUCTION( dec_R1 ) { mode_R1(decrement) }
|
||||
INSTRUCTION( dec_IR1 ) { mode_IR1(decrement) }
|
||||
|
||||
static void decrement_word(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
/* dst <- dst - 1 */
|
||||
UINT16 data = register_pair_read(cpustate, dst) - 1;
|
||||
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(data & 0x8000);
|
||||
set_flag_v(data == 0x7fff);
|
||||
|
||||
register_pair_write(cpustate, dst, data);
|
||||
}
|
||||
|
||||
INSTRUCTION( decw_RR1 ) { mode_RR1(decrement_word) }
|
||||
INSTRUCTION( decw_IR1 ) { mode_IR1(decrement_word) }
|
||||
|
||||
static void increment(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
/* dst <- dst + 1 */
|
||||
UINT8 data = register_read(cpustate, dst) + 1;
|
||||
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(data & 0x80);
|
||||
set_flag_v(data == 0x80);
|
||||
|
||||
register_write(cpustate, dst, data);
|
||||
}
|
||||
|
||||
INSTRUCTION( inc_r1 ) { mode_r1(increment) }
|
||||
INSTRUCTION( inc_R1 ) { mode_R1(increment) }
|
||||
INSTRUCTION( inc_IR1 ) { mode_IR1(increment) }
|
||||
|
||||
static void increment_word(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
/* dst <- dst + 1 */
|
||||
UINT16 data = register_pair_read(cpustate, dst) + 1;
|
||||
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(data & 0x8000);
|
||||
set_flag_v(data == 0x8000);
|
||||
|
||||
register_pair_write(cpustate, dst, data);
|
||||
}
|
||||
|
||||
INSTRUCTION( incw_RR1 ) { mode_RR1(increment_word) }
|
||||
INSTRUCTION( incw_IR1 ) { mode_IR1(increment_word) }
|
||||
|
||||
static void subtract_carry(z8_state *cpustate, UINT8 dst, UINT8 src)
|
||||
{
|
||||
/* dst <- dst - src - C */
|
||||
UINT8 data = register_read(cpustate, dst);
|
||||
UINT16 new_data = data - src;
|
||||
|
||||
set_flag_c(!(new_data & 0x100));
|
||||
set_flag_z(new_data == 0);
|
||||
set_flag_s(new_data & 0x80);
|
||||
set_flag_v(((data & 0x80) != (src & 0x80)) && ((new_data & 0x80) == (src & 0x80)));
|
||||
set_flag_d(1);
|
||||
set_flag_h(!(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10)));
|
||||
|
||||
register_write(cpustate, dst, new_data & 0xff);
|
||||
}
|
||||
|
||||
INSTRUCTION( sbc_r1_r2 ) { mode_r1_r2(subtract_carry) }
|
||||
INSTRUCTION( sbc_r1_Ir2 ) { mode_r1_Ir2(subtract_carry) }
|
||||
INSTRUCTION( sbc_R2_R1 ) { mode_R2_R1(subtract_carry) }
|
||||
INSTRUCTION( sbc_IR2_R1 ) { mode_IR2_R1(subtract_carry) }
|
||||
INSTRUCTION( sbc_R1_IM ) { mode_R1_IM(subtract_carry) }
|
||||
INSTRUCTION( sbc_IR1_IM ) { mode_IR1_IM(subtract_carry) }
|
||||
|
||||
static void subtract(z8_state *cpustate, UINT8 dst, UINT8 src)
|
||||
{
|
||||
/* dst <- dst - src */
|
||||
UINT8 data = register_read(cpustate, dst);
|
||||
UINT16 new_data = data - src;
|
||||
|
||||
set_flag_c(!(new_data & 0x100));
|
||||
set_flag_z(new_data == 0);
|
||||
set_flag_s(new_data & 0x80);
|
||||
set_flag_v(((data & 0x80) != (src & 0x80)) && ((new_data & 0x80) == (src & 0x80)));
|
||||
set_flag_d(1);
|
||||
set_flag_h(!(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10)));
|
||||
|
||||
register_write(cpustate, dst, new_data & 0xff);
|
||||
}
|
||||
|
||||
INSTRUCTION( sub_r1_r2 ) { mode_r1_r2(subtract) }
|
||||
INSTRUCTION( sub_r1_Ir2 ) { mode_r1_Ir2(subtract) }
|
||||
INSTRUCTION( sub_R2_R1 ) { mode_R2_R1(subtract) }
|
||||
INSTRUCTION( sub_IR2_R1 ) { mode_IR2_R1(subtract) }
|
||||
INSTRUCTION( sub_R1_IM ) { mode_R1_IM(subtract) }
|
||||
INSTRUCTION( sub_IR1_IM ) { mode_IR1_IM(subtract) }
|
||||
|
||||
/***************************************************************************
|
||||
LOGICAL INSTRUCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
static void and(z8_state *cpustate, UINT8 dst, UINT8 src)
|
||||
{
|
||||
/* dst <- dst AND src */
|
||||
UINT8 data = register_read(cpustate, dst) & src;
|
||||
register_write(cpustate, dst, data);
|
||||
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(data & 0x80);
|
||||
set_flag_v(0);
|
||||
}
|
||||
|
||||
INSTRUCTION( and_r1_r2 ) { mode_r1_r2(and) }
|
||||
INSTRUCTION( and_r1_Ir2 ) { mode_r1_Ir2(and) }
|
||||
INSTRUCTION( and_R2_R1 ) { mode_R2_R1(and) }
|
||||
INSTRUCTION( and_IR2_R1 ) { mode_IR2_R1(and) }
|
||||
INSTRUCTION( and_R1_IM ) { mode_R1_IM(and) }
|
||||
INSTRUCTION( and_IR1_IM ) { mode_IR1_IM(and) }
|
||||
|
||||
static void complement(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
/* dst <- NOT dst */
|
||||
UINT8 data = register_read(cpustate, dst) ^ 0xff;
|
||||
register_write(cpustate, dst, data);
|
||||
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(data & 0x80);
|
||||
set_flag_v(0);
|
||||
}
|
||||
|
||||
INSTRUCTION( com_R1 ) { mode_R1(complement) }
|
||||
INSTRUCTION( com_IR1 ) { mode_IR1(complement) }
|
||||
|
||||
static void or(z8_state *cpustate, UINT8 dst, UINT8 src)
|
||||
{
|
||||
/* dst <- dst OR src */
|
||||
UINT8 data = register_read(cpustate, dst) | src;
|
||||
register_write(cpustate, dst, data);
|
||||
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(data & 0x80);
|
||||
set_flag_v(0);
|
||||
}
|
||||
|
||||
INSTRUCTION( or_r1_r2 ) { mode_r1_r2(or) }
|
||||
INSTRUCTION( or_r1_Ir2 ) { mode_r1_Ir2(or) }
|
||||
INSTRUCTION( or_R2_R1 ) { mode_R2_R1(or) }
|
||||
INSTRUCTION( or_IR2_R1 ) { mode_IR2_R1(or) }
|
||||
INSTRUCTION( or_R1_IM ) { mode_R1_IM(or) }
|
||||
INSTRUCTION( or_IR1_IM ) { mode_IR1_IM(or) }
|
||||
|
||||
static void xor(z8_state *cpustate, UINT8 dst, UINT8 src)
|
||||
{
|
||||
/* dst <- dst XOR src */
|
||||
UINT8 data = register_read(cpustate, dst) ^ src;
|
||||
register_write(cpustate, dst, data);
|
||||
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(data & 0x80);
|
||||
set_flag_v(0);
|
||||
}
|
||||
|
||||
INSTRUCTION( xor_r1_r2 ) { mode_r1_r2(xor) }
|
||||
INSTRUCTION( xor_r1_Ir2 ) { mode_r1_Ir2(xor) }
|
||||
INSTRUCTION( xor_R2_R1 ) { mode_R2_R1(xor) }
|
||||
INSTRUCTION( xor_IR2_R1 ) { mode_IR2_R1(xor) }
|
||||
INSTRUCTION( xor_R1_IM ) { mode_R1_IM(xor) }
|
||||
INSTRUCTION( xor_IR1_IM ) { mode_IR1_IM(xor) }
|
||||
|
||||
/***************************************************************************
|
||||
PROGRAM CONTROL INSTRUCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
static void call(z8_state *cpustate, UINT16 dst)
|
||||
{
|
||||
stack_push_word(cpustate, cpustate->pc);
|
||||
cpustate->pc = dst;
|
||||
}
|
||||
|
||||
INSTRUCTION( call_IRR1 ) { UINT16 dst = register_pair_read(cpustate, get_intermediate_register(cpustate, get_register(cpustate, fetch(cpustate)))); call(cpustate, dst); }
|
||||
INSTRUCTION( call_DA ) { UINT16 dst = (fetch(cpustate) << 8) | fetch(cpustate); call(cpustate, dst); }
|
||||
|
||||
INSTRUCTION( djnz_r1_RA )
|
||||
{
|
||||
INT8 ra = (INT8)fetch(cpustate);
|
||||
|
||||
/* r <- r - 1 */
|
||||
int r = get_working_register(cpustate, opcode >> 4);
|
||||
UINT8 data = register_read(cpustate, r) - 1;
|
||||
register_write(cpustate, r, data);
|
||||
|
||||
/* if r<>0, PC <- PC + dst */
|
||||
if (data != 0)
|
||||
{
|
||||
cpustate->pc += ra;
|
||||
*cycles += 2;
|
||||
}
|
||||
}
|
||||
|
||||
INSTRUCTION( iret )
|
||||
{
|
||||
/* FLAGS <- @SP
|
||||
SP <- SP + 1 */
|
||||
register_write(cpustate, Z8_REGISTER_FLAGS, stack_pop_byte(cpustate));
|
||||
|
||||
/* PC <- @SP
|
||||
SP <- SP + 2 */
|
||||
cpustate->pc = stack_pop_word(cpustate);
|
||||
|
||||
/* IMR (7) <- 1 */
|
||||
cpustate->r[Z8_REGISTER_IMR] |= Z8_IMR_ENABLE;
|
||||
}
|
||||
|
||||
INSTRUCTION( ret )
|
||||
{
|
||||
/* PC <- @SP
|
||||
SP <- SP + 2 */
|
||||
cpustate->pc = stack_pop_word(cpustate);
|
||||
}
|
||||
|
||||
static void jump(z8_state *cpustate, UINT16 dst)
|
||||
{
|
||||
/* PC <- dst */
|
||||
cpustate->pc = dst;
|
||||
}
|
||||
|
||||
INSTRUCTION( jp_IRR1 ) { jump(cpustate, register_pair_read(cpustate, IR)); }
|
||||
|
||||
static int check_condition_code(z8_state *cpustate, int cc)
|
||||
{
|
||||
int truth = 0;
|
||||
|
||||
switch (cc)
|
||||
{
|
||||
case CC_F: truth = 0; break;
|
||||
case CC_LT: truth = flag(S) ^ flag(V); break;
|
||||
case CC_LE: truth = (flag(Z) | (flag(S) ^ flag(V))); break;
|
||||
case CC_ULE: truth = flag(C) | flag(Z); break;
|
||||
case CC_OV: truth = flag(V); break;
|
||||
case CC_MI: truth = flag(S); break;
|
||||
case CC_Z: truth = flag(Z); break;
|
||||
case CC_C: truth = flag(C); break;
|
||||
case CC_T: truth = 1; break;
|
||||
case CC_GE: truth = !(flag(S) ^ flag(V)); break;
|
||||
case CC_GT: truth = !(flag(Z) | (flag(S) ^ flag(V))); break;
|
||||
case CC_UGT: truth = (!flag(C) & !flag(Z)); break;
|
||||
case CC_NOV: truth = !flag(V); break;
|
||||
case CC_PL: truth = !flag(S); break;
|
||||
case CC_NZ: truth = !flag(Z); break;
|
||||
case CC_NC: truth = !flag(C); break;
|
||||
}
|
||||
|
||||
return truth;
|
||||
}
|
||||
|
||||
INSTRUCTION( jp_cc_DA )
|
||||
{
|
||||
UINT16 dst = (fetch(cpustate) << 8) | fetch(cpustate);
|
||||
|
||||
/* if cc is true, then PC <- dst */
|
||||
if (check_condition_code(cpustate, opcode >> 4))
|
||||
{
|
||||
jump(cpustate, dst);
|
||||
*cycles += 2;
|
||||
}
|
||||
}
|
||||
|
||||
INSTRUCTION( jr_cc_RA )
|
||||
{
|
||||
INT8 ra = (INT8)fetch(cpustate);
|
||||
UINT16 dst = cpustate->pc + ra;
|
||||
|
||||
/* if cc is true, then PC <- dst */
|
||||
if (check_condition_code(cpustate, opcode >> 4))
|
||||
{
|
||||
jump(cpustate, dst);
|
||||
*cycles += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
BIT MANIPULATION INSTRUCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
static void test_complement_under_mask(z8_state *cpustate, UINT8 dst, UINT8 src)
|
||||
{
|
||||
/* NOT(dst) AND src */
|
||||
UINT8 data = (register_read(cpustate, dst) ^ 0xff) & src;
|
||||
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(data & 0x80);
|
||||
set_flag_v(0);
|
||||
}
|
||||
|
||||
INSTRUCTION( tcm_r1_r2 ) { mode_r1_r2(test_complement_under_mask) }
|
||||
INSTRUCTION( tcm_r1_Ir2 ) { mode_r1_Ir2(test_complement_under_mask) }
|
||||
INSTRUCTION( tcm_R2_R1 ) { mode_R2_R1(test_complement_under_mask) }
|
||||
INSTRUCTION( tcm_IR2_R1 ) { mode_IR2_R1(test_complement_under_mask) }
|
||||
INSTRUCTION( tcm_R1_IM ) { mode_R1_IM(test_complement_under_mask) }
|
||||
INSTRUCTION( tcm_IR1_IM ) { mode_IR1_IM(test_complement_under_mask) }
|
||||
|
||||
static void test_under_mask(z8_state *cpustate, UINT8 dst, UINT8 src)
|
||||
{
|
||||
/* dst AND src */
|
||||
UINT8 data = register_read(cpustate, dst) & src;
|
||||
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(data & 0x80);
|
||||
set_flag_v(0);
|
||||
}
|
||||
|
||||
INSTRUCTION( tm_r1_r2 ) { mode_r1_r2(test_under_mask) }
|
||||
INSTRUCTION( tm_r1_Ir2 ) { mode_r1_Ir2(test_under_mask) }
|
||||
INSTRUCTION( tm_R2_R1 ) { mode_R2_R1(test_under_mask) }
|
||||
INSTRUCTION( tm_IR2_R1 ) { mode_IR2_R1(test_under_mask) }
|
||||
INSTRUCTION( tm_R1_IM ) { mode_R1_IM(test_under_mask) }
|
||||
INSTRUCTION( tm_IR1_IM ) { mode_IR1_IM(test_under_mask) }
|
||||
|
||||
/***************************************************************************
|
||||
ROTATE AND SHIFT INSTRUCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
static void rotate_left(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
/* << */
|
||||
UINT8 data = register_read(cpustate, dst);
|
||||
UINT8 new_data = (data << 1) | BIT(data, 7);
|
||||
|
||||
set_flag_c(data & 0x80);
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(new_data & 0x80);
|
||||
set_flag_v((data & 0x80) != (new_data & 0x80));
|
||||
|
||||
register_write(cpustate, dst, new_data);
|
||||
}
|
||||
|
||||
INSTRUCTION( rl_R1 ) { mode_R1(rotate_left) }
|
||||
INSTRUCTION( rl_IR1 ) { mode_IR1(rotate_left) }
|
||||
|
||||
static void rotate_left_carry(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
/* << C */
|
||||
UINT8 data = register_read(cpustate, dst);
|
||||
UINT8 new_data = (data << 1) | flag(C);
|
||||
|
||||
set_flag_c(data & 0x80);
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(new_data & 0x80);
|
||||
set_flag_v((data & 0x80) != (new_data & 0x80));
|
||||
|
||||
register_write(cpustate, dst, new_data);
|
||||
}
|
||||
|
||||
INSTRUCTION( rlc_R1 ) { mode_R1(rotate_left_carry) }
|
||||
INSTRUCTION( rlc_IR1 ) { mode_IR1(rotate_left_carry) }
|
||||
|
||||
static void rotate_right(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
/* >> */
|
||||
UINT8 data = register_read(cpustate, dst);
|
||||
UINT8 new_data = ((data & 0x01) << 7) | (data >> 1);
|
||||
|
||||
set_flag_c(data & 0x01);
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(new_data & 0x80);
|
||||
set_flag_v((data & 0x80) != (new_data & 0x80));
|
||||
|
||||
register_write(cpustate, dst, new_data);
|
||||
}
|
||||
|
||||
INSTRUCTION( rr_R1 ) { mode_R1(rotate_right) }
|
||||
INSTRUCTION( rr_IR1 ) { mode_IR1(rotate_right) }
|
||||
|
||||
static void rotate_right_carry(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
/* >> C */
|
||||
UINT8 data = register_read(cpustate, dst);
|
||||
UINT8 new_data = (flag(C) << 7) | (data >> 1);
|
||||
|
||||
set_flag_c(data & 0x01);
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(new_data & 0x80);
|
||||
set_flag_v((data & 0x80) != (new_data & 0x80));
|
||||
|
||||
register_write(cpustate, dst, new_data);
|
||||
}
|
||||
|
||||
INSTRUCTION( rrc_R1 ) { mode_R1(rotate_right_carry) }
|
||||
INSTRUCTION( rrc_IR1 ) { mode_IR1(rotate_right_carry) }
|
||||
|
||||
static void shift_right_arithmetic(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
/* */
|
||||
UINT8 data = register_read(cpustate, dst);
|
||||
UINT8 new_data = (data & 0x80) | ((data >> 1) & 0x7f);
|
||||
|
||||
set_flag_c(data & 0x01);
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(new_data & 0x80);
|
||||
set_flag_v(0);
|
||||
|
||||
register_write(cpustate, dst, new_data);
|
||||
}
|
||||
|
||||
INSTRUCTION( sra_R1 ) { mode_R1(shift_right_arithmetic) }
|
||||
INSTRUCTION( sra_IR1 ) { mode_IR1(shift_right_arithmetic) }
|
||||
|
||||
static void swap(z8_state *cpustate, UINT8 dst)
|
||||
{
|
||||
/* dst(7-4) <-> dst(3-0) */
|
||||
UINT8 data = register_read(cpustate, dst);
|
||||
data = (data << 4) | (data >> 4);
|
||||
register_write(cpustate, dst, data);
|
||||
|
||||
set_flag_z(data == 0);
|
||||
set_flag_s(data & 0x80);
|
||||
// set_flag_v(0); undefined
|
||||
}
|
||||
|
||||
INSTRUCTION( swap_R1 ) { mode_R1(swap) }
|
||||
INSTRUCTION( swap_IR1 ) { mode_IR1(swap) }
|
||||
|
||||
/***************************************************************************
|
||||
CPU CONTROL INSTRUCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
INSTRUCTION( ccf ) { cpustate->r[Z8_REGISTER_FLAGS] ^= Z8_FLAGS_C; }
|
||||
INSTRUCTION( di ) { cpustate->r[Z8_REGISTER_IMR] &= ~Z8_IMR_ENABLE; }
|
||||
INSTRUCTION( ei ) { cpustate->r[Z8_REGISTER_IMR] |= Z8_IMR_ENABLE; }
|
||||
INSTRUCTION( nop ) { /* no operation */ }
|
||||
INSTRUCTION( rcf ) { set_flag_c(0); }
|
||||
INSTRUCTION( scf ) { set_flag_c(1); }
|
||||
INSTRUCTION( srp_IM ) { cpustate->r[Z8_REGISTER_RP] = fetch(cpustate); }
|
@ -115,6 +115,7 @@ CPUS += AVR8
|
||||
CPUS += TMS0980
|
||||
CPUS += I4004
|
||||
CPUS += SUPERFX
|
||||
CPUS += Z8
|
||||
|
||||
|
||||
#-------------------------------------------------
|
||||
|
@ -173,6 +173,7 @@ CPU_DISASSEMBLE( v810 );
|
||||
CPU_DISASSEMBLE( z180 );
|
||||
CPU_DISASSEMBLE( z8000 );
|
||||
CPU_DISASSEMBLE( z80 );
|
||||
CPU_DISASSEMBLE( z8 );
|
||||
|
||||
|
||||
static const dasm_table_entry dasm_table[] =
|
||||
@ -295,6 +296,7 @@ static const dasm_table_entry dasm_table[] =
|
||||
{ "z180", _8bit, 0, CPU_DISASSEMBLE_NAME(z180) },
|
||||
// { "z8000", _16be, 0, CPU_DISASSEMBLE_NAME(z8000) },
|
||||
{ "z80", _8bit, 0, CPU_DISASSEMBLE_NAME(z80) },
|
||||
{ "z8", _8bit, 0, CPU_DISASSEMBLE_NAME(z8) },
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user