Implement first intrinsics for output
This commit is contained in:
@ -81,11 +81,112 @@ namespace elna::riscv
|
||||
{
|
||||
}
|
||||
|
||||
void visitor::generate_intrinsics()
|
||||
{
|
||||
this->writer->sink("printf");
|
||||
{
|
||||
auto format_string = this->writer->sink(reinterpret_cast<const std::byte *>("%c\n\0"), 4);
|
||||
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::sp, funct3_t::addi, x_register::sp, -8));
|
||||
this->instructions.push_back(instruction(base_opcode::store)
|
||||
.s(4, funct3_t::sw, x_register::sp, x_register::s0));
|
||||
this->instructions.push_back(instruction(base_opcode::store)
|
||||
.s(0, funct3_t::sw, x_register::sp, x_register::ra));
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::s0, funct3_t::addi, x_register::sp, -8));
|
||||
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::a1, funct3_t::addi, x_register::zero, 't'));
|
||||
this->instructions.push_back(instruction(base_opcode::branch)
|
||||
.b(8, funct3_t::bne, x_register::zero, x_register::a0));
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::a1, funct3_t::addi, x_register::zero, 'f'));
|
||||
|
||||
relocate(format_string, address_t::high20);
|
||||
this->instructions.push_back(instruction(base_opcode::lui).u(x_register::a5, 0));
|
||||
relocate(format_string, address_t::lower12i);
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::a0, funct3_t::addi, x_register::a5, 0));
|
||||
|
||||
relocate("printf", address_t::text);
|
||||
this->instructions.push_back(instruction(base_opcode::auipc).u(x_register::ra, 0));
|
||||
this->instructions.push_back(instruction(base_opcode::jalr)
|
||||
.i(x_register::ra, funct3_t::jalr, x_register::ra, 0));
|
||||
|
||||
this->instructions.push_back(instruction(base_opcode::load)
|
||||
.i(x_register::s0, funct3_t::lw, x_register::sp, 4));
|
||||
this->instructions.push_back(instruction(base_opcode::load)
|
||||
.i(x_register::ra, funct3_t::lw, x_register::sp, 0));
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::sp, funct3_t::addi, x_register::sp, 8));
|
||||
this->instructions.push_back(instruction(base_opcode::jalr)
|
||||
.i(x_register::zero, funct3_t::jalr, x_register::ra, 0));
|
||||
|
||||
this->writer->sink("writeb", reinterpret_cast<const std::byte *>(this->instructions.data()),
|
||||
this->instructions.size() * sizeof(instruction));
|
||||
|
||||
this->instructions.clear();
|
||||
}
|
||||
{
|
||||
auto format_string = this->writer->sink(reinterpret_cast<const std::byte *>("%d\n\0"), 4);
|
||||
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::sp, funct3_t::addi, x_register::sp, -8));
|
||||
this->instructions.push_back(instruction(base_opcode::store)
|
||||
.s(4, funct3_t::sw, x_register::sp, x_register::s0));
|
||||
this->instructions.push_back(instruction(base_opcode::store)
|
||||
.s(0, funct3_t::sw, x_register::sp, x_register::ra));
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::s0, funct3_t::addi, x_register::sp, -8));
|
||||
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::a1, funct3_t::addi, x_register::a0, 0));
|
||||
|
||||
relocate(format_string, address_t::high20);
|
||||
this->instructions.push_back(instruction(base_opcode::lui).u(x_register::a5, 0));
|
||||
relocate(format_string, address_t::lower12i);
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::a0, funct3_t::addi, x_register::a5, 0));
|
||||
|
||||
relocate("printf", address_t::text);
|
||||
this->instructions.push_back(instruction(base_opcode::auipc).u(x_register::ra, 0));
|
||||
this->instructions.push_back(instruction(base_opcode::jalr)
|
||||
.i(x_register::ra, funct3_t::jalr, x_register::ra, 0));
|
||||
|
||||
this->instructions.push_back(instruction(base_opcode::load)
|
||||
.i(x_register::s0, funct3_t::lw, x_register::sp, 4));
|
||||
this->instructions.push_back(instruction(base_opcode::load)
|
||||
.i(x_register::ra, funct3_t::lw, x_register::sp, 0));
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::sp, funct3_t::addi, x_register::sp, 8));
|
||||
this->instructions.push_back(instruction(base_opcode::jalr)
|
||||
.i(x_register::zero, funct3_t::jalr, x_register::ra, 0));
|
||||
|
||||
this->writer->sink("writei", reinterpret_cast<const std::byte *>(this->instructions.data()),
|
||||
this->instructions.size() * sizeof(instruction));
|
||||
|
||||
this->instructions.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void visitor::relocate(std::string_view name, address_t target)
|
||||
{
|
||||
this->references.push_back(reference());
|
||||
this->references.back().name = name;
|
||||
this->references.back().offset = writer->size() + instructions.size() * 4;
|
||||
this->references.back().target = target;
|
||||
}
|
||||
|
||||
void visitor::visit(source::declaration *declaration)
|
||||
{
|
||||
}
|
||||
|
||||
void visitor::visit(source::definition *definition)
|
||||
void visitor::visit(source::constant_definition *definition)
|
||||
{
|
||||
}
|
||||
|
||||
void visitor::visit(source::procedure_definition *definition)
|
||||
{
|
||||
}
|
||||
|
||||
@ -126,51 +227,8 @@ namespace elna::riscv
|
||||
|
||||
void visitor::visit(source::program *program)
|
||||
{
|
||||
this->writer->sink("printf");
|
||||
auto format_string = this->writer->sink(reinterpret_cast<const std::byte *>("%d\n\0"), 4);
|
||||
generate_intrinsics();
|
||||
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::sp, funct3_t::addi, x_register::sp, -8));
|
||||
this->instructions.push_back(instruction(base_opcode::store)
|
||||
.s(4, funct3_t::sw, x_register::sp, x_register::s0));
|
||||
this->instructions.push_back(instruction(base_opcode::store)
|
||||
.s(0, funct3_t::sw, x_register::sp, x_register::ra));
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::s0, funct3_t::addi, x_register::sp, -8));
|
||||
|
||||
this->references.push_back(reference());
|
||||
this->references.back().name = format_string;
|
||||
this->references.back().offset = writer->size() + instructions.size() * 4;
|
||||
this->references.back().target = address_t::high20;
|
||||
this->instructions.push_back(instruction(base_opcode::lui).u(x_register::a5, 0));
|
||||
this->references.push_back(reference());
|
||||
this->references.back().name = format_string;
|
||||
this->references.back().offset = writer->size() + instructions.size() * 4;
|
||||
this->references.back().target = address_t::lower12i;
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::a0, funct3_t::addi, x_register::a5, 0));
|
||||
|
||||
this->references.push_back(reference());
|
||||
this->references.back().name = "printf";
|
||||
this->references.back().offset = writer->size() + instructions.size() * 4;
|
||||
this->references.back().target = address_t::text;
|
||||
this->instructions.push_back(instruction(base_opcode::auipc).u(x_register::ra, 0));
|
||||
this->instructions.push_back(instruction(base_opcode::jalr)
|
||||
.i(x_register::ra, funct3_t::jalr, x_register::ra, 0));
|
||||
|
||||
this->instructions.push_back(instruction(base_opcode::load)
|
||||
.i(x_register::s0, funct3_t::lw, x_register::sp, 4));
|
||||
this->instructions.push_back(instruction(base_opcode::load)
|
||||
.i(x_register::ra, funct3_t::lw, x_register::sp, 0));
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::sp, funct3_t::addi, x_register::sp, 8));
|
||||
this->instructions.push_back(instruction(base_opcode::jalr)
|
||||
.i(x_register::zero, funct3_t::jalr, x_register::ra, 0));
|
||||
|
||||
this->writer->sink("writei", reinterpret_cast<const std::byte *>(this->instructions.data()),
|
||||
this->instructions.size() * sizeof(instruction));
|
||||
|
||||
this->instructions.clear();
|
||||
visit(dynamic_cast<source::block *>(program));
|
||||
this->writer->sink("main", reinterpret_cast<const std::byte *>(this->instructions.data()),
|
||||
this->instructions.size() * sizeof(instruction));
|
||||
@ -180,41 +238,7 @@ namespace elna::riscv
|
||||
{
|
||||
statement->arguments().accept(this);
|
||||
|
||||
// Print the result.
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::a1, funct3_t::addi, x_register::a0, 0));
|
||||
|
||||
this->instructions.push_back(instruction(base_opcode::auipc).u(x_register::ra, 0));
|
||||
this->instructions.push_back(instruction(base_opcode::jalr)
|
||||
.i(x_register::ra, funct3_t::jalr, x_register::ra, -instructions.size() * 4 - 40));
|
||||
}
|
||||
|
||||
void visitor::visit(source::question_mark_statement *statement)
|
||||
{
|
||||
statement->body().accept(this);
|
||||
|
||||
// Print the result.
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::a1, funct3_t::addi, x_register::a0, 0));
|
||||
|
||||
auto format_string = this->writer->sink(reinterpret_cast<const std::byte *>("%d\n\0"), 4);
|
||||
|
||||
this->references.push_back(reference());
|
||||
this->references.back().name = format_string;
|
||||
this->references.back().offset = writer->size() + instructions.size() * 4;
|
||||
this->references.back().target = address_t::high20;
|
||||
this->instructions.push_back(instruction(base_opcode::lui).u(x_register::a5, 0));
|
||||
this->references.push_back(reference());
|
||||
this->references.back().name = format_string;
|
||||
this->references.back().offset = writer->size() + instructions.size() * 4;
|
||||
this->references.back().target = address_t::lower12i;
|
||||
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::a0, funct3_t::addi, x_register::a5, 0));
|
||||
this->references.push_back(reference());
|
||||
this->references.back().name = "printf";
|
||||
this->references.back().offset = writer->size() + instructions.size() * 4;
|
||||
this->references.back().target = address_t::text;
|
||||
relocate(statement->name(), address_t::text);
|
||||
this->instructions.push_back(instruction(base_opcode::auipc).u(x_register::ra, 0));
|
||||
this->instructions.push_back(instruction(base_opcode::jalr)
|
||||
.i(x_register::ra, funct3_t::jalr, x_register::ra, 0));
|
||||
@ -242,15 +266,15 @@ namespace elna::riscv
|
||||
|
||||
void visitor::visit(source::if_statement *statement)
|
||||
{
|
||||
const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0;
|
||||
|
||||
statement->prerequisite().accept(this);
|
||||
|
||||
const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0;
|
||||
|
||||
auto before_branch = instructions.size();
|
||||
instructions.push_back(instruction(base_opcode::branch));
|
||||
statement->body().accept(this);
|
||||
instructions[before_branch]
|
||||
.b((instructions.size() - before_branch) * 4, funct3_t::beq, x_register::zero, free_register);
|
||||
.b((instructions.size() - before_branch) * 4 - 4, funct3_t::beq, x_register::zero, free_register);
|
||||
}
|
||||
|
||||
void visitor::visit(source::while_statement *statement)
|
||||
|
@ -204,22 +204,19 @@ namespace elna::riscv
|
||||
|
||||
for (auto& reference : _visitor.references)
|
||||
{
|
||||
ELFIO::Elf_Word relocated_symbol{ 0 };
|
||||
ELFIO::Elf_Word relocated_symbol = lookup(syma, reference.name);
|
||||
|
||||
switch (reference.target)
|
||||
{
|
||||
case address_t::high20:
|
||||
relocated_symbol = lookup(syma, reference.name);
|
||||
rela.add_entry(reference.offset, relocated_symbol, 26 /* ELFIO::R_RISCV_HI20 */);
|
||||
rela.add_entry(reference.offset, relocated_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||
break;
|
||||
case address_t::lower12i:
|
||||
relocated_symbol = lookup(syma, reference.name);
|
||||
rela.add_entry(reference.offset, relocated_symbol, 27 /* ELFIO::R_RISCV_LO12_I */);
|
||||
rela.add_entry(reference.offset, relocated_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||
break;
|
||||
case address_t::text:
|
||||
relocated_symbol = lookup(syma, "printf");
|
||||
rela.add_entry(reference.offset, relocated_symbol, 18 /* ELFIO::R_RISCV_CALL */);
|
||||
rela.add_entry(reference.offset, relocated_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||
break;
|
||||
|
Reference in New Issue
Block a user