s390: More prep work bfp reorg. In the future unary/binary/ternary
operations on bfp data will no longer require a rounding mode in the
s390_insn. Only type conversion operations need a rounding mode.
So in this patch S390_BFP_CONVERT is introduced and
S390_BFP128_CONVERT_TO/FROM are consolidated to S390_BFP128_CONVERT.
This also makes the representation of bfp and bfp128 symmetric.
s390_insn gets a new variant: s390_convert.
The type conversion ops get their own data type now: s390_conv_t
git-svn-id: svn://svn.valgrind.org/vex/trunk@2522 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/host_s390_isel.c b/priv/host_s390_isel.c
index 6616aed..42b92c8 100644
--- a/priv/host_s390_isel.c
+++ b/priv/host_s390_isel.c
@@ -785,7 +785,7 @@
{
IRType ty = typeOfIRExpr(env->type_env, expr);
UChar size;
- s390_bfp_unop_t bfpop;
+ s390_conv_t conv;
vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
@@ -911,18 +911,18 @@
return res;
}
- case Iop_F32toI32S: bfpop = S390_BFP_F32_TO_I32; goto do_convert;
- case Iop_F32toI64S: bfpop = S390_BFP_F32_TO_I64; goto do_convert;
- case Iop_F32toI32U: bfpop = S390_BFP_F32_TO_U32; goto do_convert;
- case Iop_F32toI64U: bfpop = S390_BFP_F32_TO_U64; goto do_convert;
- case Iop_F64toI32S: bfpop = S390_BFP_F64_TO_I32; goto do_convert;
- case Iop_F64toI64S: bfpop = S390_BFP_F64_TO_I64; goto do_convert;
- case Iop_F64toI32U: bfpop = S390_BFP_F64_TO_U32; goto do_convert;
- case Iop_F64toI64U: bfpop = S390_BFP_F64_TO_U64; goto do_convert;
- case Iop_F128toI32S: bfpop = S390_BFP_F128_TO_I32; goto do_convert_128;
- case Iop_F128toI64S: bfpop = S390_BFP_F128_TO_I64; goto do_convert_128;
- case Iop_F128toI32U: bfpop = S390_BFP_F128_TO_U32; goto do_convert_128;
- case Iop_F128toI64U: bfpop = S390_BFP_F128_TO_U64; goto do_convert_128;
+ case Iop_F32toI32S: conv = S390_BFP_F32_TO_I32; goto do_convert;
+ case Iop_F32toI64S: conv = S390_BFP_F32_TO_I64; goto do_convert;
+ case Iop_F32toI32U: conv = S390_BFP_F32_TO_U32; goto do_convert;
+ case Iop_F32toI64U: conv = S390_BFP_F32_TO_U64; goto do_convert;
+ case Iop_F64toI32S: conv = S390_BFP_F64_TO_I32; goto do_convert;
+ case Iop_F64toI64S: conv = S390_BFP_F64_TO_I64; goto do_convert;
+ case Iop_F64toI32U: conv = S390_BFP_F64_TO_U32; goto do_convert;
+ case Iop_F64toI64U: conv = S390_BFP_F64_TO_U64; goto do_convert;
+ case Iop_F128toI32S: conv = S390_BFP_F128_TO_I32; goto do_convert_128;
+ 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;
do_convert: {
s390_round_t rounding_mode;
@@ -931,7 +931,7 @@
h1 = s390_isel_float_expr(env, arg2); /* Process operand */
rounding_mode = decode_rounding_mode(arg1);
- addInstr(env, s390_insn_bfp_unop(size, bfpop, res, h1, rounding_mode));
+ addInstr(env, s390_insn_bfp_convert(size, conv, res, h1, rounding_mode));
return res;
}
@@ -951,7 +951,7 @@
addInstr(env, s390_insn_move(8, f15, op_lo));
rounding_mode = decode_rounding_mode(arg1);
- addInstr(env, s390_insn_bfp128_convert_from(size, bfpop, res, f13, f15,
+ addInstr(env, s390_insn_bfp128_convert_from(size, conv, res, f13, f15,
rounding_mode));
return res;
}
@@ -1665,6 +1665,7 @@
IRExpr *left = expr->Iex.Unop.arg;
s390_bfp_unop_t bfpop;
s390_round_t rounding_mode;
+ s390_conv_t conv;
HReg op_hi, op_lo, op, f12, f13, f14, f15;
/* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
@@ -1674,14 +1675,14 @@
f15 = make_fpr(15);
switch (expr->Iex.Unop.op) {
- case Iop_NegF128: bfpop = S390_BFP_NEG; goto float128_opnd;
- case Iop_AbsF128: bfpop = S390_BFP_ABS; goto float128_opnd;
- case Iop_I32StoF128: bfpop = S390_BFP_I32_TO_F128; goto convert_int;
- case Iop_I64StoF128: bfpop = S390_BFP_I64_TO_F128; goto convert_int;
- case Iop_I32UtoF128: bfpop = S390_BFP_U32_TO_F128; goto convert_int;
- case Iop_I64UtoF128: bfpop = S390_BFP_U64_TO_F128; goto convert_int;
- case Iop_F32toF128: bfpop = S390_BFP_F32_TO_F128; goto convert_float;
- case Iop_F64toF128: bfpop = S390_BFP_F64_TO_F128; goto convert_float;
+ case Iop_NegF128: bfpop = S390_BFP_NEG; goto float128_opnd;
+ case Iop_AbsF128: bfpop = S390_BFP_ABS; goto float128_opnd;
+ case Iop_I32StoF128: conv = S390_BFP_I32_TO_F128; goto convert_int;
+ case Iop_I64StoF128: conv = S390_BFP_I64_TO_F128; goto convert_int;
+ case Iop_I32UtoF128: conv = S390_BFP_U32_TO_F128; goto convert_int;
+ case Iop_I64UtoF128: conv = S390_BFP_U64_TO_F128; goto convert_int;
+ case Iop_F32toF128: conv = S390_BFP_F32_TO_F128; goto convert_float;
+ case Iop_F64toF128: conv = S390_BFP_F64_TO_F128; goto convert_float;
default:
goto irreducible;
}
@@ -1700,14 +1701,12 @@
convert_float:
op = s390_isel_float_expr(env, left);
- addInstr(env, s390_insn_bfp128_convert_to(16, bfpop, f12, f14,
- op));
+ addInstr(env, s390_insn_bfp128_convert_to(16, conv, f12, f14, op));
goto move_dst;
convert_int:
op = s390_isel_int_expr(env, left);
- addInstr(env, s390_insn_bfp128_convert_to(16, bfpop, f12, f14,
- op));
+ addInstr(env, s390_insn_bfp128_convert_to(16, conv, f12, f14, op));
goto move_dst;
move_dst:
@@ -1874,51 +1873,61 @@
/* --------- BINARY OP --------- */
case Iex_Binop: {
IROp op = expr->Iex.Binop.op;
+ IRExpr *irrm = expr->Iex.Binop.arg1;
IRExpr *left = expr->Iex.Binop.arg2;
HReg h1, dst;
- s390_bfp_unop_t bfpop;
s390_round_t rounding_mode;
- Int integer_operand;
-
- integer_operand = 1;
+ s390_conv_t conv;
switch (op) {
case Iop_SqrtF32:
case Iop_SqrtF64:
- bfpop = S390_BFP_SQRT;
- integer_operand = 0;
- break;
+ h1 = s390_isel_float_expr(env, left);
+ dst = newVRegF(env);
+ rounding_mode = decode_rounding_mode(irrm);
+ addInstr(env, s390_insn_bfp_unop(size, S390_BFP_SQRT, dst, h1,
+ rounding_mode));
+ return dst;
- case Iop_F64toF32:
- bfpop = S390_BFP_F64_TO_F32;
- integer_operand = 0;
- break;
+ case Iop_F64toF32: conv = S390_BFP_F64_TO_F32; goto convert_float;
+ case Iop_I32StoF32: conv = S390_BFP_I32_TO_F32; goto convert_int;
+ case Iop_I32UtoF32: conv = S390_BFP_U32_TO_F32; goto convert_int;
+ case Iop_I64StoF32: conv = S390_BFP_I64_TO_F32; goto convert_int;
+ case Iop_I64StoF64: conv = S390_BFP_I64_TO_F64; goto convert_int;
+ case Iop_I64UtoF32: conv = S390_BFP_U64_TO_F32; goto convert_int;
+ case Iop_I64UtoF64: conv = S390_BFP_U64_TO_F64; goto convert_int;
- case Iop_I32StoF32: bfpop = S390_BFP_I32_TO_F32; break;
- case Iop_I32UtoF32: bfpop = S390_BFP_U32_TO_F32; break;
- case Iop_I64StoF32: bfpop = S390_BFP_I64_TO_F32; break;
- case Iop_I64StoF64: bfpop = S390_BFP_I64_TO_F64; break;
- case Iop_I64UtoF32: bfpop = S390_BFP_U64_TO_F32; break;
- case Iop_I64UtoF64: bfpop = S390_BFP_U64_TO_F64; break;
+ convert_float:
+ h1 = s390_isel_float_expr(env, left);
+ goto convert;
+ convert_int:
+ h1 = s390_isel_int_expr(env, left);
+ goto convert;
+
+ convert:
+ dst = newVRegF(env);
+ rounding_mode = decode_rounding_mode(irrm);
+ addInstr(env, s390_insn_bfp_convert(size, conv, dst, h1,
+ rounding_mode));
+ return dst;
+
default:
goto irreducible;
case Iop_F128toF64:
case Iop_F128toF32: {
- HReg op_hi, op_lo, f12, f13, f14, f15;
+ HReg op_hi, op_lo, f13, f15;
- bfpop = op == Iop_F128toF32 ? S390_BFP_F128_TO_F32
- : S390_BFP_F128_TO_F64;
+ conv = op == Iop_F128toF32 ? S390_BFP_F128_TO_F32
+ : S390_BFP_F128_TO_F64;
- rounding_mode = decode_rounding_mode(expr->Iex.Binop.arg1);
+ rounding_mode = decode_rounding_mode(irrm);
- s390_isel_float128_expr(&op_hi, &op_lo, env, expr->Iex.Binop.arg2);
+ s390_isel_float128_expr(&op_hi, &op_lo, env, left);
- /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
- f12 = make_fpr(12);
+ /* We use non-virtual registers as pairs (f13, f15) */
f13 = make_fpr(13);
- f14 = make_fpr(14);
f15 = make_fpr(15);
/* operand --> (f13, f15) */
@@ -1926,26 +1935,11 @@
addInstr(env, s390_insn_move(8, f15, op_lo));
dst = newVRegF(env);
- addInstr(env, s390_insn_bfp128_unop(16, bfpop, f12, f14, f13, f15,
- rounding_mode));
-
- /* Move result to virtual destination registers */
- addInstr(env, s390_insn_move(8, dst, f12));
+ addInstr(env, s390_insn_bfp128_convert_from(16, conv, dst, f13, f15,
+ rounding_mode));
return dst;
}
}
-
- /* Process operand */
- if (integer_operand) {
- h1 = s390_isel_int_expr(env, left);
- } else {
- h1 = s390_isel_float_expr(env, left);
- }
-
- dst = newVRegF(env);
- rounding_mode = decode_rounding_mode(expr->Iex.Binop.arg1);
- addInstr(env, s390_insn_bfp_unop(size, bfpop, dst, h1, rounding_mode));
- return dst;
}
/* --------- UNARY OP --------- */
@@ -1953,7 +1947,10 @@
IROp op = expr->Iex.Unop.op;
IRExpr *left = expr->Iex.Unop.arg;
s390_bfp_unop_t bfpop;
- s390_round_t rounding_mode;
+ /* No rounding mode is needed for these conversions. Provide the
+ default rounding mode. It will not be used. */
+ s390_round_t rounding_mode = S390_ROUND_NEAREST_EVEN;
+ s390_conv_t conv;
HReg h1, dst;
if (op == Iop_F128HItoF64 || op == Iop_F128LOtoF64) {
@@ -1982,24 +1979,34 @@
break;
case Iop_AbsF32:
- case Iop_AbsF64: bfpop = S390_BFP_ABS; break;
- case Iop_I32StoF64: bfpop = S390_BFP_I32_TO_F64; break;
- case Iop_I32UtoF64: bfpop = S390_BFP_U32_TO_F64; break;
- case Iop_F32toF64: bfpop = S390_BFP_F32_TO_F64; break;
+ case Iop_AbsF64:
+ bfpop = S390_BFP_ABS;
+ break;
+
+ case Iop_I32StoF64: conv = S390_BFP_I32_TO_F64; goto convert_int1;
+ case Iop_I32UtoF64: conv = S390_BFP_U32_TO_F64; goto convert_int1;
+ case Iop_F32toF64: conv = S390_BFP_F32_TO_F64; goto convert_float1;
+
+ convert_float1:
+ h1 = s390_isel_float_expr(env, left);
+ goto convert1;
+
+ convert_int1:
+ h1 = s390_isel_int_expr(env, left);
+ goto convert1;
+
+ convert1:
+ dst = newVRegF(env);
+ addInstr(env, s390_insn_bfp_convert(size, conv, dst, h1, rounding_mode));
+ return dst;
+
default:
goto irreducible;
}
/* Process operand */
- if (op == Iop_I32StoF64 || op == Iop_I32UtoF64)
- h1 = s390_isel_int_expr(env, left);
- else if (bfpop == S390_BFP_NABS)
- h1 = s390_isel_float_expr(env, left->Iex.Unop.arg);
- else
- h1 = s390_isel_float_expr(env, left);
-
+ h1 = s390_isel_float_expr(env, left);
dst = newVRegF(env);
- rounding_mode = S390_ROUND_NEAREST_EVEN; /* will not be used later on */
addInstr(env, s390_insn_bfp_unop(size, bfpop, dst, h1, rounding_mode));
return dst;
}