2002-03-19 Chris G. Demetriou <cgd@broadcom.com>
authorChris Demetriou <cgd@google.com>
Wed, 20 Mar 2002 01:35:13 +0000 (01:35 +0000)
committerChris Demetriou <cgd@google.com>
Wed, 20 Mar 2002 01:35:13 +0000 (01:35 +0000)
        * interp.c: Move FPU support routines from here to...
        * cp1.c: Here.  New file.
        * Makefile.in (SIM_OBJS): Add cp1.o to object list.
        (cp1.o): New target.

sim/mips/ChangeLog
sim/mips/Makefile.in
sim/mips/cp1.c [new file with mode: 0644]
sim/mips/interp.c

index 433052c8b1e44865b10bc36944fa46cb23e777a9..33dc00fe068d99b3f63740a4df771b6af5a1dd2c 100644 (file)
@@ -1,3 +1,10 @@
+2002-03-19  Chris G. Demetriou  <cgd@broadcom.com>
+
+       * interp.c: Move FPU support routines from here to...
+       * cp1.c: Here.  New file.
+       * Makefile.in (SIM_OBJS): Add cp1.o to object list.
+       (cp1.o): New target.
+
 2002-03-12  Chris Demetriou  <cgd@broadcom.com>
 
        * configure.in (mipsisa32*-*-*, mipsisa64*-*-*): New targets.
index 98831755e36a605f90645a4963d746e762f05fc4..5d0a3364e8fc8ccb8694b249fcbcde8baab52246 100644 (file)
@@ -41,6 +41,7 @@ SIM_OBJS = \
        $(SIM_@sim_gen@_OBJ) \
        $(SIM_NEW_COMMON_OBJS) \
        $(MIPS_EXTRA_OBJS) \
+       cp1.o \
        interp.o \
        sim-main.o \
        sim-hload.o \
@@ -68,6 +69,7 @@ SIM_RUN_OBJS = nrun.o
 ## COMMON_POST_CONFIG_FRAG
 
 interp.o: $(srcdir)/interp.c config.h sim-main.h itable.h
+cp1.o: $(srcdir)/cp1.c config.h sim-main.h
 
 
 ../igen/igen:
diff --git a/sim/mips/cp1.c b/sim/mips/cp1.c
new file mode 100644 (file)
index 0000000..66ae508
--- /dev/null
@@ -0,0 +1,1095 @@
+/*> cp1.c <*/
+/* Floating Point Support for gdb MIPS simulators
+
+   This file is part of the MIPS sim
+
+               THIS SOFTWARE IS NOT COPYRIGHTED
+
+   Cygnus offers the following for use in the public domain.  Cygnus
+   makes no warranty with regard to the software or it's performance
+   and the user accepts the software "AS IS" with all faults.
+
+   CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
+   THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+   (Originally, this code was in interp.c)
+*/
+
+#include "sim-main.h"
+#include "sim-fpu.h"
+
+/* Within cp1.c we refer to sim_cpu directly.  */
+#define CPU cpu
+#define SD sd
+
+/*-- FPU support routines ---------------------------------------------------*/
+
+/* Numbers are held in normalized form. The SINGLE and DOUBLE binary
+   formats conform to ANSI/IEEE Std 754-1985. */
+/* SINGLE precision floating:
+ *    seeeeeeeefffffffffffffffffffffff
+ *      s =  1bit  = sign
+ *      e =  8bits = exponent
+ *      f = 23bits = fraction
+ */
+/* SINGLE precision fixed:
+ *    siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
+ *      s =  1bit  = sign
+ *      i = 31bits = integer
+ */
+/* DOUBLE precision floating:
+ *    seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
+ *      s =  1bit  = sign
+ *      e = 11bits = exponent
+ *      f = 52bits = fraction
+ */
+/* DOUBLE precision fixed:
+ *    siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
+ *      s =  1bit  = sign
+ *      i = 63bits = integer
+ */
+
+/* Extract sign-bit: */
+#define FP_S_s(v)    (((v) & ((unsigned)1 << 31)) ? 1 : 0)
+#define FP_D_s(v)    (((v) & ((uword64)1 << 63)) ? 1 : 0)
+/* Extract biased exponent: */
+#define FP_S_be(v)   (((v) >> 23) & 0xFF)
+#define FP_D_be(v)   (((v) >> 52) & 0x7FF)
+/* Extract unbiased Exponent: */
+#define FP_S_e(v)    (FP_S_be(v) - 0x7F)
+#define FP_D_e(v)    (FP_D_be(v) - 0x3FF)
+/* Extract complete fraction field: */
+#define FP_S_f(v)    ((v) & ~((unsigned)0x1FF << 23))
+#define FP_D_f(v)    ((v) & ~((uword64)0xFFF << 52))
+/* Extract numbered fraction bit: */
+#define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0)
+#define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0)
+
+/* Explicit QNaN values used when value required: */
+#define FPQNaN_SINGLE   (0x7FBFFFFF)
+#define FPQNaN_WORD     (0x7FFFFFFF)
+#define FPQNaN_DOUBLE   (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
+#define FPQNaN_LONG     (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
+
+/* Explicit Infinity values used when required: */
+#define FPINF_SINGLE    (0x7F800000)
+#define FPINF_DOUBLE    (((uword64)0x7FF00000 << 32) | 0x00000000)
+
+#define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor")))
+#define DOFMT(v)  (((v) == fmt_single) ? "single" : (((v) == fmt_double) ? "double" : (((v) == fmt_word) ? "word" : (((v) == fmt_long) ? "long" : (((v) == fmt_unknown) ? "<unknown>" : (((v) == fmt_uninterpreted) ? "<uninterpreted>" : (((v) == fmt_uninterpreted_32) ? "<uninterpreted_32>" : (((v) == fmt_uninterpreted_64) ? "<uninterpreted_64>" : "<format error>"))))))))
+
+uword64
+value_fpr (SIM_DESC sd,
+          sim_cpu *cpu,
+          address_word cia,
+          int fpr,
+          FP_formats fmt)
+{
+  uword64 value = 0;
+  int err = 0;
+
+  /* Treat unused register values, as fixed-point 64bit values: */
+  if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
+#if 1
+   /* If request to read data as "uninterpreted", then use the current
+      encoding: */
+   fmt = FPR_STATE[fpr];
+#else
+   fmt = fmt_long;
+#endif
+
+  /* For values not yet accessed, set to the desired format: */
+  if (FPR_STATE[fpr] == fmt_uninterpreted) {
+    FPR_STATE[fpr] = fmt;
+#ifdef DEBUG
+    printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt));
+#endif /* DEBUG */
+  }
+  if (fmt != FPR_STATE[fpr]) {
+    sim_io_eprintf(sd,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr,DOFMT(FPR_STATE[fpr]),DOFMT(fmt),pr_addr(cia));
+    FPR_STATE[fpr] = fmt_unknown;
+  }
+
+  if (FPR_STATE[fpr] == fmt_unknown) {
+   /* Set QNaN value: */
+   switch (fmt) {
+    case fmt_single:
+     value = FPQNaN_SINGLE;
+     break;
+
+    case fmt_double:
+     value = FPQNaN_DOUBLE;
+     break;
+
+    case fmt_word:
+     value = FPQNaN_WORD;
+     break;
+
+    case fmt_long:
+     value = FPQNaN_LONG;
+     break;
+
+    default:
+     err = -1;
+     break;
+   }
+  } else if (SizeFGR() == 64) {
+    switch (fmt) {
+     case fmt_single:
+     case fmt_word:
+      value = (FGR[fpr] & 0xFFFFFFFF);
+      break;
+
+     case fmt_uninterpreted:
+     case fmt_double:
+     case fmt_long:
+      value = FGR[fpr];
+      break;
+
+     default :
+      err = -1;
+      break;
+    }
+  } else {
+    switch (fmt) {
+     case fmt_single:
+     case fmt_word:
+      value = (FGR[fpr] & 0xFFFFFFFF);
+      break;
+
+     case fmt_uninterpreted:
+     case fmt_double:
+     case fmt_long:
+      if ((fpr & 1) == 0) { /* even registers only */
+#ifdef DEBUG
+       printf("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n", 
+              fpr+1, pr_uword64( (uword64) FGR[fpr+1] ),
+              fpr, pr_uword64( (uword64) FGR[fpr] ));
+#endif
+       value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF));
+      } else {
+       SignalException(ReservedInstruction,0);
+      }
+      break;
+
+     default :
+      err = -1;
+      break;
+    }
+  }
+
+  if (err)
+   SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()");
+
+#ifdef DEBUG
+  printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_uword64(value),pr_addr(cia),SizeFGR());
+#endif /* DEBUG */
+
+  return(value);
+}
+
+void
+store_fpr (SIM_DESC sd,
+          sim_cpu *cpu,
+          address_word cia,
+          int fpr,
+          FP_formats fmt,
+          uword64 value)
+{
+  int err = 0;
+
+#ifdef DEBUG
+  printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d,\n",fpr,DOFMT(fmt),pr_uword64(value),pr_addr(cia),SizeFGR());
+#endif /* DEBUG */
+
+  if (SizeFGR() == 64) {
+    switch (fmt) {
+      case fmt_uninterpreted_32:
+       fmt = fmt_uninterpreted;
+      case fmt_single :
+      case fmt_word :
+       if (STATE_VERBOSE_P(SD))
+         sim_io_eprintf (SD, "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
+          pr_addr(cia));
+       FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
+       FPR_STATE[fpr] = fmt;
+       break;
+
+      case fmt_uninterpreted_64:
+       fmt = fmt_uninterpreted;
+      case fmt_uninterpreted:
+      case fmt_double :
+      case fmt_long :
+       FGR[fpr] = value;
+       FPR_STATE[fpr] = fmt;
+       break;
+
+      default :
+       FPR_STATE[fpr] = fmt_unknown;
+       err = -1;
+       break;
+    }
+  } else {
+    switch (fmt) {
+      case fmt_uninterpreted_32:
+       fmt = fmt_uninterpreted;
+      case fmt_single :
+      case fmt_word :
+       FGR[fpr] = (value & 0xFFFFFFFF);
+       FPR_STATE[fpr] = fmt;
+       break;
+
+      case fmt_uninterpreted_64:
+       fmt = fmt_uninterpreted;
+      case fmt_uninterpreted:
+      case fmt_double :
+      case fmt_long :
+       if ((fpr & 1) == 0) { /* even register number only */
+         FGR[fpr+1] = (value >> 32);
+         FGR[fpr] = (value & 0xFFFFFFFF);
+         FPR_STATE[fpr + 1] = fmt;
+         FPR_STATE[fpr] = fmt;
+       } else {
+         FPR_STATE[fpr] = fmt_unknown;
+         FPR_STATE[fpr + 1] = fmt_unknown;
+         SignalException(ReservedInstruction,0);
+       }
+       break;
+
+      default :
+       FPR_STATE[fpr] = fmt_unknown;
+       err = -1;
+       break;
+    }
+  }
+#if defined(WARN_RESULT)
+  else
+    UndefinedResult();
+#endif /* WARN_RESULT */
+
+  if (err)
+   SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR()");
+
+#ifdef DEBUG
+  printf("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",fpr,pr_uword64(FGR[fpr]),DOFMT(fmt));
+#endif /* DEBUG */
+
+  return;
+}
+
+int
+NaN(op,fmt)
+     uword64 op;
+     FP_formats fmt; 
+{
+  int boolean = 0;
+  switch (fmt) {
+   case fmt_single:
+   case fmt_word:
+    {
+      sim_fpu wop;
+      sim_fpu_32to (&wop, op);
+      boolean = sim_fpu_is_nan (&wop);
+      break;
+    }
+   case fmt_double:
+   case fmt_long:
+    {
+      sim_fpu wop;
+      sim_fpu_64to (&wop, op);
+      boolean = sim_fpu_is_nan (&wop);
+      break;
+    }
+   default:
+    fprintf (stderr, "Bad switch\n");
+    abort ();
+  }
+
+#ifdef DEBUG
+printf("DBG: NaN: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt));
+#endif /* DEBUG */
+
+  return(boolean);
+}
+
+int
+Infinity(op,fmt)
+     uword64 op;
+     FP_formats fmt; 
+{
+  int boolean = 0;
+
+#ifdef DEBUG
+  printf("DBG: Infinity: format %s 0x%s\n",DOFMT(fmt),pr_addr(op));
+#endif /* DEBUG */
+
+  switch (fmt) {
+   case fmt_single:
+    {
+      sim_fpu wop;
+      sim_fpu_32to (&wop, op);
+      boolean = sim_fpu_is_infinity (&wop);
+      break;
+    }
+   case fmt_double:
+    {
+      sim_fpu wop;
+      sim_fpu_64to (&wop, op);
+      boolean = sim_fpu_is_infinity (&wop);
+      break;
+    }
+   default:
+    printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt));
+    break;
+  }
+
+#ifdef DEBUG
+  printf("DBG: Infinity: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt));
+#endif /* DEBUG */
+
+  return(boolean);
+}
+
+int
+Less(op1,op2,fmt)
+     uword64 op1;
+     uword64 op2;
+     FP_formats fmt; 
+{
+  int boolean = 0;
+
+  /* Argument checking already performed by the FPCOMPARE code */
+
+#ifdef DEBUG
+  printf("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
+#endif /* DEBUG */
+
+  /* The format type should already have been checked: */
+  switch (fmt) {
+   case fmt_single:
+    {
+      sim_fpu wop1;
+      sim_fpu wop2;
+      sim_fpu_32to (&wop1, op1);
+      sim_fpu_32to (&wop2, op2);
+      boolean = sim_fpu_is_lt (&wop1, &wop2);
+      break;
+    }
+   case fmt_double:
+    {
+      sim_fpu wop1;
+      sim_fpu wop2;
+      sim_fpu_64to (&wop1, op1);
+      sim_fpu_64to (&wop2, op2);
+      boolean = sim_fpu_is_lt (&wop1, &wop2);
+      break;
+    }
+   default:
+    fprintf (stderr, "Bad switch\n");
+    abort ();
+  }
+
+#ifdef DEBUG
+  printf("DBG: Less: returning %d (format = %s)\n",boolean,DOFMT(fmt));
+#endif /* DEBUG */
+
+  return(boolean);
+}
+
+int
+Equal(op1,op2,fmt)
+     uword64 op1;
+     uword64 op2;
+     FP_formats fmt; 
+{
+  int boolean = 0;
+
+  /* Argument checking already performed by the FPCOMPARE code */
+
+#ifdef DEBUG
+  printf("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
+#endif /* DEBUG */
+
+  /* The format type should already have been checked: */
+  switch (fmt) {
+   case fmt_single:
+    {
+      sim_fpu wop1;
+      sim_fpu wop2;
+      sim_fpu_32to (&wop1, op1);
+      sim_fpu_32to (&wop2, op2);
+      boolean = sim_fpu_is_eq (&wop1, &wop2);
+      break;
+    }
+   case fmt_double:
+    {
+      sim_fpu wop1;
+      sim_fpu wop2;
+      sim_fpu_64to (&wop1, op1);
+      sim_fpu_64to (&wop2, op2);
+      boolean = sim_fpu_is_eq (&wop1, &wop2);
+      break;
+    }
+   default:
+    fprintf (stderr, "Bad switch\n");
+    abort ();
+  }
+
+#ifdef DEBUG
+  printf("DBG: Equal: returning %d (format = %s)\n",boolean,DOFMT(fmt));
+#endif /* DEBUG */
+
+  return(boolean);
+}
+
+uword64
+AbsoluteValue(op,fmt)
+     uword64 op;
+     FP_formats fmt; 
+{
+  uword64 result = 0;
+
+#ifdef DEBUG
+  printf("DBG: AbsoluteValue: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
+#endif /* DEBUG */
+
+  /* The format type should already have been checked: */
+  switch (fmt) {
+   case fmt_single:
+    {
+      sim_fpu wop;
+      unsigned32 ans;
+      sim_fpu_32to (&wop, op);
+      sim_fpu_abs (&wop, &wop);
+      sim_fpu_to32 (&ans, &wop);
+      result = ans;
+      break;
+    }
+   case fmt_double:
+    {
+      sim_fpu wop;
+      unsigned64 ans;
+      sim_fpu_64to (&wop, op);
+      sim_fpu_abs (&wop, &wop);
+      sim_fpu_to64 (&ans, &wop);
+      result = ans;
+      break;
+    }
+   default:
+    fprintf (stderr, "Bad switch\n");
+    abort ();
+  }
+
+  return(result);
+}
+
+uword64
+Negate(op,fmt)
+     uword64 op;
+     FP_formats fmt; 
+{
+  uword64 result = 0;
+
+#ifdef DEBUG
+  printf("DBG: Negate: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
+#endif /* DEBUG */
+
+  /* The format type should already have been checked: */
+  switch (fmt) {
+   case fmt_single:
+    {
+      sim_fpu wop;
+      unsigned32 ans;
+      sim_fpu_32to (&wop, op);
+      sim_fpu_neg (&wop, &wop);
+      sim_fpu_to32 (&ans, &wop);
+      result = ans;
+      break;
+    }
+   case fmt_double:
+    {
+      sim_fpu wop;
+      unsigned64 ans;
+      sim_fpu_64to (&wop, op);
+      sim_fpu_neg (&wop, &wop);
+      sim_fpu_to64 (&ans, &wop);
+      result = ans;
+      break;
+    }
+   default:
+    fprintf (stderr, "Bad switch\n");
+    abort ();
+  }
+
+  return(result);
+}
+
+uword64
+Add(op1,op2,fmt)
+     uword64 op1;
+     uword64 op2;
+     FP_formats fmt; 
+{
+  uword64 result = 0;
+
+#ifdef DEBUG
+  printf("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
+#endif /* DEBUG */
+
+  /* The registers must specify FPRs valid for operands of type
+     "fmt". If they are not valid, the result is undefined. */
+
+  /* The format type should already have been checked: */
+  switch (fmt) {
+   case fmt_single:
+    {
+      sim_fpu wop1;
+      sim_fpu wop2;
+      sim_fpu ans;
+      unsigned32 res;
+      sim_fpu_32to (&wop1, op1);
+      sim_fpu_32to (&wop2, op2);
+      sim_fpu_add (&ans, &wop1, &wop2);
+      sim_fpu_to32 (&res, &ans);
+      result = res;
+      break;
+    }
+   case fmt_double:
+    {
+      sim_fpu wop1;
+      sim_fpu wop2;
+      sim_fpu ans;
+      unsigned64 res;
+      sim_fpu_64to (&wop1, op1);
+      sim_fpu_64to (&wop2, op2);
+      sim_fpu_add (&ans, &wop1, &wop2);
+      sim_fpu_to64 (&res, &ans);
+      result = res;
+      break;
+    }
+   default:
+    fprintf (stderr, "Bad switch\n");
+    abort ();
+  }
+
+#ifdef DEBUG
+  printf("DBG: Add: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
+#endif /* DEBUG */
+
+  return(result);
+}
+
+uword64
+Sub(op1,op2,fmt)
+     uword64 op1;
+     uword64 op2;
+     FP_formats fmt; 
+{
+  uword64 result = 0;
+
+#ifdef DEBUG
+  printf("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
+#endif /* DEBUG */
+
+  /* The registers must specify FPRs valid for operands of type
+     "fmt". If they are not valid, the result is undefined. */
+
+  /* The format type should already have been checked: */
+  switch (fmt) {
+   case fmt_single:
+    {
+      sim_fpu wop1;
+      sim_fpu wop2;
+      sim_fpu ans;
+      unsigned32 res;
+      sim_fpu_32to (&wop1, op1);
+      sim_fpu_32to (&wop2, op2);
+      sim_fpu_sub (&ans, &wop1, &wop2);
+      sim_fpu_to32 (&res, &ans);
+      result = res;
+    }
+    break;
+   case fmt_double:
+    {
+      sim_fpu wop1;
+      sim_fpu wop2;
+      sim_fpu ans;
+      unsigned64 res;
+      sim_fpu_64to (&wop1, op1);
+      sim_fpu_64to (&wop2, op2);
+      sim_fpu_sub (&ans, &wop1, &wop2);
+      sim_fpu_to64 (&res, &ans);
+      result = res;
+    }
+    break;
+   default:
+    fprintf (stderr, "Bad switch\n");
+    abort ();
+  }
+
+#ifdef DEBUG
+  printf("DBG: Sub: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
+#endif /* DEBUG */
+
+  return(result);
+}
+
+uword64
+Multiply(op1,op2,fmt)
+     uword64 op1;
+     uword64 op2;
+     FP_formats fmt; 
+{
+  uword64 result = 0;
+
+#ifdef DEBUG
+  printf("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
+#endif /* DEBUG */
+
+  /* The registers must specify FPRs valid for operands of type
+     "fmt". If they are not valid, the result is undefined. */
+
+  /* The format type should already have been checked: */
+  switch (fmt) {
+   case fmt_single:
+    {
+      sim_fpu wop1;
+      sim_fpu wop2;
+      sim_fpu ans;
+      unsigned32 res;
+      sim_fpu_32to (&wop1, op1);
+      sim_fpu_32to (&wop2, op2);
+      sim_fpu_mul (&ans, &wop1, &wop2);
+      sim_fpu_to32 (&res, &ans);
+      result = res;
+      break;
+    }
+   case fmt_double:
+    {
+      sim_fpu wop1;
+      sim_fpu wop2;
+      sim_fpu ans;
+      unsigned64 res;
+      sim_fpu_64to (&wop1, op1);
+      sim_fpu_64to (&wop2, op2);
+      sim_fpu_mul (&ans, &wop1, &wop2);
+      sim_fpu_to64 (&res, &ans);
+      result = res;
+      break;
+    }
+   default:
+    fprintf (stderr, "Bad switch\n");
+    abort ();
+  }
+
+#ifdef DEBUG
+  printf("DBG: Multiply: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
+#endif /* DEBUG */
+
+  return(result);
+}
+
+uword64
+Divide(op1,op2,fmt)
+     uword64 op1;
+     uword64 op2;
+     FP_formats fmt; 
+{
+  uword64 result = 0;
+
+#ifdef DEBUG
+  printf("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
+#endif /* DEBUG */
+
+  /* The registers must specify FPRs valid for operands of type
+     "fmt". If they are not valid, the result is undefined. */
+
+  /* The format type should already have been checked: */
+  switch (fmt) {
+   case fmt_single:
+    {
+      sim_fpu wop1;
+      sim_fpu wop2;
+      sim_fpu ans;
+      unsigned32 res;
+      sim_fpu_32to (&wop1, op1);
+      sim_fpu_32to (&wop2, op2);
+      sim_fpu_div (&ans, &wop1, &wop2);
+      sim_fpu_to32 (&res, &ans);
+      result = res;
+      break;
+    }
+   case fmt_double:
+    {
+      sim_fpu wop1;
+      sim_fpu wop2;
+      sim_fpu ans;
+      unsigned64 res;
+      sim_fpu_64to (&wop1, op1);
+      sim_fpu_64to (&wop2, op2);
+      sim_fpu_div (&ans, &wop1, &wop2);
+      sim_fpu_to64 (&res, &ans);
+      result = res;
+      break;
+    }
+   default:
+    fprintf (stderr, "Bad switch\n");
+    abort ();
+  }
+
+#ifdef DEBUG
+  printf("DBG: Divide: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
+#endif /* DEBUG */
+
+  return(result);
+}
+
+uword64 UNUSED
+Recip(op,fmt)
+     uword64 op;
+     FP_formats fmt; 
+{
+  uword64 result = 0;
+
+#ifdef DEBUG
+  printf("DBG: Recip: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
+#endif /* DEBUG */
+
+  /* The registers must specify FPRs valid for operands of type
+     "fmt". If they are not valid, the result is undefined. */
+
+  /* The format type should already have been checked: */
+  switch (fmt) {
+   case fmt_single:
+    {
+      sim_fpu wop;
+      sim_fpu ans;
+      unsigned32 res;
+      sim_fpu_32to (&wop, op);
+      sim_fpu_inv (&ans, &wop);
+      sim_fpu_to32 (&res, &ans);
+      result = res;
+      break;
+    }
+   case fmt_double:
+    {
+      sim_fpu wop;
+      sim_fpu ans;
+      unsigned64 res;
+      sim_fpu_64to (&wop, op);
+      sim_fpu_inv (&ans, &wop);
+      sim_fpu_to64 (&res, &ans);
+      result = res;
+      break;
+    }
+   default:
+    fprintf (stderr, "Bad switch\n");
+    abort ();
+  }
+
+#ifdef DEBUG
+  printf("DBG: Recip: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
+#endif /* DEBUG */
+
+  return(result);
+}
+
+uword64
+SquareRoot(op,fmt)
+     uword64 op;
+     FP_formats fmt; 
+{
+  uword64 result = 0;
+
+#ifdef DEBUG
+  printf("DBG: SquareRoot: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
+#endif /* DEBUG */
+
+  /* The registers must specify FPRs valid for operands of type
+     "fmt". If they are not valid, the result is undefined. */
+
+  /* The format type should already have been checked: */
+  switch (fmt) {
+   case fmt_single:
+    {
+      sim_fpu wop;
+      sim_fpu ans;
+      unsigned32 res;
+      sim_fpu_32to (&wop, op);
+      sim_fpu_sqrt (&ans, &wop);
+      sim_fpu_to32 (&res, &ans);
+      result = res;
+      break;
+    }
+   case fmt_double:
+    {
+      sim_fpu wop;
+      sim_fpu ans;
+      unsigned64 res;
+      sim_fpu_64to (&wop, op);
+      sim_fpu_sqrt (&ans, &wop);
+      sim_fpu_to64 (&res, &ans);
+      result = res;
+      break;
+    }
+   default:
+    fprintf (stderr, "Bad switch\n");
+    abort ();
+  }
+
+#ifdef DEBUG
+  printf("DBG: SquareRoot: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
+#endif /* DEBUG */
+
+  return(result);
+}
+
+#if 0
+uword64
+Max (uword64 op1,
+     uword64 op2,
+     FP_formats fmt)
+{
+  int cmp;
+  unsigned64 result;
+
+#ifdef DEBUG
+  printf("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
+#endif /* DEBUG */
+
+  /* The registers must specify FPRs valid for operands of type
+     "fmt". If they are not valid, the result is undefined. */
+
+  /* The format type should already have been checked: */
+  switch (fmt)
+    {
+    case fmt_single:
+      {
+       sim_fpu wop1;
+       sim_fpu wop2;
+       sim_fpu_32to (&wop1, op1);
+       sim_fpu_32to (&wop2, op2);
+       cmp = sim_fpu_cmp (&wop1, &wop2);
+       break;
+      }
+    case fmt_double:
+      {
+       sim_fpu wop1;
+       sim_fpu wop2;
+       sim_fpu_64to (&wop1, op1);
+       sim_fpu_64to (&wop2, op2);
+       cmp = sim_fpu_cmp (&wop1, &wop2);
+       break;
+      }
+    default:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+  
+  switch (cmp)
+    {
+    case SIM_FPU_IS_SNAN:
+    case SIM_FPU_IS_QNAN:
+      result = op1;
+    case SIM_FPU_IS_NINF:
+    case SIM_FPU_IS_NNUMBER:
+    case SIM_FPU_IS_NDENORM:
+    case SIM_FPU_IS_NZERO:
+      result = op2; /* op1 - op2 < 0 */
+    case SIM_FPU_IS_PINF:
+    case SIM_FPU_IS_PNUMBER:
+    case SIM_FPU_IS_PDENORM:
+    case SIM_FPU_IS_PZERO:
+      result = op1; /* op1 - op2 > 0 */
+    default:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+
+#ifdef DEBUG
+  printf("DBG: Max: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
+#endif /* DEBUG */
+
+  return(result);
+}
+#endif 
+
+#if 0
+uword64
+Min (uword64 op1,
+     uword64 op2,
+     FP_formats fmt)
+{
+  int cmp;
+  unsigned64 result;
+
+#ifdef DEBUG
+  printf("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
+#endif /* DEBUG */
+
+  /* The registers must specify FPRs valid for operands of type
+     "fmt". If they are not valid, the result is undefined. */
+
+  /* The format type should already have been checked: */
+  switch (fmt)
+    {
+    case fmt_single:
+      {
+       sim_fpu wop1;
+       sim_fpu wop2;
+       sim_fpu_32to (&wop1, op1);
+       sim_fpu_32to (&wop2, op2);
+       cmp = sim_fpu_cmp (&wop1, &wop2);
+       break;
+      }
+    case fmt_double:
+      {
+       sim_fpu wop1;
+       sim_fpu wop2;
+       sim_fpu_64to (&wop1, op1);
+       sim_fpu_64to (&wop2, op2);
+       cmp = sim_fpu_cmp (&wop1, &wop2);
+       break;
+      }
+    default:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+  
+  switch (cmp)
+    {
+    case SIM_FPU_IS_SNAN:
+    case SIM_FPU_IS_QNAN:
+      result = op1;
+    case SIM_FPU_IS_NINF:
+    case SIM_FPU_IS_NNUMBER:
+    case SIM_FPU_IS_NDENORM:
+    case SIM_FPU_IS_NZERO:
+      result = op1; /* op1 - op2 < 0 */
+    case SIM_FPU_IS_PINF:
+    case SIM_FPU_IS_PNUMBER:
+    case SIM_FPU_IS_PDENORM:
+    case SIM_FPU_IS_PZERO:
+      result = op2; /* op1 - op2 > 0 */
+    default:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+
+#ifdef DEBUG
+  printf("DBG: Min: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
+#endif /* DEBUG */
+
+  return(result);
+}
+#endif
+
+uword64
+convert (SIM_DESC sd,
+        sim_cpu *cpu,
+        address_word cia,
+        int rm,
+        uword64 op,
+        FP_formats from,
+        FP_formats to)
+{
+  sim_fpu wop;
+  sim_fpu_round round;
+  unsigned32 result32;
+  unsigned64 result64;
+
+#ifdef DEBUG
+#if 0 /* FIXME: doesn't compile */
+  printf("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",RMMODE(rm),pr_addr(op),DOFMT(from),DOFMT(to),pr_addr(IPC));
+#endif
+#endif /* DEBUG */
+
+  switch (rm)
+    {
+    case FP_RM_NEAREST:
+      /* Round result to nearest representable value. When two
+        representable values are equally near, round to the value
+        that has a least significant bit of zero (i.e. is even). */
+      round = sim_fpu_round_near;
+      break;
+    case FP_RM_TOZERO:
+      /* Round result to the value closest to, and not greater in
+        magnitude than, the result. */
+      round = sim_fpu_round_zero;
+      break;
+    case FP_RM_TOPINF:
+      /* Round result to the value closest to, and not less than,
+        the result. */
+      round = sim_fpu_round_up;
+      break;
+      
+    case FP_RM_TOMINF:
+      /* Round result to the value closest to, and not greater than,
+        the result. */
+      round = sim_fpu_round_down;
+      break;
+    default:
+      round = 0;
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+  
+  /* Convert the input to sim_fpu internal format */
+  switch (from)
+    {
+    case fmt_double:
+      sim_fpu_64to (&wop, op);
+      break;
+    case fmt_single:
+      sim_fpu_32to (&wop, op);
+      break;
+    case fmt_word:
+      sim_fpu_i32to (&wop, op, round);
+      break;
+    case fmt_long:
+      sim_fpu_i64to (&wop, op, round);
+      break;
+    default:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+
+  /* Convert sim_fpu format into the output */
+  /* The value WOP is converted to the destination format, rounding
+     using mode RM. When the destination is a fixed-point format, then
+     a source value of Infinity, NaN or one which would round to an
+     integer outside the fixed point range then an IEEE Invalid
+     Operation condition is raised. */
+  switch (to)
+    {
+    case fmt_single:
+      sim_fpu_round_32 (&wop, round, 0);
+      sim_fpu_to32 (&result32, &wop);
+      result64 = result32;
+      break;
+    case fmt_double:
+      sim_fpu_round_64 (&wop, round, 0);
+      sim_fpu_to64 (&result64, &wop);
+      break;
+    case fmt_word:
+      sim_fpu_to32i (&result32, &wop, round);
+      result64 = result32;
+      break;
+    case fmt_long:
+      sim_fpu_to64i (&result64, &wop, round);
+      break;
+    default:
+      result64 = 0;
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+#ifdef DEBUG
+  printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result64),DOFMT(to));
+#endif /* DEBUG */
+
+  return(result64);
+}
+
+
index 3e31ce46a71abf59189431db4f79839b7b5f37a1..5bd61a8a824e32b72f23d82307d2154676a5e8c3 100644 (file)
@@ -1892,1075 +1892,6 @@ undefined_result(sd,cia)
 }
 #endif /* WARN_RESULT */
 
-/*-- FPU support routines ---------------------------------------------------*/
-
-/* Numbers are held in normalized form. The SINGLE and DOUBLE binary
-   formats conform to ANSI/IEEE Std 754-1985. */
-/* SINGLE precision floating:
- *    seeeeeeeefffffffffffffffffffffff
- *      s =  1bit  = sign
- *      e =  8bits = exponent
- *      f = 23bits = fraction
- */
-/* SINGLE precision fixed:
- *    siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
- *      s =  1bit  = sign
- *      i = 31bits = integer
- */
-/* DOUBLE precision floating:
- *    seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
- *      s =  1bit  = sign
- *      e = 11bits = exponent
- *      f = 52bits = fraction
- */
-/* DOUBLE precision fixed:
- *    siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
- *      s =  1bit  = sign
- *      i = 63bits = integer
- */
-
-/* Extract sign-bit: */
-#define FP_S_s(v)    (((v) & ((unsigned)1 << 31)) ? 1 : 0)
-#define FP_D_s(v)    (((v) & ((uword64)1 << 63)) ? 1 : 0)
-/* Extract biased exponent: */
-#define FP_S_be(v)   (((v) >> 23) & 0xFF)
-#define FP_D_be(v)   (((v) >> 52) & 0x7FF)
-/* Extract unbiased Exponent: */
-#define FP_S_e(v)    (FP_S_be(v) - 0x7F)
-#define FP_D_e(v)    (FP_D_be(v) - 0x3FF)
-/* Extract complete fraction field: */
-#define FP_S_f(v)    ((v) & ~((unsigned)0x1FF << 23))
-#define FP_D_f(v)    ((v) & ~((uword64)0xFFF << 52))
-/* Extract numbered fraction bit: */
-#define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0)
-#define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0)
-
-/* Explicit QNaN values used when value required: */
-#define FPQNaN_SINGLE   (0x7FBFFFFF)
-#define FPQNaN_WORD     (0x7FFFFFFF)
-#define FPQNaN_DOUBLE   (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
-#define FPQNaN_LONG     (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
-
-/* Explicit Infinity values used when required: */
-#define FPINF_SINGLE    (0x7F800000)
-#define FPINF_DOUBLE    (((uword64)0x7FF00000 << 32) | 0x00000000)
-
-#define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor")))
-#define DOFMT(v)  (((v) == fmt_single) ? "single" : (((v) == fmt_double) ? "double" : (((v) == fmt_word) ? "word" : (((v) == fmt_long) ? "long" : (((v) == fmt_unknown) ? "<unknown>" : (((v) == fmt_uninterpreted) ? "<uninterpreted>" : (((v) == fmt_uninterpreted_32) ? "<uninterpreted_32>" : (((v) == fmt_uninterpreted_64) ? "<uninterpreted_64>" : "<format error>"))))))))
-
-uword64
-value_fpr (SIM_DESC sd,
-          sim_cpu *cpu,
-          address_word cia,
-          int fpr,
-          FP_formats fmt)
-{
-  uword64 value = 0;
-  int err = 0;
-
-  /* Treat unused register values, as fixed-point 64bit values: */
-  if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
-#if 1
-   /* If request to read data as "uninterpreted", then use the current
-      encoding: */
-   fmt = FPR_STATE[fpr];
-#else
-   fmt = fmt_long;
-#endif
-
-  /* For values not yet accessed, set to the desired format: */
-  if (FPR_STATE[fpr] == fmt_uninterpreted) {
-    FPR_STATE[fpr] = fmt;
-#ifdef DEBUG
-    printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt));
-#endif /* DEBUG */
-  }
-  if (fmt != FPR_STATE[fpr]) {
-    sim_io_eprintf(sd,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr,DOFMT(FPR_STATE[fpr]),DOFMT(fmt),pr_addr(cia));
-    FPR_STATE[fpr] = fmt_unknown;
-  }
-
-  if (FPR_STATE[fpr] == fmt_unknown) {
-   /* Set QNaN value: */
-   switch (fmt) {
-    case fmt_single:
-     value = FPQNaN_SINGLE;
-     break;
-
-    case fmt_double:
-     value = FPQNaN_DOUBLE;
-     break;
-
-    case fmt_word:
-     value = FPQNaN_WORD;
-     break;
-
-    case fmt_long:
-     value = FPQNaN_LONG;
-     break;
-
-    default:
-     err = -1;
-     break;
-   }
-  } else if (SizeFGR() == 64) {
-    switch (fmt) {
-     case fmt_single:
-     case fmt_word:
-      value = (FGR[fpr] & 0xFFFFFFFF);
-      break;
-
-     case fmt_uninterpreted:
-     case fmt_double:
-     case fmt_long:
-      value = FGR[fpr];
-      break;
-
-     default :
-      err = -1;
-      break;
-    }
-  } else {
-    switch (fmt) {
-     case fmt_single:
-     case fmt_word:
-      value = (FGR[fpr] & 0xFFFFFFFF);
-      break;
-
-     case fmt_uninterpreted:
-     case fmt_double:
-     case fmt_long:
-      if ((fpr & 1) == 0) { /* even registers only */
-#ifdef DEBUG
-       printf("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n", 
-              fpr+1, pr_uword64( (uword64) FGR[fpr+1] ),
-              fpr, pr_uword64( (uword64) FGR[fpr] ));
-#endif
-       value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF));
-      } else {
-       SignalException(ReservedInstruction,0);
-      }
-      break;
-
-     default :
-      err = -1;
-      break;
-    }
-  }
-
-  if (err)
-   SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()");
-
-#ifdef DEBUG
-  printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_uword64(value),pr_addr(cia),SizeFGR());
-#endif /* DEBUG */
-
-  return(value);
-}
-
-void
-store_fpr (SIM_DESC sd,
-          sim_cpu *cpu,
-          address_word cia,
-          int fpr,
-          FP_formats fmt,
-          uword64 value)
-{
-  int err = 0;
-
-#ifdef DEBUG
-  printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d,\n",fpr,DOFMT(fmt),pr_uword64(value),pr_addr(cia),SizeFGR());
-#endif /* DEBUG */
-
-  if (SizeFGR() == 64) {
-    switch (fmt) {
-      case fmt_uninterpreted_32:
-       fmt = fmt_uninterpreted;
-      case fmt_single :
-      case fmt_word :
-       if (STATE_VERBOSE_P(SD))
-         sim_io_eprintf (SD, "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
-          pr_addr(cia));
-       FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
-       FPR_STATE[fpr] = fmt;
-       break;
-
-      case fmt_uninterpreted_64:
-       fmt = fmt_uninterpreted;
-      case fmt_uninterpreted:
-      case fmt_double :
-      case fmt_long :
-       FGR[fpr] = value;
-       FPR_STATE[fpr] = fmt;
-       break;
-
-      default :
-       FPR_STATE[fpr] = fmt_unknown;
-       err = -1;
-       break;
-    }
-  } else {
-    switch (fmt) {
-      case fmt_uninterpreted_32:
-       fmt = fmt_uninterpreted;
-      case fmt_single :
-      case fmt_word :
-       FGR[fpr] = (value & 0xFFFFFFFF);
-       FPR_STATE[fpr] = fmt;
-       break;
-
-      case fmt_uninterpreted_64:
-       fmt = fmt_uninterpreted;
-      case fmt_uninterpreted:
-      case fmt_double :
-      case fmt_long :
-       if ((fpr & 1) == 0) { /* even register number only */
-         FGR[fpr+1] = (value >> 32);
-         FGR[fpr] = (value & 0xFFFFFFFF);
-         FPR_STATE[fpr + 1] = fmt;
-         FPR_STATE[fpr] = fmt;
-       } else {
-         FPR_STATE[fpr] = fmt_unknown;
-         FPR_STATE[fpr + 1] = fmt_unknown;
-         SignalException(ReservedInstruction,0);
-       }
-       break;
-
-      default :
-       FPR_STATE[fpr] = fmt_unknown;
-       err = -1;
-       break;
-    }
-  }
-#if defined(WARN_RESULT)
-  else
-    UndefinedResult();
-#endif /* WARN_RESULT */
-
-  if (err)
-   SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR()");
-
-#ifdef DEBUG
-  printf("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",fpr,pr_uword64(FGR[fpr]),DOFMT(fmt));
-#endif /* DEBUG */
-
-  return;
-}
-
-int
-NaN(op,fmt)
-     uword64 op;
-     FP_formats fmt; 
-{
-  int boolean = 0;
-  switch (fmt) {
-   case fmt_single:
-   case fmt_word:
-    {
-      sim_fpu wop;
-      sim_fpu_32to (&wop, op);
-      boolean = sim_fpu_is_nan (&wop);
-      break;
-    }
-   case fmt_double:
-   case fmt_long:
-    {
-      sim_fpu wop;
-      sim_fpu_64to (&wop, op);
-      boolean = sim_fpu_is_nan (&wop);
-      break;
-    }
-   default:
-    fprintf (stderr, "Bad switch\n");
-    abort ();
-  }
-
-#ifdef DEBUG
-printf("DBG: NaN: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt));
-#endif /* DEBUG */
-
-  return(boolean);
-}
-
-int
-Infinity(op,fmt)
-     uword64 op;
-     FP_formats fmt; 
-{
-  int boolean = 0;
-
-#ifdef DEBUG
-  printf("DBG: Infinity: format %s 0x%s\n",DOFMT(fmt),pr_addr(op));
-#endif /* DEBUG */
-
-  switch (fmt) {
-   case fmt_single:
-    {
-      sim_fpu wop;
-      sim_fpu_32to (&wop, op);
-      boolean = sim_fpu_is_infinity (&wop);
-      break;
-    }
-   case fmt_double:
-    {
-      sim_fpu wop;
-      sim_fpu_64to (&wop, op);
-      boolean = sim_fpu_is_infinity (&wop);
-      break;
-    }
-   default:
-    printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt));
-    break;
-  }
-
-#ifdef DEBUG
-  printf("DBG: Infinity: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt));
-#endif /* DEBUG */
-
-  return(boolean);
-}
-
-int
-Less(op1,op2,fmt)
-     uword64 op1;
-     uword64 op2;
-     FP_formats fmt; 
-{
-  int boolean = 0;
-
-  /* Argument checking already performed by the FPCOMPARE code */
-
-#ifdef DEBUG
-  printf("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
-  /* The format type should already have been checked: */
-  switch (fmt) {
-   case fmt_single:
-    {
-      sim_fpu wop1;
-      sim_fpu wop2;
-      sim_fpu_32to (&wop1, op1);
-      sim_fpu_32to (&wop2, op2);
-      boolean = sim_fpu_is_lt (&wop1, &wop2);
-      break;
-    }
-   case fmt_double:
-    {
-      sim_fpu wop1;
-      sim_fpu wop2;
-      sim_fpu_64to (&wop1, op1);
-      sim_fpu_64to (&wop2, op2);
-      boolean = sim_fpu_is_lt (&wop1, &wop2);
-      break;
-    }
-   default:
-    fprintf (stderr, "Bad switch\n");
-    abort ();
-  }
-
-#ifdef DEBUG
-  printf("DBG: Less: returning %d (format = %s)\n",boolean,DOFMT(fmt));
-#endif /* DEBUG */
-
-  return(boolean);
-}
-
-int
-Equal(op1,op2,fmt)
-     uword64 op1;
-     uword64 op2;
-     FP_formats fmt; 
-{
-  int boolean = 0;
-
-  /* Argument checking already performed by the FPCOMPARE code */
-
-#ifdef DEBUG
-  printf("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
-  /* The format type should already have been checked: */
-  switch (fmt) {
-   case fmt_single:
-    {
-      sim_fpu wop1;
-      sim_fpu wop2;
-      sim_fpu_32to (&wop1, op1);
-      sim_fpu_32to (&wop2, op2);
-      boolean = sim_fpu_is_eq (&wop1, &wop2);
-      break;
-    }
-   case fmt_double:
-    {
-      sim_fpu wop1;
-      sim_fpu wop2;
-      sim_fpu_64to (&wop1, op1);
-      sim_fpu_64to (&wop2, op2);
-      boolean = sim_fpu_is_eq (&wop1, &wop2);
-      break;
-    }
-   default:
-    fprintf (stderr, "Bad switch\n");
-    abort ();
-  }
-
-#ifdef DEBUG
-  printf("DBG: Equal: returning %d (format = %s)\n",boolean,DOFMT(fmt));
-#endif /* DEBUG */
-
-  return(boolean);
-}
-
-uword64
-AbsoluteValue(op,fmt)
-     uword64 op;
-     FP_formats fmt; 
-{
-  uword64 result = 0;
-
-#ifdef DEBUG
-  printf("DBG: AbsoluteValue: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
-#endif /* DEBUG */
-
-  /* The format type should already have been checked: */
-  switch (fmt) {
-   case fmt_single:
-    {
-      sim_fpu wop;
-      unsigned32 ans;
-      sim_fpu_32to (&wop, op);
-      sim_fpu_abs (&wop, &wop);
-      sim_fpu_to32 (&ans, &wop);
-      result = ans;
-      break;
-    }
-   case fmt_double:
-    {
-      sim_fpu wop;
-      unsigned64 ans;
-      sim_fpu_64to (&wop, op);
-      sim_fpu_abs (&wop, &wop);
-      sim_fpu_to64 (&ans, &wop);
-      result = ans;
-      break;
-    }
-   default:
-    fprintf (stderr, "Bad switch\n");
-    abort ();
-  }
-
-  return(result);
-}
-
-uword64
-Negate(op,fmt)
-     uword64 op;
-     FP_formats fmt; 
-{
-  uword64 result = 0;
-
-#ifdef DEBUG
-  printf("DBG: Negate: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
-#endif /* DEBUG */
-
-  /* The format type should already have been checked: */
-  switch (fmt) {
-   case fmt_single:
-    {
-      sim_fpu wop;
-      unsigned32 ans;
-      sim_fpu_32to (&wop, op);
-      sim_fpu_neg (&wop, &wop);
-      sim_fpu_to32 (&ans, &wop);
-      result = ans;
-      break;
-    }
-   case fmt_double:
-    {
-      sim_fpu wop;
-      unsigned64 ans;
-      sim_fpu_64to (&wop, op);
-      sim_fpu_neg (&wop, &wop);
-      sim_fpu_to64 (&ans, &wop);
-      result = ans;
-      break;
-    }
-   default:
-    fprintf (stderr, "Bad switch\n");
-    abort ();
-  }
-
-  return(result);
-}
-
-uword64
-Add(op1,op2,fmt)
-     uword64 op1;
-     uword64 op2;
-     FP_formats fmt; 
-{
-  uword64 result = 0;
-
-#ifdef DEBUG
-  printf("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
-  /* The registers must specify FPRs valid for operands of type
-     "fmt". If they are not valid, the result is undefined. */
-
-  /* The format type should already have been checked: */
-  switch (fmt) {
-   case fmt_single:
-    {
-      sim_fpu wop1;
-      sim_fpu wop2;
-      sim_fpu ans;
-      unsigned32 res;
-      sim_fpu_32to (&wop1, op1);
-      sim_fpu_32to (&wop2, op2);
-      sim_fpu_add (&ans, &wop1, &wop2);
-      sim_fpu_to32 (&res, &ans);
-      result = res;
-      break;
-    }
-   case fmt_double:
-    {
-      sim_fpu wop1;
-      sim_fpu wop2;
-      sim_fpu ans;
-      unsigned64 res;
-      sim_fpu_64to (&wop1, op1);
-      sim_fpu_64to (&wop2, op2);
-      sim_fpu_add (&ans, &wop1, &wop2);
-      sim_fpu_to64 (&res, &ans);
-      result = res;
-      break;
-    }
-   default:
-    fprintf (stderr, "Bad switch\n");
-    abort ();
-  }
-
-#ifdef DEBUG
-  printf("DBG: Add: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
-  return(result);
-}
-
-uword64
-Sub(op1,op2,fmt)
-     uword64 op1;
-     uword64 op2;
-     FP_formats fmt; 
-{
-  uword64 result = 0;
-
-#ifdef DEBUG
-  printf("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
-  /* The registers must specify FPRs valid for operands of type
-     "fmt". If they are not valid, the result is undefined. */
-
-  /* The format type should already have been checked: */
-  switch (fmt) {
-   case fmt_single:
-    {
-      sim_fpu wop1;
-      sim_fpu wop2;
-      sim_fpu ans;
-      unsigned32 res;
-      sim_fpu_32to (&wop1, op1);
-      sim_fpu_32to (&wop2, op2);
-      sim_fpu_sub (&ans, &wop1, &wop2);
-      sim_fpu_to32 (&res, &ans);
-      result = res;
-    }
-    break;
-   case fmt_double:
-    {
-      sim_fpu wop1;
-      sim_fpu wop2;
-      sim_fpu ans;
-      unsigned64 res;
-      sim_fpu_64to (&wop1, op1);
-      sim_fpu_64to (&wop2, op2);
-      sim_fpu_sub (&ans, &wop1, &wop2);
-      sim_fpu_to64 (&res, &ans);
-      result = res;
-    }
-    break;
-   default:
-    fprintf (stderr, "Bad switch\n");
-    abort ();
-  }
-
-#ifdef DEBUG
-  printf("DBG: Sub: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
-  return(result);
-}
-
-uword64
-Multiply(op1,op2,fmt)
-     uword64 op1;
-     uword64 op2;
-     FP_formats fmt; 
-{
-  uword64 result = 0;
-
-#ifdef DEBUG
-  printf("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
-  /* The registers must specify FPRs valid for operands of type
-     "fmt". If they are not valid, the result is undefined. */
-
-  /* The format type should already have been checked: */
-  switch (fmt) {
-   case fmt_single:
-    {
-      sim_fpu wop1;
-      sim_fpu wop2;
-      sim_fpu ans;
-      unsigned32 res;
-      sim_fpu_32to (&wop1, op1);
-      sim_fpu_32to (&wop2, op2);
-      sim_fpu_mul (&ans, &wop1, &wop2);
-      sim_fpu_to32 (&res, &ans);
-      result = res;
-      break;
-    }
-   case fmt_double:
-    {
-      sim_fpu wop1;
-      sim_fpu wop2;
-      sim_fpu ans;
-      unsigned64 res;
-      sim_fpu_64to (&wop1, op1);
-      sim_fpu_64to (&wop2, op2);
-      sim_fpu_mul (&ans, &wop1, &wop2);
-      sim_fpu_to64 (&res, &ans);
-      result = res;
-      break;
-    }
-   default:
-    fprintf (stderr, "Bad switch\n");
-    abort ();
-  }
-
-#ifdef DEBUG
-  printf("DBG: Multiply: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
-  return(result);
-}
-
-uword64
-Divide(op1,op2,fmt)
-     uword64 op1;
-     uword64 op2;
-     FP_formats fmt; 
-{
-  uword64 result = 0;
-
-#ifdef DEBUG
-  printf("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
-  /* The registers must specify FPRs valid for operands of type
-     "fmt". If they are not valid, the result is undefined. */
-
-  /* The format type should already have been checked: */
-  switch (fmt) {
-   case fmt_single:
-    {
-      sim_fpu wop1;
-      sim_fpu wop2;
-      sim_fpu ans;
-      unsigned32 res;
-      sim_fpu_32to (&wop1, op1);
-      sim_fpu_32to (&wop2, op2);
-      sim_fpu_div (&ans, &wop1, &wop2);
-      sim_fpu_to32 (&res, &ans);
-      result = res;
-      break;
-    }
-   case fmt_double:
-    {
-      sim_fpu wop1;
-      sim_fpu wop2;
-      sim_fpu ans;
-      unsigned64 res;
-      sim_fpu_64to (&wop1, op1);
-      sim_fpu_64to (&wop2, op2);
-      sim_fpu_div (&ans, &wop1, &wop2);
-      sim_fpu_to64 (&res, &ans);
-      result = res;
-      break;
-    }
-   default:
-    fprintf (stderr, "Bad switch\n");
-    abort ();
-  }
-
-#ifdef DEBUG
-  printf("DBG: Divide: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
-  return(result);
-}
-
-uword64 UNUSED
-Recip(op,fmt)
-     uword64 op;
-     FP_formats fmt; 
-{
-  uword64 result = 0;
-
-#ifdef DEBUG
-  printf("DBG: Recip: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
-#endif /* DEBUG */
-
-  /* The registers must specify FPRs valid for operands of type
-     "fmt". If they are not valid, the result is undefined. */
-
-  /* The format type should already have been checked: */
-  switch (fmt) {
-   case fmt_single:
-    {
-      sim_fpu wop;
-      sim_fpu ans;
-      unsigned32 res;
-      sim_fpu_32to (&wop, op);
-      sim_fpu_inv (&ans, &wop);
-      sim_fpu_to32 (&res, &ans);
-      result = res;
-      break;
-    }
-   case fmt_double:
-    {
-      sim_fpu wop;
-      sim_fpu ans;
-      unsigned64 res;
-      sim_fpu_64to (&wop, op);
-      sim_fpu_inv (&ans, &wop);
-      sim_fpu_to64 (&res, &ans);
-      result = res;
-      break;
-    }
-   default:
-    fprintf (stderr, "Bad switch\n");
-    abort ();
-  }
-
-#ifdef DEBUG
-  printf("DBG: Recip: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
-  return(result);
-}
-
-uword64
-SquareRoot(op,fmt)
-     uword64 op;
-     FP_formats fmt; 
-{
-  uword64 result = 0;
-
-#ifdef DEBUG
-  printf("DBG: SquareRoot: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
-#endif /* DEBUG */
-
-  /* The registers must specify FPRs valid for operands of type
-     "fmt". If they are not valid, the result is undefined. */
-
-  /* The format type should already have been checked: */
-  switch (fmt) {
-   case fmt_single:
-    {
-      sim_fpu wop;
-      sim_fpu ans;
-      unsigned32 res;
-      sim_fpu_32to (&wop, op);
-      sim_fpu_sqrt (&ans, &wop);
-      sim_fpu_to32 (&res, &ans);
-      result = res;
-      break;
-    }
-   case fmt_double:
-    {
-      sim_fpu wop;
-      sim_fpu ans;
-      unsigned64 res;
-      sim_fpu_64to (&wop, op);
-      sim_fpu_sqrt (&ans, &wop);
-      sim_fpu_to64 (&res, &ans);
-      result = res;
-      break;
-    }
-   default:
-    fprintf (stderr, "Bad switch\n");
-    abort ();
-  }
-
-#ifdef DEBUG
-  printf("DBG: SquareRoot: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
-  return(result);
-}
-
-#if 0
-uword64
-Max (uword64 op1,
-     uword64 op2,
-     FP_formats fmt)
-{
-  int cmp;
-  unsigned64 result;
-
-#ifdef DEBUG
-  printf("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
-  /* The registers must specify FPRs valid for operands of type
-     "fmt". If they are not valid, the result is undefined. */
-
-  /* The format type should already have been checked: */
-  switch (fmt)
-    {
-    case fmt_single:
-      {
-       sim_fpu wop1;
-       sim_fpu wop2;
-       sim_fpu_32to (&wop1, op1);
-       sim_fpu_32to (&wop2, op2);
-       cmp = sim_fpu_cmp (&wop1, &wop2);
-       break;
-      }
-    case fmt_double:
-      {
-       sim_fpu wop1;
-       sim_fpu wop2;
-       sim_fpu_64to (&wop1, op1);
-       sim_fpu_64to (&wop2, op2);
-       cmp = sim_fpu_cmp (&wop1, &wop2);
-       break;
-      }
-    default:
-      fprintf (stderr, "Bad switch\n");
-      abort ();
-    }
-  
-  switch (cmp)
-    {
-    case SIM_FPU_IS_SNAN:
-    case SIM_FPU_IS_QNAN:
-      result = op1;
-    case SIM_FPU_IS_NINF:
-    case SIM_FPU_IS_NNUMBER:
-    case SIM_FPU_IS_NDENORM:
-    case SIM_FPU_IS_NZERO:
-      result = op2; /* op1 - op2 < 0 */
-    case SIM_FPU_IS_PINF:
-    case SIM_FPU_IS_PNUMBER:
-    case SIM_FPU_IS_PDENORM:
-    case SIM_FPU_IS_PZERO:
-      result = op1; /* op1 - op2 > 0 */
-    default:
-      fprintf (stderr, "Bad switch\n");
-      abort ();
-    }
-
-#ifdef DEBUG
-  printf("DBG: Max: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
-  return(result);
-}
-#endif 
-
-#if 0
-uword64
-Min (uword64 op1,
-     uword64 op2,
-     FP_formats fmt)
-{
-  int cmp;
-  unsigned64 result;
-
-#ifdef DEBUG
-  printf("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
-#endif /* DEBUG */
-
-  /* The registers must specify FPRs valid for operands of type
-     "fmt". If they are not valid, the result is undefined. */
-
-  /* The format type should already have been checked: */
-  switch (fmt)
-    {
-    case fmt_single:
-      {
-       sim_fpu wop1;
-       sim_fpu wop2;
-       sim_fpu_32to (&wop1, op1);
-       sim_fpu_32to (&wop2, op2);
-       cmp = sim_fpu_cmp (&wop1, &wop2);
-       break;
-      }
-    case fmt_double:
-      {
-       sim_fpu wop1;
-       sim_fpu wop2;
-       sim_fpu_64to (&wop1, op1);
-       sim_fpu_64to (&wop2, op2);
-       cmp = sim_fpu_cmp (&wop1, &wop2);
-       break;
-      }
-    default:
-      fprintf (stderr, "Bad switch\n");
-      abort ();
-    }
-  
-  switch (cmp)
-    {
-    case SIM_FPU_IS_SNAN:
-    case SIM_FPU_IS_QNAN:
-      result = op1;
-    case SIM_FPU_IS_NINF:
-    case SIM_FPU_IS_NNUMBER:
-    case SIM_FPU_IS_NDENORM:
-    case SIM_FPU_IS_NZERO:
-      result = op1; /* op1 - op2 < 0 */
-    case SIM_FPU_IS_PINF:
-    case SIM_FPU_IS_PNUMBER:
-    case SIM_FPU_IS_PDENORM:
-    case SIM_FPU_IS_PZERO:
-      result = op2; /* op1 - op2 > 0 */
-    default:
-      fprintf (stderr, "Bad switch\n");
-      abort ();
-    }
-
-#ifdef DEBUG
-  printf("DBG: Min: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
-#endif /* DEBUG */
-
-  return(result);
-}
-#endif
-
-uword64
-convert (SIM_DESC sd,
-        sim_cpu *cpu,
-        address_word cia,
-        int rm,
-        uword64 op,
-        FP_formats from,
-        FP_formats to)
-{
-  sim_fpu wop;
-  sim_fpu_round round;
-  unsigned32 result32;
-  unsigned64 result64;
-
-#ifdef DEBUG
-#if 0 /* FIXME: doesn't compile */
-  printf("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",RMMODE(rm),pr_addr(op),DOFMT(from),DOFMT(to),pr_addr(IPC));
-#endif
-#endif /* DEBUG */
-
-  switch (rm)
-    {
-    case FP_RM_NEAREST:
-      /* Round result to nearest representable value. When two
-        representable values are equally near, round to the value
-        that has a least significant bit of zero (i.e. is even). */
-      round = sim_fpu_round_near;
-      break;
-    case FP_RM_TOZERO:
-      /* Round result to the value closest to, and not greater in
-        magnitude than, the result. */
-      round = sim_fpu_round_zero;
-      break;
-    case FP_RM_TOPINF:
-      /* Round result to the value closest to, and not less than,
-        the result. */
-      round = sim_fpu_round_up;
-      break;
-      
-    case FP_RM_TOMINF:
-      /* Round result to the value closest to, and not greater than,
-        the result. */
-      round = sim_fpu_round_down;
-      break;
-    default:
-      round = 0;
-      fprintf (stderr, "Bad switch\n");
-      abort ();
-    }
-  
-  /* Convert the input to sim_fpu internal format */
-  switch (from)
-    {
-    case fmt_double:
-      sim_fpu_64to (&wop, op);
-      break;
-    case fmt_single:
-      sim_fpu_32to (&wop, op);
-      break;
-    case fmt_word:
-      sim_fpu_i32to (&wop, op, round);
-      break;
-    case fmt_long:
-      sim_fpu_i64to (&wop, op, round);
-      break;
-    default:
-      fprintf (stderr, "Bad switch\n");
-      abort ();
-    }
-
-  /* Convert sim_fpu format into the output */
-  /* The value WOP is converted to the destination format, rounding
-     using mode RM. When the destination is a fixed-point format, then
-     a source value of Infinity, NaN or one which would round to an
-     integer outside the fixed point range then an IEEE Invalid
-     Operation condition is raised. */
-  switch (to)
-    {
-    case fmt_single:
-      sim_fpu_round_32 (&wop, round, 0);
-      sim_fpu_to32 (&result32, &wop);
-      result64 = result32;
-      break;
-    case fmt_double:
-      sim_fpu_round_64 (&wop, round, 0);
-      sim_fpu_to64 (&result64, &wop);
-      break;
-    case fmt_word:
-      sim_fpu_to32i (&result32, &wop, round);
-      result64 = result32;
-      break;
-    case fmt_long:
-      sim_fpu_to64i (&result64, &wop, round);
-      break;
-    default:
-      result64 = 0;
-      fprintf (stderr, "Bad switch\n");
-      abort ();
-    }
-#ifdef DEBUG
-  printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result64),DOFMT(to));
-#endif /* DEBUG */
-
-  return(result64);
-}
-
 
 /*-- co-processor support routines ------------------------------------------*/