CS 3723
 Programming Languages 
   Tiny® with doubles  


Overview: Here we consider how to make all Tiny® calculations use doubles instead of ints. Just fix up the compiler so that it outputs MIPS floating point instructions instead of integer ones. I used only the double format (64-bit), and not float (32-bit).

References:

  • As an initial reference, consider an old recitation from my CS 2733 (Computer Organization II) course about MIPS floating point instructions: CS 2731: MIPS Floating point recitation. The second half of this recitation includes quite a bit of sample MIPS code working with double, though not quite everything needed to redo the Tiny® compiler to do all computations in floating point.
  • Two other references were mentioned before: the SPIM Manual and Appendix A from the Patterson and Hessessy book ""Computer Organization".

Changes to Make: Here are some of the changes you must make or can make to convert the compiler to doubles:

  • Alter the memory array M so that all locations, including constants, are 8 bytes long, instead of 4 bytes. Be sure to use an .align 3 directive, and to declare the integer constants using .double 0.,1.,... You need to use registers $f2, $f4, $f6, ....
  • Load and store instructions need to be l.d and s.d
  • For output, put 3 into $v0, and load the quantity to be output from memory into $f12. Then do a syscall.
  • For input, put 7 into $v0. Then a syscall causes the double to pop into register $f0.
  • Some of the double instructions for arithmetic are add.d, sub.d, mul.d, div.d
  • I implemented the % operator by converting both operands to integers, doing an integer %, and converting the result back to double.
  • I introduced a new operator # which does truncated integer division. As above, it converts both operands to integers, does a truncated integer division, and converts the result back to a double.
  • For the conversions in the previous two items, I used an ackward combination of instructions trunc.w.d and cvt.d.w (there may be better ways). This requires the newer version of spim in the Linux lab.
  • Finally, for some of the conditional jumps, I used pairs of instructions: tc.eq.d and bc1t, or tc.eq.d and bc1f.
  • One has to rewrite the "hat" function for doubles.


Examples: With these changes, I was able to get all six of the previous integer programs to run and produce exactly the same output as before. (I had to replace the '/' operator with '#'.

In addition I tried out some new functions that that did interesting floating point calculations. The first calculates the "harmonic" series: 1 + 1/2 + 1/3 + 1/4 + 1/5 + 1/6 + ... + 1/n.

Sample Input 7: Harmonic series Output
n = 1; s = 0;
{ n - 9 *2 ?
   s = s + 1/n;
   < n; < T; < s; < N;
   n = n + 1;
} $
% javac TinyCompiler.java
% java TinyCompiler < w2.tiny > w2.s
% spim -file w2.s
1       1
2       1.5
3       1.83333333333333326
4       2.08333333333333304
5       2.28333333333333321
6       2.44999999999999973
7       2.59285714285714253
8       2.71785714285714253
9       2.82896825396825369
10      2.92896825396825378
11      3.0198773448773446
12      3.10321067821067809
13      3.18013375513375518
14      3.2515623265623268
15      3.31822899322899367
16      3.38072899322899367
17      3.43955252264075817

The next calculates pi using the advanced series:


         n
        Sum (1/16^i)(4/(8*i+1) - 2/(8*i+4) - 1/(8*i+5) - 1/(8*i+6))
        i=0

Sample Input 8: Calculate Pi Output
i = 0; s = 0; > n;
{ i - n ?
   t = 4/(8*i+1) - 2/(8*i+4) -
       1/(8*i+5) - 1/(8*i+6);
   k = 0;
   { i - k ?
      t = t/(4*4);
      k = k + 1;
   }
   s = s + t;
   i = i + 1;
   < t; < T; < s; < N;
}
< s; < N;
$
% javac TinyCompiler.java
% java TinyCompiler < pi.tiny > pi.s
% spim -file w2.s
12
3.1333333333333333      3.1333333333333333
0.00808913308913308989  3.14142246642246636
0.000164923924115100557 3.14158739034658163
5.0672208538587869e-06  3.14159245756743566
1.87892900937720114e-07 3.14159264546033645
7.7677512151773586e-09  3.14159265322808778
3.44793293050862315e-10 3.14159265357288087
1.6091877155536991e-11  3.14159265358897288
7.79570295400101777e-13 3.14159265358975226
3.88711525990974833e-14 3.14159265358979134
1.98322539359813e-15    3.14159265358979312
1.03097121697888662e-16 3.14159265358979312
3.14159265358979312
3.141592653589793238462643383279502884 ...
  (exact value for comparison)

Just for reference, here is the translated MIPS code for this example: pi.s.


Revision date: 2013-02-21. (Please use ISO 8601, the International Standard.)