aboutsummaryrefslogtreecommitdiff
path: root/sim/common/sim-fpu.c
diff options
context:
space:
mode:
authorPeter Gavin <pgavin@gmail.com>2017-12-09 05:57:25 +0900
committerStafford Horne <shorne@gmail.com>2017-12-12 23:41:43 +0900
commit07b95864f35f19636e2a95eaf3083a8b18ac7cda (patch)
tree5ebfa4d1d728e6625c033a9c8cf90f3e45468ded /sim/common/sim-fpu.c
parent638d913757609367eea219d00296a0a3d45010c2 (diff)
downloadgdb-07b95864f35f19636e2a95eaf3083a8b18ac7cda.zip
gdb-07b95864f35f19636e2a95eaf3083a8b18ac7cda.tar.gz
gdb-07b95864f35f19636e2a95eaf3083a8b18ac7cda.tar.bz2
sim: cgen: add remainder functions (needed for OR1K lf.rem.[sd])
* sim/common/ChangeLog: 2017-12-12 Peter Gavin <pgavin@gmail.com> Stafford Horne <shorne@gmail.com> * cgen-accfp.c (remsf, remdf): New function. (cgen_init_accurate_fpu): Add remsf and remdf. * cgen-fpu.h (cgen_fp_ops): Add remsf, remdf, remxf and remtf. * sim-fpu.c (sim_fpu_rem): New function. * sim-fpu.h (sim_fpu_status_invalid_irx): New enum. (sim_fpu_rem): New function. (sim_fpu_print_status): Add case for sim_fpu_status_invalid_irx.
Diffstat (limited to 'sim/common/sim-fpu.c')
-rw-r--r--sim/common/sim-fpu.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c
index 0d4d08a..8d0fb17 100644
--- a/sim/common/sim-fpu.c
+++ b/sim/common/sim-fpu.c
@@ -1551,6 +1551,89 @@ sim_fpu_div (sim_fpu *f,
INLINE_SIM_FPU (int)
+sim_fpu_rem (sim_fpu *f,
+ const sim_fpu *l,
+ const sim_fpu *r)
+{
+ if (sim_fpu_is_snan (l))
+ {
+ *f = *l;
+ f->class = sim_fpu_class_qnan;
+ return sim_fpu_status_invalid_snan;
+ }
+ if (sim_fpu_is_snan (r))
+ {
+ *f = *r;
+ f->class = sim_fpu_class_qnan;
+ return sim_fpu_status_invalid_snan;
+ }
+ if (sim_fpu_is_qnan (l))
+ {
+ *f = *l;
+ f->class = sim_fpu_class_qnan;
+ return 0;
+ }
+ if (sim_fpu_is_qnan (r))
+ {
+ *f = *r;
+ f->class = sim_fpu_class_qnan;
+ return 0;
+ }
+ if (sim_fpu_is_infinity (l))
+ {
+ *f = sim_fpu_qnan;
+ return sim_fpu_status_invalid_irx;
+ }
+ if (sim_fpu_is_zero (r))
+ {
+ *f = sim_fpu_qnan;
+ return sim_fpu_status_invalid_div0;
+ }
+ if (sim_fpu_is_zero (l))
+ {
+ *f = *l;
+ return 0;
+ }
+ if (sim_fpu_is_infinity (r))
+ {
+ *f = *l;
+ return 0;
+ }
+ {
+ sim_fpu n, tmp;
+
+ /* Remainder is calculated as l-n*r, where n is l/r rounded to the
+ nearest integer. The variable n is rounded half even. */
+
+ sim_fpu_div (&n, l, r);
+ sim_fpu_round_64 (&n, 0, 0);
+
+ if (n.normal_exp < -1) /* If n looks like zero just return l. */
+ {
+ *f = *l;
+ return 0;
+ }
+ else if (n.class == sim_fpu_class_number
+ && n.normal_exp <= (NR_FRAC_GUARD)) /* If not too large round. */
+ do_normal_round (&n, (NR_FRAC_GUARD) - n.normal_exp, sim_fpu_round_near);
+
+ /* Mark 0's as zero so multiply can detect zero. */
+ if (n.fraction == 0)
+ n.class = sim_fpu_class_zero;
+
+ /* Calculate n*r. */
+ sim_fpu_mul (&tmp, &n, r);
+ sim_fpu_round_64 (&tmp, 0, 0);
+
+ /* Finally calculate l-n*r. */
+ sim_fpu_sub (f, l, &tmp);
+
+ return 0;
+ }
+}
+
+
+INLINE_SIM_FPU (int)
sim_fpu_max (sim_fpu *f,
const sim_fpu *l,
const sim_fpu *r)
@@ -2533,6 +2616,9 @@ sim_fpu_print_status (int status,
case sim_fpu_status_invalid_sqrt:
print (arg, "%sSQRT", prefix);
break;
+ case sim_fpu_status_invalid_irx:
+ print (arg, "%sIRX", prefix);
+ break;
case sim_fpu_status_inexact:
print (arg, "%sX", prefix);
break;