| /* 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; | 
 |   uint32_t 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; | 
 |   uint32_t 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; | 
 |   uint32_t 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; | 
 |   uint32_t 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; | 
 |   uint32_t 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; | 
 |   uint32_t 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; | 
 |   uint32_t 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; | 
 |   uint32_t 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; | 
 |   uint32_t 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; | 
 |   uint32_t 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; | 
 |   uint32_t 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; | 
 |   uint64_t 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; | 
 |   uint32_t 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; | 
 |   uint32_t 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; | 
 |   uint64_t 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; | 
 |   uint64_t 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; | 
 |   uint32_t 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; | 
 |   int32_t 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; | 
 |   int32_t 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; | 
 |   int64_t 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; | 
 |   uint32_t 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; | 
 |   uint64_t 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; | 
 |   uint64_t 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; | 
 |   uint64_t 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; | 
 |   uint64_t 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; | 
 |   uint64_t 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; | 
 |   uint64_t 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; | 
 |   uint64_t 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; | 
 |   uint64_t 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; | 
 |   uint64_t 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; | 
 |   uint64_t 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; | 
 |   uint64_t 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; | 
 | } |