summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2023-03-11 09:19:24 -0500
committer AJR <ajrhacker@users.noreply.github.com>2023-03-11 09:19:24 -0500
commit6543248641a27482ed059bd8676dc18ebec40406 (patch)
tree3a8004257fc51fab814d4242418e84a47c235509 /src
parentfa4ea8e951085ebd035385a9bf88e2322079c1f0 (diff)
unidasm: Add Interdata Series 16 disassembler
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/interdata16/dasm16.cpp428
-rw-r--r--src/devices/cpu/interdata16/dasm16.h25
-rw-r--r--src/tools/unidasm.cpp2
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 &params)
+{
+ 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 &params) 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; } },