Necessary changes to support nanoMIPS on Linux.
Part 3/4 - Coregrind and tools changes
Patch by Aleksandar Rikalo, Dimitrije Nikolic, Tamara Vlahovic,
Nikola Milutinovic and Aleksandra Karadzic.
Related KDE issue: #400872.
-static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
@FLAG_M32@
+TOOL_LDFLAGS_NANOMIPS_LINUX = \
+ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
+ @FLAG_M32@ -Wl,-no-relax
+
TOOL_LDFLAGS_MIPS64_LINUX = \
-static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
@FLAG_M64@
*D1c = (cache_t) { 131072, 8, 256 };
*LLc = (cache_t) { 50331648, 24, 256 };
-#elif defined(VGA_mips32)
+#elif defined(VGA_mips32) || defined(VGA_nanomips)
// Set caches to default (for MIPS32-r2(mips 74kc))
*I1c = (cache_t) { 32768, 4, 32 };
/* How many bits at the bottom of an instruction address are
guaranteed to be zero? */
#if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
- || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_arm64)
+ || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) \
+ || defined(VGA_arm64)
# define N_IADDR_LO_ZERO_BITS 2
#elif defined(VGA_x86) || defined(VGA_amd64)
# define N_IADDR_LO_ZERO_BITS 0
req.rkind = MAny;
req.start = 0;
#if defined(VGA_arm) || defined(VGA_arm64) \
- || defined(VGA_mips32) || defined(VGA_mips64)
+ || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)
aspacem_assert(VKI_SHMLBA >= VKI_PAGE_SIZE);
#else
aspacem_assert(VKI_SHMLBA == VKI_PAGE_SIZE);
(UWord) nbytes, (UWord) 3);
vg_assert( !sr_isError(sres) );
+# elif defined(VGA_nanomips)
+
+ __builtin___clear_cache(ptr, (char*)ptr + nbytes);
+
# endif
}
(srP)->misc.MIPS64.r28 = (uc)->uc_mcontext.sc_regs[28]; \
}
+#elif defined(VGP_nanomips_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) \
+ VG_(mk_SysRes_nanomips_linux)((uc)->uc_mcontext.sc_regs[4])
+
+# 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]; \
+ }
+
#elif defined(VGP_x86_solaris)
# define VG_UCONTEXT_INSTR_PTR(uc) ((Addr)(uc)->uc_mcontext.gregs[VKI_EIP])
# define VG_UCONTEXT_STACK_PTR(uc) ((Addr)(uc)->uc_mcontext.gregs[VKI_UESP])
" syscall\n" \
".previous\n"
+#elif defined(VGP_nanomips_linux)
+# define _MY_SIGRETURN(name) \
+ ".text\n" \
+ "my_sigreturn:\n" \
+ " li $t4, " #name "\n" \
+ " syscall[32]\n" \
+ ".previous\n"
#elif defined(VGP_x86_solaris) || defined(VGP_amd64_solaris)
/* Not used on Solaris. */
# define _MY_SIGRETURN(name) \
# if !defined(VGP_ppc32_linux) && \
!defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
!defined(VGP_mips32_linux) && !defined(VGP_mips64_linux) && \
- !defined(VGO_solaris)
+ !defined(VGP_nanomips_linux) && !defined(VGO_solaris)
vg_assert(ksa_old.sa_restorer == my_sigreturn);
# endif
VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGKILL );
// Synthesise a SIGFPE.
void VG_(synth_sigfpe)(ThreadId tid, UInt code)
{
-// Only tested on mips32, mips64, and s390x
-#if !defined(VGA_mips32) && !defined(VGA_mips64) && !defined(VGA_s390x)
+// Only tested on mips32, mips64, s390x and nanomips.
+#if !defined(VGA_mips32) && !defined(VGA_mips64) && !defined(VGA_s390x) && !defined(VGA_nanomips)
vg_assert(0);
#else
vki_siginfo_t info;
/* Get the old host action */
ret = VG_(sigaction)(i, NULL, &sa);
-# if defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
+# if defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) \
+ || defined(VGP_nanomips_linux)
/* apparently we may not even ask about the disposition of these
signals, let alone change them */
if (ret != 0 && (i == VKI_SIGKILL || i == VKI_SIGSTOP))
safely test with -4095.
*/
+SysRes VG_(mk_SysRes_nanomips_linux) ( UWord a0 ) {
+ SysRes res;
+ res._isError = (a0 > 0xFFFFF000ul);
+ res._val = a0;
+ return res;
+}
+
SysRes VG_(mk_SysRes_x86_linux) ( Int val ) {
SysRes res;
res._isError = val >= -4095 && val <= -1;
}
/* Generic constructors. */
+SysRes VG_(mk_SysRes_Success) ( UWord res ) {
+ SysRes r;
+ r._isError = False;
+ r._val = res;
+ return r;
+}
+
+#if defined(VGP_nanomips_linux)
SysRes VG_(mk_SysRes_Error) ( UWord err ) {
SysRes r;
r._isError = True;
- r._val = err;
+ r._val = (UWord)(-(Word)err);
return r;
}
-
-SysRes VG_(mk_SysRes_Success) ( UWord res ) {
+#else
+SysRes VG_(mk_SysRes_Error) ( UWord err ) {
SysRes r;
- r._isError = False;
- r._val = res;
+ r._isError = True;
+ r._val = err;
return r;
}
+#endif
+
#elif defined(VGO_darwin)
".previous \n\t"
);
+#elif defined(VGP_nanomips_linux)
+extern void do_syscall_WRK (
+ RegWord a1, RegWord a2, RegWord a3,
+ RegWord a4, RegWord a5, RegWord a6,
+ RegWord syscall_no, RegWord *res_a0);
+asm (
+ ".text \n\t"
+ ".globl do_syscall_WRK \n\t"
+ ".type do_syscall_WRK, @function \n\t"
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "do_syscall_WRK: \n\t"
+ " save 32, $a7 \n\t"
+ " move $t4, $a6 \n\t"
+ " syscall[32] \n\t"
+ " restore 32, $a7 \n\t"
+ " sw $a0, 0($a7) \n\t"
+ " jrc $ra \n\t"
+ ".size do_syscall_WRK, .-do_syscall_WRK \n\t"
+ ".set pop \n\t"
+ ".previous \n\t"
+);
+
#elif defined(VGP_x86_solaris)
extern ULong
RegWord A3 = (RegWord)v1_a3[1];
return VG_(mk_SysRes_mips64_linux)( V0, V1, A3 );
+#elif defined(VGP_nanomips_linux)
+ RegWord reg_a0 = 0;
+ do_syscall_WRK(a1, a2, a3, a4, a5, a6, sysno, ®_a0);
+ return VG_(mk_SysRes_nanomips_linux)(reg_a0);
+
# elif defined(VGP_x86_solaris)
UInt val, val2, err = False;
Bool restart;
PRE_REG_READ0(long, "sync");
}
+#if !defined(VGP_nanomips_linux)
PRE(sys_fstatfs)
{
FUSE_COMPATIBLE_MAY_BLOCK();
{
POST_MEM_WRITE( ARG3, ARG2 );
}
+#endif
PRE(sys_getsid)
{
PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode);
}
+#if !defined(VGP_nanomips_linux)
PRE(sys_newfstat)
{
FUSE_COMPATIBLE_MAY_BLOCK();
{
POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
}
+#endif
-#if !defined(VGO_solaris) && !defined(VGP_arm64_linux)
+#if !defined(VGO_solaris) && !defined(VGP_arm64_linux) && \
+ !defined(VGP_nanomips_linux)
static vki_sigset_t fork_saved_mask;
// In Linux, the sys_fork() function varies across architectures, but we
PRE_MEM_RASCIIZ( "link(newpath)", ARG2);
}
+#if !defined(VGP_nanomips_linux)
PRE(sys_newlstat)
{
PRINT("sys_newlstat ( %#" FMT_REGWORD "x(%s), %#" FMT_REGWORD "x )", ARG1,
vg_assert(SUCCESS);
POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
}
+#endif
PRE(sys_mkdir)
{
PRE_REG_READ1(long, "setuid", vki_uid_t, uid);
}
+#if !defined(VGP_nanomips_linux)
PRE(sys_newstat)
{
FUSE_COMPATIBLE_MAY_BLOCK();
{
POST_MEM_WRITE( ARG3, ARG2 );
}
+#endif
PRE(sys_symlink)
{
ret = do_syscall_clone_nanomips_linux
(ML_(start_thread_NORETURN), stack, flags, ctst,
child_tidptr, parent_tidptr, NULL);
- res = VG_ (mk_SysRes_nanomips_linux) (ret, 0);
+ res = VG_ (mk_SysRes_nanomips_linux) (ret);
#else
# error Unknown platform
#endif
# elif defined(VGP_nanomips_linux)
VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
RegWord a0 = gst->guest_r4; // a0
- RegWord a1 = gst->guest_r5; // a1
- canonical->sres = VG_(mk_SysRes_nanomips_linux)(a0, a1);
+ canonical->sres = VG_(mk_SysRes_nanomips_linux)(a0);
canonical->what = SsComplete;
# elif defined(VGP_x86_darwin)
VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
vg_assert(canonical->what == SsComplete);
gst->guest_r4 = canonical->sres._val;
- gst->guest_r5 = canonical->sres._valEx;
VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
OFFSET_mips32_r4, sizeof(UWord) );
- VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
- OFFSET_mips32_r5, sizeof(UWord) );
# elif defined(VGP_x86_solaris)
VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
vg_assert(p[0] == 0x0A);
}
-#elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
- || defined(VGP_nanomips_linux)
+#elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
arch->vex.guest_PC -= 4; // sizeof(mips instr)
# endif
}
+#elif defined(VGP_nanomips_linux)
+ {
+ /* Make sure our caller is actually sane, and we're really backing
+ back over a syscall.
+ */
+ arch->vex.guest_PC -= 2;
+ /* PC has to be 16-bit aligned. */
+ vg_assert((arch->vex.guest_PC & 1) == 0);
+
+ UShort *p = ASSUME_ALIGNED(UShort *, (Addr)(arch->vex.guest_PC));
+
+ if (((*p) & 0xFFFD) != 0x1008) {
+ if (((*(p - 1)) & 0xFFFD) != 0x0008) {
+ VG_(message)(Vg_DebugMsg,
+ "?! restarting over syscall at %#x %08lx\n",
+ arch->vex.guest_PC, (UWord)(*p));
+ vg_assert(0);
+ }
+ arch->vex.guest_PC -= 2;
+ }
+ }
#elif defined(VGP_x86_solaris)
arch->vex.guest_EIP -= 2; // sizeof(int $0x91) or sizeof(syscall)
UWord a3 );
extern SysRes VG_(mk_SysRes_mips64_linux)( ULong v0, ULong v1,
ULong a3 );
-extern SysRes VG_(mk_SysRes_nanomips_linux)( UWord a0, UWord a1 );
+extern SysRes VG_(mk_SysRes_nanomips_linux)( UWord a0);
extern SysRes VG_(mk_SysRes_x86_solaris) ( Bool isErr, UInt val, UInt val2 );
extern SysRes VG_(mk_SysRes_amd64_solaris) ( Bool isErr, ULong val, ULong val2 );
extern SysRes VG_(mk_SysRes_Error) ( UWord val );
/** Log2 of BITS_PER_UWORD. */
#if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm) \
- || defined(VGA_mips32) || (defined(VGA_mips64) && defined(VGABI_N32))
+ || defined(VGA_mips32) || defined(VGA_nanomips) \
+ || (defined(VGA_mips64) && defined(VGABI_N32))
#define BITS_PER_BITS_PER_UWORD 5
#elif defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
|| defined(VGA_s390x) || (defined(VGA_mips64) && !defined(VGABI_N32)) \
#define STACK_POINTER_OFFSET OFFSET_arm64_XSP
#elif defined(VGA_s390x)
#define STACK_POINTER_OFFSET OFFSET_s390x_r15
-#elif defined(VGA_mips32)
+#elif defined(VGA_mips32) || defined(VGA_nanomips)
#define STACK_POINTER_OFFSET OFFSET_mips32_r29
#elif defined(VGA_mips64)
#define STACK_POINTER_OFFSET OFFSET_mips64_r29
/* --------------------- mips32 --------------------- */
-# elif defined(VGA_mips32)
+# elif defined(VGA_mips32) || defined(VGA_nanomips)
# define GOF(_fieldname) \
(offsetof(VexGuestMIPS32State,guest_##_fieldname))
ppIRRegArray(arr);
VG_(printf)("\n");
tl_assert(0);
+/* --------------------- nanomips ------------------- */
+# elif defined(VGA_nanomips)
+ VG_(printf)("get_reg_array_equiv_int_type(nanomips): unhandled: ");
+ ppIRRegArray(arr);
+ VG_(printf)("\n");
+ tl_assert(0);
/* --------------------- mips64 --------------------- */
# elif defined(VGA_mips64)