|
From: <sv...@va...> - 2010-08-22 12:21:23
|
Author: sewardj
Date: 2010-08-22 13:21:14 +0100 (Sun, 22 Aug 2010)
New Revision: 11283
Log:
Merge from branches/THUMB: m_machine changes needed for Thumb support:
* track guest_R15 -> guest_R15T renaming
* change min instruction size to 2
* tidy up VG_(get_IP) etc functions a bit
* add hwcaps detection code for ARM
Modified:
trunk/coregrind/m_machine.c
trunk/coregrind/pub_core_machine.h
trunk/include/pub_tool_machine.h
Modified: trunk/coregrind/m_machine.c
===================================================================
--- trunk/coregrind/m_machine.c 2010-08-22 12:16:25 UTC (rev 11282)
+++ trunk/coregrind/m_machine.c 2010-08-22 12:21:14 UTC (rev 11283)
@@ -43,45 +43,23 @@
#define STACK_PTR(regs) ((regs).vex.VG_STACK_PTR)
#define FRAME_PTR(regs) ((regs).vex.VG_FRAME_PTR)
-Addr VG_(get_SP) ( ThreadId tid )
-{
+Addr VG_(get_IP) ( ThreadId tid ) {
+ return INSTR_PTR( VG_(threads)[tid].arch );
+}
+Addr VG_(get_SP) ( ThreadId tid ) {
return STACK_PTR( VG_(threads)[tid].arch );
}
-
-Addr VG_(get_IP) ( ThreadId tid )
-{
- return INSTR_PTR( VG_(threads)[tid].arch );
-}
-
-Addr VG_(get_FP) ( ThreadId tid )
-{
+Addr VG_(get_FP) ( ThreadId tid ) {
return FRAME_PTR( VG_(threads)[tid].arch );
}
-Addr VG_(get_LR) ( ThreadId tid )
-{
-# if defined(VGA_ppc32) || defined(VGA_ppc64)
- return VG_(threads)[tid].arch.vex.guest_LR;
-# elif defined(VGA_x86) || defined(VGA_amd64)
- return 0;
-# elif defined(VGA_arm)
- return VG_(threads)[tid].arch.vex.guest_R14;
-# else
-# error "Unknown arch"
-# endif
+void VG_(set_IP) ( ThreadId tid, Addr ip ) {
+ INSTR_PTR( VG_(threads)[tid].arch ) = ip;
}
-
-void VG_(set_SP) ( ThreadId tid, Addr sp )
-{
+void VG_(set_SP) ( ThreadId tid, Addr sp ) {
STACK_PTR( VG_(threads)[tid].arch ) = sp;
}
-void VG_(set_IP) ( ThreadId tid, Addr ip )
-{
- INSTR_PTR( VG_(threads)[tid].arch ) = ip;
-}
-
-
void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
ThreadId tid )
{
@@ -106,7 +84,7 @@
regs->misc.PPC64.r_lr
= VG_(threads)[tid].arch.vex.guest_LR;
# elif defined(VGA_arm)
- regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_R15;
+ regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_R15T;
regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_R13;
regs->misc.ARM.r14
= VG_(threads)[tid].arch.vex.guest_R14;
@@ -385,13 +363,16 @@
#if defined(VGA_ppc64)
ULong VG_(machine_ppc64_has_VMX) = 0;
#endif
+#if defined(VGA_arm)
+Int VG_(machine_arm_archlevel) = 4;
+#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. */
-#if defined(VGA_ppc32) || defined(VGA_ppc64)
+#if defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_arm)
#include <setjmp.h> // For jmp_buf
static jmp_buf env_unsup_insn;
static void handler_unsup_insn ( Int x ) { __builtin_longjmp(env_unsup_insn,1); }
@@ -764,8 +745,110 @@
#elif defined(VGA_arm)
{
+ /* Same instruction set detection algorithm as for ppc32. */
+ vki_sigset_t saved_set, tmp_set;
+ vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
+ vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
+
+ volatile Bool have_VFP, have_VFP2, have_VFP3, have_NEON;
+ volatile Int archlevel;
+ Int r;
+
+ /* This is a kludge. Really we ought to back-convert saved_act
+ into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
+ since that's a no-op on all ppc64 platforms so far supported,
+ it's not worth the typing effort. At least include most basic
+ sanity check: */
+ vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
+
+ VG_(sigemptyset)(&tmp_set);
+ VG_(sigaddset)(&tmp_set, VKI_SIGILL);
+ VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
+
+ r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
+ vg_assert(r == 0);
+
+ r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
+ vg_assert(r == 0);
+ tmp_sigill_act = saved_sigill_act;
+
+ VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
+ tmp_sigfpe_act = saved_sigfpe_act;
+
+ /* NODEFER: signal handler does not return (from the kernel's point of
+ view), hence if it is to successfully catch a signal more than once,
+ we need the NODEFER flag. */
+ tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
+ tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
+ tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
+ tmp_sigill_act.ksa_handler = handler_unsup_insn;
+ VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
+
+ tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
+ tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
+ tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
+ tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
+ VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
+
+ /* VFP insns */
+ have_VFP = True;
+ if (__builtin_setjmp(env_unsup_insn)) {
+ have_VFP = False;
+ } else {
+ __asm__ __volatile__(".word 0xEEB02B42"); /* VMOV.F64 d2, d2 */
+ }
+ /* There are several generation of VFP extension but they differs very
+ little so for now we will not distinguish them. */
+ have_VFP2 = have_VFP;
+ have_VFP3 = have_VFP;
+
+ /* NEON insns */
+ have_NEON = True;
+ if (__builtin_setjmp(env_unsup_insn)) {
+ have_NEON = False;
+ } else {
+ __asm__ __volatile__(".word 0xF2244154"); /* VMOV q2, q2 */
+ }
+
+ /* ARM architecture level */
+ archlevel = 5; /* v5 will be base level */
+ if (archlevel < 7) {
+ archlevel = 7;
+ if (__builtin_setjmp(env_unsup_insn)) {
+ archlevel = 5;
+ } else {
+ __asm__ __volatile__(".word 0xF45FF000"); /* PLI [PC,#-0] */
+ }
+ }
+ if (archlevel < 6) {
+ archlevel = 6;
+ if (__builtin_setjmp(env_unsup_insn)) {
+ archlevel = 5;
+ } else {
+ __asm__ __volatile__(".word 0xE6822012"); /* PKHBT r2, r2, r2 */
+ }
+ }
+
+ VG_(convert_sigaction_fromK_to_toK)(&saved_sigill_act, &tmp_sigill_act);
+ VG_(convert_sigaction_fromK_to_toK)(&saved_sigfpe_act, &tmp_sigfpe_act);
+ VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
+ VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
+ VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
+
+ VG_(debugLog)(1, "machine", "ARMv%d VFP %d VFP2 %d VFP3 %d NEON %d\n",
+ archlevel, (Int)have_VFP, (Int)have_VFP2, (Int)have_VFP3,
+ (Int)have_NEON);
+
+ VG_(machine_arm_archlevel) = archlevel;
+
va = VexArchARM;
- vai.hwcaps = 0;
+
+ vai.hwcaps = VEX_ARM_ARCHLEVEL(archlevel);
+ if (have_VFP3) vai.hwcaps |= VEX_HWCAPS_ARM_VFP3;
+ if (have_VFP2) vai.hwcaps |= VEX_HWCAPS_ARM_VFP2;
+ if (have_VFP) vai.hwcaps |= VEX_HWCAPS_ARM_VFP;
+ if (have_NEON) vai.hwcaps |= VEX_HWCAPS_ARM_NEON;
+
return True;
}
Modified: trunk/coregrind/pub_core_machine.h
===================================================================
--- trunk/coregrind/pub_core_machine.h 2010-08-22 12:16:25 UTC (rev 11282)
+++ trunk/coregrind/pub_core_machine.h 2010-08-22 12:21:14 UTC (rev 11283)
@@ -96,7 +96,7 @@
# define VG_STACK_PTR guest_GPR1
# define VG_FRAME_PTR guest_GPR1 // No frame ptr for PPC
#elif defined(VGA_arm)
-# define VG_INSTR_PTR guest_R15
+# define VG_INSTR_PTR guest_R15T
# define VG_STACK_PTR guest_R13
# define VG_FRAME_PTR guest_R11
#else
@@ -110,6 +110,18 @@
//-------------------------------------------------------------
+// Guest state accessors that are not visible to tools. The only
+// ones that are visible are get_IP and get_SP.
+
+//Addr VG_(get_IP) ( ThreadId tid ); // in pub_tool_machine.h
+//Addr VG_(get_SP) ( ThreadId tid ); // in pub_tool_machine.h
+Addr VG_(get_FP) ( ThreadId tid );
+
+void VG_(set_IP) ( ThreadId tid, Addr encip );
+void VG_(set_SP) ( ThreadId tid, Addr sp );
+
+
+//-------------------------------------------------------------
// Get hold of the values needed for a stack unwind, for the specified
// (client) thread.
void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
@@ -198,6 +210,10 @@
extern ULong VG_(machine_ppc64_has_VMX);
#endif
+#if defined(VGA_arm)
+extern Int VG_(machine_arm_archlevel);
+#endif
+
#endif // __PUB_CORE_MACHINE_H
/*--------------------------------------------------------------------*/
Modified: trunk/include/pub_tool_machine.h
===================================================================
--- trunk/include/pub_tool_machine.h 2010-08-22 12:16:25 UTC (rev 11282)
+++ trunk/include/pub_tool_machine.h 2010-08-22 12:21:14 UTC (rev 11283)
@@ -59,7 +59,7 @@
// Supplement 1.7
#elif defined(VGP_arm_linux)
-# define VG_MIN_INSTR_SZB 4
+# define VG_MIN_INSTR_SZB 2
# define VG_MAX_INSTR_SZB 4
# define VG_CLREQ_SZB 28
# define VG_STACK_REDZONE_SZB 0
@@ -99,13 +99,11 @@
#endif
// Guest state accessors
-extern Addr VG_(get_SP) ( ThreadId tid );
-extern Addr VG_(get_IP) ( ThreadId tid );
-extern Addr VG_(get_FP) ( ThreadId tid );
-extern Addr VG_(get_LR) ( ThreadId tid );
+// Are mostly in the core_ header.
+// Only these two are available to tools.
+Addr VG_(get_IP) ( ThreadId tid );
+Addr VG_(get_SP) ( ThreadId tid );
-extern void VG_(set_SP) ( ThreadId tid, Addr sp );
-extern void VG_(set_IP) ( ThreadId tid, Addr ip );
// For get/set, 'area' is where the asked-for guest state will be copied
// into/from. If shadowNo == 0, the real (non-shadow) guest state is
|