浮動小数点加算を行うときに、MIPS で有意桁を正規化する方法を見つけようとしています。
0.001*2^-1 があるとします。この場合、正規化するには、仮数を左に 3 シフトし、指数を 3 減らす必要があります。
最上位ビットが正規化された位置に戻ったと判断するにはどうすればよいですか (以前のケースでは、3 番目のシフト後にシフトが停止したことをどのように知ることができますか)。
更新:これが私が現在使用しているコードです。2 つの入力 (浮動小数点数) が与えられた場合、プログラムは半精度の浮動小数点加算を行う必要があるため、単精度から半精度に変換します。出力は、単純に 2 つの float の合計でなければなりません
問題は正常化にあると思います。
.data
ask_user_a: .asciiz "Enter a decimal number (a): "
ask_user_b: .asciiz "Enter a decimal number (b): "
sum: .asciiz "a+b = "
error_out_of_range: .asciiz "Error: A number you entered is out of range! "
new_line: .asciiz "\n"
.text
main:
#Ask user for the input a
la $a0, ask_user_a # load the addr of ask_user_a into $a0.
li $v0, 4 # 4 is the print_string syscall.
syscall # do the syscall.
#put input a into $s0
li $v0, 6 #6 for getting floating point numbers
syscall # do the syscall
mfc1 $s0, $f0 #move floating point number to $s0
## ask user for the input b
la $a0, ask_user_b # load the addr of ask_user_b into $a0.
li $v0, 4 # 4 is the print_string syscall.
syscall # do the syscall.
#put input b into $s1
li $v0, 6 #6 for getting floating point numbers
syscall # do the syscall
mfc1 $s1, $f0 #move floating point number to $s1
#extract parts for A
srl $t0, $s0, 31 #$t0 = Sign Bit A
sll $t1, $s0, 1
srl $t1, $t1, 24
sub $t1, $t1, 127 #t1 = Exponent Bit A
sll $t2, $s0, 9
srl $t2, $t2, 9 #t2 = Mantissa A
srl $t2, $t2, 13 #Truncate Mantissa
ori $t2, $t2, 0x800000
srl $t2, $t2, 12
#extract parts for B
srl $t5, $s1, 31 #$t5 = Sign Bit B
sll $t6, $s1, 1
srl $t6, $t6, 24
sub $t6, $t6, 127 #t6 = Exponent Bit B
sll $t7, $s1, 9
srl $t7, $t7, 9 #t7 = Mantissa B
srl $t7, $t7, 13 #Truncate Mantissa
ori $t7, $t7, 0x800000
srl $t7, $t7, 12
##Check that exponent A is >16 and <-16, jump to error otherwise
blt $t1, -16, oor_error
bgt $t1, 16, oor_error
##Check that exponent B is >16 and <-16, jump to error otherwise
blt $t6, -16, oor_error
bgt $t6, 16, oor_error
j no_oor_error
#Throw error
oor_error:
la $a0, error_out_of_range # load the addr of ask_user_a into $a0.
li $v0, 4 # 4 is the print_string syscall.
syscall # do the syscall.
j exit
#There was no out of range error
no_oor_error:
#compare exponents
beq $t6, $t1, exponents_match
bgt $t6, $t1 expBgtexpA
sub $t8, $t6, $t1
srlv $t7, $t7, $t8
move $t6, $t1
j exponents_match
expBgtexpA:
sub $t8, $t1, $t6
srlv $t2, $t2, $t8
move $t1, $t6
exponents_match:
#If the signs are the same, add mants
#If the signs are diff, subtract mants
bne $t0, $t5, different_signs
add $t9, $t2, $t7
j significands_added
different_signs:
sub $t9, $t2, $t7
significands_added:
#normalize
#determine size
bne $t0, $t5, normalize_different_sign
normalize_same_sign:
andi $t8, $t9, 0x1000
beq $t8, $zero, done_normalize
srl $t9, $t9, 1
addi $t1, $t1, 1
j normalize_same_sign
normalize_different_sign:
andi $t8, $t9, 0x1000
beq $t8, $zero, done_normalize
sll $t9, $t9, 1
subi $t1, $t1, 1
j normalize_different_sign
done_normalize:
#Check for overflow
##Convert back to float
sll $t0, $t0, 31 ##move sign to 32nd bit
addi $t1, $t1, 127 ##Add bias
sll $t1, $t1, 23 #move exponent to bits 24-31
sll $t9, $t9, 11 #move over mant
andi $t9, $t9, 0x3FFFFF
sll $t9, $t9, 1
or $s2, $t0, $t1
or $s2, $s2, $t9
#Print the float
mtc1 $s2, $f12
li $v0, 2
syscall
exit:
#Exit Program
li $v0, 10 # syscall code 10 is for exit.
syscall # make the syscall.