Fix insn selection for Iop_Shr8/16 and Iop_Sar8/16 on s390.


git-svn-id: svn://svn.valgrind.org/vex/trunk@2472 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/host_s390_isel.c b/priv/host_s390_isel.c
index 6d01971..237b755 100644
--- a/priv/host_s390_isel.c
+++ b/priv/host_s390_isel.c
@@ -1105,7 +1105,28 @@
       h1   = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
       op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
       res  = newVRegI(env);
-      addInstr(env, s390_insn_move(size, res, h1));
+
+      /* As right shifts of one/two byte opreands are implemented using a
+         4-byte shift op, we first need to zero/sign-extend the shiftee. */
+      switch (expr->Iex.Binop.op) {
+      case Iop_Shr8:
+         insn = s390_insn_unop(4, S390_ZERO_EXTEND_8, res, s390_opnd_reg(h1));
+         break;
+      case Iop_Shr16:
+         insn = s390_insn_unop(4, S390_ZERO_EXTEND_16, res, s390_opnd_reg(h1));
+         break;
+      case Iop_Sar8:
+         insn = s390_insn_unop(4, S390_SIGN_EXTEND_8, res, s390_opnd_reg(h1));
+         break;
+      case Iop_Sar16:
+         insn = s390_insn_unop(4, S390_SIGN_EXTEND_16, res, s390_opnd_reg(h1));
+         break;
+      default:
+         insn = s390_insn_move(size, res, h1);
+         break;
+      }
+      addInstr(env, insn);
+
       insn = s390_insn_alu(size, opkind, res, op2);
 
       addInstr(env, insn);