assemble
This commit is contained in:
parent
680e952d04
commit
19f68cc6ac
@ -51,7 +51,7 @@ key_press_int:
|
|||||||
|
|
||||||
mov r0, [0x600]
|
mov r0, [0x600]
|
||||||
add r0, r0, VCD
|
add r0, r0, VCD
|
||||||
mov r1, [KBC_CODE]
|
mov r1, [KBD_CODE]
|
||||||
cmp r1, 44 ; spacebar
|
cmp r1, 44 ; spacebar
|
||||||
mov r2, rfl
|
mov r2, rfl
|
||||||
and r2, r2, FL_EQ
|
and r2, r2, FL_EQ
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#include <ios>
|
#include <ios>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <print>
|
#include <print>
|
||||||
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -100,7 +101,7 @@ auto Assembler::assemble_file()
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(value->ty == EOT::Imm);
|
assert(value->ty == EOT::Imm);
|
||||||
m_syms[stmt->ident] = value->as_imm();
|
m_syms[std::string(stmt->ident)] = value->as_imm();
|
||||||
|
|
||||||
} else if (parser.next_is_align()) {
|
} else if (parser.next_is_align()) {
|
||||||
auto stmt = parser.parse_align();
|
auto stmt = parser.parse_align();
|
||||||
@ -153,6 +154,11 @@ auto Assembler::assemble_file()
|
|||||||
parser.try_recover();
|
parser.try_recover();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (line->labels) {
|
||||||
|
define_labels(*line->labels);
|
||||||
|
}
|
||||||
|
|
||||||
lines.push_back(std::move(line));
|
lines.push_back(std::move(line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,33 +171,36 @@ auto Assembler::assemble_file()
|
|||||||
m_second_pass = true;
|
m_second_pass = true;
|
||||||
|
|
||||||
for (const auto& line : lines) {
|
for (const auto& line : lines) {
|
||||||
std::println("[{}] = {}", m_builder.ip(), line->ident);
|
|
||||||
assemble_line(*line);
|
assemble_line(*line);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < 64; i += 4) {
|
|
||||||
std::println("{:02x} {:02x} {:02x} {:02x}",
|
|
||||||
m_program[i],
|
|
||||||
m_program[i + 1],
|
|
||||||
m_program[i + 2],
|
|
||||||
m_program[i + 3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::move(m_program);
|
return std::move(m_program);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assembler::assemble_define_labels(const std::vector<Label>& labels)
|
void Assembler::define_labels(const std::vector<Label>& labels)
|
||||||
{
|
{
|
||||||
for (const auto& label : labels) {
|
for (const auto& label : labels) {
|
||||||
if (label.is_local) {
|
if (label.is_local) {
|
||||||
m_sublabels[label.ident] = m_builder.ip();
|
m_sublabels[label_ident(label)] = m_builder.ip();
|
||||||
} else {
|
} else {
|
||||||
m_sublabels.clear();
|
m_superlabel = label.ident;
|
||||||
m_syms[label.ident] = m_builder.ip();
|
m_syms[std::string(label.ident)] = m_builder.ip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Assembler::label_ident(const Label& label) const -> std::string
|
||||||
|
{
|
||||||
|
if (not label.is_local)
|
||||||
|
return std::string(label.ident);
|
||||||
|
|
||||||
|
return sublabel_ident(label.ident);
|
||||||
|
}
|
||||||
|
auto Assembler::sublabel_ident(std::string_view ident) const -> std::string
|
||||||
|
{
|
||||||
|
return std::format("{}{}", m_superlabel, ident);
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
enum class Mnemonic {
|
enum class Mnemonic {
|
||||||
@ -576,9 +585,9 @@ auto Assembler::eval_operand(const Expr& expr) -> std::unique_ptr<EvaledOperand>
|
|||||||
return std::make_unique<EO>(loc, EOT::Str, expr.as_str());
|
return std::make_unique<EO>(loc, EOT::Str, expr.as_str());
|
||||||
case Expr::Ty::Mem:
|
case Expr::Ty::Mem:
|
||||||
case Expr::Ty::MemWord:
|
case Expr::Ty::MemWord:
|
||||||
return eval_operand_mem(expr);
|
return eval_operand_mem(*expr.as_unary());
|
||||||
case Expr::Ty::MemByte: {
|
case Expr::Ty::MemByte: {
|
||||||
auto evaled = eval_operand_mem(expr);
|
auto evaled = eval_operand_mem(*expr.as_unary());
|
||||||
switch (evaled->ty) {
|
switch (evaled->ty) {
|
||||||
case EOT::MemWordImm:
|
case EOT::MemWordImm:
|
||||||
evaled->ty = EOT::MemByteImm;
|
evaled->ty = EOT::MemByteImm;
|
||||||
@ -587,7 +596,7 @@ auto Assembler::eval_operand(const Expr& expr) -> std::unique_ptr<EvaledOperand>
|
|||||||
evaled->ty = EOT::MemByteReg;
|
evaled->ty = EOT::MemByteReg;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
assert(false && "should be either of the above");
|
||||||
}
|
}
|
||||||
return evaled;
|
return evaled;
|
||||||
}
|
}
|
||||||
@ -631,7 +640,8 @@ auto Assembler::eval_operand_mem(const Expr& expr)
|
|||||||
expr.loc, EOT::MemWordImm, op->as_imm());
|
expr.loc, EOT::MemWordImm, op->as_imm());
|
||||||
}
|
}
|
||||||
case Expr::Ty::Reg:
|
case Expr::Ty::Reg:
|
||||||
return std::make_unique<EO>(expr.loc, EOT::Reg, expr.as_reg());
|
return std::make_unique<EO>(
|
||||||
|
expr.loc, EOT::MemWordReg, expr.as_reg());
|
||||||
case Expr::Ty::Str:
|
case Expr::Ty::Str:
|
||||||
case Expr::Ty::Mem:
|
case Expr::Ty::Mem:
|
||||||
case Expr::Ty::MemByte:
|
case Expr::Ty::MemByte:
|
||||||
@ -704,7 +714,8 @@ auto Assembler::eval_operand_to_imm(const Expr& expr)
|
|||||||
auto loc = expr.loc;
|
auto loc = expr.loc;
|
||||||
switch (expr.ty) {
|
switch (expr.ty) {
|
||||||
case Expr::Ty::Ident: {
|
case Expr::Ty::Ident: {
|
||||||
if (!m_syms.contains(expr.as_ident())) {
|
auto ident = std::string(expr.as_ident());
|
||||||
|
if (!m_syms.contains(ident)) {
|
||||||
if (m_second_pass) {
|
if (m_second_pass) {
|
||||||
error(expr.loc,
|
error(expr.loc,
|
||||||
std::format(
|
std::format(
|
||||||
@ -715,11 +726,12 @@ auto Assembler::eval_operand_to_imm(const Expr& expr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto value = m_syms[expr.as_ident()];
|
auto value = m_syms[ident];
|
||||||
return std::make_unique<EO>(loc, EOT::Imm, value);
|
return std::make_unique<EO>(loc, EOT::Imm, value);
|
||||||
}
|
}
|
||||||
case Expr::Ty::SubLabel: {
|
case Expr::Ty::SubLabel: {
|
||||||
if (!m_sublabels.contains(expr.as_ident())) {
|
auto ident = sublabel_ident(expr.as_ident());
|
||||||
|
if (!m_sublabels.contains(ident)) {
|
||||||
if (m_second_pass) {
|
if (m_second_pass) {
|
||||||
error(expr.loc,
|
error(expr.loc,
|
||||||
std::format(
|
std::format(
|
||||||
@ -730,7 +742,7 @@ auto Assembler::eval_operand_to_imm(const Expr& expr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto value = m_sublabels[expr.as_ident()];
|
auto value = m_sublabels[ident];
|
||||||
return std::make_unique<EO>(loc, EOT::Imm, value);
|
return std::make_unique<EO>(loc, EOT::Imm, value);
|
||||||
}
|
}
|
||||||
case Expr::Ty::Reg:
|
case Expr::Ty::Reg:
|
||||||
@ -908,7 +920,9 @@ auto Parser::parse_line() -> std::unique_ptr<Line>
|
|||||||
error(current_loc(), "expected identifier");
|
error(current_loc(), "expected identifier");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
ident = m_tok.text;
|
ident = is_local
|
||||||
|
? std::string_view(m_tok.text.data() - 1, m_tok.text.size() + 1)
|
||||||
|
: m_tok.text;
|
||||||
step();
|
step();
|
||||||
|
|
||||||
if (not eat(':')) {
|
if (not eat(':')) {
|
||||||
|
|||||||
@ -210,15 +210,18 @@ namespace asmer {
|
|||||||
auto assemble_file()
|
auto assemble_file()
|
||||||
-> std::expected<std::vector<uint8_t>, std::string>;
|
-> std::expected<std::vector<uint8_t>, std::string>;
|
||||||
|
|
||||||
void assemble_define_labels(const std::vector<Label>& labels);
|
|
||||||
void assemble_line(const Line& line);
|
|
||||||
|
|
||||||
auto ok() const -> bool
|
auto ok() const -> bool
|
||||||
{
|
{
|
||||||
return not m_failed;
|
return not m_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void define_labels(const std::vector<Label>& labels);
|
||||||
|
void assemble_line(const Line& line);
|
||||||
|
|
||||||
|
auto label_ident(const Label& label) const -> std::string;
|
||||||
|
auto sublabel_ident(std::string_view ident) const -> std::string;
|
||||||
|
|
||||||
auto eval_operand(const Expr& expr) -> std::unique_ptr<EvaledOperand>;
|
auto eval_operand(const Expr& expr) -> std::unique_ptr<EvaledOperand>;
|
||||||
auto eval_operand_mem(const Expr& expr)
|
auto eval_operand_mem(const Expr& expr)
|
||||||
-> std::unique_ptr<EvaledOperand>;
|
-> std::unique_ptr<EvaledOperand>;
|
||||||
@ -237,8 +240,9 @@ namespace asmer {
|
|||||||
std::string_view m_text;
|
std::string_view m_text;
|
||||||
std::vector<uint8_t> m_program;
|
std::vector<uint8_t> m_program;
|
||||||
Builder m_builder;
|
Builder m_builder;
|
||||||
std::unordered_map<std::string_view, uint16_t> m_syms {};
|
std::unordered_map<std::string, uint16_t> m_syms {};
|
||||||
std::unordered_map<std::string_view, uint16_t> m_sublabels {};
|
std::string m_superlabel {};
|
||||||
|
std::unordered_map<std::string, uint16_t> m_sublabels {};
|
||||||
bool m_second_pass = false;
|
bool m_second_pass = false;
|
||||||
bool m_failed = false;
|
bool m_failed = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -53,7 +53,8 @@ private:
|
|||||||
class FileDisk final : public BlockDevice {
|
class FileDisk final : public BlockDevice {
|
||||||
public:
|
public:
|
||||||
explicit FileDisk(fs::path file_path)
|
explicit FileDisk(fs::path file_path)
|
||||||
: m_file(file_path, std::ios_base::binary)
|
: m_file(file_path,
|
||||||
|
std::ios_base::binary | std::ios_base::in | std::ios_base::out)
|
||||||
{
|
{
|
||||||
if (not m_file) {
|
if (not m_file) {
|
||||||
throw std::invalid_argument(std::format(
|
throw std::invalid_argument(std::format(
|
||||||
|
|||||||
23
src/main.cpp
23
src/main.cpp
@ -29,6 +29,29 @@ int main(int argc, char** argv)
|
|||||||
} else {
|
} else {
|
||||||
auto disk = FileDisk(argv[1]);
|
auto disk = FileDisk(argv[1]);
|
||||||
|
|
||||||
|
auto memory_disk = MemoryDisk(128);
|
||||||
|
make_program(memory_disk.data());
|
||||||
|
|
||||||
|
auto file_block = std::vector<uint8_t>(BlockDevice::block_size);
|
||||||
|
disk.read(file_block.data(), 0);
|
||||||
|
|
||||||
|
auto memory_block = std::vector<uint8_t>(BlockDevice::block_size);
|
||||||
|
memory_disk.read(memory_block.data(), 0);
|
||||||
|
|
||||||
|
std::println("file memory");
|
||||||
|
for (size_t i = 0; i < 64; i += 4) {
|
||||||
|
std::println(
|
||||||
|
"{:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x}",
|
||||||
|
file_block[i],
|
||||||
|
file_block[i + 1],
|
||||||
|
file_block[i + 2],
|
||||||
|
file_block[i + 3],
|
||||||
|
memory_block[i],
|
||||||
|
memory_block[i + 1],
|
||||||
|
memory_block[i + 2],
|
||||||
|
memory_block[i + 3]);
|
||||||
|
}
|
||||||
|
|
||||||
auto vm = VM(*device, disk);
|
auto vm = VM(*device, disk);
|
||||||
vm.run();
|
vm.run();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user