2
votes

I have a problem with MIPS project. The task is to multiply binary64(double) number by a signed integer without using floating-point Unit. It is almost working well, but for some numbers an error occurs(ex. float-123456789123456, int - 1). By error I mean that after 7th digit my result seems to differ from the proper one. I suspect there can be a problem with transfer of some bit during the procedure(maybe in process of adding $high of mantissa2 and $low of mantissa2). I tried to correct it, but so far I have no idea how to do it. Please verify my code and correct it if possible.

            .data
text1:  .asciiz "Enter double: "
text2:  .asciiz "Enter integer: "
text3:  .asciiz "Result: "
quest:  .asciiz "\nIf you want to multiply enter 1, otherwise enter 0: "

num1a:  .word       0           #multiplicand and result(sign exponent and first part of mantissa) 
num1b:  .word       0           #second part of the multiplicand and result(remaining part of mantissa) 
num2:   .word       0           #integer

    .text
    .globl input    
input:  
    #print "Enter double: "
    la  $a0, text1
    li  $v0, 4
    syscall
    # saving input double into num1
    li  $v0, 7
    syscall                 
    swc1    $f0, num1b
    swc1    $f1, num1a
    #print "Enter integer: "
    la  $a0, text2
    li  $v0, 4
    syscall
    # saving input int into num2
    li  $v0, 5
    syscall
    sw  $v0, num2
    # loading data to registers
    lw  $t0, num1a
    lw  $t1, num1b
    lw  $t2, num2
#########################################################sign
sign:       
    move    $t3, $t0
    andi    $t3, $t3, 0x80000000    #preserve sign, zero the rest
    bgez    $t2, extract        #if less than zero we change the final sign and negate the value of integer
    xori    $t3, $t3, 0x80000000    #multiply signs (if integer is negative, then the sign is equal to $s0)
    neg $t2, $t2        #absolute value of int  
extract:    
################################################checking for zero
    or  $t5, $t0, $t1       #if both part of double are equal to zero we skip all the calculation
    beqz    $t5, result_zero
    beqz    $t2, result_zero
###############################sign, exponent and mantissa
    move    $t7, $t0    
    andi    $t7, $t7, 0x7FF00000    #extracting exponent to $t7
    move    $t8, $t0
    andi    $t8, $t8, 0x000FFFFF    #extracting first part of mantissa
    ori     $t8, $t8, 0x00100000    #adding prefix one to mantissa
    #remaining mantissa stays in register $t1
#########################################################
multiply:
    ########################multiplying mantissa part 1
    multu   $t8, $t2        #multiply mantissa1 by integer
    mflo    $t8         #low part of multiplication to $t8
    mfhi    $s1         #high part of multiplication to $s1
    ########################multiplying mantissa part 2
    multu   $t1, $t2        #mantissa part 2 multiplication
    mflo    $t1         #low part to $t1
    mfhi    $t0         #with overflow going to $t0
    ########################partial accumulation
    addu    $t8, $t8, $t0       #adding the high part of mantissa2 to result of low part of mantissa1
    bgeu    $t8, $t0, skip_add  #if the result is less than any element we add 1 to mantissa1 high
    addiu   $s1, $s1, 1
    ######
skip_add:
    bnez    $s1, shift
    bltu    $t8, 0x00200000, result     
shift: #else we shift 3 parts of mantissa and increment the the exponent
    ###extracting least significant bit of high mantissa1
    sll $s2, $s1, 31        #copying least significant beat of $s1 to most significant bit in $s2
    sll $t9, $t8, 31        #copying least significant beat of $s8 to most significant bit in $t9
    ######
    srl $s1, $s1, 1     #shifting right mantisa part1 high
    srl $t8, $t8, 1     #shifting right mantisa part1 low
    or  $t8, $t8, $s2       #copying least significant bit from mantissa1- high to most significant bit of mantissa1 low
    srl $t1, $t1, 1     #shifting right mantisa part2
    or  $t1, $t1, $t9       #copying least significant bit from mantissa1 to most significant bit of mantissa2
    ######
    addiu   $t7, $t7, 0x00100000    #increment exponent by one
    ######
    bnez    $s1, shift      #if mantissa1 high is greater than zero we continue
    bgeu    $t8, 0x00200000, shift  #if mantissa1 low exceeds final mantissa space
result:
    andi    $t8, $t8, 0x000FFFFF    #preserve mantissa, zero the rest(cut the prefix - one)
    move    $t0, $t3        #copy propoer sign
    or  $t0, $t0, $t7       #add exponent
    or  $t0, $t0, $t8       #add mantissa part1
    b   output
result_zero:
    li  $t0, 0
    li  $t1, 0
output:
    sw  $t0, num1a
    sw  $t1, num1b
    #print "Result: "
    la  $a0, text3
    li  $v0, 4
    syscall
    lwc1    $f12, num1b
    lwc1    $f13, num1a
    #print double - the result
    li  $v0, 3
    syscall
question:
    la  $a0, quest          #Do you want to enter new numbers or finish?
    li  $v0, 4
    syscall
    li  $v0, 5              #reads the answer (integer)
    syscall
    beq $v0, 1, input           #if input =1, continue, if 0 finish, otherwise ask again
    beqz    $v0, fin
    b   question
fin:
    li  $v0, 10             #exit
    syscall

I think the problem might be in this section(multiply):

addu    $t8, $t8, $t0       #adding the high part of mantissa2 to result of low part of mantissa1
bgeu    $t8, $t0, skip_add  #if the result is less than any element we add 1 to mantissa1 high
#addiu  $s1, $s1, 1
    ######
skip_add:
    bnez    $s1, shift
    bltu    $t8, 0x00200000, result 

The process of adding may cause a carry out. I tried to handle it with instruction held in comment (addiu).It means that if the result of adding two unsigned numbers is less than one of them we obtain a cary out and have to add 1 to register $s1 which holds the most significant part of mantissa.It didn't help.

1
This process will be easier if you can provide information about what errors you are experiencing and if you can perhaps drill down the issue to some subsection of your code. Given that there are likely very few people who know MIPS assembler and IEEE floating point and are on SO, the more information you provide in your question, the better. - dho
I've edited the post. I hope my thoughts are now easier to understand. - Kornel
Thankfully, the problem is solved. There was a mistake in multiply section indeed. However, the problem was in using mult function. Now it is correct and working. I hope it will help someone in the future. - Kornel
You should write an answer and accept the answer. - dho
@Kornel It is consider proper to add the correct answer with the correct code if you figured out the solution yourself so that others may benefit from it - thorkia

1 Answers

1
votes

In my opinion this is the correct code:

.data
text1:  .asciiz "Enter double: "
text2:  .asciiz "Enter integer: "
text3:  .asciiz "Result: "
quest:  .asciiz "\nIf you want to multiply enter 1, otherwise enter 0: "

num1a:  .word       0           #multiplicand and result(sign exponent and first part of mantissa) 
num1b:  .word       0           #second part of the multiplicand and result(remaining part of mantissa) 
num2:   .word       0           #integer

    .text
    .globl input    
input:  
    #print "Enter double: "
    la  $a0, text1
    li  $v0, 4
    syscall
    # saving input double into num1
    li  $v0, 7
    syscall                 
    swc1    $f0, num1b
    swc1    $f1, num1a
    #print "Enter integer: "
    la  $a0, text2
    li  $v0, 4
    syscall
    # saving input int into num2
    li  $v0, 5
    syscall
    sw  $v0, num2
    # loading data to registers
    lw  $t0, num1a
    lw  $t1, num1b
    lw  $t2, num2
#########################################################sign
sign:       
    move    $t3, $t0
    andi    $t3, $t3, 0x80000000    #preserve sign, zero the rest
    bgez    $t2, extract        #if less than zero we change the final sign and negate the value of integer
    xori    $t3, $t3, 0x80000000    #multiply signs (if integer is negative, then the sign is equal to $s0)
    neg $t2, $t2        #absolute value of int  
extract:    
################################################checking for zero
    or  $t5, $t0, $t1       #if both part of double are equal to zero we skip all the calculation
    beqz    $t5, result_zero
    beqz    $t2, result_zero
###############################sign, exponent and mantissa
    move    $t7, $t0    
    andi    $t7, $t7, 0x7FF00000    #extracting exponent to $t7
    move    $t8, $t0
    andi    $t8, $t8, 0x000FFFFF    #extracting first part of mantissa
    ori     $t8, $t8, 0x00100000    #adding prefix one to mantissa
    #remaining mantissa stays in register $t1
#########################################################
multiply:
    ########################multiplying mantissa part 1
    multu   $t8, $t2        #multiply mantissa1 by integer
    mflo    $t8         #low part of multiplication to $t8
    mfhi    $s1         #high part of multiplication to $s1
    ########################multiplying mantissa part 2
    multu   $t1, $t2        #mantissa part 2 multiplication
    mflo    $t1         #low part to $t1
    mfhi    $t0         #with overflow going to $t0
    ########################partial accumulation
    addu    $t8, $t8, $t0       #adding the high part of mantissa2 to result of low part of mantissa1
    bgeu    $t8, $t0, skip_add  #if the result is less than any element we add 1 to mantissa1 high
    addiu   $s1, $s1, 1
    ######
skip_add:
    bnez    $s1, shift
    bltu    $t8, 0x00200000, result     
shift: #else we shift 3 parts of mantissa and increment the the exponent
    ###extracting least significant bit of high mantissa1
    sll $s2, $s1, 31        #copying least significant beat of $s1 to most significant bit in $s2
    sll $t9, $t8, 31        #copying least significant beat of $s8 to most significant bit in $t9
    ######
    srl $s1, $s1, 1     #shifting right mantisa part1 high
    srl $t8, $t8, 1     #shifting right mantisa part1 low
    or  $t8, $t8, $s2       #copying least significant bit from mantissa1- high to most significant bit of mantissa1 low
    srl $t1, $t1, 1     #shifting right mantisa part2
    or  $t1, $t1, $t9       #copying least significant bit from mantissa1 to most significant bit of mantissa2
    ######
    addiu   $t7, $t7, 0x00100000    #increment exponent by one
    ######
    bnez    $s1, shift      #if mantissa1 high is greater than zero we continue
    bgeu    $t8, 0x00200000, shift  #if mantissa1 low exceeds final mantissa space
result:
    andi    $t8, $t8, 0x000FFFFF    #preserve mantissa, zero the rest(cut the prefix - one)
    move    $t0, $t3        #copy propoer sign
    or  $t0, $t0, $t7       #add exponent
    or  $t0, $t0, $t8       #add mantissa part1
    b   output
result_zero:
    li  $t0, 0
    li  $t1, 0
output:
    sw  $t0, num1a
    sw  $t1, num1b
    #print "Result: "
    la  $a0, text3
    li  $v0, 4
    syscall
    lwc1    $f12, num1b
    lwc1    $f13, num1a
    #print double - the result
    li  $v0, 3
    syscall
question:
    la  $a0, quest          #Do you want to enter new numbers or finish?
    li  $v0, 4
    syscall
    li  $v0, 5              #reads the answer (integer)
    syscall
    beq $v0, 1, input           #if input =1, continue, if 0 finish, otherwise ask again
    beqz    $v0, fin
    b   question
fin:
    li  $v0, 10             #exit
    syscall