summaryrefslogtreecommitdiff
path: root/disasm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'disasm.cpp')
-rw-r--r--disasm.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/disasm.cpp b/disasm.cpp
new file mode 100644
index 0000000..033349b
--- /dev/null
+++ b/disasm.cpp
@@ -0,0 +1,157 @@
+#include "disasm.h"
+#include "data_buffer.h"
+#include "common.h"
+
+#include <cstdio>
+
+static size_t disasm_verbatim(
+ char *out, size_t out_sz, size_t *instr_sz, uint16_t instr, uint32_t, const DataBuffer &)
+{
+ if (instr_sz) {
+ *instr_sz = kInstructionSizeStepBytes;
+ }
+ return Min(out_sz, snprintf(out, out_sz, " .short 0x%04x", instr));
+}
+
+static size_t disasm_mfff0_v4e70(
+ char *out, size_t out_sz, size_t *instr_sz, uint16_t instr, uint32_t offset, const DataBuffer &code)
+{
+ if (instr_sz) {
+ *instr_sz = kInstructionSizeStepBytes;
+ }
+ if (instr == 0x4e70) {
+ return Min(out_sz, snprintf(out, out_sz, " reset"));
+ } else if (instr == 0x4e71) {
+ return Min(out_sz, snprintf(out, out_sz, " nop"));
+ } else if (instr == 0x4e73) {
+ return Min(out_sz, snprintf(out, out_sz, " rte"));
+ } else if (instr == 0x4e75) {
+ return Min(out_sz, snprintf(out, out_sz, " rts"));
+ } else if (instr == 0x4e76) {
+ return Min(out_sz, snprintf(out, out_sz, " trapv"));
+ } else if (instr == 0x4e77) {
+ return Min(out_sz, snprintf(out, out_sz, " rtr"));
+ }
+ return disasm_verbatim(out, out_sz, instr_sz, instr, offset, code);
+}
+
+static size_t disasm_jsr(
+ char *out, size_t out_sz, size_t *instr_sz, uint16_t instr, uint32_t offset, const DataBuffer & code)
+{
+ const int addrmode = instr & 0x3f;
+ const int m = (addrmode >> 3) & 0x7;
+ const int xn = addrmode & 0x7;
+ switch (m) {
+ case 0: // 4e80 .. 4e87
+ case 1: // 4e88 .. 4e8f
+ break;
+ case 2: // 4e90 .. 4e97
+ if (instr_sz) {
+ *instr_sz = kInstructionSizeStepBytes;
+ }
+ return Min(out_sz, snprintf(out, out_sz, " jsr %%a%d@", xn));
+ case 3: // 4e98 .. 4e9f
+ case 4: // 4ea0 .. 4ea7
+ break;
+ case 5: // 4ea8 .. 4eaf, Displacement
+ {
+ if (instr_sz) {
+ *instr_sz = kInstructionSizeStepBytes * 2;
+ }
+ const int16_t dispmt = GetI16BE(code.buffer + offset + kInstructionSizeStepBytes);
+ return Min(out_sz, snprintf(out, out_sz, " jsr %%a%d@(%d:w)", xn, dispmt));
+ }
+ case 6: // 4eb0 .. 4eb7, Brief Extension Word
+ {
+ if (instr_sz) {
+ *instr_sz = kInstructionSizeStepBytes * 2;
+ }
+ const uint16_t briefext = GetU16BE(code.buffer + offset + kInstructionSizeStepBytes);
+ const char reg = ((briefext >> 15) & 1) ? 'a' : 'd';
+ const int xn2 = (briefext >> 12) & 7;
+ const char size_spec = ((briefext >> 11) & 1) ? 'l' : 'w';
+ const int8_t dispmt = briefext & 0xff;
+ return Min(out_sz, snprintf(
+ out, out_sz, " jsr %%a%d@(%d,%%%c%d:%c)",
+ xn, dispmt, reg, xn2, size_spec));
+ }
+ case 7: // 4eb8 .. 4ebf, some are with Brief Extension Word
+ switch (xn) {
+ case 0: // 4eb8 (xxx).W
+ {
+ if (instr_sz) {
+ *instr_sz = kInstructionSizeStepBytes * 2;
+ }
+ const int32_t dispmt = GetI16BE(code.buffer + offset + kInstructionSizeStepBytes);
+ return Min(out_sz, snprintf(out, out_sz, " jsr 0x%x:w", dispmt));
+ }
+ case 1: // 4eb9 (xxx).L
+ {
+ if (instr_sz) {
+ *instr_sz = kInstructionSizeStepBytes * 3;
+ }
+ const int32_t dispmt = GetI32BE(code.buffer + offset + kInstructionSizeStepBytes);
+ return Min(out_sz, snprintf(out, out_sz, " jsr 0x%x:l", dispmt));
+ }
+ case 2: // 4eba, Displacement
+ {
+ if (instr_sz) {
+ *instr_sz = kInstructionSizeStepBytes * 2;
+ }
+ const int16_t dispmt = GetI16BE(code.buffer + offset + kInstructionSizeStepBytes);
+ return Min(out_sz, snprintf(out, out_sz, " jsr %%pc@(%d:w)", dispmt));
+ }
+ case 3: // 4ebb
+ {
+ if (instr_sz) {
+ *instr_sz = kInstructionSizeStepBytes * 2;
+ }
+ const uint16_t briefext = GetU16BE(
+ code.buffer + offset + kInstructionSizeStepBytes);
+ const char reg = ((briefext >> 15) & 1) ? 'a' : 'd';
+ const int xn2 = (briefext >> 12) & 7;
+ const char size_spec = ((briefext >> 11) & 1) ? 'l' : 'w';
+ const int8_t dispmt = briefext & 0xff;
+ return Min(out_sz, snprintf(
+ out, out_sz, " jsr %%pc@(%d,%%%c%d:%c)", dispmt, reg, xn2, size_spec));
+ }
+ case 4: // 4ebc
+ case 5: // 4ebd
+ case 6: // 4ebe
+ break;
+ }
+ break;
+ }
+ return disasm_verbatim(out, out_sz, instr_sz, instr, offset, code);
+}
+
+size_t m68k_disasm(
+ char *out, size_t out_sz, size_t *instr_sz, uint16_t instr, uint32_t offset, const DataBuffer &code)
+{
+ if ((instr & 0xfff0) == 0x4e70) {
+ return disasm_mfff0_v4e70(out, out_sz, instr_sz, instr, offset, code);
+ } else if ((instr & 0xffc0) == 0x4e80) {
+ return disasm_jsr(out, out_sz, instr_sz, instr, offset, code);
+ }
+ return disasm_verbatim(out, out_sz, instr_sz, instr, offset, code);
+}
+
+size_t m68k_render_raw_data_comment(
+ char *out, size_t out_sz, uint32_t offset, size_t instr_sz, const DataBuffer &code)
+{
+ size_t overall_sz = Min(out_sz, snprintf(out, out_sz, " |"));
+ for (size_t i = 0; i < instr_sz; i += kInstructionSizeStepBytes)
+ {
+ overall_sz += Min(
+ out_sz - overall_sz,
+ snprintf(
+ out + overall_sz,
+ out_sz - overall_sz,
+ " %04x",
+ GetU16BE(code.buffer + offset + i)));
+ }
+ overall_sz += Min(
+ out_sz - overall_sz,
+ snprintf(out + overall_sz, out_sz - overall_sz, " @%08x", offset));
+ return overall_sz;
+}