summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/cop400/cop400.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/cop400/cop400.c')
-rw-r--r--src/emu/cpu/cop400/cop400.c186
1 files changed, 77 insertions, 109 deletions
diff --git a/src/emu/cpu/cop400/cop400.c b/src/emu/cpu/cop400/cop400.c
index 26fbd8e21ef..2f3b0ba15f1 100644
--- a/src/emu/cpu/cop400/cop400.c
+++ b/src/emu/cpu/cop400/cop400.c
@@ -51,7 +51,6 @@
TODO:
- - remove LBIOps
- remove InstLen
- run interrupt test suite
- run production test suite
@@ -104,20 +103,18 @@ const device_type COP445 = &device_creator<cop445_cpu_device>;
#define ROM(a) m_direct->read_decrypted_byte(a)
#define RAM_R(a) m_data->read_byte(a)
#define RAM_W(a, v) m_data->write_byte(a, v)
-#define IN(a) m_io->read_byte(a)
-#define OUT(a, v) m_io->write_byte(a, v)
-#define IN_G() (IN(COP400_PORT_G) & m_g_mask)
-#define IN_L() IN(COP400_PORT_L)
-#define IN_SI() BIT(IN(COP400_PORT_SIO), 0)
-#define IN_CKO() BIT(IN(COP400_PORT_CKO), 0)
-#define IN_IN() (m_in_mask ? IN(COP400_PORT_IN) : 0)
+#define IN_G() (m_read_g(0, 0xff) & m_g_mask)
+#define IN_L() m_read_l(0, 0xff)
+#define IN_SI() BIT(m_read_si(), 0)
+#define IN_CKO() BIT(m_read_cko(), 0)
+#define IN_IN() (m_in_mask ? m_read_in(0, 0xff) : 0)
-#define OUT_G(v) OUT(COP400_PORT_G, (v) & m_g_mask)
-#define OUT_L(v) OUT(COP400_PORT_L, (v))
-#define OUT_D(v) OUT(COP400_PORT_D, (v) & m_d_mask)
-#define OUT_SK(v) OUT(COP400_PORT_SK, (v))
-#define OUT_SO(v) OUT(COP400_PORT_SIO, (v))
+#define OUT_G(v) m_write_g(0, (v) & m_g_mask, 0xff)
+#define OUT_L(v) m_write_l(0, v, 0xff)
+#define OUT_D(v) m_write_d(0, (v) & m_d_mask, 0xff)
+#define OUT_SK(v) m_write_sk(v)
+#define OUT_SO(v) m_write_so(v)
#define PC m_pc
#define A m_a
@@ -176,7 +173,16 @@ cop400_cpu_device::cop400_cpu_device(const machine_config &mconfig, device_type
: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
, m_program_config("program", ENDIANNESS_LITTLE, 8, program_addr_bits, 0, internal_map_program)
, m_data_config("data", ENDIANNESS_LITTLE, 8, data_addr_bits, 0, internal_map_data) // data width is really 4
- , m_io_config("io", ENDIANNESS_LITTLE, 8, 9, 0)
+ , m_read_l(*this)
+ , m_write_l(*this)
+ , m_read_g(*this)
+ , m_write_g(*this)
+ , m_write_d(*this)
+ , m_read_in(*this)
+ , m_read_si(*this)
+ , m_write_so(*this)
+ , m_write_sk(*this)
+ , m_read_cko(*this)
, m_cki(COP400_CKI_DIVISOR_16)
, m_cko(COP400_CKO_OSCILLATOR_OUTPUT)
, m_microbus(COP400_MICROBUS_DISABLED)
@@ -191,9 +197,6 @@ cop400_cpu_device::cop400_cpu_device(const machine_config &mconfig, device_type
/* initialize instruction length array */
for (i=0; i<256; i++) m_InstLen[i]=1;
- /* initialize LBI opcode array */
- for (i=0x00; i<0x100; i++) m_LBIops[i] = 0;
- for (i=0; i<256; i++) m_LBIops33[i] = 0;
switch (featuremask)
{
@@ -203,11 +206,6 @@ cop400_cpu_device::cop400_cpu_device(const machine_config &mconfig, device_type
/* initialize instruction length array */
m_InstLen[0x60] = m_InstLen[0x61] = m_InstLen[0x68] =
m_InstLen[0x69] = m_InstLen[0x33] = m_InstLen[0x23] = 2;
- /* initialize LBI opcode array */
- for (i=0x08; i<0x10; i++) m_LBIops[i] = 1;
- for (i=0x18; i<0x20; i++) m_LBIops[i] = 1;
- for (i=0x28; i<0x30; i++) m_LBIops[i] = 1;
- for (i=0x38; i<0x40; i++) m_LBIops[i] = 1;
break;
case COP420_FEATURE:
@@ -217,12 +215,6 @@ cop400_cpu_device::cop400_cpu_device(const machine_config &mconfig, device_type
m_InstLen[0x60] = m_InstLen[0x61] = m_InstLen[0x62] = m_InstLen[0x63] =
m_InstLen[0x68] = m_InstLen[0x69] = m_InstLen[0x6a] = m_InstLen[0x6b] =
m_InstLen[0x33] = m_InstLen[0x23] = 2;
- /* initialize LBI opcode array */
- for (i=0x08; i<0x10; i++) m_LBIops[i] = 1;
- for (i=0x18; i<0x20; i++) m_LBIops[i] = 1;
- for (i=0x28; i<0x30; i++) m_LBIops[i] = 1;
- for (i=0x38; i<0x40; i++) m_LBIops[i] = 1;
- for (i=0x80; i<0xc0; i++) m_LBIops33[i] = 1;
break;
case COP444_FEATURE:
@@ -232,13 +224,6 @@ cop400_cpu_device::cop400_cpu_device(const machine_config &mconfig, device_type
m_InstLen[0x60] = m_InstLen[0x61] = m_InstLen[0x62] = m_InstLen[0x63] =
m_InstLen[0x68] = m_InstLen[0x69] = m_InstLen[0x6a] = m_InstLen[0x6b] =
m_InstLen[0x33] = m_InstLen[0x23] = 2;
- /* initialize LBI opcode array */
- for (i=0x00; i<0x100; i++) m_LBIops[i] = 0;
- for (i=0x08; i<0x10; i++) m_LBIops[i] = 1;
- for (i=0x18; i<0x20; i++) m_LBIops[i] = 1;
- for (i=0x28; i<0x30; i++) m_LBIops[i] = 1;
- for (i=0x38; i<0x40; i++) m_LBIops[i] = 1;
- for (i=0x80; i<0xc0; i++) m_LBIops33[i] = 1;
break;
default:
@@ -952,12 +937,24 @@ void cop400_cpu_device::device_start()
m_program = &space(AS_PROGRAM);
m_direct = &m_program->direct();
m_data = &space(AS_DATA);
- m_io = &space(AS_IO);
+
+ /* find i/o handlers */
+
+ m_read_l.resolve_safe(0);
+ m_write_l.resolve_safe();
+ m_read_g.resolve_safe(0);
+ m_write_g.resolve_safe();
+ m_write_d.resolve_safe();
+ m_read_in.resolve_safe(0);
+ m_read_si.resolve_safe(0);
+ m_write_so.resolve_safe();
+ m_write_sk.resolve_safe();
+ m_read_cko.resolve_safe(0);
/* allocate serial timer */
m_serial_timer = timer_alloc(TIMER_SERIAL);
- m_serial_timer->adjust(attotime::zero, 0, attotime::from_hz(clock() / 16));
+ m_serial_timer->adjust(attotime::zero, 0, attotime::from_ticks(16, clock()));
/* allocate counter timer */
@@ -965,7 +962,7 @@ void cop400_cpu_device::device_start()
if (m_has_counter)
{
m_counter_timer = timer_alloc(TIMER_COUNTER);
- m_counter_timer->adjust(attotime::zero, 0, attotime::from_hz(clock() / 16 / 4));
+ m_counter_timer->adjust(attotime::zero, 0, attotime::from_ticks(16 * 4, clock()));
}
/* allocate IN latch timer */
@@ -974,7 +971,7 @@ void cop400_cpu_device::device_start()
if (m_has_inil)
{
m_inil_timer = timer_alloc(TIMER_INIL);
- m_inil_timer->adjust(attotime::zero, 0, attotime::from_hz(clock() / 16));
+ m_inil_timer->adjust(attotime::zero, 0, attotime::from_ticks(16, clock()));
}
/* allocate Microbus timer */
@@ -983,7 +980,7 @@ void cop400_cpu_device::device_start()
if (m_microbus == COP400_MICROBUS_ENABLED)
{
m_microbus_timer = timer_alloc(TIMER_MICROBUS);
- m_microbus_timer->adjust(attotime::zero, 0, attotime::from_hz(clock() / 16));
+ m_microbus_timer->adjust(attotime::zero, 0, attotime::from_ticks(16, clock()));
}
/* register for state saving */
@@ -1006,7 +1003,6 @@ void cop400_cpu_device::device_start()
save_item(NAME(m_skl));
save_item(NAME(m_t));
save_item(NAME(m_skip));
- save_item(NAME(m_skip_lbi));
save_item(NAME(m_skt_latch));
save_item(NAME(m_si));
save_item(NAME(m_last_skip));
@@ -1074,7 +1070,6 @@ void cop400_cpu_device::device_start()
m_il = 0;
m_in[0] = m_in[1] = m_in[2] = m_in[3] = 0;
m_si = 0;
- m_skip_lbi = 0;
m_last_skip = 0;
m_microbus_int = 0;
m_skip = 0;
@@ -1099,6 +1094,7 @@ void cop400_cpu_device::device_reset()
T = 0;
m_skt_latch = 1;
+ m_last_opcode_function = INST(nop);
m_halt = 0;
m_idle = 0;
}
@@ -1109,8 +1105,6 @@ void cop400_cpu_device::device_reset()
void cop400_cpu_device::execute_run()
{
- UINT8 opcode;
-
do
{
m_prevpc = PC;
@@ -1128,87 +1122,61 @@ void cop400_cpu_device::execute_run()
continue;
}
- opcode = ROM(PC);
- if (m_skip_lbi)
- {
- int is_lbi = 0;
+ UINT8 opcode = ROM(PC);
+ int inst_cycles = m_opcode_map[opcode].cycles;
- if (opcode == 0x33)
- {
- is_lbi = m_LBIops33[ROM(PC+1)];
- }
- else
- {
- is_lbi = m_LBIops[opcode];
- }
+ PC++;
- if (is_lbi)
- {
- m_icount -= m_opcode_map[opcode].cycles;
+ (this->*(m_opcode_map[opcode].function))(opcode);
+ m_last_opcode_function = m_opcode_map[opcode].function;
+ m_icount -= inst_cycles;
- PC += m_InstLen[opcode];
- }
- else
- {
- m_skip_lbi = 0;
- }
- }
+ // check for interrupt
- if (!m_skip_lbi)
+ if (BIT(EN, 1) && BIT(IL, 1))
{
- int inst_cycles = m_opcode_map[opcode].cycles;
+ cop400_opcode_func function = m_opcode_map[ROM(PC)].function;
- PC++;
+ // all successive transfer of control instructions and successive LBIs have been completed
+ if ((function != INST(jp)) && (function != INST(jmp)) && (function != INST(jsr)) && !(m_last_opcode_function == INST(lbi) && function == INST(lbi)))
+ {
+ // store skip logic
+ m_last_skip = m_skip;
+ m_skip = 0;
- (this->*(m_opcode_map[opcode].function))(opcode);
- m_icount -= inst_cycles;
+ // push next PC
+ PUSH(PC);
- // check for interrupt
+ // jump to interrupt service routine
+ PC = 0x0ff;
- if (BIT(EN, 1) && BIT(IL, 1))
- {
- cop400_opcode_func function = m_opcode_map[ROM(PC)].function;
+ // disable interrupt
+ EN &= ~0x02;
+ }
- if ((function != INST(jp)) && (function != INST(jmp)) && (function != INST(jsr)))
- {
- // store skip logic
- m_last_skip = m_skip;
- m_skip = 0;
+ IL &= ~2;
+ }
- // push next PC
- PUSH(PC);
+ // skip next instruction?
- // jump to interrupt service routine
- PC = 0x0ff;
+ if (m_skip)
+ {
+ cop400_opcode_func function = m_opcode_map[ROM(PC)].function;
- // disable interrupt
- EN &= ~0x02;
- }
+ opcode = ROM(PC);
- IL &= ~2;
+ if ((function == INST(lqid)) || (function == INST(jid)))
+ {
+ m_icount -= 1;
}
-
- // skip next instruction?
-
- if (m_skip)
+ else
{
- cop400_opcode_func function = m_opcode_map[ROM(PC)].function;
-
- opcode = ROM(PC);
-
- if ((function == INST(lqid)) || (function == INST(jid)))
- {
- m_icount -= 1;
- }
- else
- {
- m_icount -= m_opcode_map[opcode].cycles;
- }
+ m_icount -= m_opcode_map[opcode].cycles;
+ }
- PC += m_InstLen[opcode];
+ PC += m_InstLen[opcode];
- m_skip = 0;
- }
+ m_skip = 0;
}
} while (m_icount > 0);
}
@@ -1239,12 +1207,12 @@ void cop400_cpu_device::state_export(const device_state_entry &entry)
}
}
-void cop400_cpu_device::state_string_export(const device_state_entry &entry, astring &str)
+void cop400_cpu_device::state_string_export(const device_state_entry &entry, std::string &str)
{
switch (entry.index())
{
case STATE_GENFLAGS:
- str.printf("%c%c%c",
+ strprintf(str, "%c%c%c",
m_c ? 'C' : '.',
m_skl ? 'S' : '.',
m_skt_latch ? 'T' : '.');