add support for linking multiple programs + binaries
This commit is contained in:
parent
b60dbed70b
commit
210a8d1b06
4
Makefile
4
Makefile
@ -4,8 +4,8 @@ LDFLAGS =
|
|||||||
TARGET =
|
TARGET =
|
||||||
CXX = $(TARGET)g++
|
CXX = $(TARGET)g++
|
||||||
|
|
||||||
OBJS = main.o fromstring.o addressing_mode.o codec.o parser.o
|
OBJS = main.o tostring.o fromstring.o addressing_mode.o codec.o parser.o symbol.o
|
||||||
HEADERS = $(wildcard *.h)
|
HEADERS = $(wildcard *.hh)
|
||||||
|
|
||||||
all: main
|
all: main
|
||||||
|
|
||||||
|
24
assembler.hh
24
assembler.hh
@ -3,6 +3,8 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "isa.hh"
|
#include "isa.hh"
|
||||||
|
|
||||||
@ -24,7 +26,27 @@ namespace assembler {
|
|||||||
isa::mode mode;
|
isa::mode mode;
|
||||||
std::variant<literal_t, reference_t, implied_t> value;
|
std::variant<literal_t, reference_t, implied_t> value;
|
||||||
size_t location;
|
size_t location;
|
||||||
|
ssize_t row; // debug
|
||||||
};
|
};
|
||||||
|
|
||||||
using program_t = std::vector<instruction_t>;
|
struct blob_t {
|
||||||
|
struct {
|
||||||
|
size_t start;
|
||||||
|
size_t start_l;
|
||||||
|
size_t start_h;
|
||||||
|
size_t size_l;
|
||||||
|
size_t size_h;
|
||||||
|
} symbol;
|
||||||
|
size_t location;
|
||||||
|
std::shared_ptr<std::string> buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
using program_t = std::vector<std::variant<instruction_t, blob_t>>;
|
||||||
|
|
||||||
|
struct symbol_strings_t {
|
||||||
|
size_t current_symbol;
|
||||||
|
std::unordered_map<std::string, size_t> map;
|
||||||
|
};
|
||||||
|
|
||||||
|
using symbol_table_t = std::unordered_map<size_t, size_t>;
|
||||||
}
|
}
|
||||||
|
28
codec.cc
28
codec.cc
@ -10,7 +10,7 @@ namespace codec {
|
|||||||
const std::map<std::tuple<isa::op, isa::mode>, uint8_t>& encode() {
|
const std::map<std::tuple<isa::op, isa::mode>, uint8_t>& encode() {
|
||||||
static const std::map<std::tuple<isa::op, isa::mode>, uint8_t> _ = {
|
static const std::map<std::tuple<isa::op, isa::mode>, uint8_t> _ = {
|
||||||
{{isa::op::BRK, isa::mode::S}, 0},
|
{{isa::op::BRK, isa::mode::S}, 0},
|
||||||
{{isa::op::ORA, isa::mode::ZPX}, 1},
|
{{isa::op::ORA, isa::mode::ZPII}, 1},
|
||||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 2},
|
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 2},
|
||||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 3},
|
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 3},
|
||||||
{{isa::op::TSB, isa::mode::ZP}, 4},
|
{{isa::op::TSB, isa::mode::ZP}, 4},
|
||||||
@ -19,7 +19,7 @@ namespace codec {
|
|||||||
{{isa::op::RMB0, isa::mode::ZP}, 7},
|
{{isa::op::RMB0, isa::mode::ZP}, 7},
|
||||||
{{isa::op::PHP, isa::mode::S}, 8},
|
{{isa::op::PHP, isa::mode::S}, 8},
|
||||||
{{isa::op::ORA, isa::mode::IMM}, 9},
|
{{isa::op::ORA, isa::mode::IMM}, 9},
|
||||||
{{isa::op::ASL, isa::mode::A}, 10},
|
{{isa::op::ASL, isa::mode::ACC}, 10},
|
||||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 11},
|
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 11},
|
||||||
{{isa::op::TSB, isa::mode::A}, 12},
|
{{isa::op::TSB, isa::mode::A}, 12},
|
||||||
{{isa::op::ORA, isa::mode::A}, 13},
|
{{isa::op::ORA, isa::mode::A}, 13},
|
||||||
@ -36,7 +36,7 @@ namespace codec {
|
|||||||
{{isa::op::RMB1, isa::mode::ZP}, 23},
|
{{isa::op::RMB1, isa::mode::ZP}, 23},
|
||||||
{{isa::op::CLC, isa::mode::I}, 24},
|
{{isa::op::CLC, isa::mode::I}, 24},
|
||||||
{{isa::op::ORA, isa::mode::AIY}, 25},
|
{{isa::op::ORA, isa::mode::AIY}, 25},
|
||||||
{{isa::op::INC, isa::mode::A}, 26},
|
{{isa::op::INC, isa::mode::ACC}, 26},
|
||||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 27},
|
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 27},
|
||||||
{{isa::op::TRB, isa::mode::A}, 28},
|
{{isa::op::TRB, isa::mode::A}, 28},
|
||||||
{{isa::op::ORA, isa::mode::AIX}, 29},
|
{{isa::op::ORA, isa::mode::AIX}, 29},
|
||||||
@ -53,7 +53,7 @@ namespace codec {
|
|||||||
{{isa::op::RMB2, isa::mode::ZP}, 39},
|
{{isa::op::RMB2, isa::mode::ZP}, 39},
|
||||||
{{isa::op::PLP, isa::mode::S}, 40},
|
{{isa::op::PLP, isa::mode::S}, 40},
|
||||||
{{isa::op::AND, isa::mode::IMM}, 41},
|
{{isa::op::AND, isa::mode::IMM}, 41},
|
||||||
{{isa::op::ROL, isa::mode::A}, 42},
|
{{isa::op::ROL, isa::mode::ACC}, 42},
|
||||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 43},
|
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 43},
|
||||||
{{isa::op::BIT, isa::mode::A}, 44},
|
{{isa::op::BIT, isa::mode::A}, 44},
|
||||||
{{isa::op::AND, isa::mode::A}, 45},
|
{{isa::op::AND, isa::mode::A}, 45},
|
||||||
@ -70,7 +70,7 @@ namespace codec {
|
|||||||
{{isa::op::RMB3, isa::mode::ZP}, 55},
|
{{isa::op::RMB3, isa::mode::ZP}, 55},
|
||||||
{{isa::op::SEC, isa::mode::I}, 56},
|
{{isa::op::SEC, isa::mode::I}, 56},
|
||||||
{{isa::op::AND, isa::mode::AIY}, 57},
|
{{isa::op::AND, isa::mode::AIY}, 57},
|
||||||
{{isa::op::DEC, isa::mode::A}, 58},
|
{{isa::op::DEC, isa::mode::ACC}, 58},
|
||||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 59},
|
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 59},
|
||||||
{{isa::op::BIT, isa::mode::AIX}, 60},
|
{{isa::op::BIT, isa::mode::AIX}, 60},
|
||||||
{{isa::op::AND, isa::mode::AIX}, 61},
|
{{isa::op::AND, isa::mode::AIX}, 61},
|
||||||
@ -87,7 +87,7 @@ namespace codec {
|
|||||||
{{isa::op::RMB4, isa::mode::ZP}, 71},
|
{{isa::op::RMB4, isa::mode::ZP}, 71},
|
||||||
{{isa::op::PHA, isa::mode::S}, 72},
|
{{isa::op::PHA, isa::mode::S}, 72},
|
||||||
{{isa::op::EOR, isa::mode::IMM}, 73},
|
{{isa::op::EOR, isa::mode::IMM}, 73},
|
||||||
{{isa::op::LSR, isa::mode::A}, 74},
|
{{isa::op::LSR, isa::mode::ACC}, 74},
|
||||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 75},
|
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 75},
|
||||||
{{isa::op::JMP, isa::mode::A}, 76},
|
{{isa::op::JMP, isa::mode::A}, 76},
|
||||||
{{isa::op::EOR, isa::mode::A}, 77},
|
{{isa::op::EOR, isa::mode::A}, 77},
|
||||||
@ -121,7 +121,7 @@ namespace codec {
|
|||||||
{{isa::op::RMB6, isa::mode::ZP}, 103},
|
{{isa::op::RMB6, isa::mode::ZP}, 103},
|
||||||
{{isa::op::PLA, isa::mode::S}, 104},
|
{{isa::op::PLA, isa::mode::S}, 104},
|
||||||
{{isa::op::ADC, isa::mode::IMM}, 105},
|
{{isa::op::ADC, isa::mode::IMM}, 105},
|
||||||
{{isa::op::ROR, isa::mode::A}, 106},
|
{{isa::op::ROR, isa::mode::ACC}, 106},
|
||||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 107},
|
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 107},
|
||||||
{{isa::op::JMP, isa::mode::AI}, 108},
|
{{isa::op::JMP, isa::mode::AI}, 108},
|
||||||
{{isa::op::ADC, isa::mode::A}, 109},
|
{{isa::op::ADC, isa::mode::A}, 109},
|
||||||
@ -287,7 +287,7 @@ namespace codec {
|
|||||||
const std::map<uint8_t, std::tuple<isa::op, isa::mode>>& decode() {
|
const std::map<uint8_t, std::tuple<isa::op, isa::mode>>& decode() {
|
||||||
static const std::map<uint8_t, std::tuple<isa::op, isa::mode>> _ = {
|
static const std::map<uint8_t, std::tuple<isa::op, isa::mode>> _ = {
|
||||||
{0, {isa::op::BRK, isa::mode::S}},
|
{0, {isa::op::BRK, isa::mode::S}},
|
||||||
{1, {isa::op::ORA, isa::mode::ZPX}},
|
{1, {isa::op::ORA, isa::mode::ZPII}},
|
||||||
//{2, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
//{2, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||||
//{3, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
//{3, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||||
{4, {isa::op::TSB, isa::mode::ZP}},
|
{4, {isa::op::TSB, isa::mode::ZP}},
|
||||||
@ -296,7 +296,7 @@ namespace codec {
|
|||||||
{7, {isa::op::RMB0, isa::mode::ZP}},
|
{7, {isa::op::RMB0, isa::mode::ZP}},
|
||||||
{8, {isa::op::PHP, isa::mode::S}},
|
{8, {isa::op::PHP, isa::mode::S}},
|
||||||
{9, {isa::op::ORA, isa::mode::IMM}},
|
{9, {isa::op::ORA, isa::mode::IMM}},
|
||||||
{10, {isa::op::ASL, isa::mode::A}},
|
{10, {isa::op::ASL, isa::mode::ACC}},
|
||||||
//{11, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
//{11, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||||
{12, {isa::op::TSB, isa::mode::A}},
|
{12, {isa::op::TSB, isa::mode::A}},
|
||||||
{13, {isa::op::ORA, isa::mode::A}},
|
{13, {isa::op::ORA, isa::mode::A}},
|
||||||
@ -313,7 +313,7 @@ namespace codec {
|
|||||||
{23, {isa::op::RMB1, isa::mode::ZP}},
|
{23, {isa::op::RMB1, isa::mode::ZP}},
|
||||||
{24, {isa::op::CLC, isa::mode::I}},
|
{24, {isa::op::CLC, isa::mode::I}},
|
||||||
{25, {isa::op::ORA, isa::mode::AIY}},
|
{25, {isa::op::ORA, isa::mode::AIY}},
|
||||||
{26, {isa::op::INC, isa::mode::A}},
|
{26, {isa::op::INC, isa::mode::ACC}},
|
||||||
//{27, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
//{27, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||||
{28, {isa::op::TRB, isa::mode::A}},
|
{28, {isa::op::TRB, isa::mode::A}},
|
||||||
{29, {isa::op::ORA, isa::mode::AIX}},
|
{29, {isa::op::ORA, isa::mode::AIX}},
|
||||||
@ -330,7 +330,7 @@ namespace codec {
|
|||||||
{39, {isa::op::RMB2, isa::mode::ZP}},
|
{39, {isa::op::RMB2, isa::mode::ZP}},
|
||||||
{40, {isa::op::PLP, isa::mode::S}},
|
{40, {isa::op::PLP, isa::mode::S}},
|
||||||
{41, {isa::op::AND, isa::mode::IMM}},
|
{41, {isa::op::AND, isa::mode::IMM}},
|
||||||
{42, {isa::op::ROL, isa::mode::A}},
|
{42, {isa::op::ROL, isa::mode::ACC}},
|
||||||
//{43, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
//{43, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||||
{44, {isa::op::BIT, isa::mode::A}},
|
{44, {isa::op::BIT, isa::mode::A}},
|
||||||
{45, {isa::op::AND, isa::mode::A}},
|
{45, {isa::op::AND, isa::mode::A}},
|
||||||
@ -347,7 +347,7 @@ namespace codec {
|
|||||||
{55, {isa::op::RMB3, isa::mode::ZP}},
|
{55, {isa::op::RMB3, isa::mode::ZP}},
|
||||||
{56, {isa::op::SEC, isa::mode::I}},
|
{56, {isa::op::SEC, isa::mode::I}},
|
||||||
{57, {isa::op::AND, isa::mode::AIY}},
|
{57, {isa::op::AND, isa::mode::AIY}},
|
||||||
{58, {isa::op::DEC, isa::mode::A}},
|
{58, {isa::op::DEC, isa::mode::ACC}},
|
||||||
//{59, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
//{59, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||||
{60, {isa::op::BIT, isa::mode::AIX}},
|
{60, {isa::op::BIT, isa::mode::AIX}},
|
||||||
{61, {isa::op::AND, isa::mode::AIX}},
|
{61, {isa::op::AND, isa::mode::AIX}},
|
||||||
@ -364,7 +364,7 @@ namespace codec {
|
|||||||
{71, {isa::op::RMB4, isa::mode::ZP}},
|
{71, {isa::op::RMB4, isa::mode::ZP}},
|
||||||
{72, {isa::op::PHA, isa::mode::S}},
|
{72, {isa::op::PHA, isa::mode::S}},
|
||||||
{73, {isa::op::EOR, isa::mode::IMM}},
|
{73, {isa::op::EOR, isa::mode::IMM}},
|
||||||
{74, {isa::op::LSR, isa::mode::A}},
|
{74, {isa::op::LSR, isa::mode::ACC}},
|
||||||
//{75, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
//{75, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||||
{76, {isa::op::JMP, isa::mode::A}},
|
{76, {isa::op::JMP, isa::mode::A}},
|
||||||
{77, {isa::op::EOR, isa::mode::A}},
|
{77, {isa::op::EOR, isa::mode::A}},
|
||||||
@ -398,7 +398,7 @@ namespace codec {
|
|||||||
{103, {isa::op::RMB6, isa::mode::ZP}},
|
{103, {isa::op::RMB6, isa::mode::ZP}},
|
||||||
{104, {isa::op::PLA, isa::mode::S}},
|
{104, {isa::op::PLA, isa::mode::S}},
|
||||||
{105, {isa::op::ADC, isa::mode::IMM}},
|
{105, {isa::op::ADC, isa::mode::IMM}},
|
||||||
{106, {isa::op::ROR, isa::mode::A}},
|
{106, {isa::op::ROR, isa::mode::ACC}},
|
||||||
//{107, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
//{107, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||||
{108, {isa::op::JMP, isa::mode::AI}},
|
{108, {isa::op::JMP, isa::mode::AI}},
|
||||||
{109, {isa::op::ADC, isa::mode::A}},
|
{109, {isa::op::ADC, isa::mode::A}},
|
||||||
|
164
main.cc
164
main.cc
@ -2,83 +2,69 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "assembler.hh"
|
#include "assembler.hh"
|
||||||
#include "addressing_mode.hh"
|
#include "addressing_mode.hh"
|
||||||
#include "codec.hh"
|
#include "codec.hh"
|
||||||
#include "parser.hh"
|
#include "parser.hh"
|
||||||
|
#include "tostring.hh"
|
||||||
|
#include "symbol.hh"
|
||||||
|
|
||||||
using symbol_table_t = std::unordered_map<size_t, assembler::program_t::const_iterator>;
|
using namespace std::literals;
|
||||||
|
|
||||||
bool resolve_symbols(assembler::program_t& program, symbol_table_t& symbol_table)
|
void serialize_program(const assembler::program_t& program, const assembler::symbol_table_t &symbol_table, std::ostream& out)
|
||||||
{
|
{
|
||||||
size_t offset = 0;
|
auto serialize_instruction = [&](assembler::instruction_t& ins) -> void {
|
||||||
|
//std::cerr << "enc " << (int)ins.op << ' ' << (int)ins.mode << '\n';
|
||||||
|
char buf[3];
|
||||||
|
|
||||||
for (auto ins = program.begin(); ins != program.end(); ins++) {
|
auto opcode_it = codec::encode().find({ins.op, ins.mode});
|
||||||
if (ins->symbol != std::nullopt) {
|
if (opcode_it == codec::encode().end()) {
|
||||||
auto [_, ok] = symbol_table.insert({*(ins->symbol), ins});
|
std::cerr << ins.row << ": illegal op,mode: "
|
||||||
if (!ok) {
|
<< tostring::op().find(ins.op)->second << ' '
|
||||||
std::cout << "duplicate symbol\n";
|
<< tostring::mode().find(ins.mode)->second << '\n';
|
||||||
return false;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << *(ins->symbol) << ' ' << offset << '\n';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ins->location = offset;
|
|
||||||
|
|
||||||
auto am_it = addressing_mode().find(ins->mode);
|
|
||||||
assert (am_it != addressing_mode().end());
|
|
||||||
offset += 1 + am_it->second.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serialize_program(const assembler::program_t& program, const symbol_table_t &symbol_table, size_t link_location, std::ostream& out)
|
|
||||||
{
|
|
||||||
char buf[3];
|
|
||||||
|
|
||||||
for (auto ins = program.cbegin(); ins != program.cend(); ins++) {
|
|
||||||
std::cerr << "enc " << (int)ins->op << ' ' << (int)ins->mode << '\n';
|
|
||||||
auto opcode_it = codec::encode().find({ins->op, ins->mode});
|
|
||||||
assert (opcode_it != codec::encode().end());
|
|
||||||
|
|
||||||
buf[0] = opcode_it->second;
|
buf[0] = opcode_it->second;
|
||||||
|
|
||||||
auto am_it = addressing_mode().find(ins->mode);
|
auto am_it = addressing_mode().find(ins.mode);
|
||||||
assert (am_it != addressing_mode().end());
|
assert (am_it != addressing_mode().end());
|
||||||
|
|
||||||
auto get_value = [&]() -> ssize_t {
|
auto get_value = [&]() -> ssize_t {
|
||||||
if (std::holds_alternative<assembler::reference_t>(ins->value)) {
|
if (std::holds_alternative<assembler::reference_t>(ins.value)) {
|
||||||
assembler::reference_t ref = std::get<assembler::reference_t>(ins->value);
|
assembler::reference_t ref = std::get<assembler::reference_t>(ins.value);
|
||||||
auto sym_it = symbol_table.find(ref.symbol);
|
auto sym_it = symbol_table.find(ref.symbol);
|
||||||
assert (sym_it != symbol_table.end());
|
if (sym_it == symbol_table.end()) {
|
||||||
auto ref_ins = sym_it->second;
|
std::cerr << "get_value: " << ref.symbol << '\n';
|
||||||
if (ins->mode == isa::mode::R) {
|
assert(false);
|
||||||
std::cout << "relative\n";
|
}
|
||||||
ssize_t offset = static_cast<ssize_t>(ref_ins->location) - static_cast<ssize_t>(ins->location + 2);
|
auto ref_location = sym_it->second;
|
||||||
|
if (ins.mode == isa::mode::R) {
|
||||||
|
ssize_t offset = static_cast<ssize_t>(ref_location) - static_cast<ssize_t>(ins.location + 2);
|
||||||
return offset;
|
return offset;
|
||||||
} else {
|
} else {
|
||||||
return ref_ins->location + link_location;
|
return ref_location;
|
||||||
}
|
}
|
||||||
} else if (std::holds_alternative<assembler::literal_t>(ins->value)) {
|
} else if (std::holds_alternative<assembler::literal_t>(ins.value)) {
|
||||||
assembler::literal_t lit = std::get<assembler::literal_t>(ins->value);
|
assembler::literal_t lit = std::get<assembler::literal_t>(ins.value);
|
||||||
return lit.num;
|
return lit.num;
|
||||||
} else if (std::holds_alternative<assembler::implied_t>(ins->value)) {
|
} else if (std::holds_alternative<assembler::implied_t>(ins.value)) {
|
||||||
assert (std::holds_alternative<assembler::implied_t>(ins->value));
|
//assert (std::holds_alternative<assembler::implied_t>(ins.value));
|
||||||
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
assert (false);
|
assert (false);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t value = get_value();
|
size_t value = get_value();
|
||||||
if (!am_it->second.valid(value)) {
|
if (!am_it->second.valid(value)) {
|
||||||
std::cout << "overflow at h" << std::hex << ins->location << '\n';
|
std::cerr << "overflow at " << ins.row << " value: " << value << '\n';
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "value " << std::hex << value << ' ' << am_it->second.len << '\n';
|
//std::cerr << "value " << std::hex << value << ' ' << am_it->second.len << '\n';
|
||||||
|
|
||||||
if (am_it->second.len >= 2)
|
if (am_it->second.len >= 2)
|
||||||
buf[2] = (value >> 8) & 0xff;
|
buf[2] = (value >> 8) & 0xff;
|
||||||
@ -86,6 +72,19 @@ void serialize_program(const assembler::program_t& program, const symbol_table_t
|
|||||||
buf[1] = (value >> 0) & 0xff;
|
buf[1] = (value >> 0) & 0xff;
|
||||||
|
|
||||||
out.write(buf, 1 + am_it->second.len);
|
out.write(buf, 1 + am_it->second.len);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
for (auto prog_it = program.cbegin(); prog_it != program.cend(); prog_it++) {
|
||||||
|
if (std::holds_alternative<assembler::instruction_t>(*prog_it)) {
|
||||||
|
auto ins = std::get<assembler::instruction_t>(*prog_it);
|
||||||
|
serialize_instruction(ins);
|
||||||
|
} else if (std::holds_alternative<assembler::blob_t>(*prog_it)) {
|
||||||
|
auto blob = std::get<assembler::blob_t>(*prog_it);
|
||||||
|
out.write(blob.buf->data(), blob.buf->size());
|
||||||
|
} else {
|
||||||
|
assert (false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,41 +95,66 @@ int main(int argc, char * argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string input_filename {argv[1]};
|
|
||||||
std::ifstream is {input_filename, std::ios::binary | std::ios::ate};
|
|
||||||
if (!is.is_open()) {
|
|
||||||
std::cerr << "failed to open " << input_filename << '\n';
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto size = is.tellg();
|
|
||||||
std::string buf(size, '\0'); // construct string to stream size
|
|
||||||
is.seekg(0);
|
|
||||||
is.read(buf.data(), size);
|
|
||||||
is.close();
|
|
||||||
|
|
||||||
|
|
||||||
assembler::program_t program;
|
assembler::program_t program;
|
||||||
symbol_table_t symbol_table;
|
assembler::symbol_strings_t symbol_strings;
|
||||||
|
symbol_strings.current_symbol = 0;
|
||||||
|
assembler::symbol_table_t symbol_table;
|
||||||
|
|
||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
ok = parser::parse(buf, program);
|
for (int i = 1; i < (argc - 1); i++) {
|
||||||
|
std::cerr << "input[" << i << "]: " << argv[i] << '\n';
|
||||||
|
std::string input_filename {argv[i]};
|
||||||
|
std::ifstream is {input_filename, std::ios::binary | std::ios::ate};
|
||||||
|
if (!is.is_open()) {
|
||||||
|
std::cerr << "failed to open " << input_filename << '\n';
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto size = is.tellg();
|
||||||
|
auto buf = std::make_unique<std::string>(size, '\0'); // construct string to stream size
|
||||||
|
is.seekg(0);
|
||||||
|
is.read(buf->data(), size);
|
||||||
|
is.close();
|
||||||
|
|
||||||
|
std::string_view ext = input_filename.substr(input_filename.size() - 4, 4);
|
||||||
|
if (ext == ".asm"s) {
|
||||||
|
ok = parser::parse(*buf, program, symbol_strings);
|
||||||
|
if (!ok)
|
||||||
|
return -1;
|
||||||
|
} else if (ext == ".bin"s) {
|
||||||
|
std::string name = input_filename.substr(0, input_filename.size() - 4);
|
||||||
|
assembler::blob_t blob {
|
||||||
|
.symbol = {
|
||||||
|
.start = symbol::get(symbol_strings, "_bin_"s + name + "_start"s),
|
||||||
|
.start_l = symbol::get(symbol_strings, "_bin_"s + name + "_start_l"s),
|
||||||
|
.start_h = symbol::get(symbol_strings, "_bin_"s + name + "_start_h"s),
|
||||||
|
.size_l = symbol::get(symbol_strings, "_bin_"s + name + "_size_l"s),
|
||||||
|
.size_h = symbol::get(symbol_strings, "_bin_"s + name + "_size_h"s),
|
||||||
|
},
|
||||||
|
.location = 0xeeee,
|
||||||
|
.buf = std::move(buf),
|
||||||
|
};
|
||||||
|
program.push_back(blob);
|
||||||
|
} else {
|
||||||
|
std::cerr << "unknown extension: " << ext << '\n';
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = symbol::resolve(0xc000, program, symbol_table);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ok = resolve_symbols(program, symbol_table);
|
std::cerr << "output: " << argv[argc - 1] << '\n';
|
||||||
if (!ok)
|
std::string output_filename {argv[argc - 1]};
|
||||||
return -1;
|
|
||||||
|
|
||||||
|
|
||||||
std::string output_filename {argv[2]};
|
|
||||||
std::ofstream out {output_filename, std::ios::binary};
|
std::ofstream out {output_filename, std::ios::binary};
|
||||||
if (!out.is_open()) {
|
if (!out.is_open()) {
|
||||||
std::cerr << "failed to open " << output_filename << '\n';
|
std::cerr << "failed to open " << output_filename << '\n';
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
serialize_program(program, symbol_table, 0x8200, out);
|
serialize_program(program, symbol_table, out);
|
||||||
|
|
||||||
out.close();
|
out.close();
|
||||||
return 0;
|
return 0;
|
||||||
|
97
parser.cc
97
parser.cc
@ -8,6 +8,7 @@
|
|||||||
#include "addressing_mode.hh"
|
#include "addressing_mode.hh"
|
||||||
#include "fromstring.hh"
|
#include "fromstring.hh"
|
||||||
#include "isa.hh"
|
#include "isa.hh"
|
||||||
|
#include "symbol.hh"
|
||||||
|
|
||||||
static bool tokenize(std::string_view buf, std::function<bool(std::string_view, ssize_t, ssize_t)> cb)
|
static bool tokenize(std::string_view buf, std::function<bool(std::string_view, ssize_t, ssize_t)> cb)
|
||||||
{
|
{
|
||||||
@ -68,30 +69,14 @@ namespace parser {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
using symbol_strings_t = std::unordered_map<std::string_view, size_t>;
|
|
||||||
|
|
||||||
namespace parser {
|
namespace parser {
|
||||||
|
|
||||||
bool parse(std::string_view buf, assembler::program_t& program)
|
bool parse(std::string_view buf, assembler::program_t& program, assembler::symbol_strings_t& symbol_strings)
|
||||||
{
|
{
|
||||||
size_t current_symbol = 0;
|
|
||||||
symbol_strings_t ss;
|
|
||||||
|
|
||||||
parser::state state = parser::state::label_or_op;
|
parser::state state = parser::state::label_or_op;
|
||||||
|
|
||||||
auto get_symbol = [&](std::string_view s) {
|
|
||||||
auto find = ss.find(s);
|
|
||||||
if (find == ss.end()) {
|
|
||||||
auto insert = ss.insert({s, current_symbol++});
|
|
||||||
assert(insert.second);
|
|
||||||
return (insert.first)->second;
|
|
||||||
} else {
|
|
||||||
return find->second;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
assembler::instruction_t current_instruction;
|
assembler::instruction_t current_instruction;
|
||||||
ssize_t current_row;
|
current_instruction.location = 0xeeee;
|
||||||
|
|
||||||
bool inside_comment = false;
|
bool inside_comment = false;
|
||||||
|
|
||||||
@ -100,11 +85,11 @@ bool parse(std::string_view buf, assembler::program_t& program)
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case parser::state::label_or_op:
|
case parser::state::label_or_op:
|
||||||
{
|
{
|
||||||
current_row = row;
|
current_instruction.row = row;
|
||||||
if (s.back() == ':') {
|
if (s.back() == ':') {
|
||||||
std::string_view key = s.substr(0, s.length() - 1);
|
std::string_view key = s.substr(0, s.length() - 1);
|
||||||
auto symbol = get_symbol(key);
|
auto symbol = symbol::get(symbol_strings, key);
|
||||||
std::cerr << "label `" << symbol << "`\n";
|
//std::cerr << "label `" << symbol << "`\n";
|
||||||
current_instruction.symbol = symbol;
|
current_instruction.symbol = symbol;
|
||||||
state = parser::state::op;
|
state = parser::state::op;
|
||||||
return true;
|
return true;
|
||||||
@ -121,28 +106,28 @@ bool parse(std::string_view buf, assembler::program_t& program)
|
|||||||
}
|
}
|
||||||
case parser::state::op:
|
case parser::state::op:
|
||||||
{
|
{
|
||||||
assert(row == current_row);
|
assert(row == current_instruction.row);
|
||||||
auto op_it = fromstring::op().find(s);
|
auto op_it = fromstring::op().find(s);
|
||||||
if (op_it == fromstring::op().end()) {
|
if (op_it == fromstring::op().end()) {
|
||||||
std::cerr << "invalid op `" << s << "`\n";
|
std::cerr << row << ',' << col << ": invalid op `" << s << "`\n";
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
current_instruction.op = op_it->second;
|
current_instruction.op = op_it->second;
|
||||||
std::cerr << "ok op `" << static_cast<int>(op_it->second) << "`\n";
|
//std::cerr << row << ": ok op `" << static_cast<int>(op_it->second) << "`\n";
|
||||||
}
|
}
|
||||||
state = parser::state::mode;
|
state = parser::state::mode;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case parser::state::mode:
|
case parser::state::mode:
|
||||||
{
|
{
|
||||||
assert(row == current_row);
|
assert(row == current_instruction.row);
|
||||||
auto mode_it = fromstring::mode().find(s);
|
auto mode_it = fromstring::mode().find(s);
|
||||||
if (mode_it == fromstring::mode().end()) {
|
if (mode_it == fromstring::mode().end()) {
|
||||||
std::cerr << "invalid mode `" << s << "`\n";
|
std::cerr << row << ',' << col << ": invalid mode `" << s << "`\n";
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
current_instruction.mode = mode_it->second;
|
current_instruction.mode = mode_it->second;
|
||||||
std::cerr << "ok mode `" << static_cast<int>(mode_it->second) << "`\n";
|
//std::cerr << "ok mode `" << static_cast<int>(mode_it->second) << "`\n";
|
||||||
}
|
}
|
||||||
state = parser::state::value;
|
state = parser::state::value;
|
||||||
return true;
|
return true;
|
||||||
@ -152,14 +137,14 @@ bool parse(std::string_view buf, assembler::program_t& program)
|
|||||||
auto am_it = addressing_mode().find(current_instruction.mode);
|
auto am_it = addressing_mode().find(current_instruction.mode);
|
||||||
assert(am_it != addressing_mode().end());
|
assert(am_it != addressing_mode().end());
|
||||||
if (am_it->second.len == 0) {
|
if (am_it->second.len == 0) {
|
||||||
std::cerr << "no value expected\n";
|
//std::cerr << row << ',' << col << ": no value expected\n";
|
||||||
assembler::implied_t i {};
|
assembler::implied_t i {};
|
||||||
current_instruction.value = i;
|
current_instruction.value = i;
|
||||||
state = parser::state::comment;
|
state = parser::state::comment;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(row == current_row);
|
assert(row == current_instruction.row);
|
||||||
|
|
||||||
auto parse_integer = [](std::string_view s, int base) -> std::optional<ssize_t> {
|
auto parse_integer = [](std::string_view s, int base) -> std::optional<ssize_t> {
|
||||||
std::string value_str {s.data(), s.length()};
|
std::string value_str {s.data(), s.length()};
|
||||||
@ -185,52 +170,62 @@ bool parse(std::string_view buf, assembler::program_t& program)
|
|||||||
case '7':
|
case '7':
|
||||||
case '8':
|
case '8':
|
||||||
case '9':
|
case '9':
|
||||||
case 'A':
|
case 'a':
|
||||||
case 'B':
|
case 'b':
|
||||||
case 'C':
|
case 'c':
|
||||||
case 'D':
|
case 'd':
|
||||||
case 'E':
|
case 'e':
|
||||||
case 'F':
|
case 'f':
|
||||||
{
|
{
|
||||||
literal = parse_integer(s, 16);
|
literal = parse_integer(s, 16);
|
||||||
if (literal == std::nullopt) {
|
if (literal == std::nullopt) {
|
||||||
std::cerr << row << ": invalid hex literal\n";
|
std::cerr << row << ',' << col << ": invalid hex literal\n";
|
||||||
}
|
}
|
||||||
current_instruction.value = as_literal(*literal);
|
current_instruction.value = as_literal(*literal);
|
||||||
std::cerr << "value hex literal `" << *literal << "`\n";
|
//std::cerr << "value hex literal `" << *literal << "`\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'h':
|
case '%':
|
||||||
|
{
|
||||||
|
literal = parse_integer(s.substr(1, s.length() - 1), 2);
|
||||||
|
if (literal == std::nullopt) {
|
||||||
|
std::cerr << row << ',' << col << ": invalid bin literal\n";
|
||||||
|
}
|
||||||
|
current_instruction.value = as_literal(*literal);
|
||||||
|
//std::cerr << "value bin literal `" << *literal << "`\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '$':
|
||||||
{
|
{
|
||||||
literal = parse_integer(s.substr(1, s.length() - 1), 16);
|
literal = parse_integer(s.substr(1, s.length() - 1), 16);
|
||||||
if (literal == std::nullopt) {
|
if (literal == std::nullopt) {
|
||||||
std::cerr << row << ": invalid hex literal\n";
|
std::cerr << row << ',' << col << ": invalid hex literal\n";
|
||||||
}
|
}
|
||||||
current_instruction.value = as_literal(*literal);
|
current_instruction.value = as_literal(*literal);
|
||||||
std::cerr << "value hex literal `" << *literal << "`\n";
|
//std::cerr << "value hex literal `" << *literal << "`\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'd':
|
case 'i':
|
||||||
{
|
{
|
||||||
literal = parse_integer(s.substr(1, s.length() - 1), 10);
|
literal = parse_integer(s.substr(1, s.length() - 1), 10);
|
||||||
if (literal == std::nullopt) {
|
if (literal == std::nullopt) {
|
||||||
std::cerr << row << ": invalid dec literal\n";
|
std::cerr << row << ',' << col << ": invalid dec literal\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
current_instruction.value = as_literal(*literal);
|
current_instruction.value = as_literal(*literal);
|
||||||
std::cerr << "value dec literal `" << *literal << "`\n";
|
//std::cerr << "value dec literal `" << *literal << "`\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ':':
|
case ':':
|
||||||
{
|
{
|
||||||
std::string_view key = s.substr(1, s.length() - 1);
|
std::string_view key = s.substr(1, s.length() - 1);
|
||||||
assembler::reference_t reference = { get_symbol(key) };
|
assembler::reference_t reference = { symbol::get(symbol_strings, key) };
|
||||||
current_instruction.value = reference;
|
current_instruction.value = reference;
|
||||||
std::cerr << "value reference `" << reference.symbol << "`\n";
|
//std::cerr << "value reference `" << reference.symbol << "`\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
std::cerr << row << ": invalid base\n";
|
std::cerr << row << ',' << col << ": invalid base\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,8 +234,8 @@ bool parse(std::string_view buf, assembler::program_t& program)
|
|||||||
}
|
}
|
||||||
case parser::state::comment:
|
case parser::state::comment:
|
||||||
{
|
{
|
||||||
if (row != current_row) {
|
if (row != current_instruction.row) {
|
||||||
std::cerr << "push " << (int)current_instruction.op << '\n';
|
//std::cerr << "push " << (int)current_instruction.op << '\n';
|
||||||
inside_comment = false;
|
inside_comment = false;
|
||||||
program.push_back(current_instruction);
|
program.push_back(current_instruction);
|
||||||
state = parser::state::label_or_op;
|
state = parser::state::label_or_op;
|
||||||
@ -253,13 +248,13 @@ bool parse(std::string_view buf, assembler::program_t& program)
|
|||||||
} else if (inside_comment) {
|
} else if (inside_comment) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << row << ": expected comment\n";
|
std::cerr << row << ',' << col << ": expected comment\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case parser::state::just_comment:
|
case parser::state::just_comment:
|
||||||
{
|
{
|
||||||
if (row != current_row) {
|
if (row != current_instruction.row) {
|
||||||
inside_comment = false;
|
inside_comment = false;
|
||||||
state = parser::state::label_or_op;
|
state = parser::state::label_or_op;
|
||||||
continue;
|
continue;
|
||||||
@ -271,7 +266,7 @@ bool parse(std::string_view buf, assembler::program_t& program)
|
|||||||
} else if (inside_comment) {
|
} else if (inside_comment) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "expected comment\n";
|
std::cerr << row << ',' << col << ": expected comment\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,5 @@
|
|||||||
#include "assembler.hh"
|
#include "assembler.hh"
|
||||||
|
|
||||||
namespace parser {
|
namespace parser {
|
||||||
bool parse(std::string_view buf, assembler::program_t& program);
|
bool parse(std::string_view buf, assembler::program_t& program, assembler::symbol_strings_t& symbol_strings);
|
||||||
}
|
}
|
||||||
|
63
symbol.cc
Normal file
63
symbol.cc
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include <string_view>
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "assembler.hh"
|
||||||
|
#include "addressing_mode.hh"
|
||||||
|
|
||||||
|
namespace symbol {
|
||||||
|
|
||||||
|
size_t get(assembler::symbol_strings_t& symbol_strings, std::string_view s) {
|
||||||
|
std::string key {s};
|
||||||
|
auto find = symbol_strings.map.find(key);
|
||||||
|
if (find == symbol_strings.map.end()) {
|
||||||
|
std::cerr << "get new: " << s << ' ' << symbol_strings.current_symbol << '\n';
|
||||||
|
auto insert = symbol_strings.map.insert({key, symbol_strings.current_symbol++});
|
||||||
|
assert(insert.second);
|
||||||
|
return (insert.first)->second;
|
||||||
|
} else {
|
||||||
|
return find->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool resolve(size_t link_location, assembler::program_t& program, assembler::symbol_table_t& symbol_table)
|
||||||
|
{
|
||||||
|
size_t offset = link_location;
|
||||||
|
|
||||||
|
for (auto prog_it = program.begin(); prog_it != program.end(); prog_it++) {
|
||||||
|
if (std::holds_alternative<assembler::instruction_t>(*prog_it)) {
|
||||||
|
auto& ins = std::get<assembler::instruction_t>(*prog_it);
|
||||||
|
ins.location = offset;
|
||||||
|
if (ins.symbol != std::nullopt) {
|
||||||
|
auto [_, ok] = symbol_table.insert({*(ins.symbol), offset});
|
||||||
|
if (!ok) {
|
||||||
|
std::cerr << ins.row << ": duplicate symbol\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto am_it = addressing_mode().find(ins.mode);
|
||||||
|
assert (am_it != addressing_mode().end());
|
||||||
|
offset += 1 + am_it->second.len;
|
||||||
|
} else if (std::holds_alternative<assembler::blob_t>(*prog_it)) {
|
||||||
|
auto& blob = std::get<assembler::blob_t>(*prog_it);
|
||||||
|
blob.location = offset + 4;
|
||||||
|
auto [_1, ok1] = symbol_table.insert({blob.symbol.start, offset});
|
||||||
|
auto [_2, ok2] = symbol_table.insert({blob.symbol.start_l, (offset >> 0) & 0xff});
|
||||||
|
auto [_3, ok3] = symbol_table.insert({blob.symbol.start_h, (offset >> 8) & 0xff});
|
||||||
|
auto [_4, ok4] = symbol_table.insert({blob.symbol.size_l, (blob.buf->size() >> 0) & 0xff});
|
||||||
|
auto [_5, ok5] = symbol_table.insert({blob.symbol.size_h, (blob.buf->size() >> 8) & 0xff});
|
||||||
|
if (!ok1 || !ok2 || !ok3 || !ok4 || !ok5) {
|
||||||
|
std::cerr << "duplicate blob symbol\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
offset += 4 + blob.buf->size();
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
11
symbol.hh
Normal file
11
symbol.hh
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "assembler.hh"
|
||||||
|
|
||||||
|
namespace symbol {
|
||||||
|
|
||||||
|
size_t get(assembler::symbol_strings_t& symbol_strings, std::string_view s);
|
||||||
|
|
||||||
|
bool resolve(size_t link_location, assembler::program_t& program, assembler::symbol_table_t& symbol_table);
|
||||||
|
|
||||||
|
}
|
246
tostring.cc
246
tostring.cc
@ -1,127 +1,133 @@
|
|||||||
#include <map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "instruction.hh"
|
#include "isa.hh"
|
||||||
#include "mneumonic.hh"
|
#include "mneumonic.hh"
|
||||||
|
|
||||||
namespace tostring {
|
namespace tostring {
|
||||||
const std::unordered_map<op_t, std::string_view> op {
|
const std::unordered_map<isa::op, std::string_view>& op() {
|
||||||
{op::ADC, mneumonic::op::ADC},
|
static const std::unordered_map<isa::op, std::string_view> _ = {
|
||||||
{op::AND, mneumonic::op::AND},
|
{isa::op::ADC, mneumonic::op::ADC},
|
||||||
{op::ASL, mneumonic::op::ASL},
|
{isa::op::AND, mneumonic::op::AND},
|
||||||
{op::BBR0, mneumonic::op::BBR0},
|
{isa::op::ASL, mneumonic::op::ASL},
|
||||||
{op::BBR1, mneumonic::op::BBR1},
|
{isa::op::BBR0, mneumonic::op::BBR0},
|
||||||
{op::BBR2, mneumonic::op::BBR2},
|
{isa::op::BBR1, mneumonic::op::BBR1},
|
||||||
{op::BBR3, mneumonic::op::BBR3},
|
{isa::op::BBR2, mneumonic::op::BBR2},
|
||||||
{op::BBR4, mneumonic::op::BBR4},
|
{isa::op::BBR3, mneumonic::op::BBR3},
|
||||||
{op::BBR5, mneumonic::op::BBR5},
|
{isa::op::BBR4, mneumonic::op::BBR4},
|
||||||
{op::BBR6, mneumonic::op::BBR6},
|
{isa::op::BBR5, mneumonic::op::BBR5},
|
||||||
{op::BBR7, mneumonic::op::BBR7},
|
{isa::op::BBR6, mneumonic::op::BBR6},
|
||||||
{op::BBS0, mneumonic::op::BBS0},
|
{isa::op::BBR7, mneumonic::op::BBR7},
|
||||||
{op::BBS1, mneumonic::op::BBS1},
|
{isa::op::BBS0, mneumonic::op::BBS0},
|
||||||
{op::BBS2, mneumonic::op::BBS2},
|
{isa::op::BBS1, mneumonic::op::BBS1},
|
||||||
{op::BBS3, mneumonic::op::BBS3},
|
{isa::op::BBS2, mneumonic::op::BBS2},
|
||||||
{op::BBS4, mneumonic::op::BBS4},
|
{isa::op::BBS3, mneumonic::op::BBS3},
|
||||||
{op::BBS5, mneumonic::op::BBS5},
|
{isa::op::BBS4, mneumonic::op::BBS4},
|
||||||
{op::BBS6, mneumonic::op::BBS6},
|
{isa::op::BBS5, mneumonic::op::BBS5},
|
||||||
{op::BBS7, mneumonic::op::BBS7},
|
{isa::op::BBS6, mneumonic::op::BBS6},
|
||||||
{op::BCC, mneumonic::op::BCC},
|
{isa::op::BBS7, mneumonic::op::BBS7},
|
||||||
{op::BCS, mneumonic::op::BCS},
|
{isa::op::BCC, mneumonic::op::BCC},
|
||||||
{op::BEQ, mneumonic::op::BEQ},
|
{isa::op::BCS, mneumonic::op::BCS},
|
||||||
{op::BIT, mneumonic::op::BIT},
|
{isa::op::BEQ, mneumonic::op::BEQ},
|
||||||
{op::BMI, mneumonic::op::BMI},
|
{isa::op::BIT, mneumonic::op::BIT},
|
||||||
{op::BNE, mneumonic::op::BNE},
|
{isa::op::BMI, mneumonic::op::BMI},
|
||||||
{op::BPL, mneumonic::op::BPL},
|
{isa::op::BNE, mneumonic::op::BNE},
|
||||||
{op::BRA, mneumonic::op::BRA},
|
{isa::op::BPL, mneumonic::op::BPL},
|
||||||
{op::BRK, mneumonic::op::BRK},
|
{isa::op::BRA, mneumonic::op::BRA},
|
||||||
{op::BVC, mneumonic::op::BVC},
|
{isa::op::BRK, mneumonic::op::BRK},
|
||||||
{op::BVS, mneumonic::op::BVS},
|
{isa::op::BVC, mneumonic::op::BVC},
|
||||||
{op::CLC, mneumonic::op::CLC},
|
{isa::op::BVS, mneumonic::op::BVS},
|
||||||
{op::CLD, mneumonic::op::CLD},
|
{isa::op::CLC, mneumonic::op::CLC},
|
||||||
{op::CLI, mneumonic::op::CLI},
|
{isa::op::CLD, mneumonic::op::CLD},
|
||||||
{op::CLV, mneumonic::op::CLV},
|
{isa::op::CLI, mneumonic::op::CLI},
|
||||||
{op::CMP, mneumonic::op::CMP},
|
{isa::op::CLV, mneumonic::op::CLV},
|
||||||
{op::CPX, mneumonic::op::CPX},
|
{isa::op::CMP, mneumonic::op::CMP},
|
||||||
{op::CPY, mneumonic::op::CPY},
|
{isa::op::CPX, mneumonic::op::CPX},
|
||||||
{op::DEC, mneumonic::op::DEC},
|
{isa::op::CPY, mneumonic::op::CPY},
|
||||||
{op::DEX, mneumonic::op::DEX},
|
{isa::op::DEC, mneumonic::op::DEC},
|
||||||
{op::DEY, mneumonic::op::DEY},
|
{isa::op::DEX, mneumonic::op::DEX},
|
||||||
{op::EOR, mneumonic::op::EOR},
|
{isa::op::DEY, mneumonic::op::DEY},
|
||||||
{op::INC, mneumonic::op::INC},
|
{isa::op::EOR, mneumonic::op::EOR},
|
||||||
{op::INX, mneumonic::op::INX},
|
{isa::op::INC, mneumonic::op::INC},
|
||||||
{op::INY, mneumonic::op::INY},
|
{isa::op::INX, mneumonic::op::INX},
|
||||||
{op::JMP, mneumonic::op::JMP},
|
{isa::op::INY, mneumonic::op::INY},
|
||||||
{op::JSR, mneumonic::op::JSR},
|
{isa::op::JMP, mneumonic::op::JMP},
|
||||||
{op::LDA, mneumonic::op::LDA},
|
{isa::op::JSR, mneumonic::op::JSR},
|
||||||
{op::LDX, mneumonic::op::LDX},
|
{isa::op::LDA, mneumonic::op::LDA},
|
||||||
{op::LDY, mneumonic::op::LDY},
|
{isa::op::LDX, mneumonic::op::LDX},
|
||||||
{op::LSR, mneumonic::op::LSR},
|
{isa::op::LDY, mneumonic::op::LDY},
|
||||||
{op::NOP, mneumonic::op::NOP},
|
{isa::op::LSR, mneumonic::op::LSR},
|
||||||
{op::ORA, mneumonic::op::ORA},
|
{isa::op::NOP, mneumonic::op::NOP},
|
||||||
{op::PHA, mneumonic::op::PHA},
|
{isa::op::ORA, mneumonic::op::ORA},
|
||||||
{op::PHP, mneumonic::op::PHP},
|
{isa::op::PHA, mneumonic::op::PHA},
|
||||||
{op::PHX, mneumonic::op::PHX},
|
{isa::op::PHP, mneumonic::op::PHP},
|
||||||
{op::PHY, mneumonic::op::PHY},
|
{isa::op::PHX, mneumonic::op::PHX},
|
||||||
{op::PLA, mneumonic::op::PLA},
|
{isa::op::PHY, mneumonic::op::PHY},
|
||||||
{op::PLP, mneumonic::op::PLP},
|
{isa::op::PLA, mneumonic::op::PLA},
|
||||||
{op::PLX, mneumonic::op::PLX},
|
{isa::op::PLP, mneumonic::op::PLP},
|
||||||
{op::PLY, mneumonic::op::PLY},
|
{isa::op::PLX, mneumonic::op::PLX},
|
||||||
{op::RMB0, mneumonic::op::RMB0},
|
{isa::op::PLY, mneumonic::op::PLY},
|
||||||
{op::RMB1, mneumonic::op::RMB1},
|
{isa::op::RMB0, mneumonic::op::RMB0},
|
||||||
{op::RMB2, mneumonic::op::RMB2},
|
{isa::op::RMB1, mneumonic::op::RMB1},
|
||||||
{op::RMB3, mneumonic::op::RMB3},
|
{isa::op::RMB2, mneumonic::op::RMB2},
|
||||||
{op::RMB4, mneumonic::op::RMB4},
|
{isa::op::RMB3, mneumonic::op::RMB3},
|
||||||
{op::RMB5, mneumonic::op::RMB5},
|
{isa::op::RMB4, mneumonic::op::RMB4},
|
||||||
{op::RMB6, mneumonic::op::RMB6},
|
{isa::op::RMB5, mneumonic::op::RMB5},
|
||||||
{op::RMB7, mneumonic::op::RMB7},
|
{isa::op::RMB6, mneumonic::op::RMB6},
|
||||||
{op::ROL, mneumonic::op::ROL},
|
{isa::op::RMB7, mneumonic::op::RMB7},
|
||||||
{op::ROR, mneumonic::op::ROR},
|
{isa::op::ROL, mneumonic::op::ROL},
|
||||||
{op::RTI, mneumonic::op::RTI},
|
{isa::op::ROR, mneumonic::op::ROR},
|
||||||
{op::RTS, mneumonic::op::RTS},
|
{isa::op::RTI, mneumonic::op::RTI},
|
||||||
{op::SBC, mneumonic::op::SBC},
|
{isa::op::RTS, mneumonic::op::RTS},
|
||||||
{op::SEC, mneumonic::op::SEC},
|
{isa::op::SBC, mneumonic::op::SBC},
|
||||||
{op::SED, mneumonic::op::SED},
|
{isa::op::SEC, mneumonic::op::SEC},
|
||||||
{op::SEI, mneumonic::op::SEI},
|
{isa::op::SED, mneumonic::op::SED},
|
||||||
{op::SMB0, mneumonic::op::SMB0},
|
{isa::op::SEI, mneumonic::op::SEI},
|
||||||
{op::SMB1, mneumonic::op::SMB1},
|
{isa::op::SMB0, mneumonic::op::SMB0},
|
||||||
{op::SMB2, mneumonic::op::SMB2},
|
{isa::op::SMB1, mneumonic::op::SMB1},
|
||||||
{op::SMB3, mneumonic::op::SMB3},
|
{isa::op::SMB2, mneumonic::op::SMB2},
|
||||||
{op::SMB4, mneumonic::op::SMB4},
|
{isa::op::SMB3, mneumonic::op::SMB3},
|
||||||
{op::SMB5, mneumonic::op::SMB5},
|
{isa::op::SMB4, mneumonic::op::SMB4},
|
||||||
{op::SMB6, mneumonic::op::SMB6},
|
{isa::op::SMB5, mneumonic::op::SMB5},
|
||||||
{op::SMB7, mneumonic::op::SMB7},
|
{isa::op::SMB6, mneumonic::op::SMB6},
|
||||||
{op::STA, mneumonic::op::STA},
|
{isa::op::SMB7, mneumonic::op::SMB7},
|
||||||
{op::STP, mneumonic::op::STP},
|
{isa::op::STA, mneumonic::op::STA},
|
||||||
{op::STX, mneumonic::op::STX},
|
{isa::op::STP, mneumonic::op::STP},
|
||||||
{op::STY, mneumonic::op::STY},
|
{isa::op::STX, mneumonic::op::STX},
|
||||||
{op::STZ, mneumonic::op::STZ},
|
{isa::op::STY, mneumonic::op::STY},
|
||||||
{op::TAX, mneumonic::op::TAX},
|
{isa::op::STZ, mneumonic::op::STZ},
|
||||||
{op::TAY, mneumonic::op::TAY},
|
{isa::op::TAX, mneumonic::op::TAX},
|
||||||
{op::TRB, mneumonic::op::TRB},
|
{isa::op::TAY, mneumonic::op::TAY},
|
||||||
{op::TSB, mneumonic::op::TSB},
|
{isa::op::TRB, mneumonic::op::TRB},
|
||||||
{op::TSX, mneumonic::op::TSX},
|
{isa::op::TSB, mneumonic::op::TSB},
|
||||||
{op::TXA, mneumonic::op::TXA},
|
{isa::op::TSX, mneumonic::op::TSX},
|
||||||
{op::TXS, mneumonic::op::TXS},
|
{isa::op::TXA, mneumonic::op::TXA},
|
||||||
{op::TYA, mneumonic::op::TYA},
|
{isa::op::TXS, mneumonic::op::TXS},
|
||||||
{op::WAI, mneumonic::op::WAI},
|
{isa::op::TYA, mneumonic::op::TYA},
|
||||||
};
|
{isa::op::WAI, mneumonic::op::WAI},
|
||||||
|
};
|
||||||
|
return _;
|
||||||
|
}
|
||||||
|
|
||||||
const std::unordered_map<amode_t, std::string_view> mode {
|
const std::unordered_map<isa::mode, std::string_view>& mode() {
|
||||||
{mode::A, mneumonic::mode::A},
|
static const std::unordered_map<isa::mode, std::string_view> _ = {
|
||||||
{mode::AII, mneumonic::mode::AII},
|
{isa::mode::A, mneumonic::mode::A},
|
||||||
{mode::AIX, mneumonic::mode::AIX},
|
{isa::mode::AII, mneumonic::mode::AII},
|
||||||
{mode::AIY, mneumonic::mode::AIY},
|
{isa::mode::AIX, mneumonic::mode::AIX},
|
||||||
{mode::AI, mneumonic::mode::AI},
|
{isa::mode::AIY, mneumonic::mode::AIY},
|
||||||
{mode::ACC, mneumonic::mode::ACC},
|
{isa::mode::AI, mneumonic::mode::AI},
|
||||||
{mode::IMM, mneumonic::mode::IMM},
|
{isa::mode::ACC, mneumonic::mode::ACC},
|
||||||
{mode::I, mneumonic::mode::I},
|
{isa::mode::IMM, mneumonic::mode::IMM},
|
||||||
{mode::R, mneumonic::mode::R},
|
{isa::mode::I, mneumonic::mode::I},
|
||||||
{mode::S, mneumonic::mode::S},
|
{isa::mode::R, mneumonic::mode::R},
|
||||||
{mode::ZP, mneumonic::mode::ZP},
|
{isa::mode::S, mneumonic::mode::S},
|
||||||
{mode::ZPII, mneumonic::mode::ZPII},
|
{isa::mode::ZP, mneumonic::mode::ZP},
|
||||||
{mode::ZPX, mneumonic::mode::ZPX},
|
{isa::mode::ZPII, mneumonic::mode::ZPII},
|
||||||
{mode::ZPY, mneumonic::mode::ZPY},
|
{isa::mode::ZPX, mneumonic::mode::ZPX},
|
||||||
{mode::ZPI, mneumonic::mode::ZPI},
|
{isa::mode::ZPY, mneumonic::mode::ZPY},
|
||||||
{mode::ZPIY, mneumonic::mode::ZPIY},
|
{isa::mode::ZPI, mneumonic::mode::ZPI},
|
||||||
};
|
{isa::mode::ZPIY, mneumonic::mode::ZPIY},
|
||||||
|
};
|
||||||
|
return _;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include "mneumonic.hh"
|
#include "mneumonic.hh"
|
||||||
|
|
||||||
namespace tostring {
|
namespace tostring {
|
||||||
extern const std::unordered_map<op_t, std::string_view> op;
|
const std::unordered_map<isa::op, std::string_view>& op();
|
||||||
|
const std::unordered_map<isa::mode, std::string_view>& mode();
|
||||||
extern const std::unordered_map<amode_t, std::string_view> mode;
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user