I want to perform 64-bit addition and subtraction:
v1v0(HiLo) = a1a0 + a3a2
using MIPS assembly language (a1a0(HiLo)
is the first 64-bit number consists of two 32-bit numbers, and a3a2(HiLo)
is the second)
and I have:
$a0 = 0xffffffff
$a1 = 0x0
$a2 = 0x1
$a3 = 0x0
I'm a beginner in MIPS, and I'm not sure how to handle carries. Could someone provide a solution with explanation?
Thanks in advance! This is the instruction set that I'm using:
http://www.cs.uregina.ca/Links/class-info/201/SPIM-IO/MIPSrefCard.pdf
To subtrate a number, i.e. v = a - b
is the same as doing an add with a negative number, i.e., v = a + (-b)
. But, in integer aritmetic, a negative number is coded as a 2-compliment, that is the same as 1-compliment + 1 and 1-compliment is a bitwise negation.
In this way, we can write that:
v1v0 = a1a0 - b1b0
v1v0 = a1a0 + ~b1~b0 + 1
so, we can write this in assembly as (assuming b1 = a3 and b0 = a2):
add64: addu $v0, $a0, $a2 # add least significant word
nor $t0, $a2, $zero # ~a2
sltu $t0, $a0, $t0 # set carry-in bit (capturing overflow)
addu $v1, $t0, $a1 # add in first most significant word
addu $v1, $v1, $a3 # add in second most significant word
jr $ra
#PS: To capture the carry bit in a unsigned sum is equivalent to test if the sum
# can not be contained in a 32 bit register. I.e. if a0 + a2 > 2^32 - 1
sub64: nor $a3, $a3, $zero # ~b1
nor $a2, $a2, $zero # ~b0
jal add64 # v1v0 = a1a0 + ~b1~b0
# adding 1 to v1v0
ori $a0, $v0, 0
ori $a1, $v1, 0
ori $a2, $zero, 1
ori $a3, $zero, 0
jal add64
jr $ra
using your ideas, which, I think you would answer your own question:
subu $v0, $a0, $a2 # $v0 = $a0 - $a2
sltu $v1, $a0, $a2 # $v1 = ($a0 < $a2)? 1:0(subtract 1 if there's a borrow for Lo words)
subu $a1, $a1, $v1 # $a1 = $a1 - $v1
subu $v1, $a1, $a3 # $v1 = $a1 - $a3