From 01e459a7119a94475301d397f9c1f8b8487bb58b Mon Sep 17 00:00:00 2001 From: AJR Date: Sat, 12 Jan 2019 14:56:05 -0500 Subject: unidasm: Don't blow up when TMS34010 disassembler tries to read 32-bit operands --- src/tools/unidasm.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'src/tools/unidasm.cpp') diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index e811991b872..328527c85ce 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -841,8 +841,6 @@ unidasm_data_buffer::unidasm_data_buffer(util::disasm_interface *_disasm, const case 3: lr8 = [](offs_t pc) -> u8 { abort(); }; - lr32 = [](offs_t pc) -> u32 { abort(); }; - lr64 = [](offs_t pc) -> u64 { abort(); }; lr16 = [this](offs_t pc) -> u16 { if(pc < base_pc) return 0x0000; @@ -851,6 +849,31 @@ unidasm_data_buffer::unidasm_data_buffer(util::disasm_interface *_disasm, const return 0x0000; return reinterpret_cast(&data[delta])[0]; }; + switch(entry->endian) { + case le: + lr32 = [this](offs_t pc) -> u32 { + if(pc < base_pc) + return 0x00000000; + offs_t delta = (pc - base_pc) >> 3; + if(delta >= size + 2) + return 0x00000000; + auto p = reinterpret_cast(&data[delta]); + return p[0] | (u32(p[1]) << 16); + }; + break; + case be: + lr32 = [this](offs_t pc) -> u32 { + if(pc < base_pc) + return 0x00000000; + offs_t delta = (pc - base_pc) >> 3; + if(delta >= size + 2) + return 0x00000000; + auto p = reinterpret_cast(&data[delta]); + return (u32(p[0]) << 16) | p[1]; + }; + break; + } + lr64 = [](offs_t pc) -> u64 { abort(); }; break; default: -- cgit v1.2.3-70-g09d2 From bb0702d2d5f5ca6c89049ae6285c0701f2a488fb Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Thu, 24 Jan 2019 15:03:38 +0700 Subject: alpha: new cpu, disassembler only --- scripts/src/cpu.lua | 17 + scripts/target/mame/mess.lua | 1 + src/devices/cpu/alpha/alpha.cpp | 91 +++++ src/devices/cpu/alpha/alpha.h | 56 +++ src/devices/cpu/alpha/alphad.cpp | 783 +++++++++++++++++++++++++++++++++++++++ src/devices/cpu/alpha/alphad.h | 23 ++ src/tools/unidasm.cpp | 2 + 7 files changed, 973 insertions(+) create mode 100644 src/devices/cpu/alpha/alpha.cpp create mode 100644 src/devices/cpu/alpha/alpha.h create mode 100644 src/devices/cpu/alpha/alphad.cpp create mode 100644 src/devices/cpu/alpha/alphad.h (limited to 'src/tools/unidasm.cpp') diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 654f5bc41ca..c3218773035 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -2780,3 +2780,20 @@ if (_OPTIONS["with-tools"]) then table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/nuon/nuondasm.cpp") table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/nuon/nuondasm.h") end + +-------------------------------------------------- +-- DEC Alpha (EV4/EV5/EV6/EV7) series +--@src/devices/cpu/alpha/alpha.h,CPUS["ALPHA"] = true +-------------------------------------------------- + +if (CPUS["ALPHA"]~=null) then + files { + MAME_DIR .. "src/devices/cpu/alpha/alpha.cpp", + MAME_DIR .. "src/devices/cpu/alpha/alpha.h", + } +end + +if (CPUS["ALPHA"]~=null or _OPTIONS["with-tools"]) then + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/alpha/alphad.cpp") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/alpha/alphad.h") +end diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 87239e7d969..9e8f282c9e6 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -136,6 +136,7 @@ CPUS["MB86901"] = true CPUS["NANOPROCESSOR"] = true CPUS["CLIPPER"] = true CPUS["CAPRICORN"] = true +CPUS["ALPHA"] = true --CPUS["DSPP"] = true -------------------------------------------------- diff --git a/src/devices/cpu/alpha/alpha.cpp b/src/devices/cpu/alpha/alpha.cpp new file mode 100644 index 00000000000..f4181060128 --- /dev/null +++ b/src/devices/cpu/alpha/alpha.cpp @@ -0,0 +1,91 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +/* + * An implementation of the Digital Alpha CPU family. + * + * Sources + * + * http://bitsavers.org/pdf/dec/alpha/21064-aa-RISC%20Microprocessor%20Preliminary%20Data%20Sheet-apr92.pdf + * http://bitsavers.org/pdf/dec/alpha/Sites_AlphaAXPArchitectureReferenceManual_2ed_1995.pdf + * + * TODO + * - skeleton only (wip) + */ + +#include "emu.h" +#include "debugger.h" +#include "alpha.h" +#include "alphad.h" + +#define LOG_GENERAL (1U << 0) +#define LOG_EXCEPTION (1U << 1) +#define LOG_SYSCALLS (1U << 2) + +//#define VERBOSE (LOG_GENERAL | LOG_EXCEPTION) + +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(DEC_21064, dec_21064_device, "21064", "DEC Alpha 21064") + +dec_21064_device::dec_21064_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : alpha_device(mconfig, DEC_21064, tag, owner, clock) +{ +} + +alpha_device::alpha_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) + : cpu_device(mconfig, type, tag, owner, clock) + , m_main_config("main", ENDIANNESS_LITTLE, 64, 32, 0) + , m_icount(0) +{ +} + +void alpha_device::device_start() +{ + set_icountptr(m_icount); + + save_item(NAME(m_pc)); + save_item(NAME(m_r)); + save_item(NAME(m_f)); + + state_add(STATE_GENPC, "GENPC", m_pc).noshow(); + state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow(); + + state_add(64, "PC", m_pc); + + // integer registers + for (unsigned i = 0; i < 32; i++) + state_add(i, util::string_format("R%d", i).c_str(), m_r[i]); + + // floating point registers + for (unsigned i = 0; i < 32; i++) + state_add(i + 32, util::string_format("F%d", i).c_str(), m_f[i]); +} + +void alpha_device::device_reset() +{ +} + +void alpha_device::execute_run() +{ + m_icount = 0; +} + +void alpha_device::execute_set_input(int inputnum, int state) +{ +} + +device_memory_interface::space_config_vector alpha_device::memory_space_config() const +{ + return space_config_vector { std::make_pair(0, &m_main_config) }; +} + +bool alpha_device::memory_translate(int spacenum, int intention, offs_t &address) +{ + return true; +} + +std::unique_ptr alpha_device::create_disassembler() +{ + return std::make_unique(); +} diff --git a/src/devices/cpu/alpha/alpha.h b/src/devices/cpu/alpha/alpha.h new file mode 100644 index 00000000000..a4d66e806c7 --- /dev/null +++ b/src/devices/cpu/alpha/alpha.h @@ -0,0 +1,56 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +#ifndef MAME_CPU_ALPHA_ALPHA_H +#define MAME_CPU_ALPHA_ALPHA_H + +#pragma once + +#include +#include "softfloat/milieu.h" +#include "softfloat/softfloat.h" + +class alpha_device : public cpu_device +{ +public: + +protected: + alpha_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_execute_interface overrides + virtual u32 execute_min_cycles() const override { return 1; } + virtual u32 execute_max_cycles() const override { return 1; } + virtual u32 execute_input_lines() const override { return 6; } + virtual void execute_run() override; + virtual void execute_set_input(int inputnum, int state) override; + + // device_memory_interface overrides + virtual space_config_vector memory_space_config() const override; + virtual bool memory_translate(int spacenum, int intention, offs_t &address) override; + + // device_disasm_interface overrides + virtual std::unique_ptr create_disassembler() override; + +private: + // emulation state + address_space_config m_main_config; + int m_icount; + + u64 m_pc; + u64 m_r[32]; // R31 is zero + u64 m_f[32]; // F31 is zero +}; + +class dec_21064_device : public alpha_device +{ +public: + dec_21064_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + +DECLARE_DEVICE_TYPE(DEC_21064, dec_21064_device) + +#endif // MAME_CPU_ALPHA_ALPHA_H diff --git a/src/devices/cpu/alpha/alphad.cpp b/src/devices/cpu/alpha/alphad.cpp new file mode 100644 index 00000000000..3282036ba0a --- /dev/null +++ b/src/devices/cpu/alpha/alphad.cpp @@ -0,0 +1,783 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +/* + * TODO + * - enforce "should be zero" fields + * - enforce "Ra must be R31" + * - assembly and register naming preferences + * - operating environment dependent PALcode + */ + +#include "emu.h" +#include "alphad.h" + +// instruction field extraction +#define Ra(x) ((x >> 21) & 31) +#define Rb(x) ((x >> 16) & 31) +#define Rc(x) (x & 31) +#define Im(x) u8(x >> 13) +#define Disp_M(x) s16(x) +#define Disp_B(x) (s32(x << 11) >> 9) + +// instruction formats +#define OPERATE_RRR(opcode, ra, rb, rc) util::stream_format(stream, "%-10s %s, %s, %s", opcode, R[ra], R[rb], R[rc]) +#define OPERATE_FFF(opcode, ra, rb, rc) util::stream_format(stream, "%-10s %s, %s, %s", opcode, F[ra], F[rb], F[rc]) +#define OPERATE_RIR(opcode, ra, im, rc) util::stream_format(stream, "%-10s %s, #%d, %s", opcode, R[ra], im, R[rc]) +#define OPERATE_RR(opcode, rb, rc) util::stream_format(stream, "%-10s %s, %s", opcode, R[rb], R[rc]) +#define OPERATE_FF(opcode, rb, rc) util::stream_format(stream, "%-10s %s, %s", opcode, F[rb], F[rc]) +#define OPERATE_RF(opcode, ra, rc) util::stream_format(stream, "%-10s %s, %s", opcode, R[ra], F[rc]) +#define OPERATE_FR(opcode, ra, rc) util::stream_format(stream, "%-10s %s, %s", opcode, F[ra], R[rc]) +#define OPERATE_IR(opcode, im, rc) util::stream_format(stream, "%-10s #%d, %s", opcode, im, R[rc]) +#define OPERATE_R(opcode, rc) util::stream_format(stream, "%-10s %s", opcode, R[rc]) + +#define MEMORY_R(opcode, ra, disp, rb) util::stream_format(stream, "%-10s %s, %d(%s)", opcode, R[ra], disp, R[rb]) +#define MEMORY_F(opcode, ra, disp, rb) util::stream_format(stream, "%-10s %s, %d(%s)", opcode, F[ra], disp, R[rb]) +#define BRANCH_R(opcode, ra, offset) util::stream_format(stream, "%-10s %s, 0x%x", opcode, R[ra], pc + 4 + offset) +#define BRANCH_F(opcode, ra, offset) util::stream_format(stream, "%-10s %s, 0x%x", opcode, F[ra], pc + 4 + offset) + +#define JUMP(opcode, ra, rb) util::stream_format(stream, "%-10s %s, (%s)", opcode, R[ra], R[rb]) + +#define MISC_0(opcode) util::stream_format(stream, "%-10s", opcode) +#define MISC_R(opcode, ra) util::stream_format(stream, "%-10s %s", opcode, R[ra]) +#define MISC_M(opcode, rb) util::stream_format(stream, "%-10s (%s)", opcode, R[rb]) + +#define PAL(opcode, fnc) util::stream_format(stream, "%-10s #0x%x", opcode, fnc) +#define PAL_0(opcode) util::stream_format(stream, "%-10s", opcode) + +#define RESERVED(opcode) util::stream_format(stream, "%-10s", opcode) +#define UNKNOWN(type) util::stream_format(stream, "unknown %s", type) + +// register names +const char *const alpha_disassembler::R[] = +{ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" +}; + +const char *const alpha_disassembler::F[] = +{ + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31" +}; + +offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) +{ + offs_t const bytes = 4; + u32 flags = SUPPORTED; + + u32 const instruction = opcodes.r32(pc); + + switch (instruction >> 26) + { + // pal format + case 0x00: + switch (instruction & 0x03ffffff) + { + case 0x0000: PAL_0("halt"); break; + case 0x0002: PAL_0("draina"); break; + case 0x0086: PAL_0("imb"); break; + + default: PAL("call_pal", instruction & 0x03ffffff); break; // CALL_PAL + } + break; + + // reserved opcodes + case 0x01: RESERVED("opc01"); break; // OPC01 + case 0x02: RESERVED("opc02"); break; // OPC02 + case 0x03: RESERVED("opc03"); break; // OPC03 + case 0x04: RESERVED("opc04"); break; // OPC04 + case 0x05: RESERVED("opc05"); break; // OPC05 + case 0x06: RESERVED("opc06"); break; // OPC06 + case 0x07: RESERVED("opc07"); break; // OPC07 + + // memory format + case 0x08: MEMORY_R("lda", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDA + case 0x09: MEMORY_R("ldah", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDAH + case 0x0a: MEMORY_R("ldbu", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDBU (BWX) + case 0x0b: MEMORY_R("ldq_u", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDQ_U + case 0x0c: MEMORY_R("ldwu", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDWU (BWX) + case 0x0d: MEMORY_R("stw", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STW (BWX) + case 0x0e: MEMORY_R("stb", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STB (BWX) + case 0x0f: MEMORY_R("stq_u", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STQ_U + + // operate format + case 0x10: // INTA* (integer arithmetic) + switch ((instruction >> 5) & 0xff) + { + // register variants + case 0x00: OPERATE_RRR("addl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDL + case 0x02: OPERATE_RRR("s4addl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S4ADDL + case 0x09: OPERATE_RRR("subl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBL + case 0x0b: OPERATE_RRR("s4subl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S4SUBL + case 0x0f: OPERATE_RRR("cmpbge", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPBGE + case 0x12: OPERATE_RRR("s8addl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S8ADDL + case 0x1b: OPERATE_RRR("s8subl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S8SUBL + case 0x1d: OPERATE_RRR("cmpult", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPULT + case 0x20: OPERATE_RRR("addq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDQ + case 0x22: OPERATE_RRR("s4addq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S4ADDQ + case 0x29: OPERATE_RRR("subq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBQ + case 0x2b: OPERATE_RRR("s4subq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S4SUBQ + case 0x2d: OPERATE_RRR("cmpeq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPEQ + case 0x32: OPERATE_RRR("s8addq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S8ADDQ + case 0x3b: OPERATE_RRR("s8subq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S8SUBQ + case 0x3d: OPERATE_RRR("cmpule", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPULE + case 0x40: OPERATE_RRR("addl/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDL/V + case 0x49: OPERATE_RRR("subl/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBL/V + case 0x4d: OPERATE_RRR("cmplt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPLT + case 0x60: OPERATE_RRR("addq/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDQ/V + case 0x69: OPERATE_RRR("subq/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBQ/V + case 0x6d: OPERATE_RRR("cmple", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPLE + + // immediate variants + case 0x80: OPERATE_RIR("addl", Ra(instruction), Im(instruction), Rc(instruction)); break; // ADDL + case 0x82: OPERATE_RIR("s4addl", Ra(instruction), Im(instruction), Rc(instruction)); break; // S4ADDL + case 0x89: OPERATE_RIR("subl", Ra(instruction), Im(instruction), Rc(instruction)); break; // SUBL + case 0x8b: OPERATE_RIR("s4subl", Ra(instruction), Im(instruction), Rc(instruction)); break; // S4SUBL + case 0x8f: OPERATE_RIR("cmpbge", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPBGE + case 0x92: OPERATE_RIR("s8addl", Ra(instruction), Im(instruction), Rc(instruction)); break; // S8ADDL + case 0x9b: OPERATE_RIR("s8subl", Ra(instruction), Im(instruction), Rc(instruction)); break; // S8SUBL + case 0x9d: OPERATE_RIR("cmpult", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPULT + case 0xa0: OPERATE_RIR("addq", Ra(instruction), Im(instruction), Rc(instruction)); break; // ADDQ + case 0xa2: OPERATE_RIR("s4addq", Ra(instruction), Im(instruction), Rc(instruction)); break; // S4ADDQ + case 0xa9: OPERATE_RIR("subq", Ra(instruction), Im(instruction), Rc(instruction)); break; // SUBQ + case 0xab: OPERATE_RIR("s4subq", Ra(instruction), Im(instruction), Rc(instruction)); break; // S4SUBQ + case 0xad: OPERATE_RIR("cmpeq", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPEQ + case 0xb2: OPERATE_RIR("s8addq", Ra(instruction), Im(instruction), Rc(instruction)); break; // S8ADDQ + case 0xbb: OPERATE_RIR("s8subq", Ra(instruction), Im(instruction), Rc(instruction)); break; // S8SUBQ + case 0xbd: OPERATE_RIR("cmpule", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPULE + case 0xc0: OPERATE_RIR("addl/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // ADDL/V + case 0xc9: OPERATE_RIR("subl/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // SUBL/V + case 0xcd: OPERATE_RIR("cmplt", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPLT + case 0xe0: OPERATE_RIR("addq/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // ADDQ/V + case 0xe9: OPERATE_RIR("subq/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // SUBQ/V + case 0xed: OPERATE_RIR("cmple", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPLE + + default: UNKNOWN("inta*"); break; + } + break; + case 0x11: // INTL* (integer logical) + switch ((instruction >> 5) & 0xff) + { + // register variants + case 0x00: OPERATE_RRR("and", Ra(instruction), Rb(instruction), Rc(instruction)); break; // AND + case 0x08: OPERATE_RRR("bic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // BIC + case 0x14: OPERATE_RRR("cmovlbs", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVLBS + case 0x16: OPERATE_RRR("cmovlbc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVLBC + case 0x20: OPERATE_RRR("bis", Ra(instruction), Rb(instruction), Rc(instruction)); break; // BIS + case 0x24: OPERATE_RRR("cmoveq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVEQ + case 0x26: OPERATE_RRR("cmovne", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVNE + case 0x28: OPERATE_RRR("ornot", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ORNOT + case 0x40: OPERATE_RRR("xor", Ra(instruction), Rb(instruction), Rc(instruction)); break; // XOR + case 0x44: OPERATE_RRR("cmovlt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVLT + case 0x46: OPERATE_RRR("cmovge", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVGE + case 0x48: OPERATE_RRR("eqv", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EQV + case 0x61: OPERATE_RR("amask", Rb(instruction), Rc(instruction)); break; // AMASK + case 0x64: OPERATE_RRR("cmovle", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVLE + case 0x66: OPERATE_RRR("cmovgt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVGT + + // immediate variants + case 0x80: OPERATE_RIR("and", Ra(instruction), Im(instruction), Rc(instruction)); break; // AND + case 0x88: OPERATE_RIR("bic", Ra(instruction), Im(instruction), Rc(instruction)); break; // BIC + case 0x94: OPERATE_RIR("cmovlbs", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVLBS + case 0x96: OPERATE_RIR("cmovlbc", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVLBC + case 0xa0: OPERATE_RIR("bis", Ra(instruction), Im(instruction), Rc(instruction)); break; // BIS + case 0xa4: OPERATE_RIR("cmoveq", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVEQ + case 0xa6: OPERATE_RIR("cmovne", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVNE + case 0xa8: OPERATE_RIR("ornot", Ra(instruction), Im(instruction), Rc(instruction)); break; // ORNOT + case 0xc0: OPERATE_RIR("xor", Ra(instruction), Im(instruction), Rc(instruction)); break; // XOR + case 0xc4: OPERATE_RIR("cmovlt", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVLT + case 0xc6: OPERATE_RIR("cmovge", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVGE + case 0xc8: OPERATE_RIR("eqv", Ra(instruction), Im(instruction), Rc(instruction)); break; // EQV + case 0xe1: OPERATE_IR("amask", Im(instruction), Rc(instruction)); break; // AMASK + case 0xe4: OPERATE_RIR("cmovle", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVLE + case 0xe6: OPERATE_RIR("cmovgt", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVGT + + // TODO: Rb must be literal #1? + case 0xec: OPERATE_R("implver", Rc(instruction)); break; // IMPLVER + + default: UNKNOWN("intl*"); break; + } + break; + case 0x12: // INTS* (integer shift) + switch ((instruction >> 5) & 0xff) + { + // register variants + case 0x02: OPERATE_RRR("mskbl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKBL + case 0x06: OPERATE_RRR("extbl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTBL + case 0x0b: OPERATE_RRR("insbl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSBL + case 0x12: OPERATE_RRR("mskwl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKWL + case 0x16: OPERATE_RRR("extwl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTWL + case 0x1b: OPERATE_RRR("inswl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSWL + case 0x22: OPERATE_RRR("mskll", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKLL + case 0x26: OPERATE_RRR("extll", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTLL + case 0x2b: OPERATE_RRR("insll", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSLL + case 0x30: OPERATE_RRR("zap", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ZAP + case 0x31: OPERATE_RRR("zapnot", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ZAPNOT + case 0x32: OPERATE_RRR("mskql", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKQL + case 0x34: OPERATE_RRR("srl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SRL + case 0x36: OPERATE_RRR("extql", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTQL + case 0x39: OPERATE_RRR("sll", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SLL + case 0x3b: OPERATE_RRR("insql", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSQL + case 0x3c: OPERATE_RRR("sra", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SRA + case 0x52: OPERATE_RRR("mskwh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKWH + case 0x57: OPERATE_RRR("inswh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSWH + case 0x5a: OPERATE_RRR("extwh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTWH + case 0x62: OPERATE_RRR("msklh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKLH + case 0x67: OPERATE_RRR("inslh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSLH + case 0x6a: OPERATE_RRR("extlh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTLH + case 0x72: OPERATE_RRR("mskqh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKQH + case 0x77: OPERATE_RRR("insqh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSQH + case 0x7a: OPERATE_RRR("extqh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTQH + + // immediate variants + case 0x82: OPERATE_RIR("mskbl", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKBL + case 0x86: OPERATE_RIR("extbl", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTBL + case 0x8b: OPERATE_RIR("insbl", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSBL + case 0x92: OPERATE_RIR("mskwl", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKWL + case 0x96: OPERATE_RIR("extwl", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTWL + case 0x9b: OPERATE_RIR("inswl", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSWL + case 0xa2: OPERATE_RIR("mskll", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKLL + case 0xa6: OPERATE_RIR("extll", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTLL + case 0xab: OPERATE_RIR("insll", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSLL + case 0xb0: OPERATE_RIR("zap", Ra(instruction), Im(instruction), Rc(instruction)); break; // ZAP + case 0xb1: OPERATE_RIR("zapnot", Ra(instruction), Im(instruction), Rc(instruction)); break; // ZAPNOT + case 0xb2: OPERATE_RIR("mskql", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKQL + case 0xb4: OPERATE_RIR("srl", Ra(instruction), Im(instruction), Rc(instruction)); break; // SRL + case 0xb6: OPERATE_RIR("extql", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTQL + case 0xb9: OPERATE_RIR("sll", Ra(instruction), Im(instruction), Rc(instruction)); break; // SLL + case 0xbb: OPERATE_RIR("insql", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSQL + case 0xbc: OPERATE_RIR("sra", Ra(instruction), Im(instruction), Rc(instruction)); break; // SRA + case 0xd2: OPERATE_RIR("mskwh", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKWH + case 0xd7: OPERATE_RIR("inswh", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSWH + case 0xda: OPERATE_RIR("extwh", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTWH + case 0xe2: OPERATE_RIR("msklh", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKLH + case 0xe7: OPERATE_RIR("inslh", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSLH + case 0xea: OPERATE_RIR("extlh", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTLH + case 0xf2: OPERATE_RIR("mskqh", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKQH + case 0xf7: OPERATE_RIR("insqh", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSQH + case 0xfa: OPERATE_RIR("extqh", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTQH + + default: UNKNOWN("ints*"); break; + } + break; + case 0x13: // INTM* (integer multiply) + switch ((instruction >> 5) & 0xff) + { + // register variants + case 0x00: OPERATE_RRR("mull", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULL + case 0x20: OPERATE_RRR("mulq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULQ + case 0x30: OPERATE_RRR("umulh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // UMULH + case 0x40: OPERATE_RRR("mull/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULL/V + case 0x60: OPERATE_RRR("mulq/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULQ/V + + // immediate variants + case 0x80: OPERATE_RIR("mull", Ra(instruction), Im(instruction), Rc(instruction)); break; // MULL + case 0xa0: OPERATE_RIR("mulq", Ra(instruction), Im(instruction), Rc(instruction)); break; // MULQ + case 0xb0: OPERATE_RIR("umulh", Ra(instruction), Im(instruction), Rc(instruction)); break; // UMULH + case 0xc0: OPERATE_RIR("mull/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // MULL/V + case 0xe0: OPERATE_RIR("mulq/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // MULQ/V + + default: UNKNOWN("intm*"); break; + } + case 0x14: // ITFP* (integer to floating) + switch ((instruction >> 5) & 0x7ff) + { + case 0x004: OPERATE_RF("itofs", Ra(instruction), Rc(instruction)); break; // ITOFS + case 0x00a: OPERATE_FF("sqrtf/c", Rb(instruction), Rc(instruction)); break; // SQRTF/C + case 0x00b: OPERATE_FF("sqrts/c", Rb(instruction), Rc(instruction)); break; // SQRTS/C + case 0x014: OPERATE_RF("itoff", Ra(instruction), Rc(instruction)); break; // ITOFF + case 0x024: OPERATE_RF("itoft", Ra(instruction), Rc(instruction)); break; // ITOFT + case 0x02a: OPERATE_FF("sqrtg/c", Rb(instruction), Rc(instruction)); break; // SQRTG/C + case 0x02b: OPERATE_FF("sqrtt/c", Rb(instruction), Rc(instruction)); break; // SQRTT/C + case 0x04b: OPERATE_FF("sqrts/m", Rb(instruction), Rc(instruction)); break; // SQRTS/M + case 0x06b: OPERATE_FF("sqrtt/m", Rb(instruction), Rc(instruction)); break; // SQRTT/M + case 0x08a: OPERATE_FF("sqrtf", Rb(instruction), Rc(instruction)); break; // SQRTF + case 0x08b: OPERATE_FF("sqrts", Rb(instruction), Rc(instruction)); break; // SQRTS + case 0x0aa: OPERATE_FF("sqrtg", Rb(instruction), Rc(instruction)); break; // SQRTG + case 0x0ab: OPERATE_FF("sqrtt", Rb(instruction), Rc(instruction)); break; // SQRTT + case 0x0cb: OPERATE_FF("sqrts/d", Rb(instruction), Rc(instruction)); break; // SQRTS/D + case 0x0eb: OPERATE_FF("sqrtt/d", Rb(instruction), Rc(instruction)); break; // SQRTT/D + case 0x10a: OPERATE_FF("sqrtf/uc", Rb(instruction), Rc(instruction)); break; // SQRTF/UC + case 0x10b: OPERATE_FF("sqrts/uc", Rb(instruction), Rc(instruction)); break; // SQRTS/UC + case 0x12a: OPERATE_FF("sqrtg/uc", Rb(instruction), Rc(instruction)); break; // SQRTG/UC + case 0x12b: OPERATE_FF("sqrtt/uc", Rb(instruction), Rc(instruction)); break; // SQRTT/UC + case 0x14b: OPERATE_FF("sqrts/um", Rb(instruction), Rc(instruction)); break; // SQRTS/UM + case 0x16b: OPERATE_FF("sqrtt/um", Rb(instruction), Rc(instruction)); break; // SQRTT/UM + case 0x18a: OPERATE_FF("sqrtf/u", Rb(instruction), Rc(instruction)); break; // SQRTF/U + case 0x1aa: OPERATE_FF("sqrtg/u", Rb(instruction), Rc(instruction)); break; // SQRTG/U + case 0x1ab: OPERATE_FF("sqrtt/u", Rb(instruction), Rc(instruction)); break; // SQRTT/U + case 0x1cb: OPERATE_FF("sqrts/ud", Rb(instruction), Rc(instruction)); break; // SQRTS/UD + case 0x1eb: OPERATE_FF("sqrtt/ud", Rb(instruction), Rc(instruction)); break; // SQRTT/UD + case 0x40a: OPERATE_FF("sqrtf/sc", Rb(instruction), Rc(instruction)); break; // SQRTF/SC + case 0x42a: OPERATE_FF("sqrtg/sc", Rb(instruction), Rc(instruction)); break; // SQRTG/SC + case 0x48a: OPERATE_FF("sqrtf/s", Rb(instruction), Rc(instruction)); break; // SQRTF/S + case 0x4aa: OPERATE_FF("sqrtg/s", Rb(instruction), Rc(instruction)); break; // SQRTG/S + case 0x50a: OPERATE_FF("sqrtf/suc", Rb(instruction), Rc(instruction)); break; // SQRTF/SUC + case 0x50b: OPERATE_FF("sqrts/suc", Rb(instruction), Rc(instruction)); break; // SQRTS/SUC + case 0x52a: OPERATE_FF("sqrtg/suc", Rb(instruction), Rc(instruction)); break; // SQRTG/SUC + case 0x52b: OPERATE_FF("sqrtt/suc", Rb(instruction), Rc(instruction)); break; // SQRTT/SUC + case 0x54b: OPERATE_FF("sqrts/sum", Rb(instruction), Rc(instruction)); break; // SQRTS/SUM + case 0x56b: OPERATE_FF("sqrtt/sum", Rb(instruction), Rc(instruction)); break; // SQRTT/SUM + case 0x58a: OPERATE_FF("sqrtf/su", Rb(instruction), Rc(instruction)); break; // SQRTF/SU + case 0x58b: OPERATE_FF("sqrts/su", Rb(instruction), Rc(instruction)); break; // SQRTS/SU + case 0x5aa: OPERATE_FF("sqrtg/su", Rb(instruction), Rc(instruction)); break; // SQRTG/SU + case 0x5ab: OPERATE_FF("sqrtt/su", Rb(instruction), Rc(instruction)); break; // SQRTT/SU + case 0x5cb: OPERATE_FF("sqrts/sud", Rb(instruction), Rc(instruction)); break; // SQRTS/SUD + case 0x5eb: OPERATE_FF("sqrtt/sud", Rb(instruction), Rc(instruction)); break; // SQRTT/SUD + case 0x70b: OPERATE_FF("sqrts/suic", Rb(instruction), Rc(instruction)); break; // SQRTS/SUIC + case 0x72b: OPERATE_FF("sqrtt/suic", Rb(instruction), Rc(instruction)); break; // SQRTT/SUIC + case 0x74b: OPERATE_FF("sqrts/suim", Rb(instruction), Rc(instruction)); break; // SQRTS/SUIM + case 0x76b: OPERATE_FF("sqrtt/suim", Rb(instruction), Rc(instruction)); break; // SQRTT/SUIM + case 0x78b: OPERATE_FF("sqrts/sui", Rb(instruction), Rc(instruction)); break; // SQRTS/SUI + case 0x7ab: OPERATE_FF("sqrtt/sui", Rb(instruction), Rc(instruction)); break; // SQRTT/SUI + case 0x7cb: OPERATE_FF("sqrts/suid", Rb(instruction), Rc(instruction)); break; // SQRTS/SUID + case 0x7eb: OPERATE_FF("sqrtt/suid", Rb(instruction), Rc(instruction)); break; // SQRTT/SUID + + default: UNKNOWN("itfp*"); break; + } + break; + case 0x15: // FLTV* (vax floating) + switch ((instruction >> 5) & 0x7ff) + { + case 0x000: OPERATE_FFF("addf/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/C + case 0x001: OPERATE_FFF("subf/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/C + case 0x002: OPERATE_FFF("mulf/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/C + case 0x003: OPERATE_FFF("divf/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/C + case 0x01e: OPERATE_FF("cvtdg/c", Rb(instruction), Rc(instruction)); break; // CVTDG/C + case 0x020: OPERATE_FFF("addg/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/C + case 0x021: OPERATE_FFF("subg/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/C + case 0x022: OPERATE_FFF("mulg/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/C + case 0x023: OPERATE_FFF("divg/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/C + case 0x02c: OPERATE_FF("cvtgf/c", Rb(instruction), Rc(instruction)); break; // CVTGF/C + case 0x02d: OPERATE_FF("cvtgd/c", Rb(instruction), Rc(instruction)); break; // CVTGD/C + case 0x02f: OPERATE_FF("cvtgq/c", Rb(instruction), Rc(instruction)); break; // CVTGQ/C + case 0x03c: OPERATE_FF("cvtqf/c", Rb(instruction), Rc(instruction)); break; // CVTQF/C + case 0x03e: OPERATE_FF("cvtqg/c", Rb(instruction), Rc(instruction)); break; // CVTQG/C + case 0x080: OPERATE_FFF("addf", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF + case 0x081: OPERATE_FFF("subf", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF + case 0x082: OPERATE_FFF("mulf", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF + case 0x083: OPERATE_FFF("divf", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF + case 0x09e: OPERATE_FF("cvtdg", Rb(instruction), Rc(instruction)); break; // CVTDG + case 0x0a0: OPERATE_FFF("addg", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG + case 0x0a1: OPERATE_FFF("subg", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG + case 0x0a2: OPERATE_FFF("mulg", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG + case 0x0a3: OPERATE_FFF("divg", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG + case 0x0a5: OPERATE_FFF("cmpgeq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGEQ + case 0x0a6: OPERATE_FFF("cmpglt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGLT + case 0x0a7: OPERATE_FFF("cmpgle", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGLE + case 0x0ac: OPERATE_FF("cvtgf", Rb(instruction), Rc(instruction)); break; // CVTGF + case 0x0ad: OPERATE_FF("cvtgd", Rb(instruction), Rc(instruction)); break; // CVTGD + case 0x0af: OPERATE_FF("cvtgq", Rb(instruction), Rc(instruction)); break; // CVTGQ + case 0x0bc: OPERATE_FF("cvtqf", Rb(instruction), Rc(instruction)); break; // CVTQF + case 0x0be: OPERATE_FF("cvtqg", Rb(instruction), Rc(instruction)); break; // CVTQG + case 0x100: OPERATE_FFF("addf/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/UC + case 0x101: OPERATE_FFF("subf/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/UC + case 0x102: OPERATE_FFF("mulf/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/UC + case 0x103: OPERATE_FFF("divf/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/UC + case 0x11e: OPERATE_FF("cvtdg/uc", Rb(instruction), Rc(instruction)); break; // CVTDG/UC + case 0x120: OPERATE_FFF("addg/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/UC + case 0x121: OPERATE_FFF("subg/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/UC + case 0x122: OPERATE_FFF("mulg/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/UC + case 0x123: OPERATE_FFF("divg/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/UC + case 0x12c: OPERATE_FF("cvtgf/uc", Rb(instruction), Rc(instruction)); break; // CVTGF/UC + case 0x12d: OPERATE_FF("cvtgd/uc", Rb(instruction), Rc(instruction)); break; // CVTGD/UC + case 0x12f: OPERATE_FF("cvtgq/vc", Rb(instruction), Rc(instruction)); break; // CVTGQ/VC + case 0x180: OPERATE_FFF("addf/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/U + case 0x181: OPERATE_FFF("subf/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/U + case 0x182: OPERATE_FFF("mulf/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/U + case 0x183: OPERATE_FFF("divf/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/U + case 0x19e: OPERATE_FF("cvtdg/u", Rb(instruction), Rc(instruction)); break; // CVTDG/U + case 0x1a0: OPERATE_FFF("addg/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/U + case 0x1a1: OPERATE_FFF("subg/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/U + case 0x1a2: OPERATE_FFF("mulg/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/U + case 0x1a3: OPERATE_FFF("divg/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/U + case 0x1ac: OPERATE_FF("cvtgf/u", Rb(instruction), Rc(instruction)); break; // CVTGF/U + case 0x1ad: OPERATE_FF("cvtgd/u", Rb(instruction), Rc(instruction)); break; // CVTGD/U + case 0x1af: OPERATE_FF("cvtgq/v", Rb(instruction), Rc(instruction)); break; // CVTGQ/V + case 0x400: OPERATE_FFF("addf/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/SC + case 0x401: OPERATE_FFF("subf/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/SC + case 0x402: OPERATE_FFF("mulf/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/SC + case 0x403: OPERATE_FFF("divf/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/SC + case 0x41e: OPERATE_FF("cvtdg/sc", Rb(instruction), Rc(instruction)); break; // CVTDG/SC + case 0x420: OPERATE_FFF("addg/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/SC + case 0x421: OPERATE_FFF("subg/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/SC + case 0x422: OPERATE_FFF("mulg/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/SC + case 0x423: OPERATE_FFF("divg/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/SC + case 0x42c: OPERATE_FF("cvtgf/sc", Rb(instruction), Rc(instruction)); break; // CVTGF/SC + case 0x42d: OPERATE_FF("cvtgd/sc", Rb(instruction), Rc(instruction)); break; // CVTGD/SC + case 0x42f: OPERATE_FF("cvtgq/sc", Rb(instruction), Rc(instruction)); break; // CVTGQ/SC + case 0x480: OPERATE_FFF("addf/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/S + case 0x481: OPERATE_FFF("subf/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/S + case 0x482: OPERATE_FFF("mulf/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/S + case 0x483: OPERATE_FFF("divf/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/S + case 0x49e: OPERATE_FF("cvtdg/s", Rb(instruction), Rc(instruction)); break; // CVTDG/S + case 0x4a0: OPERATE_FFF("addg/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/S + case 0x4a1: OPERATE_FFF("subg/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/S + case 0x4a2: OPERATE_FFF("mulg/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/S + case 0x4a3: OPERATE_FFF("divg/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/S + case 0x4a5: OPERATE_FFF("cmpgeq/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGEQ/S + case 0x4a6: OPERATE_FFF("cmpglt/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGLT/S + case 0x4a7: OPERATE_FFF("cmpgle/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGLE/S + case 0x4ac: OPERATE_FF("cvtgf/s", Rb(instruction), Rc(instruction)); break; // CVTGF/S + case 0x4ad: OPERATE_FF("cvtgd/s", Rb(instruction), Rc(instruction)); break; // CVTGD/S + case 0x4af: OPERATE_FF("cvtgq/s", Rb(instruction), Rc(instruction)); break; // CVTGQ/S + case 0x500: OPERATE_FFF("addf/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/SUC + case 0x501: OPERATE_FFF("subf/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/SUC + case 0x502: OPERATE_FFF("mulf/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/SUC + case 0x503: OPERATE_FFF("divf/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/SUC + case 0x51e: OPERATE_FF("cvtdg/suc", Rb(instruction), Rc(instruction)); break; // CVTDG/SUC + case 0x520: OPERATE_FFF("addg/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/SUC + case 0x521: OPERATE_FFF("subg/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/SUC + case 0x522: OPERATE_FFF("mulg/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/SUC + case 0x523: OPERATE_FFF("divg/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/SUC + case 0x52c: OPERATE_FF("cvtgf/suc", Rb(instruction), Rc(instruction)); break; // CVTGF/SUC + case 0x52d: OPERATE_FF("cvtgd/suc", Rb(instruction), Rc(instruction)); break; // CVTGD/SUC + case 0x52f: OPERATE_FF("cvtgq/svc", Rb(instruction), Rc(instruction)); break; // CVTGQ/SVC + case 0x580: OPERATE_FFF("addf/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/SU + case 0x581: OPERATE_FFF("subf/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/SU + case 0x582: OPERATE_FFF("mulf/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/SU + case 0x583: OPERATE_FFF("divf/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/SU + case 0x59e: OPERATE_FF("cvtdg/su", Rb(instruction), Rc(instruction)); break; // CVTDG/SU + case 0x5a0: OPERATE_FFF("addg/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/SU + case 0x5a1: OPERATE_FFF("subg/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/SU + case 0x5a2: OPERATE_FFF("mulg/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/SU + case 0x5a3: OPERATE_FFF("divg/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/SU + case 0x5ac: OPERATE_FF("cvtgf/su", Rb(instruction), Rc(instruction)); break; // CVTGF/SU + case 0x5ad: OPERATE_FF("cvtgd/su", Rb(instruction), Rc(instruction)); break; // CVTGD/SU + case 0x5af: OPERATE_FF("cvtgq/sv", Rb(instruction), Rc(instruction)); break; // CVTGQ/SV + + default: UNKNOWN("fltv*"); break; + } + break; + case 0x16: // FLTI* (ieee floating) + switch ((instruction >> 5) & 0x7ff) + { + case 0x000: OPERATE_FFF("adds/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/C + case 0x001: OPERATE_FFF("subs/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/C + case 0x002: OPERATE_FFF("muls/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/C + case 0x003: OPERATE_FFF("divs/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/C + case 0x020: OPERATE_FFF("addt/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/C + case 0x021: OPERATE_FFF("subt/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/C + case 0x022: OPERATE_FFF("mult/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/C + case 0x023: OPERATE_FFF("divt/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/C + case 0x02c: OPERATE_FF("cvttts/c", Rb(instruction), Rc(instruction)); break; // CVTTS/C + case 0x02f: OPERATE_FF("cvttq/c", Rb(instruction), Rc(instruction)); break; // CVTTQ/C + case 0x03c: OPERATE_FF("cvtqs/c", Rb(instruction), Rc(instruction)); break; // CVTQS/C + case 0x03e: OPERATE_FF("cvtqt/c", Rb(instruction), Rc(instruction)); break; // CVTQT/C + case 0x040: OPERATE_FFF("adds/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/M + case 0x041: OPERATE_FFF("subs/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/M + case 0x042: OPERATE_FFF("muls/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/M + case 0x043: OPERATE_FFF("divs/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/M + case 0x060: OPERATE_FFF("addt/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/M + case 0x061: OPERATE_FFF("subt/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/M + case 0x062: OPERATE_FFF("mult/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/M + case 0x063: OPERATE_FFF("divt/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/M + case 0x06c: OPERATE_FF("cvttts/m", Rb(instruction), Rc(instruction)); break; // CVTTS/M + case 0x06f: OPERATE_FF("cvttq/m", Rb(instruction), Rc(instruction)); break; // CVTTQ/M + case 0x07c: OPERATE_FF("cvtqs/m", Rb(instruction), Rc(instruction)); break; // CVTQS/M + case 0x07e: OPERATE_FF("cvtqt/m", Rb(instruction), Rc(instruction)); break; // CVTQT/M + case 0x080: OPERATE_FFF("adds", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS + case 0x081: OPERATE_FFF("subs", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS + case 0x082: OPERATE_FFF("muls", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS + case 0x083: OPERATE_FFF("divs", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS + case 0x0a0: OPERATE_FFF("addt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT + case 0x0a1: OPERATE_FFF("subt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT + case 0x0a2: OPERATE_FFF("mult", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT + case 0x0a3: OPERATE_FFF("divt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT + case 0x0a4: OPERATE_FFF("cmptun", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTUN + case 0x0a5: OPERATE_FFF("cmpteq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTEQ + case 0x0a6: OPERATE_FFF("cmptlt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTLT + case 0x0a7: OPERATE_FFF("cmptle", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTLE + case 0x0ac: OPERATE_FF("cvttts", Rb(instruction), Rc(instruction)); break; // CVTTS + case 0x0af: OPERATE_FF("cvttq", Rb(instruction), Rc(instruction)); break; // CVTTQ + case 0x0bc: OPERATE_FF("cvtqs", Rb(instruction), Rc(instruction)); break; // CVTQS + case 0x0be: OPERATE_FF("cvtqt", Rb(instruction), Rc(instruction)); break; // CVTQT + case 0x0c0: OPERATE_FFF("adds/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/D + case 0x0c1: OPERATE_FFF("subs/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/D + case 0x0c2: OPERATE_FFF("muls/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/D + case 0x0c3: OPERATE_FFF("divs/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/D + case 0x0e0: OPERATE_FFF("addt/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/D + case 0x0e1: OPERATE_FFF("subt/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/D + case 0x0e2: OPERATE_FFF("mult/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/D + case 0x0e3: OPERATE_FFF("divt/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/D + case 0x0ec: OPERATE_FF("cvttts/d", Rb(instruction), Rc(instruction)); break; // CVTTS/D + case 0x0ef: OPERATE_FF("cvttq/d", Rb(instruction), Rc(instruction)); break; // CVTTQ/D + case 0x0fc: OPERATE_FF("cvtqs/d", Rb(instruction), Rc(instruction)); break; // CVTQS/D + case 0x0fe: OPERATE_FF("cvtqt/d", Rb(instruction), Rc(instruction)); break; // CVTQT/D + case 0x100: OPERATE_FFF("adds/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/UC + case 0x101: OPERATE_FFF("subs/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/UC + case 0x102: OPERATE_FFF("muls/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/UC + case 0x103: OPERATE_FFF("divs/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/UC + case 0x120: OPERATE_FFF("addt/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/UC + case 0x121: OPERATE_FFF("subt/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/UC + case 0x122: OPERATE_FFF("mult/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/UC + case 0x123: OPERATE_FFF("divt/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/UC + case 0x12c: OPERATE_FF("cvttts/uc", Rb(instruction), Rc(instruction)); break; // CVTTS/UC + case 0x12f: OPERATE_FF("cvttq/vc", Rb(instruction), Rc(instruction)); break; // CVTTQ/VC + case 0x140: OPERATE_FFF("adds/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/UM + case 0x141: OPERATE_FFF("subs/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/UM + case 0x142: OPERATE_FFF("muls/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/UM + case 0x143: OPERATE_FFF("divs/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/UM + case 0x160: OPERATE_FFF("addt/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/UM + case 0x161: OPERATE_FFF("subt/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/UM + case 0x162: OPERATE_FFF("mult/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/UM + case 0x163: OPERATE_FFF("divt/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/UM + case 0x16c: OPERATE_FF("cvttts/um", Rb(instruction), Rc(instruction)); break; // CVTTS/UM + case 0x16f: OPERATE_FF("cvttq/vm", Rb(instruction), Rc(instruction)); break; // CVTTQ/VM + case 0x180: OPERATE_FFF("adds/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/U + case 0x181: OPERATE_FFF("subs/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/U + case 0x182: OPERATE_FFF("muls/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/U + case 0x183: OPERATE_FFF("divs/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/U + case 0x1a0: OPERATE_FFF("addt/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/U + case 0x1a1: OPERATE_FFF("subt/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/U + case 0x1a2: OPERATE_FFF("mult/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/U + case 0x1a3: OPERATE_FFF("divt/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/U + case 0x1ac: OPERATE_FF("cvttts/u", Rb(instruction), Rc(instruction)); break; // CVTTS/U + case 0x1af: OPERATE_FF("cvttq/v", Rb(instruction), Rc(instruction)); break; // CVTTQ/V + case 0x1c0: OPERATE_FFF("adds/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/UD + case 0x1c1: OPERATE_FFF("subs/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/UD + case 0x1c2: OPERATE_FFF("muls/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/UD + case 0x1c3: OPERATE_FFF("divs/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/UD + case 0x1e0: OPERATE_FFF("addt/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/UD + case 0x1e1: OPERATE_FFF("subs/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/UD + case 0x1e2: OPERATE_FFF("mult/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/UD + case 0x1e3: OPERATE_FFF("divt/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/UD + case 0x1ec: OPERATE_FF("cvttts/ud", Rb(instruction), Rc(instruction)); break; // CVTTS/UD + case 0x1ef: OPERATE_FF("cvttq/vd", Rb(instruction), Rc(instruction)); break; // CVTTQ/VD + case 0x2ac: OPERATE_FF("cvtst", Rb(instruction), Rc(instruction)); break; // CVTST + case 0x500: OPERATE_FFF("adds/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUC + case 0x501: OPERATE_FFF("subs/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUC + case 0x502: OPERATE_FFF("muls/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUC + case 0x503: OPERATE_FFF("divs/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUC + case 0x520: OPERATE_FFF("addt/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUC + case 0x521: OPERATE_FFF("subt/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUC + case 0x522: OPERATE_FFF("mult/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUC + case 0x523: OPERATE_FFF("divt/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUC + case 0x52c: OPERATE_FF("cvttts/suc", Rb(instruction), Rc(instruction)); break; // CVTTS/SUC + case 0x52f: OPERATE_FF("cvttq/svc", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVC + case 0x540: OPERATE_FFF("adds/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUM + case 0x541: OPERATE_FFF("subs/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUM + case 0x542: OPERATE_FFF("muls/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUM + case 0x543: OPERATE_FFF("divs/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUM + case 0x560: OPERATE_FFF("addt/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUM + case 0x561: OPERATE_FFF("subt/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUM + case 0x562: OPERATE_FFF("mult/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUM + case 0x563: OPERATE_FFF("divt/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUM + case 0x56c: OPERATE_FF("cvttts/sum", Rb(instruction), Rc(instruction)); break; // CVTTS/SUM + case 0x56f: OPERATE_FF("cvttq/svm", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVM + case 0x580: OPERATE_FFF("adds/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SU + case 0x581: OPERATE_FFF("subs/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SU + case 0x582: OPERATE_FFF("muls/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SU + case 0x583: OPERATE_FFF("divs/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SU + case 0x5a0: OPERATE_FFF("addt/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SU + case 0x5a1: OPERATE_FFF("subt/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SU + case 0x5a2: OPERATE_FFF("mult/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SU + case 0x5a3: OPERATE_FFF("divt/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SU + case 0x5a4: OPERATE_FFF("cmptun/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTUN/SU + case 0x5a5: OPERATE_FFF("cmpteq/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTEQ/SU + case 0x5a6: OPERATE_FFF("cmptlt/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTLT/SU + case 0x5a7: OPERATE_FFF("cmptle/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTLE/SU + case 0x5ac: OPERATE_FF("cvttts/su", Rb(instruction), Rc(instruction)); break; // CVTTS/SU + case 0x5af: OPERATE_FF("cvttq/sv", Rb(instruction), Rc(instruction)); break; // CVTTQ/SV + case 0x5c0: OPERATE_FFF("adds/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUD + case 0x5c1: OPERATE_FFF("subs/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUD + case 0x5c2: OPERATE_FFF("muls/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUD + case 0x5c3: OPERATE_FFF("divs/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUD + case 0x5e0: OPERATE_FFF("addt/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUD + case 0x5e1: OPERATE_FFF("subt/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUD + case 0x5e2: OPERATE_FFF("mult/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUD + case 0x5e3: OPERATE_FFF("divt/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUD + case 0x5ec: OPERATE_FF("cvttts/sud", Rb(instruction), Rc(instruction)); break; // CVTTS/SUD + case 0x5ef: OPERATE_FF("cvttq/svd", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVD + case 0x6ac: OPERATE_FF("cvtst/s", Rb(instruction), Rc(instruction)); break; // CVTST/S + case 0x700: OPERATE_FFF("adds/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUIC + case 0x701: OPERATE_FFF("subs/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUIC + case 0x702: OPERATE_FFF("muls/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUIC + case 0x703: OPERATE_FFF("divs/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUIC + case 0x720: OPERATE_FFF("addt/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUIC + case 0x721: OPERATE_FFF("subt/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUIC + case 0x722: OPERATE_FFF("mult/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUIC + case 0x723: OPERATE_FFF("divt/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUIC + case 0x72c: OPERATE_FF("cvttts/suic", Rb(instruction), Rc(instruction)); break; // CVTTS/SUIC + case 0x72f: OPERATE_FF("cvttq/svic", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVIC + case 0x73c: OPERATE_FF("cvtqs/suic", Rb(instruction), Rc(instruction)); break; // CVTQS/SUIC + case 0x73e: OPERATE_FF("cvtqt/suic", Rb(instruction), Rc(instruction)); break; // CVTQT/SUIC + case 0x740: OPERATE_FFF("adds/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUIM + case 0x741: OPERATE_FFF("subs/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUIM + case 0x742: OPERATE_FFF("muls/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUIM + case 0x743: OPERATE_FFF("divs/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUIM + case 0x760: OPERATE_FFF("addt/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUIM + case 0x761: OPERATE_FFF("subt/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUIM + case 0x762: OPERATE_FFF("mult/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUIM + case 0x763: OPERATE_FFF("divt/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUIM + case 0x76c: OPERATE_FF("cvttts/suim", Rb(instruction), Rc(instruction)); break; // CVTTS/SUIM + case 0x76f: OPERATE_FF("cvttq/svim", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVIM + case 0x77c: OPERATE_FF("cvtqs/suim", Rb(instruction), Rc(instruction)); break; // CVTQS/SUIM + case 0x77e: OPERATE_FF("cvtqt/suim", Rb(instruction), Rc(instruction)); break; // CVTQT/SUIM + case 0x780: OPERATE_FFF("adds/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUI + case 0x781: OPERATE_FFF("subs/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUI + case 0x782: OPERATE_FFF("muls/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUI + case 0x783: OPERATE_FFF("divs/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUI + case 0x7a0: OPERATE_FFF("addt/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUI + case 0x7a1: OPERATE_FFF("subt/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUI + case 0x7a2: OPERATE_FFF("mult/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUI + case 0x7a3: OPERATE_FFF("divt/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUI + case 0x7ac: OPERATE_FF("cvttts/sui", Rb(instruction), Rc(instruction)); break; // CVTTS/SUI + case 0x7af: OPERATE_FF("cvttq/svi", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVI + case 0x7bc: OPERATE_FF("cvtqs/sui", Rb(instruction), Rc(instruction)); break; // CVTQS/SUI + case 0x7be: OPERATE_FF("cvtqt/sui", Rb(instruction), Rc(instruction)); break; // CVTQT/SUI + case 0x7c0: OPERATE_FFF("adds/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUID + case 0x7c1: OPERATE_FFF("subs/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUID + case 0x7c2: OPERATE_FFF("muls/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUID + case 0x7c3: OPERATE_FFF("divs/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUID + case 0x7e0: OPERATE_FFF("addt/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUID + case 0x7e1: OPERATE_FFF("subt/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUID + case 0x7e2: OPERATE_FFF("mult/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUID + case 0x7e3: OPERATE_FFF("divt/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUID + case 0x7ec: OPERATE_FF("cvttts/suid", Rb(instruction), Rc(instruction)); break; // CVTTS/SUID + case 0x7ef: OPERATE_FF("cvttq/svid", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVID + case 0x7fc: OPERATE_FF("cvtqs/suid", Rb(instruction), Rc(instruction)); break; // CVTQS/SUID + case 0x7fe: OPERATE_FF("cvtqt/suid", Rb(instruction), Rc(instruction)); break; // CVTQT/SUID + + default: UNKNOWN("flti*"); break; + } + break; + case 0x17: // FLTL* (floating) + switch ((instruction >> 5) & 0x7ff) + { + case 0x010: OPERATE_FF("cvtlq", Rb(instruction), Rc(instruction)); break; // CVTLQ + case 0x020: OPERATE_FFF("cpys", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CPYS + case 0x021: OPERATE_FFF("cpysn", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CPYSN + case 0x022: OPERATE_FFF("cpyse", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CPYSE + case 0x024: OPERATE_FFF("mt_fpcr", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MT_FPCR + case 0x025: OPERATE_FFF("mf_fpcr", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MF_FPCR + case 0x02a: OPERATE_FFF("fcmoveq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVEQ + case 0x02b: OPERATE_FFF("fcmovne", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVNE + case 0x02c: OPERATE_FFF("fcmovlt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVLT + case 0x02d: OPERATE_FFF("fcmovge", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVGE + case 0x02e: OPERATE_FFF("fcmovle", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVLE + case 0x02f: OPERATE_FFF("fcmovgt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVGT + case 0x030: OPERATE_FF("cvtql", Rb(instruction), Rc(instruction)); break; // CVTQL + case 0x130: OPERATE_FF("cvtql/v", Rb(instruction), Rc(instruction)); break; // CVTQL/V + case 0x530: OPERATE_FF("cvtql/sv", Rb(instruction), Rc(instruction)); break; // CVTQL/SV + + default: UNKNOWN("fltl*"); break; + } + break; + case 0x18: // MISC* (miscellaneous) + switch (u16(instruction)) + { + case 0x0000: MISC_0("trapb"); break; // TRAPB + case 0x0400: MISC_0("excb"); break; // EXCB + case 0x4000: MISC_0("mb"); break; // MB + case 0x4400: MISC_0("wmb"); break; // WMB + case 0x8000: MISC_M("fetch", Rb(instruction)); break; // FETCH + case 0xa000: MISC_M("fetch_m", Rb(instruction)); break; // FETCH_M + case 0xc000: MISC_R("rpcc", Ra(instruction)); break; // RPCC + case 0xe000: MISC_R("rc", Ra(instruction)); break; // RC + case 0xe800: MISC_M("ecb", Rb(instruction)); break; // ECB + case 0xf000: MISC_R("rs", Ra(instruction)); break; // RS + case 0xf800: MISC_M("wh64", Rb(instruction)); break; // WH64 + + default: UNKNOWN("misc*"); break; + } + break; + case 0x19: PAL_0("pal19"); break; // PAL19 + case 0x1a: // JSR* (jump) + switch ((instruction >> 14) & 3) + { + case 0: JUMP("jmp", Ra(instruction), Rb(instruction)); break; // JMP + case 1: JUMP("jsr", Ra(instruction), Rb(instruction)); flags |= STEP_OVER; break; // JSR + case 2: JUMP("ret", Ra(instruction), Rb(instruction)); flags |= STEP_OUT; break; // RET + case 3: JUMP("jsr_c", Ra(instruction), Rb(instruction)); break; // JSR_COROUTINE + } + break; + case 0x1b: PAL_0("pal1b"); break; // PAL1B + case 0x1c: // FPTI* (floating to integer) + switch ((instruction >> 5) & 0xff) + { + // register variants + case 0x00: OPERATE_RR("sextb", Rb(instruction), Rc(instruction)); break; // SEXTB (BWX) + case 0x01: OPERATE_RR("sextw", Rb(instruction), Rc(instruction)); break; // SEXTW (BWX) + case 0x30: OPERATE_RR("ctpop", Rb(instruction), Rc(instruction)); break; // CTPOP (CIX) + case 0x31: OPERATE_RRR("perr", Ra(instruction), Rb(instruction), Rc(instruction)); break; // PERR (MVI) + case 0x32: OPERATE_RR("ctlz", Rb(instruction), Rc(instruction)); break; // CTLZ (CIX) + case 0x33: OPERATE_RR("cttz", Rb(instruction), Rc(instruction)); break; // CTTZ (CIX) + case 0x34: OPERATE_RR("unpkbw", Rb(instruction), Rc(instruction)); break; // UNPKBW (MVI) + case 0x35: OPERATE_RR("unpkbl", Rb(instruction), Rc(instruction)); break; // UNPKBL (MVI) + case 0x36: OPERATE_RR("pkwb", Rb(instruction), Rc(instruction)); break; // PKWB (MVI) + case 0x37: OPERATE_RR("pklb", Rb(instruction), Rc(instruction)); break; // PKLB (MVI) + case 0x38: OPERATE_RRR("minsb8", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MINSB8 (MVI) + case 0x39: OPERATE_RRR("minsw4", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MINSW4 (MVI) + case 0x3a: OPERATE_RRR("minub8", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MINUB8 (MVI) + case 0x3b: OPERATE_RRR("minuw4", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MINUW4 (MVI) + case 0x3c: OPERATE_RRR("maxub8", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MAXUB8 (MVI) + case 0x3d: OPERATE_RRR("maxuw4", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MAXUW4 (MVI) + case 0x3e: OPERATE_RRR("maxsb8", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MAXSB8 (MVI) + case 0x3f: OPERATE_RRR("maxsw4", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MAXSW4 (MVI) + case 0x70: OPERATE_FR("ftoit", Ra(instruction), Rc(instruction)); break; // FTOIT (FIX) + case 0x78: OPERATE_FR("ftois", Ra(instruction), Rc(instruction)); break; // FTOIS (FIX) + + // immediate variants + case 0x80: OPERATE_IR("sextb", Im(instruction), Rc(instruction)); break; // SEXTB (BWX) + case 0x81: OPERATE_IR("sextw", Im(instruction), Rc(instruction)); break; // SEXTW (BWX) + case 0xb8: OPERATE_RIR("minsb8", Ra(instruction), Im(instruction), Rc(instruction)); break; // MINSB8 (MVI) + case 0xb9: OPERATE_RIR("minsw4", Ra(instruction), Im(instruction), Rc(instruction)); break; // MINSW4 (MVI) + case 0xba: OPERATE_RIR("minub8", Ra(instruction), Im(instruction), Rc(instruction)); break; // MINUB8 (MVI) + case 0xbb: OPERATE_RIR("minuw4", Ra(instruction), Im(instruction), Rc(instruction)); break; // MINUW4 (MVI) + case 0xbc: OPERATE_RIR("maxub8", Ra(instruction), Im(instruction), Rc(instruction)); break; // MAXUB8 (MVI) + case 0xbd: OPERATE_RIR("maxuw4", Ra(instruction), Im(instruction), Rc(instruction)); break; // MAXUW4 (MVI) + case 0xbe: OPERATE_RIR("maxsb8", Ra(instruction), Im(instruction), Rc(instruction)); break; // MAXSB8 (MVI) + case 0xbf: OPERATE_RIR("maxsw4", Ra(instruction), Im(instruction), Rc(instruction)); break; // MAXSW4 (MVI) + + default: UNKNOWN("fpti*"); break; + } + break; + case 0x1d: PAL_0("pal1d"); break; // PAL1D + case 0x1e: PAL_0("pal1e"); break; // PAL1E + case 0x1f: PAL_0("pal1f"); break; // PAL1F + + // memory format + case 0x20: MEMORY_F("ldf", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDF + case 0x21: MEMORY_F("ldg", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDG + case 0x22: MEMORY_F("lds", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDS + case 0x23: MEMORY_F("ldt", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDT + case 0x24: MEMORY_F("stf", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STF + case 0x25: MEMORY_F("stg", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STG + case 0x26: MEMORY_F("sts", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STS + case 0x27: MEMORY_F("stt", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STT + case 0x28: MEMORY_R("ldl", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDL + case 0x29: MEMORY_R("ldq", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDQ + case 0x2a: MEMORY_R("ldl_l", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDL_L + case 0x2b: MEMORY_R("ldq_l", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDQ_L + case 0x2c: MEMORY_R("stl", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STL + case 0x2d: MEMORY_R("stq", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STQ + case 0x2e: MEMORY_R("stl_c", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STL_C + case 0x2f: MEMORY_R("stq_c", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STQ_C + + // branch format + case 0x30: BRANCH_R("br", Ra(instruction), Disp_B(instruction)); break; // BR + case 0x31: BRANCH_F("fbeq", Ra(instruction), Disp_B(instruction)); break; // FBEQ + case 0x32: BRANCH_F("fblt", Ra(instruction), Disp_B(instruction)); break; // FBLT + case 0x33: BRANCH_F("fble", Ra(instruction), Disp_B(instruction)); break; // FBLE + case 0x34: BRANCH_R("bsr", Ra(instruction), Disp_B(instruction)); break; // BSR + case 0x35: BRANCH_F("fbne", Ra(instruction), Disp_B(instruction)); break; // FBNE + case 0x36: BRANCH_F("fbge", Ra(instruction), Disp_B(instruction)); break; // FBGE + case 0x37: BRANCH_F("fbgt", Ra(instruction), Disp_B(instruction)); break; // FBGT + case 0x38: BRANCH_R("blbc", Ra(instruction), Disp_B(instruction)); break; // BLBC + case 0x39: BRANCH_R("beq", Ra(instruction), Disp_B(instruction)); break; // BEQ + case 0x3a: BRANCH_R("blt", Ra(instruction), Disp_B(instruction)); break; // BLT + case 0x3b: BRANCH_R("ble", Ra(instruction), Disp_B(instruction)); break; // BLE + case 0x3c: BRANCH_R("blbs", Ra(instruction), Disp_B(instruction)); break; // BLBS + case 0x3d: BRANCH_R("bne", Ra(instruction), Disp_B(instruction)); break; // BNE + case 0x3e: BRANCH_R("bge", Ra(instruction), Disp_B(instruction)); break; // BGE + case 0x3f: BRANCH_R("bgt", Ra(instruction), Disp_B(instruction)); break; // BGT + } + + return bytes | flags; +} diff --git a/src/devices/cpu/alpha/alphad.h b/src/devices/cpu/alpha/alphad.h new file mode 100644 index 00000000000..09fa4b8a63a --- /dev/null +++ b/src/devices/cpu/alpha/alphad.h @@ -0,0 +1,23 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +#ifndef MAME_CPU_ALPHA_ALPHAD_H +#define MAME_CPU_ALPHA_ALPHAD_H + +#pragma once + +class alpha_disassembler : public util::disasm_interface +{ +public: + alpha_disassembler() = default; + virtual ~alpha_disassembler() = default; + + virtual u32 opcode_alignment() const override { return 4; }; + virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; + +private: + static char const *const R[]; + static char const *const F[]; +}; + +#endif // MAME_CPU_ALPHA_ALPHAD_H diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index 328527c85ce..4faea8300e7 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -17,6 +17,7 @@ using util::BIT; #include "cpu/8x300/8x300dasm.h" #include "cpu/adsp2100/2100dasm.h" #include "cpu/alph8201/8201dasm.h" +#include "cpu/alpha/alphad.h" #include "cpu/alto2/alto2dsm.h" #include "cpu/am29000/am29dasm.h" #include "cpu/amis2000/amis2000d.h" @@ -301,6 +302,7 @@ static const dasm_table_entry dasm_table[] = { { "8x300", be, 0, []() -> util::disasm_interface * { return new n8x300_disassembler; } }, { "adsp21xx", le, -2, []() -> util::disasm_interface * { return new adsp21xx_disassembler; } }, + { "alpha", le, 0, []() -> util::disasm_interface * { return new alpha_disassembler; } }, { "alpha8201", le, 0, []() -> util::disasm_interface * { return new alpha8201_disassembler; } }, { "alto2", be, -2, []() -> util::disasm_interface * { return new alto2_disassembler; } }, { "am29000", be, 0, []() -> util::disasm_interface * { return new am29000_disassembler; } }, -- cgit v1.2.3-70-g09d2 From 2035fedd6e7d620cc23370049ec9ac588b243a6a Mon Sep 17 00:00:00 2001 From: AJR Date: Thu, 24 Jan 2019 07:56:16 -0500 Subject: 8x300: Apply address shift to program space --- src/devices/cpu/8x300/8x300.cpp | 14 +++++++------- src/devices/cpu/8x300/8x300.h | 2 +- src/devices/cpu/8x300/8x300dasm.cpp | 6 +++--- src/mame/drivers/fs3216.cpp | 2 +- src/mame/drivers/wicat.cpp | 4 ++-- src/tools/unidasm.cpp | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/tools/unidasm.cpp') diff --git a/src/devices/cpu/8x300/8x300.cpp b/src/devices/cpu/8x300/8x300.cpp index bf08f3a3cdb..a8a9b9dcdad 100644 --- a/src/devices/cpu/8x300/8x300.cpp +++ b/src/devices/cpu/8x300/8x300.cpp @@ -44,7 +44,7 @@ DEFINE_DEVICE_TYPE(N8X305, n8x305_cpu_device, "8x305", "Signetics 8X305") n8x300_cpu_device::n8x300_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : cpu_device(mconfig, type, tag, owner, clock) - , m_program_config("program", ENDIANNESS_BIG, 16, 14, 0) + , m_program_config("program", ENDIANNESS_BIG, 16, 13, -1) , m_io_config("io", ENDIANNESS_BIG, 8, 9, 0) , m_sc_callback(*this) { @@ -154,7 +154,7 @@ void n8x300_cpu_device::device_resolve_objects() void n8x300_cpu_device::device_start() { m_program = &space(AS_PROGRAM); - m_cache = m_program->cache<1, 0, ENDIANNESS_BIG>(); + m_cache = m_program->cache<1, -1, ENDIANNESS_BIG>(); m_io = &space(AS_IO); save_item(NAME(m_PC)); @@ -229,8 +229,8 @@ void n8x300_cpu_device::device_start() state_add( _8X300_OVF, "OVF", m_OVF).mask(0x01).formatstr("%01X"); state_add( _8X300_IVL, "IVL", m_IVL).mask(0xff).formatstr("%02X"); state_add( _8X300_IVR, "IVR", m_IVR).mask(0xff).formatstr("%02X"); - state_add(STATE_GENPC, "GENPC", m_genPC).mask(0x3ffe).callimport().noshow(); - state_add(STATE_GENPCBASE, "CURPC", m_genPC).mask(0x3ffe).callimport().noshow(); + state_add(STATE_GENPC, "GENPC", m_genPC).mask(0x1fff).callimport().noshow(); + state_add(STATE_GENPCBASE, "CURPC", m_genPC).mask(0x1fff).callimport().noshow(); set_icountptr(m_icount); } @@ -246,12 +246,12 @@ void n8x300_cpu_device::state_import(const device_state_entry &entry) { case _8X300_PC: m_AR = m_PC; - m_genPC = m_AR << 1; + m_genPC = m_AR; m_increment_pc = true; break; case _8X300_AR: - m_genPC = m_AR << 1; + m_genPC = m_AR; m_increment_pc = false; break; @@ -284,7 +284,7 @@ void n8x300_cpu_device::execute_run() uint8_t mask; /* fetch the opcode */ - m_genPC = m_AR << 1; + m_genPC = m_AR; debugger_instruction_hook(m_genPC); opcode = FETCHOP(m_genPC); diff --git a/src/devices/cpu/8x300/8x300.h b/src/devices/cpu/8x300/8x300.h index f85ead659bf..155079d225a 100644 --- a/src/devices/cpu/8x300/8x300.h +++ b/src/devices/cpu/8x300/8x300.h @@ -83,7 +83,7 @@ protected: bool m_increment_pc; address_space *m_program; - memory_access_cache<1, 0, ENDIANNESS_BIG> *m_cache; + memory_access_cache<1, -1, ENDIANNESS_BIG> *m_cache; address_space *m_io; devcb_write8 m_sc_callback; // Select Command (address latch) diff --git a/src/devices/cpu/8x300/8x300dasm.cpp b/src/devices/cpu/8x300/8x300dasm.cpp index db231195f04..762fec8f382 100644 --- a/src/devices/cpu/8x300/8x300dasm.cpp +++ b/src/devices/cpu/8x300/8x300dasm.cpp @@ -43,7 +43,7 @@ bool n8x300_disassembler::is_src_rot(uint16_t opcode) u32 n8x300_disassembler::opcode_alignment() const { - return 2; + return 1; } offs_t n8x300_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) @@ -51,7 +51,7 @@ offs_t n8x300_disassembler::disassemble(std::ostream &stream, offs_t pc, const d unsigned startpc = pc; uint16_t opcode = opcodes.r16(pc); uint8_t inst = opcode >> 13; - pc+=2; + pc+=1; // determine instruction switch (inst) @@ -127,7 +127,7 @@ offs_t n8x300_disassembler::disassemble(std::ostream &stream, offs_t pc, const d } break; case 0x07: - util::stream_format(stream, "JMP %04XH", (opcode & 0x1fff) << 1); + util::stream_format(stream, "JMP %04XH", (opcode & 0x1fff)); break; } diff --git a/src/mame/drivers/fs3216.cpp b/src/mame/drivers/fs3216.cpp index bb917962270..cbe6aa178df 100644 --- a/src/mame/drivers/fs3216.cpp +++ b/src/mame/drivers/fs3216.cpp @@ -445,7 +445,7 @@ void fs3216_state::clb_map(address_map &map) void fs3216_state::wdcpu_prog_map(address_map &map) { - map(0x000, 0x7ff).rom().region("wdcpu", 0); + map(0x0000, 0x03ff).rom().region("wdcpu", 0); } void fs3216_state::wdcpu_bank_map(address_map &map) diff --git a/src/mame/drivers/wicat.cpp b/src/mame/drivers/wicat.cpp index 54faa6c0cd1..ea8cd57c964 100644 --- a/src/mame/drivers/wicat.cpp +++ b/src/mame/drivers/wicat.cpp @@ -202,8 +202,8 @@ void wicat_state::video_io(address_map &map) void wicat_state::wd1000_mem(address_map &map) { - map(0x0000, 0x17ff).rom().region("wd3", 0x0000); - map(0x1800, 0x1fff).noprw(); + map(0x0000, 0x0bff).rom().region("wd3", 0x0000); + map(0x0c00, 0x0fff).noprw(); } void wicat_state::wd1000_io(address_map &map) diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index 4faea8300e7..e0f4bd0b7a2 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -300,7 +300,7 @@ struct options static const dasm_table_entry dasm_table[] = { - { "8x300", be, 0, []() -> util::disasm_interface * { return new n8x300_disassembler; } }, + { "8x300", be, -1, []() -> util::disasm_interface * { return new n8x300_disassembler; } }, { "adsp21xx", le, -2, []() -> util::disasm_interface * { return new adsp21xx_disassembler; } }, { "alpha", le, 0, []() -> util::disasm_interface * { return new alpha_disassembler; } }, { "alpha8201", le, 0, []() -> util::disasm_interface * { return new alpha8201_disassembler; } }, -- cgit v1.2.3-70-g09d2 From 1be6b82b346cd9a966449a3c0eaa8a7b31c71c5e Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Tue, 5 Feb 2019 19:19:30 +0700 Subject: alpha: disassembler improvements (nw) * added palcode disassembly * added standard pseudo-opcode forms --- src/devices/cpu/alpha/alpha.cpp | 13 +- src/devices/cpu/alpha/alpha.h | 10 +- src/devices/cpu/alpha/alphad.cpp | 431 ++++++++++++++++++++++++++++++++++++--- src/devices/cpu/alpha/alphad.h | 15 +- src/tools/unidasm.cpp | 3 + 5 files changed, 431 insertions(+), 41 deletions(-) (limited to 'src/tools/unidasm.cpp') diff --git a/src/devices/cpu/alpha/alpha.cpp b/src/devices/cpu/alpha/alpha.cpp index 1dc11ca7292..62fbd1bb584 100644 --- a/src/devices/cpu/alpha/alpha.cpp +++ b/src/devices/cpu/alpha/alpha.cpp @@ -15,10 +15,10 @@ #include "emu.h" #include "alpha.h" -#include "alphad.h" #include "debugger.h" +#include "softfloat3/source/include/softfloat.h" #define LOG_GENERAL (1U << 0) #define LOG_EXCEPTION (1U << 1) @@ -38,6 +38,7 @@ dec_21064_device::dec_21064_device(const machine_config &mconfig, const char *ta alpha_device::alpha_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : cpu_device(mconfig, type, tag, owner, clock) , m_main_config("main", ENDIANNESS_LITTLE, 64, 32, 0) + , m_dasm_type(alpha_disassembler::dasm_type::TYPE_UNKNOWN) , m_icount(0) { } @@ -66,11 +67,17 @@ void alpha_device::device_start() void alpha_device::device_reset() { + m_pc = 0; } void alpha_device::execute_run() { - m_icount = 0; + while (m_icount > 0) + { + debugger_instruction_hook(m_pc); + + m_icount--; + } } void alpha_device::execute_set_input(int inputnum, int state) @@ -89,5 +96,5 @@ bool alpha_device::memory_translate(int spacenum, int intention, offs_t &address std::unique_ptr alpha_device::create_disassembler() { - return std::make_unique(); + return std::make_unique(m_dasm_type); } diff --git a/src/devices/cpu/alpha/alpha.h b/src/devices/cpu/alpha/alpha.h index a4d66e806c7..b4f5db3712b 100644 --- a/src/devices/cpu/alpha/alpha.h +++ b/src/devices/cpu/alpha/alpha.h @@ -6,13 +6,12 @@ #pragma once -#include -#include "softfloat/milieu.h" -#include "softfloat/softfloat.h" +#include "alphad.h" class alpha_device : public cpu_device { public: + void set_dasm_type(alpha_disassembler::dasm_type type) { m_dasm_type = type; } protected: alpha_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); @@ -36,8 +35,11 @@ protected: virtual std::unique_ptr create_disassembler() override; private: - // emulation state + // configuration address_space_config m_main_config; + alpha_disassembler::dasm_type m_dasm_type; + + // emulation state int m_icount; u64 m_pc; diff --git a/src/devices/cpu/alpha/alphad.cpp b/src/devices/cpu/alpha/alphad.cpp index 3282036ba0a..73e74294a0e 100644 --- a/src/devices/cpu/alpha/alphad.cpp +++ b/src/devices/cpu/alpha/alphad.cpp @@ -30,11 +30,13 @@ #define OPERATE_FR(opcode, ra, rc) util::stream_format(stream, "%-10s %s, %s", opcode, F[ra], R[rc]) #define OPERATE_IR(opcode, im, rc) util::stream_format(stream, "%-10s #%d, %s", opcode, im, R[rc]) #define OPERATE_R(opcode, rc) util::stream_format(stream, "%-10s %s", opcode, R[rc]) +#define OPERATE_F(opcode, rc) util::stream_format(stream, "%-10s %s", opcode, F[rc]) #define MEMORY_R(opcode, ra, disp, rb) util::stream_format(stream, "%-10s %s, %d(%s)", opcode, R[ra], disp, R[rb]) #define MEMORY_F(opcode, ra, disp, rb) util::stream_format(stream, "%-10s %s, %d(%s)", opcode, F[ra], disp, R[rb]) #define BRANCH_R(opcode, ra, offset) util::stream_format(stream, "%-10s %s, 0x%x", opcode, R[ra], pc + 4 + offset) #define BRANCH_F(opcode, ra, offset) util::stream_format(stream, "%-10s %s, 0x%x", opcode, F[ra], pc + 4 + offset) +#define BRANCH(opcode, offset) util::stream_format(stream, "%-10s 0x%x", opcode, pc + 4 + offset) #define JUMP(opcode, ra, rb) util::stream_format(stream, "%-10s %s, (%s)", opcode, R[ra], R[rb]) @@ -76,13 +78,211 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da { // pal format case 0x00: - switch (instruction & 0x03ffffff) + switch (m_dasm_type) { + case TYPE_UNKNOWN: + switch (instruction & 0x03ffffff) + { case 0x0000: PAL_0("halt"); break; case 0x0002: PAL_0("draina"); break; case 0x0086: PAL_0("imb"); break; - default: PAL("call_pal", instruction & 0x03ffffff); break; // CALL_PAL + default: PAL("call_pal", instruction & 0x03ffffff); break; + } + break; + + case TYPE_NT: + switch (instruction & 0x03ffffff) + { + // Windows NT unprivileged PALcode + case 0x0080: PAL_0("bpt"); break; // breakpoint trap + case 0x0083: PAL_0("callsys"); break; // call system service + case 0x0086: PAL_0("imb"); break; // instruction memory barrier + case 0x00aa: PAL_0("gentrap"); break; // generate trap + case 0x00ab: PAL_0("rdteb"); break; // read TEB internal processor register + case 0x00ac: PAL_0("kbpt"); break; // kernel breakpoint trap + case 0x00ad: PAL_0("callkd"); break; // call kernel debugger + + // Windows NT privileged PALcode + case 0x0000: PAL_0("halt"); break; // trap to illegal instruction + case 0x0001: PAL_0("restart"); break; // restart the processor + case 0x0002: PAL_0("draina"); break; // drain aborts + case 0x0003: PAL_0("reboot"); break; // transfer to console firmware + case 0x0004: PAL_0("initpal"); break; // initialize the PALcode + case 0x0005: PAL_0("wrentry"); break; // write system entry + case 0x0006: PAL_0("swpirql"); break; // swap IRQL + case 0x0007: PAL_0("rdirql"); break; // read current IRQL + case 0x0008: PAL_0("di"); break; // disable interrupts + case 0x0009: PAL_0("ei"); break; // enable interrupts + case 0x000a: PAL_0("swppal"); break; // swap PALcode + case 0x000c: PAL_0("ssir"); break; // set software interrupt request + case 0x000d: PAL_0("csir"); break; // clear software interrupt request + case 0x000e: PAL_0("rfe"); break; // return from exception + case 0x000f: PAL_0("retsys"); break; // return from system service call + case 0x0010: PAL_0("swpctx"); break; // swap privileged thread context + case 0x0011: PAL_0("swpprocess"); break; // swap privileged process context + case 0x0012: PAL_0("rdmces"); break; // read machine check error summary + case 0x0013: PAL_0("wrmces"); break; // write machine check error summary + case 0x0014: PAL_0("tbia"); break; // translation buffer invalidate all + case 0x0015: PAL_0("tbis"); break; // translation buffer invalidate single + case 0x0016: PAL_0("dtbis"); break; // data translation buffer invalidate single + case 0x0017: PAL_0("tbisasn"); break; // translation buffer invalidate single ASN + case 0x0018: PAL_0("rdksp"); break; // read initial kernel stack + case 0x0019: PAL_0("swpksp"); break; // swap initial kernel stack + case 0x001a: PAL_0("rdpsr"); break; // read processor status register + case 0x001c: PAL_0("rdpcr"); break; // read PCR (processor control registers) + case 0x001e: PAL_0("rdthread"); break; // read the current thread value + case 0x0020: PAL_0("wrperfmon"); break; // write performance monitoring values + case 0x0030: PAL_0("rdcounters"); break; // read PALcode event counters + case 0x0031: PAL_0("rdstate"); break; // read internal processor state + + default: PAL("call_pal", instruction & 0x03ffffff); break; + } + break; + + case TYPE_UNIX: + switch (instruction & 0x03ffffff) + { + // Digital UNIX unprivileged PALcode + case 0x0080: PAL_0("bpt"); break; // breakpoint trap + case 0x0081: PAL_0("bugchk"); break; // bugcheck + case 0x0083: PAL_0("callsys"); break; // system call + case 0x0086: PAL_0("imb"); break; // i-stream memory barrier + case 0x0092: PAL_0("urti"); break; // return from user mode trap + case 0x009e: PAL_0("rdunique"); break; // read unique value + case 0x009f: PAL_0("wrunique"); break; // write unique value + case 0x00aa: PAL_0("gentrap"); break; // generate software trap + case 0x00ae: PAL_0("clrfen"); break; // clear floating-point enable + + // Digital UNIX privileged PALcode + case 0x0000: PAL_0("halt"); break; // halt the processor + case 0x0001: PAL_0("cflush"); break; // cache flush + case 0x0002: PAL_0("draina"); break; // drain aborts + case 0x0009: PAL_0("cserve"); break; // console service + case 0x000a: PAL_0("swppal"); break; // swap PALcode image + case 0x000d: PAL_0("wripir"); break; // write interprocessor interrupt request + case 0x0010: PAL_0("rdmces"); break; // read machine check error summary register + case 0x0011: PAL_0("wrmces"); break; // write machine check error summary register + case 0x002b: PAL_0("wrfen"); break; // write floating-point enable + case 0x002d: PAL_0("wrvptptr"); break; // write virtual page table pointer + case 0x0030: PAL_0("swpctx"); break; // swap privileged context + case 0x0031: PAL_0("wrval"); break; // write system value + case 0x0032: PAL_0("rdval"); break; // read system value + case 0x0033: PAL_0("tbi"); break; // translation buffer invalidate + case 0x0034: PAL_0("wrent"); break; // write system entry address + case 0x0035: PAL_0("swpipl"); break; // swap interrupt priority level + case 0x0036: PAL_0("rdps"); break; // read processor status + case 0x0037: PAL_0("wrkgp"); break; // write kernel global pointer + case 0x0038: PAL_0("wrusp"); break; // write user stack pointer + case 0x0039: PAL_0("wrperfmon"); break; // performance monitoring function + case 0x003a: PAL_0("rdusp"); break; // read user stack pointer + case 0x003c: PAL_0("whami"); break; // who am I + case 0x003d: PAL_0("retsys"); break; // return from system call + case 0x003e: PAL_0("wtint"); break; // wait for interrupt + case 0x003f: PAL_0("rti"); break; // return from trap or interrupt + + default: PAL("call_pal", instruction & 0x03ffffff); break; + } + break; + + case TYPE_VMS: + switch (instruction & 0x03ffffff) + { + // OpenVMS unprivileged PALcode + case 0x0080: PAL_0("bpt"); break; // breakpoint + case 0x0081: PAL_0("bugchk"); break; // bugcheck + case 0x0082: PAL_0("chme"); break; // change mode to executive + case 0x0083: PAL_0("chmk"); break; // change mode to kernel + case 0x0084: PAL_0("chms"); break; // change mode to supervisor + case 0x0085: PAL_0("chmu"); break; // change mode to user + case 0x0086: PAL_0("imb"); break; // i-stream memory barrier + case 0x0087: PAL_0("insqhil"); break; // insert into longword queue at head interlocked + case 0x0088: PAL_0("insqtil"); break; // insert into longword queue at tail interlocked + case 0x0089: PAL_0("insqhiq"); break; // insert into quadword queue at head interlocked + case 0x008a: PAL_0("insqtiq"); break; // insert into quadword queue at tail interlocked + case 0x008b: PAL_0("insquel"); break; // insert entry into longword queue + case 0x008c: PAL_0("insqueq"); break; // insert entry into quadword queue + case 0x008d: PAL_0("insquel/d"); break; // insert entry into longword queue deferred + case 0x008e: PAL_0("insqueq/d"); break; // insert entry into quadword queue deferred + case 0x008f: PAL_0("prober"); break; // probe for read access + case 0x0090: PAL_0("probew"); break; // probe for write access + case 0x0091: PAL_0("rd_ps"); break; // move processor status + case 0x0092: PAL_0("rei"); break; // return from exception or interrupt + case 0x0093: PAL_0("remqhil"); break; // remove from longword queue at head interlocked + case 0x0094: PAL_0("remqtil"); break; // remove from longword queue at tail interlocked + case 0x0095: PAL_0("remqhiq"); break; // remove from quadword queue at head interlocked + case 0x0096: PAL_0("remqtiq"); break; // remove from quadword queue at tail interlocked + case 0x0097: PAL_0("remquel"); break; // remove entry from longword queue + case 0x0098: PAL_0("remqueq"); break; // remove entry from quadword queue + case 0x0099: PAL_0("remquel/d"); break; // remove entry from longword queue deferred + case 0x009a: PAL_0("remqueq/d"); break; // remove entry from quadword queue deferred + case 0x009b: PAL_0("swasten"); break; // swap AST enable for current mode + case 0x009c: PAL_0("wr_ps_sw"); break; // write processor status software field + case 0x009d: PAL_0("rscc"); break; // read system cycle counter + case 0x009e: PAL_0("read_unq"); break; // read unique context + case 0x009f: PAL_0("write_unq"); break; // write unique context + case 0x00a0: PAL_0("amovrr"); break; // atomic move from register to register + case 0x00a1: PAL_0("amovrm"); break; // atomic move from register to memory + case 0x00a2: PAL_0("insqhilr"); break; // insert into longword queue at head interlocked resident + case 0x00a3: PAL_0("insqtilr"); break; // insert into longword queue at tail interlocked resident + case 0x00a4: PAL_0("insqhiqr"); break; // insert into quadword queue at head interlocked resident + case 0x00a5: PAL_0("insqtiqr"); break; // insert into quadword queue at tail interlocked resident + case 0x00a6: PAL_0("remqhilr"); break; // remove from longword queue at head interlocked resident + case 0x00a7: PAL_0("remqtilr"); break; // remove from longword queue at tail interlocked resident + case 0x00a8: PAL_0("remqhiqr"); break; // remove from quadword queue at head interlocked resident + case 0x00a9: PAL_0("remqtiqr"); break; // remove from quadword queue at tail interlocked resident + case 0x00aa: PAL_0("gentrap"); break; // generate software trap + case 0x00ae: PAL_0("clrfen"); break; // clear floating-point enable + + // OpenVMS privileged PALcode + case 0x0000: PAL_0("halt"); break; // halt processor + case 0x0001: PAL_0("cflush"); break; // cache flush + case 0x0002: PAL_0("draina"); break; // drain aborts + case 0x0003: PAL_0("ldqp"); break; // load quadword physical + case 0x0004: PAL_0("stqp"); break; // store quadword physical + case 0x0005: PAL_0("swpctx"); break; // swap privileged context + case 0x0006: PAL_0("mfpr_asn"); break; // move from processor register ASN + case 0x0009: PAL_0("cserve"); break; // console service + case 0x000a: PAL_0("swppal"); break; // swap PALcode image + case 0x000b: PAL_0("mfpr_fen"); break; // move from processor register FEN + case 0x000c: PAL_0("mtpr_fen"); break; // move to processor register FEN + case 0x000d: PAL_0("mtpr_ipir"); break; // move to processor register IPRI + case 0x000e: PAL_0("mfpr_ipl"); break; // move from processor register IPL + case 0x000f: PAL_0("mtpr_ipl"); break; // move to processor register IPL + case 0x0010: PAL_0("mfpr_mces"); break; // move from processor register MCES + case 0x0011: PAL_0("mtpr_mces"); break; // move to processor register MCES + case 0x0012: PAL_0("mfpr_pcbb"); break; // move from processor register PCBB + case 0x0013: PAL_0("mfpr_prbr"); break; // move from processor register PRBR + case 0x0014: PAL_0("mtpr_prbr"); break; // move to processor register PRBR + case 0x0015: PAL_0("mfpr_ptbr"); break; // move from processor register PTBR + case 0x0016: PAL_0("mfpr_scbb"); break; // move from processor register SCBB + case 0x0017: PAL_0("mtpr_scbb"); break; // move to processor register SCBB + case 0x0018: PAL_0("mtpr_sirr"); break; // move to processor register SIRR + case 0x0019: PAL_0("mfpr_sisr"); break; // move from processor register SISR + case 0x001a: PAL_0("mfpr_tbchk"); break; // move from processor register TBCHK + case 0x001b: PAL_0("mtpr_tbia"); break; // move to processor register TBIA + case 0x001c: PAL_0("mtpr_tbiap"); break; // move to processor register TBIAP + case 0x001d: PAL_0("mtpr_tbis"); break; // move to processor register TBIS + case 0x001e: PAL_0("mfpr_esp"); break; // move from processor register ESP + case 0x001f: PAL_0("mtpr_esp"); break; // move to processor register ESP + case 0x0020: PAL_0("mfpr_ssp"); break; // move from processor register SSP + case 0x0021: PAL_0("mtpr_ssp"); break; // move to processor register SSP + case 0x0022: PAL_0("mfpr_usp"); break; // move from processor register USP + case 0x0023: PAL_0("mtpr_usp"); break; // move to processor register USP + case 0x0024: PAL_0("mtpr_tbisd"); break; // move to processor register TBISD + case 0x0025: PAL_0("mtpr_tbisi"); break; // move to processor register TBISI + case 0x0026: PAL_0("mtpr_asten"); break; // move to processor register ASTEN + case 0x0027: PAL_0("mtpr_astsr"); break; // move to processor register ASTSR + case 0x0029: PAL_0("mfpr_vptb"); break; // move from processor register VPTB + case 0x002a: PAL_0("mtpr_vptb"); break; // move to processor register VPTB + case 0x002b: PAL_0("mtpr_perfmon"); break; // move to processor register PERFMON + case 0x002e: PAL_0("mtpr_datfx"); break; // move to processor register DATFX + case 0x003e: PAL_0("wtint"); break; // wait for interrupt + case 0x003f: PAL_0("mfpr_whami"); break; // move from processor register WHAMI + + default: PAL("call_pal", instruction & 0x03ffffff); break; + } + break; } break; @@ -96,10 +296,20 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da case 0x07: RESERVED("opc07"); break; // OPC07 // memory format - case 0x08: MEMORY_R("lda", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDA + case 0x08: + if (Rb(instruction) == 31) + OPERATE_IR("mov", Disp_M(instruction), Ra(instruction)); + else + MEMORY_R("lda", Ra(instruction), Disp_M(instruction), Rb(instruction)); // LDA + break; case 0x09: MEMORY_R("ldah", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDAH case 0x0a: MEMORY_R("ldbu", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDBU (BWX) - case 0x0b: MEMORY_R("ldq_u", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDQ_U + case 0x0b: + if (Ra(instruction) == 31 && Disp_M(instruction) == 0) + MISC_0("unop"); + else + MEMORY_R("ldq_u", Ra(instruction), Disp_M(instruction), Rb(instruction)); // LDQ_U + break; case 0x0c: MEMORY_R("ldwu", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDWU (BWX) case 0x0d: MEMORY_R("stw", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STW (BWX) case 0x0e: MEMORY_R("stb", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STB (BWX) @@ -110,9 +320,19 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da switch ((instruction >> 5) & 0xff) { // register variants - case 0x00: OPERATE_RRR("addl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDL + case 0x00: + if (Ra(instruction) == 31) + OPERATE_RR("sextl", Rb(instruction), Rc(instruction)); + else + OPERATE_RRR("addl", Ra(instruction), Rb(instruction), Rc(instruction)); // ADDL + break; case 0x02: OPERATE_RRR("s4addl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S4ADDL - case 0x09: OPERATE_RRR("subl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBL + case 0x09: + if (Ra(instruction) == 31) + OPERATE_RR("negl", Rb(instruction), Rc(instruction)); + else + OPERATE_RRR("subl", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBL + break; case 0x0b: OPERATE_RRR("s4subl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S4SUBL case 0x0f: OPERATE_RRR("cmpbge", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPBGE case 0x12: OPERATE_RRR("s8addl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S8ADDL @@ -120,23 +340,48 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da case 0x1d: OPERATE_RRR("cmpult", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPULT case 0x20: OPERATE_RRR("addq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDQ case 0x22: OPERATE_RRR("s4addq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S4ADDQ - case 0x29: OPERATE_RRR("subq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBQ + case 0x29: + if (Ra(instruction) == 31) + OPERATE_RR("negq", Rb(instruction), Rc(instruction)); + else + OPERATE_RRR("subq", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBQ + break; case 0x2b: OPERATE_RRR("s4subq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S4SUBQ case 0x2d: OPERATE_RRR("cmpeq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPEQ case 0x32: OPERATE_RRR("s8addq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S8ADDQ case 0x3b: OPERATE_RRR("s8subq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S8SUBQ case 0x3d: OPERATE_RRR("cmpule", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPULE case 0x40: OPERATE_RRR("addl/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDL/V - case 0x49: OPERATE_RRR("subl/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBL/V + case 0x49: + if (Ra(instruction) == 31) + OPERATE_RR("negl/v", Rb(instruction), Rc(instruction)); + else + OPERATE_RRR("subl/v", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBL/V + break; case 0x4d: OPERATE_RRR("cmplt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPLT case 0x60: OPERATE_RRR("addq/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDQ/V - case 0x69: OPERATE_RRR("subq/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBQ/V + case 0x69: + if (Ra(instruction) == 31) + OPERATE_RR("negq/v", Rb(instruction), Rc(instruction)); + else + OPERATE_RRR("subq/v", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBQ/V + break; case 0x6d: OPERATE_RRR("cmple", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPLE // immediate variants - case 0x80: OPERATE_RIR("addl", Ra(instruction), Im(instruction), Rc(instruction)); break; // ADDL + case 0x80: + if (Ra(instruction) == 31) + OPERATE_IR("sextl", Im(instruction), Rc(instruction)); + else + OPERATE_RIR("addl", Ra(instruction), Im(instruction), Rc(instruction)); // ADDL + break; case 0x82: OPERATE_RIR("s4addl", Ra(instruction), Im(instruction), Rc(instruction)); break; // S4ADDL - case 0x89: OPERATE_RIR("subl", Ra(instruction), Im(instruction), Rc(instruction)); break; // SUBL + case 0x89: + if (Ra(instruction) == 31) + OPERATE_IR("negl", Im(instruction), Rc(instruction)); + else + OPERATE_RIR("subl", Ra(instruction), Im(instruction), Rc(instruction)); // SUBL + break; case 0x8b: OPERATE_RIR("s4subl", Ra(instruction), Im(instruction), Rc(instruction)); break; // S4SUBL case 0x8f: OPERATE_RIR("cmpbge", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPBGE case 0x92: OPERATE_RIR("s8addl", Ra(instruction), Im(instruction), Rc(instruction)); break; // S8ADDL @@ -144,17 +389,32 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da case 0x9d: OPERATE_RIR("cmpult", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPULT case 0xa0: OPERATE_RIR("addq", Ra(instruction), Im(instruction), Rc(instruction)); break; // ADDQ case 0xa2: OPERATE_RIR("s4addq", Ra(instruction), Im(instruction), Rc(instruction)); break; // S4ADDQ - case 0xa9: OPERATE_RIR("subq", Ra(instruction), Im(instruction), Rc(instruction)); break; // SUBQ + case 0xa9: + if (Ra(instruction) == 31) + OPERATE_IR("negq", Im(instruction), Rc(instruction)); + else + OPERATE_RIR("subq", Ra(instruction), Im(instruction), Rc(instruction)); // SUBQ + break; case 0xab: OPERATE_RIR("s4subq", Ra(instruction), Im(instruction), Rc(instruction)); break; // S4SUBQ case 0xad: OPERATE_RIR("cmpeq", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPEQ case 0xb2: OPERATE_RIR("s8addq", Ra(instruction), Im(instruction), Rc(instruction)); break; // S8ADDQ case 0xbb: OPERATE_RIR("s8subq", Ra(instruction), Im(instruction), Rc(instruction)); break; // S8SUBQ case 0xbd: OPERATE_RIR("cmpule", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPULE case 0xc0: OPERATE_RIR("addl/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // ADDL/V - case 0xc9: OPERATE_RIR("subl/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // SUBL/V + case 0xc9: + if (Ra(instruction) == 31) + OPERATE_IR("negl/v", Im(instruction), Rc(instruction)); + else + OPERATE_RIR("subl/v", Ra(instruction), Im(instruction), Rc(instruction)); // SUBL/V + break; case 0xcd: OPERATE_RIR("cmplt", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPLT case 0xe0: OPERATE_RIR("addq/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // ADDQ/V - case 0xe9: OPERATE_RIR("subq/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // SUBQ/V + case 0xe9: + if (Ra(instruction) == 31) + OPERATE_IR("negq/v", Im(instruction), Rc(instruction)); + else + OPERATE_RIR("subq/v", Ra(instruction), Im(instruction), Rc(instruction)); // SUBQ/V + break; case 0xed: OPERATE_RIR("cmple", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPLE default: UNKNOWN("inta*"); break; @@ -168,10 +428,24 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da case 0x08: OPERATE_RRR("bic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // BIC case 0x14: OPERATE_RRR("cmovlbs", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVLBS case 0x16: OPERATE_RRR("cmovlbc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVLBC - case 0x20: OPERATE_RRR("bis", Ra(instruction), Rb(instruction), Rc(instruction)); break; // BIS + case 0x20: + if (Ra(instruction) == 31 && Rb(instruction) == 31 && Rc(instruction) == 31) + MISC_0("nop"); + else if (Ra(instruction) == 31 && Rb(instruction) == 31) + OPERATE_R("clr", Rc(instruction)); + else if (Ra(instruction) == Rb(instruction)) + OPERATE_RR("mov", Rb(instruction), Rc(instruction)); + else + OPERATE_RRR("bis", Ra(instruction), Rb(instruction), Rc(instruction)); // BIS + break; case 0x24: OPERATE_RRR("cmoveq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVEQ case 0x26: OPERATE_RRR("cmovne", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVNE - case 0x28: OPERATE_RRR("ornot", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ORNOT + case 0x28: + if (Ra(instruction) == 31) + OPERATE_RR("not", Rb(instruction), Rc(instruction)); + else + OPERATE_RRR("ornot", Ra(instruction), Rb(instruction), Rc(instruction)); // ORNOT + break; case 0x40: OPERATE_RRR("xor", Ra(instruction), Rb(instruction), Rc(instruction)); break; // XOR case 0x44: OPERATE_RRR("cmovlt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVLT case 0x46: OPERATE_RRR("cmovge", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVGE @@ -185,10 +459,20 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da case 0x88: OPERATE_RIR("bic", Ra(instruction), Im(instruction), Rc(instruction)); break; // BIC case 0x94: OPERATE_RIR("cmovlbs", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVLBS case 0x96: OPERATE_RIR("cmovlbc", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVLBC - case 0xa0: OPERATE_RIR("bis", Ra(instruction), Im(instruction), Rc(instruction)); break; // BIS + case 0xa0: + if (Ra(instruction) == 31) + OPERATE_IR("mov", Im(instruction), Rc(instruction)); + else + OPERATE_RIR("bis", Ra(instruction), Im(instruction), Rc(instruction)); // BIS + break; case 0xa4: OPERATE_RIR("cmoveq", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVEQ case 0xa6: OPERATE_RIR("cmovne", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVNE - case 0xa8: OPERATE_RIR("ornot", Ra(instruction), Im(instruction), Rc(instruction)); break; // ORNOT + case 0xa8: + if (Ra(instruction) == 31) + OPERATE_IR("not", Im(instruction), Rc(instruction)); + else + OPERATE_RIR("ornot", Ra(instruction), Im(instruction), Rc(instruction)); // ORNOT + break; case 0xc0: OPERATE_RIR("xor", Ra(instruction), Im(instruction), Rc(instruction)); break; // XOR case 0xc4: OPERATE_RIR("cmovlt", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVLT case 0xc6: OPERATE_RIR("cmovge", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVGE @@ -359,12 +643,22 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da case 0x03c: OPERATE_FF("cvtqf/c", Rb(instruction), Rc(instruction)); break; // CVTQF/C case 0x03e: OPERATE_FF("cvtqg/c", Rb(instruction), Rc(instruction)); break; // CVTQG/C case 0x080: OPERATE_FFF("addf", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF - case 0x081: OPERATE_FFF("subf", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF + case 0x081: + if (Ra(instruction) == 31) + OPERATE_FF("negf", Rb(instruction), Rc(instruction)); + else + OPERATE_FFF("subf", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBF + break; case 0x082: OPERATE_FFF("mulf", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF case 0x083: OPERATE_FFF("divf", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF case 0x09e: OPERATE_FF("cvtdg", Rb(instruction), Rc(instruction)); break; // CVTDG case 0x0a0: OPERATE_FFF("addg", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG - case 0x0a1: OPERATE_FFF("subg", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG + case 0x0a1: + if (Ra(instruction) == 31) + OPERATE_FF("negg", Rb(instruction), Rc(instruction)); + else + OPERATE_FFF("subg", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBG + break; case 0x0a2: OPERATE_FFF("mulg", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG case 0x0a3: OPERATE_FFF("divg", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG case 0x0a5: OPERATE_FFF("cmpgeq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGEQ @@ -412,12 +706,22 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da case 0x42d: OPERATE_FF("cvtgd/sc", Rb(instruction), Rc(instruction)); break; // CVTGD/SC case 0x42f: OPERATE_FF("cvtgq/sc", Rb(instruction), Rc(instruction)); break; // CVTGQ/SC case 0x480: OPERATE_FFF("addf/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/S - case 0x481: OPERATE_FFF("subf/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/S + case 0x481: + if (Ra(instruction) == 31) + OPERATE_FF("negf/s", Rb(instruction), Rc(instruction)); + else + OPERATE_FFF("subf/s", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBF/S + break; case 0x482: OPERATE_FFF("mulf/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/S case 0x483: OPERATE_FFF("divf/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/S case 0x49e: OPERATE_FF("cvtdg/s", Rb(instruction), Rc(instruction)); break; // CVTDG/S case 0x4a0: OPERATE_FFF("addg/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/S - case 0x4a1: OPERATE_FFF("subg/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/S + case 0x4a1: + if (Ra(instruction) == 31) + OPERATE_FF("negg/s", Rb(instruction), Rc(instruction)); + else + OPERATE_FFF("subg/s", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBG/S + break; case 0x4a2: OPERATE_FFF("mulg/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/S case 0x4a3: OPERATE_FFF("divg/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/S case 0x4a5: OPERATE_FFF("cmpgeq/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGEQ/S @@ -482,11 +786,21 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da case 0x07c: OPERATE_FF("cvtqs/m", Rb(instruction), Rc(instruction)); break; // CVTQS/M case 0x07e: OPERATE_FF("cvtqt/m", Rb(instruction), Rc(instruction)); break; // CVTQT/M case 0x080: OPERATE_FFF("adds", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS - case 0x081: OPERATE_FFF("subs", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS + case 0x081: + if (Ra(instruction) == 31) + OPERATE_FF("negs", Rb(instruction), Rc(instruction)); + else + OPERATE_FFF("subs", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBS + break; case 0x082: OPERATE_FFF("muls", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS case 0x083: OPERATE_FFF("divs", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS case 0x0a0: OPERATE_FFF("addt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT - case 0x0a1: OPERATE_FFF("subt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT + case 0x0a1: + if (Ra(instruction) == 31) + OPERATE_FF("negt", Rb(instruction), Rc(instruction)); + else + OPERATE_FFF("subt", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBT + break; case 0x0a2: OPERATE_FFF("mult", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT case 0x0a3: OPERATE_FFF("divt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT case 0x0a4: OPERATE_FFF("cmptun", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTUN @@ -571,11 +885,21 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da case 0x56c: OPERATE_FF("cvttts/sum", Rb(instruction), Rc(instruction)); break; // CVTTS/SUM case 0x56f: OPERATE_FF("cvttq/svm", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVM case 0x580: OPERATE_FFF("adds/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SU - case 0x581: OPERATE_FFF("subs/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SU + case 0x581: + if (Ra(instruction) == 31) + OPERATE_FF("negs/su", Rb(instruction), Rc(instruction)); + else + OPERATE_FFF("subs/su", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBS/SU + break; case 0x582: OPERATE_FFF("muls/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SU case 0x583: OPERATE_FFF("divs/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SU case 0x5a0: OPERATE_FFF("addt/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SU - case 0x5a1: OPERATE_FFF("subt/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SU + case 0x5a1: + if (Ra(instruction) == 31) + OPERATE_FF("negt/su", Rb(instruction), Rc(instruction)); + else + OPERATE_FFF("subt/su", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBT/SU + break; case 0x5a2: OPERATE_FFF("mult/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SU case 0x5a3: OPERATE_FFF("divt/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SU case 0x5a4: OPERATE_FFF("cmptun/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTUN/SU @@ -620,11 +944,21 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da case 0x77c: OPERATE_FF("cvtqs/suim", Rb(instruction), Rc(instruction)); break; // CVTQS/SUIM case 0x77e: OPERATE_FF("cvtqt/suim", Rb(instruction), Rc(instruction)); break; // CVTQT/SUIM case 0x780: OPERATE_FFF("adds/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUI - case 0x781: OPERATE_FFF("subs/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUI + case 0x781: + if (Ra(instruction) == 31) + OPERATE_FF("negs/sui", Rb(instruction), Rc(instruction)); + else + OPERATE_FFF("subs/sui", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBS/SUI + break; case 0x782: OPERATE_FFF("muls/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUI case 0x783: OPERATE_FFF("divs/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUI case 0x7a0: OPERATE_FFF("addt/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUI - case 0x7a1: OPERATE_FFF("subt/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUI + case 0x7a1: + if (Ra(instruction) == 31) + OPERATE_FF("negt/sui", Rb(instruction), Rc(instruction)); + else + OPERATE_FFF("subt/sui", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBT/SUI + break; case 0x7a2: OPERATE_FFF("mult/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUI case 0x7a3: OPERATE_FFF("divt/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUI case 0x7ac: OPERATE_FF("cvttts/sui", Rb(instruction), Rc(instruction)); break; // CVTTS/SUI @@ -651,11 +985,37 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da switch ((instruction >> 5) & 0x7ff) { case 0x010: OPERATE_FF("cvtlq", Rb(instruction), Rc(instruction)); break; // CVTLQ - case 0x020: OPERATE_FFF("cpys", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CPYS - case 0x021: OPERATE_FFF("cpysn", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CPYSN + case 0x020: + if (Ra(instruction) == 31 && Rb(instruction) == 31 && Rc(instruction) == 31) + MISC_0("fnop"); + else if (Ra(instruction) == 31 && Rb(instruction) == 31) + OPERATE_F("fclr", Rc(instruction)); + else if (Ra(instruction) == 31) + OPERATE_FF("fabs", Rb(instruction), Rc(instruction)); + else if (Ra(instruction) == Rb(instruction)) + OPERATE_FF("fmov", Rb(instruction), Rc(instruction)); + else + OPERATE_FFF("cpys", Ra(instruction), Rb(instruction), Rc(instruction)); // CPYS + break; + case 0x021: + if (Ra(instruction) == Rb(instruction)) + OPERATE_FF("fneg", Rb(instruction), Rc(instruction)); + else + OPERATE_FFF("cpysn", Ra(instruction), Rb(instruction), Rc(instruction)); // CPYSN + break; case 0x022: OPERATE_FFF("cpyse", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CPYSE - case 0x024: OPERATE_FFF("mt_fpcr", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MT_FPCR - case 0x025: OPERATE_FFF("mf_fpcr", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MF_FPCR + case 0x024: + if (Ra(instruction) == Rb(instruction) && Rb(instruction) == Rc(instruction)) + OPERATE_F("mt_fpcr", Rc(instruction)); + else + OPERATE_FFF("mt_fpcr", Ra(instruction), Rb(instruction), Rc(instruction)); // MT_FPCR + break; + case 0x025: + if (Ra(instruction) == Rb(instruction) && Rb(instruction) == Rc(instruction)) + OPERATE_F("mf_fpcr", Rc(instruction)); + else + OPERATE_FFF("mf_fpcr", Ra(instruction), Rb(instruction), Rc(instruction)); // MF_FPCR + break; case 0x02a: OPERATE_FFF("fcmoveq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVEQ case 0x02b: OPERATE_FFF("fcmovne", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVNE case 0x02c: OPERATE_FFF("fcmovlt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVLT @@ -761,7 +1121,12 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da case 0x2f: MEMORY_R("stq_c", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STQ_C // branch format - case 0x30: BRANCH_R("br", Ra(instruction), Disp_B(instruction)); break; // BR + case 0x30: + if (Ra(instruction) == 31) + BRANCH("br", Disp_B(instruction)); + else + BRANCH_R("br", Ra(instruction), Disp_B(instruction)); // BR + break; case 0x31: BRANCH_F("fbeq", Ra(instruction), Disp_B(instruction)); break; // FBEQ case 0x32: BRANCH_F("fblt", Ra(instruction), Disp_B(instruction)); break; // FBLT case 0x33: BRANCH_F("fble", Ra(instruction), Disp_B(instruction)); break; // FBLE diff --git a/src/devices/cpu/alpha/alphad.h b/src/devices/cpu/alpha/alphad.h index 09fa4b8a63a..2c6ee827503 100644 --- a/src/devices/cpu/alpha/alphad.h +++ b/src/devices/cpu/alpha/alphad.h @@ -9,7 +9,18 @@ class alpha_disassembler : public util::disasm_interface { public: - alpha_disassembler() = default; + enum dasm_type : unsigned + { + TYPE_UNKNOWN = 0, + TYPE_NT = 1, + TYPE_UNIX = 2, + TYPE_VMS = 3, + }; + + alpha_disassembler(alpha_disassembler::dasm_type type = TYPE_UNKNOWN) + : m_dasm_type(type) + { + }; virtual ~alpha_disassembler() = default; virtual u32 opcode_alignment() const override { return 4; }; @@ -18,6 +29,8 @@ public: private: static char const *const R[]; static char const *const F[]; + + dasm_type const m_dasm_type; }; #endif // MAME_CPU_ALPHA_ALPHAD_H diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index e0f4bd0b7a2..432a762c028 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -303,6 +303,9 @@ static const dasm_table_entry dasm_table[] = { "8x300", be, -1, []() -> util::disasm_interface * { return new n8x300_disassembler; } }, { "adsp21xx", le, -2, []() -> util::disasm_interface * { return new adsp21xx_disassembler; } }, { "alpha", le, 0, []() -> util::disasm_interface * { return new alpha_disassembler; } }, + { "alpha_nt", le, 0, []() -> util::disasm_interface * { return new alpha_disassembler(alpha_disassembler::TYPE_NT); } }, + { "alpha_unix", le, 0, []() -> util::disasm_interface * { return new alpha_disassembler(alpha_disassembler::TYPE_UNIX); } }, + { "alpha_vms", le, 0, []() -> util::disasm_interface * { return new alpha_disassembler(alpha_disassembler::TYPE_VMS); } }, { "alpha8201", le, 0, []() -> util::disasm_interface * { return new alpha8201_disassembler; } }, { "alto2", be, -2, []() -> util::disasm_interface * { return new alto2_disassembler; } }, { "am29000", be, 0, []() -> util::disasm_interface * { return new am29000_disassembler; } }, -- cgit v1.2.3-70-g09d2 From 156619b401e85bfe14f771a59bd8d0272fa257a4 Mon Sep 17 00:00:00 2001 From: AJR Date: Sun, 3 Mar 2019 16:56:13 -0500 Subject: Add skeleton CPU device and disassembler for HPC architecture --- scripts/src/cpu.lua | 17 + scripts/target/mame/arcade.lua | 1 + scripts/target/mame/mess.lua | 1 + src/devices/cpu/hpc/hpc.cpp | 102 ++++++ src/devices/cpu/hpc/hpc.h | 73 ++++ src/devices/cpu/hpc/hpcdasm.cpp | 739 ++++++++++++++++++++++++++++++++++++++++ src/devices/cpu/hpc/hpcdasm.h | 49 +++ src/mame/drivers/age_candy.cpp | 22 +- src/tools/unidasm.cpp | 2 + 9 files changed, 993 insertions(+), 13 deletions(-) create mode 100644 src/devices/cpu/hpc/hpc.cpp create mode 100644 src/devices/cpu/hpc/hpc.h create mode 100644 src/devices/cpu/hpc/hpcdasm.cpp create mode 100644 src/devices/cpu/hpc/hpcdasm.h (limited to 'src/tools/unidasm.cpp') diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 4095f62a4c3..631af0dbcff 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -2800,3 +2800,20 @@ if (CPUS["ALPHA"]~=null or _OPTIONS["with-tools"]) then table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/alpha/alphad.cpp") table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/alpha/alphad.h") end + +-------------------------------------------------- +-- National Semiconductor HPC +--@src/devices/cpu/hpc/hpc.h,CPUS["HPC"] = true +-------------------------------------------------- + +if (CPUS["HPC"]~=null) then + files { + MAME_DIR .. "src/devices/cpu/hpc/hpc.cpp", + MAME_DIR .. "src/devices/cpu/hpc/hpc.h", + } +end + +if (CPUS["HPC"]~=null or _OPTIONS["with-tools"]) then + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/hpc/hpcdasm.cpp") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/hpc/hpcdasm.h") +end diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index d5c8b579f1f..41c6d9ce8f9 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -133,6 +133,7 @@ CPUS["HMCS40"] = true --CPUS["SM510"] = true CPUS["ST62XX"] = true CPUS["DSPP"] = true +CPUS["HPC"] = true -------------------------------------------------- -- specify available sound cores diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 29f067ce502..ffab589c5b6 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -138,6 +138,7 @@ CPUS["CLIPPER"] = true CPUS["CAPRICORN"] = true CPUS["ALPHA"] = true --CPUS["DSPP"] = true +--CPUS["HPC"] = true -------------------------------------------------- -- specify available sound cores; some of these are diff --git a/src/devices/cpu/hpc/hpc.cpp b/src/devices/cpu/hpc/hpc.cpp new file mode 100644 index 00000000000..6cf5f30eb37 --- /dev/null +++ b/src/devices/cpu/hpc/hpc.cpp @@ -0,0 +1,102 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/*************************************************************************** + + National Semiconductor High-Performance microController (HPC) + + Currently this device is just a stub with no actual execution core. + +***************************************************************************/ + +#include "emu.h" +#include "hpc.h" +#include "hpcdasm.h" + +// device type definitions +DEFINE_DEVICE_TYPE(HPC46104, hpc46104_device, "hpc46104", "HPC46104") + + +void hpc46104_device::internal_map(address_map &map) +{ + map(0x0000, 0x00bf).ram(); + map(0x00c0, 0x00c0).rw(FUNC(hpc46104_device::psw_r), FUNC(hpc46104_device::psw_w)); + map(0x00c4, 0x00cf).ram().share("core_regs"); + // TODO: many other internal registers + map(0x01c0, 0x02ff).ram(); +} + +std::unique_ptr hpc46104_device::create_disassembler() +{ + return std::make_unique(); +} + + +hpc_device::hpc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor map) + : cpu_device(mconfig, type, tag, owner, clock) + , m_program_config("program", ENDIANNESS_LITTLE, 16, 16, 0, map) + , m_program(nullptr) + , m_core_regs(*this, "core_regs") + , m_psw(0) + , m_icount(0) +{ +} + +hpc46104_device::hpc46104_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : hpc_device(mconfig, HPC46104, tag, owner, clock, address_map_constructor(FUNC(hpc46104_device::internal_map), this)) +{ +} + +device_memory_interface::space_config_vector hpc_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(AS_PROGRAM, &m_program_config), + }; +} + + +void hpc_device::device_start() +{ + m_program = &space(AS_PROGRAM); + + set_icountptr(m_icount); + + state_add(HPC_PSW, "PSW", m_psw); + state_add(HPC_SP, "SP", m_core_regs[0]); + state_add(HPC_PC, "PC", m_core_regs[1]); + state_add(STATE_GENPC, "GENPC", m_core_regs[1]).callimport().noshow(); + state_add(STATE_GENPCBASE, "CURPC", m_core_regs[1]).callimport().noshow(); + state_add(HPC_A, "A", m_core_regs[2]); + state_add(HPC_K, "K", m_core_regs[3]); + state_add(HPC_B, "B", m_core_regs[4]); + state_add(HPC_X, "X", m_core_regs[5]); + + save_item(NAME(m_psw)); +} + +void hpc_device::device_reset() +{ + m_psw = 0x00; + std::fill_n(&m_core_regs[0], 6, 0x0000); +} + + +u8 hpc_device::psw_r() +{ + return m_psw; +} + +void hpc_device::psw_w(u8 data) +{ + m_psw = data; +} + + +void hpc_device::execute_run() +{ + m_icount = 0; +} + +void hpc_device::execute_set_input(int inputnum, int state) +{ + // TODO +} diff --git a/src/devices/cpu/hpc/hpc.h b/src/devices/cpu/hpc/hpc.h new file mode 100644 index 00000000000..3f1dad6be3e --- /dev/null +++ b/src/devices/cpu/hpc/hpc.h @@ -0,0 +1,73 @@ +// license:BSD-3-Clause +// copyright-holders:AJR + +#ifndef MAME_CPU_HPC_HPC_H +#define MAME_CPU_HPC_HPC_H + +#pragma once + + +class hpc_device : public cpu_device +{ +public: + enum { + HPC_PSW, + HPC_SP, + HPC_PC, + HPC_A, + HPC_K, + HPC_B, + HPC_X + }; + +protected: + // construction/destruction + hpc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, 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_memory_interface overrides + virtual space_config_vector memory_space_config() const override; + + // internal register access + u8 psw_r(); + void psw_w(u8 data); + +private: + // address space + address_space_config m_program_config; + address_space *m_program; + + // internal state + required_shared_ptr m_core_regs; + u8 m_psw; + + // execution sequencing + s32 m_icount; +}; + +class hpc46104_device : public hpc_device +{ +public: + // construction/destruction + hpc46104_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // device_disasm_interface overrides + virtual std::unique_ptr create_disassembler() override; + +private: + void internal_map(address_map &map); +}; + + +// device type declarations +DECLARE_DEVICE_TYPE(HPC46104, hpc46104_device) + +#endif // MAME_CPU_HPC_HPC_H diff --git a/src/devices/cpu/hpc/hpcdasm.cpp b/src/devices/cpu/hpc/hpcdasm.cpp new file mode 100644 index 00000000000..aee29751838 --- /dev/null +++ b/src/devices/cpu/hpc/hpcdasm.cpp @@ -0,0 +1,739 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/*************************************************************************** + + National Semiconductor HPC disassembler + + Note that though all 16-bit fields in instructions have the MSB first, + the HPC's memory organization is in fact little-endian. This is why r16 + is not used to read them. + +***************************************************************************/ + +#include "util/disasmintf.h" +#include "hpcdasm.h" + +#include "util/strformat.h" +#include + +const char *const hpc16164_disassembler::s_regs[128] = +{ + "psw", nullptr, "SP", "PC", "A", "K", "B", "X", + "enir", "irpd", "ircd", "sio", "porti", nullptr, "halten", "romdump", + "porta", "portb", nullptr, "upic", nullptr, nullptr, nullptr, nullptr, + "dira", "dirb", "bfun", nullptr, nullptr, nullptr, nullptr, nullptr, + "adcr1", "adcr2", "portd", "adcr3", nullptr, nullptr, nullptr, nullptr, + "ad0", "ad1", "ad2", "ad3", "ad4", "ad5", "ad6", "ad7", + "enu", "enui", "rbuf", "tbuf", "enur", nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + "t4", "r4", "t5", "r5", "t6", "r6", "t7", "r7", + "pwmode", "portp", nullptr, nullptr, nullptr, nullptr, "eicon", "eicr", + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + "i4cr", "i3cr", "i2cr", "r2", "t2", "r3", "t3", "divby", + "tmmode", "t0con", "watchdog", nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr +}; + +hpc_disassembler::hpc_disassembler(const char *const regs[]) + : util::disasm_interface() + , m_regs(regs) +{ +} + +u32 hpc_disassembler::opcode_alignment() const +{ + return 1; +} + +void hpc_disassembler::format_register(std::ostream &stream, u16 reg) const +{ + if (reg >= 0x00c0 && reg < 0x01c0) + { + const char *name = m_regs[(reg - 0x00c0) >> 1]; + if (name != nullptr) + { + stream << name; + if (BIT(reg, 0)) + stream << "+1"; + return; + } + } + + util::stream_format(stream, "0%X", reg); +} + +void hpc_disassembler::format_immediate_byte(std::ostream &stream, u8 data) const +{ + stream << "#"; + if (data >= 0x10) + stream << "0"; + util::stream_format(stream, "%02X", data); +} + +void hpc_disassembler::format_immediate_word(std::ostream &stream, u16 data) const +{ + stream << "#"; + if (data >= 0x1000) + stream << "0"; + util::stream_format(stream, "%04X", data); +} + +void hpc_disassembler::disassemble_op(std::ostream &stream, const char *op, u16 reg, u16 src, bool imm, bool indir, bool idx, bool w) const +{ + util::stream_format(stream, "%-8s", op); + if (idx) + stream << "A"; + else + format_register(stream, reg); + stream << ","; + if (imm) + { + if (w) + format_immediate_word(stream, src); + else + format_immediate_byte(stream, src); + } + else + { + if (idx) + util::stream_format(stream, "0%X", u16(reg)); + + if (indir) + stream << "["; + format_register(stream, src); + if (indir) + stream << "]"; + + if (w) + stream << ".w"; + else + stream << ".b"; + } +} + +void hpc_disassembler::disassemble_unary_op(std::ostream &stream, const char *op, u16 offset, u16 src, bool indir, bool idx, bool w) const +{ + util::stream_format(stream, "%-8s", op); + if (idx) + util::stream_format(stream, "0%X", offset); + + if (indir) + stream << "["; + format_register(stream, src); + if (indir) + stream << "]"; + + if (w) + { + if (src < 0x00c4 || src >= 0x00d0 || indir) + stream << ".w"; + } + else + stream << ".b"; +} + +void hpc_disassembler::disassemble_bit_op(std::ostream &stream, const char *op, u8 bit, u16 offset, u16 src, bool indir, bool idx) const +{ + if (src >= 0x00c0 && src < 0x01c0 && BIT(src, 0) && !indir && m_regs[(src - 0x00c0) >> 1] != nullptr) + { + src &= 0xfffe; + bit += 8; + } + + util::stream_format(stream, "%-8s%d,", op, bit); + + if (idx) + util::stream_format(stream, "0%X", offset); + + if (indir) + stream << "["; + format_register(stream, src); + if (indir) + stream << "]"; +} + +offs_t hpc_disassembler::disassemble(std::ostream &stream, offs_t pc, const hpc_disassembler::data_buffer &opcodes, const hpc_disassembler::data_buffer ¶ms) +{ + u8 opcode = opcodes.r8(pc); + u16 reg = REGISTER_A; + u16 src = REGISTER_B; + bool imm = false; + bool dmode = false; + bool indir = true; + bool idx = false; + bool jmp = false; + offs_t bytes = 1; + + switch (opcode) + { + 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: + jmp = true; + src = 0xffd0 + (opcode & 0x0f) * 2; + bytes = 1; + break; + + case 0x30: case 0x31: case 0x32: case 0x33: + jmp = true; + src = pc + 2 + ((opcode & 0x03) << 8 | opcodes.r8(pc + 1)); + bytes = 2; + break; + + case 0x34: case 0x35: case 0x36: case 0x37: + jmp = true; + src = pc - ((opcode & 0x03) << 8 | opcodes.r8(pc + 1)); + bytes = 2; + break; + + case 0x3f: + case 0x89: case 0x8a: + case 0xa9: case 0xaa: case 0xaf: + indir = false; + src = opcodes.r8(pc + 1); + bytes = 2; + break; + + 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: + 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: + jmp = true; + src = pc + 1 + (opcode & 0x1f); + break; + + 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: + 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: + jmp = true; + src = pc - (opcode & 0x1f); + break; + + case 0x80: case 0x82: + case 0xa0: + dmode = true; + indir = false; + if (BIT(opcode, 1)) + imm = true; + + src = opcodes.r8(pc + 1); + reg = opcodes.r8(pc + 2); + opcode = opcodes.r8(pc + 3); + bytes = 4; + break; + + case 0x84: case 0x86: + case 0xa4: + dmode = true; + indir = false; + if (BIT(opcode, 1)) + imm = true; + + src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2); + reg = opcodes.r8(pc + 3); + opcode = opcodes.r8(pc + 4); + bytes = 5; + break; + + case 0x81: case 0x83: + case 0xa1: + dmode = true; + indir = false; + if (BIT(opcode, 1)) + imm = true; + + src = opcodes.r8(pc + 1); + reg = (opcodes.r8(pc + 2) << 8) | opcodes.r8(pc + 3); + opcode = opcodes.r8(pc + 4); + bytes = 5; + break; + + case 0xa2: + idx = true; + reg = opcodes.r8(pc + 1); + src = opcodes.r8(pc + 2); + opcode = opcodes.r8(pc + 3); + bytes = 4; + break; + + case 0x85: case 0x87: + case 0xa5: + dmode = true; + indir = false; + if (BIT(opcode, 1)) + imm = true; + + src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2); + reg = (opcodes.r8(pc + 3) << 8) | opcodes.r8(pc + 4); + opcode = opcodes.r8(pc + 5); + bytes = 6; + break; + + case 0xa6: + idx = true; + reg = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2); + src = opcodes.r8(pc + 3); + opcode = opcodes.r8(pc + 4); + bytes = 5; + break; + + case 0x88: case 0x8b: case 0x8e: + case 0xa8: case 0xab: case 0xae: + indir = false; + src = opcodes.r8(pc + 1); + bytes = 2; + break; + + case 0x8c: + case 0xac: + indir = false; + src = opcodes.r8(pc + 1); + reg = opcodes.r8(pc + 2); + bytes = 3; + break; + + case 0x8d: + imm = true; + src = opcodes.r8(pc + 1); + reg = opcodes.r8(pc + 2); + bytes = 3; + break; + + case 0x8f: + src = REGISTER_X; + opcode = opcodes.r8(pc + 1); + bytes = 2; + break; + + case 0x90: case 0x91: case 0x92: case 0x93: + imm = true; + reg = 0x00c8 | ((opcode & 0x03) << 1); + src = opcodes.r8(pc + 1); + bytes = 2; + break; + + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + imm = true; + src = opcodes.r8(pc + 1); + bytes = 2; + break; + + case 0x94: + jmp = true; + src = pc + 2 + opcodes.r8(pc + 1); + bytes = 2; + break; + + case 0x95: + jmp = true; + src = pc - opcodes.r8(pc + 1); + bytes = 2; + break; + + case 0x96: + indir = false; + src = opcodes.r8(pc + 1); + opcode = opcodes.r8(pc + 2); + bytes = 3; + break; + + case 0x97: + indir = false; + imm = true; + src = opcodes.r8(pc + 1); + reg = opcodes.r8(pc + 2); + bytes = 3; + break; + + case 0xa7: + imm = true; + src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2); + reg = (opcodes.r8(pc + 3) << 8) | opcodes.r8(pc + 4); + bytes = 5; + break; + + case 0xad: + src = opcodes.r8(pc + 1); + opcode = opcodes.r8(pc + 2); + bytes = 3; + break; + + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + imm = true; + reg = 0x00c8 | ((opcode & 0x03) << 1); + src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2); + bytes = 3; + break; + + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + imm = true; + src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2); + bytes = 3; + break; + + case 0xb4: case 0xb5: + jmp = true; + src = pc + 3 + ((opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2)); + bytes = 3; + break; + + case 0xb6: + indir = false; + src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2); + opcode = opcodes.r8(pc + 3); + bytes = 4; + break; + + case 0xb7: + imm = true; + src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2); + reg = opcodes.r8(pc + 3); + bytes = 4; + break; + + case 0xd4: case 0xd5: case 0xd6: + case 0xf4: case 0xf5: case 0xf6: + src = REGISTER_X; + break; + } + + switch (opcode) + { + case 0x00: + util::stream_format(stream, "%-8sA", "clr"); + break; + + case 0x01: + util::stream_format(stream, "%-8sA", "comp"); + break; + + case 0x02: + stream << "sc"; + break; + + case 0x03: + stream << "rc"; + break; + + case 0x04: + util::stream_format(stream, "%-8sA", "inc"); + break; + + case 0x05: + util::stream_format(stream, "%-8sA", "dec"); + break; + + case 0x06: + stream << "ifnc"; + break; + + case 0x07: + stream << "ifc"; + break; + + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + disassemble_bit_op(stream, "sbit", opcode & 0x07, reg, src, indir, idx); + break; + + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + disassemble_bit_op(stream, "ifbit", opcode & 0x07, reg, src, indir, idx); + break; + + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + disassemble_bit_op(stream, "rbit", opcode & 0x07, reg, src, indir, idx); + break; + + 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: + util::stream_format(stream, "%-8s", "jsrp"); + if (jmp) + util::stream_format(stream, "[0%X]", src); + else + stream << "???"; + bytes |= STEP_OVER; + break; + + case 0x30: case 0x31: case 0x32: case 0x33: + case 0x34: case 0x35: case 0x36: case 0x37: + util::stream_format(stream, "%-8s", "jsr"); + if (jmp) + util::stream_format(stream, "0%X", src); + else + stream << "???"; + bytes |= STEP_OVER; + break; + + case 0x38: + util::stream_format(stream, "%-8sX,", "rbit"); + format_register(stream, reg); + break; + + case 0x39: + util::stream_format(stream, "%-8sX,", "sbit"); + format_register(stream, reg); + break; + + case 0x3a: + util::stream_format(stream, "%-8sX,", "ifbit"); + format_register(stream, reg); + break; + + case 0x3b: + util::stream_format(stream, "%-8sA", "swap"); + break; + + case 0x3c: + stream << "ret"; + bytes |= STEP_OUT; + break; + + case 0x3d: + stream << "retsk"; + bytes |= STEP_OUT; + break; + + case 0x3e: + stream << "reti"; + bytes |= STEP_OUT; + break; + + case 0x3f: + util::stream_format(stream, "%-8s", "pop"); + format_register(stream, src); + break; + + case 0x40: + stream << "nop"; + break; + + 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: + 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: + 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: + 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: + util::stream_format(stream, "%-8s", "jp"); + if (jmp) + util::stream_format(stream, "0%X", src); + else + stream << "???"; + break; + + case 0x88: case 0x8c: + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x97: + case 0xa8: case 0xac: + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb7: + case 0xc4: + case 0xd4: + case 0xe4: + case 0xf4: + disassemble_op(stream, "ld", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0x89: + case 0xa9: + disassemble_unary_op(stream, "inc", reg, src, indir, idx, BIT(opcode, 5)); + break; + + case 0x8a: + case 0xaa: + disassemble_unary_op(stream, "decsz", reg, src, indir, idx, BIT(opcode, 5)); + bytes |= STEP_OVER | (1 << OVERINSTSHIFT); + break; + + case 0x8b: + case 0xab: + case 0xc6: + case 0xd6: + case 0xe6: + case 0xf6: + disassemble_op(stream, dmode ? "ld" : "st", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0x8d: + util::stream_format(stream, "%-8sBK,", "ld"); + format_immediate_byte(stream, src); + stream << ","; + format_immediate_byte(stream, reg); + break; + + case 0x8e: + case 0xae: + case 0xc5: + case 0xd5: + case 0xe5: + case 0xf5: + disassemble_op(stream, "x", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0x94: case 0x95: + util::stream_format(stream, "%-8s", "jp"); + if (jmp) + util::stream_format(stream, "0%X", src); + else + stream << "???"; + break; + + case 0x98: case 0xb8: case 0xd8: case 0xf8: + disassemble_op(stream, "add", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0x99: case 0xb9: case 0xd9: case 0xf9: + disassemble_op(stream, "and", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0x9a: case 0xba: case 0xda: case 0xfa: + disassemble_op(stream, "or", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0x9b: case 0xbb: case 0xdb: case 0xfb: + disassemble_op(stream, "xor", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0x9c: case 0xbc: case 0xdc: case 0xfc: + disassemble_op(stream, "ifeq", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0x9d: case 0xbd: case 0xdd: case 0xfd: + disassemble_op(stream, "ifgt", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0x9e: case 0xbe: case 0xde: case 0xfe: + disassemble_op(stream, "mult", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0x9f: case 0xbf: case 0xdf: case 0xff: + disassemble_op(stream, "div", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0xa7: + util::stream_format(stream, "%-8sBK,", "ld"); + format_immediate_word(stream, src); + stream << ","; + format_immediate_word(stream, reg); + break; + + case 0xaf: + util::stream_format(stream, "%-8s", "push"); + format_register(stream, src); + break; + + case 0xb4: + util::stream_format(stream, "%-8s", "jmpl"); + if (jmp) + util::stream_format(stream, "0%X", src); + else + stream << "???"; + break; + + case 0xb5: + util::stream_format(stream, "%-8s", "jsrl"); + if (jmp) + util::stream_format(stream, "0%X", src); + else + stream << "???"; + bytes |= STEP_OVER; + break; + + case 0xc0: case 0xc2: + case 0xe0: case 0xe2: + util::stream_format(stream, "%-8sA,[B%c].%c", "lds", + BIT(opcode, 1) ? '-' : '+', + BIT(opcode, 5) ? 'w' : 'b'); + bytes |= STEP_OVER | (1 << OVERINSTSHIFT); + break; + + case 0xd0: case 0xd2: + case 0xf0: case 0xf2: + util::stream_format(stream, "%-8sA,[X%c].%c", "ld", + BIT(opcode, 1) ? '-' : '+', + BIT(opcode, 5) ? 'w' : 'b'); + break; + + case 0xc1: case 0xc3: + case 0xe1: case 0xe3: + util::stream_format(stream, "%-8sA,[B%c].%c", "xs", + BIT(opcode, 1) ? '-' : '+', + BIT(opcode, 5) ? 'w' : 'b'); + bytes |= STEP_OVER | (1 << OVERINSTSHIFT); + break; + + case 0xd1: case 0xd3: + case 0xf1: case 0xf3: + util::stream_format(stream, "%-8sA,[X%c].%c", "x", + BIT(opcode, 1) ? '-' : '+', + BIT(opcode, 5) ? 'w' : 'b'); + break; + + case 0xc7: case 0xe7: + util::stream_format(stream, "%-8sA", BIT(opcode, 5) ? "shl" : "shr"); + break; + + case 0xd7: case 0xf7: + util::stream_format(stream, "%-8sA", BIT(opcode, 5) ? "rlc" : "rrc"); + break; + + case 0xc8: case 0xe8: + disassemble_op(stream, "adc", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0xc9: case 0xe9: + disassemble_op(stream, "dadc", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0xca: case 0xea: + disassemble_op(stream, "dsubc", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0xcb: case 0xeb: + disassemble_op(stream, "subc", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + case 0xcc: case 0xec: + stream << "jid"; + if (BIT(opcode, 5)) + stream << "w"; + break; + + case 0xcf: case 0xef: + disassemble_op(stream, "divd", reg, src, imm, indir, idx, BIT(opcode, 5)); + break; + + default: + stream << "???"; + break; + } + + return bytes | SUPPORTED; +} diff --git a/src/devices/cpu/hpc/hpcdasm.h b/src/devices/cpu/hpc/hpcdasm.h new file mode 100644 index 00000000000..85aa4f550f1 --- /dev/null +++ b/src/devices/cpu/hpc/hpcdasm.h @@ -0,0 +1,49 @@ +// license:BSD-3-Clause +// copyright-holders:AJR + +#ifndef MAME_CPU_HPC_HPCDASM_H +#define MAME_CPU_HPC_HPCDASM_H + +#pragma once + +class hpc_disassembler : public util::disasm_interface +{ +protected: + enum : u16 + { + REGISTER_A = 0x00c8, + REGISTER_K = 0x00ca, + REGISTER_B = 0x00cc, + REGISTER_X = 0x00ce + }; + + // construction/destruction + hpc_disassembler(const char *const regs[]); + + // 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 ¶ms) override; + +private: + // internal helpers + void format_register(std::ostream &stream, u16 reg) const; + void format_immediate_byte(std::ostream &stream, u8 data) const; + void format_immediate_word(std::ostream &stream, u16 data) const; + void disassemble_op(std::ostream &stream, const char *op, u16 reg, u16 src, bool imm, bool indir, bool idx, bool w) const; + void disassemble_unary_op(std::ostream &stream, const char *op, u16 offset, u16 src, bool indir, bool idx, bool w) const; + void disassemble_bit_op(std::ostream &stream, const char *op, u8 bit, u16 offset, u16 src, bool indir, bool idx) const; + + // register names + const char *const *m_regs; +}; + +class hpc16164_disassembler : public hpc_disassembler +{ +public: + hpc16164_disassembler() : hpc_disassembler(s_regs) { } + +private: + static const char *const s_regs[128]; +}; + +#endif // MAME_CPU_HPC_HPCDASM_H diff --git a/src/mame/drivers/age_candy.cpp b/src/mame/drivers/age_candy.cpp index 331a421c7f7..5731611c7cd 100644 --- a/src/mame/drivers/age_candy.cpp +++ b/src/mame/drivers/age_candy.cpp @@ -13,6 +13,7 @@ Device is a 27c256 location U3 */ #include "emu.h" +#include "cpu/hpc/hpc.h" #include "speaker.h" @@ -21,7 +22,7 @@ class age_candy_state : public driver_device public: age_candy_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) - // ,m_maincpu(*this, "maincpu") + , m_maincpu(*this, "maincpu") { } void age_candy(machine_config &config); @@ -31,7 +32,7 @@ private: virtual void machine_reset() override; void age_candy_map(address_map &map); -// required_device m_maincpu; + required_device m_maincpu; }; static INPUT_PORTS_START( age_candy ) @@ -48,24 +49,19 @@ void age_candy_state::machine_reset() } -#ifdef UNUSED_DEFINITION void age_candy_state::age_candy_map(address_map &map) { - map(0xc000, 0xffff).rom().region("maincpu", 0x4000); + map(0x8000, 0xffff).rom().region("maincpu", 0); } -#endif -MACHINE_CONFIG_START(age_candy_state::age_candy) - - /* basic machine hardware */ -// MCFG_DEVICE_ADD("maincpu", HPC46104, 8000000) // unknown clock; HPC emulation needed -// MCFG_DEVICE_PROGRAM_MAP(age_candy_map) -// MCFG_DEVICE_IO_MAP(age_candy_io) +void age_candy_state::age_candy(machine_config &config) +{ + HPC46104(config, m_maincpu, 8000000); // unknown clock; HPC still not actually emulated + m_maincpu->set_addrmap(AS_PROGRAM, &age_candy_state::age_candy_map); /* sound hardware */ SPEAKER(config, "mono").front_center(); -MACHINE_CONFIG_END - +} ROM_START( age_cand ) diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index 432a762c028..e8bb305bfa1 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -55,6 +55,7 @@ using util::BIT; #include "cpu/hcd62121/hcd62121d.h" #include "cpu/hd61700/hd61700d.h" #include "cpu/hmcs40/hmcs40d.h" +#include "cpu/hpc/hpcdasm.h" #include "cpu/hphybrid/hphybrid_dasm.h" #include "cpu/i386/i386dasm.h" #include "cpu/i8008/8008dasm.h" @@ -360,6 +361,7 @@ static const dasm_table_entry dasm_table[] = { "hp_5061_3001", be, -1, []() -> util::disasm_interface * { return new hp_5061_3001_disassembler; } }, { "hp_5061_3011", be, -1, []() -> util::disasm_interface * { return new hp_5061_3011_disassembler; } }, { "hp_09825_67907", be, -1, []() -> util::disasm_interface * { return new hp_09825_67907_disassembler; } }, + { "hpc16164", le, 0, []() -> util::disasm_interface * { return new hpc16164_disassembler; } }, { "hyperstone", be, 0, []() -> util::disasm_interface * { return new hyperstone_disassembler(&hyperstone_unidasm); } }, { "i4004", le, 0, []() -> util::disasm_interface * { return new i4004_disassembler; } }, { "i4040", le, 0, []() -> util::disasm_interface * { return new i4040_disassembler; } }, -- cgit v1.2.3-70-g09d2 From c63cd721ffff3fa110cdc8579cbc1dbafd444603 Mon Sep 17 00:00:00 2001 From: AJR Date: Tue, 5 Mar 2019 12:45:11 -0500 Subject: hpc: Add HPC46003 type for future use (nw) - Further bit instruction disassembly adjustments (nw) --- src/devices/cpu/hpc/hpc.cpp | 20 ++++++++++++++++++++ src/devices/cpu/hpc/hpc.h | 15 +++++++++++++++ src/devices/cpu/hpc/hpcdasm.cpp | 32 ++++++++++++++++++++++++++++---- src/devices/cpu/hpc/hpcdasm.h | 9 +++++++++ src/tools/unidasm.cpp | 1 + 5 files changed, 73 insertions(+), 4 deletions(-) (limited to 'src/tools/unidasm.cpp') diff --git a/src/devices/cpu/hpc/hpc.cpp b/src/devices/cpu/hpc/hpc.cpp index cdfbe43dc1a..9d10ffbbbf9 100644 --- a/src/devices/cpu/hpc/hpc.cpp +++ b/src/devices/cpu/hpc/hpc.cpp @@ -13,9 +13,19 @@ #include "hpcdasm.h" // device type definitions +DEFINE_DEVICE_TYPE(HPC46003, hpc46003_device, "hpc46003", "HPC46003") DEFINE_DEVICE_TYPE(HPC46104, hpc46104_device, "hpc46104", "HPC46104") +void hpc46003_device::internal_map(address_map &map) +{ + map(0x0000, 0x00bf).ram(); + map(0x00c0, 0x00c0).rw(FUNC(hpc46003_device::psw_r), FUNC(hpc46003_device::psw_w)); + map(0x00c4, 0x00cf).ram().share("core_regs"); + // TODO: many other internal registers + map(0x01c0, 0x01ff).ram(); +} + void hpc46104_device::internal_map(address_map &map) { map(0x0000, 0x00bf).ram(); @@ -25,6 +35,11 @@ void hpc46104_device::internal_map(address_map &map) map(0x01c0, 0x02ff).ram(); } +std::unique_ptr hpc46003_device::create_disassembler() +{ + return std::make_unique(); +} + std::unique_ptr hpc46104_device::create_disassembler() { return std::make_unique(); @@ -41,6 +56,11 @@ hpc_device::hpc_device(const machine_config &mconfig, device_type type, const ch { } +hpc46003_device::hpc46003_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : hpc_device(mconfig, HPC46003, tag, owner, clock, address_map_constructor(FUNC(hpc46003_device::internal_map), this)) +{ +} + hpc46104_device::hpc46104_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : hpc_device(mconfig, HPC46104, tag, owner, clock, address_map_constructor(FUNC(hpc46104_device::internal_map), this)) { diff --git a/src/devices/cpu/hpc/hpc.h b/src/devices/cpu/hpc/hpc.h index 3f1dad6be3e..5f73a0ee2e6 100644 --- a/src/devices/cpu/hpc/hpc.h +++ b/src/devices/cpu/hpc/hpc.h @@ -52,6 +52,20 @@ private: s32 m_icount; }; +class hpc46003_device : public hpc_device +{ +public: + // construction/destruction + hpc46003_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // device_disasm_interface overrides + virtual std::unique_ptr create_disassembler() override; + +private: + void internal_map(address_map &map); +}; + class hpc46104_device : public hpc_device { public: @@ -68,6 +82,7 @@ private: // device type declarations +DECLARE_DEVICE_TYPE(HPC46003, hpc46003_device) DECLARE_DEVICE_TYPE(HPC46104, hpc46104_device) #endif // MAME_CPU_HPC_HPC_H diff --git a/src/devices/cpu/hpc/hpcdasm.cpp b/src/devices/cpu/hpc/hpcdasm.cpp index 263cdadb6f1..54cec15e627 100644 --- a/src/devices/cpu/hpc/hpcdasm.cpp +++ b/src/devices/cpu/hpc/hpcdasm.cpp @@ -16,6 +16,26 @@ #include "util/strformat.h" #include +const char *const hpc16083_disassembler::s_regs[128] = +{ + "psw", nullptr, "SP", "PC", "A", "K", "B", "X", + "enir", "irpd", "ircd", "sio", "porti", nullptr, "halten", nullptr, + "porta", "portb", nullptr, "upic", nullptr, nullptr, nullptr, nullptr, + "dira", "dirb", "bfun", nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, "portd", nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + "enu", "enui", "rbuf", "tbuf", "enur", nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + "t4", "r4", "t5", "r5", "t6", "r6", "t7", "r7", + "pwmode", "portp", nullptr, nullptr, nullptr, nullptr, "eicon", "eicr", + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + "i4cr", "i3cr", "i2cr", "r2", "t2", "r3", "t3", "divby", + "tmmode", "t0con", "watchdog", nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr +}; + const char *const hpc16164_disassembler::s_regs[128] = { "psw", nullptr, "SP", "PC", "A", "K", "B", "X", @@ -151,7 +171,7 @@ void hpc_disassembler::disassemble_bit_op(std::ostream &stream, const char *op, stream << "["; format_register(stream, src); if (indir) - stream << "]"; + stream << "].b"; } offs_t hpc_disassembler::disassemble(std::ostream &stream, offs_t pc, const hpc_disassembler::data_buffer &opcodes, const hpc_disassembler::data_buffer ¶ms) @@ -189,6 +209,10 @@ offs_t hpc_disassembler::disassemble(std::ostream &stream, offs_t pc, const hpc_ bytes = 2; break; + case 0x38: case 0x39: case 0x3a: + reg = REGISTER_X; + break; + case 0x3f: case 0x89: case 0x8a: case 0xa9: case 0xaa: case 0xaf: @@ -483,15 +507,15 @@ offs_t hpc_disassembler::disassemble(std::ostream &stream, offs_t pc, const hpc_ break; case 0x38: - util::stream_format(stream, "%-8sX,[B]", "rbit"); + disassemble_op(stream, "rbit", reg, src, imm, indir, idx, false); break; case 0x39: - util::stream_format(stream, "%-8sX,[B]", "sbit"); + disassemble_op(stream, "sbit", reg, src, imm, indir, idx, false); break; case 0x3a: - util::stream_format(stream, "%-8sX,[B]", "ifbit"); + disassemble_op(stream, "ifbit", reg, src, imm, indir, idx, false); break; case 0x3b: diff --git a/src/devices/cpu/hpc/hpcdasm.h b/src/devices/cpu/hpc/hpcdasm.h index 85aa4f550f1..ed57c6b1a35 100644 --- a/src/devices/cpu/hpc/hpcdasm.h +++ b/src/devices/cpu/hpc/hpcdasm.h @@ -37,6 +37,15 @@ private: const char *const *m_regs; }; +class hpc16083_disassembler : public hpc_disassembler +{ +public: + hpc16083_disassembler() : hpc_disassembler(s_regs) { } + +private: + static const char *const s_regs[128]; +}; + class hpc16164_disassembler : public hpc_disassembler { public: diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index e8bb305bfa1..81b9f448140 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -361,6 +361,7 @@ static const dasm_table_entry dasm_table[] = { "hp_5061_3001", be, -1, []() -> util::disasm_interface * { return new hp_5061_3001_disassembler; } }, { "hp_5061_3011", be, -1, []() -> util::disasm_interface * { return new hp_5061_3011_disassembler; } }, { "hp_09825_67907", be, -1, []() -> util::disasm_interface * { return new hp_09825_67907_disassembler; } }, + { "hpc16083", le, 0, []() -> util::disasm_interface * { return new hpc16083_disassembler; } }, { "hpc16164", le, 0, []() -> util::disasm_interface * { return new hpc16164_disassembler; } }, { "hyperstone", be, 0, []() -> util::disasm_interface * { return new hyperstone_disassembler(&hyperstone_unidasm); } }, { "i4004", le, 0, []() -> util::disasm_interface * { return new i4004_disassembler; } }, -- cgit v1.2.3-70-g09d2 From 9e122168ef4fdbb9158bc8a4fd0e5e86900496f0 Mon Sep 17 00:00:00 2001 From: Nigel Barnes Date: Sat, 23 Mar 2019 11:55:09 +0000 Subject: ns32000: Skeleton CPU device with disassembler for NS32000 family. bbc: Added preliminary Acorn 32016 2nd Processor, incomplete CPU emulation. --- scripts/src/bus.lua | 2 + scripts/src/cpu.lua | 17 + scripts/target/mame/mess.lua | 1 + src/devices/bus/bbc/tube/tube.cpp | 12 +- src/devices/bus/bbc/tube/tube_32016.cpp | 210 ++++++++ src/devices/bus/bbc/tube/tube_32016.h | 71 +++ src/devices/cpu/ns32000/ns32000.cpp | 160 ++++++ src/devices/cpu/ns32000/ns32000.h | 149 ++++++ src/devices/cpu/ns32000/ns32000dasm.cpp | 834 ++++++++++++++++++++++++++++++++ src/devices/cpu/ns32000/ns32000dasm.h | 118 +++++ src/tools/unidasm.cpp | 2 + 11 files changed, 1571 insertions(+), 5 deletions(-) create mode 100644 src/devices/bus/bbc/tube/tube_32016.cpp create mode 100644 src/devices/bus/bbc/tube/tube_32016.h create mode 100644 src/devices/cpu/ns32000/ns32000.cpp create mode 100644 src/devices/cpu/ns32000/ns32000.h create mode 100644 src/devices/cpu/ns32000/ns32000dasm.cpp create mode 100644 src/devices/cpu/ns32000/ns32000dasm.h (limited to 'src/tools/unidasm.cpp') diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index d846e8b6abd..14130a37ae7 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -409,6 +409,8 @@ if (BUSES["BBC_TUBE"]~=null) then files { MAME_DIR .. "src/devices/bus/bbc/tube/tube.cpp", MAME_DIR .. "src/devices/bus/bbc/tube/tube.h", + MAME_DIR .. "src/devices/bus/bbc/tube/tube_32016.cpp", + MAME_DIR .. "src/devices/bus/bbc/tube/tube_32016.h", MAME_DIR .. "src/devices/bus/bbc/tube/tube_6502.cpp", MAME_DIR .. "src/devices/bus/bbc/tube/tube_6502.h", MAME_DIR .. "src/devices/bus/bbc/tube/tube_80186.cpp", diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index e8084e2a362..8c461e0ce16 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -2835,3 +2835,20 @@ if (CPUS["MEG"]~=null or _OPTIONS["with-tools"]) then table.insert(disasm_files , MAME_DIR .. "src/devices/sound/megd.cpp") table.insert(disasm_files , MAME_DIR .. "src/devices/sound/megd.h") end + +-------------------------------------------------- +-- National Semiconductor NS32000 series +--@src/devices/cpu/ns32000/ns32000.h,CPUS["NS32000"] = true +-------------------------------------------------- + +if (CPUS["NS32000"]~=null) then + files { + MAME_DIR .. "src/devices/cpu/ns32000/ns32000.cpp", + MAME_DIR .. "src/devices/cpu/ns32000/ns32000.h", + } +end + +if (CPUS["NS32000"]~=null or _OPTIONS["with-tools"]) then + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/ns32000/ns32000dasm.cpp") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/ns32000/ns32000dasm.h") +end diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index bfe03e65404..d957b76c9b9 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -137,6 +137,7 @@ CPUS["NANOPROCESSOR"] = true CPUS["CLIPPER"] = true CPUS["CAPRICORN"] = true CPUS["ALPHA"] = true +CPUS["NS32000"] = true --CPUS["DSPP"] = true CPUS["HPC"] = true CPUS["MEG"] = true diff --git a/src/devices/bus/bbc/tube/tube.cpp b/src/devices/bus/bbc/tube/tube.cpp index c0ff49915a6..602ea3c845a 100644 --- a/src/devices/bus/bbc/tube/tube.cpp +++ b/src/devices/bus/bbc/tube/tube.cpp @@ -112,6 +112,7 @@ void bbc_tube_slot_device::host_w(offs_t offset, uint8_t data) // slot devices +#include "tube_32016.h" #include "tube_6502.h" #include "tube_80186.h" #include "tube_80286.h" @@ -133,7 +134,7 @@ void bbc_tube_devices(device_slot_interface &device) { device.option_add("6502", BBC_TUBE_6502); /* Acorn ANC01 6502 2nd processor */ device.option_add("z80", BBC_TUBE_Z80); /* Acorn ANC04 Z80 2nd processor */ - //device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */ + device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */ device.option_add("arm", BBC_TUBE_ARM); /* Acorn ANC13 ARM Evaluation System */ device.option_add("80286", BBC_TUBE_80286); /* Acorn 80286 2nd Processor */ //device.option_add("a500", BBC_TUBE_A500); /* Acorn A500 2nd Processor */ @@ -142,8 +143,8 @@ void bbc_tube_devices(device_slot_interface &device) //device.option_add("hdp68k", BBC_TUBE_HDP68K); /* Torch Unicorn (HDP68K) */ //device.option_add("x25", BBC_TUBE_X25); /* Econet X25 Gateway */ device.option_add("zep100", BBC_TUBE_ZEP100); /* Torch Z80 Communicator (ZEP100) (Torch) */ - //device.option_add("zep100l", BBC_TUBE_ZEP100L); /* Torch Z80 Communicator (ZEP100) (Acorn 8271) */ - //device.option_add("zep100w", BBC_TUBE_ZEP100W); /* Torch Z80 Communicator (ZEP100) (Acorn 1770) */ + //device.option_add("zep100l", BBC_TUBE_ZEP100L); /* Torch Z80 Communicator (ZEP100) (Model B) */ + //device.option_add("zep100w", BBC_TUBE_ZEP100W); /* Torch Z80 Communicator (ZEP100) (Model B+) */ /* Acorn ANC21 Universal 2nd Processor Unit */ device.option_add("65c102", BBC_TUBE_65C102); /* Acorn ADC06 65C102 co-processor */ device.option_add("80186", BBC_TUBE_80186); /* Acorn ADC08 80186 co-processor */ @@ -160,11 +161,12 @@ void bbc_extube_devices(device_slot_interface &device) { device.option_add("6502", BBC_TUBE_6502); /* Acorn ANC01 6502 2nd processor */ device.option_add("z80", BBC_TUBE_Z80); /* Acorn ANC04 Z80 2nd processor */ - //device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */ + device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */ device.option_add("arm", BBC_TUBE_ARM); /* Acorn ANC13 ARM Evaluation System */ device.option_add("80286", BBC_TUBE_80286); /* Acorn 80286 2nd Processor */ //device.option_add("a500", BBC_TUBE_A500); /* Acorn A500 2nd Processor */ //device.option_add("pmsb2p", BBC_TUBE_PMSB2P); /* PMS B2P-6502 */ + //device.option_add("zep100m", BBC_TUBE_ZEP100M); /* Torch Z80 Communicator (ZEP100) (Master) */ /* Acorn ANC21 Universal 2nd Processor Unit */ device.option_add("65c102", BBC_TUBE_65C102); /* Acorn ADC06 65C102 co-processor */ device.option_add("80186", BBC_TUBE_80186); /* Acorn ADC08 80186 co-processor */ @@ -181,7 +183,6 @@ void bbc_intube_devices(device_slot_interface &device) { device.option_add("65c102", BBC_TUBE_65C102); /* Acorn ADC06 65C102 co-processor */ device.option_add("80186", BBC_TUBE_80186); /* Acorn ADC08 80186 co-processor */ - //device.option_add("zep100m", BBC_TUBE_ZEP100M); /* Torch Z80 Communicator (ZEP100) (Master) */ //device.option_add("arm7", BBC_TUBE_ARM7); /* Sprow ARM7 co-processor */ device.option_add("rc6502", BBC_TUBE_RC6502); /* ReCo6502 (6502) */ device.option_add("rc65816", BBC_TUBE_RC65816); /* ReCo6502 (65816) */ @@ -196,6 +197,7 @@ void electron_tube_devices(device_slot_interface &device) { device.option_add("6502", BBC_TUBE_6502); /* Acorn ANC01 6502 2nd processor */ device.option_add("z80", BBC_TUBE_Z80); /* Acorn ANC04 Z80 2nd processor */ + device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */ device.option_add("arm", BBC_TUBE_ARM); /* Acorn ANC13 ARM Evaluation System */ device.option_add("65c102", BBC_TUBE_65C102); /* Acorn ADC06 65C102 co-processor */ device.option_add("80186", BBC_TUBE_80186); /* Acorn ADC08 80186 co-processor */ diff --git a/src/devices/bus/bbc/tube/tube_32016.cpp b/src/devices/bus/bbc/tube/tube_32016.cpp new file mode 100644 index 00000000000..7b6ac355e42 --- /dev/null +++ b/src/devices/bus/bbc/tube/tube_32016.cpp @@ -0,0 +1,210 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + Acorn ANC05 32016 2nd processor + + http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANC05_320162ndproc.html + + Acorn ANC06 Cambridge Co-Processor + + http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANC06_CamCoPro.html + + IC1 (ULA) TUBE + IC2 (MMU) NS32082 Not fitted + IC3 (CPU) NS32016 + IC4 (TCU) NS32201 + IC20 (FPU) NS32081 + +**********************************************************************/ + + +#include "emu.h" +#include "tube_32016.h" +#include "softlist_dev.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(BBC_TUBE_32016, bbc_tube_32016_device, "bbc_tube_32016", "Acorn 32016 2nd processor") + + +//------------------------------------------------- +// ADDRESS_MAP( tube_32016_mem ) +//------------------------------------------------- + +void bbc_tube_32016_device::tube_32016_mem(address_map &map) +{ + map(0x000000, 0xffffff).rw(FUNC(bbc_tube_32016_device::read), FUNC(bbc_tube_32016_device::write)); + map(0xf90000, 0xf90001).portr("CONFIG"); + map(0xfffff0, 0xffffff).rw("ula", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w)).umask32(0x00ff); +} + +//------------------------------------------------- +// ROM( tube_32016 ) +//------------------------------------------------- + +ROM_START(tube_32016) + ROM_REGION(0x8000, "rom", 0) + ROM_DEFAULT_BIOS("200") + ROM_SYSTEM_BIOS(0, "200", "Pandora v2.00") + ROMX_LOAD("pan200lo.rom", 0x0000, 0x4000, CRC(b1980fd0) SHA1(8084f8896cd22953abefbd43c51e1a422b30e28d), ROM_SKIP(1) | ROM_BIOS(0)) // 0201-764-02 Pandora Lo + ROMX_LOAD("pan200hi.rom", 0x0001, 0x4000, CRC(cab98d6b) SHA1(dfad1f4180c50757a74fcfe3a0ee7d7b48eb1bee), ROM_SKIP(1) | ROM_BIOS(0)) // 0201-763-02 Pandora Hi + ROM_SYSTEM_BIOS(1, "100", "Pandora v1.00") + ROMX_LOAD("pan100.rom", 0x0000, 0x8000, BAD_DUMP CRC(75333006) SHA1(996cd120103039390c9b979b16c327bb95da72e4), ROM_BIOS(1)) // 0201-763-01, 0201-764-01 Pandora + ROM_SYSTEM_BIOS(2, "061", "Pandora v0.61") + ROMX_LOAD("pan061lo.rom", 0x0000, 0x4000, CRC(6f801b35) SHA1(ce31f7c10603f3d15a06a8e32bde40df0639e446), ROM_SKIP(1) | ROM_BIOS(2)) + ROMX_LOAD("pan061hi.rom", 0x0001, 0x4000, CRC(c00b1ab0) SHA1(e6a705232278c518340ddc69ea51af91965fa332), ROM_SKIP(1) | ROM_BIOS(2)) +ROM_END + +//------------------------------------------------- +// INPUT_PORTS( tube_32016 ) +//------------------------------------------------- + +static INPUT_PORTS_START(tube_32016) + PORT_START("CONFIG") + PORT_DIPNAME(0x80, 0x80, "H") PORT_DIPLOCATION("LKS:1") + PORT_DIPSETTING(0x80, "FPU") + PORT_DIPSETTING(0x00, "No FPU") + + PORT_DIPNAME(0x40, 0x00, "G") PORT_DIPLOCATION("LKS:2") + PORT_DIPSETTING(0x40, "MMU") + PORT_DIPSETTING(0x00, "No MMU") + + PORT_DIPNAME(0x20, 0x00, "F") PORT_DIPLOCATION("LKS:3") + PORT_DIPSETTING(0x20, "Reserved") + PORT_DIPSETTING(0x00, "Reserved") + + PORT_DIPNAME(0x10, 0x00, "E") PORT_DIPLOCATION("LKS:4") + PORT_DIPSETTING(0x10, "Reserved") + PORT_DIPSETTING(0x00, "Reserved") + + PORT_DIPNAME(0x08, 0x00, "D") PORT_DIPLOCATION("LKS:5") + PORT_DIPSETTING(0x08, "Reserved") + PORT_DIPSETTING(0x00, "Reserved") + + PORT_DIPNAME(0x04, 0x00, "C") PORT_DIPLOCATION("LKS:6") + PORT_DIPSETTING(0x04, "Reserved") + PORT_DIPSETTING(0x00, "Reserved") + + PORT_DIPNAME(0x02, 0x00, "B") PORT_DIPLOCATION("LKS:7") + PORT_DIPSETTING(0x02, "Reserved") + PORT_DIPSETTING(0x00, "Reserved") + + PORT_DIPNAME(0x01, 0x00, "A") PORT_DIPLOCATION("LKS:8") + PORT_DIPSETTING(0x01, "Reserved") + PORT_DIPSETTING(0x00, "Reserved") +INPUT_PORTS_END + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void bbc_tube_32016_device::device_add_mconfig(machine_config &config) +{ + NS32016(config, m_maincpu, 12_MHz_XTAL / 2); + m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_32016_device::tube_32016_mem); + + TUBE(config, m_ula); + m_ula->pnmi_handler().set_inputline(m_maincpu, INPUT_LINE_NMI); + m_ula->pirq_handler().set_inputline(m_maincpu, INPUT_LINE_IRQ0); + + /* internal ram */ + RAM(config, m_ram).set_default_size("1M").set_default_value(0); + + /* software lists */ + SOFTWARE_LIST(config, "flop_ls_32016").set_original("bbc_flop_32016"); +} + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const tiny_rom_entry *bbc_tube_32016_device::device_rom_region() const +{ + return ROM_NAME( tube_32016 ); +} + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor bbc_tube_32016_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( tube_32016 ); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// bbc_tube_32016_device - constructor +//------------------------------------------------- + +bbc_tube_32016_device::bbc_tube_32016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, BBC_TUBE_32016, tag, owner, clock) + , device_bbc_tube_interface(mconfig, *this) + , m_maincpu(*this, "maincpu") + , m_ula(*this, "ula") + , m_ram(*this, "ram") + , m_rom(*this, "rom") + , m_rom_enabled(true) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void bbc_tube_32016_device::device_start() +{ +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void bbc_tube_32016_device::device_reset() +{ + m_rom_enabled = true; +} + + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +uint8_t bbc_tube_32016_device::host_r(offs_t offset) +{ + return m_ula->host_r(offset); +} + +void bbc_tube_32016_device::host_w(offs_t offset, uint8_t data) +{ + m_ula->host_w(offset, data); +} + + +READ8_MEMBER(bbc_tube_32016_device::read) +{ + uint16_t data = 0xffff; + + if (m_rom_enabled) + data = m_rom->base()[offset & 0x3fff]; + else if (offset < m_ram->size()) + data = m_ram->pointer()[offset]; + + return data; +} + +WRITE8_MEMBER(bbc_tube_32016_device::write) +{ + /* clear ROM select on first write */ + if (!machine().side_effects_disabled()) m_rom_enabled = false; + + if (offset < m_ram->size()) + m_ram->pointer()[offset] = data; +} diff --git a/src/devices/bus/bbc/tube/tube_32016.h b/src/devices/bus/bbc/tube/tube_32016.h new file mode 100644 index 00000000000..864b8173703 --- /dev/null +++ b/src/devices/bus/bbc/tube/tube_32016.h @@ -0,0 +1,71 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + Acorn ANC05 32016 2nd processor + + http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANC05_320162ndproc.html + + Acorn ANC06 Cambridge Co-Processor + + http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANC06_CamCoPro.html + +**********************************************************************/ + + +#ifndef MAME_BUS_BBC_TUBE_32016_H +#define MAME_BUS_BBC_TUBE_32016_H + +#include "tube.h" +#include "cpu/ns32000/ns32000.h" +#include "machine/ram.h" +#include "machine/tube.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> bbc_tube_32016_device + +class bbc_tube_32016_device : + public device_t, + public device_bbc_tube_interface +{ +public: + // construction/destruction + bbc_tube_32016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; + + virtual uint8_t host_r(offs_t offset) override; + virtual void host_w(offs_t offset, uint8_t data) override; + +private: + required_device m_maincpu; + required_device m_ula; + required_device m_ram; + required_memory_region m_rom; + + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); + + void tube_32016_mem(address_map &map); + + bool m_rom_enabled; +}; + + + +// device type definition +DECLARE_DEVICE_TYPE(BBC_TUBE_32016, bbc_tube_32016_device) + + +#endif /* MAME_BUS_BBC_TUBE_32016_H */ diff --git a/src/devices/cpu/ns32000/ns32000.cpp b/src/devices/cpu/ns32000/ns32000.cpp new file mode 100644 index 00000000000..6596d28f8dd --- /dev/null +++ b/src/devices/cpu/ns32000/ns32000.cpp @@ -0,0 +1,160 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/***************************************************************************** +* +* ns32000.cpp +* +* NS32000 CPU family +* +*****************************************************************************/ + +#include "emu.h" +#include "ns32000.h" +#include "ns32000dasm.h" +#include "debugger.h" + +//************************************************************************** +// DEVICE INTERFACE +//************************************************************************** + +DEFINE_DEVICE_TYPE(NS32008, ns32008_cpu_device, "ns32008", "National Semiconductor NS32008") +DEFINE_DEVICE_TYPE(NS32016, ns32016_cpu_device, "ns32016", "National Semiconductor NS32016") +DEFINE_DEVICE_TYPE(NS32032, ns32032_cpu_device, "ns32032", "National Semiconductor NS32032") + + +//------------------------------------------------- +// ns32000_cpu_device - constructor +//------------------------------------------------- + +ns32000_cpu_device::ns32000_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int databits, int addrbits) + : cpu_device(mconfig, type, tag, owner, clock) + , m_program_config("program", ENDIANNESS_LITTLE, databits, addrbits, 0) + , m_icount(0) +{ +} + +ns32008_cpu_device::ns32008_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : ns32000_cpu_device(mconfig, NS32008, tag, owner, clock, 8, 24) +{ +} + +ns32016_cpu_device::ns32016_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : ns32000_cpu_device(mconfig, NS32016, tag, owner, clock, 16, 24) +{ +} + +ns32032_cpu_device::ns32032_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : ns32000_cpu_device(mconfig, NS32032, tag, owner, clock, 32, 24) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void ns32000_cpu_device::device_start() +{ + set_icountptr(m_icount); + + save_item(NAME(m_pc)); + save_item(NAME(m_r)); + save_item(NAME(m_f)); + + state_add(STATE_GENPC, "GENPC", m_pc).noshow(); + state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow(); + + // dedicated registers + state_add(NS32000_PC, "PC", m_pc); + state_add(NS32000_SB, "SB", m_sb); + state_add(NS32000_FP, "FP", m_fp); + state_add(NS32000_SP1, "SP1", m_sp1); + state_add(NS32000_SP0, "SP0", m_sp0); + state_add(NS32000_INTBASE, "INTBASE", m_intbase); + state_add(NS32000_PSR, "PSR", m_psr); + state_add(NS32000_MOD, "MOD", m_mod); + + // general registers + for (unsigned i = 0; i < 8; i++) + state_add(NS32000_R0 + i, util::string_format("R%d", i).c_str(), m_r[i]); + + // floating point registers + //for (unsigned i = 0; i < 8; i++) + // state_add(NS32000_R7 + i, util::string_format("F%d", i).c_str(), m_f[i]); + + // set our instruction counter + //set_icountptr(m_icount); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void ns32000_cpu_device::device_reset() +{ + m_nmi_line = false; + m_irq_line = false; + + m_pc = 0; +} + +//------------------------------------------------- +// execute_run - execute a timeslice's worth of +// opcodes +//------------------------------------------------- + +void ns32000_cpu_device::execute_run() +{ + while (m_icount > 0) + { + debugger_instruction_hook(m_pc); + + m_icount--; + } +} + +//------------------------------------------------- +// execute_set_input - act on a changed input/ +// interrupt line +//------------------------------------------------- + +void ns32000_cpu_device::execute_set_input(int inputnum, int state) +{ + switch (inputnum) + { + case INPUT_LINE_NMI: + // NMI is edge triggered + m_nmi_line = m_nmi_line || (state == ASSERT_LINE); + break; + + case INPUT_LINE_IRQ0: + // IRQ is line triggered + m_irq_line = state == ASSERT_LINE; + break; + } +} + +//------------------------------------------------- +// memory_space_config - return the configuration +// of the specified address space, or nullptr if +// the space doesn't exist +//------------------------------------------------- + +device_memory_interface::space_config_vector ns32000_cpu_device::memory_space_config() const +{ + return space_config_vector{ std::make_pair(AS_PROGRAM, &m_program_config) }; +} + +bool ns32000_cpu_device::memory_translate(int spacenum, int intention, offs_t &address) +{ + return true; +} + +//------------------------------------------------- +// disassemble - call the disassembly +// helper function +//------------------------------------------------- + +std::unique_ptr ns32000_cpu_device::create_disassembler() +{ + return std::make_unique(); +} diff --git a/src/devices/cpu/ns32000/ns32000.h b/src/devices/cpu/ns32000/ns32000.h new file mode 100644 index 00000000000..7b17cafba99 --- /dev/null +++ b/src/devices/cpu/ns32000/ns32000.h @@ -0,0 +1,149 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/***************************************************************************** +* +* ns32000.h +* +* NS32000 CPU family +* +*****************************************************************************/ + +#ifndef MAME_CPU_NS32016_NS32016_H +#define MAME_CPU_NS32016_NS32016_H + +#pragma once + + +/*********************************************************************** + CONSTANTS +***********************************************************************/ + + + +/*********************************************************************** + TYPE DEFINITIONS +***********************************************************************/ + +class ns32000_cpu_device : public cpu_device +{ +public: + // construction/destruction + ns32000_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); + +protected: + ns32000_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int databits, int addrbits); + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_execute_interface overrides + virtual u32 execute_min_cycles() const override { return 1; } + virtual u32 execute_max_cycles() const override { return 6; } + virtual u32 execute_input_lines() const override { return 2; } + virtual void execute_run() override; + virtual void execute_set_input(int inputnum, int state) override; + virtual bool execute_input_edge_triggered(int inputnum) const override { return inputnum == INPUT_LINE_NMI; } + + + // device_memory_interface overrides + virtual space_config_vector memory_space_config() const override; + virtual bool memory_translate(int spacenum, int intention, offs_t &address) override; + + // device_disasm_interface overrides + virtual std::unique_ptr create_disassembler() override; + + // addressing modes + enum + { + ADDRESSING_MODE_REGISTER_0 = 0, + ADDRESSING_MODE_REGISTER_1, + ADDRESSING_MODE_REGISTER_2, + ADDRESSING_MODE_REGISTER_3, + ADDRESSING_MODE_REGISTER_4, + ADDRESSING_MODE_REGISTER_5, + ADDRESSING_MODE_REGISTER_6, + ADDRESSING_MODE_REGISTER_7, + ADDRESSING_MODE_REGISTER_0_RELATIVE, + ADDRESSING_MODE_REGISTER_1_RELATIVE, + ADDRESSING_MODE_REGISTER_2_RELATIVE, + ADDRESSING_MODE_REGISTER_3_RELATIVE, + ADDRESSING_MODE_REGISTER_4_RELATIVE, + ADDRESSING_MODE_REGISTER_5_RELATIVE, + ADDRESSING_MODE_REGISTER_6_RELATIVE, + ADDRESSING_MODE_REGISTER_7_RELATIVE, + ADDRESSING_MODE_FRAME_MEMORY_RELATIVE, + ADDRESSING_MODE_STACK_MEMORY_RELATIVE, + ADDRESSING_MODE_STATIC_MEMORY_RELATIVE, + ADDRESSING_MODE_RESERVED, + ADDRESSING_MODE_IMMEDIATE, + ADDRESSING_MODE_ABSOLUTE, + ADDRESSING_MODE_EXTERNAL, + ADDRESSING_MODE_TOP_OF_STACK, + ADDRESSING_MODE_FRAME_MEMORY, + ADDRESSING_MODE_STACK_MEMORY, + ADDRESSING_MODE_STATIC_MEMORY, + ADDRESSING_MODE_PROGRAM_MEMORY, + ADDRESSING_MODE_INDEX_BYTES, + ADDRESSING_MODE_INDEX_WORDS, + ADDRESSING_MODE_INDEX_DOUBLE_WORDS, + ADDRESSING_MODE_INDEX_QUAD_WORDS, + }; + + // registers + enum + { + NS32000_PC = 1, + NS32000_SB, NS32000_FP, NS32000_SP1, NS32000_SP0, NS32000_INTBASE, NS32000_PSR, NS32000_MOD, + NS32000_R0, NS32000_R1, NS32000_R2, NS32000_R3, NS32000_R4, NS32000_R5, NS32000_R6, NS32000_R7, + }; + +private: + // configuration + address_space_config m_program_config; + + // emulation state + int m_icount; + + u32 m_pc; + u32 m_sb; + u32 m_fp; + u32 m_sp1; + u32 m_sp0; + u32 m_intbase; + u32 m_psr; + u32 m_mod; + u32 m_r[8]; + u32 m_f[8]; + + u8 m_irq_line; + u8 m_nmi_line; +}; + +class ns32008_cpu_device : public ns32000_cpu_device +{ +public: + ns32008_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + +class ns32016_cpu_device : public ns32000_cpu_device +{ +public: + ns32016_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + +class ns32032_cpu_device : public ns32000_cpu_device +{ +public: + ns32032_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + +/*********************************************************************** + DEVICE TYPE DECLARATIONS +***********************************************************************/ + +DECLARE_DEVICE_TYPE(NS32008, ns32008_cpu_device) +DECLARE_DEVICE_TYPE(NS32016, ns32016_cpu_device) +DECLARE_DEVICE_TYPE(NS32032, ns32032_cpu_device) + +#endif // MAME_CPU_NS32016_NS32016_H diff --git a/src/devices/cpu/ns32000/ns32000dasm.cpp b/src/devices/cpu/ns32000/ns32000dasm.cpp new file mode 100644 index 00000000000..983abefdd3e --- /dev/null +++ b/src/devices/cpu/ns32000/ns32000dasm.cpp @@ -0,0 +1,834 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/***************************************************************************** +* +* ns32000dasm.cpp +* +* NS32000 CPU Disassembly +* +*****************************************************************************/ + +#include "emu.h" +#include "ns32000dasm.h" + +// instruction field extraction +#define Format0cond(x) ((x >> 4) & 0x0f) + +#define Format1op(x) ((x >> 4) & 0x0f) + +#define Format2i(x) ((x >> 0) & 0x03) +#define Format2op(x) ((x >> 4) & 0x07) +#define Format2short(x) ((x >> 7) & 0x0f) +#define Format2gen(x) ((x >> 11) & 0x1f) + +#define Format3i(x) ((x >> 0) & 0x03) +#define Format3op(x) ((x >> 7) & 0x0f) +#define Format3gen(x) ((x >> 11) & 0x1f) + +#define Format4i(x) ((x >> 0) & 0x03) +#define Format4op(x) ((x >> 2) & 0x0f) +#define Format4gen2(x) ((x >> 6) & 0x1f) +#define Format4gen1(x) ((x >> 11) & 0x1f) + +#define Format5i(x) ((x >> 8) & 0x03) +#define Format5op(x) ((x >> 10) & 0x07) +#define Format5short(x) ((x >> 15) & 0x0f) + +#define Format6i(x) ((x >> 8) & 0x03) +#define Format6op(x) ((x >> 10) & 0x0f) +#define Format6gen2(x) ((x >> 14) & 0x1f) +#define Format6gen1(x) ((x >> 19) & 0x1f) + +#define Format7i(x) ((x >> 8) & 0x03) +#define Format7op(x) ((x >> 10) & 0x0f) +#define Format7gen2(x) ((x >> 14) & 0x1f) +#define Format7gen1(x) ((x >> 19) & 0x1f) + +#define Format8i(x) ((x >> 8) & 0x03) +#define Format8op(x) (((x >> 8) & 0x04) | ((x >> 6) & 0x03)) +#define Format8reg(x) ((x >> 11) & 0x07) +#define Format8gen2(x) ((x >> 14) & 0x1f) +#define Format8gen1(x) ((x >> 19) & 0x1f) + +#define Format9i(x) ((x >> 8) & 0x03) +#define Format9f(x) ((x >> 10) & 0x01) +#define Format9op(x) ((x >> 11) & 0x07) +#define Format9gen2(x) ((x >> 14) & 0x1f) +#define Format9gen1(x) ((x >> 19) & 0x1f) + +#define Format11f(x) ((x >> 8) & 0x01) +#define Format11op(x) ((x >> 10) & 0x0f) +#define Format11gen2(x) ((x >> 14) & 0x1f) +#define Format11gen1(x) ((x >> 19) & 0x1f) + +#define Format14i(x) ((x >> 8) & 0x01) +#define Format14op(x) ((x >> 10) & 0x0f) +#define Format14short(x) ((x >> 15) & 0x1f) +#define Format14gen1(x) ((x >> 19) & 0x1f) + +// instructions +const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format0_op[1] = +{ + { "Bcond", DISP, 0, 0, 0, 0 } +}; +const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format1_op[16] = +{ + { "BSR", DISP, 0, 0, 0, STEP_OVER }, + { "RET", DISP, 0, 0, 0, STEP_OUT }, + { "CXP", DISP, 0, 0, 0, STEP_OVER }, + { "RXP", DISP, 0, 0, 0, STEP_OUT }, + { "RETT", 0, 0, 0, 0, STEP_OUT }, + { "RETI", DISP, 0, 0, 0, STEP_OUT }, + { "SAVE", IMM, 0, 0, 0, 0 }, + { "RESTORE", IMM, 0, 0, 0, 0 }, + { "ENTER", IMM, DISP, 0, 0, 0 }, + { "EXIT", IMM, 0, 0, 0, 0 }, + { "NOP", 0, 0, 0, 0, 0 }, + { "WAIT", 0, 0, 0, 0, 0 }, + { "DIA", 0, 0, 0, 0, 0 }, + { "FLAG", 0, 0, 0, 0, 0 }, + { "SVC", 0, 0, 0, 0, 0 }, + { "BPT", 0, 0, 0, 0, 0 }, +}; +const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format2_op[8] = +{ + { "ADDQi", QUICK, GEN | RMW | I, 0, 0, 0 }, + { "CMPQi", QUICK, GEN | READ | I, 0, 0, 0 }, + { "SPRi", SHORT, GEN | WRITE | I, 0, 0, 0 }, + { "Scondi", GEN | WRITE | I, 0, 0, 0, 0 }, + { "ACBi", QUICK, GEN | RMW | I, DISP, 0, 0 }, + { "MOVQi", QUICK, GEN | WRITE | I, 0, 0, 0 }, + { "LPRi", SHORT, GEN | READ | I, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, +}; +const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format3_op[16] = +{ + { "CXPD", GEN | ADDR, 0, 0, 0, STEP_OVER }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "BICPSRi", GEN | READ | I, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "JUMP", GEN | ADDR, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "BISPSRB", GEN | READ | B, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "ADJSPi", GEN | READ | I, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "JSR", GEN | ADDR, 0, 0, 0, STEP_OVER }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "CASEi", GEN | READ | I, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, +}; +const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format4_op[16] = +{ + { "ADDi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, + { "CMPi", GEN | READ | I, GEN | READ | I, 0, 0, 0 }, + { "BICi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "ADDCi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, + { "MOVi", GEN | READ | I, GEN | WRITE | I, 0, 0, 0 }, + { "ORi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "SUBi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, + { "ADDR", GEN | ADDR, GEN | WRITE | D, 0, 0, 0 }, + { "ANDi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "SUBCi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, + { "TBITi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 }, + { "XORi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, +}; +const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format5_op[16] = +{ + { "MOVSi", OPTIONS, 0, 0, 0, 0 }, + { "CMPSi", OPTIONS, 0, 0, 0, 0 }, + { "SETCFG", SHORT, 0, 0, 0, 0 }, + { "SKPSi", OPTIONS, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, +}; +const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format6_op[16] = +{ + { "ROTi", GEN | READ | B, GEN | RMW | I, 0, 0, 0 }, + { "ASHi", GEN | READ | B, GEN | RMW | I, 0, 0, 0 }, + { "CBITi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 }, + { "CBITIi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "LSHi", GEN | READ | B, GEN | RMW | I, 0, 0, 0 }, + { "SBITi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 }, + { "SBITIi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 }, + { "NEGi", GEN | READ | I, GEN | WRITE | I, 0, 0, 0 }, + { "NOTi", GEN | READ | I, GEN | WRITE | I, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "SUBPi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, + { "ABSi", GEN | READ | I, GEN | READ | I, 0, 0, 0 }, + { "COM", GEN | READ | I, GEN | WRITE | I, 0, 0, 0 }, + { "IBITi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 }, + { "ADDPi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, +}; +const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format7_op[16] = +{ + { "MOVMi", GEN | ADDR, GEN | ADDR, DISP, 0, 0 }, + { "CMPMi", GEN | ADDR, GEN | ADDR, DISP, 0, 0 }, + { "INSSi", GEN | READ | I, GEN | REGADDR, IMM, 0, 0 }, + { "EXTSi", GEN | REGADDR, GEN | WRITE | I, IMM, 0, 0 }, + { "MOVXBW", GEN | READ | B, GEN | WRITE | W, 0, 0, 0 }, + { "MOVZBW", GEN | READ | B, GEN | WRITE | W, 0, 0, 0 }, + { "MOVZiD", GEN | READ | I, GEN | WRITE | D, 0, 0, 0 }, + { "MOVXiD", GEN | READ | I, GEN | WRITE | D, 0, 0, 0 }, + { "MULi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, + { "MEIi", GEN | READ | I, GEN | RMW | I2, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "DEIi", GEN | READ | I, GEN | RMW | I2, 0, 0, 0 }, + { "QUOi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, + { "REMi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, + { "MODi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, + { "DIVi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 }, +}; +const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format8_op[] = +{ + { "EXTi", REG, GEN | REGADDR, GEN | WRITE | I, DISP, 0 }, + { "CVTP", REG, GEN | ADDR, GEN | WRITE | D, 0, 0 }, + { "INSi", REG, GEN | READ | I, GEN | REGADDR, DISP, 0 }, + { "CHECKi", REG, GEN | ADDR, GEN | READ | I, 0, 0 }, + { "INDEXi", REG, GEN | READ | I, GEN | READ | I, 0, 0 }, + { "FFSi", GEN | READ | I, GEN | RMW | B, 0, 0, 0 }, + { "MOVSUi", GEN | ADDR, GEN | ADDR, 0, 0, 0 }, + { "MOVUSi", GEN | ADDR, GEN | ADDR, 0, 0, 0 } +}; +const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format9_op[] = +{ + { "MOVif", GEN | READ | I, GEN | WRITE | F, 0, 0, 0 }, + { "LFSR", GEN | READ | D, 0, 0, 0, 0 }, + { "MOVLF", GEN | READ | L, GEN | WRITE | F, 0, 0, 0 }, + { "MOVFL", GEN | READ | F, GEN | WRITE | L, 0, 0, 0 }, + { "ROUNDfi", GEN | READ | F, GEN | WRITE | I, 0, 0, 0 }, + { "TRUNCfi", GEN | READ | F, GEN | WRITE | I, 0, 0, 0 }, + { "SFSR", GEN | WRITE | D, 0, 0, 0, 0 }, + { "FLOORfi", GEN | READ | F, GEN | WRITE | I, 0, 0, 0 }, +}; +const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format11_op[] = +{ + { "ADDf", GEN | READ | F, GEN | RMW | F, 0, 0, 0 }, + { "MOVf", GEN | READ | F, GEN | WRITE | F, 0, 0, 0 }, + { "CMPf", GEN | READ | F, GEN | READ | F, 0, 0, 0 }, // POLYf + { "Trap (SLAVE)", 0, 0, 0, 0, 0 }, // DOTf + { "SUBf", GEN | READ | F, GEN | RMW | F, 0, 0, 0 }, // SCALBf + { "NEGf", GEN | READ | F, GEN | WRITE | F, 0, 0, 0 }, // LOGBf + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "DIVf", GEN | READ | F, GEN | RMW | F, 0, 0, 0 }, + { "Trap (SLAVE)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "MULf", GEN | READ | F, GEN | RMW | F, 0, 0, 0 }, + { "ABSf", GEN | READ | F, GEN | READ | F, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, +}; +const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format14_op[] = +{ + { "RDVAL", GEN | ADDR, 0, 0, 0, 0 }, + { "WRVAL", GEN | ADDR, 0, 0, 0, 0 }, + { "LMR", SHORT, GEN | READ | D, 0, 0, 0 }, + { "SMR", SHORT, GEN | WRITE | D, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, // CINV + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, + { "Trap (UND)", 0, 0, 0, 0, 0 }, +}; + + +const char *const ns32000_disassembler::Format0[] = +{ + "Bcond" +}; +const char *const ns32000_disassembler::Format1[] = +{ + "BSR", "RET", "CXP", "RXP", "RETT", "RETI", "SAVE", "RESTORE", "ENTER", "EXIT", "NOP", "WAIT", "DIA", "FLAG", "SVC", "BPT" +}; +const char *const ns32000_disassembler::Format2[] = +{ + "ADDQi", "CMPQi", "SPRi", "Scondi", "ACBi", "MOVQi", "LPRi" +}; +const char *const ns32000_disassembler::Format3[] = +{ + "CXPD", "Trap (UND)", "BICPSR", "Trap (UND)", "JUMP", "Trap (UND)", "BISPSR", "Trap (UND)", "Trap (UND)", "Trap (UND)", "ADJSPi", "Trap (UND)", "JSR", "Trap (UND)", "CASEi", "Trap (UND)" +}; +const char *const ns32000_disassembler::Format4[] = +{ + "ADDi", "CMPi", "BICi", "Trap (UND)", "ADDCi", "MOVi", "ORi", "Trap (UND)", "SUBi", "ADDR", "ANDi", "Trap (UND)", "SUBCi", "TBITi", "XORi", "Trap (UND)" +}; +const char *const ns32000_disassembler::Format5[] = +{ + "MOVSi", "CMPSi", "SETCFG", "SKPSi", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)" +}; +const char *const ns32000_disassembler::Format6[] = +{ + "ROTi", "ASHi", "CBITi", "CBITIi", "Trap (UND)", "LSHi", "SBITi", "SBITIi", "NEGi", "NOTi", "Trap (UND)", "SUBPi", "ABSi", "COM", "IBITi", "ADDPi" +}; +const char *const ns32000_disassembler::Format7[] = +{ + "MOVMi", "CMPMi", "INSSi", "EXTSi", "MOVXBW", "MOVZBW", "MOVZiD", "MOVXiD", "MULi", "MEIi", "Trap (UND)", "DEIi", "QUOi", "REMi", "MODi", "DIVi" +}; +const char *const ns32000_disassembler::Format8[] = +{ + "EXTi", "CVTP", "INSi", "CHECKi", "INDEXi", "FFSi", "MOVSUi", "MOVUSi" +}; +const char *const ns32000_disassembler::Format9[] = +{ + "MOVif", "LFSR", "MOVLF", "MOVFL", "ROUNDfi", "TRUNCfi", "SFSR", "FLOORfi" +}; +const char *const ns32000_disassembler::Format11[] = +{ + "ADDf", "MOVf", "CMPf", "Trap (SLAVE)", "SUBf", "NEGf", "Trap (UND)", "Trap (UND)", "DIVf", "Trap (SLAVE)", "Trap (UND)", "Trap (UND)", "MULf", "ABSf", "Trap (UND)", "Trap (UND)" +}; +const char *const ns32000_disassembler::Format14[] = +{ + "RDVAL", "WRVAL", "LMR", "SMR", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)" +}; + +// types +const char *const ns32000_disassembler::iType[] = +{ + "B", "W", " ", "D" +}; +const char *const ns32000_disassembler::fType[] = +{ + "L", "F" +}; +const char *const ns32000_disassembler::cType[] = +{ + "Q", "D" +}; + +// index byte sizes +const char *const ns32000_disassembler::indexSize[] = +{ + "B", "W", "D", "Q" +}; + +// short codes +const char *const ns32000_disassembler::cond[] = +{ + "EQ", "NE", "CS", "CC", "HI", "LS", "GT", "LE", "FS", "FC", "LO", "HS", "LT", "GE", "R", "N" +}; +const char *const ns32000_disassembler::areg[] = +{ + "US", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "FP", "SP", "SB", "(reserved)", "(reserved)", "PSR", "INTBASE", "MOD" +}; +const char *const ns32000_disassembler::mreg[] = +{ + "BPR0", "BPR1", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "MSR", "BCNT", "PTB0", "PTB1", "(reserved)", "EIA" +}; + +// register names +const char *const ns32000_disassembler::R[] = +{ + "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7" +}; +const char *const ns32000_disassembler::M[] = +{ + "FP", "SP", "SB" +}; +const char *const ns32000_disassembler::PR[] = +{ + "UPSR", "DCR", "BPC", "DSR", "CAR", "", "", "", "FP", "SP", "SB", "USP", "CFG", "PSR", "INTBASE", "MOD" +}; + +int8_t ns32000_disassembler::short2int(uint8_t val) +{ + return (val & 0x08) ? val | 0xf0 : val; +} + +std::string ns32000_disassembler::mnemonic_index(std::string form, std::string itype, std::string ftype) +{ + if (itype.size() && form.find('i') != std::string::npos) + form.replace(form.find('i'), 1, itype); + if (ftype.size() && form.find('f') != std::string::npos) + form.replace(form.find('f'), 1, ftype); + return form; +} + +uint8_t ns32000_disassembler::opcode_format(uint8_t byte) +{ + switch (byte & 0x0f) + { + case 0x0a: return 0; + case 0x02: return 1; + case 0x0c: + case 0x0d: + case 0x0f: + if ((byte & 0x70) != 0x70) + return 2; + else + return 3; + } + + if ((byte & 0x03) != 0x02) return 4; + + switch (byte) + { + case 0x0e: return 5; + case 0x4e: return 6; + case 0xce: return 7; + case 0x2e: + case 0x6e: + case 0xae: + case 0xee: return 8; + case 0x3e: return 9; + case 0x7e: return 10; + case 0xbe: return 11; + case 0xfe: return 12; + case 0x9e: return 13; + case 0x1e: return 14; + } + + return 99; /* unknown format */ +} + +inline std::string ns32000_disassembler::get_option_list(uint8_t cfg) +{ + std::string option_list; + + option_list.append("["); + if (BIT(cfg, 0)) option_list.append("I,"); + if (BIT(cfg, 1)) option_list.append("F,"); + if (BIT(cfg, 2)) option_list.append("M,"); + if (BIT(cfg, 3)) option_list.append("C,"); + if (option_list.back() == ',') option_list.pop_back(); + option_list.append("]"); + + return option_list; +} + +inline std::string ns32000_disassembler::get_options(uint8_t opts) +{ + std::string options; + + options.append(" "); + if ((opts & 0x02) == 0x02) options.append("B,"); + if ((opts & 0x04) == 0x04) options.append("W,"); + if ((opts & 0x0c) == 0x0c) options.append("U,"); + if (options.back() == ',') options.pop_back(); + + return options; +} + +inline int32_t ns32000_disassembler::get_disp(offs_t &pc, const data_buffer &opcodes) +{ + /* displacement can be upto 3 bytes */ + uint32_t disp = bitswap<32>(opcodes.r32(pc), 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24); + + switch ((disp >> 29) & 0x07) + { + case 0: case 1: /* 7 bit positive */ + disp = (disp >> 24); + pc += 1; + break; + + case 2: case 3: /* 7 bit negative */ + disp = (disp >> 24) | 0xffffff80; + pc += 1; + break; + + case 4: /* 14 bit positive */ + disp = (disp >> 16) & 0x3fff; + pc += 2; + break; + + case 5: /* 14 bit negative */ + disp = (disp >> 16) | 0xffffc000; + pc += 2; + break; + + case 6: /* 30 bit positive */ + disp = disp & 0x3fffffff; + pc += 4; + break; + + case 7: /* 30 bit negative */ + pc += 4; + break; + } + + return disp; +} + +inline std::string ns32000_disassembler::get_reg_list(offs_t &pc, const data_buffer &opcodes, bool reverse) +{ + std::string reg_list; + + uint8_t byte = opcodes.r8(pc++); + + reg_list.append("["); + for (int i = 0; i < 8; i++) + { + if (BIT(byte, i)) reg_list.append(R[reverse ? (~i & 7) : (i & 7)]).append(","); + } + if (reg_list.back() == ',') reg_list.pop_back(); + reg_list.append("]"); + + return reg_list; +} + +void ns32000_disassembler::stream_gen(std::ostream &stream, u8 gen_addr, u8 op_len, offs_t &pc, const data_buffer &opcodes) +{ + uint8_t index_byte; + int32_t disp1, disp2; + + switch (gen_addr) + { + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: + /* Register */ + util::stream_format(stream, "%s", R[gen_addr & 0x07]); + break; + case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: + /* Register Relative */ + disp1 = get_disp(pc, opcodes); + util::stream_format(stream, "%+d(%s)", disp1, R[gen_addr & 0x07]); + break; + case 0x10: case 0x11: case 0x12: + /* Memory Relative */ + disp1 = get_disp(pc, opcodes); + disp2 = get_disp(pc, opcodes); + util::stream_format(stream, "#X%02X(#X%02X(%s))", disp2, disp1, M[gen_addr & 0x03]); + break; + case 0x13: + /* Reserved */ + util::stream_format(stream, "(reserved)"); + break; + case 0x14: + /* Immediate */ + disp1 = bitswap<32>(opcodes.r32(pc), 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24); + util::stream_format(stream, "#X%02X", (op_len == 0 ? (disp1 >> 24) : (op_len == 1 ? (disp1 >> 16) : disp1))); + pc += op_len + 1; + break; + case 0x15: + /* Absolute */ + disp1 = get_disp(pc, opcodes); + util::stream_format(stream, "@#X%02X", disp1); + break; + case 0x16: + /* External */ + disp1 = get_disp(pc, opcodes); + disp2 = get_disp(pc, opcodes); + util::stream_format(stream, "EXT(%d)+%d", disp1, disp2); + break; + case 0x17: + /* Top Of Stack */ + util::stream_format(stream, "TOS"); + break; + case 0x18: case 0x19: case 0x1a: + /* Memory Space */ + disp1 = get_disp(pc, opcodes); + util::stream_format(stream, "#X%02X(%s)", disp1, M[gen_addr & 0x03]); + break; + case 0x1b: + /* Memory Space */ + disp1 = get_disp(pc, opcodes); + util::stream_format(stream, "#X%06X", m_base_pc + disp1); + break; + case 0x1c: + /* Scaled Index */ + index_byte = opcodes.r8(pc++); + stream_gen(stream, index_byte >> 3, op_len, pc, opcodes); + util::stream_format(stream, "[%s:%c]", R[index_byte & 0x07], indexSize[gen_addr & 0x03]); + break; + } +} + +offs_t ns32000_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) +{ + uint32_t flags = SUPPORTED; + + uint32_t opcode; + std::string mnemonic; + uint8_t temp8; + + /* opcode can be upto 3 bytes */ + opcode = opcodes.r32(pc); + m_base_pc = pc; + + switch (opcode_format(opcode)) + { + case 0: /* Format 0 */ + pc += 1; + util::stream_format(stream, "%-8s #X%06X", std::string("B").append(cond[Format0cond(opcode)]), m_base_pc + get_disp(pc, opcodes)); + break; + + case 0x01: /* Format 1 */ + pc += 1; + switch (Format1op(opcode)) + { + case 0x00: + util::stream_format(stream, "%-8s #X%06X", Format1[Format1op(opcode)], m_base_pc + get_disp(pc, opcodes)); + break; + case 0x01: + util::stream_format(stream, "%-8s #X%02X", Format1[Format1op(opcode)], get_disp(pc, opcodes) & 0xffffff); + break; + case 0x02: + util::stream_format(stream, "%-8s EXT(%d)", Format1[Format1op(opcode)], get_disp(pc, opcodes)); + break; + case 0x03: case 0x04: + util::stream_format(stream, "%-8s #X%02X", Format1[Format1op(opcode)], get_disp(pc, opcodes) & 0xffffff); + break; + case 0x05: + util::stream_format(stream, "%-8s", Format1[Format1op(opcode)]); + break; + case 0x06: + util::stream_format(stream, "%-8s %s", Format1[Format1op(opcode)], get_reg_list(pc, opcodes, false)); + break; + case 0x07: case 0x09: + util::stream_format(stream, "%-8s %s", Format1[Format1op(opcode)], get_reg_list(pc, opcodes, true)); + break; + case 0x08: + util::stream_format(stream, "%-8s %s, %d", Format1[Format1op(opcode)], get_reg_list(pc, opcodes, false), get_disp(pc, opcodes)); + break; + case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: + util::stream_format(stream, "%-8s", Format1[Format1op(opcode)]); + break; + } + break; + + case 0x02: /* Format 2 */ + pc += 2; + mnemonic = mnemonic_index(Format2[Format2op(opcode)], iType[Format2i(opcode)], ""); + switch (Format2op(opcode)) + { + case 0x00: case 0x01: case 0x05: + util::stream_format(stream, "%-8s %+d, ", mnemonic, short2int(Format2short(opcode))); + stream_gen(stream, Format2gen(opcode), Format2i(opcode), pc, opcodes); + break; + case 0x02: case 0x06: + util::stream_format(stream, "%-8s %s, ", mnemonic, areg[Format2short(opcode)]); + stream_gen(stream, Format2gen(opcode), Format2i(opcode), pc, opcodes); + break; + case 0x03: + util::stream_format(stream, "%-8s ", std::string("S").append(cond[Format2short(opcode)]).append(iType[Format2i(opcode)])); + stream_gen(stream, Format2gen(opcode), Format2i(opcode), pc, opcodes); + break; + case 0x04: + util::stream_format(stream, "%-8s %+d, ", mnemonic, short2int(Format2short(opcode))); + stream_gen(stream, Format2gen(opcode), Format2i(opcode), pc, opcodes); + util::stream_format(stream, ", #X%06x", m_base_pc + get_disp(pc, opcodes)); + break; + } + break; + + case 0x03: /* Format 3 */ + pc += 2; + mnemonic = mnemonic_index(Format3[Format3op(opcode)], iType[Format3i(opcode)], ""); + switch (Format3op(opcode)) + { + case 0x00: case 0x02: case 0x04: case 0x06: case 0x0a: case 0x0c: case 0x0e: + util::stream_format(stream, "%-8s ", mnemonic); + stream_gen(stream, Format3gen(opcode), Format3i(opcode), pc, opcodes); + break; + default: /* Trap */ + util::stream_format(stream, "%-8s ", mnemonic); + break; + } + break; + + case 0x04: /* Format 4 */ + pc += 2; + mnemonic = mnemonic_index(Format4[Format4op(opcode)], iType[Format4i(opcode)], ""); + util::stream_format(stream, "%-8s ", mnemonic); + stream_gen(stream, Format4gen1(opcode), Format4i(opcode), pc, opcodes); + util::stream_format(stream, ", "); + stream_gen(stream, Format4gen2(opcode), Format4i(opcode), pc, opcodes); + break; + + case 0x05: /* Format 5 */ + pc += 3; + mnemonic = mnemonic_index(Format5[Format5op(opcode)], iType[Format5i(opcode)], ""); + switch ((opcode >> 10) & 0x0f) + { + case 0x00: case 0x01: case 0x03: + if (Format5short(opcode) & 0x01) + util::stream_format(stream, "%-8s %s", std::string(Format5[Format5op(opcode)]).append("T"), get_options(Format5short(opcode))); + else + util::stream_format(stream, "%-8s %s", mnemonic, get_options(Format5short(opcode))); + break; + case 0x02: + util::stream_format(stream, "%-8s %s", Format5[Format5op(opcode)], get_option_list(Format5short(opcode))); + break; + default: /* Trap */ + util::stream_format(stream, "%-8s ", mnemonic); + break; + } + break; + + case 0x06: /* Format 6 */ + pc += 3; + mnemonic = mnemonic_index(Format6[Format6op(opcode)], iType[Format6i(opcode)], ""); + switch ((opcode >> 10) & 0x0f) + { + case 0x00: case 0x01: case 0x02: case 0x03: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: + util::stream_format(stream, "%-8s ", mnemonic); + stream_gen(stream, Format6gen1(opcode), Format6i(opcode), pc, opcodes); + util::stream_format(stream, ", "); + stream_gen(stream, Format6gen2(opcode), Format6i(opcode), pc, opcodes); + break; + default: /* Trap */ + util::stream_format(stream, "%-8s ", mnemonic); + break; + } + break; + + case 0x07: /* Format 7 */ + pc += 3; + mnemonic = mnemonic_index(Format7[Format7op(opcode)], iType[Format7i(opcode)], ""); + switch (Format7op(opcode)) + { + case 0x00: case 0x01: + util::stream_format(stream, "%-8s ", mnemonic); + stream_gen(stream, Format7gen1(opcode), Format7i(opcode), pc, opcodes); + util::stream_format(stream, ", "); + stream_gen(stream, Format7gen2(opcode), Format7i(opcode), pc, opcodes); + util::stream_format(stream, ", %d", get_disp(pc, opcodes)); + break; + case 0x02: case 0x03: + util::stream_format(stream, "%-8s ", mnemonic); + stream_gen(stream, Format7gen1(opcode), Format7i(opcode), pc, opcodes); + util::stream_format(stream, ", "); + stream_gen(stream, Format7gen2(opcode), Format7i(opcode), pc, opcodes); + temp8 = opcodes.r8(pc++); + util::stream_format(stream, ", %d, %d", temp8 >> 5, temp8 + 1); + break; + case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: + util::stream_format(stream, "%-8s ", mnemonic); + stream_gen(stream, Format7gen1(opcode), Format7i(opcode), pc, opcodes); + util::stream_format(stream, ", "); + stream_gen(stream, Format7gen2(opcode), Format7i(opcode), pc, opcodes); + break; + default: /* Trap */ + util::stream_format(stream, "%-8s ", mnemonic); + break; + } + break; + + case 0x08: /* Format 8 */ + pc += 3; + mnemonic = mnemonic_index(Format8[Format8op(opcode)], iType[Format8i(opcode)], ""); + switch (Format8op(opcode)) + { + case 0x00: case 0x02: + util::stream_format(stream, "%-8s %s, ", mnemonic, R[Format8reg(opcode)]); + stream_gen(stream, Format8gen2(opcode), Format8i(opcode), pc, opcodes); + util::stream_format(stream, ", "); + stream_gen(stream, Format8gen1(opcode), Format8i(opcode), pc, opcodes); + util::stream_format(stream, ", %d", get_disp(pc, opcodes)); + break; + case 0x01: case 0x03: case 0x04: + util::stream_format(stream, "%-8s %s, ", mnemonic, R[Format8reg(opcode)]); + stream_gen(stream, Format8gen2(opcode), Format8i(opcode), pc, opcodes); + util::stream_format(stream, ", "); + stream_gen(stream, Format8gen1(opcode), Format8i(opcode), pc, opcodes); + break; + case 0x05: + util::stream_format(stream, "%-8s ", mnemonic); + stream_gen(stream, Format8gen2(opcode), Format8i(opcode), pc, opcodes); + util::stream_format(stream, ", "); + stream_gen(stream, Format8gen1(opcode), Format8i(opcode), pc, opcodes); + break; + case 0x06: + if (Format8reg(opcode) == 0x01) + util::stream_format(stream, "%-8s ", std::string(Format8[Format8op(opcode)]).append(iType[Format8i(opcode)])); + else + util::stream_format(stream, "%-8s ", std::string(Format8[Format8op(opcode) + 1]).append(iType[Format8i(opcode)])); + stream_gen(stream, Format8gen2(opcode), Format8i(opcode), pc, opcodes); + util::stream_format(stream, ", "); + stream_gen(stream, Format8gen1(opcode), Format8i(opcode), pc, opcodes); + break; + } + break; + + case 0x09: /* Format 9 */ + pc += 3; + mnemonic = mnemonic_index(Format9[Format9op(opcode)], iType[Format9i(opcode)], fType[Format9f(opcode)]); + switch (Format9op(opcode)) + { + case 0x00: case 0x02: case 0x04: case 0x05: case 0x07: + util::stream_format(stream, "%-8s ", mnemonic); + stream_gen(stream, Format9gen1(opcode), Format9i(opcode), pc, opcodes); + util::stream_format(stream, ", "); + stream_gen(stream, Format9gen2(opcode), Format9i(opcode), pc, opcodes); + break; + case 0x01: case 0x06: + util::stream_format(stream, "%-8s ", mnemonic); + stream_gen(stream, Format9gen1(opcode), Format9i(opcode), pc, opcodes); + break; + } + + case 0x0b: /* Format 11 */ + pc += 3; + mnemonic = mnemonic_index(Format11[Format11op(opcode)], nullptr, fType[Format11f(opcode)]); + switch (Format11op(opcode)) + { + case 0x00: case 0x01: case 0x02: case 0x04: case 0x05 : case 0x08: case 0x0c : case 0x0d: + util::stream_format(stream, "%-8s ", mnemonic); + stream_gen(stream, Format11gen1(opcode), Format11f(opcode), pc, opcodes); + util::stream_format(stream, ","); + stream_gen(stream, Format11gen2(opcode), Format11f(opcode), pc, opcodes); + break; + default: /* Trap */ + util::stream_format(stream, "%-8s ", mnemonic); + break; + } + break; + + case 0x0a: /* Format 10 */ + case 0x0c: /* Format 12 */ + case 0x0d: /* Format 13 */ + pc += 3; + util::stream_format(stream, "Trap (UND)"); + break; + + case 0x0e: /* Format 14 */ + pc += 3; + mnemonic = mnemonic_index(Format14[Format14op(opcode)], iType[Format14i(opcode)], ""); + switch (Format14op(opcode)) + { + case 0x00: case 0x01: + util::stream_format(stream, "%-8s ", mnemonic); + stream_gen(stream, Format14gen1(opcode), Format14i(opcode), pc, opcodes); + break; + case 0x02: case 0x03: + util::stream_format(stream, "%-8s %s, ", mnemonic, mreg[Format14short(opcode)]); + stream_gen(stream, Format14gen1(opcode), Format14i(opcode), pc, opcodes); + break; + default: /* Trap */ + util::stream_format(stream, "%-8s ", mnemonic); + break; + } + break; + + default: + pc += 1; + util::stream_format(stream, "unknown instruction format"); + break; + } + + return (pc - m_base_pc) | flags; +} diff --git a/src/devices/cpu/ns32000/ns32000dasm.h b/src/devices/cpu/ns32000/ns32000dasm.h new file mode 100644 index 00000000000..e9c970c9829 --- /dev/null +++ b/src/devices/cpu/ns32000/ns32000dasm.h @@ -0,0 +1,118 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/***************************************************************************** +* +* ns32000dasm.cpp +* +* NS32000 CPU Disassembly +* +*****************************************************************************/ + +#ifndef MAME_CPU_NS32000_NS32000DASM_H +#define MAME_CPU_NS32000_NS32000DASM_H + +#pragma once + +class ns32000_disassembler : public util::disasm_interface +{ +public: + + ns32000_disassembler() = default; + virtual ~ns32000_disassembler() = default; + + virtual u32 opcode_alignment() const override { return 1; } + virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; + +private: + /* implied operand attributes */ + enum + { + REG = 16, + QUICK, + SHORT, + IMM, + DISP, + GEN, + OPTIONS, + }; + /* access classes */ + enum + { + READ = 8, + WRITE, + RMW, + ADDR, + REGADDR + }; + /* length attributes */ + enum + { + B = 0, + W = 1, + D = 3, + I, + I2, + F, + L + }; + struct NS32000_OPCODE { + const char *mnemonic; + u32 operand1; + u32 operand; + u32 operand3; + u32 operand4; + offs_t dasm_flags; + }; + + static const NS32000_OPCODE format0_op[1]; + static const NS32000_OPCODE format1_op[16]; + static const NS32000_OPCODE format2_op[8]; + static const NS32000_OPCODE format3_op[16]; + static const NS32000_OPCODE format4_op[16]; + static const NS32000_OPCODE format5_op[16]; + static const NS32000_OPCODE format6_op[16]; + static const NS32000_OPCODE format7_op[16]; + static const NS32000_OPCODE format8_op[16]; + static const NS32000_OPCODE format9_op[16]; + static const NS32000_OPCODE format11_op[16]; + static const NS32000_OPCODE format14_op[16]; + + + static char const *const Format0[]; + static char const *const Format1[]; + static char const *const Format2[]; + static char const *const Format3[]; + static char const *const Format4[]; + static char const *const Format5[]; + static char const *const Format6[]; + static char const *const Format7[]; + static char const *const Format8[]; + static char const *const Format9[]; + static char const *const Format11[]; + static char const *const Format14[]; + static char const *const iType[]; + static char const *const fType[]; + static char const *const cType[]; + static char const *const indexSize[]; + static char const *const cond[]; + static char const *const areg[]; + static char const *const mreg[]; + static char const *const R[]; + static char const *const M[]; + static char const *const PR[]; + + std::string mnemonic_index(std::string form, std::string itype, std::string ftype); + uint8_t opcode_format(uint8_t byte); + int8_t short2int(uint8_t val); + static inline int32_t get_disp(offs_t &pc, const data_buffer &opcodes); + static inline std::string get_option_list(uint8_t cfg); + static inline std::string get_options(uint8_t opts); + static inline std::string get_reg_list(offs_t &pc, const data_buffer &opcodes, bool reverse); + + void stream_gen(std::ostream &stream, u8 gen_addr, u8 op_len, offs_t &pc, const data_buffer &opcodes); + + u32 m_base_pc; + unsigned m_pcmask; +}; + +#endif diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index 81b9f448140..c668fcba82d 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -99,6 +99,7 @@ using util::BIT; #include "cpu/mn10200/mn102dis.h" #include "cpu/nanoprocessor/nanoprocessor_dasm.h" #include "cpu/nec/necdasm.h" +#include "cpu/ns32000/ns32000dasm.h" #include "cpu/nuon/nuondasm.h" #include "cpu/patinhofeio/patinho_feio_dasm.h" #include "cpu/pdp1/pdp1dasm.h" @@ -420,6 +421,7 @@ static const dasm_table_entry dasm_table[] = { "mn10200", le, 0, []() -> util::disasm_interface * { return new mn10200_disassembler; } }, { "nanoprocessor", le, 0, []() -> util::disasm_interface * { return new hp_nanoprocessor_disassembler; } }, { "nec", le, 0, []() -> util::disasm_interface * { return new nec_disassembler; } }, + { "ns32000", le, 0, []() -> util::disasm_interface * { return new ns32000_disassembler; } }, { "nuon", be, 0, []() -> util::disasm_interface * { return new nuon_disassembler; } }, { "nsc8105", be, 0, []() -> util::disasm_interface * { return new m680x_disassembler(8105); } }, { "patinho_feio", le, 0, []() -> util::disasm_interface * { return new patinho_feio_disassembler; } }, -- cgit v1.2.3-70-g09d2