diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/cpu/interdata16/dasm16.cpp | 428 | ||||
-rw-r--r-- | src/devices/cpu/interdata16/dasm16.h | 25 | ||||
-rw-r--r-- | src/tools/unidasm.cpp | 2 |
3 files changed, 455 insertions, 0 deletions
diff --git a/src/devices/cpu/interdata16/dasm16.cpp b/src/devices/cpu/interdata16/dasm16.cpp new file mode 100644 index 00000000000..b47a7ba6fa6 --- /dev/null +++ b/src/devices/cpu/interdata16/dasm16.cpp @@ -0,0 +1,428 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/*************************************************************************** + + Interdata/Perkin-Elmer Series 16 disassembler + + The instrution set supported here is that of the Model 8/16E Processor, + which is backward-compatible with practically all of its predecessors. + Only SETM(R) and the double-precision floating point instructions were + relatively late additions to the 16-bit architecture; most others were + supported as least as far back as the Model 5 (1970), though + multiply/divide and floating point support were optional on a few + subsequent models. Interdata's first-generation Models 3 & 4 lacked + short-form instructions and list processing, which likely made these + processors incompatible with most later software. + + Not supported here are the unique instruction set of the low-end + Model 1, the unusual extended instructions provided on some Model 4 and + Model 50 configurations, or the only partially compatible instruction + set and extended addressing modes of Interdata's 32-bit series. + +***************************************************************************/ + +#include "emu.h" +#include "dasm16.h" + +interdata16_disassembler::interdata16_disassembler() + : util::disasm_interface() +{ +} + +u32 interdata16_disassembler::opcode_alignment() const +{ + return 2; +} + +namespace { + +static constexpr offs_t STEP_COND = interdata16_disassembler::STEP_COND; +static constexpr offs_t STEP_OVER = interdata16_disassembler::STEP_OVER; +static constexpr offs_t STEP_OUT = interdata16_disassembler::STEP_OUT; + +using namespace std::literals; + +static const std::pair<std::string_view, offs_t> s_inst_table[0x100] = +{ + // 00-0F + { {}, 0 }, + { "BALR"sv, STEP_OVER }, + { "BTCR"sv, STEP_COND }, + { "BFCR"sv, STEP_COND }, + { "NHR"sv, 0 }, + { "CLHR"sv, 0 }, + { "OHR"sv, 0 }, + { "XHR"sv, 0 }, + { "LHR"sv, 0 }, + { "CHR"sv, 0 }, + { "AHR"sv, 0 }, + { "SHR"sv, 0 }, + { "MHR"sv, 0 }, + { "DHR"sv, 0 }, + { "ACHR"sv, 0 }, + { "SCHR"sv, 0 }, + + // 10-1F + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { "SETMR"sv, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + + // 20-2F + { "BTBS"sv, STEP_COND }, + { "BTFS"sv, STEP_COND }, + { "BFBS"sv, STEP_COND }, + { "BFFS"sv, STEP_COND }, + { "LIS"sv, 0 }, + { "LCS"sv, 0 }, + { "AIS"sv, 0 }, + { "SIS"sv, 0 }, + { "LER"sv, 0 }, + { "CER"sv, 0 }, + { "AER"sv, 0 }, + { "SER"sv, 0 }, + { "MER"sv, 0 }, + { "DER"sv, 0 }, + { "FXR"sv, 0 }, + { "FLR"sv, 0 }, + + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { "LPSR"sv, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { "LDR"sv, 0 }, + { "CDR"sv, 0 }, + { "ADR"sv, 0 }, + { "SDR"sv, 0 }, + { "MDR"sv, 0 }, + { "DDR"sv, 0 }, + { "FXDR"sv, 0 }, + { "FLDR"sv, 0 }, + + // 40-4F + { "STH"sv, 0 }, + { "BAL"sv, STEP_OVER }, + { "BTC"sv, STEP_COND }, + { "BFC"sv, STEP_COND }, + { "NH"sv, 0 }, + { "CLH"sv, 0 }, + { "OH"sv, 0 }, + { "XH"sv, 0 }, + { "LH"sv, 0 }, + { "CH"sv, 0 }, + { "AH"sv, 0 }, + { "SH"sv, 0 }, + { "MH"sv, 0 }, + { "DH"sv, 0 }, + { "ACH"sv, 0 }, + { "SCH"sv, 0 }, + + // 50-5F + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { "SETM"sv, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + + // 60-6F + { "STE"sv, 0 }, + { "AHM"sv, 0 }, + { {}, 0 }, + { {}, 0 }, + { "ATL"sv, 0 }, + { "ABL"sv, 0 }, + { "RTL"sv, 0 }, + { "RBL"sv, 0 }, + { "LE"sv, 0 }, + { "CE"sv, 0 }, + { "AE"sv, 0 }, + { "SE"sv, 0 }, + { "ME"sv, 0 }, + { "DE"sv, 0 }, + { {}, 0 }, + { {}, 0 }, + + // 70-7F + { "STD"sv, 0 }, + { "STME"sv, 0 }, + { "LME", 0 }, + { "LPS", 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { "LD"sv, 0 }, + { "CD"sv, 0 }, + { "AD"sv, 0 }, + { "SD"sv, 0 }, + { "MD"sv, 0 }, + { "DD"sv, 0 }, + { {}, 0 }, + { {}, 0 }, + + // 80-8F + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + + // 90-9F + { "SRLS"sv, 0 }, + { "SLLS"sv, 0 }, + { "STBR"sv, 0 }, + { "LBR"sv, 0 }, + { "EXBR"sv, 0 }, + { "EPSR"sv, 0 }, + { "WBR"sv, 0 }, + { "RBR"sv, 0 }, + { "WHR"sv, 0 }, + { "RHR"sv, 0 }, + { "WDR"sv, 0 }, + { "RDR"sv, 0 }, + { "MHUR"sv, 0 }, + { "SSR"sv, 0 }, + { "OCR"sv, 0 }, + { "AIR"sv, 0 }, + + // A0-AF + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + + // B0-BF + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + + // C0-CF + { "BXH"sv, 0 }, + { "BXLE"sv, 0 }, + { "LPSW"sv, STEP_OUT }, + { "THI"sv, 0 }, + { "NHI"sv, 0 }, + { "CLHI"sv, 0 }, + { "OHI"sv, 0 }, + { "XHI"sv, 0 }, + { "LHI"sv, 0 }, + { "CHI"sv, 0 }, + { "AHI"sv, 0 }, + { "SHI"sv, 0 }, + { "SRHL"sv, 0 }, + { "SLHL"sv, 0 }, + { "SRHA"sv, 0 }, + { "SLHA"sv, 0 }, + + // D0-DF + { "STM"sv, 0 }, + { "LM"sv, 0 }, + { "STB"sv, 0 }, + { "LB"sv, 0 }, + { "CLB"sv, 0 }, + { "AL"sv, 0 }, + { "WB"sv, 0 }, + { "RB"sv, 0 }, + { "WH"sv, 0 }, + { "RH"sv, 0 }, + { "WD"sv, 0 }, + { "RD"sv, 0 }, + { "MHU"sv, 0 }, + { "SS"sv, 0 }, + { "OC"sv, 0 }, + { "AI"sv, 0 }, + + // E0-EF + { {}, 0 }, + { "SVC"sv, STEP_OVER }, + { "SINT"sv, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { "RRL"sv, 0 }, + { "RLL"sv, 0 }, + { "SRL"sv, 0 }, + { "SLL"sv, 0 }, + { "SRA"sv, 0 }, + { "SLA"sv, 0 }, + + // F0-FF + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 }, + { {}, 0 } +}; + +static const std::string_view s_b_mnemonics[32] = +{ + "NOP"sv, "BM"sv, "BP"sv, "BNZ"sv, "BO"sv, {}, {}, {}, "BC"sv, {}, {}, {}, {}, {}, {}, {}, + "B"sv, "BNM"sv, "BNP"sv, "BZ"sv, "BNO"sv, {}, {}, {}, "BNC"sv, {}, {}, {}, {}, {}, {}, {} +}; + +} // anonymous namespace + +void interdata16_disassembler::format_s16(std::ostream &stream, s16 halfword) +{ + if (halfword < 0) + { + stream << '-'; + halfword = -halfword; + } + if (u16(halfword) <= 9) + util::stream_format(stream, "%d", halfword); + else + util::stream_format(stream, "X'%X'", u16(halfword)); +} + +offs_t interdata16_disassembler::disassemble(std::ostream &stream, offs_t pc, const interdata16_disassembler::data_buffer &opcodes, const interdata16_disassembler::data_buffer ¶ms) +{ + const u16 i = opcodes.r16(pc); + auto const inst = s_inst_table[BIT(i, 8, 8)]; + offs_t flags = inst.second; + if (inst.first.empty()) + { + // Illegal opcodes + util::stream_format(stream, "%-6sX'%04X'", "DC", i); + return 2 | SUPPORTED; + } + else if ((i & 0xfc00) == 0x2000) + { + // Short conditional branches + const std::string_view bm = s_b_mnemonics[(i & 0x0200) >> 5 | (i & 0x00f0) >> 4]; + if (!bm.empty()) + util::stream_format(stream, "%-6sX'%04X'", util::string_format("%sS", bm), (BIT(i, 8) ? pc + BIT(i, 0, 4) * 2 : pc - BIT(i, 0, 4) * 2) & 0xffff); + else + util::stream_format(stream, "%-6s%d,%d", inst.first, BIT(i, 4, 4), BIT(i, 0, 4)); + if (BIT(i, 4, 4) == 0) + flags = 0; + return 2 | flags | SUPPORTED; + } + else + { + if ((i & 0xbe00) == 0x0200) + { + // Conditional branches + const std::string_view bm = s_b_mnemonics[BIT(i, 4, 5)]; + if (!bm.empty()) + { + if (BIT(i, 14)) + util::stream_format(stream, "%-6s", bm); + else + util::stream_format(stream, "%-6s", util::string_format("%sR", bm)); + if (BIT(i, 4, 4) == 0) + flags = 0; + } + else + util::stream_format(stream, "%-6s%d,", inst.first, BIT(i, 4, 4)); + } + else if ((i & 0xbf00) == 0x3300 || (i & 0xdf00) == 0xc200 || (i & 0xff00) == 0xd500) // LPS(R), LPSW, SINT, AL + util::stream_format(stream, "%-6s", inst.first, BIT(i, 4, 4)); + else if ((i & 0xff00) == 0xe100) // SVC + util::stream_format(stream, "%-6s%d,", inst.first, BIT(i, 4, 4)); + else + util::stream_format(stream, "%-6sR%d,", inst.first, BIT(i, 4, 4)); + + if (BIT(i, 14)) + { + // RX or RI + if (BIT(i, 0, 4) != 0) + { + format_s16(stream, opcodes.r16(pc + 2)); + util::stream_format(stream, "(R%d)", BIT(i, 0, 4)); + } + else if ((i >= 0xc900 && i < 0xd000) || i >= 0xea00) + format_s16(stream, opcodes.r16(pc + 2)); + else + util::stream_format(stream, "X'%04X'", opcodes.r16(pc + 2)); + return 4 | flags | SUPPORTED; + } + else + { + // RR or SF + if ((i & 0xf800) == 0x2000 || (i & 0xfe00) == 0x9000) + util::stream_format(stream, "%d", BIT(i, 0, 4)); + else + util::stream_format(stream, "R%d", BIT(i, 0, 4)); + return 2 | flags | SUPPORTED; + } + } +} diff --git a/src/devices/cpu/interdata16/dasm16.h b/src/devices/cpu/interdata16/dasm16.h new file mode 100644 index 00000000000..d21e13d2630 --- /dev/null +++ b/src/devices/cpu/interdata16/dasm16.h @@ -0,0 +1,25 @@ +// license:BSD-3-Clause +// copyright-holders:AJR + +#ifndef MAME_CPU_INTERDATA16_DASM16_H +#define MAME_CPU_INTERDATA16_DASM16_H + +#pragma once + +class interdata16_disassembler : public util::disasm_interface +{ +public: + // construction/destruction + interdata16_disassembler(); + +protected: + // util::disasm_interface overrides + virtual u32 opcode_alignment() const override; + virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; + +private: + // formatting helpers + static void format_s16(std::ostream &stream, s16 halfword); +}; + +#endif // MAME_CPU_INTERDATA16_DASM16_H diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index 11ee3da3d31..ae0ed8369de 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -76,6 +76,7 @@ using util::BIT; #include "cpu/i960/i960dis.h" #include "cpu/ibm1800/ibm1800d.h" #include "cpu/ie15/ie15dasm.h" +#include "cpu/interdata16/dasm16.h" #include "cpu/jaguar/jagdasm.h" #include "cpu/ks0164/ks0164d.h" #include "cpu/lc57/lc57d.h" @@ -484,6 +485,7 @@ static const dasm_table_entry dasm_table[] = { "ibm1130", be, -1, []() -> util::disasm_interface * { return new ibm1130_disassembler; } }, { "ibm1800", be, -1, []() -> util::disasm_interface * { return new ibm1800_disassembler; } }, { "ie15", le, 0, []() -> util::disasm_interface * { return new ie15_disassembler; } }, + { "interdata16", be, 0, []() -> util::disasm_interface * { return new interdata16_disassembler; } }, { "jaguardsp", be, 0, []() -> util::disasm_interface * { return new jaguar_disassembler(jaguar_disassembler::variant::DSP); } }, { "jaguargpu", be, 0, []() -> util::disasm_interface * { return new jaguar_disassembler(jaguar_disassembler::variant::GPU); } }, { "konami", be, 0, []() -> util::disasm_interface * { return new konami_disassembler; } }, |