Implement 32 bit MIPS16 instructions listed in m16.igen.
[deliverable/binutils-gdb.git] / sim / mips / interp.c
index ec9bd0c50eb9aa3b413048a18ac6cd491af149d2..a8788d7393926152a8aa0622b78cac8381a585d7 100644 (file)
@@ -14,8 +14,7 @@
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
    $Revision$
-     $Author$
-       $Date$             
+   $Date$             
 
 NOTEs:
 
@@ -39,6 +38,16 @@ code on the hardware.
 #include "sim-options.h"
 #include "sim-assert.h"
 
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#include "sky-vu.h"
+#include "sky-vpe.h"
+#include "sky-libvpe.h"
+#include "sky-pke.h"
+#include "idecode.h"
+#endif
+/* end-sanitize-sky */
+
 #include "config.h"
 
 #include <stdio.h>
@@ -75,9 +84,7 @@ 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
@@ -149,6 +156,13 @@ static void ColdReset PARAMS((SIM_DESC sd));
 #define MONITOR_SIZE (1 << 11)
 #define MEM_SIZE (2 << 20)
 
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#undef MEM_SIZE
+#define MEM_SIZE (16 << 20) /* 16 MB */
+#endif
+/* end-sanitize-sky */
+
 #if defined(TRACE)
 static char *tracefile = "trace.din"; /* default filename for trace log */
 FILE *tracefh = NULL;
@@ -157,8 +171,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)
@@ -177,7 +196,7 @@ mips_option_handler (sd, cpu, opt, arg, is_command)
         allow external control of the program points being traced
         (i.e. only from main onwards, excluding the run-time setup,
         etc.). */
-      for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++)
+      for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
        {
          sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
          if (arg == NULL)
@@ -192,7 +211,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;
            }
        }
@@ -223,6 +242,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;
@@ -236,6 +269,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 }
 };
 
@@ -266,15 +304,6 @@ static void device_init(SIM_DESC sd) {
 #endif
 }
 
-/* start-sanitize-sky */
-#ifdef TARGET_SKY
-static struct {
-  short i[16];
-  int f[NUM_VU_REGS - 16];
-} vu_regs[2];
-#endif
-/* end-sanitize-sky */
-
 /*---------------------------------------------------------------------------*/
 /*-- GDB simulator interface ------------------------------------------------*/
 /*---------------------------------------------------------------------------*/
@@ -310,10 +339,22 @@ sim_open (kind, cb, abfd, argv)
      are the kernel spaces K0 & K1.  Both of these map to a single
      smaller sub region */
   sim_do_command(sd," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */
+/* start-sanitize-sky */
+#ifndef TARGET_SKY
+/* end-sanitize-sky */
   sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
                   K1BASE, K0SIZE,
                   MEM_SIZE, /* actual size */
                   K0BASE);
+/* start-sanitize-sky */
+#else
+  sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x,0x%0x",
+                  K1BASE, K0SIZE,
+                  MEM_SIZE, /* actual size */
+                  K0BASE, 
+                  0); /* add alias at 0x0000 */
+#endif
+/* end-sanitize-sky */
 
   device_init(sd);
 
@@ -390,35 +431,19 @@ sim_open (kind, cb, abfd, argv)
     /* start-sanitize-sky */
 #ifdef TARGET_SKY
     /* Now the VU registers */
-    for( rn = 0; rn < 16; rn++ ) { /* first the integer registers */
+    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 = 16; rn < NUM_VU_REGS; rn++ ) { /* then the FP registers */
-      float f;
-
+    for( rn = NUM_VU_INTEGER_REGS; rn < NUM_VU_REGS; rn++ ) { 
       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 < 24 ) {
-       f = rn - 16 + 100.0;
-       vu_regs[0].f[rn-16] = *((unsigned *) &f);
-       f = rn - 16 + 200.0;
-       vu_regs[1].f[rn-16] = *((unsigned *) &f);
-      }
-      else {
-       f = (rn - 24)/4 + (rn - 24)%4 + 1000.0;
-       vu_regs[0].f[rn-16] = *((unsigned *) &f);
-       f = (rn - 24)/4 + (rn - 24)%4 + 2000.0;
-       vu_regs[1].f[rn-16] = *((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 */
   }
@@ -558,7 +583,7 @@ sim_write (sd,addr,buffer,size)
       int cca;
       if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isSTORE, &paddr, &cca, isRAW))
        break;
-      if (sim_core_write_buffer (SD, CPU, sim_core_read_map, buffer + index, paddr, 1) != 1)
+      if (sim_core_write_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
        break;
     }
 
@@ -587,7 +612,7 @@ sim_read (sd,addr,buffer,size)
       int cca;
       if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isLOAD, &paddr, &cca, isRAW))
        break;
-      if (sim_core_read_buffer (SD, CPU, sim_core_read_map, buffer + index, paddr, 1) != 1)
+      if (sim_core_read_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
        break;
     }
 
@@ -640,24 +665,107 @@ sim_store_register (sd,rn,memory,length)
 
   /* start-sanitize-sky */
 #ifdef TARGET_SKY
-  if (rn > NUM_R5900_REGS) 
+  if (rn >= NUM_R5900_REGS) 
     {
       rn = rn - NUM_R5900_REGS;
 
-      if( rn < 16 ) 
-       vu_regs[0].i[rn] = T2H_2( *(unsigned short *) memory );
-      else if( rn < NUM_VU_REGS )
-       vu_regs[0].f[rn - 16] = T2H_4( *(unsigned int *) memory );
-      else {
-       rn = rn - NUM_VU_REGS;
-
-       if( rn < 16 ) 
-         vu_regs[1].i[rn] = T2H_2( *(unsigned short *) memory );
-       else if( rn < NUM_VU_REGS )
-         vu_regs[1].f[rn - 16] = 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;
+           }
+       }
+
+      sim_io_eprintf( sd, "Invalid VU register (register store ignored)\n" );
+      return 0;
     }
 #endif
   /* end-sanitize-sky */
@@ -686,6 +794,8 @@ sim_store_register (sd,rn,memory,length)
       cpu->registers[rn] = T2H_8 (*(unsigned64*)memory);
       return 8;
     }
+
+  return 0;
 }
 
 int
@@ -730,25 +840,99 @@ sim_fetch_register (sd,rn,memory,length)
 
   /* start-sanitize-sky */
 #ifdef TARGET_SKY
-  if( rn > NUM_R5900_REGS 
+  if (rn >= NUM_R5900_REGS
     {
       rn = rn - NUM_R5900_REGS;
 
-      if( rn < 16 ) 
-       *((unsigned short *) memory) = H2T_2( vu_regs[0].i[rn] );
-      else if( rn < NUM_VU_REGS )
-       *((unsigned int *) memory) = H2T_4( vu_regs[0].f[rn - 16] );
-      else {
-       rn = rn - NUM_VU_REGS;
-       
-       if( rn < 16 ) 
-         (*(unsigned short *) memory) = H2T_2( vu_regs[1].i[rn] );
-       else if( rn < NUM_VU_REGS )
-         (*(unsigned int *) memory) = H2T_4( vu_regs[1].f[rn - 16] );
-       else
-         sim_io_eprintf( sd, "Invalid VU register (register fetch ignored)\n" );
-      }
-      return -1;
+      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)
+       {
+         if (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
+           return read_pke_pc (&pke0_device, memory);
+       }
+
+      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 */
@@ -778,43 +962,8 @@ sim_fetch_register (sd,rn,memory,length)
       *(unsigned64*)memory = H2T_8 ((unsigned64)(cpu->registers[rn]));
       return 8;
     }
-}
-
 
-void
-sim_info (sd,verbose)
-     SIM_DESC sd;
-     int verbose;
-{
-  /* Accessed from the GDB "info files" command: */
-  if (STATE_VERBOSE_P (sd) || verbose)
-    {
-      
-      sim_io_printf (sd, "MIPS %d-bit %s endian simulator\n",
-                    WITH_TARGET_WORD_BITSIZE,
-                    (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN ? "Big" : "Little"));
-      
-#if !defined(FASTSIM)
-      /* It would be a useful feature, if when performing multi-cycle
-        simulations (rather than single-stepping) we keep the start and
-        end times of the execution, so that we can give a performance
-        figure for the simulator. */
-#endif /* !FASTSIM */
-      sim_io_printf (sd, "Number of execution cycles = %ld\n",
-                    (long) sim_events_time (sd));
-      
-      /* print information pertaining to MIPS ISA and architecture being simulated */
-      /* things that may be interesting */
-      /* instructions executed - if available */
-      /* cycles executed - if available */
-      /* pipeline stalls - if available */
-      /* virtual time taken */
-      /* profiling size */
-      /* profiling frequency */
-      /* profile minpc */
-      /* profile maxpc */
-    }
-  profile_print (sd, STATE_VERBOSE_P (sd), NULL, NULL);
+  return 0;
 }
 
 
@@ -994,9 +1143,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;
       }
@@ -1399,349 +1551,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,
-                                                   sim_core_read_map, pAddr);
-       value1 = VH8_16 (val);
-       value = VL8_16 (val);
-       break;
-      }
-    case AccessLength_DOUBLEWORD :
-      value = sim_core_read_aligned_8 (cpu, NULL_CIA,
-                                      sim_core_read_map, pAddr);
-      break;
-    case AccessLength_SEPTIBYTE :
-      value = sim_core_read_misaligned_7 (cpu, NULL_CIA,
-                                         sim_core_read_map, pAddr);
-      break;
-    case AccessLength_SEXTIBYTE :
-      value = sim_core_read_misaligned_6 (cpu, NULL_CIA,
-                                         sim_core_read_map, pAddr);
-      break;
-    case AccessLength_QUINTIBYTE :
-      value = sim_core_read_misaligned_5 (cpu, NULL_CIA,
-                                         sim_core_read_map, pAddr);
-      break;
-    case AccessLength_WORD :
-      value = sim_core_read_aligned_4 (cpu, NULL_CIA,
-                                      sim_core_read_map, pAddr);
-      break;
-    case AccessLength_TRIPLEBYTE :
-      value = sim_core_read_misaligned_3 (cpu, NULL_CIA,
-                                         sim_core_read_map, pAddr);
-      break;
-    case AccessLength_HALFWORD :
-      value = sim_core_read_aligned_2 (cpu, NULL_CIA,
-                                      sim_core_read_map, pAddr);
-      break;
-    case AccessLength_BYTE :
-      value = sim_core_read_aligned_1 (cpu, NULL_CIA,
-                                      sim_core_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,
-                                  sim_core_write_map, pAddr, val);
-       break;
-      }
-    case AccessLength_DOUBLEWORD :
-      sim_core_write_aligned_8 (cpu, NULL_CIA,
-                               sim_core_write_map, pAddr, MemElem);
-      break;
-    case AccessLength_SEPTIBYTE :
-      sim_core_write_misaligned_7 (cpu, NULL_CIA,
-                                  sim_core_write_map, pAddr, MemElem);
-      break;
-    case AccessLength_SEXTIBYTE :
-      sim_core_write_misaligned_6 (cpu, NULL_CIA,
-                                  sim_core_write_map, pAddr, MemElem);
-      break;
-    case AccessLength_QUINTIBYTE :
-      sim_core_write_misaligned_5 (cpu, NULL_CIA,
-                                  sim_core_write_map, pAddr, MemElem);
-      break;
-    case AccessLength_WORD :
-      sim_core_write_aligned_4 (cpu, NULL_CIA,
-                               sim_core_write_map, pAddr, MemElem);
-      break;
-    case AccessLength_TRIPLEBYTE :
-      sim_core_write_misaligned_3 (cpu, NULL_CIA,
-                                  sim_core_write_map, pAddr, MemElem);
-      break;
-    case AccessLength_HALFWORD :
-      sim_core_write_aligned_2 (cpu, NULL_CIA,
-                               sim_core_write_map, pAddr, MemElem);
-      break;
-    case AccessLength_BYTE :
-      sim_core_write_aligned_1 (cpu, NULL_CIA,
-                               sim_core_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,
@@ -1765,23 +1574,6 @@ ifetch16 (SIM_DESC sd,
 }
 
 
-/* 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
@@ -1824,7 +1616,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;
 
@@ -2036,82 +1828,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
@@ -2928,6 +2644,7 @@ SquareRoot(op,fmt)
   return(result);
 }
 
+#if 0
 uword64
 Max (uword64 op1,
      uword64 op2,
@@ -2995,7 +2712,9 @@ Max (uword64 op1,
 
   return(result);
 }
+#endif 
 
+#if 0
 uword64
 Min (uword64 op1,
      uword64 op2,
@@ -3063,6 +2782,7 @@ Min (uword64 op1,
 
   return(result);
 }
+#endif
 
 uword64
 convert (SIM_DESC sd,
@@ -3237,6 +2957,48 @@ cop_ld (SIM_DESC sd,
   return;
 }
 
+
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+void
+cop_lq (SIM_DESC sd,
+       sim_cpu *cpu,
+       address_word cia,
+       int coproc_num,
+       int coproc_reg,
+       unsigned128 memword)
+{
+  switch (coproc_num)
+    {
+    case 2:
+      {
+       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));
+      break;
+    }
+  
+  return;
+}
+#endif /* TARGET_SKY */
+/* end-sanitize-sky */
+
+
 unsigned int
 cop_sw (SIM_DESC sd,
        sim_cpu *cpu,
@@ -3296,6 +3058,48 @@ cop_sd (SIM_DESC sd,
   return(value);
 }
 
+
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+unsigned128
+cop_sq (SIM_DESC sd,
+       sim_cpu *cpu,
+       address_word cia,
+       int coproc_num,
+       int coproc_reg)
+{
+  unsigned128 value = U16_8(0, 0);
+  switch (coproc_num)
+    {
+    case 2:
+      {
+       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));
+      break;
+    }
+
+  return(value);
+}
+#endif /* TARGET_SKY */
+/* end-sanitize-sky */
+
+
 void
 decode_coproc (SIM_DESC sd,
               sim_cpu *cpu,
@@ -3436,10 +3240,219 @@ decode_coproc (SIM_DESC sd,
       }
     break;
     
-    case 2: /* undefined co-processor */
-      sim_io_eprintf(sd,"COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction,pr_addr(cia));
-      break;
-      
+    case 2: /* co-processor 2 */
+      {
+       int handle = 0;
+
+       /* start-sanitize-sky */
+#ifdef TARGET_SKY
+       /* On the R5900, this refers to a "VU" vector co-processor. */
+
+       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;
+       /* 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;
+
+       /* test COP2 usability */
+       if(! (SR & status_CU2))
+         {
+           SignalException(CoProcessorUnusable,instruction);       
+           /* NOTREACHED */
+         }
+
+       /* classify & execute basic COP2 instructions */
+       if(i_25_21 == 0x08 && i_20_16 == 0x00) /* BC2F */
+         {
+           address_word offset = EXTEND16(i_15_0) << 2;
+           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(! 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(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(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 == 0x01)) /* QMFC2 */
+         {
+           int rt = i_20_16;
+           int id = i_15_11;
+
+           /* 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_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;
+               /* 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 == 0x06 && i_10_1 == 0x000) || /* CTC2 */
+               (i_25_21 == 0x05)) /* QMTC2 */
+         {
+           int rt = i_20_16;
+           int id = i_15_11;
+
+           /* interlock checking */
+           /* POLICY: never busy in macro mode */
+           if(vu0_busy() && interlock)
+             {
+               while(! vu0_micro_interlock_released())
+                 vu0_issue(sd);
+             }
+           
+           /* perform VU register address */
+           if(i_25_21 == 0x05) /* QMTC2 */
+             {
+               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());
+         }
+       /* 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); 
+           /* NOTREACHED */
+         }
+       
+       /* cleanup for semantic.c-like actions above */
+       PC = NIA;
+
+#endif /* TARGET_SKY */
+       /* end-sanitize-sky */
+
+       if(! handle)
+         {
+           sim_io_eprintf(sd, "COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
+                          instruction,pr_addr(cia));
+         }
+      }
+    break;
+    
     case 1: /* should not occur (FPU co-processor) */
     case 3: /* should not occur (FPU co-processor) */
       SignalException(ReservedInstruction,instruction);
@@ -3449,6 +3462,7 @@ decode_coproc (SIM_DESC sd,
   return;
 }
 
+
 /*-- instruction simulation -------------------------------------------------*/
 
 /* When the IGEN simulator is being built, the function below is be
@@ -3729,72 +3743,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.038447 seconds and 4 git commands to generate.