mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-02 23:04:09 +08:00
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.
This commit is contained in:
parent
638d913757
commit
07b95864f3
@ -1,3 +1,14 @@
|
||||
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.
|
||||
|
||||
2017-09-06 John Baldwin <jhb@FreeBSD.org>
|
||||
|
||||
* acinclude.m4 (SIM_AC_COMMON): Honor existing CC_FOR_BUILD in
|
||||
|
@ -92,6 +92,25 @@ divsf (CGEN_FPU* fpu, SF x, SF y)
|
||||
return res;
|
||||
}
|
||||
|
||||
static SF
|
||||
remsf (CGEN_FPU* fpu, SF x, SF y)
|
||||
{
|
||||
sim_fpu op1;
|
||||
sim_fpu op2;
|
||||
sim_fpu ans;
|
||||
unsigned32 res;
|
||||
sim_fpu_status status;
|
||||
|
||||
sim_fpu_32to (&op1, x);
|
||||
sim_fpu_32to (&op2, y);
|
||||
status = sim_fpu_rem (&ans, &op1, &op2);
|
||||
if (status != 0)
|
||||
(*fpu->ops->error) (fpu, status);
|
||||
sim_fpu_to32 (&res, &ans);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static SF
|
||||
negsf (CGEN_FPU* fpu, SF x)
|
||||
{
|
||||
@ -452,6 +471,25 @@ divdf (CGEN_FPU* fpu, DF x, DF y)
|
||||
return res;
|
||||
}
|
||||
|
||||
static DF
|
||||
remdf (CGEN_FPU* fpu, DF x, DF y)
|
||||
{
|
||||
sim_fpu op1;
|
||||
sim_fpu op2;
|
||||
sim_fpu ans;
|
||||
unsigned64 res;
|
||||
sim_fpu_status status;
|
||||
|
||||
sim_fpu_64to (&op1, x);
|
||||
sim_fpu_64to (&op2, y);
|
||||
status = sim_fpu_rem (&ans, &op1, &op2);
|
||||
if (status != 0)
|
||||
(*fpu->ops->error) (fpu, status);
|
||||
sim_fpu_to64(&res, &ans);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static DF
|
||||
negdf (CGEN_FPU* fpu, DF x)
|
||||
{
|
||||
@ -664,6 +702,7 @@ cgen_init_accurate_fpu (SIM_CPU* cpu, CGEN_FPU* fpu, CGEN_FPU_ERROR_FN* error)
|
||||
o->subsf = subsf;
|
||||
o->mulsf = mulsf;
|
||||
o->divsf = divsf;
|
||||
o->remsf = remsf;
|
||||
o->negsf = negsf;
|
||||
o->abssf = abssf;
|
||||
o->sqrtsf = sqrtsf;
|
||||
@ -682,6 +721,7 @@ cgen_init_accurate_fpu (SIM_CPU* cpu, CGEN_FPU* fpu, CGEN_FPU_ERROR_FN* error)
|
||||
o->subdf = subdf;
|
||||
o->muldf = muldf;
|
||||
o->divdf = divdf;
|
||||
o->remdf = remdf;
|
||||
o->negdf = negdf;
|
||||
o->absdf = absdf;
|
||||
o->sqrtdf = sqrtdf;
|
||||
|
@ -69,6 +69,7 @@ struct cgen_fp_ops {
|
||||
SF (*subsf) (CGEN_FPU*, SF, SF);
|
||||
SF (*mulsf) (CGEN_FPU*, SF, SF);
|
||||
SF (*divsf) (CGEN_FPU*, SF, SF);
|
||||
SF (*remsf) (CGEN_FPU*, SF, SF);
|
||||
SF (*negsf) (CGEN_FPU*, SF);
|
||||
SF (*abssf) (CGEN_FPU*, SF);
|
||||
SF (*sqrtsf) (CGEN_FPU*, SF);
|
||||
@ -93,6 +94,7 @@ struct cgen_fp_ops {
|
||||
DF (*subdf) (CGEN_FPU*, DF, DF);
|
||||
DF (*muldf) (CGEN_FPU*, DF, DF);
|
||||
DF (*divdf) (CGEN_FPU*, DF, DF);
|
||||
DF (*remdf) (CGEN_FPU*, DF, DF);
|
||||
DF (*negdf) (CGEN_FPU*, DF);
|
||||
DF (*absdf) (CGEN_FPU*, DF);
|
||||
DF (*sqrtdf) (CGEN_FPU*, DF);
|
||||
@ -142,6 +144,7 @@ struct cgen_fp_ops {
|
||||
XF (*subxf) (CGEN_FPU*, XF, XF);
|
||||
XF (*mulxf) (CGEN_FPU*, XF, XF);
|
||||
XF (*divxf) (CGEN_FPU*, XF, XF);
|
||||
XF (*remxf) (CGEN_FPU*, XF, XF);
|
||||
XF (*negxf) (CGEN_FPU*, XF);
|
||||
XF (*absxf) (CGEN_FPU*, XF);
|
||||
XF (*sqrtxf) (CGEN_FPU*, XF);
|
||||
@ -180,6 +183,7 @@ struct cgen_fp_ops {
|
||||
TF (*subtf) (CGEN_FPU*, TF, TF);
|
||||
TF (*multf) (CGEN_FPU*, TF, TF);
|
||||
TF (*divtf) (CGEN_FPU*, TF, TF);
|
||||
TF (*remtf) (CGEN_FPU*, TF, TF);
|
||||
TF (*negtf) (CGEN_FPU*, TF);
|
||||
TF (*abstf) (CGEN_FPU*, TF);
|
||||
TF (*sqrttf) (CGEN_FPU*, TF);
|
||||
|
@ -1550,6 +1550,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,
|
||||
@ -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;
|
||||
|
@ -146,11 +146,12 @@ typedef enum
|
||||
sim_fpu_status_invalid_div0 = 128, /* (X / 0) */
|
||||
sim_fpu_status_invalid_cmp = 256, /* compare */
|
||||
sim_fpu_status_invalid_sqrt = 512,
|
||||
sim_fpu_status_rounded = 1024,
|
||||
sim_fpu_status_inexact = 2048,
|
||||
sim_fpu_status_overflow = 4096,
|
||||
sim_fpu_status_underflow = 8192,
|
||||
sim_fpu_status_denorm = 16384,
|
||||
sim_fpu_status_invalid_irx = 1024, /* (inf % X) */
|
||||
sim_fpu_status_rounded = 2048,
|
||||
sim_fpu_status_inexact = 4096,
|
||||
sim_fpu_status_overflow = 8192,
|
||||
sim_fpu_status_underflow = 16384,
|
||||
sim_fpu_status_denorm = 32768,
|
||||
} sim_fpu_status;
|
||||
|
||||
|
||||
@ -230,6 +231,8 @@ INLINE_SIM_FPU (int) sim_fpu_mul (sim_fpu *f,
|
||||
const sim_fpu *l, const sim_fpu *r);
|
||||
INLINE_SIM_FPU (int) sim_fpu_div (sim_fpu *f,
|
||||
const sim_fpu *l, const sim_fpu *r);
|
||||
INLINE_SIM_FPU (int) sim_fpu_rem (sim_fpu *f,
|
||||
const sim_fpu *l, const sim_fpu *r);
|
||||
INLINE_SIM_FPU (int) sim_fpu_max (sim_fpu *f,
|
||||
const sim_fpu *l, const sim_fpu *r);
|
||||
INLINE_SIM_FPU (int) sim_fpu_min (sim_fpu *f,
|
||||
|
Loading…
Reference in New Issue
Block a user