When I developed the RISC-V assembler I also implemented some of the floating-point instructions. Here’s an example of how you could use them to perform floating-point calculations and return a floating-point result.

First evaluate the original assembler source file: RISC-V assembler in uLisp

Then add the following definitions: RISC-V assembler floating-point extensions

This file redefines the function **regno** to handle the floating-point registers, and adds definitions for the most useful floating-point instructions.

Calling a machine-code function from uLisp returns a Lisp integer value, but you can return values of other types by passing a list to the call, and putting the result back into one of the list cells.

The following example takes a list of floating-point numbers. It multiplies them together, and then puts the floating-point result back into the first element of the list:

```
(defcode product (x)
($li 'a2 1)
($fcvt.s.w 'fa1 'a2)
($mv 'a2 'a0)
repeat
($beqz 'a0 finished)
($ld 'a1 0 '(a0))
($flw 'fa0 8 '(a1))
($fmul.s 'fa1 'fa0 'fa1)
($ld 'a0 8 '(a0))
($j repeat)
finished
($ld 'a1 0 '(a2))
($fsw 'fa1 8 '(a1))
($ret))
```

Here’s an example of using it. First define a list of the numbers to be multiplied:

```
> (defvar lst '(1.2 2.3 3.4))
lst
```

Call the machine-code function:

```
> (product lst)
0
```

It returns the value of **a0**, which is always 0, but the result is put back in the first element of the list:

```
> lst
(9.384 2.3 3.4)
```

Here’s how it works. The list passed to the machine-code routine looks like this:

First **fa1** is set to the floating-point value 1.0 by:

```
($li 'a2 1)
($fcvt.s.w 'fa1 'a2)
```

The pointer to the list was passed in **a0**, and this is copied into **a2**. Then **a1** is set to the address of the first element of the list by:

```
($ld 'a1 0 '(a0))
```

and the floating-point value 1.2 in the **cdr** of the object, which has offset 8 (because the K210 is a 64-bit processor), is copied into **fa0** by:

```
($flw 'fa0 8 '(a1))
```

Register **fa1** is multiplied by this, and the process is repeated for the remaining elements in the list, until **a0** is zero indicating that we’ve reached the **nil** at the end of the list.

Finally **fa1** is put back into value cell of the first element with:

```
($ld 'a1 0 '(a2))
($fsw 'fa1 8 '(a1))
```