mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-21 04:42:53 +08:00
6df01ab8ab
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.
799 lines
13 KiB
C
799 lines
13 KiB
C
/* 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;
|
||
}
|