Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integer absolute value in MIPS?

Do you have any simple ways to make a value in a register in MIPS as an absolute value?

like image 364
aherlambang Avatar asked Feb 22 '10 16:02

aherlambang


Video Answer


3 Answers

Here's a branch-less variant:

# input and output in $t0
sra $t1,$t0,31   
xor $t0,$t0,$t1   
sub $t0,$t0,$t1    

How does this work?
First, $t1 is filled with the sign-bit of $t0. So if $t0 is positive $t1 will be set to 0, and if $t0 is negative $t1 will be set to 0xFFFFFFFF.

Next, each bit of $t0 is inverted if $t1 is 0xFFFFFFFF, or left unchanged if $t1 is 0. It just so happens that inverting all bits of a number is the same as setting it to (-number)-1 (in two's complement).

Finally, either 0xFFFFFFFF (which equals -1) or 0 is subtracted from the intermediate result.

So if $t0 originally was negative you'll get:
$t0 = ($t0 ^ 0xFFFFFFFF) - 0xFFFFFFFF == (-$t0 - 1) - -1 == (-$t0 - 1) + 1 == -$t0.
And if it originally was positive you'll get:
$t0 = ($t0 ^ 0) - 0 == $t0.

like image 110
Michael Avatar answered Sep 20 '22 02:09

Michael


Here is a pretty simple way to do it.

#assume you want the absolute value of r1
        ori $2, $zero, $1      #copy r1 into r2
        slt $3, $1, $zero      #is value < 0 ?
        beq $3, $zero, foobar  #if r1 is positive, skip next inst
        sub $2, $zero, $1      #r2 = 0 - r1
foobar:
#r2 now contains the absolute value of r1
like image 40
swanson Avatar answered Sep 19 '22 02:09

swanson


Here's a size-optimized version of it. It's slower than the sra/xor/subu answer, due to branch prediction issues, but it's one instruction smaller:

    bgtz $t0, label
label:
    subu $t0, $zero, $t0

This works because of the MIPS delay slot: if $t0 is positive, the subu instruction to negate $t0 executes twice. You may need to enable .set noreorder in your assembler.

like image 22
Myria Avatar answered Sep 17 '22 02:09

Myria