|
 |
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.)
|