summaryrefslogtreecommitdiffstats
path: root/newlib/libc/machine/riscv/ieeefp.c
diff options
context:
space:
mode:
authorKito Cheng <kito@andestech.com>2017-07-27 16:44:22 +0800
committerJeff Johnston <jjohnstn@redhat.com>2017-08-16 18:00:58 -0400
commit363dbb9e44d0101f29ec34cadd001893daab3fc6 (patch)
tree8c39ab14c5b090653f88bd4624b593ef4819e059 /newlib/libc/machine/riscv/ieeefp.c
parent7e69f983a46dfb9ae9c09e30fc20ad6a91f0ddc4 (diff)
downloadcygnal-363dbb9e44d0101f29ec34cadd001893daab3fc6.tar.gz
cygnal-363dbb9e44d0101f29ec34cadd001893daab3fc6.tar.bz2
cygnal-363dbb9e44d0101f29ec34cadd001893daab3fc6.zip
Add RISC-V port for newlib
Contributor list: - Andrew Waterman <andrew@sifive.com> - Palmer Dabbelt <palmer@dabbelt.com> - Kito Cheng <kito.cheng@gmail.com> - Scott Beamer <sbeamer@eecs.berkeley.edu>
Diffstat (limited to 'newlib/libc/machine/riscv/ieeefp.c')
-rw-r--r--newlib/libc/machine/riscv/ieeefp.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/newlib/libc/machine/riscv/ieeefp.c b/newlib/libc/machine/riscv/ieeefp.c
new file mode 100644
index 000000000..5288877a6
--- /dev/null
+++ b/newlib/libc/machine/riscv/ieeefp.c
@@ -0,0 +1,110 @@
+/* Copyright (c) 2017 SiFive Inc. All rights reserved.
+
+ This copyrighted material is made available to anyone wishing to use,
+ modify, copy, or redistribute it subject to the terms and conditions
+ of the BSD License. This program is distributed in the hope that
+ it will be useful, but WITHOUT ANY WARRANTY expressed or implied,
+ including the implied warranties of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. A copy of this license is available at
+ http://www.opensource.org/licenses.
+*/
+
+#include <ieeefp.h>
+
+#ifdef __riscv_flen
+static void
+fssr(unsigned value)
+{
+ asm volatile ("fssr %0" :: "r"(value));
+}
+
+static unsigned
+frsr()
+{
+ unsigned value;
+ asm volatile ("frsr %0" : "=r" (value));
+ return value;
+}
+
+static fp_rnd
+frm_fp_rnd (unsigned frm)
+{
+ switch (frm)
+ {
+ case 0: return FP_RN;
+ case 1: return FP_RZ;
+ case 2: return FP_RM;
+ case 3: return FP_RP;
+ /* 4 ~ 7 is invalid value, so just retun FP_RP. */
+ default:return FP_RP;
+ }
+}
+
+#endif /* __riscv_flen */
+
+fp_except
+fpgetmask(void)
+{
+ return 0;
+}
+
+fp_rnd
+fpgetround(void)
+{
+#ifdef __riscv_flen
+ unsigned rm = (frsr () >> 5) & 0x7;
+ return frm_fp_rnd (rm);
+#else
+ return FP_RZ;
+#endif /* __riscv_flen */
+}
+
+fp_except
+fpgetsticky(void)
+{
+#ifdef __riscv_flen
+ return frsr () & 0x1f;
+#else
+ return 0;
+#endif /* __riscv_flen */
+}
+
+fp_except
+fpsetmask(fp_except mask)
+{
+ return -1;
+}
+
+fp_rnd
+fpsetround(fp_rnd rnd_dir)
+{
+#ifdef __riscv_flen
+ unsigned fsr = frsr ();
+ unsigned rm = (fsr >> 5) & 0x7;
+ unsigned new_rm;
+ switch (rnd_dir)
+ {
+ case FP_RN: new_rm = 0;
+ case FP_RZ: new_rm = 1;
+ case FP_RM: new_rm = 2;
+ case FP_RP: new_rm = 3;
+ default: return -1;
+ }
+ fssr (new_rm << 5 | fsr & 0x1f);
+ return frm_fp_rnd (rm);
+#else
+ return -1;
+#endif /* __riscv_flen */
+}
+
+fp_except
+fpsetsticky(fp_except sticky)
+{
+#ifdef __riscv_flen
+ unsigned fsr = frsr ();
+ fssr (sticky & 0x1f | fsr & ~0x1f);
+ return fsr & 0x1f;
+#else
+ return -1;
+#endif /* __riscv_flen */
+}