1
/**********************************************************************
3
Zilog Z8 Single-Chip MCU emulation
6
Visit http://mamedev.org for licensing and usage restrictions.
8
**********************************************************************/
16
- expose register file to disassembler
17
- decimal adjust instruction
18
- timer Tin/Tout modes
20
- instruction pipeline
28
/***************************************************************************
30
***************************************************************************/
38
Z8_REGISTER_SIO = 0xf0,
56
#define Z8_P3_DAV0 0x04 /* not supported */
57
#define Z8_P3_DAV1 0x08 /* not supported */
58
#define Z8_P3_DAV2 0x02 /* not supported */
59
#define Z8_P3_RDY0 0x20 /* not supported */
60
#define Z8_P3_RDY1 0x10 /* not supported */
61
#define Z8_P3_RDY2 0x40 /* not supported */
62
#define Z8_P3_IRQ0 0x04 /* not supported */
63
#define Z8_P3_IRQ1 0x08 /* not supported */
64
#define Z8_P3_IRQ2 0x02 /* not supported */
65
#define Z8_P3_IRQ3 0x01 /* not supported */
66
#define Z8_P3_DI 0x01 /* not supported */
67
#define Z8_P3_DO 0x80 /* not supported */
68
#define Z8_P3_TIN 0x02 /* not supported */
69
#define Z8_P3_TOUT 0x40 /* not supported */
70
#define Z8_P3_DM 0x10 /* not supported */
72
#define Z8_PRE0_COUNT_MODULO_N 0x01
74
#define Z8_PRE1_COUNT_MODULO_N 0x01
75
#define Z8_PRE1_INTERNAL_CLOCK 0x02
77
#define Z8_TMR_LOAD_T0 0x01
78
#define Z8_TMR_ENABLE_T0 0x02
79
#define Z8_TMR_LOAD_T1 0x04
80
#define Z8_TMR_ENABLE_T1 0x08
81
#define Z8_TMR_TIN_MASK 0x30 /* not supported */
82
#define Z8_TMR_TIN_EXTERNAL_CLK 0x00 /* not supported */
83
#define Z8_TMR_TIN_GATE 0x10 /* not supported */
84
#define Z8_TMR_TIN_TRIGGER 0x20 /* not supported */
85
#define Z8_TMR_TIN_RETRIGGER 0x30 /* not supported */
86
#define Z8_TMR_TOUT_MASK 0xc0 /* not supported */
87
#define Z8_TMR_TOUT_OFF 0x00 /* not supported */
88
#define Z8_TMR_TOUT_T0 0x40 /* not supported */
89
#define Z8_TMR_TOUT_T1 0x80 /* not supported */
90
#define Z8_TMR_TOUT_INTERNAL_CLK 0xc0 /* not supported */
92
#define Z8_P01M_P0L_MODE_MASK 0x03
93
#define Z8_P01M_P0L_MODE_OUTPUT 0x00
94
#define Z8_P01M_P0L_MODE_INPUT 0x01
95
#define Z8_P01M_P0L_MODE_A8_A11 0x02 /* not supported */
96
#define Z8_P01M_INTERNAL_STACK 0x04
97
#define Z8_P01M_P1_MODE_MASK 0x18
98
#define Z8_P01M_P1_MODE_OUTPUT 0x00
99
#define Z8_P01M_P1_MODE_INPUT 0x08
100
#define Z8_P01M_P1_MODE_AD0_AD7 0x10 /* not supported */
101
#define Z8_P01M_P1_MODE_HI_Z 0x18 /* not supported */
102
#define Z8_P01M_EXTENDED_TIMING 0x20 /* not supported */
103
#define Z8_P01M_P0H_MODE_MASK 0xc0
104
#define Z8_P01M_P0H_MODE_OUTPUT 0x00
105
#define Z8_P01M_P0H_MODE_INPUT 0x40
106
#define Z8_P01M_P0H_MODE_A12_A15 0x80 /* not supported */
108
#define Z8_P3M_P2_ACTIVE_PULLUPS 0x01 /* not supported */
109
#define Z8_P3M_P0_STROBED 0x04 /* not supported */
110
#define Z8_P3M_P33_P34_MASK 0x18
111
#define Z8_P3M_P33_P34_INPUT_OUTPUT 0x00
112
#define Z8_P3M_P33_P34_INPUT_DM 0x08 /* not supported */
113
#define Z8_P3M_P33_P34_INPUT_DM_2 0x10 /* not supported */
114
#define Z8_P3M_P33_P34_DAV1_RDY1 0x18 /* not supported */
115
#define Z8_P3M_P2_STROBED 0x20 /* not supported */
116
#define Z8_P3M_P3_SERIAL 0x40 /* not supported */
117
#define Z8_P3M_PARITY 0x80 /* not supported */
119
#define Z8_IMR_ENABLE 0x80 /* not supported */
120
#define Z8_IMR_RAM_PROTECT 0x40 /* not supported */
121
#define Z8_IMR_ENABLE_IRQ5 0x20 /* not supported */
122
#define Z8_IMR_ENABLE_IRQ4 0x10 /* not supported */
123
#define Z8_IMR_ENABLE_IRQ3 0x08 /* not supported */
124
#define Z8_IMR_ENABLE_IRQ2 0x04 /* not supported */
125
#define Z8_IMR_ENABLE_IRQ1 0x02 /* not supported */
126
#define Z8_IMR_ENABLE_IRQ0 0x01 /* not supported */
128
#define Z8_FLAGS_F1 0x01
129
#define Z8_FLAGS_F2 0x02
130
#define Z8_FLAGS_H 0x04
131
#define Z8_FLAGS_D 0x08
132
#define Z8_FLAGS_V 0x10
133
#define Z8_FLAGS_S 0x20
134
#define Z8_FLAGS_Z 0x40
135
#define Z8_FLAGS_C 0x80
139
CC_F = 0, CC_LT, CC_LE, CC_ULE, CC_OV, CC_MI, CC_Z, CC_C,
140
CC_T, CC_GE, CC_GT, CC_UGT, CC_NOV, CC_PL, CC_NZ, CC_NC
143
/***************************************************************************
145
***************************************************************************/
147
#define P01M cpustate->r[Z8_REGISTER_P01M]
148
#define P2M cpustate->r[Z8_REGISTER_P2M]
149
#define P3M cpustate->r[Z8_REGISTER_P3M]
150
#define T0 cpustate->r[Z8_REGISTER_T0]
151
#define T1 cpustate->r[Z8_REGISTER_T1]
152
#define PRE0 cpustate->r[Z8_REGISTER_PRE0]
153
#define PRE1 cpustate->r[Z8_REGISTER_PRE1]
155
/***************************************************************************
157
***************************************************************************/
159
typedef struct _z8_state z8_state;
162
const address_space *program;
163
const address_space *data;
164
const address_space *io;
167
UINT16 pc; /* program counter */
168
UINT8 r[256]; /* register file */
169
UINT8 input[4]; /* port input latches */
170
UINT8 output[4]; /* port output latches */
171
UINT8 t0; /* timer 0 current count */
172
UINT8 t1; /* timer 1 current count */
175
UINT16 fake_sp; /* fake stack pointer */
176
UINT8 fake_r[16]; /* fake working registers */
179
int irq[6]; /* interrupts */
181
/* execution logic */
182
int clock; /* clock */
183
int icount; /* instruction counter */
185
cpu_state_table state_table;
192
/***************************************************************************
193
CPU STATE DESCRIPTION
194
***************************************************************************/
196
#define Z8_STATE_ENTRY(_name, _format, _member, _datamask, _flags) \
197
CPU_STATE_ENTRY(Z8_##_name, #_name, _format, z8_state, _member, _datamask, ~0, _flags)
199
static const cpu_state_entry state_array[] =
201
Z8_STATE_ENTRY(PC, "%04X", pc, 0xffff, 0)
202
Z8_STATE_ENTRY(GENPC, "%04X", pc, 0xffff, CPUSTATE_NOSHOW)
203
Z8_STATE_ENTRY(SP, "%04X", fake_sp, 0xffff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
204
Z8_STATE_ENTRY(GENSP, "%04X", fake_sp, 0xffff, CPUSTATE_NOSHOW | CPUSTATE_IMPORT | CPUSTATE_EXPORT)
205
Z8_STATE_ENTRY(RP, "%02X", r[Z8_REGISTER_RP], 0xff, 0)
206
Z8_STATE_ENTRY(T0, "%02X", t0, 0xff, 0)
207
Z8_STATE_ENTRY(T1, "%02X", t1, 0xff, 0)
209
Z8_STATE_ENTRY(R0, "%02X", fake_r[0], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
210
Z8_STATE_ENTRY(R1, "%02X", fake_r[1], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
211
Z8_STATE_ENTRY(R2, "%02X", fake_r[2], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
212
Z8_STATE_ENTRY(R3, "%02X", fake_r[3], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
213
Z8_STATE_ENTRY(R4, "%02X", fake_r[4], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
214
Z8_STATE_ENTRY(R5, "%02X", fake_r[5], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
215
Z8_STATE_ENTRY(R6, "%02X", fake_r[6], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
216
Z8_STATE_ENTRY(R7, "%02X", fake_r[7], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
217
Z8_STATE_ENTRY(R8, "%02X", fake_r[8], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
218
Z8_STATE_ENTRY(R9, "%02X", fake_r[9], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
219
Z8_STATE_ENTRY(R10, "%02X", fake_r[10], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
220
Z8_STATE_ENTRY(R11, "%02X", fake_r[11], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
221
Z8_STATE_ENTRY(R12, "%02X", fake_r[12], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
222
Z8_STATE_ENTRY(R13, "%02X", fake_r[13], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
223
Z8_STATE_ENTRY(R14, "%02X", fake_r[14], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
224
Z8_STATE_ENTRY(R15, "%02X", fake_r[15], 0xff, CPUSTATE_IMPORT | CPUSTATE_EXPORT)
227
static const cpu_state_table state_table_template =
229
NULL, /* pointer to the base of state (offsets are relative to this) */
230
0, /* subtype this table refers to */
231
ARRAY_LENGTH(state_array), /* number of entries */
232
state_array /* array of entries */
235
/***************************************************************************
237
***************************************************************************/
239
INLINE z8_state *get_safe_token(const device_config *device)
241
assert(device != NULL);
242
assert(device->token != NULL);
243
assert(device->type == CPU);
244
assert((cpu_get_type(device) == CPU_Z8601) ||
245
(cpu_get_type(device) == CPU_UB8830D) ||
246
(cpu_get_type(device) == CPU_Z8611));
247
return (z8_state *)device->token;
250
INLINE UINT8 fetch(z8_state *cpustate)
252
UINT8 data = memory_decrypted_read_byte(cpustate->program, cpustate->pc);
259
INLINE UINT8 register_read(z8_state *cpustate, UINT8 offset)
267
switch (P01M & Z8_P01M_P0L_MODE_MASK)
269
case Z8_P01M_P0L_MODE_OUTPUT: data = cpustate->output[offset] & 0x0f; break;
270
case Z8_P01M_P0L_MODE_INPUT: mask = 0x0f; break;
271
default: /* A8...A11 */ data = 0x0f; break;
274
switch (P01M & Z8_P01M_P0H_MODE_MASK)
276
case Z8_P01M_P0H_MODE_OUTPUT: data |= cpustate->output[offset] & 0xf0; break;
277
case Z8_P01M_P0H_MODE_INPUT: mask |= 0xf0; break;
278
default: /* A12...A15 */ data |= 0xf0; break;
281
if (!(P3M & Z8_P3M_P0_STROBED))
283
if (mask) cpustate->input[offset] = memory_read_byte_8be(cpustate->io, offset);
286
data |= cpustate->input[offset] & mask;
290
switch (P01M & Z8_P01M_P1_MODE_MASK)
292
case Z8_P01M_P1_MODE_OUTPUT: data = cpustate->output[offset]; break;
293
case Z8_P01M_P1_MODE_INPUT: mask = 0xff; break;
294
default: /* AD0..AD7 */ data = 0xff; break;
297
if ((P3M & Z8_P3M_P33_P34_MASK) != Z8_P3M_P33_P34_DAV1_RDY1)
299
if (mask) cpustate->input[offset] = memory_read_byte_8be(cpustate->io, offset);
302
data |= cpustate->input[offset] & mask;
306
mask = cpustate->r[Z8_REGISTER_P2M];
308
if (!(P3M & Z8_P3M_P2_STROBED))
310
if (mask) cpustate->input[offset] = memory_read_byte_8be(cpustate->io, offset);
313
data = (cpustate->input[offset] & mask) | (cpustate->output[offset] & ~mask);
317
// TODO: special port 3 modes
323
if (mask) cpustate->input[offset] = memory_read_byte_8be(cpustate->io, offset);
325
data = (cpustate->input[offset] & mask) | (cpustate->output[offset] & ~mask);
336
case Z8_REGISTER_PRE1:
337
case Z8_REGISTER_PRE0:
338
case Z8_REGISTER_P2M:
339
case Z8_REGISTER_P3M:
340
case Z8_REGISTER_P01M:
341
case Z8_REGISTER_IPR:
346
data = cpustate->r[offset];
353
INLINE UINT16 register_pair_read(z8_state *cpustate, UINT8 offset)
355
return (register_read(cpustate, offset) << 8) | register_read(cpustate, offset + 1);
358
INLINE void register_write(z8_state *cpustate, UINT8 offset, UINT8 data)
365
cpustate->output[offset] = data;
366
if ((P01M & Z8_P01M_P0L_MODE_MASK) == Z8_P01M_P0L_MODE_OUTPUT) mask |= 0x0f;
367
if ((P01M & Z8_P01M_P0H_MODE_MASK) == Z8_P01M_P0H_MODE_OUTPUT) mask |= 0xf0;
368
if (mask) memory_write_byte_8be(cpustate->io, offset, data & mask);
372
cpustate->output[offset] = data;
373
if ((P01M & Z8_P01M_P1_MODE_MASK) == Z8_P01M_P1_MODE_OUTPUT) mask = 0xff;
374
if (mask) memory_write_byte_8be(cpustate->io, offset, data & mask);
378
cpustate->output[offset] = data;
379
mask = cpustate->r[Z8_REGISTER_P2M] ^ 0xff;
380
if (mask) memory_write_byte_8be(cpustate->io, offset, data & mask);
384
cpustate->output[offset] = data;
386
// TODO: special port 3 modes
392
if (mask) memory_write_byte_8be(cpustate->io, offset, data & mask);
395
case Z8_REGISTER_SIO:
398
case Z8_REGISTER_TMR:
399
if (data & Z8_TMR_LOAD_T0)
402
timer_adjust_periodic(cpustate->t0_timer, attotime_zero, 0, ATTOTIME_IN_HZ(cpustate->clock / 2 / 4 / ((PRE0 >> 2) + 1)));
405
timer_enable(cpustate->t0_timer, data & Z8_TMR_ENABLE_T0);
407
if (data & Z8_TMR_LOAD_T1)
410
timer_adjust_periodic(cpustate->t1_timer, attotime_zero, 0, ATTOTIME_IN_HZ(cpustate->clock / 2 / 4 / ((PRE1 >> 2) + 1)));
413
timer_enable(cpustate->t1_timer, data & Z8_TMR_ENABLE_T1);
416
case Z8_REGISTER_P2M:
418
case Z8_REGISTER_P3M:
420
case Z8_REGISTER_P01M:
422
case Z8_REGISTER_IPR:
424
case Z8_REGISTER_IRQ:
426
case Z8_REGISTER_IMR:
428
case Z8_REGISTER_FLAGS:
432
case Z8_REGISTER_SPH:
434
case Z8_REGISTER_SPL:
437
// TODO ignore missing registers
441
cpustate->r[offset] = data;
444
INLINE void register_pair_write(z8_state *cpustate, UINT8 offset, UINT16 data)
446
register_write(cpustate, offset, data >> 8);
447
register_write(cpustate, offset + 1, data & 0xff);
450
INLINE UINT8 get_working_register(z8_state *cpustate, int offset)
452
return (cpustate->r[Z8_REGISTER_RP] & 0xf0) | (offset & 0x0f);
455
INLINE UINT8 get_register(z8_state *cpustate, UINT8 offset)
457
if ((offset & 0xf0) == 0xe0)
458
return get_working_register(cpustate, offset & 0x0f);
463
INLINE UINT8 get_intermediate_register(z8_state *cpustate, int offset)
465
return register_read(cpustate, get_register(cpustate, offset));
468
INLINE void stack_push_byte(z8_state *cpustate, UINT8 src)
470
if (register_read(cpustate, Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK)
473
UINT8 sp = register_read(cpustate, Z8_REGISTER_SPL) - 1;
474
register_write(cpustate, Z8_REGISTER_SPL, sp);
477
register_write(cpustate, sp, src);
482
UINT16 sp = register_pair_read(cpustate, Z8_REGISTER_SPH) - 1;
483
register_pair_write(cpustate, Z8_REGISTER_SPH, sp);
486
memory_write_byte(cpustate->data, sp, src);
490
INLINE void stack_push_word(z8_state *cpustate, UINT16 src)
492
if (register_read(cpustate, Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK)
495
UINT8 sp = register_read(cpustate, Z8_REGISTER_SPL) - 2;
496
register_write(cpustate, Z8_REGISTER_SPL, sp);
499
register_pair_write(cpustate, sp, src);
504
UINT16 sp = register_pair_read(cpustate, Z8_REGISTER_SPH) - 2;
505
register_pair_write(cpustate, Z8_REGISTER_SPH, sp);
508
memory_write_word_8le(cpustate->data, sp, src);
512
INLINE UINT8 stack_pop_byte(z8_state *cpustate)
514
if (register_read(cpustate, Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK)
517
UINT8 sp = register_read(cpustate, Z8_REGISTER_SPL) + 1;
518
register_write(cpustate, Z8_REGISTER_SPL, sp);
521
return register_read(cpustate, sp);
526
UINT16 sp = register_pair_read(cpustate, Z8_REGISTER_SPH) + 1;
527
register_pair_write(cpustate, Z8_REGISTER_SPH, sp);
530
return memory_read_byte(cpustate->data, sp);
534
INLINE UINT16 stack_pop_word(z8_state *cpustate)
536
if (register_read(cpustate, Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK)
539
UINT8 sp = register_read(cpustate, Z8_REGISTER_SPL) + 2;
540
register_write(cpustate, Z8_REGISTER_SPL, sp);
543
return register_read(cpustate, sp);
548
UINT16 sp = register_pair_read(cpustate, Z8_REGISTER_SPH) + 2;
549
register_pair_write(cpustate, Z8_REGISTER_SPH, sp);
552
return memory_read_word_8le(cpustate->data, sp);
556
INLINE void set_flag(z8_state *cpustate, UINT8 flag, int state)
559
cpustate->r[Z8_REGISTER_FLAGS] |= flag;
561
cpustate->r[Z8_REGISTER_FLAGS] &= ~flag;
564
#define set_flag_h(state) set_flag(cpustate, Z8_FLAGS_H, state);
565
#define set_flag_d(state) set_flag(cpustate, Z8_FLAGS_D, state);
566
#define set_flag_v(state) set_flag(cpustate, Z8_FLAGS_V, state);
567
#define set_flag_s(state) set_flag(cpustate, Z8_FLAGS_S, state);
568
#define set_flag_z(state) set_flag(cpustate, Z8_FLAGS_Z, state);
569
#define set_flag_c(state) set_flag(cpustate, Z8_FLAGS_C, state);
571
/***************************************************************************
573
***************************************************************************/
575
#define INSTRUCTION(mnemonic) INLINE void (mnemonic)(z8_state *cpustate, UINT8 opcode, int *cycles)
577
INSTRUCTION( illegal )
579
logerror("Z8: PC = %04x, Illegal opcode = %02x\n", cpustate->pc - 1, opcode);
584
/***************************************************************************
586
***************************************************************************/
588
typedef void (*z8_opcode_func) (z8_state *cpustate, UINT8 opcode, int *cycles);
590
typedef struct _z8_opcode_map z8_opcode_map;
591
struct _z8_opcode_map
593
z8_opcode_func function;
594
int execution_cycles;
598
static const z8_opcode_map Z8601_OPCODE_MAP[] =
600
{ 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 },
601
{ 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 },
603
{ 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 },
604
{ 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 },
606
{ 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 },
607
{ 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 },
609
{ 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 },
610
{ 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 },
612
{ 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 },
613
{ 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 },
615
{ 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 },
616
{ 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 },
618
{ 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 },
619
{ 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 },
621
{ 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 },
622
{ 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 },
624
{ 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 },
625
{ 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 },
627
{ 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 },
628
{ 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 },
630
{ 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 },
631
{ 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 },
633
{ 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 },
634
{ 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 },
636
{ 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 },
637
{ 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 },
639
{ 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 },
640
{ 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 },
642
{ 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 },
643
{ 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 },
645
{ 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 },
646
{ 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 },
649
/***************************************************************************
651
***************************************************************************/
653
static TIMER_CALLBACK( t0_tick )
655
z8_state *cpustate = (z8_state *)ptr;
659
if (cpustate->t0 == 0)
662
timer_adjust_periodic(cpustate->t0_timer, attotime_zero, 0, ATTOTIME_IN_HZ(cpustate->clock / 2 / 4 / ((PRE0 >> 2) + 1)));
663
timer_enable(cpustate->t0_timer, PRE0 & Z8_PRE0_COUNT_MODULO_N);
664
cpustate->irq[4] = ASSERT_LINE;
668
static TIMER_CALLBACK( t1_tick )
670
z8_state *cpustate = (z8_state *)ptr;
674
if (cpustate->t1 == 0)
677
timer_adjust_periodic(cpustate->t1_timer, attotime_zero, 0, ATTOTIME_IN_HZ(cpustate->clock / 2 / 4 / ((PRE1 >> 2) + 1)));
678
timer_enable(cpustate->t1_timer, PRE1 & Z8_PRE0_COUNT_MODULO_N);
679
cpustate->irq[5] = ASSERT_LINE;
683
/***************************************************************************
685
***************************************************************************/
687
static CPU_INIT( z8 )
689
z8_state *cpustate = get_safe_token(device);
691
/* set up the state table */
692
cpustate->state_table = state_table_template;
693
cpustate->state_table.baseptr = cpustate;
694
cpustate->state_table.subtypemask = 1;
696
cpustate->clock = device->clock;
698
/* find address spaces */
699
cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM);
700
cpustate->data = memory_find_address_space(device, ADDRESS_SPACE_DATA);
701
cpustate->io = memory_find_address_space(device, ADDRESS_SPACE_IO);
703
/* allocate timers */
704
cpustate->t0_timer = timer_alloc(device->machine, t0_tick, cpustate);
705
cpustate->t1_timer = timer_alloc(device->machine, t1_tick, cpustate);
707
/* register for state saving */
708
state_save_register_device_item(device, 0, cpustate->pc);
709
state_save_register_device_item_array(device, 0, cpustate->r);
710
state_save_register_device_item_array(device, 0, cpustate->input);
711
state_save_register_device_item_array(device, 0, cpustate->output);
712
state_save_register_device_item_array(device, 0, cpustate->irq);
715
/***************************************************************************
717
***************************************************************************/
719
static CPU_EXECUTE( z8 )
721
z8_state *cpustate = get_safe_token(device);
723
cpustate->icount = cycles;
730
debugger_instruction_hook(device, cpustate->pc);
732
/* TODO: sample interrupts */
733
cpustate->input[3] = memory_read_byte_8be(cpustate->io, 3);
736
opcode = fetch(cpustate);
737
cycles = Z8601_OPCODE_MAP[opcode].execution_cycles;
739
/* execute instruction */
740
(*(Z8601_OPCODE_MAP[opcode].function))(cpustate, opcode, &cycles);
742
cpustate->icount -= cycles;
744
while (cpustate->icount > 0);
746
return cycles - cpustate->icount;
749
/***************************************************************************
751
***************************************************************************/
753
static CPU_RESET( z8 )
755
z8_state *cpustate = get_safe_token(device);
757
cpustate->pc = 0x000c;
759
register_write(cpustate, Z8_REGISTER_TMR, 0x00);
760
register_write(cpustate, Z8_REGISTER_PRE1, register_read(cpustate, Z8_REGISTER_PRE1) & 0xfc);
761
register_write(cpustate, Z8_REGISTER_PRE0, register_read(cpustate, Z8_REGISTER_PRE0) & 0xfe);
762
register_write(cpustate, Z8_REGISTER_P2M, 0xff);
763
register_write(cpustate, Z8_REGISTER_P3M, 0x00);
764
register_write(cpustate, Z8_REGISTER_P01M, 0x4d);
765
register_write(cpustate, Z8_REGISTER_IRQ, 0x00);
766
register_write(cpustate, Z8_REGISTER_RP, 0x00);
769
/***************************************************************************
771
***************************************************************************/
773
static ADDRESS_MAP_START( program_2kb, ADDRESS_SPACE_PROGRAM, 8 )
774
AM_RANGE(0x0000, 0x07ff) AM_ROM
777
static ADDRESS_MAP_START( program_4kb, ADDRESS_SPACE_PROGRAM, 8 )
778
AM_RANGE(0x0000, 0x0fff) AM_ROM
781
/**************************************************************************
782
* STATE IMPORT/EXPORT
783
**************************************************************************/
785
static CPU_IMPORT_STATE( z8 )
787
z8_state *cpustate = get_safe_token(device);
789
switch (entry->index)
793
cpustate->r[Z8_REGISTER_SPH] = cpustate->fake_sp >> 8;
794
cpustate->r[Z8_REGISTER_SPL] = cpustate->fake_sp & 0xff;
797
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:
798
cpustate->r[cpustate->r[Z8_REGISTER_RP] + (entry->index - Z8_R0)] = cpustate->fake_r[entry->index - Z8_R0];
802
fatalerror("CPU_IMPORT_STATE(z8) called for unexpected value\n");
807
static CPU_EXPORT_STATE( z8 )
809
z8_state *cpustate = get_safe_token(device);
811
switch (entry->index)
815
cpustate->fake_sp = (cpustate->r[Z8_REGISTER_SPH] << 8) | cpustate->r[Z8_REGISTER_SPL];
818
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:
819
cpustate->fake_r[entry->index - Z8_R0] = cpustate->r[cpustate->r[Z8_REGISTER_RP] + (entry->index - Z8_R0)];
823
fatalerror("CPU_EXPORT_STATE(z8) called for unexpected value\n");
828
/***************************************************************************
829
GENERAL CONTEXT ACCESS
830
***************************************************************************/
832
static CPU_SET_INFO( z8 )
834
z8_state *cpustate = get_safe_token(device);
838
case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ0: cpustate->irq[0] = info->i; break;
839
case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ1: cpustate->irq[1] = info->i; break;
840
case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ2: cpustate->irq[2] = info->i; break;
841
case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ3: cpustate->irq[3] = info->i; break;
845
static CPU_GET_INFO( z8 )
847
z8_state *cpustate = (device != NULL && device->token != NULL) ? get_safe_token(device) : NULL;
851
/* --- the following bits of info are returned as 64-bit signed integers --- */
852
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(z8_state); break;
853
case CPUINFO_INT_INPUT_LINES: info->i = 4; break;
854
case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
855
case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
856
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
857
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 2; break;
858
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
859
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 3; break;
860
case CPUINFO_INT_MIN_CYCLES: info->i = 6; break;
861
case CPUINFO_INT_MAX_CYCLES: info->i = 20; break;
863
case CPUINFO_INT_DATABUS_WIDTH_PROGRAM: info->i = 8; break;
864
case CPUINFO_INT_ADDRBUS_WIDTH_PROGRAM: info->i = 16; break;
865
case CPUINFO_INT_ADDRBUS_SHIFT_PROGRAM: info->i = 0; break;
866
case CPUINFO_INT_DATABUS_WIDTH_DATA: info->i = 8; break;
867
case CPUINFO_INT_ADDRBUS_WIDTH_DATA: info->i = 16; break;
868
case CPUINFO_INT_ADDRBUS_SHIFT_DATA: info->i = 0; break;
869
case CPUINFO_INT_DATABUS_WIDTH_IO: info->i = 8; break;
870
case CPUINFO_INT_ADDRBUS_WIDTH_IO: info->i = 2; break;
871
case CPUINFO_INT_ADDRBUS_SHIFT_IO: info->i = 0; break;
873
/* --- the following bits of info are returned as pointers to functions --- */
874
case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(z8); break;
875
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(z8); break;
876
case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(z8); break;
877
case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(z8); break;
878
case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(z8); break;
879
case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(z8); break;
880
case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(z8); break;
882
/* --- the following bits of info are returned as pointers --- */
883
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
884
case CPUINFO_PTR_STATE_TABLE: info->state_table = &cpustate->state_table; break;
886
/* --- the following bits of info are returned as NULL-terminated strings --- */
887
case DEVINFO_STR_NAME: strcpy(info->s, "Z8"); break;
888
case DEVINFO_STR_FAMILY: strcpy(info->s, "Zilog Z8"); break;
889
case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
890
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
891
case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright MESS Team"); break;
893
case CPUINFO_STR_FLAGS: sprintf(info->s,
895
cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_C ? 'C' : '.',
896
cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_Z ? 'Z' : '.',
897
cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_S ? 'S' : '.',
898
cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_V ? 'V' : '.',
899
cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_D ? 'D' : '.',
900
cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_H ? 'H' : '.'); break;
904
/***************************************************************************
905
CPU-SPECIFIC CONTEXT ACCESS
906
***************************************************************************/
908
CPU_GET_INFO( z8601 )
912
/* --- the following bits of info are returned as pointers --- */
913
case CPUINFO_PTR_INTERNAL_MEMORY_MAP_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_2kb); break;
915
/* --- the following bits of info are returned as NULL-terminated strings --- */
916
case DEVINFO_STR_NAME: strcpy(info->s, "Z8601"); break;
918
default: CPU_GET_INFO_CALL(z8); break;
922
CPU_GET_INFO( ub8830d )
926
/* --- the following bits of info are returned as pointers --- */
927
case CPUINFO_PTR_INTERNAL_MEMORY_MAP_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_2kb); break;
929
/* --- the following bits of info are returned as NULL-terminated strings --- */
930
case DEVINFO_STR_NAME: strcpy(info->s, "UB8830D"); break;
932
default: CPU_GET_INFO_CALL(z8); break;
936
CPU_GET_INFO( z8611 )
940
/* --- the following bits of info are returned as pointers --- */
941
case CPUINFO_PTR_INTERNAL_MEMORY_MAP_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_4kb); break;
943
/* --- the following bits of info are returned as NULL-terminated strings --- */
944
case DEVINFO_STR_NAME: strcpy(info->s, "Z8611"); break;
946
default: CPU_GET_INFO_CALL(z8); break;