/* Simulator Floating-point support.
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GDB, the GNU debugger.
For unpacked structures (passed by value and reference), the code
quality of GCC-2.7 (on x86) for each alternative was compared.
- Needless to say the results, while better then for a packed 64 bit
+ Needless to say the results, while better than for a packed 64 bit
object, were still poor (GCC had only limited support for the
optimization of references to structure members). Regardless, the
struct-by-ref alternative achieved better results when compiled
typedef struct _sim_fpu {
sim_fpu_class class;
- int normal_exp;
- int result;
int sign;
unsigned64 fraction;
+ int normal_exp;
} sim_fpu;
typedef enum
{
+ sim_fpu_denorm_default = 0,
sim_fpu_denorm_underflow_inexact = 1,
sim_fpu_denorm_zero = 2,
} sim_fpu_denorm;
When converting from the sim_fpu internal type to 32/64 bit packed
format, the operation may result in a loss of precision. The
configuration macro WITH_FPU_CONVERSION controls this. By default,
- silent round to nearest is performed. Alternativly, round up,
+ silent round to nearest is performed. Alternatively, round up,
round down and round to zero can be performed. In a simulator
- emulating exact FPU behavour, sim_fpu_round_{32,64} should be
+ emulating exact FPU behavior, sim_fpu_round_{32,64} should be
called before packing the sim_fpu value. */
INLINE_SIM_FPU (void) sim_fpu_32to (sim_fpu *f, unsigned32 s);
INLINE_SIM_FPU (void) sim_fpu_to232 (unsigned32 *h, unsigned32 *l, const sim_fpu *f);
INLINE_SIM_FPU (void) sim_fpu_to64 (unsigned64 *d, const sim_fpu *f);
-#if WITH_TARGET_FLOATING_POINT_BITSIZE == 32
-#define sim_fpu_tofp sim_fpu_to32
-#define sim_fpu_fpto sim_fpu_32to
-#define sim_fpu_round_fp sim_fpu_round_32
-#endif
-#if WITH_TARGET_FLOATING_POINT_BITSIZE == 64
-#define sim_fpu_tofp sim_fpu_to64
-#define sim_fpu_fpto sim_fpu_64to
-#define sim_fpu_round_fp sim_fpu_round_64
-#endif
+
+/* Create a sim_fpu struct using raw information. (FRACTION & LSMASK
+ (PRECISION-1, 0)) is assumed to contain the fraction part of the
+ floating-point number. The leading bit LSBIT (PRECISION) is always
+ implied. The number created can be represented by:
+
+ (SIGN ? "-" : "+") "1." FRACTION{PRECISION-1,0} X 2 ^ NORMAL_EXP>
+
+ You can not specify zero using this function. */
+
+INLINE_SIM_FPU (void) sim_fpu_fractionto (sim_fpu *f, int sign, int normal_exp, unsigned64 fraction, int precision);
+
+/* Reverse operation. If S is a non-zero number, discards the implied
+ leading one and returns PRECISION fraction bits. No rounding is
+ performed. */
+INLINE_SIM_FPU (unsigned64) sim_fpu_tofraction (const sim_fpu *s, int precision);
+
/* Rounding operators.
-/* Arrithmetic operators.
+/* Arithmetic operators.
FIXME: In the future, additional arguments ROUNDING and BITSIZE may
be added. */
+typedef int (sim_fpu_op1) (sim_fpu *f,
+ const sim_fpu *l);
+typedef int (sim_fpu_op2) (sim_fpu *f,
+ const sim_fpu *l,
+ const sim_fpu *r);
+
INLINE_SIM_FPU (int) sim_fpu_add (sim_fpu *f,
const sim_fpu *l, const sim_fpu *r);
INLINE_SIM_FPU (int) sim_fpu_sub (sim_fpu *f,
const sim_fpu *l, const sim_fpu *r);
INLINE_SIM_FPU (int) sim_fpu_div (sim_fpu *f,
const sim_fpu *l, const sim_fpu *r);
+INLINE_SIM_FPU (int) sim_fpu_max (sim_fpu *f,
+ const sim_fpu *l, const sim_fpu *r);
+INLINE_SIM_FPU (int) sim_fpu_min (sim_fpu *f,
+ const sim_fpu *l, const sim_fpu *r);
INLINE_SIM_FPU (int) sim_fpu_neg (sim_fpu *f,
const sim_fpu *a);
INLINE_SIM_FPU (int) sim_fpu_abs (sim_fpu *f,
sim_fpu_round round);
INLINE_SIM_FPU (int) sim_fpu_u64to (sim_fpu *f, unsigned64 u,
sim_fpu_round round);
+#if 0
INLINE_SIM_FPU (int) sim_fpu_i232to (sim_fpu *f, signed32 h, signed32 l,
sim_fpu_round round);
+#endif
+#if 0
INLINE_SIM_FPU (int) sim_fpu_u232to (sim_fpu *f, unsigned32 h, unsigned32 l,
sim_fpu_round round);
+#endif
INLINE_SIM_FPU (int) sim_fpu_to32i (signed32 *i, const sim_fpu *f,
sim_fpu_round round);
sim_fpu_round round);
INLINE_SIM_FPU (int) sim_fpu_to64u (unsigned64 *u, const sim_fpu *f,
sim_fpu_round round);
+#if 0
INLINE_SIM_FPU (int) sim_fpu_to232i (signed64 *h, signed64 *l, const sim_fpu *f,
sim_fpu_round round);
+#endif
+#if 0
INLINE_SIM_FPU (int) sim_fpu_to232u (unsigned64 *h, unsigned64 *l, const sim_fpu *f,
sim_fpu_round round);
-
+#endif
/* Conversion of internal sim_fpu type to host double format.
- For debuging/tracing only. A SNaN is never returned. */
+ For debugging/tracing only. A SNaN is never returned. */
/* INLINE_SIM_FPU (float) sim_fpu_2f (const sim_fpu *f); */
INLINE_SIM_FPU (double) sim_fpu_2d (const sim_fpu *d);
/* Specific number classes.
- NB: When either a 32/64 bit floating points is converted to
+ NB: When either, a 32/64 bit floating points is converted to
internal format, or an internal format number is rounded to 32/64
bit precision, a special marker is retained that indicates that the
value was normalized. For such numbers both is_number and
- is_denorm will return true. */
+ is_denorm return true. */
INLINE_SIM_FPU (int) sim_fpu_is_nan (const sim_fpu *s); /* 1 => SNaN or QNaN */
INLINE_SIM_FPU (int) sim_fpu_is_snan (const sim_fpu *s); /* 1 => SNaN */
INLINE_SIM_FPU (int) sim_fpu_is_denorm (const sim_fpu *s); /* !zero */
+
+/* Floating point fields */
+
+INLINE_SIM_FPU (int) sim_fpu_sign (const sim_fpu *s);
+INLINE_SIM_FPU (int) sim_fpu_exp (const sim_fpu *s);
+
+
+
/* Specific comparison operators
- The comparison operators set *IS to zero and return a nonzero
- result for NaNs et.al. */
+ For NaNs et al., the comparison operators will set IS to zero and
+ return a nonzero result. */
INLINE_SIM_FPU (int) sim_fpu_lt (int *is, const sim_fpu *l, const sim_fpu *r);
INLINE_SIM_FPU (int) sim_fpu_le (int *is, const sim_fpu *l, const sim_fpu *r);
#ifndef SIM_FPU_IS_SNAN
enum {
SIM_FPU_IS_SNAN = 1, /* Noisy not-a-number */
- SIM_FPU_IS_QNAN = 2, /* Quite not-a-number */
+ SIM_FPU_IS_QNAN = 2, /* Quiet not-a-number */
SIM_FPU_IS_NINF = 3, /* -infinity */
SIM_FPU_IS_PINF = 4, /* +infinity */
SIM_FPU_IS_NNUMBER = 5, /* -number - [ -MAX .. -MIN ] */
-/* A constant of useful numbers */
+/* A number of useful constants. */
extern const sim_fpu sim_fpu_zero;
extern const sim_fpu sim_fpu_one;
extern const sim_fpu sim_fpu_two;
extern const sim_fpu sim_fpu_qnan;
+extern const sim_fpu sim_fpu_max32;
+extern const sim_fpu sim_fpu_max64;
+
+
+/* Select the applicable functions for the fp_word type */
+
+#if WITH_TARGET_FLOATING_POINT_BITSIZE == 32
+#define sim_fpu_tofp sim_fpu_to32
+#define sim_fpu_fpto sim_fpu_32to
+#define sim_fpu_round_fp sim_fpu_round_32
+#define sim_fpu_maxfp sim_fpu_max32
+#endif
+#if WITH_TARGET_FLOATING_POINT_BITSIZE == 64
+#define sim_fpu_tofp sim_fpu_to64
+#define sim_fpu_fpto sim_fpu_64to
+#define sim_fpu_round_fp sim_fpu_round_64
+#define sim_fpu_maxfp sim_fpu_max64
+#endif
+
/* For debugging */
typedef void sim_fpu_print_func (void *, char *, ...);
+/* Print a sim_fpu with full precision. */
INLINE_SIM_FPU (void) sim_fpu_print_fpu (const sim_fpu *f,
sim_fpu_print_func *print,
void *arg);
+/* Print a sim_fpu with `n' trailing digits. */
+INLINE_SIM_FPU (void) sim_fpu_printn_fpu (const sim_fpu *f,
+ sim_fpu_print_func *print,
+ int digits,
+ void *arg);
+
INLINE_SIM_FPU (void) sim_fpu_print_status (int status,
sim_fpu_print_func *print,
void *arg);
+#if H_REVEALS_MODULE_P (SIM_FPU_INLINE)
+#include "sim-fpu.c"
+#endif
+
#endif