|
From: <sv...@va...> - 2012-06-07 09:13:36
|
sewardj 2012-06-07 10:13:21 +0100 (Thu, 07 Jun 2012)
New Revision: 12616
Log:
Merge in a port for mips32-linux, by Petar Jovanovic and Dejan Jevtic,
mip...@rt..., Bug 270777.
Valgrind: changes to existing files.
Modified files:
trunk/Makefile.all.am
trunk/Makefile.tool.am
trunk/Makefile.vex.am
trunk/cachegrind/Makefile.am
trunk/cachegrind/cg_branchpred.c
trunk/cachegrind/tests/filter_stderr
trunk/callgrind/Makefile.am
trunk/callgrind/tests/filter_stderr
trunk/configure.in
trunk/coregrind/Makefile.am
trunk/coregrind/launcher-linux.c
trunk/coregrind/link_tool_exe_linux.in
trunk/coregrind/m_aspacemgr/aspacemgr-common.c
trunk/coregrind/m_aspacemgr/aspacemgr-linux.c
trunk/coregrind/m_coredump/coredump-elf.c
trunk/coregrind/m_debugger.c
trunk/coregrind/m_debuginfo/d3basics.c
trunk/coregrind/m_debuginfo/debuginfo.c
trunk/coregrind/m_debuginfo/priv_storage.h
trunk/coregrind/m_debuginfo/readdwarf.c
trunk/coregrind/m_debuginfo/readdwarf3.c
trunk/coregrind/m_debuginfo/readelf.c
trunk/coregrind/m_debuginfo/storage.c
trunk/coregrind/m_debuglog.c
trunk/coregrind/m_gdbserver/target.c
trunk/coregrind/m_gdbserver/valgrind_low.h
trunk/coregrind/m_initimg/initimg-linux.c
trunk/coregrind/m_libcassert.c
trunk/coregrind/m_libcfile.c
trunk/coregrind/m_libcproc.c
trunk/coregrind/m_machine.c
trunk/coregrind/m_main.c
trunk/coregrind/m_redir.c
trunk/coregrind/m_scheduler/scheduler.c
trunk/coregrind/m_signals.c
trunk/coregrind/m_stacktrace.c
trunk/coregrind/m_syscall.c
trunk/coregrind/m_syswrap/priv_types_n_macros.h
trunk/coregrind/m_syswrap/syswrap-linux.c
trunk/coregrind/m_syswrap/syswrap-main.c
trunk/coregrind/m_trampoline.S
trunk/coregrind/m_translate.c
trunk/coregrind/pub_core_aspacemgr.h
trunk/coregrind/pub_core_basics.h
trunk/coregrind/pub_core_debuginfo.h
trunk/coregrind/pub_core_machine.h
trunk/coregrind/pub_core_mallocfree.h
trunk/coregrind/pub_core_syscall.h
trunk/coregrind/pub_core_threadstate.h
trunk/coregrind/pub_core_trampoline.h
trunk/coregrind/pub_core_transtab_asm.h
trunk/coregrind/vgdb.c
trunk/drd/drd_bitmap.h
trunk/drd/drd_clientreq.c
trunk/drd/drd_load_store.c
trunk/drd/drd_thread.c
trunk/helgrind/tests/annotate_hbefore.c
trunk/helgrind/tests/tc07_hbl1.c
trunk/helgrind/tests/tc08_hbl2.c
trunk/helgrind/tests/tc11_XCHG.c
trunk/include/Makefile.am
trunk/include/pub_tool_basics.h
trunk/include/pub_tool_machine.h
trunk/include/pub_tool_vkiscnums_asm.h
trunk/include/valgrind.h
trunk/include/vki/vki-linux.h
trunk/memcheck/mc_machine.c
trunk/memcheck/tests/atomic_incs.c
trunk/memcheck/tests/memalign_test.c
trunk/none/tests/Makefile.am
trunk/none/tests/allexec_prepare_prereq
trunk/tests/arch_test.c
trunk/tests/platform_test
trunk/tests/sys_mman.h
Modified: trunk/none/tests/Makefile.am (+4 -1)
===================================================================
--- trunk/none/tests/Makefile.am 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/none/tests/Makefile.am 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -22,6 +22,9 @@
if VGCONF_ARCHS_INCLUDE_S390X
SUBDIRS += s390x
endif
+if VGCONF_ARCHS_INCLUDE_MIPS32
+SUBDIRS += mips32
+endif
# OS-specific tests
if VGCONF_OS_IS_LINUX
@@ -36,7 +39,7 @@
SUBDIRS += x86-linux
endif
-DIST_SUBDIRS = x86 amd64 ppc32 ppc64 arm s390x linux darwin x86-linux .
+DIST_SUBDIRS = x86 amd64 ppc32 ppc64 arm s390x mips32 linux darwin x86-linux .
dist_noinst_SCRIPTS = \
filter_cmdline0 \
Modified: trunk/memcheck/tests/atomic_incs.c (+97 -1)
===================================================================
--- trunk/memcheck/tests/atomic_incs.c 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/memcheck/tests/atomic_incs.c 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -110,6 +110,48 @@
: "+m" (*p), "+m" (dummy)
: "d" (n)
: "cc", "memory", "0", "1");
+#elif defined(VGA_mips32)
+#if defined (_MIPSEL)
+ unsigned int block[3]
+ = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "lw $t2, 4($t0)" "\n\t" // n
+ "ll $t3, 0($t1)" "\n\t"
+ "addu $t3, $t3, $t2" "\n\t"
+ "andi $t3, $t3, 0xFF" "\n\t"
+ "sc $t3, 0($t1)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t"
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3"
+ );
+ } while (block[2] != 1);
+#elif defined (_MIPSEB)
+ unsigned int block[3]
+ = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "lw $t2, 4($t0)" "\n\t" // n
+ "li $t4, 0x000000FF" "\n\t"
+ "ll $t3, 0($t1)" "\n\t"
+ "addu $t3, $t3, $t2" "\n\t"
+ "and $t3, $t3, $t4" "\n\t"
+ "wsbh $t4, $t3" "\n\t"
+ "rotr $t4, $t4, 16" "\n\t"
+ "or $t3, $t4, $t3" "\n\t"
+ "sc $t3, 0($t1)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t"
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3", "t4"
+ );
+ } while (block[2] != 1);
+#endif
#else
# error "Unsupported arch"
#endif
@@ -203,6 +245,43 @@
: "+m" (*p), "+m" (dummy)
: "d" (n)
: "cc", "memory", "0", "1");
+#elif defined(VGA_mips32)
+#if defined (_MIPSEL)
+ unsigned int block[3]
+ = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "lw $t2, 4($t0)" "\n\t" // n
+ "ll $t3, 0($t1)" "\n\t"
+ "addu $t3, $t3, $t2" "\n\t"
+ "andi $t3, $t3, 0xFFFF" "\n\t"
+ "sc $t3, 0($t1)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t"
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3"
+ );
+ } while (block[2] != 1);
+#elif defined (_MIPSEB)
+ unsigned int block[3]
+ = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "li $t2, 32694" "\n\t" // n
+ "li $t3, 0x1" "\n\t"
+ "sll $t2, $t2, 16" "\n\t"
+ "sw $t2, 0($t1)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t"
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3"
+ );
+ } while (block[2] != 1);
+#endif
#else
# error "Unsupported arch"
#endif
@@ -289,6 +368,23 @@
: "+m" (*p)
: "d" (n)
: "cc", "memory", "0", "1");
+#elif defined(VGA_mips32)
+ unsigned int block[3]
+ = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "lw $t2, 4($t0)" "\n\t" // n
+ "ll $t3, 0($t1)" "\n\t"
+ "addu $t3, $t3, $t2" "\n\t"
+ "sc $t3, 0($t1)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t"
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3"
+ );
+ } while (block[2] != 1);
#else
# error "Unsupported arch"
#endif
@@ -296,7 +392,7 @@
__attribute__((noinline)) void atomic_add_64bit ( long long int* p, int n )
{
-#if defined(VGA_x86) || defined(VGA_ppc32)
+#if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32)
/* do nothing; is not supported */
#elif defined(VGA_amd64)
// this is a bit subtle. It relies on the fact that, on a 64-bit platform,
Modified: trunk/coregrind/m_redir.c (+11 -0)
===================================================================
--- trunk/coregrind/m_redir.c 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/coregrind/m_redir.c 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -1358,6 +1358,17 @@
# elif defined(VGP_s390x_linux)
/* nothing so far */
+# elif defined(VGP_mips32_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_(mips32_linux_REDIR_FOR_strlen),
+ complain_about_stripped_glibc_ldso
+ );
+ }
+
# else
# error Unknown platform
# endif
Modified: trunk/include/pub_tool_basics.h (+10 -3)
===================================================================
--- trunk/include/pub_tool_basics.h 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/include/pub_tool_basics.h 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -163,6 +163,7 @@
typedef
struct {
UWord _val;
+ UWord _valEx; // only used on mips-linux
Bool _isError;
}
SysRes;
@@ -197,6 +198,9 @@
static inline UWord sr_Res ( SysRes sr ) {
return sr._isError ? 0 : sr._val;
}
+static inline UWord sr_ResEx ( SysRes sr ) {
+ return sr._isError ? 0 : sr._valEx;
+}
static inline UWord sr_ResHI ( SysRes sr ) {
return 0;
}
@@ -264,9 +268,11 @@
#undef VG_BIGENDIAN
#undef VG_LITTLEENDIAN
-#if defined(VGA_x86) || defined(VGA_amd64) || defined (VGA_arm)
+#if defined(VGA_x86) || defined(VGA_amd64) || defined (VGA_arm) \
+ || (defined(VGA_mips32) && defined (_MIPSEL))
# define VG_LITTLEENDIAN 1
-#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x)
+#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) \
+ || (defined(VGA_mips32) && defined (_MIPSEB))
# define VG_BIGENDIAN 1
#else
# error Unknown arch
@@ -276,7 +282,8 @@
#if defined(VGA_x86)
# define VG_REGPARM(n) __attribute__((regparm(n)))
#elif defined(VGA_amd64) || defined(VGA_ppc32) \
- || defined(VGA_ppc64) || defined(VGA_arm) || defined(VGA_s390x)
+ || defined(VGA_ppc64) || defined(VGA_arm) || defined(VGA_s390x) \
+ || defined(VGA_mips32)
# define VG_REGPARM(n) /* */
#else
# error Unknown arch
Modified: trunk/helgrind/tests/annotate_hbefore.c (+32 -0)
===================================================================
--- trunk/helgrind/tests/annotate_hbefore.c 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/helgrind/tests/annotate_hbefore.c 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -186,6 +186,38 @@
return cc == 0;
}
+#elif defined(VGA_mips32)
+
+// mips
+/* return 1 if success, 0 if failure */
+UWord do_acasW ( UWord* addr, UWord expected, UWord nyu )
+{
+ UWord old, success;
+ UWord block[3] = { (UWord)addr, nyu, expected};
+
+ __asm__ __volatile__(
+ ".set noreorder" "\n\t"
+ "lw $t0, 0(%1)" "\n\t"
+ "lw $t2, 8(%1)" "\n\t"
+ "lw $t3, 4(%1)" "\n\t"
+ "ll $t1, 0($t0)" "\n\t"
+ "bne $t1, $t2, exit_0" "\n\t"
+ "sc $t3, 0($t0)" "\n\t"
+ "move %0, $t3" "\n\t"
+ "b exit" "\n\t"
+ "nop" "\n\t"
+ "exit_0:" "\n\t"
+ "move %0, $0" "\n\t"
+ "exit:" "\n\t"
+ : /*out*/ "=r"(success)
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "t0", "t1", "t2", "t3", "memory"
+ );
+
+ assert(success == 0 || success == 1);
+ return success;
+}
+
#endif
void atomic_incW ( UWord* w )
Modified: trunk/coregrind/link_tool_exe_linux.in (+12 -1)
===================================================================
--- trunk/coregrind/link_tool_exe_linux.in 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/coregrind/link_tool_exe_linux.in 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -68,8 +68,19 @@
# so, build up the complete command here:
# 'cc' -static -Ttext='ala' 'restargs'
-my $cmd="$cc -static -Wl,-Ttext=$ala";
+# For mips we need to use "--section-start=.reginfo=$ala" because
+# "--section-start=.reginfo=$ala" will put all the sections to the
+# specificed address ($ala)
+my $x=`$cc -v 2>&1 | grep Target | sed 's/Target: //g'`;
+my $arch=substr($x, 0, index($x, '-'));
+my $cmd;
+if (($arch eq 'mips') || ($arch eq 'mipsel')) {
+ $cmd = "$cc -static -Wl,--section-start=.reginfo=$ala";
+} else {
+ $cmd = "$cc -static -Wl,-Ttext=$ala";
+}
+
# Add the rest of the parameters
foreach my $n (2 .. $#ARGV) {
$cmd = "$cmd $ARGV[$n]";
Modified: trunk/coregrind/m_initimg/initimg-linux.c (+14 -0)
===================================================================
--- trunk/coregrind/m_initimg/initimg-linux.c 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/coregrind/m_initimg/initimg-linux.c 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -1081,6 +1081,20 @@
VG_TRACK(post_reg_write, Vg_CoreStartup, /*tid*/1, VG_O_INSTR_PTR, 8);
return;
+# elif defined(VGP_mips32_linux)
+ vg_assert(0 == sizeof(VexGuestMIPS32State) % 16);
+ /* Zero out the initial state, and set up the simulated FPU in a
+ sane way. */
+ LibVEX_GuestMIPS32_initialise(&arch->vex);
+
+ /* Zero out the shadow areas. */
+ VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestMIPS32State));
+ VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestMIPS32State));
+
+ 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
Modified: trunk/coregrind/m_libcassert.c (+25 -0)
===================================================================
--- trunk/coregrind/m_libcassert.c 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/coregrind/m_libcassert.c 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -152,6 +152,31 @@
(srP)->misc.S390X.r_fp = fp; \
(srP)->misc.S390X.r_lr = lr; \
}
+#elif defined(VGP_mips32_linux)
+# define GET_STARTREGS(srP) \
+ { UInt 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.MIPS32.r30 = (ULong)fp; \
+ (srP)->misc.MIPS32.r31 = (ULong)ra; \
+ (srP)->misc.MIPS32.r28 = (ULong)gp; \
+ }
#else
# error Unknown platform
#endif
Modified: trunk/include/vki/vki-linux.h (+7 -0)
===================================================================
--- trunk/include/vki/vki-linux.h 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/include/vki/vki-linux.h 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -91,6 +91,8 @@
# include "vki-posixtypes-arm-linux.h"
#elif defined(VGA_s390x)
# include "vki-posixtypes-s390x-linux.h"
+#elif defined(VGA_mips32)
+# include "vki-posixtypes-mips32-linux.h"
#else
# error Unknown platform
#endif
@@ -211,6 +213,8 @@
# include "vki-arm-linux.h"
#elif defined(VGA_s390x)
# include "vki-s390x-linux.h"
+#elif defined(VGA_mips32)
+# include "vki-mips32-linux.h"
#else
# error Unknown platform
#endif
@@ -383,6 +387,8 @@
// From linux-2.6.8.1/include/asm-generic/siginfo.h
//----------------------------------------------------------------------
+// Some archs, such as MIPS, have non-standard vki_siginfo.
+#ifndef HAVE_ARCH_SIGINFO_T
typedef union vki_sigval {
int sival_int;
void __user *sival_ptr;
@@ -462,6 +468,7 @@
} _sigpoll;
} _sifields;
} vki_siginfo_t;
+#endif
#define __VKI_SI_FAULT 0
Modified: trunk/coregrind/m_machine.c (+121 -2)
===================================================================
--- trunk/coregrind/m_machine.c 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/coregrind/m_machine.c 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -103,6 +103,15 @@
= VG_(threads)[tid].arch.vex.guest_r11;
regs->misc.S390X.r_lr
= VG_(threads)[tid].arch.vex.guest_r14;
+# elif defined(VGA_mips32)
+ regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC;
+ regs->r_sp = VG_(threads)[tid].arch.vex.guest_r29;
+ regs->misc.MIPS32.r30
+ = VG_(threads)[tid].arch.vex.guest_r30;
+ regs->misc.MIPS32.r31
+ = VG_(threads)[tid].arch.vex.guest_r31;
+ regs->misc.MIPS32.r28
+ = VG_(threads)[tid].arch.vex.guest_r28;
# else
# error "Unknown arch"
# endif
@@ -132,6 +141,9 @@
# 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)
+ VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
+ VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
# else
# error "Unknown plat"
# endif
@@ -282,6 +294,39 @@
(*f)(tid, "r13", vex->guest_r13);
(*f)(tid, "r14", vex->guest_r14);
(*f)(tid, "r15", vex->guest_r15);
+#elif defined(VGA_mips32)
+ (*f)(tid, "r0" , vex->guest_r0 );
+ (*f)(tid, "r1" , vex->guest_r1 );
+ (*f)(tid, "r2" , vex->guest_r2 );
+ (*f)(tid, "r3" , vex->guest_r3 );
+ (*f)(tid, "r4" , vex->guest_r4 );
+ (*f)(tid, "r5" , vex->guest_r5 );
+ (*f)(tid, "r6" , vex->guest_r6 );
+ (*f)(tid, "r7" , vex->guest_r7 );
+ (*f)(tid, "r8" , vex->guest_r8 );
+ (*f)(tid, "r9" , vex->guest_r9 );
+ (*f)(tid, "r10", vex->guest_r10);
+ (*f)(tid, "r11", vex->guest_r11);
+ (*f)(tid, "r12", vex->guest_r12);
+ (*f)(tid, "r13", vex->guest_r13);
+ (*f)(tid, "r14", vex->guest_r14);
+ (*f)(tid, "r15", vex->guest_r15);
+ (*f)(tid, "r16", vex->guest_r16);
+ (*f)(tid, "r17", vex->guest_r17);
+ (*f)(tid, "r18", vex->guest_r18);
+ (*f)(tid, "r19", vex->guest_r19);
+ (*f)(tid, "r20", vex->guest_r20);
+ (*f)(tid, "r21", vex->guest_r21);
+ (*f)(tid, "r22", vex->guest_r22);
+ (*f)(tid, "r23", vex->guest_r23);
+ (*f)(tid, "r24", vex->guest_r24);
+ (*f)(tid, "r25", vex->guest_r25);
+ (*f)(tid, "r26", vex->guest_r26);
+ (*f)(tid, "r27", vex->guest_r27);
+ (*f)(tid, "r28", vex->guest_r28);
+ (*f)(tid, "r29", vex->guest_r29);
+ (*f)(tid, "r30", vex->guest_r30);
+ (*f)(tid, "r31", vex->guest_r31);
#else
# error Unknown arch
#endif
@@ -389,7 +434,7 @@
/* For hwcaps detection on ppc32/64, s390x, and arm we'll need to do SIGILL
testing, so we need a VG_MINIMAL_JMP_BUF. */
#if defined(VGA_ppc32) || defined(VGA_ppc64) \
- || defined(VGA_arm) || defined(VGA_s390x)
+ || defined(VGA_arm) || defined(VGA_s390x) || defined(VGA_mips32)
#include "pub_tool_libcsetjmp.h"
static VG_MINIMAL_JMP_BUF(env_unsup_insn);
static void handler_unsup_insn ( Int x ) {
@@ -568,6 +613,64 @@
#endif /* VGA_s390x */
+#ifdef VGA_mips32
+
+/* 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";
+ Int n, fh;
+ SysRes fd;
+ SizeT num_bytes, file_buf_size;
+ HChar *file_buf;
+
+ /* Slurp contents of /proc/cpuinfo into FILE_BUF */
+ fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR );
+ if ( sr_isError(fd) ) return -1;
+
+ fh = sr_Res(fd);
+
+ /* Determine the size of /proc/cpuinfo.
+ Work around broken-ness in /proc file system implementation.
+ fstat returns a zero size for /proc/cpuinfo although it is
+ claimed to be a regular file. */
+ num_bytes = 0;
+ file_buf_size = 1000;
+ file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
+ while (42) {
+ n = VG_(read)(fh, file_buf, file_buf_size);
+ if (n < 0) break;
+
+ num_bytes += n;
+ if (n < file_buf_size) break; /* reached EOF */
+ }
+
+ if (n < 0) num_bytes = 0; /* read error; ignore contents */
+
+ if (num_bytes > file_buf_size) {
+ VG_(free)( file_buf );
+ VG_(lseek)( fh, 0, VKI_SEEK_SET );
+ file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 );
+ n = VG_(read)( fh, file_buf, num_bytes );
+ if (n < 0) num_bytes = 0;
+ }
+
+ file_buf[num_bytes] = '\0';
+ VG_(close)(fh);
+
+ /* Parse file */
+ if (VG_(strstr) (file_buf, search_Broadcom_str) != NULL)
+ return VEX_PRID_COMP_BROADCOM;
+ if (VG_(strstr) (file_buf, search_MIPS_str) != NULL)
+ return VEX_PRID_COMP_MIPS;
+
+ /* Did not find string in the proc file. */
+ return -1;
+}
+
+#endif
+
/* Determine what insn set and insn set variant the host has, and
record it. To be called once at system startup. Returns False if
this a CPU incapable of running Valgrind. */
@@ -1249,6 +1352,17 @@
return True;
}
+#elif defined(VGA_mips32)
+ {
+ va = VexArchMIPS32;
+ UInt model = VG_(get_machine_model)();
+ if (model== -1)
+ return False;
+
+ vai.hwcaps = model;
+ return True;
+ }
+
#else
# error "Unknown arch"
#endif
@@ -1370,6 +1484,11 @@
assume we always do. */
return 16;
+# elif defined(VGA_mips32)
+ /* The guest state implies 4, but that can't really be true, can
+ it? */
+ return 8;
+
# else
# error "Unknown arch"
# endif
@@ -1383,7 +1502,7 @@
# 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_s390x_linux) || defined(VGP_mips32_linux)
return f;
# elif defined(VGP_ppc64_linux)
/* ppc64-linux uses the AIX scheme, in which f is a pointer to a
Modified: trunk/coregrind/m_syscall.c (+58 -0)
===================================================================
--- trunk/coregrind/m_syscall.c 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/coregrind/m_syscall.c 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -62,6 +62,7 @@
SysRes VG_(mk_SysRes_x86_linux) ( Int val ) {
SysRes res;
+ res._valEx = 0; /* unused except on mips-linux */
res._isError = val >= -4095 && val <= -1;
if (res._isError) {
res._val = (UInt)(-val);
@@ -74,6 +75,7 @@
/* Similarly .. */
SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) {
SysRes res;
+ res._valEx = 0; /* unused except on mips-linux */
res._isError = val >= -4095 && val <= -1;
if (res._isError) {
res._val = (ULong)(-val);
@@ -87,6 +89,7 @@
/* Note this must be in the bottom bit of the second arg */
SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) {
SysRes res;
+ res._valEx = 0; /* unused except on mips-linux */
res._isError = (cr0so & 1) != 0;
res._val = val;
return res;
@@ -95,6 +98,7 @@
/* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */
SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) {
SysRes res;
+ res._valEx = 0; /* unused except on mips-linux */
res._isError = (cr0so & 1) != 0;
res._val = val;
return res;
@@ -102,6 +106,7 @@
SysRes VG_(mk_SysRes_s390x_linux) ( Long val ) {
SysRes res;
+ res._valEx = 0; /* unused except on mips-linux */
res._isError = val >= -4095 && val <= -1;
if (res._isError) {
res._val = -val;
@@ -113,6 +118,7 @@
SysRes VG_(mk_SysRes_arm_linux) ( Int val ) {
SysRes res;
+ res._valEx = 0; /* unused except on mips-linux */
res._isError = val >= -4095 && val <= -1;
if (res._isError) {
res._val = (UInt)(-val);
@@ -122,9 +128,19 @@
return res;
}
+/* MIPS uses a3 != 0 to flag an error */
+SysRes VG_(mk_SysRes_mips32_linux) ( UWord v0, UWord v1, UWord a3 ) {
+ SysRes res;
+ res._isError = (a3 != (UWord)0);
+ res._val = v0;
+ res._valEx = v1;
+ return res;
+}
+
/* Generic constructors. */
SysRes VG_(mk_SysRes_Error) ( UWord err ) {
SysRes r;
+ r._valEx = 0; /* unused except on mips-linux */
r._isError = True;
r._val = err;
return r;
@@ -132,6 +148,7 @@
SysRes VG_(mk_SysRes_Success) ( UWord res ) {
SysRes r;
+ r._valEx = 0; /* unused except on mips-linux */
r._isError = False;
r._val = res;
return r;
@@ -575,6 +592,40 @@
return (UWord) (__svcres);
}
+#elif defined(VGP_mips32_linux)
+/* Incoming args (syscall number + up to 6 args) come in a0 - a3 and stack.
+
+ The syscall number goes in v0. The args are passed to the syscall in
+ the regs a0 - a3 and stack, i.e. the kernel's syscall calling convention.
+
+ (a3 != 0) flags an error.
+ We return the syscall return value in v0.
+ MIPS version
+*/
+extern int do_syscall_WRK (
+ int a1, int a2, int a3,
+ int a4, int a5, int a6, int syscall_no, UWord *err,
+ UWord *valHi, UWord* valLo
+ );
+asm(
+".globl do_syscall_WRK\n"
+".ent do_syscall_WRK\n"
+".text\n"
+"do_syscall_WRK:\n"
+" lw $2, 24($29)\n"
+" syscall\n"
+" lw $8, 28($29)\n"
+" sw $7, ($8)\n"
+" lw $8, 32($29)\n"
+" sw $3, ($8)\n" // store valHi
+" lw $8, 36($29)\n"
+" sw $2, ($8)\n" // store valLo
+" jr $31\n"
+" nop\n"
+".previous\n"
+".end do_syscall_WRK\n"
+);
+
#else
# error Unknown platform
#endif
@@ -682,6 +733,13 @@
}
return VG_(mk_SysRes_s390x_linux)( val );
+
+#elif defined(VGP_mips32_linux)
+ UWord err = 0;
+ UWord valHi = 0;
+ 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 );
#else
# error Unknown platform
#endif
Modified: trunk/coregrind/m_libcfile.c (+33 -7)
===================================================================
--- trunk/coregrind/m_libcfile.c 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/coregrind/m_libcfile.c 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -194,7 +194,17 @@
Int VG_(pipe) ( Int fd[2] )
{
-# if defined(VGO_linux)
+# if defined(VGP_mips32_linux)
+ /* __NR_pipe has a strange return convention on mips32-linux. */
+ SysRes res = VG_(do_syscall0)(__NR_pipe);
+ if (!sr_isError(res)) {
+ fd[0] = (Int)sr_Res(res);
+ fd[1] = (Int)sr_ResEx(res);
+ return 0;
+ } else {
+ return -1;
+ }
+# elif defined(VGO_linux)
SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
return sr_isError(res) ? -1 : 0;
# elif defined(VGO_darwin)
@@ -596,6 +606,16 @@
0, // Padding needed on PPC32
0, offset); // Big endian long long
return res;
+# 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
+ 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)
res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
@@ -837,7 +857,8 @@
res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (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_mips32_linux)
SysRes res;
res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
return sr_isError(res) ? -1 : sr_Res(res);
@@ -875,7 +896,8 @@
res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (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_mips32_linux)
SysRes res;
res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
return sr_isError(res) ? -1 : sr_Res(res);
@@ -913,7 +935,8 @@
res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (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_mips32_linux)
SysRes res;
res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
count, VKI_MSG_NOSIGNAL, 0,0);
@@ -932,7 +955,8 @@
Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
{
# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
- || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
+ || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \
+ || defined(VGP_mips32_linux)
SysRes res;
UWord args[3];
args[0] = sd;
@@ -961,7 +985,8 @@
Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
{
# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
- || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
+ || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \
+ || defined(VGP_mips32_linux)
SysRes res;
UWord args[3];
args[0] = sd;
@@ -1002,7 +1027,8 @@
res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (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_mips32_linux)
SysRes res;
res = VG_(do_syscall5)( __NR_getsockopt,
(UWord)sd, (UWord)level, (UWord)optname,
Modified: trunk/drd/drd_thread.c (+6 -0)
===================================================================
--- trunk/drd/drd_thread.c 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/drd/drd_thread.c 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -597,6 +597,12 @@
}
/** Store the thread mode: joinable or detached. */
+#if defined(VGP_mips32_linux)
+ /* There is a cse related issue in gcc for MIPS. Optimization level
+ has to be lowered, so cse related optimizations are not
+ included.*/
+ __attribute__((optimize("O1")))
+#endif
void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
{
tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
Modified: trunk/coregrind/m_scheduler/scheduler.c (+7 -0)
===================================================================
--- trunk/coregrind/m_scheduler/scheduler.c 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/coregrind/m_scheduler/scheduler.c 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -780,6 +780,10 @@
# if defined(VGA_s390x)
/* no special requirements */
# endif
+
+# if defined(VGA_mips32)
+ /* no special requirements */
+# endif
}
// NO_VGDB_POLL value ensures vgdb is not polled, while
@@ -1557,6 +1561,9 @@
#elif defined (VGA_s390x)
# define VG_CLREQ_ARGS guest_r2
# define VG_CLREQ_RET guest_r3
+#elif defined(VGA_mips32)
+# define VG_CLREQ_ARGS guest_r12
+# define VG_CLREQ_RET guest_r11
#else
# error Unknown arch
#endif
Modified: trunk/coregrind/pub_core_trampoline.h (+6 -0)
===================================================================
--- trunk/coregrind/pub_core_trampoline.h 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/coregrind/pub_core_trampoline.h 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -127,6 +127,12 @@
extern Addr VG_(s390x_linux_SUBST_FOR_rt_sigreturn);
#endif
+#if defined(VGP_mips32_linux)
+extern Addr VG_(mips32_linux_SUBST_FOR_sigreturn);
+extern Addr VG_(mips32_linux_SUBST_FOR_rt_sigreturn);
+extern UInt VG_(mips32_linux_REDIR_FOR_strlen)( void* );
+#endif
+
#endif // __PUB_CORE_TRAMPOLINE_H
/*--------------------------------------------------------------------*/
Modified: trunk/coregrind/m_debuginfo/readdwarf3.c (+2 -0)
===================================================================
--- trunk/coregrind/m_debuginfo/readdwarf3.c 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/coregrind/m_debuginfo/readdwarf3.c 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -2307,8 +2307,10 @@
case DW_ATE_unsigned: case DW_ATE_unsigned_char:
case DW_ATE_UTF: /* since DWARF4, e.g. char16_t from C++ */
case DW_ATE_boolean:/* FIXME - is this correct? */
+ case DW_ATE_unsigned_fixed:
typeE.Te.TyBase.enc = 'U'; break;
case DW_ATE_signed: case DW_ATE_signed_char:
+ case DW_ATE_signed_fixed:
typeE.Te.TyBase.enc = 'S'; break;
case DW_ATE_float:
typeE.Te.TyBase.enc = 'F'; break;
Modified: trunk/callgrind/Makefile.am (+2 -1)
===================================================================
--- trunk/callgrind/Makefile.am 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/callgrind/Makefile.am 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -50,7 +50,8 @@
../cachegrind/cg-ppc32.c \
../cachegrind/cg-ppc64.c \
../cachegrind/cg-arm.c \
- ../cachegrind/cg-s390x.c
+ ../cachegrind/cg-s390x.c \
+ ../cachegrind/cg-mips32.c
CALLGRIND_CFLAGS_COMMON = -I$(top_srcdir)/cachegrind
Modified: trunk/Makefile.tool.am (+12 -0)
===================================================================
--- trunk/Makefile.tool.am 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/Makefile.tool.am 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -59,6 +59,11 @@
TOOL_LDFLAGS_AMD64_DARWIN = \
$(TOOL_LDFLAGS_COMMON_DARWIN) -arch x86_64
+# MIPS Linux default start symbol is __start, not _start like on x86 or amd
+TOOL_LDFLAGS_MIPS32_LINUX = \
+ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
+ @FLAG_M32@
+
# On Android we must ask for non-executable stack, not sure why.
if VGCONF_PLATFORMS_INCLUDE_ARM_LINUX
if VGCONF_PLATVARIANT_IS_ANDROID
@@ -103,6 +108,8 @@
LIBREPLACEMALLOC_S390X_LINUX = \
$(top_builddir)/coregrind/libreplacemalloc_toolpreload-s390x-linux.a
+LIBREPLACEMALLOC_MIPS32_LINUX = \
+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips32-linux.a
LIBREPLACEMALLOC_LDFLAGS_X86_LINUX = \
-Wl,--whole-archive \
@@ -140,6 +147,11 @@
$(LIBREPLACEMALLOC_S390X_LINUX) \
-Wl,--no-whole-archive
+LIBREPLACEMALLOC_LDFLAGS_MIPS32_LINUX = \
+ -Wl,--whole-archive \
+ $(LIBREPLACEMALLOC_MIPS32_LINUX) \
+ -Wl,--no-whole-archive
+
#----------------------------------------------------------------------------
# General stuff
#----------------------------------------------------------------------------
Modified: trunk/drd/drd_clientreq.c (+6 -0)
===================================================================
--- trunk/drd/drd_clientreq.c 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/drd/drd_clientreq.c 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -69,6 +69,12 @@
* DRD's handler for Valgrind client requests. The code below handles both
* DRD's public and tool-internal client requests.
*/
+#if defined(VGP_mips32_linux)
+ /* There is a cse related issue in gcc for MIPS. Optimization level
+ has to be lowered, so cse related optimizations are not
+ included. */
+ __attribute__((optimize("O1")))
+#endif
static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret)
{
UWord result = 0;
Modified: trunk/coregrind/m_translate.c (+12 -1)
===================================================================
--- trunk/coregrind/m_translate.c 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/coregrind/m_translate.c 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -726,7 +726,7 @@
static Bool translations_allowable_from_seg ( NSegment const* seg )
{
-# if defined(VGA_x86) || defined(VGA_s390x)
+# if defined(VGA_x86) || defined(VGA_s390x) || defined(VGA_mips32)
Bool allowR = True;
# else
Bool allowR = False;
@@ -1188,6 +1188,12 @@
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.
+ VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
+ Int offB_GPR25 = offsetof(VexGuestMIPS32State,guest_r25);
+ addStmtToIRSB( bb, IRStmt_Put( offB_GPR25, mkU32( closure->readdr )) );
+# endif
# if defined(VG_PLAT_USES_PPCTOC)
{ VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
addStmtToIRSB(
@@ -1224,6 +1230,11 @@
: 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 )) );
+# endif
# if defined(VGP_ppc64_linux)
addStmtToIRSB(
bb,
Modified: trunk/coregrind/Makefile.am (+17 -1)
===================================================================
--- trunk/coregrind/Makefile.am 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/coregrind/Makefile.am 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -301,6 +301,7 @@
m_dispatch/dispatch-ppc64-linux.S \
m_dispatch/dispatch-arm-linux.S \
m_dispatch/dispatch-s390x-linux.S \
+ m_dispatch/dispatch-mips32-linux.S \
m_dispatch/dispatch-x86-darwin.S \
m_dispatch/dispatch-amd64-darwin.S \
m_gdbserver/m_gdbserver.c \
@@ -318,6 +319,7 @@
m_gdbserver/valgrind-low-ppc32.c \
m_gdbserver/valgrind-low-ppc64.c \
m_gdbserver/valgrind-low-s390x.c \
+ m_gdbserver/valgrind-low-mips32.c \
m_gdbserver/version.c \
m_initimg/initimg-linux.c \
m_initimg/initimg-darwin.c \
@@ -337,6 +339,7 @@
m_sigframe/sigframe-ppc64-linux.c \
m_sigframe/sigframe-arm-linux.c \
m_sigframe/sigframe-s390x-linux.c \
+ m_sigframe/sigframe-mips32-linux.c \
m_sigframe/sigframe-x86-darwin.c \
m_sigframe/sigframe-amd64-darwin.c \
m_syswrap/syscall-x86-linux.S \
@@ -345,6 +348,7 @@
m_syswrap/syscall-ppc64-linux.S \
m_syswrap/syscall-arm-linux.S \
m_syswrap/syscall-s390x-linux.S \
+ m_syswrap/syscall-mips32-linux.S \
m_syswrap/syscall-x86-darwin.S \
m_syswrap/syscall-amd64-darwin.S \
m_syswrap/syswrap-main.c \
@@ -358,6 +362,7 @@
m_syswrap/syswrap-ppc64-linux.c \
m_syswrap/syswrap-arm-linux.c \
m_syswrap/syswrap-s390x-linux.c \
+ m_syswrap/syswrap-mips32-linux.c \
m_syswrap/syswrap-x86-darwin.c \
m_syswrap/syswrap-amd64-darwin.c \
m_ume/elf.c \
@@ -532,7 +537,18 @@
m_gdbserver/s390x-generic.xml \
m_gdbserver/s390x-linux64-valgrind-s1.xml \
m_gdbserver/s390x-linux64-valgrind-s2.xml \
- m_gdbserver/s390x-linux64.xml
+ m_gdbserver/s390x-linux64.xml \
+ m_gdbserver/mips-cp0-valgrind-s1.xml \
+ m_gdbserver/mips-cp0-valgrind-s2.xml \
+ m_gdbserver/mips-cp0.xml \
+ m_gdbserver/mips-cpu-valgrind-s1.xml \
+ m_gdbserver/mips-cpu-valgrind-s2.xml \
+ m_gdbserver/mips-cpu.xml \
+ m_gdbserver/mips-linux.xml \
+ 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
# so as to make sure these get copied into the install tree
vglibdir = $(pkglibdir)
Modified: trunk/include/valgrind.h (+607 -0)
===================================================================
--- trunk/include/valgrind.h 2012-06-06 03:27:51 +01:00 (rev 12615)
+++ trunk/include/valgrind.h 2012-06-07 10:13:21 +01:00 (rev 12616)
@@ -117,6 +117,7 @@
#undef PLAT_ppc64_linux
#undef PLAT_arm_linux
#undef PLAT_s390x_linux
+#undef PLAT_mips32_linux
#if defined(__APPLE__) && defined(__i386__)
@@ -138,6 +139,8 @@
# define PLAT_arm_linux 1
#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
# define PLAT_s390x_linux 1
+#elif defined(__linux__) && defined(__mips__)
+# define PLAT_mips32_linux 1
#else
/* If we're not compiling for our target platform, don't generate
any inline asms. */
@@ -665,6 +668,70 @@
#endif /* PLAT_s390x_linux */
+/* ------------------------- mips32-linux ---------------- */
+
+#if defined(PLAT_mips32_linux)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+/* .word 0x342
+ * .word 0x742
+ * .word 0xC2
+ * .word 0x4C2*/
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "srl $0, $0, 13\n\t" \
+ "srl $0, $0, 29\n\t" \
+ "srl $0, $0, 3\n\t" \
+ "srl $0, $0, 19\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ __extension__ \
+ ({ volatile unsigned int _zzq_args[6]; \
+ volatile unsigned int _zzq_result; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ __asm__ volatile("move $11, %1\n\t" /*default*/ \
+ "move $12, %2\n\t" /*ptr*/ \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* T3 = client_request ( T4 ) */ \
+ "or $13, $13, $13\n\t" \
+ "move %0, $11\n\t" /*result*/ \
+ : "=r" (_zzq_result) \
+ : "r" (_zzq_default), "r" (&_zzq_args[0]) \
+ : "cc","memory", "t3", "t4"); \
+ _zzq_result; \
+ })
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ volatile unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %t9 = guest_NRADDR */ \
+ "or $14, $14, $14\n\t" \
+ "move %0, $11" /*result*/ \
+ : "=r" (__addr) \
+ : \
+ : "cc", "memory" , "t3" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_CALL_NOREDIR_T9 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* call-noredir *%t9 */ \
+ "or $15, $15, $15\n\t"
+#endif /* PLAT_mips32_linux */
+
/* Insert assembly code for other platforms here... */
#endif /* NVALGRIND */
@@ -3589,7 +3656,546 @@
#endif /* PLAT_s390x_linux */
+/* ------------------------- mips-linux ------------------------- */
+
+#if defined(PLAT_mips32_linux)
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
+"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
+"$25", "$31"
+
+/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
+ long) == 4. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $gp, 0($sp) \n\t" \
+ "sw $ra, 4($sp) \n\t" \
+ "subu $29, $29, 16 \n\t" \
+ "lw $t9, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 16\n\t" \
+ "lw $gp, 0($sp) \n\t" \
+ "lw $ra, 4($sp) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $v0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $gp, 0($sp) \n\t" \
+ "sw $ra, 4($sp) \n\t" \
+ "subu $29, $29, 16 \n\t" \
+ "lw $a0, 4(%1) \n\t" /* arg1*/ \
+ "lw $t9, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 16 \n\t" \
+ "lw $gp, 0($sp) \n\t" \
+ "lw $ra, 4($sp) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $v0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $gp, 0($sp) \n\t" \
+ "sw $ra, 4($sp) \n\t" \
+ "subu $29, $29, 16 \n\t" \
+ "lw $a0, 4(%1) \n\t" \
+ "lw $a1, 8(%1) \n\t" \
+ "lw $t9, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 16 \n\t" \
+ "lw $gp, 0($sp) \n\t" \
+ "lw $ra, 4($sp) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $v0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $gp, 0($sp) \n\t" \
+ "sw $ra, 4($sp) \n\t" \
+ "subu $29, $29, 16 \n\t" \
+ "lw $a0, 4(%1) \n\t" \
+ "lw $a1, 8(%1) \n\t" \
+ "lw $a2, 12(%1) \n\t" \
+ "lw $t9, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 16 \n\t" \
+ "lw $gp, 0($sp) \n\t" \
+ "lw $ra, 4($sp) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $v0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $gp, 0($sp) \n\t" \
+ "sw $ra, 4($sp) \n\t" \
+ "subu $29, $29, 16 \n\t" \
+ "lw $a0, 4(%1) \n\t" \
+ "lw $a1, 8(%1) \n\t" \
+ "lw $a2, 12(%1) \n\t" \
+ "lw $a3, 16(%1) \n\t" \
+ "lw $t9, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 16 \n\t" \
+ "lw $gp, 0($sp) \n\t" \
+ "lw $ra, 4($sp) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $v0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $gp, 0($sp) \n\t" \
+ "sw $ra, 4($sp) \n\t" \
+ "lw $a0, 20(%1) \n\t" \
+ "subu $sp, $sp, 24\n\t" \
+ "sw $a0, 16($sp) \n\t" \
+ "lw $a0, 4(%1) \n\t" \
+ "lw $a1, 8(%1) \n\t" \
+ "lw $a2, 12(%1) \n\t" \
+ "lw $a3, 16(%1) \n\t" \
+ "lw $t9, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 24 \n\t" \
+ "lw $gp, 0($sp) \n\t" \
+ "lw $ra, 4($sp) \n\t" \
+ "addu $sp, $sp, 8 \n\t" \
+ "move %0, $v0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $gp, 0($sp) \n\t" \
+ "sw $ra, 4($sp) \n\t" \
+ "lw $a0, 20(%1) \n\t" \
+ "subu $sp, $sp, 32\n\t" \
+ "sw $a0, 16($sp) \n\t" \
+ "lw $a0, 24(%1) \n\t" \
+ "nop\n\t" \
+ "sw $a0, 20($sp) \n\t" \
+ "lw $a0, 4(%1) \n\t" \
+ "lw $a1, 8(%1) \n\t" \
+ "lw $a2, 12(%1) \n\t" \
+ "lw $a3, 16(%1) \n\t" \
+ "lw $t9, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $sp, $sp, 32 \n\t" \
+ "lw $gp, 0($sp) \n\t" \
+ "lw $ra, 4($sp) \n\t" \
+ "addu $sp, $sp, 8 \n\t" \
+ "move %0, $v0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $gp, 0($sp) \n\t" \
+ "sw $ra, 4($sp) \n\t" \
+ "lw $a0, 20(%1) \n\t" \
+ "subu $sp, $sp, 32\n\t" \
+ "sw $a0, 16($sp) \n\t" \
+ "lw $a0, 24(%1) \n\t" \
+ "sw $a0, 20($sp) \n\t" ...
[truncated message content] |