ble | bleu | bgt | bgtu instructions with immediate MAX values are not correctly evaluated
Initially found out by @elsakeirouz & @DaiF1 via the following example:
ble
instruction comparing a register $ra
with a lower value & signed INT_MAX
is not correctly evaluated.
ble $ra, 2147483647, label # KO!
ble
instruction comparing a register $ra
with a lower value & any other immediate is correctly evaluated (e.g. with signed INT_MAX
- 1).
ble $ra, 2147483646, label # OK
An arithmetic operation (+) is the cause of the trouble/overflow:
void ProgramBuilder::add_ble(Register* src1, Exp* src2, Exp* dest)
{
program_->text_section().add_inst(
new Slti(Register(Register::general, Cpu::at), *src1,
new OpExp(src2, OpExp::add, new IntExp(1))));
// ...
}
from https://gitlab.lre.epita.fr/tiger/nolimips/-/blob/master/src/inst/program_builder.cc#L399
This issue is inherent to available MIPS native instructions: The comparison with an immediate via slti
(set on less than immediate) is used in such a way that it does not seem possible to use INT_MAX
.
NOTE : ble
instruction with an immediate is not natively supported in MIPS. In our case, we use the only available instruction to compare the immediate: slti
, adding 1 to the right operand.
The same logic is applicable to bleu
, bgt
, bgtu
with negated/unsigned checks.
For now, I have considered the following approaches:
- abandon those instructions
- independently check
src1 < src2
andsrc1 == src2
(and so on) - use a register to correctly compare via other instructions like a "native"
ble
(via$at
)
Do not hesitate to comment more about this issue & suggest fixes.