]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
s390: Support these DFP insns: CDGTRA, CXGTR, CGXTR, and CGDTR.
authorFlorian Krohm <florian@eich-krohm.de>
Fri, 8 Feb 2013 23:32:54 +0000 (23:32 +0000)
committerFlorian Krohm <florian@eich-krohm.de>
Fri, 8 Feb 2013 23:32:54 +0000 (23:32 +0000)
Patch by Maran Pakkirisamy (maranp@linux.vnet.ibm.com).
Part of fixing BZ #307113.

git-svn-id: svn://svn.valgrind.org/vex/trunk@2680

VEX/priv/guest_s390_defs.h
VEX/priv/guest_s390_helpers.c
VEX/priv/guest_s390_toIR.c
VEX/priv/host_s390_defs.c
VEX/priv/host_s390_defs.h
VEX/priv/host_s390_isel.c

index 642118fee5f79c9b07f2576814a1f8615b5528aa..b8ed91d0568913d1b0d4acbf5d0aa44013836488 100644 (file)
@@ -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
 };
 
 /*------------------------------------------------------------*/
index b13971456f8804183061651e7fad3899baceccff..8be925af9c4d31a2c3dea2af41d1fcceee8c8a22 100644 (file)
@@ -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);
 
index 377b5b68ac2b1c1252751f27bc75efb95e499a8b..25cfb988741f0d4b3cb7d3f708c4b1ed06ed6e44 100644 (file)
@@ -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,
index 1ff90cdd1e92c315e7173b8df6fd835dbc2ba1f3..13c1b374a397cd92152a088e888abd67b819c39c 100644 (file)
@@ -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);
index 5fb5a0d3c6f298ad840371b7b25a60ae6aadeece..e13893da6be0c07df91109dfc0092aae7080a52b 100644 (file)
@@ -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;
index 1c275702466f50e869068cb7e7ab381f91f2db32..cfca458c3abca5a7aeb026a9ae3e5598158ac79a 100644 (file)
@@ -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: