summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2017-09-03 15:33:46 -0400
committer AJR <ajrhacker@users.noreply.github.com>2017-09-03 15:33:46 -0400
commit7d7c8a1d624c170c1a2883a8682466ba7d818c1a (patch)
tree89b038142bd413d1cd8d86bd4c29426cb6a62081
parent051a55b274cbc7961905aebe25aaf6e16dd78210 (diff)
z8: Mask addresses for external memory accesses based on P0 control bits
-rw-r--r--src/devices/cpu/z8/z8.cpp65
-rw-r--r--src/devices/cpu/z8/z8.h12
-rw-r--r--src/devices/cpu/z8/z8ops.hxx51
3 files changed, 90 insertions, 38 deletions
diff --git a/src/devices/cpu/z8/z8.cpp b/src/devices/cpu/z8/z8.cpp
index 0926923de2c..4a632ecad8a 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 */
@@ -234,9 +234,30 @@ device_memory_interface::space_config_vector z8_device::memory_space_config() co
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++;
@@ -244,6 +265,29 @@ uint8_t z8_device::fetch()
}
+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++;
+
+ return data;
+}
+
+
+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;
@@ -709,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]);
@@ -773,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);
@@ -801,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);
diff --git a/src/devices/cpu/z8/z8.h b/src/devices/cpu/z8/z8.h
index e28378a4697..bc2698e5607 100644
--- a/src/devices/cpu/z8/z8.h
+++ b/src/devices/cpu/z8/z8.h
@@ -114,6 +114,7 @@ private:
/* registers */
uint16_t m_pc; /* program counter */
+ uint16_t m_ppc; /* program counter at last opcode fetch */
uint8_t m_r[256]; /* register file */
uint8_t m_input[4]; /* port input latches */
uint8_t m_output[4]; /* port output latches */
@@ -137,7 +138,10 @@ private:
TIMER_CALLBACK_MEMBER( t0_tick );
TIMER_CALLBACK_MEMBER( t1_tick );
+ inline uint16_t mask_external_address(uint16_t addr);
inline uint8_t fetch();
+ inline uint8_t fetch_opcode();
+ inline uint16_t fetch_word();
inline uint8_t register_read(uint8_t offset);
inline uint16_t register_pair_read(uint8_t offset);
inline void register_write(uint8_t offset, uint8_t data);
@@ -152,10 +156,10 @@ private:
inline void set_flag(uint8_t flag, int state);
inline void clear(uint8_t dst);
inline void load(uint8_t dst, uint8_t src);
- inline void load_from_memory(address_space *space);
- inline void load_to_memory(address_space *space);
- inline void load_from_memory_autoinc(address_space *space);
- inline void load_to_memory_autoinc(address_space *space);
+ inline void load_from_memory(address_space &space);
+ inline void load_to_memory(address_space &space);
+ inline void load_from_memory_autoinc(address_space &space);
+ inline void load_to_memory_autoinc(address_space &space);
inline void pop(uint8_t dst);
inline void push(uint8_t src);
inline void add_carry(uint8_t dst, int8_t src);
diff --git a/src/devices/cpu/z8/z8ops.hxx b/src/devices/cpu/z8/z8ops.hxx
index 48d0b226859..470df009749 100644
--- a/src/devices/cpu/z8/z8ops.hxx
+++ b/src/devices/cpu/z8/z8ops.hxx
@@ -139,31 +139,38 @@ INSTRUCTION( ld_IR2_R1 ) { mode_IR2_R1(load) }
INSTRUCTION( ld_R1_IM ) { mode_R1_IM(load) }
INSTRUCTION( ld_IR1_IM ) { mode_IR1_IM(load) }
-void z8_device::load_from_memory(address_space *space)
+void z8_device::load_from_memory(address_space &space)
{
uint8_t operands = fetch();
uint8_t dst = get_working_register(operands >> 4);
uint8_t src = get_working_register(operands & 0x0f);
uint16_t address = register_pair_read(src);
- uint8_t data = m_direct->read_byte(address);
+
+ uint8_t data;
+ if (&space == m_program && address < m_rom_size)
+ data = m_direct->read_byte(address);
+ else
+ data = space.read_byte(mask_external_address(address));
register_write(dst, data);
}
-void z8_device::load_to_memory(address_space *space)
+void z8_device::load_to_memory(address_space &space)
{
uint8_t operands = fetch();
uint8_t src = get_working_register(operands >> 4);
uint8_t dst = get_working_register(operands & 0x0f);
uint16_t address = register_pair_read(dst);
- uint8_t data = register_read(src);
+ if (&space != m_program || address >= m_rom_size)
+ address = mask_external_address(address);
- m_program->write_byte(address, data);
+ uint8_t data = register_read(src);
+ space.write_byte(address, data);
}
-void z8_device::load_from_memory_autoinc(address_space *space)
+void z8_device::load_from_memory_autoinc(address_space &space)
{
uint8_t operands = fetch();
uint8_t dst = get_working_register(operands >> 4);
@@ -171,15 +178,19 @@ void z8_device::load_from_memory_autoinc(address_space *space)
uint8_t src = get_working_register(operands & 0x0f);
uint16_t address = register_pair_read(src);
- uint8_t data = m_direct->read_byte(address);
+ uint8_t data;
+ if (&space == m_program && address < m_rom_size)
+ data = m_direct->read_byte(address);
+ else
+ data = space.read_byte(mask_external_address(address));
register_write(real_dst, data);
register_write(dst, real_dst + 1);
register_pair_write(src, address + 1);
}
-void z8_device::load_to_memory_autoinc(address_space *space)
+void z8_device::load_to_memory_autoinc(address_space &space)
{
uint8_t operands = fetch();
uint8_t src = get_working_register(operands >> 4);
@@ -189,20 +200,22 @@ void z8_device::load_to_memory_autoinc(address_space *space)
uint16_t address = register_pair_read(dst);
uint8_t data = register_read(real_src);
- m_program->write_byte(address, data);
+ if (&space != m_program || address >= m_rom_size)
+ address = mask_external_address(address);
+ space.write_byte(address, data);
register_pair_write(dst, address + 1);
register_write(src, real_src + 1);
}
-INSTRUCTION( ldc_r1_Irr2 ) { load_from_memory(m_program); }
-INSTRUCTION( ldc_r2_Irr1 ) { load_to_memory(m_program); }
-INSTRUCTION( ldci_Ir1_Irr2 ) { load_from_memory_autoinc(m_program); }
-INSTRUCTION( ldci_Ir2_Irr1 ) { load_to_memory_autoinc(m_program); }
-INSTRUCTION( lde_r1_Irr2 ) { load_from_memory(m_data); }
-INSTRUCTION( lde_r2_Irr1 ) { load_to_memory(m_data); }
-INSTRUCTION( ldei_Ir1_Irr2 ) { load_from_memory_autoinc(m_data); }
-INSTRUCTION( ldei_Ir2_Irr1 ) { load_to_memory_autoinc(m_data); }
+INSTRUCTION( ldc_r1_Irr2 ) { load_from_memory(*m_program); }
+INSTRUCTION( ldc_r2_Irr1 ) { load_to_memory(*m_program); }
+INSTRUCTION( ldci_Ir1_Irr2 ) { load_from_memory_autoinc(*m_program); }
+INSTRUCTION( ldci_Ir2_Irr1 ) { load_to_memory_autoinc(*m_program); }
+INSTRUCTION( lde_r1_Irr2 ) { load_from_memory(*m_data); }
+INSTRUCTION( lde_r2_Irr1 ) { load_to_memory(*m_data); }
+INSTRUCTION( ldei_Ir1_Irr2 ) { load_from_memory_autoinc(*m_data); }
+INSTRUCTION( ldei_Ir2_Irr1 ) { load_to_memory_autoinc(*m_data); }
void z8_device::pop(uint8_t dst)
{
@@ -490,7 +503,7 @@ void z8_device::call(uint16_t dst)
}
INSTRUCTION( call_IRR1 ) { uint16_t dst = register_pair_read(get_intermediate_register(get_register(fetch()))); call(dst); }
-INSTRUCTION( call_DA ) { uint16_t dst = (fetch() << 8) | fetch(); call(dst); }
+INSTRUCTION( call_DA ) { uint16_t dst = fetch_word(); call(dst); }
INSTRUCTION( djnz_r1_RA )
{
@@ -567,7 +580,7 @@ int z8_device::check_condition_code(int cc)
INSTRUCTION( jp_cc_DA )
{
- uint16_t dst = (fetch() << 8) | fetch();
+ uint16_t dst = fetch_word();
/* if cc is true, then PC <- dst */
if (check_condition_code(opcode >> 4))