Merge in a port for mips32-linux, by Petar Jovanovic and Dejan Jevtic,
authorsewardj <sewardj@a5019735-40e9-0310-863c-91ae7b9d1cf9>
Thu, 7 Jun 2012 09:13:21 +0000 (09:13 +0000)
committersewardj <sewardj@a5019735-40e9-0310-863c-91ae7b9d1cf9>
Thu, 7 Jun 2012 09:13:21 +0000 (09:13 +0000)
mips-valgrind@rt-rk.com, Bug 270777.

Valgrind: changes to existing files.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12616 a5019735-40e9-0310-863c-91ae7b9d1cf9

74 files changed:
Makefile.all.am
Makefile.tool.am
Makefile.vex.am
cachegrind/Makefile.am
cachegrind/cg_branchpred.c
cachegrind/tests/filter_stderr
callgrind/Makefile.am
callgrind/tests/filter_stderr
configure.in
coregrind/Makefile.am
coregrind/launcher-linux.c
coregrind/link_tool_exe_linux.in
coregrind/m_aspacemgr/aspacemgr-common.c
coregrind/m_aspacemgr/aspacemgr-linux.c
coregrind/m_coredump/coredump-elf.c
coregrind/m_debugger.c
coregrind/m_debuginfo/d3basics.c
coregrind/m_debuginfo/debuginfo.c
coregrind/m_debuginfo/priv_storage.h
coregrind/m_debuginfo/readdwarf.c
coregrind/m_debuginfo/readdwarf3.c
coregrind/m_debuginfo/readelf.c
coregrind/m_debuginfo/storage.c
coregrind/m_debuglog.c
coregrind/m_gdbserver/target.c
coregrind/m_gdbserver/valgrind_low.h
coregrind/m_initimg/initimg-linux.c
coregrind/m_libcassert.c
coregrind/m_libcfile.c
coregrind/m_libcproc.c
coregrind/m_machine.c
coregrind/m_main.c
coregrind/m_redir.c
coregrind/m_scheduler/scheduler.c
coregrind/m_signals.c
coregrind/m_stacktrace.c
coregrind/m_syscall.c
coregrind/m_syswrap/priv_types_n_macros.h
coregrind/m_syswrap/syswrap-linux.c
coregrind/m_syswrap/syswrap-main.c
coregrind/m_trampoline.S
coregrind/m_translate.c
coregrind/pub_core_aspacemgr.h
coregrind/pub_core_basics.h
coregrind/pub_core_debuginfo.h
coregrind/pub_core_machine.h
coregrind/pub_core_mallocfree.h
coregrind/pub_core_syscall.h
coregrind/pub_core_threadstate.h
coregrind/pub_core_trampoline.h
coregrind/pub_core_transtab_asm.h
coregrind/vgdb.c
drd/drd_bitmap.h
drd/drd_clientreq.c
drd/drd_load_store.c
drd/drd_thread.c
helgrind/tests/annotate_hbefore.c
helgrind/tests/tc07_hbl1.c
helgrind/tests/tc08_hbl2.c
helgrind/tests/tc11_XCHG.c
include/Makefile.am
include/pub_tool_basics.h
include/pub_tool_machine.h
include/pub_tool_vkiscnums_asm.h
include/valgrind.h
include/vki/vki-linux.h
memcheck/mc_machine.c
memcheck/tests/atomic_incs.c
memcheck/tests/memalign_test.c
none/tests/Makefile.am
none/tests/allexec_prepare_prereq
tests/arch_test.c
tests/platform_test
tests/sys_mman.h

index 439aacd755a2b1dc0145d2d90fc6302bd8f58b09..bcca5ff60acb4cb90881dd939d00f564158722aa 100644 (file)
@@ -172,6 +172,10 @@ AM_FLAG_M3264_S390X_LINUX = @FLAG_M64@
 AM_CFLAGS_S390X_LINUX     = @FLAG_M64@ $(AM_CFLAGS_BASE) -fomit-frame-pointer
 AM_CCASFLAGS_S390X_LINUX  = @FLAG_M64@ -g -mzarch -march=z900
 
+AM_FLAG_M3264_MIPS32_LINUX = @FLAG_M32@
+AM_CFLAGS_MIPS32_LINUX     = @FLAG_M32@ $(AM_CFLAGS_BASE) -mips32
+AM_CCASFLAGS_MIPS32_LINUX  = @FLAG_M32@ -mips32 -g
+
 
 # Flags for the primary target.  These must be used to build the
 # regtests and performance tests.  In fact, these must be used to
@@ -202,4 +206,5 @@ PRELOAD_LDFLAGS_ARM_LINUX    = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
 PRELOAD_LDFLAGS_X86_DARWIN   = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch i386
 PRELOAD_LDFLAGS_AMD64_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch x86_64
 PRELOAD_LDFLAGS_S390X_LINUX  = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
+PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
 
index 7924b1bb2812b801396701ed25cbde5203c7e1e8..6f5a6eab5335478fec6caf9bc1bac25cf830eddc 100644 (file)
@@ -59,6 +59,11 @@ TOOL_LDFLAGS_X86_DARWIN = \
 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_AMD64_DARWIN = \
 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_LDFLAGS_S390X_LINUX = \
        $(LIBREPLACEMALLOC_S390X_LINUX) \
        -Wl,--no-whole-archive
 
+LIBREPLACEMALLOC_LDFLAGS_MIPS32_LINUX = \
+       -Wl,--whole-archive \
+       $(LIBREPLACEMALLOC_MIPS32_LINUX) \
+       -Wl,--no-whole-archive
+
 #----------------------------------------------------------------------------
 # General stuff
 #----------------------------------------------------------------------------
index 0071634d3629e36c94a67a30af8bc79a8649cdd5..db162769f1c55f6f0298052eb3a1d1668edc7b17 100644 (file)
@@ -25,6 +25,7 @@ pkginclude_HEADERS = \
        pub/libvex_guest_ppc64.h \
        pub/libvex_guest_arm.h \
        pub/libvex_guest_s390x.h \
+       pub/libvex_guest_mips32.h \
        pub/libvex_s390x_common.h \
        pub/libvex_ir.h \
        pub/libvex_trc_values.h
@@ -41,6 +42,7 @@ noinst_HEADERS = \
        priv/guest_ppc_defs.h \
        priv/guest_arm_defs.h \
        priv/guest_s390_defs.h \
+       priv/guest_mips_defs.h \
        priv/host_generic_regs.h \
        priv/host_generic_simd64.h \
        priv/host_generic_simd128.h \
@@ -49,7 +51,8 @@ noinst_HEADERS = \
        priv/host_ppc_defs.h \
        priv/host_arm_defs.h \
        priv/host_s390_defs.h \
-       priv/host_s390_disasm.h
+       priv/host_s390_disasm.h \
+       priv/host_mips_defs.h
 
 BUILT_SOURCES = pub/libvex_guest_offsets.h
 CLEANFILES    = pub/libvex_guest_offsets.h
@@ -64,7 +67,8 @@ pub/libvex_guest_offsets.h: auxprogs/genoffsets.c \
                            pub/libvex_guest_ppc32.h \
                            pub/libvex_guest_ppc64.h \
                            pub/libvex_guest_arm.h \
-                           pub/libvex_guest_s390x.h
+                           pub/libvex_guest_s390x.h \
+                           pub/libvex_guest_mips32.h
        rm -f auxprogs/genoffsets.s
        $(CC) $(CFLAGS) \
              $(LIBVEX_CFLAGS) \
@@ -106,6 +110,8 @@ LIBVEX_SOURCES_COMMON = \
        priv/guest_arm_toIR.c \
        priv/guest_s390_helpers.c \
        priv/guest_s390_toIR.c \
+       priv/guest_mips_helpers.c \
+       priv/guest_mips_toIR.c \
        priv/host_generic_regs.c \
        priv/host_generic_simd64.c \
        priv/host_generic_simd128.c \
@@ -120,7 +126,9 @@ LIBVEX_SOURCES_COMMON = \
        priv/host_arm_isel.c \
        priv/host_s390_defs.c \
        priv/host_s390_isel.c \
-       priv/host_s390_disasm.c
+       priv/host_s390_disasm.c \
+       priv/host_mips_defs.c \
+       priv/host_mips_isel.c
 
 LIBVEX_CFLAGS = \
        -Wbad-function-cast \
index 0b6879c95b3e932421af3ab266b5e4376fa04059..f22fe17307cba2d708174c47180ee66ea46708c1 100644 (file)
@@ -46,7 +46,8 @@ CACHEGRIND_SOURCES_COMMON = \
        cg-ppc32.c \
        cg-ppc64.c \
        cg-arm.c   \
-       cg-s390x.c
+       cg-s390x.c \
+       cg-mips32.c
 
 cachegrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_SOURCES      = \
        $(CACHEGRIND_SOURCES_COMMON)
index 1db7fb592af2a63f646088bd2c419efeefd966d4..462977aee5bb1076c68c9bba5e2730beca378456 100644 (file)
@@ -44,7 +44,8 @@
 
 /* How many bits at the bottom of an instruction address are
    guaranteed to be zero? */
-#if defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_arm)
+#if defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_arm) \
+    || defined(VGA_mips32)
 #  define N_IADDR_LO_ZERO_BITS 2
 #elif defined(VGA_x86) || defined(VGA_amd64)
 #  define N_IADDR_LO_ZERO_BITS 0
index d6800cd651e68ab74aabeb4eb9c5033dd347296f..2d38fb31d1da27e13c7c626cd5bb5617eeae5402 100755 (executable)
@@ -20,4 +20,5 @@ sed "/warning: L3 cache found, using its data for the LL simulation./d" |
 sed "/Warning: Cannot auto-detect cache config on PPC.., using one or more defaults/d" |
 sed "/Warning: Cannot auto-detect cache config on ARM, using one or more defaults/d" |
 sed "/Warning: Cannot auto-detect cache config on s390x, using one or more defaults/d" |
+sed "/Warning: Cannot auto-detect cache config on MIPS.., using one or more defaults/d" |
 sed "/warning: pretending that LL cache has associativity .*$/d"
index 7cb6807fc311f3d89d7d42d288103c192acd17e3..ae4ff4fc69ac84dc7b6fa66cd094d7e467f35d66 100644 (file)
@@ -50,7 +50,8 @@ CALLGRIND_SOURCES_COMMON = \
        ../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
 
index 9664d518c5ee99aa01c3650a00533a3243bd8a7c..9acedd3c24d524d8781544a1b45a6f9fdd9f7f10 100755 (executable)
@@ -29,4 +29,5 @@ sed "/warning: L3 cache found, using its data for the LL simulation./d" |
 sed "/Warning: Cannot auto-detect cache config on PPC.., using one or more defaults/d" |
 sed "/Warning: Cannot auto-detect cache config on ARM, using one or more defaults/d" |
 sed "/Warning: Cannot auto-detect cache config on s390x, using one or more defaults/d" |
+sed "/Warning: Cannot auto-detect cache config on MIPS.., using one or more defaults/d" |
 sed "/warning: pretending that LL cache has associativity .*$/d"
index ed6be2a82e9b820797c817175c2c91cdc1610d3b..954df7c965b9ebfc561580d3be54031e822e86dd 100644 (file)
@@ -189,6 +189,21 @@ case "${host_cpu}" in
        ARCH_MAX="arm"
        ;;
 
+     mips)
+       AC_MSG_RESULT([ok (${host_cpu})])
+       ARCH_MAX="mips32"
+       ;;
+
+     mipsel)
+       AC_MSG_RESULT([ok (${host_cpu})])
+       ARCH_MAX="mips32"
+       ;;
+
+     mipsisa32r2)
+       AC_MSG_RESULT([ok (${host_cpu})])
+       ARCH_MAX="mips32"
+       ;;
+
      *) 
        AC_MSG_RESULT([no (${host_cpu})])
        AC_MSG_ERROR([Unsupported host architecture. Sorry])
@@ -535,6 +550,17 @@ case "$ARCH_MAX-$VGCONF_OS" in
         valt_load_address_sec_inner="0xUNSET"
         AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})])
         ;;
+     mips32-linux) 
+        VGCONF_ARCH_PRI="mips32"
+        VGCONF_PLATFORM_PRI_CAPS="MIPS32_LINUX"
+        VGCONF_PLATFORM_SEC_CAPS=""
+        valt_load_address_pri_norml="0x38000000"
+        valt_load_address_pri_inner="0x28000000"
+        valt_load_address_sec_norml="0xUNSET"
+        valt_load_address_sec_inner="0xUNSET"
+        AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})])
+        AC_MSG_RESULT([ok (${host_cpu}-${host_os})])
+        ;;
     *)
         VGCONF_ARCH_PRI="unknown"
         VGCONF_ARCH_SEC="unknown"
@@ -570,6 +596,8 @@ AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_ARM,
                test x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX )
 AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_S390X,
                test x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX )
+AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_MIPS32,
+               test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX )
 
 # Set up VGCONF_PLATFORMS_INCLUDE_<platform>.  Either one or two of these
 # become defined.
@@ -588,6 +616,8 @@ AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_ARM_LINUX,
 AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_S390X_LINUX,
                test x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \
                  -o x$VGCONF_PLATFORM_SEC_CAPS = xS390X_LINUX)
+AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_MIPS32_LINUX,
+               test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX)
 
 AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_X86_DARWIN,   
                test x$VGCONF_PLATFORM_PRI_CAPS = xX86_DARWIN \
@@ -605,7 +635,8 @@ AM_CONDITIONAL(VGCONF_OS_IS_LINUX,
                  -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_LINUX \
                  -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \
                  -o x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \
-                 -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX)
+                 -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \
+                 -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX)
 AM_CONDITIONAL(VGCONF_OS_IS_DARWIN,
                test x$VGCONF_PLATFORM_PRI_CAPS = xX86_DARWIN \
                  -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_DARWIN)
@@ -653,6 +684,62 @@ else
 fi
 
 
+#----------------------------------------------------------------------------
+# Define MIPS_PAGE_SHIFT (--with-pagesize)
+#----------------------------------------------------------------------------
+AC_ARG_WITH(pagesize,
+   [  --with-pagesize=        override detected page size (4, 16 or 64)],
+   [psize=$withval],
+   [psize=0]
+)
+if test "$psize" = "0"; then
+    psizer=`getconf PAGESIZE`
+    let "psize=${psizer}/1024"
+fi
+
+if test "$psize" = "4"; then
+    AC_DEFINE([MIPS_PAGE_SHIFT], 12, [configured page size 4k])
+elif test "$psize" = "16"; then
+    AC_DEFINE([MIPS_PAGE_SHIFT], 14, [configured page size 16k])
+elif test "$psize" = "64"; then
+    AC_DEFINE([MIPS_PAGE_SHIFT], 16, [configured page size 64k])
+else
+   AC_DEFINE([MIPS_PAGE_SHIFT], 12, [configured default page size 4k])
+fi
+AC_MSG_RESULT([checking for Pagesize... ${psize}k])
+
+#----------------------------------------------------------------------------
+# Define shm_align for MIPS (--shared-memory-alignment)
+#----------------------------------------------------------------------------
+AC_ARG_WITH(alignment,
+   [  --with-alignment=       shared memory alignment for MIPS],
+   [align=$withval],
+   [align=-1]
+)
+
+mod=`expr $align % 1024`
+
+let "psz=psize*1024*2"
+
+if test "$align" = "-1"; then
+    AC_DEFINE([SHM_ALIGNMENT], 2*(1UL << MIPS_PAGE_SHIFT), 
+              [configured memory alignment 2*PAGE_SIZE])
+    AC_MSG_RESULT([checking for shared memory alignment... 2*PAGE_SIZE])
+elif test "$mod" = "0"; then
+    if test $align -lt $psz;
+    then
+        AC_MSG_ERROR([Alignment must be >= PAGE_SIZE])
+    else
+        AC_DEFINE_UNQUOTED([SHM_ALIGNMENT], ${align}, 
+                  [configured memory alignment 2*PAGE_SIZE])
+        AC_MSG_RESULT([checking for shared memory alignment... ${align}])     
+    fi
+else
+    AC_MSG_ERROR([Alignment % 1024 must be zero])
+fi
+
+
 #----------------------------------------------------------------------------
 # Extra fine-tuning of installation directories
 #----------------------------------------------------------------------------
@@ -1799,7 +1886,8 @@ MPI_CC="mpicc"
 mflag_primary=
 if test x$VGCONF_PLATFORM_PRI_CAPS = xX86_LINUX \
      -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_LINUX \
-     -o x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX ; then
+     -o x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \
+     -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX ; then
   mflag_primary=$FLAG_M32
 elif test x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_LINUX \
        -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \
@@ -2244,6 +2332,7 @@ AC_CONFIG_FILES([
    none/tests/x86/Makefile
    none/tests/arm/Makefile
    none/tests/s390x/Makefile
+   none/tests/mips32/Makefile
    none/tests/linux/Makefile
    none/tests/darwin/Makefile
    none/tests/x86-linux/Makefile
index efb4de34de83ed765fa4fcd3878524b143193f27..68b8ed2937d8694444484872676ea8408c6ad677 100644 (file)
@@ -301,6 +301,7 @@ COREGRIND_SOURCES_COMMON = \
        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 @@ COREGRIND_SOURCES_COMMON = \
        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 @@ COREGRIND_SOURCES_COMMON = \
        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 @@ COREGRIND_SOURCES_COMMON = \
        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 @@ COREGRIND_SOURCES_COMMON = \
        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 @@ GDBSERVER_XML_FILES = \
        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)
index 6a200c3e67169ac0809061ce789bc4c3b91cac24..a9ad1e39cf58e202c93c92b655a91fa09a16abbf 100644 (file)
@@ -179,6 +179,12 @@ static const char *select_platform(const char *clientname)
                  ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
                platform = "arm-linux";
             }
+            else
+            if (ehdr->e_machine == EM_MIPS &&
+                (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV ||
+                 ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
+               platform = "mips32-linux";
+            }
          }
          else if (header[EI_DATA] == ELFDATA2MSB) {
             if (ehdr->e_machine == EM_PPC &&
@@ -186,6 +192,12 @@ static const char *select_platform(const char *clientname)
                  ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
                platform = "ppc32-linux";
             }
+            else 
+            if (ehdr->e_machine == EM_MIPS &&
+                (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV ||
+                 ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
+               platform = "mips32-linux";
+            }
          }
 
       } else if (n_bytes >= sizeof(Elf64_Ehdr) && header[EI_CLASS] == ELFCLASS64) {
@@ -284,7 +296,8 @@ int main(int argc, char** argv, char** envp)
        (0==strcmp(VG_PLATFORM,"ppc32-linux")) ||
        (0==strcmp(VG_PLATFORM,"ppc64-linux")) ||
        (0==strcmp(VG_PLATFORM,"arm-linux"))   ||
-       (0==strcmp(VG_PLATFORM,"s390x-linux")))
+       (0==strcmp(VG_PLATFORM,"s390x-linux")) ||
+       (0==strcmp(VG_PLATFORM,"mips32-linux")))
       default_platform = VG_PLATFORM;
    else
       barf("Unknown VG_PLATFORM '%s'", VG_PLATFORM);
index 6de2562f4560bd54339d53ab47bf3bf410dd7bbe..a47747be84a38beadd20e2ce2d6a9b140cfb7ef5 100644 (file)
@@ -68,7 +68,18 @@ my $cc = $ARGV[1];
 # 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) {
index 7f7717c5ecfc81701a2759da42c961dbd5005beb..6a65610cbe26a2936fd38e29783847aa1abd2ebc 100644 (file)
@@ -159,7 +159,7 @@ SysRes VG_(am_do_mmap_NO_NOTIFY)( Addr start, SizeT length, UInt prot,
    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_s390x_linux) || defined(VGP_mips32_linux)
    res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, 
                          prot, flags, fd, offset);
 #  elif defined(VGP_x86_darwin)
index 9980501b52243528fe5388d700b729eb6a26d3eb..0695a66b1a596d3a07e2b80cd40cf45679b9de5b 100644 (file)
@@ -2533,7 +2533,7 @@ static SysRes VG_(am_mmap_file_float_valgrind_flags) ( SizeT length, UInt prot,
    /* Ask for an advisory.  If it's negative, fail immediately. */
    req.rkind = MAny;
    req.start = 0;
-   #if defined(VGA_arm)
+   #if defined(VGA_arm) || defined(VGA_mips32)
    aspacem_assert(VKI_SHMLBA >= VKI_PAGE_SIZE);
    #else
    aspacem_assert(VKI_SHMLBA == VKI_PAGE_SIZE);
index 745bd7ee699c11fece9fff48d15b5ae5fc7b0211..ddfe2ba7134c523c416d25a96fc25a1c9a96786b 100644 (file)
@@ -375,6 +375,15 @@ static void fill_prstatus(const ThreadState *tst,
    DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
 #  undef DO
    regs->orig_gpr2 = arch->vex.guest_r2;
+#elif defined(VGP_mips32_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
@@ -455,6 +464,13 @@ static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu)
    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);
 # undef DO
+#elif defined(VGP_mips32_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
index bb559f4103258de43aa12d2362df9953d2fd4625..c08b5a78ec29da6222adf9f0b4467b0543651eb5 100644 (file)
@@ -307,6 +307,43 @@ static Int ptrace_setregs(Int pid, VexGuestArchState* vex)
 
    return VG_(ptrace)(VKI_PTRACE_POKEUSR_AREA, pid,  &pa, NULL);
 
+#elif defined(VGP_mips32_linux)
+   struct vki_user_regs_struct regs;
+   VG_(memset)(&regs, 0, sizeof(regs));
+   regs.MIPS_r0     = vex->guest_r0;
+   regs.MIPS_r1     = vex->guest_r1;
+   regs.MIPS_r2     = vex->guest_r2;
+   regs.MIPS_r3     = vex->guest_r3;
+   regs.MIPS_r4     = vex->guest_r4;
+   regs.MIPS_r5     = vex->guest_r5;
+   regs.MIPS_r6     = vex->guest_r6;
+   regs.MIPS_r7     = vex->guest_r7;
+   regs.MIPS_r8     = vex->guest_r8;
+   regs.MIPS_r9     = vex->guest_r9;
+   regs.MIPS_r10     = vex->guest_r10;
+   regs.MIPS_r11     = vex->guest_r11;
+   regs.MIPS_r12     = vex->guest_r12;
+   regs.MIPS_r13     = vex->guest_r13;
+   regs.MIPS_r14     = vex->guest_r14;
+   regs.MIPS_r15     = vex->guest_r15;
+   regs.MIPS_r16     = vex->guest_r16;
+   regs.MIPS_r17     = vex->guest_r17;
+   regs.MIPS_r18     = vex->guest_r18;
+   regs.MIPS_r19     = vex->guest_r19;
+   regs.MIPS_r20     = vex->guest_r20;
+   regs.MIPS_r21     = vex->guest_r21;
+   regs.MIPS_r22     = vex->guest_r22;
+   regs.MIPS_r23     = vex->guest_r23;
+   regs.MIPS_r24     = vex->guest_r24;
+   regs.MIPS_r25     = vex->guest_r25;
+   regs.MIPS_r26     = vex->guest_r26;
+   regs.MIPS_r27     = vex->guest_r27;
+   regs.MIPS_r28     = vex->guest_r28;
+   regs.MIPS_r29     = vex->guest_r29;
+   regs.MIPS_r30     = vex->guest_r30;
+   regs.MIPS_r31     = vex->guest_r31;
+   return VG_(ptrace)(VKI_PTRACE_SETREGS, pid, NULL, &regs);
+
 #else
 #  error Unknown arch
 #endif
index 03af598b1f789f3919f54a9c005432ce75f8af1d..5999f2eb52a9e75a4cb857ec06cd053974a0b014 100644 (file)
@@ -410,6 +410,9 @@ static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, RegSummary* regs )
 #  elif defined(VGP_s390x_linux)
    if (regno == 15) { *a = regs->sp; return True; }
    if (regno == 11) { *a = regs->fp; return True; }
+#  elif defined(VGP_mips32_linux)
+   if (regno == 29) { *a = regs->sp; return True; }
+   if (regno == 30) { *a = regs->fp; return True; }
 #  else
 #    error "Unknown platform"
 #  endif
index fa08d8ed639a6eded6bf10d447dd48a6fd6c71b6..99389c296d891eef53b5035d9c92386b793bc131 100644 (file)
@@ -792,7 +792,7 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
    is_rw_map = False;
    is_ro_map = False;
 
-#  if defined(VGA_x86) || defined(VGA_ppc32)
+#  if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32)
    is_rx_map = seg->hasR && seg->hasX;
    is_rw_map = seg->hasR && seg->hasW;
 #  elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm)
@@ -1516,6 +1516,22 @@ Bool VG_(get_fnname_no_cxx_demangle) ( Addr a, Char* buf, Int nbuf )
                          /*offsetP*/NULL );
 }
 
+/* mips-linux only: find the offset of current address. This is needed for 
+   stack unwinding for MIPS.
+*/
+Bool VG_(get_inst_offset_in_function)( Addr a,
+                                       /*OUT*/PtrdiffT* offset )
+{
+   Char fnname[64];
+   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
+                         /*below-main-renaming*/False,
+                         a, fnname, 64,
+                         /*match_anywhere_in_sym*/True, 
+                         /*show offset?*/True,
+                         /*data syms only please*/True,
+                         offset );
+}
+
 Vg_FnNameKind VG_(get_fnname_kind) ( Char* name )
 {
    if (VG_STREQ("main", name)) {
@@ -2040,6 +2056,11 @@ UWord evalCfiExpr ( XArray* exprs, Int ix,
             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)
+            case Creg_IA_IP: return eec->uregs->pc;
+            case Creg_IA_SP: return eec->uregs->sp;
+            case Creg_IA_BP: return eec->uregs->fp;
+            case Creg_MIPS_RA: return eec->uregs->ra;
 #           elif defined(VGA_ppc32) || defined(VGA_ppc64)
 #           else
 #             error "Unsupported arch"
@@ -2268,6 +2289,16 @@ static Addr compute_cfa ( D3UnwindRegs* uregs,
       case CFIC_IA_BPREL:
          cfa = cfsi->cfa_off + uregs->fp;
          break;
+#     elif defined(VGA_mips32)
+      case CFIC_IA_SPREL:
+         cfa = cfsi->cfa_off + uregs->sp;
+         break;
+      case CFIR_SAME:
+         cfa = uregs->fp;
+         break;
+      case CFIC_IA_BPREL:
+         cfa = cfsi->cfa_off + uregs->fp;
+         break;
 #     elif defined(VGA_ppc32) || defined(VGA_ppc64)
 #     else
 #       error "Unsupported arch"
@@ -2362,6 +2393,8 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
    ipHere = uregsHere->r15;
 #  elif defined(VGA_s390x)
    ipHere = uregsHere->ia;
+#  elif defined(VGA_mips32)
+   ipHere = uregsHere->pc;
 #  elif defined(VGA_ppc32) || defined(VGA_ppc64)
 #  else
 #    error "Unknown arch"
@@ -2438,6 +2471,10 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
    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)
+   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);
 #  elif defined(VGA_ppc32) || defined(VGA_ppc64)
 #  else
 #    error "Unknown arch"
index 53ca0d2c125a19293736e765966ef4c313e1dbed..193b154bc2e320b47f784c7ab1d47fc06692a3c4 100644 (file)
@@ -257,6 +257,21 @@ typedef
       Int   fp_off;
    }
    DiCfSI;
+#elif defined(VGA_mips32)
+typedef
+   struct {
+      Addr  base;
+      UInt  len;
+      UChar cfa_how; /* a CFIC_ value */
+      UChar ra_how;  /* a CFIR_ value */
+      UChar sp_how;  /* a CFIR_ value */
+      UChar fp_how;  /* a CFIR_ value */
+      Int   cfa_off;
+      Int   ra_off;
+      Int   sp_off;
+      Int   fp_off;
+   }
+   DiCfSI;
 #else
 #  error "Unknown arch"
 #endif
@@ -288,7 +303,8 @@ typedef
       Creg_ARM_R12,
       Creg_ARM_R15,
       Creg_ARM_R14,
-      Creg_S390_R14
+      Creg_S390_R14,
+      Creg_MIPS_RA
    }
    CfiReg;
 
index 36a66985035f20057b6dd6b59293c456fd27b336..9329fa2d9afbaafdd8373ede446a614f83c90cc3 100644 (file)
@@ -1843,6 +1843,10 @@ void ML_(read_debuginfo_dwarf1) (
 #  define FP_REG         11    // sometimes s390 has a frame pointer in r11
 #  define SP_REG         15    // stack is always r15
 #  define RA_REG_DEFAULT 14    // the return address is in r14
+#elif defined(VGP_mips32_linux)
+#  define FP_REG         30
+#  define SP_REG         29
+#  define RA_REG_DEFAULT 31
 #else
 #  error "Unknown platform"
 #endif
@@ -1851,7 +1855,8 @@ void ML_(read_debuginfo_dwarf1) (
    arm-linux (320) seems ludicrously high, but the ARM IHI 0040A page
    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)
+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
+    || defined(VGP_mips32_linux)
 # define N_CFI_REGS 72
 #elif defined(VGP_arm_linux)
 # define N_CFI_REGS 320
@@ -2155,7 +2160,8 @@ static Bool summarise_context( /*OUT*/DiCfSI* si,
    else
    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)
+#     if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
+         || defined(VGA_mips32)
       si->cfa_how = CFIC_IA_SPREL;
 #     elif defined(VGA_arm)
       si->cfa_how = CFIC_ARM_R13REL;
@@ -2166,7 +2172,8 @@ static Bool summarise_context( /*OUT*/DiCfSI* si,
    else
    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)
+#     if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
+         || defined(VGA_mips32)
       si->cfa_how = CFIC_IA_BPREL;
 #     elif defined(VGA_arm)
       si->cfa_how = CFIC_ARM_R12REL;
@@ -2367,6 +2374,50 @@ static Bool summarise_context( /*OUT*/DiCfSI* si,
    return True;
 
 
+#  elif defined(VGA_mips32)
+   /* --- entire tail of this fn specialised for mips --- */
+   SUMMARISE_HOW(si->ra_how, si->ra_off,
+                             ctxs->reg[ctx->ra_reg] );
+   SUMMARISE_HOW(si->fp_how, si->fp_off,
+                             ctxs->reg[FP_REG] );
+   SUMMARISE_HOW(si->sp_how, si->sp_off,
+                             ctxs->reg[SP_REG] );
+      si->sp_how = CFIR_CFAREL;
+   si->sp_off = 0;
+
+   if (si->fp_how == CFIR_UNKNOWN)
+       si->fp_how = CFIR_SAME;
+   if (si->cfa_how == CFIR_UNKNOWN) {
+      si->cfa_how = CFIC_IA_SPREL;
+      si->cfa_off = 160;
+   }
+   if (si->ra_how == CFIR_UNKNOWN) {
+      if (!debuginfo->cfsi_exprs)
+         debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
+                                             "di.ccCt.2a",
+                                             ML_(dinfo_free),
+                                             sizeof(CfiExpr) );
+      si->ra_how = CFIR_EXPR;
+      si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
+                                        Creg_MIPS_RA);
+   }
+
+   if (si->ra_how == CFIR_SAME)
+      { why = 3; goto failed; }
+
+   if (loc_start >= ctx->loc) 
+      { why = 4; goto failed; }
+   if (ctx->loc - loc_start > 10000000 /* let's say */)
+      { why = 5; goto failed; }
+
+   si->base = loc_start + ctx->initloc;
+   si->len  = (UInt)(ctx->loc - loc_start);
+
+   return True;
+
+
 
 #  elif defined(VGA_ppc32) || defined(VGA_ppc64)
 #  else
@@ -2449,6 +2500,13 @@ static Int copy_convert_CfiExpr_tree ( XArray*        dstxa,
             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)
+         if (dwreg == SP_REG)
+            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
+         if (dwreg == FP_REG)
+            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
+         if (dwreg == srcuc->ra_reg)
+            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP );
 #        elif defined(VGA_ppc32) || defined(VGA_ppc64)
 #        else
 #           error "Unknown arch"
index 99b213c88dad4721ff1921818c59aa2114d84e02..1654097fdd3696fd82f94bc317ad99027641d323 100644 (file)
@@ -2307,8 +2307,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents,
                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;
index 3a701224c369b8edb885b136dddd5f6cf42d7432..40f5eea6fff01b7dddf5343a6b66b03b6a0c6b23 100644 (file)
@@ -1955,7 +1955,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
 
       /* 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_arm_linux) || defined (VGP_s390x_linux) \
+         || defined(VGP_mips32_linux)
       /* Accept .plt where mapped as rx (code) */
       if (0 == VG_(strcmp)(name, ".plt")) {
          if (inrx && size > 0 && !di->plt_present) {
index b90b2e721a3e9ba98d8b37045e8a43be624ea5aa..a5fe07f0075f273b747441891e399e1247f59e96 100644 (file)
@@ -189,7 +189,7 @@ void ML_(ppDiCfSI) ( XArray* /* of CfiExpr */ exprs, DiCfSI* si )
    VG_(printf)(" R7=");
    SHOW_HOW(si->r7_how, si->r7_off);
 #  elif defined(VGA_ppc32) || defined(VGA_ppc64)
-#  elif defined(VGA_s390x)
+#  elif defined(VGA_s390x) || defined(VGA_mips32)
    VG_(printf)(" SP=");
    SHOW_HOW(si->sp_how, si->sp_off);
    VG_(printf)(" FP=");
@@ -629,6 +629,7 @@ static void ppCfiReg ( CfiReg reg )
       case Creg_ARM_R12: VG_(printf)("R12"); break;
       case Creg_ARM_R15: VG_(printf)("R15"); break;
       case Creg_ARM_R14: VG_(printf)("R14"); break;
+      case Creg_MIPS_RA: VG_(printf)("RA"); break;
       default: vg_assert(0);
    }
 }
index 44f7376f7a742372c4fb98101b222b84728ece7b..8e1c032742db0ff4919aeab1a927fed60f878bd3 100644 (file)
@@ -388,6 +388,43 @@ static UInt local_sys_getpid ( void )
    return (UInt)(__res);
 }
 
+#elif defined(VGP_mips32_linux)
+static UInt local_sys_write_stderr ( HChar* buf, Int n )
+{
+   volatile Int block[2];
+   block[0] = (Int)buf;
+   block[1] = n;
+   __asm__ volatile (
+      "li   $4, 2\n\t"        /* stderr */
+      "lw   $5, 0(%0)\n\t"    /* buf */
+      "lw   $6, 4(%0)\n\t"    /* n */
+      "move $7, $0\n\t"
+      "li   $2, %1\n\t"       /* set v0 = __NR_write */
+      "syscall\n\t"           /* write() */
+      "nop\n\t"
+      :
+      : "r" (block), "n" (__NR_write)
+      : "2", "4", "5", "6", "7"
+   );
+   if (block[0] < 0)
+      block[0] = -1;
+   return (UInt)block[0];
+}
+
+static UInt local_sys_getpid ( void )
+{
+   UInt __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 __res;
+}
+
 
 #else
 # error Unknown platform
index 905efb929ffad529b84294e353c5fe2b51360349..6117fcee62a83e75bb283f1378a36f7351a8b0c3 100644 (file)
@@ -618,6 +618,8 @@ void valgrind_initialize_target(void)
    ppc64_init_architecture(&the_low_target);
 #elif defined(VGA_s390x)
    s390x_init_architecture(&the_low_target);
+#elif defined(VGA_mips32)
+   s390x_init_architecture(&the_low_target);
 #else
    architecture missing in target.c valgrind_initialize_target
 #endif
index 29dafcdd8203d1631da5436e41cb7ede92c4d33d..0348895d63e6b4048ede7f4656bc4b6fce141088 100644 (file)
@@ -73,5 +73,6 @@ extern void arm_init_architecture (struct valgrind_target_ops *target);
 extern void ppc32_init_architecture (struct valgrind_target_ops *target);
 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);
 
 #endif
index b752f01aad23ad746abeff67372485a40ebedb14..8acc7b0f51c11b2f7ce4c8c1b1a73ca49f787a9a 100644 (file)
@@ -1081,6 +1081,20 @@ void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii )
    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
index 1f5b95cc61ecce10988e43225c1adfcaab0ce12a..a8e7e11a7ce406614a865843b55bdc1a4fb50c7a 100644 (file)
         (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
index 4bc07cbe38ee6d58f4c95e47ecef3ad413eae8e8..e8368b3225eb85387fcf15a3c7b9283258d531a8 100644 (file)
@@ -194,7 +194,17 @@ Int VG_(write) ( Int fd, const void* buf, Int count)
 
 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 @@ SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
                           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 @@ Int VG_(socket) ( Int domain, Int type, Int protocol )
    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 @@ Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
    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 @@ Int VG_(write_socket)( Int sd, void *msg, Int count )
    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_(write_socket)( Int sd, void *msg, Int count )
 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_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
 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 @@ Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
    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, 
index 21fee60b89c83eb02a648a56561030e9c2e4ec57..6f0c71b3878be9de00cf4663673a14576038a340 100644 (file)
@@ -549,7 +549,8 @@ Int VG_(getgroups)( Int size, UInt* list )
 
 #  elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)  \
         || defined(VGP_arm_linux)                             \
-        || defined(VGO_darwin) || defined(VGP_s390x_linux)
+        || defined(VGO_darwin) || defined(VGP_s390x_linux)    \
+        || defined(VGP_mips32_linux)
    SysRes sres;
    sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list);
    if (sr_isError(sres))
@@ -764,6 +765,11 @@ void VG_(invalidate_icache) ( void *ptr, SizeT nbytes )
    Addr endaddr   = startaddr + nbytes;
    VG_(do_syscall2)(__NR_ARM_cacheflush, startaddr, endaddr);
 
+#  elif defined(VGA_mips32)
+   SysRes sres = VG_(do_syscall3)(__NR_cacheflush, (UWord) ptr,
+                                 (UWord) nbytes, (UWord) 3);
+   vg_assert( sres._isError == 0 );
+
 #  else
 #    error "Unknown ARCH"
 #  endif
index 9980640ddf2fe8d1fc7f7dd0a36b41ab89a3471d..047c508555c2ce110f63c4a493455be61699b40c 100644 (file)
@@ -103,6 +103,15 @@ void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
       = 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 @@ void VG_(set_syscall_return_shadows) ( ThreadId tid,
 #  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 @@ static void apply_to_GPs_of_tid(ThreadId tid, void (*f)(ThreadId, HChar*, Addr))
    (*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 @@ Int VG_(machine_arm_archlevel) = 4;
 /* 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 @@ static UInt VG_(get_machine_model)(void)
 
 #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 @@ Bool VG_(machine_get_hwcaps)( void )
      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 @@ Int VG_(machine_get_size_of_largest_guest_register) ( void )
       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 @@ void* VG_(fnptr_to_fnentry)( void* f )
 #  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
index 71065ce399777ddf463886ac2f7a9f065866e7b0..7a35112eca12e924f9e6dc49c1b0549d6c53ff4f 100644 (file)
@@ -1539,8 +1539,10 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
    //   p: logging, plausible-stack
    //--------------------------------------------------------------
    VG_(debugLog)(1, "main", "Starting the address space manager\n");
-   vg_assert(VKI_PAGE_SIZE     == 4096 || VKI_PAGE_SIZE     == 65536);
-   vg_assert(VKI_MAX_PAGE_SIZE == 4096 || VKI_MAX_PAGE_SIZE == 65536);
+   vg_assert(VKI_PAGE_SIZE     == 4096 || VKI_PAGE_SIZE     == 65536
+             || VKI_PAGE_SIZE     == 16384);
+   vg_assert(VKI_MAX_PAGE_SIZE == 4096 || VKI_MAX_PAGE_SIZE == 65536
+             || VKI_MAX_PAGE_SIZE == 16384);
    vg_assert(VKI_PAGE_SIZE <= VKI_MAX_PAGE_SIZE);
    vg_assert(VKI_PAGE_SIZE     == (1 << VKI_PAGE_SHIFT));
    vg_assert(VKI_MAX_PAGE_SIZE == (1 << VKI_MAX_PAGE_SHIFT));
@@ -1894,6 +1896,8 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
       iters = 5;
 #     elif defined(VGP_s390x_linux)
       iters = 10;
+#     elif defined(VGP_mips32_linux)
+      iters = 10;
 #     elif defined(VGO_darwin)
       iters = 3;
 #     else
@@ -2473,6 +2477,10 @@ static void final_tidyup(ThreadId tid)
 #  if defined(VGP_ppc64_linux)
    VG_(threads)[tid].arch.vex.guest_GPR2 = r2;
 #  endif
+   /* mips-linux note: we need to set t9 */
+#  if defined(VGP_mips32_linux)
+   VG_(threads)[tid].arch.vex.guest_r25 = __libc_freeres_wrapper;
+#  endif
 
    /* Block all blockable signals by copying the real block state into
       the thread's block state*/
@@ -2761,6 +2769,50 @@ asm("\n"
     "\t.word "VG_STRINGIFY(VG_STACK_GUARD_SZB)"\n"
     "\t.word "VG_STRINGIFY(VG_STACK_ACTIVE_SZB)"\n"
 );
+#elif defined(VGP_mips32_linux)
+asm("\n"
+    "\t.type _gp_disp,@object\n"
+    ".text\n"
+    "\t.globl __start\n"
+    "\t.type __start,@function\n"
+    "__start:\n"
+
+    "\tbal 1f\n"
+    "\tnop\n"
+    
+    "1:\n"    
+
+    "\tlui      $28, %hi(_gp_disp)\n"
+    "\taddiu    $28, $28, %lo(_gp_disp)\n"
+    "\taddu     $28, $28, $31\n"
+    /* t1/$9 <- Addr(interim_stack) */
+    "\tlui      $9, %hi(vgPlain_interim_stack)\n"
+    /* t1/$9 <- Addr(interim_stack) */
+    "\taddiu    $9, %lo(vgPlain_interim_stack)\n"
+
+
+    "\tli    $10, "VG_STRINGIFY(VG_STACK_GUARD_SZB)"\n"
+    "\tli    $11, "VG_STRINGIFY(VG_STACK_ACTIVE_SZB)"\n"
+    
+    "\taddu     $9, $9, $10\n"
+    "\taddu     $9, $9, $11\n"
+    "\tli       $12, 0xFFFFFFF0\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     $25, %hi(_start_in_C_linux)\n"
+    "\taddiu   $25, %lo(_start_in_C_linux)\n"
+    
+    "\tbal  _start_in_C_linux\n"
+    "\tbreak  0x7\n"
+    ".previous\n"
+);
 #else
 #  error "Unknown linux platform"
 #endif
index fd24c1a025784c0581c5606277060416b7816f43..50e00ac781304483f8705cf3d9b80ecad0592679 100644 (file)
@@ -1358,6 +1358,17 @@ void VG_(redir_initialise) ( void )
 #  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
index 4c7ef60fcd00c44867c391cc6ce5a9681cb7b9e8..93fa109356ec95217e1b7194cba07b9a7d8a1863 100644 (file)
@@ -780,6 +780,10 @@ static void do_pre_run_checks ( ThreadState* tst )
 #  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 @@ void VG_(nuke_all_threads_except) ( ThreadId me, VgSchedReturnCode src )
 #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
index 81a53b1f65ecc8a30aeb61b71de89dad9d7290db..9ef6b852a50f03b591b5c6f00d2c45117c7eb32b 100644 (file)
@@ -516,6 +516,25 @@ typedef struct SigQueue {
         (srP)->misc.S390X.r_lr = (uc)->uc_mcontext.regs.gprs[14];  \
       }
 
+#elif defined(VGP_mips32_linux)
+#  define VG_UCONTEXT_INSTR_PTR(uc)   ((UWord)(((uc)->uc_mcontext.sc_pc)))
+#  define VG_UCONTEXT_STACK_PTR(uc)   ((UWord)((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_mips32_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.MIPS32.r30 = (uc)->uc_mcontext.sc_regs[30]; \
+        (srP)->misc.MIPS32.r31 = (uc)->uc_mcontext.sc_regs[31]; \
+        (srP)->misc.MIPS32.r28 = (uc)->uc_mcontext.sc_regs[28]; \
+      }
+
 
 #else 
 #  error Unknown platform
@@ -849,6 +868,14 @@ extern void my_sigreturn(void);
    " svc " #name "\n" \
    ".previous\n"
 
+#elif defined(VGP_mips32_linux)
+#  define _MY_SIGRETURN(name) \
+   ".text\n" \
+   "my_sigreturn:\n" \
+   "   li      $2, " #name "\n" /* apparently $2 is v0 */ \
+   "   syscall\n" \
+   ".previous\n"
+
 #else
 #  error Unknown platform
 #endif
@@ -891,7 +918,8 @@ static void handle_SCSS_change ( Bool force_update )
       ksa.ksa_handler = skss.skss_per_sig[sig].skss_handler;
       ksa.sa_flags    = skss.skss_per_sig[sig].skss_flags;
 #     if !defined(VGP_ppc32_linux) && \
-         !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin)
+         !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
+         !defined(VGP_mips32_linux)
       ksa.sa_restorer = my_sigreturn;
 #     endif
       /* Re above ifdef (also the assertion below), PaulM says:
@@ -924,7 +952,8 @@ static void handle_SCSS_change ( Bool force_update )
          vg_assert(ksa_old.sa_flags 
                    == skss_old.skss_per_sig[sig].skss_flags);
 #        if !defined(VGP_ppc32_linux) && \
-            !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin)
+            !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
+            !defined(VGP_mips32_linux)
          vg_assert(ksa_old.sa_restorer 
                    == my_sigreturn);
 #        endif
@@ -1855,6 +1884,27 @@ void VG_(synth_sigtrap)(ThreadId tid)
    info.si_signo = VKI_SIGTRAP;
    info.si_code = VKI_TRAP_BRKPT; /* tjh: only ever called for a brkpt ins */
 
+#  if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
+   /* This is for teq on mips. Teq on mips for ins: 0xXXX1f4 
+    * cases VKI_SIGFPE not VKI_SIGTRAP 
+   */
+   // JRS 2012-Jun-06: commented out until we know we need it
+   // This isn't a clean solution; need something that avoids looking
+   // at the guest code.
+   //UInt *ins = (void*)(vgPlain_threads[tid].arch.vex.guest_PC-4);
+   //UInt tcode = (((*ins) >> 6) & ((1 << 10) - 1));
+   //if (tcode == VKI_BRK_OVERFLOW || tcode == VKI_BRK_DIVZERO) {
+   //   if (tcode == VKI_BRK_DIVZERO)
+   //      info.si_code = VKI_FPE_INTDIV;
+   //   else
+   //      info.si_code = VKI_FPE_INTOVF;
+   //   info.si_signo = VKI_SIGFPE;
+   //   info.si_errno = 0;
+   //   info.VKI_SIGINFO_si_addr 
+   //      = (void*)(vgPlain_threads[tid].arch.vex.guest_PC-4);
+   //}
+#  endif
+
 #  if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
    uc.uc_mcontext.trapno = 3;     /* tjh: this is the x86 trap number
                                           for a breakpoint trap... */
index bb76931402a8b1b858e19d5370768a81563c9f93..19b347b8bdb4150e9832a6c643197572faa68f1e 100644 (file)
@@ -668,7 +668,9 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
 #endif
 
 /* ------------------------ s390x ------------------------- */
+
 #if defined(VGP_s390x_linux)
+
 UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
                                /*OUT*/Addr* ips, UInt max_n_ips,
                                /*OUT*/Addr* sps, /*OUT*/Addr* fps,
@@ -744,8 +746,157 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
    n_found = i;
    return n_found;
 }
+
 #endif
 
+/* ------------------------ mips 32------------------------- */
+
+#if defined(VGP_mips32_linux)
+
+UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
+                               /*OUT*/Addr* ips, UInt max_n_ips,
+                               /*OUT*/Addr* sps, /*OUT*/Addr* fps,
+                               UnwindStartRegs* startRegs,
+                               Addr fp_max_orig )
+{
+   Bool  debug = False;
+   Int   i;
+   Addr  fp_max;
+   UInt  n_found = 0;
+
+   vg_assert(sizeof(Addr) == sizeof(UWord));
+   vg_assert(sizeof(Addr) == sizeof(void*));
+
+   D3UnwindRegs uregs;
+   uregs.pc = startRegs->r_pc;
+   uregs.sp = startRegs->r_sp;
+   Addr fp_min = uregs.sp;
+
+   uregs.fp = startRegs->misc.MIPS32.r30;
+   uregs.ra = startRegs->misc.MIPS32.r31;
+
+   /* 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
+      when FP is not a reasonable stack location. */
+
+   fp_max = VG_PGROUNDUP(fp_max_orig);
+   if (fp_max >= sizeof(Addr))
+      fp_max -= sizeof(Addr);
+
+   if (debug)
+      VG_(printf)("max_n_ips=%d fp_min=0x%lx fp_max_orig=0x%lx, "
+                  "fp_max=0x%lx pc=0x%lx sp=0x%lx fp=0x%lx\n",
+                  max_n_ips, fp_min, fp_max_orig, fp_max,
+                  uregs.pc, uregs.sp, uregs.fp);
+
+   if (sps) sps[0] = uregs.sp;
+   if (fps) fps[0] = uregs.fp;
+   ips[0] = uregs.pc;
+   i = 1;
+
+   /* Loop unwinding the stack. */
+
+   while (True) {
+      if (debug) {
+         VG_(printf)("i: %d, pc: 0x%lx, sp: 0x%lx, ra: 0x%lx\n",
+                     i, uregs.pc, uregs.sp, uregs.ra);
+      }
+      if (i >= max_n_ips)
+         break;
+
+      if (VG_(use_CF_info)( &uregs, fp_min, fp_max )) {
+         if (debug)
+            VG_(printf)("USING CFI: pc: 0x%lx, sp: 0x%lx, ra: 0x%lx\n",
+                        uregs.pc, uregs.sp, uregs.ra);
+         if (0 == uregs.pc || 1 == uregs.pc) break;
+         if (sps) sps[i] = uregs.sp;
+         if (fps) fps[i] = uregs.fp;
+         ips[i++] = uregs.pc - 4;
+         uregs.pc = uregs.pc - 4;
+         continue;
+      }
+
+      int seen_sp_adjust = 0;
+      long frame_offset = 0;
+      PtrdiffT offset;
+      if (VG_(get_inst_offset_in_function)(uregs.pc, &offset)) {
+         Addr start_pc = uregs.pc - offset;
+         Addr limit_pc = uregs.pc;
+         Addr cur_pc;
+         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);
+            if(debug)
+               VG_(printf)("cur_pc: 0x%lx, inst: 0x%lx\n", cur_pc, inst);
+
+            /* 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 */
+                || high_word == 0x67bd) {  /* daddiu $sp,$sp,-i */
+               if (low_word & 0x8000)  /* negative stack adjustment? */
+                  frame_offset += 0x10000 - low_word;
+               else
+                  /* Exit loop if a positive stack adjustment is found, which
+                     usually means that the stack cleanup code in the function
+                     epilogue is reached.  */
+               break;
+            seen_sp_adjust = 1;
+            }
+         }
+         if(debug)
+            VG_(printf)("offset: 0x%lx\n", frame_offset);
+      }
+      if (seen_sp_adjust) {
+         if (0 == uregs.pc || 1 == uregs.pc) break;
+         if (uregs.pc == uregs.ra - 8) break;
+         if (sps) {
+            sps[i] = uregs.sp + frame_offset;
+         }
+         uregs.sp = uregs.sp + frame_offset;
+         
+         if (fps) {
+            fps[i] = fps[0];
+            uregs.fp = fps[0];
+         }
+         if (0 == uregs.ra || 1 == uregs.ra) break;
+         uregs.pc = uregs.ra - 8;
+         ips[i++] = uregs.ra - 8;
+         continue;
+      }
+
+      if (i == 1) {
+         if (sps) {
+            sps[i] = sps[0];
+            uregs.sp = sps[0];
+         }
+         if (fps) {
+            fps[i] = fps[0];
+            uregs.fp = fps[0];
+         }
+         if (0 == uregs.ra || 1 == uregs.ra) break;
+         uregs.pc = uregs.ra - 8;
+         ips[i++] = uregs.ra - 8;
+         continue;
+      }
+      /* No luck.  We have to give up. */
+      break;
+   }
+
+   n_found = i;
+   return n_found;
+}
+
+#endif
+
+
 /*------------------------------------------------------------*/
 /*---                                                      ---*/
 /*--- END platform-dependent unwinder worker functions     ---*/
index 05083d5ef0c2332c5cdb03348efde5c8ba5daeaf..a52aeb0aaefe5abb863714a1a2234fd7230a34b8 100644 (file)
@@ -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 @@ SysRes VG_(mk_SysRes_x86_linux) ( Int val ) {
 /* 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 @@ SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) {
 /* 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 @@ SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) {
 /* 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_ppc64_linux) ( ULong val, ULong cr0so ) {
 
 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_s390x_linux) ( Long val ) {
 
 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 @@ SysRes VG_(mk_SysRes_arm_linux) ( Int val ) {
    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_Error) ( UWord err ) {
 
 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 @@ static UWord do_syscall_WRK (
    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 @@ SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3,
    }
 
    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
index 8069cbdb64df18c8467cf51c7eb96950e14f7cfc..9040148cff07fd660e73e0f7a5fe302371d19889 100644 (file)
@@ -98,6 +98,15 @@ typedef
       Int o_arg6;
       Int uu_arg7;
       Int uu_arg8;
+#     elif defined(VGP_mips32_linux)
+      Int o_arg1;
+      Int o_arg2;
+      Int o_arg3;
+      Int o_arg4;
+      Int s_arg5;
+      Int s_arg6;
+      Int uu_arg7;
+      Int uu_arg8;
 #     elif defined(VGP_x86_darwin)
       Int s_arg1;
       Int s_arg2;
@@ -167,6 +176,16 @@ typedef
    fixed sized table exposed to the caller, but that's too inflexible;
    hence now use a function which can do arbitrary messing around to
    find the required entry. */
+#if defined(VGP_mips32_linux)
+   /* Up to 6 parameters, 4 in registers 2 on stack. */
+#  define PRA1(s,t,a) PRRAn(1,s,t,a)
+#  define PRA2(s,t,a) PRRAn(2,s,t,a)
+#  define PRA3(s,t,a) PRRAn(3,s,t,a)
+#  define PRA4(s,t,a) PRRAn(4,s,t,a)
+#  define PRA5(s,t,a) PSRAn(5,s,t,a)
+#  define PRA6(s,t,a) PSRAn(6,s,t,a)
+
+#endif
 #if defined(VGO_linux)
 extern
 SyscallTableEntry* ML_(get_linux_syscall_entry)( UInt sysno );
@@ -359,7 +378,16 @@ static inline UWord getERR ( SyscallStatus* st ) {
    PRAn  == "pre-read-argument"
 */
 
-#if defined(VGO_linux)
+#if defined(VGP_mips32_linux)
+   /* Up to 6 parameters, 4 in registers 2 on stack. */
+#  define PRA1(s,t,a) PRRAn(1,s,t,a)
+#  define PRA2(s,t,a) PRRAn(2,s,t,a)
+#  define PRA3(s,t,a) PRRAn(3,s,t,a)
+#  define PRA4(s,t,a) PRRAn(4,s,t,a)
+#  define PRA5(s,t,a) PSRAn(5,s,t,a)
+#  define PRA6(s,t,a) PSRAn(6,s,t,a)
+
+#elif defined(VGO_linux) && !defined(VGP_mips32_linux)
    /* Up to 6 parameters, all in registers. */
 #  define PRA1(s,t,a) PRRAn(1,s,t,a)
 #  define PRA2(s,t,a) PRRAn(2,s,t,a)
@@ -480,6 +508,18 @@ static inline UWord getERR ( SyscallStatus* st ) {
    since the least significant parts of the guest register are stored
    in memory at the highest address.
 */
+#if (defined(VGP_mips32_linux) && defined (_MIPSEB))
+ #define PSRAn_BE(n,s,t,a)                                         \
+    do {                                                           \
+      Addr next = layout->s_arg##n + sizeof(UWord) +              \
+                  VG_(threads)[tid].arch.vex.guest_r29;           \
+      vg_assert(sizeof(t) <= sizeof(UWord));                      \
+      VG_(tdict).track_pre_mem_read(                              \
+         Vg_CoreSysCallArgInMem, tid, s"("#a")",                  \
+         next-sizeof(t), sizeof(t)                                \
+      );                                                          \
+   } while (0)
+#else
 #define PSRAn_BE(n,s,t,a)                                         \
    do {                                                           \
       Addr next = layout->o_arg##n + sizeof(UWord) +              \
@@ -490,6 +530,7 @@ static inline UWord getERR ( SyscallStatus* st ) {
          next-sizeof(t), sizeof(t)                                \
       );                                                          \
    } while (0)
+#endif
 
 #if defined(VG_BIGENDIAN)
 #  define PSRAn(n,s,t,a) PSRAn_BE(n,s,t,a)
index 62eb3bf63a80da278659e82cbe845003daf7cc5a..7d97b6f800554ffb9d9e47960705d46c5295ef38 100644 (file)
@@ -271,6 +271,17 @@ static void run_a_thread_NORETURN ( Word tidW )
          : "d" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)
          : "2"
       );
+#elif defined(VGP_mips32_linux)
+      asm volatile (
+         "sw   %1, %0\n\t"     /* set tst->status = VgTs_Empty */
+         "li   $2, %2\n\t"     /* set v0 = __NR_exit */
+         "lw   $4, %3\n\t"     /* set a0 = tst->os_state.exitcode */
+         "syscall\n\t"         /* exit(tst->os_state.exitcode) */
+         "nop"
+         : "=m" (tst->status)
+         : "r" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)
+         : "cc", "memory" , "v0", "a0"
+      );
 #else
 # error Unknown platform
 #endif
@@ -414,7 +425,7 @@ SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
       VG_(clone) stuff */
 #if defined(VGP_x86_linux) \
     || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
-    || defined(VGP_arm_linux)
+    || defined(VGP_arm_linux) || defined(VGP_mips32_linux)
    res = VG_(do_syscall5)( __NR_clone, flags, 
                            (UWord)NULL, (UWord)parent_tidptr, 
                            (UWord)NULL, (UWord)child_tidptr );
index 991e00986180a375e5b5bf2198709babbbd70afe..8c31dd1b0e759b0ab6397891383389ef03ea8b05 100644 (file)
@@ -68,6 +68,7 @@
    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)
 
    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
@@ -462,6 +463,27 @@ void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs*       canonical,
    canonical->arg7  = 0;
    canonical->arg8  = 0;
 
+#elif defined(VGP_mips32_linux)
+   VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
+   canonical->sysno = gst->guest_r2;    // v0
+   if (canonical->sysno != __NR_syscall) {
+      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  = *((UInt*) (gst->guest_r29 + 16));    // 16(guest_SP/sp)
+      canonical->arg6  = *((UInt*) (gst->guest_r29 + 20));    // 20(sp)
+   } else {
+      // Fixme hack handle syscall()
+      canonical->sysno = gst->guest_r4;    // a0
+      canonical->arg1  = gst->guest_r5;    // a1
+      canonical->arg2  = gst->guest_r6;    // a2
+      canonical->arg3  = gst->guest_r7;    // a3
+      canonical->arg4  = *((UInt*) (gst->guest_r29 + 16));    // 16(guest_SP/sp)
+      canonical->arg5  = *((UInt*) (gst->guest_r29 + 20));    // 20(guest_SP/sp)
+      canonical->arg6  = *((UInt*) (gst->guest_r29 + 24));    // 24(guest_SP/sp)
+   }
+
 #elif defined(VGP_x86_darwin)
    VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
    UWord *stack = (UWord *)gst->guest_ESP;
@@ -695,6 +717,16 @@ void putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs*       canonical,
    gst->guest_r6     = canonical->arg5;
    gst->guest_r7     = canonical->arg6;
 
+#elif defined(VGP_mips32_linux)
+   VexGuestMIPS32State* gst = (VexGuestMIPS32State*)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;
+   *((UInt*) (gst->guest_r29 + 16)) = canonical->arg5;    // 16(guest_GPR29/sp)
+   *((UInt*) (gst->guest_r29 + 20)) = canonical->arg6;    // 20(sp)
+
 #else
 #  error "putSyscallArgsIntoGuestState: unknown arch"
 #endif
@@ -733,6 +765,14 @@ void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus*     canonical,
    canonical->sres = VG_(mk_SysRes_arm_linux)( gst->guest_R0 );
    canonical->what = SsComplete;
 
+#  elif defined(VGP_mips32_linux)
+   VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
+   UInt                v0 = gst->guest_r2;    // v0
+   UInt                v1 = gst->guest_r3;    // v1
+   UInt                a3 = gst->guest_r7;    // a3
+   canonical->sres = VG_(mk_SysRes_mips32_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;
@@ -965,6 +1005,24 @@ void putSyscallStatusIntoGuestState ( /*IN*/ ThreadId tid,
       gst->guest_r2 = sr_Res(canonical->sres);
    }
 
+#  elif defined(VGP_mips32_linux)
+   VexGuestMIPS32State* gst = (VexGuestMIPS32State*)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_mips32_r2, sizeof(UWord) );
+   VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+             OFFSET_mips32_r3, sizeof(UWord) );
+   VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+             OFFSET_mips32_r7, sizeof(UWord) );
+
 #  else
 #    error "putSyscallStatusIntoGuestState: unknown arch"
 #  endif
@@ -1033,6 +1091,17 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout )
    layout->uu_arg7  = -1; /* impossible value */
    layout->uu_arg8  = -1; /* impossible value */
 
+#elif defined(VGP_mips32_linux)
+   layout->o_sysno  = OFFSET_mips32_r2;
+   layout->o_arg1   = OFFSET_mips32_r4;
+   layout->o_arg2   = OFFSET_mips32_r5;
+   layout->o_arg3   = OFFSET_mips32_r6;
+   layout->o_arg4   = OFFSET_mips32_r7;
+   layout->s_arg5   = sizeof(UWord) * 4;
+   layout->s_arg6   = sizeof(UWord) * 5;
+   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
@@ -1887,11 +1956,45 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch )
 
       vg_assert(p[0] == 0x0A);
    }
+
+#elif defined(VGP_mips32_linux)
+
+   arch->vex.guest_PC -= 4;             // sizeof(mips instr)
+
+   /* Make sure our caller is actually sane, and we're really backing
+      back over a syscall.
+      
+      syscall == 00 00 00 0C 
+      big endian
+      syscall == 0C 00 00 00
+   */
+   {
+      UChar *p = (UChar *)(arch->vex.guest_PC);
+#     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",
+                      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",
+                      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);
+#     else
+#        error "Unknown endianness"
+#     endif
+   }
+
 #else
 #  error "ML_(fixup_guest_state_to_restart_syscall): unknown plat"
 #endif
 }
 
+
 /* 
    Fix up the guest state when a syscall is interrupted by a signal
    and so has been forced to return 'sysret'.
@@ -1902,7 +2005,7 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch )
 
      1. unblock signals
      2. perform syscall
-     3. save result to guest state (EAX, RAX, R3+CR0.SO)
+     3. save result to guest state (EAX, RAX, R3+CR0.SO, R0, V0)
      4. re-block signals
 
    If a signal
index 73ef862597bf57be94ad8d706d38b54af66272bc..d10b8407ea5b114f2333d16e76b162b5fc7dfa3d 100644 (file)
@@ -1021,6 +1021,64 @@ VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
 VG_(trampoline_stuff_end):
        .fill 2048, 2, 0x0000
 
+/*---------------------- mips32-linux ----------------------*/
+#else
+#if defined(VGP_mips32_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_(mips32_linux_SUBST_FOR_sigreturn)
+VG_(mips32_linux_SUBST_FOR_sigreturn):
+        li $v0,__NR_sigreturn
+        syscall
+        nop
+        .long 0        /*illegal insn*/
+
+.global VG_(mips32_linux_SUBST_FOR_rt_sigreturn)
+VG_(mips32_linux_SUBST_FOR_rt_sigreturn):
+       li $v0,__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_(mips32_linux_REDIR_FOR_strlen)
+.type   VG_(mips32_linux_REDIR_FOR_strlen), @function
+VG_(mips32_linux_REDIR_FOR_strlen):
+      li $v0, 0
+      //la $a0, string
+      j strlen_cond
+   strlen_loop:
+      addi $v0, $v0, 1
+      addi $a0, $a0, 1
+   strlen_cond:
+      lbu $t0, ($a0)
+      bne $t0, $zero, strlen_loop
+    jr $ra
+
+.size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_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
@@ -1032,6 +1090,7 @@ VG_(trampoline_stuff_end):
 #endif
 #endif
 #endif
+#endif
 
 #if defined(VGO_linux)
 /* Let the linker know we don't need an executable stack */
index d0551019e08de1bbcd8b28cc49a983b3b8b8816e..fc6fa6287cca3355af6c778b3af7c8ebb94786f2 100644 (file)
@@ -726,7 +726,7 @@ void log_bytes ( HChar* bytes, Int nbytes )
 
 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 @@ Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRSB* bb )
          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 @@ Bool mk_preamble__set_NRADDR_to_nraddr ( void* closureV, IRSB* bb )
             : 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,
index 150d3be1e2f1bb08db5dccd8750d2d0f8864b115..39b5ae7b745a634c5163514f9b4a0e7e1ac54dce 100644 (file)
@@ -343,7 +343,8 @@ extern Bool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard,
 // stacks.  The address space manager provides and suitably
 // protects such stacks.
 
-#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
+    || defined(VGP_mips32_linux)
 # define VG_STACK_GUARD_SZB  65536  // 1 or 16 pages
 # define VG_STACK_ACTIVE_SZB (4096 * 256) // 1Mb
 #else
index f0861d4ce2d6a7547339a69aeb994b9c0cb3ba0d..63db17f41e47357f06d543bebdef8567e849857f 100644 (file)
@@ -60,6 +60,8 @@
 #  include "libvex_guest_arm.h"
 #elif defined(VGA_s390x)
 #  include "libvex_guest_s390x.h"
+#elif defined(VGA_mips32)
+#  include "libvex_guest_mips32.h"
 #else
 #  error Unknown arch
 #endif
@@ -83,8 +85,8 @@
 
 typedef
    struct {
-      ULong r_pc; /* x86:EIP, amd64:RIP, ppc:CIA, arm:R15 */
-      ULong r_sp; /* x86:ESP, amd64:RSP, ppc:R1,  arm:R13 */
+      ULong r_pc; /* x86:EIP, amd64:RIP, ppc:CIA, arm:R15, mips:pc */
+      ULong r_sp; /* x86:ESP, amd64:RSP, ppc:R1,  arm:R13, mips:sp */
       union {
          struct {
             UInt r_ebp;
@@ -108,6 +110,11 @@ typedef
             ULong r_fp;
             ULong r_lr;
          } S390X;
+         struct {
+            UInt r30;  /* Stack frame pointer or subroutine variable  */
+            UInt r31;  /* Return address of the last subroutine call */
+            UInt r28;
+         } MIPS32;
       } misc;
    }
    UnwindStartRegs;
index fa1b12955018e83866b855672a75a1e3edbd9656..8655260729ceeaad3c1b2cdb4069a18bfba0acca 100644 (file)
@@ -93,6 +93,12 @@ Bool VG_(get_fnname_raw) ( Addr a, Char* buf, Int nbuf );
 extern
 Bool VG_(get_fnname_no_cxx_demangle) ( Addr a, Char* buf, Int nbuf );
 
+/* mips-linux only: find the offset of current address. This is needed for 
+   stack unwinding for MIPS.
+*/
+extern
+Bool VG_(get_inst_offset_in_function)( Addr a, /*OUT*/PtrdiffT* offset );
+
 
 /* Use DWARF2/3 CFA information to do one step of stack unwinding.
    D3UnwindRegs holds the current register values, and is
@@ -114,6 +120,10 @@ typedef
 typedef
    struct { Addr ia; Addr sp; Addr fp; Addr lr;}
    D3UnwindRegs;
+#elif defined(VGA_mips32)
+typedef
+   struct { Addr pc; Addr sp; Addr fp; Addr ra; }
+   D3UnwindRegs;
 #else
 #  error "Unsupported arch"
 #endif
index b76f395f9ba820a52c518d1dbae026c0822f407d..4b3ad6c9c15415c5e890902b2d45110e40b586b4 100644 (file)
 #  define VG_ELF_MACHINE      EM_S390
 #  define VG_ELF_CLASS        ELFCLASS64
 #  undef  VG_PLAT_USES_PPCTOC
+#elif defined(VGP_mips32_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        ELFCLASS32
+#  undef  VG_PLAT_USES_PPCTOC
 #else
 #  error Unknown platform
 #endif
 #  define VG_STACK_PTR        guest_SP
 #  define VG_FRAME_PTR        guest_FP
 #  define VG_FPC_REG          guest_fpc
+#elif defined(VGA_mips32)
+#  define VG_INSTR_PTR        guest_PC
+#  define VG_STACK_PTR        guest_r29
+#  define VG_FRAME_PTR        guest_r30
 #else
 #  error Unknown arch
 #endif
index c192f19f5ef77d50e68781b8fe265006c0fb89c6..508b9f3fa59763ad717395ba9c7059c32122852a 100644 (file)
@@ -80,6 +80,7 @@ typedef Int ArenaId;
       defined(VGP_ppc32_linux) || \
       defined(VGP_ppc64_linux) || \
       defined(VGP_s390x_linux) || \
+      defined(VGP_mips32_linux) || \
       defined(VGP_x86_darwin)  || \
       defined(VGP_amd64_darwin)
 #  define VG_MIN_MALLOC_SZB       16
index 1b6d35fcc9afc3d652759e80237e8d91a633ac77..2902001b04d35cc6588c2f60679850ab79ab686f 100644 (file)
@@ -79,6 +79,8 @@ extern SysRes VG_(mk_SysRes_x86_darwin)  ( UChar scclass, Bool isErr,
 extern SysRes VG_(mk_SysRes_amd64_darwin)( UChar scclass, Bool isErr,
                                            ULong wHI, ULong wLO );
 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_Error)       ( UWord val );
 extern SysRes VG_(mk_SysRes_Success)     ( UWord val );
 
index ccb41a1b6b28fef27b7ff03f02810a8e207cc31f..2e80f87bf07dacb14ac8c823d538f94f66b342af 100644 (file)
@@ -87,6 +87,8 @@ typedef
    typedef VexGuestARMState   VexGuestArchState;
 #elif defined(VGA_s390x)
    typedef VexGuestS390XState VexGuestArchState;
+#elif defined(VGA_mips32)
+   typedef VexGuestMIPS32State VexGuestArchState;
 #else
 #  error Unknown architecture
 #endif
index 4e8779226d5ab50ff62d464a9d34ec4447a5b80e..765c7f6a0b330859a826dd4044d839cde9d1fe34 100644 (file)
@@ -127,6 +127,12 @@ extern Addr VG_(s390x_linux_SUBST_FOR_sigreturn);
 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
 
 /*--------------------------------------------------------------------*/
index 00adced5228cd3aeb3346b255da04f308af2f236..12b02de7744fdbe4d937dfee8990e76f06550c33 100644 (file)
@@ -62,7 +62,7 @@
 #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)
+#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_mips32)
 #  define VG_TT_FAST_HASH(_addr)  ((((UWord)(_addr)) >> 2) & VG_TT_FAST_MASK)
 
 #else
index 46b2cfd6883220f8f4bbec11049fd46963a4111b..c0f1d815f0e4f12043a7eaed930ff7a9e7aaf479 100644 (file)
@@ -80,7 +80,8 @@
    can be "waken up". PTRACEINVOKER implies some architecture
    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(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) \
+    || defined(VGP_mips32_linux)
 #define PTRACEINVOKER
 #else
 I_die_here : (PTRACEINVOKER) architecture missing in vgdb.c
@@ -923,6 +924,8 @@ Bool invoke_gdbserver (int pid)
    sp = user_mod.regs.gpr[1];
 #elif defined(VGA_s390x)
    sp = user_mod.regs.gprs[15];
+#elif defined(VGA_mips32)
+   sp = user_mod.regs[29];
 #else
    I_die_here : (sp) architecture missing in vgdb.c
 #endif
@@ -995,6 +998,12 @@ Bool invoke_gdbserver (int pid)
 
 #elif defined(VGA_s390x)
       XERROR(0, "(fn32) s390x has no 32bits implementation");
+#elif defined(VGA_mips32)
+      /* put check arg in register 0 */
+      user_mod.regs[4] = check;
+      /* put NULL return address in ra */
+      user_mod.regs[31] = bad_return;
+      user_mod.regs[25] = shared32->invoke_gdbserver;
 #else
       I_die_here : architecture missing in vgdb.c
 #endif
@@ -1074,6 +1083,8 @@ Bool invoke_gdbserver (int pid)
       user_mod.regs.gprs[15] = sp;
       /* set program counter */
       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
 #else
       I_die_here: architecture missing in vgdb.c
 #endif
index 372c7873262f3e14658471bc17e67f6059219ca1..5cc6d481f872172b11ecfcb5b84c8a63342b7299 100644 (file)
@@ -136,7 +136,8 @@ Addr make_address(const UWord a1, const UWord a0)
 #define BITS_PER_UWORD (8U * sizeof(UWord))
 
 /** Log2 of BITS_PER_UWORD. */
-#if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm)
+#if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm) \
+    || defined(VGA_mips32)
 #define BITS_PER_BITS_PER_UWORD 5
 #elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_s390x)
 #define BITS_PER_BITS_PER_UWORD 6
index be165447858330fdab3274cd3e3c7f31097199cf..42ab3b970ce8f4bedc338470a0b65bc54eba5860 100644 (file)
@@ -69,6 +69,12 @@ void DRD_(clientreq_init)(void)
  * 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;
index 3d99112f1f0ec28c50272689391e23536b2df012..7dc8a9ffb87420077bdb9965b8a6d6b212a29785 100644 (file)
@@ -49,6 +49,8 @@
 #define STACK_POINTER_OFFSET OFFSET_arm_R13
 #elif defined(VGA_s390x)
 #define STACK_POINTER_OFFSET OFFSET_s390x_r15
+#elif defined(VGA_mips32)
+#define STACK_POINTER_OFFSET OFFSET_mips32_r29
 #else
 #error Unknown architecture.
 #endif
index c2f1a85b33aff728ab99c6b435e2d276d2a38dd4..6e2dd419674be9fd4ad02e8e6012d8be9688ea0d 100644 (file)
@@ -597,6 +597,12 @@ Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
 }
 
 /** 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
index af3fa043e4e016ba4a905d459ff0171ee1b5f785..cd58cef0f7494e1bd9b1e83fc4364b81bf80f8cb 100644 (file)
@@ -186,6 +186,38 @@ UWord do_acasW(UWord* addr, UWord expected, UWord nyu )
    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 )
index e5b11c44c38bb4bcee6ddd31a2bb689c587f6f64..92c74e018fc893dfff9b3b32f819bd0095533122 100644 (file)
@@ -14,6 +14,7 @@
 #undef PLAT_ppc64_linux
 #undef PLAT_arm_linux
 #undef PLAT_s390x_linux
+#undef PLAT_mips32_linux
 
 #if defined(__APPLE__) && defined(__i386__)
 #  define PLAT_x86_darwin 1
@@ -31,6 +32,8 @@
 #  define PLAT_arm_linux 1
 #elif defined(__linux__) && defined(__s390x__)
 #  define PLAT_s390x_linux 1
+#elif defined(__linux__) && defined(__mips__)
+#  define PLAT_mips32_linux 1
 #endif
 
 #if defined(PLAT_amd64_linux) || defined(PLAT_x86_linux) \
       "   jl    1b\n"                              \
       : "+m" (_lval) :: "cc", "1","2" \
    )
+#elif defined(PLAT_mips32_linux)
+#  define INC(_lval,_lqual)                         \
+     __asm__ __volatile__ (                         \
+      "1:\n"                                        \
+      "        move $8, %0\n"                       \
+      "        ll $9, 0($8)\n"                      \
+      "        addiu $9, $9, 1\n"                   \
+      "        sc $9, 0($8)\n"                      \
+      "        li $10, 1\n"                         \
+      "        bne $9, $10, 1b\n"                   \
+      "        nop\n"                               \
+      : /*out*/ : /*in*/ "r"(&(_lval))              \
+      : /*trash*/ "$8", "$9", "$10", "cc", "memory" \
+   )
 #else
 #  error "Fix Me for this platform"
 #endif
index 8cc682b74e4d1e007b74595cfb956190b7b8da07..b39f9ee711ac5fda4a68c6d792da77d1b66d3aa4 100644 (file)
@@ -30,6 +30,7 @@
 #undef PLAT_ppc64_linux
 #undef PLAT_arm_linux
 #undef PLAT_s390x_linux
+#undef PLAT_mips32_linux
 
 #if defined(__APPLE__) && defined(__i386__)
 #  define PLAT_x86_darwin 1
@@ -47,6 +48,8 @@
 #  define PLAT_arm_linux 1
 #elif defined(__linux__) && defined(__s390x__)
 #  define PLAT_s390x_linux 1
+#elif defined(__linux__) && defined(__mips__)
+#  define PLAT_mips32_linux 1
 #endif
 
 
       "   jl    1b\n"                              \
       : "+m" (_lval) :: "cc", "0","1" \
    )
+#elif defined(PLAT_mips32_linux)
+#  define INC(_lval,_lqual)                         \
+     __asm__ __volatile__ (                         \
+      "L1xyzzy1" _lqual":\n"                        \
+      "        move $8, %0\n"                       \
+      "        ll $9, 0($t0)\n"                     \
+      "        addi $9, $9, 1\n"                    \
+      "        sc $9, 0($t0)\n"                     \
+      "        li $10, 1\n"                         \
+      "        bne $9, $10, L1xyzzy1" _lqual        \
+      : /*out*/ : /*in*/ "r"(&(_lval))              \
+      : /*trash*/ "$8", "$9", "$10", "cc", "memory" \
+        )
 #else
 #  error "Fix Me for this platform"
 #endif
index ac85d8280edb50a021c8dcb0de86df77cf42d29b..fadc774fbaa1514a3edd0e394bc29df7904b58a0 100644 (file)
@@ -17,6 +17,7 @@
 #undef PLAT_ppc64_linux
 #undef PLAT_arm_linux
 #undef PLAT_s390x_linux
+#undef PLAT_mips32_linux
 
 #if defined(__APPLE__) && defined(__i386__)
 #  define PLAT_x86_darwin 1
@@ -34,6 +35,8 @@
 #  define PLAT_arm_linux 1
 #elif defined(__linux__) && defined(__s390x__)
 #  define PLAT_s390x_linux 1
+#elif defined(__linux__) && defined(__mips__)
+#  define PLAT_mips32_linux 1
 #endif
 
 
 #  define XCHG_M_R_with_redundant_LOCK(_addr,_lval) \
       XCHG_M_R(_addr,_lval)
 
+#elif defined(PLAT_mips32_linux) || defined(PLAT_mips64_linux)
+#  define XCHG_M_R(_addr,_lval)                              \
+     __asm__ __volatile__(                                   \
+        "move $12, %2\n"                                     \
+        "move $13, %1\n"                                     \
+        "ll $14, 0($13)\n"                                   \
+        "sc $12, 0($13)\n"                                   \
+        "move %0, $14\n"                                     \
+        : /*out*/ "=r"(_lval)                                \
+        : /*in*/  "r"(&_addr), "r"(_lval)                    \
+        : "$12", "$13", "$14", "memory", "cc"                \
+     )
+
+#  define XCHG_M_R_with_redundant_LOCK(_addr,_lval) \
+      XCHG_M_R(_addr,_lval)
+
 #elif defined(PLAT_ppc32_linux) || defined(PLAT_ppc64_linux) \
       || defined(PLAT_arm_linux)
 #  if defined(HAVE_BUILTIN_ATOMIC)
index 851649251fbed119502af8b236439dee97150561..ade27c2244ebdda9b0cf5ea3fb21a923fbc6e860 100644 (file)
@@ -49,16 +49,19 @@ nobase_pkginclude_HEADERS = \
        vki/vki-posixtypes-x86-linux.h   \
        vki/vki-posixtypes-arm-linux.h   \
        vki/vki-posixtypes-s390x-linux.h \
+       vki/vki-posixtypes-mips32-linux.h \
        vki/vki-amd64-linux.h           \
        vki/vki-ppc32-linux.h           \
        vki/vki-ppc64-linux.h           \
        vki/vki-x86-linux.h             \
        vki/vki-arm-linux.h             \
        vki/vki-s390x-linux.h           \
+       vki/vki-mips32-linux.h          \
        vki/vki-scnums-amd64-linux.h    \
        vki/vki-scnums-ppc32-linux.h    \
        vki/vki-scnums-ppc64-linux.h    \
        vki/vki-scnums-x86-linux.h      \
        vki/vki-scnums-arm-linux.h      \
        vki/vki-scnums-s390x-linux.h    \
+       vki/vki-scnums-mips32-linux.h   \
        vki/vki-scnums-darwin.h
index ae7bae69f4a305f416e2edf6936ca19818afa654..5b387e89352faa48db6bee68c4d6b1ec5758ab16 100644 (file)
@@ -163,6 +163,7 @@ typedef UInt ThreadId;
 typedef
    struct {
       UWord _val;
+      UWord _valEx;   // only used on mips-linux
       Bool  _isError;
    }
    SysRes;
@@ -197,6 +198,9 @@ static inline Bool sr_isError ( SysRes sr ) {
 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 @@ static inline Bool sr_EQ ( SysRes sr1, SysRes sr2 ) {
 #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 @@ static inline Bool sr_EQ ( SysRes sr1, SysRes sr2 ) {
 #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
index 6b30e69b102d33ff668557dba5358b5011b522cf..55fd2fb31cc12cf883149d47ab96cecc99133a41 100644 (file)
 #  define VG_CLREQ_SZB             19
 #  define VG_STACK_REDZONE_SZB    128
 
+#elif defined(VGP_mips32_linux)
+#  define VG_MIN_INSTR_SZB          4
+#  define VG_MAX_INSTR_SZB          4 
+#  define VG_CLREQ_SZB             20
+#  define VG_STACK_REDZONE_SZB      0
+
 #else
 #  error Unknown platform
 #endif
index 018cb19bf98345fc9b80552d78580de29f7c8113..649c7aafa9370d73691aa11293a042abb666ef82 100644 (file)
@@ -51,6 +51,9 @@
 #elif defined(VGP_arm_linux)
 #  include "vki/vki-scnums-arm-linux.h"
 
+#elif defined(VGP_mips32_linux)
+#  include "vki/vki-scnums-mips32-linux.h"
+
 #elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
 #  include "vki/vki-scnums-darwin.h"
 
index d10a5132f7f177ac42cad64a3994a4f25a1d8455..afb4681dbf69f97554fec6ea646e9c5b0f074999 100644 (file)
 #undef PLAT_ppc64_linux
 #undef PLAT_arm_linux
 #undef PLAT_s390x_linux
+#undef PLAT_mips32_linux
 
 
 #if defined(__APPLE__) && defined(__i386__)
 #  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 @@ typedef
 
 #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,6 +3656,545 @@ typedef
 
 #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"                                   \
+         "lw $a0, 28(%1) \n\t"                                    \
+         "sw $a0, 24($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_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
+                                 arg7,arg8)                       \
+   do {                                                           \
+      volatile OrigFn        _orig = (orig);                      \
+      volatile unsigned long _argvec[9];                          \
+      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);                         \
+      _argvec[8] = (unsigned long)(arg8);                         \
+      __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, 40\n\t"                                  \
+         "sw $a0, 16($sp) \n\t"                                   \
+         "lw $a0, 24(%1) \n\t"                                    \
+         "sw $a0, 20($sp) \n\t"                                   \
+         "lw $a0, 28(%1) \n\t"                                    \
+         "sw $a0, 24($sp) \n\t"                                   \
+         "lw $a0, 32(%1) \n\t"                                    \
+         "sw $a0, 28($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, 40 \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_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
+                                 arg7,arg8,arg9)                  \
+   do {                                                           \
+      volatile OrigFn        _orig = (orig);                      \
+      volatile unsigned long _argvec[10];                         \
+      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);                         \
+      _argvec[8] = (unsigned long)(arg8);                         \
+      _argvec[9] = (unsigned long)(arg9);                         \
+      __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, 40\n\t"                                  \
+         "sw $a0, 16($sp) \n\t"                                   \
+         "lw $a0, 24(%1) \n\t"                                    \
+         "sw $a0, 20($sp) \n\t"                                   \
+         "lw $a0, 28(%1) \n\t"                                    \
+         "sw $a0, 24($sp) \n\t"                                   \
+         "lw $a0, 32(%1) \n\t"                                    \
+         "sw $a0, 28($sp) \n\t"                                   \
+         "lw $a0, 36(%1) \n\t"                                    \
+         "sw $a0, 32($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, 40 \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_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
+                                  arg7,arg8,arg9,arg10)           \
+   do {                                                           \
+      volatile OrigFn        _orig = (orig);                      \
+      volatile unsigned long _argvec[11];                         \
+      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);                         \
+      _argvec[8] = (unsigned long)(arg8);                         \
+      _argvec[9] = (unsigned long)(arg9);                         \
+      _argvec[10] = (unsigned long)(arg10);                       \
+      __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, 48\n\t"                                  \
+         "sw $a0, 16($sp) \n\t"                                   \
+         "lw $a0, 24(%1) \n\t"                                    \
+         "sw $a0, 20($sp) \n\t"                                   \
+         "lw $a0, 28(%1) \n\t"                                    \
+         "sw $a0, 24($sp) \n\t"                                   \
+         "lw $a0, 32(%1) \n\t"                                    \
+         "sw $a0, 28($sp) \n\t"                                   \
+         "lw $a0, 36(%1) \n\t"                                    \
+         "sw $a0, 32($sp) \n\t"                                   \
+         "lw $a0, 40(%1) \n\t"                                    \
+         "sw $a0, 36($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, 48 \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_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
+                                  arg6,arg7,arg8,arg9,arg10,      \
+                                  arg11)                          \
+   do {                                                           \
+      volatile OrigFn        _orig = (orig);                      \
+      volatile unsigned long _argvec[12];                         \
+      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);                         \
+      _argvec[8] = (unsigned long)(arg8);                         \
+      _argvec[9] = (unsigned long)(arg9);                         \
+      _argvec[10] = (unsigned long)(arg10);                       \
+      _argvec[11] = (unsigned long)(arg11);                       \
+      __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, 48\n\t"                                  \
+         "sw $a0, 16($sp) \n\t"                                   \
+         "lw $a0, 24(%1) \n\t"                                    \
+         "sw $a0, 20($sp) \n\t"                                   \
+         "lw $a0, 28(%1) \n\t"                                    \
+         "sw $a0, 24($sp) \n\t"                                   \
+         "lw $a0, 32(%1) \n\t"                                    \
+         "sw $a0, 28($sp) \n\t"                                   \
+         "lw $a0, 36(%1) \n\t"                                    \
+         "sw $a0, 32($sp) \n\t"                                   \
+         "lw $a0, 40(%1) \n\t"                                    \
+         "sw $a0, 36($sp) \n\t"                                   \
+         "lw $a0, 44(%1) \n\t"                                    \
+         "sw $a0, 40($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, 48 \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_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
+                                  arg6,arg7,arg8,arg9,arg10,      \
+                                  arg11,arg12)                    \
+   do {                                                           \
+      volatile OrigFn        _orig = (orig);                      \
+      volatile unsigned long _argvec[13];                         \
+      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);                         \
+      _argvec[8] = (unsigned long)(arg8);                         \
+      _argvec[9] = (unsigned long)(arg9);                         \
+      _argvec[10] = (unsigned long)(arg10);                       \
+      _argvec[11] = (unsigned long)(arg11);                       \
+      _argvec[12] = (unsigned long)(arg12);                       \
+      __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, 56\n\t"                                  \
+         "sw $a0, 16($sp) \n\t"                                   \
+         "lw $a0, 24(%1) \n\t"                                    \
+         "sw $a0, 20($sp) \n\t"                                   \
+         "lw $a0, 28(%1) \n\t"                                    \
+         "sw $a0, 24($sp) \n\t"                                   \
+         "lw $a0, 32(%1) \n\t"                                    \
+         "sw $a0, 28($sp) \n\t"                                   \
+         "lw $a0, 36(%1) \n\t"                                    \
+         "sw $a0, 32($sp) \n\t"                                   \
+         "lw $a0, 40(%1) \n\t"                                    \
+         "sw $a0, 36($sp) \n\t"                                   \
+         "lw $a0, 44(%1) \n\t"                                    \
+         "sw $a0, 40($sp) \n\t"                                   \
+         "lw $a0, 48(%1) \n\t"                                    \
+         "sw $a0, 44($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, 56 \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)
+
+#endif /* PLAT_mips32_linux */
+
 
 /* ------------------------------------------------------------------ */
 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS.               */
@@ -4068,5 +4674,6 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
 #undef PLAT_ppc64_linux
 #undef PLAT_arm_linux
 #undef PLAT_s390x_linux
+#undef PLAT_mips32_linux
 
 #endif   /* __VALGRIND_H */
index d73b04439ba5cdc784ae9d7088e63dd3677b2a9d..ec91c9f8bbbeae762313db87963638b67bc1066d 100644 (file)
@@ -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 @@ typedef unsigned int                vki_uint;
 #  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 @@ struct vki_sched_param {
 // 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 @@ typedef struct vki_siginfo {
                } _sigpoll;
        } _sifields;
 } vki_siginfo_t;
+#endif
 
 #define __VKI_SI_FAULT 0
 
index 5bee6c2247073cd8eb44ec8a839278a6851bdb58..2df3a587e61a673ef69a2533b0aea361c252b9f3 100644 (file)
 # define MC_SIZEOF_GUEST_STATE sizeof(VexGuestARMState)
 #endif
 
+#if defined(VGA_mips32)
+# include "libvex_guest_mips32.h"
+# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestMIPS32State)
+#endif
+
 static inline Bool host_is_big_endian ( void ) {
    UInt x = 0x11223344;
    return 0x1122 == *(UShort*)(&x);
@@ -937,6 +942,117 @@ static Int get_otrack_shadow_offset_wrk ( Int offset, Int szB )
                offset,szB);
    tl_assert(0);
 #  undef GOF
+#  undef SZB
+
+   /* --------------------- mips32 --------------------- */
+
+#  elif defined(VGA_mips32)
+
+#  define GOF(_fieldname) \
+      (offsetof(VexGuestMIPS32State,guest_##_fieldname))
+#  define SZB(_fieldname) \
+      (sizeof(((VexGuestMIPS32State*)0)->guest_##_fieldname))
+
+   Int  o     = offset;
+   Int  sz    = szB;
+   tl_assert(sz > 0);
+#  if defined (VG_LITTLEENDIAN)
+   tl_assert(host_is_little_endian());
+#  elif defined (VG_BIGENDIAN)
+   tl_assert(host_is_big_endian());
+#  else
+#     error "Unknown endianness"
+#  endif
+
+   if (o == GOF(r0)  && sz == 4) return o;
+   if (o == GOF(r1)  && sz == 4) return o;
+   if (o == GOF(r2)  && sz == 4) return o;
+   if (o == GOF(r3)  && sz == 4) return o;
+   if (o == GOF(r4)  && sz == 4) return o;
+   if (o == GOF(r5)  && sz == 4) return o;
+   if (o == GOF(r6)  && sz == 4) return o;
+   if (o == GOF(r7)  && sz == 4) return o;
+   if (o == GOF(r8)  && sz == 4) return o;
+   if (o == GOF(r9)  && sz == 4) return o;
+   if (o == GOF(r10)  && sz == 4) return o;
+   if (o == GOF(r11)  && sz == 4) return o;
+   if (o == GOF(r12)  && sz == 4) return o;
+   if (o == GOF(r13)  && sz == 4) return o;
+   if (o == GOF(r14)  && sz == 4) return o;
+   if (o == GOF(r15)  && sz == 4) return o;
+   if (o == GOF(r16)  && sz == 4) return o;
+   if (o == GOF(r17)  && sz == 4) return o;
+   if (o == GOF(r18)  && sz == 4) return o;
+   if (o == GOF(r19)  && sz == 4) return o;
+   if (o == GOF(r20)  && sz == 4) return o;
+   if (o == GOF(r21)  && sz == 4) return o;
+   if (o == GOF(r22)  && sz == 4) return o;
+   if (o == GOF(r23)  && sz == 4) return o;
+   if (o == GOF(r24)  && sz == 4) return o;
+   if (o == GOF(r25)  && sz == 4) return o;
+   if (o == GOF(r26)  && sz == 4) return o;
+   if (o == GOF(r27)  && sz == 4) return o;
+   if (o == GOF(r28)  && sz == 4) return o;
+   if (o == GOF(r29)  && sz == 4) return o;
+   if (o == GOF(r30)  && sz == 4) return o;
+   if (o == GOF(r31)  && sz == 4) return o;
+   if (o == GOF(PC)  && sz == 4) return -1; /* slot unused */
+
+   if (o == GOF(HI)  && sz == 4) return o;
+   if (o == GOF(LO)  && sz == 4) return o;
+
+   if (o == GOF(FIR)     && sz == 4) return -1; /* slot unused */
+   if (o == GOF(FCCR)     && sz == 4) return -1; /* slot unused */
+   if (o == GOF(FEXR)     && sz == 4) return -1; /* slot unused */
+   if (o == GOF(FENR)     && sz == 4) return -1; /* slot unused */
+   if (o == GOF(FCSR)     && sz == 4) return -1; /* slot unused */
+   if (o == GOF(ULR) && sz == 4) return -1;
+
+   if (o == GOF(EMWARN)     && sz == 4) return -1; /* slot unused */
+   if (o == GOF(TISTART)     && sz == 4) return -1; /* slot unused */
+   if (o == GOF(TILEN)     && sz == 4) return -1; /* slot unused */
+   if (o == GOF(NRADDR)     && sz == 4) return -1; /* slot unused */
+
+   if (o >= GOF(f0)  && o+sz <= GOF(f0) +SZB(f0))  return GOF(f0);
+   if (o >= GOF(f1)  && o+sz <= GOF(f1) +SZB(f1))  return GOF(f1);
+   if (o >= GOF(f2)  && o+sz <= GOF(f2) +SZB(f2))  return GOF(f2);
+   if (o >= GOF(f3)  && o+sz <= GOF(f3) +SZB(f3))  return GOF(f3);
+   if (o >= GOF(f4)  && o+sz <= GOF(f4) +SZB(f4))  return GOF(f4);
+   if (o >= GOF(f5)  && o+sz <= GOF(f5) +SZB(f5))  return GOF(f5);
+   if (o >= GOF(f6)  && o+sz <= GOF(f6) +SZB(f6))  return GOF(f6);
+   if (o >= GOF(f7)  && o+sz <= GOF(f7) +SZB(f7))  return GOF(f7);
+   if (o >= GOF(f8)  && o+sz <= GOF(f8) +SZB(f8))  return GOF(f8);
+   if (o >= GOF(f9)  && o+sz <= GOF(f9) +SZB(f9))  return GOF(f9);
+   if (o >= GOF(f10) && o+sz <= GOF(f10)+SZB(f10)) return GOF(f10);
+   if (o >= GOF(f11) && o+sz <= GOF(f11)+SZB(f11)) return GOF(f11);
+   if (o >= GOF(f12) && o+sz <= GOF(f12)+SZB(f12)) return GOF(f12);
+   if (o >= GOF(f13) && o+sz <= GOF(f13)+SZB(f13)) return GOF(f13);
+   if (o >= GOF(f14) && o+sz <= GOF(f14)+SZB(f14)) return GOF(f14);
+   if (o >= GOF(f15) && o+sz <= GOF(f15)+SZB(f15)) return GOF(f15);
+
+   if (o >= GOF(f16) && o+sz <= GOF(f16)+SZB(f16)) return GOF(f16);
+   if (o >= GOF(f17)  && o+sz <= GOF(f17) +SZB(f17))  return GOF(f17);
+   if (o >= GOF(f18)  && o+sz <= GOF(f18) +SZB(f18))  return GOF(f18);
+   if (o >= GOF(f19)  && o+sz <= GOF(f19) +SZB(f19))  return GOF(f19);
+   if (o >= GOF(f20)  && o+sz <= GOF(f20) +SZB(f20))  return GOF(f20);
+   if (o >= GOF(f21)  && o+sz <= GOF(f21) +SZB(f21))  return GOF(f21);
+   if (o >= GOF(f22)  && o+sz <= GOF(f22) +SZB(f22))  return GOF(f22);
+   if (o >= GOF(f23)  && o+sz <= GOF(f23) +SZB(f23))  return GOF(f23);
+   if (o >= GOF(f24)  && o+sz <= GOF(f24) +SZB(f24))  return GOF(f24);
+   if (o >= GOF(f25)  && o+sz <= GOF(f25) +SZB(f25))  return GOF(f25);
+   if (o >= GOF(f26) && o+sz <= GOF(f26)+SZB(f26)) return GOF(f26);
+   if (o >= GOF(f27) && o+sz <= GOF(f27)+SZB(f27)) return GOF(f27);
+   if (o >= GOF(f28) && o+sz <= GOF(f28)+SZB(f28)) return GOF(f28);
+   if (o >= GOF(f29) && o+sz <= GOF(f29)+SZB(f29)) return GOF(f29);
+   if (o >= GOF(f30) && o+sz <= GOF(f30)+SZB(f30)) return GOF(f30);
+   if (o >= GOF(f31) && o+sz <= GOF(f31)+SZB(f31)) return GOF(f31);
+
+   if ((o > GOF(NRADDR)) && (o <= GOF(NRADDR) +12 )) return -1; /*padding registers*/
+
+   VG_(printf)("MC_(get_otrack_shadow_offset)(mips)(off=%d,sz=%d)\n",
+               offset,szB);
+   tl_assert(0);
+#  undef GOF
 #  undef SZB
 
 #  else
@@ -1022,7 +1138,6 @@ IRType MC_(get_otrack_reg_array_equiv_int_type) ( IRRegArray* arr )
 
    /* --------------------- arm --------------------- */
 #  elif defined(VGA_arm)
-
    VG_(printf)("get_reg_array_equiv_int_type(arm): unhandled: ");
    ppIRRegArray(arr);
    VG_(printf)("\n");
@@ -1033,6 +1148,14 @@ IRType MC_(get_otrack_reg_array_equiv_int_type) ( IRRegArray* arr )
    /* Should never het here because s390x does not use Ist_PutI
       and Iex_GetI. */
    tl_assert(0);
+
+/* --------------------- mips32 --------------------- */
+#  elif defined(VGA_mips32)
+   VG_(printf)("get_reg_array_equiv_int_type(mips32): unhandled: ");
+   ppIRRegArray(arr);
+   VG_(printf)("\n");
+   tl_assert(0);
+
 #  else
 #    error "FIXME: not implemented for this architecture"
 #  endif
index 80cf810fe77ac5ec99cb896120cae4e7a64242a9..ac1e775cafcd0b079f43dd40f5febf969573f029 100644 (file)
@@ -110,6 +110,48 @@ __attribute__((noinline)) void atomic_add_8bit ( char* p, int n )
       : "+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 @@ __attribute__((noinline)) void atomic_add_16bit ( short* p, int n )
       : "+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 @@ __attribute__((noinline)) void atomic_add_32bit ( int* p, int n )
       : "+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_32bit ( int* p, int n )
 
 __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,
index a9c8784cc8f1f57022d33fe7a251459ef7c2e4fe..38e165d425aaa19b5bc3985a24f631d8f54c6638 100644 (file)
@@ -10,7 +10,7 @@ int main ( void )
   int i;
   unsigned long pszB = sysconf(_SC_PAGE_SIZE);
   assert(sizeof(long) == sizeof(void*));
-  assert(pszB == 4096 || pszB == 65536);
+  assert(pszB == 4096 || pszB == 16384 || pszB == 65536);
 
   for (i = 0; i < 10; i++) {
     a[i] = valloc(11111 * (i+1));
index 2f16f5b6fc0df09379cb6109562030b6dcdbb19b..0fee10d7305cdeaf906e686b005f6b8d9ca41804 100644 (file)
@@ -22,6 +22,9 @@ endif
 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 @@ if VGCONF_PLATFORMS_INCLUDE_X86_LINUX
 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 \
index 0cd17382ef91b8e43aeca43359387d2f287e618f..d1fa03c8328955f1a49182e996e1a49a0b953c36 100755 (executable)
@@ -32,5 +32,6 @@ pair x86                        amd64
 pair ppc32                      ppc64
 pair s390x_unexisting_in_32bits s390x
 pair arm                        arm_unexisting_in_64bits
+pair mips32                     mips_unexisting_in_64bits
 
 exit 0
index 6f3d944e29eef816a9793fca7f116e1d143116af..b3740b589eebc1c32885da4145ad0ffb7a963591 100644 (file)
@@ -29,6 +29,7 @@ char* all_archs[] = {
    "ppc64",
    "arm",
    "s390x",
+   "mips32",
    NULL
 };
 
@@ -58,6 +59,9 @@ static Bool go(char* arch)
 #elif defined(VGP_arm_linux)
    if ( 0 == strcmp( arch, "arm" ) ) return True;
 
+#elif defined(VGP_mips32_linux)
+   if ( 0 == strcmp( arch, "mips32" ) ) return True;
+
 #else
 #  error Unknown platform
 #endif   // VGP_*
index 7fbf05a342428daa06c4b3a393406c4efa78af96..400fd37341daf86c5dd43f798b0dc1a361d54ce6 100644 (file)
@@ -13,7 +13,7 @@
 all_platforms=
 all_platforms="$all_platforms x86-linux amd64-linux ppc32-linux ppc64-linux"
 all_platforms="$all_platforms arm-linux"
-all_platforms="$all_platforms s390x-linux"
+all_platforms="$all_platforms s390x-linux mips32-linux"
 all_platforms="$all_platforms x86-darwin amd64-darwin"
 
 if [ $# -ne 2 ] ; then
index 7ac64d54c4d045636ac1b46ea1e53853ea04e147..c059308c1259ade7b2184f9766b2c6b16221ec6d 100644 (file)
@@ -21,7 +21,7 @@ static void* get_unmapped_page(void)
    void* ptr;
    int r;
    long pagesz = sysconf(_SC_PAGE_SIZE);
-   assert(pagesz == 4096 || pagesz == 65536);
+   assert(pagesz == 4096 || pagesz == 16384 || pagesz == 65536);
    ptr = mmap(0, pagesz, PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
    assert(ptr != (void*)-1);
    r = munmap(ptr, pagesz);