Implement simple if conditions
This commit is contained in:
@ -18,13 +18,24 @@ namespace elna::riscv
|
||||
return *this;
|
||||
}
|
||||
|
||||
instruction& instruction::s(std::uint32_t imm1, funct3_t funct3, x_register rs1, x_register rs2)
|
||||
instruction& instruction::s(std::uint32_t imm, funct3_t funct3, x_register rs1, x_register rs2)
|
||||
{
|
||||
this->representation |= ((imm1 & 0b11111) << 7)
|
||||
this->representation |= ((imm & 0x1f) << 7)
|
||||
| (static_cast<std::underlying_type<funct3_t>::type>(funct3) << 12)
|
||||
| (static_cast<std::underlying_type<x_register>::type>(rs1) << 15)
|
||||
| (static_cast<std::underlying_type<x_register>::type>(rs2) << 20)
|
||||
| ((imm1 & 0b111111100000) << 20);
|
||||
| ((imm & 0xfe0) << 20);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
instruction& instruction::b(std::uint32_t imm, funct3_t funct3, x_register rs1, x_register rs2)
|
||||
{
|
||||
this->representation |= ((imm & 0x800) >> 4) | ((imm & 0x1e) << 7)
|
||||
| (static_cast<std::underlying_type<funct3_t>::type>(funct3) << 12)
|
||||
| (static_cast<std::underlying_type<x_register>::type>(rs1) << 15)
|
||||
| (static_cast<std::underlying_type<x_register>::type>(rs2) << 20)
|
||||
| ((imm & 0x7e0) << 20) | ((imm & 0x1000) << 19);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -47,6 +58,14 @@ namespace elna::riscv
|
||||
return *this;
|
||||
}
|
||||
|
||||
instruction& instruction::j(x_register rd, std::uint32_t imm)
|
||||
{
|
||||
this->representation |= (static_cast<std::underlying_type<x_register>::type>(rd) << 7)
|
||||
| (imm & 0xff000) | ((imm & 0x800) << 9) | ((imm & 0x7fe) << 20) | ((imm & 0x100000) << 11);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const std::byte *instruction::cbegin() const
|
||||
{
|
||||
return reinterpret_cast<const std::byte *>(&this->representation);
|
||||
@ -108,13 +127,46 @@ namespace elna::riscv
|
||||
this->instructions.push_back(instruction(base_opcode::opImm)
|
||||
.i(x_register::a1, funct3_t::addi, x_register::a0, 0));
|
||||
|
||||
auto format_string = this->read_only.label("%d\n");
|
||||
|
||||
this->references.push_back(reference());
|
||||
this->references.back().name = ".CL0";
|
||||
this->references.back().name = format_string->first;
|
||||
this->references.back().offset = 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 = ".CL0";
|
||||
this->references.back().name = format_string->first;
|
||||
this->references.back().offset = 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 = 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));
|
||||
}
|
||||
|
||||
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->read_only.label("%d\n");
|
||||
|
||||
this->references.push_back(reference());
|
||||
this->references.back().name = format_string->first;
|
||||
this->references.back().offset = 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->first;
|
||||
this->references.back().offset = instructions.size() * 4;
|
||||
this->references.back().target = address_t::lower12i;
|
||||
|
||||
@ -149,6 +201,25 @@ namespace elna::riscv
|
||||
.s(variable_symbol->offset, funct3_t::sw, x_register::s0, x_register::a0));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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 - 3, funct3_t::beq, x_register::zero, free_register);
|
||||
}
|
||||
|
||||
void visitor::visit(source::while_statement *statement)
|
||||
{
|
||||
statement->prerequisite().accept(this);
|
||||
statement->body().accept(this);
|
||||
}
|
||||
|
||||
void visitor::visit(source::variable_expression *variable)
|
||||
{
|
||||
const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0;
|
||||
@ -170,16 +241,6 @@ namespace elna::riscv
|
||||
}
|
||||
}
|
||||
|
||||
void visitor::visit(source::integer_literal *number)
|
||||
{
|
||||
const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0;
|
||||
|
||||
this->instructions.push_back(
|
||||
instruction(base_opcode::opImm) // movl $x, %eax; where $x is a number.
|
||||
.i(free_register, funct3_t::addi, x_register::zero, number->number())
|
||||
);
|
||||
}
|
||||
|
||||
void visitor::visit(source::binary_expression *expression)
|
||||
{
|
||||
const auto lhs_register = this->register_in_use ? x_register::a0 : x_register::t0;
|
||||
@ -222,4 +283,24 @@ namespace elna::riscv
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void visitor::visit(source::integer_literal *number)
|
||||
{
|
||||
const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0;
|
||||
|
||||
this->instructions.push_back(
|
||||
instruction(base_opcode::opImm) // movl $x, %eax; where $x is a number.
|
||||
.i(free_register, funct3_t::addi, x_register::zero, number->number())
|
||||
);
|
||||
}
|
||||
|
||||
void visitor::visit(source::boolean_literal *number)
|
||||
{
|
||||
const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0;
|
||||
|
||||
this->instructions.push_back(
|
||||
instruction(base_opcode::opImm) // movl $x, %eax; where $x is a number.
|
||||
.i(free_register, funct3_t::addi, x_register::zero, number->boolean())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -33,13 +33,6 @@ namespace elna::riscv
|
||||
// Create string table writer
|
||||
ELFIO::string_section_accessor stra(str_sec);
|
||||
|
||||
// Create read only data section
|
||||
ELFIO::section* ro_sec = writer.sections.add(".rodata");
|
||||
ro_sec->set_type(ELFIO::SHT_PROGBITS);
|
||||
ro_sec->set_flags(ELFIO::SHF_ALLOC);
|
||||
ro_sec->set_addr_align(0x4);
|
||||
ro_sec->set_data("%d\n");
|
||||
|
||||
// Create symbol table section
|
||||
ELFIO::section* sym_sec = writer.sections.add(".symtab");
|
||||
sym_sec->set_type(ELFIO::SHT_SYMTAB);
|
||||
@ -57,24 +50,38 @@ namespace elna::riscv
|
||||
rel_sec->set_link(sym_sec->get_index());
|
||||
rel_sec->set_flags(ELFIO::SHF_ALLOC);
|
||||
|
||||
// Create read only data section
|
||||
ELFIO::section* ro_sec = writer.sections.add(".rodata");
|
||||
ro_sec->set_type(ELFIO::SHT_PROGBITS);
|
||||
ro_sec->set_flags(ELFIO::SHF_ALLOC);
|
||||
ro_sec->set_addr_align(0x4);
|
||||
|
||||
// Create symbol relocation table writers
|
||||
ELFIO::symbol_section_accessor syma(writer, sym_sec);
|
||||
ELFIO::relocation_section_accessor rela(writer, rel_sec);
|
||||
ELFIO::Elf_Word digit_symbol = syma.add_symbol(stra, ".CL0", 0x00000000, strlen("%d\n") + 1,
|
||||
ELFIO::STB_LOCAL, ELFIO::STT_NOTYPE, 0, ro_sec->get_index());
|
||||
ELFIO::Elf_Word digit_symbol;
|
||||
|
||||
for (auto read_only_text : _visitor->read_only)
|
||||
{
|
||||
ro_sec->append_data(read_only_text.second.data(), read_only_text.second.size());
|
||||
|
||||
syma.add_symbol(stra, read_only_text.first.c_str(), 0x00000000,
|
||||
read_only_text.first.size() + 1, ELFIO::STB_LOCAL, ELFIO::STT_NOTYPE, 0, ro_sec->get_index());
|
||||
}
|
||||
ELFIO::Elf_Word printf_symbol = syma.add_symbol(stra, "printf", 0x00000000, 0,
|
||||
ELFIO::STB_GLOBAL, ELFIO::STT_NOTYPE, 0, ELFIO::SHN_UNDEF);
|
||||
|
||||
for (auto& reference : _visitor->references)
|
||||
{
|
||||
// The loop assumes that address_t::lower12i always follows address_t::high20.
|
||||
switch (reference.target)
|
||||
{
|
||||
case address_t::high20:
|
||||
digit_symbol = _visitor->read_only.lookup(reference.name) + 1;
|
||||
rela.add_entry(reference.offset, digit_symbol, 26 /* ELFIO::R_RISCV_HI20 */);
|
||||
rela.add_entry(reference.offset, digit_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||
break;
|
||||
case address_t::lower12i:
|
||||
digit_symbol = _visitor->read_only.lookup(reference.name) + 1;
|
||||
rela.add_entry(reference.offset, digit_symbol, 27 /* ELFIO::R_RISCV_LO12_I */);
|
||||
rela.add_entry(reference.offset, digit_symbol, 51 /* ELFIO::R_RISCV_RELAX */);
|
||||
break;
|
||||
|
Reference in New Issue
Block a user