s390: Support insns to convert between DFP values and signed/unsigned
integers. Patch by Maran Pakkirisamy (maranp@linux.vnet.ibm.com).
Part of fixing BZ 307113.
git-svn-id: svn://svn.valgrind.org/vex/trunk@2632 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/host_s390_isel.c b/priv/host_s390_isel.c
index e585119..6142b27 100644
--- a/priv/host_s390_isel.c
+++ b/priv/host_s390_isel.c
@@ -1128,6 +1128,12 @@
case Iop_F128toI64S: conv = S390_BFP_F128_TO_I64; goto do_convert_128;
case Iop_F128toI32U: conv = S390_BFP_F128_TO_U32; goto do_convert_128;
case Iop_F128toI64U: conv = S390_BFP_F128_TO_U64; goto do_convert_128;
+ case Iop_D64toI32S: conv = S390_DFP_D64_TO_I32; goto do_convert_dfp;
+ case Iop_D64toI32U: conv = S390_DFP_D64_TO_U32; goto do_convert_dfp;
+ case Iop_D64toI64U: conv = S390_DFP_D64_TO_U64; goto do_convert_dfp;
+ case Iop_D128toI32S: conv = S390_DFP_D128_TO_I32; goto do_convert_dfp128;
+ case Iop_D128toI32U: conv = S390_DFP_D128_TO_U32; goto do_convert_dfp128;
+ case Iop_D128toI64U: conv = S390_DFP_D128_TO_U64; goto do_convert_dfp128;
do_convert: {
s390_bfp_round_t rounding_mode;
@@ -1162,6 +1168,39 @@
return res;
}
+ do_convert_dfp: {
+ s390_dfp_round_t rounding_mode;
+
+ res = newVRegI(env);
+ h1 = s390_isel_dfp_expr(env, arg2); /* Process operand */
+
+ rounding_mode = get_dfp_rounding_mode(env, arg1);
+ addInstr(env, s390_insn_dfp_convert(size, conv, res, h1,
+ rounding_mode));
+ return res;
+ }
+
+ do_convert_dfp128: {
+ s390_dfp_round_t rounding_mode;
+ HReg op_hi, op_lo, f13, f15;
+
+ res = newVRegI(env);
+ s390_isel_dfp128_expr(&op_hi, &op_lo, env, arg2); /* operand */
+
+ /* We use non-virtual registers r13 and r15 as pair */
+ f13 = make_fpr(13);
+ f15 = make_fpr(15);
+
+ /* operand --> (f13, f15) */
+ addInstr(env, s390_insn_move(8, f13, op_hi));
+ addInstr(env, s390_insn_move(8, f15, op_lo));
+
+ rounding_mode = get_dfp_rounding_mode(env, arg1);
+ addInstr(env, s390_insn_dfp128_convert_from(size, conv, res, f13,
+ f15, rounding_mode));
+ return res;
+ }
+
case Iop_8HLto16:
case Iop_16HLto32:
case Iop_32HLto64: {
@@ -2507,6 +2546,9 @@
switch (expr->Iex.Unop.op) {
case Iop_D64toD128: conv = S390_DFP_D64_TO_D128; goto convert_dfp;
+ case Iop_I32StoD128: conv = S390_DFP_I32_TO_D128; goto convert_int;
+ case Iop_I32UtoD128: conv = S390_DFP_U32_TO_D128; goto convert_int;
+ case Iop_I64UtoD128: conv = S390_DFP_U64_TO_D128; goto convert_int;
default:
goto irreducible;
}
@@ -2516,6 +2558,11 @@
addInstr(env, s390_insn_dfp128_convert_to(16, conv, f12, f14, op));
goto move_dst;
+ convert_int:
+ op = s390_isel_int_expr(env, left);
+ addInstr(env, s390_insn_dfp128_convert_to(16, conv, f12, f14, op));
+ goto move_dst;
+
move_dst:
/* Move result to virtual destination registers */
*dst_hi = newVRegF(env);
@@ -2605,11 +2652,16 @@
switch (op) {
case Iop_D64toD32: conv = S390_DFP_D64_TO_D32; goto convert_dfp;
+ case Iop_I64UtoD64: conv = S390_DFP_U64_TO_D64; goto convert_int;
convert_dfp:
h1 = s390_isel_dfp_expr(env, left);
goto convert;
+ convert_int:
+ h1 = s390_isel_int_expr(env, left);
+ goto convert;
+
convert: {
s390_dfp_round_t rounding_mode;
/* convert-from-fixed and load-rounded have a rounding mode field
@@ -2707,11 +2759,17 @@
switch (op) {
case Iop_D32toD64: conv = S390_DFP_D32_TO_D64; goto convert_dfp1;
+ case Iop_I32StoD64: conv = S390_DFP_I32_TO_D64; goto convert_int1;
+ case Iop_I32UtoD64: conv = S390_DFP_U32_TO_D64; goto convert_int1;
convert_dfp1:
h1 = s390_isel_dfp_expr(env, left);
goto convert1;
+ convert_int1:
+ h1 = s390_isel_int_expr(env, left);
+ goto convert1;
+
convert1:
dst = newVRegF(env);
/* No rounding mode is needed for these conversions. Just stick