We will use RARS for this lab.
Working with floating numbers is quite different than working with integers.
In RISC-V, the F extension adds support for 32 bit floating point
numbers (single precision). There is also an extension (D) that supports
64 bit floating point numbers (double precision).
The simulator (RARS) implements commands from both
extensions. Thus, for the lab, we have 64 bit registers available
and can refer to them as 32 or 64 bit values.
The registers are named f0, f1, ... f31, but also have aliases
such as argument registers fa0, fa1,
saved registers fs0, fs1, and temporary registers ft0, ft1.
Below, you will see how we load, store, and manipulate floating point numbers.
FP_value: .float 1.23
We have seen how to print integer values, such as this code:
# Load the value at my_value, then print it
la x10, my_value
lw a0, 0(x10)
li a7, 1
ecall
You might expect that printing
floating point values is a matter of simply loading "FP_value" into a0
and using ecall 1,
as we did with an integer, but that does not give a correct result.
We need to use the flw
command, and load the value into
fa0
. Notice that the ecall number is 2 now.
# Load the value at FP_value, then print it
la x10, FP_value
flw fa0, 0(x10) # Load 32-bit F.P. number into fa0
li a7, 2 # print a float
ecall
Implement the code from above, try it out, and verify that it works.
Questions
dlw
in place of flw
.
Do we get the same result? Explain.
flw
command from the previous example.
Then, use the fadd.s
command to add two floating numbers.
Finally, to print the result you need to follow
the ecall of previous example.
fadd.s f2, f0, f1 # f2 = f0 + f1, single precision
# ...
fmv.s fa0, f2 # copy the value to print
Before printing the value, write it to memory with the fsw
command.
Implement this, and show that it works.
Questions
fadd.s
command different from add
?
Why do we have ".s" after it, and what does it stand for?
fsw
), how does it know
the number of bits to write?
Experiment with this by putting non-zero values in neighboring memory
locations, and testing if the values are changed.
.data # Data section, initialized variables
FP_values: .float 1.7, 32.4
FP_result: .word 0
Implement this code, and run it. Verify that it works.
Questions
val1: .float 3.64
val2: .word 5
result: .word 0
To accomplish this, you will need to convert a floating point value to
an integer. Use a size with the larger range (float) for the calculations,
then convert the result to an int.
This means that you will need to convert the val2 integer to a floating
point value.
fcvt.s.w fa0, a1 # convert a1's int value to FP
# ...
fcvt.w.s a0, fa0 # convert fa0's FP value to int
li x11, 2
fmv.s.x fa0, x11 # Move x11's value to fa0
li a7, 2 # print a float
ecall
What result do you get, and why?
hex_value: .word 0x40b33333
If you load that as a floating point value and print it out, do you get
5.6? Why or why not?
In this lab, we have learned: