diff options
Diffstat (limited to 'src/devices/cpu/z8/z8.cpp')
-rw-r--r-- | src/devices/cpu/z8/z8.cpp | 738 |
1 files changed, 425 insertions, 313 deletions
diff --git a/src/devices/cpu/z8/z8.cpp b/src/devices/cpu/z8/z8.cpp index 52c2ee4627e..633a2252988 100644 --- a/src/devices/cpu/z8/z8.cpp +++ b/src/devices/cpu/z8/z8.cpp @@ -11,7 +11,6 @@ TODO: - strobed I/O - - expose register file to disassembler - timer Tin/Tout modes - serial - instruction pipeline @@ -28,30 +27,6 @@ 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 */ @@ -104,7 +79,7 @@ enum #define Z8_P01M_P0H_MODE_INPUT 0x40 #define Z8_P01M_P0H_MODE_A12_A15 0x80 -#define Z8_P3M_P2_ACTIVE_PULLUPS 0x01 /* not supported */ +#define Z8_P3M_P2_ACTIVE_PULLUPS 0x01 #define Z8_P3M_P0_STROBED 0x04 /* not supported */ #define Z8_P3M_P33_P34_MASK 0x18 #define Z8_P3M_P33_P34_INPUT_OUTPUT 0x00 @@ -119,12 +94,6 @@ enum #define Z8_IMR_RAM_PROTECT 0x40 /* not supported */ #define Z8_IRQ_MASK 0x3f -#define Z8_IRQ_FLAG_IRQ5 0x20 -#define Z8_IRQ_FLAG_IRQ4 0x10 -#define Z8_IRQ_FLAG_IRQ3 0x08 -#define Z8_IRQ_FLAG_IRQ2 0x04 -#define Z8_IRQ_FLAG_IRQ1 0x02 -#define Z8_IRQ_FLAG_IRQ0 0x01 #define Z8_FLAGS_F1 0x01 #define Z8_FLAGS_F2 0x02 @@ -145,15 +114,6 @@ enum MACROS ***************************************************************************/ -#define P01M m_r[Z8_REGISTER_P01M] -#define P2M m_r[Z8_REGISTER_P2M] -#define P3M m_r[Z8_REGISTER_P3M] -#define T0 m_r[Z8_REGISTER_T0] -#define T1 m_r[Z8_REGISTER_T1] -#define PRE0 m_r[Z8_REGISTER_PRE0] -#define PRE1 m_r[Z8_REGISTER_PRE1] - - DEFINE_DEVICE_TYPE(Z8601, z8601_device, "z8601", "Zilog Z8601") DEFINE_DEVICE_TYPE(UB8830D, ub8830d_device, "ub8830d", "UB8830D") DEFINE_DEVICE_TYPE(Z8611, z8611_device, "z8611", "Zilog Z8611") @@ -176,11 +136,37 @@ void z8_device::preprogrammed_map(address_map &map) map(0x0000, m_rom_size - 1).rom().region("internal", 0); } +void z8_device::register_map(address_map &map) +{ + map(0x00, 0x00).rw(FUNC(z8_device::p0_read), FUNC(z8_device::p0_write)); + map(0x01, 0x01).rw(FUNC(z8_device::p1_read), FUNC(z8_device::p1_write)); + map(0x02, 0x02).rw(FUNC(z8_device::p2_read), FUNC(z8_device::p2_write)); + map(0x03, 0x03).rw(FUNC(z8_device::p3_read), FUNC(z8_device::p3_write)); + map(0x04, 0x7f).ram(); + map(0xf0, 0xf0).rw(FUNC(z8_device::sio_read), FUNC(z8_device::sio_write)); + map(0xf1, 0xf1).rw(FUNC(z8_device::tmr_read), FUNC(z8_device::tmr_write)); + map(0xf2, 0xf2).rw(FUNC(z8_device::t1_read), FUNC(z8_device::t1_write)); + map(0xf3, 0xf3).w(FUNC(z8_device::pre1_write)); + map(0xf4, 0xf4).rw(FUNC(z8_device::t0_read), FUNC(z8_device::t0_write)); + map(0xf5, 0xf5).w(FUNC(z8_device::pre0_write)); + map(0xf6, 0xf6).w(FUNC(z8_device::p2m_write)); + map(0xf7, 0xf7).w(FUNC(z8_device::p3m_write)); + map(0xf8, 0xf8).w(FUNC(z8_device::p01m_write)); + map(0xf9, 0xf9).w(FUNC(z8_device::ipr_write)); + map(0xfa, 0xfa).rw(FUNC(z8_device::irq_read), FUNC(z8_device::irq_write)); + map(0xfb, 0xfb).rw(FUNC(z8_device::imr_read), FUNC(z8_device::imr_write)); + map(0xfc, 0xfc).rw(FUNC(z8_device::flags_read), FUNC(z8_device::flags_write)); + map(0xfd, 0xfd).rw(FUNC(z8_device::rp_read), FUNC(z8_device::rp_write)); + map(0xfe, 0xfe).rw(FUNC(z8_device::sph_read), FUNC(z8_device::sph_write)); + map(0xff, 0xff).rw(FUNC(z8_device::spl_read), FUNC(z8_device::spl_write)); +} + z8_device::z8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t rom_size, bool preprogrammed) : cpu_device(mconfig, type, tag, owner, clock) , m_program_config("program", ENDIANNESS_BIG, 8, 16, 0, preprogrammed ? address_map_constructor(FUNC(z8_device::preprogrammed_map), this) : address_map_constructor(FUNC(z8_device::program_map), this)) , m_data_config("data", ENDIANNESS_BIG, 8, 16, 0) + , m_register_config("register", ENDIANNESS_BIG, 8, 8, 0, address_map_constructor(FUNC(z8_device::register_map), this)) , m_input_cb{{*this}, {*this}, {*this}, {*this}} , m_output_cb{{*this}, {*this}, {*this}, {*this}} , m_rom_size(rom_size) @@ -242,13 +228,15 @@ device_memory_interface::space_config_vector z8_device::memory_space_config() co { return space_config_vector { std::make_pair(AS_PROGRAM, &m_program_config), - std::make_pair(AS_DATA, &m_data_config) + std::make_pair(AS_DATA, &m_data_config), + std::make_pair(AS_IO, &m_register_config) }; } else { return space_config_vector { - std::make_pair(AS_PROGRAM, &m_program_config) + std::make_pair(AS_PROGRAM, &m_program_config), + std::make_pair(AS_IO, &m_register_config) }; } } @@ -259,18 +247,18 @@ device_memory_interface::space_config_vector z8_device::memory_space_config() co uint16_t z8_device::mask_external_address(uint16_t addr) { - switch (P01M & (Z8_P01M_P0L_MODE_A8_A11 | Z8_P01M_P0H_MODE_A12_A15)) + switch (m_p01m & (Z8_P01M_P0L_MODE_A8_A11 | Z8_P01M_P0H_MODE_A12_A15)) { case 0: - addr = (addr & 0x00ff) | register_read(Z8_REGISTER_P0) << 8; + addr = (addr & 0x00ff) | p0_read() << 8; break; case Z8_P01M_P0L_MODE_A8_A11: - addr = (addr & 0x0fff) | (register_read(Z8_REGISTER_P0) & 0xf0) << 8; + addr = (addr & 0x0fff) | (p0_read() & 0xf0) << 8; break; case Z8_P01M_P0H_MODE_A12_A15: - addr = (addr & 0xf0ff) | (register_read(Z8_REGISTER_P0) & 0x0f) << 8; + addr = (addr & 0xf0ff) | (p0_read() & 0x0f) << 8; break; } return addr; @@ -311,218 +299,316 @@ uint16_t z8_device::fetch_word() } -uint8_t z8_device::register_read(uint8_t offset) +uint8_t z8_device::p0_read() { uint8_t data = 0xff; uint8_t mask = 0; - switch (offset) + switch (m_p01m & Z8_P01M_P0L_MODE_MASK) { - case Z8_REGISTER_P0: - switch (P01M & Z8_P01M_P0L_MODE_MASK) - { - case Z8_P01M_P0L_MODE_OUTPUT: - data = m_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 |= m_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) m_input[offset] = m_input_cb[0](0, mask); - } + case Z8_P01M_P0L_MODE_OUTPUT: + data = m_output[0] & 0x0f; + break; + case Z8_P01M_P0L_MODE_INPUT: + mask = 0x0f; + break; + default: /* A8...A11 */ + data = 0x0f; + break; + } - data |= m_input[offset] & mask; + switch (m_p01m & Z8_P01M_P0H_MODE_MASK) + { + case Z8_P01M_P0H_MODE_OUTPUT: + data |= m_output[0] & 0xf0; break; + case Z8_P01M_P0H_MODE_INPUT: + mask |= 0xf0; + break; + default: /* A12...A15 */ + data |= 0xf0; + break; + } - case Z8_REGISTER_P1: - switch (P01M & Z8_P01M_P1_MODE_MASK) - { - case Z8_P01M_P1_MODE_OUTPUT: - data = m_output[offset]; - break; - case Z8_P01M_P1_MODE_INPUT: - mask = 0xff; - break; - default: /* AD0..AD7 */ - data = 0xff; - break; - } + if (!(m_p3m & Z8_P3M_P0_STROBED)) + { + if (mask) + m_input[0] = m_input_cb[0](0, mask); + } - if ((P3M & Z8_P3M_P33_P34_MASK) != Z8_P3M_P33_P34_DAV1_RDY1) - { - if (mask) m_input[offset] = m_input_cb[1](0, mask); - } + data |= m_input[0] & mask; + return data; +} - data |= m_input[offset] & mask; - break; +void z8_device::p0_write(uint8_t data) +{ + uint8_t mask = 0; - case Z8_REGISTER_P2: - mask = m_r[Z8_REGISTER_P2M]; + m_output[0] = data; + if ((m_p01m & Z8_P01M_P0L_MODE_MASK) == Z8_P01M_P0L_MODE_OUTPUT) + mask |= 0x0f; + if ((m_p01m & Z8_P01M_P0H_MODE_MASK) == Z8_P01M_P0H_MODE_OUTPUT) + mask |= 0xf0; + if (mask) + m_output_cb[0](0, data & mask, mask); +} - if (!(P3M & Z8_P3M_P2_STROBED)) - { - if (mask) m_input[offset] = m_input_cb[2](0, mask); - } +uint8_t z8_device::p1_read() +{ + uint8_t data = 0xff; + uint8_t mask = 0; - data = (m_input[offset] & mask) | (m_output[offset] & ~mask); + switch (m_p01m & Z8_P01M_P1_MODE_MASK) + { + case Z8_P01M_P1_MODE_OUTPUT: + data = m_output[1]; + break; + case Z8_P01M_P1_MODE_INPUT: + mask = 0xff; break; + default: /* AD0..AD7 */ + data = 0xff; + break; + } - case Z8_REGISTER_P3: - // TODO: special port 3 modes - //if (!(P3M & 0x7c)) - //{ - mask = 0x0f; - //} + if ((m_p3m & Z8_P3M_P33_P34_MASK) != Z8_P3M_P33_P34_DAV1_RDY1) + { + if (mask) + m_input[1] = m_input_cb[1](0, mask); + } - if (mask) m_input[offset] = m_input_cb[3](0, mask); + data |= m_input[1] & mask; + return data; +} - data = (m_input[offset] & mask) | (m_output[offset] & ~mask); - break; +void z8_device::p1_write(uint8_t data) +{ + uint8_t mask = 0; - case Z8_REGISTER_T0: - data = m_t0; - break; + m_output[1] = data; + if ((m_p01m & Z8_P01M_P1_MODE_MASK) == Z8_P01M_P1_MODE_OUTPUT) + mask = 0xff; + if (mask) + m_output_cb[1](0, data & mask, mask); +} - case Z8_REGISTER_T1: - data = m_t1; - break; +uint8_t z8_device::p2_read() +{ + uint8_t mask = m_p2m; - 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; + // open drain lines can be externally driven where data = 1 + if (!(m_p3m & Z8_P3M_P2_ACTIVE_PULLUPS)) + mask |= m_output[2]; - default: - data = m_r[offset]; - break; + if (!(m_p3m & Z8_P3M_P2_STROBED)) + { + if (mask) + m_input[2] = m_input_cb[2](0, mask); } - return data; + return (m_input[2] & mask) | (m_output[2] & ~mask); } -uint16_t z8_device::register_pair_read(uint8_t offset) +void z8_device::p2_write(uint8_t data) { - return (register_read(offset) << 8) | register_read(offset + 1); + uint8_t mask = m_p2m ^ 0xff; + + m_output[2] = data; + if (mask) + m_output_cb[2](0, data & mask, mask); } -void z8_device::register_write(uint8_t offset, uint8_t data) +uint8_t z8_device::p3_read() +{ + uint8_t mask = 0x0f; + + // TODO: special port 3 modes + //if (!(m_p3m & 0x7c)) + //{ + //} + + if (mask) + m_input[3] = m_input_cb[3](0, mask); + + return (m_input[3] & mask) | (m_output[3] & ~mask); +} + +void z8_device::p3_write(uint8_t data) { uint8_t mask = 0; - switch (offset) + m_output[3] = data; + + // TODO: special port 3 modes + //if (!(m_p3m & 0x7c)) + //{ + mask = 0xf0; + //} + + if (mask) + m_output_cb[3](0, data & mask, mask); +} + +uint8_t z8_device::sio_read() +{ + return 0xff; +} + +void z8_device::sio_write(uint8_t data) +{ +} + +uint8_t z8_device::tmr_read() +{ + return m_tmr; +} + +void z8_device::tmr_write(uint8_t data) +{ + m_tmr = data; + + if (data & Z8_TMR_LOAD_T0) { - case Z8_REGISTER_P0: - m_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) m_output_cb[0](0, data & mask, mask); - break; + m_count[0] = m_t[0]; + m_t0_timer->adjust(attotime::zero, 0, cycles_to_attotime(4 * ((m_pre[0] >> 2) + 1))); + } - case Z8_REGISTER_P1: - m_output[offset] = data; - if ((P01M & Z8_P01M_P1_MODE_MASK) == Z8_P01M_P1_MODE_OUTPUT) mask = 0xff; - if (mask) m_output_cb[1](0, data & mask, mask); - break; + m_t0_timer->enable(data & Z8_TMR_ENABLE_T0); - case Z8_REGISTER_P2: - m_output[offset] = data; - mask = m_r[Z8_REGISTER_P2M] ^ 0xff; - if (mask) m_output_cb[2](0, data & mask, mask); - break; + if (data & Z8_TMR_LOAD_T1) + { + m_count[1] = m_t[1]; + m_t1_timer->adjust(attotime::zero, 0, cycles_to_attotime(4 * ((m_pre[1] >> 2) + 1))); + } - case Z8_REGISTER_P3: - m_output[offset] = data; + m_t1_timer->enable(data & Z8_TMR_ENABLE_T1); +} - // TODO: special port 3 modes - //if (!(P3M & 0x7c)) - //{ - mask = 0xf0; - //} +uint8_t z8_device::t0_read() +{ + return m_count[0]; +} - if (mask) m_output_cb[3](0, data & mask, mask); - break; +void z8_device::t0_write(uint8_t data) +{ + m_t[0] = data; +} - case Z8_REGISTER_SIO: - break; +uint8_t z8_device::t1_read() +{ + return m_count[1]; +} - case Z8_REGISTER_TMR: - if (data & Z8_TMR_LOAD_T0) - { - m_t0 = T0; - m_t0_timer->adjust(attotime::zero, 0, cycles_to_attotime(4 * ((PRE0 >> 2) + 1))); - } +void z8_device::t1_write(uint8_t data) +{ + m_t[1] = data; +} - m_t0_timer->enable(data & Z8_TMR_ENABLE_T0); +void z8_device::pre0_write(uint8_t data) +{ + m_pre[0] = data; +} - if (data & Z8_TMR_LOAD_T1) - { - m_t1 = T1; - m_t1_timer->adjust(attotime::zero, 0, cycles_to_attotime(4 * ((PRE1 >> 2) + 1))); - } +void z8_device::pre1_write(uint8_t data) +{ + m_pre[0] = data; +} - m_t1_timer->enable(data & Z8_TMR_ENABLE_T1); - break; +void z8_device::p01m_write(uint8_t data) +{ + m_p01m = data; +} - 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; - } +void z8_device::p2m_write(uint8_t data) +{ + m_p2m = data; +} + +void z8_device::p3m_write(uint8_t data) +{ + m_p3m = data; +} + +void z8_device::ipr_write(uint8_t data) +{ + m_ipr = data; +} + +uint8_t z8_device::irq_read() +{ + return m_irq; +} + +void z8_device::irq_write(uint8_t data) +{ + if (m_irq_initialized) + m_irq = data; +} - m_r[offset] = data; +uint8_t z8_device::imr_read() +{ + return m_imr; +} + +void z8_device::imr_write(uint8_t data) +{ + m_imr = data; +} + +uint8_t z8_device::flags_read() +{ + return m_flags; +} + +void z8_device::flags_write(uint8_t data) +{ + m_flags = data; +} + +uint8_t z8_device::rp_read() +{ + return m_rp; +} + +void z8_device::rp_write(uint8_t data) +{ + m_rp = data; +} + +uint8_t z8_device::sph_read() +{ + return m_sp.b.h; +} + +void z8_device::sph_write(uint8_t data) +{ + m_sp.b.h = data; +} + +uint8_t z8_device::spl_read() +{ + return m_sp.b.l; +} + +void z8_device::spl_write(uint8_t data) +{ + m_sp.b.l = data; +} + + +uint16_t z8_device::register_pair_read(uint8_t offset) +{ + return m_regs->read_word_unaligned(offset); } void z8_device::register_pair_write(uint8_t offset, uint16_t data) { - register_write(offset, data >> 8); - register_write(offset + 1, data & 0xff); + m_regs->write_word_unaligned(offset, data); } uint8_t z8_device::get_working_register(int offset) { - return (m_r[Z8_REGISTER_RP] & 0xf0) | (offset & 0x0f); + return (m_rp & 0xf0) | (offset & 0x0f); } uint8_t z8_device::get_register(uint8_t offset) @@ -540,11 +626,11 @@ uint8_t z8_device::get_intermediate_register(int offset) void z8_device::stack_push_byte(uint8_t src) { - if (P01M & Z8_P01M_INTERNAL_STACK) + if (m_p01m & Z8_P01M_INTERNAL_STACK) { // SP <- SP - 1 (predecrement) - uint8_t sp = register_read(Z8_REGISTER_SPL) - 1; - register_write(Z8_REGISTER_SPL, sp); + uint8_t sp = m_sp.b.l - 1; + m_sp.b.l = sp; // @SP <- src register_write(sp, src); @@ -552,8 +638,8 @@ void z8_device::stack_push_byte(uint8_t src) else { // SP <- SP - 1 (predecrement) - uint16_t sp = register_pair_read(Z8_REGISTER_SPH) - 1; - register_pair_write(Z8_REGISTER_SPH, sp); + uint16_t sp = m_sp.w - 1; + m_sp.w = sp; // @SP <- src m_data->write_byte(mask_external_address(sp), src); @@ -562,11 +648,11 @@ void z8_device::stack_push_byte(uint8_t src) void z8_device::stack_push_word(uint16_t src) { - if (P01M & Z8_P01M_INTERNAL_STACK) + if (m_p01m & Z8_P01M_INTERNAL_STACK) { // SP <- SP - 2 (predecrement) - uint8_t sp = register_read(Z8_REGISTER_SPL) - 2; - register_write(Z8_REGISTER_SPL, sp); + uint8_t sp = m_sp.b.l - 2; + m_sp.b.l = sp; // @SP <- src register_pair_write(sp, src); @@ -574,8 +660,8 @@ void z8_device::stack_push_word(uint16_t src) else { // SP <- SP - 2 (predecrement) - uint16_t sp = register_pair_read(Z8_REGISTER_SPH) - 2; - register_pair_write(Z8_REGISTER_SPH, sp); + uint16_t sp = m_sp.w - 2; + m_sp.w = sp; // @SP <- src m_data->write_word_unaligned(mask_external_address(sp), src); @@ -584,25 +670,25 @@ void z8_device::stack_push_word(uint16_t src) uint8_t z8_device::stack_pop_byte() { - if (P01M & Z8_P01M_INTERNAL_STACK) + if (m_p01m & Z8_P01M_INTERNAL_STACK) { // @SP <- src - uint8_t sp = register_read(Z8_REGISTER_SPL); + uint8_t sp = m_sp.b.l; uint8_t byte = register_read(sp); // SP <- SP + 1 (postincrement) - register_write(Z8_REGISTER_SPL, sp + 1); + m_sp.b.l = sp + 1; return byte; } else { // @SP <- src - uint16_t sp = register_pair_read(Z8_REGISTER_SPH); + uint16_t sp = m_sp.w; uint8_t byte = m_data->read_byte(mask_external_address(sp)); // SP <- SP + 1 (postincrement) - register_pair_write(Z8_REGISTER_SPH, sp + 1); + m_sp.w = sp + 1; return byte; } @@ -610,25 +696,25 @@ uint8_t z8_device::stack_pop_byte() uint16_t z8_device::stack_pop_word() { - if (P01M & Z8_P01M_INTERNAL_STACK) + if (m_p01m & Z8_P01M_INTERNAL_STACK) { // @SP <- src - uint8_t sp = register_read(Z8_REGISTER_SPL); + uint8_t sp = m_sp.b.l; uint16_t word = register_pair_read(sp); // SP <- SP + 2 (postincrement) - register_write(Z8_REGISTER_SPL, sp + 2); + m_sp.b.l = sp + 2; return word; } else { // @SP <- src - uint16_t sp = register_pair_read(Z8_REGISTER_SPH); + uint16_t sp = m_sp.w; uint16_t word = m_data->read_word_unaligned(mask_external_address(sp)); // SP <- SP + 2 (postincrement) - register_pair_write(Z8_REGISTER_SPH, sp + 2); + m_sp.w = sp + 2; return word; } @@ -637,9 +723,9 @@ uint16_t z8_device::stack_pop_word() void z8_device::set_flag(uint8_t flag, int state) { if (state) - m_r[Z8_REGISTER_FLAGS] |= flag; + m_flags |= flag; else - m_r[Z8_REGISTER_FLAGS] &= ~flag; + m_flags &= ~flag; } #define set_flag_h(state) set_flag(Z8_FLAGS_H, state); @@ -755,27 +841,27 @@ const z8_device::z8_opcode_map z8_device::Z8601_OPCODE_MAP[256] = TIMER_CALLBACK_MEMBER( z8_device::t0_tick ) { - m_t0--; + m_count[0]--; - if (m_t0 == 0) + if (m_count[0] == 0) { - m_t0 = T0; - m_t0_timer->adjust(attotime::zero, 0, cycles_to_attotime(4 * ((PRE0 >> 2) + 1))); - m_t0_timer->enable(PRE0 & Z8_PRE0_COUNT_MODULO_N); - m_r[Z8_REGISTER_IRQ] |= Z8_IRQ_FLAG_IRQ4; + m_count[0] = m_t[0]; + m_t0_timer->adjust(attotime::zero, 0, cycles_to_attotime(4 * ((m_pre[0] >> 2) + 1))); + m_t0_timer->enable(m_pre[0] & Z8_PRE0_COUNT_MODULO_N); + request_interrupt(4); } } TIMER_CALLBACK_MEMBER( z8_device::t1_tick ) { - m_t1--; + m_count[1]--; - if (m_t1 == 0) + if (m_count[1] == 0) { - m_t1 = T1; - m_t1_timer->adjust(attotime::zero, 0, cycles_to_attotime(4 * ((PRE1 >> 2) + 1))); - m_t1_timer->enable(PRE1 & Z8_PRE0_COUNT_MODULO_N); - m_r[Z8_REGISTER_IRQ] |= Z8_IRQ_FLAG_IRQ5; + m_count[1] = m_t[1]; + m_t1_timer->adjust(attotime::zero, 0, cycles_to_attotime(4 * ((m_pre[1] >> 2) + 1))); + m_t1_timer->enable(m_pre[1] & Z8_PRE0_COUNT_MODULO_N); + request_interrupt(5); } } @@ -795,21 +881,26 @@ void z8_device::device_start() state_add(Z8_PC, "PC", m_pc).callimport(); state_add(STATE_GENPC, "GENPC", m_pc).callimport().noshow(); state_add(STATE_GENPCBASE, "CURPC", m_ppc).callimport().noshow(); - state_add(Z8_SP, "SP", m_fake_sp).callimport().callexport(); - state_add(STATE_GENSP, "GENSP", m_fake_sp).callimport().callexport().noshow(); - state_add(Z8_RP, "RP", m_r[Z8_REGISTER_RP]); - state_add(STATE_GENFLAGS, "GENFLAGS", m_r[Z8_REGISTER_FLAGS]).noshow().formatstr("%6s"); - state_add(Z8_IMR, "IMR", m_r[Z8_REGISTER_IMR]); - state_add(Z8_IRQ, "IRQ", m_r[Z8_REGISTER_IRQ]); - state_add(Z8_IPR, "IPR", m_r[Z8_REGISTER_IPR]); - state_add(Z8_P01M, "P01M", m_r[Z8_REGISTER_P01M]); - state_add(Z8_P3M, "P3M", m_r[Z8_REGISTER_P3M]); - state_add(Z8_P2M, "P2M", m_r[Z8_REGISTER_P2M]); - state_add(Z8_PRE0, "PRE0", m_r[Z8_REGISTER_PRE0]); - state_add(Z8_T0, "T0", m_t0); - state_add(Z8_PRE1, "PRE1", m_r[Z8_REGISTER_PRE1]); - state_add(Z8_T1, "T1", m_t1); - state_add(Z8_TMR, "TMR", m_r[Z8_REGISTER_TMR]); + state_add(Z8_SP, "SP", m_sp.w); + state_add(STATE_GENSP, "GENSP", m_sp.w).noshow(); + state_add(Z8_RP, "RP", m_rp); + state_add(STATE_GENFLAGS, "GENFLAGS", m_flags).noshow().formatstr("%6s"); + state_add(Z8_IMR, "IMR", m_imr); + state_add(Z8_IRQ, "IRQ", m_irq); + state_add(Z8_IPR, "IPR", m_ipr); + state_add(Z8_P0, "P0", m_output[0]); + if (m_rom_size > 0) + state_add(Z8_P1, "P1", m_output[1]); + state_add(Z8_P2, "P2", m_output[2]); + state_add(Z8_P3, "P3", m_output[3]).mask(0xf0); + state_add(Z8_P01M, "P01M", m_p01m); + state_add(Z8_P2M, "P2M", m_p2m); + state_add(Z8_P3M, "P3M", m_p3m); + state_add(Z8_PRE0, "PRE0", m_pre[0]); + state_add(Z8_T0, "T0", m_t[0]); + state_add(Z8_PRE1, "PRE1", m_pre[1]); + state_add(Z8_T1, "T1", m_t[1]); + state_add(Z8_TMR, "TMR", m_tmr); for (int regnum = 0; regnum < 16; regnum++) state_add(Z8_R0 + regnum, string_format("R%d", regnum).c_str(), m_fake_r[regnum]).callimport().callexport(); @@ -819,34 +910,50 @@ void z8_device::device_start() m_program = &space(AS_PROGRAM); m_cache = m_program->cache<0, 0, ENDIANNESS_BIG>(); m_data = has_space(AS_DATA) ? &space(AS_DATA) : m_program; + m_regs = &space(AS_IO); /* allocate timers */ m_t0_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z8_device::t0_tick), this)); m_t1_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z8_device::t1_tick), this)); /* Clear state */ - for (auto & elem : m_irq_line) - elem = CLEAR_LINE; - for (auto & elem : m_r) - elem = 0; - for ( int i = 0; i < 4; i++ ) - { - m_input[i] = 0; - m_output[i] = 0; - } - for (auto & elem : m_fake_r) - elem = 0; - m_fake_sp = 0; - m_t0 = 0; - m_t1 = 0; + std::fill(std::begin(m_irq_line), std::end(m_irq_line), CLEAR_LINE); + std::fill(std::begin(m_input), std::end(m_input), 0); + std::fill(std::begin(m_output), std::end(m_output), 0); + std::fill(std::begin(m_t), std::end(m_t), 0); + std::fill(std::begin(m_count), std::end(m_count), 0); + std::fill(std::begin(m_pre), std::end(m_pre), 0); + std::fill(std::begin(m_fake_r), std::end(m_fake_r), 0); + m_pc = 0; + m_ppc = 0; + m_sp.w = 0; + m_rp = 0; + m_flags = 0; + m_p01m = 0; + m_p2m = 0; + m_p3m = 0; + m_tmr = 0; + m_irq_taken = false; + m_irq_initialized = false; /* register for state saving */ save_item(NAME(m_pc)); - save_item(NAME(m_r)); + save_item(NAME(m_ppc)); + save_item(NAME(m_sp.w)); + save_item(NAME(m_rp)); + save_item(NAME(m_flags)); save_item(NAME(m_input)); save_item(NAME(m_output)); + save_item(NAME(m_p01m)); + save_item(NAME(m_p2m)); + save_item(NAME(m_p3m)); + save_item(NAME(m_tmr)); + save_item(NAME(m_t)); + save_item(NAME(m_count)); + save_item(NAME(m_pre)); save_item(NAME(m_irq_line)); save_item(NAME(m_irq_taken)); + save_item(NAME(m_irq_initialized)); set_icountptr(m_icount); } @@ -855,16 +962,24 @@ void z8_device::device_start() INTERRUPTS ***************************************************************************/ +void z8_device::request_interrupt(int irq) +{ + assert(irq >= 0 && irq < 6); + + if (m_irq_initialized) + m_irq |= 1 << irq; +} + void z8_device::take_interrupt(int irq) { //logerror("Taking IRQ%d (previous PC = %04X)\n", irq, m_pc); m_irq_taken = true; // disable interrupts - m_r[Z8_REGISTER_IMR] &= ~Z8_IMR_ENABLE; + m_imr &= ~Z8_IMR_ENABLE; // acknowledge the IRQ - m_r[Z8_REGISTER_IRQ] &= ~(1 << irq); + m_irq &= ~(1 << irq); // get the interrupt vector address uint16_t vector = irq * 2; @@ -873,7 +988,7 @@ void z8_device::take_interrupt(int irq) // push registers onto stack stack_push_word(m_pc); - stack_push_byte(m_r[Z8_REGISTER_FLAGS]); + stack_push_byte(m_flags); // branch to the vector m_pc = m_cache->read_byte(vector) << 8; @@ -883,22 +998,22 @@ void z8_device::take_interrupt(int irq) void z8_device::process_interrupts() { m_irq_taken = false; - uint8_t pending_irqs = m_r[Z8_REGISTER_IMR] & m_r[Z8_REGISTER_IRQ] & Z8_IRQ_MASK; - if (!(m_r[Z8_REGISTER_IMR] & Z8_IMR_ENABLE) || pending_irqs == 0) + uint8_t pending_irqs = m_imr & m_irq & Z8_IRQ_MASK; + if (!(m_imr & Z8_IMR_ENABLE) || pending_irqs == 0) return; int group_a[2] = { 5, 3 }; int group_b[2] = { 2, 0 }; int group_c[2] = { 1, 4 }; - if (BIT(m_r[Z8_REGISTER_IPR], 5)) + if (BIT(m_ipr, 5)) std::swap(group_a[0], group_a[1]); - if (BIT(m_r[Z8_REGISTER_IPR], 2)) + if (BIT(m_ipr, 2)) std::swap(group_b[0], group_b[1]); - if (BIT(m_r[Z8_REGISTER_IPR], 1)) + if (BIT(m_ipr, 1)) std::swap(group_c[0], group_c[1]); - switch ((m_r[Z8_REGISTER_IPR] & 0x18) >> 2 | (m_r[Z8_REGISTER_IPR] & 0x01)) + switch ((m_ipr & 0x18) >> 2 | (m_ipr & 0x01)) { case 0: // (000) reserved according to Zilog (but must process at least IRQ4) case 1: // (001) C > A > B @@ -1030,16 +1145,18 @@ void z8_device::execute_run() void z8_device::device_reset() { m_pc = 0x000c; - - register_write(Z8_REGISTER_TMR, 0x00); - register_write(Z8_REGISTER_PRE1, PRE1 & 0xfc); - register_write(Z8_REGISTER_PRE0, PRE0 & 0xfe); - register_write(Z8_REGISTER_P2M, 0xff); - register_write(Z8_REGISTER_P3M, 0x00); - register_write(Z8_REGISTER_P01M, 0x4d); - register_write(Z8_REGISTER_IRQ, 0x00); - register_write(Z8_REGISTER_IMR, 0x00); - register_write(Z8_REGISTER_RP, 0x00); + m_rp = 0x00; + m_irq = 0x00; + m_imr &= ~Z8_IMR_ENABLE; + m_irq_initialized = false; + + p01m_write(0x4d); + p2m_write(0xff); + p3m_write(0x00); + + m_pre[0] &= ~Z8_PRE0_COUNT_MODULO_N; + m_pre[1] &= ~(Z8_PRE1_COUNT_MODULO_N | Z8_PRE1_INTERNAL_CLOCK); + tmr_write(0x00); } @@ -1060,15 +1177,12 @@ void z8_device::state_import(const device_state_entry &entry) m_pc = m_ppc; break; - case Z8_SP: - case STATE_GENSP: - m_r[Z8_REGISTER_SPH] = m_fake_sp >> 8; - m_r[Z8_REGISTER_SPL] = m_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: - m_r[m_r[Z8_REGISTER_RP] + (entry.index() - Z8_R0)] = m_fake_r[entry.index() - Z8_R0]; + { + auto dis = machine().disable_side_effects(); + register_write(m_rp + (entry.index() - Z8_R0), m_fake_r[entry.index() - Z8_R0]); break; + } default: fatalerror("CPU_IMPORT_STATE(z8) called for unexpected value\n"); @@ -1079,14 +1193,12 @@ void z8_device::state_export(const device_state_entry &entry) { switch (entry.index()) { - case Z8_SP: - case STATE_GENSP: - m_fake_sp = (m_r[Z8_REGISTER_SPH] << 8) | m_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: - m_fake_r[entry.index() - Z8_R0] = m_r[m_r[Z8_REGISTER_RP] + (entry.index() - Z8_R0)]; + { + auto dis = machine().disable_side_effects(); + m_fake_r[entry.index() - Z8_R0] = register_read(m_rp + (entry.index() - Z8_R0)); break; + } default: fatalerror("CPU_EXPORT_STATE(z8) called for unexpected value\n"); @@ -1098,12 +1210,12 @@ void z8_device::state_string_export(const device_state_entry &entry, std::string switch (entry.index()) { case STATE_GENFLAGS: str = string_format("%c%c%c%c%c%c", - m_r[Z8_REGISTER_FLAGS] & Z8_FLAGS_C ? 'C' : '.', - m_r[Z8_REGISTER_FLAGS] & Z8_FLAGS_Z ? 'Z' : '.', - m_r[Z8_REGISTER_FLAGS] & Z8_FLAGS_S ? 'S' : '.', - m_r[Z8_REGISTER_FLAGS] & Z8_FLAGS_V ? 'V' : '.', - m_r[Z8_REGISTER_FLAGS] & Z8_FLAGS_D ? 'D' : '.', - m_r[Z8_REGISTER_FLAGS] & Z8_FLAGS_H ? 'H' : '.'); break; + m_flags & Z8_FLAGS_C ? 'C' : '.', + m_flags & Z8_FLAGS_Z ? 'Z' : '.', + m_flags & Z8_FLAGS_S ? 'S' : '.', + m_flags & Z8_FLAGS_V ? 'V' : '.', + m_flags & Z8_FLAGS_D ? 'D' : '.', + m_flags & Z8_FLAGS_H ? 'H' : '.'); break; } } @@ -1114,25 +1226,25 @@ void z8_device::execute_set_input(int inputnum, int state) { case INPUT_LINE_IRQ0: if (state != CLEAR_LINE && m_irq_line[0] == CLEAR_LINE) - m_r[Z8_REGISTER_IRQ] |= Z8_IRQ_FLAG_IRQ0; + request_interrupt(0); m_irq_line[0] = state; break; case INPUT_LINE_IRQ1: if (state != CLEAR_LINE && m_irq_line[1] == CLEAR_LINE) - m_r[Z8_REGISTER_IRQ] |= Z8_IRQ_FLAG_IRQ1; + request_interrupt(1); m_irq_line[1] = state; break; case INPUT_LINE_IRQ2: if (state != CLEAR_LINE && m_irq_line[2] == CLEAR_LINE) - m_r[Z8_REGISTER_IRQ] |= Z8_IRQ_FLAG_IRQ2; + request_interrupt(2); m_irq_line[2] = state; break; case INPUT_LINE_IRQ3: if (state != CLEAR_LINE && m_irq_line[3] == CLEAR_LINE) - m_r[Z8_REGISTER_IRQ] |= Z8_IRQ_FLAG_IRQ3; + request_interrupt(3); m_irq_line[3] = state; break; |