Add r5900
authorGavin Romig-Koch <gavin@redhat.com>
Tue, 11 Feb 1997 13:26:34 +0000 (13:26 +0000)
committerGavin Romig-Koch <gavin@redhat.com>
Tue, 11 Feb 1997 13:26:34 +0000 (13:26 +0000)
26 files changed:
.Sanitize
ChangeLog
Makefile.in
bfd/.Sanitize
bfd/ChangeLog
config/.Sanitize
configure.in
gas/.Sanitize
gas/ChangeLog
gas/config/.Sanitize
gas/config/tc-mips.c
gdb/.Sanitize
gdb/ChangeLog
gdb/configure.tgt
include/opcode/.Sanitize
include/opcode/ChangeLog
ld/.Sanitize
ld/ChangeLog
opcodes/.Sanitize
opcodes/ChangeLog
opcodes/mips-opc.c
sim/mips/.Sanitize
sim/mips/ChangeLog
sim/mips/configure.in
sim/mips/gencode.c
sim/mips/support.h

index cc5d7adabe3a639299bfe903fb877a3bcd156a4e..6b73884fba35c54d2124ab035823e6a9ee45a7ad 100644 (file)
--- a/.Sanitize
+++ b/.Sanitize
@@ -361,6 +361,35 @@ else
        done
 fi
 
+r5900_files="ChangeLog config.sub configure.in"
+
+if ( echo $* | grep keep\-r5900 > /dev/null ) ; then
+       for i in $r5900_files ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Keeping r5900 stuff in $i
+                       fi
+               fi
+       done
+else
+       for i in * ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Removing traces of \"r5900\" from $i...
+                       fi
+                       cp $i new
+                       sed '/start\-sanitize\-r5900/,/end-\sanitize\-r5900/d' < $i > new
+                       if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
+                               if [ -n "${verbose}" ] ; then
+                                       echo Caching $i in .Recover...
+                               fi
+                               mv $i .Recover
+                       fi
+                       mv new $i
+               fi
+       done
+fi
+
 tic80_files="ChangeLog config.sub configure.in"
 
 if ( echo $* | grep keep\-tic80 > /dev/null ) ; then
index d17b9d318475133174a6bc925a7d676bb69bbd3b..cd57bc582c99fd20907373a0d15cb873ad37c4dd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+start-sanitize-r5900
+        Fri Feb  7 16:39:29 1997  Gavin Koch  <gavin@cygnus.com>
+        
+        * config.sub, configure.in: add r5900
+end-sanitize-r5900        
 Sat Feb  8 20:36:49 1997  Michael Meissner  <meissner@cygnus.com>
 
        * Makefile.in (all-itcl): The rule is all-itcl, not all-tcl.
index 9db3296576443a377e8dec0a975924f5a8a2601b..1170b4dc0cc27b9cf4c1da301767aa6f0a6480f5 100644 (file)
@@ -68,6 +68,7 @@ HOST_PREFIX_1 = loser-
 CFLAGS = -g
 LIBCFLAGS = $(CFLAGS)
 CFLAGS_FOR_TARGET = $(CFLAGS)
+LDFLAGS_FOR_TARGET = 
 LIBCFLAGS_FOR_TARGET = $(CFLAGS_FOR_TARGET)
 PICFLAG = 
 PICFLAG_FOR_TARGET = 
@@ -1078,6 +1079,7 @@ $(CONFIGURE_TARGET_MODULES):
            CXXFLAGS="$(CXXFLAGS_FOR_TARGET)"; export CXXFLAGS; \
            DLLTOOL="$(DLLTOOL_FOR_TARGET)"; export DLLTOOL; \
            LD="$(LD_FOR_TARGET)"; export LD; \
+            LDFLAGS="$(LDFLAGS_FOR_TARGET)"; export LDFLAGS; \
            NM="$(NM_FOR_TARGET)"; export NM; \
            RANLIB="$(RANLIB_FOR_TARGET)"; export RANLIB; \
            echo Configuring in $(TARGET_SUBDIR)/$${dir}; \
index f1ef16e2d073168171fc099be8be3a0700ed1091..0324b848f463e7119ba019b3d2d6f96faa526bbd 100644 (file)
@@ -411,6 +411,34 @@ else
        done
 fi
 
+r5900_files="ChangeLog config.bfd"
+if ( echo $* | grep keep\-r5900 > /dev/null ) ; then
+       for i in $r5900_files ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Keeping r5900 stuff in $i
+                       fi
+               fi
+       done
+else
+       for i in $r5900_files ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Removing traces of \"r5900\" from $i...
+                       fi
+                       cp $i new
+                       sed '/start\-sanitize\-r5900/,/end-\sanitize\-r5900/d' < $i > new
+                       if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
+                               if [ -n "${verbose}" ] ; then
+                                       echo Caching $i in .Recover...
+                               fi
+                               mv $i .Recover
+                       fi
+                       mv new $i
+               fi
+       done
+fi
+
 tic80_files="ChangeLog Makefile.in archures.c bfd-in2.h config.bfd configure configure.in targets.c"
 if ( echo $* | grep keep\-tic80 > /dev/null ) ; then
        for i in $tic80_files ; do
index d0736297071e65407474656c98cee72976f9496c..75c54df8ed808384152780ab976136c44f9cd7de 100644 (file)
@@ -1,3 +1,9 @@
+start-sanitize-r5900
+        Fri Feb  7 16:20:17 1997  Gavin Koch   <gavin@cygnus.com>
+        
+        * config.bfd: add r5900
+        
+end-sanitize-r5900        
 Fri Feb  7 12:39:11 1997  Ian Lance Taylor  <ian@cygnus.com>
 
        * elflink.h (elf_link_input_bfd): If we've discarded a section,
index cb8ced157e95c8ba72c6e579e007a3b6a6ea431e..97e80b565e623b1806bbebc82fe01b3ef765a5db 100644 (file)
 
 Do-first:
 
+if ( echo $* | grep keep\-r5900 > /dev/null ) ; then
+       keep_these_too="${keep_these_too} mt-r5900"
+else
+        lose_these_too="${lose_these_too} mt-r5900"
+fi
+
 # All files listed between the "Things-to-keep:" line and the
 # "Files-to-sed:" line will be kept.  All other files will be removed.
 # Directories listed in this section will have their own Sanitize
index 3685a399c1333aa84e3ebc48405f31ee7eda4663..e11ca63e397f09ff9c51352f069f50cc9bc82099 100644 (file)
@@ -208,6 +208,9 @@ fi
 case "${target}" in
   v810*)               target_makefile_frag=config/mt-v810 ;;
   i[3456]86-*-netware*) target_makefile_frag=config/mt-netware ;;
+# start-sanitize-r5900
+  mips64vr5900*-*-*)    target_makefile_frag=config/mt-r5900 ;;
+# end-sanitize-r5900
   powerpc-*-netware*)   target_makefile_frag=config/mt-netware ;;
 esac
 
index eedc78eefbc98496fef197a15cd39cfe0af1f127..f493f45aa18afb1be70b58e5bdf5f4aa5d472054 100644 (file)
@@ -219,6 +219,34 @@ else
        done
 fi
 
+r5900_files="ChangeLog"
+if ( echo $* | grep keep\-r5900 > /dev/null ) ; then
+       for i in $r5900_files ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Keeping r5900 stuff in $i
+                       fi
+               fi
+       done
+else
+       for i in $r5900_files ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Removing traces of \"r5900\" from $i...
+                       fi
+                       cp $i new
+                       sed '/start\-sanitize\-r5900/,/end-\sanitize\-r5900/d' < $i > new
+                       if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
+                               if [ -n "${verbose}" ] ; then
+                                       echo Caching $i in .Recover...
+                               fi
+                               mv $i .Recover
+                       fi
+                       mv new $i
+               fi
+       done
+fi
+
 tic80_files="ChangeLog configure.in configure"
 if ( echo $* | grep keep\-tic80 > /dev/null ) ; then
        for i in $tic80_files ; do
index 51d922ab3c0c107c0510435627a1c4b62a32d40b..968d433d459ce3d62b8b193106feccca0c3b41e2 100644 (file)
@@ -1,3 +1,9 @@
+start-sanitize-r5900
+Fri Feb  7 11:11:06 1997  Gavin Koch  <gavin@cygnus.com>
+        
+        * config/tc-mips.c: added r5900.
+        
+end-sanitize-r5900
 Mon Feb 10 22:06:00 1997  Dawn Perchik  (dawn@cygnus.com)
 
        * itbl-ops.c, itbl-lex.l, itbl-parse.y, itbl-ops.h,
index c33246c8a648c2fb161a3aba69cbd9d6dcbdd612..65a123a5980da7d80cc92f228ef29eb59cb11ff4 100644 (file)
@@ -183,4 +183,34 @@ Things-to-lose:
 
 Do-last:
 
+r5900_files="tc-mips.c"
+
+if ( echo $* | grep keep\-r5900 > /dev/null ) ; then
+       for i in $r5900_files ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Keeping r5900 stuff in $i
+                       fi
+               fi
+       done
+else
+       for i in * ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Removing traces of \"r5900\" from $i...
+                       fi
+                       cp $i new
+                       sed '/start\-sanitize\-r5900/,/end-\sanitize\-r5900/d' < $i > new
+                       if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
+                               if [ -n "${verbose}" ] ; then
+                                       echo Caching $i in .Recover...
+                               fi
+                               mv $i .Recover
+                       fi
+                       mv new $i
+               fi
+       done
+fi
+
+
 # End of file.
index edb2e13cac9774ce4af8e81f101fdfd4adc76ccc..4b3c95548b321066658a17d728f3a28560f12760 100644 (file)
@@ -148,6 +148,11 @@ static int mips_4010 = -1;
 /* Whether the 4100 MADD16 and DMADD16 are permitted. */
 static int mips_4100 = -1;
 
+/* start-sanitize-r5900 */
+/* Whether Toshiba r5900 instructions are permitted. */
+static int mips_5900 = -1;
+/* end-sanitize-r5900 */
+
 /* Whether the processor uses hardware interlocks, and thus does not
    require nops to be inserted.  */
 static int interlocks = -1;
@@ -780,6 +785,18 @@ md_begin ()
          if (mips_cpu == -1)
            mips_cpu = 5000;
        }
+      /* start-sanitize-r5900 */
+      else if (strcmp (cpu, "r5900") == 0
+              || strcmp (cpu, "mips64vr5900") == 0
+               || strcmp (cpu, "mips64vr5900el") == 0)
+       {
+         mips_isa = 3;
+         if (mips_cpu == -1)
+           mips_cpu = 5900;
+          if (mips_5900 = -1)
+            mips_5900 = 1;
+       }
+      /* end-sanitize-r5900 */
       else if (strcmp (cpu, "r8000") == 0
               || strcmp (cpu, "mips4") == 0)
        {
@@ -827,6 +844,11 @@ md_begin ()
   if (mips_4100 < 0)
     mips_4100 = 0;
 
+  /* start-sanitize-r5900 */
+  if (mips_5900 < 0)
+    mips_5900 = 0;
+  /* end-sanitize-r5900 */
+
   if (mips_4010 || mips_4100 || mips_cpu == 4300)
     interlocks = 1;
   else
@@ -2111,7 +2133,12 @@ macro_build (place, counter, ep, name, fmt, va_alist)
         || ((insn.insn_mo->pinfo & INSN_ISA) == INSN_4010
             && ! mips_4010)
         || ((insn.insn_mo->pinfo & INSN_ISA) == INSN_4100
-            && ! mips_4100))
+            && ! mips_4100)
+        /* start-sanitize-r5900 */
+         || ((insn.insn_mo->pinfo & INSN_ISA) == INSN_5900
+            && ! mips_5900)
+         /* end-sanitize-r5900 */
+         )
     {
       ++insn.insn_mo;
       assert (insn.insn_mo->name);
@@ -6110,7 +6137,12 @@ mips_ip (str, ip)
          || ((insn->pinfo & INSN_ISA) == INSN_4010
              && ! mips_4010)
          || ((insn->pinfo & INSN_ISA) == INSN_4100
-             && ! mips_4100))
+             && ! mips_4100)
+          /* start-sanitize-r5900 */
+         || ((insn->pinfo & INSN_ISA) == INSN_5900
+             && ! mips_5900)
+          /* end-sanitize-r5900 */
+          )
        {
          if (insn + 1 < &mips_opcodes[NUMOPCODES]
              && strcmp (insn->name, insn[1].name) == 0)
@@ -7708,6 +7740,12 @@ struct option md_longopts[] = {
   {"mips16", no_argument, NULL, OPTION_MIPS16},
 #define OPTION_NO_MIPS16 (OPTION_MD_BASE + 23)
   {"no-mips16", no_argument, NULL, OPTION_NO_MIPS16},
+  /* start-sanitize-5900 */
+#define OPTION_M5900 (OPTION_MD_BASE + 24)
+  {"m5900", no_argument, NULL, OPTION_M5900},
+#define OPTION_NO_M5900 (OPTION_MD_BASE + 25)
+  {"no-m5900", no_argument, NULL, OPTION_NO_M5900},
+  /* end-sanitize-5900 */
 
 #define OPTION_CALL_SHARED (OPTION_MD_BASE + 7)
 #define OPTION_NON_SHARED (OPTION_MD_BASE + 8)
@@ -7877,6 +7915,10 @@ md_parse_option (c, arg)
                    || strcmp (p, "5k") == 0
                    || strcmp (p, "5K") == 0)
                  mips_cpu = 5000;
+                /* start-sanitize-r5900 */
+                else if (strcmp (p, "5900") == 0)
+                  mips_cpu = 5900;
+                /* end-sanitize-r5900 */
                break;
 
              case '6':
@@ -7938,6 +7980,16 @@ md_parse_option (c, arg)
       mips_4100 = 0;
       break;
 
+      /* start-sanitize-r5900 */
+    case OPTION_M5900:
+      mips_5900 = 1;
+      break;
+
+    case OPTION_NO_M5900:
+      mips_5900 = 0;
+      break;
+      /* end-sanitize-r5900 */
+
     case OPTION_MIPS16:
       mips16 = 1;
       mips_no_prev_insn ();
index 1425e499aa477d5553890e1396a5fd384927fa81..422d7b707776e5ea13b6c9ecc066550759be5620 100644 (file)
@@ -600,6 +600,33 @@ else
        done
 fi
 
+if ( echo $* | grep keep\-r5900 > /dev/null ) ; then
+       for i in * ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Keeping r5900 stuff in $i
+                       fi
+               fi
+       done
+else
+       for i in * ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Removing traces of \"r5900\" from $i...
+                       fi
+                       cp $i new
+                       sed '/start\-sanitize\-r5900/,/end-\sanitize\-r5900/d' < $i > new
+                       if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
+                               if [ -n "${verbose}" ] ; then
+                                       echo Caching $i in .Recover...
+                               fi
+                               mv $i .Recover
+                       fi
+                       mv new $i
+               fi
+       done
+fi
+
 if ( echo $* | grep keep\-m32r > /dev/null ) ; then
        for i in * ; do
                if test ! -d $i && (grep sanitize-m32r $i > /dev/null) ; then
index b36296f6d3f2477c5549f3aa0a48c0fd19e4e971..a11a0e6cb8dd6d112c806d1c5394e16cfdba07aa 100644 (file)
@@ -1,3 +1,9 @@
+start-sanitize-r5900
+Fri Feb 07 09:04:37 1997  Gavin Koch  <gavin@cygnus.com>
+        
+        * configure.tgt: added r5900.
+        
+end-sanitize-r5900
 Mon Feb 10 18:35:55 1997  Mark Alexander  <marka@cygnus.com>
 
        * mips-tdep.c (non_heuristic_proc_desc): New function.
index fd784f3a0f46689a35c95db57f27a2beb7748e9b..f596678cb4ab9d1de823dc7b5a33d392338bf21f 100644 (file)
@@ -164,6 +164,10 @@ mips64*vr4100*el-*-elf*)   gdb_target=vr4300el ;;
 mips64*vr4100*-*-elf*) gdb_target=vr4300 ;;
 mips64*vr5000*el-*-elf*)       gdb_target=vr5000el ;;
 mips64*vr5000*-*-elf*) gdb_target=vr5000 ;;
+# start-sanitize-r5900
+mips64*vr5900*el-*-elf*)       gdb_target=vr5000el ;;
+mips64*vr5900*-*-elf*) gdb_target=vr5000 ;;
+# end-sanitize-r5900
 mips64*el-*-elf*)      gdb_target=embedl64 ;;
 mips64*-*-elf*)                gdb_target=embed64 ;;
 mips*el-*-ecoff*)      gdb_target=embedl ;;
index 41d25cd200e46294c5a5b23ecb042d2afd7af2e2..5d654e52c2a3aedecf22ed13cd4dc72a1fdda384 100644 (file)
@@ -169,6 +169,34 @@ else
        done
 fi
 
+r5900_files="ChangeLog mips.h"
+if ( echo $* | grep keep\-r5900 > /dev/null ) ; then
+       for i in $r5900_files ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Keeping r5900 stuff in $i
+                       fi
+               fi
+       done
+else
+       for i in $r5900_files ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Removing traces of \"r5900\" from $i...
+                       fi
+                       cp $i new
+                       sed '/start\-sanitize\-r5900/,/end-\sanitize\-r5900/d' < $i > new
+                       if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
+                               if [ -n "${verbose}" ] ; then
+                                       echo Caching $i in .Recover...
+                               fi
+                               mv $i .Recover
+                       fi
+                       mv new $i
+               fi
+       done
+fi
+
 tic80_files="ChangeLog"
 if ( echo $* | grep keep\-tic80 > /dev/null ) ; then
        for i in $tic80_files ; do
index 529eace79edaef33d8a5d737568f3e7993c37997..e31e23fe9ba8799fd51049331cbc7526ff639fc6 100644 (file)
@@ -1,3 +1,9 @@
+start-sanitize-r5900
+Fri Feb  7 11:12:44 1997  Gavin Koch  <gavin@cygnus.com>
+        
+        * mips.h: add r5900.
+        
+end-sanitize-r5900
 start-sanitize-tic80
 Mon Feb 10 10:32:17 1997  Fred Fish  <fnf@cygnus.com>
 
index d8ab22cb0a2921cd010f4d7fed68878ad89d485f..5ca2c7db657c21b1dd5b00cc0c7fbb3b02293f52 100644 (file)
@@ -202,6 +202,35 @@ else
        done
 fi
 
+r5900_files="ChangeLog configure.tgt"
+
+if ( echo $* | grep keep\-r5900 > /dev/null ) ; then
+       for i in $r5900_files ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Keeping r5900 stuff in $i
+                       fi
+               fi
+       done
+else
+       for i in $r5900_files ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Removing traces of \"r5900\" from $i...
+                       fi
+                       cp $i new
+                       sed '/start\-sanitize\-r5900/,/end-\sanitize\-r5900/d' < $i > new
+                       if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
+                               if [ -n "${verbose}" ] ; then
+                                       echo Caching $i in .Recover...
+                               fi
+                               mv $i .Recover
+                       fi
+                       mv new $i
+               fi
+       done
+fi
+
 tic80_files="ChangeLog configure.tgt Makefile.in"
 
 if ( echo $* | grep keep\-tic80 > /dev/null ) ; then
index 024e4ac989722dfdb0db53908e43f3346dec81b4..4ab3f5fce5cb9ba43ffa30418b1b79b19095d0ce 100644 (file)
@@ -1,3 +1,9 @@
+start-sanitize-r5900
+Fri Feb  7 13:16:53 1997  Gavin Koch  <gavin@cygnus.com>
+        
+        * configure.tgt: add r5900.
+        
+end-sanitize-r5900
 start-sanitize-tic80
 Sun Feb  9 18:09:13 1997  Fred Fish  <fnf@cygnus.com>
 
index ed1a58a4e2ed69721cf52275ec721c440172d843..536f4575d9ea0fc84affe5ef87f4bbba20c35818 100644 (file)
@@ -191,6 +191,34 @@ else
        done
 fi
 
+r5900_files="ChangeLog mips-opc.c"
+if ( echo $* | grep keep\-r5900 > /dev/null ) ; then
+       for i in $r5900_files ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Keeping r5900 stuff in $i
+                       fi
+               fi
+       done
+else
+       for i in $r5900_files ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Removing traces of \"r5900\" from $i...
+                       fi
+                       cp $i new
+                       sed '/start\-sanitize\-r5900/,/end-\sanitize\-r5900/d' < $i > new
+                       if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
+                               if [ -n "${verbose}" ] ; then
+                                       echo Caching $i in .Recover...
+                               fi
+                               mv $i .Recover
+                       fi
+                       mv new $i
+               fi
+       done
+fi
+
 tic80_files="ChangeLog Makefile.in configure.in configure disassemble.c"
 if ( echo $* | grep keep\-tic80 > /dev/null ) ; then
        for i in $tic80_files ; do
index 3aa9b2d8756accdbe03d6622952ba393dce2c72c..d1718803f198dc7883e23c42108d4b79aa6406e3 100644 (file)
@@ -1,3 +1,9 @@
+start-sanitize-r5900
+Fri Feb  7 11:12:44 1997  Gavin Koch  <gavin@cygnus.com>
+        
+        * mips-opc.c: add r5900.
+        
+end-sanitize-r5900
 start-sanitize-tic80
 Mon Feb 10 10:12:41 1997  Fred Fish  <fnf@cygnus.com>
 
index 7aa1d0e1bef8b1c7b990d388e3499dac39a2b68c..ab1e610993fd3f0285b31929cd7fe4968dbc274e 100644 (file)
@@ -1,5 +1,5 @@
 /* mips.h.  Mips opcode list for GDB, the GNU debugger.
-   Copyright 1993 Free Software Foundation, Inc.
+   Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
    Contributed by Ralph Campbell and OSF
    Commented and modified by Ian Lance Taylor, Cygnus Support
 
@@ -69,6 +69,24 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  *
 #define L1     INSN_4010
 #define V1      INSN_4100
 
+#define T5      ( 0                                     \
+/* start-sanitize-r5900 */                              \
+                  | INSN_5900                           \
+/* end-sanitize-r5900 */                                \
+                  | 0)
+
+#define X5      ( 0                                     \
+/* start-sanitize-r5900 */                              \
+/* insn's marked X5 are not really 5900 instructions    \
+   (mostly double fp insns), but we turn them on until  \
+   we can generate code, and make librarys that don't   \
+   use them. */                                         \
+                  | INSN_5900                           \
+/* end-sanitize-r5900 */                                \
+                  | 0)
+
+
+
 /* The order of overloaded instructions matters.  Label arguments and
    register arguments look the same. Instructions that can have either
    for arguments must apear in the correct order in this table for the
@@ -300,6 +318,9 @@ const struct mips_opcode mips_opcodes[] = {
 {"div",     "z,t",     0x0000001a, 0xffe0ffff, RD_s|RD_t|WR_HI|WR_LO   },
 {"div",     "d,v,t",   0,    (int) M_DIV_3,    INSN_MACRO      },
 {"div",     "d,v,I",   0,    (int) M_DIV_3I,   INSN_MACRO      },
+  /* start-sanitize-r5900 */
+{"div1",    "s,t",     0x7000001a, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|T5},
+  /* end-sanitize-r5900 */
 {"div.d",   "D,V,T",   0x46200003, 0xffe0003f, WR_D|RD_S|RD_T  },
 {"div.s",   "D,V,T",   0x46000003, 0xffe0003f, WR_D|RD_S|RD_T  },
 /* For divu, see the comments about div.  */
@@ -307,6 +328,9 @@ const struct mips_opcode mips_opcodes[] = {
 {"divu",    "z,t",     0x0000001b, 0xffe0ffff, RD_s|RD_t|WR_HI|WR_LO   },
 {"divu",    "d,v,t",   0,    (int) M_DIVU_3,   INSN_MACRO      },
 {"divu",    "d,v,I",   0,    (int) M_DIVU_3I,  INSN_MACRO      },
+  /* start-sanitize-r5900 */
+{"divu1",   "s,t",     0x7000001b, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|T5},
+  /* end-sanitize-r5900 */
 {"dla",     "t,A(b)",  3,    (int) M_DLA_AB,   INSN_MACRO      },
 {"dli",     "t,j",      0x24000000, 0xffe00000, WR_t|I3                }, /* addiu */
 {"dli",            "t,i",      0x34000000, 0xffe00000, WR_t|I3         }, /* ori */
@@ -404,7 +428,7 @@ const struct mips_opcode mips_opcodes[] = {
 {"ldl",            "t,A(b)",   3,    (int) M_LDL_AB,   INSN_MACRO      },
 {"ldr",            "t,o(b)",   0x6c000000, 0xfc000000, LDD|WR_t|RD_b|I3},
 {"ldr",     "t,A(b)",  3,    (int) M_LDR_AB,   INSN_MACRO      },
-{"ldxc1",   "D,t(b)",  0x4c000001, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|I4 },
+{"ldxc1",   "D,t(b)",  0x4c000001, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|I4|X5 },
 {"lh",      "t,o(b)",  0x84000000, 0xfc000000, LDD|RD_b|WR_t   },
 {"lh",      "t,A(b)",  0,    (int) M_LH_AB,    INSN_MACRO      },
 {"lhu",     "t,o(b)",  0x94000000, 0xfc000000, LDD|RD_b|WR_t   },
@@ -419,6 +443,9 @@ const struct mips_opcode mips_opcodes[] = {
 {"lld",            "t,o(b)",   0xd0000000, 0xfc000000, LDD|RD_b|WR_t|I3},
 {"lld",     "t,A(b)",  3,    (int) M_LLD_AB,   INSN_MACRO      },
 {"lui",     "t,u",     0x3c000000, 0xffe00000, WR_t            },
+  /* start-sanitize-r5900 */
+{"lq",     "t,o(b)",   0x78000000, 0xfc000000, WR_t|RD_b|T5    },
+  /* end-sanitize-r5900 */
 {"lw",      "t,o(b)",  0x8c000000, 0xfc000000, LDD|RD_b|WR_t   },
 {"lw",      "t,A(b)",  0,    (int) M_LW_AB,    INSN_MACRO      },
 {"lwc0",    "E,o(b)",  0xc0000000, 0xfc000000, CLD|RD_b|WR_CC  },
@@ -443,14 +470,26 @@ const struct mips_opcode mips_opcodes[] = {
 {"flush",   "t,A(b)",  2,    (int) M_LWR_AB,   INSN_MACRO      }, /* as lwr */
 {"lwu",     "t,o(b)",  0x9c000000, 0xfc000000, LDD|RD_b|WR_t|I3},
 {"lwu",     "t,A(b)",  3,    (int) M_LWU_AB,   INSN_MACRO      },
-{"lwxc1",   "D,t(b)",  0x4c000000, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|I4 },
+{"lwxc1",   "D,t(b)",  0x4c000000, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|I4|X5 },
 {"mad",            "s,t",      0x70000000, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|RD_HI|RD_LO|P3},
 {"madu",    "s,t",     0x70000001, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|RD_HI|RD_LO|P3},
 {"addciu",  "t,r,j",   0x70000000, 0xfc000000, WR_t|RD_s|L1    },
-{"madd.d",  "D,R,S,T", 0x4c000021, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4 },
-{"madd.s",  "D,R,S,T", 0x4c000020, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4 },
+{"madd.d",  "D,R,S,T", 0x4c000021, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4|X5 },
+{"madd.s",  "D,R,S,T", 0x4c000020, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4|X5 },
 {"madd",    "s,t",     0x0000001c, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|L1 },
+  /* start-sanitize-r5900 */
+{"madd",    "s,t",     0x70000000, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|T5},
+{"madd",    "d,s,t",   0x70000000, 0xfc0007ff, RD_s|RD_t|WR_HI|WR_LO|WR_d|T5},
+{"madd1",   "s,t",     0x70000020, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|T5},
+{"madd1",   "d,s,t",   0x70000020, 0xfc0007ff, RD_s|RD_t|WR_HI|WR_LO|WR_d|T5},
+  /* end-sanitize-r5900 */
 {"maddu",   "s,t",     0x0000001d, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|L1 },
+  /* start-sanitize-r5900 */
+{"maddu",   "s,t",     0x70000001, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|T5},
+{"maddu",   "d,s,t",   0x70000001, 0xfc0007ff, RD_s|RD_t|WR_HI|WR_LO|WR_d|T5},
+{"maddu1",  "s,t",     0x70000021, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|T5},
+{"maddu1",  "d,s,t",   0x70000021, 0xfc0007ff, RD_s|RD_t|WR_HI|WR_LO|WR_d|T5},
+  /* end-sanitize-r5900 */
 {"madd16",  "s,t",      0x00000028, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|RD_HI|RD_LO|V1 },
 {"mfc0",    "t,G",     0x40000000, 0xffe007ff, LCD|WR_t|RD_C0  },
 {"mfc1",    "t,S",     0x44000000, 0xffe007ff, LCD|WR_t|RD_S   },
@@ -458,26 +497,33 @@ const struct mips_opcode mips_opcodes[] = {
 {"mfc2",    "t,G",     0x48000000, 0xffe007ff, LCD|WR_t|RD_C2  },
 {"mfc3",    "t,G",     0x4c000000, 0xffe007ff, LCD|WR_t|RD_C3  },
 {"mfhi",    "d",       0x00000010, 0xffff07ff, WR_d|RD_HI      },
+  /* start-sanitize-r5900 */
+{"mfhi1",   "d",       0x70000010, 0xffff07ff, WR_d|RD_HI|T5   },
+  /* end-sanitize-r5900 */
 {"mflo",    "d",       0x00000012, 0xffff07ff, WR_d|RD_LO      },
+  /* start-sanitize-r5900 */
+{"mflo1",   "d",       0x70000012, 0xffff07ff, WR_d|RD_LO|T5   },
+{"mfsa",    "d",        0x00000028, 0xffff07ff, WR_d|T5         },
+  /* end-sanitize-r5900 */
 {"mov.d",   "D,S",     0x46200006, 0xffff003f, WR_D|RD_S       },
 {"mov.s",   "D,S",     0x46000006, 0xffff003f, WR_D|RD_S       },
-{"movf",    "d,s,N",   0x00000001, 0xfc0307ff, WR_d|RD_s|RD_CC|I4 },
-{"movf.d",  "D,S,N",   0x46200011, 0xffe3003f, WR_D|RD_S|RD_CC|I4 },
-{"movf.s",  "D,S,N",   0x46000011, 0xffe3003f, WR_D|RD_S|RD_CC|I4 },
-{"movn",    "d,v,t",   0x0000000b, 0xfc0007ff, WR_d|RD_s|RD_t|I4 },
+{"movf",    "d,s,N",   0x00000001, 0xfc0307ff, WR_d|RD_s|RD_CC|I4|X5 },
+{"movf.d",  "D,S,N",   0x46200011, 0xffe3003f, WR_D|RD_S|RD_CC|I4|X5 },
+{"movf.s",  "D,S,N",   0x46000011, 0xffe3003f, WR_D|RD_S|RD_CC|I4|X5 },
+{"movn",    "d,v,t",   0x0000000b, 0xfc0007ff, WR_d|RD_s|RD_t|I4|T5 },
 {"ffc",     "d,v",     0x0000000b, 0xfc0007ff, WR_d|RD_s|L1    },
-{"movn.d",  "D,S,t",   0x46200013, 0xffe0003f, WR_D|RD_S|RD_t|I4 },
-{"movn.s",  "D,S,t",   0x46000013, 0xffe0003f, WR_D|RD_S|RD_t|I4 },
-{"movt",    "d,s,N",   0x00010001, 0xfc0307ff, WR_d|RD_s|RD_CC|I4 },
+{"movn.d",  "D,S,t",   0x46200013, 0xffe0003f, WR_D|RD_S|RD_t|I4|X5 },
+{"movn.s",  "D,S,t",   0x46000013, 0xffe0003f, WR_D|RD_S|RD_t|I4|X5 },
+{"movt",    "d,s,N",   0x00010001, 0xfc0307ff, WR_d|RD_s|RD_CC|I4|X5 },
 {"movt.d",  "D,S,N",   0x46210011, 0xffe3003f, WR_D|RD_S|RD_CC|I4 },
 {"movt.s",  "D,S,N",   0x46010011, 0xffe3003f, WR_D|RD_S|RD_CC|I4 },
-{"movz",    "d,v,t",   0x0000000a, 0xfc0007ff, WR_d|RD_s|RD_t|I4 },
+{"movz",    "d,v,t",   0x0000000a, 0xfc0007ff, WR_d|RD_s|RD_t|I4|T5 },
 {"ffs",     "d,v",     0x0000000a, 0xfc0007ff, WR_d|RD_s|L1    },
-{"movz.d",  "D,S,t",   0x46200012, 0xffe0003f, WR_D|RD_S|RD_t|I4 },
-{"movz.s",  "D,S,t",   0x46000012, 0xffe0003f, WR_D|RD_S|RD_t|I4 },
+{"movz.d",  "D,S,t",   0x46200012, 0xffe0003f, WR_D|RD_S|RD_t|I4|X5 },
+{"movz.s",  "D,S,t",   0x46000012, 0xffe0003f, WR_D|RD_S|RD_t|I4|X5 },
 /* move is at the top of the table.  */
-{"msub.d",  "D,R,S,T", 0x4c000029, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4 },
-{"msub.s",  "D,R,S,T", 0x4c000028, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4 },
+{"msub.d",  "D,R,S,T", 0x4c000029, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4|X5 },
+{"msub.s",  "D,R,S,T", 0x4c000028, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4|X5 },
 {"msub",    "s,t",     0x0000001e, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|L1 },
 {"msubu",   "s,t",     0x0000001f, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|L1 },
 {"mtc0",    "t,G",     0x40800000, 0xffe007ff, COD|RD_t|WR_C0|WR_CC    },
@@ -486,7 +532,16 @@ const struct mips_opcode mips_opcodes[] = {
 {"mtc2",    "t,G",     0x48800000, 0xffe007ff, COD|RD_t|WR_C2|WR_CC    },
 {"mtc3",    "t,G",     0x4c800000, 0xffe007ff, COD|RD_t|WR_C3|WR_CC    },
 {"mthi",    "s",       0x00000011, 0xfc1fffff, RD_s|WR_HI      },
+  /* start-sanitize-r5900 */
+{"mthi1",   "s",       0x70000011, 0xfc1fffff, RD_s|WR_HI|T5   },
+  /* end-sanitize-r5900 */
 {"mtlo",    "s",       0x00000013, 0xfc1fffff, RD_s|WR_LO      },
+  /* start-sanitize-r5900 */
+{"mtlo1",   "s",       0x70000013, 0xfc1fffff, RD_s|WR_LO|T5   },
+{"mtsa",    "s",        0x00000019, 0xfc1fffff, RD_s|T5                },
+{"mtsab",   "s,j",     0x04180000, 0xfc1f0000, RD_s|T5         },
+{"mtsah",   "s,j",     0x04190000, 0xfc1f0000, RD_s|T5         },
+  /* end-sanitize-r5900 */
 {"mul.d",   "D,V,T",   0x46200002, 0xffe0003f, WR_D|RD_S|RD_T  },
 {"mul.s",   "D,V,T",   0x46000002, 0xffe0003f, WR_D|RD_S|RD_T  },
 {"mul",     "d,v,t",   0x70000002, 0xfc0007ff, WR_d|RD_s|RD_t|WR_HI|WR_LO|P3},
@@ -497,15 +552,23 @@ const struct mips_opcode mips_opcodes[] = {
 {"mulou",   "d,v,t",   0,    (int) M_MULOU,    INSN_MACRO      },
 {"mulou",   "d,v,I",   0,    (int) M_MULOU_I,  INSN_MACRO      },
 {"mult",    "s,t",     0x00000018, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO   },
+{"mult",    "d,s,t",   0x00000018, 0xfc0007ff, RD_s|RD_t|WR_HI|WR_LO|WR_d },
+  /* start-sanitize-r5900 */
+{"mult1",   "d,s,t",   0x70000018, 0xfc0007ff, RD_s|RD_t|WR_HI|WR_LO|WR_d|T5},
+  /* end-sanitize-r5900 */
 {"multu",   "s,t",     0x00000019, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO   },
+{"multu",   "d,s,t",   0x00000019, 0xfc0007ff, RD_s|RD_t|WR_HI|WR_LO|WR_d },
+  /* start-sanitize-r5900 */
+{"multu1",  "d,s,t",   0x70000019, 0xfc0007ff, RD_s|RD_t|WR_HI|WR_LO|WR_d|T5},
+  /* end-sanitize-r5900 */
 {"neg",     "d,w",     0x00000022, 0xffe007ff, WR_d|RD_t       }, /* sub 0 */
 {"negu",    "d,w",     0x00000023, 0xffe007ff, WR_d|RD_t       }, /* subu 0 */
 {"neg.d",   "D,V",     0x46200007, 0xffff003f, WR_D|RD_S       },
 {"neg.s",   "D,V",     0x46000007, 0xffff003f, WR_D|RD_S       },
 {"nmadd.d", "D,R,S,T", 0x4c000031, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4 },
 {"nmadd.s", "D,R,S,T", 0x4c000030, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4 },
-{"nmsub.d", "D,R,S,T", 0x4c000039, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4 },
-{"nmsub.s", "D,R,S,T", 0x4c000038, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4 },
+{"nmsub.d", "D,R,S,T", 0x4c000039, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4|X5 },
+{"nmsub.s", "D,R,S,T", 0x4c000038, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|I4|X5 },
 /* nop is at the start of the table.  */
 {"nor",     "d,v,t",   0x00000027, 0xfc0007ff, WR_d|RD_s|RD_t  },
 {"nor",     "t,r,I",   0,    (int) M_NOR_I,    INSN_MACRO      },
@@ -513,8 +576,135 @@ const struct mips_opcode mips_opcodes[] = {
 {"or",      "d,v,t",   0x00000025, 0xfc0007ff, WR_d|RD_s|RD_t  },
 {"or",      "t,r,I",   0,    (int) M_OR_I,     INSN_MACRO      },
 {"ori",     "t,r,i",   0x34000000, 0xfc000000, WR_t|RD_s       },
+
+  /* start-sanitize-r5900 */
+{"pabsh",   "d,t",     0x70000168, 0xffe007ff, WR_d|RD_t|T5    },
+{"pabsw",   "d,t",     0x70000068, 0xffe007ff, WR_d|RD_t|T5    },
+{"paddb",   "d,v,t",   0x70000208, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"paddh",   "d,v,t",   0x70000108, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"paddw",   "d,v,t",   0x70000008, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"paddsb",  "d,v,t",   0x70000608, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"paddsh",  "d,v,t",   0x70000508, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"paddsw",  "d,v,t",   0x70000408, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"paddub",  "d,v,t",   0x70000628, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"padduh",  "d,v,t",   0x70000528, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"padduw",  "d,v,t",   0x70000428, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"padsbh",  "d,v,t",   0x70000128, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"pand",    "d,v,t",   0x70000489, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"pceqb",   "d,v,t",   0x700002a8, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"pceqh",   "d,v,t",   0x700001a8, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"pceqw",   "d,v,t",   0x700000a8, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+
+{"pcgtb",   "d,v,t",   0x70000288, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"pcgth",   "d,v,t",   0x70000188, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"pcgtw",   "d,v,t",   0x70000088, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+
+{"pcpyh",   "d,t",     0x700006e9, 0xffe007ff, WR_d|RD_t|T5    },
+
+{"pcpyld",  "d,v,t",   0x70000389, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"pcpyud",  "d,v,t",   0x700003a9, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+
+{"pdivbw",   "s,t",    0x70000749, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|T5},
+{"pdivuw",   "s,t",    0x70000369, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|T5},
+{"pdivw",    "s,t",    0x70000349, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO|T5},
+
+{"pexch",    "d,t",    0x700006a9, 0xffe007ff, WR_d|RD_t|T5    },
+{"pexcw",    "d,t",    0x700007a9, 0xffe007ff, WR_d|RD_t|T5    },
+{"pexoh",    "d,t",    0x70000689, 0xffe007ff, WR_d|RD_t|T5    },
+{"pexow",    "d,t",    0x70000789, 0xffe007ff, WR_d|RD_t|T5    },
+
+{"pext1",    "d,t",    0x70000788, 0xffe007ff, WR_d|RD_t|T5    },
+
+{"pextlb",   "d,v,t",  0x70000688, 0xfc0007ff, WR_d|RD_s|RD_t|T5 },
+{"pextlh",   "d,v,t",  0x70000588, 0xfc0007ff, WR_d|RD_s|RD_t|T5 },
+{"pextlw",   "d,v,t",  0x70000488, 0xfc0007ff, WR_d|RD_s|RD_t|T5 },
+{"pextub",   "d,v,t",  0x700006a8, 0xfc0007ff, WR_d|RD_s|RD_t|T5 },
+{"pextuh",   "d,v,t",  0x700005a8, 0xfc0007ff, WR_d|RD_s|RD_t|T5 },
+{"pextuw",   "d,v,t",  0x700004a8, 0xfc0007ff, WR_d|RD_s|RD_t|T5 },
+
+{"phmaddh",  "d,v,t",  0x70000449, 0xfc0007ff,WR_d|RD_s|RD_t|WR_HI|WR_LO|T5 },
+{"phmsubh",  "d,v,t",  0x70000549, 0xfc0007ff,WR_d|RD_s|RD_t|WR_HI|WR_LO|T5 },
+
+{"pinth",    "d,v,t",  0x70000289, 0xfc0007ff, WR_d|RD_s|RD_t|T5 },
+{"pintoh",   "d,v,t",  0x700002a9, 0xfc0007ff, WR_d|RD_s|RD_t|T5 },
+
+{"plzcw",    "d,v",    0x70000004, 0xfc1f07ff, WR_d|RD_s|T5 },
+
+{"pmaddh",   "d,v,t",  0x70000409, 0xfc0007ff,WR_d|RD_s|RD_t|WR_HI|WR_LO|T5 },
+{"pmadduw",  "d,v,t",  0x70000029, 0xfc0007ff,WR_d|RD_s|RD_t|WR_HI|WR_LO|T5 },
+{"pmaddw",   "d,v,t",  0x70000009, 0xfc0007ff,WR_d|RD_s|RD_t|WR_HI|WR_LO|T5 },
+
+{"pmaxh",    "d,v,t",  0x700001c8, 0xfc0007ff, WR_d|RD_s|RD_t|T5 },
+{"pmaxw",    "d,v,t",  0x700000c8, 0xfc0007ff, WR_d|RD_s|RD_t|T5 },
+
+{"pmfhi",    "d",      0x70000209, 0xffff07ff, WR_d|RD_HI|T5 },
+{"pmflo",    "d",      0x70000249, 0xffff07ff, WR_d|RD_LO|T5 },
+
+{"pmfhl.lw", "d",      0x70000030, 0xffff07ff, WR_d|RD_LO|RD_HI|T5 },
+{"pmfhl.uw", "d",      0x70000070, 0xffff07ff, WR_d|RD_LO|RD_HI|T5 },
+{"pmfhl.slw","d",      0x700000b0, 0xffff07ff, WR_d|RD_LO|RD_HI|T5 },
+{"pmfhl.lh", "d",      0x700000f0, 0xffff07ff, WR_d|RD_LO|RD_HI|T5 },
+{"pmfhl.sh", "d",      0x70000130, 0xffff07ff, WR_d|RD_LO|RD_HI|T5 },
+
+{"pminh",    "d,v,t",  0x700001e8, 0xfc0007ff, WR_d|RD_s|RD_t|T5 },
+{"pminw",    "d,v,t",  0x700000e8, 0xfc0007ff, WR_d|RD_s|RD_t|T5 },
+
+{"pmsubh",   "d,v,t",  0x70000509, 0xfc0007ff,WR_d|RD_s|RD_t|WR_HI|WR_LO|T5 },
+{"pmsubw",   "d,v,t",  0x70000109, 0xfc0007ff,WR_d|RD_s|RD_t|WR_HI|WR_LO|T5 },
+
+{"pmthi",    "v",      0x70000229, 0xfc1fffff, WR_HI|RD_s|T5 },
+{"pmtlo",    "v",      0x70000269, 0xfc1fffff, WR_LO|RD_s|T5 },
+
+{"pmthl.lw", "v",      0x70000031, 0xfc1fffff, WR_HI|WR_LO|RD_s|T5 },
+
+{"pmulth",   "d,v,t",  0x70000709, 0xfc0007ff,WR_d|RD_s|RD_t|WR_HI|WR_LO|T5 },
+{"pmultuw",  "d,v,t",  0x70000329, 0xfc0007ff,WR_d|RD_s|RD_t|WR_HI|WR_LO|T5 },
+{"pmultw",   "d,v,t",  0x70000309, 0xfc0007ff,WR_d|RD_s|RD_t|WR_HI|WR_LO|T5 },
+
+{"pnor",    "d,v,t",   0x700004e9, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"por",     "d,v,t",   0x700004a9, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+
+{"ppac1",   "d,t",     0x700007c8, 0xffe007ff, WR_d|RD_t|T5    },
+
+{"ppacb",   "d,v,t",   0x700006c8, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"ppach",   "d,v,t",   0x700005c8, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"ppacw",   "d,v,t",   0x700004c8, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+
+{"prevh",   "d,t",     0x700006c9, 0xffe007ff, WR_d|RD_t|T5    },
+{"prot3w",  "d,t",     0x700007c9, 0xffe007ff, WR_d|RD_t|T5    },
+
+{"psllh",  "d,t,<",    0x70000034, 0xffe0003f, WR_d|RD_t|T5    },
+{"psllvw", "d,t,s",    0x70000089, 0xfc0007ff, WR_d|RD_t|RD_s|T5 },
+{"psllw",  "d,t,<",    0x7000003c, 0xffe0003f, WR_d|RD_t|T5    },
+
+{"psrah",  "d,t,<",    0x70000037, 0xffe0003f, WR_d|RD_t|T5    },
+{"psravw", "d,t,s",    0x700000e9, 0xfc0007ff, WR_d|RD_t|RD_s|T5 },
+{"psraw",  "d,t,<",    0x7000003f, 0xffe0003f, WR_d|RD_t|T5    },
+
+{"psrlh",  "d,t,<",    0x70000036, 0xffe0003f, WR_d|RD_t|T5    },
+{"psrlvw", "d,t,s",    0x700000c9, 0xfc0007ff, WR_d|RD_t|RD_s|T5 },
+{"psrlw",  "d,t,<",    0x7000003e, 0xffe0003f, WR_d|RD_t|T5    },
+
+{"psubb",  "d,v,t",    0x70000248, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"psubh",  "d,v,t",    0x70000148, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"psubsb", "d,v,t",    0x70000648, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"psubsh", "d,v,t",    0x70000548, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"psubsw", "d,v,t",    0x70000448, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"psubub", "d,v,t",    0x70000668, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"psubuh", "d,v,t",    0x70000568, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"psubuw", "d,v,t",    0x70000468, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+{"psubw",  "d,v,t",    0x70000048, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+
+{"pxor",   "d,v,t",    0x700004c9, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+  /* end-sanitize-r5900 */
+
 {"pref",    "k,o(b)",  0xcc000000, 0xfc000000, RD_b|I4         },
 {"prefx",   "h,t(b)",  0x4c00000f, 0xfc0007ff, RD_b|RD_t|I4    },
+
+  /* start-sanitize-r5900 */
+{"qfsrv",   "d,v,t",   0x700006e8, 0xfc0007ff, WR_d|RD_s|RD_t|T5  },
+  /* end-sanitize-r5900 */
+
 {"recip.d", "D,S",     0x46200015, 0xffff003f, WR_D|RD_S|I4    },
 {"recip.s", "D,S",     0x46000015, 0xffff003f, WR_D|RD_S|I4    },
 {"rem",     "z,s,t",   0x0000001a, 0xfc00ffff, RD_s|RD_t|WR_HI|WR_LO },
@@ -558,7 +748,7 @@ const struct mips_opcode mips_opcodes[] = {
 {"sdl",     "t,A(b)",  3,    (int) M_SDL_AB,   INSN_MACRO      },
 {"sdr",     "t,o(b)",  0xb4000000, 0xfc000000, SM|RD_t|RD_b|I3 },
 {"sdr",     "t,A(b)",  3,    (int) M_SDR_AB,   INSN_MACRO      },
-{"sdxc1",   "S,t(b)",   0x4c000009, 0xfc0007ff, SM|RD_S|RD_t|RD_b|I4 },
+{"sdxc1",   "S,t(b)",   0x4c000009, 0xfc0007ff, SM|RD_S|RD_t|RD_b|I4|X5 },
 {"selsl",   "d,v,t",   0x00000005, 0xfc0007ff, WR_d|RD_s|RD_t|L1 },
 {"selsr",   "d,v,t",   0x00000001, 0xfc0007ff, WR_d|RD_s|RD_t|L1 },
 {"seq",     "d,v,t",   0,    (int) M_SEQ,      INSN_MACRO      },
@@ -588,6 +778,9 @@ const struct mips_opcode mips_opcodes[] = {
 {"sltu",    "d,v,I",   0,    (int) M_SLTU_I,   INSN_MACRO      },
 {"sne",     "d,v,t",   0,    (int) M_SNE,      INSN_MACRO      },
 {"sne",     "d,v,I",   0,    (int) M_SNE_I,    INSN_MACRO      },
+  /* start-sanitize-r5900 */
+{"sq",     "t,o(b)",   0x7c000000, 0xfc000000, SM|RD_t|RD_b|T5 },
+  /* end-sanitize-r5900 */
 {"sqrt.d",  "D,S",     0x46200004, 0xffff003f, WR_D|RD_S|I2    },
 {"sqrt.s",  "D,S",     0x46000004, 0xffff003f, WR_D|RD_S|I2    },
 {"srav",    "d,t,s",   0x00000007, 0xfc0007ff, WR_d|RD_t|RD_s  },
@@ -626,7 +819,7 @@ const struct mips_opcode mips_opcodes[] = {
 {"swr",     "t,A(b)",  0,    (int) M_SWR_AB,   INSN_MACRO      },
 {"invalidate", "t,o(b)",0xb8000000, 0xfc000000,        RD_t|RD_b|I2    }, /* same */
 {"invalidate", "t,A(b)",2,    (int) M_SWR_AB,  INSN_MACRO      }, /* as swr */
-{"swxc1",   "S,t(b)",   0x4c000008, 0xfc0007ff, SM|RD_S|RD_t|RD_b|I4 },
+{"swxc1",   "S,t(b)",   0x4c000008, 0xfc0007ff, SM|RD_S|RD_t|RD_b|I4|X5 },
 {"sync",    "",                0x0000000f, 0xffffffff, I2              },
 {"syscall", "",                0x0000000c, 0xffffffff, TRAP            },
 {"syscall", "B",       0x0000000c, 0xfc00003f, TRAP            },
index b9a0f2ecf7d514dc02441a9199a9a1a289fec454..578283d47f6c60205be6dde670f8739f5b59fdee 100644 (file)
@@ -38,8 +38,37 @@ tconfig.in
 
 Things-to-lose:
 
-
 Do-last:
 
+r5900_files="ChangeLog configure configure.in interp.c gencode.c"
+
+if ( echo $* | grep keep\-r5900 > /dev/null ) ; then
+       for i in $r5900_files ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Keeping r5900 stuff in $i
+                       fi
+               fi
+       done
+else
+       for i in * ; do
+               if test ! -d $i && (grep sanitize-r5900 $i > /dev/null) ; then
+                       if [ -n "${verbose}" ] ; then
+                               echo Removing traces of \"r5900\" from $i...
+                       fi
+                       cp $i new
+                       sed '/start\-sanitize\-r5900/,/end-\sanitize\-r5900/d' < $i > new
+                       if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
+                               if [ -n "${verbose}" ] ; then
+                                       echo Caching $i in .Recover...
+                               fi
+                               mv $i .Recover
+                       fi
+                       mv new $i
+               fi
+       done
+fi
+
+
 
 # End of file.
index 4b71012e1f008306b402c3beb70ed447d9f60257..961eaa195ef6cdc35665085e94af083855fe1fb5 100644 (file)
@@ -1,3 +1,10 @@
+start-sanitize-r5900
+Fri Feb  7 11:12:44 1997  Gavin Koch  <gavin@cygnus.com>
+        
+        * Makefile.in, configure, configure.in, gencode.c, 
+        interp.c, support.h: add r5900.
+        
+end-sanitize-r5900
 Thu Feb  6 17:16:15 1997  Ian Lance Taylor  <ian@cygnus.com>
 
        * interp.c (mips16_entry): Add support for floating point cases.
index 938ba7fc425811e97f7c88812161d1cde4712738..179940af75e40862e339a51d103e22d84e4202e3 100644 (file)
@@ -7,6 +7,9 @@ SIM_AC_COMMON
 
 # Ensure a reasonable default simulator is constructed:
 case "${target}" in
+# start-sanitize-r5900
+  mips64vr59*-*-*)      SIMCONF="-mips3 --warnings -mcpu=r5900";;
+# end-sanitize-r5900
   mips64*-*-*)          SIMCONF="-mips0 --warnings";;
   mips16*-*-*)          SIMCONF="-mips0 --warnings";;
   mips*-*-*)            SIMCONF="-mips2 --warnings";;
index 6f0393ef7ef165c93dd985ad7690975a2a95f409..7518746a2a8d2bc22bc2b5b012bd76f140d28022 100644 (file)
@@ -208,6 +208,7 @@ typedef struct operand_encoding {
 #define OP_SIGNX  (1 << 1)      /* Sign-extend the operand */
 #define OP_SHIFT2 (1 << 2)      /* Shift field left by 2 */
 #define OP_BITS5  (1 << 3)      /* Only take the lo 5-bits of the operand */
+#define OP_GPR1   (1 << 4)      /* fetch from the GPR1 registers */
 
 struct operand_encoding opfields[] = {
  {'0',-1,-1,"",      "",              (OP_NONE)},  /* special case for explicit zero */
@@ -240,8 +241,11 @@ struct operand_encoding opfields[] = {
  {'x',23, 1,"int",   "to",            (OP_NONE)},  /* TRUE if move To; FALSE if move From */
  {'y', 0,16,"t_reg", "offset",        (OP_SIGNX)}, /* signed offset */
  {'z', 0,16,"ut_reg","op2",           (OP_NONE)},  /* unsigned immediate (zero extended) */
+ {'S',21, 5,"t_reg", "rs_reg",  (OP_GPR|OP_GPR1)}, /* rs field, GPR[rs] and GPR1[rs] as source */
+ {'T',16, 5,"t_reg", "rt_reg",  (OP_GPR|OP_GPR1)}, /* rt field, GPR[rt] and GPR1[rt] as source */
 };
 
+
 /* Main instruction encoding types: */
 typedef enum {
  NORMAL,
@@ -251,6 +255,12 @@ typedef enum {
  COP1X,
  COP1S, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
 
+ MMINORM,
+ MMI0,
+ MMI1,
+ MMI2,
+ MMI3,
+
  /* mips16 encoding types.  */
  I, RI, RR, RRI, RRR, RRI_A, ISHIFT, I8, I8_MOVR32, I8_MOV32R, I64, RI64
 } inst_type;
@@ -296,6 +306,55 @@ typedef enum {
  FPSQRT,
  FPCONVERT,
  FPCOMPARE,
+ /* start-sanitize-r5900 */
+ MADD,
+ PABS,
+ PADD,
+ PADSBH,
+ POP,
+ PCMP,
+ PCPYH,
+ PCPYLD,
+ PCPYUD,
+ PEXCH,
+ PEXCW,
+ PEXOH,
+ PEXOW,
+ PEXTLB,
+ PEXTLH,
+ PEXTLW,
+ PEXTUB,
+ PEXTUH,
+ PEXTUW,
+ PPACB,
+ PPACH,
+ PPACW,
+ PREVH,
+ PROT3W,
+ PINTH,
+ PINTOH,
+ PMXX,
+ PMFHL,
+ PMTHL,
+ PMAXMIN,
+ QFSRV,
+ MxSA,
+ MTSAB,
+ MTSAH,
+ PSHIFT,
+ PSLLVW,
+ PSRLVW,
+ PSRAVW,
+ PLZCW,
+ PHMADDH,
+ PMULTH,
+ PMULTW,
+ PDIVBW,
+ PDIVW,
+ PEXT5,
+ PPAC5,
+ /* end-sanitize-r5900 */
+ NYI,                   /* Not Yet Implemented, placeholder, errors if used */
  RSVD                   /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
 } opcode_type;
 
@@ -309,9 +368,9 @@ typedef enum {
 #define DOUBLEWORD      (3)     /* 64bit */
 #define SINGLE          (4)     /* single precision FP */
 #define DOUBLE          (5)     /* double precision FP */
+#define QUADWORD        (6)     /* 128bit */
 
 /* Shorthand to get the size field from the flags value: */
-#define GETDATASIZE()   ((MIPS_DECODE[loop].flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
 #define GETDATASIZEINSN(i) (((i)->flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
 
 /* The rest are single bit flags: */
@@ -348,6 +407,26 @@ typedef enum {
    all options are applicable to all instruction types. This will free
    up more space for new flags. */
 
+/* Overloadings of above bits */
+#define PIPE1        LIKELY      /* Using pipeline 1 (DIV,MUL) */
+#define OP3          EQ          /* 3 operand version of operation  (MUL)     */
+
+#define SATURATE     OVERFLOW    /* for PADD, saturate for overflow           */
+
+#define SUBTRACT     LEFT        /* for PMULT, PMULT becomes PMSUB            */
+#define ADDITION     RIGHT       /* for PMULT, PMULT becomes PMADD            */
+
+#define FROM         LEFT        /* move from special register                */
+#define TO           RIGHT       /* move to special register                  */
+
+/* For bitwise parallel operations */ 
+#define POP_AND      BYTE        /* for POP, op = &                           */
+#define POP_OR       HALFWORD    /* for POP, op = |                           */
+#define POP_NOR      WORD        /* for POP, op = ~(x | y)                    */
+#define POP_XOR      DOUBLEWORD  /* for POP, op = ^                           */
+
+#define GET_OP_FROM_INSN(insn) GETDATASIZEINSN(insn)
+   
 typedef struct instruction {
  char         *name;   /* ASCII mnemonic name */
  unsigned int  isa;    /* MIPS ISA number where instruction introduced */
@@ -373,6 +452,43 @@ typedef struct instruction {
 /* The other bits are allocated downwards, to avoid renumbering if we
    have to extend the bits allocated to the pure ISA number. */
 #define ARCH_VR4100       ((unsigned)1 << 31) /* NEC VR4100 extension instructions */
+/* start-sanitize-r5900 */
+#define ARCH_R5900        ((unsigned)1 << 30) /* Toshiba r5900 extension instructions */
+/* end-sanitize-r5900 */
+
+/* A list (or'ed) of extension insn sets that can be requested independant of the ISA# */
+#define MASK_ISA_INDEP  (0                                             \
+                         /* start-sanitize-r5900 */                    \
+                         | ARCH_R5900                                  \
+                         /* end-sanitize-r5900 */                      \
+                         | 0)
+
+
+
+
+/* Very short names for use in the table below to keep it neet. */
+#define G1 (3 | ARCH_VR4100)
+
+#define G2 (4                                        \
+            /* start-sanitize-r5900 */               \
+            | ARCH_R5900                             \
+            /* end-sanitize-r5900 */                 \
+            | 0)
+
+#define G3 (4                                                           \
+            /* start-sanitize-r5900 */                                  \
+            /* insn that are not really 5900 insn but were left in */   \
+            /* until we can rewrite the code-gen and libs          */   \
+            | ARCH_R5900                                                \
+            /* end-sanitize-r5900 */                                    \
+            | 0)
+
+
+
+/* start-sanitize-r5900 */
+#define T5 ARCH_R5900       
+/* end-sanitize-r5900 */
+
 
 /* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
    COP0 space. This means that an external decoder should be added
@@ -425,8 +541,14 @@ struct instruction MIPS_DECODE[] = {
  {"DDIVU",   3,"000000sssssggggg0000000000011111",SPECIAL,DIV,      (DOUBLEWORD | UNSIGNED | HI | LO)},
  {"DIV",     1,"000000sssssggggg0000000000011010",SPECIAL,DIV,      (WORD | WORD32 | SIGNEXTEND | HI | LO)},
  {"DIV",     1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1,   FPDIV,    (FP | WORD | HI | LO)},
+ /* start-sanitize-r5900 */
+ {"DIV1",   T5,"011100sssssggggg0000000000011010",MMINORM,DIV,      (WORD | WORD32 | SIGNEXTEND | HI | LO | PIPE1)},
+ /* end-sanitize-r5900 */
  {"DIVU",    1,"000000sssssggggg0000000000011011",SPECIAL,DIV,      (WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO)},
- {"DMADD16", (ARCH_VR4100 | 3),"000000sssssggggg0000000000101001",SPECIAL,MADD16,   (DOUBLEWORD | HI | LO)},
+ /* start-sanitize-r5900 */
+ {"DIVU1",  T5,"011100sssssggggg0000000000011011",MMINORM,DIV,      (WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO | PIPE1)},
+ /* end-sanitize-r5900 */
+ {"DMADD16",G1,"000000sssssggggg0000000000101001",SPECIAL,MADD16,   (DOUBLEWORD | HI | LO)},
  {"DMULT",   3,"000000sssssggggg0000000000011100",SPECIAL,MUL,      (DOUBLEWORD | HI | LO)},
  {"DMULTU",  3,"000000sssssggggg0000000000011101",SPECIAL,MUL,      (DOUBLEWORD | UNSIGNED | HI | LO)},
  {"DMxC1",   3,"01000100x01kkkkkvvvvv00000000000",COP1S,  FPMOVEC,  (FP | DOUBLEWORD)},
@@ -455,38 +577,69 @@ struct instruction MIPS_DECODE[] = {
  {"LDC2",    2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD,     (DOUBLEWORD | COPROC)},
  {"LDL",     3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD,     (DOUBLEWORD | LEFT)},      /* NOTE: See "LB" comment */
  {"LDR",     3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD,     (DOUBLEWORD | RIGHT)},     /* NOTE: See "LB" comment */
- {"LDXC1",   4,"010011sssssggggg00000rrrrr000001",COP1X,  LOAD,     (FP | DOUBLEWORD | COPROC | REG)},
+ {"LDXC1",  G3,"010011sssssggggg00000rrrrr000001",COP1X,  LOAD,     (FP | DOUBLEWORD | COPROC | REG)},
  {"LH",      1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD,     (HALFWORD | SIGNEXTEND)},
  {"LHU",     1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD,     (HALFWORD)},
  {"LL",      2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD,     (WORD | ATOMIC | SIGNEXTEND)},
  {"LLD",     3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD,     (DOUBLEWORD | ATOMIC)},
  {"LUI",     1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL, MOVE,     (SHIFT16)}, /* Cheat and specify sign-extension of immediate field */
+ /* start-sanitize-r5900 */
+ {"LQ",     T5,"011110sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD,     (QUADWORD)},
+ /* end-sanitize-r5900 */
  {"LW",      1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD,     (WORD | SIGNEXTEND)},
  {"LWC1",    1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD,     (WORD | COPROC)},
  {"LWC2",    1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD,     (WORD | COPROC)},
  {"LWL",     1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD,     (WORD | LEFT)},
  {"LWR",     1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD,     (WORD | RIGHT)},
  {"LWU",     3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD,     (WORD)},
- {"LWXC1",   4,"010011sssssggggg00000rrrrr000000",COP1X,  LOAD,     (FP | WORD | COPROC | REG)},
- {"MADD16",  (ARCH_VR4100 | 3),"000000sssssggggg0000000000101000",SPECIAL,MADD16,   (WORD | HI | LO)},
- {"MADD.D",  4,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X,  FPADD,    (FP | MULTIPLY | DOUBLE)},
- {"MADD.S",  4,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X,  FPADD,    (FP | MULTIPLY | SINGLE)},
+ {"LWXC1",  G3,"010011sssssggggg00000rrrrr000000",COP1X,  LOAD,     (FP | WORD | COPROC | REG)},
+ /* start-sanitize-r5900 */
+ {"MADD",   T5,"011100sssssgggggddddd00000000000",MMINORM,MADD,     (NONE)},
+ {"MADD1",  T5,"011100sssssgggggddddd00000100000",MMINORM,MADD,     (PIPE1)},
+ {"MADDU",  T5,"011100sssssgggggddddd00000000001",MMINORM,MADD,     (UNSIGNED)},
+ {"MADDU1", T5,"011100sssssgggggddddd00000100001",MMINORM,MADD,     (UNSIGNED | PIPE1)},
+ /* end-sanitize-r5900 */
+ {"MADD16", G1,"000000sssssggggg0000000000101000",SPECIAL,MADD16,   (WORD | HI | LO)},
+ {"MADD.D", G3,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X,  FPADD,    (FP | MULTIPLY | DOUBLE)},
+ {"MADD.S", G3,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X,  FPADD,    (FP | MULTIPLY | SINGLE)},
  {"MFHI",    1,"0000000000000000ddddd00000010000",SPECIAL,MOVE,     (HI | LEFT)},    /* with following, from and to denoted by usage of LEFT or RIGHT */
+ /* start-sanitize-r5900 */
+ {"MFHI1",  T5,"0111000000000000ddddd00000010000",MMINORM,MOVE,     (HI | LEFT | PIPE1)},
+ /* end-sanitize-r5900 */
  {"MFLO",    1,"0000000000000000ddddd00000010010",SPECIAL,MOVE,     (LO | LEFT)},
+ /* start-sanitize-r5900 */
+ {"MFLO1",  T5,"0111000000000000ddddd00000010010",MMINORM,MOVE,     (LO | LEFT | PIPE1)},
+ {"MFSA",   T5,"0000000000000000ddddd00000101000",SPECIAL,MxSA,     (FROM)},
+ /* end-sanitize-r5900 */
  {"MTHI",    1,"000000sssss000000000000000010001",SPECIAL,MOVE,     (HI | RIGHT)},
+ /* start-sanitize-r5900 */
+ {"MTHI1",  T5,"011100sssss000000000000000010001",MMINORM,MOVE,     (HI | RIGHT | PIPE1)},
+ /* end-sanitize-r5900 */
  {"MTLO",    1,"000000sssss000000000000000010011",SPECIAL,MOVE,     (LO | RIGHT)},
+ /* start-sanitize-r5900 */
+ {"MTLO1",  T5,"011100sssss000000000000000010011",MMINORM,MOVE,     (LO | RIGHT | PIPE1)},
+ {"MTSA",   T5,"000000sssss000000000000000101001",SPECIAL,MxSA,     (TO)},
+ {"MTSAB",  T5,"000001sssss11000iiiiiiiiiiiiiiii",REGIMM, MTSAB,    (NONE)},
+ {"MTSAH",  T5,"000001sssss11001iiiiiiiiiiiiiiii",REGIMM, MTSAH,    (NONE)},
+ /* end-sanitize-r5900 */
  {"MOV",     1,"01000110mmm00000vvvvvrrrrr000110",COP1,   FPMOVE,   (FP)},
- {"MOVN",    4,"000000sssssgggggddddd00000001011",SPECIAL,MOVE,     (NOT | EQ)},
- {"MOVN",    4,"01000110mmmgggggvvvvvrrrrr010011",COP1,   FPMOVE,   (FP | NOT | EQ)},
- {"MOV%c",   4,"000000sssssqqq0cddddd00000000001",SPECIAL,FPMOVE,   (FP | CONDITIONAL | INTEGER)},
- {"MOV%c",   4,"01000110mmmqqq0cvvvvvrrrrr010001",COP1,   FPMOVE,   (FP | CONDITIONAL)},
- {"MOVZ",    4,"000000sssssgggggddddd00000001010",SPECIAL,MOVE,     (EQ)},
- {"MOVZ",    4,"01000110mmmgggggvvvvvrrrrr010010",COP1,   FPMOVE,   (FP | EQ)},
- {"MSUB.D",  4,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X,  FPSUB,    (FP | MULTIPLY | DOUBLE)},
- {"MSUB.S",  4,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X,  FPSUB,    (FP | MULTIPLY | SINGLE)},
+ {"MOVN",   G2,"000000sssssgggggddddd00000001011",SPECIAL,MOVE,     (NOT | EQ)},
+ {"MOVN",   G2,"01000110mmmgggggvvvvvrrrrr010011",COP1,   FPMOVE,   (FP | NOT | EQ)},
+ {"MOV%c",  G3,"000000sssssqqq0cddddd00000000001",SPECIAL,FPMOVE,   (FP | CONDITIONAL | INTEGER)},
+ {"MOV%c",  G3,"01000110mmmqqq0cvvvvvrrrrr010001",COP1,   FPMOVE,   (FP | CONDITIONAL)},
+ {"MOVZ",   G2,"000000sssssgggggddddd00000001010",SPECIAL,MOVE,     (EQ)},
+ {"MOVZ",   G2,"01000110mmmgggggvvvvvrrrrr010010",COP1,   FPMOVE,   (FP | EQ)},
+ {"MSUB.D", G3,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X,  FPSUB,    (FP | MULTIPLY | DOUBLE)},
+ {"MSUB.S", G3,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X,  FPSUB,    (FP | MULTIPLY | SINGLE)},
  {"MUL",     1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1,   FPMUL,    (FP | HI | LO)},
- {"MULT",    1,"000000sssssggggg0000000000011000",SPECIAL,MUL,      (WORD | WORD32 | HI | LO)},
- {"MULTU",   1,"000000sssssggggg0000000000011001",SPECIAL,MUL,      (WORD | WORD32 | UNSIGNED | HI | LO)},
+ {"MULT",    1,"000000sssssgggggddddd00000011000",SPECIAL,MUL,      (OP3 | WORD | WORD32 | HI | LO)},
+ /* start-sanitize-r5900 */
+ {"MULT1",  T5,"011100sssssgggggddddd00000011000",MMINORM,MUL,      (OP3 | WORD | WORD32 | HI | LO | PIPE1)},
+ /* end-sanitize-r5900 */
+ {"MULTU",   1,"000000sssssgggggddddd00000011001",SPECIAL,MUL,      (OP3 | WORD | WORD32 | UNSIGNED | HI | LO)},
+ /* start-sanitize-r5900 */
+ {"MULTU1", T5,"011100sssssgggggddddd00000011001",MMINORM,MUL,      (OP3 | WORD | WORD32 | UNSIGNED | HI | LO | PIPE1)},
+ /* end-sanitize-r5900 */
  {"MxC1",    1,"01000100x00kkkkkvvvvv00000000000",COP1S,  FPMOVEC,  (FP | WORD)},
  {"NEG",     1,"01000110mmm00000vvvvvrrrrr000111",COP1,   FPNEG,    (FP)},
  {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X,  FPADD,    (FP | NOT | MULTIPLY | DOUBLE)},
@@ -496,8 +649,136 @@ struct instruction MIPS_DECODE[] = {
  {"NOR",     1,"000000sssssgggggddddd00000100111",SPECIAL,OR,       (NOT)},
  {"OR",      1,"000000sssssgggggddddd00000100101",SPECIAL,OR,       (NONE)},
  {"ORI",     1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL, OR,       (NONE)},
- {"PREF",    4,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, PREFETCH, (NONE)},
+
+ /* start-sanitize-r5900 */
+ {"PABSH",  T5,"01110000000TTTTTddddd00101101000",MMI1,   PABS,     (HALFWORD)},
+ {"PABSW",  T5,"01110000000TTTTTddddd00001101000",MMI1,   PABS,     (WORD)},
+
+ {"PADDB",  T5,"011100SSSSSTTTTTddddd01000001000",MMI0,   PADD,     (BYTE)},
+ {"PADDH",  T5,"011100SSSSSTTTTTddddd00100001000",MMI0,   PADD,     (HALFWORD)},
+ {"PADDW",  T5,"011100SSSSSTTTTTddddd00000001000",MMI0,   PADD,     (WORD)},
+
+ {"PADDSB", T5,"011100SSSSSTTTTTddddd11000001000",MMI0,   PADD,     (BYTE | SATURATE)},
+ {"PADDSH", T5,"011100SSSSSTTTTTddddd10100001000",MMI0,   PADD,     (HALFWORD | SATURATE)},
+ {"PADDSW", T5,"011100SSSSSTTTTTddddd10000001000",MMI0,   PADD,     (WORD | SATURATE)},
+
+ {"PADDUB", T5,"011100SSSSSTTTTTddddd11000101000",MMI1,   PADD,     (BYTE | UNSIGNED)},
+ {"PADDUH", T5,"011100SSSSSTTTTTddddd10100101000",MMI1,   PADD,     (HALFWORD | UNSIGNED)},
+ {"PADDUW", T5,"011100SSSSSTTTTTddddd10000101000",MMI1,   PADD,     (WORD | UNSIGNED)},
+
+ {"PADSBH", T5,"011100SSSSSTTTTTddddd00100101000",MMI1,   PADSBH,   (NONE)},
+
+ {"PAND",   T5,"011100SSSSSTTTTTddddd10010001001",MMI2,   POP,      (POP_AND)},
+
+ {"PCEQB",  T5,"011100SSSSSTTTTTddddd01010101000",MMI1,   PCMP,     (EQ | BYTE)},
+ {"PCEQH",  T5,"011100SSSSSTTTTTddddd00110101000",MMI1,   PCMP,     (EQ | HALFWORD)},
+ {"PCEQW",  T5,"011100SSSSSTTTTTddddd00010101000",MMI1,   PCMP,     (EQ | WORD)},
+
+ {"PCGTB",  T5,"011100SSSSSTTTTTddddd01010001000",MMI0,   PCMP,     (GT | BYTE)},
+ {"PCGTH",  T5,"011100SSSSSTTTTTddddd00110001000",MMI0,   PCMP,     (GT | HALFWORD)},
+ {"PCGTW",  T5,"011100SSSSSTTTTTddddd00010001000",MMI0,   PCMP,     (GT | WORD)},
+
+ {"PCPYH",  T5,"01110000000TTTTTddddd11011101001",MMI3,   PCPYH,    (NONE)},
+ {"PCPYLD", T5,"011100SSSSSTTTTTddddd01110001001",MMI2,   PCPYLD,   (NONE)},
+ {"PCPYUD", T5,"011100SSSSSTTTTTddddd01110101001",MMI3,   PCPYUD,   (NONE)},
+
+ {"PDIVBW", T5,"011100SSSSSTTTTT0000011101001001",MMI2,   PDIVBW,   (NONE)},
+ {"PDIVUW", T5,"011100SSSSSTTTTT0000001101101001",MMI3,   PDIVW,    (UNSIGNED)},
+ {"PDIVW",  T5,"011100SSSSSTTTTT0000001101001001",MMI2,   PDIVW,    (NONE)},
+ {"PEXCH",  T5,"01110000000TTTTTddddd11010101001",MMI3,   PEXCH,    (NONE)},
+ {"PEXCW",  T5,"01110000000TTTTTddddd11110101001",MMI3,   PEXCW,    (NONE)},
+ {"PEXOH",  T5,"01110000000TTTTTddddd11010001001",MMI2,   PEXOH,    (NONE)},
+ {"PEXOW",  T5,"01110000000TTTTTddddd11110001001",MMI2,   PEXOW,    (NONE)},
+
+ {"PEXT5",  T5,"01110000000TTTTTddddd11110001000",MMI0,   PEXT5,    (NONE)},
+
+ {"PEXTLB", T5,"011100SSSSSTTTTTddddd11010001000",MMI0,   PEXTLB,   (NONE)},
+ {"PEXTLH", T5,"011100SSSSSTTTTTddddd10110001000",MMI0,   PEXTLH,   (NONE)},
+ {"PEXTLW", T5,"011100SSSSSTTTTTddddd10010001000",MMI0,   PEXTLW,   (NONE)},
+ {"PEXTUB", T5,"011100SSSSSTTTTTddddd11010101000",MMI1,   PEXTUB,   (NONE)},
+ {"PEXTUH", T5,"011100SSSSSTTTTTddddd10110101000",MMI1,   PEXTUH,   (NONE)},
+ {"PEXTUW", T5,"011100SSSSSTTTTTddddd10010101000",MMI1,   PEXTUW,   (NONE)},
+
+ {"PHMADDH",T5,"011100SSSSSTTTTTddddd10001001001",MMI2,   PHMADDH,  (NONE)},
+ {"PHMSUBH",T5,"011100SSSSSTTTTTddddd10101001001",MMI2,   PHMADDH,  (SUBTRACT)},
+
+ {"PINTH",  T5,"011100SSSSSTTTTTddddd01010001001",MMI2,   PINTH,    (NONE)},
+ {"PINTOH", T5,"011100SSSSSTTTTTddddd01010101001",MMI3,   PINTOH,   (NONE)},
+
+ {"PLZCW",  T5,"011100SSSSS00000ddddd00000000100",MMINORM,PLZCW,    (NONE)},
+
+ {"PMADDH", T5,"011100SSSSSTTTTTddddd10000001001",MMI2,   PMULTH,   (ADDITION)},
+ {"PMADDUW",T5,"011100SSSSSTTTTTddddd00000101001",MMI3,   PMULTW,   (UNSIGNED)},
+ {"PMADDW", T5,"011100SSSSSTTTTTddddd00000001001",MMI2,   PMULTW,   (ADDITION)},
+
+ {"PMAXH",  T5,"011100SSSSSTTTTTddddd00111001000",MMI0,   PMAXMIN,  (GT | HALFWORD)},
+ {"PMAXW",  T5,"011100SSSSSTTTTTddddd00011001000",MMI0,   PMAXMIN,  (GT | WORD)},
+
+ {"PMFHI",  T5,"0111000000000000ddddd01000001001",MMI2,   PMXX,     (HI|FROM)},
+ {"PMFLO",  T5,"0111000000000000ddddd01001001001",MMI2,   PMXX,     (LO|FROM)},
+
+ {"PMFHL",  T5,"0111000000000000dddddaaaaa110000",MMINORM,PMFHL,    (NONE)},
+
+ {"PMINH",  T5,"011100SSSSSTTTTTddddd00111101000",MMI1,   PMAXMIN,  (LT | HALFWORD)},
+ {"PMINW",  T5,"011100SSSSSTTTTTddddd00011101000",MMI1,   PMAXMIN,  (LT | WORD)},
+
+ {"PMSUBH", T5,"011100SSSSSTTTTTddddd10100001001",MMI2,   PMULTH,   (SUBTRACT)},
+ {"PMSUBW", T5,"011100SSSSSTTTTTddddd00100001001",MMI2,   PMULTW,   (SUBTRACT)},
+
+ {"PMTHI",  T5,"011100SSSSS000000000001000101001",MMI3,   PMXX,     (HI|TO)},
+ {"PMTLO",  T5,"011100SSSSS000000000001001101001",MMI3,   PMXX,     (LO|TO)},
+
+{"PMTHL.LW",T5,"011100SSSSS000000000000000110001",MMINORM,PMTHL,    (NONE)},
+
+ {"PMULTH", T5,"011100SSSSSTTTTTddddd11100001001",MMI2,   PMULTH,   (NONE)},
+ {"PMULTUW",T5,"011100SSSSSTTTTTddddd01100101001",MMI3,   PMULTW,   (UNSIGNED)},
+ {"PMULTW", T5,"011100SSSSSTTTTTddddd01100001001",MMI2,   PMULTW,   (NONE)},
+
+ {"PNOR",   T5,"011100SSSSSTTTTTddddd10011101001",MMI3,   POP,      (POP_NOR)},
+ {"POR",    T5,"011100SSSSSTTTTTddddd10010101001",MMI3,   POP,      (POP_OR)},
+
+ {"PPAC5",  T5,"01110000000TTTTTddddd11111001000",MMI0,   PPAC5,    (NONE)},
+
+ {"PPACB",  T5,"011100SSSSSTTTTTddddd11011001000",MMI0,   PPACB,    (NONE)},
+ {"PPACH",  T5,"011100SSSSSTTTTTddddd10111001000",MMI0,   PPACH,    (NONE)},
+ {"PPACW",  T5,"011100SSSSSTTTTTddddd10011001000",MMI0,   PPACW,    (NONE)},
+
+ {"PREVH",  T5,"01110000000TTTTTddddd11011001001",MMI2,   PREVH,    (NONE)},
+ {"PROT3W", T5,"01110000000TTTTTddddd11111001001",MMI2,   PROT3W,   (NONE)},
+
+ {"PSLLH",  T5,"01110000000TTTTTdddddaaaaa110100",MMINORM,PSHIFT,   (LEFT | LOGICAL | HALFWORD)},
+ {"PSLLVW", T5,"011100SSSSSTTTTTddddd00010001001",MMI2,   PSLLVW,   (NONE)},
+ {"PSLLW",  T5,"01110000000TTTTTdddddaaaaa111100",MMINORM,PSHIFT,   (LEFT | LOGICAL | WORD)},
+
+ {"PSRAH",  T5,"01110000000TTTTTdddddaaaaa110111",MMINORM,PSHIFT,   (RIGHT | ARITHMETIC | HALFWORD)},
+ {"PSRAVW", T5,"011100SSSSSTTTTTddddd00011101001",MMI3,   PSRAVW,   (NONE)},
+ {"PSRAW",  T5,"01110000000TTTTTdddddaaaaa111111",MMINORM,PSHIFT,   (RIGHT | ARITHMETIC | WORD)},
+
+ {"PSRLH",  T5,"01110000000TTTTTdddddaaaaa110110",MMINORM,PSHIFT,   (RIGHT | LOGICAL | HALFWORD)},
+ {"PSRLVW", T5,"011100SSSSSTTTTTddddd00011001001",MMI2,   PSRLVW,   (NONE)},
+ {"PSRLW",  T5,"01110000000TTTTTdddddaaaaa111110",MMINORM,PSHIFT,   (RIGHT | LOGICAL | WORD)},
+
+ {"PSUBB",  T5,"011100SSSSSTTTTTddddd01001001000",MMI0,   PADD,     (SUBTRACT | BYTE)},
+ {"PSUBH",  T5,"011100SSSSSTTTTTddddd00101001000",MMI0,   PADD,     (SUBTRACT | HALFWORD)},
+ {"PSUBSB", T5,"011100SSSSSTTTTTddddd11001001000",MMI0,   PADD,     (SUBTRACT | SATURATE | BYTE )},
+ {"PSUBSH", T5,"011100SSSSSTTTTTddddd10101001000",MMI0,   PADD,     (SUBTRACT | SATURATE | HALFWORD)},
+ {"PSUBSW", T5,"011100SSSSSTTTTTddddd10001001000",MMI0,   PADD,     (SUBTRACT | SATURATE | WORD)},
+ {"PSUBUB", T5,"011100SSSSSTTTTTddddd11001101000",MMI1,   PADD,     (SUBTRACT | UNSIGNED | BYTE)},
+ {"PSUBUH", T5,"011100SSSSSTTTTTddddd10101101000",MMI1,   PADD,     (SUBTRACT | UNSIGNED | HALFWORD)},
+ {"PSUBUW", T5,"011100SSSSSTTTTTddddd10001101000",MMI1,   PADD,     (SUBTRACT | UNSIGNED | WORD)},
+ {"PSUBW",  T5,"011100SSSSSTTTTTddddd00001001000",MMI0,   PADD,     (SUBTRACT | WORD)},
+
+ {"PXOR",   T5,"011100SSSSSTTTTTddddd10011001001",MMI2,   POP,      (POP_XOR)},
+ /* end-sanitize-r5900 */
+
+ {"PREF",   G2,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, PREFETCH, (NONE)},
  {"PREFX",   4,"010011sssssgggggvvvvv00000001111",COP1X,  FPPREFX,  (FP)},
+
+ /* start-sanitize-r5900 */
+ {"QFSRV",  T5,"011100SSSSSTTTTTddddd11011101000",MMI1,   QFSRV,    (NONE)},
+ /* end-sanitize-r5900 */
+
  {"RECIP",   4,"01000110mmm00000vvvvvrrrrr010101",COP1,   FPRECIP,  (FP)},
  {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1,   FPROUND,  (FP | FIXED | DOUBLEWORD)},
  {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1,   FPROUND,  (FP | FIXED | WORD)},
@@ -510,7 +791,7 @@ struct instruction MIPS_DECODE[] = {
  {"SDC2",    2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL, STORE,    (DOUBLEWORD | COPROC)},
  {"SDL",     3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE,    (DOUBLEWORD | LEFT)},
  {"SDR",     3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE,    (DOUBLEWORD | RIGHT)},
- {"SDXC1",   4,"010011sssssgggggvvvvv00000001001",COP1X,  STORE,    (FP | DOUBLEWORD | COPROC | REG)},
+ {"SDXC1",  G3,"010011sssssgggggvvvvv00000001001",COP1X,  STORE,    (FP | DOUBLEWORD | COPROC | REG)},
  {"SH",      1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL, STORE,    (HALFWORD)},
  {"SLL",     1,"00000000000gggggdddddaaaaa000000",SPECIAL,SHIFT,    (WORD | LEFT | LOGICAL)}, /* rd = rt << sa */
  {"SLLV",    1,"000000ooooogggggddddd00000000100",SPECIAL,SHIFT,    (WORD | LEFT | LOGICAL)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
@@ -518,6 +799,9 @@ struct instruction MIPS_DECODE[] = {
  {"SLTI",    1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET,      (LT)},
  {"SLTU",    1,"000000sssssgggggddddd00000101011",SPECIAL,SET,      (LT | UNSIGNED)},
  {"SLTIU",   1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET,      (LT | UNSIGNED)},
+ /* start-sanitize-r5900 */
+ {"SQ",     T5,"011111sssssTTTTTeeeeeeeeeeeeeeee",NORMAL, STORE,    (QUADWORD)},
+ /* end-sanitize-r5900 */
  {"SQRT",    2,"01000110mmm00000vvvvvrrrrr000100",COP1,   FPSQRT,   (FP)},
  {"SRA",     1,"00000000000gggggdddddaaaaa000011",SPECIAL,SHIFT,    (WORD | WORD32 | RIGHT | ARITHMETIC)},
  {"SRAV",    1,"000000ooooogggggddddd00000000111",SPECIAL,SHIFT,    (WORD | WORD32 | RIGHT | ARITHMETIC)},
@@ -531,7 +815,7 @@ struct instruction MIPS_DECODE[] = {
  {"SWC2",    1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL, STORE,    (WORD | COPROC)},
  {"SWL",     1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE,    (WORD | LEFT)},
  {"SWR",     1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE,    (WORD | RIGHT)},
- {"SWXC1",   4,"010011sssssgggggvvvvv00000001000",COP1X,  STORE,    (FP | WORD | COPROC | REG)},
+ {"SWXC1",  G3,"010011sssssgggggvvvvv00000001000",COP1X,  STORE,    (FP | WORD | COPROC | REG)},
  {"SYNC",    2,"000000000000000000000aaaaa001111",SPECIAL,SYNC,     (NONE)}, /* z = 5bit stype field */
  {"SYSCALL", 1,"000000????????????????????001100",SPECIAL,SYSCALL,  (NOARG)},
  {"TEQ",     2,"000000sssssggggg??????????110100",SPECIAL,TRAP,     (EQ)},
@@ -650,15 +934,175 @@ static void build_instruction
 
 /*---------------------------------------------------------------------------*/
 
-/* We use the letter ordinal as the bit-position in our flags field: */
-#define fieldval(l)     (1 << ((l) - 'a'))
+static char* 
+name_for_data_len( insn )
+     struct instruction* insn;
+  {
+    if (GETDATASIZEINSN(insn) == BYTE)
+      return "BYTE";
+
+    else if (GETDATASIZEINSN(insn) == HALFWORD)
+      return "HALFWORD";
+
+    else if (GETDATASIZEINSN(insn) == WORD)
+      return "WORD";
+
+    else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+      return "DOUBLEWORD";
+
+    else if (GETDATASIZEINSN(insn) == QUADWORD)
+      return "QUADWORD";
+
+    else
+      return 0;
+  }
+
+static char* 
+letter_for_data_len( insn )
+     struct instruction* insn;
+  {
+    if (GETDATASIZEINSN(insn) == BYTE)
+      return "B";
+
+    else if (GETDATASIZEINSN(insn) == HALFWORD)
+      return "H";
+
+    else if (GETDATASIZEINSN(insn) == WORD)
+      return "W";
+
+    else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+      return "D";
+
+    else if (GETDATASIZEINSN(insn) == QUADWORD)
+      return "Q";
+
+    else
+      return 0;
+  }
+
+static char* 
+type_for_data_len( insn )
+     struct instruction* insn;
+  {
+    if (GETDATASIZEINSN(insn) == BYTE)
+      return "int";
+
+    else if (GETDATASIZEINSN(insn) == HALFWORD)
+      return "int";
+
+    else if (GETDATASIZEINSN(insn) == WORD)
+      return "long";
+
+    else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+      return "long long";
+
+    else if (GETDATASIZEINSN(insn) == QUADWORD)
+      return 0;
+
+    else
+      return 0;
+  }
 
-unsigned int
+static char* 
+max_for_data_len( insn )
+     struct instruction* insn;
+  {
+    if (GETDATASIZEINSN(insn) == BYTE)
+      return "127";
+
+    else if (GETDATASIZEINSN(insn) == HALFWORD)
+      return "32767";
+
+    else if (GETDATASIZEINSN(insn) == WORD)
+      return "(int)0x7FFFFFFF";
+
+    else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+      return 0;
+
+    else if (GETDATASIZEINSN(insn) == QUADWORD)
+      return 0;
+
+    else
+      return 0;
+  }
+
+static char* 
+min_for_data_len( insn )
+     struct instruction* insn;
+  {
+    if (GETDATASIZEINSN(insn) == BYTE)
+      return "-128";
+
+    else if (GETDATASIZEINSN(insn) == HALFWORD)
+      return "-32768";
+
+    else if (GETDATASIZEINSN(insn) == WORD)
+      return "(int)0x80000000";
+
+    else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+      return 0;
+
+    else if (GETDATASIZEINSN(insn) == QUADWORD)
+      return 0;
+
+    else
+      return 0;
+  }
+
+static char* 
+umax_for_data_len( insn )
+     struct instruction* insn;
+  {
+    if (GETDATASIZEINSN(insn) == BYTE)
+      return "0xFF";
+
+    else if (GETDATASIZEINSN(insn) == HALFWORD)
+      return "0xFFFF";
+
+    else if (GETDATASIZEINSN(insn) == WORD)
+      return "0xFFFFFFFF";
+
+    else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+      return 0;
+
+    else if (GETDATASIZEINSN(insn) == QUADWORD)
+      return 0;
+
+    else
+      return 0;
+  }
+
+static char* 
+bits_for_data_len( insn )
+     struct instruction* insn;
+  {
+    if (GETDATASIZEINSN(insn) == BYTE)
+      return "8";
+
+    else if (GETDATASIZEINSN(insn) == HALFWORD)
+      return "16";
+
+    else if (GETDATASIZEINSN(insn) == WORD)
+      return "32";
+
+    else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+      return "64";
+
+    else if (GETDATASIZEINSN(insn) == QUADWORD)
+      return "128";
+
+    else
+      return 0;
+  }
+
+/*---------------------------------------------------------------------------*/
+
+
+void
 convert_bitmap(bitmap,onemask,zeromask,dontmask)
      char *bitmap;
      unsigned int *onemask, *zeromask, *dontmask;
 {
-  unsigned int flags = 0x00000000;
   int loop; /* current bitmap position */
   int lastsp = -1; /* last bitmap field starting position */
   int lastoe = -1; /* last bitmap field encoding */
@@ -707,12 +1151,11 @@ convert_bitmap(bitmap,onemask,zeromask,dontmask)
          {
            if (opfields[oefield].fpos != -1) {
              /* If flag not set, then check starting position: */
-             if (!(flags & fieldval(bitmap[31 - loop]))) {
+             if (lastoe != oefield) {
                if (loop != opfields[oefield].fpos) {
                  fprintf(stderr,"Bitmap field '%c' (0x%02X) at wrong offset %d in bitmap \"%s\"\n",(((bitmap[31 - loop] < 0x20) || (bitmap[31 - loop] >= 0x7F)) ? '.' : bitmap[31 - loop]),bitmap[31 - loop],loop,bitmap);
                  exit(4);
                }
-               flags |= fieldval(bitmap[31 - loop]);
                lastsp = loop;
                lastoe = oefield;
              }
@@ -730,8 +1173,6 @@ convert_bitmap(bitmap,onemask,zeromask,dontmask)
  /* NOTE: Since we check for the position and size of fields when
     parsing the "bitmap" above, we do *NOT* need to check that invalid
     field combinations have been used. */
-
- return(flags);
 }
 
 /* Get the value of a 16 bit bitstring for a given shift count and
@@ -766,41 +1207,169 @@ bitmap_val (bitmap, shift, bits)
 /*---------------------------------------------------------------------------*/
 
 static void
-build_operands(flags)
-     unsigned int flags;
+build_operands(doisa,features,insn)
+     int doisa;
+     unsigned int features;
+     instruction* insn;
 {
-  int loop;
-  for (loop = 0; (loop < (sizeof(opfields) / sizeof(operand_encoding))); loop++)
-   if ((opfields[loop].fpos != -1) && (flags & fieldval(opfields[loop].id))) {
-     printf("  %s %s = ",opfields[loop].type,opfields[loop].name);
+  int proc64 = ((features & FEATURE_PROC32) ? 0 : -1);
+  int finish_jump_flag = 0;
+  int check_mult = 0;
+  int check_condition_code = 0;
+  int sfield_used = 0;
+  int gfield_used = 0;
+  int any_operand = 0;
 
-     if (opfields[loop].flags & OP_SIGNX)
-      printf("SIGNEXTEND((%s)",opfields[loop].type);
+  int current_field_id = -1;
+  int bitpos;
 
-     if (opfields[loop].flags & OP_GPR)
-      printf("GPR[");
+  for (bitpos=0; bitpos<32; bitpos++) {
+    if (insn->bitmap[31-bitpos] != current_field_id)
+      {
+        int opindex;
 
-     if (opfields[loop].flags & OP_SHIFT2)
-      printf("(");
+        current_field_id = insn->bitmap[31-bitpos];
 
-     printf("((instruction >> %d) & 0x%08X)",opfields[loop].fpos,((1 << opfields[loop].flen) - 1));
+        for (opindex = 0; (opindex < (sizeof(opfields) / sizeof(operand_encoding))); opindex++)
+          if ((opfields[opindex].fpos != -1) && (opfields[opindex].id == insn->bitmap[31-bitpos])) {
 
-     if (opfields[loop].flags & OP_SHIFT2)
-      printf(" << 2)");
+            any_operand = 1;
 
-     if (opfields[loop].flags & OP_GPR)
-      printf("]");
+            printf("  %s %s = ",opfields[opindex].type,opfields[opindex].name);
 
-     if (opfields[loop].flags & OP_BITS5)
-      printf("&0x1F");
+            if (opfields[opindex].flags & OP_SIGNX)
+              printf("SIGNEXTEND((%s)",opfields[opindex].type);
 
-     if (opfields[loop].flags & OP_SIGNX)
-      printf(",%d)",(opfields[loop].flen + ((opfields[loop].flags & OP_SHIFT2) ? 2 : 0)));
+            if (opfields[opindex].flags & OP_GPR)
+              printf("GPR[");
 
-     printf(";\n");
-   }
+            if (opfields[opindex].flags & OP_SHIFT2)
+              printf("(");
 
- return;
+            printf("((instruction >> %d) & 0x%08X)",opfields[opindex].fpos,((1 << opfields[opindex].flen) - 1));
+
+            if (opfields[opindex].flags & OP_SHIFT2)
+              printf(" << 2)");
+
+            if (opfields[opindex].flags & OP_GPR)
+              printf("]");
+
+            if (opfields[opindex].flags & OP_BITS5)
+              printf("&0x1F");
+
+            if (opfields[opindex].flags & OP_SIGNX)
+              printf(",%d)",(opfields[opindex].flen + ((opfields[opindex].flags & OP_SHIFT2) ? 2 : 0)));
+
+            printf(";\n");
+
+            if (opfields[opindex].flags & OP_GPR1)
+              {
+                printf("  %s %s1 = GPR1[",opfields[opindex].type,opfields[opindex].name);
+                printf("((instruction >> %d) & 0x%08X)",
+                       opfields[opindex].fpos,
+                       ((1 << opfields[opindex].flen) - 1));
+              printf("];\n");
+              }
+
+            if (opfields[opindex].id == 'j')
+              finish_jump_flag = 1;
+
+            if (opfields[opindex].id == 'e')
+              check_mult = 8;
+            
+            if (opfields[opindex].id == 'w')
+              check_mult = 4;
+
+            if (opfields[opindex].id == 'w')
+              check_mult = 2;
+
+            if (opfields[opindex].id == 'p')
+              check_condition_code = 1;
+
+            if (opfields[opindex].id == 's')
+              sfield_used = 1;
+
+            if (opfields[opindex].id == 'g')
+              gfield_used = 1;
+          }
+      }
+  }
+
+  if ( !any_operand && !(insn->flags & NOARG)) {
+    fprintf(stderr,"Bitmap error: Instruction with no operand fields \"%s\"\n",insn->name) ;
+    exit(5) ;
+  }
+
+  /* Finish constructing the jump address if required: */
+  if (finish_jump_flag)
+    printf("  op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
+
+  /* Now perform required operand checks: */
+
+  /* The following code has been removed, since it seems perfectly
+     reasonable to have a non-aligned offset that is added to another
+     non-aligned base to create an aligned address. Some more
+     information on exactly what the MIPS IV specification requires is
+     needed before deciding on the best strategy. Experimentation with a
+     VR4300 suggests that we do not need to raise the warning. */
+#if 0
+  /* For MIPS IV (and onwards), certain instruction operand values
+     will give undefined results. For the simulator we could
+     generate explicit exceptions (i.e. ReservedInstruction) to
+     make it easier to spot invalid use. However, for the moment we
+     just raise a warning. NOTE: This is a different check to the
+     later decoding, which checks for the final address being
+     valid. */
+     
+  if (check_mult != 0 && check_mult != 1) {
+    printf("  if (instruction & 0x%1X)\n", check_mult);
+    printf("  {\n");
+    /* NOTE: If we change this to a SignalException(), we must
+       ensure that the following opcode processing is not
+       executed. i.e. the code falls straight out to the simulator
+       control loop. */
+    printf("   sim_warning(\"Instruction has lo-order offset bits set in instruction\");\n");
+    printf("  }\n");
+  }
+#endif
+
+  /* The extended condition codes only appeared in ISA IV */
+  if (check_condition_code && (doisa < 4)) {
+    printf("  if (condition_code != 0)\n");
+    printf("  {\n");
+    printf("   SignalException(ReservedInstruction,instruction);\n");
+    printf("  }\n");
+    printf("  else\n");
+  }
+  
+  if ((insn->flags & WORD32) && (GETDATASIZEINSN(insn) != WORD)) {
+    fprintf(stderr,"Error in opcode table: WORD32 set for non-WORD opcode\n");
+    exit(1);
+  }
+  
+#if 1
+  /* The R4000 book differs slightly from the MIPS IV ISA
+     manual. An example is the sign-extension of a 64-bit processor
+     SUBU operation, and what is meant by an Undefined Result. This
+     is now provided purely as a warning. After examining a HW
+     implementation, this is now purely a warning... and the actual
+     operation is performed, with possibly undefined results. */
+  if (((insn->flags & WORD32) && proc64) && (features & FEATURE_WARN_RESULT)) {
+    /* The compiler should optimise out an OR with zero */
+    printf("  if (%s | %s)\n",(sfield_used ? "NOTWORDVALUE(op1)" : "0"),(gfield_used ? "NOTWORDVALUE(op2)" : "0"));
+    printf("   UndefinedResult();\n") ;
+  }
+#else
+  /* Check that the source is a 32bit value */
+  if ((insn->flags & WORD32) && proc64) {
+    /* The compiler should optimise out an OR with zero */
+    printf("  if (%s | %s)\n",(sfield_used ? "NOTWORDVALUE(op1)" : "0"),(gfield_used ? "NOTWORDVALUE(op2)" : "0"));
+    printf("   UndefinedResult();\n") ;
+    printf("  else\n") ;
+  }
+#endif
+
+  return;
 }
 
 /* The mips16 operand table.  */
@@ -1063,7 +1632,7 @@ build_mips16_operands (bitmap)
          printf ("        unsigned int bigend = (BigEndianCPU ? 3 : 0);\n");
          printf ("        unsigned int byte;\n");
          printf ("        paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 1)));\n");
-         printf ("        memval = LoadMemory (uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL);\n");
+         printf ("        LoadMemory (&memval,0,uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL);\n");
          printf ("        byte = (((PC &~ (uword64) 1) & 0x7) ^ (bigend << 1));\n");
          printf ("        memval = (memval >> (8 * byte)) & 0xffff;\n");
          printf ("        %s = (((%s & 0x1f) << 23)\n", op->name, op->name);
@@ -1201,10 +1770,17 @@ process_instructions(doarch,features)
     int limit;
     printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP,OP_MASK_OP);
     limit = (OP_MASK_OP + 1);
+
+    printf("#ifdef DEBUG\n");
+    printf("printf(\"DBG: instruction = 0x%%08X\\n\",instruction);\n");
+    printf("#endif\n");
+
     printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
     limit += (OP_MASK_SPEC + 1);
+
     printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_RT,OP_MASK_RT);
     limit += (OP_MASK_RT + 1);
+
     printf("else if (num == 0x11) {\n");
     printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM,OP_SH_COP1NORM,(OP_MASK_COP1NORM << OP_SH_COP1NORM));
     printf("  if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP,OP_SH_COP1CMP,(OP_MASK_COP1CMP << OP_SH_COP1CMP));
@@ -1212,6 +1788,7 @@ process_instructions(doarch,features)
     printf("  else\n");
     printf("   num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
     limit += (OP_MASK_SPEC + 1);
+
     printf(" else\n");
     /* To keep this code quick, we just clear out the "to" bit
        here. The proper (though slower) code would be to have another
@@ -1220,27 +1797,66 @@ process_instructions(doarch,features)
        move operation. */
     printf("  num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit,OP_SH_COP1SPEC,OP_MASK_COP1SPEC,OP_MASK_COP1SCLR);
     limit += (OP_MASK_COP1SPEC + 1);
+
     printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
     limit += (OP_MASK_SPEC + 1);
+
+    printf("else if (num == 0x1C) {\n");
+    printf("  int mmi_func = ((instruction >> %d) & 0x%08X);\n",OP_SH_MMI,OP_MASK_MMI);
+
+    printf("  if (mmi_func == 0x08) \n");
+    printf("    num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
+    limit += (OP_MASK_MMISUB + 1);
+
+    printf("  else if (mmi_func == 0x28) \n");
+    printf("    num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
+    limit += (OP_MASK_MMISUB + 1);
+
+    printf("  else if (mmi_func == 0x09) \n");
+    printf("    num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
+    limit += (OP_MASK_MMISUB + 1);
+
+    printf("  else if (mmi_func == 0x29) \n");
+    printf("    num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
+    limit += (OP_MASK_MMISUB + 1);
+
+    printf("  else \n");
+    printf("    num = (%d + mmi_func);\n",limit);
+    limit += (OP_MASK_MMI + 1);
+
+    printf("}\n");
+
     printf("/* Total possible switch entries: %d */\n",limit) ;
   }
+
+ printf("#ifdef DEBUG\n");
+ printf("printf(\"DBG: num = %%d\\n\",num);\n");
+ printf("#endif\n");
+
  printf("switch (num)\n") ;
  printf("{\n");
 
  for (loop = 0; (loop < limit); loop++) {
-   /* First check that the ISA number we are constructing for is
-      valid, before checking if the instruction matches any of the
+   /* First check if the insn is in a requested isa# independent set,
+      then check that the ISA number we are constructing for is
+      valid, then if the instruction matches any of the
       architecture specific flags. NOTE: We allow a selected ISA of
       zero to be used to match all standard instructions. */
-   if ((((MIPS_DECODE[loop].isa & MASK_ISA) <= doisa) && (((MIPS_DECODE[loop].isa & ~MASK_ISA) == 0) || ((MIPS_DECODE[loop].isa & ~MASK_ISA) & doarch) != 0)) && (!(MIPS_DECODE[loop].flags & FP) || ((MIPS_DECODE[loop].flags & FP) && dofp))) {
+   if (((MIPS_DECODE[loop].isa & doarch & MASK_ISA_INDEP)
+        || (((MIPS_DECODE[loop].isa & MASK_ISA) <= doisa) 
+            && (((MIPS_DECODE[loop].isa & ~MASK_ISA) == 0) 
+                || ((MIPS_DECODE[loop].isa & ~MASK_ISA) & doarch) != 0)))
+       && (!(MIPS_DECODE[loop].flags & FP) || ((MIPS_DECODE[loop].flags & FP) && dofp))) {
      unsigned int onemask;
      unsigned int zeromask;
      unsigned int dontmask;
      unsigned int mask;
      unsigned int number;
-     unsigned int flags = convert_bitmap(MIPS_DECODE[loop].bitmap,&onemask,&zeromask,&dontmask);
 
-     if (!(MIPS_DECODE[loop].flags & COPROC) && ((GETDATASIZE() == DOUBLEWORD) && !proc64)) {
+     convert_bitmap(MIPS_DECODE[loop].bitmap,&onemask,&zeromask,&dontmask);
+
+     if (!(MIPS_DECODE[loop].flags & COPROC) 
+         && ((GETDATASIZEINSN(&MIPS_DECODE[loop]) == DOUBLEWORD) && !proc64)) {
        fprintf(stderr,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE[loop].name);
        exit(4);
      }
@@ -1282,6 +1898,50 @@ process_instructions(doarch,features)
         number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ;
         break ;
 
+       case MMI0 :
+        mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
+                | (OP_MASK_MMISUB << OP_SH_MMISUB));
+        number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) 
+           + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
+           + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
+        break ;
+
+       case MMI1 :
+        mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
+                | (OP_MASK_MMISUB << OP_SH_MMISUB));
+        number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) 
+           + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
+           + (OP_MASK_MMISUB + 1)
+           + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
+        break ;
+
+       case MMI2 :
+        mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
+                | (OP_MASK_MMISUB << OP_SH_MMISUB));
+        number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) 
+           + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
+           + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1)
+           + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
+        break ;
+
+       case MMI3 :
+        mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
+                | (OP_MASK_MMISUB << OP_SH_MMISUB));
+        number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) 
+           + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
+           + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1)
+           + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
+        break ;
+
+       case MMINORM :
+        mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)) ;
+        number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) 
+           + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
+           + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1)
+           + (OP_MASK_MMISUB + 1) 
+           + ((onemask >> OP_SH_MMI) & OP_MASK_MMI)) ;
+        break ;
+
        default :
         fprintf(stderr,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE[loop].mark,loop,MIPS_DECODE[loop].name) ;
         exit(5) ;
@@ -1303,11 +1963,6 @@ process_instructions(doarch,features)
        printf(" else\n") ;
      }
 
-     if ((flags == 0) && !(MIPS_DECODE[loop].flags & NOARG)) {
-       fprintf(stderr,"Bitmap error: Instruction with no operand fields \"%s\"\n",MIPS_DECODE[loop].name) ;
-       exit(5) ;
-     }
-
      printf(" {\n") ;
 
      /* Get hold of the operands */
@@ -1321,75 +1976,7 @@ process_instructions(doarch,features)
       * particular operand here, since they are caught by the
       * compilation of the produced code.
       */
-     build_operands(flags);
-
-     /* Finish constructing the jump address if required: */
-     if (flags & fieldval('j'))
-      printf("  op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
-
-     /* Now perform required operand checks: */
-
-/* The following code has been removed, since it seems perfectly
-   reasonable to have a non-aligned offset that is added to another
-   non-aligned base to create an aligned address. Some more
-   information on exactly what the MIPS IV specification requires is
-   needed before deciding on the best strategy. Experimentation with a
-   VR4300 suggests that we do not need to raise the warning. */
-#if 0
-     /* For MIPS IV (and onwards), certain instruction operand values
-        will give undefined results. For the simulator we could
-        generate explicit exceptions (i.e. ReservedInstruction) to
-        make it easier to spot invalid use. However, for the moment we
-        just raise a warning. NOTE: This is a different check to the
-        later decoding, which checks for the final address being
-        valid. */
-     if ((flags & (fieldval('e') | fieldval('w') | fieldval('h'))) && (doisa >= 4)) {
-       printf("  if (instruction & 0x%1X)\n",((flags & fieldval('e')) ? 0x7 : ((flags & fieldval('w')) ? 0x3 : 0x1)));
-       printf("  {\n");
-       /* NOTE: If we change this to a SignalException(), we must
-          ensure that the following opcode processing is not
-          executed. i.e. the code falls straight out to the simulator
-          control loop. */
-       printf("   sim_warning(\"Instruction has lo-order offset bits set in instruction\");\n");
-       printf("  }\n");
-     }
-#endif
-
-     /* The extended condition codes only appeared in ISA IV */
-     if ((flags & fieldval('p')) && (doisa < 4)) {
-       printf("  if (condition_code != 0)\n");
-       printf("  {\n");
-       printf("   SignalException(ReservedInstruction,instruction);\n");
-       printf("  }\n");
-       printf("  else\n");
-     }
-
-     if ((MIPS_DECODE[loop].flags & WORD32) && (GETDATASIZE() != WORD)) {
-       fprintf(stderr,"Error in opcode table: WORD32 set for non-WORD opcode\n");
-       exit(1);
-     }
-
-#if 1
-     /* The R4000 book differs slightly from the MIPS IV ISA
-        manual. An example is the sign-extension of a 64-bit processor
-        SUBU operation, and what is meant by an Undefined Result. This
-        is now provided purely as a warning. After examining a HW
-        implementation, this is now purely a warning... and the actual
-        operation is performed, with possibly undefined results. */
-     if (((MIPS_DECODE[loop].flags & WORD32) && proc64) && (features & FEATURE_WARN_RESULT)) {
-       /* The compiler should optimise out an OR with zero */
-       printf("  if (%s | %s)\n",((flags & fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags & fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
-       printf("   UndefinedResult();\n") ;
-     }
-#else
-     /* Check that the source is a 32bit value */
-     if ((MIPS_DECODE[loop].flags & WORD32) && proc64) {
-       /* The compiler should optimise out an OR with zero */
-       printf("  if (%s | %s)\n",((flags & fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags & fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
-       printf("   UndefinedResult();\n") ;
-       printf("  else\n") ;
-     }
-#endif
+     build_operands(doisa, features, &MIPS_DECODE[loop]);
 
      printf("  {\n") ;
 
@@ -1588,6 +2175,9 @@ build_instruction (doisa, features, mips16, insn)
      break ;
 
     case MUL:
+     {
+     char* pipe = (insn->flags & PIPE1) ? "1" : "";
+
      if (features & FEATURE_WARN_LOHI) {
        printf("   CHECKHILO(\"Multiplication\");\n");
      }
@@ -1602,47 +2192,61 @@ build_instruction (doisa, features, mips16, insn)
           printf("   if (op1 < 0) { op1 = - op1; ++sign; }\n");
           printf("   if (op2 < 0) { op2 = - op2; ++sign; }\n");
         }
-       printf("   LO = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n");
-       printf("   HI = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n");
+       printf("   LO%s = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n",pipe);
+       printf("   HI%s = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n",pipe);
        printf("   mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n");
        printf("   midhi = SET64HI(WORD64LO(mid));\n");
-       printf("   temp = (LO + midhi);\n");
-       printf("   if ((temp == midhi) ? (LO != 0) : (temp < midhi))\n");
-       printf("    HI += 1;\n");
-       printf("   HI += WORD64HI(mid);\n");
+       printf("   temp = (LO%s + midhi);\n",pipe);
+       printf("   if ((temp == midhi) ? (LO%s != 0) : (temp < midhi))\n",pipe);
+       printf("     HI%s += 1;\n",pipe);
+       printf("   HI%s += WORD64HI(mid);\n",pipe);
        printf("   mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n");
        printf("   midhi = SET64HI(WORD64LO(mid));\n");
-       printf("   LO = (temp + midhi);\n");
-       printf("   if ((LO == midhi) ? (temp != 0) : (LO < midhi))\n");
-       printf("    HI += 1;\n");
-       printf("   HI += WORD64HI(mid);\n");
+       printf("   LO%s = (temp + midhi);\n",pipe);
+       printf("   if ((LO%s == midhi) ? (temp != 0) : (LO%s < midhi))\n",pipe,pipe);
+       printf("     HI%s += 1;\n",pipe);
+       printf("   HI%s += WORD64HI(mid);\n",pipe);
        if ((insn->flags & UNSIGNED) == 0)
-        printf("   if (sign & 1) { LO = - LO; HI = (LO == 0 ? 0 : -1) - HI; }\n");
+        printf("   if (sign & 1) { LO%s = - LO%s; HI%s = (LO%s == 0 ? 0 : -1) - HI%s; }\n",pipe,pipe,pipe,pipe,pipe);
      } else {
        if (insn->flags & UNSIGNED)
         printf("   uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n");
        else
         printf("   uword64 temp = ((word64) op1 * (word64) op2);\n");
-       printf("   LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype);
-       printf("   HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype);
+       printf("   LO%s = SIGNEXTEND((%s)WORD64LO(temp),32);\n",pipe,regtype);
+       printf("   HI%s = SIGNEXTEND((%s)WORD64HI(temp),32);\n",pipe,regtype);
      }
+     if (insn->flags & OP3)
+       {
+         printf("     if ( destreg != 0 )\n");
+         printf("         GPR[destreg] = LO%s;\n",pipe);
+       }
      printf("   }\n");
      break ;
-
+     }
     case DIV:
      {
       int boolU = (insn->flags & UNSIGNED);
+      int pipe1 = (insn->flags & PIPE1);
 
       if (features & FEATURE_WARN_LOHI) {
        printf("   CHECKHILO(\"Division\");\n");
       }
       printf("   {\n");
       if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
-       printf("   LO = ((%sword64)op1 / (%sword64)op2);\n",(boolU ? "u" : ""),(boolU ? "u" : ""));
-       printf("   HI = ((%sword64)op1 %c (%sword64)op2);\n",(boolU ? "u" : ""),'%',(boolU ? "u" : ""));
+       printf("   LO%s = ((%sword64)op1 / (%sword64)op2);\n",
+               (pipe1 ? "1" : ""),
+               (boolU ? "u" : ""),(boolU ? "u" : ""));
+       printf("   HI%s = ((%sword64)op1 %c (%sword64)op2);\n",
+               (pipe1 ? "1" : ""),
+               (boolU ? "u" : ""),'%',(boolU ? "u" : ""));
       } else {
-       printf("   LO = SIGNEXTEND(((%sint)op1 / (%sint)op2),32);\n",(boolU ? "unsigned " : ""),(boolU ? "unsigned " : ""));
-       printf("   HI = SIGNEXTEND(((%sint)op1 %c (%sint)op2),32);\n",(boolU ? "unsigned " : ""),'%',(boolU ? "unsigned " : ""));
+       printf("   LO%s = SIGNEXTEND(((%sint)op1 / (%sint)op2),32);\n",
+               (pipe1 ? "1" : ""),
+               (boolU ? "unsigned " : ""),(boolU ? "unsigned " : ""));
+       printf("   HI%s = SIGNEXTEND(((%sint)op1 %c (%sint)op2),32);\n",
+               (pipe1 ? "1" : ""),
+               (boolU ? "unsigned " : ""),'%',(boolU ? "unsigned " : ""));
       }
       printf("   }\n");
      }
@@ -1717,17 +2321,18 @@ build_instruction (doisa, features, mips16, insn)
     case MOVE:
      if (insn->flags & (HI | LO)) {
        char *regname = ((insn->flags & LO) ? "LO" : "HI");
+       int pipe1 = (insn->flags & PIPE1);
        if (insn->flags & LEFT)
-       printf("   GPR[destreg] = %s;\n",regname);
+       printf("   GPR[destreg] = %s%s;\n",regname,(pipe1 ? "1" : ""));
        else {
         if (features & FEATURE_WARN_LOHI) {
-          printf("   if (%sACCESS != 0)\n",regname);
+          printf("   if (%s%sACCESS != 0)\n",regname,(pipe1 ? "1" : ""));
           printf("     sim_warning(\"MT (move-to) over-writing %s register value\");\n",regname);
         }
-        printf("   %s = op1;\n",regname);
+        printf("   %s%s = op1;\n",regname,(pipe1 ? "1" : ""));
        }
        if (features & FEATURE_WARN_LOHI)
-       printf("   %sACCESS = 3; /* 3rd instruction will be safe */\n",regname);
+       printf("   %s%sACCESS = 3; /* 3rd instruction will be safe */\n",regname,(pipe1 ? "1" : ""));
      } else
       if (insn->flags & SHIFT16)
        printf("   GPR[destreg] = (op2 << 16);\n");
@@ -1971,6 +2576,11 @@ build_instruction (doisa, features, mips16, insn)
         datalen = 8;
         accesslength = "AccessLength_DOUBLEWORD";
         break ;
+
+       case QUADWORD :
+        datalen = 16;
+        accesslength = "AccessLength_QUADWORD";
+        break ;
       }
 
       if (insn->flags & REG)
@@ -1995,6 +2605,7 @@ build_instruction (doisa, features, mips16, insn)
       else {
        printf("    {\n");
        printf("     uword64 memval;\n");
+        printf("     uword64 memval1;\n");
 
        if ((insn->flags & COPROC) && ((datalen != 4) && (datalen != 8))) {
          fprintf(stderr,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn->name);
@@ -2022,14 +2633,18 @@ build_instruction (doisa, features, mips16, insn)
              printf("     int byte;\n");
              printf("     paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
              printf("     byte = ((vaddr & mask) ^ bigend);\n");
-             printf("     if (%sBigEndianCPU)\n",((insn->flags & LEFT) ? "!" : ""));
+             printf("     if (%s!ByteSwapMem)\n",((insn->flags & LEFT) ? "!" : ""));
              printf("      paddr &= ~mask;\n");
 
              if (isload) {
                if (insn->flags & LEFT)
-                printf("     memval = LoadMemory(uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
+                  {
+                    printf("     LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
+                  }
                else
-                printf("     memval = LoadMemory(uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen - 1));
+                  {
+                    printf("     LoadMemory(&memval,&memval1,uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen - 1));
+                  }
              }
 
              if (insn->flags & LEFT) {
@@ -2063,7 +2678,7 @@ build_instruction (doisa, features, mips16, insn)
                    printf("    }\n");
                  }
 #endif
-                 printf("     StoreMemory(uncached,byte,memval,paddr,vaddr,isREAL);\n");
+                 printf("     StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL);\n");
                }
              } else { /* RIGHT */
                if (isload) {
@@ -2093,7 +2708,7 @@ build_instruction (doisa, features, mips16, insn)
                } else { /* store */
                  printf("     memval = ((uword64) op2 << (byte * 8));\n");
                  build_endian_shift(proc64,datalen,2,s_left,32);
-                 printf("     StoreMemory(uncached,(%s - byte),memval,paddr,vaddr,isREAL);\n",accesslength);
+                 printf("     StoreMemory(uncached,(%s - byte),memval,memval1,paddr,vaddr,isREAL);\n",accesslength);
                }
              }
            }
@@ -2126,14 +2741,14 @@ build_instruction (doisa, features, mips16, insn)
            printf("     unsigned int byte;\n");
 
 /* TODO: This should really also check for 32bit world performing 32bit access */
-           if (datalen != 8) /* not for DOUBLEWORD */
+           if (datalen < 8) /* not for DOUBLEWORD or QUADWORD*/
             printf("     paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
 
-           printf("     memval = LoadMemory(uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength);
-
+           printf("     LoadMemory(&memval,&memval1,uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength);
+              
            /* The following will only make sense if the
               "LoadMemory" above returns a DOUBLEWORD entity */
-           if (datalen != 8) { /* not for DOUBLEWORD */
+           if (datalen < 8) { /* not for DOUBLEWORD or QUADWORD*/
              int valmask;
              switch (datalen) {
               case 1:
@@ -2182,7 +2797,11 @@ build_instruction (doisa, features, mips16, insn)
                       ? "1"
                       : "((instruction >> 26) & 0x3)"));
              else
-              printf("     GPR[destreg] = memval;\n");
+                {
+                  printf("     GPR[destreg] = memval;\n");
+                  if (datalen > 8)
+                    printf("     GPR1[destreg] = memval1;\n");
+                }
            }
          } else { /* store operation */
            if ((datalen == 1) || (datalen == 2)) {
@@ -2218,7 +2837,7 @@ build_instruction (doisa, features, mips16, insn)
                       ((insn->flags & FP) ? "fs" : "destreg"));
               else
                printf("     memval = ((uword64) op2 << (8 * byte));\n");
-            } else { /* SD and SCD */
+            } else if (datalen <= 8) { /* SD and SCD */
               if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) {
                 fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name);
                 exit(4);
@@ -2231,13 +2850,20 @@ build_instruction (doisa, features, mips16, insn)
                       ((insn->flags & FP) ? "fs" : "destreg"));
               else
                printf("     memval = op2;\n");
+            } else { /* wider than 8 */
+               if (insn->flags & COPROC) {
+                fprintf(stderr,"COPROC not available for 128 bit operations \"%s\"\n",insn->name);
+                exit(4);
+               }
+               printf("     memval  = rt_reg;\n");
+               printf("     memval1 = rt_reg1;\n");
             }
 
            if (insn->flags & ATOMIC)
             printf("      if (LLBIT)\n");
 
            printf("      {\n");
-           printf("       StoreMemory(uncached,%s,memval,paddr,vaddr,isREAL);\n",accesslength);
+           printf("       StoreMemory(uncached,%s,memval,memval1,paddr,vaddr,isREAL);\n",accesslength);
            printf("      }\n");
          }
 
@@ -2638,6 +3264,703 @@ build_instruction (doisa, features, mips16, insn)
      printf("   }\n");
      break ;
 
+/* start-sanitize-r5900 */
+    case MADD:
+     {
+       char* pipeline = (insn->flags & PIPE1) ? "1" : "";
+       int notsigned = (insn->flags & UNSIGNED);
+       char* prodtype = notsigned ? "uword64" : "word64";
+
+       printf("%s prod = (%s)WORD64(WORD64LO(HI%s),WORD64LO(LO%s)) + ((%s)%s(op1%s) * (%s)%s(op2%s));\n",
+              prodtype, prodtype, pipeline, pipeline, 
+              prodtype, (notsigned ? "WORD64LO" : "SIGNEXTEND"), (notsigned ? "" : ",32"),
+              prodtype, (notsigned ? "WORD64LO" : "SIGNEXTEND"), (notsigned ? "" : ",32")
+              );
+       printf("GPR[destreg] = LO%s = SIGNEXTEND(prod,32);\n", pipeline );
+       printf("HI%s = SIGNEXTEND( WORD64HI(prod), 32);\n", pipeline );
+       break;
+     }
+
+    case MxSA:
+      {
+        if (insn->flags & TO)
+          printf("SA = op1;\n");
+        else
+          printf("GPR[destreg] = SA;\n");
+        break;
+      }
+
+    case MTSAB:
+     printf("SA = ((op1 & 0xF) ^ (op2 & 0xF)) * 8;\n");
+     break;
+
+    case MTSAH:
+     printf("SA = ((op1 & 0x7) ^ (op2 & 0x7)) * 16;\n");
+     break;
+
+    case QFSRV:
+     printf("int bytes = (SA / 8) %% 16;\n");   /* mod 16 to avoid garbage */
+     printf("if (SA %% 8)\n");
+     printf("   SignalException(ReservedInstruction,instruction);\n");
+     printf("else\n");
+     printf("    {\n");
+     printf("    int i;\n");
+     printf("    for(i=0;i<(16-bytes);i++)\n");
+     printf("        GPR_SB(destreg,i) = RT_SB(bytes+i);\n");
+     printf("    for(;i<16;i++)\n");
+     printf("        GPR_SB(destreg,i) = RS_SB(i-(16-bytes));\n");
+     printf("    }\n");
+     break;
+
+    case PADD:
+     {
+       char* op = (insn->flags & SUBTRACT) ? "-" : "+";
+       char* name = name_for_data_len( insn );
+       char* letter = letter_for_data_len( insn );
+
+       char* tmptype;
+       char* maximum;
+       char* minimum;
+       char* signedness;
+
+       if ( insn->flags & UNSIGNED )
+         {
+           tmptype = type_for_data_len( insn );
+           signedness = "unsigned";
+           maximum = umax_for_data_len( insn );
+           minimum = 0;
+         }
+       else if ( insn->flags & SATURATE )
+         {
+           tmptype = type_for_data_len( insn );
+           signedness = "";
+           maximum = 0;
+           minimum = 0;
+         }
+       else
+         {
+           tmptype = type_for_data_len( insn );
+           signedness = "";
+           maximum = max_for_data_len( insn );
+           minimum = min_for_data_len( insn );
+         }
+
+       printf("int i;\n");
+       printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
+       printf("     {\n");
+       printf("     %s %s r = RS_S%s(i) %s RT_S%s(i);\n", signedness, tmptype, letter, op, letter );
+       if ( maximum )
+         {
+           printf("     if (r > %s)      GPR_S%s(destreg,i) = %s;\n", maximum, letter, maximum );
+           if ( minimum )
+             printf("     else if (r < %s) GPR_S%s(destreg,i) = %s;\n", minimum, letter, minimum );
+           printf("     else             ");
+         }
+       printf("GPR_S%s(destreg,i) = r;\n", letter );
+       printf("     }\n");
+       break;
+     }
+
+    case PMULTH:
+     {
+       char* op;
+       if ( insn->flags & SUBTRACT )
+         op = "-";
+       else if ( insn->flags & ADDITION )
+         op = "+";
+       else
+         op = "";
+
+       printf("GPR_SW(destreg,0) = LO_SW(0) %s= (RS_SH(0) * RT_SH(0));\n", op);
+       printf("                    LO_SW(1) %s= (RS_SH(1) * RT_SH(1));\n", op);
+       printf("GPR_SW(destreg,1) = HI_SW(0) %s= (RS_SH(2) * RT_SH(2));\n", op);
+       printf("                    HI_SW(1) %s= (RS_SH(3) * RT_SH(3));\n", op);
+       printf("GPR_SW(destreg,2) = LO_SW(2) %s= (RS_SH(4) * RT_SH(4));\n", op);
+       printf("                    LO_SW(3) %s= (RS_SH(5) * RT_SH(5));\n", op);
+       printf("GPR_SW(destreg,3) = HI_SW(2) %s= (RS_SH(6) * RT_SH(6));\n", op);
+       printf("                    HI_SW(3) %s= (RS_SH(7) * RT_SH(7));\n", op);
+       break;
+     }
+
+    case PMULTW:
+     {
+       char* op;
+       char* sign  = (insn->flags & UNSIGNED) ? "U" : "S";
+       char* prodtype = (insn->flags & UNSIGNED) ? "uword64" : "word64";
+       char* constructor = (insn->flags & UNSIGNED) ? "UWORD64" : "WORD64";
+
+       printf("%s prod0;\n", prodtype );
+       printf("%s prod1;\n", prodtype );
+
+       if ( insn->flags & SUBTRACT )
+         {
+           op = "-";
+           printf("prod0 = %s( HI_SW(0), LO_SW(0) );\n", constructor );
+           printf("prod1 = %s( HI_SW(2), LO_SW(2) );\n", constructor );
+         }
+       else if ( insn->flags & ADDITION )
+         {
+           op = "+";
+           printf("prod0 = %s( HI_SW(0), LO_SW(0) );\n", constructor );
+           printf("prod1 = %s( HI_SW(2), LO_SW(2) );\n", constructor );
+         }
+       else
+         op = "";
+
+       printf("prod0 %s= (%s)RS_SW(0) * (%s)RT_SW(0);\n", op, prodtype, prodtype );
+       printf("prod1 %s= (%s)RS_SW(2) * (%s)RT_SW(2);\n", op, prodtype, prodtype );
+
+       printf("GPR_%sD(destreg,0) = prod0;\n", sign );
+       printf("GPR_%sD(destreg,1) = prod1;\n", sign );
+
+       printf("LO  = SIGNEXTEND( prod0, 32 );\n");
+       printf("HI  = SIGNEXTEND( WORD64HI(prod0), 32 );\n");
+       printf("LO1 = SIGNEXTEND( prod1, 32 );\n");
+       printf("HI1 = SIGNEXTEND( WORD64HI(prod1), 32 );\n");
+       break;
+     }
+
+    case PDIVW:
+      {
+        char* sign = (insn->flags & UNSIGNED) ? "U" : "S";
+
+        printf("LO  = RS_%sW(0) / RT_%sW(0);\n", sign, sign );
+        printf("HI  = RS_%sW(0) %% RT_%sW(0);\n", sign, sign );
+        printf("LO1 = RS_%sW(2) / RT_%sW(2);\n", sign, sign );
+        printf("HI1 = RS_%sW(2) %% RT_%sW(2);\n", sign, sign );
+        break;
+      }
+
+    case PDIVBW:
+      printf("int devisor = RT_SH(0);\n");
+      printf("LO_SW(0) = RS_SW(0) / devisor;\n");
+      printf("HI_SW(0) = SIGNEXTEND( (RS_SW(0) %% devisor), 16 );\n");
+      printf("LO_SW(1) = RS_SW(1) / devisor;\n");
+      printf("HI_SW(1) = SIGNEXTEND( (RS_SW(1) %% devisor), 16 );\n");
+      printf("LO_SW(2) = RS_SW(2) / devisor;\n");
+      printf("HI_SW(2) = SIGNEXTEND( (RS_SW(2) %% devisor), 16 );\n");
+      printf("LO_SW(3) = RS_SW(3) / devisor;\n");
+      printf("HI_SW(3) = SIGNEXTEND( (RS_SW(3) %% devisor), 16 );\n");
+      break;
+
+    case PADSBH:
+     printf("int i;\n");
+     printf("for(i=0;i<HALFWORDS_IN_MMI_REGS/2;i++)\n");
+     printf("  GPR_SH(destreg,i) = RS_SH(i) - RT_SH(i);\n");
+     printf("for(;i<HALFWORDS_IN_MMI_REGS;i++)\n");
+     printf("  GPR_SH(destreg,i) = RS_SH(i) + RT_SH(i);\n");
+     break;
+
+    case PHMADDH:
+     {
+       char* op = (insn->flags & SUBTRACT) ? "-" : "+";
+       printf("GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) %s (RS_SH(0) * RT_SH(0));\n", op );
+       printf("GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) %s (RS_SH(2) * RT_SH(2));\n", op );
+       printf("GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) %s (RS_SH(4) * RT_SH(4));\n", op );
+       printf("GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) %s (RS_SH(6) * RT_SH(6));\n", op );
+     }
+     break;
+
+    case PSHIFT:
+     {
+       char* name = name_for_data_len( insn );
+       char* letter = letter_for_data_len( insn );
+       char* bits = bits_for_data_len( insn );
+       char* shift = (insn->flags & RIGHT) ? ">>" : "<<";
+       char* sign = (insn->flags & ARITHMETIC) ? "S" : "U";
+
+       printf("int shift_by = op1 & (%s-1);\n", bits );
+       printf("int i;\n");
+       printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
+       printf("    GPR_%s%s(destreg,i) = ", sign, letter );
+       if ( insn->flags & ARITHMETIC )
+         printf("SIGNEXTEND( ");
+       printf("(RT_%s%s(i) %s shift_by)", sign, letter, shift );
+       if ( insn->flags & ARITHMETIC )
+         printf(", (%s-shift_by) )", bits );
+       printf(";\n");
+       break;
+     }
+
+    case PSLLVW:
+     printf("GPR_UD(destreg,0) = RT_UW(0) << (RS_UB(0) & 0x1F);\n");
+     printf("GPR_UD(destreg,1) = RT_UW(2) << (RS_UB(8) & 0x1F);\n");
+     break;
+
+    case PSRLVW:
+     printf("GPR_UD(destreg,0) = RT_UW(0) >> (RS_UB(0) & 0x1F);\n");
+     printf("GPR_UD(destreg,1) = RT_UW(2) >> (RS_UB(8) & 0x1F);\n");
+     break;
+
+    case PSRAVW:
+     printf("GPR_SD(destreg,0) = SIGNEXTEND( (RT_SW (0) >> (RS_UB(0) & 0x1F)), 32-(RS_UB(0) & 0x1F) );\n");
+     printf("GPR_SD(destreg,1) = SIGNEXTEND( (RT_SW (2) >> (RS_UB(8) & 0x1F)), 32-(RS_UB(8) & 0x1F) );\n");
+     break;
+
+    case POP:
+     {
+       char* op1;
+       char* op2;
+       
+       if ( GET_OP_FROM_INSN(insn) == POP_AND )
+         {
+           op1 = "&";
+           op2 = "";
+         }
+       else if ( GET_OP_FROM_INSN(insn) == POP_OR )
+         {
+           op1 = "|";
+           op2 = "";
+         }
+       else if ( GET_OP_FROM_INSN(insn) == POP_NOR )
+         {
+           op1 = "|";
+           op2 = "~";
+         }
+       else if ( GET_OP_FROM_INSN(insn) == POP_XOR )
+         {
+           op1 = "^";
+           op2 = "";
+         }
+       
+       printf("int i;\n");
+       printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
+       printf("  GPR_UW(destreg,i) = %s(RS_UW(i) %s RT_UW(i));\n", op2, op1 );
+       break;
+     }
+
+    case PCMP:
+     {
+       char* name = name_for_data_len( insn );
+       char* letter = letter_for_data_len( insn );
+       char* maximum = umax_for_data_len( insn );
+       char* op = (insn->flags & GT) ? ">" : "==";
+
+       printf("int i;\n");
+       printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
+       printf("     {\n");
+       printf("     if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = %s;\n", 
+              letter, op, letter, letter, maximum );
+       printf("     else                        GPR_S%s(destreg,i) = 0;\n", letter );
+       printf("     }\n");
+       break;
+     }
+
+    case PMAXMIN:
+     {
+       char* name = name_for_data_len( insn );
+       char* letter = letter_for_data_len( insn );
+       char* op = (insn->flags & GT) ? ">" : "<";
+
+       printf("int i;\n");
+       printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
+       printf("     {\n");
+       printf("     if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = RS_S%s(i);\n", 
+              letter, op, letter, letter, letter );
+       printf("     else                        GPR_S%s(destreg,i) = RT_S%s(i);\n", letter, letter );
+       printf("     }\n");
+       break;
+     }
+
+    case PABS:
+     {
+       char* name = name_for_data_len( insn );
+       char* letter = letter_for_data_len( insn );
+
+       printf("int i;\n");
+       printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
+       printf("  {\n");
+       printf("  if (RT_S%s(i) < 0)\n", letter );
+       printf("    GPR_S%s(destreg,i) = -RT_S%s(i);\n", letter, letter );
+       printf("  else\n");
+       printf("    GPR_S%s(destreg,i) =  RT_S%s(i);\n", letter, letter );
+       printf("  }\n");
+       break;
+     }
+
+    case PCPYH:
+     printf("GPR_UH(destreg,7) = GPR_UH(destreg,6) = GPR_UH(destreg,5) = GPR_UH(destreg,4) = RT_UH(4);\n");
+     printf("GPR_UH(destreg,3) = GPR_UH(destreg,2) = GPR_UH(destreg,1) = GPR_UH(destreg,0) = RT_UH(0);\n");
+     break;
+
+    case PCPYLD:
+     printf("GPR_UD(destreg,0) = RT_UD(0);\n");
+     printf("GPR_UD(destreg,1) = RS_UD(0);\n");
+     break;
+
+    case PCPYUD:
+     printf("GPR_UD(destreg,0) = RS_UD(1);\n");
+     printf("GPR_UD(destreg,1) = RT_UD(1);\n");
+     break;
+
+    case PEXCH:
+     printf("GPR_UH(destreg,0) = RT_UH(0);\n");
+     printf("GPR_UH(destreg,1) = RT_UH(2);\n");
+     printf("GPR_UH(destreg,2) = RT_UH(1);\n");
+     printf("GPR_UH(destreg,3) = RT_UH(3);\n");
+     printf("GPR_UH(destreg,4) = RT_UH(4);\n");
+     printf("GPR_UH(destreg,5) = RT_UH(6);\n");
+     printf("GPR_UH(destreg,6) = RT_UH(5);\n");
+     printf("GPR_UH(destreg,7) = RT_UH(7);\n");
+     break;
+
+    case PEXCW:
+     printf("GPR_UW(destreg,0) = RT_UW(0);\n");
+     printf("GPR_UW(destreg,1) = RT_UW(2);\n");
+     printf("GPR_UW(destreg,2) = RT_UW(1);\n");
+     printf("GPR_UW(destreg,3) = RT_UW(3);\n");
+     break;
+
+    case PEXOH:
+     printf("GPR_UH(destreg,0) = RT_UH(2);\n");
+     printf("GPR_UH(destreg,1) = RT_UH(1);\n");
+     printf("GPR_UH(destreg,2) = RT_UH(0);\n");
+     printf("GPR_UH(destreg,3) = RT_UH(3);\n");
+     printf("GPR_UH(destreg,4) = RT_UH(6);\n");
+     printf("GPR_UH(destreg,5) = RT_UH(5);\n");
+     printf("GPR_UH(destreg,6) = RT_UH(4);\n");
+     printf("GPR_UH(destreg,7) = RT_UH(7);\n");
+     break;
+
+    case PEXOW:
+     printf("GPR_UW(destreg,0) = RT_UW(2);\n");
+     printf("GPR_UW(destreg,1) = RT_UW(1);\n");
+     printf("GPR_UW(destreg,2) = RT_UW(0);\n");
+     printf("GPR_UW(destreg,3) = RT_UW(3);\n");
+     break;
+
+    case PEXTLB:
+     printf("GPR_UB(destreg,0)  = RT_UB(0);\n");
+     printf("GPR_UB(destreg,1)  = RS_UB(0);\n");
+     printf("GPR_UB(destreg,2)  = RT_UB(1);\n");
+     printf("GPR_UB(destreg,3)  = RS_UB(1);\n");
+     printf("GPR_UB(destreg,4)  = RT_UB(2);\n");
+     printf("GPR_UB(destreg,5)  = RS_UB(2);\n");
+     printf("GPR_UB(destreg,6)  = RT_UB(3);\n");
+     printf("GPR_UB(destreg,7)  = RS_UB(3);\n");
+     printf("GPR_UB(destreg,8)  = RT_UB(4);\n");
+     printf("GPR_UB(destreg,9)  = RS_UB(4);\n");
+     printf("GPR_UB(destreg,10) = RT_UB(5);\n");
+     printf("GPR_UB(destreg,11) = RS_UB(5);\n");
+     printf("GPR_UB(destreg,12) = RT_UB(6);\n");
+     printf("GPR_UB(destreg,13) = RS_UB(6);\n");
+     printf("GPR_UB(destreg,14) = RT_UB(7);\n");
+     printf("GPR_UB(destreg,15) = RS_UB(7);\n");
+     break;
+
+    case PEXTLH:
+     printf("GPR_UH(destreg,0)  = RT_UH(0);\n");
+     printf("GPR_UH(destreg,1)  = RS_UH(0);\n");
+     printf("GPR_UH(destreg,2)  = RT_UH(1);\n");
+     printf("GPR_UH(destreg,3)  = RS_UH(1);\n");
+     printf("GPR_UH(destreg,4)  = RT_UH(2);\n");
+     printf("GPR_UH(destreg,5)  = RS_UH(2);\n");
+     printf("GPR_UH(destreg,6)  = RT_UH(3);\n");
+     printf("GPR_UH(destreg,7)  = RS_UH(3);\n");
+     break;
+
+    case PEXTLW:
+     printf("GPR_UW(destreg,0)  = RT_UW(0);\n");
+     printf("GPR_UW(destreg,1)  = RS_UW(0);\n");
+     printf("GPR_UW(destreg,2)  = RT_UW(1);\n");
+     printf("GPR_UW(destreg,3)  = RS_UW(1);\n");
+     break;
+
+    case PEXTUB:
+     printf("GPR_UB(destreg,0)  = RT_UB(8);\n");
+     printf("GPR_UB(destreg,1)  = RS_UB(8);\n");
+     printf("GPR_UB(destreg,2)  = RT_UB(9);\n");
+     printf("GPR_UB(destreg,3)  = RS_UB(9);\n");
+     printf("GPR_UB(destreg,4)  = RT_UB(10);\n");
+     printf("GPR_UB(destreg,5)  = RS_UB(10);\n");
+     printf("GPR_UB(destreg,6)  = RT_UB(11);\n");
+     printf("GPR_UB(destreg,7)  = RS_UB(11);\n");
+     printf("GPR_UB(destreg,8)  = RT_UB(12);\n");
+     printf("GPR_UB(destreg,9)  = RS_UB(12);\n");
+     printf("GPR_UB(destreg,10) = RT_UB(13);\n");
+     printf("GPR_UB(destreg,11) = RS_UB(13);\n");
+     printf("GPR_UB(destreg,12) = RT_UB(14);\n");
+     printf("GPR_UB(destreg,13) = RS_UB(14);\n");
+     printf("GPR_UB(destreg,14) = RT_UB(15);\n");
+     printf("GPR_UB(destreg,15) = RS_UB(15);\n");
+     break;
+
+    case PEXTUH:
+     printf("GPR_UH(destreg,0)  = RT_UH(4);\n");
+     printf("GPR_UH(destreg,1)  = RS_UH(4);\n");
+     printf("GPR_UH(destreg,2)  = RT_UH(5);\n");
+     printf("GPR_UH(destreg,3)  = RS_UH(5);\n");
+     printf("GPR_UH(destreg,4)  = RT_UH(6);\n");
+     printf("GPR_UH(destreg,5)  = RS_UH(6);\n");
+     printf("GPR_UH(destreg,6)  = RT_UH(7);\n");
+     printf("GPR_UH(destreg,7)  = RS_UH(7);\n");
+     break;
+
+    case PEXTUW:
+     printf("GPR_UW(destreg,0)  = RT_UW(2);\n");
+     printf("GPR_UW(destreg,1)  = RS_UW(2);\n");
+     printf("GPR_UW(destreg,2)  = RT_UW(3);\n");
+     printf("GPR_UW(destreg,3)  = RS_UW(3);\n");
+     break;
+
+    case PPACB:
+     printf("GPR_UB(destreg,0)  = RT_UB(0);\n");
+     printf("GPR_UB(destreg,1)  = RT_UB(2);\n");
+     printf("GPR_UB(destreg,2)  = RT_UB(4);\n");
+     printf("GPR_UB(destreg,3)  = RT_UB(6);\n");
+     printf("GPR_UB(destreg,4)  = RT_UB(8);\n");
+     printf("GPR_UB(destreg,5)  = RT_UB(10);\n");
+     printf("GPR_UB(destreg,6)  = RT_UB(12);\n");
+     printf("GPR_UB(destreg,7)  = RT_UB(14);\n");
+     printf("GPR_UB(destreg,8)  = RS_UB(0);\n");
+     printf("GPR_UB(destreg,9)  = RS_UB(2);\n");
+     printf("GPR_UB(destreg,10) = RS_UB(4);\n");
+     printf("GPR_UB(destreg,11) = RS_UB(6);\n");
+     printf("GPR_UB(destreg,12) = RS_UB(8);\n");
+     printf("GPR_UB(destreg,13) = RS_UB(10);\n");
+     printf("GPR_UB(destreg,14) = RS_UB(12);\n");
+     printf("GPR_UB(destreg,15) = RS_UB(14);\n");
+     break;
+
+    case PPACH:
+     printf("GPR_UH(destreg,0)  = RT_UH(0);\n");
+     printf("GPR_UH(destreg,1)  = RT_UH(2);\n");
+     printf("GPR_UH(destreg,2)  = RT_UH(4);\n");
+     printf("GPR_UH(destreg,3)  = RT_UH(6);\n");
+     printf("GPR_UH(destreg,4)  = RS_UH(0);\n");
+     printf("GPR_UH(destreg,5)  = RS_UH(2);\n");
+     printf("GPR_UH(destreg,6)  = RS_UH(4);\n");
+     printf("GPR_UH(destreg,7)  = RS_UH(6);\n");
+     break;
+
+    case PPACW:
+     printf("GPR_UW(destreg,0)  = RT_UW(0);\n");
+     printf("GPR_UW(destreg,1)  = RT_UW(2);\n");
+     printf("GPR_UW(destreg,2)  = RS_UW(0);\n");
+     printf("GPR_UW(destreg,3)  = RS_UW(2);\n");
+     break;
+
+    case PREVH:
+     printf("GPR_UH(destreg,0)  = RT_UH(3);\n");
+     printf("GPR_UH(destreg,1)  = RT_UH(2);\n");
+     printf("GPR_UH(destreg,2)  = RT_UH(1);\n");
+     printf("GPR_UH(destreg,3)  = RT_UH(0);\n");
+     printf("GPR_UH(destreg,4)  = RT_UH(7);\n");
+     printf("GPR_UH(destreg,5)  = RT_UH(6);\n");
+     printf("GPR_UH(destreg,6)  = RT_UH(5);\n");
+     printf("GPR_UH(destreg,7)  = RT_UH(4);\n");
+     break;
+
+    case PROT3W:
+     printf("GPR_UW(destreg,0)  = RT_UW(0);\n");
+     printf("GPR_UW(destreg,1)  = RT_UW(3);\n");
+     printf("GPR_UW(destreg,2)  = RT_UW(1);\n");
+     printf("GPR_UW(destreg,3)  = RT_UW(2);\n");
+     break;
+
+    case PINTH:
+     printf("GPR_UH(destreg,0)  = RT_UH(0);\n");
+     printf("GPR_UH(destreg,1)  = RS_UH(4);\n");
+     printf("GPR_UH(destreg,2)  = RT_UH(1);\n");
+     printf("GPR_UH(destreg,3)  = RS_UH(5);\n");
+     printf("GPR_UH(destreg,4)  = RT_UH(2);\n");
+     printf("GPR_UH(destreg,5)  = RS_UH(6);\n");
+     printf("GPR_UH(destreg,6)  = RT_UH(3);\n");
+     printf("GPR_UH(destreg,7)  = RS_UH(7);\n");
+     break;
+
+    case PINTOH:
+     printf("GPR_UH(destreg,0) = RT_UH(0);\n");
+     printf("GPR_UH(destreg,1) = RS_UH(0);\n");
+     printf("GPR_UH(destreg,2) = RT_UH(2);\n");
+     printf("GPR_UH(destreg,3) = RS_UH(2);\n");
+     printf("GPR_UH(destreg,4) = RT_UH(4);\n");
+     printf("GPR_UH(destreg,5) = RS_UH(4);\n");
+     printf("GPR_UH(destreg,6) = RT_UH(6);\n");
+     printf("GPR_UH(destreg,7) = RS_UH(6);\n");
+     break;
+
+    case PMXX:  /* Parallel move HI or LO / TO or FROM */
+     {
+       if ( (insn->flags & (HI|FROM)) == (HI|FROM) )
+         {
+           printf("GPR_SD(destreg,0) = HI;\n");
+           printf("GPR_SD(destreg,1) = HI1;\n");
+         }
+       else if ( (insn->flags & (LO|FROM)) == (LO|FROM) )
+         {
+           printf("GPR_SD(destreg,0) = LO;\n");
+           printf("GPR_SD(destreg,1) = LO1;\n");
+         }
+       else if ( (insn->flags & (HI|TO)) == (HI|TO) )
+         {
+           printf("HI  = RS_SD(0);\n");
+           printf("HI1 = RS_SD(1);\n");
+         }
+       else if ( (insn->flags & (LO|TO)) == (LO|TO) )
+         {
+           printf("LO  = RS_SD(0);\n");
+           printf("LO1 = RS_SD(1);\n");
+         }
+       break;
+     }
+
+    case PMTHL:
+     printf("LO_UW(0) = RS_UW(0);\n");
+     printf("HI_UW(0) = RS_UW(1);\n");
+     printf("LO_UW(2) = RS_UW(2);\n");
+     printf("HI_UW(2) = RS_UW(3);\n");
+     break;
+
+    case PMFHL:
+     printf("if (op1 == 0)\n");
+     printf("  {\n");
+     printf("  GPR_UW(destreg,0) = LO_UW(0);\n");
+     printf("  GPR_UW(destreg,1) = HI_UW(0);\n");
+     printf("  GPR_UW(destreg,2) = LO_UW(2);\n");
+     printf("  GPR_UW(destreg,3) = HI_UW(2);\n");
+     printf("  }\n");
+     printf("else if (op1 == 1)\n");
+     printf("  {\n");
+     printf("  GPR_UW(destreg,0) = LO_UW(1);\n");
+     printf("  GPR_UW(destreg,1) = HI_UW(1);\n");
+     printf("  GPR_UW(destreg,2) = LO_UW(3);\n");
+     printf("  GPR_UW(destreg,3) = HI_UW(3);\n");
+     printf("  }\n");
+     printf("else if (op1 == 2)\n");
+     printf("  {\n");
+     printf("  unsigned long long t = ((uword64)HI_UW(0) << 32) | (uword64)LO_UW(0);\n");
+     printf("  if ( t > 0x7FFFFFFF )\n");
+     printf("    GPR_SD(destreg,0) = 0x7FFFFFFF;\n");
+     printf("  else if ( t > (uword64)0xFFFFFFFF80000000LL )\n");
+     printf("    GPR_SD(destreg,0) = (uword64)0xFFFFFFFF80000000LL;\n");
+     printf("  else\n");
+     printf("    GPR_SD(destreg,0) = SIGNEXTEND(t,32);\n");
+     printf("  }\n");
+     printf("else if (op1 == 3)\n");
+     printf("  {\n");
+     printf("  GPR_UH(destreg,0) = LO_UH(0);\n");
+     printf("  GPR_UH(destreg,1) = LO_UH(2);\n");
+     printf("  GPR_UH(destreg,2) = HI_UH(0);\n");
+     printf("  GPR_UH(destreg,3) = HI_UH(2);\n");
+     printf("  GPR_UH(destreg,4) = LO_UH(4);\n");
+     printf("  GPR_UH(destreg,5) = LO_UH(6);\n");
+     printf("  GPR_UH(destreg,6) = HI_UH(4);\n");
+     printf("  GPR_UH(destreg,7) = HI_UH(6);\n");
+     printf("  }\n");
+     printf("else if (op1 == 4)\n");
+     printf("  {\n");
+     printf("  if (LO_UW(0) > 0x00007FFF)\n");
+     printf("    GPR_UH(destreg,0) = 0x7FFF;\n");
+     printf("  else if (LO_UW(0) >= 0xFFFF8000)\n");
+     printf("    GPR_UH(destreg,0) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,0) = LO_UH(0);\n");
+
+     printf("  if (LO_UW(1) > 0x00007FFF)\n");
+     printf("    GPR_UH(destreg,1) = 0x7FFF;\n");
+     printf("  else if (LO_UW(1) >= 0xFFFF8000)\n");
+     printf("    GPR_UH(destreg,1) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,1) = LO_UH(2);\n");
+
+     printf("  if (HI_UW(0) > 0x00007FFF)\n");
+     printf("    GPR_UH(destreg,0) = 0x7FFF;\n");
+     printf("  else if (HI_UW(0) >= 0xFFFF8000)\n");
+     printf("    GPR_UH(destreg,0) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,0) = HI_UH(0);\n");
+
+     printf("  if (HI_UW(1) > 0x00007FFF)\n");
+     printf("    GPR_UH(destreg,1) = 0x7FFF;\n");
+     printf("  else if (HI_UW(1) >= 0xFFFF8000)\n");
+     printf("    GPR_UH(destreg,1) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,1) = HI_UH(2);\n");
+
+     printf("  if (LO_UW(2) > 0x00007FFF)\n");
+     printf("    GPR_UH(destreg,4) = 0x7FFF;\n");
+     printf("  else if (LO_UW(2) >= 0xFFFF8000)\n");
+     printf("    GPR_UH(destreg,4) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,4) = LO_UH(4);\n");
+
+     printf("  if (LO_UW(3) > 0x00007FFF)\n");
+     printf("    GPR_UH(destreg,5) = 0x7FFF;\n");
+     printf("  else if (LO_UW(3) >= 0xFFFF8000)\n");
+     printf("    GPR_UH(destreg,5) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,5) = LO_UH(6);\n");
+
+     printf("  if (HI_UW(2) > 0x00007FFF)\n");
+     printf("    GPR_UH(destreg,6) = 0x7FFF;\n");
+     printf("  else if (HI_UW(2) >= 0xFFFF8000)\n");
+     printf("    GPR_UH(destreg,6) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,6) = HI_UH(4);\n");
+
+     printf("  if (HI_UW(3) > 0x00007FFF)\n");
+     printf("    GPR_UH(destreg,7) = 0x7FFF;\n");
+     printf("  else if (HI_UW(3) >= 0xFFFF8000)\n");
+     printf("    GPR_UH(destreg,7) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,7) = HI_UH(6);\n");
+
+     printf("  }\n");
+     break;
+
+    case PLZCW:
+      printf("unsigned long value;\n");
+      printf("int test;\n");
+      printf("int count;\n");
+      printf("int i;\n");
+
+      printf("value = RS_UW(0);\n");
+      printf("count = 0;\n");
+      printf("test = !!(value & (1 << 31));\n");
+      printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
+      printf("  count++;\n");
+      printf("GPR_UW(destreg,0) = count;\n");
+
+      printf("value = RS_UW(1);\n");
+      printf("count = 0;\n");
+      printf("test = !!(value & (1 << 31));\n");
+      printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
+      printf("  count++;\n");
+      printf("GPR_UW(destreg,1) = count;\n");
+      break;
+
+    case PEXT5:
+      printf("int i;\n");
+      printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
+      printf("  {\n");
+      printf("  int x = RT_UW(i);\n");
+      printf("  GPR_UW(destreg,i) = ((x & (1  << 15)) << (24 - 15))  \n");
+      printf("                    | ((x & (31 << 10)) << (19 - 10))  \n");
+      printf("                    | ((x & (31 << 5))  << (11 - 5))   \n");
+      printf("                    | ((x & (31 << 0))  << (3  - 0));  \n");
+      printf("  }\n");
+      break;
+
+    case PPAC5:
+      printf("int i;\n");
+      printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
+      printf("  {\n");
+      printf("  int x = RT_UW(i);\n");
+      printf("  GPR_UW(destreg,i) = ((x & (1  << 24)) >> (24 - 15))  \n");
+      printf("                    | ((x & (31 << 19)) >> (19 - 10))  \n");
+      printf("                    | ((x & (31 << 11)) >> (11 - 5))   \n");
+      printf("                    | ((x & (31 <<  3)) >> (3  - 0));  \n");
+      printf("  }\n");
+      break;
+/* end-sanitize-r5900 */
+
+    case NYI:
+     fprintf(stderr,"Warning: Unimplemented opcode: %s\n",insn->name) ;
+
+     printf("SignalException(ReservedInstruction,instruction);\n");
+     break;
+
     default:
      fprintf(stderr,"Unrecognised opcode type %d\n",insn->type) ;
      exit(6) ;
@@ -2680,6 +4003,9 @@ struct architectures {
 
 static const struct architectures available_architectures[] = {
   {"4100",ARCH_VR4100}, /* NEC MIPS VR4100 */
+  /* start-sanitize-r5900 */
+  {"5900",ARCH_R5900},
+  /* end-sanitize-r5900 */
   {0,     0}            /* terminator */
 };
 
@@ -3041,3 +4367,10 @@ my_strtoul(nptr, endptr, base)
 /*---------------------------------------------------------------------------*/
 
 /*> EOF gencode.c <*/
+
+
+
+
+
+
+
index f921e62435886b90dcaa6f727fa6467284a85bfa..c1fb7435283eb15e372a02dd8fd3ba7bf2642c89 100644 (file)
@@ -46,6 +46,8 @@ typedef unsigned long long uword64;
 #define WORD64HI(t)     (unsigned int)(((uword64)(t))>>32)
 #define SET64LO(t)      (((uword64)(t))&0xFFFFFFFF)
 #define SET64HI(t)     (((uword64)(t))<<32)
+#define WORD64(h,l)     ((word64)((SET64HI(h)|SET64LO(l))))
+#define UWORD64(h,l)     (SET64HI(h)|SET64LO(l))
 
 /* Sign-extend the given value (e) as a value (b) bits long. We cannot
    assume the HI32bits of the operand are zero, so we must perform a
@@ -84,6 +86,7 @@ typedef struct uword64 {
 #define WORD64HI(t)     (unsigned int)(t.hi)
 #define SET64LO(t)      (..TODO..) /* need structure into which value will be placed */
 #define SET64HI(t)      (..TODO..) /* need structure into which value will be placed */
+#define WORD64(h,l)     (SET64HI(h)|SET64LO(l))
 
 /* TODO: Update these to manipulate the split structure values */
 #define SIGNEXTEND(e,b)         /* TODO */