diff --git a/src/devices/cpu/tx0/tx0.cpp b/src/devices/cpu/tx0/tx0.cpp index 3f9bdcf2087..ff3a8e0ac45 100644 --- a/src/devices/cpu/tx0/tx0.cpp +++ b/src/devices/cpu/tx0/tx0.cpp @@ -15,8 +15,9 @@ #include "tx0dasm.h" #include "debugger.h" -#define LOG 0 -#define LOG_EXTRA 0 +#define LOG_RIM (1 << 1U) +//#define VERBOSE (LOG_RIM) +#include "logmacro.h" #define READ_TX0_18BIT(A) ((signed)m_program->read_dword(A)) @@ -255,9 +256,6 @@ void tx0_64kw_device::execute_run() { do { - debugger_instruction_hook(PC); - - if (m_ioh && m_ios) { m_ioh = 0; @@ -265,7 +263,10 @@ void tx0_64kw_device::execute_run() if ((! m_run) && (! m_rim)) + { + debugger_instruction_hook(PC); m_icount = 0; /* if processor is stopped, just burn cycles */ + } else if (m_rim) { switch (m_rim_step) @@ -295,6 +296,7 @@ void tx0_64kw_device::execute_run() m_rim = 0; /* exit read-in mode */ m_run = (IR == 2) ? 1 : 0; /* stop if add instruction */ m_rim_step = 0; + LOGMASKED(LOG_RIM, "RIM %s: PC <- %06o\n", (IR == 2) ? "start" : "stop", PC); } else if ((IR == 0) || (IR == 3)) /* sto or opr instruction? */ { @@ -321,6 +323,7 @@ void tx0_64kw_device::execute_run() { /* data transfer complete */ m_ios = 0; + LOGMASKED(LOG_RIM, "RIM transfer: %06o <- %06o\n", MAR, AC); tx0_write(MAR, MBR = AC); m_rim_step = 0; @@ -332,6 +335,7 @@ void tx0_64kw_device::execute_run() { if (m_cycle == 0) { /* fetch new instruction */ + debugger_instruction_hook(PC); MBR = tx0_read(MAR = PC); INCREMENT_PC_64KW; IR = MBR >> 16; /* basic opcode */ @@ -358,9 +362,6 @@ void tx0_8kw_device::execute_run() { do { - debugger_instruction_hook(PC); - - if (m_ioh && m_ios) { m_ioh = 0; @@ -368,7 +369,10 @@ void tx0_8kw_device::execute_run() if ((! m_run) && (! m_rim)) + { + debugger_instruction_hook(PC); m_icount = 0; /* if processor is stopped, just burn cycles */ + } else if (m_rim) { switch (m_rim_step) @@ -398,6 +402,7 @@ void tx0_8kw_device::execute_run() m_rim = 0; /* exit read-in mode */ m_run = (IR == 16) ? 1 : 0; /* stop if add instruction */ m_rim_step = 0; + LOGMASKED(LOG_RIM, "RIM %s: PC <- %05o\n", (IR == 16) ? "start" : "stop", PC); } else if ((IR == 0) || (IR == 24)) /* sto or opr instruction? */ { @@ -424,6 +429,7 @@ void tx0_8kw_device::execute_run() { /* data transfer complete */ m_ios = 0; + LOGMASKED(LOG_RIM, "RIM transfer: %05o <- %06o\n", MAR, AC); tx0_write(MAR, MBR = AC); m_rim_step = 0; @@ -435,6 +441,7 @@ void tx0_8kw_device::execute_run() { if (m_cycle == 0) { /* fetch new instruction */ + debugger_instruction_hook(PC); MBR = tx0_read(MAR = PC); INCREMENT_PC_8KW; IR = MBR >> 13; /* basic opcode */ @@ -551,6 +558,8 @@ void tx0_64kw_device::execute_instruction_64kw() break; case 3: /* OPeRate */ + MBR = 0; + if ((MAR & 0000104) == 0000100) /* (1.1) PEN = Read the light pen flip-flops 1 and 2 into AC(0) and AC(1). */ @@ -560,19 +569,19 @@ void tx0_64kw_device::execute_instruction_64kw() /* (1.1) TAC = Insert a one in each digital position of the AC wherever there is a one in the corresponding digital position of the TAC. */ - /*...*/ { } - - if (MAR & 0000040) - /* (1.2) COM = Complement every digit in the accumulator */ - AC ^= 0777777; + AC |= m_tac; if ((MAR & 0000003) == 1) /* (1.2) AMB = Store the contents of the AC in the MBR. */ MBR = AC; + if (MAR & 0000040) + /* (1.2) COM = Complement every digit in the accumulator */ + AC ^= 0777777; + if ((MAR & 0000003) == 3) /* (1.2) TBR = Store the contents of the TBR in the MBR. */ - /*...*/ { } + MBR |= m_tbr; if ((MAR & 0000003) == 2) /* (1.3) LMB = Store the contents of the LR in the MBR. */ @@ -633,8 +642,6 @@ void tx0_device::indexed_address_eval() { MAR = MAR + XR; MAR = (MAR + (MAR >> 14)) & 0037777; /* propagate carry around */ - if (MAR & 0020000) /* fix negative (right???) */ - MAR = (MAR + 1) & 0017777; } /* execute one instruction */ @@ -921,6 +928,9 @@ void tx0_8kw_device::execute_instruction_8kw() /* (1.1) TAC = transfer TAC into ac (inclusive or) */ AC |= m_tac; + if ((IR & 002) == 00) + MBR = 0; // MBR cleared at 1.1 + if (((IR & 001) == 00) && ((MAR & 017000) == 002000)) /* (1.2) TBR = transfer TBR into mbr (inclusive or) */ MBR |= m_tbr; @@ -953,8 +963,7 @@ void tx0_8kw_device::execute_instruction_8kw() break; default: - if (LOG) - logerror("unrecognized instruction"); + LOG("unrecognized instruction\n"); break; } } @@ -991,8 +1000,7 @@ void tx0_8kw_device::execute_instruction_8kw() break; default: - if (LOG) - logerror("unrecognized instruction"); + LOG("unrecognized instruction\n"); break; } } diff --git a/src/devices/cpu/tx0/tx0dasm.cpp b/src/devices/cpu/tx0/tx0dasm.cpp index 34d49194ed3..2ea131211e1 100644 --- a/src/devices/cpu/tx0/tx0dasm.cpp +++ b/src/devices/cpu/tx0/tx0dasm.cpp @@ -1,5 +1,11 @@ // license:BSD-3-Clause -// copyright-holders:Raphael Nabet +// copyright-holders:AJR +/*************************************************************************** + + MIT TX-0 disassembler + +***************************************************************************/ + #include "emu.h" #include "tx0dasm.h" @@ -8,126 +14,689 @@ u32 tx0_64kw_disassembler::opcode_alignment() const return 1; } -offs_t tx0_64kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) -{ - int md; - int x; - - md = opcodes.r32(pc); - - x = md & 0177777; - switch (md >> 16) - { - case 0: - util::stream_format(stream, "sto 0%06o", x); - break; - case 1: - util::stream_format(stream, "add 0%06o", x); - break; - case 2: - util::stream_format(stream, "trn 0%06o", x); - break; - case 3: - util::stream_format(stream, "opr 0%06o", x); - break; - } - return 1; -} - u32 tx0_8kw_disassembler::opcode_alignment() const { return 1; } -offs_t tx0_8kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) +namespace { + +const std::string_view s_addressable_insts[24] = { - int md; - int x; + "sto", "stx", "sxa", "ado", "slr", "slx", "stz", {}, + "add", "adx", "ldx", "aux", "llr", "llx", "lda", "lax", + "trn", "tze", "tsx", "tix", "tra", "trx", "tlv", {} +}; - md = opcodes.r32(pc); +const std::string_view s_tape_insts[8] = +{ + "bsr", "rtb", "rew", "wtb", + "bsr", "rtd", "rew", "wtd" +}; - x = md & 0017777; - switch (md >> 13) +} // anonymous namespace + +offs_t tx0_64kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const tx0_64kw_disassembler::data_buffer &opcodes, const tx0_64kw_disassembler::data_buffer ¶ms) +{ + u32 inst = opcodes.r32(pc) & 0777777; + + if (inst < 0600000) { - case 0: - util::stream_format(stream, "sto 0%05o", x); + // Addressable instructions (only 3 in this version) + util::stream_format(stream, "%s %06o", s_addressable_insts[(inst & 0600000) >> 13], inst & 0177777); + } + else switch (inst) + { + case 0600012: + stream << "cry"; break; - case 1: - util::stream_format(stream, "stx 0%05o", x); + + case 0600022: + stream << "lpd"; break; - case 2: - util::stream_format(stream, "sxa 0%05o", x); + + case 0600031: + stream << "cyl"; break; - case 3: - util::stream_format(stream, "ado 0%05o", x); + + case 0600032: + stream << "lad"; break; - case 4: - util::stream_format(stream, "slr 0%05o", x); + + case 0600040: + stream << "com"; break; - case 5: - util::stream_format(stream, "slx 0%05o", x); + + case 0600051: + stream << "amz"; break; - case 6: - util::stream_format(stream, "stz 0%05o", x); + + case 0600100: + stream << "pen"; break; - case 8: - util::stream_format(stream, "add 0%05o", x); + + case 0600200: + stream << "lro"; break; - case 9: - util::stream_format(stream, "adx 0%05o", x); + + case 0600201: + stream << "alr"; break; - case 10: - util::stream_format(stream, "ldx 0%05o", x); + + case 0600221: + stream << "ala"; break; - case 11: - util::stream_format(stream, "aux 0%05o", x); + + case 0600261: + stream << "alc"; break; - case 12: - util::stream_format(stream, "llr 0%05o", x); + + case 0600400: + stream << "shr"; break; - case 13: - util::stream_format(stream, "llx 0%05o", x); + + case 0600600: + stream << "cyr"; break; - case 14: - util::stream_format(stream, "lda 0%05o", x); + + case 0622000: + stream << "dis"; break; - case 15: - util::stream_format(stream, "lax 0%05o", x); + + case 0622021: + stream << "dsa"; break; - case 16: - util::stream_format(stream, "trn 0%05o", x); + + case 0622061: + stream << "dsc"; break; - case 17: - util::stream_format(stream, "tze 0%05o", x); + + case 0624000: + stream << "prt"; break; - case 18: - util::stream_format(stream, "tsx 0%05o", x); + + case 0624021: + stream << "pna"; break; - case 19: - util::stream_format(stream, "tix 0%05o", x); + + case 0624061: + stream << "pnc"; break; - case 20: - util::stream_format(stream, "tra 0%05o", x); + + case 0624600: + stream << "pnt"; break; - case 21: - util::stream_format(stream, "trx 0%05o", x); + + case 0626021: case 0627021: + util::stream_format(stream, "p%da", BIT(inst, 9) ? 7 : 6); break; - case 22: - util::stream_format(stream, "tlv 0%05o", x); + + case 0626600: case 0627600: + util::stream_format(stream, "p%dh", BIT(inst, 9) ? 7 : 6); break; - case 24: - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - util::stream_format(stream, "opr 0%06o", md & 0177777); + + case 0630000: + stream << "hlt"; break; + + case 0640000: + stream << "clr"; + break; + + case 0666020: case 0667020: + util::stream_format(stream, "p%do", BIT(inst, 9) ? 7 : 6); + break; + + case 0700000: + stream << "cll"; + break; + + case 0740000: + stream << "cla"; + break; + + case 0740004: + stream << "tac"; + break; + + case 0740022: + stream << "lac"; + break; + + case 0740023: + stream << "tbr"; + break; + + case 0740040: + stream << "clc"; + break; + + case 0740200: + stream << "cal"; + break; + + case 0761000: + stream << "r1c"; + break; + + case 0761031: + stream << "r1l"; + break; + + case 0761600: + stream << "r1r"; + break; + + case 0763000: + stream << "r3c"; + break; + + case 0766000: + stream << "p6s"; + break; + default: - util::stream_format(stream, "illegal"); + if (inst >= 0760000) + util::stream_format(stream, "ios %o", inst & 017777); + else + util::stream_format(stream, "opr %o", inst & 0177777); break; } - return 1; + + return 1 | SUPPORTED; +} + +offs_t tx0_8kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const tx0_8kw_disassembler::data_buffer &opcodes, const tx0_8kw_disassembler::data_buffer ¶ms) +{ + u32 inst = opcodes.r32(pc) & 0777777; + + if (inst < 0600000) + { + // Addressable instructions + std::string_view str = s_addressable_insts[(inst & 0760000) >> 13]; + if (str.empty()) + util::stream_format(stream, "%06o", inst); + else + { + util::stream_format(stream, "%s %05o", str, inst & 017777); + + if ((inst & 0760000) == 0440000) // tsx + return 1 | STEP_OVER | SUPPORTED; + else if ((inst & 0760000) == 0520000) // trx + return 1 | STEP_OUT | SUPPORTED; + } + } + else if ((inst & 037000) == 004000) + { + // Select class + if (BIT(inst, 15)) + stream << "claU"; + util::stream_format(stream, "%s %d", s_tape_insts[BIT(inst, 2, 3)], inst & 3); + } + else + { + if ((inst & 037000) == 02000) + { + stream << "tbr"; + if ((inst & 0100757) == 0) + return 1 | SUPPORTED; + stream << 'U'; + } + else if (inst == 0706020) + { + stream << "rpf"; + return 1 | SUPPORTED; + } + else if ((inst & 037000) == 07000) + { + if (BIT(inst, 14)) + stream << "spf"; + else + stream << "cpf"; + if ((inst & 0100777) == 0) + return 1 | SUPPORTED; + stream << 'U'; + } + else if ((inst & 037000) == 020000) + { + stream << "cpy"; + if ((inst & 0100777) == 0) + return 1 | SUPPORTED; + stream << 'U'; + } + else if ((inst & 037000) == 025000) + { + stream << "typ"; + if ((inst & 0100777) == 0) + return 1 | SUPPORTED; + stream << 'U'; + } + else if ((inst & 036777) == 026600) + { + util::stream_format(stream, "p%dh", BIT(inst, 9) ? 7 : 6); + return 1 | SUPPORTED; + } + else if ((inst & 076777) == 066020) + { + util::stream_format(stream, "p%do", BIT(inst, 9) ? 7 : 6); + return 1 | SUPPORTED; + } + else if ((inst & 037000) == 030000) + { + // HLT is actually executed last, but normally written first + stream << "hlt"; + if ((inst & 0100777) == 0) + return 1 | SUPPORTED; + stream << 'U'; + } + else if ((inst & 037000) == 031000) + { + stream << "cll"; + if ((inst & 0100777) == 0) + return 1 | SUPPORTED; + stream << 'U'; + } + else if ((inst & 037000) == 032000) + { + stream << "clr"; + if ((inst & 0100777) == 0) + return 1 | SUPPORTED; + stream << 'U'; + } + else if ((inst & 037000) != 0) + { + if (BIT(inst, 15)) + { + switch (inst & 037000) + { + case 01000: + stream << "tac"; + break; + + case 03000: + stream << "claUpen"; + break; + + case 010000: case 011000: case 012000: case 013000: case 014000: case 015000: case 016000: case 017000: + util::stream_format(stream, "claUex%d", BIT(inst, 9, 3)); + break; + + case 021000: + if ((inst & 0777) == 0600) + { + stream << "r1r"; + return 1 | SUPPORTED; + } + stream << "r1c"; + break; + + case 022000: + stream << "claUdis"; + break; + + case 023000: + stream << "r3c"; + break; + + case 024000: + stream << "claUprt"; + break; + + case 026000: + if ((inst & 040777) == 040020) + { + stream << "p6b"; + return 1 | SUPPORTED; + } + stream << "p6s"; + break; + + default: + util::stream_format(stream, "opr %o", inst & 0177777); + return 1 | SUPPORTED; + } + if ((inst & 0777) == 0) + return 1 | SUPPORTED; + inst &= 040777; + stream << 'U'; + } + else + { + switch (inst & 037000) + { + case 03000: + stream << "pen"; + break; + + case 010000: case 011000: case 012000: case 013000: case 014000: case 015000: case 016000: case 017000: + util::stream_format(stream, "ex%d", BIT(inst, 9, 3)); + break; + + case 021000: + stream << "r1l"; + break; + + case 022000: + if ((inst & 040777) == 040020) + { + stream << "dso"; + return 1 | SUPPORTED; + } + stream << "dis"; + break; + + case 023000: + stream << "r3l"; + break; + + case 024000: + if ((inst & 040777) == 040020) + { + stream << "pno"; + return 1 | SUPPORTED; + } + else if ((inst & 040777) == 040060) + { + stream << "pnc"; + return 1 | SUPPORTED; + } + else if ((inst & 0777) == 0600) + { + stream << "pnt"; + return 1 | SUPPORTED; + } + stream << "prt"; + break; + + default: + util::stream_format(stream, "opr %o", inst & 0177777); + return 1 | SUPPORTED; + } + if ((inst & 0777) == 0) + return 1 | SUPPORTED; + stream << 'U'; + } + } + else if (inst == 0600000) + { + stream << "nop"; + return 1 | SUPPORTED; + } + + switch (inst & 0140777) + { + case 0: + break; + + case 000001: + stream << "xro"; + break; + + case 000003: + stream << "lxr"; + break; + + case 000012: + stream << "cry"; + break; + + case 000022: + stream << "lpd"; + break; + + case 000031: + stream << "alx"; + break; + + case 000032: + stream << "lad"; + break; + + case 000033: + stream << "ladUxro"; + break; + + case 000040: case 040040: + stream << "com"; + break; + + case 000041: + stream << "comUxro"; + break; + + case 000043: + stream << "comUlxr"; + break; + + case 000062: + stream << "lpdUcom"; + break; + + case 000072: + stream << "lcd"; + break; + + case 000130: + stream << "xad"; + break; + + case 000170: + stream << "xcd"; + break; + + case 000200: + stream << "lro"; + break; + + case 000240: + stream << "comUlro"; + break; + + case 000272: + stream << "lcdUlro"; + break; + + case 000300: + stream << "xlr"; + break; + + case 000303: + stream << "ixl"; + break; + + case 000400: + stream << "shr"; + break; + + case 000600: + stream << "cyr"; + break; + + case 000612: + stream << "cyrUcry"; // M-5001-19 names this 'ran' (random number generator) + break; + + case 000640: + stream << "comUcyr"; + break; + + case 040001: + stream << "axr"; + break; + + case 040021: + stream << "axo"; + break; + + case 040030: + stream << "cyl"; + break; + + case 040031: + stream << "axrUcyl"; + break; + + case 040050: + stream << "amz"; + break; + + case 040061: + stream << "axc"; + break; + + case 040200: + stream << "alr"; + break; + + case 040201: + stream << "alrUaxr"; + break; + + case 040203: + stream << "rax"; + break; + + case 040205: + stream << "orl"; + break; + + case 040207: + stream << "anl"; + break; + + case 040220: + stream << "alo"; + break; + + case 040230: + stream << "all"; + break; + + case 040231: + stream << "alrUalx"; + break; + + case 040232: + stream << "iad"; + break; + + case 040240: + stream << "alrUcom"; + break; + + case 040247: + stream << "anlUcom"; + break; + + case 040260: + stream << "alc"; + break; + + case 040601: + stream << "arx"; + break; + + case 0100000: case 0140000: + stream << "cla"; + break; + + case 0100001: + stream << "cax"; + break; + + case 0100012: + stream << "lal"; + break; + + case 0100022: case 0140022: + stream << "lac"; + break; + + case 0100023: + stream << "lacUlxr"; + break; + + case 0100040: case 0140040: + stream << "clc"; + break; + + case 0100062: + stream << "lcc"; + break; + + case 0100072: + stream << "laz"; + break; + + case 0100110: + stream << "xal"; + break; + + case 0100120: + stream << "xac"; + break; + + case 0100160: + stream << "xcc"; + break; + + case 0100200: + stream << "cal"; + break; + + case 0100240: + stream << "calUcom"; + break; + + case 0100322: + stream << "rxa"; + break; + + case 0100622: + stream << "lar"; + break; + + case 0140025: + stream << "ora"; + break; + + case 0140027: + stream << "ana"; + break; + + case 0140065: + stream << "oraUcom"; // M-5001-19-1 names this 'orc' + break; + + case 0140067: + stream << "anaUcom"; // M-5001-19-1 names this 'anc' + break; + + case 0140205: + stream << "oro"; + break; + + case 0140207: + stream << "ano"; + break; + + case 0140212: + stream << "lalUalr"; // M-5001-19-1 names this 'ill' + break; + + case 0140222: + stream << "ial"; + break; + + case 0140262: + stream << "ialUcom"; + break; + + default: + util::stream_format(stream, "opr %o", inst & 0140777); + break; + } + } + + return 1 | SUPPORTED; } diff --git a/src/mame/drivers/tx0.cpp b/src/mame/drivers/tx0.cpp index 286e735647e..bb9af652fd4 100644 --- a/src/mame/drivers/tx0.cpp +++ b/src/mame/drivers/tx0.cpp @@ -406,6 +406,7 @@ public: // image-level overrides virtual iodevice_t image_type() const noexcept override { return IO_PUNCHTAPE; } + virtual bool support_command_line_image_creation() const noexcept override { return true; } virtual bool is_readable() const noexcept override { return false; } virtual bool is_writeable() const noexcept override { return true; } @@ -764,7 +765,7 @@ WRITE_LINE_MEMBER( tx0_state::tx0_io_prt ) /* read current AC */ ac = m_maincpu->state_int(TX0_AC); /* shuffle and print 6-bit word */ - ch = ((ac & 0100000) >> 15) | ((ac & 0010000) >> 11) | ((ac & 0001000) >> 7) | ((ac & 0000100) >> 3) | ((ac & 0000010) << 1) | ((ac & 0000001) << 5); + ch = bitswap<6>(ac, 15, 12, 9, 6, 3, 0); typewriter_out(ch); m_typewriter.prt_timer->adjust(attotime::from_msec(100));