diff options
Diffstat (limited to 'src/emu/cpu/cop400/cop400.c')
-rw-r--r-- | src/emu/cpu/cop400/cop400.c | 186 |
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' : '.'); |