From 8cfcc54e124fa0511376a73006dda3334c35731a Mon Sep 17 00:00:00 2001 From: sfja Date: Wed, 21 Jan 2026 22:13:57 +0100 Subject: [PATCH] assemble operands and instructions --- src/assembler.cpp | 582 ++++++++++++++++++++++++++++++++++++++++------ src/assembler.hpp | 51 +++- src/scanner.cpp | 36 ++- src/scanner.hpp | 19 +- 4 files changed, 600 insertions(+), 88 deletions(-) diff --git a/src/assembler.cpp b/src/assembler.cpp index 3348f01..4d0c91e 100644 --- a/src/assembler.cpp +++ b/src/assembler.cpp @@ -19,6 +19,7 @@ using namespace vc5::tools; using namespace vc5::tools::asmer; +using namespace std::literals; namespace fs = std::filesystem; using TT = Tok::Ty; @@ -33,6 +34,7 @@ auto vc5::tools::assemble_file(fs::path input_path, fs::path output_path) { auto input_file = std::ifstream(input_path, std::ios_base::binary); + if (not input_file) { return std::unexpected( std::format("could not open file '{}' for reading", @@ -46,28 +48,14 @@ auto vc5::tools::assemble_file(fs::path input_path, fs::path output_path) input_file.read(&text[0], size); } - auto parser = Parser(text); + auto assembler = Assembler(text); + auto result = assembler.assemble_file(); - auto program = std::vector(65536); - auto builder = Builder(program.data()); - - auto assembler = Assembler(text, builder); - - auto lines = std::vector(); - - while (true) { - auto ins = parser.parse_ins(); - if (not ins) { - break; - } - } - - if (not parser.ok()) { - return std::unexpected("parsing failed"); - } + auto& program = *result; { auto output_file = std::ofstream(output_path, std::ios_base::binary); + if (not output_file) { return std::unexpected( std::format("could not open file '{}' for writing", @@ -81,22 +69,75 @@ auto vc5::tools::assemble_file(fs::path input_path, fs::path output_path) return {}; } -auto Assembler::assemble_file(std::string_view text) +auto Assembler::assemble_file() -> std::expected, std::string> { - auto parser = Parser(text); - - auto program = std::vector(65536); - auto builder = Builder(program.data()); - - auto assembler = Assembler(text, builder); - - auto lines = std::vector(); + auto parser = Parser(m_text); + auto lines = std::vector>(); while (true) { - auto ins = parser.parse_ins(); - if (not ins) { - break; + + if (parser.next_is_const()) { + auto stmt = parser.parse_const(); + if (not stmt) { + return std::unexpected("parsing failed"); + } + + auto value = eval_operand_to_imm(*stmt->expr); + if (not value) { + return std::unexpected("assembling failed"); + } + + assert(value->ty == EOT::Imm); + m_syms[stmt->ident] = value->as_imm(); + + } else if (parser.next_is_align()) { + auto stmt = parser.parse_align(); + if (not stmt) { + return std::unexpected("parsing failed"); + } + + auto value = eval_operand_to_imm(*stmt->expr); + if (not value) { + return std::unexpected("assembling failed"); + } + assert(value->ty == EOT::Imm); + + uint16_t bits = value->as_imm(); + if (bits == 0 or bits % 8 != 0) { + error(stmt->loc, std::format("cannot align to {}", bits)); + return std::unexpected("assembling failed"); + } + + uint16_t align_bit = bits / 8; + uint16_t align_mask = align_bit - 1; + + uint16_t ip = m_builder.ip(); + + if ((ip & align_mask) != 0) { + ip &= ~align_mask; + ip += align_bit; + } + + uint16_t delta = ip - m_builder.ip(); + if (delta == 0) + continue; + + auto ops = Line::Args(); + for (uint16_t i = 0; i < delta; ++i) { + auto op = std::make_unique(stmt->loc, Expr::Ty::Int, 0); + ops.push_back(std::move(op)); + } + lines.push_back(std::make_unique( + stmt->loc, nullptr, "db", std::move(ops))); + + } else { + + auto line = parser.parse_line(); + if (not line) { + break; + } + lines.push_back(std::move(line)); } } @@ -104,59 +145,268 @@ auto Assembler::assemble_file(std::string_view text) return std::unexpected("parsing failed"); } - return { std::move(program) }; + m_builder.set_ip(0); + m_second_pass = true; + + return std::move(m_program); } void Assembler::assemble_define_labels(const std::vector