Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion riscv64/fenv.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@
* $FreeBSD: head/lib/msun/riscv/fenv.c 332792 2018-04-19 20:36:15Z brooks $
*/

/*
* Keep the hard-float functions private. The FreeBSD-derived FE_* values are
* shifted into fcsr.frm, unlike the raw encodings used on Linux, so exporting
* these functions would interpose an incompatible fenv implementation.
* Soft-float keeps external definitions because the header only declares them.
*/
#ifdef __riscv_float_abi_soft
#define __fenv_static
#endif
#include <openlibm_fenv.h>

#ifdef __GNUC_GNU_INLINE__
Expand All @@ -45,7 +53,6 @@ const fenv_t __fe_dfl_env = {0};
#define __env_mask(env) (0) /* No exception traps. */
#define __env_round(env) (((env) >> 5) & _ROUND_MASK)
#include "fenv-softfloat.h"
#endif

extern inline int feclearexcept(int __excepts);
extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
Expand All @@ -61,3 +68,4 @@ extern inline int feupdateenv(const fenv_t *__envp);
extern inline int feenableexcept(int __mask);
extern inline int fedisableexcept(int __mask);
extern inline int fegetexcept(void);
#endif /* __riscv_float_abi_soft */
3 changes: 2 additions & 1 deletion test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ regression-build: $(REGRESSION_BINS)

# -pthread lets thread-safety regressions (e.g. test-222) spawn threads. It is
# harmless for the single-threaded tests and is a no-op stub on glibc >= 2.34.
# -lm lets regressions use platform services that openlibm does not export.
regression/%: regression/%.c regression/regress-util.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_add) $(LDFLAGS) $(LDFLAGS_arch) $< -D__BSD_VISIBLE -I ../include -I../src $(OPENLIBM_LIB) -pthread -o $@
$(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_add) $(LDFLAGS) $(LDFLAGS_arch) $< -D__BSD_VISIBLE -I ../include -I../src $(OPENLIBM_LIB) -lm -pthread -o $@

bench: bench-syslibm bench-openlibm

Expand Down
61 changes: 61 additions & 0 deletions test/regression/test-252.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Regression test for issue #252. Hard-float RISC-V openlibm used to
* interpose its FreeBSD-ABI fenv functions on callers using the incompatible
* Linux ABI. Use the system <fenv.h> and pull in libopenlibm through
* isopenlibm().
*/
#include <fenv.h>

#include "regress-util.h"

int isopenlibm(void);

#if !defined(__riscv) || defined(__riscv_float_abi_soft) || \
!defined(FE_TONEAREST) || !defined(FE_TOWARDZERO) || !defined(FE_UPWARD)

int
main(void)
{
return REGRESS_SKIP;
}

#else

/*
* Keep the operands volatile and the division out of line: without
* -frounding-math the compiler otherwise folds or moves the divisions across
* the fesetround() calls.
*/
static volatile double one = 1.0, three = 3.0;

static double __attribute__((noinline))
divide(void)
{
volatile double r = one / three;
return r;
}

int
main(void)
{
double nearest, down, up;

CHECK(isopenlibm() == 1);

nearest = divide();
CHECK(fesetround(FE_TOWARDZERO) == 0);
CHECK(fegetround() == FE_TOWARDZERO);
down = divide();
CHECK(fesetround(FE_UPWARD) == 0);
CHECK(fegetround() == FE_UPWARD);
up = divide();
CHECK(fesetround(FE_TONEAREST) == 0);
CHECK(fegetround() == FE_TONEAREST);

/* 1/3 is inexact, so the directed modes must bracket the nearest result. */
CHECK(down < up);
CHECK(down <= nearest && nearest <= up);
return 0;
}

#endif