mips: adding MIPS64LE support to Valgrind

Necessary changes to Valgrind to support MIPS64LE on Linux.
Minor cleanup/style changes embedded in the patch as well.
The change corresponds to r2687 in VEX.
Patch written by Dejan Jevtic and Petar Jovanovic.

More information about this issue:
https://bugs.kde.org/show_bug.cgi?id=313267


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13292 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index d557e14..d2ac70d 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -308,6 +308,7 @@
 	m_dispatch/dispatch-arm-linux.S \
 	m_dispatch/dispatch-s390x-linux.S \
 	m_dispatch/dispatch-mips32-linux.S \
+	m_dispatch/dispatch-mips64-linux.S \
 	m_dispatch/dispatch-x86-darwin.S \
 	m_dispatch/dispatch-amd64-darwin.S \
 	m_gdbserver/inferiors.c \
@@ -325,6 +326,7 @@
 	m_gdbserver/valgrind-low-ppc64.c \
 	m_gdbserver/valgrind-low-s390x.c \
 	m_gdbserver/valgrind-low-mips32.c \
+	m_gdbserver/valgrind-low-mips64.c \
 	m_gdbserver/version.c \
 	m_initimg/initimg-linux.c \
 	m_initimg/initimg-darwin.c \
@@ -345,6 +347,7 @@
 	m_sigframe/sigframe-arm-linux.c \
 	m_sigframe/sigframe-s390x-linux.c \
 	m_sigframe/sigframe-mips32-linux.c \
+	m_sigframe/sigframe-mips64-linux.c \
 	m_sigframe/sigframe-x86-darwin.c \
 	m_sigframe/sigframe-amd64-darwin.c \
 	m_syswrap/syscall-x86-linux.S \
@@ -354,6 +357,7 @@
 	m_syswrap/syscall-arm-linux.S \
 	m_syswrap/syscall-s390x-linux.S \
 	m_syswrap/syscall-mips32-linux.S \
+	m_syswrap/syscall-mips64-linux.S \
 	m_syswrap/syscall-x86-darwin.S \
 	m_syswrap/syscall-amd64-darwin.S \
 	m_syswrap/syswrap-main.c \
@@ -368,6 +372,7 @@
 	m_syswrap/syswrap-arm-linux.c \
 	m_syswrap/syswrap-s390x-linux.c \
 	m_syswrap/syswrap-mips32-linux.c \
+	m_syswrap/syswrap-mips64-linux.c \
 	m_syswrap/syswrap-x86-darwin.c \
 	m_syswrap/syswrap-amd64-darwin.c \
 	m_syswrap/syswrap-xen.c \
@@ -554,7 +559,18 @@
 	m_gdbserver/mips-linux-valgrind.xml \
 	m_gdbserver/mips-fpu-valgrind-s1.xml \
 	m_gdbserver/mips-fpu-valgrind-s2.xml \
-	m_gdbserver/mips-fpu.xml
+	m_gdbserver/mips-fpu.xml \
+	m_gdbserver/mips64-cp0-valgrind-s1.xml \
+	m_gdbserver/mips64-cp0-valgrind-s2.xml \
+	m_gdbserver/mips64-cp0.xml \
+	m_gdbserver/mips64-cpu-valgrind-s1.xml \
+	m_gdbserver/mips64-cpu-valgrind-s2.xml \
+	m_gdbserver/mips64-cpu.xml \
+	m_gdbserver/mips64-linux.xml \
+	m_gdbserver/mips64-linux-valgrind.xml \
+	m_gdbserver/mips64-fpu-valgrind-s1.xml \
+	m_gdbserver/mips64-fpu-valgrind-s2.xml \
+	m_gdbserver/mips64-fpu.xml
 
 # so as to make sure these get copied into the install tree
 vglibdir = $(pkglibdir)
diff --git a/coregrind/launcher-linux.c b/coregrind/launcher-linux.c
index 5c77071..469380f 100644
--- a/coregrind/launcher-linux.c
+++ b/coregrind/launcher-linux.c
@@ -211,6 +211,10 @@
                 (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV ||
                  ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
                platform = "amd64-linux";
+            } else if (ehdr->e_machine == EM_MIPS &&
+                (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV ||
+                 ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
+               platform = "mips64-linux";
             }
          } else if (header[EI_DATA] == ELFDATA2MSB) {
 #           if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android)
@@ -224,6 +228,10 @@
                 (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV ||
                  ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
                platform = "s390x-linux";
+            } else if (ehdr->e_machine == EM_MIPS &&
+                (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV ||
+                 ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
+               platform = "mips64-linux";
             }
 #           endif
          }
@@ -300,7 +308,8 @@
        (0==strcmp(VG_PLATFORM,"ppc64-linux")) ||
        (0==strcmp(VG_PLATFORM,"arm-linux"))   ||
        (0==strcmp(VG_PLATFORM,"s390x-linux")) ||
-       (0==strcmp(VG_PLATFORM,"mips32-linux")))
+       (0==strcmp(VG_PLATFORM,"mips32-linux")) ||
+       (0==strcmp(VG_PLATFORM,"mips64-linux")))
       default_platform = VG_PLATFORM;
    else
       barf("Unknown VG_PLATFORM '%s'", VG_PLATFORM);
diff --git a/coregrind/m_aspacemgr/aspacemgr-common.c b/coregrind/m_aspacemgr/aspacemgr-common.c
index 45d7d08..228ba8f 100644
--- a/coregrind/m_aspacemgr/aspacemgr-common.c
+++ b/coregrind/m_aspacemgr/aspacemgr-common.c
@@ -159,7 +159,8 @@
    res = VG_(do_syscall6)(__NR_mmap2, (UWord)start, length,
                           prot, flags, fd, offset / 4096);
 #  elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) \
-        || defined(VGP_s390x_linux) || defined(VGP_mips32_linux)
+        || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \
+        || defined(VGP_mips64_linux)
    res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, 
                          prot, flags, fd, offset);
 #  elif defined(VGP_x86_darwin)
diff --git a/coregrind/m_aspacemgr/aspacemgr-linux.c b/coregrind/m_aspacemgr/aspacemgr-linux.c
index eddb4de..9db3820 100644
--- a/coregrind/m_aspacemgr/aspacemgr-linux.c
+++ b/coregrind/m_aspacemgr/aspacemgr-linux.c
@@ -2533,7 +2533,7 @@
    /* Ask for an advisory.  If it's negative, fail immediately. */
    req.rkind = MAny;
    req.start = 0;
-   #if defined(VGA_arm) || defined(VGA_mips32)
+   #if defined(VGA_arm) || defined(VGA_mips32) || defined(VGA_mips64)
    aspacem_assert(VKI_SHMLBA >= VKI_PAGE_SIZE);
    #else
    aspacem_assert(VKI_SHMLBA == VKI_PAGE_SIZE);
diff --git a/coregrind/m_cache.c b/coregrind/m_cache.c
index f83f62d..077fc0a 100644
--- a/coregrind/m_cache.c
+++ b/coregrind/m_cache.c
@@ -539,7 +539,7 @@
 }
 
 #elif defined(VGA_arm) || defined(VGA_ppc32) || defined(VGA_ppc64) || \
-      defined(VGA_mips32)
+      defined(VGA_mips32) || defined(VGA_mips64)
 
 static Bool
 get_cache_info(VexArchInfo *vai)
diff --git a/coregrind/m_coredump/coredump-elf.c b/coregrind/m_coredump/coredump-elf.c
index bc6b3f8..ebf31d0 100644
--- a/coregrind/m_coredump/coredump-elf.c
+++ b/coregrind/m_coredump/coredump-elf.c
@@ -384,6 +384,15 @@
 #  undef DO
    regs->MIPS_hi   = arch->vex.guest_HI;
    regs->MIPS_lo   = arch->vex.guest_LO;
+#elif defined(VGP_mips64_linux)
+#  define DO(n)  regs->MIPS_r##n = arch->vex.guest_r##n
+   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
+   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
+   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
+   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
+#  undef DO
+   regs->MIPS_hi   = arch->vex.guest_HI;
+   regs->MIPS_lo   = arch->vex.guest_LO;
 #else
 #  error Unknown ELF platform
 #endif
@@ -471,6 +480,13 @@
    DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
    DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
 #  undef DO
+#elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
+#  define DO(n)  (*fpu)[n] = *(double*)(&arch->vex.guest_f##n)
+   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
+   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
+   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
+   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
+#  undef DO
 #else
 #  error Unknown ELF platform
 #endif
diff --git a/coregrind/m_debugger.c b/coregrind/m_debugger.c
index 14ae9ef..e53094b 100644
--- a/coregrind/m_debugger.c
+++ b/coregrind/m_debugger.c
@@ -307,7 +307,7 @@
 
    return VG_(ptrace)(VKI_PTRACE_POKEUSR_AREA, pid,  &pa, NULL);
 
-#elif defined(VGP_mips32_linux)
+#elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
    struct vki_user_regs_struct regs;
    VG_(memset)(&regs, 0, sizeof(regs));
    regs.MIPS_r0     = vex->guest_r0;
diff --git a/coregrind/m_debuginfo/d3basics.c b/coregrind/m_debuginfo/d3basics.c
index 88475bc..13297fb 100644
--- a/coregrind/m_debuginfo/d3basics.c
+++ b/coregrind/m_debuginfo/d3basics.c
@@ -415,6 +415,9 @@
 #  elif defined(VGP_mips32_linux)
    if (regno == 29) { *a = regs->sp; return True; }
    if (regno == 30) { *a = regs->fp; return True; }
+#  elif defined(VGP_mips64_linux)
+   if (regno == 29) { *a = regs->sp; return True; }
+   if (regno == 30) { *a = regs->fp; return True; }
 #  else
 #    error "Unknown platform"
 #  endif
diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c
index 2d7ec82..e866420 100644
--- a/coregrind/m_debuginfo/debuginfo.c
+++ b/coregrind/m_debuginfo/debuginfo.c
@@ -819,7 +819,8 @@
    is_rw_map = False;
    is_ro_map = False;
 
-#  if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32)
+#  if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32) \
+      || defined(VGA_mips64)
    is_rx_map = seg->hasR && seg->hasX;
    is_rw_map = seg->hasR && seg->hasW;
 #  elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm)
@@ -2105,7 +2106,7 @@
             case Creg_IA_SP: return eec->uregs->sp;
             case Creg_IA_BP: return eec->uregs->fp;
             case Creg_S390_R14: return eec->uregs->lr;
-#           elif defined(VGA_mips32)
+#           elif defined(VGA_mips32) || defined(VGA_mips64)
             case Creg_IA_IP: return eec->uregs->pc;
             case Creg_IA_SP: return eec->uregs->sp;
             case Creg_IA_BP: return eec->uregs->fp;
@@ -2344,7 +2345,7 @@
       case CFIC_IA_BPREL:
          cfa = cfsi->cfa_off + uregs->fp;
          break;
-#     elif defined(VGA_mips32)
+#     elif defined(VGA_mips32) || defined(VGA_mips64)
       case CFIC_IA_SPREL:
          cfa = cfsi->cfa_off + uregs->sp;
          break;
@@ -2448,7 +2449,7 @@
    ipHere = uregsHere->r15;
 #  elif defined(VGA_s390x)
    ipHere = uregsHere->ia;
-#  elif defined(VGA_mips32)
+#  elif defined(VGA_mips32) || defined(VGA_mips64)
    ipHere = uregsHere->pc;
 #  elif defined(VGA_ppc32) || defined(VGA_ppc64)
 #  else
@@ -2526,7 +2527,7 @@
    COMPUTE(uregsPrev.ia, uregsHere->ia, cfsi->ra_how, cfsi->ra_off);
    COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off);
    COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi->fp_how, cfsi->fp_off);
-#  elif defined(VGA_mips32)
+#  elif defined(VGA_mips32) || defined(VGA_mips64)
    COMPUTE(uregsPrev.pc, uregsHere->pc, cfsi->ra_how, cfsi->ra_off);
    COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off);
    COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi->fp_how, cfsi->fp_off);
diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h
index a88c2e4..ecf7fae 100644
--- a/coregrind/m_debuginfo/priv_storage.h
+++ b/coregrind/m_debuginfo/priv_storage.h
@@ -257,7 +257,7 @@
       Int   fp_off;
    }
    DiCfSI;
-#elif defined(VGA_mips32)
+#elif defined(VGA_mips32) || defined(VGA_mips64)
 typedef
    struct {
       Addr  base;
diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c
index e547170..ce34bc7 100644
--- a/coregrind/m_debuginfo/readdwarf.c
+++ b/coregrind/m_debuginfo/readdwarf.c
@@ -1859,6 +1859,10 @@
 #  define FP_REG         30
 #  define SP_REG         29
 #  define RA_REG_DEFAULT 31
+#elif defined(VGP_mips64_linux)
+#  define FP_REG         30
+#  define SP_REG         29
+#  define RA_REG_DEFAULT 31
 #else
 #  error "Unknown platform"
 #endif
@@ -1868,7 +1872,7 @@
    7 (DWARF for the ARM Architecture) specifies that values up to 320
    might exist, for Neon/VFP-v3. */
 #if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
-    || defined(VGP_mips32_linux)
+    || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
 # define N_CFI_REGS 72
 #elif defined(VGP_arm_linux)
 # define N_CFI_REGS 320
@@ -2173,7 +2177,7 @@
    if (ctxs->cfa_is_regoff && ctxs->cfa_reg == SP_REG) {
       si->cfa_off = ctxs->cfa_off;
 #     if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
-         || defined(VGA_mips32)
+         || defined(VGA_mips32) || defined(VGA_mips64)
       si->cfa_how = CFIC_IA_SPREL;
 #     elif defined(VGA_arm)
       si->cfa_how = CFIC_ARM_R13REL;
@@ -2185,7 +2189,7 @@
    if (ctxs->cfa_is_regoff && ctxs->cfa_reg == FP_REG) {
       si->cfa_off = ctxs->cfa_off;
 #     if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
-         || defined(VGA_mips32)
+         || defined(VGA_mips32) || defined(VGA_mips64)
       si->cfa_how = CFIC_IA_BPREL;
 #     elif defined(VGA_arm)
       si->cfa_how = CFIC_ARM_R12REL;
@@ -2386,7 +2390,7 @@
    return True;
 
 
-#  elif defined(VGA_mips32)
+#  elif defined(VGA_mips32) || defined(VGA_mips64)
  
    /* --- entire tail of this fn specialised for mips --- */
  
@@ -2512,7 +2516,7 @@
             return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
          if (dwreg == srcuc->ra_reg)
             return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP ); /* correct? */
-#        elif defined(VGA_mips32)
+#        elif defined(VGA_mips32) || defined(VGA_mips64)
          if (dwreg == SP_REG)
             return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
          if (dwreg == FP_REG)
diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c
index 204af55..cf7b5d3 100644
--- a/coregrind/m_debuginfo/readelf.c
+++ b/coregrind/m_debuginfo/readelf.c
@@ -2042,7 +2042,7 @@
       /* PLT is different on different platforms, it seems. */
 #     if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
          || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \
-         || defined(VGP_mips32_linux)
+         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
       /* Accept .plt where mapped as rx (code) */
       if (0 == VG_(strcmp)(name, ".plt")) {
          if (inrx && !di->plt_present) {
@@ -2693,7 +2693,8 @@
          && !defined(VGP_s390x_linux) \
          && !defined(VGP_ppc64_linux) \
          && !defined(VGPV_arm_linux_android) \
-         && !defined(VGPV_x86_linux_android)
+         && !defined(VGPV_x86_linux_android) \
+         && !defined(VGP_mips64_linux)
       if (stab_img && stabstr_img) {
          ML_(read_debuginfo_stabs) ( di, stab_img, stab_sz, 
                                          stabstr_img, stabstr_sz );
diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c
index f344c8f..43e4a8f 100644
--- a/coregrind/m_debuginfo/storage.c
+++ b/coregrind/m_debuginfo/storage.c
@@ -189,7 +189,7 @@
    VG_(printf)(" R7=");
    SHOW_HOW(si->r7_how, si->r7_off);
 #  elif defined(VGA_ppc32) || defined(VGA_ppc64)
-#  elif defined(VGA_s390x) || defined(VGA_mips32)
+#  elif defined(VGA_s390x) || defined(VGA_mips32) || defined(VGA_mips64)
    VG_(printf)(" SP=");
    SHOW_HOW(si->sp_how, si->sp_off);
    VG_(printf)(" FP=");
diff --git a/coregrind/m_debuglog.c b/coregrind/m_debuglog.c
index 3c6025e..961d86c 100644
--- a/coregrind/m_debuglog.c
+++ b/coregrind/m_debuglog.c
@@ -427,6 +427,42 @@
    return __res;
 }
 
+#elif defined(VGP_mips64_linux)
+static UInt local_sys_write_stderr ( const HChar* buf, Int n )
+{
+   volatile Long block[2];
+   block[0] = (Long)buf;
+   block[1] = n;
+   __asm__ volatile (
+      "li   $4, 2\n\t"      /* std output*/
+      "ld   $5, 0(%0)\n\t"  /*$5 = buf*/
+      "ld   $6, 8(%0)\n\t"  /*$6 = n */
+      "move $7, $0\n\t"
+      "li   $2, %1\n\t"     /* set v0 = __NR_write */
+      "\tsyscall\n"
+      "\tnop\n"
+      : /*wr*/
+      : /*rd*/  "r" (block), "n" (__NR_write)
+      : "2", "4", "5", "6", "7"
+   );
+   if (block[0] < 0)
+      block[0] = -1;
+   return (UInt)(Int)block[0];
+}
+ 
+static UInt local_sys_getpid ( void )
+{
+   ULong __res;
+   __asm__ volatile (
+      "li   $2, %1\n\t"  /* set v0 = __NR_getpid */
+      "syscall\n\t"      /* getpid() */
+      "nop\n\t"
+      "move  %0, $2\n"
+      : "=r" (__res)
+      : "n" (__NR_getpid)
+      : "$2" );
+   return (UInt)(__res);
+}
 
 #else
 # error Unknown platform
diff --git a/coregrind/m_dispatch/dispatch-mips32-linux.S b/coregrind/m_dispatch/dispatch-mips32-linux.S
index f732b3c..a059b98 100644
--- a/coregrind/m_dispatch/dispatch-mips32-linux.S
+++ b/coregrind/m_dispatch/dispatch-mips32-linux.S
@@ -87,8 +87,8 @@
        return values can be written */
     sw $4, 60($29)
 
-    /* Load address of guest state into guest state register (r10) */
-    move $10, $5
+    /* Load address of guest state into guest state register ($23) */
+    move $23, $5
 
     /* and jump into the code cache.  Chained translations in
            the code cache run, until for whatever reason, they can't
@@ -103,9 +103,9 @@
 /*----------------------------------------------------*/
 
 postamble:
-        /* At this point, r2 and r3 contain two
-           words to be returned to the caller.  r2
-           holds a TRC value, and r3 optionally may
+        /* At this point, $2 and $3 contain two
+           words to be returned to the caller.  $2
+           holds a TRC value, and $3 optionally may
            hold another word (for CHAIN_ME exits, the
            address of the place to patch.) */
 
@@ -175,7 +175,7 @@
 .global VG_(disp_cp_xindir)
 VG_(disp_cp_xindir):
         /* Where are we going? */
-        lw  $11, OFFSET_mips32_PC($10)
+        lw  $11, OFFSET_mips32_PC($23)
 
         lw $13, vgPlain_stats__n_xindirs_32
         addiu $13, $13, 0x1
@@ -222,7 +222,7 @@
 VG_(disp_cp_xassisted):
         /* guest-state-pointer contains the TRC. Put the value into the
            return register */
-        move    $2, $10
+        move    $2, $23
         move    $3, $0
         b       postamble
 
diff --git a/coregrind/m_dispatch/dispatch-mips64-linux.S b/coregrind/m_dispatch/dispatch-mips64-linux.S
new file mode 100644
index 0000000..152a633
--- /dev/null
+++ b/coregrind/m_dispatch/dispatch-mips64-linux.S
@@ -0,0 +1,245 @@
+
+/*--------------------------------------------------------------------*/
+/*--- The core dispatch loop, for jumping to a code address.       ---*/
+/*---                                      dispatch-mips64-linux.S ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+  This file is part of Valgrind, a dynamic binary instrumentation
+  framework.
+
+  Copyright (C) 2000-2013 RT-RK
+     mips-valgrind@rt-rk.com 
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#if defined(VGP_mips64_linux)
+
+#include "pub_core_basics_asm.h"
+#include "pub_core_dispatch_asm.h"
+#include "pub_core_transtab_asm.h"
+#include "libvex_guest_offsets.h"	/* for OFFSET_mips_PC */
+
+
+/*------------------------------------------------------------*/
+/*---                                                      ---*/
+/*--- The dispatch loop.  VG_(disp_run_translations) is    ---*/
+/*--- used to run all translations,                        ---*/
+/*--- including no-redir ones.                             ---*/
+/*---                                                      ---*/
+/*------------------------------------------------------------*/
+
+/*----------------------------------------------------*/
+/*--- Entry and preamble (set everything up)       ---*/
+/*----------------------------------------------------*/
+
+/* signature:
+void VG_(disp_run_translations)( UWord* two_words,
+                                 void*  guest_state, 
+                                 Addr   host_addr );
+*/
+
+.text
+.globl VG_(disp_run_translations)
+VG_(disp_run_translations):
+    /* a0 ($4) holds two_words   */
+    /* a1 ($5) holds guest_state */
+    /* a2 ($6) holds host_addr   */
+
+    /* New stack frame.  Stack must remain 16 aligned (at least) */
+    daddiu $29, -176
+
+    /* Save ra */
+    sd  $31, 72($29)
+
+    /* ... and s0 - s7 */
+    sd $16, 80($29)
+    sd $17, 88($29)
+    sd $18, 96($29)
+    sd $19, 104($29)
+    sd $20, 112($29)
+    sd $21, 120($29)
+    sd $22, 128($29)
+    sd $23, 136($29)
+
+    /* ... and gp, fp/s8 */
+    sd $28, 144($29)
+    sd $30, 152($29)
+
+    /* Save a0 ($4) on stack. In postamble it will be restored such that the
+       return values can be written */
+    sd $4, 160($29)
+
+    /* Load address of guest state into guest state register ($23) */
+    move $23, $5
+
+    /* and jump into the code cache.  Chained translations in
+           the code cache run, until for whatever reason, they can't
+           continue.  When that happens, the translation in question
+           will jump (or call) to one of the continuation points
+           VG_(cp_...) below. */
+    jr $6
+    /*NOTREACHED*/
+    
+/*----------------------------------------------------*/
+/*--- Postamble and exit.                          ---*/
+/*----------------------------------------------------*/
+
+postamble:
+        /* At this point, $2 and $3 contain two
+           words to be returned to the caller.  $2
+           holds a TRC value, and $3 optionally may
+           hold another word (for CHAIN_ME exits, the
+           address of the place to patch.) */
+
+    /* Restore $4 from stack; holds address of two_words */
+    ld $4, 160($29)
+    sd  $2, 0($4)         /* Store $2 to two_words[0] */
+    sd  $3, 8($4)         /* Store $3 to two_words[1] */
+
+    /* Restore callee-saved registers... */
+
+    /* Restore ra */
+    ld $31, 72($29)
+
+    /* ... and s0 - s7 */
+    ld $16, 80($29)
+    ld $17, 88($29)
+    ld $18, 96($29)
+    ld $19, 104($29)
+    ld $20, 112($29)
+    ld $21, 120($29)
+    ld $22, 128($29)
+    ld $23, 136($29)
+
+    /* ... and gp, fp/s8 */
+    ld $28, 144($29)
+    ld $30, 152($29)
+
+    daddiu $29, 176   /* stack_size */
+    jr $31
+    nop
+
+/*----------------------------------------------------*/
+/*--- Continuation points                          ---*/
+/*----------------------------------------------------*/
+
+/* ------ Chain me to slow entry point ------ */
+.global VG_(disp_cp_chain_me_to_slowEP)
+VG_(disp_cp_chain_me_to_slowEP):
+        /* We got called.  The return address indicates
+           where the patching needs to happen.  Collect
+           the return address and, exit back to C land,
+           handing the caller the pair (Chain_me_S, RA) */
+        li $2, VG_TRC_CHAIN_ME_TO_SLOW_EP
+        move $3, $31
+        /* 8 = mkLoadImm_EXACTLY2or6
+           4 = jalr $9
+           4 = nop */
+        daddiu  $3, $3, -32
+        b    postamble
+
+/* ------ Chain me to slow entry point ------ */
+.global VG_(disp_cp_chain_me_to_fastEP)
+VG_(disp_cp_chain_me_to_fastEP):
+        /* We got called.  The return address indicates
+           where the patching needs to happen.  Collect
+           the return address and, exit back to C land,
+           handing the caller the pair (Chain_me_S, RA) */
+        li $2, VG_TRC_CHAIN_ME_TO_FAST_EP
+        move $3, $31
+        /* 8 = mkLoadImm_EXACTLY2or6
+           4 = jalr $9
+           4 = nop */
+        daddiu  $3, $3, -32
+        b    postamble
+
+/* ------ Indirect but boring jump ------ */
+.global VG_(disp_cp_xindir)
+VG_(disp_cp_xindir):
+        /* Where are we going? */
+        ld  $11, OFFSET_mips64_PC($23)
+
+        lw $13, vgPlain_stats__n_xindirs_32
+        addiu $13, $13, 0x1
+        sw $13, vgPlain_stats__n_xindirs_32
+
+        /* try a fast lookup in the translation cache */
+        /* t1 = VG_TT_FAST_HASH(addr) * sizeof(ULong*)
+                = (t8 >> 2 & VG_TT_FAST_MASK)  << 3 */
+
+        move $14, $11
+        li $12, VG_TT_FAST_MASK
+        srl $14, $14, 2
+        and $14, $14, $12
+        sll $14, $14, 3
+
+        /* t2 = (addr of VG_(tt_fast)) + t1 */
+        la $13, VG_(tt_fast)
+        addu $13, $13, $14
+
+        ld $12, 0($13) /* t3 = VG_(tt_fast)[hash] :: ULong* */
+        addi $13, $13, 8
+        ld $25, 0($13) /* little-endian, so comparing 1st 32bit word */
+        nop
+
+check:
+        bne $12, $11, fast_lookup_failed
+        /* run the translation */
+        jr $25
+        .long   0x0   /* persuade insn decoders not to speculate past here */
+
+fast_lookup_failed:
+        /* %PC is up to date */
+        /* back out decrement of the dispatch counter */
+        /* hold dispatch_ctr in t0 (r8) */
+        lw $13, vgPlain_stats__n_xindirs_32
+        addiu $13, $13, 0x1
+        sw $13, vgPlain_stats__n_xindirs_32
+        li $2, VG_TRC_INNER_FASTMISS
+        li $3, 0
+        b       postamble
+
+/* ------ Assisted jump ------ */
+        .global VG_(disp_cp_xassisted)
+VG_(disp_cp_xassisted):
+        /* guest-state-pointer contains the TRC. Put the value into the
+           return register */
+        move    $2, $23
+        move    $3, $0
+        b       postamble
+
+/* ------ Event check failed ------ */
+        .global VG_(disp_cp_evcheck_fail)
+VG_(disp_cp_evcheck_fail):
+        li      $2, VG_TRC_INNER_COUNTERZERO
+        move    $3, $0
+        b       postamble
+
+.size VG_(disp_run_translations), .-VG_(disp_run_translations)
+
+
+/* Let the linker know we do not need an executable stack */
+.section .note.GNU-stack,"",@progbits
+
+#endif // defined(VGP_mips64_linux)
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/m_gdbserver/mips64-cp0-valgrind-s1.xml b/coregrind/m_gdbserver/mips64-cp0-valgrind-s1.xml
new file mode 100644
index 0000000..21447d1
--- /dev/null
+++ b/coregrind/m_gdbserver/mips64-cp0-valgrind-s1.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.cp0.valgrind.s1">
+  <reg name="statuss1" bitsize="64" regnum="32"/>
+  <reg name="badvaddrs1" bitsize="64" regnum="35"/>
+  <reg name="causes1" bitsize="64" regnum="36"/>
+</feature>
diff --git a/coregrind/m_gdbserver/mips64-cp0-valgrind-s2.xml b/coregrind/m_gdbserver/mips64-cp0-valgrind-s2.xml
new file mode 100644
index 0000000..3623f39
--- /dev/null
+++ b/coregrind/m_gdbserver/mips64-cp0-valgrind-s2.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.cp0.valgrind.s2">
+  <reg name="statuss2" bitsize="64" regnum="32"/>
+  <reg name="badvaddrs2" bitsize="64" regnum="35"/>
+  <reg name="causes2" bitsize="64" regnum="36"/>
+</feature>
diff --git a/coregrind/m_gdbserver/mips64-cp0.xml b/coregrind/m_gdbserver/mips64-cp0.xml
new file mode 100644
index 0000000..d6d422f
--- /dev/null
+++ b/coregrind/m_gdbserver/mips64-cp0.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.cp0">
+  <reg name="status" bitsize="64" regnum="32"/>
+  <reg name="badvaddr" bitsize="64" regnum="35"/>
+  <reg name="cause" bitsize="64" regnum="36"/>
+</feature>
diff --git a/coregrind/m_gdbserver/mips64-cpu-valgrind-s1.xml b/coregrind/m_gdbserver/mips64-cpu-valgrind-s1.xml
new file mode 100644
index 0000000..549dd72
--- /dev/null
+++ b/coregrind/m_gdbserver/mips64-cpu-valgrind-s1.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.cpu.valgrind.s1">
+  <reg name="r0s1" bitsize="64" regnum="0"/>
+  <reg name="r1s1" bitsize="64"/>
+  <reg name="r2s1" bitsize="64"/>
+  <reg name="r3s1" bitsize="64"/>
+  <reg name="r4s1" bitsize="64"/>
+  <reg name="r5s1" bitsize="64"/>
+  <reg name="r6s1" bitsize="64"/>
+  <reg name="r7s1" bitsize="64"/>
+  <reg name="r8s1" bitsize="64"/>
+  <reg name="r9s1" bitsize="64"/>
+  <reg name="r10s1" bitsize="64"/>
+  <reg name="r11s1" bitsize="64"/>
+  <reg name="r12s1" bitsize="64"/>
+  <reg name="r13s1" bitsize="64"/>
+  <reg name="r14s1" bitsize="64"/>
+  <reg name="r15s1" bitsize="64"/>
+  <reg name="r16s1" bitsize="64"/>
+  <reg name="r17s1" bitsize="64"/>
+  <reg name="r18s1" bitsize="64"/>
+  <reg name="r19s1" bitsize="64"/>
+  <reg name="r20s1" bitsize="64"/>
+  <reg name="r21s1" bitsize="64"/>
+  <reg name="r22s1" bitsize="64"/>
+  <reg name="r23s1" bitsize="64"/>
+  <reg name="r24s1" bitsize="64"/>
+  <reg name="r25s1" bitsize="64"/>
+  <reg name="r26s1" bitsize="64"/>
+  <reg name="r27s1" bitsize="64"/>
+  <reg name="r28s1" bitsize="64"/>
+  <reg name="r29s1" bitsize="64"/>
+  <reg name="r30s1" bitsize="64"/>
+  <reg name="r31s1" bitsize="64"/>
+
+  <reg name="los1" bitsize="64" regnum="33"/>
+  <reg name="his1" bitsize="64" regnum="34"/>
+  <reg name="pcs1" bitsize="64" regnum="37"/>
+</feature>
diff --git a/coregrind/m_gdbserver/mips64-cpu-valgrind-s2.xml b/coregrind/m_gdbserver/mips64-cpu-valgrind-s2.xml
new file mode 100644
index 0000000..f054a8f
--- /dev/null
+++ b/coregrind/m_gdbserver/mips64-cpu-valgrind-s2.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.cpu.valgrind.s2">
+  <reg name="r0s2" bitsize="64" regnum="0"/>
+  <reg name="r1s2" bitsize="64"/>
+  <reg name="r2s2" bitsize="64"/>
+  <reg name="r3s2" bitsize="64"/>
+  <reg name="r4s2" bitsize="64"/>
+  <reg name="r5s2" bitsize="64"/>
+  <reg name="r6s2" bitsize="64"/>
+  <reg name="r7s2" bitsize="64"/>
+  <reg name="r8s2" bitsize="64"/>
+  <reg name="r9s2" bitsize="64"/>
+  <reg name="r10s2" bitsize="64"/>
+  <reg name="r11s2" bitsize="64"/>
+  <reg name="r12s2" bitsize="64"/>
+  <reg name="r13s2" bitsize="64"/>
+  <reg name="r14s2" bitsize="64"/>
+  <reg name="r15s2" bitsize="64"/>
+  <reg name="r16s2" bitsize="64"/>
+  <reg name="r17s2" bitsize="64"/>
+  <reg name="r18s2" bitsize="64"/>
+  <reg name="r19s2" bitsize="64"/>
+  <reg name="r20s2" bitsize="64"/>
+  <reg name="r21s2" bitsize="64"/>
+  <reg name="r22s2" bitsize="64"/>
+  <reg name="r23s2" bitsize="64"/>
+  <reg name="r24s2" bitsize="64"/>
+  <reg name="r25s2" bitsize="64"/>
+  <reg name="r26s2" bitsize="64"/>
+  <reg name="r27s2" bitsize="64"/>
+  <reg name="r28s2" bitsize="64"/>
+  <reg name="r29s2" bitsize="64"/>
+  <reg name="r30s2" bitsize="64"/>
+  <reg name="r31s2" bitsize="64"/>
+
+  <reg name="los2" bitsize="64" regnum="33"/>
+  <reg name="his2" bitsize="64" regnum="34"/>
+  <reg name="pcs2" bitsize="64" regnum="37"/>
+</feature>
diff --git a/coregrind/m_gdbserver/mips64-cpu.xml b/coregrind/m_gdbserver/mips64-cpu.xml
new file mode 100644
index 0000000..5ee6cfa
--- /dev/null
+++ b/coregrind/m_gdbserver/mips64-cpu.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.cpu">
+  <reg name="r0" bitsize="64" regnum="0"/>
+  <reg name="r1" bitsize="64"/>
+  <reg name="r2" bitsize="64"/>
+  <reg name="r3" bitsize="64"/>
+  <reg name="r4" bitsize="64"/>
+  <reg name="r5" bitsize="64"/>
+  <reg name="r6" bitsize="64"/>
+  <reg name="r7" bitsize="64"/>
+  <reg name="r8" bitsize="64"/>
+  <reg name="r9" bitsize="64"/>
+  <reg name="r10" bitsize="64"/>
+  <reg name="r11" bitsize="64"/>
+  <reg name="r12" bitsize="64"/>
+  <reg name="r13" bitsize="64"/>
+  <reg name="r14" bitsize="64"/>
+  <reg name="r15" bitsize="64"/>
+  <reg name="r16" bitsize="64"/>
+  <reg name="r17" bitsize="64"/>
+  <reg name="r18" bitsize="64"/>
+  <reg name="r19" bitsize="64"/>
+  <reg name="r20" bitsize="64"/>
+  <reg name="r21" bitsize="64"/>
+  <reg name="r22" bitsize="64"/>
+  <reg name="r23" bitsize="64"/>
+  <reg name="r24" bitsize="64"/>
+  <reg name="r25" bitsize="64"/>
+  <reg name="r26" bitsize="64"/>
+  <reg name="r27" bitsize="64"/>
+  <reg name="r28" bitsize="64"/>
+  <reg name="r29" bitsize="64"/>
+  <reg name="r30" bitsize="64"/>
+  <reg name="r31" bitsize="64"/>
+
+  <reg name="lo" bitsize="64" regnum="33"/>
+  <reg name="hi" bitsize="64" regnum="34"/>
+  <reg name="pc" bitsize="64" regnum="37"/>
+</feature>
diff --git a/coregrind/m_gdbserver/mips64-fpu-valgrind-s1.xml b/coregrind/m_gdbserver/mips64-fpu-valgrind-s1.xml
new file mode 100644
index 0000000..6aa735e
--- /dev/null
+++ b/coregrind/m_gdbserver/mips64-fpu-valgrind-s1.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.fpu.valgrind.s1">
+  <reg name="f0s1" bitsize="64" type="ieee_double" regnum="38"/>
+  <reg name="f1s1" bitsize="64" type="ieee_double"/>
+  <reg name="f2s1" bitsize="64" type="ieee_double"/>
+  <reg name="f3s1" bitsize="64" type="ieee_double"/>
+  <reg name="f4s1" bitsize="64" type="ieee_double"/>
+  <reg name="f5s1" bitsize="64" type="ieee_double"/>
+  <reg name="f6s1" bitsize="64" type="ieee_double"/>
+  <reg name="f7s1" bitsize="64" type="ieee_double"/>
+  <reg name="f8s1" bitsize="64" type="ieee_double"/>
+  <reg name="f9s1" bitsize="64" type="ieee_double"/>
+  <reg name="f10s1" bitsize="64" type="ieee_double"/>
+  <reg name="f11s1" bitsize="64" type="ieee_double"/>
+  <reg name="f12s1" bitsize="64" type="ieee_double"/>
+  <reg name="f13s1" bitsize="64" type="ieee_double"/>
+  <reg name="f14s1" bitsize="64" type="ieee_double"/>
+  <reg name="f15s1" bitsize="64" type="ieee_double"/>
+  <reg name="f16s1" bitsize="64" type="ieee_double"/>
+  <reg name="f17s1" bitsize="64" type="ieee_double"/>
+  <reg name="f18s1" bitsize="64" type="ieee_double"/>
+  <reg name="f19s1" bitsize="64" type="ieee_double"/>
+  <reg name="f20s1" bitsize="64" type="ieee_double"/>
+  <reg name="f21s1" bitsize="64" type="ieee_double"/>
+  <reg name="f22s1" bitsize="64" type="ieee_double"/>
+  <reg name="f23s1" bitsize="64" type="ieee_double"/>
+  <reg name="f24s1" bitsize="64" type="ieee_double"/>
+  <reg name="f25s1" bitsize="64" type="ieee_double"/>
+  <reg name="f26s1" bitsize="64" type="ieee_double"/>
+  <reg name="f27s1" bitsize="64" type="ieee_double"/>
+  <reg name="f28s1" bitsize="64" type="ieee_double"/>
+  <reg name="f29s1" bitsize="64" type="ieee_double"/>
+  <reg name="f30s1" bitsize="64" type="ieee_double"/>
+  <reg name="f31s1" bitsize="64" type="ieee_double"/>
+
+  <reg name="fcsrs1" bitsize="64" group="float"/>
+  <reg name="firs1" bitsize="64" group="float"/>
+</feature>
diff --git a/coregrind/m_gdbserver/mips64-fpu-valgrind-s2.xml b/coregrind/m_gdbserver/mips64-fpu-valgrind-s2.xml
new file mode 100644
index 0000000..3d5c278
--- /dev/null
+++ b/coregrind/m_gdbserver/mips64-fpu-valgrind-s2.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.fpu.valgrind.s2">
+  <reg name="f0s2" bitsize="64" type="ieee_double" regnum="38"/>
+  <reg name="f1s2" bitsize="64" type="ieee_double"/>
+  <reg name="f2s2" bitsize="64" type="ieee_double"/>
+  <reg name="f3s2" bitsize="64" type="ieee_double"/>
+  <reg name="f4s2" bitsize="64" type="ieee_double"/>
+  <reg name="f5s2" bitsize="64" type="ieee_double"/>
+  <reg name="f6s2" bitsize="64" type="ieee_double"/>
+  <reg name="f7s2" bitsize="64" type="ieee_double"/>
+  <reg name="f8s2" bitsize="64" type="ieee_double"/>
+  <reg name="f9s2" bitsize="64" type="ieee_double"/>
+  <reg name="f10s2" bitsize="64" type="ieee_double"/>
+  <reg name="f11s2" bitsize="64" type="ieee_double"/>
+  <reg name="f12s2" bitsize="64" type="ieee_double"/>
+  <reg name="f13s2" bitsize="64" type="ieee_double"/>
+  <reg name="f14s2" bitsize="64" type="ieee_double"/>
+  <reg name="f15s2" bitsize="64" type="ieee_double"/>
+  <reg name="f16s2" bitsize="64" type="ieee_double"/>
+  <reg name="f17s2" bitsize="64" type="ieee_double"/>
+  <reg name="f18s2" bitsize="64" type="ieee_double"/>
+  <reg name="f19s2" bitsize="64" type="ieee_double"/>
+  <reg name="f20s2" bitsize="64" type="ieee_double"/>
+  <reg name="f21s2" bitsize="64" type="ieee_double"/>
+  <reg name="f22s2" bitsize="64" type="ieee_double"/>
+  <reg name="f23s2" bitsize="64" type="ieee_double"/>
+  <reg name="f24s2" bitsize="64" type="ieee_double"/>
+  <reg name="f25s2" bitsize="64" type="ieee_double"/>
+  <reg name="f26s2" bitsize="64" type="ieee_double"/>
+  <reg name="f27s2" bitsize="64" type="ieee_double"/>
+  <reg name="f28s2" bitsize="64" type="ieee_double"/>
+  <reg name="f29s2" bitsize="64" type="ieee_double"/>
+  <reg name="f30s2" bitsize="64" type="ieee_double"/>
+  <reg name="f31s2" bitsize="64" type="ieee_double"/>
+
+  <reg name="fcsrs2" bitsize="64" group="float"/>
+  <reg name="firs2" bitsize="64" group="float"/>
+</feature>
diff --git a/coregrind/m_gdbserver/mips64-fpu.xml b/coregrind/m_gdbserver/mips64-fpu.xml
new file mode 100644
index 0000000..e5a3915
--- /dev/null
+++ b/coregrind/m_gdbserver/mips64-fpu.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.fpu">
+  <reg name="f0" bitsize="64" type="ieee_double" regnum="38"/>
+  <reg name="f1" bitsize="64" type="ieee_double"/>
+  <reg name="f2" bitsize="64" type="ieee_double"/>
+  <reg name="f3" bitsize="64" type="ieee_double"/>
+  <reg name="f4" bitsize="64" type="ieee_double"/>
+  <reg name="f5" bitsize="64" type="ieee_double"/>
+  <reg name="f6" bitsize="64" type="ieee_double"/>
+  <reg name="f7" bitsize="64" type="ieee_double"/>
+  <reg name="f8" bitsize="64" type="ieee_double"/>
+  <reg name="f9" bitsize="64" type="ieee_double"/>
+  <reg name="f10" bitsize="64" type="ieee_double"/>
+  <reg name="f11" bitsize="64" type="ieee_double"/>
+  <reg name="f12" bitsize="64" type="ieee_double"/>
+  <reg name="f13" bitsize="64" type="ieee_double"/>
+  <reg name="f14" bitsize="64" type="ieee_double"/>
+  <reg name="f15" bitsize="64" type="ieee_double"/>
+  <reg name="f16" bitsize="64" type="ieee_double"/>
+  <reg name="f17" bitsize="64" type="ieee_double"/>
+  <reg name="f18" bitsize="64" type="ieee_double"/>
+  <reg name="f19" bitsize="64" type="ieee_double"/>
+  <reg name="f20" bitsize="64" type="ieee_double"/>
+  <reg name="f21" bitsize="64" type="ieee_double"/>
+  <reg name="f22" bitsize="64" type="ieee_double"/>
+  <reg name="f23" bitsize="64" type="ieee_double"/>
+  <reg name="f24" bitsize="64" type="ieee_double"/>
+  <reg name="f25" bitsize="64" type="ieee_double"/>
+  <reg name="f26" bitsize="64" type="ieee_double"/>
+  <reg name="f27" bitsize="64" type="ieee_double"/>
+  <reg name="f28" bitsize="64" type="ieee_double"/>
+  <reg name="f29" bitsize="64" type="ieee_double"/>
+  <reg name="f30" bitsize="64" type="ieee_double"/>
+  <reg name="f31" bitsize="64" type="ieee_double"/>
+
+  <reg name="fcsr" bitsize="64" group="float"/>
+  <reg name="fir" bitsize="64" group="float"/>
+</feature>
\ No newline at end of file
diff --git a/coregrind/m_gdbserver/mips64-linux-valgrind.xml b/coregrind/m_gdbserver/mips64-linux-valgrind.xml
new file mode 100644
index 0000000..baf6533
--- /dev/null
+++ b/coregrind/m_gdbserver/mips64-linux-valgrind.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <xi:include href="mips64-cpu.xml"/>
+  <xi:include href="mips64-cp0.xml"/>
+  <xi:include href="mips64-fpu.xml"/>
+  <xi:include href="mips64-cpu-valgrind-s1.xml"/>
+  <xi:include href="mips64-cp0-valgrind-s1.xml"/>
+  <xi:include href="mips64-fpu-valgrind-s1.xml"/>
+  <xi:include href="mips64-cpu-valgrind-s2.xml"/>
+  <xi:include href="mips64-cp0-valgrind-s2.xml"/>
+  <xi:include href="mips64-fpu-valgrind-s2.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="64" group="system"/>
+  </feature>
+</target>
diff --git a/coregrind/m_gdbserver/mips64-linux.xml b/coregrind/m_gdbserver/mips64-linux.xml
new file mode 100644
index 0000000..58d5a15
--- /dev/null
+++ b/coregrind/m_gdbserver/mips64-linux.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <xi:include href="mips64-cpu.xml"/>
+  <xi:include href="mips64-cp0.xml"/>
+  <xi:include href="mips64-fpu.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="64" group="system"/>
+  </feature>
+</target>
\ No newline at end of file
diff --git a/coregrind/m_gdbserver/target.c b/coregrind/m_gdbserver/target.c
index 7c95ecd..72cf242 100644
--- a/coregrind/m_gdbserver/target.c
+++ b/coregrind/m_gdbserver/target.c
@@ -649,6 +649,8 @@
    s390x_init_architecture(&the_low_target);
 #elif defined(VGA_mips32)
    mips32_init_architecture(&the_low_target);
+#elif defined(VGA_mips64)
+   mips64_init_architecture(&the_low_target);
 #else
    architecture missing in target.c valgrind_initialize_target
 #endif
diff --git a/coregrind/m_gdbserver/valgrind-low-mips64.c b/coregrind/m_gdbserver/valgrind-low-mips64.c
new file mode 100644
index 0000000..9c07336
--- /dev/null
+++ b/coregrind/m_gdbserver/valgrind-low-mips64.c
@@ -0,0 +1,259 @@
+/* Low level interface to valgrind, for the remote server for GDB integrated
+   in valgrind.
+   Copyright (C) 2011
+   Free Software Foundation, Inc.
+
+   This file is part of VALGRIND.
+   It has been inspired from a file from gdbserver in gdb 6.6.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include "server.h"
+#include "target.h"
+#include "regdef.h"
+#include "regcache.h"
+
+#include "pub_core_aspacemgr.h"
+#include "pub_tool_machine.h"
+#include "pub_core_threadstate.h"
+#include "pub_core_transtab.h"
+#include "pub_core_gdbserver.h" 
+
+#include "valgrind_low.h"
+
+#include "libvex_guest_mips64.h"
+
+static struct reg regs[] = {
+   { "r0", 0, 64 },
+   { "r1", 64, 64 },
+   { "r2", 128, 64 },
+   { "r3", 192, 64 },
+   { "r4", 256, 64 },
+   { "r5", 320, 64 },
+   { "r6", 384, 64 },
+   { "r7", 448, 64 },
+   { "r8", 512, 64 },
+   { "r9", 576, 64 },
+   { "r10", 640, 64 },
+   { "r11", 704, 64 },
+   { "r12", 768, 64 },
+   { "r13", 832, 64 },
+   { "r14", 896, 64 },
+   { "r15", 960, 64 },
+   { "r16", 1024, 64 },
+   { "r17", 1088, 64 },
+   { "r18", 1152, 64 },
+   { "r19", 1216, 64 },
+   { "r20", 1280, 64 },
+   { "r21", 1344, 64 },
+   { "r22", 1408, 64 },
+   { "r23", 1472, 64 },
+   { "r24", 1536, 64 },
+   { "r25", 1600, 64 },
+   { "r26", 1664, 64 },
+   { "r27", 1728, 64 },
+   { "r28", 1792, 64 },
+   { "r29", 1856, 64 },
+   { "r30", 1920, 64 },
+   { "r31", 1984, 64 },
+   { "status", 2048, 64 },
+   { "lo", 2112, 64 },
+   { "hi", 2176, 64 },
+   { "badvaddr", 2240, 64 },
+   { "cause", 2304, 64 },
+   { "pc", 2368, 64 },
+   { "f0", 2432, 64 },
+   { "f1", 2496, 64 },
+   { "f2", 2560, 64 },
+   { "f3", 2624, 64 },
+   { "f4", 2688, 64 },
+   { "f5", 2752, 64 },
+   { "f6", 2816, 64 },
+   { "f7", 2880, 64 },
+   { "f8", 2944, 64 },
+   { "f9", 3008, 64 },
+   { "f10", 3072, 64 },
+   { "f11", 3136, 64 },
+   { "f12", 3200, 64 },
+   { "f13", 3264, 64 },
+   { "f14", 3328, 64 },
+   { "f15", 3392, 64 },
+   { "f16", 3456, 64 },
+   { "f17", 3520, 64 },
+   { "f18", 3584, 64 },
+   { "f19", 3648, 64 },
+   { "f20", 3712, 64 },
+   { "f21", 3776, 64 },
+   { "f22", 3840, 64 },
+   { "f23", 3904, 64 },
+   { "f24", 3968, 64 },
+   { "f25", 4032, 64 },
+   { "f26", 4096, 64 },
+   { "f27", 4160, 64 },
+   { "f28", 4224, 64 },
+   { "f29", 4288, 64 },
+   { "f30", 4352, 64 },
+   { "f31", 4416, 64 },
+   { "fcsr", 4480, 64 },
+   { "fir", 4544, 64 },
+   { "restart", 4608, 64 }
+};
+
+
+#define num_regs (sizeof (regs) / sizeof (regs[0]))
+
+static const char *expedite_regs[] = { "r29", "pc", 0 };
+
+static
+CORE_ADDR get_pc (void)
+{
+   unsigned long pc;
+
+   collect_register_by_name ("pc", &pc);
+
+   dlog(1, "stop pc is %p\n", (void *) pc);
+   return pc;
+}
+
+static
+void set_pc (CORE_ADDR newpc)
+{
+   Bool mod;
+   supply_register_by_name ("pc", &newpc, &mod);
+   if (mod)
+      dlog(1, "set pc to %p\n", C2v (newpc));
+   else
+      dlog(1, "set pc not changed %p\n", C2v (newpc));
+}
+
+/* store registers in the guest state (gdbserver_to_valgrind)
+   or fetch register from the guest state (valgrind_to_gdbserver). */
+static
+void transfer_register (ThreadId tid, int abs_regno, void * buf,
+                        transfer_direction dir, int size, Bool *mod)
+{
+   ThreadState* tst = VG_(get_ThreadState)(tid);
+   int set = abs_regno / num_regs;
+   int regno = abs_regno % num_regs;
+   *mod = False;
+
+   VexGuestMIPS64State* mips1 = (VexGuestMIPS64State*) get_arch (set, tst);
+
+   switch (regno) { 
+   case 0:  VG_(transfer) (&mips1->guest_r0,  buf, dir, size, mod); break;
+   case 1:  VG_(transfer) (&mips1->guest_r1,  buf, dir, size, mod); break;
+   case 2:  VG_(transfer) (&mips1->guest_r2,  buf, dir, size, mod); break;
+   case 3:  VG_(transfer) (&mips1->guest_r3,  buf, dir, size, mod); break;
+   case 4:  VG_(transfer) (&mips1->guest_r4,  buf, dir, size, mod); break;
+   case 5:  VG_(transfer) (&mips1->guest_r5,  buf, dir, size, mod); break;
+   case 6:  VG_(transfer) (&mips1->guest_r6,  buf, dir, size, mod); break;
+   case 7:  VG_(transfer) (&mips1->guest_r7,  buf, dir, size, mod); break;
+   case 8:  VG_(transfer) (&mips1->guest_r8,  buf, dir, size, mod); break;
+   case 9:  VG_(transfer) (&mips1->guest_r9,  buf, dir, size, mod); break;
+   case 10: VG_(transfer) (&mips1->guest_r10,  buf, dir, size, mod); break;
+   case 11: VG_(transfer) (&mips1->guest_r11,  buf, dir, size, mod); break;
+   case 12: VG_(transfer) (&mips1->guest_r12, buf, dir, size, mod); break;
+   case 13: VG_(transfer) (&mips1->guest_r13, buf, dir, size, mod); break;
+   case 14: VG_(transfer) (&mips1->guest_r14, buf, dir, size, mod); break;
+   case 15: VG_(transfer) (&mips1->guest_r15, buf, dir, size, mod); break;
+   case 16: VG_(transfer) (&mips1->guest_r16, buf, dir, size, mod); break;
+   case 17: VG_(transfer) (&mips1->guest_r17, buf, dir, size, mod); break;
+   case 18: VG_(transfer) (&mips1->guest_r18,  buf, dir, size, mod); break;
+   case 19: VG_(transfer) (&mips1->guest_r19,  buf, dir, size, mod); break;
+   case 20: VG_(transfer) (&mips1->guest_r20,  buf, dir, size, mod); break;
+   case 21: VG_(transfer) (&mips1->guest_r21,  buf, dir, size, mod); break;
+   case 22: VG_(transfer) (&mips1->guest_r22,  buf, dir, size, mod); break;
+   case 23: VG_(transfer) (&mips1->guest_r23,  buf, dir, size, mod); break;
+   case 24: VG_(transfer) (&mips1->guest_r24,  buf, dir, size, mod); break;
+   case 25: VG_(transfer) (&mips1->guest_r25,  buf, dir, size, mod); break;
+   case 26: VG_(transfer) (&mips1->guest_r26,  buf, dir, size, mod); break;
+   case 27: VG_(transfer) (&mips1->guest_r27,  buf, dir, size, mod); break;
+   case 28: VG_(transfer) (&mips1->guest_r28, buf, dir, size, mod); break;
+   case 29: VG_(transfer) (&mips1->guest_r29, buf, dir, size, mod); break;
+   case 30: VG_(transfer) (&mips1->guest_r30, buf, dir, size, mod); break;
+   case 31: VG_(transfer) (&mips1->guest_r31, buf, dir, size, mod); break;
+   case 32: *mod = False; break; // GDBTD???? VEX { "status", 1024, 64 }
+   case 33: VG_(transfer) (&mips1->guest_LO, buf, dir, size, mod); break;
+   case 34: VG_(transfer) (&mips1->guest_HI, buf, dir, size, mod); break;
+   case 35: *mod = False; break; // GDBTD???? VEX { "badvaddr", 1120, 64 },
+   case 36: *mod = False; break; // GDBTD???? VEX { "cause", 1152, 64 },
+   case 37: VG_(transfer) (&mips1->guest_PC,  buf, dir, size, mod); break;
+   case 38: VG_(transfer) (&mips1->guest_f0,  buf, dir, size, mod); break;
+   case 39: VG_(transfer) (&mips1->guest_f1,  buf, dir, size, mod); break;
+   case 40: VG_(transfer) (&mips1->guest_f2,  buf, dir, size, mod); break;
+   case 41: VG_(transfer) (&mips1->guest_f3,  buf, dir, size, mod); break;
+   case 42: VG_(transfer) (&mips1->guest_f4,  buf, dir, size, mod); break;
+   case 43: VG_(transfer) (&mips1->guest_f5,  buf, dir, size, mod); break;
+   case 44: VG_(transfer) (&mips1->guest_f6,  buf, dir, size, mod); break;
+   case 45: VG_(transfer) (&mips1->guest_f7, buf, dir, size, mod); break;
+   case 46: VG_(transfer) (&mips1->guest_f8, buf, dir, size, mod); break;
+   case 47: VG_(transfer) (&mips1->guest_f9, buf, dir, size, mod); break;
+   case 48: VG_(transfer) (&mips1->guest_f10, buf, dir, size, mod); break;
+   case 49: VG_(transfer) (&mips1->guest_f11, buf, dir, size, mod); break;
+   case 50: VG_(transfer) (&mips1->guest_f12, buf, dir, size, mod); break;
+   case 51: VG_(transfer) (&mips1->guest_f13,  buf, dir, size, mod); break;
+   case 52: VG_(transfer) (&mips1->guest_f14,  buf, dir, size, mod); break;
+   case 53: VG_(transfer) (&mips1->guest_f15,  buf, dir, size, mod); break;
+   case 54: VG_(transfer) (&mips1->guest_f16,  buf, dir, size, mod); break;
+   case 55: VG_(transfer) (&mips1->guest_f17,  buf, dir, size, mod); break;
+   case 56: VG_(transfer) (&mips1->guest_f18,  buf, dir, size, mod); break;
+   case 57: VG_(transfer) (&mips1->guest_f19, buf, dir, size, mod); break;
+   case 58: VG_(transfer) (&mips1->guest_f20, buf, dir, size, mod); break;
+   case 59: VG_(transfer) (&mips1->guest_f21, buf, dir, size, mod); break;
+   case 60: VG_(transfer) (&mips1->guest_f22, buf, dir, size, mod); break;
+   case 61: VG_(transfer) (&mips1->guest_f23, buf, dir, size, mod); break;
+   case 62: VG_(transfer) (&mips1->guest_f24,  buf, dir, size, mod); break;
+   case 63: VG_(transfer) (&mips1->guest_f25,  buf, dir, size, mod); break;
+   case 64: VG_(transfer) (&mips1->guest_f26,  buf, dir, size, mod); break;
+   case 65: VG_(transfer) (&mips1->guest_f27,  buf, dir, size, mod); break;
+   case 66: VG_(transfer) (&mips1->guest_f28,  buf, dir, size, mod); break;
+   case 67: VG_(transfer) (&mips1->guest_f29,  buf, dir, size, mod); break;
+   case 68: VG_(transfer) (&mips1->guest_f30, buf, dir, size, mod); break;
+   case 69: VG_(transfer) (&mips1->guest_f31, buf, dir, size, mod); break;
+   case 70: VG_(transfer) (&mips1->guest_FCSR, buf, dir, size, mod); break;
+   case 71: VG_(transfer) (&mips1->guest_FIR, buf, dir, size, mod); break;
+   case 72: *mod = False; break; // GDBTD???? VEX{ "restart", 2304, 64 },
+   default: VG_(printf)("regno: %d\n", regno); vg_assert(0);
+   }
+}
+
+static
+const char* target_xml (Bool shadow_mode)
+{
+   if (shadow_mode) {
+      return "mips64-linux-valgrind.xml";
+   } else {
+      return "mips64-linux.xml";
+   }  
+}
+
+static struct valgrind_target_ops low_target = {
+   num_regs,
+   regs,
+   29, //sp = r29, which is register offset 29 in regs
+   transfer_register,
+   get_pc,
+   set_pc,
+   "mips64",
+   target_xml
+};
+
+void mips64_init_architecture (struct valgrind_target_ops *target)
+{
+   *target = low_target;
+   set_register_cache (regs, num_regs);
+   gdbserver_expedite_regs = expedite_regs;
+}
diff --git a/coregrind/m_gdbserver/valgrind_low.h b/coregrind/m_gdbserver/valgrind_low.h
index 3ff6d19..c8d53cb 100644
--- a/coregrind/m_gdbserver/valgrind_low.h
+++ b/coregrind/m_gdbserver/valgrind_low.h
@@ -74,5 +74,6 @@
 extern void ppc64_init_architecture (struct valgrind_target_ops *target);
 extern void s390x_init_architecture (struct valgrind_target_ops *target);
 extern void mips32_init_architecture (struct valgrind_target_ops *target);
+extern void mips64_init_architecture (struct valgrind_target_ops *target);
 
 #endif
diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c
index 1510f8c..f9a68a6 100644
--- a/coregrind/m_initimg/initimg-linux.c
+++ b/coregrind/m_initimg/initimg-linux.c
@@ -1110,6 +1110,20 @@
    arch->vex.guest_PC = iifii.initial_client_IP;
    arch->vex.guest_r31 = iifii.initial_client_SP;
 
+#   elif defined(VGP_mips64_linux)
+   vg_assert(0 == sizeof(VexGuestMIPS64State) % 16);
+   /* Zero out the initial state, and set up the simulated FPU in a
+      sane way. */
+   LibVEX_GuestMIPS64_initialise(&arch->vex);
+
+   /* Zero out the shadow areas. */
+   VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestMIPS64State));
+   VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestMIPS64State));
+
+   arch->vex.guest_r29 = iifii.initial_client_SP;
+   arch->vex.guest_PC = iifii.initial_client_IP;
+   arch->vex.guest_r31 = iifii.initial_client_SP;
+
 #  else
 #    error Unknown platform
 #  endif
diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c
index c38fe84..c8efdde 100644
--- a/coregrind/m_libcassert.c
+++ b/coregrind/m_libcassert.c
@@ -177,6 +177,31 @@
         (srP)->misc.MIPS32.r31 = (ULong)ra;               \
         (srP)->misc.MIPS32.r28 = (ULong)gp;               \
       }
+#elif defined(VGP_mips64_linux)
+#  define GET_STARTREGS(srP)                              \
+      { ULong pc, sp, fp, ra, gp;                          \
+      asm("move $8, $31;"             /* t0 = ra */       \
+          "bal m_libcassert_get_ip;"  /* ra = pc */       \
+          "m_libcassert_get_ip:\n"                        \
+          "move %0, $31;"                                 \
+          "move $31, $8;"             /* restore lr */    \
+          "move %1, $29;"                                 \
+          "move %2, $30;"                                 \
+          "move %3, $31;"                                 \
+          "move %4, $28;"                                 \
+          : "=r" (pc),                                    \
+            "=r" (sp),                                    \
+            "=r" (fp),                                    \
+            "=r" (ra),                                    \
+            "=r" (gp)                                     \
+          : /* reads none */                              \
+          : "$8" /* trashed */ );                         \
+        (srP)->r_pc = (ULong)pc - 8;                      \
+        (srP)->r_sp = (ULong)sp;                          \
+        (srP)->misc.MIPS64.r30 = (ULong)fp;               \
+        (srP)->misc.MIPS64.r31 = (ULong)ra;               \
+        (srP)->misc.MIPS64.r28 = (ULong)gp;               \
+      }
 #else
 #  error Unknown platform
 #endif
diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c
index 2e8ebca..3364abc 100644
--- a/coregrind/m_libcfile.c
+++ b/coregrind/m_libcfile.c
@@ -194,9 +194,9 @@
 
 Int VG_(pipe) ( Int fd[2] )
 {
-#  if defined(VGP_mips32_linux)
+#  if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
    /* __NR_pipe has a strange return convention on mips32-linux. */
-   SysRes res = VG_(do_syscall0)(__NR_pipe);
+   SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
    if (!sr_isError(res)) {
       fd[0] = (Int)sr_Res(res);
       fd[1] = (Int)sr_ResEx(res);
@@ -612,18 +612,19 @@
                           0, // Padding needed on PPC32
                           0, offset); // Big endian long long
    return res;
-#  elif defined(VGP_mips32_linux) && VKI_LITTLE_ENDIAN
+#  elif defined(VGP_mips32_linux) && (VKI_LITTLE_ENDIAN)
    vg_assert(sizeof(OffT) == 4);
    res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count, 
                           0, offset, 0);
    return res;
-#  elif defined(VGP_mips32_linux) && VKI_BIG_ENDIAN
+#  elif defined(VGP_mips32_linux) && (VKI_BIG_ENDIAN)
    vg_assert(sizeof(OffT) == 4);
    res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count, 
                           0, 0, offset);
    return res;
 #  elif defined(VGP_amd64_linux) \
-      || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) 
+      || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \
+      || defined(VGP_mips64_linux) 
    res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
    return res;
 #  elif defined(VGP_amd64_darwin)
@@ -864,7 +865,7 @@
    return sr_isError(res) ? -1 : sr_Res(res);
 
 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
-        || defined(VGP_mips32_linux)
+        || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
    SysRes res;
    res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
    return sr_isError(res) ? -1 : sr_Res(res);
@@ -903,7 +904,7 @@
    return sr_isError(res) ? -1 : sr_Res(res);
 
 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
-        || defined(VGP_mips32_linux)
+        || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
    SysRes res;
    res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
    return sr_isError(res) ? -1 : sr_Res(res);
@@ -942,7 +943,7 @@
    return sr_isError(res) ? -1 : sr_Res(res);
 
 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
-        || defined(VGP_mips32_linux)
+        || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
    SysRes res;
    res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, 
                                        count, VKI_MSG_NOSIGNAL, 0,0);
@@ -971,7 +972,8 @@
    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
    return sr_isError(res) ? -1 : sr_Res(res);
 
-#  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
+#  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+        || defined(VGP_mips64_linux)
    SysRes res;
    res = VG_(do_syscall3)( __NR_getsockname,
                            (UWord)sd, (UWord)name, (UWord)namelen );
@@ -1001,7 +1003,8 @@
    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
    return sr_isError(res) ? -1 : sr_Res(res);
 
-#  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
+#  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+        || defined(VGP_mips64_linux)
    SysRes res;
    res = VG_(do_syscall3)( __NR_getpeername,
                            (UWord)sd, (UWord)name, (UWord)namelen );
@@ -1034,7 +1037,7 @@
    return sr_isError(res) ? -1 : sr_Res(res);
 
 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
-        || defined(VGP_mips32_linux)
+        || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
    SysRes res;
    res = VG_(do_syscall5)( __NR_getsockopt,
                            (UWord)sd, (UWord)level, (UWord)optname, 
diff --git a/coregrind/m_libcproc.c b/coregrind/m_libcproc.c
index 6832869..045a378 100644
--- a/coregrind/m_libcproc.c
+++ b/coregrind/m_libcproc.c
@@ -533,7 +533,8 @@
    platform. */
 Int VG_(getgroups)( Int size, UInt* list )
 {
-#  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
+#  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
+      || defined(VGP_mips64_linux)
    Int    i;
    SysRes sres;
    UShort list16[64];
@@ -762,7 +763,7 @@
    Addr endaddr   = startaddr + nbytes;
    VG_(do_syscall2)(__NR_ARM_cacheflush, startaddr, endaddr);
 
-#  elif defined(VGA_mips32)
+#  elif defined(VGA_mips32) || defined(VGA_mips64)
    SysRes sres = VG_(do_syscall3)(__NR_cacheflush, (UWord) ptr,
                                  (UWord) nbytes, (UWord) 3);
    vg_assert( sres._isError == 0 );
diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c
index bbbea7e..b40cb28 100644
--- a/coregrind/m_machine.c
+++ b/coregrind/m_machine.c
@@ -113,6 +113,15 @@
       = VG_(threads)[tid].arch.vex.guest_r31;
    regs->misc.MIPS32.r28
       = VG_(threads)[tid].arch.vex.guest_r28;
+#  elif defined(VGA_mips64)
+   regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC;
+   regs->r_sp = VG_(threads)[tid].arch.vex.guest_r29;
+   regs->misc.MIPS64.r30
+      = VG_(threads)[tid].arch.vex.guest_r30;
+   regs->misc.MIPS64.r31
+      = VG_(threads)[tid].arch.vex.guest_r31;
+   regs->misc.MIPS64.r28
+      = VG_(threads)[tid].arch.vex.guest_r28;
 #  else
 #    error "Unknown arch"
 #  endif
@@ -142,7 +151,7 @@
 #  elif defined(VGP_s390x_linux)
    VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
    VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
-#  elif defined(VGP_mips32_linux)
+#  elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
    VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
    VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
 #  else
@@ -296,7 +305,7 @@
    (*f)(tid, "r13", vex->guest_r13);
    (*f)(tid, "r14", vex->guest_r14);
    (*f)(tid, "r15", vex->guest_r15);
-#elif defined(VGA_mips32)
+#elif defined(VGA_mips32) || defined(VGA_mips64)
    (*f)(tid, "r0" , vex->guest_r0 );
    (*f)(tid, "r1" , vex->guest_r1 );
    (*f)(tid, "r2" , vex->guest_r2 );
@@ -615,13 +624,14 @@
 
 #endif /* VGA_s390x */
 
-#ifdef VGA_mips32
+#if defined(VGA_mips32) || defined(VGA_mips64)
 
 /* Read /proc/cpuinfo and return the machine model. */
 static UInt VG_(get_machine_model)(void)
 {
-   char *search_MIPS_str = "MIPS";
-   char *search_Broadcom_str = "Broadcom";
+   const char *search_MIPS_str = "MIPS";
+   const char *search_Broadcom_str = "Broadcom";
+   const char *search_Netlogic_str = "Netlogic";
    Int    n, fh;
    SysRes fd;
    SizeT  num_bytes, file_buf_size;
@@ -664,6 +674,8 @@
    /* Parse file */
    if (VG_(strstr) (file_buf, search_Broadcom_str) != NULL)
        return VEX_PRID_COMP_BROADCOM;
+   if (VG_(strstr) (file_buf, search_Netlogic_str) != NULL)
+       return VEX_PRID_COMP_NETLOGIC;
    if (VG_(strstr) (file_buf, search_MIPS_str) != NULL)
        return VEX_PRID_COMP_MIPS;
 
@@ -1377,6 +1389,20 @@
      return True;
    }
 
+#elif defined(VGA_mips64)
+   {
+     va = VexArchMIPS64;
+     UInt model = VG_(get_machine_model)();
+     if (model== -1)
+         return False;
+
+     vai.hwcaps = model;
+
+     VG_(machine_get_cache_info)(&vai);
+
+     return True;
+   }
+
 #else
 #  error "Unknown arch"
 #endif
@@ -1503,6 +1529,9 @@
       it? */
    return 8;
 
+#  elif defined(VGA_mips64)
+   return 8;
+
 #  else
 #    error "Unknown arch"
 #  endif
@@ -1516,7 +1545,8 @@
 #  if defined(VGP_x86_linux) || defined(VGP_amd64_linux)  \
       || defined(VGP_arm_linux)                           \
       || defined(VGP_ppc32_linux) || defined(VGO_darwin)  \
-      || defined(VGP_s390x_linux) || defined(VGP_mips32_linux)
+      || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \
+      || defined(VGP_mips64_linux)
    return f;
 #  elif defined(VGP_ppc64_linux)
    /* ppc64-linux uses the AIX scheme, in which f is a pointer to a
diff --git a/coregrind/m_main.c b/coregrind/m_main.c
index e0df961..fe87466 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -2008,7 +2008,7 @@
       iters = 5;
 #     elif defined(VGP_s390x_linux)
       iters = 10;
-#     elif defined(VGP_mips32_linux)
+#     elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
       iters = 10;
 #     elif defined(VGO_darwin)
       iters = 3;
@@ -2591,7 +2591,7 @@
    VG_(threads)[tid].arch.vex.guest_GPR2 = r2;
 #  endif
    /* mips-linux note: we need to set t9 */
-#  if defined(VGP_mips32_linux)
+#  if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
    VG_(threads)[tid].arch.vex.guest_r25 = __libc_freeres_wrapper;
 #  endif
 
@@ -2937,6 +2937,45 @@
     "\tbreak  0x7\n"
     ".previous\n"
 );
+#elif defined(VGP_mips64_linux)
+asm(
+".text\n"
+".globl __start\n"
+".type __start,@function\n"
+"__start:\n"
+    "\t.set noreorder\n"
+    "\t.cpload $25\n"
+    "\t.set reorder\n"
+    "\t.cprestore 16\n"
+    "\tlui    $9, %hi(vgPlain_interim_stack)\n"
+    /* t1/$9 <- Addr(interim_stack) */
+    "\tdaddiu $9, %lo(vgPlain_interim_stack)\n"
+
+    "\tli     $10, "VG_STRINGIFY(VG_STACK_GUARD_SZB)"\n"
+    "\tli     $11, "VG_STRINGIFY(VG_STACK_ACTIVE_SZB)"\n"
+
+    "\tdaddu  $9, $9, $10\n"
+    "\tdaddu  $9, $9, $11\n"
+    "\tli     $12, 0xFFFFFF00\n"
+    "\tand    $9, $9, $12\n"
+    /* now t1/$9 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
+       VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
+       boundary.  And $29 is the original SP.  Set the SP to t1 and
+       call _start_in_C, passing it the initial SP. */
+
+    "\tmove   $4, $29\n"     // a0 <- $sp (_start_in_C first arg)
+    "\tmove   $29, $9\n"     // $sp <- t1 (new sp)
+
+    "\tlui    $9, %highest(_start_in_C_linux)\n"
+    "\tori    $9, %higher(_start_in_C_linux)\n"
+    "\tdsll32 $9, $9, 0x0\n"
+    "\tlui    $10, %hi(_start_in_C_linux)\n"
+    "\tdaddiu $10, %lo(_start_in_C_linux)\n"
+    "\tdaddu  $25, $9, $10\n"
+    "\tjalr   $25\n"
+    "\tnop\n"
+".end __start\n"
+);
 #else
 #  error "Unknown linux platform"
 #endif
diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c
index 40f6980..df9246b 100644
--- a/coregrind/m_redir.c
+++ b/coregrind/m_redir.c
@@ -1369,6 +1369,17 @@
       );
    }
 
+#  elif defined(VGP_mips64_linux)
+   if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
+
+      /* this is mandatory - can't sanely continue without it */
+      add_hardwired_spec(
+         "ld.so.3", "strlen",
+         (Addr)&VG_(mips64_linux_REDIR_FOR_strlen),
+         complain_about_stripped_glibc_ldso
+      );
+   }
+
 #  else
 #    error Unknown platform
 #  endif
diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c
index ebe6eb4..1e5a8c1 100644
--- a/coregrind/m_scheduler/scheduler.c
+++ b/coregrind/m_scheduler/scheduler.c
@@ -790,7 +790,7 @@
    /* no special requirements */
 #  endif
 
-#  if defined(VGA_mips32)
+#  if defined(VGA_mips32) || defined(VGA_mips64)
   /* no special requirements */
 #  endif
 }
@@ -1597,7 +1597,7 @@
 #elif defined (VGA_s390x)
 #  define VG_CLREQ_ARGS       guest_r2
 #  define VG_CLREQ_RET        guest_r3
-#elif defined(VGA_mips32)
+#elif defined(VGA_mips32) || defined(VGA_mips64)
 #  define VG_CLREQ_ARGS       guest_r12
 #  define VG_CLREQ_RET        guest_r11
 #else
diff --git a/coregrind/m_sigframe/sigframe-mips32-linux.c b/coregrind/m_sigframe/sigframe-mips32-linux.c
index c711a6a..e0220be 100644
--- a/coregrind/m_sigframe/sigframe-mips32-linux.c
+++ b/coregrind/m_sigframe/sigframe-mips32-linux.c
@@ -116,7 +116,8 @@
 }
 
 static 
-void setup_sigcontext2 ( ThreadState* tst, struct vki_sigcontext **sc1, const vki_siginfo_t *si)
+void setup_sigcontext2 ( ThreadState* tst, struct vki_sigcontext **sc1,
+                         const vki_siginfo_t *si)
 {
 
   struct vki_sigcontext *sc = *sc1;
@@ -171,7 +172,6 @@
 {
   Addr sp;
   ThreadState* tst = VG_(get_ThreadState)(tid);
-  Addr faultaddr;
   Int sigNo = siginfo->si_signo;
   struct vg_sig_private *priv;
 
@@ -192,12 +192,6 @@
     return;
 
   vg_assert(VG_IS_8_ALIGNED(sp));
-
-  /* SIGILL defines addr to be the faulting address */
-
-  faultaddr = (Addr)siginfo->_sifields._sigfault._addr;
-  if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
-    faultaddr = tst->arch.vex.guest_PC;
       
   if (flags & VKI_SA_SIGINFO)
     {
diff --git a/coregrind/m_sigframe/sigframe-mips64-linux.c b/coregrind/m_sigframe/sigframe-mips64-linux.c
new file mode 100644
index 0000000..fc8e613
--- /dev/null
+++ b/coregrind/m_sigframe/sigframe-mips64-linux.c
@@ -0,0 +1,317 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Create/destroy signal delivery frames.                       ---*/
+/*---                                  sigframe-mips64-linux.c     ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2010-2013 RT-RK 
+      mips-valgrind@rt-rk.com 
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#if defined(VGP_mips64_linux)
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
+#include "pub_core_libcsetjmp.h"  /* to keep _threadstate.h happy */
+#include "pub_core_threadstate.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_machine.h"
+#include "pub_core_options.h"
+#include "pub_core_sigframe.h"
+#include "pub_core_signals.h"
+#include "pub_core_tooliface.h"
+#include "pub_core_trampoline.h"
+#include "pub_core_transtab.h"  /* VG_(discard_translations) */
+
+struct vg_sig_private {
+   UInt magicPI;
+   UInt sigNo_private;
+   VexGuestMIPS64State vex_shadow1;
+   VexGuestMIPS64State vex_shadow2;
+};
+
+struct sigframe {
+   UInt sf_ass[4];  /* argument save space for o32 */
+   UInt sf_pad[2];  /* Was: signal trampoline */
+   struct vki_sigcontext sf_sc;
+   vki_sigset_t sf_mask;
+   struct vg_sig_private priv;
+};
+
+struct rt_sigframe {
+   UInt rs_ass[4];  /* argument save space for o32 */
+   UInt rs_pad[2];  /* Was: signal trampoline */
+   vki_siginfo_t rs_info;
+   struct vki_ucontext rs_uc;
+   struct vg_sig_private priv;
+};
+
+/* Extend the stack segment downwards if needed so as to ensure the new signal
+   frames are mapped to something. Return a Bool indicating whether or not the
+   operation was successful.
+*/
+static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
+{
+   ThreadId tid = tst->tid;
+   NSegment const* stackseg = NULL;
+
+   if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
+      stackseg = VG_(am_find_nsegment)(addr);
+   }
+
+   if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
+      VG_(message)(Vg_UserMsg,
+         "Can't extend stack to %#lx during signal delivery for thread %d:\n",
+         addr, tid);
+      if (stackseg == NULL)
+         VG_(message)(Vg_UserMsg, " no stack segment\n");
+      else
+         VG_(message)(Vg_UserMsg, " too small or bad protection modes\n");
+
+      /* set SIGSEGV to default handler */
+      VG_(set_default_handler)(VKI_SIGSEGV);
+      VG_(synth_fault_mapping)(tid, addr);
+
+      /* The whole process should be about to die, since the default
+         action of SIGSEGV to kill the whole process. */
+      return False;
+   }
+
+   /* For tracking memory events, indicate the entire frame has been
+      allocated. */
+   VG_TRACK(new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
+            size + VG_STACK_REDZONE_SZB, tid);
+
+   return True;
+}
+
+static void setup_sigcontext ( ThreadState* tst, struct vki_sigcontext **sc1,
+                               const vki_siginfo_t *si)
+{
+   struct vki_sigcontext *sc = *sc1;
+
+   VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
+            (Addr)sc, sizeof(unsigned long long)*34);
+   sc->sc_regs[1] = tst->arch.vex.guest_r1;
+   sc->sc_regs[2] = tst->arch.vex.guest_r2;
+   sc->sc_regs[3] = tst->arch.vex.guest_r3;
+   sc->sc_regs[4] = tst->arch.vex.guest_r4;
+   sc->sc_regs[5] = tst->arch.vex.guest_r5;
+   sc->sc_regs[6] = tst->arch.vex.guest_r6;
+   sc->sc_regs[7] = tst->arch.vex.guest_r7;
+   sc->sc_regs[8] = tst->arch.vex.guest_r8;
+   sc->sc_regs[9] = tst->arch.vex.guest_r9;
+   sc->sc_regs[10] = tst->arch.vex.guest_r10;
+   sc->sc_regs[11] = tst->arch.vex.guest_r11;
+   sc->sc_regs[12] = tst->arch.vex.guest_r12;
+   sc->sc_regs[13] = tst->arch.vex.guest_r13;
+   sc->sc_regs[14] = tst->arch.vex.guest_r14;
+   sc->sc_regs[15] = tst->arch.vex.guest_r15;
+   sc->sc_regs[16] = tst->arch.vex.guest_r16;
+   sc->sc_regs[17] = tst->arch.vex.guest_r17;
+   sc->sc_regs[18] = tst->arch.vex.guest_r18;
+   sc->sc_regs[19] = tst->arch.vex.guest_r19;
+   sc->sc_regs[20] = tst->arch.vex.guest_r20;
+   sc->sc_regs[21] = tst->arch.vex.guest_r21;
+   sc->sc_regs[22] = tst->arch.vex.guest_r22;
+   sc->sc_regs[23] = tst->arch.vex.guest_r23;
+   sc->sc_regs[24] = tst->arch.vex.guest_r24;
+   sc->sc_regs[25] = tst->arch.vex.guest_r25;
+   sc->sc_regs[26] = tst->arch.vex.guest_r26;
+   sc->sc_regs[27] = tst->arch.vex.guest_r27;
+   sc->sc_regs[28] = tst->arch.vex.guest_r28;
+   sc->sc_regs[29] = tst->arch.vex.guest_r29;
+   sc->sc_regs[30] = tst->arch.vex.guest_r30;
+   sc->sc_regs[31] = tst->arch.vex.guest_r31;
+   sc->sc_pc = tst->arch.vex.guest_PC;
+   sc->sc_mdhi = tst->arch.vex.guest_HI;
+   sc->sc_mdlo = tst->arch.vex.guest_LO;
+}
+
+/* EXPORTED */
+void VG_(sigframe_create) ( ThreadId tid,
+                            Addr sp_top_of_frame,
+                            const vki_siginfo_t *siginfo,
+                            const struct vki_ucontext *siguc,
+                            void *handler,
+                            UInt flags,
+                            const vki_sigset_t *mask,
+                            void *restorer )
+{
+   Addr sp;
+   ThreadState* tst = VG_(get_ThreadState)(tid);
+   Int sigNo = siginfo->si_signo;
+   struct vg_sig_private *priv;
+   /* Stack must be 16-byte aligned */
+   sp_top_of_frame &= ~0xf;
+
+   sp = sp_top_of_frame - sizeof(struct rt_sigframe);
+
+   tst = VG_(get_ThreadState)(tid);
+   if (!extend(tst, sp, sp_top_of_frame - sp))
+      return;
+
+   sp = VG_ROUNDDN(sp, 16);
+
+   struct rt_sigframe *frame = (struct rt_sigframe *)sp;
+   struct vki_ucontext *ucp = &frame->rs_uc;
+   if (VG_(clo_trace_signals))
+      VG_(printf)("rt_sigframe\n");
+   /* Create siginfo. */
+   VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo",
+            (Addr)&frame->rs_info, sizeof(frame->rs_info));
+
+   VG_(memcpy)(&frame->rs_info, siginfo, sizeof(*siginfo));
+
+   VG_TRACK(post_mem_write, Vg_CoreSignal, tid,
+            (Addr)&frame->rs_info, sizeof(frame->rs_info));
+
+   /* Create the ucontext. */
+   VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
+            (Addr)ucp, offsetof(struct vki_ucontext, uc_mcontext));
+
+   ucp->uc_flags = 0;
+   ucp->uc_link = 0;
+   ucp->uc_stack = tst->altstack;
+
+   VG_TRACK(post_mem_write, Vg_CoreSignal, tid, (Addr)ucp,
+            offsetof(struct vki_ucontext, uc_mcontext));
+
+   struct vki_sigcontext *scp = &(frame->rs_uc.uc_mcontext);
+   setup_sigcontext(tst, &(scp), siginfo);
+   ucp->uc_sigmask = tst->sig_mask;
+   priv = &frame->priv;
+
+   /* Arguments to signal handler:
+
+      a0 = signal number
+      a1 = 0 (should be cause)
+      a2 = pointer to ucontext
+
+      $25 and c0_epc point to the signal handler, $29 points to
+      the struct rt_sigframe. */
+
+   tst->arch.vex.guest_r4 = siginfo->si_signo;
+   tst->arch.vex.guest_r5 = (Addr) &frame->rs_info;
+   tst->arch.vex.guest_r6 = (Addr) &frame->rs_uc;
+   tst->arch.vex.guest_r29 = (Addr) frame;
+   tst->arch.vex.guest_r25 = (Addr) handler;
+
+   if (flags & VKI_SA_RESTORER) 
+      tst->arch.vex.guest_r31 = (Addr) restorer;
+   else 
+      tst->arch.vex.guest_r31 = (Addr)&VG_(mips64_linux_SUBST_FOR_rt_sigreturn);
+
+   priv->magicPI       = 0x31415927;
+   priv->sigNo_private = sigNo;
+   priv->vex_shadow1   = tst->arch.vex_shadow1;
+   priv->vex_shadow2   = tst->arch.vex_shadow2;
+   /* Set the thread so it will next run the handler. */
+   VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
+   if (VG_(clo_trace_signals))
+      VG_(printf)("handler = %p\n", handler);
+   tst->arch.vex.guest_PC = (Addr) handler;
+   /* This thread needs to be marked runnable, but we leave that
+      the caller to do. */
+}
+
+/* EXPORTED */
+void VG_(sigframe_destroy) ( ThreadId tid, Bool isRT )
+{
+   ThreadState *tst;
+   struct vg_sig_private *priv1;
+   Addr sp;
+   UInt frame_size;
+   struct vki_sigcontext *mc;
+   Int sigNo;
+
+   vg_assert(VG_(is_valid_tid)(tid));
+   tst = VG_(get_ThreadState)(tid);
+   sp   = tst->arch.vex.guest_r29;
+   struct rt_sigframe *frame = (struct rt_sigframe *)sp;
+   struct vki_ucontext *ucp = &frame->rs_uc;
+   frame_size = sizeof(*frame);
+   mc = &ucp->uc_mcontext;
+   tst->sig_mask = ucp->uc_sigmask;
+   tst->tmp_sig_mask = ucp->uc_sigmask;
+   priv1 = &frame->priv;
+   sigNo = priv1->sigNo_private;
+   vg_assert(priv1->magicPI == 0x31415927);
+   /* restore regs */
+   tst->arch.vex.guest_r1 = mc->sc_regs[1];
+   tst->arch.vex.guest_r2 = mc->sc_regs[2];
+   tst->arch.vex.guest_r3 = mc->sc_regs[3];
+   tst->arch.vex.guest_r4 = mc->sc_regs[4];
+   tst->arch.vex.guest_r5 = mc->sc_regs[5];
+   tst->arch.vex.guest_r6 = mc->sc_regs[6];
+   tst->arch.vex.guest_r7 = mc->sc_regs[7];
+   tst->arch.vex.guest_r8 = mc->sc_regs[8];
+   tst->arch.vex.guest_r9 = mc->sc_regs[9];
+   tst->arch.vex.guest_r10 = mc->sc_regs[10];
+   tst->arch.vex.guest_r11 = mc->sc_regs[11];
+   tst->arch.vex.guest_r12 = mc->sc_regs[12];
+   tst->arch.vex.guest_r13= mc->sc_regs[13];
+   tst->arch.vex.guest_r14 = mc->sc_regs[14];
+   tst->arch.vex.guest_r15 = mc->sc_regs[15];
+   tst->arch.vex.guest_r16 = mc->sc_regs[16];
+   tst->arch.vex.guest_r17 = mc->sc_regs[17];
+   tst->arch.vex.guest_r18 = mc->sc_regs[18];
+   tst->arch.vex.guest_r19 = mc->sc_regs[19];
+   tst->arch.vex.guest_r20 = mc->sc_regs[20];
+   tst->arch.vex.guest_r21 = mc->sc_regs[21];
+   tst->arch.vex.guest_r22 = mc->sc_regs[22];
+   tst->arch.vex.guest_r23 = mc->sc_regs[23];
+   tst->arch.vex.guest_r24 = mc->sc_regs[24];
+   tst->arch.vex.guest_r25 = mc->sc_regs[25];
+   tst->arch.vex.guest_r26 = mc->sc_regs[26];
+   tst->arch.vex.guest_r27 = mc->sc_regs[27];
+   tst->arch.vex.guest_r28 = mc->sc_regs[28];
+   tst->arch.vex.guest_r30 = mc->sc_regs[30];
+   tst->arch.vex.guest_PC = mc->sc_pc;
+   tst->arch.vex.guest_r31 = mc->sc_regs[31];
+   tst->arch.vex.guest_r29 = mc->sc_regs[29];
+
+   tst->arch.vex.guest_HI = mc->sc_mdhi;
+   tst->arch.vex.guest_LO = mc->sc_mdlo;
+   tst->arch.vex_shadow1 = priv1->vex_shadow1;
+   tst->arch.vex_shadow2 = priv1->vex_shadow2;
+
+   VG_TRACK(die_mem_stack_signal, sp, frame_size);
+   if (VG_(clo_trace_signals))
+      VG_(message)(Vg_DebugMsg,
+         "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#llx\n",
+         tid, isRT, tst->arch.vex.guest_PC);
+   /* tell the tools */
+   VG_TRACK( post_deliver_signal, tid, sigNo );
+}
+
+#endif /* defined(VGP_mips64_linux) */
+
+/*--------------------------------------------------------------------*/
+/*--- end                                  sigframe-mips64-linux.c ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c
index 88f7b9d..4423190 100644
--- a/coregrind/m_signals.c
+++ b/coregrind/m_signals.c
@@ -535,6 +535,24 @@
         (srP)->misc.MIPS32.r28 = (uc)->uc_mcontext.sc_regs[28]; \
       }
 
+#elif defined(VGP_mips64_linux)
+#  define VG_UCONTEXT_INSTR_PTR(uc)       (((uc)->uc_mcontext.sc_pc))
+#  define VG_UCONTEXT_STACK_PTR(uc)       ((uc)->uc_mcontext.sc_regs[29])
+#  define VG_UCONTEXT_FRAME_PTR(uc)       ((uc)->uc_mcontext.sc_regs[30])
+#  define VG_UCONTEXT_SYSCALL_NUM(uc)     ((uc)->uc_mcontext.sc_regs[2])
+#  define VG_UCONTEXT_SYSCALL_SYSRES(uc)                        \
+      /* Convert the value in uc_mcontext.rax into a SysRes. */ \
+      VG_(mk_SysRes_mips64_linux)((uc)->uc_mcontext.sc_regs[2], \
+                                  (uc)->uc_mcontext.sc_regs[3], \
+                                  (uc)->uc_mcontext.sc_regs[7])
+
+#  define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc)               \
+      { (srP)->r_pc = (uc)->uc_mcontext.sc_pc;                  \
+        (srP)->r_sp = (uc)->uc_mcontext.sc_regs[29];            \
+        (srP)->misc.MIPS64.r30 = (uc)->uc_mcontext.sc_regs[30]; \
+        (srP)->misc.MIPS64.r31 = (uc)->uc_mcontext.sc_regs[31]; \
+        (srP)->misc.MIPS64.r28 = (uc)->uc_mcontext.sc_regs[28]; \
+      }
 
 #else 
 #  error Unknown platform
@@ -876,6 +894,14 @@
    "	syscall\n" \
    ".previous\n"
 
+#elif defined(VGP_mips64_linux)
+#  define _MY_SIGRETURN(name) \
+   ".text\n" \
+   "my_sigreturn:\n" \
+   "   li $2, " #name "\n" \
+   "   syscall\n" \
+   ".previous\n"
+
 #else
 #  error Unknown platform
 #endif
@@ -953,7 +979,7 @@
                    == skss_old.skss_per_sig[sig].skss_flags);
 #        if !defined(VGP_ppc32_linux) && \
             !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
-            !defined(VGP_mips32_linux)
+            !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux)
          vg_assert(ksa_old.sa_restorer 
                    == my_sigreturn);
 #        endif
@@ -1944,8 +1970,8 @@
 // Synthesise a SIGFPE.
 void VG_(synth_sigfpe)(ThreadId tid, UInt code)
 {
-// Only tested on mips32
-#if !defined(VGA_mips32)
+// Only tested on mips32 and mips64
+#if !defined(VGA_mips32) && !defined(VGA_mips64)
    vg_assert(0);
 #else
    vki_siginfo_t info;
diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c
index ea8b166..0420200 100644
--- a/coregrind/m_stacktrace.c
+++ b/coregrind/m_stacktrace.c
@@ -1110,10 +1110,8 @@
 
 #endif
 
-/* ------------------------ mips 32------------------------- */
-
-#if defined(VGP_mips32_linux)
-
+/* ------------------------ mips 32/64 ------------------------- */
+#if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
 UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
                                /*OUT*/Addr* ips, UInt max_n_ips,
                                /*OUT*/Addr* sps, /*OUT*/Addr* fps,
@@ -1134,8 +1132,13 @@
    uregs.sp = startRegs->r_sp;
    Addr fp_min = uregs.sp;
 
+#if defined(VGP_mips32_linux)
    uregs.fp = startRegs->misc.MIPS32.r30;
    uregs.ra = startRegs->misc.MIPS32.r31;
+#elif defined(VGP_mips64_linux)
+   uregs.fp = startRegs->misc.MIPS64.r30;
+   uregs.ra = startRegs->misc.MIPS64.r31;
+#endif
 
    /* Snaffle IPs from the client's stack into ips[0 .. max_n_ips-1],
       stopping when the trail goes cold, which we guess to be
@@ -1192,7 +1195,6 @@
          for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += 4) {
             unsigned long inst, high_word, low_word;
             unsigned long * cur_inst;
-            int reg;
             /* Fetch the instruction.   */
             cur_inst = (unsigned long *)cur_pc;
             inst = *((UInt *) cur_inst);
@@ -1202,7 +1204,6 @@
             /* Save some code by pre-extracting some useful fields.  */
             high_word = (inst >> 16) & 0xffff;
             low_word = inst & 0xffff;
-            reg = high_word & 0x1f;
 
             if (high_word == 0x27bd        /* addiu $sp,$sp,-i */
                 || high_word == 0x23bd     /* addi $sp,$sp,-i */
diff --git a/coregrind/m_syscall.c b/coregrind/m_syscall.c
index 668d08b..4312d13 100644
--- a/coregrind/m_syscall.c
+++ b/coregrind/m_syscall.c
@@ -137,6 +137,15 @@
    return res;
 }
 
+/* MIPS uses a3 != 0 to flag an error */
+SysRes VG_(mk_SysRes_mips64_linux) ( ULong v0, ULong v1, ULong a3 ) {
+   SysRes res;
+   res._isError = (a3 != (ULong)0);
+   res._val     = v0;
+   res._valEx   = v1;
+   return res;
+}
+
 /* Generic constructors. */
 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
    SysRes r;
@@ -626,6 +635,25 @@
 ".end do_syscall_WRK\n"
 );
 
+#elif defined(VGP_mips64_linux)
+extern UWord do_syscall_WRK ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5,
+                              UWord a6, UWord syscall_no, ULong* V1_val );
+asm (
+".text\n"
+".globl do_syscall_WRK\n"
+"do_syscall_WRK:\n"
+"   daddiu $29, $29, -8\n"
+"   sd $11, 0($29)\n"
+"   move $2, $10\n"
+"   syscall\n"
+"   ld $11, 0($29)\n"
+"   daddiu $29, $29, 8\n"
+"   sd $3, 0($11)\n"  /* store vale of v1 in last param */
+"   sd $7, 8($11)\n"  /* store vale of a3 in last param */
+"   jr $31\n"
+".previous\n"
+);
+
 #else
 #  error Unknown platform
 #endif
@@ -740,6 +768,16 @@
    UWord valLo = 0;
    (void) do_syscall_WRK(a1,a2,a3,a4,a5,a6, sysno,&err,&valHi,&valLo);
    return VG_(mk_SysRes_mips32_linux)( valLo, valHi, (ULong)err );
+
+#elif defined(VGP_mips64_linux)
+   ULong v1_a3[2];
+   v1_a3[0] = 0xFF00;
+   v1_a3[1] = 0xFF00;
+   ULong V0 = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno,v1_a3);
+   ULong V1 = (ULong)v1_a3[0];
+   ULong A3 = (ULong)v1_a3[1];
+   return VG_(mk_SysRes_mips64_linux)( V0, V1, A3 );
+
 #else
 #  error Unknown platform
 #endif
diff --git a/coregrind/m_syswrap/priv_types_n_macros.h b/coregrind/m_syswrap/priv_types_n_macros.h
index 70752ab..ce07877 100644
--- a/coregrind/m_syswrap/priv_types_n_macros.h
+++ b/coregrind/m_syswrap/priv_types_n_macros.h
@@ -89,7 +89,8 @@
       Int o_sysno;
 #     if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
          || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
-         || defined(VGP_arm_linux) || defined(VGP_s390x_linux)
+         || defined(VGP_arm_linux) || defined(VGP_s390x_linux) \
+         || defined(VGP_mips64_linux)
       Int o_arg1;
       Int o_arg2;
       Int o_arg3;
diff --git a/coregrind/m_syswrap/syscall-mips64-linux.S b/coregrind/m_syswrap/syscall-mips64-linux.S
new file mode 100644
index 0000000..4405b54
--- /dev/null
+++ b/coregrind/m_syswrap/syscall-mips64-linux.S
@@ -0,0 +1,156 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Support for doing system calls.      syscall-mips64-linux.S  ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+  This file is part of Valgrind, a dynamic binary instrumentation
+  framework.
+
+   Copyright (C) 2010-2013 RT-RK
+      mips-valgrind@rt-rk.com
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#if defined(VGP_mips64_linux)
+
+#include "pub_core_basics_asm.h"
+#include "pub_core_vkiscnums_asm.h"
+#include "libvex_guest_offsets.h"
+
+/*----------------------------------------------------------------*/
+/*
+   Perform a syscall for the client. This will run a syscall
+   with the client's specific per-thread signal mask.
+
+   The structure of this function is such that, if the syscall is
+   interrupted by a signal, we can determine exactly what
+   execution state we were in with respect to the execution of
+   the syscall by examining the value of PC in the signal
+   handler. This means that we can always do the appropriate
+   thing to precisely emulate the kernel's signal/syscall
+   interactions.
+
+   The syscall number is taken from the argument, even though it
+   should also be in regs->v0. The syscall result is written
+   back to regs->v0 on completion.
+
+   VG_(fixup_guest_state_after_syscall_interrupted) does the
+   thread state fixup in the case where we were interrupted by a
+   signal.
+
+   Prototype:
+
+   UWord ML_(do_syscall_for_client_WRK)(
+             Int syscallno,                 // $4 - a0
+             void* guest_state,             // $5 - a1
+             const vki_sigset_t *sysmask,   // $6 - a2
+             const vki_sigset_t *postmask,  // $7 - a3
+             Int nsigwords)                 // $8 - a4
+*/
+
+/* from vki_arch.h */
+#define VKI_SIG_SETMASK 3
+
+.globl ML_(do_syscall_for_client_WRK)
+ML_(do_syscall_for_client_WRK):
+
+   /* save regs $a0 - $a4 on stack */
+   daddiu  $29, $29, -48
+   sd      $4, 0($29)                /* syscallno */
+   sd      $5, 8($29)                /* guest_state */
+   sd      $6, 16($29)               /* sysmask */
+   sd      $7, 24($29)               /* postmask */
+   sd      $8, 32($29)               /* nsigwords */
+
+1: li      $2, __NR_rt_sigprocmask
+   li      $4, VKI_SIG_SETMASK
+   move    $5, $6                    /* sysmask */
+   move    $6, $7                    /* postmask */
+   move    $7, $8                    /* nsigwords */
+   syscall
+
+   bnez    $7, 7f
+   nop
+
+   /* Actually do the client syscall */ 
+   ld      $5, 8($29)                /* guest_state */
+   ld      $4, OFFSET_mips64_r4($5)  /* a0 */
+
+   ld      $6, OFFSET_mips64_r6($5)  /* a2 */
+   ld      $7, OFFSET_mips64_r7($5)  /* a3 */
+   ld      $8, OFFSET_mips64_r8($5)  /* a4 */
+   ld      $9, OFFSET_mips64_r9($5)  /* a5 */
+
+   ld      $5, OFFSET_mips64_r5($5)  /* a1 */
+   ld      $2, 0($29)                /* syscallno */
+2: nop
+
+   syscall
+
+   /* Saving return values into Guest state  */
+3: ld      $5, 8($29)                /* guest_state */
+   sd      $2, OFFSET_mips64_r2($5)  /* v0 */
+   sd      $7, OFFSET_mips64_r7($5)  /* a3 */
+
+4: li      $2, __NR_rt_sigprocmask
+   li      $4, VKI_SIG_SETMASK
+   ld      $5, 24($29)               /* postmask */
+   move    $6, $0                    /* 0 (zero) */
+   ld      $7, 32($29)               /* nsigwords */
+   syscall
+
+   bnez    $7, 7f
+   nop
+
+5: /* restore 29 and return */
+   daddiu  $29, $29, 48
+   jr      $31
+   nop
+
+7: /* error */
+   daddiu  $29, $29, 48
+   li      $2, 0x8000
+   jr      $31
+   nop
+
+.section .rodata
+/* export the ranges so that
+   VG_(fixup_guest_state_after_syscall_interrupted) can do the
+   right thing */
+
+.globl ML_(blksys_setup)
+.globl ML_(blksys_restart)
+.globl ML_(blksys_complete)
+.globl ML_(blksys_committed)
+.globl ML_(blksys_finished)
+ML_(blksys_setup):      .quad 1b
+ML_(blksys_restart):    .quad 2b
+ML_(blksys_complete):   .quad 3b
+ML_(blksys_committed):  .quad 4b
+ML_(blksys_finished):   .quad 5b
+.previous
+/* Let the linker know we don't need an executable stack */
+.section .note.GNU-stack,"",%progbits
+
+#endif // defined(VGP_mips64_linux)
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index 46bc736..bc04001 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -274,7 +274,7 @@
          : "d" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)
          : "2"
       );
-#elif defined(VGP_mips32_linux)
+#elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
       asm volatile (
          "sw   %1, %0\n\t"     /* set tst->status = VgTs_Empty */
          "li  	$2, %2\n\t"     /* set v0 = __NR_exit */
@@ -428,7 +428,8 @@
       VG_(clone) stuff */
 #if defined(VGP_x86_linux) \
     || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
-    || defined(VGP_arm_linux) || defined(VGP_mips32_linux)
+    || defined(VGP_arm_linux) || defined(VGP_mips32_linux) \
+    || defined(VGP_mips64_linux)
    res = VG_(do_syscall5)( __NR_clone, flags, 
                            (UWord)NULL, (UWord)parent_tidptr, 
                            (UWord)NULL, (UWord)child_tidptr );
diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c
index f696f51..2dbbaa1 100644
--- a/coregrind/m_syswrap/syswrap-main.c
+++ b/coregrind/m_syswrap/syswrap-main.c
@@ -68,7 +68,8 @@
    ppc32  r0    r3   r4   r5   r6   r7   r8   n/a  n/a  r3+CR0.SO (== ARG1)
    ppc64  r0    r3   r4   r5   r6   r7   r8   n/a  n/a  r3+CR0.SO (== ARG1)
    arm    r7    r0   r1   r2   r3   r4   r5   n/a  n/a  r0        (== ARG1)
-   mips   v0    a0   a1   a2   a3 stack stack n/a  n/a  v0        (== NUM)
+   mips32 v0    a0   a1   a2   a3 stack stack n/a  n/a  v0        (== NUM)
+   mips64 v0    a0   a1   a2   a3   a4   a5   a6   a7   v0        (== NUM)
 
    On s390x the svc instruction is used for system calls. The system call
    number is encoded in the instruction (8 bit immediate field). Since Linux
@@ -486,6 +487,16 @@
       canonical->arg8 = __NR_syscall;
    }
 
+#elif defined(VGP_mips64_linux)
+   VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla;
+   canonical->sysno = gst->guest_r2;    // v0
+   canonical->arg1  = gst->guest_r4;    // a0
+   canonical->arg2  = gst->guest_r5;    // a1
+   canonical->arg3  = gst->guest_r6;    // a2
+   canonical->arg4  = gst->guest_r7;    // a3
+   canonical->arg5  = gst->guest_r8;    // a4
+   canonical->arg6  = gst->guest_r9;    // a5
+
 #elif defined(VGP_x86_darwin)
    VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
    UWord *stack = (UWord *)gst->guest_ESP;
@@ -740,6 +751,16 @@
       *((UInt*) (gst->guest_r29 + 20)) = canonical->arg5;    // 20(sp)
       *((UInt*) (gst->guest_r29 + 24)) = canonical->arg6;    // 24(sp)
    }
+
+#elif defined(VGP_mips64_linux)
+   VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla;
+   gst->guest_r2 = canonical->sysno;
+   gst->guest_r4 = canonical->arg1;
+   gst->guest_r5 = canonical->arg2;
+   gst->guest_r6 = canonical->arg3;
+   gst->guest_r7 = canonical->arg4;
+   gst->guest_r8 = canonical->arg5;
+   gst->guest_r9 = canonical->arg6;
 #else
 #  error "putSyscallArgsIntoGuestState: unknown arch"
 #endif
@@ -786,6 +807,14 @@
    canonical->sres = VG_(mk_SysRes_mips32_linux)( v0, v1, a3 );
    canonical->what = SsComplete;
 
+#  elif defined(VGP_mips64_linux)
+   VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla;
+   ULong                v0 = gst->guest_r2;    // v0
+   ULong                v1 = gst->guest_r3;    // v1
+   ULong                a3 = gst->guest_r7;    // a3
+   canonical->sres = VG_(mk_SysRes_mips64_linux)(v0, v1, a3);
+   canonical->what = SsComplete;
+
 #  elif defined(VGP_x86_darwin)
    /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */
    VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
@@ -1036,6 +1065,24 @@
    VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
              OFFSET_mips32_r7, sizeof(UWord) );
 
+#  elif defined(VGP_mips64_linux)
+   VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla;
+   vg_assert(canonical->what == SsComplete);
+   if (sr_isError(canonical->sres)) {
+      gst->guest_r2 = (Int)sr_Err(canonical->sres);
+      gst->guest_r7 = (Int)sr_Err(canonical->sres);
+   } else {
+      gst->guest_r2 = sr_Res(canonical->sres);
+      gst->guest_r3 = sr_ResEx(canonical->sres);
+      gst->guest_r7 = (Int)sr_Err(canonical->sres);
+   }
+   VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+             OFFSET_mips64_r2, sizeof(UWord) );
+   VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+             OFFSET_mips64_r3, sizeof(UWord) );
+   VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+             OFFSET_mips64_r7, sizeof(UWord) );
+
 #  else
 #    error "putSyscallStatusIntoGuestState: unknown arch"
 #  endif
@@ -1115,6 +1162,17 @@
    layout->uu_arg7  = -1; /* impossible value */
    layout->uu_arg8  = -1; /* impossible value */
 
+#elif defined(VGP_mips64_linux)
+   layout->o_sysno  = OFFSET_mips64_r2;
+   layout->o_arg1   = OFFSET_mips64_r4;
+   layout->o_arg2   = OFFSET_mips64_r5;
+   layout->o_arg3   = OFFSET_mips64_r6;
+   layout->o_arg4   = OFFSET_mips64_r7;
+   layout->o_arg5   = OFFSET_mips64_r8;
+   layout->o_arg6   = OFFSET_mips64_r9;
+   layout->uu_arg7  = -1; /* impossible value */
+   layout->uu_arg8  = -1; /* impossible value */
+
 #elif defined(VGP_x86_darwin)
    layout->o_sysno  = OFFSET_x86_EAX;
    // syscall parameters are on stack in C convention
@@ -1970,7 +2028,7 @@
       vg_assert(p[0] == 0x0A);
    }
 
-#elif defined(VGP_mips32_linux)
+#elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
 
    arch->vex.guest_PC -= 4;             // sizeof(mips instr)
 
@@ -1986,14 +2044,14 @@
 #     if defined (VG_LITTLEENDIAN)
       if (p[0] != 0x0c || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0x00)
          VG_(message)(Vg_DebugMsg,
-                      "?! restarting over syscall at %#x %02x %02x %02x %02x\n",
+                      "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
                       arch->vex.guest_PC, p[0], p[1], p[2], p[3]);
 
       vg_assert(p[0] == 0x0c && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x00);
 #     elif defined (VG_BIGENDIAN)
       if (p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0x0c)
          VG_(message)(Vg_DebugMsg,
-                      "?! restarting over syscall at %#x %02x %02x %02x %02x\n",
+                      "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
                       arch->vex.guest_PC, p[0], p[1], p[2], p[3]);
 
       vg_assert(p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x0c);
diff --git a/coregrind/m_syswrap/syswrap-mips32-linux.c b/coregrind/m_syswrap/syswrap-mips32-linux.c
index f21f2ac..88e76a3 100644
--- a/coregrind/m_syswrap/syswrap-mips32-linux.c
+++ b/coregrind/m_syswrap/syswrap-mips32-linux.c
@@ -949,12 +949,10 @@
 
 PRE (sys_sigreturn) 
 {
-  ThreadState * tst;
   PRINT ("sys_sigreturn ( )");
   vg_assert (VG_ (is_valid_tid) (tid));
   vg_assert (tid >= 1 && tid < VG_N_THREADS);
   vg_assert (VG_ (is_running_thread) (tid));
-  tst = VG_ (get_ThreadState) (tid);
   VG_ (sigframe_destroy) (tid, False);
   /* Tell the driver not to update the guest state with the "result",
      and set a bogus result to keep it happy. */ 
diff --git a/coregrind/m_syswrap/syswrap-mips64-linux.c b/coregrind/m_syswrap/syswrap-mips64-linux.c
new file mode 100644
index 0000000..f6a4bc4
--- /dev/null
+++ b/coregrind/m_syswrap/syswrap-mips64-linux.c
@@ -0,0 +1,1304 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Platform-specific syscalls stuff.    syswrap-mips64-linux.c ----*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2010-2013 RT-RK
+      mips-valgrind@rt-rk.com
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#if defined(VGP_mips64_linux)
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
+#include "pub_core_libcsetjmp.h"   /* to keep _threadstate.h happy */
+#include "pub_core_threadstate.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_debuglog.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_libcproc.h"
+#include "pub_core_libcsignal.h"
+#include "pub_core_options.h"
+#include "pub_core_scheduler.h"
+#include "pub_core_sigframe.h"     /* For VG_(sigframe_destroy)() */
+#include "pub_core_signals.h"
+#include "pub_core_syscall.h"
+#include "pub_core_syswrap.h"
+#include "pub_core_tooliface.h"
+#include "pub_core_stacks.h"       /* VG_(register_stack) */
+#include "pub_core_transtab.h"     /* VG_(discard_translations) */
+#include "priv_types_n_macros.h"
+#include "priv_syswrap-generic.h"  /* for decls of generic wrappers */
+#include "priv_syswrap-linux.h"    /* for decls of linux-ish wrappers */
+#include "priv_syswrap-main.h"
+
+#include "pub_core_debuginfo.h"    /* VG_(di_notify_*) */
+#include "pub_core_xarray.h"
+#include "pub_core_clientstate.h"  /* VG_(brk_base), VG_(brk_limit) */
+#include "pub_core_errormgr.h"
+#include "pub_tool_gdbserver.h"    /* VG_(gdbserver) */
+#include "pub_core_libcfile.h"
+#include "pub_core_machine.h"      /* VG_(get_SP) */
+#include "pub_core_mallocfree.h"
+#include "pub_core_stacktrace.h"   /* For VG_(get_and_pp_StackTrace)() */
+#include "pub_core_ume.h"
+
+#include "config.h"
+
+#include <errno.h>
+
+/* ---------------------------------------------------------------------
+                             clone() handling
+   ------------------------------------------------------------------ */
+
+/* Call f(arg1), but first switch stacks, using 'stack' as the new stack, and
+   use 'retaddr' as f's return-to address. Also, clear all the integer registers
+   before entering f. */
+__attribute__ ((noreturn))
+void ML_(call_on_new_stack_0_1) ( Addr stack,             /* $4 - $a0 */
+                                  Addr retaddr,           /* $5 - $a1 */
+                                  void (*f_desc) (Word),  /* $6 - $a2 */
+                                  Word arg1 );            /* $7 - $a3 */
+asm (
+".text\n"
+".globl vgModuleLocal_call_on_new_stack_0_1\n"
+"vgModuleLocal_call_on_new_stack_0_1:\n"
+"   move $29, $4\n"  /* set stack */
+"   move $4,  $7\n"  /* arg1 to $4 */
+"   move $25, $6\n"
+"   move $31, $5\n"  /* retaddr to $ra */
+"   jr $25\n"        /* jump to f */
+"   break 0x7\n"     /* should never get here */
+".previous\n"
+);
+
+/* Perform a clone system call.  clone is strange because it has fork()-like
+   return-twice semantics, so it needs special handling here.
+
+   Upon entry, we have:
+
+      word (fn)(void*)    in a0 = 4
+      void* child_stack   in a1 = 5
+      word flags          in a2 = 6
+      void* arg           in a3 = 7
+      pid_t* parent_tid   in a4 = 8
+      void* tls           in a5 = 9
+      pid_t* child_tid    in a6 = 10  
+
+   System call requires:
+
+      int    $__NR_clone  in v0 
+      int    flags        in a0 = 4 
+      void*  child_stack  in a1 = 5 
+      pid_t* parent_tid   in a2 = 6
+      void*  tls_ptr      in a3 = 7 
+      pid_t* child_tid    in a4 = 8 */
+
+#define __NR_CLONE        __NR_clone
+#define __NR_EXIT         __NR_exit
+
+ULong do_syscall_clone_mips64_linux ( Word (*fn) (void *),  /* a0 - 4 */
+                                      void* stack,          /* a1 - 5 */
+                                      Int   flags,          /* a2 - 6 */
+                                      void* arg,            /* a3 - 7 */
+                                      Int*  parent_tid,     /* a4 - 8 */
+                                      void* /* Int tls */,  /* a5 - 9 */
+                                      Int*  child_tid );    /* a6 - 10 */
+
+asm(
+".text\n" 
+".set noreorder\n"
+".set nomacro\n"
+".globl do_syscall_clone_mips64_linux\n"
+"do_syscall_clone_mips64_linux:\n"
+"   daddiu $29, $29, -32\n"
+"   sd $31, 0($29)\n"
+"   sd $30, 8($29)\n"
+"   sd $28, 16($29)\n"
+
+"   daddiu  $5, $5, -32\n"
+"   sd $4, 0($5)\n"   /* fn */
+"   sd $7, 8($5)\n"   /* arg */
+"   sd $6, 16($5)\n"  /* flags */
+
+/* 1. arg for syscalls */
+"   move $4, $6\n"   /* flags */
+"   move $6, $8\n"   /* parent */
+"   move $7, $a5\n"  /* tls */
+"   move $8, $a6\n"  /* child */
+
+/* 2. do a syscall to clone */
+"   li  $2, 5055\n"  /* syscall num for clone */
+"   syscall\n"
+
+/* 3. See if we are a child, call fn and after that exit */
+"   bnez $7, p_or_error\n"
+"   nop\n"
+
+"   bnez $2, p_or_error\n"
+"   nop\n"
+
+"   ld $25,0($29)\n"
+"   jalr $25\n"
+"   ld $4,8($29)\n"
+
+"   move $4, $2\n\t"  /* retval from fn is in $v0 */
+"   li $2, 5058\n\t"  /* NR_exit */
+"   syscall\n\t"
+"   nop\n\t"
+/* 4. If we are parent or error, just return to caller */
+"   p_or_error:\n"
+"   ld $31, 0($29)\n"
+"   ld $30, 8($29)\n"
+"   ld $28, 16($29)\n"
+"   jr $31\n"
+"   daddi $29,$29, 32\n"
+".previous\n"
+);
+
+#undef __NR_CLONE
+#undef __NR_EXIT
+
+/* forward declarations */
+static void setup_child ( ThreadArchState *, ThreadArchState *);
+static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr);
+
+/* When a client clones, we need to keep track of the new thread. This means:
+   1. allocate a ThreadId+ThreadState+stack for the the thread
+
+   2. initialize the thread's new VCPU state
+
+   3. create the thread using the same args as the client requested, but using
+      the scheduler entrypoint for IP, and a separate stack for SP. */
+static SysRes do_clone ( ThreadId ptid,
+                         UInt flags, Addr sp,
+                         Int* parent_tidptr,
+                         Int* child_tidptr,
+                         Addr child_tls )
+{
+   const Bool debug = False;
+   ThreadId ctid = VG_ (alloc_ThreadState) ();
+   ThreadState * ptst = VG_ (get_ThreadState) (ptid);
+   ThreadState * ctst = VG_ (get_ThreadState) (ctid);
+   UInt ret = 0;
+   UWord * stack;
+   NSegment const *seg;
+   SysRes res;
+   vki_sigset_t blockall, savedmask;
+
+   VG_(sigfillset)(&blockall);
+   vg_assert(VG_(is_running_thread)(ptid));
+   vg_assert(VG_(is_valid_tid)(ctid));
+   stack = (UWord *)ML_(allocstack)(ctid);
+   if (stack == NULL) {
+      res = VG_(mk_SysRes_Error)(VKI_ENOMEM);
+      goto out;
+   }
+   setup_child(&ctst->arch, &ptst->arch);
+
+   /* on MIPS we need to set V0 and A3 to zero */
+   ctst->arch.vex.guest_r2 = 0;
+   ctst->arch.vex.guest_r7 = 0;
+   if (sp != 0)
+      ctst->arch.vex.guest_r29 = sp;
+
+   ctst->os_state.parent = ptid;
+   ctst->sig_mask = ptst->sig_mask;
+   ctst->tmp_sig_mask = ptst->sig_mask;
+
+   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
+   seg = VG_(am_find_nsegment)((Addr)sp);
+
+   if (seg && seg->kind != SkResvn) {
+      ctst->client_stack_highest_word = sp;
+      ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
+      VG_(register_stack)(seg->start, ctst->client_stack_highest_word);
+      if (debug)
+        VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
+                    ctid, seg->start, sp /* VG_PGROUNDUP (sp) */ );
+   } else {
+      VG_(message)(Vg_UserMsg,
+                    "!? New thread %d starts with sp+%#lx) unmapped\n",
+                    ctid, sp);
+      ctst->client_stack_szB = 0;
+   }
+
+   VG_TRACK(pre_thread_ll_create, ptid, ctid);
+   if (flags & VKI_CLONE_SETTLS) {
+       if (debug)
+         VG_(printf)("clone child has SETTLS: tls at %#lx\n", child_tls);
+       res = sys_set_tls(ctid, child_tls);
+       if (sr_isError(res))
+          goto out;
+       ctst->arch.vex.guest_r27 = child_tls;
+   }
+
+   flags &= ~VKI_CLONE_SETTLS;
+   VG_ (sigprocmask) (VKI_SIG_SETMASK, &blockall, &savedmask);
+   /* Create the new thread */
+   ret = do_syscall_clone_mips64_linux(ML_(start_thread_NORETURN),
+                                       stack, flags, &VG_(threads)[ctid],
+                                       parent_tidptr, NULL /*child_tls*/,
+                                       child_tidptr);
+   if (debug)
+     VG_(printf)("ret: 0x%x\n", ret);
+
+   res = VG_(mk_SysRes_mips64_linux)( /* val */ ret, 0, /* errflag */ 0);
+
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
+
+   out:
+   if (sr_isError (res)) {
+      VG_ (cleanup_thread) (&ctst->arch);
+      ctst->status = VgTs_Empty;
+      VG_TRACK (pre_thread_ll_exit, ctid);
+   }
+   ptst->arch.vex.guest_r2 = 0;
+
+   return res;
+}
+
+/* ---------------------------------------------------------------------
+                          More thread stuff
+   ------------------------------------------------------------------ */
+void VG_(cleanup_thread) ( ThreadArchState * arch ) { };
+
+void setup_child ( /* OUT */ ThreadArchState * child,
+                   /* IN  */ ThreadArchState * parent )
+{
+   /* We inherit our parent's guest state. */
+   child->vex = parent->vex;
+   child->vex_shadow1 = parent->vex_shadow1;
+   child->vex_shadow2 = parent->vex_shadow2;
+}
+
+SysRes sys_set_tls ( ThreadId tid, Addr tlsptr )
+{
+   VG_(threads)[tid].arch.vex.guest_ULR = tlsptr;
+   return VG_(mk_SysRes_Success)( 0 );
+}
+
+/* ---------------------------------------------------------------------
+           PRE/POST wrappers for mips/Linux-specific syscalls
+   ------------------------------------------------------------------ */
+
+#define PRE(name)       DEFN_PRE_TEMPLATE(mips_linux, name)
+#define POST(name)      DEFN_POST_TEMPLATE(mips_linux, name)
+
+/* Add prototypes for the wrappers declared here, so that gcc doesn't harass us
+   for not having prototypes. Really this is a kludge -- the right thing to do
+   is to make these wrappers 'static' since they aren't visible outside this
+   file, but that requires even more macro magic. */
+
+DECL_TEMPLATE (mips_linux, sys_set_thread_area);
+DECL_TEMPLATE (mips_linux, sys_clone);
+DECL_TEMPLATE (mips_linux, sys_socket);
+DECL_TEMPLATE (mips_linux, sys_setsockopt);
+DECL_TEMPLATE (mips_linux, sys_getsockopt);
+DECL_TEMPLATE (mips_linux, sys_connect);
+DECL_TEMPLATE (mips_linux, sys_accept);
+DECL_TEMPLATE (mips_linux, sys_tee);
+DECL_TEMPLATE (mips_linux, sys_splice);
+DECL_TEMPLATE (mips_linux, sys_vmsplice);
+DECL_TEMPLATE (mips_linux, sys_ustat);
+DECL_TEMPLATE (mips_linux, sys_sysfs);
+DECL_TEMPLATE (mips_linux, sys_swapon);
+DECL_TEMPLATE (mips_linux, sys_swapoff);
+DECL_TEMPLATE (mips_linux, sys_setdomainname);
+DECL_TEMPLATE (mips_linux, sys_sethostname);
+DECL_TEMPLATE (mips_linux, sys_accept4);
+DECL_TEMPLATE (mips_linux, sys_sendto);
+DECL_TEMPLATE (mips_linux, sys_recvfrom);
+DECL_TEMPLATE (mips_linux, sys_sendmsg);
+DECL_TEMPLATE (mips_linux, sys_recvmsg);
+DECL_TEMPLATE (mips_linux, sys_shutdown);
+DECL_TEMPLATE (mips_linux, sys_bind);
+DECL_TEMPLATE (mips_linux, sys_reboot);
+DECL_TEMPLATE (mips_linux, sys_listen);
+DECL_TEMPLATE (mips_linux, sys_getsockname);
+DECL_TEMPLATE (mips_linux, sys_getpeername);
+DECL_TEMPLATE (mips_linux, sys_socketpair);
+DECL_TEMPLATE (mips_linux, sys_semget);
+DECL_TEMPLATE (mips_linux, sys_semop);
+DECL_TEMPLATE (mips_linux, sys_semtimedop);
+DECL_TEMPLATE (mips_linux, sys_cacheflush);
+DECL_TEMPLATE (mips_linux, sys_semctl);
+DECL_TEMPLATE (mips_linux, sys_sched_rr_get_interval);
+DECL_TEMPLATE (mips_linux, sys_msgget);
+DECL_TEMPLATE (mips_linux, sys_msgrcv);
+DECL_TEMPLATE (mips_linux, sys_unshare);
+DECL_TEMPLATE (mips_linux, sys_msgsnd);
+DECL_TEMPLATE (mips_linux, sys_msgctl);
+DECL_TEMPLATE (mips_linux, sys_shmget);
+DECL_TEMPLATE (mips_linux, wrap_sys_shmat);
+DECL_TEMPLATE (mips_linux, sys_shmdt);
+DECL_TEMPLATE (mips_linux, sys_shmdt);
+DECL_TEMPLATE (mips_linux, sys_shmctl);
+DECL_TEMPLATE (mips_linux, sys_arch_prctl);
+DECL_TEMPLATE (mips_linux, sys_ptrace);
+DECL_TEMPLATE (mips_linux, sys_mmap);
+DECL_TEMPLATE (mips_linux, sys_rt_sigreturn);
+DECL_TEMPLATE (mips_linux, sys_pipe);
+
+PRE(sys_socketpair)
+{
+   PRINT("sys_socketpair ( %ld, %ld, %ld, %#lx )", ARG1, ARG2, ARG3, ARG4);
+   PRE_REG_READ4(long, "socketpair", int, d, int, type, int, protocol,
+                 int *, sv);
+   ML_(generic_PRE_sys_socketpair)(tid, ARG1, ARG2, ARG3, ARG4);
+}
+
+POST(sys_socketpair)
+{
+   vg_assert(SUCCESS);
+   ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
+                                    ARG1, ARG2, ARG3, ARG4);
+}
+
+PRE(wrap_sys_shmat)
+{
+   UWord arg2tmp;
+   PRINT("wrap_sys_shmat ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "shmat", int, shmid, const void *, shmaddr, int, shmflg);
+   arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1, ARG2, ARG3);
+   if (arg2tmp == 0)
+      SET_STATUS_Failure(VKI_EINVAL);
+   else
+      ARG2 = arg2tmp;
+}
+
+POST(wrap_sys_shmat)
+{
+   ML_(generic_POST_sys_shmat)(tid, RES, ARG1, ARG2, ARG3);
+}
+
+PRE(sys_shmdt)
+{
+   PRINT("sys_shmdt ( %#lx )", ARG1);
+   PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
+   if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1))
+      SET_STATUS_Failure(VKI_EINVAL);
+}
+
+POST(sys_shmdt)
+{
+   ML_(generic_POST_sys_shmdt)(tid, RES, ARG1);
+}
+
+PRE(sys_shmctl)
+{
+   PRINT("sys_shmctl ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "shmctl", int, shmid, int, cmd, struct shmid_ds *, buf);
+   ML_(generic_PRE_sys_shmctl)(tid, ARG1, ARG2, ARG3);
+}
+
+POST(sys_shmctl)
+{
+   ML_(generic_POST_sys_shmctl)(tid, RES, ARG1, ARG2, ARG3);
+}
+
+PRE(sys_shmget)
+{
+   PRINT("sys_shmget ( %ld, %ld, %ld )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg);
+}
+
+PRE(sys_tee)
+{
+   PRINT("sys_tee ( %ld, %ld, %ld, %ld )", ARG1, ARG2, ARG3, ARG4);
+   PRE_REG_READ4(long, "sys_tee", int, fdin, int, fdout, vki_size_t, len,
+                 int, flags);
+}
+
+PRE(sys_splice)
+{
+   PRINT("sys_splice ( %ld, %ld, %ld, %ld, %ld, %ld )", ARG1, ARG2, ARG3,
+                                                        ARG4, ARG5, ARG6);
+
+   PRE_REG_READ6(long, "sys_splice", int, fdin, vki_loff_t, sizein, int,
+                 fdout, vki_loff_t, sizeout, vki_size_t, len, int, flags);
+}
+
+PRE(sys_vmsplice)
+{
+   PRINT("sys_vmsplice ( %ld, %ld, %ld, %ld )", ARG1, ARG2, ARG3, ARG4);
+   PRE_REG_READ4(long, "sys_vmsplice", int, fdin, struct vki_iovec *, v,
+                 vki_size_t, len, int, flags);
+}
+
+PRE(sys_unshare)
+{
+   PRINT("sys_unshare ( %ld )", ARG1);
+   PRE_REG_READ1(long, "sys_unshare", int, flags);
+}
+
+PRE(sys_msgctl)
+{
+   PRINT("sys_msgctl ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "msgctl", int, msqid, int, cmd, struct msqid_ds *, buf);
+   ML_(linux_PRE_sys_msgctl) (tid, ARG1, ARG2, ARG3);
+}
+
+POST(sys_msgctl)
+{
+   ML_(linux_POST_sys_msgctl)(tid, RES, ARG1, ARG2, ARG3);
+}
+
+PRE(sys_msgget)
+{
+   PRINT("sys_msgget ( %ld, %ld )", ARG1, ARG2);
+   PRE_REG_READ2(long, "msgget", vki_key_t, key, int, msgflg);
+}
+
+PRE(sys_sched_rr_get_interval)
+{
+   PRINT("sys_sched_rr_get_interval ( %ld, %#lx)", ARG1, ARG2);
+   PRE_REG_READ2(long, "sched_rr_get_interval", int, flags,
+                 struct timespec *, timer);
+   *flags |= SfMayBlock;
+}
+
+PRE(sys_ustat)
+{
+   PRINT("sys_ustat ( %ld, %#lx)", ARG1, ARG2);
+   PRE_REG_READ2(long, "ustat", int, flags, const void *, path);
+}
+
+PRE(sys_swapon)
+{
+   PRINT("sys_swapon ( %#lx, %ld )", ARG1, ARG2);
+   PRE_REG_READ2(long, "swapon", const void *, path, int, flags);
+}
+
+PRE(sys_swapoff)
+{
+   PRINT("sys_swapoff ( %#lx )", ARG1);
+   PRE_REG_READ1(long, "swapoff", const void *, path);
+}
+
+PRE(sys_sysfs)
+{
+   PRINT("sys_sysfs ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "sysfs", int, flags, int, desc, const void *, path);
+}
+
+PRE(sys_msgsnd)
+{
+   PRINT("sys_msgsnd ( %ld, %#lx, %ld, %ld )", ARG1, ARG2, ARG3, ARG4);
+   PRE_REG_READ4(long, "msgsnd", int, msqid, struct msgbuf *, msgp,
+                 vki_size_t, msgsz, int, msgflg);
+   ML_(linux_PRE_sys_msgsnd)(tid, ARG1, ARG2, ARG3, ARG4);
+   if ((ARG4 & VKI_IPC_NOWAIT) == 0)
+      *flags |= SfMayBlock;
+}
+
+PRE(sys_msgrcv)
+{
+   PRINT("sys_msgrcv ( %ld, %#lx, %ld, %ld, %ld )", ARG1, ARG2, ARG3, ARG4,
+                                                    ARG5);
+   PRE_REG_READ5(long, "msgrcv", int, msqid, struct msgbuf *, msgp,
+                 vki_size_t, msgsz, long, msgytp, int, msgflg);
+   ML_(linux_PRE_sys_msgrcv) (tid, ARG1, ARG2, ARG3, ARG4, ARG5);
+   if ((ARG4 & VKI_IPC_NOWAIT) == 0)
+      *flags |= SfMayBlock;
+}
+
+POST(sys_msgrcv)
+{
+   ML_(linux_POST_sys_msgrcv)(tid, RES, ARG1, ARG2, ARG3, ARG4, ARG5);
+}
+
+PRE(sys_semctl)
+{
+   switch (ARG3 & ~VKI_IPC_64) {
+      case VKI_IPC_INFO:
+      case VKI_SEM_INFO:
+        PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )", ARG1, ARG2, ARG3, ARG4);
+        PRE_REG_READ4(long, "semctl", int, semid, int, semnum, int, cmd,
+                      struct seminfo *, arg);
+      break;
+      case VKI_IPC_STAT:
+      case VKI_SEM_STAT:
+      case VKI_IPC_SET:
+         PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )", ARG1, ARG2, ARG3, ARG4);
+         PRE_REG_READ4(long, "semctl", int, semid, int, semnum, int, cmd,
+                       struct semid_ds *, arg);
+         break;
+      case VKI_GETALL:
+      case VKI_SETALL:
+         PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )", ARG1, ARG2, ARG3, ARG4);
+         PRE_REG_READ4(long, "semctl", int, semid, int, semnum, int, cmd,
+                       unsigned short *, arg);
+         break;
+      default:
+         PRINT("sys_semctl ( %ld, %ld, %ld )", ARG1, ARG2, ARG3);
+         PRE_REG_READ3(long, "semctl", int, semid, int, semnum, int, cmd);
+         break;
+   }
+   ML_(generic_PRE_sys_semctl)(tid, ARG1, ARG2, ARG3, ARG4);
+}
+
+POST(sys_semctl)
+{
+   ML_(generic_POST_sys_semctl)(tid, RES, ARG1, ARG2, ARG3, ARG4);
+}
+
+PRE(sys_semget)
+{
+   PRINT("sys_semget ( %ld, %ld, %ld )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg);
+}
+
+PRE(sys_semop)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_semop ( %ld, %#lx, %lu )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "semop", int, semid, struct sembuf *, sops,
+                 unsigned, nsoops);
+   ML_(generic_PRE_sys_semop)(tid, ARG1, ARG2, ARG3);
+}
+
+PRE(sys_semtimedop)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_semtimedop ( %ld, %#lx, %lu, %#lx )", ARG1, ARG2, ARG3, ARG4);
+   PRE_REG_READ4(long, "semtimedop", int, semid, struct sembuf *, sops,
+                 unsigned, nsoops, struct timespec *, timeout);
+   ML_(generic_PRE_sys_semtimedop)(tid, ARG1, ARG2, ARG3, ARG4);
+}
+
+/* Very much MIPS specific */
+PRE(sys_cacheflush)
+{
+   PRINT("cacheflush (%lx, %#lx, %#lx)", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "cacheflush", void *, addrlow, void *, addrhigh,
+                 int, flags);
+   VG_(discard_translations)((Addr64) ARG1, ((ULong) ARG2) - ((ULong) ARG1) +
+                             1ULL /*paranoia */ , "PRE(sys_cacheflush)");
+   SET_STATUS_Success(0);
+}
+
+PRE(sys_getpeername)
+{
+   PRINT("sys_getpeername ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "getpeername", int, s, struct sockaddr *, name,
+                 int *, namelen);
+   ML_(generic_PRE_sys_getpeername) (tid, ARG1, ARG2, ARG3);
+}
+
+POST(sys_getpeername)
+{
+   vg_assert (SUCCESS);
+   ML_(generic_POST_sys_getpeername)(tid, VG_ (mk_SysRes_Success) (RES),
+                                     ARG1, ARG2, ARG3);
+}
+
+PRE(sys_getsockname)
+{
+   PRINT("sys_getsockname ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "getsockname", int, s, struct sockaddr *, name,
+                 int *, namelen);
+   ML_(generic_PRE_sys_getsockname)(tid, ARG1, ARG2, ARG3);
+}
+
+POST(sys_getsockname)
+{
+   vg_assert(SUCCESS);
+   ML_(generic_POST_sys_getsockname)(tid, VG_ (mk_SysRes_Success) (RES),
+                                     ARG1, ARG2, ARG3);
+}
+
+PRE(sys_shutdown)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_shutdown ( %ld, %ld )", ARG1, ARG2);
+   PRE_REG_READ2(int, "shutdown", int, s, int, how);
+}
+
+PRE(sys_reboot)
+{
+   PRINT("sys_reboot ( %ld )", ARG1);
+   PRE_REG_READ1(int, "reboot", int, flags);
+   *flags |= SfMayBlock;
+}
+
+PRE(sys_bind)
+{
+   PRINT("sys_bind ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "bind", int, sockfd, struct sockaddr *, my_addr,
+                 int, addrlen);
+   ML_(generic_PRE_sys_bind)(tid, ARG1, ARG2, ARG3);
+}
+
+PRE(sys_setdomainname)
+{
+   PRINT ("sys_setdomainname ( %#lx, %ld )", ARG1, ARG2);
+   PRE_REG_READ2 (long, "setdomainname", const void *, name, int, len);
+}
+
+PRE(sys_sethostname)
+{
+   PRINT ("sys_sethostname ( %ld, %ld )", ARG1, ARG2);
+   PRE_REG_READ2 (long, "sethostname", const void *, name, int, len);
+}
+
+PRE(sys_listen)
+{
+   PRINT ("sys_listen ( %ld, %ld )", ARG1, ARG2);
+   PRE_REG_READ2 (long, "listen", int, s, int, backlog);
+}
+
+PRE(sys_sendmsg)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_sendmsg ( %ld, %#lx, %ld )",ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "sendmsg", int, s, const struct msghdr *, msg,
+                 int, flags);
+   ML_(generic_PRE_sys_sendmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
+}
+
+PRE(sys_recvmsg)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_recvmsg ( %ld, %#lx, %ld )",ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
+   ML_(generic_PRE_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
+}
+
+POST(sys_recvmsg)
+{
+   ML_(generic_POST_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2, RES);
+}
+
+PRE(sys_sendto)
+{
+   *flags |= SfMayBlock;
+   PRINT ("sys_sendto ( %ld, %#lx, %ld, %lu, %#lx, %ld )", ARG1, ARG2, ARG3,
+                                                           ARG4, ARG5, ARG6);
+   PRE_REG_READ6 (long, "sendto", int, s, const void *, msg, int, len,
+                  unsigned int, flags, const struct sockaddr *, to, int, tolen);
+   ML_(generic_PRE_sys_sendto) (tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
+}
+
+PRE(sys_recvfrom)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )", ARG1, ARG2,
+                                                 ARG3, ARG4, ARG5, ARG6);
+   PRE_REG_READ6(long, "recvfrom", int, s, void *, buf, int, len,
+                 unsigned int, flags, struct sockaddr *, from, int *, fromlen);
+   ML_(generic_PRE_sys_recvfrom)(tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
+}
+
+POST(sys_recvfrom)
+{
+   vg_assert(SUCCESS);
+   ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
+                                  ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
+}
+
+PRE (sys_connect)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_connect ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "connect", int, sockfd, struct sockaddr *, serv_addr,
+                 int, addrlen);
+   ML_(generic_PRE_sys_connect)(tid, ARG1, ARG2, ARG3);
+}
+
+PRE(sys_accept)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_accept ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "accept",  int, s, struct sockaddr *, addr,
+                 int, *addrlen);
+   ML_(generic_PRE_sys_accept)(tid, ARG1, ARG2, ARG3);
+}
+
+PRE(sys_accept4)
+{
+   *flags |= SfMayBlock;
+}
+
+POST(sys_accept)
+{
+   SysRes r;
+   vg_assert(SUCCESS);
+   r = ML_(generic_POST_sys_accept)(tid, VG_ (mk_SysRes_Success) (RES),
+                                    ARG1, ARG2, ARG3);
+   SET_STATUS_from_SysRes(r);
+}
+
+PRE(sys_setsockopt)
+{
+   PRINT("sys_setsockopt ( %ld, %ld, %ld, %#lx, %ld )", ARG1, ARG2, ARG3,
+                                                        ARG4, ARG5);
+   PRE_REG_READ5(long, "setsockopt", int, s, int, level, int, optname,
+                 const void *, optval, int, optlen);
+   ML_(generic_PRE_sys_setsockopt)(tid, ARG1, ARG2, ARG3, ARG4, ARG5);
+}
+
+PRE(sys_getsockopt)
+{
+   PRINT("sys_getsockopt ( %ld, %ld, %ld, %#lx, %#lx )", ARG1, ARG2, ARG3,
+                                                         ARG4, ARG5);
+   PRE_REG_READ5(long, "getsockopt", int, s, int, level, int, optname,
+                 void *, optval, int, *optlen);
+   ML_(linux_PRE_sys_getsockopt)(tid, ARG1, ARG2, ARG3, ARG4, ARG5);
+}
+
+POST(sys_getsockopt)
+{
+   vg_assert(SUCCESS);
+   ML_(linux_POST_sys_getsockopt)(tid, VG_(mk_SysRes_Success) (RES),
+                                  ARG1, ARG2, ARG3, ARG4, ARG5);
+}
+
+PRE(sys_socket)
+{
+   PRINT("sys_socket ( %ld, %ld, %ld )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
+}
+
+POST(sys_socket)
+{
+   SysRes r;
+   vg_assert(SUCCESS);
+   r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
+   SET_STATUS_from_SysRes(r);
+}
+
+PRE(sys_ptrace)
+{
+   PRINT("sys_ptrace ( %ld, %ld, %#lx, %#lx )", ARG1, ARG2, ARG3, ARG4);
+   PRE_REG_READ4(int, "ptrace", long, request, long, pid, long, addr,
+                 long, data);
+   switch (ARG1) {
+      case VKI_PTRACE_PEEKTEXT:
+      case VKI_PTRACE_PEEKDATA:
+      case VKI_PTRACE_PEEKUSR:
+         PRE_MEM_WRITE("ptrace(peek)", ARG4, sizeof(long));
+         break;
+      case VKI_PTRACE_GETEVENTMSG:
+         PRE_MEM_WRITE("ptrace(geteventmsg)", ARG4, sizeof(unsigned long));
+         break;
+      case VKI_PTRACE_GETSIGINFO:
+         PRE_MEM_WRITE("ptrace(getsiginfo)", ARG4, sizeof(vki_siginfo_t));
+         break;
+      case VKI_PTRACE_SETSIGINFO:
+         PRE_MEM_READ("ptrace(setsiginfo)", ARG4, sizeof(vki_siginfo_t));
+         break;
+      default:
+        break;
+   }
+}
+
+POST(sys_ptrace)
+{
+   switch (ARG1) {
+      case VKI_PTRACE_PEEKTEXT:
+      case VKI_PTRACE_PEEKDATA:
+      case VKI_PTRACE_PEEKUSR:
+         POST_MEM_WRITE (ARG4, sizeof(long));
+         break;
+      case VKI_PTRACE_GETEVENTMSG:
+         POST_MEM_WRITE (ARG4, sizeof(unsigned long));
+      break;
+      case VKI_PTRACE_GETSIGINFO:
+         POST_MEM_WRITE (ARG4, sizeof(vki_siginfo_t));
+         break;
+      default:
+      break;
+   }
+}
+
+PRE (sys_mmap)
+{
+   SysRes r;
+   PRINT("sys_mmap ( %#lx, %llu, %lu, %lu, %lu, %ld )", ARG1, (ULong)ARG2,
+                                                        ARG3, ARG4, ARG5, ARG6);
+   PRE_REG_READ6(long, "mmap", unsigned long, start, vki_size_t, length,
+                 int, prot, int, flags, int, fd, unsigned long, offset);
+   r = ML_(generic_PRE_sys_mmap)(tid, ARG1, ARG2, ARG3, ARG4, ARG5,
+                                 (Off64T) ARG6);
+   SET_STATUS_from_SysRes(r);
+}
+
+PRE(sys_clone)
+{
+   Bool badarg = False;
+   UInt cloneflags;
+   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )", ARG1, ARG2, ARG3,
+                                                      ARG4, ARG5);
+   PRE_REG_READ2(int, "clone", unsigned long, flags, void *, child_stack);
+   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
+      if (VG_(tdict).track_pre_reg_read) {
+         PRA3("clone", int *, parent_tidptr);
+      }
+      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
+      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), VKI_PROT_WRITE)) {
+         badarg = True;
+      }
+   }
+   if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
+      if (VG_(tdict).track_pre_reg_read) {
+         PRA5("clone", int *, child_tidptr);
+      }
+      PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof (Int));
+      if (!VG_(am_is_valid_for_client)(ARG5, sizeof (Int), VKI_PROT_WRITE))
+         badarg = True;
+   }
+   if (badarg) {
+      SET_STATUS_Failure(VKI_EFAULT);
+      return;
+   }
+   cloneflags = ARG1;
+   if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
+      SET_STATUS_Failure(VKI_EINVAL);
+      return;
+   }
+   /* Only look at the flags we really care about */
+   switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
+           |VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
+      case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
+         /* thread creation */
+         SET_STATUS_from_SysRes(do_clone(tid,
+                                         ARG1,          /* flags */
+                                         (Addr)ARG2,    /* child SP */
+                                         (Int *)ARG3,   /* parent_tidptr */
+                                         (Int *)ARG5,   /* child_tidptr */
+                                         (Addr)ARG4));  /* child_tls */
+         break;
+
+      case VKI_CLONE_VFORK | VKI_CLONE_VM:  /* vfork */
+         /* FALLTHROUGH - assume vfork == fork */
+         cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
+      case 0:  /* plain fork */
+         SET_STATUS_from_SysRes(ML_(do_fork_clone)(tid,
+                                cloneflags,     /* flags */
+                                (Int *)ARG3,    /* parent_tidptr */
+                                (Int *)ARG5));  /* child_tidptr */
+         break;
+
+      default:
+         /* should we just ENOSYS? */
+         VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1);
+         VG_(message)(Vg_UserMsg, "\n");
+         VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
+         VG_(message)(Vg_UserMsg,
+                       " - via a threads library (LinuxThreads or NPTL)\n");
+         VG_(message)(Vg_UserMsg,
+                       " - via the implementation of fork or vfork\n");
+         VG_(unimplemented)("Valgrind does not support general clone().");
+   }
+   if (SUCCESS) {
+      if (ARG1 & VKI_CLONE_PARENT_SETTID)
+         POST_MEM_WRITE(ARG3, sizeof(Int));
+      if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
+         POST_MEM_WRITE(ARG5, sizeof(Int));
+      /* Thread creation was successful; let the child have the chance to run */
+      *flags |= SfYieldAfter;
+   }
+}
+
+PRE(sys_rt_sigreturn)
+{
+   /* See comments on PRE(sys_rt_sigreturn) in syswrap-s390x-linux.c for
+      an explanation of what follows. */
+   ThreadState* tst;
+   PRINT("sys_rt_sigreturn ( )");
+
+   vg_assert(VG_(is_valid_tid)(tid));
+   vg_assert(tid >= 1 && tid < VG_N_THREADS);
+   vg_assert(VG_(is_running_thread)(tid));
+
+   tst = VG_(get_ThreadState)(tid);
+
+   /* This is only so that the IA is (might be) useful to report if
+      something goes wrong in the sigreturn */
+   ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
+
+   /* Restore register state from frame and remove it */
+   VG_(sigframe_destroy)(tid, True);
+
+   /* Tell the driver not to update the guest state with the "result",
+      and set a bogus result to keep it happy. */
+   *flags |= SfNoWriteResult;
+   SET_STATUS_Success(0);
+
+   /* Check to see if any signals arose as a result of this. */
+   *flags |= SfPollAfter;
+}
+
+PRE(sys_set_thread_area)
+{
+   PRINT("set_thread_area (%lx)", ARG1);
+   PRE_REG_READ1(long, "set_thread_area", unsigned long, addr);
+   SET_STATUS_from_SysRes(sys_set_tls(tid, ARG1));
+}
+
+PRE(sys_pipe)
+{
+   PRINT("sys_pipe ( %#lx )", ARG1);
+   PRE_REG_READ1(int, "pipe", int *, filedes);
+   PRE_MEM_WRITE( "pipe(filedes)", ARG1, 2*sizeof(int) );
+}
+
+POST(sys_pipe)
+{
+   Int p0, p1;
+   vg_assert(SUCCESS);
+   p0 = RES;
+   p1 = sr_ResEx(status->sres);
+
+   if (!ML_(fd_allowed)(p0, "pipe", tid, True) ||
+       !ML_(fd_allowed)(p1, "pipe", tid, True)) {
+      VG_(close)(p0);
+      VG_(close)(p1);
+      SET_STATUS_Failure( VKI_EMFILE );
+   } else {
+      if (VG_(clo_track_fds)) {
+         ML_(record_fd_open_nameless)(tid, p0);
+         ML_(record_fd_open_nameless)(tid, p1);
+      }
+   }
+}
+
+#undef PRE
+#undef POST
+
+/* ---------------------------------------------------------------------
+   The mips64/Linux syscall table
+   ------------------------------------------------------------------ */
+
+/* Add an mips64-linux specific wrapper to a syscall table. */
+#define PLAX_(sysno, name)    WRAPPER_ENTRY_X_(mips_linux, sysno, name)
+#define PLAXY(sysno, name)    WRAPPER_ENTRY_XY(mips_linux, sysno, name)
+
+static SyscallTableEntry syscall_main_table[] = {
+   GENXY (__NR_read, sys_read),  /* 5000 */
+   GENX_ (__NR_write, sys_write),
+   GENXY (__NR_open, sys_open),
+   GENXY (__NR_close, sys_close),
+   GENXY (__NR_stat, sys_newstat),
+   GENXY (__NR_fstat, sys_newfstat),
+   GENXY (__NR_lstat, sys_newlstat),
+   GENXY (__NR_poll, sys_poll),
+   LINX_ (__NR_lseek, sys_lseek),
+   PLAX_ (__NR_mmap, sys_mmap),
+   GENXY (__NR_mprotect, sys_mprotect),
+   GENXY (__NR_munmap, sys_munmap),
+   GENX_ (__NR_brk, sys_brk),
+   LINXY (__NR_rt_sigaction, sys_rt_sigaction),
+   LINXY (__NR_rt_sigprocmask, sys_rt_sigprocmask),
+   LINXY (__NR_ioctl, sys_ioctl),
+   LINXY (__NR_eventfd2, sys_eventfd2),
+   LINXY (__NR_signalfd4, sys_signalfd4),
+   GENXY (__NR_pread64, sys_pread64),
+   GENX_ (__NR_pwrite64, sys_pwrite64),
+   GENXY (__NR_readv, sys_readv),
+   GENX_ (__NR_writev, sys_writev),
+   GENX_ (__NR_access, sys_access),
+   PLAXY (__NR_pipe, sys_pipe),
+   LINXY (__NR_pipe2, sys_pipe2),
+   GENX_ (__NR__newselect,sys_select),
+   LINX_ (__NR_sched_yield, sys_sched_yield),
+   GENX_ (__NR_mremap, sys_mremap),
+   GENX_ (__NR_msync, sys_msync),
+   GENXY (__NR_mincore, sys_mincore),
+   GENX_ (__NR_madvise, sys_madvise),
+   PLAX_ (__NR_shmget, sys_shmget),
+   /* PLAXY(__NR_shmat,sys_shmat), */
+   PLAXY (__NR_shmctl, sys_shmctl),
+   GENXY (__NR_dup, sys_dup),
+   GENXY (__NR_dup2, sys_dup2),
+   /* GENXY(__NR_dup3,sys_dup3), */
+   GENX_ (__NR_pause, sys_pause),
+   GENXY (__NR_nanosleep, sys_nanosleep),
+   GENXY (__NR_getitimer, sys_getitimer),
+   GENXY (__NR_setitimer, sys_setitimer),
+   GENX_ (__NR_alarm, sys_alarm),
+   GENX_ (__NR_getpid, sys_getpid),
+   /* LINX_(__NR_fallocate,sys_fallocate), */
+   LINXY (__NR_sendfile, sys_sendfile),
+   PLAXY (__NR_socket, sys_socket),
+   PLAX_ (__NR_connect, sys_connect),
+   PLAXY (__NR_accept, sys_accept),
+   /* PLAX_(__NR_accept4,sys_accept4), */
+   PLAX_ (__NR_sendto, sys_sendto),
+   PLAXY (__NR_recvfrom, sys_recvfrom),
+   PLAX_ (__NR_sendmsg, sys_sendmsg),
+   PLAXY (__NR_recvmsg, sys_recvmsg),
+   PLAX_ (__NR_shutdown, sys_shutdown),
+   PLAX_ (__NR_bind, sys_bind),
+   PLAX_ (__NR_listen, sys_listen),
+   PLAXY (__NR_getsockname, sys_getsockname),
+   PLAXY (__NR_getpeername, sys_getpeername),
+   PLAXY (__NR_socketpair, sys_socketpair),
+   PLAX_ (__NR_setsockopt, sys_setsockopt),
+   PLAXY (__NR_getsockopt, sys_getsockopt),
+   PLAX_ (__NR_clone, sys_clone),
+   GENX_ (__NR_fork, sys_fork),
+   GENX_ (__NR_execve, sys_execve),
+   GENX_ (__NR_exit, sys_exit),
+   GENXY (__NR_wait4, sys_wait4),
+   GENX_ (__NR_kill, sys_kill),
+   GENXY (__NR_uname, sys_newuname),
+   PLAX_ (__NR_semget, sys_semget),
+   PLAX_ (__NR_semop, sys_semop),
+   PLAXY (__NR_semctl, sys_semctl),
+   PLAXY (__NR_shmdt, sys_shmdt),
+   PLAX_ (__NR_msgget, sys_msgget),
+   PLAX_ (__NR_msgsnd, sys_msgsnd),
+   PLAXY (__NR_msgrcv, sys_msgrcv),
+   PLAXY (__NR_msgctl, sys_msgctl),
+   LINXY (__NR_fcntl, sys_fcntl),
+   GENX_ (__NR_flock, sys_flock),
+   GENX_ (__NR_fsync, sys_fsync),
+   GENX_ (__NR_fdatasync, sys_fdatasync),
+   GENX_ (__NR_truncate, sys_truncate),
+   GENX_ (__NR_ftruncate, sys_ftruncate),
+   GENXY (__NR_getdents, sys_getdents),
+   GENXY (__NR_getcwd, sys_getcwd),
+   GENX_ (__NR_chdir, sys_chdir),
+   GENX_ (__NR_fchdir, sys_fchdir),
+   GENX_ (__NR_rename, sys_rename),
+   GENX_ (__NR_mkdir, sys_mkdir),
+   GENX_ (__NR_rmdir, sys_rmdir),
+   GENXY (__NR_creat, sys_creat),
+   GENX_ (__NR_link, sys_link),
+   GENX_ (__NR_unlink, sys_unlink),
+   GENX_ (__NR_symlink, sys_symlink),
+   GENX_ (__NR_readlink, sys_readlink),
+   GENX_ (__NR_chmod, sys_chmod),
+   GENX_ (__NR_fchmod, sys_fchmod),
+   GENX_ (__NR_chown, sys_chown),
+   GENX_ (__NR_fchown, sys_fchown),
+   GENX_ (__NR_lchown, sys_lchown),
+   GENX_ (__NR_umask, sys_umask),
+   GENXY (__NR_gettimeofday, sys_gettimeofday),
+   GENXY (__NR_getrlimit, sys_getrlimit),
+   GENXY (__NR_getrusage, sys_getrusage),
+   LINXY (__NR_sysinfo, sys_sysinfo),
+   GENXY (__NR_times, sys_times),
+   PLAXY (__NR_ptrace, sys_ptrace),
+   GENX_ (__NR_getuid, sys_getuid),
+   LINXY (__NR_syslog, sys_syslog),
+   GENX_ (__NR_getgid, sys_getgid),
+   GENX_ (__NR_setuid, sys_setuid),
+   GENX_ (__NR_setgid, sys_setgid),
+   GENX_ (__NR_geteuid, sys_geteuid),
+   GENX_ (__NR_getegid, sys_getegid),
+   GENX_ (__NR_setpgid, sys_setpgid),
+   GENX_ (__NR_getppid, sys_getppid),
+   GENX_ (__NR_getpgrp, sys_getpgrp),
+   GENX_ (__NR_setsid, sys_setsid),
+   GENX_ (__NR_setreuid, sys_setreuid),
+   GENX_ (__NR_setregid, sys_setregid),
+   GENXY (__NR_getgroups, sys_getgroups),
+   GENX_ (__NR_setgroups, sys_setgroups),
+   LINX_ (__NR_setresuid, sys_setresuid),
+   LINXY (__NR_getresuid, sys_getresuid),
+   LINX_ (__NR_setresgid, sys_setresgid),
+   LINXY (__NR_getresgid, sys_getresgid),
+   GENX_ (__NR_getpgid, sys_getpgid),
+   LINX_ (__NR_setfsuid, sys_setfsuid),
+   LINX_ (__NR_setfsgid, sys_setfsgid),
+   GENX_ (__NR_getsid, sys_getsid),
+   LINXY (__NR_capget, sys_capget),
+   LINX_ (__NR_capset, sys_capset),
+   LINXY (__NR_rt_sigpending, sys_rt_sigpending),
+   LINXY (__NR_rt_sigtimedwait, sys_rt_sigtimedwait),
+   LINXY (__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo),
+   LINX_ (__NR_rt_sigsuspend, sys_rt_sigsuspend),
+   GENXY (__NR_sigaltstack, sys_sigaltstack),
+   LINX_ (__NR_utime, sys_utime),
+   GENX_ (__NR_mknod, sys_mknod),
+   LINX_ (__NR_personality, sys_personality),
+   PLAX_ (__NR_ustat, sys_ustat),
+   GENXY (__NR_statfs, sys_statfs),
+   GENXY (__NR_fstatfs, sys_fstatfs),
+   PLAX_ (__NR_sysfs, sys_sysfs),
+   GENX_ (__NR_getpriority, sys_getpriority),
+   GENX_ (__NR_setpriority, sys_setpriority),
+   LINXY (__NR_sched_setparam, sys_sched_setparam),
+   LINXY (__NR_sched_getparam, sys_sched_getparam),
+   LINX_ (__NR_sched_setscheduler, sys_sched_setscheduler),
+   LINX_ (__NR_sched_getscheduler, sys_sched_getscheduler),
+   LINX_ (__NR_sched_get_priority_max, sys_sched_get_priority_max),
+   LINX_ (__NR_sched_get_priority_min, sys_sched_get_priority_min),
+   PLAX_ (__NR_sched_rr_get_interval, sys_sched_rr_get_interval),
+   GENX_ (__NR_mlock, sys_mlock),
+   GENX_ (__NR_munlock, sys_munlock),
+   GENX_ (__NR_mlockall, sys_mlockall),
+   LINX_ (__NR_munlockall, sys_munlockall),
+   LINX_ (__NR_vhangup, sys_vhangup),
+   /* GENX_(__NR_pivot_root,sys_pivot_root), */
+   LINXY (__NR__sysctl, sys_sysctl),
+   LINXY (__NR_prctl, sys_prctl),
+   LINXY (__NR_adjtimex, sys_adjtimex),
+   GENX_ (__NR_setrlimit, sys_setrlimit),
+   GENX_ (__NR_chroot, sys_chroot),
+   GENX_ (__NR_sync, sys_sync),
+   GENX_ (__NR_acct, sys_acct),
+   GENX_ (__NR_settimeofday, sys_settimeofday),
+   LINX_ (__NR_mount, sys_mount),
+   LINX_ (__NR_umount2, sys_umount),
+   PLAX_ (__NR_swapon, sys_swapon),
+   PLAX_ (__NR_swapoff, sys_swapoff),
+   PLAX_ (__NR_reboot, sys_reboot),
+   PLAX_ (__NR_sethostname, sys_sethostname),
+   PLAX_ (__NR_setdomainname, sys_setdomainname),
+   GENX_ (__NR_create_module, sys_ni_syscall),
+   LINX_ (__NR_init_module, sys_init_module),
+   LINX_ (__NR_delete_module, sys_delete_module),
+   GENX_ (__NR_get_kernel_syms, sys_ni_syscall),
+   GENX_ (__NR_query_module, sys_ni_syscall),
+   LINX_ (__NR_quotactl, sys_quotactl),
+   /* GENX_(__NR_nfsservctl,sys_nfsservctl), */
+   GENXY (__NR_getpmsg, sys_getpmsg),
+   GENX_ (__NR_putpmsg, sys_putpmsg),
+   GENX_ (__NR_afs_syscall, sys_ni_syscall),
+   /* GENX_(__NR_reserved177,sys_reserved177), */
+   LINX_ (__NR_gettid, sys_gettid),
+   /* GENX_(__NR_readahead,sys_readahead), */
+   LINX_ (__NR_setxattr, sys_setxattr),
+   LINX_ (__NR_lsetxattr, sys_lsetxattr),
+   LINX_ (__NR_fsetxattr, sys_fsetxattr),
+   LINXY (__NR_getxattr, sys_getxattr),
+   LINXY (__NR_lgetxattr, sys_lgetxattr),
+   LINXY (__NR_fgetxattr, sys_fgetxattr),
+   LINXY (__NR_listxattr, sys_listxattr),
+   LINXY (__NR_llistxattr, sys_llistxattr),
+   LINXY (__NR_flistxattr, sys_flistxattr),
+   LINX_ (__NR_removexattr, sys_removexattr),
+   LINX_ (__NR_lremovexattr, sys_lremovexattr),
+   LINX_ (__NR_fremovexattr, sys_fremovexattr),
+   LINXY (__NR_tkill, sys_tkill),
+   /* GENX_(__NR_reserved193,sys_reserved193), */
+   LINXY (__NR_futex, sys_futex),
+   LINX_ (__NR_sched_setaffinity, sys_sched_setaffinity),
+   LINXY (__NR_sched_getaffinity, sys_sched_getaffinity),
+   PLAX_ (__NR_cacheflush, sys_cacheflush),
+   LINXY (__NR_io_setup, sys_io_setup),
+   LINX_ (__NR_io_destroy, sys_io_destroy),
+   LINXY (__NR_io_getevents, sys_io_getevents),
+   LINX_ (__NR_io_submit, sys_io_submit),
+   LINXY (__NR_io_cancel, sys_io_cancel),
+   LINX_ (__NR_exit_group, sys_exit_group),
+   /* LINXY (__NR_lookup_dcookie, sys_lookup_dcookie), */
+   LINXY (__NR_epoll_create, sys_epoll_create),
+   /* LINXY(__NR_epoll_create1,sys_epoll_create1), */
+   LINX_ (__NR_epoll_ctl, sys_epoll_ctl),
+   LINXY (__NR_epoll_wait, sys_epoll_wait),
+   PLAX_(__NR_rt_sigreturn,sys_rt_sigreturn),
+   /* LINXY(__NR_fcntl64,sys_fcntl64), */
+   LINX_ (__NR_set_tid_address, sys_set_tid_address),
+   PLAX_ (__NR_semtimedop, sys_semtimedop),
+   LINX_ (__NR_fadvise64, sys_fadvise64),
+   LINXY (__NR_timer_create, sys_timer_create),
+   LINXY (__NR_timer_settime, sys_timer_settime),
+   LINXY (__NR_timer_gettime, sys_timer_gettime),
+   LINX_ (__NR_timer_getoverrun, sys_timer_getoverrun),
+   LINX_ (__NR_timer_delete, sys_timer_delete),
+   LINX_ (__NR_clock_settime, sys_clock_settime),
+   LINXY (__NR_clock_gettime, sys_clock_gettime),
+   LINXY (__NR_clock_getres, sys_clock_getres),
+   LINXY (__NR_clock_nanosleep, sys_clock_nanosleep),
+   LINX_ (__NR_tgkill, sys_tgkill),
+   GENX_ (__NR_utimes, sys_utimes),
+   LINX_ (__NR_mbind, sys_mbind),
+   LINXY (__NR_get_mempolicy, sys_get_mempolicy),
+   LINX_ (__NR_set_mempolicy, sys_set_mempolicy),
+   LINXY (__NR_mq_open, sys_mq_open),
+   LINX_ (__NR_mq_unlink, sys_mq_unlink),
+   LINX_ (__NR_mq_timedsend, sys_mq_timedsend),
+   LINXY (__NR_mq_timedreceive, sys_mq_timedreceive),
+   LINX_ (__NR_mq_notify, sys_mq_notify),
+   LINXY (__NR_mq_getsetattr, sys_mq_getsetattr),
+   GENX_ (__NR_vserver, sys_ni_syscall),
+   LINXY (__NR_waitid, sys_waitid),
+   LINX_ (__NR_add_key, sys_add_key),
+   LINX_ (__NR_request_key, sys_request_key),
+   LINXY (__NR_keyctl, sys_keyctl),
+   PLAX_ (__NR_set_thread_area, sys_set_thread_area),
+   LINX_ (__NR_inotify_init, sys_inotify_init),
+   LINX_ (__NR_inotify_add_watch, sys_inotify_add_watch),
+   LINX_ (__NR_inotify_rm_watch, sys_inotify_rm_watch),
+   LINXY (__NR_openat, sys_openat),
+   LINX_ (__NR_mkdirat, sys_mkdirat),
+   LINX_ (__NR_mknodat, sys_mknodat),
+   LINX_ (__NR_fchownat, sys_fchownat),
+   LINX_ (__NR_futimesat, sys_futimesat),
+   LINX_ (__NR_unlinkat, sys_unlinkat),
+   LINX_ (__NR_renameat, sys_renameat),
+   LINX_ (__NR_linkat, sys_linkat),
+   LINX_ (__NR_symlinkat, sys_symlinkat),
+   LINX_ (__NR_readlinkat, sys_readlinkat),
+   LINX_ (__NR_fchmodat, sys_fchmodat),
+   LINX_ (__NR_faccessat, sys_faccessat),
+   LINX_ (__NR_pselect6, sys_pselect6),
+   LINXY (__NR_ppoll, sys_ppoll),
+   PLAX_ (__NR_unshare, sys_unshare),
+   PLAX_ (__NR_splice, sys_splice),
+   LINX_ (__NR_sync_file_range, sys_sync_file_range),
+   PLAX_ (__NR_tee, sys_tee),
+   PLAX_ (__NR_vmsplice, sys_vmsplice),
+   LINX_ (__NR_set_robust_list, sys_set_robust_list),
+   LINXY (__NR_get_robust_list, sys_get_robust_list),
+   LINXY (__NR_epoll_pwait, sys_epoll_pwait),
+   LINX_ (__NR_ioprio_set, sys_ioprio_set),
+   LINX_ (__NR_ioprio_get, sys_ioprio_get),
+   LINX_ (__NR_utimensat, sys_utimensat),
+   LINXY (__NR_signalfd, sys_signalfd),
+   LINXY (__NR_eventfd, sys_eventfd),
+   LINX_ (__NR_fallocate, sys_fallocate),
+   LINXY (__NR_timerfd_create, sys_timerfd_create),
+   LINXY (__NR_timerfd_gettime, sys_timerfd_gettime),
+   LINXY (__NR_timerfd_settime, sys_timerfd_settime)
+};
+
+SyscallTableEntry * ML_(get_linux_syscall_entry) ( UInt sysno )
+{
+   const UInt syscall_main_table_size
+      = sizeof(syscall_main_table) / sizeof(syscall_main_table[0]);
+
+   if (sysno < syscall_main_table_size) {
+      SyscallTableEntry * sys = &syscall_main_table[sysno];
+      if (sys->before == NULL)
+         return NULL;  /* no entry */
+      else
+         return sys;
+   }
+   /* Can't find a wrapper */
+   return NULL;
+}
+
+#endif  /* defined(VGP_mips64_linux) */
+
+/*--------------------------------------------------------------------*/ 
+/*--- end                                   syswrap-mips64-linux.c ---*/ 
+/*--------------------------------------------------------------------*/ 
diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S
index d41e2d6..f2a86ea 100644
--- a/coregrind/m_trampoline.S
+++ b/coregrind/m_trampoline.S
@@ -1079,6 +1079,62 @@
 #	undef UD2_1024
 #	undef UD2_PAGE
 
+/*---------------------- mips64-linux ----------------------*/
+#else
+#if defined(VGP_mips64_linux)
+
+#       define UD2_16     trap ; trap ; trap; trap
+#       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
+#       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
+#       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
+#       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
+
+.global VG_(trampoline_stuff_start)
+VG_(trampoline_stuff_start):
+
+.global VG_(mips64_linux_SUBST_FOR_rt_sigreturn)
+VG_(mips64_linux_SUBST_FOR_rt_sigreturn):
+        li $2,__NR_rt_sigreturn
+        syscall
+        nop
+        .long 0	/*illegal insn*/
+
+/* There's no particular reason that this needs to be handwritten
+   assembly, but since that's what this file contains, here's a
+   simple strlen implementation (written in C and compiled by gcc.)
+*/
+.global VG_(mips64_linux_REDIR_FOR_strlen)
+.type   VG_(mips64_linux_REDIR_FOR_strlen), @function
+VG_(mips64_linux_REDIR_FOR_strlen):
+        lbu $12, 0($4)
+        li  $13, 0
+        beq $12, $0, M01 
+        nop
+
+M02: 
+        addiu $13, $13, 1 
+        addiu $4, $4, 1 
+        lbu $12, 0($4) 
+        bne $12, $0, M02 
+        nop 
+
+M01: 
+        move $2, $13 
+        jr $31 
+        nop
+
+.size VG_(mips64_linux_REDIR_FOR_strlen), .-VG_(mips64_linux_REDIR_FOR_strlen)
+
+.global VG_(trampoline_stuff_end)
+VG_(trampoline_stuff_end):
+
+
+#	undef UD2_16
+#	undef UD2_64
+#	undef UD2_256
+#	undef UD2_1024
+#	undef UD2_PAGE
+
 /*---------------- unknown ----------------*/
 #else
 #  error Unknown platform
@@ -1091,6 +1147,7 @@
 #endif
 #endif
 #endif
+#endif
 
 #if defined(VGO_linux)
 /* Let the linker know we don't need an executable stack */
diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c
index 6f8eeef..5088c36 100644
--- a/coregrind/m_translate.c
+++ b/coregrind/m_translate.c
@@ -749,7 +749,8 @@
 
 static Bool translations_allowable_from_seg ( NSegment const* seg )
 {
-#  if defined(VGA_x86) || defined(VGA_s390x) || defined(VGA_mips32)
+#  if defined(VGA_x86) || defined(VGA_s390x) || defined(VGA_mips32) \
+      || defined(VGA_mips64)
    Bool allowR = True;
 #  else
    Bool allowR = False;
@@ -1211,11 +1212,16 @@
          nraddr_szB == 8 ? mkU64(0) : mkU32(0)
       )
    );
-#  if defined(VGP_mips32_linux)
    // t9 needs to be set to point to the start of the redirected function.
+#  if defined(VGP_mips32_linux)
    VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
-   Int    offB_GPR25 = offsetof(VexGuestMIPS32State,guest_r25);
-   addStmtToIRSB( bb, IRStmt_Put( offB_GPR25, mkU32( closure->readdr )) );
+   Int offB_GPR25 = offsetof(VexGuestMIPS32State, guest_r25);
+   addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU32(closure->readdr)));
+#  endif
+#  if defined(VGP_mips64_linux)
+   VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
+   Int offB_GPR25 = offsetof(VexGuestMIPS64State, guest_r25);
+   addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU64(closure->readdr)));
 #  endif
 #  if defined(VG_PLAT_USES_PPCTOC)
    { VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
@@ -1253,10 +1259,14 @@
             : IRExpr_Const(IRConst_U32( (UInt)closure->nraddr ))
       )
    );
-#  if defined(VGP_mips32_linux)
    // t9 needs to be set to point to the start of the redirected function.
-   Int    offB_GPR25 = offsetof(VexGuestMIPS32State,guest_r25);
-   addStmtToIRSB( bb, IRStmt_Put( offB_GPR25, mkU32( closure->readdr )) );
+#  if defined(VGP_mips32_linux)
+   Int offB_GPR25 = offsetof(VexGuestMIPS32State, guest_r25);
+   addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU32(closure->readdr)));
+#  endif
+#  if defined(VGP_mips64_linux)
+   Int offB_GPR25 = offsetof(VexGuestMIPS64State, guest_r25);
+   addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU64(closure->readdr)));
 #  endif
 #  if defined(VGP_ppc64_linux)
    addStmtToIRSB( 
diff --git a/coregrind/m_ume/elf.c b/coregrind/m_ume/elf.c
index 4686e43..9a43bf5 100644
--- a/coregrind/m_ume/elf.c
+++ b/coregrind/m_ume/elf.c
@@ -338,8 +338,14 @@
          which totally screws things up, because nothing else can go
          there.  So bump the hacky load addess along by 0x8000, to
          0x108000. */
+      /* Later .. on mips64 we can't use 0x108000, because mapelf will fail. */
+#if defined(VGP_mips64_linux)
+      if (ebase < 0x100000)
+         ebase = 0x100000;
+#else
       if (ebase < 0x108000)
          ebase = 0x108000;
+#endif
    }
 
    info->phnum = e->e.e_phnum;
diff --git a/coregrind/pub_core_aspacemgr.h b/coregrind/pub_core_aspacemgr.h
index 17b33f6..b6821f3 100644
--- a/coregrind/pub_core_aspacemgr.h
+++ b/coregrind/pub_core_aspacemgr.h
@@ -345,7 +345,7 @@
 // protects such stacks.
 
 #if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
-    || defined(VGP_mips32_linux)
+    || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
 # define VG_STACK_GUARD_SZB  65536  // 1 or 16 pages
 # define VG_STACK_ACTIVE_SZB (4096 * 256) // 1Mb
 #else
diff --git a/coregrind/pub_core_basics.h b/coregrind/pub_core_basics.h
index 4431b38..a086986 100644
--- a/coregrind/pub_core_basics.h
+++ b/coregrind/pub_core_basics.h
@@ -62,6 +62,8 @@
 #  include "libvex_guest_s390x.h"
 #elif defined(VGA_mips32)
 #  include "libvex_guest_mips32.h"
+#elif defined(VGA_mips64)
+#  include "libvex_guest_mips64.h"
 #else
 #  error Unknown arch
 #endif
@@ -115,6 +117,11 @@
             UInt r31;  /* Return address of the last subroutine call */
             UInt r28;
          } MIPS32;
+         struct {
+            ULong r30;  /* Stack frame pointer or subroutine variable */
+            ULong r31;  /* Return address of the last subroutine call */
+            ULong r28;
+         } MIPS64;
       } misc;
    }
    UnwindStartRegs;
diff --git a/coregrind/pub_core_debuginfo.h b/coregrind/pub_core_debuginfo.h
index bcf1a74..6705bff 100644
--- a/coregrind/pub_core_debuginfo.h
+++ b/coregrind/pub_core_debuginfo.h
@@ -120,7 +120,7 @@
 typedef
    struct { Addr ia; Addr sp; Addr fp; Addr lr;}
    D3UnwindRegs;
-#elif defined(VGA_mips32)
+#elif defined(VGA_mips32) || defined(VGA_mips64)
 typedef
    struct { Addr pc; Addr sp; Addr fp; Addr ra; }
    D3UnwindRegs;
diff --git a/coregrind/pub_core_machine.h b/coregrind/pub_core_machine.h
index 11e590a..97324a3 100644
--- a/coregrind/pub_core_machine.h
+++ b/coregrind/pub_core_machine.h
@@ -86,6 +86,17 @@
 #  define VG_ELF_MACHINE      EM_MIPS
 #  define VG_ELF_CLASS        ELFCLASS32
 #  undef  VG_PLAT_USES_PPCTOC
+#elif defined(VGP_mips64_linux)
+#  if defined (VG_LITTLEENDIAN)
+#    define VG_ELF_DATA2XXX     ELFDATA2LSB
+#  elif defined (VG_BIGENDIAN)
+#    define VG_ELF_DATA2XXX     ELFDATA2MSB
+#  else
+#    error "Unknown endianness"
+#  endif
+#  define VG_ELF_MACHINE      EM_MIPS
+#  define VG_ELF_CLASS        ELFCLASS64
+#  undef  VG_PLAT_USES_PPCTOC
 #else
 #  error Unknown platform
 #endif
@@ -119,6 +130,10 @@
 #  define VG_INSTR_PTR        guest_PC
 #  define VG_STACK_PTR        guest_r29
 #  define VG_FRAME_PTR        guest_r30
+#elif defined(VGA_mips64)
+#  define VG_INSTR_PTR        guest_PC
+#  define VG_STACK_PTR        guest_r29
+#  define VG_FRAME_PTR        guest_r30
 #else
 #  error Unknown arch
 #endif
diff --git a/coregrind/pub_core_mallocfree.h b/coregrind/pub_core_mallocfree.h
index 54b4020..814d230 100644
--- a/coregrind/pub_core_mallocfree.h
+++ b/coregrind/pub_core_mallocfree.h
@@ -71,7 +71,8 @@
 // greater than 8.
 #if   defined(VGP_x86_linux)   || \
       defined(VGP_arm_linux)   || \
-      defined(VGP_mips32_linux)
+      defined(VGP_mips32_linux) || \
+      defined(VGP_mips64_linux)
 #  define VG_MIN_MALLOC_SZB        8
 // Nb: We always use 16 bytes for Darwin, even on 32-bits, so it can be used
 // for any AltiVec- or SSE-related type.  This matches the Darwin libc.
diff --git a/coregrind/pub_core_syscall.h b/coregrind/pub_core_syscall.h
index 9cd0ea8..1648f8c 100644
--- a/coregrind/pub_core_syscall.h
+++ b/coregrind/pub_core_syscall.h
@@ -81,6 +81,8 @@
 extern SysRes VG_(mk_SysRes_s390x_linux) ( Long val );
 extern SysRes VG_(mk_SysRes_mips32_linux)( UWord v0, UWord v1,
                                            UWord a3 );
+extern SysRes VG_(mk_SysRes_mips64_linux)( ULong v0, ULong v1,
+                                           ULong a3 );
 extern SysRes VG_(mk_SysRes_Error)       ( UWord val );
 extern SysRes VG_(mk_SysRes_Success)     ( UWord val );
 
diff --git a/coregrind/pub_core_threadstate.h b/coregrind/pub_core_threadstate.h
index 0bd9927..7e7fa87 100644
--- a/coregrind/pub_core_threadstate.h
+++ b/coregrind/pub_core_threadstate.h
@@ -89,6 +89,8 @@
    typedef VexGuestS390XState VexGuestArchState;
 #elif defined(VGA_mips32)
    typedef VexGuestMIPS32State VexGuestArchState;
+#elif defined(VGA_mips64)
+   typedef VexGuestMIPS64State VexGuestArchState;
 #else
 #  error Unknown architecture
 #endif
diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h
index 209213f..b536ede 100644
--- a/coregrind/pub_core_trampoline.h
+++ b/coregrind/pub_core_trampoline.h
@@ -133,6 +133,11 @@
 extern UInt  VG_(mips32_linux_REDIR_FOR_strlen)( void* );
 #endif
 
+#if defined(VGP_mips64_linux)
+extern Addr  VG_(mips64_linux_SUBST_FOR_rt_sigreturn);
+extern UInt  VG_(mips64_linux_REDIR_FOR_strlen)( void* );
+#endif
+
 #endif   // __PUB_CORE_TRAMPOLINE_H
 
 /*--------------------------------------------------------------------*/
diff --git a/coregrind/pub_core_transtab_asm.h b/coregrind/pub_core_transtab_asm.h
index 6473294..c3b3855 100644
--- a/coregrind/pub_core_transtab_asm.h
+++ b/coregrind/pub_core_transtab_asm.h
@@ -62,7 +62,8 @@
 #elif defined(VGA_s390x) || defined(VGA_arm)
 #  define VG_TT_FAST_HASH(_addr)  ((((UWord)(_addr)) >> 1) & VG_TT_FAST_MASK)
 
-#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_mips32)
+#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_mips32) \
+      || defined(VGA_mips64)
 #  define VG_TT_FAST_HASH(_addr)  ((((UWord)(_addr)) >> 2) & VG_TT_FAST_MASK)
 
 #else
diff --git a/coregrind/vgdb.c b/coregrind/vgdb.c
index b46c4b9..fed0d92 100644
--- a/coregrind/vgdb.c
+++ b/coregrind/vgdb.c
@@ -81,7 +81,7 @@
    specific code and/or some OS specific code. */
 #if defined(VGA_arm) || defined(VGA_x86) || defined(VGA_amd64) \
     || defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) \
-    || defined(VGP_mips32_linux)
+    || defined(VGP_mips32_linux) || defined(VGA_mips64)
 #define PTRACEINVOKER
 #else
 I_die_here : (PTRACEINVOKER) architecture missing in vgdb.c
@@ -926,6 +926,8 @@
    sp = user_mod.regs.gprs[15];
 #elif defined(VGA_mips32)
    sp = user_mod.regs[29*2];
+#elif defined(VGA_mips64)
+   sp = user_mod.regs[29];
 #else
    I_die_here : (sp) architecture missing in vgdb.c
 #endif
@@ -1011,6 +1013,8 @@
       user_mod.regs[34*2+1] = 0;
       user_mod.regs[25*2] = shared32->invoke_gdbserver;
       user_mod.regs[25*2+1] = 0;
+#elif defined(VGA_mips64)
+      assert(0); // cannot vgdb a 32 bits executable with a 64 bits exe
 #else
       I_die_here : architecture missing in vgdb.c
 #endif
@@ -1092,6 +1096,13 @@
       user_mod.regs.psw.addr = shared64->invoke_gdbserver;
 #elif defined(VGA_mips32)
       assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe
+#elif defined(VGA_mips64)
+      /* put check arg in register 4 */
+      user_mod.regs[4] = check;
+      /* put NULL return address in ra */
+      user_mod.regs[31] = bad_return;
+      user_mod.regs[34] = shared64->invoke_gdbserver;
+      user_mod.regs[25] = shared64->invoke_gdbserver;
 #else
       I_die_here: architecture missing in vgdb.c
 #endif