From 45d6b8b322f40b87c89a4058ed4eaf62a843e9c8 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Sat, 24 Dec 2016 17:09:12 -0500 Subject: [PATCH] disassembler. --- Makefile | 11 ++ disasm.cpp | 443 ++++++++++++++++++++++++++++++++++++++++++++++++++++ dumpobj.cpp | 12 +- 3 files changed, 465 insertions(+), 1 deletion(-) create mode 100644 Makefile create mode 100644 disasm.cpp diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6c794af --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +CC=c++ -std=c++11 -g +CXX=c++ -std=c++11 -g +OBJS = dumpobj.o disasm.o + +dumpobj : dumpobj.o disasm.o + +.PHONY: + clean + +clean: + $(RM) dumpobj $(OBJS) \ No newline at end of file diff --git a/disasm.cpp b/disasm.cpp new file mode 100644 index 0000000..19ca2eb --- /dev/null +++ b/disasm.cpp @@ -0,0 +1,443 @@ +#include +#include +#include + +static constexpr const char opcodes[] = + "brkoracoporatsboraaslora" + "phporaaslphdtsboraaslora" + "bploraoraoratrboraaslora" + "clcorainctcstrboraaslora" + "jsrandjslandbitandroland" + "plpandrolpldbitandroland" + "bmiandandandbitandroland" + "secanddectscbitandroland" + "rtieorwdmeormvpeorlsreor" + "phaeorlsrphkjmpeorlsreor" + "bvceoreoreormvneorlsreor" + "clieorphytcdjmleorlsreor" + "rtsadcperadcstzadcroradc" + "plaadcrorrtljmpadcroradc" + "bvsadcadcadcstzadcroradc" + "seiadcplytdcjmpadcroradc" + "brastabrlstastystastxsta" + "deybittxaphbstystastxsta" + "bccstastastastystastxsta" + "tyastatxstxystzstastzsta" + "ldyldaldxldaldyldaldxlda" + "tayldataxplbldyldaldxlda" + "bcsldaldaldaldyldaldxlda" + "clvldatsxtyxldyldaldxlda" + "cpycmprepcmpcpycmpdeccmp" + "inycmpdexwaicpycmpdeccmp" + "bnecmpcmpcmppeicmpdeccmp" + "cldcmpphxstpjmlcmpdeccmp" + "cpxsbcsepsbccpxsbcincsbc" + "inxsbcnopxbacpxsbcincsbc" + "beqsbcsbcsbcpeasbcincsbc" + "sedsbcplxxcejsrsbcincsbc" + ; + +static constexpr const int mImplied = 0x0000; +static constexpr const int mImmediate = 0x1000; +static constexpr const int mAbsolute = 0x2000; +static constexpr const int mAbsoluteI = 0x3000; +static constexpr const int mAbsoluteIL = 0x4000; +static constexpr const int mAbsoluteLong = 0x5000; +static constexpr const int mDP = 0x6000; +static constexpr const int mDPI = 0x7000; +static constexpr const int mDPIL = 0x8000; +static constexpr const int mRelative = 0x9000; +static constexpr const int mBlockMove = 0xa000; + +static constexpr const int m_S = 0x0100; +static constexpr const int m_X = 0x0200; +static constexpr const int m_Y = 0x0400; + +static constexpr const int m_M = 0x0010; +static constexpr const int m_I = 0x0020; + +static constexpr const int modes[] = +{ + 1 | mAbsolute, // 00 brk #imm + 1 | mDPI | m_X, // 01 ora (dp,x) + 1 | mAbsolute, // 02 cop #imm + 1 | mDP | m_S, // 03 ora ,s + 1 | mDP, // 04 tsb abs + + 1 | mRelative, // 10 bpl + 1 | mDPI | m_Y, // 11 ora (dp),y + 1 | mDPI, // 12 ora (dp) + 1 | mDPI | m_S | m_Y, // 13 ora ,s,y + 1 | mDP, // 14 trb abs,x + + 2 | mAbsolute, // 20 jsr |abs + 1 | mDPI | m_X, // 21 and (dp,x) + 3 | mAbsoluteLong, // 22 jsl >abs + 1 | mDP | m_S, // 23 and ,s + 1 | mDP, // 24 bit abs + + 1 | mRelative, // 30 bmi + 1 | mDPI | m_Y, // 31 and (dp),y + 1 | mDPI, // 32 and (dp) + 1 | mDPI | m_S | m_Y, // 33 and ,s,y + 1 | mDP | m_X, // 34 bit dp,x + 1 | mDP | m_X, // 35 and dp,x + 1 | mDP | m_X, // 36 rol abs,x + + 0 | mImplied, // 40 rti + 1 | mDPI | m_X, // 41 eor (dp,x) + 1 | mAbsolute, // 42 wdm #imm + 1 | mDP | m_S, // 43 eor ,s + 2 | mBlockMove, // 44 mvp x,x + 1 | mDP, // 45 eor dp + 1 | mDP, // 46 lsr dp + 1 | mDPIL | m_Y, // 47 eor [dp],y + 0 | mImplied, // 48 pha + 1 | mImmediate | m_M, // 49 eor #imm + 0 | mImplied, // 4a lsr a + 0 | mImplied, // 4b phk + 2 | mAbsolute, // 4c jmp |abs + 2 | mAbsolute, // 4d eor |abs + 2 | mAbsolute, // 4e lsr |abs + 3 | mAbsoluteLong, // 4f eor >abs + + 1 | mRelative, // 50 bvc + 1 | mDPI | m_Y, // 51 eor (dp),y + 1 | mDPI, // 52 eor (dp) + 1 | mDPI | m_S | m_Y, // 53 eor ,s,y + 2 | mBlockMove, // 54 mvn x,x + 1 | mDP | m_X, // 55 eor dp,x + 1 | mDP | m_X, // 56 lsr dp,x + 1 | mDPIL | m_Y, // 57 eor [dp],y + 0 | mImplied, // 58 cli + 2 | mAbsolute | m_Y, // 59 eor |abs,y + 0 | mImplied, // 5a phy + 0 | mImplied, // 5b tcd + 3 | mAbsoluteLong, // 5c jml >abs + 2 | mAbsolute | m_X, // 5d eor |abs,x + 2 | mAbsolute | m_X, // 5e lsr |abs,x + 3 | mAbsoluteLong | m_X, // 5f eor >abs,x + + 0 | mImplied, // 60 rts + 1 | mDPI | m_X, // 61 adc (dp,x) + 2 | mRelative, // 62 per |abs + 1 | mDP | m_S, // 63 adc ,s + 1 | mDP, // 64 stz abs + + 1 | mRelative, // 70 bvs + 1 | mDPI | m_Y, // 71 adc (dp),y + 1 | mDPI, // 72 adc (dp) + 1 | mDPI | m_S | m_Y, // 73 adc ,s,y + 1 | mDP | m_X, // 74 stz dp,x + 1 | mDP | m_X, // 75 adc dp,x + 1 | mDP | m_X, // 76 ror dp,x + 1 | mDPIL | m_Y, // 77 adc [dp],y + 0 | mImplied, // 78 sei + 2 | mAbsolute | m_Y, // 79 adc |abs,y + 0 | mImplied, // 7a ply + 0 | mImplied, // 7b tdc + 2 | mAbsoluteI | m_X, // 7c jmp (abs,x) + 2 | mAbsolute | m_X, // 7d adc |abs,x + 2 | mAbsolute | m_X, // 7e ror |abs,x + 3 | mAbsoluteLong | m_X, // 7f adc >abs,x + + 1 | mRelative, // 80 bra + 1 | mDPI | m_X, // 81 sta (dp,x) + 2 | mRelative, // 82 brl |abs + 1 | mDP | m_S, // 83 sta ,s + 1 | mDP, // 84 sty abs + + 1 | mRelative, // 90 bcc + 1 | mDPI | m_Y, // 91 sta (dp),y + 1 | mDPI, // 92 sta (dp) + 1 | mDPI | m_S | m_Y, // 93 sta ,s,y + 1 | mDP | m_X, // 94 sty dp,x + 1 | mDP | m_X, // 95 sta dp,x + 1 | mDP | m_Y, // 96 stx dp,y + 1 | mDPIL | m_Y, // 97 sta [dp],y + 0 | mImplied, // 98 tya + 2 | mAbsolute | m_Y, // 99 sta |abs,y + 0 | mImplied, // 9a txs + 0 | mImplied, // 9b txy + 2 | mAbsolute, // 9c stz |abs + 2 | mAbsolute | m_X, // 9d sta |abs,x + 2 | mAbsolute | m_X, // 9e stz |abs,x + 3 | mAbsoluteLong | m_X, // 9f sta >abs,x + + 1 | mImmediate | m_I, // a0 ldy #imm + 1 | mDPI | m_X, // a1 lda (dp,x) + 1 | mImmediate | m_I, // a2 ldx #imm + 1 | mDP | m_S, // a3 lda ,s + 1 | mDP, // a4 ldy abs + + 1 | mRelative, // b0 bcs + 1 | mDPI | m_Y, // b1 lda (dp),y + 1 | mDPI, // b2 lda (dp) + 1 | mDPI | m_S | m_Y, // b3 lda ,s,y + 1 | mDP | m_X, // b4 ldy abs,x + + 1 | mImmediate | m_I, // c0 cpy #imm + 1 | mDPI | m_X, // c1 cmp (dp,x) + 1 | mAbsolute, // c2 rep # + 1 | mDP | m_S, // c3 cmp ,s + 1 | mDP, // c4 cpy abs + + 1 | mRelative, // d0 bne + 1 | mDPI | m_Y, // d1 cmp (dp),y + 1 | mDPI, // d2 cmp (dp) + 1 | mDPI | m_S | m_Y, // d3 cmp ,s,y + 1 | mDPI, // d4 pei (dp) + 1 | mDP | m_X, // d5 cmp dp,x + 1 | mDP | m_X, // d6 dec dp,x + 1 | mDPIL | m_Y, // d7 cmp [dp],y + 0 | mImplied, // d8 cld + 2 | mAbsolute | m_Y, // d9 cmp |abs,y + 0 | mImplied, // da phx + 0 | mImplied, // db stp + 2 | mAbsoluteIL, // dc jml [abs] + 2 | mAbsolute | m_X, // dd cmp |abs,x + 2 | mAbsolute | m_X, // de dec |abs,x + 3 | mAbsoluteLong | m_X, // df cmp >abs,x + + 1 | mImmediate | m_I, // e0 cpx #imm + 1 | mDPI | m_X, // e1 sbc (dp,x) + 1 | mAbsolute, // e2 sep #imm + 1 | mDP | m_S, // e3 sbc ,s + 1 | mDP, // e4 cpx abs + + 1 | mRelative, // f0 beq + 1 | mDPI | m_Y, // f1 sbc (dp),y + 1 | mDPI, // f2 sbc (dp) + 1 | mDPI | m_S | m_Y, // f3 sbc ,s,y + 2 | mAbsolute, // f4 pea |abs + 1 | mDP | m_X, // f5 sbc dp,x + 1 | mDP | m_X, // f6 inc dp,x + 1 | mDPIL | m_Y, // f7 sbc [dp],y + 0 | mImplied, // f8 sed + 2 | mAbsolute | m_Y, // f9 sbc |abs,y + 0 | mImplied, // fa plx + 0 | mImplied, // fb xce + 2 | mAbsoluteI, // fc jsr (abs) + 2 | mAbsolute | m_X, // fd sbc |abs,x + 2 | mAbsolute | m_X, // fe inc |abs,x + 3 | mAbsoluteLong | m_X, // ff sbc >abs,x + +}; + +unsigned init_flags(bool longM, bool longX) { + unsigned flags = 0; + if (longM) flags |= m_M; + if (longX) flags |= m_I; + return flags; +} + + +void dump(const std::vector &data, unsigned &pc) { + + int count = 0; + for (auto &x : data) { + if (count == 0) printf("\t.byte\t"); + else printf(", "); + printf("$%02x", x); + ++count; + ++pc; + if (count == 8) { printf("\n"); count = 0; } + } + if (count) printf("\n"); +} + +void disasm(const std::vector &data, unsigned &flags, unsigned &pc) { + int i = 0; + for (; i < data.size(); ) { + uint8_t op = data[i]; + int attr = modes[op]; + int size = attr & 0x0f; + + // check if size increase for m/x bits. + if (attr & flags & m_I) size++; + if (attr & flags & m_M) size++; + + if (i + size + 1 > data.size()) + break; + + ++i; + + printf("\t%.3s", &opcodes[op * 3]); + + switch(attr & 0xf000) { + case mImmediate: printf("\t#"); break; + case mDP: printf("\t<"); break; + case mAbsolute: printf("\t|"); break; + case mAbsoluteLong: printf("\t>"); break; + case mAbsoluteI: printf("("); break; + case mDPIL: printf("[<"); break; + } + + + uint32_t arg = 0; + for (int j = 0; j < size; ++j) { + arg |= (data[i++] << (8 * j)); + } + + // todo -- relative, block mode. + switch(size) { + case 0: break; + case 1: printf("$%02x", arg); break; + case 2: printf("$%04x", arg); break; + case 3: printf("$%06x", arg); break; + } + + switch(attr & 0x0f00) { + case m_X: printf(",x"); break; + case m_Y: if (!(attr & (mDPI|mDPIL))) printf(",y"); break; + case m_S: + case m_S | m_Y: + printf(",s"); break; + } + + switch(attr & 0xf000) { + case mAbsoluteI: + case mDPI: + printf(")"); break; + case mAbsoluteIL: + case mDPIL: + printf("]"); break; + } + + // (xxx,s),y + // (xxx),y + // [xxx],y + switch(attr & 0x0f00) { + case m_Y: if (attr & (mDPI|mDPIL)) printf(",y"); break; + case m_S | m_Y: + printf(",y"); break; + } + + switch(op) { + case 0xc2: // REP + if (arg & 0x20) flags |= m_M; + if (arg & 0x10) flags |= m_I; + case 0xe2: // SEP + if (arg & 0x20) flags &= ~m_M; + if (arg & 0x10) flags &= ~m_I; + break; + } + + printf("\n"); + pc += size + 1; + } + // any remaining data... + while (i < data.size()) { + printf("\t.byte\t$%02x\n", data[i]); + ++i; + ++pc; + } +} diff --git a/dumpobj.cpp b/dumpobj.cpp index 06a6af1..1045e39 100644 --- a/dumpobj.cpp +++ b/dumpobj.cpp @@ -19,6 +19,13 @@ enum class endian { }; + +extern unsigned init_flags(bool longM, bool longX); +void dump(const std::vector &data, unsigned &pc); +extern void disasm(const std::vector &data, unsigned &flags, unsigned &pc); + + + template void swap_if(T &t, std::false_type) {} @@ -175,6 +182,7 @@ void dump_obj(const char *name, int fd) uint8_t op = REC_END; uint32_t pc = 0; + unsigned flags = init_flags(true, true); auto iter = data.begin(); while (iter != data.end()) { @@ -182,9 +190,11 @@ void dump_obj(const char *name, int fd) op = read_8(iter); if (op == 0) break; if (op < 0xf0) { + std::vector tmp(iter, iter + op); + iter += op; - pc += op; printf("DATA: %02x\n", op); + disasm(tmp, flags, pc); continue; }