]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
s390: Add support for fixbr(a) instructions.
authorFlorian Krohm <florian@eich-krohm.de>
Sat, 5 Sep 2015 20:35:52 +0000 (20:35 +0000)
committerFlorian Krohm <florian@eich-krohm.de>
Sat, 5 Sep 2015 20:35:52 +0000 (20:35 +0000)
New IROp Iop_RoundF128toInt.
Patch by Andreas Arnez <arnez@linux.vnet.ibm.com>.
Part of fixing BZ #350290.

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

VEX/priv/guest_s390_toIR.c
VEX/priv/host_s390_defs.c
VEX/priv/host_s390_defs.h
VEX/priv/host_s390_isel.c
VEX/priv/ir_defs.c
VEX/pub/libvex_ir.h

index 5ac5380cf6a03b0a7e140309b77a2eea2356c780..116a6062597caa0d7b4b080e2e3d28dd9aa54e01 100644 (file)
@@ -12409,6 +12409,19 @@ s390_irgen_FIDBRA(UChar m3, UChar m4 __attribute__((unused)),
    return "fidbra";
 }
 
+static const HChar *
+s390_irgen_FIXBRA(UChar m3, UChar m4 __attribute__((unused)),
+                  UChar r1, UChar r2)
+{
+   IRTemp result = newTemp(Ity_F128);
+
+   assign(result, binop(Iop_RoundF128toInt, mkexpr(encode_bfp_rounding_mode(m3)),
+                        get_fpr_pair(r2)));
+   put_fpr_pair(r1, mkexpr(result));
+
+   return "fixbra";
+}
+
 static const HChar *
 s390_irgen_LNEBR(UChar r1, UChar r2)
 {
@@ -14531,7 +14544,9 @@ s390_decode_4byte_and_irgen(const UChar *bytes)
    case 0xb346: s390_format_RRF_UUFF(s390_irgen_LEXBR, ovl.fmt.RRF2.m3,
                                      ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
                                      ovl.fmt.RRF2.r2);  goto ok;
-   case 0xb347: /* FIXBR */ goto unimplemented;
+   case 0xb347: s390_format_RRF_UUFF(s390_irgen_FIXBRA, ovl.fmt.RRF2.m3,
+                                     ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1,
+                                     ovl.fmt.RRF2.r2);  goto ok;
    case 0xb348: /* KXBR */ goto unimplemented;
    case 0xb349: s390_format_RRE_FF(s390_irgen_CXBR, ovl.fmt.RRE.r1,
                                    ovl.fmt.RRE.r2);  goto ok;
index 94344ca49567d4a8336b2998b2461fcf84dbd632..9885d474f09f605524292a8471e8f00c3ad44ffb 100644 (file)
@@ -3972,6 +3972,23 @@ s390_emit_FIDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
 }
 
 
+static UChar *
+s390_emit_FIXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
+{
+   vassert(m3 == 0 || s390_host_has_fpext);
+
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
+      if (m4 == 0)
+         s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fixbr", r1, m3, r2);
+      else
+         s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
+                     "fixbra", r1, m3, r2, m4);
+   }
+
+   return emit_RRF2(p, 0xb3470000, m3, m4, r1, r2);
+}
+
+
 static UChar *
 s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
 {
@@ -5748,7 +5765,7 @@ s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
 }
 
 
-static s390_insn *
+s390_insn *
 s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
                          HReg dst_lo, HReg op_hi, HReg op_lo,
                          s390_bfp_round_t rounding_mode)
@@ -5756,9 +5773,10 @@ s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
 
    if (size == 16) {
-      /* From smaller size to 16 bytes */
+      /* From smaller or equal size to 16 bytes */
       vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
-      vassert(hregIsInvalid(op_lo));
+      vassert(hregIsInvalid(op_lo)
+              || is_valid_fp128_regpair(op_hi, op_lo));
    } else {
       /* From 16 bytes to smaller size */
       vassert(is_valid_fp128_regpair(op_hi, op_lo));
@@ -6728,7 +6746,8 @@ s390_insn_as_string(const s390_insn *insn)
       case S390_BFP_F128_TO_F32:
       case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
       case S390_BFP_F32_TO_F32I:
-      case S390_BFP_F64_TO_F64I: op = "v-f2fi"; break;
+      case S390_BFP_F64_TO_F64I:
+      case S390_BFP_F128_TO_F128I: op = "v-f2fi"; break;
       default: goto fail;
       }
       s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi,
@@ -9003,6 +9022,7 @@ s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn)
       /* Load FP integer */
    case S390_BFP_F32_TO_F32I: return s390_emit_FIEBRA(buf, m3, m4, r1, r2);
    case S390_BFP_F64_TO_F64I: return s390_emit_FIDBRA(buf, m3, m4, r1, r2);
+   case S390_BFP_F128_TO_F128I: return s390_emit_FIXBRA(buf, m3, m4, r1, r2);
 
    default: goto fail;
    }
index 7390f7f5e5879730fd22e59754f6717647c8540c..a7c4b1e9f2351dcfcdcc353989e06640d094a64c 100644 (file)
@@ -244,7 +244,8 @@ typedef enum {
    S390_BFP_F128_TO_F32,
    S390_BFP_F128_TO_F64,
    S390_BFP_F32_TO_F32I,
-   S390_BFP_F64_TO_F64I
+   S390_BFP_F64_TO_F64I,
+   S390_BFP_F128_TO_F128I
 } s390_bfp_conv_t;
 
 /* Type conversion operations: to and/or from decimal floating point */
@@ -660,6 +661,9 @@ s390_insn *s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst,
 s390_insn *s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2);
 s390_insn *s390_insn_bfp_convert(UChar size, s390_bfp_conv_t tag, HReg dst,
                                  HReg op, s390_bfp_round_t);
+s390_insn *s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
+                                    HReg dst_lo, HReg op_hi, HReg op_lo,
+                                    s390_bfp_round_t rounding_mode);
 s390_insn *s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t, HReg dst_hi,
                                   HReg dst_lo, HReg op2_hi, HReg op2_lo);
 s390_insn *s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t, HReg dst_hi,
index 84e42f0b72c234124de6a0a11a747bb96b432059..02f399d0496f48cfcbb0a138c942b21e5d08cbd0 100644 (file)
@@ -2143,6 +2143,42 @@ s390_isel_float128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env,
          return;
       }
 
+      case Iop_RoundF128toInt: {
+         IRExpr *irrm;
+         IRExpr *left;
+         s390_bfp_round_t rm;
+         HReg op_hi, op_lo;
+         HReg f0, f2, f4, f6;           /* real registers */
+
+         f4 = make_fpr(4); /* source */
+         f6 = make_fpr(6); /* source */
+         f0 = make_fpr(0); /* destination */
+         f2 = make_fpr(2); /* destination */
+
+         irrm = expr->Iex.Binop.arg1;
+         left = expr->Iex.Binop.arg2;
+         
+         if (s390_host_has_fpext) {
+            rm = get_bfp_rounding_mode(env, irrm);
+         } else {
+            set_bfp_rounding_mode_in_fpc(env, irrm);
+            rm = S390_BFP_ROUND_PER_FPC;
+         }
+
+         s390_isel_float128_expr(&op_hi, &op_lo, env, left);
+         /* operand --> (f4, f6) */
+         addInstr(env, s390_insn_move(8, f4, op_hi));
+         addInstr(env, s390_insn_move(8, f6, op_lo));
+         addInstr(env, s390_insn_bfp128_convert(16, S390_BFP_F128_TO_F128I,
+                                                f0, f2, f4, f6, rm));
+         /* (f0, f2) --> destination */
+         *dst_hi = newVRegF(env);
+         *dst_lo = newVRegF(env);
+         addInstr(env, s390_insn_move(8, *dst_hi, f0));
+         addInstr(env, s390_insn_move(8, *dst_lo, f2));
+         return;
+      }
+
       default:
          goto irreducible;
       }
index 8c9b9ab0327253c897fd48a22a46b0797f4a5a29..88a2bf0fce7fad8ec396fe678edce55751ec591b 100644 (file)
@@ -396,6 +396,7 @@ void ppIROp ( IROp op )
       case Iop_F32toF64: vex_printf("F32toF64"); return;
       case Iop_F64toF32: vex_printf("F64toF32"); return;
 
+      case Iop_RoundF128toInt: vex_printf("RoundF128toInt"); return;
       case Iop_RoundF64toInt: vex_printf("RoundF64toInt"); return;
       case Iop_RoundF32toInt: vex_printf("RoundF32toInt"); return;
       case Iop_RoundF64toF32: vex_printf("RoundF64toF32"); return;
@@ -3161,6 +3162,7 @@ void typeOfPrimop ( IROp op,
          UNARY(Ity_F128, Ity_F128);
 
       case Iop_SqrtF128:
+      case Iop_RoundF128toInt:
          BINARY(ity_RMode,Ity_F128, Ity_F128);
 
       case Iop_I32StoF128: UNARY(Ity_I32, Ity_F128);
index f1c09abab54e88c8c35607e39d21e796f3939c94..9f10991d541318a097b0536bd3426d0a5fde57d4 100644 (file)
@@ -713,6 +713,8 @@ typedef
       Iop_CosF64,    /* FCOS */
       Iop_TanF64,    /* FTAN */
       Iop_2xm1F64,   /* (2^arg - 1.0) */
+      Iop_RoundF128toInt, /* F128 value to nearest integral value (still
+                             as F128) */
       Iop_RoundF64toInt, /* F64 value to nearest integral value (still
                             as F64) */
       Iop_RoundF32toInt, /* F32 value to nearest integral value (still