Patch by Maran Pakkirisamy (maranp@linux.vnet.ibm.com).
Part of fixing BZ #307113.
git-svn-id: svn://svn.valgrind.org/vex/trunk@2680
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
};
/*------------------------------------------------------------*/
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);
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)
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)
{
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,
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,
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,
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,
}
+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)
{
}
+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)
{
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:
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:
/* 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);
/* 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);
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;
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;
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:
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: