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>
|
2017-09-06 John Baldwin <jhb@FreeBSD.org>
|
||||||
|
|
||||||
* acinclude.m4 (SIM_AC_COMMON): Honor existing CC_FOR_BUILD in
|
* 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;
|
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
|
static SF
|
||||||
negsf (CGEN_FPU* fpu, SF x)
|
negsf (CGEN_FPU* fpu, SF x)
|
||||||
{
|
{
|
||||||
@ -452,6 +471,25 @@ divdf (CGEN_FPU* fpu, DF x, DF y)
|
|||||||
return res;
|
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
|
static DF
|
||||||
negdf (CGEN_FPU* fpu, DF x)
|
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->subsf = subsf;
|
||||||
o->mulsf = mulsf;
|
o->mulsf = mulsf;
|
||||||
o->divsf = divsf;
|
o->divsf = divsf;
|
||||||
|
o->remsf = remsf;
|
||||||
o->negsf = negsf;
|
o->negsf = negsf;
|
||||||
o->abssf = abssf;
|
o->abssf = abssf;
|
||||||
o->sqrtsf = sqrtsf;
|
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->subdf = subdf;
|
||||||
o->muldf = muldf;
|
o->muldf = muldf;
|
||||||
o->divdf = divdf;
|
o->divdf = divdf;
|
||||||
|
o->remdf = remdf;
|
||||||
o->negdf = negdf;
|
o->negdf = negdf;
|
||||||
o->absdf = absdf;
|
o->absdf = absdf;
|
||||||
o->sqrtdf = sqrtdf;
|
o->sqrtdf = sqrtdf;
|
||||||
|
@ -69,6 +69,7 @@ struct cgen_fp_ops {
|
|||||||
SF (*subsf) (CGEN_FPU*, SF, SF);
|
SF (*subsf) (CGEN_FPU*, SF, SF);
|
||||||
SF (*mulsf) (CGEN_FPU*, SF, SF);
|
SF (*mulsf) (CGEN_FPU*, SF, SF);
|
||||||
SF (*divsf) (CGEN_FPU*, SF, SF);
|
SF (*divsf) (CGEN_FPU*, SF, SF);
|
||||||
|
SF (*remsf) (CGEN_FPU*, SF, SF);
|
||||||
SF (*negsf) (CGEN_FPU*, SF);
|
SF (*negsf) (CGEN_FPU*, SF);
|
||||||
SF (*abssf) (CGEN_FPU*, SF);
|
SF (*abssf) (CGEN_FPU*, SF);
|
||||||
SF (*sqrtsf) (CGEN_FPU*, SF);
|
SF (*sqrtsf) (CGEN_FPU*, SF);
|
||||||
@ -93,6 +94,7 @@ struct cgen_fp_ops {
|
|||||||
DF (*subdf) (CGEN_FPU*, DF, DF);
|
DF (*subdf) (CGEN_FPU*, DF, DF);
|
||||||
DF (*muldf) (CGEN_FPU*, DF, DF);
|
DF (*muldf) (CGEN_FPU*, DF, DF);
|
||||||
DF (*divdf) (CGEN_FPU*, DF, DF);
|
DF (*divdf) (CGEN_FPU*, DF, DF);
|
||||||
|
DF (*remdf) (CGEN_FPU*, DF, DF);
|
||||||
DF (*negdf) (CGEN_FPU*, DF);
|
DF (*negdf) (CGEN_FPU*, DF);
|
||||||
DF (*absdf) (CGEN_FPU*, DF);
|
DF (*absdf) (CGEN_FPU*, DF);
|
||||||
DF (*sqrtdf) (CGEN_FPU*, DF);
|
DF (*sqrtdf) (CGEN_FPU*, DF);
|
||||||
@ -142,6 +144,7 @@ struct cgen_fp_ops {
|
|||||||
XF (*subxf) (CGEN_FPU*, XF, XF);
|
XF (*subxf) (CGEN_FPU*, XF, XF);
|
||||||
XF (*mulxf) (CGEN_FPU*, XF, XF);
|
XF (*mulxf) (CGEN_FPU*, XF, XF);
|
||||||
XF (*divxf) (CGEN_FPU*, XF, XF);
|
XF (*divxf) (CGEN_FPU*, XF, XF);
|
||||||
|
XF (*remxf) (CGEN_FPU*, XF, XF);
|
||||||
XF (*negxf) (CGEN_FPU*, XF);
|
XF (*negxf) (CGEN_FPU*, XF);
|
||||||
XF (*absxf) (CGEN_FPU*, XF);
|
XF (*absxf) (CGEN_FPU*, XF);
|
||||||
XF (*sqrtxf) (CGEN_FPU*, XF);
|
XF (*sqrtxf) (CGEN_FPU*, XF);
|
||||||
@ -180,6 +183,7 @@ struct cgen_fp_ops {
|
|||||||
TF (*subtf) (CGEN_FPU*, TF, TF);
|
TF (*subtf) (CGEN_FPU*, TF, TF);
|
||||||
TF (*multf) (CGEN_FPU*, TF, TF);
|
TF (*multf) (CGEN_FPU*, TF, TF);
|
||||||
TF (*divtf) (CGEN_FPU*, TF, TF);
|
TF (*divtf) (CGEN_FPU*, TF, TF);
|
||||||
|
TF (*remtf) (CGEN_FPU*, TF, TF);
|
||||||
TF (*negtf) (CGEN_FPU*, TF);
|
TF (*negtf) (CGEN_FPU*, TF);
|
||||||
TF (*abstf) (CGEN_FPU*, TF);
|
TF (*abstf) (CGEN_FPU*, TF);
|
||||||
TF (*sqrttf) (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)
|
INLINE_SIM_FPU (int)
|
||||||
sim_fpu_max (sim_fpu *f,
|
sim_fpu_max (sim_fpu *f,
|
||||||
const sim_fpu *l,
|
const sim_fpu *l,
|
||||||
@ -2533,6 +2616,9 @@ sim_fpu_print_status (int status,
|
|||||||
case sim_fpu_status_invalid_sqrt:
|
case sim_fpu_status_invalid_sqrt:
|
||||||
print (arg, "%sSQRT", prefix);
|
print (arg, "%sSQRT", prefix);
|
||||||
break;
|
break;
|
||||||
|
case sim_fpu_status_invalid_irx:
|
||||||
|
print (arg, "%sIRX", prefix);
|
||||||
|
break;
|
||||||
case sim_fpu_status_inexact:
|
case sim_fpu_status_inexact:
|
||||||
print (arg, "%sX", prefix);
|
print (arg, "%sX", prefix);
|
||||||
break;
|
break;
|
||||||
|
@ -146,11 +146,12 @@ typedef enum
|
|||||||
sim_fpu_status_invalid_div0 = 128, /* (X / 0) */
|
sim_fpu_status_invalid_div0 = 128, /* (X / 0) */
|
||||||
sim_fpu_status_invalid_cmp = 256, /* compare */
|
sim_fpu_status_invalid_cmp = 256, /* compare */
|
||||||
sim_fpu_status_invalid_sqrt = 512,
|
sim_fpu_status_invalid_sqrt = 512,
|
||||||
sim_fpu_status_rounded = 1024,
|
sim_fpu_status_invalid_irx = 1024, /* (inf % X) */
|
||||||
sim_fpu_status_inexact = 2048,
|
sim_fpu_status_rounded = 2048,
|
||||||
sim_fpu_status_overflow = 4096,
|
sim_fpu_status_inexact = 4096,
|
||||||
sim_fpu_status_underflow = 8192,
|
sim_fpu_status_overflow = 8192,
|
||||||
sim_fpu_status_denorm = 16384,
|
sim_fpu_status_underflow = 16384,
|
||||||
|
sim_fpu_status_denorm = 32768,
|
||||||
} sim_fpu_status;
|
} 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);
|
const sim_fpu *l, const sim_fpu *r);
|
||||||
INLINE_SIM_FPU (int) sim_fpu_div (sim_fpu *f,
|
INLINE_SIM_FPU (int) sim_fpu_div (sim_fpu *f,
|
||||||
const sim_fpu *l, const sim_fpu *r);
|
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,
|
INLINE_SIM_FPU (int) sim_fpu_max (sim_fpu *f,
|
||||||
const sim_fpu *l, const sim_fpu *r);
|
const sim_fpu *l, const sim_fpu *r);
|
||||||
INLINE_SIM_FPU (int) sim_fpu_min (sim_fpu *f,
|
INLINE_SIM_FPU (int) sim_fpu_min (sim_fpu *f,
|
||||||
|
Loading…
Reference in New Issue
Block a user