Fsqrt.s assembler instruction RISC-V


#1

Hello,

Is it possible to add in the current floating-point assembler library the fsqrt.s function?
I found this definition.

> fsqrt.s
> 
> 31-27   26-25   24-20   19-15   14-12   11-7   6-2   1-0
> 
> 01011     00    00000     rs1     rm     rd   10100   11

I tried to do it myself, but I must admit it’s no so clear to me how to do that :)

Thanks a lot,
Fausto


#2

OK, I think this works:

(defun $fsqrt.s (rd rs1)
  (fmuldiv #x2C 'x0 rs1 7 rd #x53))

It uses the existing fmuldiv routine that is set up to handle instructions with these bit fields.

#x2C is just bits 31 to 25 in your definition, but in hexadecimal.

#x53 is just bits 6 to 0 in hexadecimal.

rm is the rounding mode. 7 seems to be a default choice.

rd and rs1 are the destination and source registers, and 'x0 is just zero.

Here’s a test, based on my earlier example, but taking the square root at the end and putting the result back in the first element of the list:

(defcode square-root (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))
  ($fsqrt.s 'a1 'a1)
  ($fsw 'fa1 8 '(a1))
  ($ret))

Testing it:

> (defvar b '(23.45))
b

> (square-root b)
0

> b
(4.84252)

Update: I’ve renamed the routine square-root to avoid a clash with the built-in function.


#3

Thanks a lot! Also, for the clear explanation! :)


#4

I think the biggest takeaway for me from microcontrollers in general and uLisp in particular is that many of these low-level things are nowhere near as scary as they look.