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);