Code to transfer the integer 9 to the coprocessor, get the ceiling of its square root, then transfer this value back, and print it:
addi $t1, $zero, 9
mtc1 $t1, $f0
sqrt.s $f0, $f0 # (*)
ceil.w.s $f0, $f0 # (*)
mfc1 $t0, $f0
addi $v0, $zero, 1
addi $a0, $t0, 0
syscall
Note on lines with (*): (1) I also tried with .d instead of .s; (2) I also tried making the source and destination registers different ($f0
to $f2
, and back).
My result is 1 (if I take the floor instead, 0). However, if I comment the *-ed lines out, 9 is transferred to and fro fine: 9 is printed.
I added a syscall "print_double" (=3) after transfer (and before transfer back to CPU) to print the number transferred, and a very small positive number is printed.
My questions:
(a) What is going on?
(b) mtc1
: is the integer transferred from the CPU received as a double, or a single? Before sending it back with mfc1
, does it need to be a single or double, or does it not matter? (I experimented using cvt.d.s
, etc., to no avail)
Remark: I'm doing this for fun using "Computer Organization and Design" (Patterson, Hennessy). The 4th edition has the syntax for mtc1
wrong in appendix B.10 - order of rd
and rs
should be as above.
Adding a cvt.s.w
to convert the loaded integer to single-precision floating point fixes the problem:
addi $t1, $zero, 36
mtc1 $t1, $f0
cvt.s.w $f0,$f0 # convert the integer in $f0 to floating point
sqrt.s $f0, $f0
ceil.w.s $f0, $f0 # ceil and convert from floating point to integer
mfc1 $t0, $f0
addi $v0, $zero, 1
addi $a0, $t0, 0
syscall