diff options
author | 2020-06-11 23:13:53 +0200 | |
---|---|---|
committer | 2020-06-11 23:14:04 +0200 | |
commit | 1edc4eb3599bcb0464376875e0d38a6582a134fe (patch) | |
tree | 2afa614a7d1a1572265b837fa3ef65653104481d /src/devices/cpu/pic1670 | |
parent | 757c179183c6b4f80375c58900716a1df2b5ac34 (diff) |
pic1670: Add a disassembler [O. Galibert]
Diffstat (limited to 'src/devices/cpu/pic1670')
-rw-r--r-- | src/devices/cpu/pic1670/pic1670d.cpp | 103 | ||||
-rw-r--r-- | src/devices/cpu/pic1670/pic1670d.h | 34 |
2 files changed, 137 insertions, 0 deletions
diff --git a/src/devices/cpu/pic1670/pic1670d.cpp b/src/devices/cpu/pic1670/pic1670d.cpp new file mode 100644 index 00000000000..a9fc677ad06 --- /dev/null +++ b/src/devices/cpu/pic1670/pic1670d.cpp @@ -0,0 +1,103 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert + +// PIC1670 disassembler + +#include "emu.h" +#include "pic1670d.h" + +u32 pic1670_disassembler::opcode_alignment() const +{ + return 1; +} + +char pic1670_disassembler::fw(u16 opcode) +{ + return opcode & 0x40 ? 'f' : 'w'; +} + +std::string pic1670_disassembler::freg(u16 opcode) const +{ + static const char *const fnames[0x10] = { + "(fsr)", "w", "pc", "asr", "fsr", "isr", "rtcca", "rtccb", + "riopa", "iopa", "riopb" "iopb", "riorpc", "iopc", "riopd", "iopd" + }; + u16 reg = opcode & 0x3f; + if(reg < 0x10) + return fnames[reg]; + return util::string_format("f_%02x", reg); +} + +std::string pic1670_disassembler::imm8(u16 opcode) +{ + if((opcode & 0xff) < 10) + return util::string_format("%d", opcode & 0xff); + else + return util::string_format("'h'%02x", opcode & 0xff); +} + +// Note: the decodes have more don't care than the manual, they reflect the +// reality of the opcode decode of the die, e.g. bits 3,4,5 are not used there + +#define P std::ostream &stream, const pic1670_disassembler *d, u16 opcode, u16 pc +const pic1670_disassembler::instruction pic1670_disassembler::instructions[] { + { 0x0004, 0x1fc7, [](P) -> u32 { util::stream_format(stream, "daw" ); return 1; } }, + { 0x0040, 0x1fc0, [](P) -> u32 { util::stream_format(stream, "movwf %s", d->freg(opcode) ); return 1; } }, + { 0x0080, 0x1f80, [](P) -> u32 { util::stream_format(stream, "subbwf %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0100, 0x1f80, [](P) -> u32 { util::stream_format(stream, "subwf %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0180, 0x1f80, [](P) -> u32 { util::stream_format(stream, "decf %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0200, 0x1f80, [](P) -> u32 { util::stream_format(stream, "iorwf %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0280, 0x1f80, [](P) -> u32 { util::stream_format(stream, "andwf %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0300, 0x1f80, [](P) -> u32 { util::stream_format(stream, "xorwf %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0380, 0x1f80, [](P) -> u32 { util::stream_format(stream, "addwf %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0400, 0x1f80, [](P) -> u32 { util::stream_format(stream, "adcwf %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0480, 0x1f80, [](P) -> u32 { util::stream_format(stream, "comf %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0500, 0x1f80, [](P) -> u32 { util::stream_format(stream, "incf %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0580, 0x1f80, [](P) -> u32 { util::stream_format(stream, "decfsz %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0600, 0x1f80, [](P) -> u32 { util::stream_format(stream, "rlcf %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0680, 0x1f80, [](P) -> u32 { util::stream_format(stream, "rrcf %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0700, 0x1f80, [](P) -> u32 { util::stream_format(stream, "swapf %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + { 0x0780, 0x1f80, [](P) -> u32 { util::stream_format(stream, "incfsz %s, %c", d->freg(opcode), fw(opcode)); return 1; } }, + + { 0x1000, 0x1fc0, [](P) -> u32 { util::stream_format(stream, "movfw %s", d->freg(opcode) ); return 1; } }, + { 0x1040, 0x1fc0, [](P) -> u32 { util::stream_format(stream, "clrf %s", d->freg(opcode) ); return 1; } }, + { 0x1080, 0x1fc0, [](P) -> u32 { util::stream_format(stream, "rrncf %s", d->freg(opcode) ); return 1; } }, + { 0x10c0, 0x1fc0, [](P) -> u32 { util::stream_format(stream, "rlncf %s", d->freg(opcode) ); return 1; } }, + { 0x1100, 0x1fc0, [](P) -> u32 { util::stream_format(stream, "cpfslt %s", d->freg(opcode) ); return 1; } }, + { 0x1140, 0x1fc0, [](P) -> u32 { util::stream_format(stream, "cpfseq %s", d->freg(opcode) ); return 1; } }, + { 0x1180, 0x1fc0, [](P) -> u32 { util::stream_format(stream, "cpfsgt %s", d->freg(opcode) ); return 1; } }, + { 0x11c0, 0x1fc0, [](P) -> u32 { util::stream_format(stream, "testf %s", d->freg(opcode) ); return 1; } }, + + { 0x0800, 0x1e00, [](P) -> u32 { util::stream_format(stream, "bcf %d, %s", (opcode >> 6) & 7, d->freg(opcode)); return 1; } }, + { 0x0a00, 0x1e00, [](P) -> u32 { util::stream_format(stream, "bsf %d, %s", (opcode >> 6) & 7, d->freg(opcode)); return 1; } }, + { 0x0c00, 0x1e00, [](P) -> u32 { util::stream_format(stream, "btfsc %d, %s", (opcode >> 6) & 7, d->freg(opcode)); return 1; } }, + { 0x0e00, 0x1e00, [](P) -> u32 { util::stream_format(stream, "btfss %d, %s", (opcode >> 6) & 7, d->freg(opcode)); return 1; } }, + + { 0x0000, 0x1fc7, [](P) -> u32 { util::stream_format(stream, "nop" ); return 1; } }, + { 0x0001, 0x1fc7, [](P) -> u32 { util::stream_format(stream, "halt" ); return 1; } }, + { 0x0002, 0x1fc7, [](P) -> u32 { util::stream_format(stream, "retfi" ); return 1 | STEP_OUT; } }, + { 0x0003, 0x1fc7, [](P) -> u32 { util::stream_format(stream, "retfs" ); return 1 | STEP_OUT; } }, + { 0x1200, 0x1f00, [](P) -> u32 { util::stream_format(stream, "movlw %s", imm8(opcode)); return 1; } }, + { 0x1300, 0x1f00, [](P) -> u32 { util::stream_format(stream, "addlw %s", imm8(opcode)); return 1; } }, + { 0x1400, 0x1f00, [](P) -> u32 { util::stream_format(stream, "iorlw %s", imm8(opcode)); return 1; } }, + { 0x1500, 0x1f00, [](P) -> u32 { util::stream_format(stream, "andlw %s", imm8(opcode)); return 1; } }, + { 0x1600, 0x1f00, [](P) -> u32 { util::stream_format(stream, "xorlw %s", imm8(opcode)); return 1; } }, + { 0x1700, 0x1f00, [](P) -> u32 { util::stream_format(stream, "retlw %s", imm8(opcode)); return 1 | STEP_OUT; } }, + + { 0x1800, 0x1c00, [](P) -> u32 { util::stream_format(stream, "goto %03x", opcode & 0x3ff); return 1; } }, + { 0x1c00, 0x1c00, [](P) -> u32 { util::stream_format(stream, "call %03x", opcode & 0x3ff); return 1 | STEP_OVER; } }, + + { 0x0000, 0x0000, [](P) -> u32 { util::stream_format(stream, "?%04x", opcode); return 1; } }, +}; + +#undef P + +offs_t pic1670_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) +{ + u16 opcode = opcodes.r16(pc); + + for(u32 i=0;; i++) + if((opcode & instructions[i].mask) == instructions[i].value) + return instructions[i].cb(stream, this, opcode, pc) | SUPPORTED; + return 0; +} diff --git a/src/devices/cpu/pic1670/pic1670d.h b/src/devices/cpu/pic1670/pic1670d.h new file mode 100644 index 00000000000..cf96f43b632 --- /dev/null +++ b/src/devices/cpu/pic1670/pic1670d.h @@ -0,0 +1,34 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert + +// PIC1670 disassembler + +#ifndef MAME_CPU_PIC1670_PIC1670D_H +#define MAME_CPU_PIC1670_PIC1670D_H + +#pragma once + +class pic1670_disassembler : public util::disasm_interface +{ +public: + pic1670_disassembler() = default; + virtual ~pic1670_disassembler() = default; + + 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: + struct instruction { + u16 value; + u16 mask; + u32 (*cb)(std::ostream &, const pic1670_disassembler *, u16, u16); + }; + + static const instruction instructions[]; + + std::string freg(u16 opcode) const; + static char fw(u16 opcode); + static std::string imm8(u16 opcode); +}; + +#endif // MAME_CPU_PIC1670_PIC1670D_H |