-2

I have to make a program in MIPS assembly that divide a Double precision floating number by a Single precision number (with standard IEEE 754) without using the Floating Pointer Unit. The only thing I can't understand is how handle the mantissa of the two numbers to compute the division. How to iterate over individual bits?

.data

res:    .asciiz "Result is: "
neg_res:.asciiz "Result is: - "
choice: .asciiz "\nMake your choice:\n1. Execute\n2. Exit\n"
wrong:  .asciiz "Inserted value is wrong! Please try one more time."
first:  .asciiz "Insert the first number: "
n:      .asciiz "\n"
second: .asciiz "Insert the second number: "
divz:   .asciiz "Can't divide for 0! Please try one more time." 

.text

main:
    la  $a0, choice
    li  $v0, 4
    syscall                  # Print menu

    li  $v0, 5
    syscall                  # Input choice

    move    $t7, $v0       
    beq     $t7, 2, end      # Control=2
    blt     $t7, 1, err      # Control<1
    bgt     $t7, 2, err      # Control>2

getdoub:
    la  $a0, first
    li  $v0, 4
    syscall             # Message for input numerator

    li  $v0, 7
    syscall
    mov.d   $f4, $f0        # Input double numerator

    c.eq.d  $f4, $f30
    bc1t    print_dou       # Print result if numerator is = 0

getfloat:
    la  $a0, second
    li  $v0, 4
    syscall             # Message for input denominator

    li  $v0, 6
    syscall
    mov.s   $f6, $f0        # Input float denominator

    c.eq.s  $f6, $f30
    bc1t    errz            # Print error if denominator is = 0

    sign_d:
    cvt.d.s $f6, $f6        # Convert from single to double to avoid errors in compare

    c.lt.d  $f4, $f6          # Control sign of double
    bc1t    minus_d         # If c1 is true (that means $f4<$f8) jump to minus_d
    b   plus_d              # Otherwise plus_d

minus_d:
    li  $t0, 1          # Negative sign

plus_d:
    li  $t0, 0          # Positive sign

extr_double:
    mfc1.d  $t2, $f4         # Iin $t2 I've sign, exponent and 20 bit of mantissa    in t3, 32 bit of mantissa
    li  $t6, 2146435072 # Mask for 11 bit of exponent
    and     $t1, $t2, $t6     # In $t1 Exponent
    li  $t6, 1048575    # Mask for 20 bit of mantissa
    and     $t2, $t2,$t6
    add     $t2, $t2, 2097152 # In t2 I've mantissa 1 and in t3 ho la mantissa 2 automatically


sign_s:
    cvt.s.d $f8, $f8        # Convert $f8 from double to single
    c.lt.s  $f6, $f8        # Same control made for numerator
    bc1t    minus_s
    b   plus_s

minus_s:
    li  $t4, 1
    b   extr_sing

plus_s:
    li $t4,0         # t4 sign

extr_sing:
    mfc1    $t6, $f6
    li  $t7, 2139095040 # 8 bit of exponent a 1 
    and     $t5, $t6, $t7       # In $t5 I've exponent

    li  $t7, 8388607    # Mask for 23 bit
    and     $t6, $t6, $t7
    add     $t6, $t6, 16777216  # In $t6 I've mantissa

sign:   # Sign of result
    xor     $t0, $t0, $t4     
    beqz    $t0, print_res
    b   p_neg_res

exp:
    sub     $t5, $t5, 1023   # Taking real exponent
    sub     $t1, $t1, 127    # Taking real exponent
    sub     $t1, $t1, $t5     # In $t1 I've the exponent of the final number
    add     $t1, $t1, 1023   # Adding bias (the final number will be a double)
    sll     $t1, $t1, 20      # Shifting so when I add $t2 (the first part of mantissa) I    have the number in the right position

divis:
    div     $t3, $t3, $t6     # First part of division (32 bit of mantissa) 
    div     $t2, $t2, $t6     # Second part of division (20 bit of mantissa)

        #HUGE QUESTION MARK
    add $t2, $t1, $t2       # Adding exponent and mantissa, in this way in $t2 I have all the information
    mtc1.d $t2, $f4         # $t2 & $t3 are moved in $f4 & $f5 so I have a double number   in $f4...I Hope
    b print_dou

print_res:  # Print positive result
    la  $a0, res
    li  $v0, 4
    syscall
    b   divis

p_neg_res:  # Print negative result
    la  $a0, neg_res
    li  $v0, 4
    syscall
    b   divis

err:    # Error in the choice
    la  $a0, wrong
    li  $v0, 4
    syscall
    b   main

end:    # End of program
   li   $v0, 10
   syscall

errz:   # Error dividing by 0
    la  $a0, divz
    li  $v0, 4
    syscall
    b   main

print_dou:  # Print the number!!
    mov.d   $f12, $f30 # bylo #f4
    li  $v0, 3
    syscall
    b   main
nytmrae55
  • 1
  • 1

1 Answers1

1

When you compute the exponent of the result in $t1, you have the right idea, but although the respective operands of 1.0 / 1.5f and 1.5 / 1.0f are identical, the exponent of the results differ by one. What you could do, in the first case, is shift the significand of the numerator left by one at the same time you decrement $t1.

You will need to set the respective implicit significand bits after having extracted the two significands (obviously, set the previously-implicit bits before the adjustment recommended in the first paragraph, otherwise it will be complicated).

After that you will to implement a division. The following instructions do not implement a 53-bit division:

div     $t3, $t3, $t6     # First part of division (32 bit of mantissa) 
div     $t2, $t2, $t6     # Second part of division (20 bit of mantissa)

First, they forget about the implicit bit, and second, that's just not how it works.

You start with 1xxxxxxxxx(52 or 53 bits)xxxxxxxxxxx and 1yyyyy(23 bits)yyyyy. In the first paragraph, you made sure that the numerator's significand was larger than the denominator's, so the first digit is computed as 1 (it will be implicitly stored in the end result). Next you need to subtract the latter from the former. If you have not shifted in step 1, the subtraction looks like this:

 1xxxxxxxxxxx
-1yyyyyyy
_____________
 zzzzzzzzzzzz

And if you have shifted in step 1, it looks like this:

 1xxxxxxxxxxx
- 1yyyyyyy
_____________
 zzzzzzzzzzzz

Shift the result left by one, and compare the new value to 1yyyyyyyy. If the new value is greater than or equal to 1yyyyyyyy, the next digit is 1 and 1yyyyyyy must be subtracted again. If it is lower, the next digit is 0 (and do not subtract).

In both cases, shift left again and compute the next digit. and so on...

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281