Merge in a port for mips32-linux, by Petar Jovanovic and Dejan Jevtic,
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
diff --git a/Makefile.all.am b/Makefile.all.am
index 439aacd..bcca5ff 100644
--- a/Makefile.all.am
+++ b/Makefile.all.am
@@ -172,6 +172,10 @@
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_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@
diff --git a/Makefile.tool.am b/Makefile.tool.am
index 7924b1b..6f5a6ea 100644
--- a/Makefile.tool.am
+++ b/Makefile.tool.am
@@ -59,6 +59,11 @@
TOOL_LDFLAGS_AMD64_DARWIN = \
$(TOOL_LDFLAGS_COMMON_DARWIN) -arch x86_64
+# MIPS Linux default start symbol is __start, not _start like on x86 or amd
+TOOL_LDFLAGS_MIPS32_LINUX = \
+ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
+ @FLAG_M32@
+
# On Android we must ask for non-executable stack, not sure why.
if VGCONF_PLATFORMS_INCLUDE_ARM_LINUX
if VGCONF_PLATVARIANT_IS_ANDROID
@@ -103,6 +108,8 @@
LIBREPLACEMALLOC_S390X_LINUX = \
$(top_builddir)/coregrind/libreplacemalloc_toolpreload-s390x-linux.a
+LIBREPLACEMALLOC_MIPS32_LINUX = \
+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips32-linux.a
LIBREPLACEMALLOC_LDFLAGS_X86_LINUX = \
-Wl,--whole-archive \
@@ -140,6 +147,11 @@
$(LIBREPLACEMALLOC_S390X_LINUX) \
-Wl,--no-whole-archive
+LIBREPLACEMALLOC_LDFLAGS_MIPS32_LINUX = \
+ -Wl,--whole-archive \
+ $(LIBREPLACEMALLOC_MIPS32_LINUX) \
+ -Wl,--no-whole-archive
+
#----------------------------------------------------------------------------
# General stuff
#----------------------------------------------------------------------------
diff --git a/Makefile.vex.am b/Makefile.vex.am
index 0071634..db16276 100644
--- a/Makefile.vex.am
+++ b/Makefile.vex.am
@@ -25,6 +25,7 @@
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 @@
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 @@
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_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 @@
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 @@
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 \
diff --git a/cachegrind/Makefile.am b/cachegrind/Makefile.am
index 0b6879c..f22fe17 100644
--- a/cachegrind/Makefile.am
+++ b/cachegrind/Makefile.am
@@ -46,7 +46,8 @@
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)
diff --git a/cachegrind/cg_branchpred.c b/cachegrind/cg_branchpred.c
index 1db7fb5..462977a 100644
--- a/cachegrind/cg_branchpred.c
+++ b/cachegrind/cg_branchpred.c
@@ -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
diff --git a/cachegrind/tests/filter_stderr b/cachegrind/tests/filter_stderr
index d6800cd..2d38fb3 100755
--- a/cachegrind/tests/filter_stderr
+++ b/cachegrind/tests/filter_stderr
@@ -20,4 +20,5 @@
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"
diff --git a/callgrind/Makefile.am b/callgrind/Makefile.am
index 7cb6807..ae4ff4f 100644
--- a/callgrind/Makefile.am
+++ b/callgrind/Makefile.am
@@ -50,7 +50,8 @@
../cachegrind/cg-ppc32.c \
../cachegrind/cg-ppc64.c \
../cachegrind/cg-arm.c \
- ../cachegrind/cg-s390x.c
+ ../cachegrind/cg-s390x.c \
+ ../cachegrind/cg-mips32.c
CALLGRIND_CFLAGS_COMMON = -I$(top_srcdir)/cachegrind
diff --git a/callgrind/tests/filter_stderr b/callgrind/tests/filter_stderr
index 9664d51..9acedd3 100755
--- a/callgrind/tests/filter_stderr
+++ b/callgrind/tests/filter_stderr
@@ -29,4 +29,5 @@
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"
diff --git a/configure.in b/configure.in
index ed6be2a..954df7c 100644
--- a/configure.in
+++ b/configure.in
@@ -189,6 +189,21 @@
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 @@
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 @@
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_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 @@
-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)
@@ -654,6 +685,62 @@
#----------------------------------------------------------------------------
+# 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
#----------------------------------------------------------------------------
AC_ARG_WITH(tmpdir,
@@ -1799,7 +1886,8 @@
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 @@
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
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index efb4de3..68b8ed2 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -301,6 +301,7 @@
m_dispatch/dispatch-ppc64-linux.S \
m_dispatch/dispatch-arm-linux.S \
m_dispatch/dispatch-s390x-linux.S \
+ m_dispatch/dispatch-mips32-linux.S \
m_dispatch/dispatch-x86-darwin.S \
m_dispatch/dispatch-amd64-darwin.S \
m_gdbserver/m_gdbserver.c \
@@ -318,6 +319,7 @@
m_gdbserver/valgrind-low-ppc32.c \
m_gdbserver/valgrind-low-ppc64.c \
m_gdbserver/valgrind-low-s390x.c \
+ m_gdbserver/valgrind-low-mips32.c \
m_gdbserver/version.c \
m_initimg/initimg-linux.c \
m_initimg/initimg-darwin.c \
@@ -337,6 +339,7 @@
m_sigframe/sigframe-ppc64-linux.c \
m_sigframe/sigframe-arm-linux.c \
m_sigframe/sigframe-s390x-linux.c \
+ m_sigframe/sigframe-mips32-linux.c \
m_sigframe/sigframe-x86-darwin.c \
m_sigframe/sigframe-amd64-darwin.c \
m_syswrap/syscall-x86-linux.S \
@@ -345,6 +348,7 @@
m_syswrap/syscall-ppc64-linux.S \
m_syswrap/syscall-arm-linux.S \
m_syswrap/syscall-s390x-linux.S \
+ m_syswrap/syscall-mips32-linux.S \
m_syswrap/syscall-x86-darwin.S \
m_syswrap/syscall-amd64-darwin.S \
m_syswrap/syswrap-main.c \
@@ -358,6 +362,7 @@
m_syswrap/syswrap-ppc64-linux.c \
m_syswrap/syswrap-arm-linux.c \
m_syswrap/syswrap-s390x-linux.c \
+ m_syswrap/syswrap-mips32-linux.c \
m_syswrap/syswrap-x86-darwin.c \
m_syswrap/syswrap-amd64-darwin.c \
m_ume/elf.c \
@@ -532,7 +537,18 @@
m_gdbserver/s390x-generic.xml \
m_gdbserver/s390x-linux64-valgrind-s1.xml \
m_gdbserver/s390x-linux64-valgrind-s2.xml \
- m_gdbserver/s390x-linux64.xml
+ m_gdbserver/s390x-linux64.xml \
+ m_gdbserver/mips-cp0-valgrind-s1.xml \
+ m_gdbserver/mips-cp0-valgrind-s2.xml \
+ m_gdbserver/mips-cp0.xml \
+ m_gdbserver/mips-cpu-valgrind-s1.xml \
+ m_gdbserver/mips-cpu-valgrind-s2.xml \
+ m_gdbserver/mips-cpu.xml \
+ m_gdbserver/mips-linux.xml \
+ m_gdbserver/mips-linux-valgrind.xml \
+ m_gdbserver/mips-fpu-valgrind-s1.xml \
+ m_gdbserver/mips-fpu-valgrind-s2.xml \
+ m_gdbserver/mips-fpu.xml
# so as to make sure these get copied into the install tree
vglibdir = $(pkglibdir)
diff --git a/coregrind/launcher-linux.c b/coregrind/launcher-linux.c
index 6a200c3..a9ad1e3 100644
--- a/coregrind/launcher-linux.c
+++ b/coregrind/launcher-linux.c
@@ -179,6 +179,12 @@
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 @@
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 @@
(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);
diff --git a/coregrind/link_tool_exe_linux.in b/coregrind/link_tool_exe_linux.in
index 6de2562..a47747b 100644
--- a/coregrind/link_tool_exe_linux.in
+++ b/coregrind/link_tool_exe_linux.in
@@ -68,7 +68,18 @@
# 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) {
diff --git a/coregrind/m_aspacemgr/aspacemgr-common.c b/coregrind/m_aspacemgr/aspacemgr-common.c
index 7f7717c..6a65610 100644
--- a/coregrind/m_aspacemgr/aspacemgr-common.c
+++ b/coregrind/m_aspacemgr/aspacemgr-common.c
@@ -159,7 +159,7 @@
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)
diff --git a/coregrind/m_aspacemgr/aspacemgr-linux.c b/coregrind/m_aspacemgr/aspacemgr-linux.c
index 9980501..0695a66 100644
--- a/coregrind/m_aspacemgr/aspacemgr-linux.c
+++ b/coregrind/m_aspacemgr/aspacemgr-linux.c
@@ -2533,7 +2533,7 @@
/* Ask for an advisory. If it's negative, fail immediately. */
req.rkind = MAny;
req.start = 0;
- #if defined(VGA_arm)
+ #if defined(VGA_arm) || defined(VGA_mips32)
aspacem_assert(VKI_SHMLBA >= VKI_PAGE_SIZE);
#else
aspacem_assert(VKI_SHMLBA == VKI_PAGE_SIZE);
diff --git a/coregrind/m_coredump/coredump-elf.c b/coregrind/m_coredump/coredump-elf.c
index 745bd7e..ddfe2ba 100644
--- a/coregrind/m_coredump/coredump-elf.c
+++ b/coregrind/m_coredump/coredump-elf.c
@@ -375,6 +375,15 @@
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 @@
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
diff --git a/coregrind/m_debugger.c b/coregrind/m_debugger.c
index bb559f4..c08b5a7 100644
--- a/coregrind/m_debugger.c
+++ b/coregrind/m_debugger.c
@@ -307,6 +307,43 @@
return VG_(ptrace)(VKI_PTRACE_POKEUSR_AREA, pid, &pa, NULL);
+#elif defined(VGP_mips32_linux)
+ struct vki_user_regs_struct regs;
+ VG_(memset)(®s, 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, ®s);
+
#else
# error Unknown arch
#endif
diff --git a/coregrind/m_debuginfo/d3basics.c b/coregrind/m_debuginfo/d3basics.c
index 03af598..5999f2e 100644
--- a/coregrind/m_debuginfo/d3basics.c
+++ b/coregrind/m_debuginfo/d3basics.c
@@ -410,6 +410,9 @@
# 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
diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c
index fa08d8e..99389c2 100644
--- a/coregrind/m_debuginfo/debuginfo.c
+++ b/coregrind/m_debuginfo/debuginfo.c
@@ -792,7 +792,7 @@
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 @@
/*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 @@
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 @@
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 @@
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 @@
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"
diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h
index 53ca0d2..193b154 100644
--- a/coregrind/m_debuginfo/priv_storage.h
+++ b/coregrind/m_debuginfo/priv_storage.h
@@ -257,6 +257,21 @@
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 @@
Creg_ARM_R12,
Creg_ARM_R15,
Creg_ARM_R14,
- Creg_S390_R14
+ Creg_S390_R14,
+ Creg_MIPS_RA
}
CfiReg;
diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c
index 36a6698..9329fa2 100644
--- a/coregrind/m_debuginfo/readdwarf.c
+++ b/coregrind/m_debuginfo/readdwarf.c
@@ -1843,6 +1843,10 @@
# 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 @@
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 @@
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 @@
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 @@
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 @@
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"
diff --git a/coregrind/m_debuginfo/readdwarf3.c b/coregrind/m_debuginfo/readdwarf3.c
index 99b213c..1654097 100644
--- a/coregrind/m_debuginfo/readdwarf3.c
+++ b/coregrind/m_debuginfo/readdwarf3.c
@@ -2307,8 +2307,10 @@
case DW_ATE_unsigned: case DW_ATE_unsigned_char:
case DW_ATE_UTF: /* since DWARF4, e.g. char16_t from C++ */
case DW_ATE_boolean:/* FIXME - is this correct? */
+ case DW_ATE_unsigned_fixed:
typeE.Te.TyBase.enc = 'U'; break;
case DW_ATE_signed: case DW_ATE_signed_char:
+ case DW_ATE_signed_fixed:
typeE.Te.TyBase.enc = 'S'; break;
case DW_ATE_float:
typeE.Te.TyBase.enc = 'F'; break;
diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c
index 3a70122..40f5eea 100644
--- a/coregrind/m_debuginfo/readelf.c
+++ b/coregrind/m_debuginfo/readelf.c
@@ -1955,7 +1955,8 @@
/* 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) {
diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c
index b90b2e7..a5fe07f 100644
--- a/coregrind/m_debuginfo/storage.c
+++ b/coregrind/m_debuginfo/storage.c
@@ -189,7 +189,7 @@
VG_(printf)(" R7=");
SHOW_HOW(si->r7_how, si->r7_off);
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
-# elif defined(VGA_s390x)
+# 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 @@
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);
}
}
diff --git a/coregrind/m_debuglog.c b/coregrind/m_debuglog.c
index 44f7376..8e1c032 100644
--- a/coregrind/m_debuglog.c
+++ b/coregrind/m_debuglog.c
@@ -388,6 +388,43 @@
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
diff --git a/coregrind/m_gdbserver/target.c b/coregrind/m_gdbserver/target.c
index 905efb9..6117fce 100644
--- a/coregrind/m_gdbserver/target.c
+++ b/coregrind/m_gdbserver/target.c
@@ -618,6 +618,8 @@
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
diff --git a/coregrind/m_gdbserver/valgrind_low.h b/coregrind/m_gdbserver/valgrind_low.h
index 29dafcd..0348895 100644
--- a/coregrind/m_gdbserver/valgrind_low.h
+++ b/coregrind/m_gdbserver/valgrind_low.h
@@ -73,5 +73,6 @@
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
diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c
index b752f01..8acc7b0 100644
--- a/coregrind/m_initimg/initimg-linux.c
+++ b/coregrind/m_initimg/initimg-linux.c
@@ -1081,6 +1081,20 @@
VG_TRACK(post_reg_write, Vg_CoreStartup, /*tid*/1, VG_O_INSTR_PTR, 8);
return;
+# elif defined(VGP_mips32_linux)
+ vg_assert(0 == sizeof(VexGuestMIPS32State) % 16);
+ /* Zero out the initial state, and set up the simulated FPU in a
+ sane way. */
+ LibVEX_GuestMIPS32_initialise(&arch->vex);
+
+ /* Zero out the shadow areas. */
+ VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestMIPS32State));
+ VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestMIPS32State));
+
+ arch->vex.guest_r29 = iifii.initial_client_SP;
+ arch->vex.guest_PC = iifii.initial_client_IP;
+ arch->vex.guest_r31 = iifii.initial_client_SP;
+
# else
# error Unknown platform
# endif
diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c
index 1f5b95c..a8e7e11 100644
--- a/coregrind/m_libcassert.c
+++ b/coregrind/m_libcassert.c
@@ -152,6 +152,31 @@
(srP)->misc.S390X.r_fp = fp; \
(srP)->misc.S390X.r_lr = lr; \
}
+#elif defined(VGP_mips32_linux)
+# define GET_STARTREGS(srP) \
+ { UInt pc, sp, fp, ra, gp; \
+ asm("move $8, $31;" /* t0 = ra */ \
+ "bal m_libcassert_get_ip;" /* ra = pc */ \
+ "m_libcassert_get_ip:\n" \
+ "move %0, $31;" \
+ "move $31, $8;" /* restore lr */ \
+ "move %1, $29;" \
+ "move %2, $30;" \
+ "move %3, $31;" \
+ "move %4, $28;" \
+ : "=r" (pc), \
+ "=r" (sp), \
+ "=r" (fp), \
+ "=r" (ra), \
+ "=r" (gp) \
+ : /* reads none */ \
+ : "$8" /* trashed */ ); \
+ (srP)->r_pc = (ULong)pc - 8; \
+ (srP)->r_sp = (ULong)sp; \
+ (srP)->misc.MIPS32.r30 = (ULong)fp; \
+ (srP)->misc.MIPS32.r31 = (ULong)ra; \
+ (srP)->misc.MIPS32.r28 = (ULong)gp; \
+ }
#else
# error Unknown platform
#endif
diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c
index 4bc07cb..e8368b3 100644
--- a/coregrind/m_libcfile.c
+++ b/coregrind/m_libcfile.c
@@ -194,7 +194,17 @@
Int VG_(pipe) ( Int fd[2] )
{
-# if defined(VGO_linux)
+# if defined(VGP_mips32_linux)
+ /* __NR_pipe has a strange return convention on mips32-linux. */
+ SysRes res = VG_(do_syscall0)(__NR_pipe);
+ if (!sr_isError(res)) {
+ fd[0] = (Int)sr_Res(res);
+ fd[1] = (Int)sr_ResEx(res);
+ return 0;
+ } else {
+ return -1;
+ }
+# elif defined(VGO_linux)
SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
return sr_isError(res) ? -1 : 0;
# elif defined(VGO_darwin)
@@ -596,6 +606,16 @@
0, // Padding needed on PPC32
0, offset); // Big endian long long
return res;
+# elif defined(VGP_mips32_linux) && VKI_LITTLE_ENDIAN
+ vg_assert(sizeof(OffT) == 4);
+ res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
+ 0, offset, 0);
+ return res;
+# elif defined(VGP_mips32_linux) && VKI_BIG_ENDIAN
+ vg_assert(sizeof(OffT) == 4);
+ res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
+ 0, 0, offset);
+ return res;
# elif defined(VGP_amd64_linux) \
|| defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
@@ -837,7 +857,8 @@
res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
return sr_isError(res) ? -1 : sr_Res(res);
-# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
+# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+ || defined(VGP_mips32_linux)
SysRes res;
res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
return sr_isError(res) ? -1 : sr_Res(res);
@@ -875,7 +896,8 @@
res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
return sr_isError(res) ? -1 : sr_Res(res);
-# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
+# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+ || defined(VGP_mips32_linux)
SysRes res;
res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
return sr_isError(res) ? -1 : sr_Res(res);
@@ -913,7 +935,8 @@
res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
return sr_isError(res) ? -1 : sr_Res(res);
-# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
+# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+ || defined(VGP_mips32_linux)
SysRes res;
res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
count, VKI_MSG_NOSIGNAL, 0,0);
@@ -932,7 +955,8 @@
Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
{
# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
- || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
+ || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \
+ || defined(VGP_mips32_linux)
SysRes res;
UWord args[3];
args[0] = sd;
@@ -961,7 +985,8 @@
Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
{
# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
- || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
+ || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \
+ || defined(VGP_mips32_linux)
SysRes res;
UWord args[3];
args[0] = sd;
@@ -1002,7 +1027,8 @@
res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
return sr_isError(res) ? -1 : sr_Res(res);
-# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
+# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+ || defined(VGP_mips32_linux)
SysRes res;
res = VG_(do_syscall5)( __NR_getsockopt,
(UWord)sd, (UWord)level, (UWord)optname,
diff --git a/coregrind/m_libcproc.c b/coregrind/m_libcproc.c
index 21fee60..6f0c71b 100644
--- a/coregrind/m_libcproc.c
+++ b/coregrind/m_libcproc.c
@@ -549,7 +549,8 @@
# 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 @@
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
diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c
index 9980640..047c508 100644
--- a/coregrind/m_machine.c
+++ b/coregrind/m_machine.c
@@ -103,6 +103,15 @@
= VG_(threads)[tid].arch.vex.guest_r11;
regs->misc.S390X.r_lr
= VG_(threads)[tid].arch.vex.guest_r14;
+# elif defined(VGA_mips32)
+ regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC;
+ regs->r_sp = VG_(threads)[tid].arch.vex.guest_r29;
+ regs->misc.MIPS32.r30
+ = VG_(threads)[tid].arch.vex.guest_r30;
+ regs->misc.MIPS32.r31
+ = VG_(threads)[tid].arch.vex.guest_r31;
+ regs->misc.MIPS32.r28
+ = VG_(threads)[tid].arch.vex.guest_r28;
# else
# error "Unknown arch"
# endif
@@ -132,6 +141,9 @@
# elif defined(VGP_s390x_linux)
VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
+# elif defined(VGP_mips32_linux)
+ VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
+ VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
# else
# error "Unknown plat"
# endif
@@ -282,6 +294,39 @@
(*f)(tid, "r13", vex->guest_r13);
(*f)(tid, "r14", vex->guest_r14);
(*f)(tid, "r15", vex->guest_r15);
+#elif defined(VGA_mips32)
+ (*f)(tid, "r0" , vex->guest_r0 );
+ (*f)(tid, "r1" , vex->guest_r1 );
+ (*f)(tid, "r2" , vex->guest_r2 );
+ (*f)(tid, "r3" , vex->guest_r3 );
+ (*f)(tid, "r4" , vex->guest_r4 );
+ (*f)(tid, "r5" , vex->guest_r5 );
+ (*f)(tid, "r6" , vex->guest_r6 );
+ (*f)(tid, "r7" , vex->guest_r7 );
+ (*f)(tid, "r8" , vex->guest_r8 );
+ (*f)(tid, "r9" , vex->guest_r9 );
+ (*f)(tid, "r10", vex->guest_r10);
+ (*f)(tid, "r11", vex->guest_r11);
+ (*f)(tid, "r12", vex->guest_r12);
+ (*f)(tid, "r13", vex->guest_r13);
+ (*f)(tid, "r14", vex->guest_r14);
+ (*f)(tid, "r15", vex->guest_r15);
+ (*f)(tid, "r16", vex->guest_r16);
+ (*f)(tid, "r17", vex->guest_r17);
+ (*f)(tid, "r18", vex->guest_r18);
+ (*f)(tid, "r19", vex->guest_r19);
+ (*f)(tid, "r20", vex->guest_r20);
+ (*f)(tid, "r21", vex->guest_r21);
+ (*f)(tid, "r22", vex->guest_r22);
+ (*f)(tid, "r23", vex->guest_r23);
+ (*f)(tid, "r24", vex->guest_r24);
+ (*f)(tid, "r25", vex->guest_r25);
+ (*f)(tid, "r26", vex->guest_r26);
+ (*f)(tid, "r27", vex->guest_r27);
+ (*f)(tid, "r28", vex->guest_r28);
+ (*f)(tid, "r29", vex->guest_r29);
+ (*f)(tid, "r30", vex->guest_r30);
+ (*f)(tid, "r31", vex->guest_r31);
#else
# error Unknown arch
#endif
@@ -389,7 +434,7 @@
/* For hwcaps detection on ppc32/64, s390x, and arm we'll need to do SIGILL
testing, so we need a VG_MINIMAL_JMP_BUF. */
#if defined(VGA_ppc32) || defined(VGA_ppc64) \
- || defined(VGA_arm) || defined(VGA_s390x)
+ || defined(VGA_arm) || defined(VGA_s390x) || defined(VGA_mips32)
#include "pub_tool_libcsetjmp.h"
static VG_MINIMAL_JMP_BUF(env_unsup_insn);
static void handler_unsup_insn ( Int x ) {
@@ -568,6 +613,64 @@
#endif /* VGA_s390x */
+#ifdef VGA_mips32
+
+/* Read /proc/cpuinfo and return the machine model. */
+static UInt VG_(get_machine_model)(void)
+{
+ char *search_MIPS_str = "MIPS";
+ char *search_Broadcom_str = "Broadcom";
+ Int n, fh;
+ SysRes fd;
+ SizeT num_bytes, file_buf_size;
+ HChar *file_buf;
+
+ /* Slurp contents of /proc/cpuinfo into FILE_BUF */
+ fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR );
+ if ( sr_isError(fd) ) return -1;
+
+ fh = sr_Res(fd);
+
+ /* Determine the size of /proc/cpuinfo.
+ Work around broken-ness in /proc file system implementation.
+ fstat returns a zero size for /proc/cpuinfo although it is
+ claimed to be a regular file. */
+ num_bytes = 0;
+ file_buf_size = 1000;
+ file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
+ while (42) {
+ n = VG_(read)(fh, file_buf, file_buf_size);
+ if (n < 0) break;
+
+ num_bytes += n;
+ if (n < file_buf_size) break; /* reached EOF */
+ }
+
+ if (n < 0) num_bytes = 0; /* read error; ignore contents */
+
+ if (num_bytes > file_buf_size) {
+ VG_(free)( file_buf );
+ VG_(lseek)( fh, 0, VKI_SEEK_SET );
+ file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 );
+ n = VG_(read)( fh, file_buf, num_bytes );
+ if (n < 0) num_bytes = 0;
+ }
+
+ file_buf[num_bytes] = '\0';
+ VG_(close)(fh);
+
+ /* Parse file */
+ if (VG_(strstr) (file_buf, search_Broadcom_str) != NULL)
+ return VEX_PRID_COMP_BROADCOM;
+ if (VG_(strstr) (file_buf, search_MIPS_str) != NULL)
+ return VEX_PRID_COMP_MIPS;
+
+ /* Did not find string in the proc file. */
+ return -1;
+}
+
+#endif
+
/* Determine what insn set and insn set variant the host has, and
record it. To be called once at system startup. Returns False if
this a CPU incapable of running Valgrind. */
@@ -1249,6 +1352,17 @@
return True;
}
+#elif defined(VGA_mips32)
+ {
+ va = VexArchMIPS32;
+ UInt model = VG_(get_machine_model)();
+ if (model== -1)
+ return False;
+
+ vai.hwcaps = model;
+ return True;
+ }
+
#else
# error "Unknown arch"
#endif
@@ -1370,6 +1484,11 @@
assume we always do. */
return 16;
+# elif defined(VGA_mips32)
+ /* The guest state implies 4, but that can't really be true, can
+ it? */
+ return 8;
+
# else
# error "Unknown arch"
# endif
@@ -1383,7 +1502,7 @@
# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
|| defined(VGP_arm_linux) \
|| defined(VGP_ppc32_linux) || defined(VGO_darwin) \
- || defined(VGP_s390x_linux)
+ || defined(VGP_s390x_linux) || defined(VGP_mips32_linux)
return f;
# elif defined(VGP_ppc64_linux)
/* ppc64-linux uses the AIX scheme, in which f is a pointer to a
diff --git a/coregrind/m_main.c b/coregrind/m_main.c
index 71065ce..7a35112 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -1539,8 +1539,10 @@
// 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 @@
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 @@
# 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 @@
"\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
diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c
index fd24c1a..50e00ac 100644
--- a/coregrind/m_redir.c
+++ b/coregrind/m_redir.c
@@ -1358,6 +1358,17 @@
# elif defined(VGP_s390x_linux)
/* nothing so far */
+# elif defined(VGP_mips32_linux)
+ if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
+
+ /* this is mandatory - can't sanely continue without it */
+ add_hardwired_spec(
+ "ld.so.3", "strlen",
+ (Addr)&VG_(mips32_linux_REDIR_FOR_strlen),
+ complain_about_stripped_glibc_ldso
+ );
+ }
+
# else
# error Unknown platform
# endif
diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c
index 4c7ef60..93fa109 100644
--- a/coregrind/m_scheduler/scheduler.c
+++ b/coregrind/m_scheduler/scheduler.c
@@ -780,6 +780,10 @@
# if defined(VGA_s390x)
/* no special requirements */
# endif
+
+# if defined(VGA_mips32)
+ /* no special requirements */
+# endif
}
// NO_VGDB_POLL value ensures vgdb is not polled, while
@@ -1557,6 +1561,9 @@
#elif defined (VGA_s390x)
# define VG_CLREQ_ARGS guest_r2
# define VG_CLREQ_RET guest_r3
+#elif defined(VGA_mips32)
+# define VG_CLREQ_ARGS guest_r12
+# define VG_CLREQ_RET guest_r11
#else
# error Unknown arch
#endif
diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c
index 81a53b1..9ef6b85 100644
--- a/coregrind/m_signals.c
+++ b/coregrind/m_signals.c
@@ -516,6 +516,25 @@
(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 @@
" 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 @@
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 @@
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 @@
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... */
diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c
index bb76931..19b347b 100644
--- a/coregrind/m_stacktrace.c
+++ b/coregrind/m_stacktrace.c
@@ -668,7 +668,9 @@
#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 @@
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 ---*/
diff --git a/coregrind/m_syscall.c b/coregrind/m_syscall.c
index 05083d5..a52aeb0 100644
--- a/coregrind/m_syscall.c
+++ b/coregrind/m_syscall.c
@@ -62,6 +62,7 @@
SysRes VG_(mk_SysRes_x86_linux) ( Int val ) {
SysRes res;
+ res._valEx = 0; /* unused except on mips-linux */
res._isError = val >= -4095 && val <= -1;
if (res._isError) {
res._val = (UInt)(-val);
@@ -74,6 +75,7 @@
/* Similarly .. */
SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) {
SysRes res;
+ res._valEx = 0; /* unused except on mips-linux */
res._isError = val >= -4095 && val <= -1;
if (res._isError) {
res._val = (ULong)(-val);
@@ -87,6 +89,7 @@
/* Note this must be in the bottom bit of the second arg */
SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) {
SysRes res;
+ res._valEx = 0; /* unused except on mips-linux */
res._isError = (cr0so & 1) != 0;
res._val = val;
return res;
@@ -95,6 +98,7 @@
/* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */
SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) {
SysRes res;
+ res._valEx = 0; /* unused except on mips-linux */
res._isError = (cr0so & 1) != 0;
res._val = val;
return res;
@@ -102,6 +106,7 @@
SysRes VG_(mk_SysRes_s390x_linux) ( Long val ) {
SysRes res;
+ res._valEx = 0; /* unused except on mips-linux */
res._isError = val >= -4095 && val <= -1;
if (res._isError) {
res._val = -val;
@@ -113,6 +118,7 @@
SysRes VG_(mk_SysRes_arm_linux) ( Int val ) {
SysRes res;
+ res._valEx = 0; /* unused except on mips-linux */
res._isError = val >= -4095 && val <= -1;
if (res._isError) {
res._val = (UInt)(-val);
@@ -122,9 +128,19 @@
return res;
}
+/* MIPS uses a3 != 0 to flag an error */
+SysRes VG_(mk_SysRes_mips32_linux) ( UWord v0, UWord v1, UWord a3 ) {
+ SysRes res;
+ res._isError = (a3 != (UWord)0);
+ res._val = v0;
+ res._valEx = v1;
+ return res;
+}
+
/* Generic constructors. */
SysRes VG_(mk_SysRes_Error) ( UWord err ) {
SysRes r;
+ r._valEx = 0; /* unused except on mips-linux */
r._isError = True;
r._val = err;
return r;
@@ -132,6 +148,7 @@
SysRes VG_(mk_SysRes_Success) ( UWord res ) {
SysRes r;
+ r._valEx = 0; /* unused except on mips-linux */
r._isError = False;
r._val = res;
return r;
@@ -575,6 +592,40 @@
return (UWord) (__svcres);
}
+#elif defined(VGP_mips32_linux)
+/* Incoming args (syscall number + up to 6 args) come in a0 - a3 and stack.
+
+ The syscall number goes in v0. The args are passed to the syscall in
+ the regs a0 - a3 and stack, i.e. the kernel's syscall calling convention.
+
+ (a3 != 0) flags an error.
+ We return the syscall return value in v0.
+ MIPS version
+*/
+extern int do_syscall_WRK (
+ int a1, int a2, int a3,
+ int a4, int a5, int a6, int syscall_no, UWord *err,
+ UWord *valHi, UWord* valLo
+ );
+asm(
+".globl do_syscall_WRK\n"
+".ent do_syscall_WRK\n"
+".text\n"
+"do_syscall_WRK:\n"
+" lw $2, 24($29)\n"
+" syscall\n"
+" lw $8, 28($29)\n"
+" sw $7, ($8)\n"
+" lw $8, 32($29)\n"
+" sw $3, ($8)\n" // store valHi
+" lw $8, 36($29)\n"
+" sw $2, ($8)\n" // store valLo
+" jr $31\n"
+" nop\n"
+".previous\n"
+".end do_syscall_WRK\n"
+);
+
#else
# error Unknown platform
#endif
@@ -682,6 +733,13 @@
}
return VG_(mk_SysRes_s390x_linux)( val );
+
+#elif defined(VGP_mips32_linux)
+ UWord err = 0;
+ UWord valHi = 0;
+ UWord valLo = 0;
+ (void) do_syscall_WRK(a1,a2,a3,a4,a5,a6, sysno,&err,&valHi,&valLo);
+ return VG_(mk_SysRes_mips32_linux)( valLo, valHi, (ULong)err );
#else
# error Unknown platform
#endif
diff --git a/coregrind/m_syswrap/priv_types_n_macros.h b/coregrind/m_syswrap/priv_types_n_macros.h
index 8069cbd..9040148 100644
--- a/coregrind/m_syswrap/priv_types_n_macros.h
+++ b/coregrind/m_syswrap/priv_types_n_macros.h
@@ -98,6 +98,15 @@
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 @@
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 @@
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 @@
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 @@
next-sizeof(t), sizeof(t) \
); \
} while (0)
+#endif
#if defined(VG_BIGENDIAN)
# define PSRAn(n,s,t,a) PSRAn_BE(n,s,t,a)
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index 62eb3bf..7d97b6f 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -271,6 +271,17 @@
: "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 @@
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 );
diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c
index 991e009..8c31dd1 100644
--- a/coregrind/m_syswrap/syswrap-main.c
+++ b/coregrind/m_syswrap/syswrap-main.c
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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
diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S
index 73ef862..d10b840 100644
--- a/coregrind/m_trampoline.S
+++ b/coregrind/m_trampoline.S
@@ -1021,6 +1021,64 @@
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 @@
#endif
#endif
#endif
+#endif
#if defined(VGO_linux)
/* Let the linker know we don't need an executable stack */
diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c
index d055101..fc6fa62 100644
--- a/coregrind/m_translate.c
+++ b/coregrind/m_translate.c
@@ -726,7 +726,7 @@
static Bool translations_allowable_from_seg ( NSegment const* seg )
{
-# if defined(VGA_x86) || defined(VGA_s390x)
+# if defined(VGA_x86) || defined(VGA_s390x) || defined(VGA_mips32)
Bool allowR = True;
# else
Bool allowR = False;
@@ -1188,6 +1188,12 @@
nraddr_szB == 8 ? mkU64(0) : mkU32(0)
)
);
+# if defined(VGP_mips32_linux)
+ // t9 needs to be set to point to the start of the redirected function.
+ VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
+ Int offB_GPR25 = offsetof(VexGuestMIPS32State,guest_r25);
+ addStmtToIRSB( bb, IRStmt_Put( offB_GPR25, mkU32( closure->readdr )) );
+# endif
# if defined(VG_PLAT_USES_PPCTOC)
{ VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
addStmtToIRSB(
@@ -1224,6 +1230,11 @@
: IRExpr_Const(IRConst_U32( (UInt)closure->nraddr ))
)
);
+# if defined(VGP_mips32_linux)
+ // t9 needs to be set to point to the start of the redirected function.
+ Int offB_GPR25 = offsetof(VexGuestMIPS32State,guest_r25);
+ addStmtToIRSB( bb, IRStmt_Put( offB_GPR25, mkU32( closure->readdr )) );
+# endif
# if defined(VGP_ppc64_linux)
addStmtToIRSB(
bb,
diff --git a/coregrind/pub_core_aspacemgr.h b/coregrind/pub_core_aspacemgr.h
index 150d3be..39b5ae7 100644
--- a/coregrind/pub_core_aspacemgr.h
+++ b/coregrind/pub_core_aspacemgr.h
@@ -343,7 +343,8 @@
// 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
diff --git a/coregrind/pub_core_basics.h b/coregrind/pub_core_basics.h
index f0861d4..63db17f 100644
--- a/coregrind/pub_core_basics.h
+++ b/coregrind/pub_core_basics.h
@@ -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 @@
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;
diff --git a/coregrind/pub_core_debuginfo.h b/coregrind/pub_core_debuginfo.h
index fa1b129..8655260 100644
--- a/coregrind/pub_core_debuginfo.h
+++ b/coregrind/pub_core_debuginfo.h
@@ -93,6 +93,12 @@
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
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
diff --git a/coregrind/pub_core_machine.h b/coregrind/pub_core_machine.h
index b76f395..4b3ad6c 100644
--- a/coregrind/pub_core_machine.h
+++ b/coregrind/pub_core_machine.h
@@ -75,6 +75,17 @@
# 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
@@ -104,6 +115,10 @@
# 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
diff --git a/coregrind/pub_core_mallocfree.h b/coregrind/pub_core_mallocfree.h
index c192f19..508b9f3 100644
--- a/coregrind/pub_core_mallocfree.h
+++ b/coregrind/pub_core_mallocfree.h
@@ -80,6 +80,7 @@
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
diff --git a/coregrind/pub_core_syscall.h b/coregrind/pub_core_syscall.h
index 1b6d35f..2902001 100644
--- a/coregrind/pub_core_syscall.h
+++ b/coregrind/pub_core_syscall.h
@@ -79,6 +79,8 @@
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 );
diff --git a/coregrind/pub_core_threadstate.h b/coregrind/pub_core_threadstate.h
index ccb41a1..2e80f87 100644
--- a/coregrind/pub_core_threadstate.h
+++ b/coregrind/pub_core_threadstate.h
@@ -87,6 +87,8 @@
typedef VexGuestARMState VexGuestArchState;
#elif defined(VGA_s390x)
typedef VexGuestS390XState VexGuestArchState;
+#elif defined(VGA_mips32)
+ typedef VexGuestMIPS32State VexGuestArchState;
#else
# error Unknown architecture
#endif
diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h
index 4e87792..765c7f6 100644
--- a/coregrind/pub_core_trampoline.h
+++ b/coregrind/pub_core_trampoline.h
@@ -127,6 +127,12 @@
extern Addr VG_(s390x_linux_SUBST_FOR_rt_sigreturn);
#endif
+#if defined(VGP_mips32_linux)
+extern Addr VG_(mips32_linux_SUBST_FOR_sigreturn);
+extern Addr VG_(mips32_linux_SUBST_FOR_rt_sigreturn);
+extern UInt VG_(mips32_linux_REDIR_FOR_strlen)( void* );
+#endif
+
#endif // __PUB_CORE_TRAMPOLINE_H
/*--------------------------------------------------------------------*/
diff --git a/coregrind/pub_core_transtab_asm.h b/coregrind/pub_core_transtab_asm.h
index 00adced..12b02de 100644
--- a/coregrind/pub_core_transtab_asm.h
+++ b/coregrind/pub_core_transtab_asm.h
@@ -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
diff --git a/coregrind/vgdb.c b/coregrind/vgdb.c
index 46b2cfd..c0f1d81 100644
--- a/coregrind/vgdb.c
+++ b/coregrind/vgdb.c
@@ -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 @@
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 @@
#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 @@
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
diff --git a/drd/drd_bitmap.h b/drd/drd_bitmap.h
index 372c787..5cc6d48 100644
--- a/drd/drd_bitmap.h
+++ b/drd/drd_bitmap.h
@@ -136,7 +136,8 @@
#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
diff --git a/drd/drd_clientreq.c b/drd/drd_clientreq.c
index be16544..42ab3b9 100644
--- a/drd/drd_clientreq.c
+++ b/drd/drd_clientreq.c
@@ -69,6 +69,12 @@
* DRD's handler for Valgrind client requests. The code below handles both
* DRD's public and tool-internal client requests.
*/
+#if defined(VGP_mips32_linux)
+ /* There is a cse related issue in gcc for MIPS. Optimization level
+ has to be lowered, so cse related optimizations are not
+ included. */
+ __attribute__((optimize("O1")))
+#endif
static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret)
{
UWord result = 0;
diff --git a/drd/drd_load_store.c b/drd/drd_load_store.c
index 3d99112..7dc8a9f 100644
--- a/drd/drd_load_store.c
+++ b/drd/drd_load_store.c
@@ -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
diff --git a/drd/drd_thread.c b/drd/drd_thread.c
index c2f1a85..6e2dd41 100644
--- a/drd/drd_thread.c
+++ b/drd/drd_thread.c
@@ -597,6 +597,12 @@
}
/** Store the thread mode: joinable or detached. */
+#if defined(VGP_mips32_linux)
+ /* There is a cse related issue in gcc for MIPS. Optimization level
+ has to be lowered, so cse related optimizations are not
+ included.*/
+ __attribute__((optimize("O1")))
+#endif
void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
{
tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
diff --git a/helgrind/tests/annotate_hbefore.c b/helgrind/tests/annotate_hbefore.c
index af3fa04..cd58cef 100644
--- a/helgrind/tests/annotate_hbefore.c
+++ b/helgrind/tests/annotate_hbefore.c
@@ -186,6 +186,38 @@
return cc == 0;
}
+#elif defined(VGA_mips32)
+
+// mips
+/* return 1 if success, 0 if failure */
+UWord do_acasW ( UWord* addr, UWord expected, UWord nyu )
+{
+ UWord old, success;
+ UWord block[3] = { (UWord)addr, nyu, expected};
+
+ __asm__ __volatile__(
+ ".set noreorder" "\n\t"
+ "lw $t0, 0(%1)" "\n\t"
+ "lw $t2, 8(%1)" "\n\t"
+ "lw $t3, 4(%1)" "\n\t"
+ "ll $t1, 0($t0)" "\n\t"
+ "bne $t1, $t2, exit_0" "\n\t"
+ "sc $t3, 0($t0)" "\n\t"
+ "move %0, $t3" "\n\t"
+ "b exit" "\n\t"
+ "nop" "\n\t"
+ "exit_0:" "\n\t"
+ "move %0, $0" "\n\t"
+ "exit:" "\n\t"
+ : /*out*/ "=r"(success)
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "t0", "t1", "t2", "t3", "memory"
+ );
+
+ assert(success == 0 || success == 1);
+ return success;
+}
+
#endif
void atomic_incW ( UWord* w )
diff --git a/helgrind/tests/tc07_hbl1.c b/helgrind/tests/tc07_hbl1.c
index e5b11c4..92c74e0 100644
--- a/helgrind/tests/tc07_hbl1.c
+++ b/helgrind/tests/tc07_hbl1.c
@@ -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) \
@@ -71,6 +74,20 @@
" 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
diff --git a/helgrind/tests/tc08_hbl2.c b/helgrind/tests/tc08_hbl2.c
index 8cc682b..b39f9ee 100644
--- a/helgrind/tests/tc08_hbl2.c
+++ b/helgrind/tests/tc08_hbl2.c
@@ -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
@@ -88,6 +91,19 @@
" 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
diff --git a/helgrind/tests/tc11_XCHG.c b/helgrind/tests/tc11_XCHG.c
index ac85d82..fadc774 100644
--- a/helgrind/tests/tc11_XCHG.c
+++ b/helgrind/tests/tc11_XCHG.c
@@ -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
@@ -71,6 +74,22 @@
# 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)
diff --git a/include/Makefile.am b/include/Makefile.am
index 8516492..ade27c2 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -49,16 +49,19 @@
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
diff --git a/include/pub_tool_basics.h b/include/pub_tool_basics.h
index ae7bae6..5b387e8 100644
--- a/include/pub_tool_basics.h
+++ b/include/pub_tool_basics.h
@@ -163,6 +163,7 @@
typedef
struct {
UWord _val;
+ UWord _valEx; // only used on mips-linux
Bool _isError;
}
SysRes;
@@ -197,6 +198,9 @@
static inline UWord sr_Res ( SysRes sr ) {
return sr._isError ? 0 : sr._val;
}
+static inline UWord sr_ResEx ( SysRes sr ) {
+ return sr._isError ? 0 : sr._valEx;
+}
static inline UWord sr_ResHI ( SysRes sr ) {
return 0;
}
@@ -264,9 +268,11 @@
#undef VG_BIGENDIAN
#undef VG_LITTLEENDIAN
-#if defined(VGA_x86) || defined(VGA_amd64) || defined (VGA_arm)
+#if defined(VGA_x86) || defined(VGA_amd64) || defined (VGA_arm) \
+ || (defined(VGA_mips32) && defined (_MIPSEL))
# define VG_LITTLEENDIAN 1
-#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x)
+#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) \
+ || (defined(VGA_mips32) && defined (_MIPSEB))
# define VG_BIGENDIAN 1
#else
# error Unknown arch
@@ -276,7 +282,8 @@
#if defined(VGA_x86)
# define VG_REGPARM(n) __attribute__((regparm(n)))
#elif defined(VGA_amd64) || defined(VGA_ppc32) \
- || defined(VGA_ppc64) || defined(VGA_arm) || defined(VGA_s390x)
+ || defined(VGA_ppc64) || defined(VGA_arm) || defined(VGA_s390x) \
+ || defined(VGA_mips32)
# define VG_REGPARM(n) /* */
#else
# error Unknown arch
diff --git a/include/pub_tool_machine.h b/include/pub_tool_machine.h
index 6b30e69..55fd2fb 100644
--- a/include/pub_tool_machine.h
+++ b/include/pub_tool_machine.h
@@ -83,6 +83,12 @@
# 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
diff --git a/include/pub_tool_vkiscnums_asm.h b/include/pub_tool_vkiscnums_asm.h
index 018cb19..649c7aa 100644
--- a/include/pub_tool_vkiscnums_asm.h
+++ b/include/pub_tool_vkiscnums_asm.h
@@ -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"
diff --git a/include/valgrind.h b/include/valgrind.h
index d10a513..afb4681 100644
--- a/include/valgrind.h
+++ b/include/valgrind.h
@@ -117,6 +117,7 @@
#undef PLAT_ppc64_linux
#undef PLAT_arm_linux
#undef PLAT_s390x_linux
+#undef PLAT_mips32_linux
#if defined(__APPLE__) && defined(__i386__)
@@ -138,6 +139,8 @@
# define PLAT_arm_linux 1
#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
# define PLAT_s390x_linux 1
+#elif defined(__linux__) && defined(__mips__)
+# define PLAT_mips32_linux 1
#else
/* If we're not compiling for our target platform, don't generate
any inline asms. */
@@ -665,6 +668,70 @@
#endif /* PLAT_s390x_linux */
+/* ------------------------- mips32-linux ---------------- */
+
+#if defined(PLAT_mips32_linux)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+/* .word 0x342
+ * .word 0x742
+ * .word 0xC2
+ * .word 0x4C2*/
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "srl $0, $0, 13\n\t" \
+ "srl $0, $0, 29\n\t" \
+ "srl $0, $0, 3\n\t" \
+ "srl $0, $0, 19\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ __extension__ \
+ ({ volatile unsigned int _zzq_args[6]; \
+ volatile unsigned int _zzq_result; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ __asm__ volatile("move $11, %1\n\t" /*default*/ \
+ "move $12, %2\n\t" /*ptr*/ \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* T3 = client_request ( T4 ) */ \
+ "or $13, $13, $13\n\t" \
+ "move %0, $11\n\t" /*result*/ \
+ : "=r" (_zzq_result) \
+ : "r" (_zzq_default), "r" (&_zzq_args[0]) \
+ : "cc","memory", "t3", "t4"); \
+ _zzq_result; \
+ })
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ volatile unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %t9 = guest_NRADDR */ \
+ "or $14, $14, $14\n\t" \
+ "move %0, $11" /*result*/ \
+ : "=r" (__addr) \
+ : \
+ : "cc", "memory" , "t3" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_CALL_NOREDIR_T9 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* call-noredir *%t9 */ \
+ "or $15, $15, $15\n\t"
+#endif /* PLAT_mips32_linux */
+
/* Insert assembly code for other platforms here... */
#endif /* NVALGRIND */
@@ -3589,6 +3656,545 @@
#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 @@
#undef PLAT_ppc64_linux
#undef PLAT_arm_linux
#undef PLAT_s390x_linux
+#undef PLAT_mips32_linux
#endif /* __VALGRIND_H */
diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h
index d73b044..ec91c9f 100644
--- a/include/vki/vki-linux.h
+++ b/include/vki/vki-linux.h
@@ -91,6 +91,8 @@
# include "vki-posixtypes-arm-linux.h"
#elif defined(VGA_s390x)
# include "vki-posixtypes-s390x-linux.h"
+#elif defined(VGA_mips32)
+# include "vki-posixtypes-mips32-linux.h"
#else
# error Unknown platform
#endif
@@ -211,6 +213,8 @@
# include "vki-arm-linux.h"
#elif defined(VGA_s390x)
# include "vki-s390x-linux.h"
+#elif defined(VGA_mips32)
+# include "vki-mips32-linux.h"
#else
# error Unknown platform
#endif
@@ -383,6 +387,8 @@
// From linux-2.6.8.1/include/asm-generic/siginfo.h
//----------------------------------------------------------------------
+// Some archs, such as MIPS, have non-standard vki_siginfo.
+#ifndef HAVE_ARCH_SIGINFO_T
typedef union vki_sigval {
int sival_int;
void __user *sival_ptr;
@@ -462,6 +468,7 @@
} _sigpoll;
} _sifields;
} vki_siginfo_t;
+#endif
#define __VKI_SI_FAULT 0
diff --git a/memcheck/mc_machine.c b/memcheck/mc_machine.c
index 5bee6c2..2df3a58 100644
--- a/memcheck/mc_machine.c
+++ b/memcheck/mc_machine.c
@@ -76,6 +76,11 @@
# 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);
@@ -939,6 +944,117 @@
# 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
# error "FIXME: not implemented for this architecture"
# endif
@@ -1022,7 +1138,6 @@
/* --------------------- arm --------------------- */
# elif defined(VGA_arm)
-
VG_(printf)("get_reg_array_equiv_int_type(arm): unhandled: ");
ppIRRegArray(arr);
VG_(printf)("\n");
@@ -1033,6 +1148,14 @@
/* 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
diff --git a/memcheck/tests/atomic_incs.c b/memcheck/tests/atomic_incs.c
index 80cf810..ac1e775 100644
--- a/memcheck/tests/atomic_incs.c
+++ b/memcheck/tests/atomic_incs.c
@@ -110,6 +110,48 @@
: "+m" (*p), "+m" (dummy)
: "d" (n)
: "cc", "memory", "0", "1");
+#elif defined(VGA_mips32)
+#if defined (_MIPSEL)
+ unsigned int block[3]
+ = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "lw $t2, 4($t0)" "\n\t" // n
+ "ll $t3, 0($t1)" "\n\t"
+ "addu $t3, $t3, $t2" "\n\t"
+ "andi $t3, $t3, 0xFF" "\n\t"
+ "sc $t3, 0($t1)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t"
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3"
+ );
+ } while (block[2] != 1);
+#elif defined (_MIPSEB)
+ unsigned int block[3]
+ = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "lw $t2, 4($t0)" "\n\t" // n
+ "li $t4, 0x000000FF" "\n\t"
+ "ll $t3, 0($t1)" "\n\t"
+ "addu $t3, $t3, $t2" "\n\t"
+ "and $t3, $t3, $t4" "\n\t"
+ "wsbh $t4, $t3" "\n\t"
+ "rotr $t4, $t4, 16" "\n\t"
+ "or $t3, $t4, $t3" "\n\t"
+ "sc $t3, 0($t1)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t"
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3", "t4"
+ );
+ } while (block[2] != 1);
+#endif
#else
# error "Unsupported arch"
#endif
@@ -203,6 +245,43 @@
: "+m" (*p), "+m" (dummy)
: "d" (n)
: "cc", "memory", "0", "1");
+#elif defined(VGA_mips32)
+#if defined (_MIPSEL)
+ unsigned int block[3]
+ = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "lw $t2, 4($t0)" "\n\t" // n
+ "ll $t3, 0($t1)" "\n\t"
+ "addu $t3, $t3, $t2" "\n\t"
+ "andi $t3, $t3, 0xFFFF" "\n\t"
+ "sc $t3, 0($t1)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t"
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3"
+ );
+ } while (block[2] != 1);
+#elif defined (_MIPSEB)
+ unsigned int block[3]
+ = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "li $t2, 32694" "\n\t" // n
+ "li $t3, 0x1" "\n\t"
+ "sll $t2, $t2, 16" "\n\t"
+ "sw $t2, 0($t1)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t"
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3"
+ );
+ } while (block[2] != 1);
+#endif
#else
# error "Unsupported arch"
#endif
@@ -289,6 +368,23 @@
: "+m" (*p)
: "d" (n)
: "cc", "memory", "0", "1");
+#elif defined(VGA_mips32)
+ unsigned int block[3]
+ = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "lw $t2, 4($t0)" "\n\t" // n
+ "ll $t3, 0($t1)" "\n\t"
+ "addu $t3, $t3, $t2" "\n\t"
+ "sc $t3, 0($t1)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t"
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3"
+ );
+ } while (block[2] != 1);
#else
# error "Unsupported arch"
#endif
@@ -296,7 +392,7 @@
__attribute__((noinline)) void atomic_add_64bit ( long long int* p, int n )
{
-#if defined(VGA_x86) || defined(VGA_ppc32)
+#if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32)
/* do nothing; is not supported */
#elif defined(VGA_amd64)
// this is a bit subtle. It relies on the fact that, on a 64-bit platform,
diff --git a/memcheck/tests/memalign_test.c b/memcheck/tests/memalign_test.c
index a9c8784..38e165d 100644
--- a/memcheck/tests/memalign_test.c
+++ b/memcheck/tests/memalign_test.c
@@ -10,7 +10,7 @@
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));
diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am
index 2f16f5b..0fee10d 100644
--- a/none/tests/Makefile.am
+++ b/none/tests/Makefile.am
@@ -22,6 +22,9 @@
if VGCONF_ARCHS_INCLUDE_S390X
SUBDIRS += s390x
endif
+if VGCONF_ARCHS_INCLUDE_MIPS32
+SUBDIRS += mips32
+endif
# OS-specific tests
if VGCONF_OS_IS_LINUX
@@ -36,7 +39,7 @@
SUBDIRS += x86-linux
endif
-DIST_SUBDIRS = x86 amd64 ppc32 ppc64 arm s390x linux darwin x86-linux .
+DIST_SUBDIRS = x86 amd64 ppc32 ppc64 arm s390x mips32 linux darwin x86-linux .
dist_noinst_SCRIPTS = \
filter_cmdline0 \
diff --git a/none/tests/allexec_prepare_prereq b/none/tests/allexec_prepare_prereq
index 0cd1738..d1fa03c 100755
--- a/none/tests/allexec_prepare_prereq
+++ b/none/tests/allexec_prepare_prereq
@@ -32,5 +32,6 @@
pair ppc32 ppc64
pair s390x_unexisting_in_32bits s390x
pair arm arm_unexisting_in_64bits
+pair mips32 mips_unexisting_in_64bits
exit 0
diff --git a/tests/arch_test.c b/tests/arch_test.c
index 6f3d944..b3740b5 100644
--- a/tests/arch_test.c
+++ b/tests/arch_test.c
@@ -29,6 +29,7 @@
"ppc64",
"arm",
"s390x",
+ "mips32",
NULL
};
@@ -58,6 +59,9 @@
#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_*
diff --git a/tests/platform_test b/tests/platform_test
index 7fbf05a..400fd37 100644
--- a/tests/platform_test
+++ b/tests/platform_test
@@ -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
diff --git a/tests/sys_mman.h b/tests/sys_mman.h
index 7ac64d5..c059308 100644
--- a/tests/sys_mman.h
+++ b/tests/sys_mman.h
@@ -21,7 +21,7 @@
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);