Inline assembly for F instructions with rounding mode

95 views
Skip to first unread message

Anoop Mysore

unread,
May 2, 2023, 9:57:37 AM5/2/23
to RISC-V SW Dev
(Tl;dr at the bottom)
Providing a rounding mode alongside a floating point instruction seems to work for me when used in an inline assembly. For example: 
    fadd.s ft0, ft0, ft0, rtz
It generates the same assembly code.

However, if I instead want to pass the rounding mode as an argument to inline assembly like so:
        asm volatile (
                      "fcvt.s.w fa5, %[a];"  // convert int a to float in register fa5
                      "fcvt.s.w fa6, %[b];"
                      "fmul.s fa7, fa5, fa6, %[frm];"
                      "fcvt.w.s %[rf], fa7"
                      : [rf] "=r" (rf)
                      : [a]  "rm" (f[i]) ,
                        [b]  "rm" (f[j]) ,
                        [frm] "s" ("rtz") 
// also tried "X" instead of "s" (reference: https://gcc.gnu.org/onlinedocs/gcc/Simple-Constraints.html)
                     );
There's an error:
Error: illegal operands `fmul.s fa7,fa5,fa6,.LC4'

(Tl; dr) Is there a way to send in rounding mode as an argument in inline assembly?

Nick Knight

unread,
May 2, 2023, 11:34:23 AM5/2/23
to Anoop Mysore, RISC-V SW Dev
The workaround I use, when I need to pipe strings into asm templates, is the following:

#define FRM "rtz"
asm ("fmul.s fa7, fa5, fa6, " FRM);


I am curious if there is a cleaner approach, like you are attempting.

Best,
Nick Knight

--
You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.
To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/f9377a84-5b28-4aa4-b51d-aeae04c85274n%40groups.riscv.org.

Anoop Mysore

unread,
May 2, 2023, 11:38:33 AM5/2/23
to Nick Knight, RISC-V SW Dev
Were you able to get sprintf to work?

Nick Knight

unread,
May 2, 2023, 11:42:03 AM5/2/23
to Anoop Mysore, RISC-V SW Dev
No. You are looking for a compile-time solution, whereas my workaround happens at preprocess-time. Which is why I'm calling it a workaround vs. a solution.

Tommy Murphy

unread,
May 2, 2023, 12:53:46 PM5/2/23
to RISC-V SW Dev, mysa...@gmail.com
However, if I instead want to pass the rounding mode as an argument to inline assembly like so:
        asm volatile (
                      "fcvt.s.w fa5, %[a];"  // convert int a to float in register fa5
                      "fcvt.s.w fa6, %[b];"
                      "fmul.s fa7, fa5, fa6, %[frm];"
                      "fcvt.w.s %[rf], fa7"
                      : [rf] "=r" (rf)
                      : [a]  "rm" (f[i]) ,
                        [b]  "rm" (f[j]) ,
                        [frm] "s" ("rtz") 
// also tried "X" instead of "s" (reference: https://gcc.gnu.org/onlinedocs/gcc/Simple-Constraints.html)
                     );
There's an error:
Error: illegal operands `fmul.s fa7,fa5,fa6,.LC4'
 
Can you provide a self-contained reproducible test case that can, for example, be used as-is in Compiler Explorer?
I cannot get your code smippet above to work (i.e. to generate the error that you're getting) in Compiler Explorer.

Bruce Hoult

unread,
May 3, 2023, 2:36:52 AM5/3/23
to Nick Knight, Anoop Mysore, RISC-V SW Dev
Here's a different but closely related question.

Is there a way to use a macro for all the things like '[vl] "=r" (vl)' e.g. so you can just write ': OUT(vl) : IN(n), IN(dst), IN(src)' in the common case where you're passing in variables not arbitrary expressions. My attempts have failed.

Anoop Mysore

unread,
May 3, 2023, 10:57:31 AM5/3/23
to RISC-V SW Dev, tommy_...@hotmail.com, Anoop Mysore
In Compiler Explorer, it compiles (although doesn't generate binary).
Compiling workbook: https://godbolt.org/z/64zPKcEMh

Anoop Mysore

unread,
May 3, 2023, 11:58:51 AM5/3/23
to RISC-V SW Dev, Anoop Mysore, tommy_...@hotmail.com
Manually operating on fcsr is one way:
  const enum rounding_modes {RNE, RTZ=0x20, RDN=0x40, RUP=0x60, RMM=0x80, DYN=0xe0} rounding_mode;
  switch (rounding_mode) {
    case RDN:  
      asm volatile (
        "li    a5, %[rm];"
        "csrrw a5, fcsr, a5;"
        : // no outputs
        : [rm] "i" (RDN)
        );
      break;
    ....

That didn't work when I swapped out RDN for a `const int` variable. The error says: 
warning: asm operand 0 probably doesn't match constraints
   19 |       asm volatile (
      |       ^~~
error: impossible constraint in 'asm'

Reply all
Reply to author
Forward
0 new messages