Blame valgrind-3.14.0-s390x-vec-float-point-code.patch

Mark Wielaard 802130
commit 600a0099a1eb2335a3f9563534c112e11817002b
Mark Wielaard 802130
Author: Vadim Barkov <vbrkov@gmail.com>
Mark Wielaard 802130
Date:   Fri Oct 5 13:51:49 2018 +0300
Mark Wielaard 69cd31
Mark Wielaard 802130
    Bug 385411 s390x: Add z13 vector floating point support
Mark Wielaard 802130
    
Mark Wielaard 802130
    This adds support for the z/Architecture vector FP instructions that were
Mark Wielaard 802130
    introduced with z13.
Mark Wielaard 802130
    
Mark Wielaard 802130
    The patch was contributed by Vadim Barkov, with some clean-up and minor
Mark Wielaard 802130
    adjustments by Andreas Arnez.
Mark Wielaard 69cd31
Mark Wielaard 69cd31
diff --git a/VEX/priv/guest_s390_defs.h b/VEX/priv/guest_s390_defs.h
Mark Wielaard 802130
index 3bfecbe..d72cc9f 100644
Mark Wielaard 69cd31
--- a/VEX/priv/guest_s390_defs.h
Mark Wielaard 69cd31
+++ b/VEX/priv/guest_s390_defs.h
Mark Wielaard 69cd31
@@ -281,7 +281,11 @@ enum {
Mark Wielaard 69cd31
    S390_VEC_OP_VMALH = 13,
Mark Wielaard 69cd31
    S390_VEC_OP_VCH = 14,
Mark Wielaard 69cd31
    S390_VEC_OP_VCHL = 15,
Mark Wielaard 69cd31
-   S390_VEC_OP_LAST = 16 // supposed to be the last element in enum
Mark Wielaard 69cd31
+   S390_VEC_OP_VFCE = 16,
Mark Wielaard 69cd31
+   S390_VEC_OP_VFCH = 17,
Mark Wielaard 69cd31
+   S390_VEC_OP_VFCHE = 18,
Mark Wielaard 69cd31
+   S390_VEC_OP_VFTCI = 19,
Mark Wielaard 69cd31
+   S390_VEC_OP_LAST = 20 // supposed to be the last element in enum
Mark Wielaard 69cd31
 } s390x_vec_op_t;
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
 /* Arguments of s390x_dirtyhelper_vec_op(...) which are packed into one
Mark Wielaard 69cd31
@@ -300,8 +304,10 @@ typedef union {
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
       unsigned int m4 : 4;        // field m4 of insn or zero if it's missing
Mark Wielaard 69cd31
       unsigned int m5 : 4;        // field m5 of insn or zero if it's missing
Mark Wielaard 69cd31
+      unsigned int m6 : 4;        // field m6 of insn or zero if it's missing
Mark Wielaard 69cd31
+      unsigned int i3 : 12;       // field i3 of insn or zero if it's missing
Mark Wielaard 69cd31
       unsigned int read_only: 1;  // don't write result to Guest State
Mark Wielaard 69cd31
-      unsigned int reserved : 27; // reserved for future
Mark Wielaard 69cd31
+      unsigned int reserved : 11; // reserved for future
Mark Wielaard 69cd31
    };
Mark Wielaard 69cd31
    ULong serialized;
Mark Wielaard 69cd31
 } s390x_vec_op_details_t;
Mark Wielaard 69cd31
diff --git a/VEX/priv/guest_s390_helpers.c b/VEX/priv/guest_s390_helpers.c
Mark Wielaard 802130
index d9773e7..5877743 100644
Mark Wielaard 69cd31
--- a/VEX/priv/guest_s390_helpers.c
Mark Wielaard 69cd31
+++ b/VEX/priv/guest_s390_helpers.c
Mark Wielaard 69cd31
@@ -2498,6 +2498,10 @@ s390x_dirtyhelper_vec_op(VexGuestS390XState *guest_state,
Mark Wielaard 69cd31
       {0xe7, 0xa9}, /* VMALH */
Mark Wielaard 69cd31
       {0xe7, 0xfb}, /* VCH */
Mark Wielaard 69cd31
       {0xe7, 0xf9}, /* VCHL */
Mark Wielaard 69cd31
+      {0xe7, 0xe8}, /* VFCE */
Mark Wielaard 69cd31
+      {0xe7, 0xeb}, /* VFCH */
Mark Wielaard 69cd31
+      {0xe7, 0xea}, /* VFCHE */
Mark Wielaard 69cd31
+      {0xe7, 0x4a}  /* VFTCI */
Mark Wielaard 69cd31
    };
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
    union {
Mark Wielaard 69cd31
@@ -2525,6 +2529,28 @@ s390x_dirtyhelper_vec_op(VexGuestS390XState *guest_state,
Mark Wielaard 69cd31
         unsigned int rxb : 4;
Mark Wielaard 69cd31
         unsigned int op2 : 8;
Mark Wielaard 69cd31
       } VRRd;
Mark Wielaard 69cd31
+      struct {
Mark Wielaard 802130
+         UInt op1 : 8;
Mark Wielaard 802130
+         UInt v1  : 4;
Mark Wielaard 802130
+         UInt v2  : 4;
Mark Wielaard 802130
+         UInt v3  : 4;
Mark Wielaard 802130
+         UInt     : 4;
Mark Wielaard 802130
+         UInt m6  : 4;
Mark Wielaard 802130
+         UInt m5  : 4;
Mark Wielaard 802130
+         UInt m4  : 4;
Mark Wielaard 802130
+         UInt rxb : 4;
Mark Wielaard 802130
+         UInt op2 : 8;
Mark Wielaard 69cd31
+      } VRRc;
Mark Wielaard 69cd31
+      struct {
Mark Wielaard 802130
+         UInt op1 : 8;
Mark Wielaard 802130
+         UInt v1  : 4;
Mark Wielaard 802130
+         UInt v2  : 4;
Mark Wielaard 802130
+         UInt i3  : 12;
Mark Wielaard 802130
+         UInt m5  : 4;
Mark Wielaard 802130
+         UInt m4  : 4;
Mark Wielaard 802130
+         UInt rxb : 4;
Mark Wielaard 802130
+         UInt op2 : 8;
Mark Wielaard 69cd31
+      } VRIe;
Mark Wielaard 69cd31
       UChar bytes[6];
Mark Wielaard 69cd31
    } the_insn;
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
@@ -2578,6 +2604,27 @@ s390x_dirtyhelper_vec_op(VexGuestS390XState *guest_state,
Mark Wielaard 69cd31
       the_insn.VRRd.m6 = d->m5;
Mark Wielaard 69cd31
       break;
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+   case S390_VEC_OP_VFCE:
Mark Wielaard 69cd31
+   case S390_VEC_OP_VFCH:
Mark Wielaard 69cd31
+   case S390_VEC_OP_VFCHE:
Mark Wielaard 69cd31
+      the_insn.VRRc.v1 = 1;
Mark Wielaard 69cd31
+      the_insn.VRRc.v2 = 2;
Mark Wielaard 69cd31
+      the_insn.VRRc.v3 = 3;
Mark Wielaard 69cd31
+      the_insn.VRRc.rxb = 0b1110;
Mark Wielaard 69cd31
+      the_insn.VRRc.m4 = d->m4;
Mark Wielaard 69cd31
+      the_insn.VRRc.m5 = d->m5;
Mark Wielaard 69cd31
+      the_insn.VRRc.m6 = d->m6;
Mark Wielaard 69cd31
+      break;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   case S390_VEC_OP_VFTCI:
Mark Wielaard 69cd31
+      the_insn.VRIe.v1 = 1;
Mark Wielaard 69cd31
+      the_insn.VRIe.v2 = 2;
Mark Wielaard 69cd31
+      the_insn.VRIe.rxb = 0b1100;
Mark Wielaard 69cd31
+      the_insn.VRIe.i3 = d->i3;
Mark Wielaard 69cd31
+      the_insn.VRIe.m4 = d->m4;
Mark Wielaard 69cd31
+      the_insn.VRIe.m5 = d->m5;
Mark Wielaard 69cd31
+      break;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
    default:
Mark Wielaard 69cd31
       vex_printf("operation = %d\n", d->op);
Mark Wielaard 69cd31
       vpanic("s390x_dirtyhelper_vec_op: unknown operation");
Mark Wielaard 69cd31
diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c
Mark Wielaard 802130
index 50a5a41..1c4ac39 100644
Mark Wielaard 69cd31
--- a/VEX/priv/guest_s390_toIR.c
Mark Wielaard 69cd31
+++ b/VEX/priv/guest_s390_toIR.c
Mark Wielaard 802130
@@ -86,6 +86,7 @@ typedef enum {
Mark Wielaard 802130
    S390_DECODE_UNKNOWN_INSN,
Mark Wielaard 802130
    S390_DECODE_UNIMPLEMENTED_INSN,
Mark Wielaard 802130
    S390_DECODE_UNKNOWN_SPECIAL_INSN,
Mark Wielaard 802130
+   S390_DECODE_SPECIFICATION_EXCEPTION,
Mark Wielaard 802130
    S390_DECODE_ERROR
Mark Wielaard 802130
 } s390_decode_t;
Mark Wielaard 802130
 
Mark Wielaard 802130
@@ -421,6 +422,26 @@ yield_if(IRExpr *condition)
Mark Wielaard 802130
                     S390X_GUEST_OFFSET(guest_IA)));
Mark Wielaard 802130
 }
Mark Wielaard 802130
 
Mark Wielaard 802130
+/* Convenience macro to yield a specification exception if the given condition
Mark Wielaard 802130
+   is not met.  Used to pass this type of decoding error up through the call
Mark Wielaard 802130
+   chain. */
Mark Wielaard 802130
+#define s390_insn_assert(mnm, cond)             \
Mark Wielaard 802130
+   do {                                         \
Mark Wielaard 802130
+      if (!(cond)) {                            \
Mark Wielaard 802130
+         dis_res->whatNext = Dis_StopHere;      \
Mark Wielaard 802130
+         dis_res->jk_StopHere = Ijk_NoDecode;   \
Mark Wielaard 802130
+         return (mnm);                          \
Mark Wielaard 802130
+      }                                         \
Mark Wielaard 802130
+   } while (0)
Mark Wielaard 802130
+
Mark Wielaard 802130
+/* Convenience function to check for a specification exception. */
Mark Wielaard 802130
+static Bool
Mark Wielaard 802130
+is_specification_exception(void)
Mark Wielaard 802130
+{
Mark Wielaard 802130
+   return (dis_res->whatNext == Dis_StopHere &&
Mark Wielaard 802130
+           dis_res->jk_StopHere == Ijk_NoDecode);
Mark Wielaard 802130
+}
Mark Wielaard 802130
+
Mark Wielaard 802130
 static __inline__ IRExpr *get_fpr_dw0(UInt);
Mark Wielaard 802130
 static __inline__ void    put_fpr_dw0(UInt, IRExpr *);
Mark Wielaard 802130
 static __inline__ IRExpr *get_dpr_dw0(UInt);
Mark Wielaard 802130
@@ -1770,6 +1791,11 @@ s390_vr_get_type(const UChar m)
Mark Wielaard 69cd31
 /* Determine if Zero Search (ZS) flag is set in m field */
Mark Wielaard 69cd31
 #define s390_vr_is_zs_set(m) (((m) & 0b0010) != 0)
Mark Wielaard 69cd31
 
Mark Wielaard 802130
+/* Check if the "Single-Element-Control" bit is set.
Mark Wielaard 69cd31
+   Used in vector FP instructions.
Mark Wielaard 69cd31
+ */
Mark Wielaard 69cd31
+#define s390_vr_is_single_element_control_set(m) (((m) & 0x8) != 0)
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
 /* Generates arg1 < arg2 (or arg1 <= arg2 if allow_equal == True) expression.
Mark Wielaard 69cd31
    Arguments must have V128 type and are treated as unsigned 128-bit numbers.
Mark Wielaard 69cd31
 */
Mark Wielaard 802130
@@ -2001,12 +2027,14 @@ s390_vr_offset_by_index(UInt archreg,IRType type, UChar index)
Mark Wielaard 69cd31
       return vr_offset(archreg) + sizeof(UShort) * index;
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
    case Ity_I32:
Mark Wielaard 69cd31
+   case Ity_F32:
Mark Wielaard 69cd31
       if(index > 3) {
Mark Wielaard 69cd31
          goto invalidIndex;
Mark Wielaard 69cd31
       }
Mark Wielaard 69cd31
       return vr_offset(archreg) + sizeof(UInt) * index;
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
    case Ity_I64:
Mark Wielaard 69cd31
+   case Ity_F64:
Mark Wielaard 69cd31
       if(index > 1) {
Mark Wielaard 69cd31
          goto invalidIndex;
Mark Wielaard 69cd31
       }
Mark Wielaard 802130
@@ -2237,8 +2265,8 @@ encode_bfp_rounding_mode(UChar mode)
Mark Wielaard 69cd31
    case S390_BFP_ROUND_PER_FPC:
Mark Wielaard 69cd31
       rm = get_bfp_rounding_mode_from_fpc();
Mark Wielaard 69cd31
       break;
Mark Wielaard 69cd31
-   case S390_BFP_ROUND_NEAREST_AWAY:  /* not supported */
Mark Wielaard 69cd31
-   case S390_BFP_ROUND_PREPARE_SHORT: /* not supported */
Mark Wielaard 69cd31
+   case S390_BFP_ROUND_NEAREST_AWAY:  rm = mkU32(Irrm_NEAREST_TIE_AWAY_0); break;
Mark Wielaard 69cd31
+   case S390_BFP_ROUND_PREPARE_SHORT: rm = mkU32(Irrm_PREPARE_SHORTER); break;
Mark Wielaard 69cd31
    case S390_BFP_ROUND_NEAREST_EVEN:  rm = mkU32(Irrm_NEAREST); break;
Mark Wielaard 69cd31
    case S390_BFP_ROUND_ZERO:          rm = mkU32(Irrm_ZERO);    break;
Mark Wielaard 69cd31
    case S390_BFP_ROUND_POSINF:        rm = mkU32(Irrm_PosINF);  break;
Mark Wielaard 802130
@@ -3524,6 +3552,26 @@ s390_format_VRI_VVIM(const HChar *(*irgen)(UChar v1, UChar v3, UShort i2, UChar
Mark Wielaard 69cd31
       s390_disasm(ENC5(MNM, VR, VR, UINT, UINT), mnm, v1, v3, i2, m4);
Mark Wielaard 69cd31
 }
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+static void
Mark Wielaard 802130
+s390_format_VRI_VVIMM(const HChar *(*irgen)(UChar v1, UChar v2, UShort i3,
Mark Wielaard 802130
+                                            UChar m4, UChar m5),
Mark Wielaard 802130
+                      UChar v1, UChar v2, UShort i3, UChar m4, UChar m5,
Mark Wielaard 802130
+                      UChar rxb)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   const HChar *mnm;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   if (!s390_host_has_vx) {
Mark Wielaard 69cd31
+      emulation_failure(EmFail_S390X_vx);
Mark Wielaard 69cd31
+      return;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   v1 = s390_vr_getVRindex(v1, 1, rxb);
Mark Wielaard 69cd31
+   v2 = s390_vr_getVRindex(v2, 2, rxb);
Mark Wielaard 69cd31
+   mnm = irgen(v1, v2, i3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   if (vex_traceflags & VEX_TRACE_FE)
Mark Wielaard 69cd31
+      s390_disasm(ENC6(MNM, VR, VR, UINT, UINT, UINT), mnm, v1, v2, i3, m4, m5);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
 static void
Mark Wielaard 69cd31
 s390_format_VRS_RRDVM(const HChar *(*irgen)(UChar r1, IRTemp op2addr, UChar v3,
Mark Wielaard 802130
@@ -3680,7 +3728,7 @@ s390_format_VRV_VVRDMT(const HChar *(*irgen)(UChar v1, IRTemp op2addr, UChar m3)
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
 static void
Mark Wielaard 69cd31
-s390_format_VRRd_VVVVMM(const HChar *(*irgen)(UChar v1, UChar v2, UChar v3,
Mark Wielaard 69cd31
+s390_format_VRR_VVVVMM(const HChar *(*irgen)(UChar v1, UChar v2, UChar v3,
Mark Wielaard 69cd31
                                               UChar v4, UChar m5, UChar m6),
Mark Wielaard 69cd31
                         UChar v1, UChar v2, UChar v3, UChar v4, UChar m5,
Mark Wielaard 69cd31
                         UChar m6, UChar rxb)
Mark Wielaard 802130
@@ -3794,6 +3842,92 @@ s390_format_VRRd_VVVVM(const HChar *(*irgen)(UChar v1, UChar v2, UChar v3,
Mark Wielaard 69cd31
 }
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+static void
Mark Wielaard 802130
+s390_format_VRRa_VVMMM(const HChar *(*irgen)(UChar v1, UChar v2, UChar m3,
Mark Wielaard 802130
+                                             UChar m4, UChar m5),
Mark Wielaard 802130
+                       UChar v1, UChar v2, UChar m3, UChar m4, UChar m5,
Mark Wielaard 802130
+                       UChar rxb)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   const HChar *mnm;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   if (!s390_host_has_vx) {
Mark Wielaard 69cd31
+      emulation_failure(EmFail_S390X_vx);
Mark Wielaard 69cd31
+      return;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   v1 = s390_vr_getVRindex(v1, 1, rxb);
Mark Wielaard 69cd31
+   v2 = s390_vr_getVRindex(v2, 2, rxb);
Mark Wielaard 69cd31
+   mnm = irgen(v1, v2, m3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   if (vex_traceflags & VEX_TRACE_FE)
Mark Wielaard 69cd31
+      s390_disasm(ENC6(MNM, VR, VR, UINT, UINT, UINT), mnm, v1, v2, m3, m4, m5);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static void
Mark Wielaard 802130
+s390_format_VRRa_VVVMM(const HChar *(*irgen)(UChar v1, UChar v2, UChar v3,
Mark Wielaard 802130
+                                             UChar m4, UChar m5),
Mark Wielaard 802130
+                       UChar v1, UChar v2, UChar v3, UChar m4, UChar m5,
Mark Wielaard 802130
+                       UChar rxb)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   const HChar *mnm;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   if (!s390_host_has_vx) {
Mark Wielaard 69cd31
+      emulation_failure(EmFail_S390X_vx);
Mark Wielaard 69cd31
+      return;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   v1 = s390_vr_getVRindex(v1, 1, rxb);
Mark Wielaard 69cd31
+   v2 = s390_vr_getVRindex(v2, 2, rxb);
Mark Wielaard 69cd31
+   v3 = s390_vr_getVRindex(v3, 3, rxb);
Mark Wielaard 69cd31
+   mnm = irgen(v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   if (vex_traceflags & VEX_TRACE_FE)
Mark Wielaard 69cd31
+      s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), mnm, v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static void
Mark Wielaard 802130
+s390_format_VRRa_VVMM(const HChar *(*irgen)(UChar v1, UChar v2, UChar m3,
Mark Wielaard 802130
+                                            UChar m4),
Mark Wielaard 69cd31
+                       UChar v1, UChar v2, UChar m3, UChar m4, UChar rxb)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   const HChar *mnm;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   if (!s390_host_has_vx) {
Mark Wielaard 69cd31
+      emulation_failure(EmFail_S390X_vx);
Mark Wielaard 69cd31
+      return;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   v1 = s390_vr_getVRindex(v1, 1, rxb);
Mark Wielaard 69cd31
+   v2 = s390_vr_getVRindex(v2, 2, rxb);
Mark Wielaard 69cd31
+   mnm = irgen(v1, v2, m3, m4);
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   if (vex_traceflags & VEX_TRACE_FE)
Mark Wielaard 69cd31
+      s390_disasm(ENC5(MNM, VR, VR, UINT, UINT), mnm, v1, v2, m3, m4);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static void
Mark Wielaard 802130
+s390_format_VRRa_VVVMMM(const HChar *(*irgen)(UChar v1, UChar v2, UChar v3,
Mark Wielaard 802130
+                                              UChar m4, UChar m5, UChar m6),
Mark Wielaard 802130
+                        UChar v1, UChar v2, UChar v3, UChar m4, UChar m5,
Mark Wielaard 802130
+                        UChar m6, UChar rxb)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   const HChar *mnm;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   if (!s390_host_has_vx) {
Mark Wielaard 69cd31
+      emulation_failure(EmFail_S390X_vx);
Mark Wielaard 69cd31
+      return;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   v1 = s390_vr_getVRindex(v1, 1, rxb);
Mark Wielaard 69cd31
+   v2 = s390_vr_getVRindex(v2, 2, rxb);
Mark Wielaard 69cd31
+   v3 = s390_vr_getVRindex(v3, 3, rxb);
Mark Wielaard 69cd31
+   mnm = irgen(v1, v2, v3, m4, m5, m6);
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   if (vex_traceflags & VEX_TRACE_FE)
Mark Wielaard 802130
+      s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT),
Mark Wielaard 802130
+                  mnm, v1, v2, v3, m4, m5, m6);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
 /*------------------------------------------------------------*/
Mark Wielaard 69cd31
 /*--- Build IR for opcodes                                 ---*/
Mark Wielaard 69cd31
 /*------------------------------------------------------------*/
Mark Wielaard 802130
@@ -17895,6 +18029,575 @@ s390_irgen_VMALH(UChar v1, UChar v2, UChar v3, UChar v4, UChar m5)
Mark Wielaard 69cd31
    return "vmalh";
Mark Wielaard 69cd31
 }
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+static void
Mark Wielaard 802130
+s390_vector_fp_convert(IROp op, IRType fromType, IRType toType,
Mark Wielaard 802130
+                       UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   Bool isSingleElementOp = s390_vr_is_single_element_control_set(m4);
Mark Wielaard 802130
+   UChar maxIndex = isSingleElementOp ? 0 : 1;
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   /* For Iop_F32toF64 we do this:
Mark Wielaard 69cd31
+      f32[0] -> f64[0]
Mark Wielaard 69cd31
+      f32[2] -> f64[1]
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+      For Iop_F64toF32 we do this:
Mark Wielaard 69cd31
+      f64[0] -> f32[0]
Mark Wielaard 69cd31
+      f64[1] -> f32[2]
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+      The magic below with scaling factors is used to achieve the logic
Mark Wielaard 802130
+      described above.
Mark Wielaard 69cd31
+   */
Mark Wielaard 69cd31
+   const UChar sourceIndexScaleFactor = (op == Iop_F32toF64) ? 2 : 1;
Mark Wielaard 69cd31
+   const UChar destinationIndexScaleFactor = (op == Iop_F64toF32) ? 2 : 1;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   const Bool isUnary = (op == Iop_F32toF64);
Mark Wielaard 69cd31
+   for (UChar i = 0; i <= maxIndex; i++) {
Mark Wielaard 69cd31
+      IRExpr* argument = get_vr(v2, fromType, i * sourceIndexScaleFactor);
Mark Wielaard 69cd31
+      IRExpr* result;
Mark Wielaard 802130
+      if (!isUnary) {
Mark Wielaard 69cd31
+         result = binop(op,
Mark Wielaard 69cd31
+                        mkexpr(encode_bfp_rounding_mode(m5)),
Mark Wielaard 69cd31
+                        argument);
Mark Wielaard 69cd31
+      } else {
Mark Wielaard 69cd31
+         result = unop(op, argument);
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+      put_vr(v1, toType, i * destinationIndexScaleFactor, result);
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   if (isSingleElementOp) {
Mark Wielaard 69cd31
+      put_vr_dw1(v1, mkU64(0));
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VCDG(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vcdg", m3 == 3);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   if (!s390_host_has_fpext && m5 != S390_BFP_ROUND_PER_FPC) {
Mark Wielaard 69cd31
+      emulation_warning(EmWarn_S390X_fpext_rounding);
Mark Wielaard 69cd31
+      m5 = S390_BFP_ROUND_PER_FPC;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   s390_vector_fp_convert(Iop_I64StoF64, Ity_I64, Ity_F64, v1, v2, m3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "vcdg";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VCDLG(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vcdlg", m3 == 3);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   if (!s390_host_has_fpext && m5 != S390_BFP_ROUND_PER_FPC) {
Mark Wielaard 69cd31
+      emulation_warning(EmWarn_S390X_fpext_rounding);
Mark Wielaard 69cd31
+      m5 = S390_BFP_ROUND_PER_FPC;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   s390_vector_fp_convert(Iop_I64UtoF64, Ity_I64, Ity_F64, v1, v2, m3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "vcdlg";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VCGD(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vcgd", m3 == 3);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   if (!s390_host_has_fpext && m5 != S390_BFP_ROUND_PER_FPC) {
Mark Wielaard 69cd31
+      emulation_warning(EmWarn_S390X_fpext_rounding);
Mark Wielaard 69cd31
+      m5 = S390_BFP_ROUND_PER_FPC;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   s390_vector_fp_convert(Iop_F64toI64S, Ity_F64, Ity_I64, v1, v2, m3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "vcgd";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VCLGD(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vclgd", m3 == 3);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   if (!s390_host_has_fpext && m5 != S390_BFP_ROUND_PER_FPC) {
Mark Wielaard 69cd31
+      emulation_warning(EmWarn_S390X_fpext_rounding);
Mark Wielaard 69cd31
+      m5 = S390_BFP_ROUND_PER_FPC;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   s390_vector_fp_convert(Iop_F64toI64U, Ity_F64, Ity_I64, v1, v2, m3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "vclgd";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VFI(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vfi", m3 == 3);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   if (!s390_host_has_fpext && m5 != S390_BFP_ROUND_PER_FPC) {
Mark Wielaard 69cd31
+      emulation_warning(EmWarn_S390X_fpext_rounding);
Mark Wielaard 69cd31
+      m5 = S390_BFP_ROUND_PER_FPC;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   s390_vector_fp_convert(Iop_RoundF64toInt, Ity_F64, Ity_F64,
Mark Wielaard 802130
+                          v1, v2, m3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "vcgld";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VLDE(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vlde", m3 == 2);
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   s390_vector_fp_convert(Iop_F32toF64, Ity_F32, Ity_F64, v1, v2, m3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "vlde";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VLED(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vled", m3 == 3);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   if (!s390_host_has_fpext && m5 != S390_BFP_ROUND_PER_FPC) {
Mark Wielaard 69cd31
+      m5 = S390_BFP_ROUND_PER_FPC;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   s390_vector_fp_convert(Iop_F64toF32, Ity_F64, Ity_F32, v1, v2, m3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   return "vled";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VFPSO(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vfpso", m3 == 3);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   IRExpr* result;
Mark Wielaard 69cd31
+   switch (m5) {
Mark Wielaard 802130
+   case 0: {
Mark Wielaard 69cd31
+      /* Invert sign */
Mark Wielaard 802130
+      if (!s390_vr_is_single_element_control_set(m4)) {
Mark Wielaard 69cd31
+         result = unop(Iop_Neg64Fx2, get_vr_qw(v2));
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+      else {
Mark Wielaard 802130
+         result = binop(Iop_64HLtoV128,
Mark Wielaard 802130
+                        unop(Iop_ReinterpF64asI64,
Mark Wielaard 802130
+                             unop(Iop_NegF64, get_vr(v2, Ity_F64, 0))),
Mark Wielaard 802130
+                        mkU64(0));
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+      break;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   case 1: {
Mark Wielaard 69cd31
+      /* Set sign to negative */
Mark Wielaard 69cd31
+      IRExpr* highHalf = mkU64(0x8000000000000000ULL);
Mark Wielaard 802130
+      if (!s390_vr_is_single_element_control_set(m4)) {
Mark Wielaard 69cd31
+         IRExpr* lowHalf = highHalf;
Mark Wielaard 69cd31
+         IRExpr* mask = binop(Iop_64HLtoV128, highHalf, lowHalf);
Mark Wielaard 69cd31
+         result = binop(Iop_OrV128, get_vr_qw(v2), mask);
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+      else {
Mark Wielaard 802130
+         result = binop(Iop_64HLtoV128,
Mark Wielaard 802130
+                        binop(Iop_Or64, get_vr_dw0(v2), highHalf),
Mark Wielaard 802130
+                        mkU64(0ULL));
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      break;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   case 2: {
Mark Wielaard 69cd31
+      /* Set sign to positive */
Mark Wielaard 802130
+      if (!s390_vr_is_single_element_control_set(m4)) {
Mark Wielaard 69cd31
+         result = unop(Iop_Abs64Fx2, get_vr_qw(v2));
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+      else {
Mark Wielaard 802130
+         result = binop(Iop_64HLtoV128,
Mark Wielaard 802130
+                        unop(Iop_ReinterpF64asI64,
Mark Wielaard 802130
+                             unop(Iop_AbsF64, get_vr(v2, Ity_F64, 0))),
Mark Wielaard 802130
+                        mkU64(0));
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      break;
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   default:
Mark Wielaard 69cd31
+      vpanic("s390_irgen_VFPSO: Invalid m5 value");
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   put_vr_qw(v1, result);
Mark Wielaard 802130
+   if (s390_vr_is_single_element_control_set(m4)) {
Mark Wielaard 802130
+      put_vr_dw1(v1, mkU64(0ULL));
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "vfpso";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static void s390x_vec_fp_binary_op(IROp generalOp, IROp singleElementOp,
Mark Wielaard 802130
+                                   UChar v1, UChar v2, UChar v3, UChar m4,
Mark Wielaard 802130
+                                   UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   IRExpr* result;
Mark Wielaard 802130
+   if (!s390_vr_is_single_element_control_set(m5)) {
Mark Wielaard 802130
+      result = triop(generalOp, get_bfp_rounding_mode_from_fpc(),
Mark Wielaard 802130
+                     get_vr_qw(v2), get_vr_qw(v3));
Mark Wielaard 69cd31
+   } else {
Mark Wielaard 802130
+      IRExpr* highHalf = triop(singleElementOp,
Mark Wielaard 802130
+                               get_bfp_rounding_mode_from_fpc(),
Mark Wielaard 802130
+                               get_vr(v2, Ity_F64, 0),
Mark Wielaard 802130
+                               get_vr(v3, Ity_F64, 0));
Mark Wielaard 802130
+      result = binop(Iop_64HLtoV128, unop(Iop_ReinterpF64asI64, highHalf),
Mark Wielaard 802130
+                     mkU64(0ULL));
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   put_vr_qw(v1, result);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static void s390x_vec_fp_unary_op(IROp generalOp, IROp singleElementOp,
Mark Wielaard 69cd31
+                                  UChar v1, UChar v2, UChar m3, UChar m4)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   IRExpr* result;
Mark Wielaard 802130
+   if (!s390_vr_is_single_element_control_set(m4)) {
Mark Wielaard 802130
+      result = binop(generalOp, get_bfp_rounding_mode_from_fpc(),
Mark Wielaard 802130
+                     get_vr_qw(v2));
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+   else {
Mark Wielaard 802130
+      IRExpr* highHalf = binop(singleElementOp,
Mark Wielaard 802130
+                               get_bfp_rounding_mode_from_fpc(),
Mark Wielaard 802130
+                               get_vr(v2, Ity_F64, 0));
Mark Wielaard 802130
+      result = binop(Iop_64HLtoV128, unop(Iop_ReinterpF64asI64, highHalf),
Mark Wielaard 802130
+                     mkU64(0ULL));
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   put_vr_qw(v1, result);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static void
Mark Wielaard 802130
+s390_vector_fp_mulAddOrSub(IROp singleElementOp,
Mark Wielaard 802130
+                           UChar v1, UChar v2, UChar v3, UChar v4,
Mark Wielaard 802130
+                           UChar m5, UChar m6)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   Bool isSingleElementOp = s390_vr_is_single_element_control_set(m5);
Mark Wielaard 69cd31
+   IRTemp irrm_temp = newTemp(Ity_I32);
Mark Wielaard 69cd31
+   assign(irrm_temp, get_bfp_rounding_mode_from_fpc());
Mark Wielaard 69cd31
+   IRExpr* irrm = mkexpr(irrm_temp);
Mark Wielaard 69cd31
+   IRExpr* result;
Mark Wielaard 802130
+   IRExpr* highHalf = qop(singleElementOp,
Mark Wielaard 802130
+                          irrm,
Mark Wielaard 802130
+                          get_vr(v2, Ity_F64, 0),
Mark Wielaard 802130
+                          get_vr(v3, Ity_F64, 0),
Mark Wielaard 802130
+                          get_vr(v4, Ity_F64, 0));
Mark Wielaard 802130
+
Mark Wielaard 802130
+   if (isSingleElementOp) {
Mark Wielaard 802130
+      result = binop(Iop_64HLtoV128, unop(Iop_ReinterpF64asI64, highHalf),
Mark Wielaard 802130
+                     mkU64(0ULL));
Mark Wielaard 69cd31
+   } else {
Mark Wielaard 802130
+      IRExpr* lowHalf = qop(singleElementOp,
Mark Wielaard 802130
+                            irrm,
Mark Wielaard 802130
+                            get_vr(v2, Ity_F64, 1),
Mark Wielaard 802130
+                            get_vr(v3, Ity_F64, 1),
Mark Wielaard 802130
+                            get_vr(v4, Ity_F64, 1));
Mark Wielaard 802130
+      result = binop(Iop_64HLtoV128, unop(Iop_ReinterpF64asI64, highHalf),
Mark Wielaard 802130
+                     unop(Iop_ReinterpF64asI64, lowHalf));
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   put_vr_qw(v1, result);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VFA(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vfa", m4 == 3);
Mark Wielaard 69cd31
+   s390x_vec_fp_binary_op(Iop_Add64Fx2, Iop_AddF64, v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+   return "vfa";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VFS(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vfs", m4 == 3);
Mark Wielaard 69cd31
+   s390x_vec_fp_binary_op(Iop_Sub64Fx2, Iop_SubF64, v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+   return "vfs";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VFM(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vfm", m4 == 3);
Mark Wielaard 69cd31
+   s390x_vec_fp_binary_op(Iop_Mul64Fx2, Iop_MulF64, v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+   return "vfm";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VFD(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vfd", m4 == 3);
Mark Wielaard 69cd31
+   s390x_vec_fp_binary_op(Iop_Div64Fx2, Iop_DivF64, v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+   return "vfd";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VFSQ(UChar v1, UChar v2, UChar m3, UChar m4)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vfsq", m3 == 3);
Mark Wielaard 69cd31
+   s390x_vec_fp_unary_op(Iop_Sqrt64Fx2, Iop_SqrtF64, v1, v2, m3, m4);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "vfsq";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VFMA(UChar v1, UChar v2, UChar v3, UChar v4, UChar m5, UChar m6)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vfma", m6 == 3);
Mark Wielaard 802130
+   s390_vector_fp_mulAddOrSub(Iop_MAddF64, v1, v2, v3, v4, m5, m6);
Mark Wielaard 69cd31
+   return "vfma";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VFMS(UChar v1, UChar v2, UChar v3, UChar v4, UChar m5, UChar m6)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vfms", m6 == 3);
Mark Wielaard 802130
+   s390_vector_fp_mulAddOrSub(Iop_MSubF64, v1, v2, v3, v4, m5, m6);
Mark Wielaard 69cd31
+   return "vfms";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_WFC(UChar v1, UChar v2, UChar m3, UChar m4)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("wfc", m3 == 3);
Mark Wielaard 802130
+   s390_insn_assert("wfc", m4 == 0);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   IRTemp cc_vex = newTemp(Ity_I32);
Mark Wielaard 802130
+   assign(cc_vex, binop(Iop_CmpF64,
Mark Wielaard 802130
+                        get_vr(v1, Ity_F64, 0), get_vr(v2, Ity_F64, 0)));
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   IRTemp cc_s390 = newTemp(Ity_I32);
Mark Wielaard 69cd31
+   assign(cc_s390, convert_vex_bfpcc_to_s390(cc_vex));
Mark Wielaard 69cd31
+   s390_cc_thunk_put1(S390_CC_OP_SET, cc_s390, False);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "wfc";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_WFK(UChar v1, UChar v2, UChar m3, UChar m4)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   s390_irgen_WFC(v1, v2, m3, m4);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "wfk";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VFCE(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5, UChar m6)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vfce", m4 == 3);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   Bool isSingleElementOp = s390_vr_is_single_element_control_set(m5);
Mark Wielaard 69cd31
+   if (!s390_vr_is_cs_set(m6)) {
Mark Wielaard 802130
+      if (!isSingleElementOp) {
Mark Wielaard 69cd31
+         put_vr_qw(v1, binop(Iop_CmpEQ64Fx2, get_vr_qw(v2), get_vr_qw(v3)));
Mark Wielaard 69cd31
+      } else {
Mark Wielaard 802130
+         IRExpr* comparisonResult = binop(Iop_CmpF64, get_vr(v2, Ity_F64, 0),
Mark Wielaard 802130
+                                          get_vr(v3, Ity_F64, 0));
Mark Wielaard 802130
+         IRExpr* result = mkite(binop(Iop_CmpEQ32, comparisonResult,
Mark Wielaard 802130
+                                      mkU32(Ircr_EQ)),
Mark Wielaard 69cd31
+                                mkU64(0xffffffffffffffffULL),
Mark Wielaard 69cd31
+                                mkU64(0ULL));
Mark Wielaard 69cd31
+         put_vr_qw(v1, binop(Iop_64HLtoV128, result, mkU64(0ULL)));
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+   } else {
Mark Wielaard 69cd31
+      IRDirty* d;
Mark Wielaard 69cd31
+      IRTemp cc = newTemp(Ity_I64);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      s390x_vec_op_details_t details = { .serialized = 0ULL };
Mark Wielaard 69cd31
+      details.op = S390_VEC_OP_VFCE;
Mark Wielaard 69cd31
+      details.v1 = v1;
Mark Wielaard 69cd31
+      details.v2 = v2;
Mark Wielaard 69cd31
+      details.v3 = v3;
Mark Wielaard 69cd31
+      details.m4 = m4;
Mark Wielaard 69cd31
+      details.m5 = m5;
Mark Wielaard 69cd31
+      details.m6 = m6;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_vec_op",
Mark Wielaard 69cd31
+                            &s390x_dirtyhelper_vec_op,
Mark Wielaard 69cd31
+                            mkIRExprVec_2(IRExpr_GSPTR(),
Mark Wielaard 69cd31
+                                          mkU64(details.serialized)));
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+      const UChar elementSize = isSingleElementOp ? sizeof(ULong) : sizeof(V128);
Mark Wielaard 69cd31
+      d->nFxState = 3;
Mark Wielaard 69cd31
+      vex_bzero(&d->fxState, sizeof(d->fxState));
Mark Wielaard 69cd31
+      d->fxState[0].fx = Ifx_Read;
Mark Wielaard 69cd31
+      d->fxState[0].offset = S390X_GUEST_OFFSET(guest_v0) + v2 * sizeof(V128);
Mark Wielaard 802130
+      d->fxState[0].size = elementSize;
Mark Wielaard 69cd31
+      d->fxState[1].fx = Ifx_Read;
Mark Wielaard 69cd31
+      d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v3 * sizeof(V128);
Mark Wielaard 802130
+      d->fxState[1].size = elementSize;
Mark Wielaard 69cd31
+      d->fxState[2].fx = Ifx_Write;
Mark Wielaard 69cd31
+      d->fxState[2].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128);
Mark Wielaard 69cd31
+      d->fxState[2].size = sizeof(V128);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      stmt(IRStmt_Dirty(d));
Mark Wielaard 69cd31
+      s390_cc_set(cc);
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "vfce";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VFCH(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5, UChar m6)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   vassert(m4 == 3);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   Bool isSingleElementOp = s390_vr_is_single_element_control_set(m5);
Mark Wielaard 69cd31
+   if (!s390_vr_is_cs_set(m6)) {
Mark Wielaard 802130
+      if (!isSingleElementOp) {
Mark Wielaard 69cd31
+         put_vr_qw(v1, binop(Iop_CmpLE64Fx2, get_vr_qw(v3), get_vr_qw(v2)));
Mark Wielaard 69cd31
+      } else {
Mark Wielaard 802130
+         IRExpr* comparisonResult = binop(Iop_CmpF64, get_vr(v2, Ity_F64, 0),
Mark Wielaard 802130
+                                          get_vr(v3, Ity_F64, 0));
Mark Wielaard 802130
+         IRExpr* result = mkite(binop(Iop_CmpEQ32, comparisonResult,
Mark Wielaard 802130
+                                      mkU32(Ircr_GT)),
Mark Wielaard 69cd31
+                                mkU64(0xffffffffffffffffULL),
Mark Wielaard 69cd31
+                                mkU64(0ULL));
Mark Wielaard 69cd31
+         put_vr_qw(v1, binop(Iop_64HLtoV128, result, mkU64(0ULL)));
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+   else {
Mark Wielaard 69cd31
+      IRDirty* d;
Mark Wielaard 69cd31
+      IRTemp cc = newTemp(Ity_I64);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      s390x_vec_op_details_t details = { .serialized = 0ULL };
Mark Wielaard 69cd31
+      details.op = S390_VEC_OP_VFCH;
Mark Wielaard 69cd31
+      details.v1 = v1;
Mark Wielaard 69cd31
+      details.v2 = v2;
Mark Wielaard 69cd31
+      details.v3 = v3;
Mark Wielaard 69cd31
+      details.m4 = m4;
Mark Wielaard 69cd31
+      details.m5 = m5;
Mark Wielaard 69cd31
+      details.m6 = m6;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_vec_op",
Mark Wielaard 69cd31
+                            &s390x_dirtyhelper_vec_op,
Mark Wielaard 69cd31
+                            mkIRExprVec_2(IRExpr_GSPTR(),
Mark Wielaard 69cd31
+                                          mkU64(details.serialized)));
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+      const UChar elementSize = isSingleElementOp ? sizeof(ULong) : sizeof(V128);
Mark Wielaard 69cd31
+      d->nFxState = 3;
Mark Wielaard 69cd31
+      vex_bzero(&d->fxState, sizeof(d->fxState));
Mark Wielaard 69cd31
+      d->fxState[0].fx = Ifx_Read;
Mark Wielaard 69cd31
+      d->fxState[0].offset = S390X_GUEST_OFFSET(guest_v0) + v2 * sizeof(V128);
Mark Wielaard 802130
+      d->fxState[0].size = elementSize;
Mark Wielaard 69cd31
+      d->fxState[1].fx = Ifx_Read;
Mark Wielaard 69cd31
+      d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v3 * sizeof(V128);
Mark Wielaard 802130
+      d->fxState[1].size = elementSize;
Mark Wielaard 69cd31
+      d->fxState[2].fx = Ifx_Write;
Mark Wielaard 69cd31
+      d->fxState[2].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128);
Mark Wielaard 69cd31
+      d->fxState[2].size = sizeof(V128);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      stmt(IRStmt_Dirty(d));
Mark Wielaard 69cd31
+      s390_cc_set(cc);
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "vfch";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VFCHE(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5, UChar m6)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vfche", m4 == 3);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   Bool isSingleElementOp = s390_vr_is_single_element_control_set(m5);
Mark Wielaard 69cd31
+   if (!s390_vr_is_cs_set(m6)) {
Mark Wielaard 802130
+      if (!isSingleElementOp) {
Mark Wielaard 69cd31
+         put_vr_qw(v1, binop(Iop_CmpLT64Fx2, get_vr_qw(v3), get_vr_qw(v2)));
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+      else {
Mark Wielaard 802130
+         IRExpr* comparisonResult = binop(Iop_CmpF64, get_vr(v3, Ity_F64, 0),
Mark Wielaard 802130
+                                          get_vr(v2, Ity_F64, 0));
Mark Wielaard 802130
+         IRExpr* result = mkite(binop(Iop_CmpEQ32, comparisonResult,
Mark Wielaard 802130
+                                      mkU32(Ircr_LT)),
Mark Wielaard 69cd31
+                                mkU64(0xffffffffffffffffULL),
Mark Wielaard 69cd31
+                                mkU64(0ULL));
Mark Wielaard 69cd31
+         put_vr_qw(v1, binop(Iop_64HLtoV128, result, mkU64(0ULL)));
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+   else {
Mark Wielaard 69cd31
+      IRDirty* d;
Mark Wielaard 69cd31
+      IRTemp cc = newTemp(Ity_I64);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      s390x_vec_op_details_t details = { .serialized = 0ULL };
Mark Wielaard 69cd31
+      details.op = S390_VEC_OP_VFCHE;
Mark Wielaard 69cd31
+      details.v1 = v1;
Mark Wielaard 69cd31
+      details.v2 = v2;
Mark Wielaard 69cd31
+      details.v3 = v3;
Mark Wielaard 69cd31
+      details.m4 = m4;
Mark Wielaard 69cd31
+      details.m5 = m5;
Mark Wielaard 69cd31
+      details.m6 = m6;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_vec_op",
Mark Wielaard 69cd31
+                            &s390x_dirtyhelper_vec_op,
Mark Wielaard 69cd31
+                            mkIRExprVec_2(IRExpr_GSPTR(),
Mark Wielaard 69cd31
+                                          mkU64(details.serialized)));
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+      const UChar elementSize = isSingleElementOp ? sizeof(ULong) : sizeof(V128);
Mark Wielaard 69cd31
+      d->nFxState = 3;
Mark Wielaard 69cd31
+      vex_bzero(&d->fxState, sizeof(d->fxState));
Mark Wielaard 69cd31
+      d->fxState[0].fx = Ifx_Read;
Mark Wielaard 69cd31
+      d->fxState[0].offset = S390X_GUEST_OFFSET(guest_v0) + v2 * sizeof(V128);
Mark Wielaard 802130
+      d->fxState[0].size = elementSize;
Mark Wielaard 69cd31
+      d->fxState[1].fx = Ifx_Read;
Mark Wielaard 69cd31
+      d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v3 * sizeof(V128);
Mark Wielaard 802130
+      d->fxState[1].size = elementSize;
Mark Wielaard 69cd31
+      d->fxState[2].fx = Ifx_Write;
Mark Wielaard 69cd31
+      d->fxState[2].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128);
Mark Wielaard 69cd31
+      d->fxState[2].size = sizeof(V128);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      stmt(IRStmt_Dirty(d));
Mark Wielaard 69cd31
+      s390_cc_set(cc);
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "vfche";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static const HChar *
Mark Wielaard 69cd31
+s390_irgen_VFTCI(UChar v1, UChar v2, UShort i3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 802130
+   s390_insn_assert("vftci", m4 == 3);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   Bool isSingleElementOp = s390_vr_is_single_element_control_set(m5);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   IRDirty* d;
Mark Wielaard 69cd31
+   IRTemp cc = newTemp(Ity_I64);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   s390x_vec_op_details_t details = { .serialized = 0ULL };
Mark Wielaard 69cd31
+   details.op = S390_VEC_OP_VFTCI;
Mark Wielaard 69cd31
+   details.v1 = v1;
Mark Wielaard 69cd31
+   details.v2 = v2;
Mark Wielaard 69cd31
+   details.i3 = i3;
Mark Wielaard 69cd31
+   details.m4 = m4;
Mark Wielaard 69cd31
+   details.m5 = m5;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_vec_op",
Mark Wielaard 69cd31
+                         &s390x_dirtyhelper_vec_op,
Mark Wielaard 69cd31
+                         mkIRExprVec_2(IRExpr_GSPTR(),
Mark Wielaard 69cd31
+                                       mkU64(details.serialized)));
Mark Wielaard 69cd31
+
Mark Wielaard 802130
+   const UChar elementSize = isSingleElementOp ? sizeof(ULong) : sizeof(V128);
Mark Wielaard 69cd31
+   d->nFxState = 2;
Mark Wielaard 69cd31
+   vex_bzero(&d->fxState, sizeof(d->fxState));
Mark Wielaard 69cd31
+   d->fxState[0].fx = Ifx_Read;
Mark Wielaard 69cd31
+   d->fxState[0].offset = S390X_GUEST_OFFSET(guest_v0) + v2 * sizeof(V128);
Mark Wielaard 802130
+   d->fxState[0].size = elementSize;
Mark Wielaard 69cd31
+   d->fxState[1].fx = Ifx_Write;
Mark Wielaard 69cd31
+   d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128);
Mark Wielaard 69cd31
+   d->fxState[1].size = sizeof(V128);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   stmt(IRStmt_Dirty(d));
Mark Wielaard 69cd31
+   s390_cc_set(cc);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return "vftci";
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
 /* New insns are added here.
Mark Wielaard 69cd31
    If an insn is contingent on a facility being installed also
Mark Wielaard 69cd31
    check whether the list of supported facilities in function
Mark Wielaard 802130
@@ -19358,6 +20061,18 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
Mark Wielaard 69cd31
         unsigned int op2 : 8;
Mark Wielaard 69cd31
       } VRR;
Mark Wielaard 69cd31
       struct {
Mark Wielaard 802130
+         UInt op1 : 8;
Mark Wielaard 802130
+         UInt v1  : 4;
Mark Wielaard 802130
+         UInt v2  : 4;
Mark Wielaard 802130
+         UInt v3  : 4;
Mark Wielaard 802130
+         UInt     : 4;
Mark Wielaard 802130
+         UInt m5  : 4;
Mark Wielaard 802130
+         UInt m4  : 4;
Mark Wielaard 802130
+         UInt m3  : 4;
Mark Wielaard 802130
+         UInt rxb : 4;
Mark Wielaard 802130
+         UInt op2 : 8;
Mark Wielaard 802130
+      } VRRa;
Mark Wielaard 802130
+      struct {
Mark Wielaard 69cd31
         unsigned int op1 : 8;
Mark Wielaard 69cd31
         unsigned int v1  : 4;
Mark Wielaard 802130
         unsigned int v2  : 4;
Mark Wielaard 802130
@@ -19370,6 +20085,18 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
Mark Wielaard 69cd31
         unsigned int op2 : 8;
Mark Wielaard 69cd31
       } VRRd;
Mark Wielaard 802130
       struct {
Mark Wielaard 69cd31
+         unsigned int op1 : 8;
Mark Wielaard 69cd31
+         unsigned int v1  : 4;
Mark Wielaard 69cd31
+         unsigned int v2  : 4;
Mark Wielaard 69cd31
+         unsigned int v3  : 4;
Mark Wielaard 69cd31
+         unsigned int m6  : 4;
Mark Wielaard 69cd31
+         unsigned int     : 4;
Mark Wielaard 69cd31
+         unsigned int m5  : 4;
Mark Wielaard 69cd31
+         unsigned int v4  : 4;
Mark Wielaard 69cd31
+         unsigned int rxb : 4;
Mark Wielaard 69cd31
+         unsigned int op2 : 8;
Mark Wielaard 69cd31
+      } VRRe;
Mark Wielaard 802130
+      struct {
Mark Wielaard 69cd31
         unsigned int op1 : 8;
Mark Wielaard 69cd31
         unsigned int v1  : 4;
Mark Wielaard 802130
         unsigned int v3  : 4;
Mark Wielaard 802130
@@ -19390,6 +20117,16 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
Mark Wielaard 69cd31
         unsigned int op2 : 8;
Mark Wielaard 69cd31
       } VRId;
Mark Wielaard 69cd31
       struct {
Mark Wielaard 802130
+         UInt op1 : 8;
Mark Wielaard 802130
+         UInt v1  : 4;
Mark Wielaard 802130
+         UInt v2  : 4;
Mark Wielaard 802130
+         UInt i3  : 12;
Mark Wielaard 802130
+         UInt m5  : 4;
Mark Wielaard 802130
+         UInt m4  : 4;
Mark Wielaard 802130
+         UInt rxb : 4;
Mark Wielaard 802130
+         UInt op2 : 8;
Mark Wielaard 802130
+      } VRIe;
Mark Wielaard 802130
+      struct {
Mark Wielaard 69cd31
         unsigned int op1 : 8;
Mark Wielaard 69cd31
         unsigned int v1  : 4;
Mark Wielaard 802130
         unsigned int v3  : 4;
Mark Wielaard 802130
@@ -19974,7 +20711,10 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
Mark Wielaard 69cd31
    case 0xe70000000046ULL: s390_format_VRI_VIM(s390_irgen_VGM, ovl.fmt.VRI.v1,
Mark Wielaard 69cd31
                                                ovl.fmt.VRI.i2, ovl.fmt.VRI.m3,
Mark Wielaard 69cd31
                                                ovl.fmt.VRI.rxb);  goto ok;
Mark Wielaard 69cd31
-   case 0xe7000000004aULL: /* VFTCI */ goto unimplemented;
Mark Wielaard 69cd31
+   case 0xe7000000004aULL: s390_format_VRI_VVIMM(s390_irgen_VFTCI, ovl.fmt.VRIe.v1,
Mark Wielaard 69cd31
+                                                 ovl.fmt.VRIe.v2, ovl.fmt.VRIe.i3,
Mark Wielaard 69cd31
+                                                 ovl.fmt.VRIe.m4, ovl.fmt.VRIe.m5,
Mark Wielaard 69cd31
+                                                 ovl.fmt.VRIe.rxb);  goto ok;
Mark Wielaard 69cd31
    case 0xe7000000004dULL: s390_format_VRI_VVIM(s390_irgen_VREP, ovl.fmt.VRI.v1,
Mark Wielaard 69cd31
                                                ovl.fmt.VRI.v3, ovl.fmt.VRI.i2,
Mark Wielaard 69cd31
                                                ovl.fmt.VRI.m3, ovl.fmt.VRI.rxb);  goto ok;
Mark Wielaard 802130
@@ -20087,19 +20827,27 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
Mark Wielaard 69cd31
                                                ovl.fmt.VRR.v2, ovl.fmt.VRR.r3,
Mark Wielaard 69cd31
                                                ovl.fmt.VRR.m4, ovl.fmt.VRR.rxb);  goto ok;
Mark Wielaard 69cd31
    case 0xe70000000085ULL: /* VBPERM */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe7000000008aULL: s390_format_VRRd_VVVVMM(s390_irgen_VSTRC, ovl.fmt.VRRd.v1,
Mark Wielaard 69cd31
-                                                   ovl.fmt.VRRd.v2, ovl.fmt.VRRd.v3,
Mark Wielaard 69cd31
-                                                   ovl.fmt.VRRd.v4, ovl.fmt.VRRd.m5,
Mark Wielaard 69cd31
-                                                   ovl.fmt.VRRd.m6,
Mark Wielaard 69cd31
-                                                   ovl.fmt.VRRd.rxb);  goto ok;
Mark Wielaard 69cd31
+   case 0xe7000000008aULL: s390_format_VRR_VVVVMM(s390_irgen_VSTRC, ovl.fmt.VRRd.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRd.v2, ovl.fmt.VRRd.v3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRd.v4, ovl.fmt.VRRd.m5,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRd.m6,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRd.rxb);  goto ok;
Mark Wielaard 69cd31
    case 0xe7000000008cULL: s390_format_VRR_VVVV(s390_irgen_VPERM, ovl.fmt.VRR.v1,
Mark Wielaard 69cd31
                                                ovl.fmt.VRR.v2, ovl.fmt.VRR.r3,
Mark Wielaard 69cd31
                                                ovl.fmt.VRR.m4, ovl.fmt.VRR.rxb);  goto ok;
Mark Wielaard 69cd31
    case 0xe7000000008dULL: s390_format_VRR_VVVV(s390_irgen_VSEL, ovl.fmt.VRR.v1,
Mark Wielaard 69cd31
                                                ovl.fmt.VRR.v2, ovl.fmt.VRR.r3,
Mark Wielaard 69cd31
                                                ovl.fmt.VRR.m4, ovl.fmt.VRR.rxb);  goto ok;
Mark Wielaard 69cd31
-   case 0xe7000000008eULL: /* VFMS */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe7000000008fULL: /* VFMA */ goto unimplemented;
Mark Wielaard 69cd31
+   case 0xe7000000008eULL: s390_format_VRR_VVVVMM(s390_irgen_VFMS, ovl.fmt.VRRe.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRe.v2, ovl.fmt.VRRe.v3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRe.v4, ovl.fmt.VRRe.m5,
Mark Wielaard 802130
+                                                  ovl.fmt.VRRe.m6,
Mark Wielaard 802130
+                                                  ovl.fmt.VRRe.rxb);  goto ok;
Mark Wielaard 69cd31
+   case 0xe7000000008fULL: s390_format_VRR_VVVVMM(s390_irgen_VFMA, ovl.fmt.VRRe.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRe.v2, ovl.fmt.VRRe.v3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRe.v4, ovl.fmt.VRRe.m5,
Mark Wielaard 802130
+                                                  ovl.fmt.VRRe.m6,
Mark Wielaard 802130
+                                                  ovl.fmt.VRRe.rxb);  goto ok;
Mark Wielaard 69cd31
    case 0xe70000000094ULL: s390_format_VRR_VVVM(s390_irgen_VPK, ovl.fmt.VRR.v1,
Mark Wielaard 69cd31
                                                ovl.fmt.VRR.v2, ovl.fmt.VRR.r3,
Mark Wielaard 69cd31
                                                ovl.fmt.VRR.m4, ovl.fmt.VRR.rxb);  goto ok;
Mark Wielaard 802130
@@ -20184,17 +20932,50 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
Mark Wielaard 69cd31
                                                   ovl.fmt.VRRd.v2, ovl.fmt.VRRd.v3,
Mark Wielaard 69cd31
                                                   ovl.fmt.VRRd.v4, ovl.fmt.VRRd.m5,
Mark Wielaard 69cd31
                                                   ovl.fmt.VRRd.rxb);  goto ok;
Mark Wielaard 69cd31
-   case 0xe700000000c0ULL: /* VCLGD */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000c1ULL: /* VCDLG */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000c2ULL: /* VCGD */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000c3ULL: /* VCDG */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000c4ULL: /* VLDE */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000c5ULL: /* VLED */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000c7ULL: /* VFI */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000caULL: /* WFK */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000cbULL: /* WFC */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000ccULL: /* VFPSO */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000ceULL: /* VFSQ */ goto unimplemented;
Mark Wielaard 69cd31
+   case 0xe700000000c0ULL: s390_format_VRRa_VVMMM(s390_irgen_VCLGD, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.v2, ovl.fmt.VRRa.m3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.m4, ovl.fmt.VRRa.m5,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000c1ULL: s390_format_VRRa_VVMMM(s390_irgen_VCDLG, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.v2, ovl.fmt.VRRa.m3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.m4, ovl.fmt.VRRa.m5,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000c2ULL: s390_format_VRRa_VVMMM(s390_irgen_VCGD, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.v2, ovl.fmt.VRRa.m3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.m4, ovl.fmt.VRRa.m5,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000c3ULL: s390_format_VRRa_VVMMM(s390_irgen_VCDG, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.v2, ovl.fmt.VRRa.m3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.m4, ovl.fmt.VRRa.m5,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000c4ULL: s390_format_VRRa_VVMMM(s390_irgen_VLDE, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.v2, ovl.fmt.VRRa.m3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.m4, ovl.fmt.VRRa.m5,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000c5ULL: s390_format_VRRa_VVMMM(s390_irgen_VLED, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.v2, ovl.fmt.VRRa.m3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.m4, ovl.fmt.VRRa.m5,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000c7ULL: s390_format_VRRa_VVMMM(s390_irgen_VFI, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.v2, ovl.fmt.VRRa.m3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.m4, ovl.fmt.VRRa.m5,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000caULL: s390_format_VRRa_VVMM(s390_irgen_WFK, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                 ovl.fmt.VRRa.v2, ovl.fmt.VRRa.m3,
Mark Wielaard 802130
+                                                 ovl.fmt.VRRa.m4,
Mark Wielaard 802130
+                                                 ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000cbULL: s390_format_VRRa_VVMM(s390_irgen_WFC, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                 ovl.fmt.VRRa.v2, ovl.fmt.VRRa.m3,
Mark Wielaard 802130
+                                                 ovl.fmt.VRRa.m4,
Mark Wielaard 802130
+                                                 ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000ccULL: s390_format_VRRa_VVMMM(s390_irgen_VFPSO, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.v2, ovl.fmt.VRRa.m3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.m4, ovl.fmt.VRRa.m5,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000ceULL: s390_format_VRRa_VVMM(s390_irgen_VFSQ, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                 ovl.fmt.VRRa.v2, ovl.fmt.VRRa.m3,
Mark Wielaard 802130
+                                                 ovl.fmt.VRRa.m4,
Mark Wielaard 802130
+                                                 ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
    case 0xe700000000d4ULL: s390_format_VRR_VVM(s390_irgen_VUPLL, ovl.fmt.VRR.v1,
Mark Wielaard 69cd31
                                                ovl.fmt.VRR.v2, ovl.fmt.VRR.m4,
Mark Wielaard 69cd31
                                                ovl.fmt.VRR.rxb);  goto ok;
Mark Wielaard 802130
@@ -20221,13 +21002,37 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
Mark Wielaard 69cd31
    case 0xe700000000dfULL: s390_format_VRR_VVM(s390_irgen_VLP, ovl.fmt.VRR.v1,
Mark Wielaard 69cd31
                                                ovl.fmt.VRR.v2, ovl.fmt.VRR.m4,
Mark Wielaard 69cd31
                                                ovl.fmt.VRR.rxb);  goto ok;
Mark Wielaard 69cd31
-   case 0xe700000000e2ULL: /* VFS */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000e3ULL: /* VFA */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000e5ULL: /* VFD */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000e7ULL: /* VFM */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000e8ULL: /* VFCE */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000eaULL: /* VFCHE */ goto unimplemented;
Mark Wielaard 69cd31
-   case 0xe700000000ebULL: /* VFCH */ goto unimplemented;
Mark Wielaard 69cd31
+   case 0xe700000000e2ULL: s390_format_VRRa_VVVMM(s390_irgen_VFS, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.v2, ovl.fmt.VRRa.v3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.m3, ovl.fmt.VRRa.m4,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000e3ULL: s390_format_VRRa_VVVMM(s390_irgen_VFA, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.v2, ovl.fmt.VRRa.v3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.m3, ovl.fmt.VRRa.m4,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000e5ULL: s390_format_VRRa_VVVMM(s390_irgen_VFD, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.v2, ovl.fmt.VRRa.v3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.m3, ovl.fmt.VRRa.m4,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000e7ULL: s390_format_VRRa_VVVMM(s390_irgen_VFM, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.v2, ovl.fmt.VRRa.v3,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.m3, ovl.fmt.VRRa.m4,
Mark Wielaard 69cd31
+                                                  ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000e8ULL: s390_format_VRRa_VVVMMM(s390_irgen_VFCE, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                   ovl.fmt.VRRa.v2, ovl.fmt.VRRa.v3,
Mark Wielaard 69cd31
+                                                   ovl.fmt.VRRa.m3, ovl.fmt.VRRa.m4,
Mark Wielaard 802130
+                                                   ovl.fmt.VRRa.m5,
Mark Wielaard 802130
+                                                   ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000eaULL: s390_format_VRRa_VVVMMM(s390_irgen_VFCHE, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                   ovl.fmt.VRRa.v2, ovl.fmt.VRRa.v3,
Mark Wielaard 69cd31
+                                                   ovl.fmt.VRRa.m3, ovl.fmt.VRRa.m4,
Mark Wielaard 802130
+                                                   ovl.fmt.VRRa.m5,
Mark Wielaard 802130
+                                                   ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
+   case 0xe700000000ebULL: s390_format_VRRa_VVVMMM(s390_irgen_VFCH, ovl.fmt.VRRa.v1,
Mark Wielaard 69cd31
+                                                   ovl.fmt.VRRa.v2, ovl.fmt.VRRa.v3,
Mark Wielaard 69cd31
+                                                   ovl.fmt.VRRa.m3, ovl.fmt.VRRa.m4,
Mark Wielaard 802130
+                                                   ovl.fmt.VRRa.m5,
Mark Wielaard 802130
+                                                   ovl.fmt.VRRa.rxb); goto ok;
Mark Wielaard 69cd31
    case 0xe700000000eeULL: /* VFMIN */ goto unimplemented;
Mark Wielaard 69cd31
    case 0xe700000000efULL: /* VFMAX */ goto unimplemented;
Mark Wielaard 69cd31
    case 0xe700000000f0ULL: s390_format_VRR_VVVM(s390_irgen_VAVGL, ovl.fmt.VRR.v1,
Mark Wielaard 802130
@@ -21148,7 +21953,13 @@ s390_decode_and_irgen(const UChar *bytes, UInt insn_length, DisResult *dres)
Mark Wielaard 802130
       dis_res->jk_StopHere = Ijk_Boring;
Mark Wielaard 802130
    }
Mark Wielaard 802130
 
Mark Wielaard 802130
-   if (status == S390_DECODE_OK) return insn_length;  /* OK */
Mark Wielaard 802130
+   if (status == S390_DECODE_OK) {
Mark Wielaard 802130
+      /* Adjust status if a specification exception was indicated. */
Mark Wielaard 802130
+      if (is_specification_exception())
Mark Wielaard 802130
+         status = S390_DECODE_SPECIFICATION_EXCEPTION;
Mark Wielaard 802130
+      else
Mark Wielaard 802130
+         return insn_length;  /* OK */
Mark Wielaard 802130
+   }
Mark Wielaard 802130
 
Mark Wielaard 802130
    /* Decoding failed somehow */
Mark Wielaard 802130
    if (sigill_diag) {
Mark Wielaard 802130
@@ -21166,6 +21977,10 @@ s390_decode_and_irgen(const UChar *bytes, UInt insn_length, DisResult *dres)
Mark Wielaard 802130
          vex_printf("unimplemented special insn: ");
Mark Wielaard 802130
          break;
Mark Wielaard 802130
 
Mark Wielaard 802130
+      case S390_DECODE_SPECIFICATION_EXCEPTION:
Mark Wielaard 802130
+         vex_printf("specification exception: ");
Mark Wielaard 802130
+         break;
Mark Wielaard 802130
+
Mark Wielaard 802130
       case S390_DECODE_ERROR:
Mark Wielaard 802130
          vex_printf("decoding error: ");
Mark Wielaard 802130
          break;
Mark Wielaard 69cd31
diff --git a/VEX/priv/host_s390_defs.c b/VEX/priv/host_s390_defs.c
Mark Wielaard 802130
index 98ac938..22cdd04 100644
Mark Wielaard 69cd31
--- a/VEX/priv/host_s390_defs.c
Mark Wielaard 69cd31
+++ b/VEX/priv/host_s390_defs.c
Mark Wielaard 802130
@@ -1711,6 +1711,23 @@ emit_VRR_VVM(UChar *p, ULong op, UChar v1, UChar v2, UChar m4)
Mark Wielaard 69cd31
    return emit_6bytes(p, the_insn);
Mark Wielaard 69cd31
 }
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 802130
+emit_VRR_VVMMM(UChar *p, ULong op, UChar v1, UChar v2, UChar m3, UChar m4,
Mark Wielaard 802130
+               UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   ULong the_insn = op;
Mark Wielaard 69cd31
+   ULong rxb = s390_update_rxb(0, 1, &v1;;
Mark Wielaard 69cd31
+   rxb = s390_update_rxb(rxb, 2, &v2;;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   the_insn |= ((ULong)v1) << 36;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)v2) << 32;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)m5) << 20;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)m4) << 16;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)m3) << 12;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)rxb) << 8;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_6bytes(p, the_insn);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
 static UChar *
Mark Wielaard 69cd31
 emit_VRR_VVVM(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar m4)
Mark Wielaard 802130
@@ -1762,6 +1779,26 @@ emit_VRR_VVVV(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar v4)
Mark Wielaard 69cd31
    return emit_6bytes(p, the_insn);
Mark Wielaard 69cd31
 }
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 802130
+emit_VRRe_VVVVMM(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar v4,
Mark Wielaard 802130
+                 UChar m5, UChar m6)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   ULong the_insn = op;
Mark Wielaard 69cd31
+   ULong rxb = s390_update_rxb(0, 1, &v1;;
Mark Wielaard 69cd31
+   rxb = s390_update_rxb(rxb, 2, &v2;;
Mark Wielaard 69cd31
+   rxb = s390_update_rxb(rxb, 3, &v3;;
Mark Wielaard 69cd31
+   rxb = s390_update_rxb(rxb, 4, &v4;;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   the_insn |= ((ULong)v1) << 36;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)v2) << 32;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)v3) << 28;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)m6) << 24;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)m5) << 16;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)v4) << 12;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)rxb) << 8;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_6bytes(p, the_insn);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
 static UChar *
Mark Wielaard 69cd31
 emit_VRR_VRR(UChar *p, ULong op, UChar v1, UChar r2, UChar r3)
Mark Wielaard 802130
@@ -1777,6 +1814,33 @@ emit_VRR_VRR(UChar *p, ULong op, UChar v1, UChar r2, UChar r3)
Mark Wielaard 69cd31
    return emit_6bytes(p, the_insn);
Mark Wielaard 69cd31
 }
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 802130
+emit_VRR_VVVMMM(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar m4,
Mark Wielaard 802130
+                UChar m5, UChar m6)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   ULong the_insn = op;
Mark Wielaard 69cd31
+   ULong rxb = s390_update_rxb(0, 1, &v1;;
Mark Wielaard 69cd31
+   rxb = s390_update_rxb(rxb, 2, &v2;;
Mark Wielaard 69cd31
+   rxb = s390_update_rxb(rxb, 3, &v3;;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   the_insn |= ((ULong)v1) << 36;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)v2) << 32;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)v3) << 28;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)m6) << 20;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)m5) << 16;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)m4) << 12;
Mark Wielaard 69cd31
+   the_insn |= ((ULong)rxb) << 8;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_6bytes(p, the_insn);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static UChar*
Mark Wielaard 802130
+emit_VRR_VVVMM(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar m4,
Mark Wielaard 802130
+               UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   return emit_VRR_VVVMMM(p, op, v1, v2, v3, m4, m5, 0);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
 /*------------------------------------------------------------*/
Mark Wielaard 69cd31
 /*--- Functions to emit particular instructions            ---*/
Mark Wielaard 69cd31
 /*------------------------------------------------------------*/
Mark Wielaard 802130
@@ -6057,6 +6121,116 @@ s390_emit_VLVGP(UChar *p, UChar v1, UChar r2, UChar r3)
Mark Wielaard 69cd31
    return emit_VRR_VRR(p, 0xE70000000062ULL, v1, r2, r3);
Mark Wielaard 69cd31
 }
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 69cd31
+s390_emit_VFPSO(UChar *p, UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
Mark Wielaard 802130
+      s390_disasm(ENC6(MNM, VR, VR, UINT, UINT, UINT), "vfpso", v1, v2, m3, m4,
Mark Wielaard 802130
+                  m5);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_VRR_VVMMM(p, 0xE700000000CCULL, v1, v2, m3, m4, m5);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 69cd31
+s390_emit_VFA(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
Mark Wielaard 69cd31
+      s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vfa", v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_VRR_VVVMM(p, 0xE700000000e3ULL, v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 69cd31
+s390_emit_VFS(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
Mark Wielaard 69cd31
+      s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vfs", v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_VRR_VVVMM(p, 0xE700000000e2ULL, v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 69cd31
+s390_emit_VFM(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
Mark Wielaard 69cd31
+      s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vfm", v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_VRR_VVVMM(p, 0xE700000000e7ULL, v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 69cd31
+s390_emit_VFD(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
Mark Wielaard 69cd31
+      s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vfd", v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_VRR_VVVMM(p, 0xE700000000e5ULL, v1, v2, v3, m4, m5);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 69cd31
+s390_emit_VFSQ(UChar *p, UChar v1, UChar v2, UChar m3, UChar m4)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
Mark Wielaard 69cd31
+      s390_disasm(ENC5(MNM, VR, VR, UINT, UINT), "vfsq", v1, v2, m3, m4);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_VRR_VVMMM(p, 0xE700000000CEULL, v1, v2, m3, m4, 0);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 802130
+s390_emit_VFMA(UChar *p, UChar v1, UChar v2, UChar v3, UChar v4, UChar m5,
Mark Wielaard 802130
+               UChar m6)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
Mark Wielaard 802130
+      s390_disasm(ENC7(MNM, VR, VR, VR, VR, UINT, UINT), "vfma",
Mark Wielaard 802130
+                  v1, v2, v3, v4, m5, m6);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_VRRe_VVVVMM(p, 0xE7000000008fULL, v1, v2, v3, v4, m5, m6);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 802130
+s390_emit_VFMS(UChar *p, UChar v1, UChar v2, UChar v3, UChar v4, UChar m5,
Mark Wielaard 802130
+               UChar m6)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
Mark Wielaard 802130
+      s390_disasm(ENC7(MNM, VR, VR, VR, VR, UINT, UINT), "vfms",
Mark Wielaard 802130
+                  v1, v2, v3, v4, m5, m6);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_VRRe_VVVVMM(p, 0xE7000000008eULL, v1, v2, v3, v4, m5, m6);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 802130
+s390_emit_VFCE(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5,
Mark Wielaard 802130
+               UChar m6)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
Mark Wielaard 802130
+      s390_disasm(ENC7(MNM, VR, VR, VR, UINT, UINT, UINT), "vfce",
Mark Wielaard 802130
+                  v1, v2, v3, m4, m5, m6);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_VRR_VVVMMM(p, 0xE700000000e8ULL, v1, v2, v3, m4, m5, m6);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 802130
+s390_emit_VFCH(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5,
Mark Wielaard 802130
+               UChar m6)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
Mark Wielaard 802130
+      s390_disasm(ENC7(MNM, VR, VR, VR, UINT, UINT, UINT), "vfch",
Mark Wielaard 802130
+                  v1, v2, v3, m4, m5, m6);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_VRR_VVVMMM(p, 0xE700000000ebULL, v1, v2, v3, m4, m5, m6);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+static UChar *
Mark Wielaard 802130
+s390_emit_VFCHE(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5,
Mark Wielaard 802130
+                UChar m6)
Mark Wielaard 69cd31
+{
Mark Wielaard 69cd31
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
Mark Wielaard 802130
+      s390_disasm(ENC7(MNM, VR, VR, VR, UINT, UINT, UINT), "vfche",
Mark Wielaard 802130
+                  v1, v2, v3, m4, m5, m6);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+   return emit_VRR_VVVMMM(p, 0xE700000000eaULL, v1, v2, v3, m4, m5, m6);
Mark Wielaard 69cd31
+}
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
 /*---------------------------------------------------------------*/
Mark Wielaard 69cd31
 /*--- Constructors for the various s390_insn kinds            ---*/
Mark Wielaard 69cd31
 /*---------------------------------------------------------------*/
Mark Wielaard 802130
@@ -7201,7 +7375,6 @@ s390_insn *s390_insn_vec_triop(UChar size, s390_vec_triop_t tag, HReg dst,
Mark Wielaard 69cd31
 {
Mark Wielaard 69cd31
    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
-   vassert(size == 16);
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
    insn->tag  = S390_INSN_VEC_TRIOP;
Mark Wielaard 69cd31
    insn->size = size;
Mark Wielaard 802130
@@ -7508,6 +7681,18 @@ s390_insn_as_string(const s390_insn *insn)
Mark Wielaard 69cd31
          op = "v-vunpacku";
Mark Wielaard 69cd31
          break;
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_NEG:
Mark Wielaard 69cd31
+         op = "v-vfloatneg";
Mark Wielaard 69cd31
+         break;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_SQRT:
Mark Wielaard 69cd31
+         op = "v-vfloatsqrt";
Mark Wielaard 69cd31
+         break;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_ABS:
Mark Wielaard 69cd31
+         op = "v-vfloatabs";
Mark Wielaard 69cd31
+         break;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
       default:
Mark Wielaard 69cd31
          goto fail;
Mark Wielaard 69cd31
       }
Mark Wielaard 802130
@@ -7880,6 +8065,13 @@ s390_insn_as_string(const s390_insn *insn)
Mark Wielaard 69cd31
       case S390_VEC_PWSUM_DW:         op = "v-vpwsumdw"; break;
Mark Wielaard 69cd31
       case S390_VEC_PWSUM_QW:         op = "v-vpwsumqw"; break;
Mark Wielaard 69cd31
       case S390_VEC_INIT_FROM_GPRS:   op = "v-vinitfromgprs"; break;
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_ADD:        op = "v-vfloatadd"; break;
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_SUB:        op = "v-vfloatsub"; break;
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_MUL:        op = "v-vfloatmul"; break;
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_DIV:        op = "v-vfloatdiv"; break;
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_COMPARE_EQUAL: op = "v-vfloatcmpeq"; break;
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_COMPARE_LESS_OR_EQUAL:  op = "v-vfloatcmple"; break;
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_COMPARE_LESS: op = "v-vfloatcmpl"; break;
Mark Wielaard 69cd31
       default: goto fail;
Mark Wielaard 69cd31
       }
Mark Wielaard 69cd31
       s390_sprintf(buf, "%M %R, %R, %R", op, insn->variant.vec_binop.dst,
Mark Wielaard 802130
@@ -7889,6 +8081,8 @@ s390_insn_as_string(const s390_insn *insn)
Mark Wielaard 69cd31
    case S390_INSN_VEC_TRIOP:
Mark Wielaard 69cd31
       switch (insn->variant.vec_triop.tag) {
Mark Wielaard 69cd31
       case S390_VEC_PERM:  op = "v-vperm";  break;
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_MADD: op = "v-vfloatmadd"; break;
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_MSUB: op = "v-vfloatmsub"; break;
Mark Wielaard 69cd31
       default: goto fail;
Mark Wielaard 69cd31
       }
Mark Wielaard 69cd31
       s390_sprintf(buf, "%M %R, %R, %R, %R", op, insn->variant.vec_triop.dst,
Mark Wielaard 802130
@@ -9036,6 +9230,27 @@ s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
Mark Wielaard 69cd31
       return s390_emit_VPOPCT(buf, v1, v2, s390_getM_from_size(insn->size));
Mark Wielaard 69cd31
    }
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+   case S390_VEC_FLOAT_NEG: {
Mark Wielaard 69cd31
+      vassert(insn->variant.unop.src.tag == S390_OPND_REG);
Mark Wielaard 69cd31
+      vassert(insn->size == 8);
Mark Wielaard 69cd31
+      UChar v1 = hregNumber(insn->variant.unop.dst);
Mark Wielaard 69cd31
+      UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
Mark Wielaard 69cd31
+      return s390_emit_VFPSO(buf, v1, v2, s390_getM_from_size(insn->size), 0, 0);
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+   case S390_VEC_FLOAT_ABS: {
Mark Wielaard 69cd31
+      vassert(insn->variant.unop.src.tag == S390_OPND_REG);
Mark Wielaard 69cd31
+      vassert(insn->size == 8);
Mark Wielaard 69cd31
+      UChar v1 = hregNumber(insn->variant.unop.dst);
Mark Wielaard 69cd31
+      UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
Mark Wielaard 69cd31
+      return s390_emit_VFPSO(buf, v1, v2, s390_getM_from_size(insn->size), 0, 2);
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
+   case S390_VEC_FLOAT_SQRT: {
Mark Wielaard 69cd31
+      vassert(insn->variant.unop.src.tag == S390_OPND_REG);
Mark Wielaard 69cd31
+      vassert(insn->size == 8);
Mark Wielaard 69cd31
+      UChar v1 = hregNumber(insn->variant.unop.dst);
Mark Wielaard 69cd31
+      UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
Mark Wielaard 69cd31
+      return s390_emit_VFSQ(buf, v1, v2, s390_getM_from_size(insn->size), 0);
Mark Wielaard 69cd31
+   }
Mark Wielaard 69cd31
    default:
Mark Wielaard 69cd31
       vpanic("s390_insn_unop_emit");
Mark Wielaard 69cd31
    }
Mark Wielaard 802130
@@ -11049,6 +11264,21 @@ s390_insn_vec_binop_emit(UChar *buf, const s390_insn *insn)
Mark Wielaard 69cd31
          return s390_emit_VSUMQ(buf, v1, v2, v3, s390_getM_from_size(size));
Mark Wielaard 69cd31
       case S390_VEC_INIT_FROM_GPRS:
Mark Wielaard 69cd31
          return s390_emit_VLVGP(buf, v1, v2, v3);
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_ADD:
Mark Wielaard 69cd31
+         return s390_emit_VFA(buf, v1, v2, v3, s390_getM_from_size(size), 0);
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_SUB:
Mark Wielaard 69cd31
+         return s390_emit_VFS(buf, v1, v2, v3, s390_getM_from_size(size), 0);
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_MUL:
Mark Wielaard 69cd31
+         return s390_emit_VFM(buf, v1, v2, v3, s390_getM_from_size(size), 0);
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_DIV:
Mark Wielaard 69cd31
+         return s390_emit_VFD(buf, v1, v2, v3, s390_getM_from_size(size), 0);
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_COMPARE_EQUAL:
Mark Wielaard 69cd31
+         return s390_emit_VFCE(buf, v1, v2, v3, s390_getM_from_size(size), 0, 0);
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_COMPARE_LESS_OR_EQUAL:
Mark Wielaard 69cd31
+         return s390_emit_VFCH(buf, v1, v3, v2, s390_getM_from_size(size), 0, 0);
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_COMPARE_LESS:
Mark Wielaard 69cd31
+         return s390_emit_VFCHE(buf, v1, v3, v2, s390_getM_from_size(size), 0, 0);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
       default:
Mark Wielaard 69cd31
          goto fail;
Mark Wielaard 69cd31
    }
Mark Wielaard 802130
@@ -11070,8 +11300,14 @@ s390_insn_vec_triop_emit(UChar *buf, const s390_insn *insn)
Mark Wielaard 69cd31
    UChar v4 = hregNumber(insn->variant.vec_triop.op3);
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
    switch (tag) {
Mark Wielaard 69cd31
-      case S390_VEC_PERM:
Mark Wielaard 69cd31
+      case S390_VEC_PERM: {
Mark Wielaard 69cd31
+         vassert(insn->size == 16);
Mark Wielaard 69cd31
          return s390_emit_VPERM(buf, v1, v2, v3, v4);
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_MADD:
Mark Wielaard 69cd31
+         return s390_emit_VFMA(buf, v1, v2, v3, v4, 0, 3);
Mark Wielaard 69cd31
+      case S390_VEC_FLOAT_MSUB:
Mark Wielaard 69cd31
+         return s390_emit_VFMS(buf, v1, v2, v3, v4, 0, 3);
Mark Wielaard 69cd31
       default:
Mark Wielaard 69cd31
          goto fail;
Mark Wielaard 69cd31
    }
Mark Wielaard 69cd31
diff --git a/VEX/priv/host_s390_defs.h b/VEX/priv/host_s390_defs.h
Mark Wielaard 802130
index 7ea0101..40f0472 100644
Mark Wielaard 69cd31
--- a/VEX/priv/host_s390_defs.h
Mark Wielaard 69cd31
+++ b/VEX/priv/host_s390_defs.h
Mark Wielaard 69cd31
@@ -202,7 +202,10 @@ typedef enum {
Mark Wielaard 69cd31
    S390_VEC_ABS,
Mark Wielaard 69cd31
    S390_VEC_COUNT_LEADING_ZEROES,
Mark Wielaard 69cd31
    S390_VEC_COUNT_TRAILING_ZEROES,
Mark Wielaard 69cd31
-   S390_VEC_COUNT_ONES
Mark Wielaard 69cd31
+   S390_VEC_COUNT_ONES,
Mark Wielaard 69cd31
+   S390_VEC_FLOAT_NEG,
Mark Wielaard 69cd31
+   S390_VEC_FLOAT_ABS,
Mark Wielaard 69cd31
+   S390_VEC_FLOAT_SQRT
Mark Wielaard 69cd31
 } s390_unop_t;
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
 /* The kind of ternary BFP operations */
Mark Wielaard 69cd31
@@ -394,11 +397,20 @@ typedef enum {
Mark Wielaard 69cd31
    S390_VEC_PWSUM_QW,
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
    S390_VEC_INIT_FROM_GPRS,
Mark Wielaard 69cd31
+   S390_VEC_FLOAT_ADD,
Mark Wielaard 69cd31
+   S390_VEC_FLOAT_SUB,
Mark Wielaard 69cd31
+   S390_VEC_FLOAT_MUL,
Mark Wielaard 69cd31
+   S390_VEC_FLOAT_DIV,
Mark Wielaard 69cd31
+   S390_VEC_FLOAT_COMPARE_EQUAL,
Mark Wielaard 69cd31
+   S390_VEC_FLOAT_COMPARE_LESS_OR_EQUAL,
Mark Wielaard 69cd31
+   S390_VEC_FLOAT_COMPARE_LESS
Mark Wielaard 69cd31
 } s390_vec_binop_t;
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
 /* The vector operations with three operands */
Mark Wielaard 69cd31
 typedef enum {
Mark Wielaard 69cd31
-   S390_VEC_PERM
Mark Wielaard 69cd31
+   S390_VEC_PERM,
Mark Wielaard 69cd31
+   S390_VEC_FLOAT_MADD,
Mark Wielaard 69cd31
+   S390_VEC_FLOAT_MSUB
Mark Wielaard 69cd31
 } s390_vec_triop_t;
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
 /* The details of a CDAS insn. Carved out to keep the size of
Mark Wielaard 69cd31
diff --git a/VEX/priv/host_s390_isel.c b/VEX/priv/host_s390_isel.c
Mark Wielaard 802130
index bc34f90..79581ff 100644
Mark Wielaard 69cd31
--- a/VEX/priv/host_s390_isel.c
Mark Wielaard 69cd31
+++ b/VEX/priv/host_s390_isel.c
Mark Wielaard 69cd31
@@ -787,10 +787,12 @@ get_bfp_rounding_mode(ISelEnv *env, IRExpr *irrm)
Mark Wielaard 69cd31
       IRRoundingMode mode = irrm->Iex.Const.con->Ico.U32;
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
       switch (mode) {
Mark Wielaard 69cd31
-      case Irrm_NEAREST:  return S390_BFP_ROUND_NEAREST_EVEN;
Mark Wielaard 69cd31
-      case Irrm_ZERO:     return S390_BFP_ROUND_ZERO;
Mark Wielaard 69cd31
-      case Irrm_PosINF:   return S390_BFP_ROUND_POSINF;
Mark Wielaard 69cd31
-      case Irrm_NegINF:   return S390_BFP_ROUND_NEGINF;
Mark Wielaard 69cd31
+      case Irrm_NEAREST_TIE_AWAY_0: return S390_BFP_ROUND_NEAREST_AWAY;
Mark Wielaard 69cd31
+      case Irrm_PREPARE_SHORTER:    return S390_BFP_ROUND_PREPARE_SHORT;
Mark Wielaard 69cd31
+      case Irrm_NEAREST:            return S390_BFP_ROUND_NEAREST_EVEN;
Mark Wielaard 69cd31
+      case Irrm_ZERO:               return S390_BFP_ROUND_ZERO;
Mark Wielaard 69cd31
+      case Irrm_PosINF:             return S390_BFP_ROUND_POSINF;
Mark Wielaard 69cd31
+      case Irrm_NegINF:             return S390_BFP_ROUND_NEGINF;
Mark Wielaard 69cd31
       default:
Mark Wielaard 69cd31
          vpanic("get_bfp_rounding_mode");
Mark Wielaard 69cd31
       }
Mark Wielaard 69cd31
@@ -3871,6 +3873,17 @@ s390_isel_vec_expr_wrk(ISelEnv *env, IRExpr *expr)
Mark Wielaard 69cd31
          vec_op = S390_VEC_COUNT_ONES;
Mark Wielaard 69cd31
          goto Iop_V_wrk;
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+      case Iop_Neg64Fx2:
Mark Wielaard 69cd31
+         size = 8;
Mark Wielaard 69cd31
+         vec_op = S390_VEC_FLOAT_NEG;
Mark Wielaard 69cd31
+         goto Iop_V_wrk;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      case Iop_Abs64Fx2:
Mark Wielaard 69cd31
+         size = 8;
Mark Wielaard 69cd31
+         vec_op = S390_VEC_FLOAT_ABS;
Mark Wielaard 69cd31
+         goto Iop_V_wrk;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
       Iop_V_wrk: {
Mark Wielaard 69cd31
          dst = newVRegV(env);
Mark Wielaard 69cd31
          reg1 = s390_isel_vec_expr(env, arg);
Mark Wielaard 69cd31
@@ -4388,6 +4401,28 @@ s390_isel_vec_expr_wrk(ISelEnv *env, IRExpr *expr)
Mark Wielaard 69cd31
          vec_op = S390_VEC_ELEM_ROLL_V;
Mark Wielaard 69cd31
          goto Iop_VV_wrk;
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+      case Iop_CmpEQ64Fx2:
Mark Wielaard 69cd31
+         size = 8;
Mark Wielaard 69cd31
+         vec_op = S390_VEC_FLOAT_COMPARE_EQUAL;
Mark Wielaard 69cd31
+         goto Iop_VV_wrk;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      case Iop_CmpLE64Fx2: {
Mark Wielaard 69cd31
+         size = 8;
Mark Wielaard 69cd31
+         vec_op = S390_VEC_FLOAT_COMPARE_LESS_OR_EQUAL;
Mark Wielaard 69cd31
+         goto Iop_VV_wrk;
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      case Iop_CmpLT64Fx2: {
Mark Wielaard 69cd31
+         size = 8;
Mark Wielaard 69cd31
+         vec_op = S390_VEC_FLOAT_COMPARE_LESS;
Mark Wielaard 69cd31
+         goto Iop_VV_wrk;
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      case Iop_Sqrt64Fx2:
Mark Wielaard 69cd31
+         size = 8;
Mark Wielaard 69cd31
+         vec_op = S390_VEC_FLOAT_SQRT;
Mark Wielaard 69cd31
+         goto Iop_irrm_V_wrk;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
       case Iop_ShlN8x16:
Mark Wielaard 69cd31
          size = 1;
Mark Wielaard 69cd31
          shift_op = S390_VEC_ELEM_SHL_INT;
Mark Wielaard 69cd31
@@ -4493,6 +4528,14 @@ s390_isel_vec_expr_wrk(ISelEnv *env, IRExpr *expr)
Mark Wielaard 69cd31
          return dst;
Mark Wielaard 69cd31
       }
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+      Iop_irrm_V_wrk: {
Mark Wielaard 69cd31
+         set_bfp_rounding_mode_in_fpc(env, arg1);
Mark Wielaard 69cd31
+         reg1 = s390_isel_vec_expr(env, arg2);
Mark Wielaard 802130
+
Mark Wielaard 69cd31
+         addInstr(env, s390_insn_unop(size, vec_op, dst, s390_opnd_reg(reg1)));
Mark Wielaard 69cd31
+         return dst;
Mark Wielaard 69cd31
+      }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
       case Iop_64HLtoV128:
Mark Wielaard 69cd31
          reg1 = s390_isel_int_expr(env, arg1);
Mark Wielaard 69cd31
          reg2 = s390_isel_int_expr(env, arg2);
Mark Wielaard 69cd31
@@ -4516,6 +4559,7 @@ s390_isel_vec_expr_wrk(ISelEnv *env, IRExpr *expr)
Mark Wielaard 69cd31
       IRExpr* arg1 = expr->Iex.Triop.details->arg1;
Mark Wielaard 69cd31
       IRExpr* arg2 = expr->Iex.Triop.details->arg2;
Mark Wielaard 69cd31
       IRExpr* arg3 = expr->Iex.Triop.details->arg3;
Mark Wielaard 69cd31
+      IROp vec_op;
Mark Wielaard 69cd31
       switch (op) {
Mark Wielaard 69cd31
       case Iop_SetElem8x16:
Mark Wielaard 69cd31
          size = 1;
Mark Wielaard 802130
@@ -4551,6 +4595,36 @@ s390_isel_vec_expr_wrk(ISelEnv *env, IRExpr *expr)
Mark Wielaard 69cd31
                                            dst, reg1, reg2, reg3));
Mark Wielaard 69cd31
          return dst;
Mark Wielaard 69cd31
 
Mark Wielaard 69cd31
+      case Iop_Add64Fx2:
Mark Wielaard 69cd31
+         size = 8;
Mark Wielaard 69cd31
+         vec_op = S390_VEC_FLOAT_ADD;
Mark Wielaard 69cd31
+         goto Iop_irrm_VV_wrk;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      case Iop_Sub64Fx2:
Mark Wielaard 69cd31
+         size = 8;
Mark Wielaard 69cd31
+         vec_op = S390_VEC_FLOAT_SUB;
Mark Wielaard 69cd31
+         goto Iop_irrm_VV_wrk;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      case Iop_Mul64Fx2:
Mark Wielaard 69cd31
+         size = 8;
Mark Wielaard 69cd31
+         vec_op = S390_VEC_FLOAT_MUL;
Mark Wielaard 69cd31
+         goto Iop_irrm_VV_wrk;
Mark Wielaard 69cd31
+      case Iop_Div64Fx2:
Mark Wielaard 69cd31
+         size = 8;
Mark Wielaard 69cd31
+         vec_op = S390_VEC_FLOAT_DIV;
Mark Wielaard 69cd31
+         goto Iop_irrm_VV_wrk;
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+      Iop_irrm_VV_wrk: {
Mark Wielaard 69cd31
+         set_bfp_rounding_mode_in_fpc(env, arg1);
Mark Wielaard 69cd31
+         reg1 = s390_isel_vec_expr(env, arg2);
Mark Wielaard 69cd31
+         reg2 = s390_isel_vec_expr(env, arg3);
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+         addInstr(env, s390_insn_vec_binop(size, vec_op,
Mark Wielaard 69cd31
+                                           dst, reg1, reg2));
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
+         return dst;
Mark Wielaard 69cd31
+       }
Mark Wielaard 69cd31
+
Mark Wielaard 69cd31
       default:
Mark Wielaard 69cd31
          goto irreducible;
Mark Wielaard 69cd31
       }