]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
s390: Support the "test data class/group" and "extract significance"
authorFlorian Krohm <florian@eich-krohm.de>
Thu, 27 Dec 2012 20:14:03 +0000 (20:14 +0000)
committerFlorian Krohm <florian@eich-krohm.de>
Thu, 27 Dec 2012 20:14:03 +0000 (20:14 +0000)
insns. Patch by Maran Pakkirisamy (maranp@linux.vnet.ibm.com).
This is part of fixing BZ 307113.

[ revision 2621 was also implemented by Maran. ]

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

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 51eaaeea617fc360ddca538a2062e99b7da92ee9..8d71d68e4dab80b96d29296df3201f32b28e5dbd 100644 (file)
@@ -138,7 +138,13 @@ enum {
    S390_CC_OP_BFP_64_TO_UINT_64 = 40,
    S390_CC_OP_BFP_128_TO_UINT_64 = 41,
    S390_CC_OP_DFP_RESULT_64 = 42,
-   S390_CC_OP_DFP_RESULT_128 = 43
+   S390_CC_OP_DFP_RESULT_128 = 43,
+   S390_CC_OP_DFP_TDC_32 = 44,
+   S390_CC_OP_DFP_TDC_64 = 45,
+   S390_CC_OP_DFP_TDC_128 = 46,
+   S390_CC_OP_DFP_TDG_32 = 47,
+   S390_CC_OP_DFP_TDG_64 = 48,
+   S390_CC_OP_DFP_TDG_128 = 49
 };
 
 /*------------------------------------------------------------*/
@@ -198,6 +204,12 @@ enum {
    | S390_CC_OP_BFP_128_TO_UINT_64  | F source hi 64 bits   | F source low 64 bits | Z rounding mode |
    | S390_CC_OP_DFP_RESULT_64       | D result              |                      |                 |
    | S390_CC_OP_DFP_RESULT_128      | D result hi 64 bits   | D result low 64 bits |                 |
+   | S390_CC_OP_DFP_TDC_32          | D value               | Z class              |                 |
+   | S390_CC_OP_DFP_TDC_64          | D value               | Z class              |                 |
+   | S390_CC_OP_DFP_TDC_128         | D value hi 64 bits    | D value low 64 bits  | Z class         |
+   | S390_CC_OP_DFP_TDG_32          | D value               | Z group              |                 |
+   | S390_CC_OP_DFP_TDG_64          | D value               | Z group              |                 |
+   | S390_CC_OP_DFP_TDG_128         | D value hi 64 bits    | D value low 64 bits  | Z group         |
    +--------------------------------+-----------------------+----------------------+-----------------+
 */
 
index f34201df97c2d66b5804612744a257559016d0e9..0fd647488c28f0ecf8bede8c5c5d08966ca3f072 100644 (file)
@@ -1177,6 +1177,33 @@ decode_bfp_rounding_mode(UInt irrm)
    psw >> 28;   /* cc */                                                \
 })
 
+#define S390_CC_FOR_DFP_TD(opcode,cc_dep1,cc_dep2)                      \
+({                                                                      \
+   __asm__ volatile (                                                   \
+        opcode ",%[value],0(%[class])\n\t"                              \
+        "ipm %[psw]\n\t"           : [psw] "=d"(psw)                    \
+                                   : [value] "f"(cc_dep1),              \
+                                     [class] "a"(cc_dep2)               \
+                                   : "cc");                             \
+   psw >> 28;   /* cc */                                                \
+})
+
+#define S390_CC_FOR_DFP128_TD(opcode,cc_dep1,cc_dep2,cc_ndep)           \
+({                                                                      \
+   /* Recover the original DEP2 value. See comment near                 \
+      s390_cc_thunk_put1d128Z for rationale. */                         \
+   cc_dep2 = cc_dep2 ^ cc_ndep;                                         \
+   __asm__ volatile (                                                   \
+        "ldr  4,%[high]\n\t"                                            \
+        "ldr  6,%[low]\n\t"                                             \
+        opcode ",4,0(%[class])\n\t"                                     \
+        "ipm  %[psw]\n\t"          : [psw] "=d"(psw)                    \
+                                   : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
+                                     [class] "a"(cc_ndep)               \
+                                   : "cc", "f4", "f6");                 \
+   psw >> 28;   /* cc */                                                \
+})
+
 
 /* Return the value of the condition code from the supplied thunk parameters.
    This is not the value of the PSW. It is the value of the 2 CC bits within
@@ -1399,6 +1426,26 @@ s390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep)
    case S390_CC_OP_DFP_RESULT_128:
       return S390_CC_FOR_DFP128_RESULT(cc_dep1, cc_dep2);
 
+   case S390_CC_OP_DFP_TDC_32:  /* TDCET */
+      return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000050", cc_dep1, cc_dep2);
+
+   case S390_CC_OP_DFP_TDC_64:  /* TDCDT */
+      return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000054", cc_dep1, cc_dep2);
+
+   case S390_CC_OP_DFP_TDC_128: /* TDCXT */
+      return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000058", cc_dep1,
+                                   cc_dep2, cc_ndep);
+
+   case S390_CC_OP_DFP_TDG_32:  /* TDGET */
+      return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000051", cc_dep1, cc_dep2);
+
+   case S390_CC_OP_DFP_TDG_64:  /* TDGDT */
+      return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000055", cc_dep1, cc_dep2);
+
+   case S390_CC_OP_DFP_TDG_128: /* TDGXT */
+      return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000059", cc_dep1,
+                                   cc_dep2, cc_ndep);
+
    default:
       break;
    }
index f90f05da7f138bdc9d90e68209fc927189b53c11..5e086587a2c19a39024295b24825a73a6a87ad81 100644 (file)
@@ -707,6 +707,24 @@ s390_cc_thunk_put1d128(UInt opc, IRTemp d1)
 }
 
 
+/* Write a 128-bit decimal floating point value and an integer into the flags
+   thunk. The integer value is zero-extended first. */
+static void
+s390_cc_thunk_put1d128Z(UInt opc, IRTemp d1, IRTemp nd)
+{
+   IRExpr *op, *hi, *lo, *lox, *ndep;
+
+   op   = mkU64(opc);
+   hi   = unop(Iop_D128HItoD64, mkexpr(d1));
+   lo   = unop(Iop_ReinterpD64asI64, unop(Iop_D128LOtoD64, mkexpr(d1)));
+   ndep = s390_cc_widen(nd, False);
+
+   lox = binop(Iop_Xor64, lo, ndep);  /* convey dependency */
+
+   s390_cc_thunk_fill(op, hi, lox, ndep);
+}
+
+
 static void
 s390_cc_set(UInt val)
 {
@@ -9364,6 +9382,22 @@ s390_irgen_DXTRA(UChar r3, UChar m4, UChar r1, UChar r2)
    return (m4 == 0) ? "dxtr" : "dxtra";
 }
 
+static const HChar *
+s390_irgen_ESDTR(UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+   put_gpr_dw0(r1, unop(Iop_ExtractSigD64, get_dpr_dw0(r2)));
+   return "esdtr";
+}
+
+static const HChar *
+s390_irgen_ESXTR(UChar r1, UChar r2)
+{
+   vassert(s390_host_has_dfp);
+   put_gpr_dw0(r1, unop(Iop_ExtractSigD128, get_dpr_pair(r2)));
+   return "esxtr";
+}
+
 static const HChar *
 s390_irgen_LDETR(UChar m4 __attribute__((unused)), UChar r1, UChar r2)
 {
@@ -9539,6 +9573,84 @@ s390_irgen_SXTRA(UChar r3, UChar m4, UChar r1, UChar r2)
    return (m4 == 0) ? "sxtr" : "sxtra";
 }
 
+static const HChar *
+s390_irgen_TDCET(UChar r1, IRTemp op2addr)
+{
+   IRTemp value = newTemp(Ity_D32);
+
+   vassert(s390_host_has_dfp);
+   assign(value, get_dpr_w0(r1));
+
+   s390_cc_thunk_putFZ(S390_CC_OP_DFP_TDC_32, value, op2addr);
+
+   return "tdcet";
+}
+
+static const HChar *
+s390_irgen_TDCDT(UChar r1, IRTemp op2addr)
+{
+   IRTemp value = newTemp(Ity_D64);
+
+   vassert(s390_host_has_dfp);
+   assign(value, get_dpr_dw0(r1));
+
+   s390_cc_thunk_putFZ(S390_CC_OP_DFP_TDC_64, value, op2addr);
+
+   return "tdcdt";
+}
+
+static const HChar *
+s390_irgen_TDCXT(UChar r1, IRTemp op2addr)
+{
+   IRTemp value = newTemp(Ity_D128);
+
+   vassert(s390_host_has_dfp);
+   assign(value, get_dpr_pair(r1));
+
+   s390_cc_thunk_put1d128Z(S390_CC_OP_DFP_TDC_128, value, op2addr);
+
+   return "tdcxt";
+}
+
+static const HChar *
+s390_irgen_TDGET(UChar r1, IRTemp op2addr)
+{
+   IRTemp value = newTemp(Ity_D32);
+
+   vassert(s390_host_has_dfp);
+   assign(value, get_dpr_w0(r1));
+
+   s390_cc_thunk_putFZ(S390_CC_OP_DFP_TDG_32, value, op2addr);
+
+   return "tdget";
+}
+
+static const HChar *
+s390_irgen_TDGDT(UChar r1, IRTemp op2addr)
+{
+   IRTemp value = newTemp(Ity_D64);
+
+   vassert(s390_host_has_dfp);
+   assign(value, get_dpr_dw0(r1));
+
+   s390_cc_thunk_putFZ(S390_CC_OP_DFP_TDG_64, value, op2addr);
+
+   return "tdgdt";
+}
+
+static const HChar *
+s390_irgen_TDGXT(UChar r1, IRTemp op2addr)
+{
+   IRTemp value = newTemp(Ity_D128);
+
+   vassert(s390_host_has_dfp);
+   assign(value, get_dpr_pair(r1));
+
+   s390_cc_thunk_put1d128Z(S390_CC_OP_DFP_TDG_128, value, op2addr);
+
+   return "tdgxt";
+}
+
 static const HChar *
 s390_irgen_CLC(UChar length, IRTemp start1, IRTemp start2)
 {
@@ -13560,7 +13672,8 @@ s390_decode_4byte_and_irgen(UChar *bytes)
    case 0xb3e4: s390_format_RRE_FF(s390_irgen_CDTR, ovl.fmt.RRE.r1,
                                    ovl.fmt.RRE.r2);  goto ok;
    case 0xb3e5: /* EEDTR */ goto unimplemented;
-   case 0xb3e7: /* ESDTR */ goto unimplemented;
+   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 0xb3ea: /* CUXTR */ goto unimplemented;
@@ -13568,7 +13681,8 @@ s390_decode_4byte_and_irgen(UChar *bytes)
    case 0xb3ec: s390_format_RRE_FF(s390_irgen_CXTR, ovl.fmt.RRE.r1,
                                    ovl.fmt.RRE.r2);  goto ok;
    case 0xb3ed: /* EEXTR */ goto unimplemented;
-   case 0xb3ef: /* ESXTR */ 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 0xb3f2: /* CDUTR */ goto unimplemented;
    case 0xb3f3: /* CDSTR */ goto unimplemented;
@@ -14993,12 +15107,24 @@ s390_decode_6byte_and_irgen(UChar *bytes)
    case 0xed0000000041ULL: /* SRDT */ goto unimplemented;
    case 0xed0000000048ULL: /* SLXT */ goto unimplemented;
    case 0xed0000000049ULL: /* SRXT */ goto unimplemented;
-   case 0xed0000000050ULL: /* TDCET */ goto unimplemented;
-   case 0xed0000000051ULL: /* TDGET */ goto unimplemented;
-   case 0xed0000000054ULL: /* TDCDT */ goto unimplemented;
-   case 0xed0000000055ULL: /* TDGDT */ goto unimplemented;
-   case 0xed0000000058ULL: /* TDCXT */ goto unimplemented;
-   case 0xed0000000059ULL: /* TDGXT */ goto unimplemented;
+   case 0xed0000000050ULL: s390_format_RXE_FRRD(s390_irgen_TDCET, ovl.fmt.RXE.r1,
+                                                ovl.fmt.RXE.x2, ovl.fmt.RXE.b2,
+                                                ovl.fmt.RXE.d2);  goto ok;
+   case 0xed0000000051ULL: s390_format_RXE_FRRD(s390_irgen_TDGET, ovl.fmt.RXE.r1,
+                                                ovl.fmt.RXE.x2, ovl.fmt.RXE.b2,
+                                                ovl.fmt.RXE.d2);  goto ok;
+   case 0xed0000000054ULL: s390_format_RXE_FRRD(s390_irgen_TDCDT, ovl.fmt.RXE.r1,
+                                                ovl.fmt.RXE.x2, ovl.fmt.RXE.b2,
+                                                ovl.fmt.RXE.d2);  goto ok;
+   case 0xed0000000055ULL: s390_format_RXE_FRRD(s390_irgen_TDGDT, ovl.fmt.RXE.r1,
+                                                ovl.fmt.RXE.x2, ovl.fmt.RXE.b2,
+                                                ovl.fmt.RXE.d2);  goto ok;
+   case 0xed0000000058ULL: s390_format_RXE_FRRD(s390_irgen_TDCXT, ovl.fmt.RXE.r1,
+                                                ovl.fmt.RXE.x2, ovl.fmt.RXE.b2,
+                                                ovl.fmt.RXE.d2);  goto ok;
+   case 0xed0000000059ULL: s390_format_RXE_FRRD(s390_irgen_TDGXT, ovl.fmt.RXE.r1,
+                                                ovl.fmt.RXE.x2, ovl.fmt.RXE.b2,
+                                                ovl.fmt.RXE.d2);  goto ok;
    case 0xed0000000064ULL: s390_format_RXY_FRRD(s390_irgen_LEY, ovl.fmt.RXY.r1,
                                                 ovl.fmt.RXY.x2, ovl.fmt.RXY.b2,
                                                 ovl.fmt.RXY.dl2,
index adea62e7402a5208c8cf20b365c735163840f8b1..46453768368eef64a95529c8f19a09e192704ad1 100644 (file)
@@ -722,6 +722,15 @@ s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
       break;
    }
 
+   case S390_INSN_DFP_UNOP:
+      addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_hi);
+      addHRegUse(u, HRmRead,  insn->variant.dfp_unop.op_hi);  /* operand */
+      if (insn->size == 16) {
+         addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_lo);
+         addHRegUse(u, HRmRead,  insn->variant.dfp_unop.op_lo);  /* operand */
+      }
+      break;
+
    case S390_INSN_DFP_COMPARE:
       addHRegUse(u, HRmWrite, insn->variant.dfp_compare.dst);
       addHRegUse(u, HRmRead,  insn->variant.dfp_compare.op1_hi);  /* left */
@@ -998,6 +1007,19 @@ s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
       break;
    }
 
+   case S390_INSN_DFP_UNOP:
+      insn->variant.dfp_unop.dst_hi =
+         lookupHRegRemap(m, insn->variant.dfp_unop.dst_hi);
+      insn->variant.dfp_unop.op_hi  =
+         lookupHRegRemap(m, insn->variant.dfp_unop.op_hi);
+      if (insn->size == 16) {
+         insn->variant.dfp_unop.dst_lo =
+            lookupHRegRemap(m, insn->variant.dfp_unop.dst_lo);
+         insn->variant.dfp_unop.op_lo  =
+            lookupHRegRemap(m, insn->variant.dfp_unop.op_lo);
+      }
+      break;
+
    case S390_INSN_DFP_COMPARE:
       insn->variant.dfp_compare.dst =
          lookupHRegRemap(m, insn->variant.dfp_compare.dst);
@@ -4126,6 +4148,26 @@ s390_emit_DXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
 }
 
 
+static UChar *
+s390_emit_ESDTR(UChar *p, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC3(MNM, GPR, FPR), "esdtr", r1, r2);
+
+   return emit_RRE(p, 0xb3e70000, r1, r2);
+}
+
+
+static UChar *
+s390_emit_ESXTR(UChar *p, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC3(MNM, GPR, FPR), "esxtr", r1, r2);
+
+   return emit_RRE(p, 0xb3ef0000, r1, r2);
+}
+
+
 static UChar *
 s390_emit_LDETR(UChar *p, UChar m4, UChar r1, UChar r2)
 {
@@ -5377,6 +5419,25 @@ s390_insn_dfp_binop(UChar size, s390_dfp_binop_t tag, HReg dst, HReg op2,
 }
 
 
+s390_insn *
+s390_insn_dfp_unop(UChar size, s390_dfp_unop_t tag, HReg dst, HReg op)
+{
+   s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
+
+   vassert(size == 8);
+
+   insn->tag  = S390_INSN_DFP_UNOP;
+   insn->size = size;
+   insn->variant.dfp_unop.tag = tag;
+   insn->variant.dfp_unop.dst_hi = dst;
+   insn->variant.dfp_unop.op_hi  = op;
+   insn->variant.dfp_unop.dst_lo = INVALID_HREG;
+   insn->variant.dfp_unop.op_lo  = INVALID_HREG;
+
+   return insn;
+}
+
+
 s390_insn *
 s390_insn_dfp_compare(UChar size, s390_dfp_cmp_t tag, HReg dst,
                       HReg op1, HReg op2)
@@ -5449,6 +5510,28 @@ s390_insn_dfp128_binop(UChar size, s390_dfp_binop_t tag, HReg dst_hi,
 }
 
 
+s390_insn *
+s390_insn_dfp128_unop(UChar size, s390_dfp_unop_t tag, HReg dst,
+                      HReg op_hi, HReg op_lo)
+{
+   s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
+
+   /* destination is an 8 byte integer value */
+   vassert(size == 8);
+   vassert(is_valid_fp128_regpair(op_hi, op_lo));
+
+   insn->tag  = S390_INSN_DFP_UNOP;
+   insn->size = size;
+   insn->variant.dfp_unop.tag = tag;
+   insn->variant.dfp_unop.dst_hi = dst;
+   insn->variant.dfp_unop.dst_lo = INVALID_HREG;
+   insn->variant.dfp_unop.op_hi = op_hi;
+   insn->variant.dfp_unop.op_lo = op_lo;
+
+   return insn;
+}
+
+
 s390_insn *
 s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t tag, HReg dst, HReg op1_hi,
                          HReg op1_lo, HReg op2_hi, HReg op2_lo)
@@ -6114,6 +6197,16 @@ s390_insn_as_string(const s390_insn *insn)
       break;
    }
 
+   case S390_INSN_DFP_UNOP:
+      switch (insn->variant.dfp_unop.tag) {
+      case S390_DFP_EXTRACT_SIG_D64:
+      case S390_DFP_EXTRACT_SIG_D128:  op = "v-d2sig";  break;
+      default: goto fail;
+      }
+      s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_unop.dst_hi,
+                   insn->variant.dfp_unop.op_hi);
+      break;
+
    case S390_INSN_DFP_COMPARE:
       switch (insn->variant.dfp_compare.tag) {
       case S390_DFP_COMPARE:     op = "v-dcmp"; break;
@@ -8303,6 +8396,22 @@ s390_insn_dfp_binop_emit(UChar *buf, const s390_insn *insn)
 }
 
 
+static UChar *
+s390_insn_dfp_unop_emit(UChar *buf, const s390_insn *insn)
+{
+   UInt  r1 = hregNumber(insn->variant.dfp_unop.dst_hi);
+   UInt  r2 = hregNumber(insn->variant.dfp_unop.op_hi);
+
+   switch (insn->variant.dfp_unop.tag) {
+   case S390_DFP_EXTRACT_SIG_D64:  return s390_emit_ESDTR(buf, r1, r2); break;
+   case S390_DFP_EXTRACT_SIG_D128: return s390_emit_ESXTR(buf, r1, r2); break;
+   default: goto fail;
+   }
+ fail:
+   vpanic("s390_insn_dfp_unop_emit");
+}
+
+
 static UChar *
 s390_insn_dfp_compare_emit(UChar *buf, const s390_insn *insn)
 {
@@ -8999,6 +9108,10 @@ emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, s390_insn *insn,
       end = s390_insn_dfp_binop_emit(buf, insn);
       break;
 
+   case S390_INSN_DFP_UNOP:
+      end = s390_insn_dfp_unop_emit(buf, insn);
+      break;
+
    case S390_INSN_DFP_COMPARE:
       end = s390_insn_dfp_compare_emit(buf, insn);
       break;
index 56b8b126bb4e68c93e9df3245a1b4a17c7139a1e..4e7fcca2e8dde97c03ddcc0f18224a781dc1c4e7 100644 (file)
@@ -141,6 +141,7 @@ typedef enum {
    S390_INSN_BFP_COMPARE,
    S390_INSN_BFP_CONVERT,
    S390_INSN_DFP_BINOP, /* Decimal floating point */
+   S390_INSN_DFP_UNOP,
    S390_INSN_DFP_COMPARE,
    S390_INSN_DFP_CONVERT,
    S390_INSN_MFENCE,
@@ -254,6 +255,12 @@ typedef enum {
    S390_DFP_DIV
 } s390_dfp_binop_t;
 
+/* The kind of unary DFP operations */
+typedef enum {
+   S390_DFP_EXTRACT_SIG_D64,
+   S390_DFP_EXTRACT_SIG_D128,
+} s390_dfp_unop_t;
+
 /* The kind of DFP compare operations */
 typedef enum {
    S390_DFP_COMPARE,
@@ -443,6 +450,13 @@ typedef struct {
       struct {
          s390_dfp_binop *details;
       } dfp_binop;
+      struct {
+         s390_dfp_unop_t tag;
+         HReg         dst_hi; /* 128-bit result high part; 64-bit result */
+         HReg         dst_lo; /* 128-bit result low part */
+         HReg         op_hi;  /* 128-bit operand high part; 64-bit opnd */
+         HReg         op_lo;  /* 128-bit operand low part */
+      } dfp_unop;
       struct {
          s390_dfp_conv_t  tag;
          s390_dfp_round_t rounding_mode;
@@ -568,6 +582,7 @@ s390_insn *s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t,
 s390_insn *s390_insn_dfp_binop(UChar size, s390_dfp_binop_t, HReg dst,
                                HReg op2, HReg op3,
                                s390_dfp_round_t rounding_mode);
+s390_insn *s390_insn_dfp_unop(UChar size, s390_dfp_unop_t, HReg dst, HReg op);
 s390_insn *s390_insn_dfp_compare(UChar size, s390_dfp_cmp_t, HReg dst,
                                  HReg op1, HReg op2);
 s390_insn *s390_insn_dfp_convert(UChar size, s390_dfp_conv_t tag, HReg dst,
@@ -576,6 +591,8 @@ s390_insn *s390_insn_dfp128_binop(UChar size, s390_dfp_binop_t, HReg dst_hi,
                                   HReg dst_lo, HReg op2_hi, HReg op2_lo,
                                   HReg op3_hi, HReg op3_lo,
                                   s390_dfp_round_t rounding_mode);
+s390_insn *s390_insn_dfp128_unop(UChar size, s390_dfp_unop_t, HReg dst,
+                                 HReg op_hi, HReg op_lo);
 s390_insn *s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t, HReg dst,
                                     HReg op1_hi, HReg op1_lo, HReg op2_hi,
                                     HReg op2_lo);
index ce81ceeb890f18e1e382373beb569e64004a4fd2..bb5aef29b2c3036316aafb27c9e09f1b00222f1d 100644 (file)
@@ -1448,6 +1448,32 @@ s390_isel_int_expr_wrk(ISelEnv *env, IRExpr *expr)
          return dst;
       }
 
+      if (unop == Iop_ExtractSigD64) {
+         dst = newVRegI(env);
+         h1  = s390_isel_dfp_expr(env, arg);     /* Process the operand */
+         addInstr(env,
+                  s390_insn_dfp_unop(size, S390_DFP_EXTRACT_SIG_D64, dst, h1));
+         return dst;
+      }
+
+      if (unop == Iop_ExtractSigD128) {
+         HReg op_hi, op_lo, f13, f15;
+         dst = newVRegI(env);
+         s390_isel_dfp128_expr(&op_hi, &op_lo, env, arg); /* Process operand */
+
+         /* We use non-virtual registers r13 and r15 as pair */
+         f13 = make_fpr(13);
+         f15 = make_fpr(15);
+
+         /* operand --> (f13, f15) */
+         addInstr(env, s390_insn_move(8, f13, op_hi));
+         addInstr(env, s390_insn_move(8, f15, op_lo));
+
+         addInstr(env, s390_insn_dfp128_unop(size, S390_DFP_EXTRACT_SIG_D128,
+                                             dst, f13, f15));
+         return dst;
+      }
+
       /* Expressions whose argument is 1-bit wide */
       if (typeOfIRExpr(env->type_env, arg) == Ity_I1) {
          s390_cc_t cond = s390_isel_cc(env, arg);