lib: fix GET_FXX_REG assembly

Charles Papon charles.papon.90 at gmail.com
Sat May 15 16:23:06 BST 2021


Hoo right, i forced a0 on the wrong variable. this was misleading. I
have a patch for that, but now i see that RV64 do not use the memory
to get the FPU register value :
# define get_f64(which) fmv.x.d a0, which; jr t0

So right, that patch isn't the good one XD

> The only bug in the existing code is that it needs to grow separate offset and __val variables like SET_F64_REG in order to handle RV32 correctly

What do you mean by grow ? stack allocation ?

On Sat, May 15, 2021 at 3:32 PM Jessica Clarke <jrtc27 at jrtc27.com> wrote:
>
> On 15 May 2021, at 13:06, Charles Papon <charles.papon.90 at gmail.com> wrote:
> >
> > The previous implementation was producing some broken assembly. See
> > github #212 for more details
> >
> > PR : https://github.com/riscv/opensbi/pull/214
> >
> > ---
> > include/sbi/riscv_fp.h | 32 ++++++++++++++++----------------
> > 1 file changed, 16 insertions(+), 16 deletions(-)
> >
> > diff --git a/include/sbi/riscv_fp.h b/include/sbi/riscv_fp.h
> > index a685884..b2c0636 100644
> > --- a/include/sbi/riscv_fp.h
> > +++ b/include/sbi/riscv_fp.h
> > @@ -21,14 +21,14 @@
> >
> > #ifdef __riscv_flen
> >
> > -#define GET_F32_REG(insn, pos, regs)
> >                                  \
> > - ({
> >                           \
> > - register s32 value asm("a0") =
> >                   \
> > - SHIFT_RIGHT(insn, (pos)-3) & 0xf8;
> >           \
> > - ulong tmp;
> >                   \
> > - asm("1: auipc %0, %%pcrel_hi(get_f32_reg); add %0, %0, %1; jalr t0,
> > %0, %%pcrel_lo(1b)" \
> > -    : "=&r"(tmp), "+&r"(value)::"t0");
> >                  \
> > - value;
> >                   \
> > +#define GET_F32_REG(insn, pos, regs)
> >                                   \
> > + ({
> >                                \
> > + register ulong rf_address asm("a0") = SHIFT_RIGHT(insn, (pos)-3) &
> > 0xf8;                         \
> > + ulong tmp;
> >                            \
> > + volatile u32 value;
> >                            \
> > + asm volatile("1: auipc %0, %%pcrel_hi(get_f32_reg); add %0, %0, %2;
> > jalr t0, %0, %%pcrel_lo(1b)" \
> > + : "=&r"(tmp) : "r"(&value), "r"(rf_address)  :"t0");
> >                        \
> > + value;
> >                            \
> >  })
> > #define SET_F32_REG(insn, pos, regs, val)
> >                                      \
> >  ({
> >                               \
> > @@ -42,14 +42,14 @@
> >  : "t0");
> >               \
> >  })
> > #define init_fp_reg(i) SET_F32_REG((i) << 3, 3, 0, 0)
> > -#define GET_F64_REG(insn, pos, regs)
> >                                  \
> > - ({
> >                           \
> > - register ulong value asm("a0") =
> >                   \
> > - SHIFT_RIGHT(insn, (pos)-3) & 0xf8;
> >           \
> > - ulong tmp;
> >                   \
> > - asm("1: auipc %0, %%pcrel_hi(get_f64_reg); add %0, %0, %1; jalr t0,
> > %0, %%pcrel_lo(1b)" \
> > -    : "=&r"(tmp), "+&r"(value)::"t0");
> >                  \
> > - sizeof(ulong) == 4 ? *(int64_t *)value : (int64_t)value;
> >                   \
> > +#define GET_F64_REG(insn, pos, regs)
> >                                    \
> > + ({
> >                                 \
> > + register ulong rf_address asm("a0") = SHIFT_RIGHT(insn, (pos)-3) &
> > 0xf8;                          \
> > + ulong tmp;
> >                             \
> > + volatile u64 value;
> >                             \
> > + asm volatile("1: auipc %0, %%pcrel_hi(get_f64_reg); add %0, %0, %2;
> > jalr t0, %0, %%pcrel_lo(1b)"  \
> > + : "=&r"(tmp) : "r"(&value), "r"(rf_address)  :"t0");
> >                         \
> > + value;
> >                             \
> >  })
> > #define SET_F64_REG(insn, pos, regs, val)
> >                                      \
> >  ({
>
> This patch is wrong for numerous reasons:
>
> 1. The volatile is unnecessary as loads have side-effects modelled by the
>    constraints; only stores need volatile.
>
> 2. Similarly, value does not need to be volatile.
>
> 3. But value doesn’t even need to exist.
>
> 4. You’ve lost the clobber on a0 through the old value.
>
> 5. Your formatting of the constraints is wrong.
>
> 6. GET_F64_REG is now even more broken on RV32. It won’t crash, but you’re
>    reading a completely random uninitialised value from value.
>
> On RV32, get_f64_reg expects a0 to be a pointer to a u64 and will store the
> 64-bit value there. The only bug in the existing code is that it needs to grow
> separate offset and __val variables like SET_F64_REG in order to handle RV32
> correctly. You have not fixed that bug, but you have also introduced many
> additional problems.
>
> Jess
>



More information about the opensbi mailing list