Reputation: 391
I am trying to multiply two IEEE 754 numbers in MIPS assembly without using floating point operations.
I have two floating point numbers stored in $a0 and $a1
multiply_fp: #$s0 = final sign bit, $s1 = final exponent, $s2 = final mantissa
#check the sign bit
srl $t1, $a0, 31 # leave just sign bit
srl $t2, $a1, 31 # leave just sign bit
bnez $t1, negative # check if sign bit is 1
bnez $t2, negative # check if sign bit is 1
positive:
addi $s0, $zero, 0 # set sign bit to 0
j exponent
negative:
addi $s0, $zero, 10000000000000000000000000000000 #set sign bit to 1
exponent:
andi $t1, $a0, 01111111100000000000000000000000 #get exponent bits from fp1
andi $t2, $a1, 01111111100000000000000000000000 #get exponent bits from fp2
srl $t1, $t1, 23 #move them all the way to the right
srl $t2, $t2, 23
add $s1, $t1, $t2 #add them together
addi $s1, $s1, -127 #subtract 127 from the sum
sll $s1, $s1, 23 #move them back to the right position
mantissa:
andi $t1, $a0, 00000000011111111111111111111111 #get the mantissa bits from fp1
andi $t2, $a1, 00000000011111111111111111111111 #get the mantissa bits from fp2
ori $t1, $t1, 00000000100000000000000000000000 #add a 1 at the msb
ori $t2, $t2, 00000000100000000000000000000000
mul $s2, $t1, $t2 #multiply the mantissas
andi $s2, 00000000011111111111111111111111 #cut the 1 back off
combine:
or $v0, $s0, $s1
or $v0, $v0, $s2
jr $ra
I am having trouble with the mantissa section I think. According to my logic I am to multiply the fraction portion and then get rid of leading 1. For example 1.011 * 1.010 = 1.10111 and I would cut off the leading 1 to result in 10111 as my new mantissa. I do this similarly by just removing the decimal points so: 1011 * 1010 = 110111 and cut off the leading 1 to result in 10111.
However the mul function is giving very odd results, and I'm not sure why. Can anyone see errors with my logic?
Upvotes: 3
Views: 3537
Reputation: 446
srl $t1, $a0, 23 //This take the exponent part
andi $t1, $t1, 0xFF
in that part $t1
is the exponent part of this number, if anyone wants to find exponent part of it they can use it.
I have wrote this because in my lab assignment i have to find the exponent part,thanks to this i can figure out my problem.
If anyone has problem like that they can use the code which is above.
Upvotes: 1
Reputation: 16586
Unfortunately I'm not that good with IEEE 754 to fix your mul without some studying, but the function prologue got me interested...
If you enter it with two negative numbers, it will jump to negative:
, while the answer should be positive.
You can calculate target sign for example like this:
multiply_fp:
xor $s0, $a0, $a1 # multiply sign bits
andi $s0, 0x80000000 # extract sign bit to s0
And I'm not sure what assembler you use, I have only MARS here, and that one compiles those binary numbers wrongly. I was also unable to find any help for its syntax (the included help is very vague about numeric constants and possible formatting).
So instead of:
andi $t1, $a0, 01111111100000000000000000000000 #get exponent bits from fp1
andi $t2, $a1, 01111111100000000000000000000000 #get exponent bits from fp2
I would stick to good old hexa:
andi $t1, $a0, 0x7F800000 #get exponent bits from fp1
andi $t2, $a1, 0x7F800000 #get exponent bits from fp2
When I tried in MARS to call your code with ~0
in both a0, a1
, after andi
the result is 0x9D800000
, which is plain wrong. The same goes for the mantissa andi
, completely borked in MARS.
Maybe your assembler does understand those, but I suggest to verify.
And you should probably handle exponent under/overflow, like this?
# calculate exponent - extract exponents to t1, t2
srl $t1, $a0, 23
srl $t2, $a1, 23
andi $t1, $t1, 0xFF
andi $t2, $t2, 0xFF
addu $s1, $t1, $t2 # add exponents together
bltu $s1, 127, exp_too_small # if exp is less than 127 => too small
addiu $s1, $s1, -127 # subtract 127 from the sum
sll $s1, $s1, 23 #move exp back to the right position
bltz $s1, exp_too_big # if sign bit is set, exponent is too big
Upvotes: 2