[3/4] riscv: Map between ieeefp.h exception bits and RISC-V FCSR bits

Message ID 20200121064637.1355843-3-keithp@keithp.com
State Accepted
Commit 5377a847764461493c620644f6530892344d1cdd
Headers show
Series
  • [1/4] riscv: Use current pseudo-instructions to access the FCSR register
Related show

Commit Message

Keith Packard Jan. 21, 2020, 6:46 a.m.
If we had architecture-specific exception bits, we could just set them
to match the processor, but instead ieeefp.h is shared by all targets
so we need to map between the public values and the register contents.

Signed-off-by: Keith Packard <keithp@keithp.com>

---
 newlib/libc/machine/riscv/ieeefp.c | 40 +++++++++++++++++++++++++++---
 1 file changed, 37 insertions(+), 3 deletions(-)

-- 
2.25.0.rc1

Patch

diff --git a/newlib/libc/machine/riscv/ieeefp.c b/newlib/libc/machine/riscv/ieeefp.c
index c45832280..60ecacfc2 100644
--- a/newlib/libc/machine/riscv/ieeefp.c
+++ b/newlib/libc/machine/riscv/ieeefp.c
@@ -40,6 +40,40 @@  frm_fp_rnd (unsigned frm)
     }
 }
 
+static fp_except
+frm_fp_except (unsigned except)
+{
+  fp_except fp = 0;
+  if (except & (1 << 0))
+    fp |= FP_X_IMP;
+  if (except & (1 << 1))
+    fp |= FP_X_UFL;
+  if (except & (1 << 2))
+    fp |= FP_X_OFL;
+  if (except & (1 << 3))
+    fp |= FP_X_DX;
+  if (except & (1 << 4))
+    fp |= FP_X_INV;
+  return fp;
+}
+
+static unsigned
+frm_except(fp_except fp)
+{
+  unsigned except = 0;
+  if (fp & FP_X_IMP)
+    except |= (1 << 0);
+  if (fp & FP_X_UFL)
+    except |= (1 << 1);
+  if (fp & FP_X_OFL)
+    except |= (1 << 2);
+  if (fp & FP_X_DX)
+    except |= (1 << 3);
+  if (fp & FP_X_INV)
+    except |= (1 << 4);
+  return except;
+}
+
 #endif /* __riscv_flen */
 
 fp_except
@@ -63,7 +97,7 @@  fp_except
 fpgetsticky(void)
 {
 #ifdef __riscv_flen
-  return frsr () & 0x1f;
+  return frm_fp_except(frsr ());
 #else
   return 0;
 #endif /* __riscv_flen */
@@ -102,8 +136,8 @@  fpsetsticky(fp_except sticky)
 {
 #ifdef __riscv_flen
   unsigned fsr = frsr ();
-  fssr (sticky & 0x1f | fsr & ~0x1f);
-  return fsr & 0x1f;
+  fssr (frm_except(sticky) | (fsr & ~0x1f));
+  return frm_fp_except(fsr);
 #else
   return -1;
 #endif /* __riscv_flen */