]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Merge from branches/THUMB: m_machine changes needed for Thumb support:
authorJulian Seward <jseward@acm.org>
Sun, 22 Aug 2010 12:21:14 +0000 (12:21 +0000)
committerJulian Seward <jseward@acm.org>
Sun, 22 Aug 2010 12:21:14 +0000 (12:21 +0000)
* 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

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11283

coregrind/m_machine.c
coregrind/pub_core_machine.h
include/pub_tool_machine.h

index 911c32eddd441c70c3c52bfcdcfbc5221edc0582..250a21c7ed4338cab469867e2a54656796a46d83 100644 (file)
 #define STACK_PTR(regs)    ((regs).vex.VG_STACK_PTR)
 #define FRAME_PTR(regs)    ((regs).vex.VG_FRAME_PTR)
 
-Addr VG_(get_SP) ( ThreadId tid )
-{
-   return STACK_PTR( VG_(threads)[tid].arch );
-}
-
-Addr VG_(get_IP) ( ThreadId tid )
-{
+Addr VG_(get_IP) ( ThreadId tid ) {
    return INSTR_PTR( VG_(threads)[tid].arch );
 }
-
-Addr VG_(get_FP) ( ThreadId tid )
-{
+Addr VG_(get_SP) ( ThreadId tid ) {
+   return STACK_PTR( VG_(threads)[tid].arch );
+}
+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 @@ void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
    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 @@ UInt VG_(machine_ppc32_has_VMX) = 0;
 #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 @@ Bool VG_(machine_get_hwcaps)( void )
 
 #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;
    }
 
index bd90fd4e6e102efdef631bc9addaa6d1840af8bb..91d048aabbd31404e7226350db86f3df32a1326c 100644 (file)
@@ -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
 #define VG_O_INSTR_PTR        (offsetof(VexGuestArchState, VG_INSTR_PTR))
 
 
+//-------------------------------------------------------------
+// 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.
@@ -198,6 +210,10 @@ extern UInt VG_(machine_ppc32_has_VMX);
 extern ULong VG_(machine_ppc64_has_VMX);
 #endif
 
+#if defined(VGA_arm)
+extern Int VG_(machine_arm_archlevel);
+#endif
+
 #endif   // __PUB_CORE_MACHINE_H
 
 /*--------------------------------------------------------------------*/
index daa7d8741292ce9c5f0113d1638f05eadae74464..c9d77dd72621aed34f1ea096a051c6e0d11dd7ae 100644 (file)
@@ -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
 #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