summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2019-09-05 14:46:00 -0400
committer AJR <ajrhacker@users.noreply.github.com>2019-10-23 21:54:26 -0400
commit41a333e7919ad8f16508bdaf4f9a2192a3c06589 (patch)
treedbca0c36360806c15ad49d5acdf17838aab37612 /src
parentd7f1b7ae495a2855e022e5d6e1758fd80f3df86e (diff)
Add Fujitsu FR disassembler and skeleton CPU device
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/fr/fr.cpp137
-rw-r--r--src/devices/cpu/fr/fr.h69
-rw-r--r--src/devices/cpu/fr/frdasm.cpp977
-rw-r--r--src/devices/cpu/fr/frdasm.h49
-rw-r--r--src/tools/unidasm.cpp2
5 files changed, 1234 insertions, 0 deletions
diff --git a/src/devices/cpu/fr/fr.cpp b/src/devices/cpu/fr/fr.cpp
new file mode 100644
index 00000000000..07ecaad136f
--- /dev/null
+++ b/src/devices/cpu/fr/fr.cpp
@@ -0,0 +1,137 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Fujitsu FR series
+
+ Currently this device is just a stub with no actual execution core.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "fr.h"
+#include "frdasm.h"
+
+// device type definitions
+DEFINE_DEVICE_TYPE(MB91101A, mb91101a_device, "mb91101a", "Fujitsu MB91101A")
+
+fr_cpu_device::fr_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int addrbits, address_map_constructor map)
+ : cpu_device(mconfig, type, tag, owner, clock)
+ , m_space_config("program", ENDIANNESS_BIG, 32, addrbits, 0, map)
+ , m_space(nullptr)
+ , m_cache(nullptr)
+ , m_regs{0}
+ , m_pc(0)
+ , m_ps(0)
+ , m_tbr(0)
+ , m_rp(0)
+ , m_md(0)
+ , m_icount(0)
+{
+}
+
+mb91101a_device::mb91101a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : fr_cpu_device(mconfig, MB91101A, tag, owner, clock, 32, address_map_constructor())
+{
+}
+
+std::unique_ptr<util::disasm_interface> fr_cpu_device::create_disassembler()
+{
+ return std::make_unique<fr_disassembler>();
+}
+
+device_memory_interface::space_config_vector fr_cpu_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_space_config),
+ };
+}
+
+void fr_cpu_device::device_start()
+{
+ m_space = &space(AS_PROGRAM);
+ m_cache = m_space->cache<2, 0, ENDIANNESS_BIG>();
+
+ set_icountptr(m_icount);
+
+ state_add(FR_PC, "PC", m_pc).mask(0xfffffffe);
+ state_add(STATE_GENPC, "GENPC", m_pc).mask(0xfffffffe).noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_pc).mask(0xfffffffe).noshow();
+ state_add(FR_PS, "PS", m_ps).mask(0x001f073f).formatstr("%08X");
+ state_add(STATE_GENFLAGS, "CURFLAGS", m_ps).mask(0x001f073f).noshow().formatstr("%19s");
+ state_add<u8>(FR_CCR, "CCR",
+ [this]() { return u8(m_ps & 0x0000003f); },
+ [this](u8 value) { m_ps = (m_ps & 0x001f0700) | value; }).mask(0x3f).noshow();
+ state_add<u8>(FR_ILM, "ILM",
+ [this]() { return u8((m_ps & 0x001f0000) >> 16); },
+ [this](u8 value) { m_ps = (m_ps & 0x0000073f) | u32(value) << 16; }).mask(0x1f).noshow();
+ state_add(FR_TBR, "TBR", m_tbr);
+ state_add(FR_RP, "RP", m_rp);
+ state_add(FR_SSP, "SSP", m_regs[15]);
+ state_add(FR_USP, "USP", m_regs[16]);
+ state_add(FR_MD, "MD", m_md);
+ state_add<u32>(FR_MDH, "MDH",
+ [this]() { return u32(m_md >> 32); },
+ [this](u32 value) { m_md = (m_md & 0x00000000ffffffffULL) | u64(value) << 32; }).noshow();
+ state_add<u32>(FR_MDL, "MDL",
+ [this]() { return u32(m_md & 0x00000000ffffffffULL); },
+ [this](u32 value) { m_md = (m_md & 0xffffffff00000000ULL) | value; }).noshow();
+ for (int i = 0; i < 15; i++)
+ state_add(FR_R0 + i, string_format("R%d", i).c_str(), m_regs[i]);
+ state_add<u32>(FR_R15, "R15",
+ [this]() { return m_regs[BIT(m_ps, 5) ? 16 : 15]; },
+ [this](u32 value) { m_regs[BIT(m_ps, 5) ? 16 : 15] = value; });
+
+ save_item(NAME(m_regs));
+ save_item(NAME(m_pc));
+ save_item(NAME(m_ps));
+ save_item(NAME(m_tbr));
+ save_item(NAME(m_rp));
+ save_item(NAME(m_md));
+}
+
+void fr_cpu_device::device_reset()
+{
+ // Only TBR, SSP, ILM and certain CCR and SCR bits are reset here; PC will be reloaded subsequently
+ m_ps = (m_ps & 0x0000060f) | 0x000f0000;
+ m_tbr = 0x000ffc00;
+ m_regs[15] = 0x00000000;
+}
+
+void fr_cpu_device::execute_run()
+{
+ m_pc = m_space->read_dword(m_tbr + 0x3fc);
+
+ debugger_instruction_hook(m_pc);
+
+ m_icount = 0;
+}
+
+void fr_cpu_device::execute_set_input(int inputnum, int state)
+{
+ // TODO
+}
+
+void fr_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ str = string_format("<%d%d%d%d%d> %c%c%c--%c%c%c%c%c%c",
+ BIT(m_ps, 20),
+ BIT(m_ps, 19),
+ BIT(m_ps, 18),
+ BIT(m_ps, 17),
+ BIT(m_ps, 16),
+ BIT(m_ps, 10) ? 'D' : '.',
+ BIT(m_ps, 9) ? 'd' : '.',
+ BIT(m_ps, 8) ? 'T' : '.',
+ BIT(m_ps, 5) ? 'S' : '.',
+ BIT(m_ps, 4) ? 'I' : '.',
+ BIT(m_ps, 3) ? 'N' : '.',
+ BIT(m_ps, 2) ? 'Z' : '.',
+ BIT(m_ps, 1) ? 'V' : '.',
+ BIT(m_ps, 0) ? 'C' : '.');
+ break;
+ }
+}
diff --git a/src/devices/cpu/fr/fr.h b/src/devices/cpu/fr/fr.h
new file mode 100644
index 00000000000..c5b4899cace
--- /dev/null
+++ b/src/devices/cpu/fr/fr.h
@@ -0,0 +1,69 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_CPU_FR_FR_H
+#define MAME_CPU_FR_FR_H 1
+
+#pragma once
+
+
+class fr_cpu_device : public cpu_device
+{
+public:
+ enum {
+ FR_PC, FR_PS, FR_CCR, FR_ILM,
+ FR_TBR, FR_RP, FR_SSP, FR_USP,
+ FR_MD, FR_MDH, FR_MDL,
+ FR_R0, FR_R1, FR_R2, FR_R3,
+ FR_R4, FR_R5, FR_R6, FR_R7,
+ FR_R8, FR_R9, FR_R10, FR_R11,
+ FR_R12, FR_R13, FR_R14, FR_R15
+ };
+
+protected:
+ // construction/destruction
+ fr_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int addrbits, address_map_constructor map);
+
+ // 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_regs[17]; // includes both SSP and USP
+ u32 m_pc;
+ u32 m_ps;
+ u32 m_tbr;
+ u32 m_rp;
+ u64 m_md;
+ s32 m_icount;
+};
+
+class mb91101a_device : public fr_cpu_device
+{
+public:
+ // device type constructor
+ mb91101a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+DECLARE_DEVICE_TYPE(MB91101A, mb91101a_device)
+
+#endif // MAME_CPU_FR_FR_H
diff --git a/src/devices/cpu/fr/frdasm.cpp b/src/devices/cpu/fr/frdasm.cpp
new file mode 100644
index 00000000000..4a6998e0240
--- /dev/null
+++ b/src/devices/cpu/fr/frdasm.cpp
@@ -0,0 +1,977 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Fujitsu FR family disassembler
+
+ While Fujitsu's manuals also refer to R13, R14 and R15 by function as
+ AC (accumulator), FP (frame pointer) and SP (stack pointer), these
+ aliases do not appear to be commonly used. All indexed addressing modes
+ are based on one of these three registers.
+
+ The PS (program status) register can only be manipulated with special
+ instructions, some of which affect only the sections known as CCR
+ (condition code register) and ILM (interrupt level mask).
+
+ TODO: The FR81 family has extra opcodes (primarily floating-point
+ instructions) which are not included here.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "frdasm.h"
+
+fr_disassembler::fr_disassembler()
+ : util::disasm_interface()
+{
+}
+
+u32 fr_disassembler::opcode_alignment() const
+{
+ return 2;
+}
+
+void fr_disassembler::format_u8(std::ostream &stream, u8 value)
+{
+ util::stream_format(stream, "#0x%02X", value);
+}
+
+void fr_disassembler::format_i8(std::ostream &stream, u8 value)
+{
+ if (value >= 0x0a)
+ util::stream_format(stream, "#0x%X", value);
+ else
+ util::stream_format(stream, "#%d", value);
+}
+
+void fr_disassembler::format_disp(std::ostream &stream, u8 offs, unsigned shift)
+{
+ // 10-bit (word), 9-bit (half-word) or 8-bit (byte) signed displacement
+ u16 disp;
+ if (BIT(offs, 7))
+ {
+ disp = u16(0x100 - offs) << shift;
+ stream << "-";
+ }
+ else
+ disp = u16(offs) << shift;
+
+ if (disp >= 0x0a)
+ util::stream_format(stream, "0x%X", disp);
+ else
+ util::stream_format(stream, "%d", disp);
+}
+
+void fr_disassembler::format_u10(std::ostream &stream, u16 value)
+{
+ if (value >= 0x0a)
+ util::stream_format(stream, "#0x%X", value);
+ else
+ util::stream_format(stream, "#%d", value);
+}
+
+void fr_disassembler::format_i20(std::ostream &stream, u32 value)
+{
+ util::stream_format(stream, "#0x%05X", value);
+}
+
+void fr_disassembler::format_i32(std::ostream &stream, u32 value)
+{
+ util::stream_format(stream, "#0x%08X", value);
+}
+
+void fr_disassembler::format_label(std::ostream &stream, offs_t addr)
+{
+ util::stream_format(stream, "0x%X", u32(addr));
+}
+
+void fr_disassembler::format_dir(std::ostream &stream, u16 addr)
+{
+ if (addr >= 0x100)
+ util::stream_format(stream, "@0x%03X", addr);
+ else
+ util::stream_format(stream, "@0x%02X", addr);
+}
+
+void fr_disassembler::format_ac_rdisp(std::ostream &stream, u8 rj)
+{
+ util::stream_format(stream, "@(R13, R%d)", rj);
+}
+
+void fr_disassembler::format_sp_udisp(std::ostream &stream, u8 disp)
+{
+ // unsigned displacement
+ util::stream_format(stream, "@(R15, %d)", disp);
+}
+
+void fr_disassembler::format_rs(std::ostream &stream, u8 reg)
+{
+ switch (reg)
+ {
+ case 0: // Table Base Register
+ stream << "TBR";
+ break;
+
+ case 1: // Return Pointer
+ stream << "RP";
+ break;
+
+ case 2: // System Stack Pointer (R15 when S = 0)
+ stream << "SSP";
+ break;
+
+ case 3: // User Stack Pointer (R15 when S = 1)
+ stream << "USP";
+ break;
+
+ case 4: // Multiply/Divide Register (high 32 bits)
+ stream << "MDH";
+ break;
+
+ case 5: // Multiply/Divide Register (low 32 bits)
+ stream << "MDL";
+ break;
+
+ default:
+ stream << "reserved";
+ break;
+ }
+}
+
+offs_t fr_disassembler::dasm_invalid(std::ostream &stream, u16 opcode)
+{
+ util::stream_format(stream, "%-8s0x%04X", ".DATA.H", opcode);
+ return 2 | SUPPORTED;
+}
+
+offs_t fr_disassembler::dasm_i4op(std::ostream &stream, u16 opcode, const char *inst)
+{
+ // Arithmetic instructions with 4-bit (effectively 5-bit) positive or negative immediate offset
+ util::stream_format(stream, "%-8s#", inst);
+ u8 value = (opcode & 0x00f0) >> 4;
+ if (BIT(opcode, 9))
+ {
+ stream << "-";
+ value = 0x10 - value;
+ }
+ if (value >= 0x0a)
+ util::stream_format(stream, "0x%X", value);
+ else
+ util::stream_format(stream, "%d", value);
+
+ util::stream_format(stream, ", R%d", opcode & 0x000f);
+ return 2 | SUPPORTED;
+}
+
+offs_t fr_disassembler::dasm_shift(std::ostream &stream, u16 opcode, const char *inst)
+{
+ // Register shifts with 4-bit (effectively 5-bit) immediate offset
+ util::stream_format(stream, "%-8s#%d, R%d", inst, (opcode & 0x01f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+}
+
+offs_t fr_disassembler::dasm_rrop(std::ostream &stream, u16 opcode, const char *inst)
+{
+ // Simple register-to-register operations (and multiplication)
+ util::stream_format(stream, "%-8sR%d, R%d", inst, (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+}
+
+offs_t fr_disassembler::dasm_ld_fp_disp(std::ostream &stream, u16 opcode, const char *inst, unsigned shift)
+{
+ // Load (zero extended) from memory at frame pointer ± 10-bit/9-bit/8-bit displacement
+ util::stream_format(stream, "%-8s@(R14, ", inst);
+ format_disp(stream, (opcode & 0x0ff0) >> 4, shift);
+ util::stream_format(stream, "), R%d", opcode & 0x000f);
+ return 2 | SUPPORTED;
+}
+
+offs_t fr_disassembler::dasm_st_fp_disp(std::ostream &stream, u16 opcode, const char *inst, unsigned shift)
+{
+ // Store to memory at frame pointer ± 10-bit/9-bit/8-bit displacement
+ util::stream_format(stream, "%-8sR%d, @(R14, ", inst, opcode & 0x000f);
+ format_disp(stream, (opcode & 0x0ff0) >> 4, shift);
+ stream << ")";
+ return 2 | SUPPORTED;
+}
+
+offs_t fr_disassembler::dasm_ldstm(std::ostream &stream, u16 opcode, const char *inst)
+{
+ // Load/store register list in (R0-R7) or (R8-R15)
+ util::stream_format(stream, "%-8s(", inst);
+ int base = BIT(opcode, 8) ? 8 : 0;
+ for (int i = 0; i < 8; i++)
+ {
+ if (BIT(opcode, i))
+ {
+ util::stream_format(stream, "R%d", BIT(opcode, 9) ? base + 7 - i : base + i);
+ opcode &= ~(1 << i);
+ if ((opcode & 0x00ff) != 0)
+ stream << ", ";
+ else
+ break;
+ }
+ }
+ stream << ")";
+ return 2 | SUPPORTED;
+}
+
+offs_t fr_disassembler::dasm_bop(std::ostream &stream, u16 opcode, const char *inst)
+{
+ // Operands are 4-bit immediate mask and upper or lower nibble of memory
+ util::stream_format(stream, "%-8s#0x%X, @R%d", inst, (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+}
+
+offs_t fr_disassembler::dasm_cop(std::ostream &stream, u16 op1, u16 op2, const char *inst, bool crj, bool cri)
+{
+ // Coprocessor instructions
+ util::stream_format(stream, "%-8s#%d, ", inst, op1 & 0x000f);
+ format_u8(stream, (op2 & 0xff00) >> 8);
+ util::stream_format(stream, ", %sR%d, %sR%d", crj ? "C" : "", (op2 & 0x00f0) >> 4, cri ? "C" : "", op2 & 0x000f);
+ return 4 | SUPPORTED;
+}
+
+offs_t fr_disassembler::dasm_call(std::ostream &stream, offs_t pc, const char *inst, u16 disp)
+{
+ // 12-bit relative calls, with or without delay slot
+ util::stream_format(stream, "%-8s", inst);
+ if (disp >= 0x800)
+ format_label(stream, pc + 2 - 0x1000 + disp);
+ else
+ format_label(stream, pc + 2 + disp);
+ return 2 | SUPPORTED | STEP_OVER;
+}
+
+offs_t fr_disassembler::dasm_branch(std::ostream &stream, offs_t pc, const char *inst, u16 disp)
+{
+ // Conditional/unconditional 9-bit relative branches, with or without delay slot
+ util::stream_format(stream, "%-8s", inst);
+ if (disp >= 0x100)
+ format_label(stream, pc + 2 - 0x200 + disp);
+ else
+ format_label(stream, pc + 2 + disp);
+ return 2 | SUPPORTED;
+}
+
+offs_t fr_disassembler::dasm_07(std::ostream &stream, offs_t pc, const fr_disassembler::data_buffer &opcodes, u16 opcode)
+{
+ switch (opcode & 0x00f0)
+ {
+ case 0x00:
+ util::stream_format(stream, "%-8s@R15+, R%d", "LD", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x10:
+ util::stream_format(stream, "%-8sR%d, PS", "MOV", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x80:
+ util::stream_format(stream, "%-8s@R15+, ", "LD");
+ format_rs(stream, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x90:
+ util::stream_format(stream, "%-8s@R15+, PS", "MOV");
+ return 2 | SUPPORTED;
+
+ default:
+ return dasm_invalid(stream, opcode);
+ }
+}
+
+offs_t fr_disassembler::dasm_17(std::ostream &stream, offs_t pc, const fr_disassembler::data_buffer &opcodes, u16 opcode)
+{
+ switch (opcode & 0x00f0)
+ {
+ case 0x00:
+ util::stream_format(stream, "%-8sR%d, @-R15", "ST", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x10:
+ util::stream_format(stream, "%-8sPS, R%d", "MOV", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x80:
+ util::stream_format(stream, "%-8s", "ST");
+ format_rs(stream, opcode & 0x000f);
+ stream << ", @-R15";
+ return 2 | SUPPORTED;
+
+ case 0x90:
+ util::stream_format(stream, "%-8sPS, @-R15", "ST");
+ return 2 | SUPPORTED;
+
+ default:
+ return dasm_invalid(stream, opcode);
+ }
+}
+
+offs_t fr_disassembler::dasm_97(std::ostream &stream, offs_t pc, const fr_disassembler::data_buffer &opcodes, u16 opcode)
+{
+ switch (opcode & 0x00f0)
+ {
+ case 0x00:
+ util::stream_format(stream, "%-8s@R%d", "JMP", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x10:
+ util::stream_format(stream, "%-8s@R%d", "CALL", opcode & 0x000f);
+ return 2 | SUPPORTED | STEP_OVER;
+
+ case 0x20:
+ if ((opcode & 0x000f) == 0)
+ {
+ stream << "RET";
+ return 2 | SUPPORTED | STEP_OUT;
+ }
+ else
+ return dasm_invalid(stream, opcode);
+
+ case 0x30:
+ if ((opcode & 0x000f) == 0)
+ {
+ stream << "RETI";
+ return 2 | SUPPORTED | STEP_OUT;
+ }
+ else
+ return dasm_invalid(stream, opcode);
+
+ case 0x40:
+ util::stream_format(stream, "%-8sR%d", "DIV0S", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x50:
+ util::stream_format(stream, "%-8sR%d", "DIV0U", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x60:
+ util::stream_format(stream, "%-8sR%d", "DIV1", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x70:
+ util::stream_format(stream, "%-8sR%d", "DIV2", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x80:
+ util::stream_format(stream, "%-8sR%d", "EXTSB", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x90:
+ util::stream_format(stream, "%-8sR%d", "EXTUB", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0xa0:
+ util::stream_format(stream, "%-8sR%d", "EXTSH", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0xb0:
+ util::stream_format(stream, "%-8sR%d", "EXTUH", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ default:
+ return dasm_invalid(stream, opcode);
+ }
+}
+
+offs_t fr_disassembler::dasm_9f(std::ostream &stream, offs_t pc, const fr_disassembler::data_buffer &opcodes, u16 opcode)
+{
+ switch (opcode & 0x00f0)
+ {
+ case 0x00:
+ util::stream_format(stream, "%-8s@R%d", "JMP:D", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x10:
+ util::stream_format(stream, "%-8s@R%d", "CALL:D", opcode & 0x000f);
+ return 2 | SUPPORTED | STEP_OVER | step_over_extra(1);
+
+ case 0x20:
+ if ((opcode & 0x000f) == 0)
+ {
+ stream << "RET:D";
+ return 2 | SUPPORTED | STEP_OUT | step_over_extra(1);
+ }
+ else
+ return dasm_invalid(stream, opcode);
+
+
+ case 0x30:
+ if ((opcode & 0x000f) == 0)
+ {
+ // Emulator software interrupt (#0x09)
+ stream << "INTE";
+ return 2 | SUPPORTED | STEP_OVER;
+ }
+ else
+ return dasm_invalid(stream, opcode);
+
+ case 0x60:
+ if ((opcode & 0x000f) == 0)
+ {
+ stream << "DIV3";
+ return 2 | SUPPORTED;
+ }
+ else
+ return dasm_invalid(stream, opcode);
+
+ case 0x70:
+ if ((opcode & 0x000f) == 0)
+ {
+ stream << "DIV4S";
+ return 2 | SUPPORTED;
+ }
+ else
+ return dasm_invalid(stream, opcode);
+
+
+ case 0x80: // LDI:32
+ util::stream_format(stream, "%-8s", "LDI");
+ format_i32(stream, opcodes.r32(pc + 2));
+ util::stream_format(stream, ", R%d", opcode & 0x000f);
+ return 6 | SUPPORTED;
+
+ case 0x90:
+ if ((opcode & 0x000f) == 0)
+ {
+ stream << "LEAVE";
+ return 2 | SUPPORTED;
+ }
+ else
+ return dasm_invalid(stream, opcode);
+
+ case 0xa0:
+ if ((opcode & 0x000f) == 0)
+ {
+ stream << "NOP";
+ return 2 | SUPPORTED;
+ }
+ else
+ return dasm_invalid(stream, opcode);
+
+ case 0xc0:
+ return dasm_cop(stream, opcode, opcodes.r16(pc + 2), "COPOP", true, true);
+
+ case 0xd0:
+ return dasm_cop(stream, opcode, opcodes.r16(pc + 2), "COPLD", false, true);
+
+ case 0xe0:
+ return dasm_cop(stream, opcode, opcodes.r16(pc + 2), "COPST", true, false);
+
+ case 0xf0:
+ return dasm_cop(stream, opcode, opcodes.r16(pc + 2), "COPSV", true, false);
+
+ default:
+ return dasm_invalid(stream, opcode);
+ }
+}
+
+offs_t fr_disassembler::disassemble(std::ostream &stream, offs_t pc, const fr_disassembler::data_buffer &opcodes, const fr_disassembler::data_buffer &params)
+{
+ u16 opcode = opcodes.r16(pc);
+
+ switch (opcode >> 8)
+ {
+ case 0x00:
+ util::stream_format(stream, "%-8s", "LD");
+ format_ac_rdisp(stream, (opcode & 0x00f0) >> 4);
+ util::stream_format(stream, ", R%d", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x01:
+ util::stream_format(stream, "%-8s", "LDUH");
+ format_ac_rdisp(stream, (opcode & 0x00f0) >> 4);
+ util::stream_format(stream, ", R%d", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x02:
+ util::stream_format(stream, "%-8s", "LDUB");
+ format_ac_rdisp(stream, (opcode & 0x00f0) >> 4);
+ util::stream_format(stream, ", R%d", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x03:
+ util::stream_format(stream, "%-8s", "LD");
+ format_sp_udisp(stream, (opcode & 0x00f0) >> 2);
+ util::stream_format(stream, ", R%d", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x04:
+ util::stream_format(stream, "%-8s@R%d, R%d", "LD", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x05:
+ util::stream_format(stream, "%-8s@R%d, R%d", "LDUH", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x06:
+ util::stream_format(stream, "%-8s@R%d, R%d", "LDUB", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x07:
+ return dasm_07(stream, pc, opcodes, opcode);
+
+ case 0x08:
+ util::stream_format(stream, "%-8s", "DMOV");
+ format_dir(stream, (opcode & 0x00ff) << 2);
+ stream << ", R13";
+ return 2 | SUPPORTED;
+
+ case 0x09:
+ util::stream_format(stream, "%-8s", "DMOVH");
+ format_dir(stream, (opcode & 0x00ff) << 1);
+ stream << ", R13";
+ return 2 | SUPPORTED;
+
+ case 0x0a:
+ util::stream_format(stream, "%-8s", "DMOVB");
+ format_dir(stream, opcode & 0x00ff);
+ stream << ", R13";
+ return 2 | SUPPORTED;
+
+ case 0x0b:
+ util::stream_format(stream, "%-8s", "DMOV");
+ format_dir(stream, (opcode & 0x00ff) << 2);
+ stream << ", @-R15";
+ return 2 | SUPPORTED;
+
+ case 0x0c:
+ util::stream_format(stream, "%-8s", "DMOV");
+ format_dir(stream, (opcode & 0x00ff) << 2);
+ stream << ", @R13+";
+ return 2 | SUPPORTED;
+
+ case 0x0d:
+ util::stream_format(stream, "%-8s", "DMOVH");
+ format_dir(stream, (opcode & 0x00ff) << 1);
+ stream << ", @R13+";
+ return 2 | SUPPORTED;
+
+ case 0x0e:
+ util::stream_format(stream, "%-8s", "DMOVB");
+ format_dir(stream, opcode & 0x00ff);
+ stream << ", @R13+";
+ return 2 | SUPPORTED;
+
+ case 0x0f:
+ util::stream_format(stream, "%-8s", "ENTER");
+ format_u10(stream, (opcode & 0x00ff) << 2);
+ return 2 | SUPPORTED;
+
+ case 0x10:
+ util::stream_format(stream, "%-8sR%d, ", "ST", opcode & 0x000f);
+ format_ac_rdisp(stream, (opcode & 0x00f0) >> 4);
+ return 2 | SUPPORTED;
+
+ case 0x11:
+ util::stream_format(stream, "%-8sR%d, ", "STH", opcode & 0x000f);
+ format_ac_rdisp(stream, (opcode & 0x00f0) >> 4);
+ return 2 | SUPPORTED;
+
+ case 0x12:
+ util::stream_format(stream, "%-8sR%d, ", "STB", opcode & 0x000f);
+ format_ac_rdisp(stream, (opcode & 0x00f0) >> 4);
+ return 2 | SUPPORTED;
+
+ case 0x13:
+ util::stream_format(stream, "%-8sR%d, ", "ST", opcode & 0x000f);
+ format_sp_udisp(stream, (opcode & 0x00f0) >> 2);
+ return 2 | SUPPORTED;
+
+ case 0x14:
+ util::stream_format(stream, "%-8sR%d, @R%d", "ST", opcode & 0x000f, (opcode & 0x00f0) >> 4);
+ return 2 | SUPPORTED;
+
+ case 0x15:
+ util::stream_format(stream, "%-8sR%d, @R%d", "STH", opcode & 0x000f, (opcode & 0x00f0) >> 4);
+ return 2 | SUPPORTED;
+
+ case 0x16:
+ util::stream_format(stream, "%-8sR%d, @R%d", "STB", opcode & 0x000f, (opcode & 0x00f0) >> 4);
+ return 2 | SUPPORTED;
+
+ case 0x17:
+ return dasm_17(stream, pc, opcodes, opcode);
+
+ case 0x18:
+ util::stream_format(stream, "%-8sR13, ", "DMOV");
+ format_dir(stream, (opcode & 0x00ff) << 2);
+ return 2 | SUPPORTED;
+
+ case 0x19:
+ util::stream_format(stream, "%-8sR13, ", "DMOVH");
+ format_dir(stream, (opcode & 0x00ff) << 1);
+ return 2 | SUPPORTED;
+
+ case 0x1a:
+ util::stream_format(stream, "%-8sR13, ", "DMOVB");
+ format_dir(stream, opcode & 0x00ff);
+ return 2 | SUPPORTED;
+
+ case 0x1b:
+ util::stream_format(stream, "%-8s@R15+, ", "DMOV");
+ format_dir(stream, (opcode & 0x00ff) << 2);
+ return 2 | SUPPORTED;
+
+ case 0x1c:
+ util::stream_format(stream, "%-8s@R13+, ", "DMOV");
+ format_dir(stream, (opcode & 0x00ff) << 2);
+ return 2 | SUPPORTED;
+
+ case 0x1d:
+ util::stream_format(stream, "%-8s@R13+, ", "DMOVH");
+ format_dir(stream, (opcode & 0x00ff) << 1);
+ return 2 | SUPPORTED;
+
+ case 0x1e:
+ util::stream_format(stream, "%-8s@R13+, ", "DMOVB");
+ format_dir(stream, opcode & 0x00ff);
+ return 2 | SUPPORTED;
+
+ case 0x1f:
+ util::stream_format(stream, "%-8s", "INT");
+ format_u8(stream, opcode & 0x00ff);
+ return 2 | SUPPORTED | STEP_OVER;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ return dasm_ld_fp_disp(stream, opcode, "LD", 2);
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ return dasm_st_fp_disp(stream, opcode, "ST", 2);
+
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ return dasm_ld_fp_disp(stream, opcode, "LDUH", 1);
+
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ return dasm_st_fp_disp(stream, opcode, "STH", 1);
+
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ return dasm_ld_fp_disp(stream, opcode, "LDUB", 0);
+
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ return dasm_st_fp_disp(stream, opcode, "STB", 0);
+
+ case 0x80:
+ return dasm_bop(stream, opcode, "BANDL");
+
+ case 0x81:
+ return dasm_bop(stream, opcode, "BANDH");
+
+ case 0x82:
+ return dasm_rrop(stream, opcode, "AND");
+
+ case 0x83:
+ util::stream_format(stream, "%-8s", "ANDCCR");
+ format_u8(stream, opcode & 0x00ff);
+ return 2 | SUPPORTED;
+
+ case 0x84:
+ util::stream_format(stream, "%-8sR%d, @R%d", "AND", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x85:
+ util::stream_format(stream, "%-8sR%d, @R%d", "ANDH", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x86:
+ util::stream_format(stream, "%-8sR%d, @R%d", "ANDB", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x87:
+ util::stream_format(stream, "%-8s", "STILM");
+ format_u8(stream, opcode & 0x00ff);
+ return 2 | SUPPORTED;
+
+ case 0x88:
+ return dasm_bop(stream, opcode, "BTSTL");
+
+ case 0x89:
+ return dasm_bop(stream, opcode, "BTSTH");
+
+ case 0x8a:
+ util::stream_format(stream, "%-8s@R%d, R%d", "XCHB", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x8b:
+ return dasm_rrop(stream, opcode, "MOV");
+
+ case 0x8c:
+ return dasm_ldstm(stream, opcode, "LDM0");
+
+ case 0x8d:
+ return dasm_ldstm(stream, opcode, "LDM1");
+
+ case 0x8e:
+ return dasm_ldstm(stream, opcode, "STM0");
+
+ case 0x8f:
+ return dasm_ldstm(stream, opcode, "STM1");
+
+ case 0x90:
+ return dasm_bop(stream, opcode, "BORL");
+
+ case 0x91:
+ return dasm_bop(stream, opcode, "BORH");
+
+ case 0x92:
+ return dasm_rrop(stream, opcode, "OR");
+
+ case 0x93:
+ util::stream_format(stream, "%-8s", "ORCCR");
+ format_u8(stream, opcode & 0x00ff);
+ return 2 | SUPPORTED;
+
+ case 0x94:
+ util::stream_format(stream, "%-8sR%d, @R%d", "OR", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x95:
+ util::stream_format(stream, "%-8sR%d, @R%d", "ORH", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x96:
+ util::stream_format(stream, "%-8sR%d, @R%d", "ORB", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x97:
+ return dasm_97(stream, pc, opcodes, opcode);
+
+ case 0x98:
+ return dasm_bop(stream, opcode, "BEORL");
+
+ case 0x99:
+ return dasm_bop(stream, opcode, "BEORH");
+
+ case 0x9a:
+ return dasm_rrop(stream, opcode, "EOR");
+
+ case 0x9b: // LDI:20
+ util::stream_format(stream, "%-8s", "LDI");
+ format_i20(stream, u32(opcode & 0x00f0) << 12 | opcodes.r16(pc + 2));
+ util::stream_format(stream, ", R%d", opcode & 0x000f);
+ return 4 | SUPPORTED;
+
+ case 0x9c:
+ util::stream_format(stream, "%-8sR%d, @R%d", "EOR", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x9d:
+ util::stream_format(stream, "%-8sR%d, @R%d", "EORH", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x9e:
+ util::stream_format(stream, "%-8sR%d, @R%d", "EORB", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0x9f:
+ return dasm_9f(stream, pc, opcodes, opcode);
+
+ case 0xa0:
+ case 0xa1: // ADDN2
+ return dasm_i4op(stream, opcode, "ADDN");
+
+ case 0xa2:
+ return dasm_rrop(stream, opcode, "ADDN");
+
+ case 0xa3:
+ util::stream_format(stream, "%-8s#", "ADDSP");
+ format_disp(stream, opcode & 0x00ff, 2);
+ return 2 | SUPPORTED;
+
+ case 0xa4:
+ case 0xa5: // ADD2
+ return dasm_i4op(stream, opcode, "ADD");
+
+ case 0xa6:
+ return dasm_rrop(stream, opcode, "ADD");
+
+ case 0xa7:
+ return dasm_rrop(stream, opcode, "ADDC");
+
+ case 0xa8:
+ case 0xa9: // CMP2
+ return dasm_i4op(stream, opcode, "CMP");
+
+ case 0xaa:
+ return dasm_rrop(stream, opcode, "CMP");
+
+ case 0xab:
+ return dasm_rrop(stream, opcode, "MULH");
+
+ case 0xac:
+ return dasm_rrop(stream, opcode, "SUB");
+
+ case 0xad:
+ return dasm_rrop(stream, opcode, "SUBC");
+
+ case 0xae:
+ return dasm_rrop(stream, opcode, "SUBN");
+
+ case 0xaf:
+ return dasm_rrop(stream, opcode, "MUL");
+
+ case 0xb0:
+ case 0xb1: // LSR2
+ return dasm_shift(stream, opcode, "LSR");
+
+ case 0xb2:
+ return dasm_rrop(stream, opcode, "LSR");
+
+ case 0xb3:
+ util::stream_format(stream, "%-8sR%d, ", "MOV", opcode & 0x000f);
+ format_rs(stream, (opcode & 0x00f0) >> 4);
+ return 2 | SUPPORTED;
+
+ case 0xb4:
+ case 0xb5: // LSL2
+ return dasm_shift(stream, opcode, "LSL");
+
+ case 0xb6:
+ return dasm_rrop(stream, opcode, "LSL");
+
+ case 0xb7:
+ util::stream_format(stream, "%-8s", "MOV");
+ format_rs(stream, (opcode & 0x00f0) >> 4);
+ util::stream_format(stream, ", R%d", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0xb8:
+ case 0xb9: // ASR2
+ return dasm_shift(stream, opcode, "ASR");
+
+ case 0xba:
+ return dasm_rrop(stream, opcode, "ASR");
+
+ case 0xbb:
+ return dasm_rrop(stream, opcode, "MULUH");
+
+ case 0xbc:
+ util::stream_format(stream, "%-8s@R%d+, #%d", "LDRES", opcode & 0x000f, (opcode & 0x00f0) >> 4);
+ return 2 | SUPPORTED;
+
+ case 0xbd:
+ util::stream_format(stream, "%-8s#%d, @R%d+", "STRES", (opcode & 0x00f0) >> 4, opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0xbf:
+ return dasm_rrop(stream, opcode, "MULU");
+
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: // LDI:8
+ util::stream_format(stream, "%-8s", "LDI");
+ format_i8(stream, (opcode & 0x0ff0) >> 4);
+ util::stream_format(stream, ", R%d", opcode & 0x000f);
+ return 2 | SUPPORTED;
+
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ return dasm_call(stream, pc, "CALL", (opcode & 0x07ff) << 1);
+
+ case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ return dasm_call(stream, pc, "CALL:D", (opcode & 0x07ff) << 1) | step_over_extra(1);
+
+ case 0xe0:
+ return dasm_branch(stream, pc, "BRA", (opcode & 0x00ff) << 1);
+
+ case 0xe1:
+ return dasm_branch(stream, pc, "BNO", (opcode & 0x00ff) << 1);
+
+ case 0xe2:
+ return dasm_branch(stream, pc, "BEQ", (opcode & 0x00ff) << 1);
+
+ case 0xe3:
+ return dasm_branch(stream, pc, "BNE", (opcode & 0x00ff) << 1);
+
+ case 0xe4:
+ return dasm_branch(stream, pc, "BC", (opcode & 0x00ff) << 1);
+
+ case 0xe5:
+ return dasm_branch(stream, pc, "BNC", (opcode & 0x00ff) << 1);
+
+ case 0xe6:
+ return dasm_branch(stream, pc, "BN", (opcode & 0x00ff) << 1);
+
+ case 0xe7:
+ return dasm_branch(stream, pc, "BP", (opcode & 0x00ff) << 1);
+
+ case 0xe8:
+ return dasm_branch(stream, pc, "BV", (opcode & 0x00ff) << 1);
+
+ case 0xe9:
+ return dasm_branch(stream, pc, "BNV", (opcode & 0x00ff) << 1);
+
+ case 0xea:
+ return dasm_branch(stream, pc, "BLT", (opcode & 0x00ff) << 1);
+
+ case 0xeb:
+ return dasm_branch(stream, pc, "BGE", (opcode & 0x00ff) << 1);
+
+ case 0xec:
+ return dasm_branch(stream, pc, "BLE", (opcode & 0x00ff) << 1);
+
+ case 0xed:
+ return dasm_branch(stream, pc, "BGT", (opcode & 0x00ff) << 1);
+
+ case 0xee:
+ return dasm_branch(stream, pc, "BLS", (opcode & 0x00ff) << 1);
+
+ case 0xef:
+ return dasm_branch(stream, pc, "BHI", (opcode & 0x00ff) << 1);
+
+ case 0xf0:
+ return dasm_branch(stream, pc, "BRA:D", (opcode & 0x00ff) << 1);
+
+ case 0xf1:
+ return dasm_branch(stream, pc, "BNO:D", (opcode & 0x00ff) << 1);
+
+ case 0xf2:
+ return dasm_branch(stream, pc, "BEQ:D", (opcode & 0x00ff) << 1);
+
+ case 0xf3:
+ return dasm_branch(stream, pc, "BNE:D", (opcode & 0x00ff) << 1);
+
+ case 0xf4:
+ return dasm_branch(stream, pc, "BC:D", (opcode & 0x00ff) << 1);
+
+ case 0xf5:
+ return dasm_branch(stream, pc, "BNC:D", (opcode & 0x00ff) << 1);
+
+ case 0xf6:
+ return dasm_branch(stream, pc, "BN:D", (opcode & 0x00ff) << 1);
+
+ case 0xf7:
+ return dasm_branch(stream, pc, "BP:D", (opcode & 0x00ff) << 1);
+
+ case 0xf8:
+ return dasm_branch(stream, pc, "BV:D", (opcode & 0x00ff) << 1);
+
+ case 0xf9:
+ return dasm_branch(stream, pc, "BNV:D", (opcode & 0x00ff) << 1);
+
+ case 0xfa:
+ return dasm_branch(stream, pc, "BLT:D", (opcode & 0x00ff) << 1);
+
+ case 0xfb:
+ return dasm_branch(stream, pc, "BGE:D", (opcode & 0x00ff) << 1);
+
+ case 0xfc:
+ return dasm_branch(stream, pc, "BLE:D", (opcode & 0x00ff) << 1);
+
+ case 0xfd:
+ return dasm_branch(stream, pc, "BGT:D", (opcode & 0x00ff) << 1);
+
+ case 0xfe:
+ return dasm_branch(stream, pc, "BLS:D", (opcode & 0x00ff) << 1);
+
+ case 0xff:
+ return dasm_branch(stream, pc, "BHI:D", (opcode & 0x00ff) << 1);
+
+ default:
+ return dasm_invalid(stream, opcode);
+ }
+}
diff --git a/src/devices/cpu/fr/frdasm.h b/src/devices/cpu/fr/frdasm.h
new file mode 100644
index 00000000000..c02dfbb1b22
--- /dev/null
+++ b/src/devices/cpu/fr/frdasm.h
@@ -0,0 +1,49 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_CPU_FR_FRDASM_H
+#define MAME_CPU_FR_FRDASM_H 1
+
+#pragma once
+
+class fr_disassembler : public util::disasm_interface
+{
+public:
+ // construction/destruction
+ fr_disassembler();
+
+ // 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;
+
+protected:
+ // internal helpers
+ void format_u8(std::ostream &stream, u8 value);
+ void format_i8(std::ostream &stream, u8 value);
+ void format_disp(std::ostream &stream, u8 offs, unsigned shift);
+ void format_u10(std::ostream &stream, u16 value);
+ void format_i20(std::ostream &stream, u32 value);
+ void format_i32(std::ostream &stream, u32 value);
+ void format_label(std::ostream &stream, offs_t addr);
+ void format_dir(std::ostream &stream, u16 addr);
+ void format_ac_rdisp(std::ostream &stream, u8 rj);
+ void format_sp_udisp(std::ostream &stream, u8 disp);
+ void format_rs(std::ostream &stream, u8 reg);
+ offs_t dasm_invalid(std::ostream &stream, u16 opcode);
+ offs_t dasm_i4op(std::ostream &stream, u16 opcode, const char *inst);
+ offs_t dasm_shift(std::ostream &stream, u16 opcode, const char *inst);
+ offs_t dasm_rrop(std::ostream &stream, u16 opcode, const char *inst);
+ offs_t dasm_ld_fp_disp(std::ostream &stream, u16 opcode, const char *inst, unsigned shift);
+ offs_t dasm_st_fp_disp(std::ostream &stream, u16 opcode, const char *inst, unsigned shift);
+ offs_t dasm_ldstm(std::ostream &stream, u16 opcode, const char *inst);
+ offs_t dasm_bop(std::ostream &stream, u16 opcode, const char *inst);
+ offs_t dasm_cop(std::ostream &stream, u16 op1, u16 op2, const char *inst, bool crj, bool cri);
+ offs_t dasm_call(std::ostream &stream, offs_t pc, const char *inst, u16 disp);
+ offs_t dasm_branch(std::ostream &stream, offs_t pc, const char *inst, u16 disp);
+ offs_t dasm_07(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 opcode);
+ offs_t dasm_17(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 opcode);
+ offs_t dasm_97(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 opcode);
+ offs_t dasm_9f(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 opcode);
+};
+
+#endif // MAME_CPU_FR_FRDASM_H
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index 677b3a65edb..3e776f586c0 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -49,6 +49,7 @@ using util::BIT;
#include "cpu/esrip/esripdsm.h"
#include "cpu/f2mc16/f2mc16dasm.h"
#include "cpu/f8/f8dasm.h"
+#include "cpu/fr/frdasm.h"
#include "cpu/g65816/g65816ds.h"
#include "cpu/h6280/6280dasm.h"
#include "cpu/h8/h8d.h"
@@ -359,6 +360,7 @@ static const dasm_table_entry dasm_table[] =
{ "esrip", be, 0, []() -> util::disasm_interface * { return new esrip_disassembler; } },
{ "f2mc16", le, 0, []() -> util::disasm_interface * { return new f2mc16_disassembler; } },
{ "f8", be, 0, []() -> util::disasm_interface * { return new f8_disassembler; } },
+ { "fr", be, 0, []() -> util::disasm_interface * { return new fr_disassembler; } },
{ "g65816", le, 0, []() -> util::disasm_interface * { return new g65816_disassembler(&g65816_unidasm); } },
{ "h6280", le, 0, []() -> util::disasm_interface * { return new h6280_disassembler; } },
{ "h8", be, 0, []() -> util::disasm_interface * { return new h8_disassembler; } },