Adjust the vbit tester to deal with shift operations that require
an immediate constant as the shift amount. This is needed for
powerpc Iop_ShlD64 etc. What it basically means that we do not
iterate over the bits in the 2nd operand because there are no
V-bits to set. An immediate constant is always completely defined.
Fixes bugzilla #305948.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12969 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/NEWS b/NEWS
index 831a060..acd5ad1 100644
--- a/NEWS
+++ b/NEWS
@@ -45,6 +45,7 @@
 305690 m  [381] DRD reporting invalid semaphore when sem_trywait returns
                 EAGAIN or sem_timedwait returns ETIMEDOUT
 305926 m  [381] Invalid alignment checks for some AVX instructions
+305948    [390] ppc64: code generation for ShlD64 / ShrD64 asserts
 306054    [390] s390x: Condition code computation for convert-to-int/logical
 306310    [390] 3.8.0 release tarball missing some files
 n-i-bz m  [381] shmat of a segment > 4Gb does not work 
diff --git a/docs/internals/3_8_BUGSTATUS.txt b/docs/internals/3_8_BUGSTATUS.txt
index 2f81b5a..33e1d93 100644
--- a/docs/internals/3_8_BUGSTATUS.txt
+++ b/docs/internals/3_8_BUGSTATUS.txt
@@ -91,8 +91,6 @@
 
 305728  Add support for AVX2 instructions
 
-305948  ppc64: code generation for ShlD64 / ShrD64 asserts
-
 305957  m_debuginfo/d3basics.c:965 (vgModuleLocal_evaluate_GX):
         Assertion 'aMin == (Addr)0' failed.
 
diff --git a/memcheck/tests/vbit-test/binary.c b/memcheck/tests/vbit-test/binary.c
index 23eaaec..78afc9b 100644
--- a/memcheck/tests/vbit-test/binary.c
+++ b/memcheck/tests/vbit-test/binary.c
@@ -189,6 +189,10 @@
    }
 
    // 2nd (right) operand
+
+   /* If the operand is an immediate value, there are no v-bits to set. */
+   if (op->shift_amount_is_immediate) return;
+
    num_input_bits = bitsof_irtype(opnds[1].type);
 
    for (i = 0; i < num_input_bits; ++i) {
@@ -410,6 +414,11 @@
       that propagates to the output. Do this for all bits in each
       operand. */
    for (i = 0; i < 2; ++i) {
+
+      /* If this is a shift op that requires an immediate shift amount,
+         do not iterate the v-bits of the 2nd operand */
+      if (i == 1 && op->shift_amount_is_immediate) break;
+
       num_input_bits = bitsof_irtype(opnds[i].type);
       opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
       opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
@@ -418,6 +427,11 @@
          won't crash. */
       memset(&opnds[1].value, 0xff, sizeof opnds[1].value);
 
+      /* For immediate shift amounts choose a value of '1'. That should
+         not cause a problem. */
+      if (op->shift_amount_is_immediate)
+         opnds[1].value.u8 = 1;
+
       for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
          opnds[i].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[i].type));
 
diff --git a/memcheck/tests/vbit-test/irops.c b/memcheck/tests/vbit-test/irops.c
index 24e15cd..5423384 100644
--- a/memcheck/tests/vbit-test/irops.c
+++ b/memcheck/tests/vbit-test/irops.c
@@ -9,7 +9,7 @@
 /* The opcodes appear in the same order here as in libvex_ir.h
    That is not necessary but helpful when supporting a new architecture.
 */
-static const irop_t irops[] = {
+static irop_t irops[] = {
   { DEFOP(Iop_Add8,    UNDEF_LEFT), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0 },
   { DEFOP(Iop_Add16,   UNDEF_LEFT), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0 },
   { DEFOP(Iop_Add32,   UNDEF_LEFT), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 1, .ppc64 = 1, .ppc32 = 1, .mips32 = 1 },
@@ -479,10 +479,10 @@
   { DEFOP(Iop_SubD128,               UNDEF_ALL),  .s390x = 0, .ppc64 = 1, .ppc32 = 1 },
   { DEFOP(Iop_MulD128,               UNDEF_ALL),  .s390x = 0, .ppc64 = 1, .ppc32 = 1 },
   { DEFOP(Iop_DivD128,               UNDEF_ALL),  .s390x = 0, .ppc64 = 1, .ppc32 = 1 },
-  { DEFOP(Iop_ShlD64,                UNDEF_SHL),  .s390x = 0, .ppc64 = 0, .ppc32 = 0 }, // BZ #305948
-  { DEFOP(Iop_ShrD64,                UNDEF_SHR),  .s390x = 0, .ppc64 = 0, .ppc32 = 0 }, // BZ #305948
-  { DEFOP(Iop_ShlD128,               UNDEF_SHL),  .s390x = 0, .ppc64 = 0, .ppc32 = 0 }, // BZ #305948
-  { DEFOP(Iop_ShrD128,               UNDEF_SHR),  .s390x = 0, .ppc64 = 0, .ppc32 = 0 }, // BZ #305948
+  { DEFOP(Iop_ShlD64,                UNDEF_ALL),  .s390x = 0, .ppc64 = 1, .ppc32 = 1 },
+  { DEFOP(Iop_ShrD64,                UNDEF_ALL),  .s390x = 0, .ppc64 = 1, .ppc32 = 1 },
+  { DEFOP(Iop_ShlD128,               UNDEF_ALL),  .s390x = 0, .ppc64 = 1, .ppc32 = 1 },
+  { DEFOP(Iop_ShrD128,               UNDEF_ALL),  .s390x = 0, .ppc64 = 1, .ppc32 = 1 },
   { DEFOP(Iop_D32toD64,              UNDEF_ALL),  .s390x = 0, .ppc64 = 1, .ppc32 = 1 },
   { DEFOP(Iop_D64toD128,             UNDEF_ALL),  .s390x = 0, .ppc64 = 1, .ppc32 = 1 },
   { DEFOP(Iop_I64StoD128,            UNDEF_ALL),  .s390x = 0, .ppc64 = 1, .ppc32 = 1 },
@@ -859,13 +859,13 @@
 
 /* Return a descriptor for OP, iff it exists and it is implemented
    for the current architecture. */
-const irop_t *
+irop_t *
 get_irop(IROp op)
 {
    unsigned i;
 
    for (i = 0; i < sizeof irops / sizeof *irops; ++i) {
-      const irop_t *p = irops + i;
+      irop_t *p = irops + i;
       if (p->op == op) {
 #ifdef __s390x__
 #define S390X_FEATURES "../../../tests/s390x_features"
diff --git a/memcheck/tests/vbit-test/main.c b/memcheck/tests/vbit-test/main.c
index c510f3c..e9e2a26 100644
--- a/memcheck/tests/vbit-test/main.c
+++ b/memcheck/tests/vbit-test/main.c
@@ -50,6 +50,20 @@
 
 int verbose = 0;
 
+
+/* Certain IROps require special handling. */
+static void
+fixup_irops(void)
+{
+#ifdef __powerpc__
+   get_irop(Iop_ShlD64)->shift_amount_is_immediate = 1;
+   get_irop(Iop_ShrD64)->shift_amount_is_immediate = 1;
+   get_irop(Iop_ShlD128)->shift_amount_is_immediate = 1;
+   get_irop(Iop_ShrD128)->shift_amount_is_immediate = 1;
+#endif
+}
+
+
 int 
 main(int argc, char *argv[])
 {
@@ -75,6 +89,8 @@
 
    setbuf(stdout, NULL);  // make stdout unbuffered
 
+   fixup_irops();         // determine need for special handling
+
    // Iterate over all primops
    IROp first = Iop_INVALID + 1;
    IROp last  = Iop_LAST;
diff --git a/memcheck/tests/vbit-test/valgrind.c b/memcheck/tests/vbit-test/valgrind.c
index 976ae2c..6073fcb 100644
--- a/memcheck/tests/vbit-test/valgrind.c
+++ b/memcheck/tests/vbit-test/valgrind.c
@@ -27,6 +27,8 @@
 
    cb.num_operands = get_num_operands(op->op);
 
+   cb.shift_amount_is_immediate = op->shift_amount_is_immediate;
+
    return cb;
 }
 
diff --git a/memcheck/tests/vbit-test/vtest.h b/memcheck/tests/vbit-test/vtest.h
index 2550c9c..bb7b2fd 100644
--- a/memcheck/tests/vbit-test/vtest.h
+++ b/memcheck/tests/vbit-test/vtest.h
@@ -63,6 +63,7 @@
    IROp op;
    const char *name;
    undef_t     undef_kind;
+   int         shift_amount_is_immediate;
    // Indicate whether IROp can be tested on a particular architecture
    unsigned    s390x  : 1;
    unsigned    amd64  : 1;
@@ -95,7 +96,7 @@
 
 
 /* Function prototypes */
-const irop_t *get_irop(IROp);
+irop_t *get_irop(IROp);
 int  is_floating_point_op_with_rounding_mode(IROp);
 int  get_num_operands(IROp);