Mark Wielaard 93919c
commit 9b28d5ecf72accc80d267a3fcfd0bd4212ff34d8
Mark Wielaard 93919c
Author: florian <florian@8f6e269a-dfd6-0310-a8e1-e2731360e62c>
Mark Wielaard 93919c
Date:   Tue Dec 10 16:51:15 2013 +0000
Mark Wielaard 93919c
Mark Wielaard 93919c
    The result of rounding a 128-bit BFP/DFP value to 32/64 bit needs to
Mark Wielaard 93919c
    be stored in a register pair. This constraint was not observed previously
Mark Wielaard 93919c
    and the result was stored in any FPR that happened to be chosen. If the
Mark Wielaard 93919c
    selected FPR was not identifying a proper FPR pair, a SIGILL was delivered.
Mark Wielaard 93919c
    Fixes BZ #328455.
Mark Wielaard 93919c
    
Mark Wielaard 93919c
    
Mark Wielaard 93919c
    git-svn-id: svn://svn.valgrind.org/vex/trunk@2801 8f6e269a-dfd6-0310-a8e1-e2731360e62c
Mark Wielaard 93919c
Mark Wielaard 93919c
diff --git a/priv/host_s390_defs.c b/priv/host_s390_defs.c
Mark Wielaard 93919c
index 0b61a5d..ce76285 100644
Mark Wielaard 93919c
--- a/VEX/priv/host_s390_defs.c
Mark Wielaard 93919c
+++ b/VEX/priv/host_s390_defs.c
Mark Wielaard 93919c
@@ -5861,7 +5861,6 @@ s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
Mark Wielaard 93919c
    } else {
Mark Wielaard 93919c
       /* From 16 bytes to smaller size */
Mark Wielaard 93919c
       vassert(is_valid_fp128_regpair(op_hi, op_lo));
Mark Wielaard 93919c
-      vassert(hregIsInvalid(dst_lo));
Mark Wielaard 93919c
    }
Mark Wielaard 93919c
 
Mark Wielaard 93919c
    insn->tag  = S390_INSN_BFP_CONVERT;
Mark Wielaard 93919c
@@ -5891,11 +5890,11 @@ s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
Mark Wielaard 93919c
 
Mark Wielaard 93919c
 
Mark Wielaard 93919c
 s390_insn *
Mark Wielaard 93919c
-s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst,
Mark Wielaard 93919c
-                              HReg op_hi, HReg op_lo,
Mark Wielaard 93919c
+s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
Mark Wielaard 93919c
+                              HReg dst_lo, HReg op_hi, HReg op_lo,
Mark Wielaard 93919c
                               s390_bfp_round_t rounding_mode)
Mark Wielaard 93919c
 {
Mark Wielaard 93919c
-   return s390_insn_bfp128_convert(size, tag, dst, INVALID_HREG, op_hi, op_lo,
Mark Wielaard 93919c
+   return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
Mark Wielaard 93919c
                                    rounding_mode);
Mark Wielaard 93919c
 }
Mark Wielaard 93919c
 
Mark Wielaard 93919c
@@ -6192,7 +6191,6 @@ s390_insn_dfp128_convert(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
Mark Wielaard 93919c
    } else {
Mark Wielaard 93919c
       /* From 16 bytes to smaller size */
Mark Wielaard 93919c
       vassert(is_valid_fp128_regpair(op_hi, op_lo));
Mark Wielaard 93919c
-      vassert(hregIsInvalid(dst_lo));
Mark Wielaard 93919c
    }
Mark Wielaard 93919c
 
Mark Wielaard 93919c
    insn->tag  = S390_INSN_DFP_CONVERT;
Mark Wielaard 93919c
@@ -6222,11 +6220,11 @@ s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
Mark Wielaard 93919c
 
Mark Wielaard 93919c
 
Mark Wielaard 93919c
 s390_insn *
Mark Wielaard 93919c
-s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst,
Mark Wielaard 93919c
-                              HReg op_hi, HReg op_lo,
Mark Wielaard 93919c
+s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
Mark Wielaard 93919c
+                              HReg dst_lo, HReg op_hi, HReg op_lo,
Mark Wielaard 93919c
                               s390_dfp_round_t rounding_mode)
Mark Wielaard 93919c
 {
Mark Wielaard 93919c
-   return s390_insn_dfp128_convert(size, tag, dst, INVALID_HREG, op_hi, op_lo,
Mark Wielaard 93919c
+   return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
Mark Wielaard 93919c
                                    rounding_mode);
Mark Wielaard 93919c
 }
Mark Wielaard 93919c
 
Mark Wielaard 93919c
diff --git a/priv/host_s390_defs.h b/priv/host_s390_defs.h
Mark Wielaard 93919c
index dafc8ae..5b6fc1f 100644
Mark Wielaard 93919c
--- a/VEX/priv/host_s390_defs.h
Mark Wielaard 93919c
+++ b/VEX/priv/host_s390_defs.h
Mark Wielaard 93919c
@@ -665,8 +665,8 @@ s390_insn *s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi,
Mark Wielaard 93919c
 s390_insn *s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t,
Mark Wielaard 93919c
                                        HReg dst_hi, HReg dst_lo, HReg op);
Mark Wielaard 93919c
 s390_insn *s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t,
Mark Wielaard 93919c
-                                         HReg dst, HReg op_hi, HReg op_lo,
Mark Wielaard 93919c
-                                         s390_bfp_round_t);
Mark Wielaard 93919c
+                                         HReg dst_hi, HReg dst_lo, HReg op_hi,
Mark Wielaard 93919c
+                                         HReg op_lo, s390_bfp_round_t);
Mark Wielaard 93919c
 s390_insn *s390_insn_dfp_binop(UChar size, s390_dfp_binop_t, HReg dst,
Mark Wielaard 93919c
                                HReg op2, HReg op3,
Mark Wielaard 93919c
                                s390_dfp_round_t rounding_mode);
Mark Wielaard 93919c
@@ -699,8 +699,8 @@ s390_insn *s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t, HReg dst,
Mark Wielaard 93919c
 s390_insn *s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t,
Mark Wielaard 93919c
                                        HReg dst_hi, HReg dst_lo, HReg op);
Mark Wielaard 93919c
 s390_insn *s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t,
Mark Wielaard 93919c
-                                         HReg dst, HReg op_hi, HReg op_lo,
Mark Wielaard 93919c
-                                         s390_dfp_round_t);
Mark Wielaard 93919c
+                                         HReg dst_hi, HReg dst_lo, HReg op_hi,
Mark Wielaard 93919c
+                                         HReg op_lo, s390_dfp_round_t);
Mark Wielaard 93919c
 s390_insn *s390_insn_dfp128_reround(UChar size, HReg dst_hi, HReg dst_lo,
Mark Wielaard 93919c
                                     HReg op2, HReg op3_hi, HReg op3_lo,
Mark Wielaard 93919c
                                     s390_dfp_round_t);
Mark Wielaard 93919c
diff --git a/priv/host_s390_isel.c b/priv/host_s390_isel.c
Mark Wielaard 93919c
index aaccff6..3662ffd 100644
Mark Wielaard 93919c
--- a/VEX/priv/host_s390_isel.c
Mark Wielaard 93919c
+++ b/VEX/priv/host_s390_isel.c
Mark Wielaard 93919c
@@ -1257,7 +1257,8 @@ s390_isel_int_expr_wrk(ISelEnv *env, IRExpr *expr)
Mark Wielaard 93919c
          addInstr(env, s390_insn_move(8, f15, op_lo));
Mark Wielaard 93919c
 
Mark Wielaard 93919c
          rounding_mode = get_bfp_rounding_mode(env, arg1);
Mark Wielaard 93919c
-         addInstr(env, s390_insn_bfp128_convert_from(size, conv, res, f13, f15,
Mark Wielaard 93919c
+         addInstr(env, s390_insn_bfp128_convert_from(size, conv, res,
Mark Wielaard 93919c
+                                                     INVALID_HREG, f13, f15,
Mark Wielaard 93919c
                                                      rounding_mode));
Mark Wielaard 93919c
          return res;
Mark Wielaard 93919c
       }
Mark Wielaard 93919c
@@ -1290,7 +1291,8 @@ s390_isel_int_expr_wrk(ISelEnv *env, IRExpr *expr)
Mark Wielaard 93919c
             addInstr(env, s390_insn_move(8, f15, op_lo));
Mark Wielaard 93919c
 
Mark Wielaard 93919c
             rounding_mode = get_dfp_rounding_mode(env, arg1);
Mark Wielaard 93919c
-            addInstr(env, s390_insn_dfp128_convert_from(size, dconv, res, f13,
Mark Wielaard 93919c
+            addInstr(env, s390_insn_dfp128_convert_from(size, dconv, res,
Mark Wielaard 93919c
+                                                        INVALID_HREG, f13,
Mark Wielaard 93919c
                                                         f15, rounding_mode));
Mark Wielaard 93919c
             return res;
Mark Wielaard 93919c
          }
Mark Wielaard 93919c
@@ -2455,7 +2457,7 @@ s390_isel_float_expr_wrk(ISelEnv *env, IRExpr *expr)
Mark Wielaard 93919c
 
Mark Wielaard 93919c
       case Iop_F128toF64:
Mark Wielaard 93919c
       case Iop_F128toF32: {
Mark Wielaard 93919c
-         HReg op_hi, op_lo, f13, f15;
Mark Wielaard 93919c
+         HReg op_hi, op_lo, f12, f13, f14, f15;
Mark Wielaard 93919c
          s390_bfp_round_t rounding_mode;
Mark Wielaard 93919c
 
Mark Wielaard 93919c
          conv = op == Iop_F128toF32 ? S390_BFP_F128_TO_F32
Mark Wielaard 93919c
@@ -2463,15 +2465,18 @@ s390_isel_float_expr_wrk(ISelEnv *env, IRExpr *expr)
Mark Wielaard 93919c
 
Mark Wielaard 93919c
          s390_isel_float128_expr(&op_hi, &op_lo, env, left);
Mark Wielaard 93919c
 
Mark Wielaard 93919c
-         /* We use non-virtual registers as pairs (f13, f15) */
Mark Wielaard 93919c
+         /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
Mark Wielaard 93919c
+         f12 = make_fpr(12);
Mark Wielaard 93919c
          f13 = make_fpr(13);
Mark Wielaard 93919c
+         f14 = make_fpr(14);
Mark Wielaard 93919c
          f15 = make_fpr(15);
Mark Wielaard 93919c
 
Mark Wielaard 93919c
          /* operand --> (f13, f15) */
Mark Wielaard 93919c
          addInstr(env, s390_insn_move(8, f13, op_hi));
Mark Wielaard 93919c
          addInstr(env, s390_insn_move(8, f15, op_lo));
Mark Wielaard 93919c
 
Mark Wielaard 93919c
-         dst = newVRegF(env);
Mark Wielaard 93919c
+         /* result --> (f12, f14) */
Mark Wielaard 93919c
+
Mark Wielaard 93919c
          /* load-rounded has a rounding mode field when the floating point
Mark Wielaard 93919c
             extension facility is installed. */
Mark Wielaard 93919c
          if (s390_host_has_fpext) {
Mark Wielaard 93919c
@@ -2480,8 +2485,12 @@ s390_isel_float_expr_wrk(ISelEnv *env, IRExpr *expr)
Mark Wielaard 93919c
             set_bfp_rounding_mode_in_fpc(env, irrm);
Mark Wielaard 93919c
             rounding_mode = S390_BFP_ROUND_PER_FPC;
Mark Wielaard 93919c
          }
Mark Wielaard 93919c
-         addInstr(env, s390_insn_bfp128_convert_from(size, conv, dst, f13, f15,
Mark Wielaard 93919c
-                                                     rounding_mode));
Mark Wielaard 93919c
+
Mark Wielaard 93919c
+         addInstr(env, s390_insn_bfp128_convert_from(size, conv, f12, f14,
Mark Wielaard 93919c
+                                                     f13, f15, rounding_mode));
Mark Wielaard 93919c
+         dst = newVRegF(env);
Mark Wielaard 93919c
+         addInstr(env, s390_insn_move(8, dst, f12));
Mark Wielaard 93919c
+
Mark Wielaard 93919c
          return dst;
Mark Wielaard 93919c
       }
Mark Wielaard 93919c
       }
Mark Wielaard 93919c
@@ -3044,22 +3053,25 @@ s390_isel_dfp_expr_wrk(ISelEnv *env, IRExpr *expr)
Mark Wielaard 93919c
       }
Mark Wielaard 93919c
 
Mark Wielaard 93919c
       case Iop_D128toD64: {
Mark Wielaard 93919c
-         HReg op_hi, op_lo, f13, f15;
Mark Wielaard 93919c
+         HReg op_hi, op_lo, f12, f13, f14, f15;
Mark Wielaard 93919c
          s390_dfp_round_t rounding_mode;
Mark Wielaard 93919c
 
Mark Wielaard 93919c
          conv = S390_DFP_D128_TO_D64;
Mark Wielaard 93919c
 
Mark Wielaard 93919c
          s390_isel_dfp128_expr(&op_hi, &op_lo, env, left);
Mark Wielaard 93919c
 
Mark Wielaard 93919c
-         /* We use non-virtual registers as pairs (f13, f15) */
Mark Wielaard 93919c
+         /* We use non-virtual registers as pairs (f13, f15) and (f12, f14) */
Mark Wielaard 93919c
+         f12 = make_fpr(12);
Mark Wielaard 93919c
          f13 = make_fpr(13);
Mark Wielaard 93919c
+         f14 = make_fpr(14);
Mark Wielaard 93919c
          f15 = make_fpr(15);
Mark Wielaard 93919c
 
Mark Wielaard 93919c
          /* operand --> (f13, f15) */
Mark Wielaard 93919c
          addInstr(env, s390_insn_move(8, f13, op_hi));
Mark Wielaard 93919c
          addInstr(env, s390_insn_move(8, f15, op_lo));
Mark Wielaard 93919c
 
Mark Wielaard 93919c
-         dst = newVRegF(env);
Mark Wielaard 93919c
+         /* result --> (f12, f14) */
Mark Wielaard 93919c
+ 
Mark Wielaard 93919c
          /* load-rounded has a rounding mode field when the floating point
Mark Wielaard 93919c
             extension facility is installed. */
Mark Wielaard 93919c
          if (s390_host_has_fpext) {
Mark Wielaard 93919c
@@ -3068,8 +3080,11 @@ s390_isel_dfp_expr_wrk(ISelEnv *env, IRExpr *expr)
Mark Wielaard 93919c
             set_dfp_rounding_mode_in_fpc(env, irrm);
Mark Wielaard 93919c
             rounding_mode = S390_DFP_ROUND_PER_FPC_0;
Mark Wielaard 93919c
          }
Mark Wielaard 93919c
-         addInstr(env, s390_insn_dfp128_convert_from(size, conv, dst, f13, f15,
Mark Wielaard 93919c
-                                                     rounding_mode));
Mark Wielaard 93919c
+         addInstr(env, s390_insn_dfp128_convert_from(size, conv, f12, f14,
Mark Wielaard 93919c
+                                                     f13, f15, rounding_mode));
Mark Wielaard 93919c
+         dst = newVRegF(env);
Mark Wielaard 93919c
+         addInstr(env, s390_insn_move(8, dst, f12));
Mark Wielaard 93919c
+
Mark Wielaard 93919c
          return dst;
Mark Wielaard 93919c
       }
Mark Wielaard 93919c