]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
s390: Support some more BFP <-> DFP conversions (the ones
authorFlorian Krohm <florian@eich-krohm.de>
Mon, 17 Jun 2013 21:03:56 +0000 (21:03 +0000)
committerFlorian Krohm <florian@eich-krohm.de>
Mon, 17 Jun 2013 21:03:56 +0000 (21:03 +0000)
that were added in VEX r2727).
Patch by Maran Pakkirisamy (maranp@linux.vnet.ibm.com).
Part of fixing BZ 307113.

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

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
VEX/priv/s390_defs.h

index 950c7892a51e33cdd36645103bcb67c9090c22cd..5f2ae20dd1f287c139c627d1b49d24c155793cd7 100644 (file)
@@ -154,8 +154,9 @@ enum {
    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,
-   S390_CC_OP_PFPO_64 = 58,
-   S390_CC_OP_PFPO_128 = 59
+   S390_CC_OP_PFPO_32 = 58,
+   S390_CC_OP_PFPO_64 = 59,
+   S390_CC_OP_PFPO_128 = 60
 };
 
 /*------------------------------------------------------------*/
@@ -229,6 +230,7 @@ enum {
    | S390_CC_OP_DFP_128_TO_INT_32   | D source hi 64 bits   | D source low 64 bits | Z rounding mode |
    | S390_CC_OP_DFP_64_TO_INT_64    | D source              | Z rounding mode      |                 |
    | S390_CC_OP_DFP_128_TO_INT_64   | D source hi 64 bits   | D source low 64 bits | Z rounding mode |
+   | S390_CC_OP_PFPO_32             | F|D source            | Z GR0 low 32 bits    |                 |
    | S390_CC_OP_PFPO_64             | F|D source            | Z GR0 low 32 bits    |                 |
    | S390_CC_OP_PFPO_128            | F|D source hi 64 bits | F|D src low 64 bits  | Z GR0 low 32 bits |
    +--------------------------------+-----------------------+----------------------+-----------------+
index 2ad798a3f6de14948094db5d392848fcb88d1018..f27092972a8140f7a3df05aeb5f4cb716520c6a7 100644 (file)
@@ -1741,6 +1741,18 @@ s390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep)
       return S390_CC_FOR_DFP128_UCONVERT(".insn rrf,0xb94a0000", cc_dep1,
                                          cc_dep2, cc_ndep);
 
+   case S390_CC_OP_PFPO_32: {
+      __asm__ volatile(
+           "ler 4, %[cc_dep1]\n\t"      /* 32 bit FR move */
+           "lr  0, %[cc_dep2]\n\t"      /* 32 bit GR move */
+           ".short 0x010a\n\t"          /* PFPO */
+           "ipm %[psw]\n\t"             : [psw] "=d"(psw)
+                                        : [cc_dep1] "f"(cc_dep1),
+                                          [cc_dep2] "d"(cc_dep2)
+                                        : "r0", "r1", "f4");
+      return psw >> 28;  /* cc */
+   }
+
    case S390_CC_OP_PFPO_64: {
       __asm__ volatile(
            "ldr 4, %[cc_dep1]\n\t"
index 2aefba25358e8557d8fc07a3f39436b5f1ac84f4..2f715978a8a8841e3646de9a22c900537203fdaf 100644 (file)
@@ -7199,18 +7199,42 @@ s390_irgen_PFPO(void)
    IRTemp test_bit = newTemp(Ity_I32); /* bit 32 of GR 0 - test validity */
    IRTemp fn = newTemp(Ity_I32);       /* [33:55] of GR 0 - function code */
    IRTemp ef = newTemp(Ity_I32);       /* Emulation Failure */
-   IRTemp src1 = newTemp(Ity_F64);
-   IRTemp dst1 = newTemp(Ity_D64);
-   IRTemp src2 = newTemp(Ity_D64);
-   IRTemp dst2 = newTemp(Ity_F64);
-   IRTemp src3 = newTemp(Ity_F64);
+   IRTemp src1 = newTemp(Ity_F32);
+   IRTemp dst1 = newTemp(Ity_D32);
+   IRTemp src2 = newTemp(Ity_F32);
+   IRTemp dst2 = newTemp(Ity_D64);
+   IRTemp src3 = newTemp(Ity_F32);
    IRTemp dst3 = newTemp(Ity_D128);
-   IRTemp src4 = newTemp(Ity_D128);
-   IRTemp dst4 = newTemp(Ity_F64);
-   IRTemp src5 = newTemp(Ity_F128);
-   IRTemp dst5 = newTemp(Ity_D128);
-   IRTemp src6 = newTemp(Ity_D128);
-   IRTemp dst6 = newTemp(Ity_F128);
+   IRTemp src4 = newTemp(Ity_F64);
+   IRTemp dst4 = newTemp(Ity_D32);
+   IRTemp src5 = newTemp(Ity_F64);
+   IRTemp dst5 = newTemp(Ity_D64);
+   IRTemp src6 = newTemp(Ity_F64);
+   IRTemp dst6 = newTemp(Ity_D128);
+   IRTemp src7 = newTemp(Ity_F128);
+   IRTemp dst7 = newTemp(Ity_D32);
+   IRTemp src8 = newTemp(Ity_F128);
+   IRTemp dst8 = newTemp(Ity_D64);
+   IRTemp src9 = newTemp(Ity_F128);
+   IRTemp dst9 = newTemp(Ity_D128);
+   IRTemp src10 = newTemp(Ity_D32);
+   IRTemp dst10 = newTemp(Ity_F32);
+   IRTemp src11 = newTemp(Ity_D32);
+   IRTemp dst11 = newTemp(Ity_F64);
+   IRTemp src12 = newTemp(Ity_D32);
+   IRTemp dst12 = newTemp(Ity_F128);
+   IRTemp src13 = newTemp(Ity_D64);
+   IRTemp dst13 = newTemp(Ity_F32);
+   IRTemp src14 = newTemp(Ity_D64);
+   IRTemp dst14 = newTemp(Ity_F64);
+   IRTemp src15 = newTemp(Ity_D64);
+   IRTemp dst15 = newTemp(Ity_F128);
+   IRTemp src16 = newTemp(Ity_D128);
+   IRTemp dst16 = newTemp(Ity_F32);
+   IRTemp src17 = newTemp(Ity_D128);
+   IRTemp dst17 = newTemp(Ity_F64);
+   IRTemp src18 = newTemp(Ity_D128);
+   IRTemp dst18 = newTemp(Ity_F128);
    IRExpr *irrm;
 
    vassert(s390_host_has_pfpo);
@@ -7225,7 +7249,7 @@ s390_irgen_PFPO(void)
    irrm = get_rounding_mode_from_gr0();
 
    /* test_bit is 1 */
-   assign(src1, get_fpr_dw0(4)); /* get source from FPR 4,6 */
+   assign(src1, get_fpr_w0(4)); /* get source from FPR 4,6 */
    s390_cc_thunk_putFZ(S390_CC_OP_PFPO_64, src1, gr0);
 
    /* Return code set in GR1 is usually 0. Non-zero value is set only
@@ -7253,52 +7277,148 @@ s390_irgen_PFPO(void)
                     )
         );
 
-   /* F64 -> D64 */
+   /* F32 -> D32 */
    /* get source from FPR 4,6 - already set in src1 */
-   assign(dst1, binop(Iop_F64toD64, irrm, mkexpr(src1)));
-   put_dpr_dw0(0, mkexpr(dst1)); /* put the result in FPR 0,2 */
+   assign(dst1, binop(Iop_F32toD32, irrm, mkexpr(src1)));
+   put_dpr_w0(0, mkexpr(dst1)); /* put the result in FPR 0,2 */
    put_gpr_w1(1, mkU32(0x0));
-   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_64, src1, gr0);
-   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_F64_TO_D64)));
+   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_32, src1, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_F32_TO_D32)));
 
-   /* D64 -> F64 */
-   assign(src2, get_dpr_dw0(4)); /* get source from FPR 4,6 */
-   assign(dst2, binop(Iop_D64toF64, irrm, mkexpr(src2)));
-   put_fpr_dw0(0, mkexpr(dst2)); /* put the result in FPR 0,2 */
+   /* F32 -> D64 */
+   assign(src2, get_fpr_w0(4)); /* get source from FPR 4,6 */
+   assign(dst2, binop(Iop_F32toD64, irrm, mkexpr(src2)));
+   put_dpr_dw0(0, mkexpr(dst2)); /* put the result in FPR 0,2 */
    put_gpr_w1(1, mkU32(0x0));
-   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_64, src2, gr0);
-   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_D64_TO_F64)));
+   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_32, src2, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_F32_TO_D64)));
 
-   /* F64 -> D128 */
-   assign(src3, get_fpr_dw0(4)); /* get source from FPR 4,6 */
-   assign(dst3, binop(Iop_F64toD128, irrm, mkexpr(src3)));
+   /* F32 -> D128 */
+   assign(src3, get_fpr_w0(4)); /* get source from FPR 4,6 */
+   assign(dst3, binop(Iop_F32toD128, irrm, mkexpr(src3)));
    put_dpr_pair(0, mkexpr(dst3)); /* put the result in FPR 0,2 */
    put_gpr_w1(1, mkU32(0x0));
-   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_64, src3, gr0);
+   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_32, src3, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_F32_TO_D128)));
+
+   /* F64 -> D32 */
+   assign(src4, get_fpr_dw0(4)); /* get source from FPR 4,6 */
+   assign(dst4, binop(Iop_F64toD32, irrm, mkexpr(src4)));
+   put_dpr_w0(0, mkexpr(dst4)); /* put the result in FPR 0,2 */
+   put_gpr_w1(1, mkU32(0x0));
+   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_64, src4, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_F64_TO_D32)));
+
+   /* F64 -> D64 */
+   assign(src5, get_fpr_dw0(4)); /* get source from FPR 4,6 */
+   assign(dst5, binop(Iop_F64toD64, irrm, mkexpr(src5)));
+   put_dpr_dw0(0, mkexpr(dst5)); /* put the result in FPR 0,2 */
+   put_gpr_w1(1, mkU32(0x0));
+   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_64, src5, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_F64_TO_D64)));
+
+   /* F64 -> D128 */
+   assign(src6, get_fpr_dw0(4)); /* get source from FPR 4,6 */
+   assign(dst6, binop(Iop_F64toD128, irrm, mkexpr(src6)));
+   put_dpr_pair(0, mkexpr(dst6)); /* put the result in FPR 0,2 */
+   put_gpr_w1(1, mkU32(0x0));
+   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_64, src6, gr0);
    next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_F64_TO_D128)));
 
-   /* D128 -> F64 */
-   assign(src4, get_dpr_pair(4)); /* get source from FPR 4,6 */
-   assign(dst4, binop(Iop_D128toF64, irrm, mkexpr(src4)));
-   put_fpr_dw0(0, mkexpr(dst4)); /* put the result in FPR 0,2 */
+   /* F128 -> D32 */
+   assign(src7, get_fpr_pair(4)); /* get source from FPR 4,6 */
+   assign(dst7, binop(Iop_F128toD32, irrm, mkexpr(src7)));
+   put_dpr_w0(0, mkexpr(dst7)); /* put the result in FPR 0,2 */
    put_gpr_w1(1, mkU32(0x0));
-   s390_cc_thunk_put1d128Z(S390_CC_OP_PFPO_128, src4, gr0);
-   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_D128_TO_F64)));
+   s390_cc_thunk_put1f128Z(S390_CC_OP_PFPO_128, src7, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_F128_TO_D32)));
+
+   /* F128 -> D64 */
+   assign(src8, get_fpr_pair(4)); /* get source from FPR 4,6 */
+   assign(dst8, binop(Iop_F128toD64, irrm, mkexpr(src8)));
+   put_dpr_dw0(0, mkexpr(dst8)); /* put the result in FPR 0,2 */
+   put_gpr_w1(1, mkU32(0x0));
+   s390_cc_thunk_put1f128Z(S390_CC_OP_PFPO_128, src8, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_F128_TO_D64)));
 
    /* F128 -> D128 */
-   assign(src5, get_fpr_pair(4)); /* get source from FPR 4,6 */
-   assign(dst5, binop(Iop_F128toD128, irrm, mkexpr(src5)));
-   put_dpr_pair(0, mkexpr(dst5)); /* put the result in FPR 0,2 */
+   assign(src9, get_fpr_pair(4)); /* get source from FPR 4,6 */
+   assign(dst9, binop(Iop_F128toD128, irrm, mkexpr(src9)));
+   put_dpr_pair(0, mkexpr(dst9)); /* put the result in FPR 0,2 */
    put_gpr_w1(1, mkU32(0x0));
-   s390_cc_thunk_put1f128Z(S390_CC_OP_PFPO_128, src5, gr0);
+   s390_cc_thunk_put1f128Z(S390_CC_OP_PFPO_128, src9, gr0);
    next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_F128_TO_D128)));
 
+   /* D32 -> F32 */
+   assign(src10, get_dpr_w0(4)); /* get source from FPR 4,6 */
+   assign(dst10, binop(Iop_D32toF32, irrm, mkexpr(src10)));
+   put_fpr_w0(0, mkexpr(dst10)); /* put the result in FPR 0,2 */
+   put_gpr_w1(1, mkU32(0x0));
+   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_32, src10, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_D32_TO_F32)));
+
+   /* D32 -> F64 */
+   assign(src11, get_dpr_w0(4)); /* get source from FPR 4,6 */
+   assign(dst11, binop(Iop_D32toF64, irrm, mkexpr(src11)));
+   put_fpr_dw0(0, mkexpr(dst11)); /* put the result in FPR 0,2 */
+   put_gpr_w1(1, mkU32(0x0));
+   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_32, src11, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_D32_TO_F64)));
+
+   /* D32 -> F128 */
+   assign(src12, get_dpr_w0(4)); /* get source from FPR 4,6 */
+   assign(dst12, binop(Iop_D32toF128, irrm, mkexpr(src12)));
+   put_fpr_pair(0, mkexpr(dst12)); /* put the result in FPR 0,2 */
+   put_gpr_w1(1, mkU32(0x0));
+   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_32, src12, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_D32_TO_F128)));
+
+   /* D64 -> F32 */
+   assign(src13, get_dpr_dw0(4)); /* get source from FPR 4,6 */
+   assign(dst13, binop(Iop_D64toF32, irrm, mkexpr(src13)));
+   put_fpr_w0(0, mkexpr(dst13)); /* put the result in FPR 0,2 */
+   put_gpr_w1(1, mkU32(0x0));
+   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_64, src13, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_D64_TO_F32)));
+
+   /* D64 -> F64 */
+   assign(src14, get_dpr_dw0(4)); /* get source from FPR 4,6 */
+   assign(dst14, binop(Iop_D64toF64, irrm, mkexpr(src14)));
+   put_fpr_dw0(0, mkexpr(dst14)); /* put the result in FPR 0,2 */
+   put_gpr_w1(1, mkU32(0x0));
+   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_64, src14, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_D64_TO_F64)));
+
+   /* D64 -> F128 */
+   assign(src15, get_dpr_dw0(4)); /* get source from FPR 4,6 */
+   assign(dst15, binop(Iop_D64toF128, irrm, mkexpr(src15)));
+   put_fpr_pair(0, mkexpr(dst15)); /* put the result in FPR 0,2 */
+   put_gpr_w1(1, mkU32(0x0));
+   s390_cc_thunk_putFZ(S390_CC_OP_PFPO_64, src15, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_D64_TO_F128)));
+
+   /* D128 -> F32 */
+   assign(src16, get_dpr_pair(4)); /* get source from FPR 4,6 */
+   assign(dst16, binop(Iop_D128toF32, irrm, mkexpr(src16)));
+   put_fpr_w0(0, mkexpr(dst16)); /* put the result in FPR 0,2 */
+   put_gpr_w1(1, mkU32(0x0));
+   s390_cc_thunk_put1d128Z(S390_CC_OP_PFPO_128, src16, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_D128_TO_F32)));
+
+   /* D128 -> F64 */
+   assign(src17, get_dpr_pair(4)); /* get source from FPR 4,6 */
+   assign(dst17, binop(Iop_D128toF64, irrm, mkexpr(src17)));
+   put_fpr_dw0(0, mkexpr(dst17)); /* put the result in FPR 0,2 */
+   put_gpr_w1(1, mkU32(0x0));
+   s390_cc_thunk_put1d128Z(S390_CC_OP_PFPO_128, src17, gr0);
+   next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_D128_TO_F64)));
+
    /* D128 -> F128 */
-   assign(src6, get_dpr_pair(4)); /* get source from FPR 4,6 */
-   assign(dst6, binop(Iop_D128toF128, irrm, mkexpr(src6)));
-   put_fpr_pair(0, mkexpr(dst6)); /* put the result in FPR 0,2 */
+   assign(src18, get_dpr_pair(4)); /* get source from FPR 4,6 */
+   assign(dst18, binop(Iop_D128toF128, irrm, mkexpr(src18)));
+   put_fpr_pair(0, mkexpr(dst18)); /* put the result in FPR 0,2 */
    put_gpr_w1(1, mkU32(0x0));
-   s390_cc_thunk_put1d128Z(S390_CC_OP_PFPO_128, src6, gr0);
+   s390_cc_thunk_put1d128Z(S390_CC_OP_PFPO_128, src18, gr0);
    next_insn_if(binop(Iop_CmpEQ32, mkexpr(fn), mkU32(S390_PFPO_D128_TO_F128)));
 
    return "pfpo";
index e9dc34d781ce95961fd6d12ffc8ca67eee090839..7a3eab7d500ad905d9690fd2de0e3d28a8a747e8 100644 (file)
@@ -6923,11 +6923,23 @@ s390_insn_as_string(const s390_insn *insn)
       s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
 
       switch (fp_convert->tag) {
-      case S390_FP_F64_TO_D64:   op = "v-f2d"; break;
-      case S390_FP_D64_TO_F64:   op = "v-d2f"; break;
-      case S390_FP_F64_TO_D128:  op = "v-f2d"; break;
-      case S390_FP_D128_TO_F64:  op = "v-d2f"; break;
+      case S390_FP_F32_TO_D32:
+      case S390_FP_F32_TO_D64:
+      case S390_FP_F32_TO_D128:
+      case S390_FP_F64_TO_D32:
+      case S390_FP_F64_TO_D64:
+      case S390_FP_F64_TO_D128:
+      case S390_FP_F128_TO_D32:
+      case S390_FP_F128_TO_D64:
       case S390_FP_F128_TO_D128: op = "v-f2d"; break;
+      case S390_FP_D32_TO_F32:
+      case S390_FP_D32_TO_F64:
+      case S390_FP_D32_TO_F128:
+      case S390_FP_D64_TO_F32:
+      case S390_FP_D64_TO_F64:
+      case S390_FP_D64_TO_F128:
+      case S390_FP_D128_TO_F32:
+      case S390_FP_D128_TO_F64:
       case S390_FP_D128_TO_F128: op = "v-d2f"; break;
       default: goto fail;
       }
@@ -7096,11 +7108,23 @@ s390_insn_as_string(const s390_insn *insn)
       s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
 
       switch (fp_convert->tag) {
+      case S390_FP_F32_TO_D32:
+      case S390_FP_F32_TO_D64:
+      case S390_FP_F32_TO_D128:
+      case S390_FP_D32_TO_F32:
+      case S390_FP_D32_TO_F64:
+      case S390_FP_D32_TO_F128:  p += vex_sprintf(p, "4 -> "); goto common;
+      case S390_FP_F64_TO_D32:
       case S390_FP_F64_TO_D64:
+      case S390_FP_F64_TO_D128:
+      case S390_FP_D64_TO_F32:
       case S390_FP_D64_TO_F64:
-      case S390_FP_F64_TO_D128:  p += vex_sprintf(p, "8 -> "); goto common;
-      case S390_FP_D128_TO_F64:
+      case S390_FP_D64_TO_F128:  p += vex_sprintf(p, "8 -> "); goto common;
+      case S390_FP_F128_TO_D32:
+      case S390_FP_F128_TO_D64:
       case S390_FP_F128_TO_D128:
+      case S390_FP_D128_TO_F32:
+      case S390_FP_D128_TO_F64:
       case S390_FP_D128_TO_F128: p += vex_sprintf(p, "16 -> "); goto common;
       default:
          goto common;
@@ -9317,11 +9341,23 @@ s390_insn_fp_convert_emit(UChar *buf, const s390_insn *insn)
    vassert(rm < 2 || rm > 7);
 
    switch (fp_convert->tag) {
+   case S390_FP_F32_TO_D32:   pfpo = S390_PFPO_F32_TO_D32   << 8; break;
+   case S390_FP_F32_TO_D64:   pfpo = S390_PFPO_F32_TO_D64   << 8; break;
+   case S390_FP_F32_TO_D128:  pfpo = S390_PFPO_F32_TO_D128  << 8; break;
+   case S390_FP_F64_TO_D32:   pfpo = S390_PFPO_F64_TO_D32   << 8; break;
    case S390_FP_F64_TO_D64:   pfpo = S390_PFPO_F64_TO_D64   << 8; break;
-   case S390_FP_D64_TO_F64:   pfpo = S390_PFPO_D64_TO_F64   << 8; break;
    case S390_FP_F64_TO_D128:  pfpo = S390_PFPO_F64_TO_D128  << 8; break;
-   case S390_FP_D128_TO_F64:  pfpo = S390_PFPO_D128_TO_F64  << 8; break;
+   case S390_FP_F128_TO_D32:  pfpo = S390_PFPO_F128_TO_D32  << 8; break;
+   case S390_FP_F128_TO_D64:  pfpo = S390_PFPO_F128_TO_D64  << 8; break;
    case S390_FP_F128_TO_D128: pfpo = S390_PFPO_F128_TO_D128 << 8; break;
+   case S390_FP_D32_TO_F32:   pfpo = S390_PFPO_D32_TO_F32   << 8; break;
+   case S390_FP_D32_TO_F64:   pfpo = S390_PFPO_D32_TO_F64   << 8; break;
+   case S390_FP_D32_TO_F128:  pfpo = S390_PFPO_D32_TO_F128  << 8; break;
+   case S390_FP_D64_TO_F32:   pfpo = S390_PFPO_D64_TO_F32   << 8; break;
+   case S390_FP_D64_TO_F64:   pfpo = S390_PFPO_D64_TO_F64   << 8; break;
+   case S390_FP_D64_TO_F128:  pfpo = S390_PFPO_D64_TO_F128  << 8; break;
+   case S390_FP_D128_TO_F32:  pfpo = S390_PFPO_D128_TO_F32  << 8; break;
+   case S390_FP_D128_TO_F64:  pfpo = S390_PFPO_D128_TO_F64  << 8; break;
    case S390_FP_D128_TO_F128: pfpo = S390_PFPO_D128_TO_F128 << 8; break;
    default: goto fail;
    }
index c6a91fc172e67c78484ef234ad49286f9810c8af..3fca721fcfe4542cbf4ccd0739567624f10acf06 100644 (file)
@@ -268,11 +268,23 @@ typedef enum {
 } s390_dfp_conv_t;
 
 typedef enum {
+   S390_FP_F32_TO_D32,
+   S390_FP_F32_TO_D64,
+   S390_FP_F32_TO_D128,
+   S390_FP_F64_TO_D32,
    S390_FP_F64_TO_D64,
-   S390_FP_D64_TO_F64,
    S390_FP_F64_TO_D128,
-   S390_FP_D128_TO_F64,
+   S390_FP_F128_TO_D32,
+   S390_FP_F128_TO_D64,
    S390_FP_F128_TO_D128,
+   S390_FP_D32_TO_F32,
+   S390_FP_D32_TO_F64,
+   S390_FP_D32_TO_F128,
+   S390_FP_D64_TO_F32,
+   S390_FP_D64_TO_F64,
+   S390_FP_D64_TO_F128,
+   S390_FP_D128_TO_F32,
+   S390_FP_D128_TO_F64,
    S390_FP_D128_TO_F128
 } s390_fp_conv_t;
 
index c20bf592b87e83845ac26ac177abc7e13c21e8e2..d84125d8ab17d4476bfc3658085d59373140ab77 100644 (file)
@@ -1974,6 +1974,45 @@ s390_isel_float128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env,
          *dst_lo = s390_isel_float_expr(env, expr->Iex.Binop.arg2);
          return;
 
+      case Iop_D32toF128:
+      case Iop_D64toF128: {
+         IRExpr *irrm;
+         IRExpr *left;
+         s390_dfp_round_t rm;
+         HReg h1; /* virtual reg. to hold source */
+         HReg f0, f2, f4, r1; /* real registers used by PFPO */
+         s390_fp_conv_t fpconv;
+
+         switch (expr->Iex.Binop.op) {
+         case Iop_D32toF128:
+            fpconv = S390_FP_D32_TO_F128;
+            break;
+         case Iop_D64toF128:
+            fpconv = S390_FP_D64_TO_F128;
+            break;
+         default: goto irreducible;
+         }
+
+         f4 = make_fpr(4); /* source */
+         f0 = make_fpr(0); /* destination */
+         f2 = make_fpr(2); /* destination */
+         r1 = make_gpr(1); /* GPR #1 clobbered */
+         irrm = expr->Iex.Binop.arg1;
+         left = expr->Iex.Binop.arg2;
+         rm = get_dfp_rounding_mode(env, irrm);
+         h1 = s390_isel_dfp_expr(env, left);
+         addInstr(env, s390_insn_move(8, f4, h1));
+         addInstr(env, s390_insn_fp128_convert(16, fpconv, f0, f2,
+                                               f4, INVALID_HREG, r1, rm));
+         /* (f0, f2) --> destination */
+         *dst_hi = newVRegF(env);
+         *dst_lo = newVRegF(env);
+         addInstr(env, s390_insn_move(8, *dst_hi, f0));
+         addInstr(env, s390_insn_move(8, *dst_lo, f2));
+
+         return;
+      }
+
       case Iop_D128toF128: {
          IRExpr *irrm;
          IRExpr *left;
@@ -2246,7 +2285,11 @@ s390_isel_float_expr_wrk(ISelEnv *env, IRExpr *expr)
       case Iop_I64StoF64: conv = S390_BFP_I64_TO_F64; goto convert_int;
       case Iop_I64UtoF32: conv = S390_BFP_U64_TO_F32; goto convert_int;
       case Iop_I64UtoF64: conv = S390_BFP_U64_TO_F64; goto convert_int;
+      case Iop_D32toF32:  fpconv = S390_FP_D32_TO_F32;  goto convert_dfp;
+      case Iop_D32toF64:  fpconv = S390_FP_D32_TO_F64;  goto convert_dfp;
+      case Iop_D64toF32:  fpconv = S390_FP_D64_TO_F32;  goto convert_dfp;
       case Iop_D64toF64:  fpconv = S390_FP_D64_TO_F64;  goto convert_dfp;
+      case Iop_D128toF32: fpconv = S390_FP_D128_TO_F32; goto convert_dfp128;
       case Iop_D128toF64: fpconv = S390_FP_D128_TO_F64; goto convert_dfp128;
 
       convert_float:
@@ -2638,12 +2681,24 @@ s390_isel_dfp128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env,
          return;
       }
 
+      case Iop_F32toD128:
       case Iop_F64toD128: {
          IRExpr *irrm;
          IRExpr *left;
          s390_dfp_round_t rm;
          HReg h1; /* virtual reg. to hold source */
          HReg f0, f2, f4, r1; /* real registers used by PFPO */
+         s390_fp_conv_t fpconv;
+
+         switch (expr->Iex.Binop.op) {
+         case Iop_F32toD128:       /* (D128, I64) -> D128 */
+            fpconv = S390_FP_F32_TO_D128;
+            break;
+         case Iop_F64toD128:       /* (D128, I64) -> D128 */
+            fpconv = S390_FP_F64_TO_D128;
+            break;
+         default: goto irreducible;
+         }
 
          f4 = make_fpr(4); /* source */
          f0 = make_fpr(0); /* destination */
@@ -2654,7 +2709,7 @@ s390_isel_dfp128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env,
          rm = get_dfp_rounding_mode(env, irrm);
          h1 = s390_isel_float_expr(env, left);
          addInstr(env, s390_insn_move(8, f4, h1));
-         addInstr(env, s390_insn_fp128_convert(16, S390_FP_F64_TO_D128, f0, f2,
+         addInstr(env, s390_insn_fp128_convert(16, fpconv, f0, f2,
                                                f4, INVALID_HREG, r1, rm));
          /* (f0, f2) --> destination */
          *dst_hi = newVRegF(env);
@@ -2823,7 +2878,12 @@ s390_isel_dfp_expr_wrk(ISelEnv *env, IRExpr *expr)
       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;
+      case Iop_F32toD32:  fpconv = S390_FP_F32_TO_D32; goto convert_bfp;
+      case Iop_F32toD64:  fpconv = S390_FP_F32_TO_D64; goto convert_bfp;
+      case Iop_F64toD32:  fpconv = S390_FP_F64_TO_D32; goto convert_bfp;
       case Iop_F64toD64:  fpconv = S390_FP_F64_TO_D64; goto convert_bfp;
+      case Iop_F128toD32: fpconv = S390_FP_F128_TO_D32; goto convert_bfp128;
+      case Iop_F128toD64: fpconv = S390_FP_F128_TO_D64; goto convert_bfp128;
 
       convert_dfp:
          h1 = s390_isel_dfp_expr(env, left);
@@ -2867,6 +2927,28 @@ s390_isel_dfp_expr_wrk(ISelEnv *env, IRExpr *expr)
          return dst;
       }
 
+      convert_bfp128: {
+         s390_dfp_round_t rm;
+         HReg op_hi, op_lo;
+         HReg f0, f4, f6, r1; /* real registers used by PFPO */
+
+         f4 = make_fpr(4); /* source */
+         f6 = make_fpr(6); /* source */
+         f0 = make_fpr(0); /* destination */
+         r1 = make_gpr(1); /* GPR #1 clobbered */
+         s390_isel_float128_expr(&op_hi, &op_lo, env, left);
+         dst = newVRegF(env);
+         rm = get_dfp_rounding_mode(env, irrm);
+         /* operand --> (f4, f6) */
+         addInstr(env, s390_insn_move(8, f4, op_hi));
+         addInstr(env, s390_insn_move(8, f6, op_lo));
+         addInstr(env, s390_insn_fp128_convert(16, fpconv, f0, INVALID_HREG,
+                                               f4, f6, r1, rm));
+         /* f0 --> destination */
+         addInstr(env, s390_insn_move(8, dst, f0));
+         return dst;
+      }
+
       case Iop_D128toD64: {
          HReg op_hi, op_lo, f13, f15;
          s390_dfp_round_t rounding_mode;
index 9a3ef3d67e555c51c764362688bbf86355fbdbbf..7d576eea50b4f32fa997d9976f9d9cf10cd52b56 100644 (file)
@@ -123,14 +123,26 @@ typedef enum {
    S390_FPC_DFP_ROUND_PREPARE_SHORT    = 7
 } s390_fpc_dfp_round_t;
 
-/* PFPO function code as it is encoded in bits [33:55] of GP0
+/* PFPO function code as it is encoded in bits [33:55] of GR0
    when PFPO insn is executed. */
 typedef enum {
+   S390_PFPO_F32_TO_D32   = 0x010805,
+   S390_PFPO_F32_TO_D64   = 0x010905,
+   S390_PFPO_F32_TO_D128  = 0x010A05,
+   S390_PFPO_F64_TO_D32   = 0x010806,
    S390_PFPO_F64_TO_D64   = 0x010906,
-   S390_PFPO_D64_TO_F64   = 0x010609,
    S390_PFPO_F64_TO_D128  = 0x010A06,
-   S390_PFPO_D128_TO_F64  = 0x01060A,
+   S390_PFPO_F128_TO_D32  = 0x010807,
+   S390_PFPO_F128_TO_D64  = 0x010907,
    S390_PFPO_F128_TO_D128 = 0x010A07,
+   S390_PFPO_D32_TO_F32   = 0x010508,
+   S390_PFPO_D32_TO_F64   = 0x010608,
+   S390_PFPO_D32_TO_F128  = 0x010708,
+   S390_PFPO_D64_TO_F32   = 0x010509,
+   S390_PFPO_D64_TO_F64   = 0x010609,
+   S390_PFPO_D64_TO_F128  = 0x010709,
+   S390_PFPO_D128_TO_F32  = 0x01050A,
+   S390_PFPO_D128_TO_F64  = 0x01060A,
    S390_PFPO_D128_TO_F128 = 0x01070A
 } s390_pfpo_function_t;