From: Florian Krohm Date: Thu, 27 Dec 2012 20:14:03 +0000 (+0000) Subject: s390: Support the "test data class/group" and "extract significance" X-Git-Tag: svn/VALGRIND_3_9_0^2~164 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=55e9dc24aefe6c7decc9ac26fa78b083bfca1058;p=thirdparty%2Fvalgrind.git s390: Support the "test data class/group" and "extract significance" 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 --- diff --git a/VEX/priv/guest_s390_defs.h b/VEX/priv/guest_s390_defs.h index 51eaaeea61..8d71d68e4d 100644 --- a/VEX/priv/guest_s390_defs.h +++ b/VEX/priv/guest_s390_defs.h @@ -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 | +--------------------------------+-----------------------+----------------------+-----------------+ */ diff --git a/VEX/priv/guest_s390_helpers.c b/VEX/priv/guest_s390_helpers.c index f34201df97..0fd647488c 100644 --- a/VEX/priv/guest_s390_helpers.c +++ b/VEX/priv/guest_s390_helpers.c @@ -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; } diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index f90f05da7f..5e086587a2 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -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, diff --git a/VEX/priv/host_s390_defs.c b/VEX/priv/host_s390_defs.c index adea62e740..4645376836 100644 --- a/VEX/priv/host_s390_defs.c +++ b/VEX/priv/host_s390_defs.c @@ -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; diff --git a/VEX/priv/host_s390_defs.h b/VEX/priv/host_s390_defs.h index 56b8b126bb..4e7fcca2e8 100644 --- a/VEX/priv/host_s390_defs.h +++ b/VEX/priv/host_s390_defs.h @@ -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); diff --git a/VEX/priv/host_s390_isel.c b/VEX/priv/host_s390_isel.c index ce81ceeb89..bb5aef29b2 100644 --- a/VEX/priv/host_s390_isel.c +++ b/VEX/priv/host_s390_isel.c @@ -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);