diff options
Diffstat (limited to 'src/devices/cpu/tx0/tx0dasm.cpp')
-rw-r--r-- | src/devices/cpu/tx0/tx0dasm.cpp | 889 |
1 files changed, 889 insertions, 0 deletions
diff --git a/src/devices/cpu/tx0/tx0dasm.cpp b/src/devices/cpu/tx0/tx0dasm.cpp new file mode 100644 index 00000000000..a8152a43216 --- /dev/null +++ b/src/devices/cpu/tx0/tx0dasm.cpp @@ -0,0 +1,889 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/*************************************************************************** + + MIT TX-0 disassembler + + Mnemonics and relative timing of operate class micro-instructions + until mid-1960 (as given in M-5001-27): + + 0.8 | 700000 (CLL) Clear left 9 bits of AC + 0.8 | 640000 (CLR) Clear right 9 bits of AC + ----+-------------------------------------------------------- + IOS | 610000 (EX0) Operate external equipment 0 + IOS | 611000 (EX1) Operate external equipment 1 + IOS | 612000 (EX2) Operate external equipment 2 + IOS | 613000 (EX3) Operate external equipment 3 + IOS | 614000 (EX4) Operate external equipment 4 + IOS | 615000 (EX5) Operate external equipment 5 + IOS | 616000 (EX6) Operate external equipment 6 + IOS | 617000 (EX7) Operate external equipment 7 + IOS | 621000 (R1L) Read one line of tape from PETR into AC + IOS | 622000 (DIS) Display point on scope (coordinates in AC) + IOS | 623000 (R3L) Read three lines of tape from PETR into AC + IOS | 624000 (PRT) Print character on Flexowriter + IOS | 626000 (P6H) Punch six holes (as specified by AC) + IOS | 627000 (P7H) Punch seven holes (as specified by AC) + ----+-------------------------------------------------------- + 1.1 | Clear MBR + 1.1 | 600100 (PEN) Set AC bits 0 and 1 from LP0 and LP1 + 1.1 | 600004 (TAC) Transfer (inclusive or) TAC to AC + 1.2 | 600001 (AMB) Transfer AC to MBR (executed before COM) + 1.2 | 600040 (COM) Complement AC + 1.2 | 600003 (TBR) Transfer (inclusive or) TBR to MBR + 1.3 | 600200 (MLR) Transfer MBR to LR + 1.3 | 600002 (LMB) Transfer LR to MBR + 1.3 | 600104 (ORL) Inclusive or MBR into LR + 1.3 | 600304 (ANL) And MBR into LR + 1.4 | 600020 (PAD) Partial add (exclusive or) MBR to AC + 1.4 | 600400 (SHR) Shift AC right once + 1.4 | 600600 (CYR) Cycle AC right once + 1.7 | 600010 (CRY) Add carry digits to AC (according to MBR) + 1.8 | 603000 (HLT) Halt computer + + ANL and ORL were added in May 1959, along with TRA (M-5001-6). + LLR and SLR were added a few months later (M-5001-7). + + A few derived OPRs not mentioned in M-5001-27 are documented in + the listing of the updated vocabulary table for the TRA-patched + version of UT3 and in a listing of "Macro ii-a=part 2" dated + 3-61 (though this also includes some OPRs which were probably + added after 1960). + + Mnemonics and relative timing of operate class micro-instructions + after 1960 (as given in M-5001-27-3 and M-5001-27-4): + + 0.6 | 631000 (CLL) Clear left 9 bits of AC + 0.6 | 632000 (CLR) Clear right 9 bits of AC + 0.7 | 640000 (AMB) Transfer AC to MBR + 0.8 | 700000 (CLA) Clear AC + ----+------------------------------------------------------------ + ** | 604000 (SEL) Select magnetic tape device + | 6x4x00 Backspace tape + | 6x4x04 Read select tape + | 6x4x10 Rewind tape + | 6x4x14 Write select tape + ** | 620000 (CPY) Synchronize with copy (transfer to or from LR) + ----+------------------------------------------------------------ + 1.1 | 601000 (TAC) Transfer (inclusive or) TAC to AC + 1.1 | 603000 (PEN) Set AC bits 0 and 1 from LP0 and LP1 + 1.2 | 600100 (XMB) Transfer XR to MBR (with sign extension) + 1.2 | 600040 (COM) Complement AC + 1.2 | 602000 (TBR) Transfer (inclusive or) TBR to MBR + 1.2 | 606000 (RPF) Read (inclusive or) PFR into MBR + 1.3 | 600005 (ORB) Inclusive or LR into MBR + 1.3 | 600007 (ANB) And LR into MBR + 1.4 | 600200 (MBL) Transfer MBR to LR + 1.4 | 600002 (LMB) Transfer LR to MBR + 1.5 | 600020 (PAD) Partial add (exclusive or) MBR to AC + 1.6 | 600400 (SHR) Shift AC right once + 1.6 | 600600 (CYR) Cycle AC right once + 1.6 | 607000 (SPF) Set PFR from MBR + 1.7 | 600010 (CRY) Add carry digits to AC (according to MBR) + 1.8 | 600001 (MBX) Transfer MBR to XR + 1.8 | 603000 (HLT) Halt computer + + Previously supported Input-Output Stop group codes were unchanged. + However, the old semantics of R1L cycling AC left after reading one + line are no longer obtainable because AMB now occurs before rather than + after IOS. Anticipation of this incompatibity (q.v. M-5001-16) is + likely why R1L is unlisted in M-5001-27. + +***************************************************************************/ + +#include "emu.h" +#include "tx0dasm.h" + +u32 tx0_64kw_disassembler::opcode_alignment() const +{ + return 1; +} + +u32 tx0_8kw_disassembler::opcode_alignment() const +{ + return 1; +} + +namespace { + +const std::string_view s_addressable_insts[24] = +{ + "sto", "stx", "sxa", "ado", "slr", "slx", "stz", {}, + "add", "adx", "ldx", "aux", "llr", "llx", "lda", "lax", + "trn", "tze", "tsx", "tix", "tra", "trx", "tlv", {} +}; + +const std::string_view s_tape_insts[8] = +{ + "bsr", "rtb", "rew", "wtb", + "bsr", "rtd", "rew", "wtd" +}; + +} // 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) + { + // Addressable instructions (only 3 in this version) + util::stream_format(stream, "%s %06o", s_addressable_insts[(inst & 0600000) >> 13], inst & 0177777); + if (inst >= 0400000) // trn + return 1 | STEP_COND | SUPPORTED; + } + else + dasm_opr(stream, inst); + + return 1 | SUPPORTED; +} + +void tx0_64kw_disassembler::dasm_opr(std::ostream &stream, u32 inst) +{ + switch (inst) + { + case 0600012: + stream << "cry"; + break; + + case 0600022: + stream << "lpd"; + break; + + case 0600031: + stream << "cyl"; + break; + + case 0600032: + stream << "lad"; + break; + + case 0600040: + stream << "com"; + break; + + case 0600051: + stream << "amz"; + break; + + case 0600072: + stream << "lcd"; + break; + + case 0600100: + stream << "pen"; + break; + + case 0600121: + stream << "cpa"; + break; + + case 0600200: + stream << "lro"; + break; + + case 0600201: + stream << "alr"; + break; + + case 0600221: + stream << "ala"; + break; + + case 0600261: + stream << "alc"; + break; + + case 0600400: + stream << "shr"; + break; + + case 0600600: + stream << "cyr"; + break; + + case 0622000: + stream << "dis"; + break; + + case 0622021: + stream << "dsa"; + break; + + case 0622061: + stream << "dsc"; + break; + + case 0622100: + stream << "dip"; + break; + + case 0624000: + stream << "prt"; + break; + + case 0624021: + stream << "pna"; + break; + + case 0624061: + stream << "pnc"; + break; + + case 0624600: + stream << "pnt"; + break; + + case 0626021: case 0627021: + util::stream_format(stream, "p%da", BIT(inst, 9) ? 7 : 6); + break; + + case 0626600: case 0627600: + util::stream_format(stream, "p%dh", BIT(inst, 9) ? 7 : 6); + break; + + 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 0740012: + stream << "lal"; + break; + + case 0740022: + stream << "lac"; + break; + + case 0740023: + stream << "tbr"; + break; + + case 0740040: + stream << "clc"; + break; + + case 0740062: + stream << "lcc"; + break; + + case 0740072: + stream << "laz"; + 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, "opr %o", inst & 0177777); + break; + } +} + +offs_t tx0_8kwo_disassembler::disassemble(std::ostream &stream, offs_t pc, const tx0_8kwo_disassembler::data_buffer &opcodes, const tx0_8kwo_disassembler::data_buffer ¶ms) +{ + u32 inst = opcodes.r32(pc) & 0777777; + + if (inst < 0600000) + { + // Addressable instructions (only 6 in this version) + if ((inst & 060000) != 0) + util::stream_format(stream, "%06o", inst); + else + util::stream_format(stream, "%s %05o", s_addressable_insts[(inst & 0700000) >> 13], inst & 017777); + if ((inst & 0700000) == 0400000) // trn + return 1 | STEP_COND | SUPPORTED; + } + else switch (inst) + { + case 0600105: + stream << "orl"; + break; + + case 0600125: + stream << "ora"; + break; + + case 0600305: + stream << "anl"; + break; + + case 0600325: + stream << "ana"; + break; + + case 0610000: case 0611000: case 0612000: case 0613000: case 0614000: case 0615000: case 0616000: case 0617000: + util::stream_format(stream, "ex%d", BIT(inst, 9, 3)); + break; + + default: + dasm_opr(stream, inst); + break; + } + + 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 >= 0400000) + { + if ((inst & 0760000) == 0440000) // tsx + return 1 | STEP_OVER | SUPPORTED; + else if ((inst & 0760000) == 0520000) // trx + return 1 | STEP_OUT | SUPPORTED; + else if ((inst & 0760000) != 0500000) // trn, tze, tix, tlv + return 1 | STEP_COND | 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 & 0137020) == 0102020) + { + stream << "tbr"; + if ((inst & 000757) == 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 040227: + stream << "anl 20"; // no consistent mnemonic used in program macros + 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 040250: + stream << "alrUamz"; + break; + + case 040260: + stream << "alc"; + break; + + case 040601: + stream << "arx"; + break; + + case 0100000: + stream << "cla"; + break; + + case 0100001: + stream << "cax"; + break; + + case 0100012: + stream << "lal"; + break; + + case 0100022: + stream << "lac"; + break; + + case 0100023: + stream << "lacUlxr"; + break; + + case 0100040: + stream << "clc"; + break; + + case 0100041: + stream << "clcUxro"; + 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 0100201: + stream << "calUxro"; + break; + + case 0100212: + stream << "lalUlro"; + break; + + case 0100222: + stream << "lacUlro"; + 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 << "orc"; // as in M-5001-19-1 + break; + + case 0140067: + stream << "anc"; // as in M-5001-19-1 + 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; +} |