Browse Source

Disable newlib's dynamic rounding without F

GCC's softfloat is built by default without support for dynamic
rounding modes.  This makes softfloat newlib's floating point always
round-to-zero, and returns a failure code when trying to set it.

This patch is needed to make newlib compile on anything without F, as
it used to try use an undefined instruction to do this.
pull/53/head
Palmer Dabbelt 11 years ago
parent
commit
1b33b0210f
  1. 18
      newlib/newlib/libc/machine/riscv/ieeefp.c

18
newlib/newlib/libc/machine/riscv/ieeefp.c

@ -1,5 +1,6 @@
#include <ieeefp.h>
#ifdef __riscv_hard_float
static void fssr(int value)
{
asm volatile ("fssr %0" :: "r"(value));
@ -11,6 +12,7 @@ static int frsr()
asm volatile ("frsr %0" : "=r"(value));
return value;
}
#endif
fp_except fpgetmask(void)
{
@ -19,13 +21,21 @@ fp_except fpgetmask(void)
fp_rnd fpgetround(void)
{
#ifdef __riscv_hard_float
int rm = frsr() >> 5;
return rm == 0 ? FP_RN : rm == 1 ? FP_RZ : rm == 2 ? FP_RM : FP_RP;
#else
return FP_RZ;
#endif
}
fp_except fpgetsticky(void)
{
#ifdef __riscv_hard_float
return frsr() & 0x1f;
#else
return 0;
#endif
}
fp_except fpsetmask(fp_except mask)
@ -35,16 +45,24 @@ fp_except fpsetmask(fp_except mask)
fp_rnd fpsetround(fp_rnd rnd_dir)
{
#ifdef __riscv_hard_float
int fsr = frsr();
int rm = fsr >> 5;
int new_rm = rnd_dir == FP_RN ? 0 : rnd_dir == FP_RZ ? 1 : rnd_dir == FP_RM ? 2 : 3;
fssr(new_rm << 5 | fsr & 0x1f);
return rm == 0 ? FP_RN : rm == 1 ? FP_RZ : rm == 2 ? FP_RM : FP_RP;
#else
return -1;
#endif
}
fp_except fpsetsticky(fp_except sticky)
{
#ifdef __riscv_hard_float
int fsr = frsr();
fssr(sticky & 0x1f | fsr & ~0x1f);
return fsr & 0x1f;
#else
return -1;
#endif
}

Loading…
Cancel
Save