]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
s390: Add support for the "convert from/to logical" instruction family.
authorFlorian Krohm <florian@eich-krohm.de>
Sat, 1 Sep 2012 00:12:11 +0000 (00:12 +0000)
committerFlorian Krohm <florian@eich-krohm.de>
Sat, 1 Sep 2012 00:12:11 +0000 (00:12 +0000)
A few (7) new IROps are introduced.
Patch by Christian Borntraeger (borntraeger@de.ibm.com).
Fixes bugzilla #274695.

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

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/ir_defs.c
VEX/pub/libvex_ir.h

index 56c06ec897cb0bbcdee8227b55dcf63a7186233e..dad843dbe0a9bcbea255f7d4935fa0f0e92a2539 100644 (file)
@@ -131,7 +131,13 @@ enum {
    S390_CC_OP_BFP_TDC_32 = 32,
    S390_CC_OP_BFP_TDC_64 = 33,
    S390_CC_OP_BFP_TDC_128 = 34,
-   S390_CC_OP_SET = 35
+   S390_CC_OP_SET = 35,
+   S390_CC_OP_BFP_32_TO_UINT_32 = 36,
+   S390_CC_OP_BFP_64_TO_UINT_32 = 37,
+   S390_CC_OP_BFP_128_TO_UINT_32 = 38,
+   S390_CC_OP_BFP_32_TO_UINT_64 = 39,
+   S390_CC_OP_BFP_64_TO_UINT_64 = 40,
+   S390_CC_OP_BFP_128_TO_UINT_64 = 41
 };
 
 /*------------------------------------------------------------*/
@@ -182,6 +188,12 @@ enum {
    | S390_CC_OP_BFP_TDC_64          | F value               | Z class              |             |
    | S390_CC_OP_BFP_TDC_128         | F value hi 64 bits    | F value low 64 bits  | Z class     |
    | S390_CC_OP_SET                 | Z condition code      |                      |             |
+   | S390_CC_OP_BFP_32_TO_UINT_32   | F source              |                      |             |
+   | S390_CC_OP_BFP_64_TO_UINT_32   | F source              |                      |             |
+   | S390_CC_OP_BFP_128_TO_UINT_32  | F source hi 64 bits   | F source low 64 bits |             |
+   | S390_CC_OP_BFP_32_TO_UINT_64   | F source              |                      |             |
+   | S390_CC_OP_BFP_64_TO_UINT_64   | F source              |                      |             |
+   | S390_CC_OP_BFP_128_TO_UINT_64  | F source hi 64 bits   | F source low 64 bits |             |
    +--------------------------------+-----------------------+----------------------+-------------+
 */
 
index 81d6727daab31c520a90db575bd1d2a7660a25b8..1cd315bcf171fcfbad27303a2ee2e5532fc463ec 100644 (file)
@@ -944,6 +944,16 @@ ULong s390_do_ecag(ULong op2addr) { return 0; }
    psw >> 28;   /* cc */ \
 })
 
+#define S390_CC_FOR_BFP_UCONVERT(opcode,cc_dep1) \
+({ \
+   __asm__ volatile ( \
+        opcode ",0,%[op],0,0\n\t" \
+        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
+                                   : [op]  "f"(cc_dep1) \
+                                   : "cc", "r0");\
+   psw >> 28;   /* cc */ \
+})
+
 #define S390_CC_FOR_BFP128_CONVERT(opcode,hi,lo) \
 ({ \
    __asm__ volatile ( \
@@ -956,6 +966,18 @@ ULong s390_do_ecag(ULong op2addr) { return 0; }
    psw >> 28;   /* cc */ \
 })
 
+#define S390_CC_FOR_BFP128_UCONVERT(opcode,hi,lo) \
+({ \
+   __asm__ volatile ( \
+        "ldr   4,%[high]\n\t" \
+        "ldr   6,%[low]\n\t" \
+        opcode ",0,4,0,0\n\t" \
+        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
+                                   : [high] "f"(hi), [low] "f"(lo) \
+                                   : "cc", "r0", "f4", "f6");\
+   psw >> 28;   /* cc */ \
+})
+
 #define S390_CC_FOR_BFP_TDC(opcode,cc_dep1,cc_dep2) \
 ({ \
    __asm__ volatile ( \
@@ -1179,6 +1201,25 @@ s390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep)
    case S390_CC_OP_SET:
       return cc_dep1;
 
+   case S390_CC_OP_BFP_32_TO_UINT_32:
+      return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39c0000", cc_dep1);
+
+   case S390_CC_OP_BFP_64_TO_UINT_32:
+      return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39d0000", cc_dep1);
+
+   case S390_CC_OP_BFP_128_TO_UINT_32:
+      return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb39e0000", cc_dep1, cc_dep2);
+
+   case S390_CC_OP_BFP_32_TO_UINT_64:
+      return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ac0000", cc_dep1);
+
+   case S390_CC_OP_BFP_64_TO_UINT_64:
+      return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ad0000", cc_dep1);
+
+   case S390_CC_OP_BFP_128_TO_UINT_64:
+      return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb3ae0000", cc_dep1, cc_dep2);
+
+
    default:
       break;
    }
index d7e18dd2ae63717df43b6dd2446fee4477edd828..0aece5b282188561d4363c35a7287bbd6c5d6ebb 100644 (file)
@@ -1702,6 +1702,27 @@ s390_format_RRF_F0FF(HChar *(*irgen)(UChar, UChar, UChar),
       s390_disasm(ENC4(MNM, FPR, FPR, FPR), mnm, r1, r3, r2);
 }
 
+static void
+s390_format_RRF_UUFR(HChar *(*irgen)(UChar m3, UChar m4, UChar r1, UChar r2),
+                     UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   HChar *mnm = irgen(m3, m4, r1, r2);
+
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_FE))
+      s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), mnm, r1, m3, r2, m4);
+}
+
+static void
+s390_format_RRF_UURF(HChar *(*irgen)(UChar m3, UChar m4, UChar r1, UChar r2),
+                     UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   HChar *mnm = irgen(m3, m4, r1, r2);
+
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_FE))
+      s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), mnm, r1, m3, r2, m4);
+}
+
+
 static void
 s390_format_RRF_U0RR(HChar *(*irgen)(UChar m3, UChar r1, UChar r2),
                      UChar m3, UChar r1, UChar r2, Int xmnm_kind)
@@ -8250,6 +8271,121 @@ s390_irgen_CDGBR(UChar r1, UChar r2)
    return "cdgbr";
 }
 
+static HChar *
+s390_irgen_CELFBR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   IRTemp op2 = newTemp(Ity_I32);
+
+   assign(op2, get_gpr_w1(r2));
+   put_fpr_w0(r1, binop(Iop_I32UtoF32, mkU32(encode_rounding_mode(m3)),
+                                       mkexpr(op2)));
+
+   return "celfbr";
+}
+
+static HChar *
+s390_irgen_CDLFBR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   IRTemp op2 = newTemp(Ity_I32);
+
+   assign(op2, get_gpr_w1(r2));
+   put_fpr_dw0(r1, unop(Iop_I32UtoF64, mkexpr(op2)));
+
+   return "cdlfbr";
+}
+
+static HChar *
+s390_irgen_CELGBR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   IRTemp op2 = newTemp(Ity_I64);
+
+   assign(op2, get_gpr_dw0(r2));
+   put_fpr_w0(r1, binop(Iop_I64UtoF32, mkU32(encode_rounding_mode(m3)),
+                                       mkexpr(op2)));
+
+   return "celgbr";
+}
+
+static HChar *
+s390_irgen_CDLGBR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   IRTemp op2 = newTemp(Ity_I64);
+
+   assign(op2, get_gpr_dw0(r2));
+   put_fpr_dw0(r1, binop(Iop_I64UtoF64, mkU32(encode_rounding_mode(m3)),
+                                        mkexpr(op2)));
+
+   return "cdlgbr";
+}
+
+static HChar *
+s390_irgen_CLFEBR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   IRTemp op = newTemp(Ity_F32);
+   IRTemp result = newTemp(Ity_I32);
+
+   assign(op, get_fpr_w0(r2));
+   assign(result, binop(Iop_F32toI32U, mkU32(encode_rounding_mode(m3)),
+          mkexpr(op)));
+   put_gpr_w1(r1, mkexpr(result));
+   s390_cc_thunk_putF(S390_CC_OP_BFP_32_TO_UINT_32, op);
+
+   return "clfebr";
+}
+
+static HChar *
+s390_irgen_CLFDBR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   IRTemp op = newTemp(Ity_F64);
+   IRTemp result = newTemp(Ity_I32);
+
+   assign(op, get_fpr_dw0(r2));
+   assign(result, binop(Iop_F64toI32U, mkU32(encode_rounding_mode(m3)),
+          mkexpr(op)));
+   put_gpr_w1(r1, mkexpr(result));
+   s390_cc_thunk_putF(S390_CC_OP_BFP_64_TO_UINT_32, op);
+
+   return "clfdbr";
+}
+
+static HChar *
+s390_irgen_CLGEBR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   IRTemp op = newTemp(Ity_F32);
+   IRTemp result = newTemp(Ity_I64);
+
+   assign(op, get_fpr_w0(r2));
+   assign(result, binop(Iop_F32toI64U, mkU32(encode_rounding_mode(m3)),
+          mkexpr(op)));
+   put_gpr_dw0(r1, mkexpr(result));
+   s390_cc_thunk_putF(S390_CC_OP_BFP_32_TO_UINT_64, op);
+
+   return "clgebr";
+}
+
+static HChar *
+s390_irgen_CLGDBR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   IRTemp op = newTemp(Ity_F64);
+   IRTemp result = newTemp(Ity_I64);
+
+   assign(op, get_fpr_dw0(r2));
+   assign(result, binop(Iop_F64toI64U, mkU32(encode_rounding_mode(m3)),
+          mkexpr(op)));
+   put_gpr_dw0(r1, mkexpr(result));
+   s390_cc_thunk_putF(S390_CC_OP_BFP_64_TO_UINT_64, op);
+
+   return "clgdbr";
+}
+
 static HChar *
 s390_irgen_CFEBR(UChar r3, UChar r1, UChar r2)
 {
@@ -10145,6 +10281,19 @@ s390_irgen_CXFBR(UChar r1, UChar r2)
    return "cxfbr";
 }
 
+static HChar *
+s390_irgen_CXLFBR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   IRTemp op2 = newTemp(Ity_I32);
+
+   assign(op2, get_gpr_w1(r2));
+   put_fpr_pair(r1, unop(Iop_I32UtoF128, mkexpr(op2)));
+
+   return "cxlfbr";
+}
+
+
 static HChar *
 s390_irgen_CXGBR(UChar r1, UChar r2)
 {
@@ -10156,6 +10305,18 @@ s390_irgen_CXGBR(UChar r1, UChar r2)
    return "cxgbr";
 }
 
+static HChar *
+s390_irgen_CXLGBR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   IRTemp op2 = newTemp(Ity_I64);
+
+   assign(op2, get_gpr_dw0(r2));
+   put_fpr_pair(r1, unop(Iop_I64UtoF128, mkexpr(op2)));
+
+   return "cxlgbr";
+}
+
 static HChar *
 s390_irgen_CFXBR(UChar r3, UChar r1, UChar r2)
 {
@@ -10171,6 +10332,23 @@ s390_irgen_CFXBR(UChar r3, UChar r1, UChar r2)
    return "cfxbr";
 }
 
+static HChar *
+s390_irgen_CLFXBR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   IRTemp op = newTemp(Ity_F128);
+   IRTemp result = newTemp(Ity_I32);
+
+   assign(op, get_fpr_pair(r2));
+   assign(result, binop(Iop_F128toI32U, mkU32(encode_rounding_mode(m3)),
+                        mkexpr(op)));
+   put_gpr_w1(r1, mkexpr(result));
+   s390_cc_thunk_put1f128(S390_CC_OP_BFP_128_TO_UINT_32, op);
+
+   return "clfxbr";
+}
+
+
 static HChar *
 s390_irgen_CGXBR(UChar r3, UChar r1, UChar r2)
 {
@@ -10186,6 +10364,22 @@ s390_irgen_CGXBR(UChar r3, UChar r1, UChar r2)
    return "cgxbr";
 }
 
+static HChar *
+s390_irgen_CLGXBR(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   IRTemp op = newTemp(Ity_F128);
+   IRTemp result = newTemp(Ity_I64);
+
+   assign(op, get_fpr_pair(r2));
+   assign(result, binop(Iop_F128toI64U, mkU32(encode_rounding_mode(m3)),
+                        mkexpr(op)));
+   put_gpr_dw0(r1, mkexpr(result));
+   s390_cc_thunk_put1f128(S390_CC_OP_BFP_128_TO_UINT_64, op);
+
+   return "clgxbr";
+}
+
 static HChar *
 s390_irgen_DXBR(UChar r1, UChar r2)
 {
@@ -12004,7 +12198,7 @@ s390_decode_4byte_and_irgen(UChar *bytes)
       } RRF;
       struct {
          unsigned int op : 16;
-         unsigned int r3 :  4;
+         unsigned int m3 :  4;
          unsigned int m4 :  4;
          unsigned int r1 :  4;
          unsigned int r2 :  4;
@@ -12386,9 +12580,15 @@ s390_decode_4byte_and_irgen(UChar *bytes)
    case 0xb384: s390_format_RRE_R0(s390_irgen_SFPC, ovl.fmt.RRE.r1);  goto ok;
    case 0xb385: /* SFASR */ goto unimplemented;
    case 0xb38c: s390_format_RRE_R0(s390_irgen_EFPC, ovl.fmt.RRE.r1);  goto ok;
-   case 0xb390: /* CELFBR */ goto unimplemented;
-   case 0xb391: /* CDLFBR */ goto unimplemented;
-   case 0xb392: /* CXLFBR */ goto unimplemented;
+   case 0xb390: s390_format_RRF_UUFR(s390_irgen_CELFBR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb391: s390_format_RRF_UUFR(s390_irgen_CDLFBR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb392: s390_format_RRF_UUFR(s390_irgen_CXLFBR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
    case 0xb394: s390_format_RRE_FR(s390_irgen_CEFBR, ovl.fmt.RRE.r1,
                                    ovl.fmt.RRE.r2);  goto ok;
    case 0xb395: s390_format_RRE_FR(s390_irgen_CDFBR, ovl.fmt.RRE.r1,
@@ -12404,9 +12604,24 @@ s390_decode_4byte_and_irgen(UChar *bytes)
    case 0xb39a: s390_format_RRF_U0RF(s390_irgen_CFXBR, ovl.fmt.RRF3.r3,
                                      ovl.fmt.RRF3.r1, ovl.fmt.RRF3.r2);
                                      goto ok;
-   case 0xb3a0: /* CELGBR */ goto unimplemented;
-   case 0xb3a1: /* CDLGBR */ goto unimplemented;
-   case 0xb3a2: /* CXLGBR */ goto unimplemented;
+   case 0xb39c: s390_format_RRF_UURF(s390_irgen_CLFEBR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb39d: s390_format_RRF_UURF(s390_irgen_CLFDBR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb39e: s390_format_RRF_UURF(s390_irgen_CLFXBR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb3a0: s390_format_RRF_UUFR(s390_irgen_CELGBR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb3a1: s390_format_RRF_UUFR(s390_irgen_CDLGBR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb3a2: s390_format_RRF_UUFR(s390_irgen_CXLGBR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
    case 0xb3a4: s390_format_RRE_FR(s390_irgen_CEGBR, ovl.fmt.RRE.r1,
                                    ovl.fmt.RRE.r2);  goto ok;
    case 0xb3a5: s390_format_RRE_FR(s390_irgen_CDGBR, ovl.fmt.RRE.r1,
@@ -12422,6 +12637,15 @@ s390_decode_4byte_and_irgen(UChar *bytes)
    case 0xb3aa: s390_format_RRF_U0RF(s390_irgen_CGXBR, ovl.fmt.RRF3.r3,
                                      ovl.fmt.RRF3.r1, ovl.fmt.RRF3.r2);
                                      goto ok;
+   case 0xb3ac: s390_format_RRF_UURF(s390_irgen_CLGEBR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb3ad: s390_format_RRF_UURF(s390_irgen_CLGDBR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
+   case 0xb3ae: s390_format_RRF_UURF(s390_irgen_CLGXBR, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
    case 0xb3b4: /* CEFR */ goto unimplemented;
    case 0xb3b5: /* CDFR */ goto unimplemented;
    case 0xb3b6: /* CXFR */ goto unimplemented;
index aea1073d15ba4f07acbe31a57d84ea3299825070..96088eccde1afddd0ab4dc147ab92deea30ae04e 100644 (file)
@@ -1095,6 +1095,20 @@ emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
 }
 
 
+static UChar *
+emit_RRF2(UChar *p, UInt op, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   ULong the_insn = op;
+
+   the_insn |= ((ULong)m3) << 12;
+   the_insn |= ((ULong)m4) << 8;
+   the_insn |= ((ULong)r1) << 4;
+   the_insn |= ((ULong)r2) << 0;
+
+   return emit_4bytes(p, the_insn);
+}
+
+
 static UChar *
 emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
 {
@@ -3225,6 +3239,126 @@ s390_emit_CXGBR(UChar *p, UChar r1, UChar r2)
 }
 
 
+static UChar *
+s390_emit_CELFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celfbr", r1, m3, r2, m4);
+
+   return emit_RRF2(p, 0xb3900000, m3, m4, r1, r2);
+}
+
+
+static UChar *
+s390_emit_CDLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlfbr", r1, m3, r2, m4);
+
+   return emit_RRF2(p, 0xb3910000, m3, m4, r1, r2);
+}
+
+
+static UChar *
+s390_emit_CXLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlfbr", r1, m3, r2, m4);
+
+   return emit_RRF2(p, 0xb3920000, m3, m4, r1, r2);
+}
+
+
+static UChar *
+s390_emit_CELGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celgbr", r1, m3, r2, m4);
+
+   return emit_RRF2(p, 0xb3a00000, m3, m4, r1, r2);
+}
+
+
+static UChar *
+s390_emit_CDLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgbr", r1, m3, r2, m4);
+
+   return emit_RRF2(p, 0xb3a10000, m3, m4, r1, r2);
+}
+
+
+static UChar *
+s390_emit_CXLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgbr", r1, m3, r2, m4);
+
+   return emit_RRF2(p, 0xb3a20000, m3, m4, r1, r2);
+}
+
+
+static UChar *
+s390_emit_CLFEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfebr", r1, m3, r2, m4);
+
+   return emit_RRF2(p, 0xb39c0000, m3, m4, r1, r2);
+}
+
+
+static UChar *
+s390_emit_CLFDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdbr", r1, m3, r2, m4);
+
+   return emit_RRF2(p, 0xb39d0000, m3, m4, r1, r2);
+}
+
+
+static UChar *
+s390_emit_CLFXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxbr", r1, m3, r2, m4);
+
+   return emit_RRF2(p, 0xb39e0000, m3, m4, r1, r2);
+}
+
+
+static UChar *
+s390_emit_CLGEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgebr", r1, m3, r2, m4);
+
+   return emit_RRF2(p, 0xb3ac0000, m3, m4, r1, r2);
+}
+
+
+static UChar *
+s390_emit_CLGDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdbr", r1, m3, r2, m4);
+
+   return emit_RRF2(p, 0xb3ad0000, m3, m4, r1, r2);
+}
+
+
+static UChar *
+s390_emit_CLGXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxbr", r1, m3, r2, m4);
+
+   return emit_RRF2(p, 0xb3ae0000, m3, m4, r1, r2);
+}
+
+
 static UChar *
 s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
 {
@@ -5091,12 +5225,24 @@ s390_insn_as_string(const s390_insn *insn)
       case S390_BFP_I64_TO_F32:
       case S390_BFP_I64_TO_F64:
       case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
+      case S390_BFP_U32_TO_F32:
+      case S390_BFP_U32_TO_F64:
+      case S390_BFP_U32_TO_F128:
+      case S390_BFP_U64_TO_F32:
+      case S390_BFP_U64_TO_F64:
+      case S390_BFP_U64_TO_F128: op = "v-u2f"; break;
       case S390_BFP_F32_TO_I32:
       case S390_BFP_F32_TO_I64:
       case S390_BFP_F64_TO_I32:
       case S390_BFP_F64_TO_I64:
       case S390_BFP_F128_TO_I32:
       case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
+      case S390_BFP_F32_TO_U32:
+      case S390_BFP_F32_TO_U64:
+      case S390_BFP_F64_TO_U32:
+      case S390_BFP_F64_TO_U64:
+      case S390_BFP_F128_TO_U32:
+      case S390_BFP_F128_TO_U64: op = "v-f2u"; break;
       case S390_BFP_F32_TO_F64:
       case S390_BFP_F32_TO_F128:
       case S390_BFP_F64_TO_F32:
@@ -5140,8 +5286,12 @@ s390_insn_as_string(const s390_insn *insn)
       case S390_BFP_SQRT:        op = "v-fsqrt"; break;
       case S390_BFP_I32_TO_F128:
       case S390_BFP_I64_TO_F128: op = "v-i2f";   break;
+      case S390_BFP_U32_TO_F128:
+      case S390_BFP_U64_TO_F128: op = "v-u2f";   break;
       case S390_BFP_F128_TO_I32:
       case S390_BFP_F128_TO_I64: op = "v-f2i";   break;
+      case S390_BFP_F128_TO_U32:
+      case S390_BFP_F128_TO_U64: op = "v-f2u";   break;
       case S390_BFP_F32_TO_F128:
       case S390_BFP_F64_TO_F128:
       case S390_BFP_F128_TO_F32:
@@ -5241,19 +5391,31 @@ s390_insn_as_string(const s390_insn *insn)
       case S390_BFP_I32_TO_F32:
       case S390_BFP_I32_TO_F64:
       case S390_BFP_I32_TO_F128:
+      case S390_BFP_U32_TO_F32:
+      case S390_BFP_U32_TO_F64:
+      case S390_BFP_U32_TO_F128:
       case S390_BFP_F32_TO_I32:
       case S390_BFP_F32_TO_I64:
+      case S390_BFP_F32_TO_U32:
+      case S390_BFP_F32_TO_U64:
       case S390_BFP_F32_TO_F64:
       case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
       case S390_BFP_I64_TO_F32:
       case S390_BFP_I64_TO_F64:
       case S390_BFP_I64_TO_F128:
+      case S390_BFP_U64_TO_F32:
+      case S390_BFP_U64_TO_F64:
+      case S390_BFP_U64_TO_F128:
       case S390_BFP_F64_TO_I32:
       case S390_BFP_F64_TO_I64:
+      case S390_BFP_F64_TO_U32:
+      case S390_BFP_F64_TO_U64:
       case S390_BFP_F64_TO_F32:
       case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
       case S390_BFP_F128_TO_I32:
       case S390_BFP_F128_TO_I64:
+      case S390_BFP_F128_TO_U32:
+      case S390_BFP_F128_TO_U64:
       case S390_BFP_F128_TO_F32:
       case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
       default:
@@ -5265,11 +5427,15 @@ s390_insn_as_string(const s390_insn *insn)
    case S390_INSN_BFP128_CONVERT_FROM:
       switch (insn->variant.bfp128_unop.tag) {
       case S390_BFP_I32_TO_F128:
+      case S390_BFP_U32_TO_F128:
       case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
       case S390_BFP_I64_TO_F128:
+      case S390_BFP_U64_TO_F128:
       case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
       case S390_BFP_F128_TO_I32:
       case S390_BFP_F128_TO_I64:
+      case S390_BFP_F128_TO_U32:
+      case S390_BFP_F128_TO_U64:
       case S390_BFP_F128_TO_F32:
       case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
       default:
@@ -7134,6 +7300,13 @@ s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
    case S390_BFP_F64_TO_I32:  return s390_emit_CFDBR(buf, m3, r1, r2);
    case S390_BFP_F32_TO_I64:  return s390_emit_CGEBR(buf, m3, r1, r2);
    case S390_BFP_F64_TO_I64:  return s390_emit_CGDBR(buf, m3, r1, r2);
+
+   /* We leave m4 as 0 - as gcc */
+   case S390_BFP_F32_TO_U32:  return s390_emit_CLFEBR(buf, m3, 0, r1, r2);
+   case S390_BFP_F64_TO_U32:  return s390_emit_CLFDBR(buf, m3, 0, r1, r2);
+   case S390_BFP_F32_TO_U64:  return s390_emit_CLGEBR(buf, m3, 0, r1, r2);
+   case S390_BFP_F64_TO_U64:  return s390_emit_CLGDBR(buf, m3, 0, r1, r2);
+
    default: break;
    }
 
@@ -7187,6 +7360,14 @@ s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
    case S390_BFP_I64_TO_F64:  buf = s390_emit_CDGBR(buf, r1, r2); break;
    case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1, r2); break;
 
+   /* We leave m4 as 0 - as gcc */
+   case S390_BFP_U32_TO_F32:  buf = s390_emit_CELFBR(buf, m3, 0, r1, r2); break;
+   case S390_BFP_U32_TO_F64:  buf = s390_emit_CDLFBR(buf, m3, 0, r1, r2); break;
+   case S390_BFP_U32_TO_F128: buf = s390_emit_CXLFBR(buf, m3, 0, r1, r2); break;
+   case S390_BFP_U64_TO_F32:  buf = s390_emit_CELGBR(buf, m3, 0, r1, r2); break;
+   case S390_BFP_U64_TO_F64:  buf = s390_emit_CDLGBR(buf, m3, 0, r1, r2); break;
+   case S390_BFP_U64_TO_F128: buf = s390_emit_CXLGBR(buf, m3, 0, r1, r2); break;
+
    case S390_BFP_F32_TO_F64:  buf = s390_emit_LDEBR(buf, r1, r2); break;
    case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1, r2); break;
    case S390_BFP_F64_TO_F32:  buf = s390_emit_LEDBR(buf, r1, r2); break;
@@ -7354,6 +7535,11 @@ s390_insn_bfp128_convert_to_emit(UChar *buf, const s390_insn *insn)
    switch (insn->variant.bfp128_unop.tag) {
    case S390_BFP_I32_TO_F128: buf = s390_emit_CXFBR(buf, r1_hi, r2); break;
    case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1_hi, r2); break;
+   /* Rounding makes no sense -> m3 == 0. m4 is also 0 */
+   case S390_BFP_U32_TO_F128: buf = s390_emit_CXLFBR(buf, 0, 0, r1_hi, r2);
+                              break;
+   case S390_BFP_U64_TO_F128: buf = s390_emit_CXLGBR(buf, 0, 0, r1_hi, r2);
+                              break;
    case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1_hi, r2); break;
    case S390_BFP_F64_TO_F128: buf = s390_emit_LXDBR(buf, r1_hi, r2); break;
    default:  goto fail;
@@ -7389,6 +7575,12 @@ s390_insn_bfp128_convert_from_emit(UChar *buf, const s390_insn *insn)
    case S390_BFP_F128_TO_I64:
       return s390_emit_CGXBR(buf, rounding_mode, r1, r2_hi);
 
+   case S390_BFP_F128_TO_U32:
+      return s390_emit_CLFXBR(buf, rounding_mode, 0, r1, r2_hi);
+
+   case S390_BFP_F128_TO_U64:
+      return s390_emit_CLGXBR(buf, rounding_mode, 0, r1, r2_hi);
+
    default: break;
    }
 
index c967b0e7e0ba5cd104dd1c6176ce5f37ebfb2624..06491b8a03f048db70d6585dd1371e069e8824a8 100644 (file)
@@ -206,16 +206,28 @@ typedef enum {
    S390_BFP_I64_TO_F32,
    S390_BFP_I64_TO_F64,
    S390_BFP_I64_TO_F128,
+   S390_BFP_U32_TO_F32,
+   S390_BFP_U32_TO_F64,
+   S390_BFP_U32_TO_F128,
+   S390_BFP_U64_TO_F32,
+   S390_BFP_U64_TO_F64,
+   S390_BFP_U64_TO_F128,
    S390_BFP_F32_TO_I32,
    S390_BFP_F32_TO_I64,
+   S390_BFP_F32_TO_U32,
+   S390_BFP_F32_TO_U64,
    S390_BFP_F32_TO_F64,
    S390_BFP_F32_TO_F128,
    S390_BFP_F64_TO_I32,
    S390_BFP_F64_TO_I64,
+   S390_BFP_F64_TO_U32,
+   S390_BFP_F64_TO_U64,
    S390_BFP_F64_TO_F32,
    S390_BFP_F64_TO_F128,
    S390_BFP_F128_TO_I32,
    S390_BFP_F128_TO_I64,
+   S390_BFP_F128_TO_U32,
+   S390_BFP_F128_TO_U64,
    S390_BFP_F128_TO_F32,
    S390_BFP_F128_TO_F64
 } s390_bfp_unop_t;
index 8b673fa61dfd7b70d76d697529481ff4fe6f112a..abfd2a6f7c2a555cbe80ec15e5cddbc4e2c35303 100644 (file)
@@ -913,10 +913,16 @@ s390_isel_int_expr_wrk(ISelEnv *env, IRExpr *expr)
 
       case Iop_F32toI32S:  bfpop = S390_BFP_F32_TO_I32;  goto do_convert;
       case Iop_F32toI64S:  bfpop = S390_BFP_F32_TO_I64;  goto do_convert;
+      case Iop_F32toI32U:  bfpop = S390_BFP_F32_TO_U32;  goto do_convert;
+      case Iop_F32toI64U:  bfpop = S390_BFP_F32_TO_U64;  goto do_convert;
       case Iop_F64toI32S:  bfpop = S390_BFP_F64_TO_I32;  goto do_convert;
       case Iop_F64toI64S:  bfpop = S390_BFP_F64_TO_I64;  goto do_convert;
+      case Iop_F64toI32U:  bfpop = S390_BFP_F64_TO_U32;  goto do_convert;
+      case Iop_F64toI64U:  bfpop = S390_BFP_F64_TO_U64;  goto do_convert;
       case Iop_F128toI32S: bfpop = S390_BFP_F128_TO_I32; goto do_convert_128;
       case Iop_F128toI64S: bfpop = S390_BFP_F128_TO_I64; goto do_convert_128;
+      case Iop_F128toI32U: bfpop = S390_BFP_F128_TO_U32; goto do_convert_128;
+      case Iop_F128toI64U: bfpop = S390_BFP_F128_TO_U64; goto do_convert_128;
 
       do_convert: {
          s390_round_t rounding_mode;
@@ -1672,6 +1678,8 @@ s390_isel_float128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env,
       case Iop_AbsF128:       bfpop = S390_BFP_ABS;          goto float128_opnd;
       case Iop_I32StoF128:    bfpop = S390_BFP_I32_TO_F128;  goto convert_int;
       case Iop_I64StoF128:    bfpop = S390_BFP_I64_TO_F128;  goto convert_int;
+      case Iop_I32UtoF128:    bfpop = S390_BFP_U32_TO_F128;  goto convert_int;
+      case Iop_I64UtoF128:    bfpop = S390_BFP_U64_TO_F128;  goto convert_int;
       case Iop_F32toF128:     bfpop = S390_BFP_F32_TO_F128;  goto convert_float;
       case Iop_F64toF128:     bfpop = S390_BFP_F64_TO_F128;  goto convert_float;
       default:
@@ -1887,8 +1895,12 @@ s390_isel_float_expr_wrk(ISelEnv *env, IRExpr *expr)
          break;
 
       case Iop_I32StoF32: bfpop = S390_BFP_I32_TO_F32; break;
+      case Iop_I32UtoF32: bfpop = S390_BFP_U32_TO_F32; break;
       case Iop_I64StoF32: bfpop = S390_BFP_I64_TO_F32; break;
       case Iop_I64StoF64: bfpop = S390_BFP_I64_TO_F64; break;
+      case Iop_I64UtoF32: bfpop = S390_BFP_U64_TO_F32; break;
+      case Iop_I64UtoF64: bfpop = S390_BFP_U64_TO_F64; break;
+
       default:
          goto irreducible;
 
@@ -1972,13 +1984,14 @@ s390_isel_float_expr_wrk(ISelEnv *env, IRExpr *expr)
       case Iop_AbsF32:
       case Iop_AbsF64:        bfpop = S390_BFP_ABS;  break;
       case Iop_I32StoF64:     bfpop = S390_BFP_I32_TO_F64;  break;
+      case Iop_I32UtoF64:     bfpop = S390_BFP_U32_TO_F64;  break;
       case Iop_F32toF64:      bfpop = S390_BFP_F32_TO_F64;  break;
       default:
          goto irreducible;
       }
 
       /* Process operand */
-      if (op == Iop_I32StoF64)
+      if (op == Iop_I32StoF64 || op == Iop_I32UtoF64)
          h1 = s390_isel_int_expr(env, left);
       else if (bfpop == S390_BFP_NABS)
          h1 = s390_isel_float_expr(env, left->Iex.Unop.arg);
index f02523663674bd1eb53a07f0c13bf6d74c402a0f..8138d597309dad11935584efffd47e627373388e 100644 (file)
@@ -288,8 +288,12 @@ void ppIROp ( IROp op )
       case Iop_F128LOtoF64: vex_printf("F128LOtoF64"); return;
       case Iop_I32StoF128: vex_printf("I32StoF128"); return;
       case Iop_I64StoF128: vex_printf("I64StoF128"); return;
+      case Iop_I32UtoF128: vex_printf("I32UtoF128"); return;
+      case Iop_I64UtoF128: vex_printf("I64UtoF128"); return;
       case Iop_F128toI32S: vex_printf("F128toI32S"); return;
       case Iop_F128toI64S: vex_printf("F128toI64S"); return;
+      case Iop_F128toI32U: vex_printf("F128toI32U"); return;
+      case Iop_F128toI64U: vex_printf("F128toI64U"); return;
       case Iop_F32toF128:  vex_printf("F32toF128");  return;
       case Iop_F64toF128:  vex_printf("F64toF128");  return;
       case Iop_F128toF64:  vex_printf("F128toF64");  return;
@@ -365,12 +369,15 @@ void ppIROp ( IROp op )
       case Iop_F64toI32S: vex_printf("F64toI32S"); return;
       case Iop_F64toI64S: vex_printf("F64toI64S"); return;
       case Iop_F64toI64U: vex_printf("F64toI64U"); return;
+      case Iop_F32toI32U: vex_printf("F32toI32U");  return;
+      case Iop_F32toI64U: vex_printf("F32toI64U");  return;
 
       case Iop_F64toI32U: vex_printf("F64toI32U"); return;
 
       case Iop_I32StoF64: vex_printf("I32StoF64"); return;
       case Iop_I64StoF64: vex_printf("I64StoF64"); return;
       case Iop_I64UtoF64: vex_printf("I64UtoF64"); return;
+      case Iop_I32UtoF32: vex_printf("I32UtoF32"); return;
       case Iop_I64UtoF32: vex_printf("I64UtoF32"); return;
 
       case Iop_I32UtoF64: vex_printf("I32UtoF64"); return;
@@ -2418,7 +2425,10 @@ void typeOfPrimop ( IROp op,
 
       case Iop_F32toI32S: BINARY(ity_RMode,Ity_F32, Ity_I32);
       case Iop_F32toI64S: BINARY(ity_RMode,Ity_F32, Ity_I64);
+      case Iop_F32toI32U: BINARY(ity_RMode,Ity_F32, Ity_I32);
+      case Iop_F32toI64U: BINARY(ity_RMode,Ity_F32, Ity_I64);
 
+      case Iop_I32UtoF32: BINARY(ity_RMode,Ity_I32, Ity_F32);
       case Iop_I32StoF32: BINARY(ity_RMode,Ity_I32, Ity_F32);
       case Iop_I64StoF32: BINARY(ity_RMode,Ity_I64, Ity_F32);
 
@@ -2705,9 +2715,15 @@ void typeOfPrimop ( IROp op,
       case Iop_I32StoF128: UNARY(Ity_I32, Ity_F128);
       case Iop_I64StoF128: UNARY(Ity_I64, Ity_F128);
 
+      case Iop_I32UtoF128: UNARY(Ity_I32, Ity_F128);
+      case Iop_I64UtoF128: UNARY(Ity_I64, Ity_F128);
+
       case Iop_F128toI32S: BINARY(ity_RMode,Ity_F128, Ity_I32);
       case Iop_F128toI64S: BINARY(ity_RMode,Ity_F128, Ity_I64);
 
+      case Iop_F128toI32U: BINARY(ity_RMode,Ity_F128, Ity_I32);
+      case Iop_F128toI64U: BINARY(ity_RMode,Ity_F128, Ity_I64);
+
       case Iop_F32toF128: UNARY(Ity_F32, Ity_F128);
       case Iop_F64toF128: UNARY(Ity_F64, Ity_F128);
 
index 6886087899b2d4b506a612f806950d671fbdb1ba..ae397a19763b29ac0e93b7328254162ebe9665ec 100644 (file)
@@ -632,10 +632,13 @@ typedef
       Iop_I64UtoF64, /* IRRoundingMode(I32) x unsigned I64 -> F64 */
       Iop_I64UtoF32, /* IRRoundingMode(I32) x unsigned I64 -> F32 */
 
+      Iop_I32UtoF32, /* IRRoundingMode(I32) x unsigned I32 -> F32 */
       Iop_I32UtoF64, /*                       unsigned I32 -> F64 */
 
       Iop_F32toI32S, /* IRRoundingMode(I32) x F32 -> signed I32 */
       Iop_F32toI64S, /* IRRoundingMode(I32) x F32 -> signed I64 */
+      Iop_F32toI32U, /* IRRoundingMode(I32) x F32 -> unsigned I32 */
+      Iop_F32toI64U, /* IRRoundingMode(I32) x F32 -> unsigned I64 */
 
       Iop_I32StoF32, /* IRRoundingMode(I32) x signed I32 -> F32 */
       Iop_I64StoF32, /* IRRoundingMode(I32) x signed I64 -> F32 */
@@ -665,11 +668,15 @@ typedef
 
       Iop_I32StoF128, /*                signed I32  -> F128 */
       Iop_I64StoF128, /*                signed I64  -> F128 */
+      Iop_I32UtoF128, /*              unsigned I32  -> F128 */
+      Iop_I64UtoF128, /*              unsigned I64  -> F128 */
       Iop_F32toF128,  /*                       F32  -> F128 */
       Iop_F64toF128,  /*                       F64  -> F128 */
 
       Iop_F128toI32S, /* IRRoundingMode(I32) x F128 -> signed I32  */
       Iop_F128toI64S, /* IRRoundingMode(I32) x F128 -> signed I64  */
+      Iop_F128toI32U, /* IRRoundingMode(I32) x F128 -> unsigned I32  */
+      Iop_F128toI64U, /* IRRoundingMode(I32) x F128 -> unsigned I64  */
       Iop_F128toF64,  /* IRRoundingMode(I32) x F128 -> F64         */
       Iop_F128toF32,  /* IRRoundingMode(I32) x F128 -> F32         */