diff options
Diffstat (limited to 'src/devices/cpu/tms1000/tms0980.cpp')
-rw-r--r-- | src/devices/cpu/tms1000/tms0980.cpp | 202 |
1 files changed, 116 insertions, 86 deletions
diff --git a/src/devices/cpu/tms1000/tms0980.cpp b/src/devices/cpu/tms1000/tms0980.cpp index 5cd7fa01137..0b764041412 100644 --- a/src/devices/cpu/tms1000/tms0980.cpp +++ b/src/devices/cpu/tms1000/tms0980.cpp @@ -4,59 +4,52 @@ TMS1000 family - TMS0980, TMS1980 +TMS0980 die notes: +- 144x4bit RAM array at the bottom-left (128+16, set up as 8x18x4) +- 2048x9bit ROM array at the bottom-left +- main instructions PLAs at the top half, to the right of the midline + * top section is assumed to be the CKI bus select + * middle section is for microinstruction redirection, this part may differ per die + * rest is fixed instructions select, from top-to-bottom: SEAC, LDX, COMX, COMX8, + TDO, SBIT, RETN, SETR, REAC, XDA, SAL, RBIT, ..., OFF, SBL, LDP, redir(------00- + R0^BL) +- 64-term microinstructions PLA between the RAM and ROM, supporting 20 microinstructions +- 16-term inverted output PLA and segment PLA above the RAM (rotate opla 90 degrees) + +TMS1980 is a TMS0980 with a TMS1x00 style opla +- RAM, ROM, and main instructions PLAs is the same as TMS0980 +- one of the microinstructions redirects to a RSTR instruction, like on TMS0270 +- 32-term output PLA above the RAM, 7 bits! (rotate opla 270 degrees) + */ #include "emu.h" #include "tms0980.h" #include "tms1k_dasm.h" -#include "debugger.h" - -// TMS0980 -// - 144x4bit RAM array at the bottom-left (128+16, set up as 8x18x4) -// - 2048x9bit ROM array at the bottom-left -// - main instructions PLAs at the top half, to the right of the midline -// * top section is assumed to be the CKI bus select -// * middle section is for microinstruction redirection, this part may differ per die -// * rest is fixed instructions select, from top-to-bottom: SEAC, LDX, COMX, COMX8, -// TDO, SBIT, RETN, SETR, REAC, XDA, SAL, RBIT, ..., OFF, SBL, LDP, redir(------00- + R0^BL) -// - 64-term microinstructions PLA between the RAM and ROM, supporting 20 microinstructions -// - 16-term inverted output PLA and segment PLA above the RAM (rotate opla 90 degrees) -DEFINE_DEVICE_TYPE(TMS0980, tms0980_cpu_device, "tms0980", "Texas Instruments TMS0980") // 28-pin DIP, 9 R pins -// TMS1980 is a TMS0980 with a TMS1x00 style opla -// - RAM, ROM, and main instructions PLAs is the same as TMS0980 -// - one of the microinstructions redirects to a RSTR instruction, like on TMS0270 -// - 32-term inverted output PLA above the RAM, 7 bits! (rotate opla 270 degrees) + +// device definitions +DEFINE_DEVICE_TYPE(TMS0980, tms0980_cpu_device, "tms0980", "Texas Instruments TMS0980") // 28-pin DIP, 9 R pins DEFINE_DEVICE_TYPE(TMS1980, tms1980_cpu_device, "tms1980", "Texas Instruments TMS1980") // 28-pin DIP, 7 O pins, 10 R pins, high voltage -// internal memory maps -void tms0980_cpu_device::program_11bit_9(address_map &map) -{ - map(0x000, 0x7ff).rom(); -} +tms0980_cpu_device::tms0980_cpu_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) : + tms0970_cpu_device(mconfig, type, tag, owner, clock, o_pins, r_pins, pc_bits, byte_bits, x_bits, stack_levels, rom_width, rom_map, ram_width, ram_map) +{ } -void tms0980_cpu_device::data_144x4(address_map &map) -{ - map(0x00, 0x7f).ram(); - map(0x80, 0x8f).ram().mirror(0x70); // DAM -} +tms0980_cpu_device::tms0980_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + tms0980_cpu_device(mconfig, TMS0980, tag, owner, clock, 8 /* o pins */, 9 /* r pins */, 7 /* pc bits */, 9 /* byte width */, 4 /* x width */, 1 /* stack levels */, 11 /* rom width */, address_map_constructor(FUNC(tms0980_cpu_device::rom_11bit), this), 8 /* ram width */, address_map_constructor(FUNC(tms0980_cpu_device::ram_144x4), this)) +{ } +tms1980_cpu_device::tms1980_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + tms0980_cpu_device(mconfig, TMS1980, tag, owner, clock, 7, 10, 7, 9, 4, 1, 11, address_map_constructor(FUNC(tms1980_cpu_device::rom_11bit), this), 8, address_map_constructor(FUNC(tms1980_cpu_device::ram_144x4), this)) +{ } -// device definitions -tms0980_cpu_device::tms0980_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : tms0980_cpu_device(mconfig, TMS0980, tag, owner, clock, 8 /* o pins */, 9 /* r pins */, 7 /* pc bits */, 9 /* byte width */, 4 /* x width */, 11 /* prg width */, address_map_constructor(FUNC(tms0980_cpu_device::program_11bit_9), this), 8 /* data width */, address_map_constructor(FUNC(tms0980_cpu_device::data_144x4), this)) -{ -} - -tms0980_cpu_device::tms0980_cpu_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) - : tms0970_cpu_device(mconfig, type, tag, owner, clock, o_pins, r_pins, pc_bits, byte_bits, x_bits, prgwidth, program, datawidth, data) -{ -} -tms1980_cpu_device::tms1980_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : tms0980_cpu_device(mconfig, TMS1980, tag, owner, clock, 7, 10, 7, 9, 4, 11, address_map_constructor(FUNC(tms1980_cpu_device::program_11bit_9), this), 8, address_map_constructor(FUNC(tms1980_cpu_device::data_144x4), this)) +// internal memory maps +void tms0980_cpu_device::ram_144x4(address_map &map) { + map(0x00, 0x7f).ram(); + map(0x80, 0x8f).ram().mirror(0x70); // DAM } @@ -64,18 +57,18 @@ tms1980_cpu_device::tms1980_cpu_device(const machine_config &mconfig, const char void tms0980_cpu_device::device_add_mconfig(machine_config &config) { // main opcodes PLA, microinstructions PLA, output PLA, segment PLA - PLA(config, "ipla", 9, 22, 24).set_format(pla_device::FMT::BERKELEY); - PLA(config, "mpla", 6, 20, 64).set_format(pla_device::FMT::BERKELEY); - PLA(config, "opla", 4, 8, 16).set_format(pla_device::FMT::BERKELEY); - PLA(config, "spla", 3, 8, 8).set_format(pla_device::FMT::BERKELEY); + PLA(config, m_ipla, 9, 22, 24).set_format(pla_device::FMT::BERKELEY); + PLA(config, m_mpla, 6, 20, 64).set_format(pla_device::FMT::BERKELEY); + PLA(config, m_opla, 4, 8, 16).set_format(pla_device::FMT::BERKELEY); + PLA(config, m_spla, 3, 8, 8).set_format(pla_device::FMT::BERKELEY); } void tms1980_cpu_device::device_add_mconfig(machine_config &config) { // main opcodes PLA, microinstructions PLA, output PLA - PLA(config, "ipla", 9, 22, 24).set_format(pla_device::FMT::BERKELEY); - PLA(config, "mpla", 6, 22, 64).set_format(pla_device::FMT::BERKELEY); - PLA(config, "opla", 5, 7, 32).set_format(pla_device::FMT::BERKELEY); + PLA(config, m_ipla, 9, 22, 24).set_format(pla_device::FMT::BERKELEY); + PLA(config, m_mpla, 6, 22, 64).set_format(pla_device::FMT::BERKELEY); + PLA(config, m_opla, 5, 7, 32).set_format(pla_device::FMT::BERKELEY); } @@ -87,40 +80,6 @@ std::unique_ptr<util::disasm_interface> tms0980_cpu_device::create_disassembler( // device_reset -u32 tms0980_cpu_device::decode_fixed(u16 op) -{ - u32 decode = 0; - u32 mask = m_ipla->read(op); - - // 1 line per PLA row, no OR-mask - const u32 id[15] = { F_LDP, F_SBL, F_OFF, F_RBIT, F_SAL, F_XDA, F_REAC, F_SETR, F_RETN, F_SBIT, F_TDO, F_COMX8, F_COMX, F_LDX, F_SEAC }; - - for (int bit = 0; bit < 15; bit++) - if (mask & (0x80 << bit)) - decode |= id[bit]; - - return decode; -} - -u32 tms0980_cpu_device::decode_micro(u8 sel) -{ - u32 decode = 0; - sel = bitswap<8>(sel,7,6,0,1,2,3,4,5); // lines are reversed - u32 mask = m_mpla->read(sel); - mask ^= 0x43fc3; // invert active-negative - - // M_RSTR is specific to TMS02x0/TMS1980, it redirects to F_RSTR - // M_UNK1 is specific to TMS0270, unknown/unused yet and apparently not connected on every TMS0270 - // _______ ______ _____ _____ _____ _____ ______ _____ ______ _____ _____ - const u32 md[22] = { M_NDMTP, M_DMTP, M_AUTY, M_AUTA, M_CKM, M_SSE, M_CKP, M_YTP, M_MTP, M_ATN, M_NATN, M_MTN, M_15TN, M_CKN, M_NE, M_C8, M_SSS, M_CME, M_CIN, M_STO, M_RSTR, M_UNK1 }; - - for (int bit = 0; bit < 22 && bit < m_mpla->outputs(); bit++) - if (mask & (1 << bit)) - decode |= md[bit]; - - return decode; -} - void tms0980_cpu_device::device_reset() { // common reset @@ -128,7 +87,7 @@ void tms0980_cpu_device::device_reset() // pre-decode instructionset m_fixed_decode.resize(0x200); - memset(&m_fixed_decode[0], 0, 0x200*sizeof(u32)); + memset(&m_fixed_decode[0], 0, 0x200*sizeof(u64)); m_micro_decode.resize(0x200); memset(&m_micro_decode[0], 0, 0x200*sizeof(u32)); @@ -139,7 +98,7 @@ void tms0980_cpu_device::device_reset() m_fixed_decode[op] = (op & 0x80) ? F_CALL: F_BR; // 6 output bits select a microinstruction index - m_micro_decode[op] = m_decode_micro.isnull() ? decode_micro(m_ipla->read(op) & 0x3f) : m_decode_micro(op); + m_micro_decode[op] = m_decode_micro.isunset() ? decode_micro(m_ipla->read(op) & 0x3f) : m_decode_micro(op); // the other ipla terms each select a fixed instruction m_fixed_decode[op] |= decode_fixed(op); @@ -151,7 +110,41 @@ void tms0980_cpu_device::device_reset() memset(&m_micro_decode[0], 0, 0x40*sizeof(u32)); for (int op = 0; op < 0x40; op++) - m_micro_direct[op] = m_decode_micro.isnull() ? decode_micro(op) : m_decode_micro(op + 0x200); + m_micro_direct[op] = m_decode_micro.isunset() ? decode_micro(op) : m_decode_micro(op + 0x200); +} + +u32 tms0980_cpu_device::decode_fixed(offs_t offset) +{ + u32 decode = 0; + u32 mask = m_ipla->read(offset); + + // 1 line per PLA row, no OR-mask + const u32 id[15] = { F_LDP, F_SBL, F_OFF, F_RBIT, F_SAL, F_XDA, F_REAC, F_SETR, F_RETN, F_SBIT, F_TDO, F_COMX8, F_COMX, F_LDX, F_SEAC }; + + for (int bit = 0; bit < 15; bit++) + if (mask & (0x80 << bit)) + decode |= id[bit]; + + return decode; +} + +u32 tms0980_cpu_device::decode_micro(offs_t offset) +{ + u32 decode = 0; + offset = bitswap<6>(offset,0,1,2,3,4,5); // lines are reversed + u32 mask = m_mpla->read(offset); + mask ^= 0x43fc3; // invert active-negative + + // M_RSTR is specific to TMS02x0/TMS1980, it redirects to F_RSTR + // M_UNK1 is specific to TMS0270, unknown/unused yet and apparently not connected on every TMS0270 + // _______ ______ _____ _____ _____ _____ ______ _____ ______ _____ _____ + const u32 md[22] = { M_NDMTP, M_DMTP, M_AUTY, M_AUTA, M_CKM, M_SSE, M_CKP, M_YTP, M_MTP, M_ATN, M_NATN, M_MTN, M_15TN, M_CKN, M_NE, M_C8, M_SSS, M_CME, M_CIN, M_STO, M_RSTR, M_UNK1 }; + + for (int bit = 0; bit < 22 && bit < m_mpla->outputs(); bit++) + if (mask & (1 << bit)) + decode |= md[bit]; + + return decode; } @@ -170,7 +163,7 @@ void tms0980_cpu_device::read_opcode() { debugger_instruction_hook(m_rom_address); m_opcode = m_program->read_word(m_rom_address) & 0x1ff; - m_c4 = bitswap<8>(m_opcode,7,6,5,4,0,1,2,3) & 0xf; // opcode operand is bitswapped for most opcodes + m_c4 = bitswap<4>(m_opcode,0,1,2,3); // opcode operand is bitswapped for most opcodes m_fixed = m_fixed_decode[m_opcode]; m_micro = read_micro(); @@ -186,7 +179,7 @@ void tms0980_cpu_device::read_opcode() // i/o handling u8 tms0980_cpu_device::read_k_input() { - u8 k = m_read_k(0, 0xff) & 0x1f; + u8 k = m_read_k() & 0x1f; u8 k3 = (k & 0x10) ? 3: 0; // the K3 line is simply K1|K2 return (k & 0xf) | k3; } @@ -225,8 +218,45 @@ void tms0980_cpu_device::op_comx() m_x ^= (m_x_mask >> 1); } +void tms0980_cpu_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 tms0980_cpu_device::op_off() +{ + // OFF: request auto power-off + m_power_off(1); +} + +void tms0980_cpu_device::op_seac() +{ + // SEAC: set end around carry + m_eac = 1; +} + +void tms0980_cpu_device::op_reac() +{ + // REAC: reset end around carry + m_eac = 0; +} + +void tms0980_cpu_device::op_sal() +{ + // SAL: set add latch (reset is done with RETN) + m_add = 1; +} + +void tms0980_cpu_device::op_sbl() +{ + // SBL: set branch latch (reset is done with RETN) + m_bl = 1; +} + void tms1980_cpu_device::op_tdo() { // TDO: transfer accumulator and status(not status_latch!) to O-output - write_o_output(m_status << 4 | m_a); + write_o_reg(m_status << 4 | m_a); } |