Skip to content

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 and src1 == 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.

Edited by Aurélien Delval-Carbonne