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/guest_s390_toIR.c b/priv/guest_s390_toIR.c
index 750250b..ec9dbe4 100644
--- a/priv/guest_s390_toIR.c
+++ b/priv/guest_s390_toIR.c
@@ -9301,6 +9301,154 @@
 }
 
 static const HChar *
+s390_irgen_CDFTR(UChar m3 __attribute__((unused)),
+                 UChar m4 __attribute__((unused)), UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+
+   if (! s390_host_has_fpext) {
+      emulation_failure(EmFail_S390X_fpext);
+   } else {
+      IRTemp op2 = newTemp(Ity_I32);
+
+      assign(op2, get_gpr_w1(r2));
+      put_dpr_dw0(r1, unop(Iop_I32StoD64, mkexpr(op2)));
+   }
+   return "cdftr";
+}
+
+static const HChar *
+s390_irgen_CXFTR(UChar m3 __attribute__((unused)),
+                 UChar m4 __attribute__((unused)), UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+
+   if (! s390_host_has_fpext) {
+      emulation_failure(EmFail_S390X_fpext);
+   } else {
+      IRTemp op2 = newTemp(Ity_I32);
+
+      assign(op2, get_gpr_w1(r2));
+      put_dpr_pair(r1, unop(Iop_I32StoD128, mkexpr(op2)));
+   }
+   return "cxftr";
+}
+
+static const HChar *
+s390_irgen_CDLFTR(UChar m3 __attribute__((unused)),
+                  UChar m4 __attribute__((unused)), UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+
+   if (! s390_host_has_fpext) {
+      emulation_failure(EmFail_S390X_fpext);
+   } else {
+      IRTemp op2 = newTemp(Ity_I32);
+
+      assign(op2, get_gpr_w1(r2));
+      put_dpr_dw0(r1, unop(Iop_I32UtoD64, mkexpr(op2)));
+   }
+   return "cdlftr";
+}
+
+static const HChar *
+s390_irgen_CXLFTR(UChar m3 __attribute__((unused)),
+                  UChar m4 __attribute__((unused)), UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+
+   if (! s390_host_has_fpext) {
+      emulation_failure(EmFail_S390X_fpext);
+   } else {
+      IRTemp op2 = newTemp(Ity_I32);
+
+      assign(op2, get_gpr_w1(r2));
+      put_dpr_pair(r1, unop(Iop_I32UtoD128, mkexpr(op2)));
+   }
+   return "cxlftr";
+}
+
+static const HChar *
+s390_irgen_CDLGTR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+
+   if (! s390_host_has_fpext) {
+      emulation_failure(EmFail_S390X_fpext);
+   } else {
+      IRTemp op2 = newTemp(Ity_I64);
+
+      assign(op2, get_gpr_dw0(r2));
+      put_dpr_dw0(r1, binop(Iop_I64UtoD64,
+                            mkexpr(encode_dfp_rounding_mode(m3)),
+                            mkexpr(op2)));
+   }
+   return "cdlgtr";
+}
+
+static const HChar *
+s390_irgen_CXLGTR(UChar m3 __attribute__((unused)),
+                  UChar m4 __attribute__((unused)), UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+
+   if (! s390_host_has_fpext) {
+      emulation_failure(EmFail_S390X_fpext);
+   } else {
+      IRTemp op2 = newTemp(Ity_I64);
+
+      assign(op2, get_gpr_dw0(r2));
+      put_dpr_pair(r1, unop(Iop_I64UtoD128, mkexpr(op2)));
+   }
+   return "cxlgtr";
+}
+
+static const HChar *
+s390_irgen_CFDTR(UChar m3, UChar m4 __attribute__((unused)),
+                 UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+
+   if (! s390_host_has_fpext) {
+      emulation_failure(EmFail_S390X_fpext);
+   } else {
+      IRTemp op = newTemp(Ity_D64);
+      IRTemp result = newTemp(Ity_I32);
+      IRTemp rounding_mode = encode_dfp_rounding_mode(m3);
+
+      assign(op, get_dpr_dw0(r2));
+      assign(result, binop(Iop_D64toI32S, mkexpr(rounding_mode),
+                           mkexpr(op)));
+      put_gpr_w1(r1, mkexpr(result));
+      s390_cc_thunk_putFZ(S390_CC_OP_DFP_64_TO_INT_32, op, rounding_mode);
+   }
+   return "cfdtr";
+}
+
+static const HChar *
+s390_irgen_CFXTR(UChar m3, UChar m4 __attribute__((unused)),
+                 UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+
+   if (! s390_host_has_fpext) {
+      emulation_failure(EmFail_S390X_fpext);
+   } else {
+      IRTemp op = newTemp(Ity_D128);
+      IRTemp result = newTemp(Ity_I32);
+      IRTemp rounding_mode = encode_dfp_rounding_mode(m3);
+
+      assign(op, get_dpr_pair(r2));
+      assign(result, binop(Iop_D128toI32S, mkexpr(rounding_mode),
+                           mkexpr(op)));
+      put_gpr_w1(r1, mkexpr(result));
+      s390_cc_thunk_put1d128Z(S390_CC_OP_DFP_128_TO_INT_32, op, rounding_mode);
+   }
+   return "cfxtr";
+}
+
+static const HChar *
 s390_irgen_CEDTR(UChar r1, UChar r2)
 {
    IRTemp op1 = newTemp(Ity_D64);
@@ -9339,6 +9487,95 @@
 }
 
 static const HChar *
+s390_irgen_CLFDTR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+
+   if (! s390_host_has_fpext) {
+      emulation_failure(EmFail_S390X_fpext);
+   } else {
+      IRTemp op = newTemp(Ity_D64);
+      IRTemp result = newTemp(Ity_I32);
+      IRTemp rounding_mode = encode_dfp_rounding_mode(m3);
+
+      assign(op, get_dpr_dw0(r2));
+      assign(result, binop(Iop_D64toI32U, mkexpr(rounding_mode),
+                           mkexpr(op)));
+      put_gpr_w1(r1, mkexpr(result));
+      s390_cc_thunk_putFZ(S390_CC_OP_DFP_64_TO_UINT_32, op, rounding_mode);
+   }
+   return "clfdtr";
+}
+
+static const HChar *
+s390_irgen_CLFXTR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+
+   if (! s390_host_has_fpext) {
+      emulation_failure(EmFail_S390X_fpext);
+   } else {
+      IRTemp op = newTemp(Ity_D128);
+      IRTemp result = newTemp(Ity_I32);
+      IRTemp rounding_mode = encode_dfp_rounding_mode(m3);
+
+      assign(op, get_dpr_pair(r2));
+      assign(result, binop(Iop_D128toI32U, mkexpr(rounding_mode),
+                           mkexpr(op)));
+      put_gpr_w1(r1, mkexpr(result));
+      s390_cc_thunk_put1d128Z(S390_CC_OP_DFP_128_TO_UINT_32, op, rounding_mode);
+   }
+   return "clfxtr";
+}
+
+static const HChar *
+s390_irgen_CLGDTR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+
+   if (! s390_host_has_fpext) {
+      emulation_failure(EmFail_S390X_fpext);
+   } else {
+      IRTemp op = newTemp(Ity_D64);
+      IRTemp result = newTemp(Ity_I64);
+      IRTemp rounding_mode = encode_dfp_rounding_mode(m3);
+
+      assign(op, get_dpr_dw0(r2));
+      assign(result, binop(Iop_D64toI64U, mkexpr(rounding_mode),
+                           mkexpr(op)));
+      put_gpr_dw0(r1, mkexpr(result));
+      s390_cc_thunk_putFZ(S390_CC_OP_DFP_64_TO_UINT_64, op, rounding_mode);
+   }
+   return "clgdtr";
+}
+
+static const HChar *
+s390_irgen_CLGXTR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+
+   if (! s390_host_has_fpext) {
+      emulation_failure(EmFail_S390X_fpext);
+   } else {
+      IRTemp op = newTemp(Ity_D128);
+      IRTemp result = newTemp(Ity_I64);
+      IRTemp rounding_mode = encode_dfp_rounding_mode(m3);
+
+      assign(op, get_dpr_pair(r2));
+      assign(result, binop(Iop_D128toI64U, mkexpr(rounding_mode),
+                           mkexpr(op)));
+      put_gpr_dw0(r1, mkexpr(result));
+      s390_cc_thunk_put1d128Z(S390_CC_OP_DFP_128_TO_UINT_64, op,
+                              rounding_mode);
+   }
+   return "clgxtr";
+}
+
+static const HChar *
 s390_irgen_DDTRA(UChar r3, UChar m4, UChar r1, UChar r2)
 {
    IRTemp op1 = newTemp(Ity_D64);
@@ -13836,20 +14073,44 @@
                                    ovl.fmt.RRE.r2);  goto ok;
    case 0xb93e: /* KIMD */ goto unimplemented;
    case 0xb93f: /* KLMD */ goto unimplemented;
-   case 0xb941: /* CFDTR */ goto unimplemented;
-   case 0xb942: /* CLGDTR */ goto unimplemented;
-   case 0xb943: /* CLFDTR */ goto unimplemented;
+   case 0xb941: s390_format_RRF_UURF(s390_irgen_CFDTR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb942: s390_format_RRF_UURF(s390_irgen_CLGDTR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb943: s390_format_RRF_UURF(s390_irgen_CLFDTR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
    case 0xb946: s390_format_RRE_RR(s390_irgen_BCTGR, ovl.fmt.RRE.r1,
                                    ovl.fmt.RRE.r2);  goto ok;
-   case 0xb949: /* CFXTR */ goto unimplemented;
-   case 0xb94a: /* CLGXTR */ goto unimplemented;
-   case 0xb94b: /* CLFXTR */ goto unimplemented;
-   case 0xb951: /* CDFTR */ goto unimplemented;
-   case 0xb952: /* CDLGTR */ goto unimplemented;
-   case 0xb953: /* CDLFTR */ goto unimplemented;
-   case 0xb959: /* CXFTR */ goto unimplemented;
-   case 0xb95a: /* CXLGTR */ goto unimplemented;
-   case 0xb95b: /* CXLFTR */ goto unimplemented;
+   case 0xb949: s390_format_RRF_UURF(s390_irgen_CFXTR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb94a: s390_format_RRF_UURF(s390_irgen_CLGXTR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb94b: s390_format_RRF_UURF(s390_irgen_CLFXTR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb951: s390_format_RRF_UUFR(s390_irgen_CDFTR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb952: s390_format_RRF_UUFR(s390_irgen_CDLGTR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb953: s390_format_RRF_UUFR(s390_irgen_CDLFTR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb959: s390_format_RRF_UUFR(s390_irgen_CXFTR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb95a: s390_format_RRF_UUFR(s390_irgen_CXLGTR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb95b: s390_format_RRF_UUFR(s390_irgen_CXLFTR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
    case 0xb960: /* CGRT */ goto unimplemented;
    case 0xb961: /* CLGRT */ goto unimplemented;
    case 0xb972: /* CRT */ goto unimplemented;