1999-07-06 02:58:41 +02:00
|
|
|
|
/* 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
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#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;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_32to (&op1, x);
|
|
|
|
|
sim_fpu_32to (&op2, y);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_sub (&ans, &op1, &op2);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
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;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_32to (&op1, x);
|
|
|
|
|
sim_fpu_32to (&op2, y);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_mul (&ans, &op1, &op2);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
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;
|
1999-10-19 04:47:02 +02:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_32to (&op1, x);
|
|
|
|
|
sim_fpu_32to (&op2, y);
|
1999-10-19 04:47:02 +02:00
|
|
|
|
status = sim_fpu_div (&ans, &op1, &op2);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
sim_fpu_to32 (&res, &ans);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-08 21:57:25 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
1999-07-06 02:58:41 +02:00
|
|
|
|
static SF
|
|
|
|
|
negsf (CGEN_FPU* fpu, SF x)
|
|
|
|
|
{
|
|
|
|
|
sim_fpu op1;
|
|
|
|
|
sim_fpu ans;
|
|
|
|
|
unsigned32 res;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_32to (&op1, x);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_neg (&ans, &op1);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
sim_fpu_to32 (&res, &ans);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SF
|
|
|
|
|
abssf (CGEN_FPU* fpu, SF x)
|
|
|
|
|
{
|
|
|
|
|
sim_fpu op1;
|
|
|
|
|
sim_fpu ans;
|
|
|
|
|
unsigned32 res;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_32to (&op1, x);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_abs (&ans, &op1);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
sim_fpu_to32 (&res, &ans);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SF
|
|
|
|
|
sqrtsf (CGEN_FPU* fpu, SF x)
|
|
|
|
|
{
|
|
|
|
|
sim_fpu op1;
|
|
|
|
|
sim_fpu ans;
|
|
|
|
|
unsigned32 res;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_32to (&op1, x);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_sqrt (&ans, &op1);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
sim_fpu_to32 (&res, &ans);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SF
|
|
|
|
|
invsf (CGEN_FPU* fpu, SF x)
|
|
|
|
|
{
|
|
|
|
|
sim_fpu op1;
|
|
|
|
|
sim_fpu ans;
|
|
|
|
|
unsigned32 res;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_32to (&op1, x);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_inv (&ans, &op1);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
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;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_32to (&op1, x);
|
|
|
|
|
sim_fpu_32to (&op2, y);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_min (&ans, &op1, &op2);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
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;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_32to (&op1, x);
|
|
|
|
|
sim_fpu_32to (&op2, y);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_max (&ans, &op1, &op2);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-13 14:27:10 +02:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-03-30 22:21:37 +02:00
|
|
|
|
static DF
|
2010-01-25 05:08:52 +01:00
|
|
|
|
fextsfdf (CGEN_FPU* fpu, int how UNUSED, SF x)
|
2000-03-30 22:21:37 +02:00
|
|
|
|
{
|
|
|
|
|
sim_fpu op1;
|
|
|
|
|
unsigned64 res;
|
|
|
|
|
|
|
|
|
|
sim_fpu_32to (&op1, x);
|
|
|
|
|
sim_fpu_to64 (&res, &op1);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SF
|
2010-01-25 05:08:52 +01:00
|
|
|
|
ftruncdfsf (CGEN_FPU* fpu, int how UNUSED, DF x)
|
2000-03-30 22:21:37 +02:00
|
|
|
|
{
|
|
|
|
|
sim_fpu op1;
|
|
|
|
|
unsigned32 res;
|
|
|
|
|
|
|
|
|
|
sim_fpu_64to (&op1, x);
|
|
|
|
|
sim_fpu_to32 (&res, &op1);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
1999-07-06 02:58:41 +02:00
|
|
|
|
static SF
|
2010-01-25 05:08:52 +01:00
|
|
|
|
floatsisf (CGEN_FPU* fpu, int how UNUSED, SI x)
|
1999-07-06 02:58:41 +02:00
|
|
|
|
{
|
|
|
|
|
sim_fpu ans;
|
|
|
|
|
unsigned32 res;
|
|
|
|
|
|
|
|
|
|
sim_fpu_i32to (&ans, x, sim_fpu_round_near);
|
|
|
|
|
sim_fpu_to32 (&res, &ans);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
1999-07-07 19:31:57 +02:00
|
|
|
|
static DF
|
2010-01-25 05:08:52 +01:00
|
|
|
|
floatsidf (CGEN_FPU* fpu, int how UNUSED, SI x)
|
1999-07-07 19:31:57 +02:00
|
|
|
|
{
|
|
|
|
|
sim_fpu ans;
|
|
|
|
|
unsigned64 res;
|
|
|
|
|
|
|
|
|
|
sim_fpu_i32to (&ans, x, sim_fpu_round_near);
|
|
|
|
|
sim_fpu_to64 (&res, &ans);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-13 14:27:10 +02:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
1999-07-06 02:58:41 +02:00
|
|
|
|
static SF
|
2010-01-25 05:08:52 +01:00
|
|
|
|
ufloatsisf (CGEN_FPU* fpu, int how UNUSED, USI x)
|
1999-07-06 02:58:41 +02:00
|
|
|
|
{
|
|
|
|
|
sim_fpu ans;
|
|
|
|
|
unsigned32 res;
|
|
|
|
|
|
|
|
|
|
sim_fpu_u32to (&ans, x, sim_fpu_round_near);
|
|
|
|
|
sim_fpu_to32 (&res, &ans);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SI
|
2010-01-25 05:08:52 +01:00
|
|
|
|
fixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
|
1999-07-06 02:58:41 +02:00
|
|
|
|
{
|
|
|
|
|
sim_fpu op1;
|
|
|
|
|
unsigned32 res;
|
|
|
|
|
|
|
|
|
|
sim_fpu_32to (&op1, x);
|
|
|
|
|
sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
1999-07-07 19:31:57 +02:00
|
|
|
|
static SI
|
2010-01-25 05:08:52 +01:00
|
|
|
|
fixdfsi (CGEN_FPU* fpu, int how UNUSED, DF x)
|
1999-07-07 19:31:57 +02:00
|
|
|
|
{
|
|
|
|
|
sim_fpu op1;
|
|
|
|
|
unsigned32 res;
|
|
|
|
|
|
|
|
|
|
sim_fpu_64to (&op1, x);
|
|
|
|
|
sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-13 14:27:10 +02:00
|
|
|
|
static DI
|
|
|
|
|
fixdfdi (CGEN_FPU* fpu, int how UNUSED, DF x)
|
|
|
|
|
{
|
|
|
|
|
sim_fpu op1;
|
|
|
|
|
unsigned64 res;
|
|
|
|
|
|
|
|
|
|
sim_fpu_64to (&op1, x);
|
|
|
|
|
sim_fpu_to64i (&res, &op1, sim_fpu_round_near);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
1999-07-06 02:58:41 +02:00
|
|
|
|
static USI
|
2010-01-25 05:08:52 +01:00
|
|
|
|
ufixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
|
1999-07-06 02:58:41 +02:00
|
|
|
|
{
|
|
|
|
|
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;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_64to (&op1, x);
|
|
|
|
|
sim_fpu_64to (&op2, y);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_sub (&ans, &op1, &op2);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
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;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_64to (&op1, x);
|
|
|
|
|
sim_fpu_64to (&op2, y);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_mul (&ans, &op1, &op2);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
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;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_64to (&op1, x);
|
|
|
|
|
sim_fpu_64to (&op2, y);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_div (&ans, &op1, &op2);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
sim_fpu_to64 (&res, &ans);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-08 21:57:25 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
1999-07-06 02:58:41 +02:00
|
|
|
|
static DF
|
|
|
|
|
negdf (CGEN_FPU* fpu, DF x)
|
|
|
|
|
{
|
|
|
|
|
sim_fpu op1;
|
|
|
|
|
sim_fpu ans;
|
|
|
|
|
unsigned64 res;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_64to (&op1, x);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_neg (&ans, &op1);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
sim_fpu_to64 (&res, &ans);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DF
|
|
|
|
|
absdf (CGEN_FPU* fpu, DF x)
|
|
|
|
|
{
|
|
|
|
|
sim_fpu op1;
|
|
|
|
|
sim_fpu ans;
|
|
|
|
|
unsigned64 res;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_64to (&op1, x);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_abs (&ans, &op1);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
sim_fpu_to64 (&res, &ans);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DF
|
|
|
|
|
sqrtdf (CGEN_FPU* fpu, DF x)
|
|
|
|
|
{
|
|
|
|
|
sim_fpu op1;
|
|
|
|
|
sim_fpu ans;
|
|
|
|
|
unsigned64 res;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_64to (&op1, x);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_sqrt (&ans, &op1);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
sim_fpu_to64 (&res, &ans);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DF
|
|
|
|
|
invdf (CGEN_FPU* fpu, DF x)
|
|
|
|
|
{
|
|
|
|
|
sim_fpu op1;
|
|
|
|
|
sim_fpu ans;
|
|
|
|
|
unsigned64 res;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_64to (&op1, x);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_inv (&ans, &op1);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
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;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_64to (&op1, x);
|
|
|
|
|
sim_fpu_64to (&op2, y);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_min (&ans, &op1, &op2);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
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;
|
1999-12-07 04:56:43 +01:00
|
|
|
|
sim_fpu_status status;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
sim_fpu_64to (&op1, x);
|
|
|
|
|
sim_fpu_64to (&op2, y);
|
1999-12-07 04:56:43 +01:00
|
|
|
|
status = sim_fpu_max (&ans, &op1, &op2);
|
|
|
|
|
if (status != 0)
|
|
|
|
|
(*fpu->ops->error) (fpu, status);
|
1999-07-06 02:58:41 +02:00
|
|
|
|
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);
|
|
|
|
|
}
|
2019-06-13 14:27:10 +02:00
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
/* 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;
|
2017-12-08 21:57:25 +01:00
|
|
|
|
o->remsf = remsf;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
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;
|
2019-06-13 14:27:10 +02:00
|
|
|
|
o->unorderedsf = unorderedsf;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
|
|
|
|
|
o->adddf = adddf;
|
|
|
|
|
o->subdf = subdf;
|
|
|
|
|
o->muldf = muldf;
|
|
|
|
|
o->divdf = divdf;
|
2017-12-08 21:57:25 +01:00
|
|
|
|
o->remdf = remdf;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
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;
|
2019-06-13 14:27:10 +02:00
|
|
|
|
o->unordereddf = unordereddf;
|
2000-03-30 22:21:37 +02:00
|
|
|
|
o->fextsfdf = fextsfdf;
|
|
|
|
|
o->ftruncdfsf = ftruncdfsf;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
o->floatsisf = floatsisf;
|
1999-07-07 19:31:57 +02:00
|
|
|
|
o->floatsidf = floatsidf;
|
2019-06-13 14:27:10 +02:00
|
|
|
|
o->floatdidf = floatdidf;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
o->ufloatsisf = ufloatsisf;
|
|
|
|
|
o->fixsfsi = fixsfsi;
|
1999-07-07 19:31:57 +02:00
|
|
|
|
o->fixdfsi = fixdfsi;
|
2019-06-13 14:27:10 +02:00
|
|
|
|
o->fixdfdi = fixdfdi;
|
1999-07-06 02:58:41 +02:00
|
|
|
|
o->ufixsfsi = ufixsfsi;
|
|
|
|
|
}
|