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)(®s, 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