MIPS - IEEE binary64(双精度)和有符号整数乘法

时间:2015-01-09 18:05:35

标签: double mips ieee-754 mars-simulator

我的MIPS项目有问题。任务是将binary64(double)数乘以有符号整数而不使用浮点单位。它几乎运行良好,但对于某些数字发生错误(例如,float-123456789123456,int-1)。错误的意思是说,在第7位之后,我的结果似乎与正确的结果不同。我怀疑在程序中传输一些位可能会有问题(可能是在添加$ high的mantissa2和$ low of mantissa2的过程中)。我试图纠正它,但到目前为止我不知道该怎么做。请验证我的代码并在可能的情况下进行更正。

            .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

我认为问题可能在本节(乘法):

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 

添加过程可能导致执行。我尝试用注释(addiu)中的指令处理它。这意味着如果添加两个无符号数的结果小于其中一个,我们得到一个cary out并且必须添加1来注册$ s1,其中包含最重要的mantissa的一部分。它没有帮助。

1 个答案:

答案 0 :(得分:1)

在我看来,这是正确的代码:

.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