From: Florian Krohm Date: Thu, 9 Jul 2015 20:59:24 +0000 (+0000) Subject: s390: Add support for FIEBR(A) and FIDBR(A). X-Git-Tag: svn/VALGRIND_3_11_0^2~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=56af9928a3de756a5c6fd7cabe979f16a6c3fc94;p=thirdparty%2Fvalgrind.git s390: Add support for FIEBR(A) and FIDBR(A). Patch by Andreas Arnez (arnez@linux.vnet.ibm.com). Part of fixing BZ #342841. git-svn-id: svn://svn.valgrind.org/vex/trunk@3162 --- diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 023cb7d9b1..9b563f75cd 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -12383,6 +12383,32 @@ s390_irgen_LXEB(UChar r1, IRTemp op2addr) return "lxeb"; } +static const HChar * +s390_irgen_FIEBRA(UChar m3, UChar m4 __attribute__((unused)), + UChar r1, UChar r2) +{ + IRTemp result = newTemp(Ity_F32); + + assign(result, binop(Iop_RoundF32toInt, mkexpr(encode_bfp_rounding_mode(m3)), + get_fpr_w0(r2))); + put_fpr_w0(r1, mkexpr(result)); + + return "fiebra"; +} + +static const HChar * +s390_irgen_FIDBRA(UChar m3, UChar m4 __attribute__((unused)), + UChar r1, UChar r2) +{ + IRTemp result = newTemp(Ity_F64); + + assign(result, binop(Iop_RoundF64toInt, mkexpr(encode_bfp_rounding_mode(m3)), + get_fpr_dw0(r2))); + put_fpr_dw0(r1, mkexpr(result)); + + return "fidbra"; +} + static const HChar * s390_irgen_LNEBR(UChar r1, UChar r2) { @@ -14520,11 +14546,15 @@ s390_decode_4byte_and_irgen(const UChar *bytes) case 0xb350: /* TBEDR */ goto unimplemented; case 0xb351: /* TBDR */ goto unimplemented; case 0xb353: /* DIEBR */ goto unimplemented; - case 0xb357: /* FIEBR */ goto unimplemented; + case 0xb357: s390_format_RRF_UUFF(s390_irgen_FIEBRA, ovl.fmt.RRF2.m3, + ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1, + ovl.fmt.RRF2.r2); goto ok; case 0xb358: /* THDER */ goto unimplemented; case 0xb359: /* THDR */ goto unimplemented; case 0xb35b: /* DIDBR */ goto unimplemented; - case 0xb35f: /* FIDBR */ goto unimplemented; + case 0xb35f: s390_format_RRF_UUFF(s390_irgen_FIDBRA, ovl.fmt.RRF2.m3, + ovl.fmt.RRF2.m4, ovl.fmt.RRF2.r1, + ovl.fmt.RRF2.r2); goto ok; case 0xb360: /* LPXR */ goto unimplemented; case 0xb361: /* LNXR */ goto unimplemented; case 0xb362: /* LTXR */ goto unimplemented; diff --git a/VEX/priv/host_s390_defs.c b/VEX/priv/host_s390_defs.c index 974ec6d47f..3d821f9e08 100644 --- a/VEX/priv/host_s390_defs.c +++ b/VEX/priv/host_s390_defs.c @@ -3938,6 +3938,40 @@ s390_emit_LEXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) } +static UChar * +s390_emit_FIEBRA(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), "fiebr", r1, m3, r2); + else + s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), + "fiebra", r1, m3, r2, m4); + } + + return emit_RRF2(p, 0xb3570000, m3, m4, r1, r2); +} + + +static UChar * +s390_emit_FIDBRA(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), "fidbr", r1, m3, r2); + else + s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), + "fidbra", r1, m3, r2, m4); + } + + return emit_RRF2(p, 0xb35f0000, m3, m4, r1, r2); +} + + static UChar * s390_emit_MEEBR(UChar *p, UChar r1, UChar r2) { @@ -6693,6 +6727,8 @@ s390_insn_as_string(const s390_insn *insn) case S390_BFP_F64_TO_F128: 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; default: goto fail; } s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi, @@ -8964,6 +9000,10 @@ s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn) case S390_BFP_F128_TO_F32: return s390_emit_LEXBRA(buf, m3, m4, r1, r2); case S390_BFP_F128_TO_F64: return s390_emit_LDXBRA(buf, m3, m4, r1, r2); + /* 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); + default: goto fail; } diff --git a/VEX/priv/host_s390_defs.h b/VEX/priv/host_s390_defs.h index 9d732f975e..d10376b0d7 100644 --- a/VEX/priv/host_s390_defs.h +++ b/VEX/priv/host_s390_defs.h @@ -242,7 +242,9 @@ typedef enum { S390_BFP_F128_TO_U32, S390_BFP_F128_TO_U64, S390_BFP_F128_TO_F32, - S390_BFP_F128_TO_F64 + S390_BFP_F128_TO_F64, + S390_BFP_F32_TO_F32I, + S390_BFP_F64_TO_F64I } s390_bfp_conv_t; /* Type conversion operations: to and/or from decimal floating point */ diff --git a/VEX/priv/host_s390_isel.c b/VEX/priv/host_s390_isel.c index dee892aeb6..37ef88b5c6 100644 --- a/VEX/priv/host_s390_isel.c +++ b/VEX/priv/host_s390_isel.c @@ -2378,6 +2378,8 @@ s390_isel_float_expr_wrk(ISelEnv *env, IRExpr *expr) return dst; case Iop_F64toF32: conv = S390_BFP_F64_TO_F32; goto convert_float; + case Iop_RoundF32toInt: conv = S390_BFP_F32_TO_F32I; goto convert_float; + case Iop_RoundF64toInt: conv = S390_BFP_F64_TO_F64I; goto convert_float; case Iop_I32StoF32: conv = S390_BFP_I32_TO_F32; goto convert_int; case Iop_I32UtoF32: conv = S390_BFP_U32_TO_F32; goto convert_int; case Iop_I64StoF32: conv = S390_BFP_I64_TO_F32; goto convert_int;