How to do less than or equal in Assembly Language(MIPS)?

As usual, ask a compiler (e.g. on the Godbolt compiler explorer). See also How to remove “noise” from GCC/clang assembly output?


<= alone (without the increment) is best implemented with a reversed slt (to do b<a which is the opposite of a<=b) and then xori to flip the result.

int booleanize_le(int y, int z){
    return (z<=y);
}
# GCC5.4 -O3 -fno-delayed-branch
booleanize_le(int, int):
        slt     $2,$4,$5        # slt retval, y, z
        xori    $2,$2,0x1       # !retval, i.e. flip 0 <-> 1 since it was already boolean
        j       $31                       # return
  # (omitting the NOP in the branch-delay slot)

Fun fact: clang for RISC-V does the same thing, slt/xori, because RISC-V is like MIPS in only providing slt for compare-into-boolean. (Because you can booleanize any relation like ==, <=, >, or whatever into an integer register with at most 2 instructions.)


But in your case where you want to increment, and you’re using addi so clearly z must be a signed int (otherwise your code would fault on increment from 0x7fffffffU to 0x80000000U; use addiu if you want well-defined wrap around).

C rules for signed-overflow being undefined behaviour basically match use of MIPS addi, which means compilers will also assume ++z doesn’t wrap, and do the optimization we want. They and we we can just use the original z value. (z+1)<=y is the same thing as z<y if z+1 doesn’t / can’t wrap.

int booleanize_inc_le_signed(int y, int z){
    return ((++z)<=y);
}
booleanize_inc_le_signed(int, int):
        slt     $2,$5,$4             # z<y  before incrementing
        j       $31
    # increment optimized away in this function, but you'd do it with
    addiu   $5, $5, 1

If z had been unsigned, that optimization isn’t possible and the compiler does just increment and then use the unsigned version of the 2-instruction <= slt/xori sequence:

int booleanize_inc_le_unsigned(unsigned int y, unsigned int z){
    return ((++z)<=y);
}
booleanize_inc_le_unsigned(unsigned int, unsigned int):
        addiu   $5,$5,1                # z++
        sltu    $2,$4,$5               # y<z (unsigned)
        xori    $2,$2,0x1              # return !(y<z)
        j       $31

Other relations

Exact equality, a == b

    xor     $2,$4,$5          # find bit-differences
    sltu    $2,$2,1           # (a^b) < 1U

Not equal, a != b

    xor     $2,$4,$5
    sltu    $2,$0,$2          # 0U < (a^b)

One integer being non-zero: a!=0, i.e. !!a

    sltu    $2,$0,$4          # 0U < a

Any others can obviously be derived, or just ask a compiler (use the Godbolt link).

Leave a Comment