s390: Add support for DFP "shift significant" insns.
Based on patch by Maran Pakkirisamy (maranp@linux.vnet.ibm.com).
Part of fixing BZ 307113.


git-svn-id: svn://svn.valgrind.org/vex/trunk@2626 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/host_s390_isel.c b/priv/host_s390_isel.c
index bb5aef2..e585119 100644
--- a/priv/host_s390_isel.c
+++ b/priv/host_s390_isel.c
@@ -2443,12 +2443,50 @@
 
       /* --------- BINARY OP --------- */
    case Iex_Binop: {
+
       switch (expr->Iex.Binop.op) {
       case Iop_D64HLtoD128:
          *dst_hi = s390_isel_dfp_expr(env, expr->Iex.Binop.arg1);
          *dst_lo = s390_isel_dfp_expr(env, expr->Iex.Binop.arg2);
          return;
 
+      case Iop_ShlD128:
+      case Iop_ShrD128: {
+         HReg op1_hi, op1_lo, op2, f9, f11, f13, f15;
+         s390_dfp_intop_t intop;
+         IRExpr *left   = expr->Iex.Binop.arg1;
+         IRExpr *right  = expr->Iex.Binop.arg2;
+
+         switch (expr->Iex.Binop.op) {
+         case Iop_ShlD128: intop = S390_DFP_SHIFT_LEFT;  break;
+         case Iop_ShrD128: intop = S390_DFP_SHIFT_RIGHT; break;
+         default: goto irreducible;
+         }
+
+         /* We use non-virtual registers as pairs (f9, f11) and (f13, f15)) */
+         f9  = make_fpr(9); /* 128 bit dfp operand */
+         f11 = make_fpr(11);
+
+         f13 = make_fpr(13); /* 128 bit dfp destination */
+         f15 = make_fpr(15);
+
+         s390_isel_dfp128_expr(&op1_hi, &op1_lo, env, left);  /* dfp operand */
+         addInstr(env, s390_insn_move(8, f9,  op1_hi));
+         addInstr(env, s390_insn_move(8, f11, op1_lo));
+
+         op2 = s390_isel_int_expr(env, right);  /* int operand */
+
+         addInstr(env,
+                  s390_insn_dfp128_intop(16, intop, f13, f15, op2, f9, f11));
+
+         /* Move result to virtual destination register */
+         *dst_hi = newVRegF(env);
+         *dst_lo = newVRegF(env);
+         addInstr(env, s390_insn_move(8, *dst_hi, f13));
+         addInstr(env, s390_insn_move(8, *dst_lo, f15));
+         return;
+      }
+
       default:
          goto irreducible;
       }
@@ -2587,8 +2625,6 @@
                                                 rounding_mode));
             return dst;
          }
-      default:
-         goto irreducible;
 
       case Iop_D128toD64: {
          HReg op_hi, op_lo, f13, f15;
@@ -2620,6 +2656,30 @@
          return dst;
       }
 
+      case Iop_ShlD64:
+      case Iop_ShrD64: {
+         HReg op2;
+         HReg op3;
+         s390_dfp_intop_t intop;
+         IRExpr *op1   = expr->Iex.Binop.arg1;
+         IRExpr *shift = expr->Iex.Binop.arg2;
+
+         switch (expr->Iex.Binop.op) {
+         case Iop_ShlD64: intop = S390_DFP_SHIFT_LEFT;  break;
+         case Iop_ShrD64: intop = S390_DFP_SHIFT_RIGHT; break;
+         default: goto irreducible;
+         }
+
+         op2 = s390_isel_int_expr(env, shift);
+         op3 = s390_isel_dfp_expr(env, op1);
+         dst = newVRegF(env);
+
+         addInstr(env, s390_insn_dfp_intop(size, intop, dst, op2, op3));
+         return dst;
+      }
+
+      default:
+         goto irreducible;
       }
    }