summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2019-12-30 19:15:31 -0500
committer AJR <ajrhacker@users.noreply.github.com>2019-12-30 19:15:31 -0500
commitf48f57ef81e37e6c12e777a68dbd9a00e59f11b4 (patch)
treeb73173e30277373c08b7580c60d7499a15eb79a0
parentb052050f3cf697baf22528012829c5539bf27ca0 (diff)
Add new disassembler for WE32100 architecture
New machines marked as NOT_WORKING ---------------------------------- AT&T 3B2/300 [Bitsavers] New clones marked as NOT_WORKING -------------------------------- AT&T 3B2/310 [Bitsavers] AT&T 3B2/400 [Bitsavers]
-rw-r--r--scripts/src/cpu.lua17
-rw-r--r--scripts/target/mame/mess.lua2
-rw-r--r--src/devices/cpu/we32000/we32100.cpp113
-rw-r--r--src/devices/cpu/we32000/we32100.h59
-rw-r--r--src/devices/cpu/we32000/we32100d.cpp859
-rw-r--r--src/devices/cpu/we32000/we32100d.h36
-rw-r--r--src/mame/mame.lst5
-rw-r--r--src/mame/mess.flt1
-rw-r--r--src/tools/unidasm.cpp2
9 files changed, 1094 insertions, 0 deletions
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua
index 2a83be1f0ad..08ab14077a2 100644
--- a/scripts/src/cpu.lua
+++ b/scripts/src/cpu.lua
@@ -3031,3 +3031,20 @@ if (CPUS["PACE"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/pace/pacedasm.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/pace/pacedasm.h")
end
+
+--------------------------------------------------
+-- AT&T WE32000/WE32100/WE32200
+--@src/devices/cpu/we32000/we32100.h,CPUS["WE32000"] = true
+--------------------------------------------------
+
+if (CPUS["WE32000"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/cpu/we32000/we32100.cpp",
+ MAME_DIR .. "src/devices/cpu/we32000/we32100.h",
+ }
+end
+
+if (CPUS["WE32000"]~=null or _OPTIONS["with-tools"]) then
+ table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/we32000/we32100d.cpp")
+ table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/we32000/we32100d.h")
+end
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 127eaa0efa4..44d51e4577d 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -150,6 +150,7 @@ CPUS["FR"] = true
CPUS["DSP56000"] = true
CPUS["VT50"] = true
CPUS["PACE"] = true
+CPUS["WE32000"] = true
--------------------------------------------------
-- specify available sound cores; some of these are
@@ -1752,6 +1753,7 @@ files {
createMESSProjects(_target, _subtarget, "att")
files {
+ MAME_DIR .. "src/mame/drivers/att3b2.cpp",
MAME_DIR .. "src/mame/drivers/att4425.cpp",
MAME_DIR .. "src/mame/drivers/att610.cpp",
MAME_DIR .. "src/mame/drivers/att630.cpp",
diff --git a/src/devices/cpu/we32000/we32100.cpp b/src/devices/cpu/we32000/we32100.cpp
new file mode 100644
index 00000000000..1d4b5fbcd04
--- /dev/null
+++ b/src/devices/cpu/we32000/we32100.cpp
@@ -0,0 +1,113 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ AT&T WE32100 32-Bit Microprocessor
+
+ Currently this device is just a stub with no actual execution core.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "we32100.h"
+#include "we32100d.h"
+
+// device type definitions
+DEFINE_DEVICE_TYPE(WE32100, we32100_device, "we32100", "AT&T WE32100")
+
+we32100_device::we32100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : cpu_device(mconfig, WE32100, tag, owner, clock)
+ , m_space_config("program", ENDIANNESS_BIG, 32, 32, 0)
+ , m_space(nullptr)
+ , m_cache(nullptr)
+ , m_r{0}
+ , m_icount(0)
+{
+}
+
+std::unique_ptr<util::disasm_interface> we32100_device::create_disassembler()
+{
+ return std::make_unique<we32100_disassembler>();
+}
+
+device_memory_interface::space_config_vector we32100_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_space_config),
+ };
+}
+
+void we32100_device::device_start()
+{
+ m_space = &space(AS_PROGRAM);
+ m_cache = m_space->cache<2, 0, ENDIANNESS_BIG>();
+
+ set_icountptr(m_icount);
+
+ state_add(STATE_GENPC, "GENPC", m_r[15]).noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_r[15]).noshow();
+ state_add(STATE_GENFLAGS, "CURFLAGS", m_r[11]).noshow().formatstr("%23s");
+ for (int i = 0; i < 9; i++)
+ state_add(WE_R0 + i, string_format("r%d", i).c_str(), m_r[i]);
+ for (int i = 9; i < 15; i++)
+ state_add(WE_R0 + i, string_format("r%d", i).c_str(), m_r[i]).noshow();
+ state_add(WE_FP, "FP", m_r[9]);
+ state_add(WE_AP, "AP", m_r[10]);
+ state_add(WE_PSW, "PSW", m_r[11]);
+ state_add(WE_SP, "SP", m_r[12]);
+ state_add(WE_PCBP, "PCBP", m_r[13]);
+ state_add(WE_ISP, "ISP", m_r[14]);
+ state_add(WE_PC, "PC", m_r[15]);
+
+ save_item(NAME(m_r));
+}
+
+void we32100_device::device_reset()
+{
+ // TODO
+}
+
+void we32100_device::execute_run()
+{
+ // On-reset sequence: load PCBP, then load PSW, PC and SP from there
+ m_r[13] = m_space->read_dword(0x00000080);
+ m_r[11] = m_space->read_dword(m_r[13]);
+ m_r[15] = m_space->read_dword(m_r[13] + 4);
+ m_r[12] = m_space->read_dword(m_r[13] + 8);
+
+ debugger_instruction_hook(m_r[15]);
+
+ m_icount = 0;
+}
+
+void we32100_device::execute_set_input(int inputnum, int state)
+{
+ // TODO
+}
+
+void we32100_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ str = string_format("%c%c%c%c%c%c%c%c%c<%X>%c(%c)%c%c<%X>%c%c",
+ BIT(m_r[11], 25) ? 'f' : '.',
+ BIT(m_r[11], 24) ? 'Q' : '.',
+ BIT(m_r[11], 23) ? 'c' : '.',
+ BIT(m_r[11], 22) ? 'O' : '.',
+ BIT(m_r[11], 21) ? 'N' : '.',
+ BIT(m_r[11], 20) ? 'Z' : '.',
+ BIT(m_r[11], 19) ? 'V' : '.',
+ BIT(m_r[11], 18) ? 'C' : '.',
+ BIT(m_r[11], 17) ? 'T' : '.',
+ (m_r[11] & 0x0001e000) >> 13,
+ "KESU"[(m_r[11] & 0x00001800) >> 11],
+ "KESU"[(m_r[11] & 0x00000600) >> 9],
+ BIT(m_r[11], 8) ? 'R' : '.',
+ BIT(m_r[11], 7) ? 'I' : '.',
+ (m_r[11] & 0x00000078) >> 3,
+ BIT(m_r[11], 2) ? 'T' : '.',
+ "RPSN"[m_r[11] & 0x00000003]);
+ break;
+ }
+}
diff --git a/src/devices/cpu/we32000/we32100.h b/src/devices/cpu/we32000/we32100.h
new file mode 100644
index 00000000000..54e1edc4a3e
--- /dev/null
+++ b/src/devices/cpu/we32000/we32100.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ AT&T WE32100 32-Bit Microprocessor
+
+***************************************************************************/
+
+#ifndef MAME_CPU_WE32000_WE32100_H
+#define MAME_CPU_WE32000_WE32100_H
+
+#pragma once
+
+
+class we32100_device : public cpu_device
+{
+public:
+ enum {
+ WE_R0, WE_R1, WE_R2, WE_R3, WE_R4, WE_R5, WE_R6, WE_R7, WE_R8,
+ WE_R9, WE_R10, WE_R11, WE_R12, WE_R13, WE_R14, WE_R15,
+ WE_FP, WE_AP, WE_PSW, WE_SP, WE_PCBP, WE_ISP, WE_PC
+ };
+
+ // construction/destruction
+ we32100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_execute_interface overrides
+ virtual void execute_run() override;
+ virtual void execute_set_input(int inputnum, int state) override;
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
+ // device_state_interface overrides
+ void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+private:
+ // address space
+ address_space_config m_space_config;
+ address_space *m_space;
+ memory_access_cache<2, 0, ENDIANNESS_BIG> *m_cache;
+
+ // internal state
+ u32 m_r[16];
+ s32 m_icount;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(WE32100, we32100_device)
+
+#endif // MAME_CPU_WE32000_WE32100_H
diff --git a/src/devices/cpu/we32000/we32100d.cpp b/src/devices/cpu/we32000/we32100d.cpp
new file mode 100644
index 00000000000..c33aba03290
--- /dev/null
+++ b/src/devices/cpu/we32000/we32100d.cpp
@@ -0,0 +1,859 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Disassembler for AT&T's WE32100 processor.
+
+ Operands are formatted similarly to AT&T's m32dis. Note that operand
+ encoding is little-endian even though memory accesses are big-endian.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "we32100d.h"
+
+
+//**************************************************************************
+// WE32100 DISASSEMBLER
+//**************************************************************************
+
+we32100_disassembler::we32100_disassembler()
+ : util::disasm_interface()
+{
+}
+
+u32 we32100_disassembler::opcode_alignment() const
+{
+ return 1;
+}
+
+const char *const we32100_disassembler::s_rnames[16] = {
+ "r0",
+ "r1",
+ "r2",
+ "r3",
+ "r4",
+ "r5",
+ "r6",
+ "r7",
+ "r8",
+ "fp", // Frame Pointer
+ "ap", // Argument Pointer
+ "psw", // Processor Status Word (privileged)
+ "sp", // Stack Pointer
+ "pcbp", // Process Control Block Pointer (privileged)
+ "isp", // Interrupt Stack Pointer (privileged)
+ "pc" // Program Counter
+};
+
+void we32100_disassembler::format_signed(std::ostream &stream, s32 x)
+{
+ if (x == 0)
+ stream << "0";
+ else if (x > 0)
+ util::stream_format(stream, "0x%x", x);
+ else
+ util::stream_format(stream, "-0x%x", u32(-x));
+}
+
+void we32100_disassembler::dasm_am(std::ostream &stream, offs_t &pc, const we32100_disassembler::data_buffer &opcodes, u8 n, bool dst)
+{
+ switch (n & 0xf0)
+ {
+ case 0x00: case 0x10: case 0x20: case 0x30: case 0xf0:
+ if (dst)
+ util::stream_format(stream, "invalid(0x%02x)", n);
+ else
+ {
+ stream << "&";
+ format_signed(stream, s8(n));
+ }
+ break;
+
+ case 0x40:
+ if (n != 0x4f)
+ util::stream_format(stream, "%%%s", s_rnames[n & 0x0f]);
+ else if (dst)
+ util::stream_format(stream, "invalid(0x%02x)", n);
+ else
+ {
+ util::stream_format(stream, "&0x%08x", swapendian_int32(opcodes.r32(pc)));
+ pc += 4;
+ }
+ break;
+
+ case 0x50:
+ if (n != 0x5b && n != 0x5f)
+ util::stream_format(stream, "(%%%s)", s_rnames[n & 0x0f]);
+ else if (n == 0x5b || dst)
+ util::stream_format(stream, "invalid(0x%02x)", n);
+ else
+ {
+ util::stream_format(stream, "&0x%04x", swapendian_int16(opcodes.r16(pc)));
+ pc += 2;
+ }
+ break;
+
+ case 0x60:
+ if (n != 0x6f)
+ {
+ format_signed(stream, n & 0x0f);
+ stream << "(%fp)";
+ }
+ else if (dst)
+ util::stream_format(stream, "invalid(0x%02x)", n);
+ else
+ util::stream_format(stream, "&0x%02x", opcodes.r8(pc++));
+ break;
+
+ case 0x70:
+ if (n != 0x7f)
+ {
+ format_signed(stream, n & 0x0f);
+ stream << "(%ap)";
+ }
+ else
+ {
+ util::stream_format(stream, "$0x%08x", swapendian_int32(opcodes.r32(pc)));
+ pc += 4;
+ }
+ break;
+
+ case 0x80: case 0x90:
+ if ((n & 0x0f) == 0x0b)
+ util::stream_format(stream, "invalid(0x%02x)", n);
+ else
+ {
+ if (BIT(n, 4))
+ stream << "*";
+ format_signed(stream, s32(swapendian_int32(opcodes.r32(pc))));
+ pc += 4;
+ util::stream_format(stream, "(%%%s)", s_rnames[n & 0x0f]);
+ }
+ break;
+
+ case 0xa0: case 0xb0:
+ if ((n & 0x0f) == 0x0b)
+ util::stream_format(stream, "invalid(0x%02x)", n);
+ else
+ {
+ if (BIT(n, 4))
+ stream << "*";
+ format_signed(stream, s16(swapendian_int16(opcodes.r16(pc))));
+ pc += 2;
+ util::stream_format(stream, "(%%%s)", s_rnames[n & 0x0f]);
+ }
+ break;
+
+ case 0xc0: case 0xd0:
+ if ((n & 0x0f) == 0x0b)
+ util::stream_format(stream, "invalid(0x%02x)", n);
+ else
+ {
+ if (BIT(n, 4))
+ stream << "*";
+ format_signed(stream, s8(opcodes.r8(pc++)));
+ util::stream_format(stream, "(%%%s)", s_rnames[n & 0x0f]);
+ }
+ break;
+
+ case 0xe0:
+ if (n == 0xef)
+ {
+ util::stream_format(stream, "*$0x%08x", swapendian_int32(opcodes.r32(pc)));
+ pc += 4;
+ }
+ else if (BIT(n, 3) || (n & 0x03) == 0x01)
+ util::stream_format(stream, "reserved(0x%02x)", n);
+ else
+ {
+ if (!BIT(n, 0))
+ util::stream_format(stream, "{%cword}", BIT(n, 2) ? 's' : 'u');
+ else if (!BIT(n, 1))
+ util::stream_format(stream, "{%chalf}", BIT(n, 2) ? 's' : 'u');
+ else
+ util::stream_format(stream, "{%cbyte}", BIT(n, 2) ? 's' : 'u');
+ u8 m = opcodes.r8(pc++);
+ dasm_am(stream, pc, opcodes, m, dst);
+ }
+ break;
+ }
+}
+
+void we32100_disassembler::dasm_src(std::ostream &stream, offs_t &pc, const we32100_disassembler::data_buffer &opcodes)
+{
+ u8 n = opcodes.r8(pc++);
+ dasm_am(stream, pc, opcodes, n, false);
+}
+
+void we32100_disassembler::dasm_srcw(std::ostream &stream, offs_t &pc, const we32100_disassembler::data_buffer &opcodes)
+{
+ u8 n = opcodes.r8(pc++);
+ if (n < 0xe0 || n >= 0xef)
+ dasm_am(stream, pc, opcodes, n, false);
+ else
+ util::stream_format(stream, "invalid(0x%02x)", n);
+}
+
+void we32100_disassembler::dasm_dst(std::ostream &stream, offs_t &pc, const we32100_disassembler::data_buffer &opcodes)
+{
+ u8 n = opcodes.r8(pc++);
+ dasm_am(stream, pc, opcodes, n, true);
+}
+
+void we32100_disassembler::dasm_dstw(std::ostream &stream, offs_t &pc, const we32100_disassembler::data_buffer &opcodes)
+{
+ u8 n = opcodes.r8(pc++);
+ if (n < 0xe0 || n == 0xef)
+ dasm_am(stream, pc, opcodes, n, true);
+ else
+ util::stream_format(stream, "invalid(0x%02x)", n);
+}
+
+void we32100_disassembler::dasm_ea(std::ostream &stream, offs_t &pc, const we32100_disassembler::data_buffer &opcodes)
+{
+ u8 n = opcodes.r8(pc++);
+ if (n >= 0x50 && (n < 0xe0 || n == 0xef) && n != 0x5f && n != 0x6f)
+ dasm_am(stream, pc, opcodes, n, false);
+ else
+ util::stream_format(stream, "invalid(0x%02x)", n);
+}
+
+void we32100_disassembler::dasm_sr(std::ostream &stream, offs_t &pc, const we32100_disassembler::data_buffer &opcodes)
+{
+ u8 n = opcodes.r8(pc++);
+ if (n >= 0x40 && n <= 0x49)
+ util::stream_format(stream, "%%%s", s_rnames[n & 0x0f]);
+ else
+ util::stream_format(stream, "invalid(0x%02x)", n);
+}
+
+void we32100_disassembler::dasm_bdisp(std::ostream &stream, offs_t &pc, const we32100_disassembler::data_buffer &opcodes, bool byte)
+{
+ u32 ppc = pc - 1;
+ int disp;
+ if (byte)
+ {
+ disp = s8(opcodes.r8(pc++));
+ }
+ else
+ {
+ disp = s16(swapendian_int16(opcodes.r16(pc)));
+ pc += 2;
+ }
+ format_signed(stream, disp);
+ util::stream_format(stream, " <%x>", u32(ppc + disp));
+}
+
+offs_t we32100_disassembler::dasm_30xx(std::ostream &stream, offs_t &pc, const we32100_disassembler::data_buffer &opcodes)
+{
+ u32 flags = SUPPORTED;
+ u8 op = opcodes.r8(pc++);
+
+ switch (op)
+ { case 0x09:
+ stream << "MVERNO";
+ break;
+
+ case 0x0d:
+ stream << "ENBVJMP"; // (privileged)
+ break;
+
+ case 0x13:
+ stream << "DISVJMP"; // (privileged)
+ break;
+
+ case 0x19:
+ stream << "MOVBLW";
+ break;
+
+ case 0x1f:
+ stream << "STREND";
+ break;
+
+ case 0x2f:
+ stream << "INTACK"; // (privileged)
+ break;
+
+ case 0x35:
+ stream << "STRCPY";
+ break;
+
+ case 0x45:
+ stream << "RETG";
+ flags |= STEP_OUT;
+ break;
+
+ case 0x61:
+ stream << "GATE";
+ flags |= STEP_OVER;
+ break;
+
+ case 0xac:
+ stream << "CALLPS"; // (privileged)
+ flags |= STEP_OVER;
+ break;
+
+ case 0xc8:
+ stream << "RETPS"; // (privileged)
+ flags |= STEP_OUT;
+ break;
+
+ default:
+ stream << "reserved";
+ break;
+ }
+
+ return flags;
+}
+
+offs_t we32100_disassembler::disassemble(std::ostream &stream, offs_t pc, const we32100_disassembler::data_buffer &opcodes, const we32100_disassembler::data_buffer &params)
+{
+ offs_t ppc = pc;
+ u32 flags = SUPPORTED;
+ u8 op = opcodes.r8(pc++);
+
+ if ((op & 0x03) == 0x01
+ || op == 0x00
+ || op == 0x26
+ || (op & 0xfa) == 0x0a
+ || (op & 0xfd) == 0x12
+ || (op & 0xfe) == 0x1a
+ || (op & 0xfc) == 0x98
+ || (op & 0xde) == 0xc2
+ || (op & 0xfe) == 0xd6
+ || (op & 0xfe) == 0xda)
+ {
+ stream << "reserved";
+ }
+ else switch (op & 0xfc)
+ {
+ case 0x00: case 0x04:
+ if (!BIT(op, 1))
+ {
+ util::stream_format(stream, "%-8s", "MOVAW");
+ dasm_ea(stream, pc, opcodes);
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ }
+ else if (!BIT(op, 0))
+ {
+ util::stream_format(stream, "%-8s0x%08x,", BIT(op, 4) ? "SPOPRT" : "SPOPRD", swapendian_int32(opcodes.r32(pc)));
+ pc += 4;
+ dasm_src(stream, pc, opcodes);
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s0x%08x,", BIT(op, 4) ? "SPOPT2" : "SPOPD2", swapendian_int32(opcodes.r32(pc)));
+ pc += 4;
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ }
+ break;
+
+ case 0x08:
+ stream << "RET";
+ flags |= STEP_OUT;
+ break;
+
+ case 0x0c:
+ util::stream_format(stream, "%-8s", "MOVTRW"); // (privileged)
+ dasm_src(stream, pc, opcodes); // or effective address?
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0x10:
+ if (!BIT(op, 1))
+ {
+ util::stream_format(stream, "%-8s", "SAVE");
+ dasm_sr(stream, pc, opcodes);
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s0x%08x,", "SPOPWD", swapendian_int32(opcodes.r32(pc)));
+ pc += 4;
+ dasm_dst(stream, pc, opcodes);
+ }
+ break;
+
+ case 0x14:
+ if (!BIT(op, 1))
+ {
+ util::stream_format(stream, "%-8s0x%02x", "EXTOP", opcodes.r8(pc++));
+ flags |= STEP_OVER;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s0x%08x,", "SPOPWT", swapendian_int32(opcodes.r32(pc)));
+ pc += 4;
+ dasm_dst(stream, pc, opcodes);
+ }
+ break;
+
+ case 0x18:
+ util::stream_format(stream, "%-8s", "RESTORE");
+ dasm_sr(stream, pc, opcodes);
+ break;
+
+ case 0x1c:
+ util::stream_format(stream, "%-8s", util::string_format("SWAP%cI", "W?HB"[op & 0x03]));
+ dasm_ea(stream, pc, opcodes);
+ break;
+
+ case 0x20:
+ if (!BIT(op, 1))
+ {
+ util::stream_format(stream, "%-8s", "POPW");
+ dasm_dstw(stream, pc, opcodes);
+ }
+ else if (!BIT(op, 0))
+ {
+ util::stream_format(stream, "%-8s0x%08x,", "SPOPRS", swapendian_int32(opcodes.r32(pc)));
+ pc += 4;
+ dasm_src(stream, pc, opcodes);
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s0x%08x,", "SPOPS2", swapendian_int32(opcodes.r32(pc)));
+ pc += 4;
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ }
+ break;
+
+ case 0x24:
+ if (!BIT(op, 1))
+ {
+ util::stream_format(stream, "%-8s", "JMP");
+ dasm_ea(stream, pc, opcodes);
+ }
+ else
+ stream << "CFLUSH";
+ break;
+
+ case 0x28:
+ util::stream_format(stream, "%-8s", util::string_format("TST%c", "W?HB"[op & 0x03]));
+ dasm_src(stream, pc, opcodes);
+ break;
+
+ case 0x2c:
+ if (!BIT(op, 1))
+ {
+ util::stream_format(stream, "%-8s", "CALL");
+ dasm_ea(stream, pc, opcodes);
+ stream << ",";
+ dasm_ea(stream, pc, opcodes);
+ flags |= STEP_OVER;
+ }
+ else if (!BIT(op, 0))
+ {
+ stream << "BPT";
+ flags |= STEP_OVER;
+ }
+ else
+ {
+ stream << "WAIT"; // (privileged)
+ }
+ break;
+
+ case 0x30:
+ if (!BIT(op, 1))
+ flags = dasm_30xx(stream, pc, opcodes);
+ else if (!BIT(op, 0))
+ {
+ util::stream_format(stream, "%-8s0x%08x", "SPOP", swapendian_int32(opcodes.r32(pc)));
+ pc += 4;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s0x%08x,", "SPOPWS", swapendian_int32(opcodes.r32(pc)));
+ pc += 4;
+ dasm_dst(stream, pc, opcodes);
+ }
+ break;
+
+ case 0x34:
+ if (!BIT(op, 1))
+ {
+ util::stream_format(stream, "%-8s", "JSB");
+ dasm_ea(stream, pc, opcodes);
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BSBB" : "BSBH");
+ dasm_bdisp(stream, pc, opcodes, BIT(op, 0));
+ }
+ flags |= STEP_OVER;
+ break;
+
+ case 0x38:
+ util::stream_format(stream, "%-8s", util::string_format("BIT%c", "W?HB"[op & 0x03]));
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ break;
+
+ case 0x3c:
+ util::stream_format(stream, "%-8s", util::string_format("CMP%c", "W?HB"[op & 0x03]));
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ break;
+
+ case 0x40:
+ if (!BIT(op, 1))
+ {
+ stream << "RGEQ";
+ flags |= STEP_OUT;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BGEB" : "BGEH");
+ dasm_bdisp(stream, pc, opcodes, BIT(op, 0));
+ }
+ break;
+
+ case 0x44: case 0x54:
+ if (!BIT(op, 1))
+ {
+ stream << "RGTR";
+ if (BIT(op, 4))
+ stream << "U";
+ flags |= STEP_OUT;
+ }
+ else
+ {
+ if (BIT(op, 4))
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BGUB" : "BGUH");
+ else
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BGB" : "BGH");
+ dasm_bdisp(stream, pc, opcodes, BIT(op, 0));
+ }
+ break;
+
+ case 0x48:
+ if (!BIT(op, 1))
+ {
+ stream << "RLSS";
+ flags |= STEP_OUT;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BLB" : "BLH");
+ dasm_bdisp(stream, pc, opcodes, BIT(op, 0));
+ }
+ break;
+
+ case 0x4c: case 0x5c:
+ if (!BIT(op, 1))
+ {
+ stream << "RLEQ";
+ if (BIT(op, 4))
+ stream << "U";
+ flags |= STEP_OUT;
+ }
+ else
+ {
+ if (BIT(op, 4))
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BLEUB" : "BLEUH");
+ else
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BLEB" : "BLEH");
+ dasm_bdisp(stream, pc, opcodes, BIT(op, 0));
+ }
+ break;
+
+ case 0x50:
+ if (!BIT(op, 1))
+ {
+ stream << "RCC";
+ flags |= STEP_OUT;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BCC" : "BCC");
+ dasm_bdisp(stream, pc, opcodes, BIT(op, 0));
+ }
+ break;
+
+ case 0x58:
+ if (!BIT(op, 1))
+ {
+ stream << "RCS";
+ flags |= STEP_OUT;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BCSB" : "BCSH");
+ dasm_bdisp(stream, pc, opcodes, BIT(op, 0));
+ }
+ break;
+
+ case 0x60:
+ if (!BIT(op, 1))
+ {
+ stream << "RVS";
+ flags |= STEP_OUT;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BVCB" : "BVCH");
+ dasm_bdisp(stream, pc, opcodes, BIT(op, 0));
+ }
+ break;
+
+ case 0x64: case 0x74:
+ if (!BIT(op, 1))
+ {
+ stream << "RNEQ";
+ if (!BIT(op, 4))
+ stream << "U";
+ flags |= STEP_OUT;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BNEB" : "BNEH");
+ dasm_bdisp(stream, pc, opcodes, BIT(op, 0));
+ }
+ break;
+
+ case 0x68:
+ if (!BIT(op, 1))
+ {
+ stream << "RVS";
+ flags |= STEP_OUT;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BVSB" : "BVSH");
+ dasm_bdisp(stream, pc, opcodes, BIT(op, 0));
+ }
+ break;
+
+ case 0x6c: case 0x7c:
+ if (!BIT(op, 1))
+ {
+ stream << "REQL";
+ if (!BIT(op, 4))
+ stream << "U";
+ flags |= STEP_OUT;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BEB" : "BEH");
+ dasm_bdisp(stream, pc, opcodes, BIT(op, 0));
+ }
+ break;
+
+ case 0x70:
+ if (!BIT(op, 1))
+ stream << "NOP";
+ else if (BIT(op, 0))
+ util::stream_format(stream, "%-8s0x%02x", "NOP2", opcodes.r8(pc++));
+ else
+ {
+ util::stream_format(stream, "%-8s0x%04x", "NOP3", swapendian_int16(opcodes.r16(pc)));
+ pc += 2;
+ }
+ break;
+
+ case 0x78:
+ if (!BIT(op, 1))
+ {
+ stream << "RSB";
+ flags |= STEP_OUT;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(op, 0) ? "BRB" : "BRH");
+ dasm_bdisp(stream, pc, opcodes, BIT(op, 0));
+ }
+ break;
+
+ case 0x80:
+ util::stream_format(stream, "%-8s", util::string_format("CLR%c", "W?HB"[op & 0x03]));
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0x84:
+ util::stream_format(stream, "%-8s", util::string_format("MOV%c", "W?HB"[op & 0x03]));
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0x88:
+ util::stream_format(stream, "%-8s", util::string_format("MCOM%c", "W?HB"[op & 0x03]));
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0x8c:
+ util::stream_format(stream, "%-8s", util::string_format("MNEG%c", "W?HB"[op & 0x03]));
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0x90:
+ util::stream_format(stream, "%-8s", util::string_format("INC%c", "W?HB"[op & 0x03]));
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0x94:
+ util::stream_format(stream, "%-8s", util::string_format("DEC%c", "W?HB"[op & 0x03]));
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0x9c: case 0xdc:
+ util::stream_format(stream, "%-8s", util::string_format("ADD%c%d", "W?HB"[op & 0x03], BIT(op, 6) ? 3 : 2));
+ dasm_src(stream, pc, opcodes);
+ if (BIT(op, 6))
+ {
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ }
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0xa0:
+ util::stream_format(stream, "%-8s", "PUSHW");
+ dasm_srcw(stream, pc, opcodes);
+ break;
+
+ case 0xa4: case 0xe4:
+ util::stream_format(stream, "%-8s", util::string_format("MOD%c%d", "W?HB"[op & 0x03], BIT(op, 6) ? 3 : 2));
+ dasm_src(stream, pc, opcodes);
+ if (BIT(op, 6))
+ {
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ }
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0xa8: case 0xe8:
+ util::stream_format(stream, "%-8s", util::string_format("MUL%c%d", "W?HB"[op & 0x03], BIT(op, 6) ? 3 : 2));
+ dasm_src(stream, pc, opcodes);
+ if (BIT(op, 6))
+ {
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ }
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0xac: case 0xec:
+ util::stream_format(stream, "%-8s", util::string_format("DIV%c%d", "W?HB"[op & 0x03], BIT(op, 6) ? 3 : 2));
+ dasm_src(stream, pc, opcodes);
+ if (BIT(op, 6))
+ {
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ }
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0xb0: case 0xf0:
+ util::stream_format(stream, "%-8s", util::string_format("OR%c%d", "W?HB"[op & 0x03], BIT(op, 6) ? 3 : 2));
+ dasm_src(stream, pc, opcodes);
+ if (BIT(op, 6))
+ {
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ }
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0xb4: case 0xf4:
+ util::stream_format(stream, "%-8s", util::string_format("XOR%c%d", "W?HB"[op & 0x03], BIT(op, 6) ? 3 : 2));
+ dasm_src(stream, pc, opcodes);
+ if (BIT(op, 6))
+ {
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ }
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0xb8: case 0xf8:
+ util::stream_format(stream, "%-8s", util::string_format("AND%c%d", "W?HB"[op & 0x03], BIT(op, 6) ? 3 : 2));
+ dasm_src(stream, pc, opcodes);
+ if (BIT(op, 6))
+ {
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ }
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0xbc: case 0xfc:
+ util::stream_format(stream, "%-8s", util::string_format("SUB%c%d", "W?HB"[op & 0x03], BIT(op, 6) ? 3 : 2));
+ dasm_src(stream, pc, opcodes);
+ if (BIT(op, 6))
+ {
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ }
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0xc0: case 0xc4: case 0xd0: case 0xd4:
+ util::stream_format(stream, "%-8s", util::string_format("%c%cS%c3", BIT(op, 4) ? 'L' : 'A', BIT(op, 2) ? 'R' : 'L', "W?HB"[op & 0x03]));
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0xc8:
+ util::stream_format(stream, "%-8s", util::string_format("INS%c3", "W?HB"[op & 0x03]));
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0xcc:
+ util::stream_format(stream, "%-8s", util::string_format("EXT%c3", "W?HB"[op & 0x03]));
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0xd8:
+ util::stream_format(stream, "%-8s", "ROTW");
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_src(stream, pc, opcodes);
+ stream << ",";
+ dasm_dst(stream, pc, opcodes);
+ break;
+
+ case 0xe0:
+ util::stream_format(stream, "%-8s", "PUSHAW");
+ dasm_ea(stream, pc, opcodes);
+ break;
+ }
+
+ return flags | ((pc - ppc) & LENGTHMASK);
+}
diff --git a/src/devices/cpu/we32000/we32100d.h b/src/devices/cpu/we32000/we32100d.h
new file mode 100644
index 00000000000..1c287d85702
--- /dev/null
+++ b/src/devices/cpu/we32000/we32100d.h
@@ -0,0 +1,36 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_CPU_WE32000_WE32100D_H
+#define MAME_CPU_WE32000_WE32100D_H
+
+#pragma once
+
+class we32100_disassembler : public util::disasm_interface
+{
+public:
+ // construction/destruction
+ we32100_disassembler();
+
+protected:
+ // disassembler 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:
+ static const char *const s_rnames[16];
+
+ // internal helpers
+ void format_signed(std::ostream &stream, s32 x);
+ void dasm_am(std::ostream &stream, offs_t &pc, const data_buffer &opcodes, u8 n, bool dst);
+ void dasm_src(std::ostream &stream, offs_t &pc, const data_buffer &opcodes);
+ void dasm_srcw(std::ostream &stream, offs_t &pc, const data_buffer &opcodes);
+ void dasm_dst(std::ostream &stream, offs_t &pc, const data_buffer &opcodes);
+ void dasm_dstw(std::ostream &stream, offs_t &pc, const data_buffer &opcodes);
+ void dasm_ea(std::ostream &stream, offs_t &pc, const data_buffer &opcodes);
+ void dasm_sr(std::ostream &stream, offs_t &pc, const data_buffer &opcodes);
+ void dasm_bdisp(std::ostream &stream, offs_t &pc, const data_buffer &opcodes, bool byte);
+ offs_t dasm_30xx(std::ostream &stream, offs_t &pc, const data_buffer &opcodes);
+};
+
+#endif // MAME_CPU_WE32000_WE32100D_H
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 852d5ff126c..c8a442d5213 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -2971,6 +2971,11 @@ atrwild
atricmon
atrbonpk
+@source:att3b2.cpp
+3b2_300 //
+3b2_310 //
+3b2_400 //
+
@source:att4425.cpp
att4425 //
diff --git a/src/mame/mess.flt b/src/mame/mess.flt
index 37fe0f6bd21..875b99e6db8 100644
--- a/src/mame/mess.flt
+++ b/src/mame/mess.flt
@@ -83,6 +83,7 @@ atarist.cpp
atm.cpp
atom.cpp
atpci.cpp
+att3b2.cpp
att4425.cpp
att610.cpp
att630.cpp
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index fd8e932658c..6e899c4f88b 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -160,6 +160,7 @@ using util::BIT;
#include "cpu/v60/v60d.h"
#include "cpu/v810/v810dasm.h"
#include "cpu/vt50/vt50dasm.h"
+#include "cpu/we32000/we32100d.h"
#include "cpu/z180/z180dasm.h"
#include "cpu/z8/z8dasm.h"
#include "cpu/z80/z80dasm.h"
@@ -528,6 +529,7 @@ static const dasm_table_entry dasm_table[] =
{ "v810", le, 0, []() -> util::disasm_interface * { return new v810_disassembler; } },
{ "vt50", le, 0, []() -> util::disasm_interface * { return new vt50_disassembler; } },
{ "vt52", le, 0, []() -> util::disasm_interface * { return new vt52_disassembler; } },
+ { "we32100", be, 0, []() -> util::disasm_interface * { return new we32100_disassembler; } },
{ "x86_16", le, 0, []() -> util::disasm_interface * { i386_unidasm.mode = 16; return new i386_disassembler(&i386_unidasm); } },
{ "x86_32", le, 0, []() -> util::disasm_interface * { i386_unidasm.mode = 32; return new i386_disassembler(&i386_unidasm); } },
{ "x86_64", le, 0, []() -> util::disasm_interface * { i386_unidasm.mode = 64; return new i386_disassembler(&i386_unidasm); } },