disassemble: initial disassembler
This commit is contained in:
parent
ddf46ce8fd
commit
5cd19c51ce
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,8 @@
|
|||||||
main
|
main
|
||||||
scu-dsp-asm
|
scu-dsp-asm
|
||||||
scu-dsp-asm.*
|
scu-dsp-asm.*
|
||||||
|
scu-dsp-dis
|
||||||
|
scu-dsp-dis.*
|
||||||
.~*
|
.~*
|
||||||
*.o
|
*.o
|
||||||
*.gch
|
*.gch
|
||||||
|
37
Makefile
37
Makefile
@ -3,28 +3,37 @@ CXXFLAGS = -Og -g -Wall -Wextra -Werror -Wfatal-errors -Wno-c99-designator -std=
|
|||||||
LDFLAGS =
|
LDFLAGS =
|
||||||
|
|
||||||
TARGET ?=
|
TARGET ?=
|
||||||
CXX = $(TARGET)clang++
|
CXX = $(TARGET)g++
|
||||||
|
|
||||||
SRC = main.cpp
|
ASM_SRC = main.cpp
|
||||||
SRC += lexer.cpp
|
ASM_SRC += lexer.cpp
|
||||||
SRC += ast_printer.cpp
|
ASM_SRC += ast_printer.cpp
|
||||||
SRC += ast_resolver.cpp
|
ASM_SRC += ast_resolver.cpp
|
||||||
SRC += ast_emitter.cpp
|
ASM_SRC += ast_emitter.cpp
|
||||||
SRC += parser.cpp
|
ASM_SRC += parser.cpp
|
||||||
SRC += stmt_string.cpp
|
ASM_SRC += stmt_string.cpp
|
||||||
OBJ = $(patsubst %.cpp,%.o,$(SRC))
|
ASM_OBJ = $(patsubst %.cpp,%.o,$(ASM_SRC))
|
||||||
DEP = $(patsubst %.cpp,%.d,$(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
|
%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -MMD -MF $(basename $<).d -c $< -o $@
|
$(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 $@
|
$(CXX) $(STATIC) $(LDFLAGS) $^ -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "stmt_base.hpp"
|
#include "stmt_base.hpp"
|
||||||
#include "stmt_ins.hpp"
|
#include "stmt_ins.hpp"
|
||||||
|
#include "ins.hpp"
|
||||||
|
|
||||||
namespace dsp {
|
namespace dsp {
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ using op_t = std::variant<andl_t,
|
|||||||
mov_imm_d1_t,
|
mov_imm_d1_t,
|
||||||
mov_ram_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)
|
control_word_t(std::vector<op_t> ops)
|
||||||
: ops(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> build_ops(uint32_t code)
|
||||||
{
|
{
|
||||||
std::vector<op_t> ops;
|
std::vector<op_t> ops;
|
||||||
if (andl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<andl_t>, code});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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});
|
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");
|
|
||||||
}
|
|
||||||
return ops;
|
return ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,9 +72,9 @@ struct control_word_t : stmt_accept_t<control_word_t>
|
|||||||
|
|
||||||
const std::vector<op_t> ops;
|
const std::vector<op_t> ops;
|
||||||
|
|
||||||
uint32_t mask() const { return 0b11 << 30; }
|
static constexpr uint32_t mask() { return 0b11 << 30; }
|
||||||
uint32_t code() const { return 0b00 << 30; }
|
static constexpr uint32_t code() { return 0b00 << 30; }
|
||||||
uint32_t bits() const { return 0; }
|
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>
|
template <typename T>
|
||||||
struct ins_t
|
struct ins_t
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
virtual uint32_t bits() const;
|
|
||||||
|
|
||||||
uint32_t render() const
|
uint32_t render() const
|
||||||
{
|
{
|
||||||
return T::code() | bits();
|
return T::code() | T::bits();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
static bool pred(uint32_t ins)
|
static bool pred(uint32_t ins)
|
||||||
{
|
{
|
||||||
|
3
main.cpp
3
main.cpp
@ -1,8 +1,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
|
||||||
#include <bitset>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <iomanip>
|
#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()) {
|
while (auto stmt_o = pass2.statement()) {
|
||||||
uint32_t output = (*stmt_o)->accept(&emitter);
|
uint32_t output = (*stmt_o)->accept(&emitter);
|
||||||
if (output != 0xffff'ffff) {
|
if (output != 0xffff'ffff) {
|
||||||
//std::cout << std::bitset<32>(output) << std::endl;
|
|
||||||
if (hex_output) write_hex(os, output);
|
if (hex_output) write_hex(os, output);
|
||||||
else write_raw(os, output);
|
else write_raw(os, output);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ struct mov_ram_d1_t;
|
|||||||
struct control_word_t;
|
struct control_word_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace load{
|
namespace load {
|
||||||
struct mvi_t;
|
struct mvi_t;
|
||||||
struct mvi_cond_t;
|
struct mvi_cond_t;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user