From 4cf001dcc25cc2a1e539f59074a67b24c366319a Mon Sep 17 00:00:00 2001 From: kettenis Date: Thu, 29 Apr 2021 17:19:18 +0000 Subject: [PATCH] Clean up and make sure the rounding mode bits match the hardware. Implement fp[gs]etround(3) and fp[gs]etsticky(3) and tweak the fp[gs]etmask(3) implementation to provide the right weak symbols. This implementation deliberately ignores the additional "round to nearest, away from zero" as this interface is derived from i386-specific code and the i387 FPU doesn't implement such a rounding mode. This is a legacy API and code should use instead. ok drahn@ --- lib/libc/arch/riscv64/gen/fpgetmask.c | 5 ++-- lib/libc/arch/riscv64/gen/fpgetround.c | 29 ++++++++++++++++++++++ lib/libc/arch/riscv64/gen/fpgetsticky.c | 29 ++++++++++++++++++++++ lib/libc/arch/riscv64/gen/fpsetmask.c | 5 ++-- lib/libc/arch/riscv64/gen/fpsetround.c | 31 +++++++++++++++++++++++ lib/libc/arch/riscv64/gen/fpsetsticky.c | 29 ++++++++++++++++++++++ sys/arch/riscv64/include/ieeefp.h | 33 ++++++------------------- 7 files changed, 130 insertions(+), 31 deletions(-) create mode 100644 lib/libc/arch/riscv64/gen/fpgetround.c create mode 100644 lib/libc/arch/riscv64/gen/fpgetsticky.c create mode 100644 lib/libc/arch/riscv64/gen/fpsetround.c create mode 100644 lib/libc/arch/riscv64/gen/fpsetsticky.c diff --git a/lib/libc/arch/riscv64/gen/fpgetmask.c b/lib/libc/arch/riscv64/gen/fpgetmask.c index 6e94f99bd33..4d8fac984e2 100644 --- a/lib/libc/arch/riscv64/gen/fpgetmask.c +++ b/lib/libc/arch/riscv64/gen/fpgetmask.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fpgetmask.c,v 1.1 2021/04/28 08:22:56 kettenis Exp $ */ +/* $OpenBSD: fpgetmask.c,v 1.2 2021/04/29 17:19:18 kettenis Exp $ */ /* * Copyright (c) 2018 Mark Kettenis * @@ -17,10 +17,9 @@ #include -__weak_alias(_fpgetmask,fpgetmask); - fp_except fpgetmask(void) { return 0; } +DEF_WEAK(fpgetmask); diff --git a/lib/libc/arch/riscv64/gen/fpgetround.c b/lib/libc/arch/riscv64/gen/fpgetround.c new file mode 100644 index 00000000000..6d2351f9d1e --- /dev/null +++ b/lib/libc/arch/riscv64/gen/fpgetround.c @@ -0,0 +1,29 @@ +/* $OpenBSD: fpgetround.c,v 1.1 2021/04/29 17:19:18 kettenis Exp $ */ +/* + * Copyright (c) 2021 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +fp_rnd +fpgetround(void) +{ + uint32_t frm; + + __asm volatile ("frrm %0" : "=r"(frm)); + return frm & 0x3; +} +DEF_WEAK(fpgetround); diff --git a/lib/libc/arch/riscv64/gen/fpgetsticky.c b/lib/libc/arch/riscv64/gen/fpgetsticky.c new file mode 100644 index 00000000000..81a14b0dcda --- /dev/null +++ b/lib/libc/arch/riscv64/gen/fpgetsticky.c @@ -0,0 +1,29 @@ +/* $OpenBSD: fpgetsticky.c,v 1.1 2021/04/29 17:19:18 kettenis Exp $ */ +/* + * Copyright (c) 2021 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +fp_except +fpgetsticky(void) +{ + uint32_t fflags; + + __asm volatile ("frflags %0" : "=r"(fflags)); + return fflags; +} +DEF_WEAK(fpgetsticky); diff --git a/lib/libc/arch/riscv64/gen/fpsetmask.c b/lib/libc/arch/riscv64/gen/fpsetmask.c index 03485db6c93..d4b1edd5d79 100644 --- a/lib/libc/arch/riscv64/gen/fpsetmask.c +++ b/lib/libc/arch/riscv64/gen/fpsetmask.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fpsetmask.c,v 1.1 2021/04/28 08:22:56 kettenis Exp $ */ +/* $OpenBSD: fpsetmask.c,v 1.2 2021/04/29 17:19:18 kettenis Exp $ */ /* * Copyright (c) 2018 Mark Kettenis * @@ -17,10 +17,9 @@ #include -__weak_alias(_fpsetmask,fpsetmask); - fp_except fpsetmask(fp_except mask) { return 0; } +DEF_WEAK(fpsetmask); diff --git a/lib/libc/arch/riscv64/gen/fpsetround.c b/lib/libc/arch/riscv64/gen/fpsetround.c new file mode 100644 index 00000000000..e9e26b32466 --- /dev/null +++ b/lib/libc/arch/riscv64/gen/fpsetround.c @@ -0,0 +1,31 @@ +/* $OpenBSD: fpsetround.c,v 1.1 2021/04/29 17:19:18 kettenis Exp $ */ +/* + * Copyright (c) 2021 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +fp_rnd +fpsetround(fp_rnd rnd_dir) +{ + uint32_t frm; + + __asm volatile ("fsrm %0, %1" : "=r"(frm) : "r"(rnd_dir)); + + /* Truncating to 2 bits means both RNE and RMM become FP_RN. */ + return frm & 0x3; +} +DEF_WEAK(fpsetround); diff --git a/lib/libc/arch/riscv64/gen/fpsetsticky.c b/lib/libc/arch/riscv64/gen/fpsetsticky.c new file mode 100644 index 00000000000..a7069c38b75 --- /dev/null +++ b/lib/libc/arch/riscv64/gen/fpsetsticky.c @@ -0,0 +1,29 @@ +/* $OpenBSD: fpsetsticky.c,v 1.1 2021/04/29 17:19:18 kettenis Exp $ */ +/* + * Copyright (c) 2021 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +fp_except +fpsetsticky(fp_except sticky) +{ + uint32_t fflags; + + __asm volatile ("fsflags %0, %1" : "=r"(fflags) : "r"(sticky)); + return fflags; +} +DEF_WEAK(fpsetsticky); diff --git a/sys/arch/riscv64/include/ieeefp.h b/sys/arch/riscv64/include/ieeefp.h index 3cd1684b341..f64ce9dc19e 100644 --- a/sys/arch/riscv64/include/ieeefp.h +++ b/sys/arch/riscv64/include/ieeefp.h @@ -1,5 +1,4 @@ -/* $OpenBSD: ieeefp.h,v 1.1 2021/04/23 02:42:16 drahn Exp $ */ -/* $NetBSD: ieeefp.h,v 1.1 2001/01/10 19:02:06 bjh21 Exp $ */ +/* $OpenBSD: ieeefp.h,v 1.2 2021/04/29 17:19:18 kettenis Exp $ */ /* * Based on ieeefp.h written by J.T. Conklin, Apr 28, 1995 @@ -9,34 +8,18 @@ #ifndef _MACHINE_IEEEFP_H_ #define _MACHINE_IEEEFP_H_ -/* FP exception codes */ - -#define FP_EXCEPT_INV 0 -#define FP_EXCEPT_DZ 1 -#define FP_EXCEPT_OFL 2 -#define FP_EXCEPT_UFL 3 -#define FP_EXCEPT_IMP 4 - -/* Exception type (used by fpsetmask() et al.) */ - typedef int fp_except; - -/* Bit defines for fp_except */ - -#define FP_X_INV (1 << FP_EXCEPT_INV) /* invalid operation exception */ -#define FP_X_DZ (1 << FP_EXCEPT_DZ) /* divide-by-zero exception */ -#define FP_X_OFL (1 << FP_EXCEPT_OFL) /* overflow exception */ -#define FP_X_UFL (1 << FP_EXCEPT_UFL) /* underflow exception */ -#define FP_X_IMP (1 << FP_EXCEPT_IMP) /* imprecise (loss of precision; "inexact") */ -#define FP_X_MASK 0x1f - -/* Rounding modes */ +#define FP_X_INV 0x10 /* invalid operation exception */ +#define FP_X_DZ 0x08 /* divide-by-zero exception */ +#define FP_X_OFL 0x04 /* overflow exception */ +#define FP_X_UFL 0x02 /* underflow exception */ +#define FP_X_IMP 0x01 /* imprecise (loss of precision) */ typedef enum { FP_RN=0, /* round to nearest representable number */ - FP_RP=1, /* round toward positive infinity */ + FP_RZ=1 /* round to zero (truncate) */ FP_RM=2, /* round toward negative infinity */ - FP_RZ=3 /* round to zero (truncate) */ + FP_RP=3, /* round toward positive infinity */ } fp_rnd; #endif /* _MACHINE_IEEEFP_H_ */ -- 2.20.1