Kenta
Kenta

Reputation: 391

Multiplying two IEEE 754 floating point numbers in MIPS

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

Answers (2)

GhostDede
GhostDede

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

Ped7g
Ped7g

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

Related Questions