diff options
Diffstat (limited to 'src/devices/cpu/tms1000/tms1k_base.cpp')
-rw-r--r-- | src/devices/cpu/tms1000/tms1k_base.cpp | 358 |
1 files changed, 179 insertions, 179 deletions
diff --git a/src/devices/cpu/tms1000/tms1k_base.cpp b/src/devices/cpu/tms1000/tms1k_base.cpp index 3f14dba6c5e..f885532d813 100644 --- a/src/devices/cpu/tms1000/tms1k_base.cpp +++ b/src/devices/cpu/tms1000/tms1k_base.cpp @@ -4,13 +4,6 @@ TMS1000 family - base/shared - TODO: - - accurate INIT pin (currently, just use INPUT_LINE_RESET) - - emulate newer die revisions? TMS1xxx rev. E and up have 4 cycles - per opcode instead of 6. But which steps go where, is unknown. - For now, just overclock the MCU instead. - - The TMS0980 and TMS1000-family MCU cores are very similar. The TMS0980 has a slightly bigger addressable area and uses 9bit instructions where the TMS1000 family uses 8bit instruction. The instruction set themselves are very similar @@ -70,33 +63,42 @@ unknown cycle: CME, SSE, SSS #include "emu.h" #include "tms1k_base.h" -#include "debugger.h" - -tms1k_base_device::tms1k_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 o_pins, u8 r_pins, u8 pc_bits, u8 byte_bits, u8 x_bits, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data) - : cpu_device(mconfig, type, tag, owner, clock) - , m_program_config("program", ENDIANNESS_BIG, byte_bits > 8 ? 16 : 8, prgwidth, byte_bits > 8 ? -1 : 0, program) - , m_data_config("data", ENDIANNESS_BIG, 8, datawidth, 0, data) - , m_mpla(*this, "mpla") - , m_ipla(*this, "ipla") - , m_opla(*this, "opla") - , m_spla(*this, "spla") - , m_o_pins(o_pins) - , m_r_pins(r_pins) - , m_pc_bits(pc_bits) - , m_byte_bits(byte_bits) - , m_x_bits(x_bits) - , m_output_pla_table(nullptr) - , m_read_k(*this) - , m_write_o(*this) - , m_write_r(*this) - , m_power_off(*this) - , m_read_ctl(*this) - , m_write_ctl(*this) - , m_write_pdc(*this) -{ -} - -// disasm + +tms1k_base_device::tms1k_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 o_pins, u8 r_pins, u8 pc_bits, u8 byte_bits, u8 x_bits, u8 stack_levels, int rom_width, address_map_constructor rom_map, int ram_width, address_map_constructor ram_map) : + cpu_device(mconfig, type, tag, owner, clock), + m_program_config("program", ENDIANNESS_BIG, byte_bits > 8 ? 16 : 8, rom_width, byte_bits > 8 ? -1 : 0, rom_map), + m_data_config("data", ENDIANNESS_BIG, 8, ram_width, 0, ram_map), + m_mpla(*this, "mpla"), + m_ipla(*this, "ipla"), + m_opla(*this, "opla"), + m_opla_b(*this, "opla_b"), + m_spla(*this, "spla"), + m_o_pins(o_pins), + m_r_pins(r_pins), + m_pc_bits(pc_bits), + m_byte_bits(byte_bits), + m_x_bits(x_bits), + m_stack_levels(stack_levels), + m_option_dec_div(0), + m_read_k(*this, 0), + m_write_o(*this), + m_write_r(*this), + m_read_j(*this, 0), + m_read_r(*this, 0), + m_power_off(*this), + m_read_ctl(*this, 0), + m_write_ctl(*this), + m_write_pdc(*this), + m_output_pla_table(nullptr), + m_decode_micro(*this, 0) +{ } + + + +//------------------------------------------------- +// disasm +//------------------------------------------------- + void tms1k_base_device::state_string_export(const device_state_entry &entry, std::string &str) const { switch (entry.index()) @@ -105,20 +107,27 @@ void tms1k_base_device::state_string_export(const device_state_entry &entry, std case STATE_GENPCBASE: str = string_format("%03X", m_rom_address << ((m_byte_bits > 8) ? 1 : 0)); break; + + case STATE_GENFLAGS: + // not a single flags register, first 3 are TMS0980-family + str = string_format("%c%c%c %c%c%c", + m_bl ? 'B':'b', + m_add ? 'A':'a', + m_eac ? 'E':'e', + (m_clatch & 1) ? 'C':'c', + m_status ? 'S':'s', + m_status_latch ? 'L':'l' + ); + break; } } + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- -enum -{ - TMS1XXX_PC=1, TMS1XXX_SR, TMS1XXX_PA, TMS1XXX_PB, - TMS1XXX_A, TMS1XXX_X, TMS1XXX_Y, TMS1XXX_STATUS -}; - void tms1k_base_device::device_start() { m_program = &space(AS_PROGRAM); @@ -129,14 +138,8 @@ void tms1k_base_device::device_start() m_pc_mask = (1 << m_pc_bits) - 1; m_x_mask = (1 << m_x_bits) - 1; - // resolve callbacks - m_read_k.resolve_safe(0); - m_write_o.resolve_safe(); - m_write_r.resolve_safe(); - m_power_off.resolve_safe(); - m_read_ctl.resolve_safe(0); - m_write_ctl.resolve_safe(); - m_write_pdc.resolve_safe(); + if (m_opla_b != nullptr && m_output_pla_table == nullptr) + set_output_pla(&m_opla_b->as_u16()); // zerofill m_pc = 0; @@ -217,28 +220,20 @@ void tms1k_base_device::device_start() save_item(NAME(m_subcycle)); // register state for debugger - state_add(TMS1XXX_PC, "PC", m_pc ).formatstr("%02X"); - state_add(TMS1XXX_SR, "SR", m_sr ).formatstr("%01X"); - state_add(TMS1XXX_PA, "PA", m_pa ).formatstr("%01X"); - state_add(TMS1XXX_PB, "PB", m_pb ).formatstr("%01X"); - state_add(TMS1XXX_A, "A", m_a ).formatstr("%01X"); - state_add(TMS1XXX_X, "X", m_x ).formatstr("%01X"); - state_add(TMS1XXX_Y, "Y", m_y ).formatstr("%01X"); - state_add(TMS1XXX_STATUS, "STATUS", m_status).formatstr("%01X"); - state_add(STATE_GENPC, "GENPC", m_rom_address).formatstr("%03X").noshow(); state_add(STATE_GENPCBASE, "CURPC", m_rom_address).formatstr("%03X").noshow(); - state_add(STATE_GENFLAGS, "GENFLAGS", m_sr).formatstr("%8s").noshow(); + state_add(STATE_GENFLAGS, "GENFLAGS", m_status).formatstr("%7s").noshow(); - set_icountptr(m_icount); -} + m_state_count = 0; + state_add(++m_state_count, "PC", m_pc).formatstr("%02X"); // 1 + state_add(++m_state_count, "SR", m_sr).formatstr("%01X"); // 2 + state_add(++m_state_count, "PA", m_pa).formatstr("%01X"); // 3 + state_add(++m_state_count, "PB", m_pb).formatstr("%01X"); // 4 + state_add(++m_state_count, "A", m_a).formatstr("%01X"); // 5 + state_add(++m_state_count, "X", m_x).formatstr("%01X"); // 6 + state_add(++m_state_count, "Y", m_y).formatstr("%01X"); // 7 -device_memory_interface::space_config_vector tms1k_base_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) - }; + set_icountptr(m_icount); } @@ -270,15 +265,59 @@ void tms1k_base_device::device_reset() // clear outputs m_r = 0; - m_write_r(0, m_r & m_r_mask, 0xffff); - write_o_output(0); - m_write_r(0, m_r & m_r_mask, 0xffff); + write_r_output(0); + write_o_reg(0); + write_r_output(0); m_power_off(0); } //------------------------------------------------- +// common internal memory maps +//------------------------------------------------- + +device_memory_interface::space_config_vector tms1k_base_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) + }; +} + +void tms1k_base_device::rom_10bit(address_map &map) +{ + map(0x000, 0x3ff).rom(); +} + +void tms1k_base_device::rom_11bit(address_map &map) +{ + map(0x000, 0x7ff).rom(); +} + +void tms1k_base_device::rom_12bit(address_map &map) +{ + map(0x000, 0xfff).rom(); +} + +void tms1k_base_device::ram_6bit(address_map &map) +{ + map(0x00, 0x3f).ram(); +} + +void tms1k_base_device::ram_7bit(address_map &map) +{ + map(0x00, 0x7f).ram(); +} + +void tms1k_base_device::ram_8bit(address_map &map) +{ + map(0x00, 0xff).ram(); +} + + + +//------------------------------------------------- // program counter/opcode decode //------------------------------------------------- @@ -315,18 +354,12 @@ void tms1k_base_device::read_opcode() // i/o handling //------------------------------------------------- -void tms1k_base_device::write_o_output(u8 index) +void tms1k_base_device::write_o_reg(u8 index) { // a hardcoded table is supported if the output pla is unknown m_o_index = index; m_o = (m_output_pla_table == nullptr) ? m_opla->read(index) : m_output_pla_table[index]; - m_write_o(0, m_o & m_o_mask, 0xffff); -} - -u8 tms1k_base_device::read_k_input() -{ - // K1,2,4,8 (KC test pin is not emulated) - return m_read_k(0, 0xff) & 0xf; + write_o_output(m_o); } void tms1k_base_device::set_cki_bus() @@ -363,77 +396,62 @@ void tms1k_base_device::set_cki_bus() // handle branches: -// TMS1000/common -// note: add(latch) and bl(branch latch) are specific to 0980 series, -// c(chapter) bits are specific to 1100(and 1400) series +// add(latch) and bl(branch latch) are specific to 0980 series, c(chapter) bits are specific to 1100(and 1400) series +// TMS1400 and up and the CMOS chips have multiple stack levels, branches work a bit differently + +// BR/BL: conditional branch -void tms1k_base_device::op_br() +void tms1k_base_device::op_br1() { - // BR/BL: conditional branch if (m_status) { if (m_clatch == 0) m_pa = m_pb; + m_ca = m_cb; m_pc = m_opcode & m_pc_mask; } } -void tms1k_base_device::op_call() +void tms1k_base_device::op_brn() { - // CALL/CALLL: conditional call if (m_status) { - u8 prev_pa = m_pa; - - if (m_clatch == 0) - { - m_clatch = 1; - m_sr = m_pc; - m_pa = m_pb; - m_cs = m_ca; - } + m_pa = m_pb; // don't care about clatch m_ca = m_cb; - m_pb = prev_pa; m_pc = m_opcode & m_pc_mask; } } -void tms1k_base_device::op_retn() -{ - // RETN: return from subroutine - if (m_clatch == 1) - { - m_clatch = 0; - m_pc = m_sr; - m_ca = m_cs; - } - m_add = 0; - m_bl = 0; - m_pa = m_pb; -} - - -// TMS1400/TMS1000C 3-level stack version +// CALL/CALLL: conditional call -void tms1k_base_device::op_br3() +void tms1k_base_device::op_call1() { - // BR/BL: conditional branch if (m_status) { - m_pa = m_pb; // don't care about clatch + u8 prev_pa = m_pa; + + if (!m_clatch) + { + m_clatch = 1; + m_sr = m_pc; + m_pa = m_pb; + m_cs = m_ca; + } + m_ca = m_cb; + m_pb = prev_pa; m_pc = m_opcode & m_pc_mask; } } -void tms1k_base_device::op_call3() +void tms1k_base_device::op_calln() { - // CALL/CALLL: conditional call if (m_status) { - // mask clatch 3 bits (no need to mask others) - m_clatch = (m_clatch << 1 | 1) & 7; + // mask clatch bits (no need to mask others) + u8 smask = (1 << m_stack_levels) - 1; + m_clatch = (m_clatch << 1 | 1) & smask; m_sr = m_sr << m_pc_bits | m_pc; m_pc = m_opcode & m_pc_mask; @@ -451,9 +469,24 @@ void tms1k_base_device::op_call3() } } -void tms1k_base_device::op_retn3() +// RETN: return from subroutine + +void tms1k_base_device::op_retn1() +{ + if (m_clatch) + { + m_clatch = 0; + m_pc = m_sr; + m_ca = m_cs; + } + + m_add = 0; + m_bl = 0; + m_pa = m_pb; +} + +void tms1k_base_device::op_retnn() { - // RETN: return from subroutine if (m_clatch & 1) { m_clatch >>= 1; @@ -494,32 +527,32 @@ void tms1k_base_device::op_setr() { // SETR: set one R-output line m_r = m_r | (1 << m_y); - m_write_r(0, m_r & m_r_mask, 0xffff); + write_r_output(m_r); } void tms1k_base_device::op_rstr() { // RSTR: reset one R-output line m_r = m_r & ~(1 << m_y); - m_write_r(0, m_r & m_r_mask, 0xffff); + write_r_output(m_r); } void tms1k_base_device::op_tdo() { - // TDO: transfer accumulator and status latch to O-output - write_o_output(m_status_latch << 4 | m_a); + // TDO: transfer accumulator and status latch to O-register + write_o_reg(m_status_latch << 4 | m_a); } void tms1k_base_device::op_clo() { - // CLO: clear O-output - write_o_output(0); + // CLO: clear O-register + write_o_reg(0); } void tms1k_base_device::op_ldx() { // LDX: load X register with (x_bits) constant - m_x = m_c4 >> (4-m_x_bits); + m_x = m_c4 >> (4 - m_x_bits); } void tms1k_base_device::op_comx() @@ -532,7 +565,7 @@ void tms1k_base_device::op_comx8() { // COMX8: complement MSB of X register // note: on TMS1100, the mnemonic is simply called "COMX" - m_x ^= 1 << (m_x_bits-1); + m_x ^= 1 << (m_x_bits - 1); } void tms1k_base_device::op_ldp() @@ -541,18 +574,12 @@ void tms1k_base_device::op_ldp() m_pb = m_c4; } - -// TMS1100-specific - void tms1k_base_device::op_comc() { // COMC: complement chapter buffer m_cb ^= 1; } - -// TMS1400-specific - void tms1k_base_device::op_tpc() { // TPC: transfer page buffer to chapter buffer @@ -560,54 +587,14 @@ void tms1k_base_device::op_tpc() } -// TMS0980-specific (and possibly child classes) - -void tms1k_base_device::op_xda() -{ - // XDA: exchange DAM and A - // note: setting A to DAM is done with DMTP and AUTA during this instruction - m_ram_address |= (0x10 << (m_x_bits-1)); -} - -void tms1k_base_device::op_off() -{ - // OFF: request auto power-off - m_power_off(1); -} - -void tms1k_base_device::op_seac() -{ - // SEAC: set end around carry - m_eac = 1; -} - -void tms1k_base_device::op_reac() -{ - // REAC: reset end around carry - m_eac = 0; -} - -void tms1k_base_device::op_sal() -{ - // SAL: set add latch (reset is done with RETN) - m_add = 1; -} - -void tms1k_base_device::op_sbl() -{ - // SBL: set branch latch (reset is done with RETN) - m_bl = 1; -} - - //------------------------------------------------- // execute //------------------------------------------------- -void tms1k_base_device::execute_one() +void tms1k_base_device::execute_one(int subcycle) { - switch (m_subcycle) + switch (subcycle) { case 0: // fetch: rom address 1/2 @@ -621,7 +608,7 @@ void tms1k_base_device::execute_one() dynamic_output(); set_cki_bus(); m_ram_in = m_data->read_byte(m_ram_address) & 0xf; - m_dam_in = m_data->read_byte(m_ram_address | (0x10 << (m_x_bits-1))) & 0xf; + m_dam_in = m_data->read_byte(m_ram_address | (0x10 << (m_x_bits - 1))) & 0xf; m_p = 0; m_n = 0; m_carry_in = 0; @@ -693,6 +680,12 @@ void tms1k_base_device::execute_one() if (m_fixed & F_LDP) op_ldp(); if (m_fixed & F_COMC) op_comc(); if (m_fixed & F_TPC) op_tpc(); + + if (m_fixed & F_TAX) op_tax(); + if (m_fixed & F_TAC) op_tac(); + if (m_fixed & F_TADM) op_tadm(); + if (m_fixed & F_TMA) op_tma(); + if (m_fixed & F_OFF) op_off(); if (m_fixed & F_SEAC) op_seac(); if (m_fixed & F_REAC) op_reac(); @@ -700,6 +693,8 @@ void tms1k_base_device::execute_one() if (m_fixed & F_SBL) op_sbl(); if (m_fixed & F_XDA) op_xda(); + if (m_fixed & F_EXTRA) op_extra(); + // after fixed opcode handling: store status, write ram m_status = status; if (m_ram_out != -1) @@ -719,6 +714,11 @@ void tms1k_base_device::execute_one() if (m_micro & M_AUTY) m_y = m_adder_out & 0xf; if (m_micro & M_STSL) m_status_latch = m_status; + // fixed opcodes with accumulator as destination + if (m_fixed & F_TXA) op_txa(); + if (m_fixed & F_TRA) op_tra(); + if (m_fixed & F_TCA) op_tca(); + // fetch: update pc, ram address 2/2 read_opcode(); m_ram_address = m_x << 4 | m_y; @@ -729,8 +729,6 @@ void tms1k_base_device::execute_one() // execute: br/call 1/2 break; } - - m_subcycle = (m_subcycle + 1) % 6; } void tms1k_base_device::execute_run() @@ -738,6 +736,8 @@ void tms1k_base_device::execute_run() while (m_icount > 0) { m_icount--; - execute_one(); + + execute_one(m_subcycle); + m_subcycle = (m_subcycle + 1) % 6; } } |