diff options
author | Oxore <oxore@protonmail.com> | 2023-04-21 18:42:46 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-04-21 18:42:46 +0300 |
commit | 8856f2ee0e19f50c4c4fb3dc7fccc8150a00da81 (patch) | |
tree | 575d6b65bf425a27d487f6987c6331763e388ec8 /disasm.cpp | |
parent | 25762ee11dadb333f5b63c359abb615dc5f16b09 (diff) |
Refactor asm rendering
Diffstat (limited to 'disasm.cpp')
-rw-r--r-- | disasm.cpp | 157 |
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; +} |