* Adapted R5900 COP2 interface code to clarified micro-mode interlock
[deliverable/binutils-gdb.git] / sim / mips / interp.c
index cd8a8afaf5359b204e7ea43dcd017d1ee9f7b79e..5ed3d4453b73bd99999c8c8ab97547019b33ff9e 100644 (file)
@@ -43,6 +43,10 @@ code on the hardware.
 #include "sky-vu.h"
 #include "sky-vpe.h"
 #include "sky-libvpe.h"
+#include "sky-pke.h"
+#include "idecode.h"
+#include "support.h"
+#undef SD
 #endif
 /* end-sanitize-sky */
 
@@ -73,12 +77,6 @@ code on the hardware.
 
 #include "sysdep.h"
 
-/* start-sanitize-sky */
-#ifdef TARGET_SKY
-#include "sky-vu.h"
-#endif
-/* end-sanitize-sky */
-
 #ifndef PARAMS
 #define PARAMS(x) 
 #endif
@@ -88,17 +86,15 @@ char* pr_uword64 PARAMS ((uword64 addr));
 
 
 /* Get the simulator engine description, without including the code: */
-#if (WITH_IGEN)
-#define LOADDRMASK (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3)
-#else
+#if !(WITH_IGEN)
 #define SIM_MANIFESTS
 #include "oengine.c"
 #undef SIM_MANIFESTS
 #endif
 
 /* Within interp.c we refer to the sim_state and sim_cpu directly. */
-#define SD sd
 #define CPU cpu
+#define SD sd
 
 
 /* The following reserved instruction value is used when a simulator
@@ -177,8 +173,13 @@ static void open_trace PARAMS((SIM_DESC sd));
 
 static DECLARE_OPTION_HANDLER (mips_option_handler);
 
-#define OPTION_DINERO_TRACE  200
-#define OPTION_DINERO_FILE   201
+enum {
+  OPTION_DINERO_TRACE  = OPTION_START,
+  OPTION_DINERO_FILE
+/* start-sanitize-sky */
+  ,OPTION_FLOAT_TYPE
+/* end-sanitize-sky */
+};
 
 static SIM_RC
 mips_option_handler (sd, cpu, opt, arg, is_command)
@@ -212,7 +213,7 @@ mips_option_handler (sd, cpu, opt, arg, is_command)
            STATE &= ~simTRACE;
          else
            {
-             fprintf (stderr, "Unreconized dinero-trace option `%s'\n", arg);
+             fprintf (stderr, "Unrecognized dinero-trace option `%s'\n", arg);
              return SIM_RC_FAIL;
            }
        }
@@ -243,6 +244,20 @@ Re-compile simulator with \"-DTRACE\" to enable this option.\n");
 #endif /* TRACE */
       return SIM_RC_OK;
 
+/* start-sanitize-sky */
+    case OPTION_FLOAT_TYPE:
+      /* Use host (fast) or target (accurate) floating point implementation. */
+      if (arg && strcmp (arg, "host") == 0)
+       STATE_FP_TYPE_OPT (sd) &= ~STATE_FP_TYPE_OPT_TARGET;
+      else if (arg && strcmp (arg, "target") == 0)
+       STATE_FP_TYPE_OPT (sd) |= STATE_FP_TYPE_OPT_TARGET;
+      else
+       {
+         fprintf (stderr, "Unrecognized float-type option `%s'\n", arg);
+         return SIM_RC_FAIL;
+       }
+      return SIM_RC_OK;
+/* end-sanitize-sky */
     }
 
   return SIM_RC_OK;
@@ -256,6 +271,11 @@ static const OPTION mips_options[] =
   { {"dinero-file", required_argument, NULL, OPTION_DINERO_FILE},
       '\0', "FILE", "Write dinero trace to FILE",
       mips_option_handler },
+/* start-sanitize-sky */
+  { {"float-type", required_argument, NULL, OPTION_FLOAT_TYPE},
+      '\0', "host|target", "Use host (fast) or target (accurate) floating point",
+      mips_option_handler },
+/* end-sanitize-sky */
   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
 };
 
@@ -286,15 +306,6 @@ static void device_init(SIM_DESC sd) {
 #endif
 }
 
-/* start-sanitize-sky */
-#ifdef TARGET_SKY
-static struct {
-  short i[NUM_VU_INTEGER_REGS];
-  int f[NUM_VU_REGS - NUM_VU_INTEGER_REGS];
-} vu_regs[2];
-#endif
-/* end-sanitize-sky */
-
 /*---------------------------------------------------------------------------*/
 /*-- GDB simulator interface ------------------------------------------------*/
 /*---------------------------------------------------------------------------*/
@@ -425,33 +436,16 @@ sim_open (kind, cb, abfd, argv)
     for( rn = 0; rn < NUM_VU_INTEGER_REGS; rn++ ) { 
       cpu->register_widths[rn + NUM_R5900_REGS] = 16;
       cpu->register_widths[rn + NUM_R5900_REGS + NUM_VU_REGS] = 16;
-
-      /* Hack for now - to test gdb interface */
-      vu_regs[0].i[rn] = rn + 0x100;
-      vu_regs[1].i[rn] = rn + 0x200;
     }
 
     for( rn = NUM_VU_INTEGER_REGS; rn < NUM_VU_REGS; rn++ ) { 
-      float f;
-      int first_vec_reg = NUM_VU_INTEGER_REGS + 8;
-
       cpu->register_widths[rn + NUM_R5900_REGS] = 32;
       cpu->register_widths[rn + NUM_R5900_REGS + NUM_VU_REGS] = 32;
-
-      /* Hack for now - to test gdb interface */
-      if( rn < first_vec_reg ) {
-       f = rn - NUM_VU_INTEGER_REGS + 100.0;
-       vu_regs[0].f[rn-NUM_VU_INTEGER_REGS] = *((unsigned *) &f);
-       f = rn - NUM_VU_INTEGER_REGS + 200.0;
-       vu_regs[1].f[rn-NUM_VU_INTEGER_REGS] = *((unsigned *) &f);
-      }
-      else {
-       f = (rn - first_vec_reg)/4 + (rn - first_vec_reg)%4 + 1000.0;
-       vu_regs[0].f[rn-NUM_VU_INTEGER_REGS] = *((unsigned *) &f);
-       f = (rn - first_vec_reg)/4 + (rn - first_vec_reg)%4 + 2000.0;
-       vu_regs[1].f[rn-NUM_VU_INTEGER_REGS] = *((unsigned *) &f);
-      }
     }
+
+    /* Finally the VIF registers */
+    for( rn = 2*NUM_VU_REGS; rn < 2*NUM_VU_REGS + 2*NUM_VIF_REGS; rn++ )
+      cpu->register_widths[rn + NUM_R5900_REGS] = 32;
 #endif
     /* end-sanitize-sky */
   }
@@ -675,28 +669,105 @@ sim_store_register (sd,rn,memory,length)
 #ifdef TARGET_SKY
   if (rn >= NUM_R5900_REGS) 
     {
-      int size = 4;    /* Default register size */
-
       rn = rn - NUM_R5900_REGS;
 
-      if (rn < NUM_VU_INTEGER_REGS)
-       size = write_vu_int_reg (& vu0_device.state->regs, rn, memory);
-      else if( rn < NUM_VU_REGS )
-       vu_regs[0].f[rn - NUM_VU_INTEGER_REGS] 
-         = T2H_4( *(unsigned int *) memory );
-      else {
-       rn = rn - NUM_VU_REGS;
-
-       if( rn < NUM_VU_INTEGER_REGS ) 
-         size = write_vu_int_reg (& vu1_device.state->regs, rn, memory);
-       else if( rn < NUM_VU_REGS )
-         vu_regs[1].f[rn - NUM_VU_INTEGER_REGS] 
-           = T2H_4( *(unsigned int *) memory );
-       else
-         sim_io_eprintf( sd, "Invalid VU register (register store ignored)\n" );
-      }
+      if( rn < NUM_VU_REGS )
+       {
+         if (rn < NUM_VU_INTEGER_REGS)
+           return write_vu_int_reg (&(vu0_device.regs), rn, memory);
+         else if (rn >= FIRST_VEC_REG)
+           {
+             rn -= FIRST_VEC_REG;
+             return write_vu_vec_reg (&(vu0_device.regs), rn>>2, rn&3,
+                                      memory);
+           }
+         else switch (rn - NUM_VU_INTEGER_REGS)
+           {
+           case 0:
+             return write_vu_special_reg (&vu0_device, VU_REG_CIA, 
+                                          memory);
+           case 1:
+             return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MR,
+                                       memory);
+           case 2: /* VU0 has no P register */
+             return 4;
+           case 3:
+             return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MI,
+                                       memory);
+           case 4:
+             return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MQ,
+                                       memory);
+           default:
+             return write_vu_acc_reg (&(vu0_device.regs), 
+                                     rn - (NUM_VU_INTEGER_REGS + 5),
+                                     memory);
+           }
+       }
+
+      rn = rn - NUM_VU_REGS;
+
+      if (rn < NUM_VU_REGS)
+       {
+         if (rn < NUM_VU_INTEGER_REGS) 
+           return write_vu_int_reg (&(vu1_device.regs), rn, memory);
+         else if (rn >= FIRST_VEC_REG)
+           {
+             rn -= FIRST_VEC_REG;
+             return write_vu_vec_reg (&(vu1_device.regs), 
+                                      rn >> 2, rn & 3, memory);
+           }
+         else switch (rn - NUM_VU_INTEGER_REGS)
+           {
+           case 0:
+             return write_vu_special_reg (&vu1_device, VU_REG_CIA,
+                                          memory);
+           case 1:
+             return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MR,
+                                       memory);
+           case 2: 
+             return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MP,
+                                       memory);
+           case 3:
+             return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MI,
+                                       memory);
+           case 4:
+             return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MQ,
+                                       memory);
+           default:
+             return write_vu_acc_reg (&(vu1_device.regs), 
+                                      rn - (NUM_VU_INTEGER_REGS + 5),
+                                      memory);
+           }
+       }
+
+      rn -= NUM_VU_REGS;       /* VIF0 registers are next */
+
+      if (rn < NUM_VIF_REGS)
+       {
+         if (rn < NUM_VIF_REGS-1)
+           return write_pke_reg (&pke0_device, rn, memory);
+         else
+           {
+             sim_io_eprintf( sd, "Can't write vif0_pc (store ignored)\n" );
+             return 0;
+           }
+       }
+
+      rn -= NUM_VIF_REGS;      /* VIF1 registers are last */
+
+      if (rn < NUM_VIF_REGS)
+       {
+         if (rn < NUM_VIF_REGS-1)
+           return write_pke_reg (&pke1_device, rn, memory);
+         else
+           {
+             sim_io_eprintf( sd, "Can't write vif1_pc (store ignored)\n" );
+             return 0;
+           }
+       }
 
-      return size;
+      sim_io_eprintf( sd, "Invalid VU register (register store ignored)\n" );
+      return 0;
     }
 #endif
   /* end-sanitize-sky */
@@ -725,6 +796,8 @@ sim_store_register (sd,rn,memory,length)
       cpu->registers[rn] = T2H_8 (*(unsigned64*)memory);
       return 8;
     }
+
+  return 0;
 }
 
 int
@@ -771,29 +844,97 @@ sim_fetch_register (sd,rn,memory,length)
 #ifdef TARGET_SKY
   if (rn >= NUM_R5900_REGS) 
     {
-      int size = 4; /* default register width */
-
       rn = rn - NUM_R5900_REGS;
 
-      if (rn < NUM_VU_INTEGER_REGS)
-       size = read_vu_int_reg (& vu0_device.state->regs, rn, memory);
-      else if (rn < NUM_VU_REGS)
-       *((unsigned int *) memory) 
-         = H2T_4( vu_regs[0].f[rn - NUM_VU_INTEGER_REGS] );
-      else 
+      if (rn < NUM_VU_REGS)
+       {
+         if (rn < NUM_VU_INTEGER_REGS)
+           return read_vu_int_reg (&(vu0_device.regs), rn, memory);
+         else if (rn >= FIRST_VEC_REG)
+           {
+             rn -= FIRST_VEC_REG;
+             return read_vu_vec_reg (&(vu0_device.regs), rn>>2, rn & 3,
+                                     memory);
+           }
+         else switch (rn - NUM_VU_INTEGER_REGS)
+           {
+           case 0:
+             return read_vu_special_reg(&vu0_device, VU_REG_CIA, memory);
+           case 1:
+             return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MR,
+                                     memory);
+           case 2: /* VU0 has no P register */
+             *((int *) memory) = 0;
+             return 4;
+           case 3:
+             return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MI,
+                                     memory);
+           case 4:
+             return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MQ,
+                                     memory);
+           default:
+             return read_vu_acc_reg (&(vu0_device.regs), 
+                                     rn - (NUM_VU_INTEGER_REGS + 5),
+                                     memory);
+           }
+       }
+
+      rn -= NUM_VU_REGS;       /* VU1 registers are next */
+
+      if (rn < NUM_VU_REGS)
        {
-         rn = rn - NUM_VU_REGS;
-       
          if (rn < NUM_VU_INTEGER_REGS) 
-           size = read_vu_int_reg (& vu1_device.state->regs, rn, memory);
-         else if (rn < NUM_VU_REGS)
-           (*(unsigned int *) memory) 
-             = H2T_4( vu_regs[1].f[rn - NUM_VU_INTEGER_REGS] );
+           return read_vu_int_reg (&(vu1_device.regs), rn, memory);
+         else if (rn >= FIRST_VEC_REG)
+           {
+             rn -= FIRST_VEC_REG;
+             return read_vu_vec_reg (&(vu1_device.regs), 
+                                     rn >> 2, rn & 3, memory);
+           }
+         else switch (rn - NUM_VU_INTEGER_REGS)
+           {
+           case 0:
+             return read_vu_special_reg(&vu1_device, VU_REG_CIA, memory);
+           case 1:
+             return read_vu_misc_reg (&(vu1_device.regs), 
+                                      VU_REG_MR, memory);
+           case 2:
+             return read_vu_misc_reg (&(vu1_device.regs), 
+                                      VU_REG_MP, memory);
+           case 3:
+             return read_vu_misc_reg (&(vu1_device.regs), 
+                                      VU_REG_MI, memory);
+           case 4:
+             return read_vu_misc_reg (&(vu1_device.regs), 
+                                      VU_REG_MQ, memory);
+           default:
+             return read_vu_acc_reg (&(vu1_device.regs), 
+                                     rn - (NUM_VU_INTEGER_REGS + 5),
+                                     memory);
+           }
+       }
+
+      rn -= NUM_VU_REGS;       /* VIF0 registers are next */
+
+      if (rn < NUM_VIF_REGS)
+       {
+         if (rn < NUM_VIF_REGS-1)
+           return read_pke_reg (&pke0_device, rn, memory);
          else
-           sim_io_eprintf( sd, "Invalid VU register (register fetch ignored)\n" );
+           return read_pke_pc (&pke0_device, memory);
        }
 
-      return size;
+      rn -= NUM_VIF_REGS;      /* VIF1 registers are last */
+
+      if (rn < NUM_VIF_REGS)
+       {
+         if (rn < NUM_VIF_REGS-1)
+           return read_pke_reg (&pke1_device, rn, memory);
+         else
+           return read_pke_pc (&pke1_device, memory);
+       }
+
+      sim_io_eprintf( sd, "Invalid VU register (register fetch ignored)\n" );
     }
 #endif
   /* end-sanitize-sky */
@@ -823,6 +964,8 @@ sim_fetch_register (sd,rn,memory,length)
       *(unsigned64*)memory = H2T_8 ((unsigned64)(cpu->registers[rn]));
       return 8;
     }
+
+  return 0;
 }
 
 
@@ -1002,9 +1145,12 @@ sim_monitor (SIM_DESC sd,
       /*      [A0 + 4] = instruction cache size */
       /*      [A0 + 8] = data cache size */
       {
-       address_word value = MEM_SIZE /* FIXME STATE_MEM_SIZE (sd) */;
+       unsigned_4 value = MEM_SIZE /* FIXME STATE_MEM_SIZE (sd) */;
+       unsigned_4 zero = 0;
        H2T (value);
-       sim_write (sd, A0, (char *)&value, sizeof (value));
+       sim_write (sd, A0 + 0, (char *)&value, 4);
+       sim_write (sd, A0 + 4, (char *)&zero, 4);
+       sim_write (sd, A0 + 8, (char *)&zero, 4);
        /* sim_io_eprintf (sd, "sim: get_mem_info() depreciated\n"); */
        break;
       }
@@ -1407,387 +1553,6 @@ ColdReset (SIM_DESC sd)
     }
 }
 
-/* Description from page A-22 of the "MIPS IV Instruction Set" manual
-   (revision 3.1) */
-/* Translate a virtual address to a physical address and cache
-   coherence algorithm describing the mechanism used to resolve the
-   memory reference. Given the virtual address vAddr, and whether the
-   reference is to Instructions ot Data (IorD), find the corresponding
-   physical address (pAddr) and the cache coherence algorithm (CCA)
-   used to resolve the reference. If the virtual address is in one of
-   the unmapped address spaces the physical address and the CCA are
-   determined directly by the virtual address. If the virtual address
-   is in one of the mapped address spaces then the TLB is used to
-   determine the physical address and access type; if the required
-   translation is not present in the TLB or the desired access is not
-   permitted the function fails and an exception is taken.
-
-   NOTE: Normally (RAW == 0), when address translation fails, this
-   function raises an exception and does not return. */
-
-int
-address_translation (SIM_DESC sd,
-                    sim_cpu *cpu,
-                    address_word cia,
-                    address_word vAddr,
-                    int IorD,
-                    int LorS,
-                    address_word *pAddr,
-                    int *CCA,
-                    int raw)
-{
-  int res = -1; /* TRUE : Assume good return */
-
-#ifdef DEBUG
-  sim_io_printf(sd,"AddressTranslation(0x%s,%s,%s,...);\n",pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "iSTORE" : "isLOAD"));
-#endif
-
-  /* Check that the address is valid for this memory model */
-
-  /* For a simple (flat) memory model, we simply pass virtual
-     addressess through (mostly) unchanged. */
-  vAddr &= 0xFFFFFFFF;
-
-  *pAddr = vAddr; /* default for isTARGET */
-  *CCA = Uncached; /* not used for isHOST */
-
-  return(res);
-}
-
-/* Description from page A-23 of the "MIPS IV Instruction Set" manual
-   (revision 3.1) */
-/* Prefetch data from memory. Prefetch is an advisory instruction for
-   which an implementation specific action is taken. The action taken
-   may increase performance, but must not change the meaning of the
-   program, or alter architecturally-visible state. */
-
-void 
-prefetch (SIM_DESC sd,
-         sim_cpu *cpu,
-         address_word cia,
-         int CCA,
-         address_word pAddr,
-         address_word vAddr,
-         int DATA,
-         int hint)
-{
-#ifdef DEBUG
-  sim_io_printf(sd,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint);
-#endif /* DEBUG */
-
-  /* For our simple memory model we do nothing */
-  return;
-}
-
-/* Description from page A-22 of the "MIPS IV Instruction Set" manual
-   (revision 3.1) */
-/* Load a value from memory. Use the cache and main memory as
-   specified in the Cache Coherence Algorithm (CCA) and the sort of
-   access (IorD) to find the contents of AccessLength memory bytes
-   starting at physical location pAddr. The data is returned in the
-   fixed width naturally-aligned memory element (MemElem). The
-   low-order two (or three) bits of the address and the AccessLength
-   indicate which of the bytes within MemElem needs to be given to the
-   processor. If the memory access type of the reference is uncached
-   then only the referenced bytes are read from memory and valid
-   within the memory element. If the access type is cached, and the
-   data is not present in cache, an implementation specific size and
-   alignment block of memory is read and loaded into the cache to
-   satisfy a load reference. At a minimum, the block is the entire
-   memory element. */
-void
-load_memory (SIM_DESC sd,
-            sim_cpu *cpu,
-            address_word cia,
-            uword64* memvalp,
-            uword64* memval1p,
-            int CCA,
-            int AccessLength,
-            address_word pAddr,
-            address_word vAddr,
-            int IorD)
-{
-  uword64 value = 0;
-  uword64 value1 = 0;
-
-#ifdef DEBUG
-  sim_io_printf(sd,"DBG: LoadMemory(%p,%p,%d,%d,0x%s,0x%s,%s)\n",memvalp,memval1p,CCA,AccessLength,pr_addr(pAddr),pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"));
-#endif /* DEBUG */
-
-#if defined(WARN_MEM)
-  if (CCA != uncached)
-    sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
-#endif /* WARN_MEM */
-
-  /* If instruction fetch then we need to check that the two lo-order
-     bits are zero, otherwise raise a InstructionFetch exception: */
-  if ((IorD == isINSTRUCTION)
-      && ((pAddr & 0x3) != 0)
-      && (((pAddr & 0x1) != 0) || ((vAddr & 0x1) == 0)))
-    SignalExceptionInstructionFetch ();
-
-  if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
-    {
-      /* In reality this should be a Bus Error */
-      sim_io_error (sd, "AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",
-                   AccessLength,
-                   (LOADDRMASK + 1) << 2,
-                   pr_addr (pAddr));
-    }
-
-#if defined(TRACE)
-  dotrace (SD, CPU, tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
-#endif /* TRACE */
-  
-  /* Read the specified number of bytes from memory.  Adjust for
-     host/target byte ordering/ Align the least significant byte
-     read. */
-
-  switch (AccessLength)
-    {
-    case AccessLength_QUADWORD :
-      {
-       unsigned_16 val = sim_core_read_aligned_16 (cpu, NULL_CIA, read_map, pAddr);
-       value1 = VH8_16 (val);
-       value = VL8_16 (val);
-       break;
-      }
-    case AccessLength_DOUBLEWORD :
-      value = sim_core_read_aligned_8 (cpu, NULL_CIA,
-                                      read_map, pAddr);
-      break;
-    case AccessLength_SEPTIBYTE :
-      value = sim_core_read_misaligned_7 (cpu, NULL_CIA,
-                                         read_map, pAddr);
-      break;
-    case AccessLength_SEXTIBYTE :
-      value = sim_core_read_misaligned_6 (cpu, NULL_CIA,
-                                         read_map, pAddr);
-      break;
-    case AccessLength_QUINTIBYTE :
-      value = sim_core_read_misaligned_5 (cpu, NULL_CIA,
-                                         read_map, pAddr);
-      break;
-    case AccessLength_WORD :
-      value = sim_core_read_aligned_4 (cpu, NULL_CIA,
-                                      read_map, pAddr);
-      break;
-    case AccessLength_TRIPLEBYTE :
-      value = sim_core_read_misaligned_3 (cpu, NULL_CIA,
-                                         read_map, pAddr);
-      break;
-    case AccessLength_HALFWORD :
-      value = sim_core_read_aligned_2 (cpu, NULL_CIA,
-                                      read_map, pAddr);
-      break;
-    case AccessLength_BYTE :
-      value = sim_core_read_aligned_1 (cpu, NULL_CIA,
-                                      read_map, pAddr);
-      break;
-    default:
-      abort ();
-    }
-  
-#ifdef DEBUG
-  printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
-        (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
-#endif /* DEBUG */
-  
-  /* See also store_memory. */
-  if (AccessLength <= AccessLength_DOUBLEWORD)
-    {
-      if (BigEndianMem)
-       /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
-          shifted to the most significant byte position.  */
-       value <<= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8);
-      else
-       /* For little endian target, byte (pAddr&LOADDRMASK == 0)
-          is already in the correct postition. */
-       value <<= ((pAddr & LOADDRMASK) * 8);
-    }
-  
-#ifdef DEBUG
-  printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
-        pr_uword64(value1),pr_uword64(value));
-#endif /* DEBUG */
-  
-  *memvalp = value;
-  if (memval1p) *memval1p = value1;
-}
-
-
-/* Description from page A-23 of the "MIPS IV Instruction Set" manual
-   (revision 3.1) */
-/* Store a value to memory. The specified data is stored into the
-   physical location pAddr using the memory hierarchy (data caches and
-   main memory) as specified by the Cache Coherence Algorithm
-   (CCA). The MemElem contains the data for an aligned, fixed-width
-   memory element (word for 32-bit processors, doubleword for 64-bit
-   processors), though only the bytes that will actually be stored to
-   memory need to be valid. The low-order two (or three) bits of pAddr
-   and the AccessLength field indicates which of the bytes within the
-   MemElem data should actually be stored; only these bytes in memory
-   will be changed. */
-
-void
-store_memory (SIM_DESC sd,
-             sim_cpu *cpu,
-             address_word cia,
-             int CCA,
-             int AccessLength,
-             uword64 MemElem,
-             uword64 MemElem1,   /* High order 64 bits */
-             address_word pAddr,
-             address_word vAddr)
-{
-#ifdef DEBUG
-  sim_io_printf(sd,"DBG: StoreMemory(%d,%d,0x%s,0x%s,0x%s,0x%s)\n",CCA,AccessLength,pr_uword64(MemElem),pr_uword64(MemElem1),pr_addr(pAddr),pr_addr(vAddr));
-#endif /* DEBUG */
-  
-#if defined(WARN_MEM)
-  if (CCA != uncached)
-    sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
-#endif /* WARN_MEM */
-  
-  if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
-    sim_io_error(sd,"AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",AccessLength,(LOADDRMASK + 1)<<2,pr_addr(pAddr));
-  
-#if defined(TRACE)
-  dotrace (SD, CPU, tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
-#endif /* TRACE */
-  
-#ifdef DEBUG
-  printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
-#endif /* DEBUG */
-  
-  /* See also load_memory */
-  if (AccessLength <= AccessLength_DOUBLEWORD)
-    {
-      if (BigEndianMem)
-       /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
-          shifted to the most significant byte position.  */
-       MemElem >>= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8);
-      else
-       /* For little endian target, byte (pAddr&LOADDRMASK == 0)
-          is already in the correct postition. */
-       MemElem >>= ((pAddr & LOADDRMASK) * 8);
-    }
-  
-#ifdef DEBUG
-  printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
-#endif /* DEBUG */
-  
-  switch (AccessLength)
-    {
-    case AccessLength_QUADWORD :
-      {
-       unsigned_16 val = U16_8 (MemElem1, MemElem);
-       sim_core_write_aligned_16 (cpu, NULL_CIA, write_map, pAddr, val);
-       break;
-      }
-    case AccessLength_DOUBLEWORD :
-      sim_core_write_aligned_8 (cpu, NULL_CIA,
-                               write_map, pAddr, MemElem);
-      break;
-    case AccessLength_SEPTIBYTE :
-      sim_core_write_misaligned_7 (cpu, NULL_CIA,
-                                  write_map, pAddr, MemElem);
-      break;
-    case AccessLength_SEXTIBYTE :
-      sim_core_write_misaligned_6 (cpu, NULL_CIA,
-                                  write_map, pAddr, MemElem);
-      break;
-    case AccessLength_QUINTIBYTE :
-      sim_core_write_misaligned_5 (cpu, NULL_CIA,
-                                  write_map, pAddr, MemElem);
-      break;
-    case AccessLength_WORD :
-      sim_core_write_aligned_4 (cpu, NULL_CIA,
-                               write_map, pAddr, MemElem);
-      break;
-    case AccessLength_TRIPLEBYTE :
-      sim_core_write_misaligned_3 (cpu, NULL_CIA,
-                                  write_map, pAddr, MemElem);
-      break;
-    case AccessLength_HALFWORD :
-      sim_core_write_aligned_2 (cpu, NULL_CIA,
-                               write_map, pAddr, MemElem);
-      break;
-    case AccessLength_BYTE :
-      sim_core_write_aligned_1 (cpu, NULL_CIA,
-                               write_map, pAddr, MemElem);
-      break;
-    default:
-      abort ();
-    }  
-  
-  return;
-}
-
-
-unsigned32
-ifetch32 (SIM_DESC sd,
-         sim_cpu *cpu,
-         address_word cia,
-         address_word vaddr)
-{
-  /* Copy the action of the LW instruction */
-  address_word reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0);
-  address_word bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0);
-  unsigned64 value;
-  address_word paddr;
-  unsigned32 instruction;
-  unsigned byte;
-  int cca;
-  AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &cca, isTARGET, isREAL);
-  paddr = ((paddr & ~LOADDRMASK) | ((paddr & LOADDRMASK) ^ (reverse << 2)));
-  LoadMemory (&value, NULL, cca, AccessLength_WORD, paddr, vaddr, isINSTRUCTION, isREAL);
-  byte = ((vaddr & LOADDRMASK) ^ (bigend << 2));
-  instruction = ((value >> (8 * byte)) & 0xFFFFFFFF);
-  return instruction;
-}
-
-
-unsigned16
-ifetch16 (SIM_DESC sd,
-         sim_cpu *cpu,
-         address_word cia,
-         address_word vaddr)
-{
-  /* Copy the action of the LW instruction */
-  address_word reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0);
-  address_word bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0);
-  unsigned64 value;
-  address_word paddr;
-  unsigned16 instruction;
-  unsigned byte;
-  int cca;
-  AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &cca, isTARGET, isREAL);
-  paddr = ((paddr & ~LOADDRMASK) | ((paddr & LOADDRMASK) ^ (reverse << 2)));
-  LoadMemory (&value, NULL, cca, AccessLength_WORD, paddr, vaddr, isINSTRUCTION, isREAL);
-  byte = ((vaddr & LOADDRMASK) ^ (bigend << 2));
-  instruction = ((value >> (8 * byte)) & 0xFFFFFFFF);
-  return instruction;
-}
-
-
-/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
-/* Order loads and stores to synchronise shared memory. Perform the
-   action necessary to make the effects of groups of synchronizable
-   loads and stores indicated by stype occur in the same order for all
-   processors. */
-void
-sync_operation (SIM_DESC sd,
-               sim_cpu *cpu,
-               address_word cia,
-               int stype)
-{
-#ifdef DEBUG
-  sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype);
-#endif /* DEBUG */
-  return;
-}
-
 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
 /* Signal an exception condition. This will result in an exception
    that aborts the instruction. The instruction operation pseudocode
@@ -1830,7 +1595,7 @@ signal_exception (SIM_DESC sd,
         code = (instruction >> 6) & 0xFFFFF;
         
         sim_io_eprintf(sd,"Ignoring instruction `syscall %d' (PC 0x%s)\n",
-                    code, pr_addr(cia));
+                      code, pr_addr(cia));
       }
      break;
 
@@ -1891,7 +1656,7 @@ signal_exception (SIM_DESC sd,
           sim_engine_restart (sd, NULL, NULL, NULL_CIA);
         }
        /* else fall through to normal exception processing */
-       sim_io_eprintf(sd,"ReservedInstruction 0x%08X at PC = 0x%s\n",instruction,pr_addr(cia));
+       sim_io_eprintf(sd,"ReservedInstruction at PC = 0x%s\n", pr_addr (cia));
      }
 
     case BreakPoint:
@@ -2042,82 +1807,6 @@ undefined_result(sd,cia)
 }
 #endif /* WARN_RESULT */
 
-void
-cache_op (SIM_DESC sd,
-         sim_cpu *cpu,
-         address_word cia,
-         int op,
-         address_word pAddr,
-         address_word vAddr,
-         unsigned int instruction)
-{
-#if 1 /* stop warning message being displayed (we should really just remove the code) */
-  static int icache_warning = 1;
-  static int dcache_warning = 1;
-#else
-  static int icache_warning = 0;
-  static int dcache_warning = 0;
-#endif
-
-  /* If CP0 is not useable (User or Supervisor mode) and the CP0
-     enable bit in the Status Register is clear - a coprocessor
-     unusable exception is taken. */
-#if 0
-  sim_io_printf(sd,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia));
-#endif
-
-  switch (op & 0x3) {
-    case 0: /* instruction cache */
-      switch (op >> 2) {
-        case 0: /* Index Invalidate */
-        case 1: /* Index Load Tag */
-        case 2: /* Index Store Tag */
-        case 4: /* Hit Invalidate */
-        case 5: /* Fill */
-        case 6: /* Hit Writeback */
-          if (!icache_warning)
-            {
-              sim_io_eprintf(sd,"Instruction CACHE operation %d to be coded\n",(op >> 2));
-              icache_warning = 1;
-            }
-          break;
-
-        default:
-          SignalException(ReservedInstruction,instruction);
-          break;
-      }
-      break;
-
-    case 1: /* data cache */
-      switch (op >> 2) {
-        case 0: /* Index Writeback Invalidate */
-        case 1: /* Index Load Tag */
-        case 2: /* Index Store Tag */
-        case 3: /* Create Dirty */
-        case 4: /* Hit Invalidate */
-        case 5: /* Hit Writeback Invalidate */
-        case 6: /* Hit Writeback */ 
-          if (!dcache_warning)
-            {
-              sim_io_eprintf(sd,"Data CACHE operation %d to be coded\n",(op >> 2));
-              dcache_warning = 1;
-            }
-          break;
-
-        default:
-          SignalException(ReservedInstruction,instruction);
-          break;
-      }
-      break;
-
-    default: /* unrecognised cache ID */
-      SignalException(ReservedInstruction,instruction);
-      break;
-  }
-
-  return;
-}
-
 /*-- FPU support routines ---------------------------------------------------*/
 
 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
@@ -3248,6 +2937,8 @@ cop_ld (SIM_DESC sd,
 }
 
 
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
 void
 cop_lq (SIM_DESC sd,
        sim_cpu *cpu,
@@ -3258,12 +2949,23 @@ cop_lq (SIM_DESC sd,
 {
   switch (coproc_num)
     {
-      /* start-sanitize-sky */
     case 2:
-      /* XXX COP2 */
-      break;
-      /* end-sanitize-sky */
-      
+      {
+       unsigned_16 xyzw;
+
+       while(vu0_busy())
+         vu0_issue(sd);
+       
+       memcpy(& xyzw, & memword, sizeof(xyzw));
+       xyzw = H2T_16(xyzw);
+       /* one word at a time, argh! */
+       write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 0, A4_16(& xyzw, 3));
+       write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 1, A4_16(& xyzw, 2));
+       write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 2, A4_16(& xyzw, 1));
+       write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 3, A4_16(& xyzw, 0));
+      }
+    break;
+    
     default:
       sim_io_printf(sd,"COP_LQ(%d,%d,??) at PC = 0x%s : TODO (architecture specific)\n",
                    coproc_num,coproc_reg,pr_addr(cia));
@@ -3272,6 +2974,8 @@ cop_lq (SIM_DESC sd,
   
   return;
 }
+#endif /* TARGET_SKY */
+/* end-sanitize-sky */
 
 
 unsigned int
@@ -3334,6 +3038,8 @@ cop_sd (SIM_DESC sd,
 }
 
 
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
 unsigned128
 cop_sq (SIM_DESC sd,
        sim_cpu *cpu,
@@ -3341,15 +3047,26 @@ cop_sq (SIM_DESC sd,
        int coproc_num,
        int coproc_reg)
 {
-  unsigned128 value = {0, 0};
+  unsigned128 value = U16_8(0, 0);
   switch (coproc_num)
     {
-      /* start-sanitize-sky */
     case 2:
-      /* XXX COP2 */
-      break;
-      /* end-sanitize-sky */
+      {
+       unsigned_16 xyzw;
 
+       while(vu0_busy())
+         vu0_issue(sd);
+       
+       /* one word at a time, argh! */
+       read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 0, A4_16(& xyzw, 3));
+       read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 1, A4_16(& xyzw, 2));
+       read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 2, A4_16(& xyzw, 1));
+       read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 3, A4_16(& xyzw, 0));
+       xyzw = T2H_16(xyzw);
+       return xyzw;
+      }
+    break;
+    
     default:
       sim_io_printf(sd,"COP_SQ(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",
                    coproc_num,coproc_reg,pr_addr(cia));
@@ -3358,6 +3075,8 @@ cop_sq (SIM_DESC sd,
 
   return(value);
 }
+#endif /* TARGET_SKY */
+/* end-sanitize-sky */
 
 
 void
@@ -3500,7 +3219,7 @@ decode_coproc (SIM_DESC sd,
       }
     break;
     
-    case 2: /* undefined co-processor */
+    case 2: /* co-processor 2 */
       {
        int handle = 0;
 
@@ -3510,17 +3229,18 @@ decode_coproc (SIM_DESC sd,
 
        int i_25_21 = (instruction >> 21) & 0x1f;
        int i_20_16 = (instruction >> 16) & 0x1f;
+       int i_20_6 = (instruction >> 6) & 0x7fff;
        int i_15_11 = (instruction >> 11) & 0x1f;
        int i_15_0 = instruction & 0xffff;
        int i_10_1 = (instruction >> 1) & 0x3ff;
+       int i_10_0 = instruction & 0x7ff;
+       int i_10_6 = (instruction >> 6) & 0x1f;
+       int i_5_0 = instruction & 0x03f;
        int interlock = instruction & 0x01;
-       unsigned_4 vpe_status = sim_core_read_aligned_4 (cpu, cia, read_map, VPE0_STAT);
-       int vpe_busy = (vpe_status & 0x00000001);
        /* setup for semantic.c-like actions below */
        typedef unsigned_4 instruction_word;
        int CIA = cia;
        int NIA = cia + 4;
-       sim_cpu* CPU_ = cpu;
 
        handle = 1;
 
@@ -3531,107 +3251,194 @@ decode_coproc (SIM_DESC sd,
            /* NOTREACHED */
          }
 
+#define MY_INDEX  itable_COPz_NORMAL
+#define MY_PREFIX COPz_NORMAL
+#define MY_NAME "COPz_NORMAL"
+
        /* classify & execute basic COP2 instructions */
        if(i_25_21 == 0x08 && i_20_16 == 0x00) /* BC2F */
          {
            address_word offset = EXTEND16(i_15_0) << 2;
-           if(! vpe_busy) DELAY_SLOT(cia + 4 + offset);
+           if(! vu0_busy()) DELAY_SLOT(cia + 4 + offset);
          }
        else if(i_25_21 == 0x08 && i_20_16==0x02) /* BC2FL */
          {
            address_word offset = EXTEND16(i_15_0) << 2;
-           if(! vpe_busy) DELAY_SLOT(cia + 4 + offset);
+           if(! vu0_busy()) DELAY_SLOT(cia + 4 + offset);
            else NULLIFY_NEXT_INSTRUCTION();
          }
        else if(i_25_21 == 0x08 && i_20_16 == 0x01) /* BC2T */
          {
            address_word offset = EXTEND16(i_15_0) << 2;
-           if(vpe_busy) DELAY_SLOT(cia + 4 + offset);
+           if(vu0_busy()) DELAY_SLOT(cia + 4 + offset);
          }
        else if(i_25_21 == 0x08 && i_20_16 == 0x03) /* BC2TL */
          {
            address_word offset = EXTEND16(i_15_0) << 2;
-           if(vpe_busy) DELAY_SLOT(cia + 4 + offset);
+           if(vu0_busy()) DELAY_SLOT(cia + 4 + offset);
            else NULLIFY_NEXT_INSTRUCTION();
          }
        else if((i_25_21 == 0x02 && i_10_1 == 0x000) || /* CFC2 */
-               (i_25_21 == 0x06 && i_10_1 == 0x000)) /* CTC2 */
+               (i_25_21 == 0x01)) /* QMFC2 */
          {
            int rt = i_20_16;
            int id = i_15_11;
-           int to_vu = (i_25_21 == 0x06); /* transfer direction */
-           address_word vu_cr_addr; /* VU control register address */
-
-           if(interlock)
-             while(vpe_busy)
-               {
-                 vu0_issue(sd); /* advance one clock cycle */
-                 vpe_status = sim_core_read_aligned_4 (cpu, cia, read_map, VPE0_STAT);
-                 vpe_busy = vpe_status & 0x00000001;
-               }
-
-           /* compute VU register address */
-           vu_cr_addr = VU0_MST + (id * 16);
-
-           /* read or write word */
-           if(to_vu) /* CTC2 */
+
+           /* interlock checking */
+           /* POLICY: never busy in macro mode */
+           while(vu0_busy() && interlock)
+             vu0_issue(sd);
+
+           /* perform VU register address */
+           if(i_25_21 == 0x01) /* QMFC2 */
              {
-               unsigned_4 data = GPR[rt];
-               sim_core_write_aligned_4(cpu, cia, write_map, vu_cr_addr, data);
+               unsigned_16 xyzw;
+               /* one word at a time, argh! */
+               read_vu_vec_reg(&(vu0_device.regs), id, 0, A4_16(& xyzw, 3));
+               read_vu_vec_reg(&(vu0_device.regs), id, 1, A4_16(& xyzw, 2));
+               read_vu_vec_reg(&(vu0_device.regs), id, 2, A4_16(& xyzw, 1));
+               read_vu_vec_reg(&(vu0_device.regs), id, 3, A4_16(& xyzw, 0));
+               xyzw = T2H_16(xyzw);
+               memcpy(& GPR[rt], & xyzw, sizeof(xyzw));
              }
            else /* CFC2 */
              {
-               unsigned_4 data = sim_core_read_aligned_4(cpu, cia, read_map, vu_cr_addr);
-               GPR[rt] = EXTEND64(data);
+               unsigned_4 data;
+               /* enum + int calculation, argh! */
+               id = VU_REG_MST + 16 * id;
+               read_vu_misc_reg(&(vu0_device.regs), id, & data);
+               GPR[rt] = EXTEND32(T2H_4(data));
              }
          }
-       else if((i_25_21 == 0x01) || /* QMFC2 */
-               (i_25_21 == 0x05))   /* QMTC2 */
+       else if((i_25_21 == 0x06 && i_10_1 == 0x000) || /* CTC2 */
+               (i_25_21 == 0x05)) /* QMTC2 */
          {
            int rt = i_20_16;
            int id = i_15_11;
-           int to_vu = (i_25_21 == 0x05); /* transfer direction */
-           address_word vu_cr_addr; /* VU control register address */
-
-           if(interlock)
-             while(vpe_busy)
-               {
-                 vu0_issue(sd); /* advance one clock cycle */
-                 vpe_status = sim_core_read_aligned_4 (cpu, cia, read_map, VPE0_STAT);
-                 vpe_busy = vpe_status & 0x00000001;
-               }
-
-           /* compute VU register address */
-           vu_cr_addr = VU0_VF00 + (id * 16);
-
-           /* read or write word */
-           if(to_vu) /* CTC2 */
+
+           /* interlock checking: wait until M or E bits set */
+           /* POLICY: never busy in macro mode */
+           while(vu0_busy() && interlock)
              {
-               unsigned_4 data = GPR[rt];
-               sim_core_write_aligned_4(cpu, cia, write_map, vu_cr_addr, data);
+               if(vu0_micro_interlock_released())
+                 {
+                   vu0_micro_interlock_clear();
+                   break;
+                 }
+
+               vu0_issue(sd);
              }
-           else /* CFC2 */
+           
+           /* perform VU register address */
+           if(i_25_21 == 0x05) /* QMTC2 */
              {
-               unsigned_4 data = sim_core_read_aligned_4(cpu, cia, read_map, vu_cr_addr);
-               GPR[rt] = EXTEND64(data);
+               unsigned_16 xyzw;
+               memcpy(& xyzw, & GPR[rt], sizeof(xyzw));
+               xyzw = H2T_16(xyzw);
+               /* one word at a time, argh! */
+               write_vu_vec_reg(&(vu0_device.regs), id, 0, A4_16(& xyzw, 3));
+               write_vu_vec_reg(&(vu0_device.regs), id, 1, A4_16(& xyzw, 2));
+               write_vu_vec_reg(&(vu0_device.regs), id, 2, A4_16(& xyzw, 1));
+               write_vu_vec_reg(&(vu0_device.regs), id, 3, A4_16(& xyzw, 0));
              }
+           else /* CTC2 */
+             {
+               unsigned_4 data = H2T_4(GPR[rt]);
+               /* enum + int calculation, argh! */
+               id = VU_REG_MST + 16 * id;
+               write_vu_misc_reg(&(vu0_device.regs), id, & data);
+             }
+         }
+       else if(i_10_0 == 0x3bf) /* VWAITQ */
+         {
+           while(vu0_q_busy())
+             vu0_issue(sd);
+         }
+       else if(i_5_0 == 0x38) /* VCALLMS */
+         {
+           unsigned_4 data = H2T_2(i_20_6);
+
+           while(vu0_busy())
+             vu0_issue(sd);
+
+           /* write to reserved CIA register to get VU0 moving */
+           write_vu_special_reg(& vu0_device, VU_REG_CIA, & data);
+
+           ASSERT(vu0_busy());
+         }
+       else if(i_5_0 == 0x39) /* VCALLMSR */
+         {
+           unsigned_4 data;
+
+           while(vu0_busy())
+             vu0_issue(sd);
+
+           read_vu_special_reg(& vu0_device, VU_REG_CMSAR0, & data);
+           /* write to reserved CIA register to get VU0 moving */
+           write_vu_special_reg(& vu0_device, VU_REG_CIA, & data);
+
+           ASSERT(vu0_busy());
          }
-       /* other COP2 instructions */
+       /* handle all remaining UPPER VU instructions in one block */
+       else if((i_5_0 <  0x30) || /* VADDx .. VMINI */
+               (i_5_0 >= 0x3c && i_10_6 < 0x0c)) /* VADDAx .. VNOP */
+         {
+           unsigned_4 vu_upper, vu_lower;
+           vu_upper =
+             0x00000000 | /* bits 31 .. 25 */
+             (instruction & 0x01ffffff); /* bits 24 .. 0 */
+           vu_lower = 0x8000033c; /* NOP */
+
+           /* POLICY: never busy in macro mode */
+           while(vu0_busy())
+             vu0_issue(sd);
+
+           vu0_macro_issue(vu_upper, vu_lower);
+
+           /* POLICY: wait for completion of macro-instruction */
+           while(vu0_busy())
+             vu0_issue(sd);
+         }
+       /* handle all remaining LOWER VU instructions in one block */
+       else if((i_5_0 >= 0x30 && i_5_0 <= 0x35) || /* VIADD .. VIOR */
+               (i_5_0 >= 0x3c && i_10_6 >= 0x0c)) /* VMOVE .. VRXOR */
+         {                            /* N.B.: VWAITQ already covered by prior case */
+           unsigned_4 vu_upper, vu_lower;
+           vu_upper = 0x000002ff; /* NOP/NOP */
+           vu_lower =
+             0x80000000 | /* bits 31 .. 25 */
+             (instruction & 0x01ffffff); /* bits 24 .. 0 */
+
+           /* POLICY: never busy in macro mode */
+           while(vu0_busy())
+             vu0_issue(sd);
+
+           vu0_macro_issue(vu_upper, vu_lower);
+
+           /* POLICY: wait for completion of macro-instruction */
+           while(vu0_busy())
+             vu0_issue(sd);
+         }
+       /* ... no other COP2 instructions ... */
        else
          {
-           SignalException(ReservedInstruction,instruction); 
+           SignalException(ReservedInstruction, instruction); 
            /* NOTREACHED */
          }
        
        /* cleanup for semantic.c-like actions above */
        PC = NIA;
 
+#undef MY_INDEX
+#undef MY_PREFIX
+#undef MY_NAME
+
 #endif /* TARGET_SKY */
        /* end-sanitize-sky */
 
        if(! handle)
          {
-           sim_io_eprintf(sd,"COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
+           sim_io_eprintf(sd, "COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
                           instruction,pr_addr(cia));
          }
       }
@@ -3927,72 +3734,6 @@ pr_uword64(addr)
 }
 
 
-void
-pending_tick (SIM_DESC sd,
-             sim_cpu *cpu,
-             address_word cia)
-{
-  if (PENDING_TRACE)                                                   
-    sim_io_printf (sd, "PENDING_DRAIN - pending_in = %d, pending_out = %d, pending_total = %d\n", PENDING_IN, PENDING_OUT, PENDING_TOTAL); 
-  if (PENDING_OUT != PENDING_IN)                                       
-    {                                                                  
-      int loop;                                                        
-      int index = PENDING_OUT;                                 
-      int total = PENDING_TOTAL;                                       
-      if (PENDING_TOTAL == 0)                                          
-       sim_engine_abort (SD, CPU, cia, "PENDING_DRAIN - Mis-match on pending update pointers\n"); 
-      for (loop = 0; (loop < total); loop++)                           
-       {                                                               
-         if (PENDING_SLOT_DEST[index] != NULL)                 
-           {                                                           
-             PENDING_SLOT_DELAY[index] -= 1;                           
-             if (PENDING_SLOT_DELAY[index] == 0)                       
-               {                                                       
-                 if (PENDING_SLOT_BIT[index] >= 0)                     
-                   switch (PENDING_SLOT_SIZE[index])                 
-                     {                                         
-                     case 32:                                  
-                       if (PENDING_SLOT_VALUE[index])          
-                         *(unsigned32*)PENDING_SLOT_DEST[index] |=     
-                           BIT32 (PENDING_SLOT_BIT[index]);            
-                       else                                            
-                         *(unsigned32*)PENDING_SLOT_DEST[index] &=     
-                           BIT32 (PENDING_SLOT_BIT[index]);            
-                       break;                                  
-                     case 64:                                  
-                       if (PENDING_SLOT_VALUE[index])          
-                         *(unsigned64*)PENDING_SLOT_DEST[index] |=     
-                           BIT64 (PENDING_SLOT_BIT[index]);            
-                       else                                            
-                         *(unsigned64*)PENDING_SLOT_DEST[index] &=     
-                           BIT64 (PENDING_SLOT_BIT[index]);            
-                       break;                                  
-                       break;                                  
-                     }
-                 else
-                   switch (PENDING_SLOT_SIZE[index])                 
-                     {                                         
-                     case 32:                                  
-                       *(unsigned32*)PENDING_SLOT_DEST[index] =        
-                         PENDING_SLOT_VALUE[index];                    
-                       break;                                  
-                     case 64:                                  
-                       *(unsigned64*)PENDING_SLOT_DEST[index] =        
-                         PENDING_SLOT_VALUE[index];                    
-                       break;                                  
-                     }                                                 
-               }                                                       
-             if (PENDING_OUT == index)                         
-               {                                                       
-                 PENDING_SLOT_DEST[index] = NULL;                      
-                 PENDING_OUT = (PENDING_OUT + 1) % PSLOTS;             
-                 PENDING_TOTAL--;                                      
-               }                                                       
-           }                                                           
-       }                                                               
-      index = (index + 1) % PSLOTS;                                    
-    }                                                                  
-}
 
 /*---------------------------------------------------------------------------*/
 /*> EOF interp.c <*/
This page took 0.038206 seconds and 4 git commands to generate.