binutils-gdb/sim/common/cgen-accfp.c
Mike Frysinger 6df01ab8ab sim: switch config.h usage to defs.h
The defs.h header will take care of including the various config.h
headers.  For now, it's just config.h, but we'll add more when we
integrate gnulib in.

This header should be used instead of config.h, and should be the
first include in every .c file.  We won't rely on the old behavior
where we expected files to include the port's sim-main.h which then
includes the common sim-basics.h which then includes config.h.  We
have a ton of code that includes things before sim-main.h, and it
sometimes needs to be that way.  Creating a dedicated header avoids
the ordering mess and implicit inclusion that shows up otherwise.
2021-05-16 22:38:41 -04:00

799 lines
13 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Accurate fp support for CGEN-based simulators.
Copyright (C) 1999 Cygnus Solutions.
This implemention assumes:
typedef USI SF;
typedef UDI DF;
TODO:
- lazy encoding/decoding
- checking return code (say by callback)
- proper rounding
*/
/* This must come before any other includes. */
#include "defs.h"
#include "sim-main.h"
#include "sim-fpu.h"
/* SF mode support */
static SF
addsf (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_add (&ans, &op1, &op2);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to32 (&res, &ans);
return res;
}
static SF
subsf (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_sub (&ans, &op1, &op2);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to32 (&res, &ans);
return res;
}
static SF
mulsf (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_mul (&ans, &op1, &op2);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to32 (&res, &ans);
return res;
}
static SF
divsf (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_div (&ans, &op1, &op2);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to32 (&res, &ans);
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)
{
sim_fpu op1;
sim_fpu ans;
unsigned32 res;
sim_fpu_status status;
sim_fpu_32to (&op1, x);
status = sim_fpu_neg (&ans, &op1);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to32 (&res, &ans);
return res;
}
static SF
abssf (CGEN_FPU* fpu, SF x)
{
sim_fpu op1;
sim_fpu ans;
unsigned32 res;
sim_fpu_status status;
sim_fpu_32to (&op1, x);
status = sim_fpu_abs (&ans, &op1);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to32 (&res, &ans);
return res;
}
static SF
sqrtsf (CGEN_FPU* fpu, SF x)
{
sim_fpu op1;
sim_fpu ans;
unsigned32 res;
sim_fpu_status status;
sim_fpu_32to (&op1, x);
status = sim_fpu_sqrt (&ans, &op1);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to32 (&res, &ans);
return res;
}
static SF
invsf (CGEN_FPU* fpu, SF x)
{
sim_fpu op1;
sim_fpu ans;
unsigned32 res;
sim_fpu_status status;
sim_fpu_32to (&op1, x);
status = sim_fpu_inv (&ans, &op1);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to32 (&res, &ans);
return res;
}
static SF
minsf (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_min (&ans, &op1, &op2);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to32 (&res, &ans);
return res;
}
static SF
maxsf (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_max (&ans, &op1, &op2);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to32 (&res, &ans);
return res;
}
static CGEN_FP_CMP
cmpsf (CGEN_FPU* fpu, SF x, SF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_32to (&op1, x);
sim_fpu_32to (&op2, y);
if (sim_fpu_is_nan (&op1)
|| sim_fpu_is_nan (&op2))
return FP_CMP_NAN;
if (x < y)
return FP_CMP_LT;
if (x > y)
return FP_CMP_GT;
return FP_CMP_EQ;
}
static int
eqsf (CGEN_FPU* fpu, SF x, SF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_32to (&op1, x);
sim_fpu_32to (&op2, y);
return sim_fpu_is_eq (&op1, &op2);
}
static int
nesf (CGEN_FPU* fpu, SF x, SF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_32to (&op1, x);
sim_fpu_32to (&op2, y);
return sim_fpu_is_ne (&op1, &op2);
}
static int
ltsf (CGEN_FPU* fpu, SF x, SF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_32to (&op1, x);
sim_fpu_32to (&op2, y);
return sim_fpu_is_lt (&op1, &op2);
}
static int
lesf (CGEN_FPU* fpu, SF x, SF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_32to (&op1, x);
sim_fpu_32to (&op2, y);
return sim_fpu_is_le (&op1, &op2);
}
static int
gtsf (CGEN_FPU* fpu, SF x, SF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_32to (&op1, x);
sim_fpu_32to (&op2, y);
return sim_fpu_is_gt (&op1, &op2);
}
static int
gesf (CGEN_FPU* fpu, SF x, SF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_32to (&op1, x);
sim_fpu_32to (&op2, y);
return sim_fpu_is_ge (&op1, &op2);
}
static int
unorderedsf (CGEN_FPU* fpu, SF x, SF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_32to (&op1, x);
sim_fpu_32to (&op2, y);
return sim_fpu_is_nan (&op1) || sim_fpu_is_nan (&op2);
}
static DF
fextsfdf (CGEN_FPU* fpu, int how UNUSED, SF x)
{
sim_fpu op1;
unsigned64 res;
sim_fpu_32to (&op1, x);
sim_fpu_to64 (&res, &op1);
return res;
}
static SF
ftruncdfsf (CGEN_FPU* fpu, int how UNUSED, DF x)
{
sim_fpu op1;
unsigned32 res;
sim_fpu_64to (&op1, x);
sim_fpu_to32 (&res, &op1);
return res;
}
static SF
floatsisf (CGEN_FPU* fpu, int how UNUSED, SI x)
{
sim_fpu ans;
unsigned32 res;
sim_fpu_i32to (&ans, x, sim_fpu_round_near);
sim_fpu_to32 (&res, &ans);
return res;
}
static DF
floatsidf (CGEN_FPU* fpu, int how UNUSED, SI x)
{
sim_fpu ans;
unsigned64 res;
sim_fpu_i32to (&ans, x, sim_fpu_round_near);
sim_fpu_to64 (&res, &ans);
return res;
}
static DF
floatdidf (CGEN_FPU* fpu, int how UNUSED, DI x)
{
sim_fpu ans;
unsigned64 res;
sim_fpu_i64to (&ans, x, sim_fpu_round_near);
sim_fpu_to64 (&res, &ans);
return res;
}
static SF
ufloatsisf (CGEN_FPU* fpu, int how UNUSED, USI x)
{
sim_fpu ans;
unsigned32 res;
sim_fpu_u32to (&ans, x, sim_fpu_round_near);
sim_fpu_to32 (&res, &ans);
return res;
}
static SI
fixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
{
sim_fpu op1;
signed32 res;
sim_fpu_32to (&op1, x);
sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
return res;
}
static SI
fixdfsi (CGEN_FPU* fpu, int how UNUSED, DF x)
{
sim_fpu op1;
signed32 res;
sim_fpu_64to (&op1, x);
sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
return res;
}
static DI
fixdfdi (CGEN_FPU* fpu, int how UNUSED, DF x)
{
sim_fpu op1;
signed64 res;
sim_fpu_64to (&op1, x);
sim_fpu_to64i (&res, &op1, sim_fpu_round_near);
return res;
}
static USI
ufixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
{
sim_fpu op1;
unsigned32 res;
sim_fpu_32to (&op1, x);
sim_fpu_to32u (&res, &op1, sim_fpu_round_near);
return res;
}
/* DF mode support */
static DF
adddf (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_add (&ans, &op1, &op2);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to64 (&res, &ans);
return res;
}
static DF
subdf (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_sub (&ans, &op1, &op2);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to64 (&res, &ans);
return res;
}
static DF
muldf (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_mul (&ans, &op1, &op2);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to64 (&res, &ans);
return res;
}
static DF
divdf (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_div (&ans, &op1, &op2);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to64 (&res, &ans);
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)
{
sim_fpu op1;
sim_fpu ans;
unsigned64 res;
sim_fpu_status status;
sim_fpu_64to (&op1, x);
status = sim_fpu_neg (&ans, &op1);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to64 (&res, &ans);
return res;
}
static DF
absdf (CGEN_FPU* fpu, DF x)
{
sim_fpu op1;
sim_fpu ans;
unsigned64 res;
sim_fpu_status status;
sim_fpu_64to (&op1, x);
status = sim_fpu_abs (&ans, &op1);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to64 (&res, &ans);
return res;
}
static DF
sqrtdf (CGEN_FPU* fpu, DF x)
{
sim_fpu op1;
sim_fpu ans;
unsigned64 res;
sim_fpu_status status;
sim_fpu_64to (&op1, x);
status = sim_fpu_sqrt (&ans, &op1);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to64 (&res, &ans);
return res;
}
static DF
invdf (CGEN_FPU* fpu, DF x)
{
sim_fpu op1;
sim_fpu ans;
unsigned64 res;
sim_fpu_status status;
sim_fpu_64to (&op1, x);
status = sim_fpu_inv (&ans, &op1);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to64 (&res, &ans);
return res;
}
static DF
mindf (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_min (&ans, &op1, &op2);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to64 (&res, &ans);
return res;
}
static DF
maxdf (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_max (&ans, &op1, &op2);
if (status != 0)
(*fpu->ops->error) (fpu, status);
sim_fpu_to64 (&res, &ans);
return res;
}
static CGEN_FP_CMP
cmpdf (CGEN_FPU* fpu, DF x, DF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_64to (&op1, x);
sim_fpu_64to (&op2, y);
if (sim_fpu_is_nan (&op1)
|| sim_fpu_is_nan (&op2))
return FP_CMP_NAN;
if (x < y)
return FP_CMP_LT;
if (x > y)
return FP_CMP_GT;
return FP_CMP_EQ;
}
static int
eqdf (CGEN_FPU* fpu, DF x, DF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_64to (&op1, x);
sim_fpu_64to (&op2, y);
return sim_fpu_is_eq (&op1, &op2);
}
static int
nedf (CGEN_FPU* fpu, DF x, DF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_64to (&op1, x);
sim_fpu_64to (&op2, y);
return sim_fpu_is_ne (&op1, &op2);
}
static int
ltdf (CGEN_FPU* fpu, DF x, DF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_64to (&op1, x);
sim_fpu_64to (&op2, y);
return sim_fpu_is_lt (&op1, &op2);
}
static int
ledf (CGEN_FPU* fpu, DF x, DF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_64to (&op1, x);
sim_fpu_64to (&op2, y);
return sim_fpu_is_le (&op1, &op2);
}
static int
gtdf (CGEN_FPU* fpu, DF x, DF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_64to (&op1, x);
sim_fpu_64to (&op2, y);
return sim_fpu_is_gt (&op1, &op2);
}
static int
gedf (CGEN_FPU* fpu, DF x, DF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_64to (&op1, x);
sim_fpu_64to (&op2, y);
return sim_fpu_is_ge (&op1, &op2);
}
static int
unordereddf (CGEN_FPU* fpu, DF x, DF y)
{
sim_fpu op1;
sim_fpu op2;
sim_fpu_64to (&op1, x);
sim_fpu_64to (&op2, y);
return sim_fpu_is_nan (&op1) || sim_fpu_is_nan (&op2);
}
/* Initialize FP_OPS to use accurate library. */
void
cgen_init_accurate_fpu (SIM_CPU* cpu, CGEN_FPU* fpu, CGEN_FPU_ERROR_FN* error)
{
CGEN_FP_OPS* o;
fpu->owner = cpu;
/* ??? small memory leak, not freed by sim_close */
fpu->ops = (CGEN_FP_OPS*) xmalloc (sizeof (CGEN_FP_OPS));
o = fpu->ops;
memset (o, 0, sizeof (*o));
o->error = error;
o->addsf = addsf;
o->subsf = subsf;
o->mulsf = mulsf;
o->divsf = divsf;
o->remsf = remsf;
o->negsf = negsf;
o->abssf = abssf;
o->sqrtsf = sqrtsf;
o->invsf = invsf;
o->minsf = minsf;
o->maxsf = maxsf;
o->cmpsf = cmpsf;
o->eqsf = eqsf;
o->nesf = nesf;
o->ltsf = ltsf;
o->lesf = lesf;
o->gtsf = gtsf;
o->gesf = gesf;
o->unorderedsf = unorderedsf;
o->adddf = adddf;
o->subdf = subdf;
o->muldf = muldf;
o->divdf = divdf;
o->remdf = remdf;
o->negdf = negdf;
o->absdf = absdf;
o->sqrtdf = sqrtdf;
o->invdf = invdf;
o->mindf = mindf;
o->maxdf = maxdf;
o->cmpdf = cmpdf;
o->eqdf = eqdf;
o->nedf = nedf;
o->ltdf = ltdf;
o->ledf = ledf;
o->gtdf = gtdf;
o->gedf = gedf;
o->unordereddf = unordereddf;
o->fextsfdf = fextsfdf;
o->ftruncdfsf = ftruncdfsf;
o->floatsisf = floatsisf;
o->floatsidf = floatsidf;
o->floatdidf = floatdidf;
o->ufloatsisf = ufloatsisf;
o->fixsfsi = fixsfsi;
o->fixdfsi = fixdfsi;
o->fixdfdi = fixdfdi;
o->ufixsfsi = ufixsfsi;
}