This commit was manufactured by cvs2svn to create branch
[external/binutils.git] / sim / common / sim-fpu.h
index 4871006..72323f5 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
@@ -42,7 +42,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
    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
@@ -89,10 +89,9 @@ typedef enum
 
 typedef struct _sim_fpu {
   sim_fpu_class class;
-  int normal_exp;
-  int result;
   int sign;
   unsigned64 fraction;
+  int normal_exp;
 } sim_fpu;
 
 
@@ -116,6 +115,7 @@ typedef enum
 
 typedef enum
 {
+  sim_fpu_denorm_default = 0,
   sim_fpu_denorm_underflow_inexact = 1,
   sim_fpu_denorm_zero = 2,
 } sim_fpu_denorm;
@@ -164,9 +164,9 @@ typedef enum
    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);
@@ -177,16 +177,23 @@ INLINE_SIM_FPU (void) sim_fpu_to32 (unsigned32 *s, const sim_fpu *f);
 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.
@@ -203,11 +210,17 @@ INLINE_SIM_FPU (int) sim_fpu_round_64 (sim_fpu *f,
 
 
 
-/* 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,
@@ -216,6 +229,10 @@ INLINE_SIM_FPU (int) sim_fpu_mul (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,
@@ -237,10 +254,14 @@ INLINE_SIM_FPU (int) sim_fpu_i64to (sim_fpu *f, signed64 i,
                                    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);
@@ -250,16 +271,19 @@ INLINE_SIM_FPU (int) sim_fpu_to64i (signed64 *i, const sim_fpu *f,
                                    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);
@@ -271,11 +295,11 @@ INLINE_SIM_FPU (void) sim_fpu_d2 (sim_fpu *f, double 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 */
@@ -287,10 +311,18 @@ INLINE_SIM_FPU (int) sim_fpu_is_number (const sim_fpu *s); /* !zero */
 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);
@@ -322,7 +354,7 @@ INLINE_SIM_FPU (int) sim_fpu_is_gt (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 ] */
@@ -339,24 +371,54 @@ INLINE_SIM_FPU (int) sim_fpu_cmp (const sim_fpu *l, const sim_fpu *r);
 
 
 
-/* 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