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.