From 5cd19c51ce03d73d1143d1df0f83a582932ecae7 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sun, 3 Sep 2023 05:30:36 +0000 Subject: [PATCH] disassemble: initial disassembler --- .gitignore | 2 ++ Makefile | 37 ++++++++++++-------- control_word.hpp | 54 ++++++++++++++--------------- disassemble.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ ins.hpp | 6 +--- main.cpp | 3 -- visitable.hpp | 2 +- 7 files changed, 142 insertions(+), 51 deletions(-) create mode 100644 disassemble.cpp diff --git a/.gitignore b/.gitignore index ff325b4..ed1a363 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ main scu-dsp-asm scu-dsp-asm.* +scu-dsp-dis +scu-dsp-dis.* .~* *.o *.gch diff --git a/Makefile b/Makefile index 99aa9f9..bcf3c57 100644 --- a/Makefile +++ b/Makefile @@ -3,28 +3,37 @@ CXXFLAGS = -Og -g -Wall -Wextra -Werror -Wfatal-errors -Wno-c99-designator -std= LDFLAGS = TARGET ?= -CXX = $(TARGET)clang++ +CXX = $(TARGET)g++ -SRC = main.cpp -SRC += lexer.cpp -SRC += ast_printer.cpp -SRC += ast_resolver.cpp -SRC += ast_emitter.cpp -SRC += parser.cpp -SRC += stmt_string.cpp -OBJ = $(patsubst %.cpp,%.o,$(SRC)) -DEP = $(patsubst %.cpp,%.d,$(SRC)) +ASM_SRC = main.cpp +ASM_SRC += lexer.cpp +ASM_SRC += ast_printer.cpp +ASM_SRC += ast_resolver.cpp +ASM_SRC += ast_emitter.cpp +ASM_SRC += parser.cpp +ASM_SRC += stmt_string.cpp +ASM_OBJ = $(patsubst %.cpp,%.o,$(ASM_SRC)) +ASM_DEP = $(patsubst %.cpp,%.d,$(ASM_SRC)) +ASM_MAIN ?= scu-dsp-asm -MAIN ?= scu-dsp-asm +DIS_SRC = disassemble.cpp +DIS_SRC += ast_printer.cpp +DIS_SRC += stmt_string.cpp +DIS_OBJ = $(patsubst %.cpp,%.o,$(DIS_SRC)) +DIS_DEP = $(patsubst %.cpp,%.d,$(DIS_SRC)) +DIS_MAIN ?= scu-dsp-dis -all: $(MAIN) +all: $(ASM_MAIN) $(DIS_MAIN) --include $(DEP) +-include $(sort $(ASM_DEP) $(DIS_DEP)) %.o: %.cpp $(CXX) $(CXXFLAGS) -MMD -MF $(basename $<).d -c $< -o $@ -$(MAIN): $(OBJ) +$(SRC_MAIN): $(SRC_OBJ) + $(CXX) $(STATIC) $(LDFLAGS) $^ -o $@ + +$(DIS_MAIN): $(DIS_OBJ) $(CXX) $(STATIC) $(LDFLAGS) $^ -o $@ clean: diff --git a/control_word.hpp b/control_word.hpp index c58f773..90fbcdc 100644 --- a/control_word.hpp +++ b/control_word.hpp @@ -7,6 +7,7 @@ #include "stmt_base.hpp" #include "stmt_ins.hpp" +#include "ins.hpp" namespace dsp { @@ -32,7 +33,7 @@ using op_t = std::variant; -struct control_word_t : stmt_accept_t +struct control_word_t : stmt_accept_t, ins_t { control_word_t(std::vector ops) : ops(ops) @@ -42,30 +43,27 @@ struct control_word_t : stmt_accept_t std::vector build_ops(uint32_t code) { std::vector ops; - if (andl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (orl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (xorl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (add_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (sub_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (ad2_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (sr_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (rr_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (sl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (rl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (rl8_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (mov_ram_x_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (mov_mul_p_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (mov_ram_p_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (mov_ram_y_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (clr_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (mov_alu_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (mov_ram_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (mov_imm_d1_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else if (mov_ram_d1_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); - else { - std::cerr << "invalid control word code: " << (code) << std::endl; - throw std::runtime_error("invalid control word code"); - } + if (andl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (orl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (xorl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (add_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (sub_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (ad2_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (sr_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (rr_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (sl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (rl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (rl8_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (mov_ram_x_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (mov_mul_p_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (mov_ram_p_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (mov_ram_y_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (clr_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (mov_alu_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (mov_ram_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (mov_imm_d1_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + if (mov_ram_d1_t::pred(code)) ops.emplace_back(op_t{std::in_place_type, code}); + return ops; } @@ -74,9 +72,9 @@ struct control_word_t : stmt_accept_t const std::vector ops; - uint32_t mask() const { return 0b11 << 30; } - uint32_t code() const { return 0b00 << 30; } - uint32_t bits() const { return 0; } + static constexpr uint32_t mask() { return 0b11 << 30; } + static constexpr uint32_t code() { return 0b00 << 30; } + static constexpr uint32_t bits() { return 0; } }; } diff --git a/disassemble.cpp b/disassemble.cpp new file mode 100644 index 0000000..b3fa828 --- /dev/null +++ b/disassemble.cpp @@ -0,0 +1,89 @@ +#include +#include +#include + +#include "stmt.hpp" +#include "stmt_ins.hpp" +#include "control_word.hpp" +#include "ast_printer.hpp" + +static uint32_t uint32_be(std::string_view v) +{ + return static_cast(v[0]) << 24 + | static_cast(v[1]) << 16 + | static_cast(v[2]) << 8 + | static_cast(v[3]) << 0; +} + +static dsp::stmt_t * decompile(uint32_t code) +{ + using namespace dsp::op; + using namespace dsp::load; + using namespace dsp::dma; + using namespace dsp::jump; + using namespace dsp::loop; + using namespace dsp::end; + using namespace dsp::nop; + + if (control_word_t::pred(code)) return new control_word_t(code); + else if (mvi_t::pred(code)) return new mvi_t(code); + else if (mvi_cond_t::pred(code)) return new mvi_cond_t(code); + else if (d0_dst_imm_t::pred(code)) return new d0_dst_imm_t(code); + else if (src_d0_imm_t::pred(code)) return new src_d0_imm_t(code); + else if (d0_dst_ram_t::pred(code)) return new d0_dst_ram_t(code); + else if (src_d0_ram_t::pred(code)) return new src_d0_ram_t(code); + else if (jmp_t::pred(code)) return new jmp_t(code); + else if (jmp_cond_t::pred(code)) return new jmp_cond_t(code); + else if (btm_t::pred(code)) return new btm_t(code); + else if (lps_t::pred(code)) return new lps_t(code); + else if (end_t::pred(code)) return new end_t(code); + else if (endi_t::pred(code)) return new endi_t(code); + else + throw std::runtime_error("undefined code"); +} + +static void run(std::string source) +{ + std::string_view buf(source); + dsp::ast::printer_t printer(std::cout); + + for (decltype(buf)::size_type i = 0; i < (buf.length() / 4); i++) { + uint32_t code = uint32_be(buf.substr(i * 4, 4)); + + dsp::stmt_t * stmt = decompile(code); + stmt->accept(&printer); + std::cout << std::endl; + } +} + +static int run_file(char const * const input_filename) +{ + std::ifstream is {input_filename, std::ios::binary | std::ios::ate}; + if (!is.is_open()) { + std::cerr << "failed to open " << input_filename << std::endl; + return -1; + } + const std::streampos size = is.tellg(); + std::string buf(size, '\0'); + is.seekg(0); + if (!is.read(&buf[0], size)) { + std::cerr << "read failed" << std::endl; + return -1; + } + + run(buf); + + return 0; +} + +int main(const int argc, char const * const argv[]) +{ + const std::string c_source("-s"); + + switch (argc) { + case 2: return run_file(argv[1]); + default: + std::cerr << "Usage: " << argv[0] << " input-filename" << std::endl; + return -1; + } +} diff --git a/ins.hpp b/ins.hpp index d6a4604..e3c23c1 100644 --- a/ins.hpp +++ b/ins.hpp @@ -9,14 +9,10 @@ namespace dsp { template struct ins_t { - /* - virtual uint32_t bits() const; - uint32_t render() const { - return T::code() | bits(); + return T::code() | T::bits(); } - */ static bool pred(uint32_t ins) { diff --git a/main.cpp b/main.cpp index f746505..3c328d5 100644 --- a/main.cpp +++ b/main.cpp @@ -1,8 +1,6 @@ #include #include #include -#include -#include #include #include #include @@ -72,7 +70,6 @@ static void run(std::ostream& os, std::string source, bool hex_output, bool verb while (auto stmt_o = pass2.statement()) { uint32_t output = (*stmt_o)->accept(&emitter); if (output != 0xffff'ffff) { - //std::cout << std::bitset<32>(output) << std::endl; if (hex_output) write_hex(os, output); else write_raw(os, output); } diff --git a/visitable.hpp b/visitable.hpp index 453d055..7d4f931 100644 --- a/visitable.hpp +++ b/visitable.hpp @@ -37,7 +37,7 @@ struct mov_ram_d1_t; struct control_word_t; } -namespace load{ +namespace load { struct mvi_t; struct mvi_cond_t; }