diff options
Diffstat (limited to 'src/devices/cpu/z8/z8.cpp')
-rw-r--r-- | src/devices/cpu/z8/z8.cpp | 153 |
1 files changed, 103 insertions, 50 deletions
diff --git a/src/devices/cpu/z8/z8.cpp b/src/devices/cpu/z8/z8.cpp index cef5a96e0ab..cbabf70eab2 100644 --- a/src/devices/cpu/z8/z8.cpp +++ b/src/devices/cpu/z8/z8.cpp @@ -91,7 +91,7 @@ enum #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_P0L_MODE_A8_A11 0x02 #define Z8_P01M_INTERNAL_STACK 0x04 #define Z8_P01M_P1_MODE_MASK 0x18 #define Z8_P01M_P1_MODE_OUTPUT 0x00 @@ -102,7 +102,7 @@ enum #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_P01M_P0H_MODE_A12_A15 0x80 #define Z8_P3M_P2_ACTIVE_PULLUPS 0x01 /* not supported */ #define Z8_P3M_P0_STROBED 0x04 /* not supported */ @@ -214,19 +214,63 @@ offs_t z8_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint device_memory_interface::space_config_vector z8_device::memory_space_config() const { - return space_config_vector { - std::make_pair(AS_PROGRAM, &m_program_config), - std::make_pair(AS_DATA, &m_data_config) - }; + // Separate data space is optional + if (has_configured_map(AS_DATA)) + { + return space_config_vector { + std::make_pair(AS_PROGRAM, &m_program_config), + std::make_pair(AS_DATA, &m_data_config) + }; + } + else + { + return space_config_vector { + std::make_pair(AS_PROGRAM, &m_program_config) + }; + } } /*************************************************************************** INLINE FUNCTIONS ***************************************************************************/ +uint16_t z8_device::mask_external_address(uint16_t addr) +{ + switch (P01M & (Z8_P01M_P0L_MODE_A8_A11 | Z8_P01M_P0H_MODE_A12_A15)) + { + case 0: + addr = (addr & 0x00ff) | register_read(Z8_REGISTER_P0) << 8; + break; + + case Z8_P01M_P0L_MODE_A8_A11: + addr = (addr & 0x0fff) | (register_read(Z8_REGISTER_P0) & 0xf0) << 8; + break; + + case Z8_P01M_P0H_MODE_A12_A15: + addr = (addr & 0xf0ff) | (register_read(Z8_REGISTER_P0) & 0x0f) << 8; + break; + } + return addr; +} + + uint8_t z8_device::fetch() { - uint8_t data = m_direct->read_byte(m_pc); + uint16_t real_pc = (m_pc < m_rom_size) ? m_pc : mask_external_address(m_pc); + uint8_t data = m_direct->read_byte(real_pc); + + m_pc++; + + return data; +} + + +uint8_t z8_device::fetch_opcode() +{ + m_ppc = (m_pc < m_rom_size) ? m_pc : mask_external_address(m_pc); + debugger_instruction_hook(this, m_ppc); + + uint8_t data = m_direct->read_byte(m_ppc); m_pc++; @@ -234,6 +278,16 @@ uint8_t z8_device::fetch() } +uint16_t z8_device::fetch_word() +{ + // ensure correct order of operations by using separate instructions + uint16_t data = fetch() << 8; + data |= fetch(); + + return data; +} + + uint8_t z8_device::register_read(uint8_t offset) { uint8_t data = 0xff; @@ -447,21 +501,21 @@ void z8_device::stack_push_byte(uint8_t src) { if (register_read(Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK) { - /* SP <- SP - 1 */ + // SP <- SP - 1 (predecrement) uint8_t sp = register_read(Z8_REGISTER_SPL) - 1; register_write(Z8_REGISTER_SPL, sp); - /* @SP <- src */ + // @SP <- src register_write(sp, src); } else { - /* SP <- SP - 1 */ + // SP <- SP - 1 (predecrement) uint16_t sp = register_pair_read(Z8_REGISTER_SPH) - 1; register_pair_write(Z8_REGISTER_SPH, sp); - /* @SP <- src */ - m_data->write_byte(sp, src); + // @SP <- src + m_data->write_byte(mask_external_address(sp), src); } } @@ -469,21 +523,21 @@ void z8_device::stack_push_word(uint16_t src) { if (register_read(Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK) { - /* SP <- SP - 2 */ + // SP <- SP - 2 (predecrement) uint8_t sp = register_read(Z8_REGISTER_SPL) - 2; register_write(Z8_REGISTER_SPL, sp); - /* @SP <- src */ + // @SP <- src register_pair_write(sp, src); } else { - /* SP <- SP - 2 */ + // SP <- SP - 2 (predecrement) uint16_t sp = register_pair_read(Z8_REGISTER_SPH) - 2; register_pair_write(Z8_REGISTER_SPH, sp); - /* @SP <- src */ - m_data->write_word(sp, src); + // @SP <- src + m_data->write_word(mask_external_address(sp), src); } } @@ -491,21 +545,25 @@ uint8_t z8_device::stack_pop_byte() { if (register_read(Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK) { - /* SP <- SP + 1 */ - uint8_t sp = register_read(Z8_REGISTER_SPL) + 1; - register_write(Z8_REGISTER_SPL, sp); + // @SP <- src + uint8_t sp = register_read(Z8_REGISTER_SPL); + uint8_t byte = register_read(sp); - /* @SP <- src */ - return register_read(sp); + // SP <- SP + 1 (postincrement) + register_write(Z8_REGISTER_SPL, sp + 1); + + return byte; } else { - /* SP <- SP + 1 */ - uint16_t sp = register_pair_read(Z8_REGISTER_SPH) + 1; - register_pair_write(Z8_REGISTER_SPH, sp); + // @SP <- src + uint16_t sp = register_pair_read(Z8_REGISTER_SPH); + uint8_t byte = m_data->read_byte(mask_external_address(sp)); + + // SP <- SP + 1 (postincrement) + register_pair_write(Z8_REGISTER_SPH, sp + 1); - /* @SP <- src */ - return m_data->read_byte(sp); + return byte; } } @@ -513,21 +571,25 @@ uint16_t z8_device::stack_pop_word() { if (register_read(Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK) { - /* SP <- SP + 2 */ - uint8_t sp = register_read(Z8_REGISTER_SPL) + 2; - register_write(Z8_REGISTER_SPL, sp); + // @SP <- src + uint8_t sp = register_read(Z8_REGISTER_SPL); + uint16_t word = register_pair_read(sp); + + // SP <- SP + 2 (postincrement) + register_write(Z8_REGISTER_SPL, sp + 2); - /* @SP <- src */ - return register_read(sp); + return word; } else { - /* SP <- SP + 2 */ - uint16_t sp = register_pair_read(Z8_REGISTER_SPH) + 2; - register_pair_write(Z8_REGISTER_SPH, sp); + // @SP <- src + uint16_t sp = register_pair_read(Z8_REGISTER_SPH); + uint16_t word = m_data->read_word(mask_external_address(sp)); + + // SP <- SP + 2 (postincrement) + register_pair_write(Z8_REGISTER_SPH, sp + 2); - /* @SP <- src */ - return m_data->read_word(sp); + return word; } } @@ -691,7 +753,7 @@ void z8_device::device_start() { state_add(Z8_PC, "PC", m_pc); state_add(STATE_GENPC, "GENPC", m_pc).noshow(); - state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow(); + state_add(STATE_GENPCBASE, "CURPC", m_ppc).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]); @@ -715,7 +777,7 @@ void z8_device::device_start() /* find address spaces */ m_program = &space(AS_PROGRAM); m_direct = &m_program->direct(); - m_data = &space(AS_DATA); + m_data = has_space(AS_DATA) ? &space(AS_DATA) : m_program; /* allocate timers */ m_t0_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z8_device::t0_tick), this)); @@ -755,17 +817,12 @@ void z8_device::execute_run() { do { - uint8_t opcode; - int cycles; - - debugger_instruction_hook(this, m_pc); - /* TODO: sample interrupts */ m_input[3] = m_input_cb[3](); /* fetch opcode */ - opcode = fetch(); - cycles = Z8601_OPCODE_MAP[opcode].execution_cycles; + uint8_t opcode = fetch_opcode(); + int cycles = Z8601_OPCODE_MAP[opcode].execution_cycles; /* execute instruction */ (this->*(Z8601_OPCODE_MAP[opcode].function))(opcode, &cycles); @@ -783,10 +840,6 @@ void z8_device::device_reset() { m_pc = 0x000c; - // crude hack for Z8681 - if (m_rom_size == 0) - m_pc |= m_input_cb[0]() << 8; - register_write(Z8_REGISTER_TMR, 0x00); register_write(Z8_REGISTER_PRE1, PRE1 & 0xfc); register_write(Z8_REGISTER_PRE0, PRE0 & 0xfe); |