]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Hook the ppc32 stuff up to the revised CPU detection machinery, and
authorJulian Seward <jseward@acm.org>
Sun, 13 Nov 2005 00:30:22 +0000 (00:30 +0000)
committerJulian Seward <jseward@acm.org>
Sun, 13 Nov 2005 00:30:22 +0000 (00:30 +0000)
add a bunch of code to detect what the cpu can do at startup by
catching SIGILLs.  Shame PPC doesn't offer any sane mechanism for
finding out what instruction subsets the CPU is capable of (a la
x86/amd64 cpuid).

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

coregrind/m_dispatch/dispatch-ppc32-linux.S
coregrind/m_machine.c
coregrind/m_main.c
coregrind/m_transtab.c

index 6a34f0b5a804c6c9b2be26a862675312b4aca29d..e956a37759fd729453b633a30b1646174f858263 100644 (file)
@@ -178,8 +178,8 @@ VG_(run_innerloop):
 
         /* set host AltiVec control word to the default mode expected 
            by VEX-generated code. */
-        lis     3,VG_(have_altivec_ppc32)@ha
-        lwz     3,VG_(have_altivec_ppc32)@l(3)
+        lis     3,VG_(machine_ppc32_has_VMX)@ha
+        lwz     3,VG_(machine_ppc32_has_VMX)@l(3)
         cmplwi  3,0
         beq     L1
         /* generate vector {0x0,0x0,0x0,0x00010000} */
index c0342533f4080584354855c90e189444b5f8ae06..be3e0d283886095b4381d0d73c1bffe3ae59ea94 100644 (file)
@@ -34,6 +34,8 @@
 #include "pub_core_libcbase.h"
 #include "pub_core_machine.h"
 #include "pub_core_cpuid.h"
+#include "pub_core_libcsignal.h"   // for ppc32 messing with SIGILL
+
 
 #define INSTR_PTR(regs)    ((regs).vex.VG_INSTR_PTR)
 #define STACK_PTR(regs)    ((regs).vex.VG_STACK_PTR)
@@ -262,6 +264,12 @@ UInt VG_(machine_ppc32_has_VMX) = 0;
    record it.  To be called once at system startup.  Returns False if
    this a CPU incapable of running Valgrind. */
 
+#if defined(VGA_ppc32)
+#include <setjmp.h> // For jmp_buf
+static jmp_buf env_sigill;
+static void handler_sigill ( Int x ) { __builtin_longjmp(env_sigill,1); }
+#endif
+
 Bool VG_(machine_get_hwcaps)( void )
 {
    vg_assert(hwcaps_done == False);
@@ -317,25 +325,108 @@ Bool VG_(machine_get_hwcaps)( void )
    return True;
 
 #elif defined(VGA_ppc32)
-   va          = VexArchPPC32;
-   vai.subarch = VexSubArchPPC32_AV;
-   /* But we're not done yet: VG_(machine_ppc32_set_clszB) must be
-      called before we're ready to go. */
-   return True;
+   { /* ppc32 doesn't seem to have a sane way to find out what insn
+        sets the CPU supports.  So we have to arse around with
+        SIGILLs.  Yuck. */
+     vki_sigset_t         saved_set, tmp_set;
+     struct vki_sigaction saved_act, tmp_act;
+
+     Bool have_fp, have_vmx;
+
+     VG_(sigemptyset)(&tmp_set);
+     VG_(sigaddset)(&tmp_set, VKI_SIGILL);
+
+     VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
+
+     VG_(sigaction)(VKI_SIGILL, NULL, &saved_act);
+     tmp_act = saved_act;
+
+     tmp_act.sa_flags &= ~VKI_SA_RESETHAND;
+     tmp_act.sa_flags &= ~VKI_SA_SIGINFO;
+
+     tmp_act.ksa_handler = handler_sigill;
+     VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
+
+     have_fp = True;
+     if (__builtin_setjmp(env_sigill)) {
+        have_fp = False;
+     } else {
+        __asm__ __volatile__("fmr 0,0");
+     }
+
+     tmp_act.ksa_handler = handler_sigill;
+     VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
+
+     have_vmx = True;
+     if (__builtin_setjmp(env_sigill)) {
+        have_vmx = False;
+     } else {
+        __asm__ __volatile__("vor 0,0,0");
+     }
+
+     VG_(sigaction)(VKI_SIGILL, &saved_act, NULL);
+     VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
+
+     /* VG_(printf)("FP %d VMX %d\n", (Int)have_fp, (Int)have_vmx); */
+
+     /* We can only support 3 cases, not 4 (vmx but no fp).  So make
+       fp a prerequisite for vmx. */
+     if (have_vmx && !have_fp)
+        have_vmx = False;
+
+     VG_(machine_ppc32_has_FPU) = have_fp  ? 1 : 0;
+     VG_(machine_ppc32_has_VMX) = have_vmx ? 1 : 0;
+
+     va = VexArchPPC32;
+
+     if (have_fp == False && have_vmx == False) {
+        vai.subarch = VexSubArchPPC32_noAV; // _I
+     }
+     else if (have_fp == True && have_vmx == False) {
+        vai.subarch = VexSubArchPPC32_noAV; // _FI
+     }
+     else if (have_fp == True && have_vmx == True) {
+        vai.subarch = VexSubArchPPC32_AV; // _VFI
+     } else {
+        /* this can't happen. */
+        vg_assert2(0, "VG_(machine_get_hwcaps)(ppc32)");
+     }
+
+     /* But we're not done yet: VG_(machine_ppc32_set_clszB) must be
+        called before we're ready to go. */
+     return True;
+   }
 
 #else
 #  error "Unknown arch"
 #endif
 }
 
+/* Notify host cpu cache line size, as per above comment. */
+#if defined(VGA_ppc32)
+void VG_(machine_ppc32_set_clszB)( Int szB )
+{
+   vg_assert(hwcaps_done);
+
+   /* Either the value must not have been set yet (zero) or we can
+      tolerate it being set to the same value multiple times, as the
+      stack scanning logic in m_main is a bit stupid. */
+   vg_assert(vai.ppc32_cache_line_szB == 0
+             || vai.ppc32_cache_line_szB == szB);
+
+   vg_assert(szB == 32 || szB == 128);
+   vai.ppc32_cache_line_szB = szB;
+}
+#endif
+
 
 /* Fetch host cpu info, once established. */
 void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa,
                                    /*OUT*/VexArchInfo* pVai )
 {
    vg_assert(hwcaps_done);
-   *pVa = va;
-   *pVai = vai;
+   if (pVa)  *pVa  = va;
+   if (pVai) *pVai = vai;
 }
 
 
index 5423ce25619ec3cca7724048b27dded77f20c57b..795fd0be0c9d7ea9227e2bb548c8f9f668b7fae3 100644 (file)
@@ -545,15 +545,6 @@ Addr setup_client_stack( void*  init_sp,
             break;
 
          case AT_HWCAP:
-#           if defined(VGP_ppc32_linux)
-            /* Acquire altivecness info */
-            VG_(debugLog)(2, "main", "PPC32 hwcaps: 0x%x\n", 
-                                     (UInt)auxv->u.a_val);
-            if (auxv->u.a_val & 0x10000000)
-               VG_(have_altivec_ppc32) = 1;
-            VG_(debugLog)(2, "main", "PPC32 AltiVec support: %u\n", 
-                                     VG_(have_altivec_ppc32));
-#           endif
             break;
 
          case AT_DCACHEBSIZE:
@@ -562,7 +553,7 @@ Addr setup_client_stack( void*  init_sp,
 #           if defined(VGP_ppc32_linux)
             /* acquire cache info */
             if (auxv->u.a_val > 0) {
-               VG_(cache_line_size_ppc32) = auxv->u.a_val;
+               VG_(machine_ppc32_set_clszB)( auxv->u.a_val );
                VG_(debugLog)(2, "main", 
                                 "PPC32 cache line size %u (type %u)\n", 
                                 (UInt)auxv->u.a_val, (UInt)auxv->a_type );
index 9e99da3b530ca3c473e42820668d5da6648bfcbf..bf57d09f66068dea9987b0b68087495180acf0bb 100644 (file)
@@ -737,8 +737,12 @@ static void invalidate_icache ( void *ptr, Int nbytes )
 #  if defined(VGA_ppc32)
    Addr startaddr = (Addr) ptr;
    Addr endaddr   = startaddr + nbytes;
-   Addr cls       = VG_(cache_line_size_ppc32);
+   Addr cls;
    Addr addr;
+   VexArchInfo vai;
+
+   VG_(machine_get_VexArchInfo)( NULL, &vai );
+   cls = vai.ppc32_cache_line_szB;
 
    /* Stay sane .. */
    vg_assert(cls == 32 || cls == 128);