disassemble: initial disassembler
This commit is contained in:
parent
ddf46ce8fd
commit
5cd19c51ce
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,8 @@
|
||||
main
|
||||
scu-dsp-asm
|
||||
scu-dsp-asm.*
|
||||
scu-dsp-dis
|
||||
scu-dsp-dis.*
|
||||
.~*
|
||||
*.o
|
||||
*.gch
|
||||
|
37
Makefile
37
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:
|
||||
|
@ -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<andl_t,
|
||||
mov_imm_d1_t,
|
||||
mov_ram_d1_t>;
|
||||
|
||||
struct control_word_t : stmt_accept_t<control_word_t>
|
||||
struct control_word_t : stmt_accept_t<control_word_t>, ins_t<control_word_t>
|
||||
{
|
||||
control_word_t(std::vector<op_t> ops)
|
||||
: ops(ops)
|
||||
@ -43,29 +44,26 @@ struct control_word_t : stmt_accept_t<control_word_t>
|
||||
{
|
||||
std::vector<op_t> ops;
|
||||
if (andl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<andl_t>, code});
|
||||
else if (orl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<orl_t>, code});
|
||||
else if (xorl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<xorl_t>, code});
|
||||
else if (add_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<add_t>, code});
|
||||
else if (sub_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<sub_t>, code});
|
||||
else if (ad2_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<ad2_t>, code});
|
||||
else if (sr_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<sr_t>, code});
|
||||
else if (rr_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<rr_t>, code});
|
||||
else if (sl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<sl_t>, code});
|
||||
else if (rl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<rl_t>, code});
|
||||
else if (rl8_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<rl8_t>, code});
|
||||
else if (mov_ram_x_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_x_t>, code});
|
||||
else if (mov_mul_p_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_mul_p_t>, code});
|
||||
else if (mov_ram_p_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_p_t>, code});
|
||||
else if (mov_ram_y_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_y_t>, code});
|
||||
else if (clr_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<clr_a_t>, code});
|
||||
else if (mov_alu_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_alu_a_t>, code});
|
||||
else if (mov_ram_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_a_t>, code});
|
||||
else if (mov_imm_d1_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_imm_d1_t>, code});
|
||||
else if (mov_ram_d1_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_d1_t>, code});
|
||||
else {
|
||||
std::cerr << "invalid control word code: " << (code) << std::endl;
|
||||
throw std::runtime_error("invalid control word code");
|
||||
}
|
||||
if (orl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<orl_t>, code});
|
||||
if (xorl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<xorl_t>, code});
|
||||
if (add_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<add_t>, code});
|
||||
if (sub_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<sub_t>, code});
|
||||
if (ad2_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<ad2_t>, code});
|
||||
if (sr_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<sr_t>, code});
|
||||
if (rr_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<rr_t>, code});
|
||||
if (sl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<sl_t>, code});
|
||||
if (rl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<rl_t>, code});
|
||||
if (rl8_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<rl8_t>, code});
|
||||
if (mov_ram_x_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_x_t>, code});
|
||||
if (mov_mul_p_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_mul_p_t>, code});
|
||||
if (mov_ram_p_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_p_t>, code});
|
||||
if (mov_ram_y_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_y_t>, code});
|
||||
if (clr_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<clr_a_t>, code});
|
||||
if (mov_alu_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_alu_a_t>, code});
|
||||
if (mov_ram_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_a_t>, code});
|
||||
if (mov_imm_d1_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_imm_d1_t>, code});
|
||||
if (mov_ram_d1_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_d1_t>, code});
|
||||
|
||||
return ops;
|
||||
}
|
||||
|
||||
@ -74,9 +72,9 @@ struct control_word_t : stmt_accept_t<control_word_t>
|
||||
|
||||
const std::vector<op_t> 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; }
|
||||
};
|
||||
|
||||
}
|
||||
|
89
disassemble.cpp
Normal file
89
disassemble.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
#include <fstream>
|
||||
|
||||
#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<uint8_t>(v[0]) << 24
|
||||
| static_cast<uint8_t>(v[1]) << 16
|
||||
| static_cast<uint8_t>(v[2]) << 8
|
||||
| static_cast<uint8_t>(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;
|
||||
}
|
||||
}
|
6
ins.hpp
6
ins.hpp
@ -9,14 +9,10 @@ namespace dsp {
|
||||
template <typename T>
|
||||
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)
|
||||
{
|
||||
|
3
main.cpp
3
main.cpp
@ -1,8 +1,6 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <bitset>
|
||||
#include <sstream>
|
||||
#include <array>
|
||||
#include <iomanip>
|
||||
@ -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);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ struct mov_ram_d1_t;
|
||||
struct control_word_t;
|
||||
}
|
||||
|
||||
namespace load{
|
||||
namespace load {
|
||||
struct mvi_t;
|
||||
struct mvi_cond_t;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user