summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/e132xs/e1dasm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/e132xs/e1dasm.cpp')
-rw-r--r--src/devices/cpu/e132xs/e1dasm.cpp1132
1 files changed, 1132 insertions, 0 deletions
diff --git a/src/devices/cpu/e132xs/e1dasm.cpp b/src/devices/cpu/e132xs/e1dasm.cpp
new file mode 100644
index 00000000000..fe8e64b4d9e
--- /dev/null
+++ b/src/devices/cpu/e132xs/e1dasm.cpp
@@ -0,0 +1,1132 @@
+// license:BSD-3-Clause
+// copyright-holders:Pierpaolo Prazzoli
+/*
+
+ Hyperstone E1 disassembler
+ written by Pierpaolo Prazzoli
+
+*/
+
+#include "emu.h"
+#include "e1dasm.h"
+
+#include "e1defs.h"
+
+#include <cassert>
+
+
+namespace {
+
+const char *const L_REG[] =
+{
+ "L0", "L1", "L2", "L3", "L4", "L5", "L6", "L7",
+ "L8", "L9", "L10", "L11", "L12", "L13", "L14", "L15"
+};
+
+const char *const G_REG[] =
+{
+ "PC", "SR", "FER", "G03", "G04", "G05", "G06", "G07",
+ "G08", "G09", "G10", "G11", "G12", "G13", "G14", "G15",
+ "G16", "G17", "SP", "UB", "BCR", "TPR", "TCR", "TR",
+ "WCR", "ISR", "FCR", "MCR", "G28", "G29", "G30", "G31"
+};
+
+const char *const SETxx[] =
+{
+ "SETADR", nullptr, "SET1", "SET0", "SETLE", "SETGT", "SETLT", "SETGE",
+ "SETSE", "SETHT", "SETST", "SETHE", "SETE", "SETNE", "SETV", "SETNV",
+ nullptr, nullptr, "SET1M", nullptr, "SETLEM", "SETGTM", "SETLTM", "SETGEM",
+ "SETSEM", "SETTHM", "SETSTM", "SETHEM", "SETEM", "SETNEM", "SETVM", "SETNVM"
+};
+
+const char *const Fxxx[] =
+{
+ "FADD", "FADDD", "FSUB", "FSUBD", "FMUL", "FMULD", "FDIV", "FDIVD",
+ "FCMP", "FCMPD", "FCMPU", "FCMPUD", "FCVT", "FCVTD"
+};
+
+const char *const Bxx[] =
+{
+ "BV", "BNV", "BE", "BNE", "BC", "BNC", "BSE", "BHT",
+ "BN", "BNN", "BLE", "BGT", "BR"
+};
+
+const char *const TRAPxx[] =
+{
+ nullptr, nullptr, nullptr, nullptr, "TRAPLE", "TRAPGT", "TRAPLT", "TRAPGE",
+ "TRAPSE", "TRAPHT", "TRAPST", "TRAPHE", "TRAPE", "TRAPNE", "TRAPV", "TRAP"
+};
+
+#define DESTCODE(op) ((op & 0x00f0) >> 4)
+#define SOURCECODE(op) (op & 0x000f)
+
+#define SOURCEBIT(op) ((op & 0x100) >> 8)
+#define DESTBIT(op) ((op & 0x200) >> 9)
+
+#define DASM_N_VALUE(op) ((((op & 0x100) >> 8) << 4 ) | (op & 0x0f))
+
+
+void LL_format(std::string_view &source, std::string_view &dest, uint16_t op)
+{
+ source = L_REG[SOURCECODE(op)];
+ dest = L_REG[DESTCODE(op)];
+}
+
+void LR_format(std::string_view &source, std::string_view &dest, uint16_t op)
+{
+ if (SOURCEBIT(op))
+ source = L_REG[SOURCECODE(op)];
+ else
+ source = G_REG[SOURCECODE(op)];
+
+ dest = L_REG[DESTCODE(op)];
+}
+
+void RR_format(std::string_view &source, std::string_view &dest, uint16_t op, unsigned h_flag)
+{
+ if (SOURCEBIT(op))
+ source = L_REG[SOURCECODE(op)];
+ else
+ source = G_REG[SOURCECODE(op) + h_flag * 16];
+
+ if (DESTBIT(op))
+ dest = L_REG[DESTCODE(op)];
+ else
+ dest = G_REG[DESTCODE(op) + h_flag * 16];
+}
+
+uint8_t Ln_format(std::string_view &dest, uint16_t op)
+{
+ dest = L_REG[DESTCODE(op)];
+
+ return DASM_N_VALUE(op);
+}
+
+uint8_t Rn_format(std::string_view &dest, uint16_t op)
+{
+ if (DESTBIT(op))
+ dest = L_REG[DESTCODE(op)];
+ else
+ dest = G_REG[DESTCODE(op)];
+
+ return DASM_N_VALUE(op);
+}
+
+
+void format_addsub(
+ std::ostream &stream,
+ std::string_view inst,
+ std::string_view dest,
+ std::string_view source,
+ uint8_t source_bit,
+ uint8_t source_code)
+{
+ util::stream_format(stream, "%-7s %s, %s",
+ inst,
+ dest,
+ (!source_bit && (source_code == SR_REGISTER)) ? "C" : source);
+}
+
+} // anonymous namespace
+
+
+
+template <typename T>
+uint32_t hyperstone_disassembler::LRconst_format(std::string_view &source, std::string_view &dest, uint16_t op, offs_t pc, T &&read_hw)
+{
+ uint16_t next_op;
+ uint32_t const_val;
+
+ if (SOURCEBIT(op))
+ source = L_REG[SOURCECODE(op)];
+ else
+ source = G_REG[SOURCECODE(op)];
+
+ dest = L_REG[DESTCODE(op)];
+
+ size = 4;
+
+ pc += 2;
+ next_op = read_hw(pc);
+
+ if (E_BIT(next_op))
+ {
+ uint16_t next_op2;
+
+ size = 6;
+
+ pc += 2;
+ next_op2 = read_hw(pc);
+ const_val = next_op2;
+ const_val |= ((next_op & 0x3fff) << 16 );
+
+ if (S_BIT_CONST(next_op))
+ const_val |= 0xc0000000;
+ }
+ else
+ {
+ const_val = next_op & 0x3fff;
+
+ if (S_BIT_CONST(next_op))
+ const_val |= 0xffffc000;
+ }
+
+ return const_val;
+}
+
+template <typename T>
+uint32_t hyperstone_disassembler::RRconst_format(std::string_view &source, std::string_view &dest, uint16_t op, offs_t pc, T &&read_hw)
+{
+ uint16_t next_op;
+ uint32_t const_val;
+
+ if (SOURCEBIT(op))
+ source = L_REG[SOURCECODE(op)];
+ else
+ source = G_REG[SOURCECODE(op)];
+
+ if (DESTBIT(op))
+ dest = L_REG[DESTCODE(op)];
+ else
+ dest = G_REG[DESTCODE(op)];
+
+ size = 4;
+
+ pc += 2;
+ next_op = read_hw(pc);
+
+ if (E_BIT(next_op))
+ {
+ uint16_t next_op2;
+
+ size = 6;
+
+ pc += 2;
+ next_op2 = read_hw(pc);
+ const_val = next_op2;
+ const_val |= ((next_op & 0x3fff) << 16 );
+
+ if (S_BIT_CONST(next_op))
+ {
+ const_val |= 0xc0000000;
+ }
+ }
+ else
+ {
+ const_val = next_op & 0x3fff;
+
+ if (S_BIT_CONST(next_op))
+ const_val |= 0xffffc000;
+ }
+
+ return const_val;
+}
+
+template <typename T>
+int32_t hyperstone_disassembler::Rimm_format(std::string_view &dest, uint16_t op, offs_t pc, T &&read_hw, unsigned h_flag)
+{
+ uint16_t imm1, imm2;
+ int32_t ret;
+
+ int n = DASM_N_VALUE(op);
+
+ if (DESTBIT(op))
+ dest = L_REG[DESTCODE(op)];
+ else
+ dest = G_REG[DESTCODE(op) + h_flag * 16];
+
+ switch (n)
+ {
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
+ case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16:
+ return n;
+
+ case 17:
+ pc += 2;
+ imm1 = read_hw(pc);
+ pc += 2;
+ imm2 = read_hw(pc);
+ ret = (imm1 << 16) | imm2;
+
+ size = 6;
+ return ret;
+
+
+ case 18:
+ pc += 2;
+ ret = read_hw(pc);
+
+ size = 4;
+ return ret;
+
+ case 19:
+ pc += 2;
+ ret = (int32_t) (0xffff0000 | read_hw(pc));
+
+ size = 4;
+ return ret;
+
+ case 20:
+ return 32; //bit 5 = 1, others = 0
+
+ case 21:
+ return 64; //bit 6 = 1, others = 0
+
+ case 22:
+ return 128; //bit 7 = 1, others = 0
+
+ case 23:
+ return 0x80000000; //bit 31 = 1, others = 0 (2 at the power of 31)
+
+ case 24:
+ return -8;
+
+ case 25:
+ return -7;
+
+ case 26:
+ return -6;
+
+ case 27:
+ return -5;
+
+ case 28:
+ return -4;
+
+ case 29:
+ return -3;
+
+ case 30:
+ return -2;
+
+ case 31:
+ return -1;
+
+ default:
+ return 0; //should never goes here
+ }
+}
+
+template <typename T>
+int32_t hyperstone_disassembler::PCrel_format(uint16_t op, offs_t pc, T &&read_hw)
+{
+ int32_t ret;
+
+ if( op & 0x80 ) //bit 7 = 1
+ {
+ uint16_t next;
+
+ size = 4;
+
+ pc += 2;
+
+ next = read_hw(pc);
+
+ ret = (op & 0x7f) << 16;
+
+ ret |= (next & 0xfffe);
+
+ if( next & 1 )
+ ret |= 0xff800000; //ok?
+ }
+ else
+ {
+ ret = op & 0x7e;
+
+ if( op & 1 )
+ ret |= 0xffffff80; //ok?
+ }
+
+ return (pc + ret);
+}
+
+template <typename T>
+uint32_t hyperstone_disassembler::RRdis_format(std::string_view &source, std::string_view &dest, uint16_t op, uint16_t next_op, offs_t pc, T &&read_hw)
+{
+ uint32_t ret;
+
+ if (SOURCEBIT(op))
+ source = L_REG[SOURCECODE(op)];
+ else
+ source = G_REG[SOURCECODE(op)];
+
+ if (DESTBIT(op))
+ dest = L_REG[DESTCODE(op)];
+ else
+ dest = G_REG[DESTCODE(op)];
+
+ if (E_BIT(next_op))
+ {
+ uint16_t next;
+
+ size = 6;
+
+ next = read_hw(pc + 4);
+
+ ret = next;
+ ret |= ( ( next_op & 0xfff ) << 16 );
+
+ if( S_BIT_CONST(next_op) )
+ {
+ ret |= 0xf0000000;
+ }
+ }
+ else
+ {
+ ret = next_op & 0xfff;
+ if( S_BIT_CONST(next_op) )
+ {
+ ret |= 0xfffff000;
+ }
+ }
+
+ return ret;
+}
+
+u32 hyperstone_disassembler::opcode_alignment() const
+{
+ return 2;
+}
+
+hyperstone_disassembler::hyperstone_disassembler(config *conf) : m_config(conf)
+{
+}
+
+offs_t hyperstone_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
+{
+ return do_disassemble(stream, pc, [&opcodes] (offs_t addr) { return opcodes.r16(addr); });
+}
+
+offs_t hyperstone_disassembler::disassemble_one(std::ostream &stream, offs_t pc, const uint16_t *opptr)
+{
+ return do_disassemble(
+ stream,
+ pc,
+ [pc, opptr] (offs_t addr)
+ {
+ assert(addr >= pc);
+ assert(addr < (pc + 6));
+ return opptr[(addr - pc) >> 1];
+ });
+}
+
+
+/*****************************/
+/* Main disassembly function */
+/*****************************/
+template <typename T>
+offs_t hyperstone_disassembler::do_disassemble(std::ostream &stream, offs_t pc, T &&read_hw)
+{
+ std::string_view source, dest;
+ uint32_t flags = 0;
+
+ const uint16_t op = read_hw(pc);
+
+ size = 2;
+
+ const uint8_t source_code = SOURCECODE(op);
+ const uint8_t dest_code = DESTCODE(op);
+ const uint8_t source_bit = SOURCEBIT(op);
+ const uint8_t dest_bit = DESTBIT(op);
+
+ const int h_flag = m_config ? m_config->get_h() : 0;
+
+ const uint8_t op_num = (op & 0xff00) >> 8;
+
+ switch (op_num)
+ {
+ // CHK - CHKZ - NOP
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ if (source_bit && dest_bit && !source_code && !dest_code)
+ {
+ util::stream_format(stream, "NOP");
+ }
+ else
+ {
+ RR_format(source, dest, op, 0);
+ if (!source_bit && (source_code == SR_REGISTER))
+ util::stream_format(stream, "CHKZ %s, 0", dest);
+ else
+ util::stream_format(stream, "CHK %s, %s", dest, source);
+ }
+ break;
+
+ // MOVD - RET
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ RR_format(source, dest, op, 0);
+
+ if (!dest_bit && (dest_code == PC_REGISTER))
+ {
+ if (!source_bit && ((source_code == PC_REGISTER) || (source_code == SR_REGISTER)))
+ {
+ // RET with PC or SR as source is reserved for future expansion
+ util::stream_format(stream, "D.HU $%04x", op);
+ }
+ else
+ {
+ RR_format(source, dest, op, 0);
+ util::stream_format(stream, "RET PC, %s", source);
+ flags = STEP_OUT;
+ }
+ }
+ else if (!source_bit && (source_code == SR_REGISTER))
+ {
+ util::stream_format(stream, "MOVD %s, 0", dest);
+ }
+ else
+ {
+ util::stream_format(stream, "MOVD %s, %s", dest, source);
+ }
+ break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: // DIVU
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f: // DIVS
+ RR_format(source, dest, op, 0);
+ util::stream_format(stream, "DIV%c %s, %s", (op_num & 0x4) ? 'S' : 'U', dest, source);
+ break;
+
+ // XMx - XXx
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ {
+ RR_format(source, dest, op, 0);
+
+ size = 4;
+
+ pc += 2;
+ const uint16_t ilm1 = read_hw(pc);
+
+ const int xcode = X_CODE(ilm1);
+
+ if (xcode < 4)
+ {
+ uint16_t lim;
+
+ if (E_BIT(ilm1))
+ {
+ size = 6;
+
+ pc += 2;
+ const uint16_t ilm2 = read_hw(pc);
+
+ lim = ((ilm1 & 0xfff) << 16) | ilm2;
+ }
+ else
+ {
+ lim = ilm1 & 0xfff;
+ }
+
+ util::stream_format(stream, "XM%x %s, %s, $%x", 1 << xcode, dest, source, lim);
+ }
+ else
+ {
+ util::stream_format(stream, "XX%x %s, %s, 0", 1 << (xcode & 0x3), dest, source);
+ }
+ }
+ break;
+
+ // MASK
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ {
+ const uint32_t const_val = RRconst_format(source, dest, op, pc, read_hw);
+ util::stream_format(stream, "MASK %s, %s, $%x", dest, source, const_val);
+ if (!source_bit && (source_code == PC_REGISTER))
+ util::stream_format(stream, " ; $%x", uint32_t((pc + size) & const_val));
+ }
+ break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: // SUM
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f: // SUMS
+ {
+ const uint32_t const_val = RRconst_format(source, dest, op, pc, read_hw);
+ util::stream_format(stream, "SUM%c %s, %s, $%x",
+ (op_num & 0x4) ? 'S' : ' ',
+ dest,
+ (!source_bit && (source_code == SR_REGISTER)) ? "C" : source,
+ const_val);
+ if (!source_bit && (source_code == PC_REGISTER))
+ util::stream_format(stream, " ; $%x", uint32_t(pc + size + const_val));
+ }
+ break;
+
+ // CMP
+ case 0x20: case 0x21: case 0x22: case 0x23:
+ RR_format(source, dest, op, 0);
+ format_addsub(stream, "CMP", dest, source, source_bit, source_code);
+ break;
+
+ // MOV
+ case 0x24: case 0x25: case 0x26: case 0x27:
+ RR_format(source, dest, op, h_flag);
+ util::stream_format(stream, "MOV %s, %s", dest, source);
+ break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: // ADD
+ case 0x2c: case 0x2d: case 0x2e: case 0x2f: // ADDS
+ RR_format(source, dest, op, 0);
+ format_addsub(stream, (op_num & 0x4) ? "ADDS" : "ADD", dest, source, source_bit, source_code);
+ break;
+
+ // CMPB
+ case 0x30: case 0x31: case 0x32: case 0x33:
+ RR_format(source, dest, op, 0);
+ util::stream_format(stream, "CMPB %s, %s", dest, source);
+ break;
+
+ // ANDN
+ case 0x34: case 0x35: case 0x36: case 0x37:
+ RR_format(source, dest, op, 0);
+ util::stream_format(stream, "ANDN %s, %s", dest, source);
+ break;
+
+ // OR
+ case 0x38: case 0x39: case 0x3a: case 0x3b:
+ RR_format(source, dest, op, 0);
+ util::stream_format(stream, "OR %s, %s", dest, source);
+ break;
+
+ // XOR
+ case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ RR_format(source, dest, op, 0);
+ util::stream_format(stream, "XOR %s, %s", dest, source);
+ break;
+
+ // SUBC
+ case 0x40: case 0x41: case 0x42: case 0x43:
+ RR_format(source, dest, op, 0);
+ format_addsub(stream, "SUBC", dest, source, source_bit, source_code);
+ break;
+
+ // NOT
+ case 0x44: case 0x45: case 0x46: case 0x47:
+ RR_format(source, dest, op, 0);
+ util::stream_format(stream, "NOT %s, %s", dest, source);
+ break;
+
+ case 0x48: case 0x49: case 0x4a: case 0x4b: // SUB
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f: // SUBS
+ RR_format(source, dest, op, 0);
+ format_addsub(stream, (op_num & 0x4) ? "SUBS" : "SUB", dest, source, source_bit, source_code);
+ break;
+
+ // ADDC
+ case 0x50: case 0x51: case 0x52: case 0x53:
+ RR_format(source, dest, op, 0);
+ format_addsub(stream, "ADDC", dest, source, source_bit, source_code);
+ break;
+
+ // AND
+ case 0x54: case 0x55: case 0x56: case 0x57:
+ RR_format(source, dest, op, 0);
+ util::stream_format(stream, "AND %s, %s", dest, source);
+ break;
+
+ case 0x58: case 0x59: case 0x5a: case 0x5b: // NEG
+ case 0x5c: case 0x5d: case 0x5e: case 0x5f: // NEGS
+ RR_format(source, dest, op, 0);
+ format_addsub(stream, (op_num & 0x4) ? "NEGS" : "NEG", dest, source, source_bit, source_code);
+ break;
+
+ // CMPI
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ {
+ const uint32_t imm = Rimm_format(dest, op, pc, read_hw, 0);
+ util::stream_format(stream, "CMPI %s, $%x", dest, imm);
+ }
+ break;
+
+ // MOVI
+ case 0x64: case 0x65: case 0x66: case 0x67:
+ {
+ const uint32_t imm = Rimm_format(dest, op, pc, read_hw, h_flag);
+ util::stream_format(stream, "MOVI %s, $%x", dest, imm);
+ }
+ break;
+
+ case 0x68: case 0x69: case 0x6a: case 0x6b: // ADDI
+ case 0x6c: case 0x6d: case 0x6e: case 0x6f: // ADDSI
+ if (!DASM_N_VALUE(op))
+ {
+ util::stream_format(stream, "%-7s %s, CZ", (op_num & 0x4) ? "ADDSI" : "ADDI", dest);
+ }
+ else
+ {
+ const uint32_t imm = Rimm_format(dest, op, pc, read_hw, 0);
+ util::stream_format(stream, "%-7s %s, $%x", (op_num & 0x4) ? "ADDSI" : "ADDI", dest, imm);
+ if (!dest_bit && (dest_code == PC_REGISTER))
+ util::stream_format(stream, " ; $%x", uint32_t(pc + size + imm));
+ }
+ break;
+
+ // CMPBI
+ case 0x70: case 0x71: case 0x72: case 0x73:
+ if (!DASM_N_VALUE(op))
+ {
+ util::stream_format(stream, "CMPBI %s, ANYBZ", dest);
+ }
+ else
+ {
+ uint32_t imm = Rimm_format(dest, op, pc, read_hw, 0);
+ if (DASM_N_VALUE(op) == 31)
+ imm = 0x7fffffff; //bit 31 = 0, others = 1
+
+ util::stream_format(stream, "CMPBI %s, $%x", dest, imm);
+ }
+ break;
+
+ // ANDNI
+ case 0x74: case 0x75: case 0x76: case 0x77:
+ {
+ uint32_t imm = Rimm_format(dest, op, pc, read_hw, 0);
+ if (DASM_N_VALUE(op) == 31)
+ imm = 0x7fffffff; //bit 31 = 0, others = 1
+
+ util::stream_format(stream, "ANDNI %s, $%x", dest, imm);
+ if (!dest_bit && (dest_code == PC_REGISTER))
+ util::stream_format(stream, " ; $%x", uint32_t((pc + size) & ~imm));
+ }
+ break;
+
+ // ORI
+ case 0x78: case 0x79: case 0x7a: case 0x7b:
+ {
+ const uint32_t imm = Rimm_format(dest, op, pc, read_hw, 0);
+
+ util::stream_format(stream, "ORI %s, $%x", dest, imm);
+ if (!dest_bit && (dest_code == PC_REGISTER))
+ util::stream_format(stream, " ; $%x", uint32_t((pc + size) | imm));
+ }
+ break;
+
+ // XORI
+ case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ {
+ const uint32_t imm = Rimm_format(dest, op, pc, read_hw, 0);
+
+ util::stream_format(stream, "XORI %s, $%x", dest, imm);
+ if (!dest_bit && (dest_code == PC_REGISTER))
+ util::stream_format(stream, " ; $%x", uint32_t((pc + size) ^ imm));
+ }
+ break;
+
+ case 0x80: case 0x81: // SHRDI
+ case 0x84: case 0x85: // SARDI
+ {
+ const uint8_t n = Ln_format(dest, op);
+ util::stream_format(stream, "S%cRDI %s, $%x", (op_num & 0x4) ? 'A' : 'H', dest, n);
+ }
+ break;
+
+ case 0x82: // SHRD
+ case 0x83: // SHR
+ case 0x86: // SARD
+ case 0x87: // SAR
+ LL_format(source, dest, op);
+ util::stream_format(stream, "S%cR%c %s, %s",
+ (op_num & 0x4) ? 'A' : 'H',
+ (op_num & 0x1) ? ' ' : 'D',
+ dest,
+ source);
+ break;
+
+ // SHLDI
+ case 0x88: case 0x89:
+ {
+ const uint8_t n = Ln_format(dest, op);
+ util::stream_format(stream, "SHLDI %s, $%x", dest, n);
+ }
+ break;
+
+ case 0x8a: // SHLD
+ case 0x8b: // SHL
+ LL_format(source, dest, op);
+ util::stream_format(stream, "SHL%c %s, %s", (op_num & 0x1) ? ' ' : 'D', dest, source);
+ break;
+
+ // RESERVED
+ case 0x8c: case 0x8d:
+ case 0xac: case 0xad: case 0xae: case 0xaf:
+ util::stream_format(stream, "D.HU $%04x", op);
+ break;
+
+ // TESTLZ
+ case 0x8e:
+ LL_format(source, dest, op);
+ util::stream_format(stream, "TESTLZ %s, %s", dest, source);
+ break;
+
+ // ROL
+ case 0x8f:
+ LL_format(source, dest, op);
+ util::stream_format(stream, "ROL %s, %s", dest, source);
+ break;
+
+ case 0x90: case 0x91: case 0x92: case 0x93: // LDxx.D/A/IOD/IOA
+ case 0x98: case 0x99: case 0x9a: case 0x9b: // STxx.D/A/IOD/IOA
+ {
+ const uint16_t next_op = read_hw(pc + 2);
+ const uint32_t dis = RRdis_format(source, dest, op, next_op, pc, read_hw);
+
+ if (size == 2)
+ size = 4;
+
+ if ((op_num & 0x8) && !source_bit && (source_code == SR_REGISTER))
+ source = "0";
+
+ if (!dest_bit && (dest_code == SR_REGISTER))
+ dest = "0";
+
+ const std::string_view inst = (op_num & 0x8) ? "ST" : "LD";
+ const char mode = (!dest_bit && (dest_code == SR_REGISTER)) ? 'A' : 'D';
+
+ switch (DD(next_op))
+ {
+ case 0:
+ // LD/STBS.D/A
+ util::stream_format(stream, "%sBS.%c %s, %s, $%x", inst, mode, dest, source, dis);
+ if (!dest_bit && (dest_code == PC_REGISTER))
+ util::stream_format(stream, " ; $%x", uint32_t(pc + size + dis));
+ break;
+
+ case 1:
+ // LD/STBU.D/A
+ util::stream_format(stream, "%sBU.%c %s, %s, $%x", inst, mode, dest, source, dis);
+ if (!dest_bit && (dest_code == PC_REGISTER))
+ util::stream_format(stream, " ; $%x", uint32_t(pc + size + dis));
+ break;
+
+ case 2:
+ // LD/STHU.D/A
+ // LD/STHS.D/A
+ util::stream_format(stream, "%sH%c.%c %s, %s, $%x", inst, (dis & 1) ? 'S' : 'U', mode, dest, source, dis & ~1);
+ if (!dest_bit && (dest_code == PC_REGISTER))
+ util::stream_format(stream, " ; $%x", uint32_t(pc + size + (dis & ~1)) & ~1);
+ break;
+
+ case 3:
+ if (dis & 2)
+ {
+ // LD/STW.IOD/A
+ // LD/STD.IOD/A
+ util::stream_format(stream, "%s%c.IO%c %s, %s, $%x", inst, (dis & 1) ? 'D' : 'W', mode, dest, source, dis & ~3);
+ }
+ else
+ {
+ // LD/STW.D/A
+ // LD/STD.D/A
+ util::stream_format(stream, "%s%c.%c %s, %s, $%x", inst, (dis & 1) ? 'D' : 'W', mode, dest, source, dis & ~3);
+ }
+ if (!dest_bit && (dest_code == PC_REGISTER))
+ util::stream_format(stream, " ; $%x", uint32_t(pc + size + (dis & ~3)) & ~3);
+ break;
+ }
+ }
+ break;
+
+ case 0x94: case 0x95: case 0x96: case 0x97: // LDxx.N/S
+ case 0x9c: case 0x9d: case 0x9e: case 0x9f: // STxx.N/S
+ {
+ const uint16_t next_op = read_hw(pc + 2);
+ const uint32_t dis = RRdis_format(source, dest, op, next_op, pc, read_hw);
+
+ if (size == 2)
+ size = 4;
+
+ if (!dest_bit && ((dest_code == PC_REGISTER) || (dest_code == SR_REGISTER)))
+ {
+ util::stream_format(stream, "Reserved");
+ break;
+ }
+
+ if ((op_num & 0x8) && !source_bit && (source_code == SR_REGISTER))
+ source = "0";
+
+ const std::string_view inst = (op_num & 0x8) ? "ST" : "LD";
+
+ switch (DD(next_op))
+ {
+ case 0:
+ // LD/STBS.N
+ util::stream_format(stream, "%sBS.N %s, %s, $%x", inst, dest, source, dis);
+ break;
+
+ case 1:
+ // LD/STBU.N
+ util::stream_format(stream, "%sBU.N %s, %s, $%x", inst, dest, source, dis);
+ break;
+
+ case 2:
+ // LD/STHU.N
+ // LD/STHS.N
+ util::stream_format(stream, "%sH%c.N %s, %s, $%x", inst, (dis & 1) ? 'S' : 'U', dest, source, dis & ~1);
+ break;
+
+ case 3:
+ if ((dis & 3) == 3)
+ {
+ // LD/STW.S
+ util::stream_format(stream, "%sW.S %s, %s, $%x", inst, dest, source, dis & ~3);
+ }
+ else if ((dis & 3) == 2)
+ {
+ // Reserved
+ util::stream_format(stream, "Reserved");
+ }
+ else
+ {
+ // LD/STW.N
+ // LD/STD.N
+ util::stream_format(stream, "%s%c.N %s, %s, $%x", inst, (dis & 1) ? 'D' : 'W', dest, source, dis & ~3);
+ }
+ break;
+ }
+ }
+ break;
+
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3: // SHRI
+ case 0xa4: case 0xa5: case 0xa6: case 0xa7: // SARI
+ {
+ const uint8_t n = Rn_format(dest, op);
+ util::stream_format(stream, "S%cRI %s, $%x", (op_num & 0x4) ? 'A' : 'H', dest, n);
+ }
+ break;
+
+ // SHLI
+ case 0xa8: case 0xa9: case 0xaa: case 0xab:
+ {
+ const uint8_t n = Rn_format(dest, op);
+ util::stream_format(stream, "SHLI %s, $%x", dest, n);
+ }
+ break;
+
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: // MULU
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7: // MULS
+ RR_format(source, dest, op, 0);
+ util::stream_format(stream, "MUL%c %s, %s", (op_num & 0x4) ? 'S' : 'U', dest, source);
+ break;
+
+ // SETxx - SETADR - FETCH
+ case 0xb8: case 0xb9: case 0xba: case 0xbb:
+ {
+ const uint8_t n = Rn_format(dest, op);
+
+ if (!dest_bit && (dest_code == PC_REGISTER))
+ {
+ // SETxx with PC as destination is reserved for future use
+ util::stream_format(stream, "D.HU $%04x", op);
+ }
+ else if (!dest_bit && (dest_code == SR_REGISTER))
+ {
+ util::stream_format(stream, "FETCH $%x", (n / 2) + 1);
+ }
+ else
+ {
+ char const *const inst = SETxx[n];
+ if (inst)
+ util::stream_format(stream, "%-7s %s", inst, dest);
+ else
+ util::stream_format(stream, "D.HU $%04x", op);
+ }
+ }
+ break;
+
+ // MUL
+ case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ RR_format(source, dest, op, 0);
+ util::stream_format(stream, "MUL %s, %s", dest, source);
+ break;
+
+ case 0xc0: // FADD
+ case 0xc1: // FADDD
+ case 0xc2: // FSUB
+ case 0xc3: // FSUBD
+ case 0xc4: // FMUL
+ case 0xc5: // FMULD
+ case 0xc6: // FDIV
+ case 0xc7: // FDIVD
+ case 0xc8: // FCMP
+ case 0xc9: // FCMPD
+ case 0xca: // FCMPU
+ case 0xcb: // FCMPUD
+ case 0xcc: // FCVT
+ case 0xcd: // FCVTD
+ LL_format(source, dest, op);
+ util::stream_format(stream, "%-7s %s, %s", Fxxx[op_num & 0xf], dest, source);
+ break;
+
+ // EXTEND
+ case 0xce:
+ {
+ LL_format(source, dest, op);
+
+ pc += 2;
+ const uint16_t extended_op = read_hw(pc);
+
+ size = 4;
+
+ switch (extended_op)
+ {
+ case 0x100:
+ case EMUL:
+ util::stream_format(stream, "EMUL %s, %s", dest, source);
+ break;
+
+ case EMULU:
+ util::stream_format(stream, "EMULU %s, %s", dest, source);
+ break;
+
+ case EMULS:
+ util::stream_format(stream, "EMULS %s, %s", dest, source);
+ break;
+
+ case EMAC:
+ util::stream_format(stream, "EMAC %s, %s", dest, source);
+ break;
+
+ case EMACD:
+ util::stream_format(stream, "EMACD %s, %s", dest, source);
+ break;
+
+ case EMSUB:
+ util::stream_format(stream, "EMSUB %s, %s", dest, source);
+ break;
+
+ case EMSUBD:
+ util::stream_format(stream, "EMSUBD %s, %s", dest, source);
+ break;
+
+ case EHMAC:
+ util::stream_format(stream, "EHMAC %s, %s", dest, source);
+ break;
+
+ case EHMACD:
+ util::stream_format(stream, "EHMACD %s, %s", dest, source);
+ break;
+
+ case EHCMULD:
+ util::stream_format(stream, "EHCMULD %s, %s", dest, source);
+ break;
+
+ case EHCMACD:
+ util::stream_format(stream, "EHCMACD %s, %s", dest, source);
+ break;
+
+ case EHCSUMD:
+ util::stream_format(stream, "EHCSUMD %s, %s", dest, source);
+ break;
+
+ case EHCFFTD:
+ util::stream_format(stream, "EHCFFTD %s, %s", dest, source);
+ break;
+
+ case EHCFFTSD:
+ util::stream_format(stream, "EHCFFTSD %s, %s", dest, source);
+ break;
+
+ default:
+ util::stream_format(stream, "Ext. OP $%X @ %X", extended_op, pc);
+ osd_printf_verbose("Illegal Extended Opcode: %X @ %X\n", extended_op, pc);
+ break;
+ }
+ }
+ break;
+
+ // DO
+ case 0xcf:
+ LL_format(source, dest, op);
+ util::stream_format(stream, "DO %s, %s", dest, source);
+ break;
+
+ case 0xd0: case 0xd1: // LDW.R
+ case 0xd2: case 0xd3: // LDD.R
+ case 0xd4: case 0xd5: // LDW.P
+ case 0xd6: case 0xd7: // LDD.P
+ case 0xd8: case 0xd9: // STW.R
+ case 0xda: case 0xdb: // STD.R
+ case 0xdc: case 0xdd: // STW.P
+ case 0xde: case 0xdf: // STD.P
+ LR_format(source, dest, op);
+ util::stream_format(stream, "%s%c.%c %s, %s",
+ (op_num & 0x8) ? "ST" : "LD",
+ (op_num & 0x2) ? 'D' : 'W',
+ (op_num & 0x4) ? 'P' : 'R',
+ dest,
+ ((op_num & 0x8) && !source_bit && (source_code == SR_REGISTER)) ? "0" : source);
+ break;
+
+ case 0xe0: // DBV
+ case 0xe1: // DBNV
+ case 0xe2: // DBE
+ case 0xe3: // DBNE
+ case 0xe4: // DBC
+ case 0xe5: // DBNC
+ case 0xe6: // DBSE
+ case 0xe7: // DBHT
+ case 0xe8: // DBN
+ case 0xe9: // DBNN
+ case 0xea: // DBLE
+ case 0xeb: // DBGT
+ case 0xec: // DBR
+ {
+ const int32_t rel = PCrel_format(op, pc, read_hw) + 2;
+ util::stream_format(stream, "D%-6s $%x", Bxx[op_num & 0xf], rel);
+ if (op_num != 0xec)
+ flags = STEP_COND | step_over_extra(1);
+ }
+ break;
+
+ // FRAME
+ case 0xed:
+ LL_format(source, dest, op);
+ util::stream_format(stream, "FRAME %s, %s", dest, source);
+ break;
+
+ // CALL
+ case 0xee: case 0xef:
+ {
+ const uint32_t const_val = LRconst_format(source, dest, op, pc, read_hw);
+
+ util::stream_format(stream, "CALL %s, %s, $%x", dest, (!source_bit && (source_code == SR_REGISTER)) ? "0" : source, const_val);
+ if (!source_bit && (source_code == PC_REGISTER))
+ util::stream_format(stream, " ; $%x", uint32_t(pc + size + const_val));
+ flags = STEP_OVER;
+ }
+ break;
+
+ case 0xf0: // BV
+ case 0xf1: // BNV
+ case 0xf2: // BE
+ case 0xf3: // BNE
+ case 0xf4: // BC
+ case 0xf5: // BNC
+ case 0xf6: // BSE
+ case 0xf7: // BHT
+ case 0xf8: // BN
+ case 0xf9: // BNN
+ case 0xfa: // BLE
+ case 0xfb: // BGT
+ case 0xfc: // BR
+ {
+ const int32_t rel = PCrel_format(op, pc, read_hw) + 2;
+ util::stream_format(stream, "%-7s $%x", Bxx[op_num & 0xf], rel);
+ if (op_num != 0xfc)
+ flags = STEP_COND;
+ }
+ break;
+
+ // TRAPxx - TRAP
+ case 0xfd: case 0xfe: case 0xff:
+ {
+ const uint8_t code = ((op & 0x300) >> 6) | (op & 0x03);
+ const uint8_t trapno = (op & 0xfc) >> 2;
+
+ util::stream_format(stream, "%-7s %d", TRAPxx[code], trapno);
+ if (code == TRAP)
+ flags = STEP_OVER;
+ else
+ flags = STEP_OVER | STEP_COND;
+ }
+ break;
+ }
+
+ return size | flags | SUPPORTED;
+}