summaryrefslogtreecommitdiffstats
path: root/src/devices/cpu/z8/z8.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/z8/z8.cpp')
-rw-r--r--src/devices/cpu/z8/z8.cpp153
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);