disassemble: initial disassembler

This commit is contained in:
Zack Buhman 2023-09-03 05:30:36 +00:00
parent ddf46ce8fd
commit 5cd19c51ce
7 changed files with 142 additions and 51 deletions

2
.gitignore vendored
View File

@ -1,6 +1,8 @@
main
scu-dsp-asm
scu-dsp-asm.*
scu-dsp-dis
scu-dsp-dis.*
.~*
*.o
*.gch

View File

@ -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:

View File

@ -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)
@ -42,30 +43,27 @@ struct control_word_t : stmt_accept_t<control_word_t>
std::vector<op_t> build_ops(uint32_t code)
{
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 (andl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<andl_t>, 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
View 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;
}
}

View File

@ -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)
{

View File

@ -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);
}

View File

@ -37,7 +37,7 @@ struct mov_ram_d1_t;
struct control_word_t;
}
namespace load{
namespace load {
struct mvi_t;
struct mvi_cond_t;
}