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