2002-06-06 Chris Demetriou <cgd@broadcom.com>
authorChris Demetriou <cgd@google.com>
Fri, 7 Jun 2002 00:13:24 +0000 (00:13 +0000)
committerChris Demetriou <cgd@google.com>
Fri, 7 Jun 2002 00:13:24 +0000 (00:13 +0000)
            Ed Satterthwaite  <ehs@broadcom.com>

* cp1.h: New file.
* sim-main.h: Include cp1.h.
(SETFCC, GETFCC, IR, UF, OF, DX, IO, UO, FP_FLAGS, FP_ENABLE)
(FP_CAUSE, GETFS, FP_RM_NEAREST, FP_RM_TOZERO, FP_RM_TOPINF)
(FP_RM_TOMINF, GETRM): Remove.  Moved to cp1.h.
(FP_FS, FP_MASK_RM, FP_SH_RM, Nan, Less, Equal): Remove.
(value_fcr, store_fcr, test_fcsr, fp_cmp): New prototypes.
(ValueFCR, StoreFCR, TestFCSR, Compare): New macros.
* cp1.c: Don't include sim-fpu.h; already included by
sim-main.h.  Clean up formatting of some comments.
(NaN, Equal, Less): Remove.
(test_fcsr, value_fcr, store_fcr, update_fcsr, fp_test)
(fp_cmp): New functions.
* mips.igen (do_c_cond_fmt): Remove.
(C.cond.fmta, C.cond.fmtb): Replace uses of do_c_cond_fmt_a with
Compare.  Add result tracing.
(CxC1): Remove, replace with...
(CFC1a, CFC1b, CFC1c, CTC1a, CTC1b, CTC1c): New instructions.
(DMxC1): Remove, replace with...
(DMFC1a, DMFC1b, DMTC1a, DMTC1b): New instructions.
(MxC1): Remove, replace with...
(MFC1a, MFC1b, MTC1a, MTC1b): New instructions.

sim/mips/ChangeLog
sim/mips/cp1.c
sim/mips/cp1.h [new file with mode: 0644]
sim/mips/mips.igen
sim/mips/sim-main.h

index 771edae..dff7b80 100644 (file)
@@ -1,3 +1,29 @@
+2002-06-06  Chris Demetriou  <cgd@broadcom.com>
+            Ed Satterthwaite  <ehs@broadcom.com>
+
+       * cp1.h: New file.
+       * sim-main.h: Include cp1.h.
+       (SETFCC, GETFCC, IR, UF, OF, DX, IO, UO, FP_FLAGS, FP_ENABLE)
+       (FP_CAUSE, GETFS, FP_RM_NEAREST, FP_RM_TOZERO, FP_RM_TOPINF)
+       (FP_RM_TOMINF, GETRM): Remove.  Moved to cp1.h.
+       (FP_FS, FP_MASK_RM, FP_SH_RM, Nan, Less, Equal): Remove.
+       (value_fcr, store_fcr, test_fcsr, fp_cmp): New prototypes.
+       (ValueFCR, StoreFCR, TestFCSR, Compare): New macros.
+       * cp1.c: Don't include sim-fpu.h; already included by
+       sim-main.h.  Clean up formatting of some comments.
+       (NaN, Equal, Less): Remove.
+       (test_fcsr, value_fcr, store_fcr, update_fcsr, fp_test)
+       (fp_cmp): New functions.
+       * mips.igen (do_c_cond_fmt): Remove.
+       (C.cond.fmta, C.cond.fmtb): Replace uses of do_c_cond_fmt_a with
+       Compare.  Add result tracing.
+       (CxC1): Remove, replace with...
+       (CFC1a, CFC1b, CFC1c, CTC1a, CTC1b, CTC1c): New instructions.
+       (DMxC1): Remove, replace with...
+       (DMFC1a, DMFC1b, DMTC1a, DMTC1b): New instructions.
+       (MxC1): Remove, replace with... 
+       (MFC1a, MFC1b, MTC1a, MTC1b): New instructions.  
+
 2002-06-04  Chris Demetriou  <cgd@broadcom.com>
 
        * sim-main.h (FGRIDX): Remove, replace all uses with...
index 442c311..3641df7 100644 (file)
@@ -40,7 +40,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "sim-main.h"
-#include "sim-fpu.h"
 
 /* Within cp1.c we refer to sim_cpu directly.  */
 #define CPU cpu
@@ -313,77 +312,163 @@ store_fpr (sim_cpu *cpu,
   return;
 }
 
-int
-NaN (op, fmt)
-     uword64 op;
-     FP_formats fmt;
+
+/* CP1 control/status registers */
+
+void
+test_fcsr (sim_cpu *cpu,
+          address_word cia)
 {
-  int boolean = 0;
-  switch (fmt)
+  unsigned int cause;
+
+  cause = (FCSR & fcsr_CAUSE_mask) >> fcsr_CAUSE_shift;
+  if ((cause & ((FCSR & fcsr_ENABLES_mask) >> fcsr_ENABLES_shift)) != 0
+      || (cause & (1 << UO)))
     {
-    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 ();
+      SignalExceptionFPE();
     }
+}
 
-#ifdef DEBUG
-  printf ("DBG: NaN: returning %d for 0x%s (format = %s)\n",
-         boolean, pr_addr (op), fpu_format_name (fmt));
-#endif /* DEBUG */
+unsigned_word
+value_fcr(sim_cpu *cpu,
+         address_word cia,
+         int fcr)
+{
+  unsigned32 value = 0;
+
+  switch (fcr)
+    {
+    case 0:  /* FP Implementation and Revision Register */
+      value = FCR0;
+      break;
+    case 25:  /* FP Condition Codes Register */
+      value = (FCR31 & fcsr_FCC_mask) >> fcsr_FCC_shift;
+      value = (value & 0x1) | (value >> 1);   /* close FCC gap */
+      break;
+    case 26:  /* FP Exceptions Register */
+      value = FCR31 & (fcsr_CAUSE_mask | fcsr_FLAGS_mask);
+      break;
+    case 28:  /* FP Enables Register */
+      value = FCR31 & (fcsr_ENABLES_mask | fcsr_RM_mask);
+      if (FCR31 & fcsr_FS)
+       value |= 0x4;                        /* nonstandard FS bit */
+      break;
+    case 31:  /* FP Control/Status Register */
+      value = FCR31 & ~fcsr_ZERO_mask;
+      break;
+    }
 
-  return (boolean);
+  return (EXTEND32 (value));
 }
 
-int
-Less (op1, op2, fmt)
-     uword64 op1;
-     uword64 op2;
-     FP_formats fmt;
+void
+store_fcr(sim_cpu *cpu,
+         address_word cia,
+         int fcr,
+         unsigned_word value)
 {
-  int boolean = 0;
+  unsigned32 v;
 
-  /* Argument checking already performed by the FPCOMPARE code */
+  v = VL4_8(value);
+  switch (fcr)
+    {
+    case 25:  /* FP Condition Codes Register */
+      v = (v << 1) | (v & 0x1);             /* adjust for FCC gap */
+      FCR31 &= ~fcsr_FCC_mask;
+      FCR31 |= ((v << fcsr_FCC_shift) & fcsr_FCC_mask);
+      break;
+    case 26:  /* FP Exceptions Register */
+      FCR31 &= ~(fcsr_CAUSE_mask | fcsr_FLAGS_mask);
+      FCR31 |= (v & (fcsr_CAUSE_mask | fcsr_FLAGS_mask));
+      test_fcsr(cpu, cia);
+      break;
+    case 28:  /* FP Enables Register */
+      if (v & 0x4)                         /* nonstandard FS bit */
+       v |= fcsr_FS;
+      else
+       v &= ~fcsr_FS;
+      FCR31 &= (fcsr_FCC_mask | fcsr_CAUSE_mask | fcsr_FLAGS_mask);
+      FCR31 |= (v & (fcsr_FS | fcsr_ENABLES_mask | fcsr_RM_mask));
+      test_fcsr(cpu, cia);
+      break;
+    case 31:  /* FP Control/Status Register */
+      FCR31 = v & ~fcsr_ZERO_mask;
+      test_fcsr(cpu, cia);
+      break;
+    }
+}
 
-#ifdef DEBUG
-  printf ("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",
-         fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
-#endif /* DEBUG */
+void
+update_fcsr (sim_cpu *cpu,
+            address_word cia,
+            sim_fpu_status status)
+{
+  FCSR &= ~fcsr_CAUSE_mask;
 
-  /* The format type should already have been checked:  */
+  if (status != 0)
+    {
+      unsigned int cause = 0;
+
+      /* map between sim_fpu codes and MIPS FCSR */
+      if (status & (sim_fpu_status_invalid_snan
+                   | sim_fpu_status_invalid_isi
+                   | sim_fpu_status_invalid_idi
+                   | sim_fpu_status_invalid_zdz
+                   | sim_fpu_status_invalid_imz
+                   | sim_fpu_status_invalid_cmp
+                   | sim_fpu_status_invalid_sqrt
+                   | sim_fpu_status_invalid_cvi))
+       cause |= (1 << IO);
+      if (status & sim_fpu_status_invalid_div0)
+       cause |= (1 << DZ);
+      if (status & sim_fpu_status_overflow)
+       cause |= (1 << OF);
+      if (status & sim_fpu_status_underflow)
+       cause |= (1 << UF);
+      if (status & sim_fpu_status_inexact)
+       cause |= (1 << IR);
+#if 0 /* Not yet.  */
+      /* Implicit clearing of other bits by unimplemented done by callers. */
+      if (status & sim_fpu_status_unimplemented)
+       cause |= (1 << UO);
+#endif
+
+      FCSR |= (cause << fcsr_CAUSE_shift);
+      test_fcsr (cpu, cia);
+      FCSR |= ((cause & ~(1 << UO)) << fcsr_FLAGS_shift);
+    }
+  return;
+}
+
+
+/* Comparison operations.  */
+
+static sim_fpu_status
+fp_test(unsigned64 op1,
+       unsigned64 op2,
+       FP_formats fmt,
+       int abs,
+       int cond,
+       int *condition)
+{
+  sim_fpu wop1;
+  sim_fpu wop2;
+  sim_fpu_status status = 0;
+  int  less, equal, unordered;
+
+  /* The format type has already 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:
@@ -391,61 +476,60 @@ Less (op1, op2, fmt)
       abort ();
     }
 
-#ifdef DEBUG
-  printf ("DBG: Less: returning %d (format = %s)\n",
-         boolean, fpu_format_name (fmt));
-#endif /* DEBUG */
-
-  return (boolean);
+  if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2))
+    {
+      if ((cond & (1 << 3)) ||
+         sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2))
+       status = sim_fpu_status_invalid_snan;
+      less = 0;
+      equal = 0;
+      unordered = 1;
+    }
+  else
+    {
+      if (abs)
+       {
+         status |= sim_fpu_abs (&wop1, &wop1);
+         status |= sim_fpu_abs (&wop2, &wop2);
+       }
+      equal = sim_fpu_is_eq (&wop1, &wop2);
+      less = !equal && sim_fpu_is_lt (&wop1, &wop2);
+      unordered = 0;
+    }
+  *condition = (((cond & (1 << 2)) && less)
+               || ((cond & (1 << 1)) && equal)
+               || ((cond & (1 << 0)) && unordered));
+  return status;
 }
 
-int
-Equal (op1, op2, fmt)
-     uword64 op1;
-     uword64 op2;
-     FP_formats fmt;
+void
+fp_cmp(sim_cpu *cpu,
+       address_word cia,
+       unsigned64 op1,
+       unsigned64 op2,
+       FP_formats fmt,
+       int abs,
+       int cond,
+       int cc)
 {
-  int boolean = 0;
-
-  /* Argument checking already performed by the FPCOMPARE code */
+  sim_fpu_status status = 0;
 
-#ifdef DEBUG
-  printf ("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",
-         fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
-#endif /* DEBUG */
-
-  /* The format type should already have been checked:  */
+  /* 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);
+       int result;
+       status = fp_test(op1, op2, fmt, abs, cond, &result);
+       update_fcsr (cpu, cia, status);
+       SETFCC (cc, result);
        break;
       }
     default:
-      fprintf (stderr, "Bad switch\n");
+      sim_io_eprintf (SD, "Bad switch\n");
       abort ();
     }
-
-#ifdef DEBUG
-  printf ("DBG: Equal: returning %d (format = %s)\n",
-         boolean, fpu_format_name (fmt));
-#endif /* DEBUG */
-
-  return (boolean);
 }
 
 
@@ -613,6 +697,8 @@ fp_sqrt(sim_cpu *cpu,
 }
 
 
+/* Conversion operations.  */
+
 uword64
 convert (sim_cpu *cpu,
         address_word cia,
diff --git a/sim/mips/cp1.h b/sim/mips/cp1.h
new file mode 100644 (file)
index 0000000..90919e3
--- /dev/null
@@ -0,0 +1,81 @@
+/*> cp1.h <*/
+/* MIPS Simulator FPU (CoProcessor 1) definitions.
+   Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc.
+   Derived from sim-main.h contributed by Cygnus Solutions,
+   modified substially by Broadcom Corporation (SiByte).
+
+This file is part of GDB, the GNU debugger.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef CP1_H
+#define CP1_H
+
+/* See sim-main.h for allocation of registers FCR0 and FCR31 (FCSR) 
+   in CPU state (struct sim_cpu), and for FPU functions.  */
+
+#define fcsr_FCC_mask      (0xFE800000)
+#define fcsr_FCC_shift     (23)
+#define        fcsr_FCC_bit(cc)   ((cc) == 0 ? 23 : (24 + (cc)))
+#define fcsr_FS            (1 << 24) /* MIPS III onwards : Flush to Zero */
+#define fcsr_ZERO_mask     (0x007C0000)
+#define fcsr_CAUSE_mask    (0x0003F000)
+#define fcsr_CAUSE_shift   (12)
+#define fcsr_ENABLES_mask  (0x00000F80)
+#define fcsr_ENABLES_shift (7)
+#define fcsr_FLAGS_mask    (0x0000007C)
+#define fcsr_FLAGS_shift   (2)
+#define fcsr_RM_mask       (0x00000003)
+#define fcsr_RM_shift      (0)
+
+
+/* Macros to update and retrieve the FCSR condition-code bits.  This
+   is complicated by the fact that there is a hole in the index range
+   of the bits within the FCSR register.  (Note that the number of bits
+   visible depends on the ISA in use, but that is handled elsewhere.)  */
+#define SETFCC(cc,v) \
+  do { \
+    (FCSR = ((FCSR & ~(1 << fcsr_FCC_bit(cc))) | ((v) << fcsr_FCC_bit(cc)))); \
+  } while (0)
+#define GETFCC(cc) ((FCSR & (1 << fcsr_FCC_bit(cc))) != 0 ? 1 : 0)
+
+
+/* Read flush-to-zero bit (not right-justified).  */
+#define GETFS()            ((int)(FCSR & fcsr_FS))
+
+
+/* FCSR flag bits definitions and access macros.  */
+#define IR            0   /* I: Inexact Result */
+#define UF            1   /* U: UnderFlow */
+#define OF            2   /* O: OverFlow */
+#define DZ            3   /* Z: Division by Zero */
+#define IO            4   /* V: Invalid Operation */
+#define UO            5   /* E: Unimplemented Operation (CAUSE field only) */
+
+#define FP_FLAGS(b)   (1 << ((b) + fcsr_FLAGS_shift))
+#define FP_ENABLE(b)  (1 << ((b) + fcsr_ENABLES_shift))
+#define FP_CAUSE(b)   (1 << ((b) + fcsr_CAUSE_shift))
+
+
+/* Rounding mode bit definitions and access macros.  */
+#define FP_RM_NEAREST 0   /* Round to nearest (Round).  */
+#define FP_RM_TOZERO  1   /* Round to zero (Trunc).  */
+#define FP_RM_TOPINF  2   /* Round to Plus infinity (Ceil).  */
+#define FP_RM_TOMINF  3   /* Round to Minus infinity (Floor).  */
+
+#define GETRM()       ((FCSR >> fcsr_RM_shift) & fcsr_RM_mask)
+
+
+#endif /* CP1_H */
index 874b685..f374a54 100644 (file)
 }
 
 
-
-
-
-
-// C.EQ.S
-// C.EQ.D
-// ...
-
-:function:::void:do_c_cond_fmt:int fmt, int ft, int fs, int cc, int cond, instruction_word insn
-{
-  int less;
-  int equal;
-  int unordered;
-  int condition;
-  unsigned64 ofs = ValueFPR (fs, fmt);
-  unsigned64 oft = ValueFPR (ft, fmt);
-  if (NaN (ofs, fmt) || NaN (oft, fmt))
-    {
-      if (FCSR & FP_ENABLE (IO))
-       {
-         FCSR |= FP_CAUSE (IO);
-         SignalExceptionFPE ();
-       }
-      less = 0;
-      equal = 0;
-      unordered = 1;
-    }
-  else
-    {
-      less = Less (ofs, oft, fmt);
-      equal = Equal (ofs, oft, fmt);
-      unordered = 0;
-    }
-  condition = (((cond & (1 << 2)) && less)
-              || ((cond & (1 << 1)) && equal)
-              || ((cond & (1 << 0)) && unordered));
-  SETFCC (cc, condition);
-}
-
 010001,10,3.FMT,5.FT,5.FS,3.0,00,11,4.COND:COP1:32,f::C.cond.fmta
 "c.%s<COND>.%s<FMT> f<FS>, f<FT>"
 *mipsI:
   int fmt = FMT;
   check_fpu (SD_);
   check_fmt_p (SD_, fmt, instruction_0);
-  do_c_cond_fmt (SD_, fmt, FT, FS, 0, COND, instruction_0);
+  Compare (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt, COND, 0);
+  TRACE_ALU_RESULT (ValueFCR (31));
 }
 
 010001,10,3.FMT,5.FT,5.FS,3.CC,00,11,4.COND:COP1:32,f::C.cond.fmtb
   int fmt = FMT;
   check_fpu (SD_);
   check_fmt_p (SD_, fmt, instruction_0);
-  do_c_cond_fmt (SD_, fmt, FT, FS, CC, COND, instruction_0);
+  Compare (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt, COND, CC);
+  TRACE_ALU_RESULT (ValueFCR (31));
 }
 
 
 }
 
 
-// CFC1
-// CTC1
-010001,00,X,10,5.RT,5.FS,00000000000:COP1Sa:32,f::CxC1
-"c%s<X>c1 r<RT>, f<FS>"
+010001,00010,5.RT,5.FS,00000000000:COP1:32,f::CFC1a
+"cfc1 r<RT>, f<FS>"
 *mipsI:
 *mipsII:
 *mipsIII:
 {
   check_fpu (SD_);
-  if (X)
+  if (FS == 0)
+    PENDING_FILL (RT, EXTEND32 (FCR0));
+  else if (FS == 31)
+    PENDING_FILL (RT, EXTEND32 (FCR31));
+  /* else NOP */
+}
+
+010001,00010,5.RT,5.FS,00000000000:COP1:32,f::CFC1b
+"cfc1 r<RT>, f<FS>"
+*mipsIV:
+*vr4100:
+*vr5000:
+*r3900:
+{
+  check_fpu (SD_);
+  if (FS == 0 || FS == 31)
     {
-      if (FS == 0)
-       PENDING_FILL(FCR0IDX,VL4_8(GPR[RT]));
-      else if (FS == 31)
-       PENDING_FILL(FCR31IDX,VL4_8(GPR[RT]));
-      /* else NOP */
-      PENDING_SCHED(FCSR, FCR31 & (1<<23), 1, 23);
-    }
-  else
-    { /* control from */
-      if (FS == 0)
-       PENDING_FILL(RT, EXTEND32 (FCR0));
-      else if (FS == 31)
-       PENDING_FILL(RT, EXTEND32 (FCR31));
-      /* else NOP */
+      unsigned_word  fcr = ValueFCR (FS);
+      TRACE_ALU_INPUT1 (fcr);
+      GPR[RT] = fcr;
     }
+  /* else NOP */
+  TRACE_ALU_RESULT (GPR[RT]);
 }
-010001,00,X,10,5.RT,5.FS,00000000000:COP1Sb:32,f::CxC1
-"c%s<X>c1 r<RT>, f<FS>"
-*mipsIV:
+
+010001,00010,5.RT,5.FS,00000000000:COP1:32,f::CFC1c
+"cfc1 r<RT>, f<FS>"
 *mipsV:
 *mips32:
 *mips64:
+{
+  check_fpu (SD_);
+  if (FS == 0 || FS == 25 || FS == 26 || FS == 28 || FS == 31)
+    {
+      unsigned_word  fcr = ValueFCR (FS);
+      TRACE_ALU_INPUT1 (fcr);
+      GPR[RT] = fcr;
+    }
+  /* else NOP */
+  TRACE_ALU_RESULT (GPR[RT]);
+}
+
+010001,00110,5.RT,5.FS,00000000000:COP1:32,f::CTC1a
+"ctc1 r<RT>, f<FS>"
+*mipsI:
+*mipsII:
+*mipsIII:
+{
+  check_fpu (SD_);
+  if (FS == 31)
+    PENDING_FILL (FCRCS_REGNUM, VL4_8 (GPR[RT]));
+  /* else NOP */
+}
+
+010001,00110,5.RT,5.FS,00000000000:COP1:32,f::CTC1b
+"ctc1 r<RT>, f<FS>"
+*mipsIV:
 *vr4100:
 *vr5000:
 *r3900:
 {
   check_fpu (SD_);
-  if (X)
-    {
-      /* control to */
-      TRACE_ALU_INPUT1 (GPR[RT]);
-      if (FS == 0)
-       {
-         FCR0 = VL4_8(GPR[RT]);
-         TRACE_ALU_RESULT (FCR0);
-       }
-      else if (FS == 31)
-       {
-         FCR31 = VL4_8(GPR[RT]);
-         SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0));
-         TRACE_ALU_RESULT (FCR31);
-       }
-      else
-       {
-         TRACE_ALU_RESULT0 ();
-       }
-      /* else NOP */
-    }
-  else
-    { /* control from */
-      if (FS == 0)
-       {
-         TRACE_ALU_INPUT1 (FCR0);
-         GPR[RT] = EXTEND32 (FCR0);
-       }
-      else if (FS == 31)
-       {
-         TRACE_ALU_INPUT1 (FCR31);
-         GPR[RT] = EXTEND32 (FCR31);
-       }
-      TRACE_ALU_RESULT (GPR[RT]);
-      /* else NOP */
-    }
+  TRACE_ALU_INPUT1 (GPR[RT]);
+  if (FS == 31)
+    StoreFCR (FS, GPR[RT]);
+  /* else NOP */
+}
+
+010001,00110,5.RT,5.FS,00000000000:COP1:32,f::CTC1c
+"ctc1 r<RT>, f<FS>"
+*mipsV:
+*mips32:
+*mips64:
+{
+  check_fpu (SD_);
+  TRACE_ALU_INPUT1 (GPR[RT]);
+  if (FS == 25 || FS == 26 || FS == 28 || FS == 31)
+      StoreFCR (FS, GPR[RT]);
+  /* else NOP */
 }
 
 
 }
 
 
-// DMFC1
-// DMTC1
-010001,00,X,01,5.RT,5.FS,00000000000:COP1Sa:64,f::DMxC1
-"dm%s<X>c1 r<RT>, f<FS>"
+010001,00001,5.RT,5.FS,00000000000:COP1:64,f::DMFC1a
+"dmfc1 r<RT>, f<FS>"
 *mipsIII:
 {
+  unsigned64 v;
   check_fpu (SD_);
   check_u64 (SD_, instruction_0);
-  if (X)
-    {
-      if (SizeFGR() == 64)
-       PENDING_FILL((FS + FGR_BASE),GPR[RT]);
-      else if ((FS & 0x1) == 0)
-       {
-         PENDING_FILL(((FS + 1) + FGR_BASE),VH4_8(GPR[RT]));
-         PENDING_FILL((FS + FGR_BASE),VL4_8(GPR[RT]));
-       }
-    }
+  if (SizeFGR () == 64)
+    v = FGR[FS];
+  else if ((FS & 0x1) == 0)
+    v = SET64HI (FGR[FS+1]) | FGR[FS];
   else
-    {
-      if (SizeFGR() == 64)
-       PENDING_FILL(RT,FGR[FS]);
-      else if ((FS & 0x1) == 0)
-       PENDING_FILL(RT,(SET64HI(FGR[FS+1]) | FGR[FS]));
-      else
-       {
-         if (STATE_VERBOSE_P(SD))
-           sim_io_eprintf (SD,
-             "Warning: PC 0x%lx: semantic_DMxC1_COP1Sa 32-bit use of odd FPR number\n",
-             (long) CIA);
-         PENDING_FILL(RT,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);
-       }
-    }
+    v = SET64HI (0xDEADC0DE) | 0xBAD0BAD0;
+  PENDING_FILL (RT, v);
+  TRACE_ALU_RESULT (v);
 }
-010001,00,X,01,5.RT,5.FS,00000000000:COP1Sb:64,f::DMxC1
-"dm%s<X>c1 r<RT>, f<FS>"
+
+010001,00001,5.RT,5.FS,00000000000:COP1:64,f::DMFC1b
+"dmfc1 r<RT>, f<FS>"
 *mipsIV:
 *mipsV:
 *mips64:
 {
   check_fpu (SD_);
   check_u64 (SD_, instruction_0);
-  if (X)
-    {
-      if (SizeFGR() == 64)
-       StoreFPR (FS, fmt_uninterpreted_64, GPR[RT]);
-      else if ((FS & 0x1) == 0)
-       StoreFPR (FS, fmt_uninterpreted_64, SET64HI (FGR[FS+1]) | FGR[FS]);
-    }
+  if (SizeFGR () == 64)
+    GPR[RT] = FGR[FS];
+  else if ((FS & 0x1) == 0)
+    GPR[RT] = SET64HI (FGR[FS+1]) | FGR[FS];
   else
+    GPR[RT] = SET64HI (0xDEADC0DE) | 0xBAD0BAD0;
+  TRACE_ALU_RESULT (GPR[RT]);
+}
+
+
+010001,00101,5.RT,5.FS,00000000000:COP1:64,f::DMTC1a
+"dmtc1 r<RT>, f<FS>"
+*mipsIII:
+{
+  unsigned64 v;
+  check_fpu (SD_);
+  check_u64 (SD_, instruction_0);
+  if (SizeFGR () == 64)
+    PENDING_FILL ((FS + FGR_BASE), GPR[RT]);
+  else if ((FS & 0x1) == 0)
     {
-      if (SizeFGR() == 64)
-       GPR[RT] = FGR[FS];
-      else if ((FS & 0x1) == 0)
-       GPR[RT] = SET64HI (FGR[FS+1]) | FGR[FS];
-      else
-       {
-         if (STATE_VERBOSE_P(SD))
-           sim_io_eprintf (SD,
-             "Warning: PC 0x%lx: DMxC1 32-bit use of odd FPR number\n",
-                           (long) CIA);
-         GPR[RT] = SET64HI (0xDEADC0DE) | 0xBAD0BAD0;
-       }
+      PENDING_FILL (((FS + 1) + FGR_BASE), VH4_8 (GPR[RT]));
+      PENDING_FILL ((FS + FGR_BASE), VL4_8 (GPR[RT]));
     }
+  else
+    Unpredictable ();
+  TRACE_FP_RESULT (GPR[RT]);
+}
+
+010001,00101,5.RT,5.FS,00000000000:COP1:64,f::DMTC1b
+"dmtc1 r<RT>, f<FS>"
+*mipsIV:
+*mipsV:
+*mips64:
+*vr4100:
+*vr5000:
+*r3900:
+{
+  check_fpu (SD_);
+  check_u64 (SD_, instruction_0);
+  if (SizeFGR () == 64)
+    StoreFPR (FS, fmt_uninterpreted_64, GPR[RT]);
+  else if ((FS & 0x1) == 0)
+    StoreFPR (FS, fmt_uninterpreted_64, GPR[RT]);
+  else
+    Unpredictable ();
 }
 
 
 }
 
 
-// MFC1
-// MTC1
-010001,00,X,00,5.RT,5.FS,00000000000:COP1Sa:32,f::MxC1
-"m%s<X>c1 r<RT>, f<FS>"
+010001,00000,5.RT,5.FS,00000000000:COP1:32,f::MFC1a
+"mfc1 r<RT>, f<FS>"
 *mipsI:
 *mipsII:
 *mipsIII:
 {
+  unsigned64 v;
   check_fpu (SD_);
-  if (X)
-    { /*MTC1*/
-      if (SizeFGR() == 64)
-       {
-         if (STATE_VERBOSE_P(SD))
-           sim_io_eprintf (SD,
-                           "Warning:  PC 0x%lx: MTC1 not DMTC1 with 64 bit regs\n",
-                           (long) CIA);
-         PENDING_FILL ((FS + FGR_BASE), (SET64HI(0xDEADC0DE) | VL4_8(GPR[RT])));
-       }
-      else
-       PENDING_FILL ((FS + FGR_BASE), VL4_8(GPR[RT]));
-    }
-  else /*MFC1*/
-    PENDING_FILL (RT, EXTEND32 (FGR[FS]));
+  v = EXTEND32 (FGR[FS]);
+  PENDING_FILL (RT, v);
+  TRACE_ALU_RESULT (v);
 }
-010001,00,X,00,5.RT,5.FS,00000000000:COP1Sb:32,f::MxC1
-"m%s<X>c1 r<RT>, f<FS>"
+  
+010001,00000,5.RT,5.FS,00000000000:COP1:32,f::MFC1b
+"mfc1 r<RT>, f<FS>"
 *mipsIV:
 *mipsV:
 *mips32:
 *vr4100:
 *vr5000:
 *r3900:
-{
-  int fs = FS;
+{ 
   check_fpu (SD_);
-  if (X)
-    /*MTC1*/
-    StoreFPR (FS, fmt_uninterpreted_32, VL4_8 (GPR[RT]));
-  else /*MFC1*/
-    GPR[RT] = EXTEND32 (FGR[FS]);
+  GPR[RT] = EXTEND32 (FGR[FS]);
+  TRACE_ALU_RESULT (GPR[RT]);
 }
 
 
 }
 
 
-// MTC1 see MxC1
+010001,00100,5.RT,5.FS,00000000000:COP1:32,f::MTC1a
+"mtc1 r<RT>, f<FS>"
+*mipsI:
+*mipsII:
+*mipsIII:
+{ 
+  check_fpu (SD_);
+  if (SizeFGR () == 64)
+    PENDING_FILL ((FS + FGR_BASE), (SET64HI (0xDEADC0DE) | VL4_8 (GPR[RT])));
+  else
+    PENDING_FILL ((FS + FGR_BASE), VL4_8 (GPR[RT]));
+  TRACE_FP_RESULT (GPR[RT]);
+} 
+
+010001,00100,5.RT,5.FS,00000000000:COP1:32,f::MTC1b
+"mtc1 r<RT>, f<FS>"
+*mipsIV:
+*mipsV:
+*mips32:
+*mips64:
+*vr4100:
+*vr5000:
+*r3900:
+{
+  check_fpu (SD_); 
+  StoreFPR (FS, fmt_uninterpreted_32, VL4_8 (GPR[RT]));
+}
 
 
 010001,10,3.FMT,5.FT,5.FS,5.FD,000010:COP1:32,f::MUL.fmt
index 0c3d17b..efbf98a 100644 (file)
@@ -64,6 +64,7 @@ typedef unsigned64 uword64;
 /* Floating-point operations: */
 
 #include "sim-fpu.h"
+#include "cp1.h"
 
 /* FPU registers must be one of the following types. All other values
    are reserved (and undefined). */
@@ -80,17 +81,6 @@ typedef enum {
  fmt_uninterpreted_64 = 0x80000000U,
 } FP_formats;
 
-/* Macro to update FPSR condition-code field. This is complicated by
-   the fact that there is a hole in the index range of the bits within
-   the FCSR register. Also, the number of bits visible depends on the
-   MIPS ISA version being supported. */
-
-#define SETFCC(cc,v) {\
-  int bit = ((cc == 0) ? 23 : (24 + (cc)));\
-  FCSR = ((FCSR & ~(1 << bit)) | ((v) << bit));\
-}
-#define GETFCC(cc) (((((cc) == 0) ? (FCSR & (1 << 23)) : (FCSR & (1 << (24 + (cc))))) != 0) ? 1U : 0)
-
 /* This should be the COC1 value at the start of the preceding
    instruction: */
 #define PREVCOC1() ((STATE & simPCOC1) ? 1 : 0)
@@ -104,36 +94,6 @@ typedef enum {
 #define SizeFGR() (WITH_TARGET_FLOATING_POINT_BITSIZE)
 #endif
 
-/* Standard FCRS bits: */
-#define IR (0) /* Inexact Result */
-#define UF (1) /* UnderFlow */
-#define OF (2) /* OverFlow */
-#define DZ (3) /* Division by Zero */
-#define IO (4) /* Invalid Operation */
-#define UO (5) /* Unimplemented Operation */
-
-/* Get masks for individual flags: */
-#if 1 /* SAFE version */
-#define FP_FLAGS(b)  (((unsigned)(b) < 5) ? (1 << ((b) + 2)) : 0)
-#define FP_ENABLE(b) (((unsigned)(b) < 5) ? (1 << ((b) + 7)) : 0)
-#define FP_CAUSE(b)  (((unsigned)(b) < 6) ? (1 << ((b) + 12)) : 0)
-#else
-#define FP_FLAGS(b)  (1 << ((b) + 2))
-#define FP_ENABLE(b) (1 << ((b) + 7))
-#define FP_CAUSE(b)  (1 << ((b) + 12))
-#endif
-
-#define FP_FS         (1 << 24) /* MIPS III onwards : Flush to Zero */
-
-#define FP_MASK_RM    (0x3)
-#define FP_SH_RM      (0)
-#define FP_RM_NEAREST (0) /* Round to nearest        (Round) */
-#define FP_RM_TOZERO  (1) /* Round to zero           (Trunc) */
-#define FP_RM_TOPINF  (2) /* Round to Plus infinity  (Ceil) */
-#define FP_RM_TOMINF  (3) /* Round to Minus infinity (Floor) */
-#define GETRM()       (int)((FCSR >> FP_SH_RM) & FP_MASK_RM)
-
-
 
 
 
@@ -716,10 +676,18 @@ void store_fpr (SIM_STATE, int fpr, FP_formats fmt, unsigned64 value);
 #define StoreFPR(FPR,FMT,VALUE) store_fpr (SIM_ARGS, (FPR), (FMT), (VALUE))
 
 
+/* FCR access.  */
+unsigned_word value_fcr (SIM_STATE, int fcr);
+#define ValueFCR(FCR) value_fcr (SIM_ARGS, (FCR))
+void store_fcr (SIM_STATE, int fcr, unsigned_word value);
+#define StoreFCR(FCR,VALUE) store_fcr (SIM_ARGS, (FCR), (VALUE))
+void test_fcsr (SIM_STATE);
+#define TestFCSR() test_fcsr (SIM_ARGS)
+
+
 /* FPU operations.  */
-int NaN (unsigned64 op, FP_formats fmt);
-int Less (unsigned64 op1, unsigned64 op2, FP_formats fmt);
-int Equal (unsigned64 op1, unsigned64 op2, FP_formats fmt);
+void fp_cmp (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt, int abs, int cond, int cc);
+#define Compare(op1,op2,fmt,cond,cc) fp_cmp(SIM_ARGS, op1, op2, fmt, 0, cond, cc)
 unsigned64 fp_abs (SIM_STATE, unsigned64 op, FP_formats fmt);
 #define AbsoluteValue(op,fmt) fp_abs(SIM_ARGS, op, fmt)
 unsigned64 fp_neg (SIM_STATE, unsigned64 op, FP_formats fmt);