From: Florian Krohm Date: Fri, 8 Feb 2013 23:32:54 +0000 (+0000) Subject: s390: Support these DFP insns: CDGTRA, CXGTR, CGXTR, and CGDTR. X-Git-Tag: svn/VALGRIND_3_9_0^2~114 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1bde52db23b2184a5e0a049f8ee55ad38c91de90;p=thirdparty%2Fvalgrind.git s390: Support these DFP insns: CDGTRA, CXGTR, CGXTR, and CGDTR. Patch by Maran Pakkirisamy (maranp@linux.vnet.ibm.com). Part of fixing BZ #307113. git-svn-id: svn://svn.valgrind.org/vex/trunk@2680 --- diff --git a/VEX/priv/guest_s390_defs.h b/VEX/priv/guest_s390_defs.h index 642118fee5..b8ed91d056 100644 --- a/VEX/priv/guest_s390_defs.h +++ b/VEX/priv/guest_s390_defs.h @@ -150,7 +150,9 @@ enum { S390_CC_OP_DFP_64_TO_UINT_64 = 52, S390_CC_OP_DFP_128_TO_UINT_64 = 53, S390_CC_OP_DFP_64_TO_INT_32 = 54, - S390_CC_OP_DFP_128_TO_INT_32 = 55 + S390_CC_OP_DFP_128_TO_INT_32 = 55, + S390_CC_OP_DFP_64_TO_INT_64 = 56, + S390_CC_OP_DFP_128_TO_INT_64 = 57 }; /*------------------------------------------------------------*/ diff --git a/VEX/priv/guest_s390_helpers.c b/VEX/priv/guest_s390_helpers.c index b13971456f..8be925af9c 100644 --- a/VEX/priv/guest_s390_helpers.c +++ b/VEX/priv/guest_s390_helpers.c @@ -1690,6 +1690,13 @@ s390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep) return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb9490000", cc_dep1, cc_dep2, cc_ndep); + case S390_CC_OP_DFP_64_TO_INT_64: /* CGDTR */ + return S390_CC_FOR_DFP_CONVERT(".insn rrf,0xb3e10000", cc_dep1, cc_dep2); + + case S390_CC_OP_DFP_128_TO_INT_64: /* CGXTR */ + return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb3e90000", cc_dep1, + cc_dep2, cc_ndep); + case S390_CC_OP_DFP_64_TO_UINT_32: /* CLFDTR */ return S390_CC_FOR_DFP_UCONVERT(".insn rrf,0xb9430000", cc_dep1, cc_dep2); diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 377b5b68ac..25cfb98874 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -9334,6 +9334,39 @@ s390_irgen_CXFTR(UChar m3 __attribute__((unused)), return "cxftr"; } +static const HChar * +s390_irgen_CDGTRA(UChar m3, UChar m4 __attribute__((unused)), + UChar r1, UChar r2) +{ + IRTemp op2 = newTemp(Ity_I64); + + vassert(s390_host_has_dfp); + if (! s390_host_has_fpext && m3 != S390_DFP_ROUND_PER_FPC_0) { + emulation_warning(EmWarn_S390X_fpext_rounding); + m3 = S390_DFP_ROUND_PER_FPC_0; + } + + assign(op2, get_gpr_dw0(r2)); + put_dpr_dw0(r1, binop(Iop_I64StoD64, mkexpr(encode_dfp_rounding_mode(m3)), + mkexpr(op2))); + + return (m3 == 0) ? "cdgtr" : "cdgtra"; +} + +static const HChar * +s390_irgen_CXGTR(UChar m3 __attribute__((unused)), + UChar m4 __attribute__((unused)), UChar r1, UChar r2) +{ + IRTemp op2 = newTemp(Ity_I64); + + vassert(s390_host_has_dfp); + + assign(op2, get_gpr_dw0(r2)); + put_dpr_pair(r1, unop(Iop_I64StoD128, mkexpr(op2))); + + return "cxgtr"; +} + static const HChar * s390_irgen_CDLFTR(UChar m3 __attribute__((unused)), UChar m4 __attribute__((unused)), UChar r1, UChar r2) @@ -9448,6 +9481,51 @@ s390_irgen_CFXTR(UChar m3, UChar m4 __attribute__((unused)), return "cfxtr"; } +static const HChar * +s390_irgen_CGDTR(UChar m3, UChar m4 __attribute__((unused)), + UChar r1, UChar r2) +{ + IRTemp op = newTemp(Ity_D64); + IRTemp rounding_mode = encode_dfp_rounding_mode(m3); + + vassert(s390_host_has_dfp); + + /* If fpext is not installed and m3 is in 1:7, + rounding mode performed is unpredictable */ + if (! s390_host_has_fpext && m3 > 0 && m3 < 8) { + emulation_warning(EmWarn_S390X_fpext_rounding); + m3 = S390_DFP_ROUND_PER_FPC_0; + } + + assign(op, get_dpr_dw0(r2)); + put_gpr_dw0(r1, binop(Iop_D64toI64S, mkexpr(rounding_mode), mkexpr(op))); + s390_cc_thunk_putFZ(S390_CC_OP_DFP_64_TO_INT_64, op, rounding_mode); + + return "cgdtr"; +} + +static const HChar * +s390_irgen_CGXTR(UChar m3, UChar m4 __attribute__((unused)), + UChar r1, UChar r2) +{ + IRTemp op = newTemp(Ity_D128); + IRTemp rounding_mode = encode_dfp_rounding_mode(m3); + + vassert(s390_host_has_dfp); + + /* If fpext is not installed and m3 is in 1:7, + rounding mode performed is unpredictable */ + if (! s390_host_has_fpext && m3 > 0 && m3 < 8) { + emulation_warning(EmWarn_S390X_fpext_rounding); + m3 = S390_DFP_ROUND_PER_FPC_0; + } + assign(op, get_dpr_pair(r2)); + put_gpr_dw0(r1, binop(Iop_D128toI64S, mkexpr(rounding_mode), mkexpr(op))); + s390_cc_thunk_put1d128Z(S390_CC_OP_DFP_128_TO_INT_64, op, rounding_mode); + + return "cgxtr"; +} + static const HChar * s390_irgen_CEDTR(UChar r1, UChar r2) { @@ -13959,7 +14037,9 @@ s390_decode_4byte_and_irgen(UChar *bytes) ovl.fmt.RRE.r2); goto ok; case 0xb3df: /* FIXTR */ goto unimplemented; case 0xb3e0: /* KDTR */ goto unimplemented; - case 0xb3e1: /* CGDTR */ goto unimplemented; + case 0xb3e1: s390_format_RRF_UURF(s390_irgen_CGDTR, ovl.fmt.RRF2.m3, + ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1, + ovl.fmt.RRF2.r2); goto ok; case 0xb3e2: /* CUDTR */ goto unimplemented; case 0xb3e3: /* CSDTR */ goto unimplemented; case 0xb3e4: s390_format_RRE_FF(s390_irgen_CDTR, ovl.fmt.RRE.r1, @@ -13968,7 +14048,9 @@ s390_decode_4byte_and_irgen(UChar *bytes) case 0xb3e7: s390_format_RRE_RF(s390_irgen_ESDTR, ovl.fmt.RRE.r1, ovl.fmt.RRE.r2); goto ok; case 0xb3e8: /* KXTR */ goto unimplemented; - case 0xb3e9: /* CGXTR */ goto unimplemented; + case 0xb3e9: s390_format_RRF_UURF(s390_irgen_CGXTR, ovl.fmt.RRF2.m3, + ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1, + ovl.fmt.RRF2.r2); goto ok; case 0xb3ea: /* CUXTR */ goto unimplemented; case 0xb3eb: /* CSXTR */ goto unimplemented; case 0xb3ec: s390_format_RRE_FF(s390_irgen_CXTR, ovl.fmt.RRE.r1, @@ -13976,7 +14058,9 @@ s390_decode_4byte_and_irgen(UChar *bytes) case 0xb3ed: /* EEXTR */ goto unimplemented; case 0xb3ef: s390_format_RRE_RF(s390_irgen_ESXTR, ovl.fmt.RRE.r1, ovl.fmt.RRE.r2); goto ok; - case 0xb3f1: /* CDGTR */ goto unimplemented; + case 0xb3f1: s390_format_RRF_UUFR(s390_irgen_CDGTRA, ovl.fmt.RRF2.m3, + ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1, + ovl.fmt.RRF2.r2); goto ok; case 0xb3f2: /* CDUTR */ goto unimplemented; case 0xb3f3: /* CDSTR */ goto unimplemented; case 0xb3f4: s390_format_RRE_FF(s390_irgen_CEDTR, ovl.fmt.RRE.r1, @@ -13984,7 +14068,9 @@ s390_decode_4byte_and_irgen(UChar *bytes) case 0xb3f5: /* QADTR */ goto unimplemented; case 0xb3f6: /* IEDTR */ goto unimplemented; case 0xb3f7: /* RRDTR */ goto unimplemented; - case 0xb3f9: /* CXGTR */ goto unimplemented; + case 0xb3f9: s390_format_RRF_UUFR(s390_irgen_CXGTR, ovl.fmt.RRF2.m3, + ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1, + ovl.fmt.RRF2.r2); goto ok; case 0xb3fa: /* CXUTR */ goto unimplemented; case 0xb3fb: /* CXSTR */ goto unimplemented; case 0xb3fc: s390_format_RRE_FF(s390_irgen_CEXTR, ovl.fmt.RRE.r1, diff --git a/VEX/priv/host_s390_defs.c b/VEX/priv/host_s390_defs.c index 1ff90cdd1e..13c1b374a3 100644 --- a/VEX/priv/host_s390_defs.c +++ b/VEX/priv/host_s390_defs.c @@ -4156,6 +4156,41 @@ s390_emit_CXTR(UChar *p, UChar r1, UChar r2) } +static UChar * +s390_emit_CDGTRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) +{ + vassert(s390_host_has_dfp); + vassert(m4 == 0); + vassert(m3 == 0 || s390_host_has_fpext); + + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { + if (m3 == 0) + s390_disasm(ENC3(MNM, FPR, GPR), "cdgtr", r1, r2); + else + s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdgtra", r1, m3, r2, m4); + } + + return emit_RRF2(p, 0xb3f10000, m3, m4, r1, r2); +} + + +static UChar * +s390_emit_CXGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) +{ + vassert(s390_host_has_dfp); + vassert(m4 == 0); + /* rounding mode m3 is not considered, as the corresponding + IRop (Iop_I64StoD128) does not take rounding mode. */ + vassert(m3 == 0); + + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { + s390_disasm(ENC3(MNM, FPR, GPR), "cxgtr", r1, r2); + } + + return emit_RRF2(p, 0xb3f90000, m3, m4, r1, r2); +} + + static UChar * s390_emit_CDFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) { @@ -4292,6 +4327,36 @@ s390_emit_CFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) } +static UChar * +s390_emit_CGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) +{ + vassert(s390_host_has_dfp); + vassert(m4 == 0); + vassert(s390_host_has_fpext || m3 < 1 || m3 > 7); + + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { + s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdtr", r1, m3, r2); + } + + return emit_RRF2(p, 0xb3e10000, m3, m4, r1, r2); +} + + +static UChar * +s390_emit_CGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) +{ + vassert(s390_host_has_dfp); + vassert(m4 == 0); + vassert(s390_host_has_fpext || m3 < 1 || m3 > 7); + + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { + s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxtr", r1, m3, r2); + } + + return emit_RRF2(p, 0xb3e90000, m3, m4, r1, r2); +} + + static UChar * s390_emit_CLFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) { @@ -6586,13 +6651,17 @@ s390_insn_as_string(const s390_insn *insn) case S390_DFP_D64_TO_D128: case S390_DFP_D128_TO_D64: op = "v-d2d"; break; case S390_DFP_I32_TO_D64: - case S390_DFP_I32_TO_D128: op = "v-i2d"; break; + case S390_DFP_I32_TO_D128: + case S390_DFP_I64_TO_D64: + case S390_DFP_I64_TO_D128: op = "v-i2d"; break; case S390_DFP_U32_TO_D64: case S390_DFP_U32_TO_D128: case S390_DFP_U64_TO_D64: case S390_DFP_U64_TO_D128: op = "v-u2d"; break; case S390_DFP_D64_TO_I32: - case S390_DFP_D128_TO_I32: op = "v-d2i"; break; + case S390_DFP_D128_TO_I32: + case S390_DFP_D64_TO_I64: + case S390_DFP_D128_TO_I64: op = "v-d2i"; break; case S390_DFP_D64_TO_U32: case S390_DFP_D64_TO_U64: case S390_DFP_D128_TO_U32: @@ -6742,13 +6811,17 @@ s390_insn_as_string(const s390_insn *insn) case S390_DFP_U32_TO_D128: p += vex_sprintf(p, "4 -> "); goto common; case S390_DFP_D64_TO_D32: case S390_DFP_D64_TO_D128: + case S390_DFP_I64_TO_D64: + case S390_DFP_I64_TO_D128: case S390_DFP_U64_TO_D64: case S390_DFP_U64_TO_D128: case S390_DFP_D64_TO_I32: + case S390_DFP_D64_TO_I64: case S390_DFP_D64_TO_U32: case S390_DFP_D64_TO_U64: p += vex_sprintf(p, "8 -> "); goto common; case S390_DFP_D128_TO_D64: case S390_DFP_D128_TO_I32: + case S390_DFP_D128_TO_I64: case S390_DFP_D128_TO_U32: case S390_DFP_D128_TO_U64: p += vex_sprintf(p, "16 -> "); goto common; default: @@ -8890,6 +8963,8 @@ s390_insn_dfp_convert_emit(UChar *buf, const s390_insn *insn) /* Convert to fixed */ case S390_DFP_D64_TO_I32: return s390_emit_CFDTR(buf, m3, m4, r1, r2); case S390_DFP_D128_TO_I32: return s390_emit_CFXTR(buf, m3, m4, r1, r2); + case S390_DFP_D64_TO_I64: return s390_emit_CGDTR(buf, m3, m4, r1, r2); + case S390_DFP_D128_TO_I64: return s390_emit_CGXTR(buf, m3, m4, r1, r2); /* Convert to logical */ case S390_DFP_D64_TO_U32: return s390_emit_CLFDTR(buf, m3, m4, r1, r2); @@ -8900,6 +8975,8 @@ s390_insn_dfp_convert_emit(UChar *buf, const s390_insn *insn) /* Convert from fixed */ case S390_DFP_I32_TO_D64: return s390_emit_CDFTR(buf, 0, m4, r1, r2); case S390_DFP_I32_TO_D128: return s390_emit_CXFTR(buf, 0, m4, r1, r2); + case S390_DFP_I64_TO_D64: return s390_emit_CDGTRA(buf, m3, m4, r1, r2); + case S390_DFP_I64_TO_D128: return s390_emit_CXGTR(buf, 0, m4, r1, r2); /* Convert from logical */ case S390_DFP_U32_TO_D64: return s390_emit_CDLFTR(buf, m3, m4, r1, r2); diff --git a/VEX/priv/host_s390_defs.h b/VEX/priv/host_s390_defs.h index 5fb5a0d3c6..e13893da6b 100644 --- a/VEX/priv/host_s390_defs.h +++ b/VEX/priv/host_s390_defs.h @@ -249,14 +249,18 @@ typedef enum { S390_DFP_D128_TO_D64, S390_DFP_I32_TO_D64, S390_DFP_I32_TO_D128, + S390_DFP_I64_TO_D64, + S390_DFP_I64_TO_D128, S390_DFP_U32_TO_D64, S390_DFP_U32_TO_D128, S390_DFP_U64_TO_D64, S390_DFP_U64_TO_D128, S390_DFP_D64_TO_I32, + S390_DFP_D64_TO_I64, S390_DFP_D64_TO_U32, S390_DFP_D64_TO_U64, S390_DFP_D128_TO_I32, + S390_DFP_D128_TO_I64, S390_DFP_D128_TO_U32, S390_DFP_D128_TO_U64 } s390_dfp_conv_t; diff --git a/VEX/priv/host_s390_isel.c b/VEX/priv/host_s390_isel.c index 1c27570246..cfca458c3a 100644 --- a/VEX/priv/host_s390_isel.c +++ b/VEX/priv/host_s390_isel.c @@ -1135,9 +1135,11 @@ s390_isel_int_expr_wrk(ISelEnv *env, IRExpr *expr) case Iop_F128toI64U: conv = S390_BFP_F128_TO_U64; goto do_convert_128; case Iop_D64toI32S: dconv = S390_DFP_D64_TO_I32; goto do_convert_dfp; + case Iop_D64toI64S: dconv = S390_DFP_D64_TO_I64; goto do_convert_dfp; case Iop_D64toI32U: dconv = S390_DFP_D64_TO_U32; goto do_convert_dfp; case Iop_D64toI64U: dconv = S390_DFP_D64_TO_U64; goto do_convert_dfp; case Iop_D128toI32S: dconv = S390_DFP_D128_TO_I32; goto do_convert_dfp128; + case Iop_D128toI64S: dconv = S390_DFP_D128_TO_I64; goto do_convert_dfp128; case Iop_D128toI32U: dconv = S390_DFP_D128_TO_U32; goto do_convert_dfp128; case Iop_D128toI64U: dconv = S390_DFP_D128_TO_U64; goto do_convert_dfp128; @@ -2520,18 +2522,16 @@ s390_isel_dfp128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env, case Iex_Unop: { IRExpr *left = expr->Iex.Unop.arg; s390_dfp_conv_t conv; - // HReg op, f12, f13, f14, f15; HReg op, f12, f14; - /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */ + /* We use non-virtual registers as pairs (f12, f14)) */ f12 = make_fpr(12); - // f13 = make_fpr(13); f14 = make_fpr(14); - // f15 = make_fpr(15); 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_I64StoD128: conv = S390_DFP_I64_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: @@ -2637,6 +2637,7 @@ s390_isel_dfp_expr_wrk(ISelEnv *env, IRExpr *expr) switch (op) { case Iop_D64toD32: conv = S390_DFP_D64_TO_D32; goto convert_dfp; + case Iop_I64StoD64: conv = S390_DFP_I64_TO_D64; goto convert_int; case Iop_I64UtoD64: conv = S390_DFP_U64_TO_D64; goto convert_int; convert_dfp: