Implement comparison operators

This commit is contained in:
2024-04-02 09:07:13 +02:00
parent 3c19bf1504
commit 4251c361c7
9 changed files with 205 additions and 42 deletions

View File

@ -235,11 +235,13 @@ namespace elna::riscv
void visitor::visit(source::call_statement *statement)
{
std::size_t argument_offset{ 0 };
for (auto& argument : statement->arguments())
{
argument->accept(this);
const auto free_register = this->register_in_use ? x_register::a0 : x_register::t0;
this->instructions.push_back(instruction(base_opcode::store)
.s(argument_offset, funct3_t::sw, x_register::sp, x_register::a0));
.s(argument_offset, funct3_t::sw, x_register::sp, free_register));
argument_offset += 4;
}
relocate(statement->name(), address_t::text);
@ -321,19 +323,21 @@ namespace elna::riscv
this->register_in_use = true;
expression->lhs().accept(this);
auto lhs_stack_position = this->variable_counter * 4;
++this->variable_counter;
this->instructions.push_back( // movl %eax, -x(%rbp); where x is a number.
this->instructions.push_back(
instruction(base_opcode::store)
.s(static_cast<std::uint32_t>(this->variable_counter * 4), funct3_t::sw, x_register::sp, x_register::a0)
.s(static_cast<std::uint32_t>(lhs_stack_position), funct3_t::sw, x_register::sp, x_register::a0)
);
auto lhs_stack_position = ++this->variable_counter;
this->register_in_use = false;
expression->rhs().accept(this);
this->register_in_use = lhs_register == x_register::a0; // Restore.
this->instructions.push_back(instruction(base_opcode::load)
.i(x_register::a0, funct3_t::lw, x_register::sp,
static_cast<std::int8_t>((lhs_stack_position - 1) * 4))
static_cast<std::int8_t>(lhs_stack_position))
);
// Calculate the result and assign it to a variable on the stack.
@ -355,6 +359,38 @@ namespace elna::riscv
this->instructions.push_back(instruction(base_opcode::op)
.r(lhs_register, funct3_t::div, x_register::a0, x_register::t0, funct7_t::muldiv));
break;
case source::binary_operator::equals:
this->instructions.push_back(instruction(base_opcode::op)
.r(lhs_register, funct3_t::sub, x_register::a0, x_register::t0, funct7_t::sub));
this->instructions.push_back(instruction(base_opcode::opImm)
.i(lhs_register, funct3_t::sltiu, lhs_register, 1));
break;
case source::binary_operator::not_equals:
this->instructions.push_back(instruction(base_opcode::op)
.r(lhs_register, funct3_t::sub, x_register::a0, x_register::t0, funct7_t::sub));
this->instructions.push_back(instruction(base_opcode::op)
.r(lhs_register, funct3_t::sltu, x_register::zero, lhs_register));
break;
case source::binary_operator::less:
this->instructions.push_back(instruction(base_opcode::op)
.r(lhs_register, funct3_t::sltu, x_register::a0, x_register::t0));
break;
case source::binary_operator::greater_equal:
this->instructions.push_back(instruction(base_opcode::op)
.r(lhs_register, funct3_t::sltu, x_register::t0, x_register::a0));
break;
case source::binary_operator::greater:
this->instructions.push_back(instruction(base_opcode::op)
.r(lhs_register, funct3_t::slt, x_register::a0, x_register::t0));
this->instructions.push_back(instruction(base_opcode::opImm)
.i(lhs_register, funct3_t::xori, lhs_register, 1));
break;
case source::binary_operator::less_equal:
this->instructions.push_back(instruction(base_opcode::op)
.r(lhs_register, funct3_t::slt, x_register::t0, x_register::a0));
this->instructions.push_back(instruction(base_opcode::opImm)
.i(lhs_register, funct3_t::xori, lhs_register, 1));
break;
}
}