I've condensed my problem to the following code:
.data newline: .asciiz "\n" .text .globl main main: li $t0, 4 li $t1, 16 mtc1 $t0, $f2 # Two integers get stored as floats mtc1 $t1, $f30 div.d $f12, $f2, $f30 li $v0, 3 syscall # First division works, returns 0.25 la $a0, newline li $v0, 4 syscall # prints new line div.d $f12, $f12, $f30 li $v0, 3 syscall # Second division doesn't work as expected, returns Infinity Output is:
0.25 Infinity Why is that? I'd expect 0.25/16 to be ~ 0.015625 instead of Infinity.
First value of $f12: 0x3fd0000000000000 Second value of $f12:0x7ff0000000000000
I'm relatively new to MIPS so it might be something easy. Thanks for any answers!
51 Answer
The apparent success of the first division is due to an artifact of how small positive integers and positive subnormal doubles are represented. Both have leading zeros, with the binary bit pattern corresponding to the significant bits of the value in the least significant bits. The effect of treating the integers as doubles was to divide each value by 2 to the power 1074.
Although f2 and f30, viewed as double precision float, contained tiny values, about 2.0E-323 and 7.9E-323, their ratio was the same as 4/16. Dividing a moderate number such as 0.25 by a tiny number overflows to infinity.
Here is a short Java program illustrating this:
public class Test { public static void main(String[] args) { long t0 = 4; long t1 = 16; double f2 = Double.longBitsToDouble(t0); double f30 = Double.longBitsToDouble(t1); System.out.println("f2=" + f2); System.out.println("f30=" + f30); double f12 = f2 / f30; System.out.println("f12=" + f12); System.out.println("f12/f30=" + f12 / f30); } } output:
f2=2.0E-323 f30=7.9E-323 f12=0.25 f12/f30=Infinity 3