|
From: <sv...@va...> - 2013-12-10 16:51:27
|
Author: florian
Date: Tue Dec 10 16:51:15 2013
New Revision: 2801
Log:
The result of rounding a 128-bit BFP/DFP value to 32/64 bit needs to
be stored in a register pair. This constraint was not observed previously
and the result was stored in any FPR that happened to be chosen. If the
selected FPR was not identifying a proper FPR pair, a SIGILL was delivered.
Fixes BZ #328455.
Modified:
trunk/priv/host_s390_defs.c
trunk/priv/host_s390_defs.h
trunk/priv/host_s390_isel.c
Modified: trunk/priv/host_s390_defs.c
==============================================================================
--- trunk/priv/host_s390_defs.c (original)
+++ trunk/priv/host_s390_defs.c Tue Dec 10 16:51:15 2013
@@ -5861,7 +5861,6 @@
} else {
/* From 16 bytes to smaller size */
vassert(is_valid_fp128_regpair(op_hi, op_lo));
- vassert(hregIsInvalid(dst_lo));
}
insn->tag = S390_INSN_BFP_CONVERT;
@@ -5891,11 +5890,11 @@
s390_insn *
-s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst,
- HReg op_hi, HReg op_lo,
+s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
+ HReg dst_lo, HReg op_hi, HReg op_lo,
s390_bfp_round_t rounding_mode)
{
- return s390_insn_bfp128_convert(size, tag, dst, INVALID_HREG, op_hi, op_lo,
+ return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
rounding_mode);
}
@@ -6192,7 +6191,6 @@
} else {
/* From 16 bytes to smaller size */
vassert(is_valid_fp128_regpair(op_hi, op_lo));
- vassert(hregIsInvalid(dst_lo));
}
insn->tag = S390_INSN_DFP_CONVERT;
@@ -6222,11 +6220,11 @@
s390_insn *
-s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst,
- HReg op_hi, HReg op_lo,
+s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
+ HReg dst_lo, HReg op_hi, HReg op_lo,
s390_dfp_round_t rounding_mode)
{
- return s390_insn_dfp128_convert(size, tag, dst, INVALID_HREG, op_hi, op_lo,
+ return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
rounding_mode);
}
Modified: trunk/priv/host_s390_defs.h
==============================================================================
--- trunk/priv/host_s390_defs.h (original)
+++ trunk/priv/host_s390_defs.h Tue Dec 10 16:51:15 2013
@@ -665,8 +665,8 @@
s390_insn *s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t,
HReg dst_hi, HReg dst_lo, HReg op);
s390_insn *s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t,
- HReg dst, HReg op_hi, HReg op_lo,
- s390_bfp_round_t);
+ HReg dst_hi, HReg dst_lo, HReg op_hi,
+ HReg op_lo, s390_bfp_round_t);
s390_insn *s390_insn_dfp_binop(UChar size, s390_dfp_binop_t, HReg dst,
HReg op2, HReg op3,
s390_dfp_round_t rounding_mode);
@@ -699,8 +699,8 @@
s390_insn *s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t,
HReg dst_hi, HReg dst_lo, HReg op);
s390_insn *s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t,
- HReg dst, HReg op_hi, HReg op_lo,
- s390_dfp_round_t);
+ HReg dst_hi, HReg dst_lo, HReg op_hi,
+ HReg op_lo, s390_dfp_round_t);
s390_insn *s390_insn_dfp128_reround(UChar size, HReg dst_hi, HReg dst_lo,
HReg op2, HReg op3_hi, HReg op3_lo,
s390_dfp_round_t);
Modified: trunk/priv/host_s390_isel.c
==============================================================================
--- trunk/priv/host_s390_isel.c (original)
+++ trunk/priv/host_s390_isel.c Tue Dec 10 16:51:15 2013
@@ -1257,7 +1257,8 @@
addInstr(env, s390_insn_move(8, f15, op_lo));
rounding_mode = get_bfp_rounding_mode(env, arg1);
- addInstr(env, s390_insn_bfp128_convert_from(size, conv, res, f13, f15,
+ addInstr(env, s390_insn_bfp128_convert_from(size, conv, res,
+ INVALID_HREG, f13, f15,
rounding_mode));
return res;
}
@@ -1290,7 +1291,8 @@
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, dconv, res, f13,
+ addInstr(env, s390_insn_dfp128_convert_from(size, dconv, res,
+ INVALID_HREG, f13,
f15, rounding_mode));
return res;
}
@@ -2455,7 +2457,7 @@
case Iop_F128toF64:
case Iop_F128toF32: {
- HReg op_hi, op_lo, f13, f15;
+ HReg op_hi, op_lo, f12, f13, f14, f15;
s390_bfp_round_t rounding_mode;
conv = op == Iop_F128toF32 ? S390_BFP_F128_TO_F32
@@ -2463,15 +2465,18 @@
s390_isel_float128_expr(&op_hi, &op_lo, env, left);
- /* We use non-virtual registers as pairs (f13, f15) */
+ /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
+ f12 = make_fpr(12);
f13 = make_fpr(13);
+ f14 = make_fpr(14);
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));
- dst = newVRegF(env);
+ /* result --> (f12, f14) */
+
/* load-rounded has a rounding mode field when the floating point
extension facility is installed. */
if (s390_host_has_fpext) {
@@ -2480,8 +2485,12 @@
set_bfp_rounding_mode_in_fpc(env, irrm);
rounding_mode = S390_BFP_ROUND_PER_FPC;
}
- addInstr(env, s390_insn_bfp128_convert_from(size, conv, dst, f13, f15,
- rounding_mode));
+
+ addInstr(env, s390_insn_bfp128_convert_from(size, conv, f12, f14,
+ f13, f15, rounding_mode));
+ dst = newVRegF(env);
+ addInstr(env, s390_insn_move(8, dst, f12));
+
return dst;
}
}
@@ -3044,22 +3053,25 @@
}
case Iop_D128toD64: {
- HReg op_hi, op_lo, f13, f15;
+ HReg op_hi, op_lo, f12, f13, f14, f15;
s390_dfp_round_t rounding_mode;
conv = S390_DFP_D128_TO_D64;
s390_isel_dfp128_expr(&op_hi, &op_lo, env, left);
- /* We use non-virtual registers as pairs (f13, f15) */
+ /* We use non-virtual registers as pairs (f13, f15) and (f12, f14) */
+ f12 = make_fpr(12);
f13 = make_fpr(13);
+ f14 = make_fpr(14);
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));
- dst = newVRegF(env);
+ /* result --> (f12, f14) */
+
/* load-rounded has a rounding mode field when the floating point
extension facility is installed. */
if (s390_host_has_fpext) {
@@ -3068,8 +3080,11 @@
set_dfp_rounding_mode_in_fpc(env, irrm);
rounding_mode = S390_DFP_ROUND_PER_FPC_0;
}
- addInstr(env, s390_insn_dfp128_convert_from(size, conv, dst, f13, f15,
- rounding_mode));
+ addInstr(env, s390_insn_dfp128_convert_from(size, conv, f12, f14,
+ f13, f15, rounding_mode));
+ dst = newVRegF(env);
+ addInstr(env, s390_insn_move(8, dst, f12));
+
return dst;
}
|