Commit ed0bcece authored by Aurelien Jarno's avatar Aurelien Jarno Committed by Alexander Graf
Browse files

target-s390x: implement LOAD FP INTEGER instructions



This is needed to pass the gcc.c-torture/execute/ieee/20010114-2.c test
in the gcc testsuite.

Signed-off-by: default avatarAurelien Jarno <aurelien@aurel32.net>
Reviewed-by: default avatarRichard Henderson <rth@twiddle.net>
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent 9182886d
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -552,6 +552,37 @@ uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
    return ret;
}

/* round to integer 32-bit */
uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
{
    int hold = swap_round_mode(env, m3);
    float32 ret = float32_round_to_int(f2, &env->fpu_status);
    set_float_rounding_mode(hold, &env->fpu_status);
    handle_exceptions(env, GETPC());
    return ret;
}

/* round to integer 64-bit */
uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
{
    int hold = swap_round_mode(env, m3);
    float64 ret = float64_round_to_int(f2, &env->fpu_status);
    set_float_rounding_mode(hold, &env->fpu_status);
    handle_exceptions(env, GETPC());
    return ret;
}

/* round to integer 128-bit */
uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
{
    int hold = swap_round_mode(env, m3);
    float128 ret = float128_round_to_int(make_float128(ah, al),
                                         &env->fpu_status);
    set_float_rounding_mode(hold, &env->fpu_status);
    handle_exceptions(env, GETPC());
    return RET128(ret);
}

/* 32-bit FP multiply and add */
uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
                      uint64_t f2, uint64_t f3)
+3 −0
Original line number Diff line number Diff line
@@ -60,6 +60,9 @@ DEF_HELPER_FLAGS_4(clgxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
DEF_HELPER_FLAGS_3(clfeb, TCG_CALL_NO_WG, i64, env, i64, i32)
DEF_HELPER_FLAGS_3(clfdb, TCG_CALL_NO_WG, i64, env, i64, i32)
DEF_HELPER_FLAGS_4(clfxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
DEF_HELPER_FLAGS_3(fieb, TCG_CALL_NO_WG, i64, env, i64, i32)
DEF_HELPER_FLAGS_3(fidb, TCG_CALL_NO_WG, i64, env, i64, i32)
DEF_HELPER_FLAGS_4(fixb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
DEF_HELPER_FLAGS_4(maeb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_4(madb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_4(mseb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
+4 −0
Original line number Diff line number Diff line
@@ -479,6 +479,10 @@
    C(0xb29d, LFPC,    S,     Z,   0, m2_32u, 0, 0, sfpc, 0)
/* LOAD FPC AND SIGNAL */
    C(0xb2bd, LFAS,    S,     IEEEE_SIM, 0, m2_32u, 0, 0, sfas, 0)
/* LOAD FP INTEGER */
    C(0xb357, FIEBR,   RRF_e, Z,   0, e2, new, e1, fieb, 0)
    C(0xb35f, FIDBR,   RRF_e, Z,   0, f2_o, f1, 0, fidb, 0)
    C(0xb347, FIXBR,   RRF_e, Z,   0, x2_o, x1, 0, fixb, 0)

/* LOAD LENGTHENED */
    C(0xb304, LDEBR,   RRE,   Z,   0, e2, f1, 0, ldeb, 0)
+25 −0
Original line number Diff line number Diff line
@@ -2116,6 +2116,31 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o)
    return NO_EXIT;
}

static ExitStatus op_fieb(DisasContext *s, DisasOps *o)
{
    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
    gen_helper_fieb(o->out, cpu_env, o->in2, m3);
    tcg_temp_free_i32(m3);
    return NO_EXIT;
}

static ExitStatus op_fidb(DisasContext *s, DisasOps *o)
{
    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
    gen_helper_fidb(o->out, cpu_env, o->in2, m3);
    tcg_temp_free_i32(m3);
    return NO_EXIT;
}

static ExitStatus op_fixb(DisasContext *s, DisasOps *o)
{
    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
    gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m3);
    return_low128(o->out2);
    tcg_temp_free_i32(m3);
    return NO_EXIT;
}

static ExitStatus op_flogr(DisasContext *s, DisasOps *o)
{
    /* We'll use the original input for cc computation, since we get to