Add Power PC ISA check to the vbit-test

The support for the Valgrind Iops is dependent on the Power processor
support for various instructions.  The instructions supported by a
given Power processor is based on the version of the ISA.  The patch
add a check to the vbit-test to ensure it does not try to test an Iop
that generates an instruction on the host that is not supported.

This patch fixes bugzilla 352765.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15653 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/memcheck/tests/vbit-test/irops.c b/memcheck/tests/vbit-test/irops.c
index d0e3b58..9e9f017 100644
--- a/memcheck/tests/vbit-test/irops.c
+++ b/memcheck/tests/vbit-test/irops.c
@@ -1143,6 +1143,38 @@
          return p->amd64 ? p : NULL;
 #endif
 #ifdef __powerpc__
+#define  MIN_POWER_ISA  "../../../tests/min_power_isa"
+
+         switch (op) {
+         case Iop_DivS64E:
+         case Iop_DivU64E:
+         case Iop_DivU32E:
+         case Iop_DivS32E:
+         case Iop_F64toI64U:
+         case Iop_F64toI32U:
+         case Iop_I64UtoF64:
+         case Iop_I64UtoF32:
+         case Iop_I64StoD64: {
+            int rc;
+            /* IROps require a processor that supports ISA 2.06 or newer */
+            rc = system(MIN_POWER_ISA " 2.06 ");
+            rc /= 256;
+            /* MIN_POWER_ISA returns 0 if underlying HW supports the
+             * specified ISA or newer. Returns 1 if the HW does not support
+             * the specified ISA.  Returns 2 on error.
+             */
+            if (rc == 1) return NULL;
+            if (rc > 2) {
+               panic(" ERROR, min_power_isa() return code is invalid.\n");
+            }
+         }
+         break;
+
+         /* Other */
+         default:
+         break;
+         }
+
 #ifdef __powerpc64__
          return p->ppc64 ? p : NULL;
 #else
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 708c28e..9c0cc3a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,6 +1,26 @@
 
 include $(top_srcdir)/Makefile.tool-tests.am
 
+if HAS_ISA_2_05
+ISA_2_05_FLAG = -DHAS_ISA_2_05
+else
+ISA_2_05_FLAG =
+endif
+
+if HAS_ISA_2_06
+ISA_2_06_FLAG = -DHAS_ISA_2_06
+else
+ISA_2_06_FLAG =
+endif
+
+if HAS_ISA_2_07
+ISA_2_07_FLAG = -DHAS_ISA_2_07
+else
+ISA_2_07_FLAG =
+endif
+
+min_power_isa_FLAGS = $(ISA_2_05_FLAG)  $(ISA_2_06_FLAG) $(ISA_2_07_FLAG)
+
 dist_noinst_SCRIPTS = \
 	check_headers_and_includes \
 	check_makefile_consistency \
@@ -29,7 +49,8 @@
 	s390x_features \
 	mips_features \
 	power_insn_available \
-	is_ppc64_BE
+	is_ppc64_BE \
+	min_power_isa
 
 AM_CFLAGS   += $(AM_FLAG_M3264_PRI)
 AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
@@ -40,3 +61,4 @@
 x86_amd64_features_CFLAGS = $(AM_CFLAGS)
 endif
 
+min_power_isa_CFLAGS = $(min_power_isa_FLAGS)
diff --git a/tests/min_power_isa.c b/tests/min_power_isa.c
new file mode 100644
index 0000000..efcf526
--- /dev/null
+++ b/tests/min_power_isa.c
@@ -0,0 +1,65 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* main() */
+int main(int argc, char **argv)
+{
+   /* This program is passed in a minimum ISA that the underlying hardwre
+    * needs to support.  If the HW supports this ISA or newer, return 0
+    * for supported.  Otherwise, return 1 for not supported.  Return 2 for
+    * usage error.
+    *
+    *  First argument is required, it must be an ISA version number.
+    *  Second argument "-debug" is optional.  If passed, then the defined ISA
+    *  values are printed.
+    */
+   char *min_isa;
+   int isa_level = 0;
+   int debug = 0;
+
+   /* set the isa_level set by the Make */
+
+   if ((argc == 3) && (strcmp(argv[2], "-debug") == 0)) {
+      debug = 1;
+
+   } else if (argc != 2) {
+      fprintf(stderr, "usage: min_power_ISA <ISA> [-debug]\n" );
+      exit(2);
+   }
+
+   min_isa = argv[1];
+
+#ifdef HAS_ISA_2_05
+   if (debug) printf("HAS_ISA_2_05 is set\n");
+   isa_level = 5;
+#endif
+
+#ifdef HAS_ISA_2_06
+   if (debug) printf("HAS_ISA_2_06 is set\n");
+   isa_level = 6;
+#endif
+
+#ifdef HAS_ISA_2_07
+   if (debug) printf("HAS_ISA_2_07 is set\n");
+   isa_level = 7;
+#endif
+
+   /* return 0 for supported (success), 1 for not supported (failure) */
+   if (strcmp (min_isa, "2.05") == 0) {
+      return !(isa_level >= 5);
+
+   } else if (strcmp (min_isa, "2.06") == 0) {
+      return !(isa_level >= 6);
+
+   } else if (strcmp (min_isa, "2.07") == 0) {
+      return !(isa_level >= 7);
+
+   } else {
+      fprintf(stderr, "ERROR: invalid ISA version.  Valid versions numbers are:\n" );
+      fprintf(stderr, "       2.05, 2.06, 2.07\n" );
+      exit(2);
+   }
+
+   return 1;
+}