diff --git a/addressing_mode.cc b/addressing_mode.cc index ac53d8d..ca74bdb 100644 --- a/addressing_mode.cc +++ b/addressing_mode.cc @@ -10,6 +10,8 @@ static bool is_uint8(ssize_t n) { return n >= 0 && n <= 255; } static bool is_int8(ssize_t n) { return n >= -128 && n <= 127; } +static bool is_imm8(ssize_t n) { return n >= -128 && n <= 255; } + static bool always_valid(ssize_t _) { return true; } std::unordered_map& addressing_mode() { @@ -20,7 +22,7 @@ std::unordered_map& addressing_mode() { {isa::mode::AIY, { .len = 2, .valid = is_uint16 }}, {isa::mode::AI, { .len = 2, .valid = is_uint16 }}, {isa::mode::ACC, { .len = 0, .valid = always_valid }}, - {isa::mode::IMM, { .len = 1, .valid = is_uint8 }}, + {isa::mode::IMM, { .len = 1, .valid = is_imm8 }}, {isa::mode::I, { .len = 0, .valid = always_valid }}, {isa::mode::R, { .len = 1, .valid = is_int8 }}, {isa::mode::S, { .len = 0, .valid = always_valid }}, diff --git a/assembler.hh b/assembler.hh index 212a232..a4f251f 100644 --- a/assembler.hh +++ b/assembler.hh @@ -36,6 +36,8 @@ namespace assembler { size_t start_h; size_t size_l; size_t size_h; + size_t end_l; + size_t end_h; } symbol; size_t location; std::shared_ptr buf; diff --git a/link.py b/link.py new file mode 100644 index 0000000..2aaaf68 --- /dev/null +++ b/link.py @@ -0,0 +1,29 @@ +import sys + +assert len(sys.argv) > 2 + + +mem = bytearray(2 ** 15) + + +with open(sys.argv[1], 'rb') as f: + l = f.read() + + +for i, a in enumerate(l): + mem[i + 0x4000] = a + + +# NMIB +mem[0xfffa - 0x8000] = 0x00 +mem[0xfffb - 0x8000] = 0xc0 +# RESB +mem[0xfffc - 0x8000] = 0x00 +mem[0xfffd - 0x8000] = 0xc0 +# IRQB +mem[0xfffe - 0x8000] = 0x02 +mem[0xffff - 0x8000] = 0xc0 + + +with open(sys.argv[2], 'wb') as f: + f.write(mem) diff --git a/main.cc b/main.cc index 045c622..c824791 100644 --- a/main.cc +++ b/main.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include "assembler.hh" #include "addressing_mode.hh" @@ -13,9 +14,9 @@ using namespace std::literals; -void serialize_program(const assembler::program_t& program, const assembler::symbol_table_t &symbol_table, std::ostream& out) +bool serialize_program(const assembler::program_t& program, const assembler::symbol_table_t &symbol_table, std::ostream& out) { - auto serialize_instruction = [&](assembler::instruction_t& ins) -> void { + auto serialize_instruction = [&](assembler::instruction_t& ins) -> bool { //std::cerr << "enc " << (int)ins.op << ' ' << (int)ins.mode << '\n'; char buf[3]; @@ -24,15 +25,9 @@ void serialize_program(const assembler::program_t& program, const assembler::sym std::cerr << ins.row << ": illegal op,mode: " << tostring::op().find(ins.op)->second << ' ' << tostring::mode().find(ins.mode)->second << '\n'; - return; + return false; } - /* - std::cerr << tostring::op().find(ins.op)->second << ' ' - << tostring::mode().find(ins.mode)->second << ' ' - << std::hex << (int)opcode_it->second << '\n'; - */ - buf[0] = opcode_it->second; auto am_it = addressing_mode().find(ins.mode); @@ -67,7 +62,7 @@ void serialize_program(const assembler::program_t& program, const assembler::sym size_t value = get_value(); if (!am_it->second.valid(value)) { std::cerr << "overflow at " << ins.row << " value: " << value << '\n'; - return; + return false; } //std::cerr << "value " << std::hex << value << ' ' << am_it->second.len << '\n'; @@ -77,14 +72,28 @@ void serialize_program(const assembler::program_t& program, const assembler::sym if (am_it->second.len >= 1) buf[1] = (value >> 0) & 0xff; + std::cerr << std::hex << ins.location << ' ' + << tostring::op().find(ins.op)->second << ' ' + << tostring::mode().find(ins.mode)->second << ' '; + if (am_it->second.len == 2) + std::cerr << std::hex << (value & 0xffff) << '\n'; + else if (am_it->second.len == 1) + std::cerr << std::hex << (value & 0xff) << '\n'; + else + std::cerr << '\n'; + out.write(buf, 1 + am_it->second.len); + + return true; }; for (auto prog_it = program.cbegin(); prog_it != program.cend(); prog_it++) { if (std::holds_alternative(*prog_it)) { auto ins = std::get(*prog_it); - serialize_instruction(ins); + auto ok = serialize_instruction(ins); + if (!ok) + return false; } else if (std::holds_alternative(*prog_it)) { auto blob = std::get(*prog_it); out.write(blob.buf->data(), blob.buf->size()); @@ -92,6 +101,8 @@ void serialize_program(const assembler::program_t& program, const assembler::sym assert (false); } } + + return true; } int main(int argc, char * argv[]) @@ -128,7 +139,7 @@ int main(int argc, char * argv[]) ok = parser::parse(*buf, program, symbol_strings); if (!ok) return -1; - } else if (ext == ".bin"s) { + } else if (ext == ".bin"s or ext == ".txt"s) { std::string name = input_filename.substr(0, input_filename.size() - 4); assembler::blob_t blob { .symbol = { @@ -137,6 +148,8 @@ int main(int argc, char * argv[]) .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), + .end_l = symbol::get(symbol_strings, "_bin_"s + name + "_end_l"s), + .end_h = symbol::get(symbol_strings, "_bin_"s + name + "_end_h"s), }, .location = 0xeeee, .buf = std::move(buf), @@ -159,14 +172,19 @@ int main(int argc, char * argv[]) std::cerr << "output: " << argv[argc - 1] << '\n'; std::string output_filename {argv[argc - 1]}; - std::ofstream out {output_filename, std::ios::binary}; + std::ofstream out {output_filename + ".part", std::ios::binary}; if (!out.is_open()) { std::cerr << "failed to open " << output_filename << '\n'; return -1; } - serialize_program(program, symbol_table, out); + ok = serialize_program(program, symbol_table, out); + if (!ok) { + return -1; + } out.close(); + std::rename((output_filename + ".part").data(), output_filename.data()); + return 0; } diff --git a/symbol.cc b/symbol.cc index 82192ee..73122b5 100644 --- a/symbol.cc +++ b/symbol.cc @@ -47,7 +47,9 @@ bool resolve(size_t link_location, assembler::program_t& program, assembler::sym 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) { + auto [_6, ok6] = symbol_table.insert({blob.symbol.end_l, ((offset + blob.buf->size() - 1) >> 0) & 0xff}); + auto [_7, ok7] = symbol_table.insert({blob.symbol.end_h, ((offset + blob.buf->size() - 1) >> 8) & 0xff}); + if (!ok1 || !ok2 || !ok3 || !ok4 || !ok5 || !ok6 || !ok7) { std::cerr << "duplicate blob symbol\n"; return false; }