diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c index fad3575549..ee731555d3 100644 --- a/target-alpha/fpu_helper.c +++ b/target-alpha/fpu_helper.c @@ -820,3 +820,10 @@ uint64_t helper_cvtqg(CPUAlphaState *env, uint64_t a) fr = int64_to_float64(a, &FP_STATUS); return float64_to_g(fr); } + +void helper_fcvtql_v_input(CPUAlphaState *env, uint64_t val) +{ + if (val != (int32_t)val) { + arith_excp(env, GETPC(), EXC_M_IOV, 0); + } +} diff --git a/target-alpha/helper.h b/target-alpha/helper.h index 4f127c49c5..2389e96ea3 100644 --- a/target-alpha/helper.h +++ b/target-alpha/helper.h @@ -96,6 +96,7 @@ DEF_HELPER_FLAGS_3(fp_exc_raise_s, TCG_CALL_NO_WG, void, env, i32, i32) DEF_HELPER_FLAGS_2(ieee_input, TCG_CALL_NO_WG, void, env, i64) DEF_HELPER_FLAGS_2(ieee_input_cmp, TCG_CALL_NO_WG, void, env, i64) +DEF_HELPER_FLAGS_2(fcvtql_v_input, TCG_CALL_NO_WG, void, env, i64) #if !defined (CONFIG_USER_ONLY) DEF_HELPER_2(hw_ret, void, env, i64) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 7515ed3465..59ae23d7d3 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -716,61 +716,32 @@ static inline void gen_fp_exc_raise(int rc, int fn11) gen_fp_exc_raise_ignore(rc, fn11, fn11 & QUAL_I ? 0 : float_flag_inexact); } -static void gen_fcvtlq(int rb, int rc) +static void gen_fcvtlq(TCGv vc, TCGv vb) { - if (unlikely(rc == 31)) { - return; - } - if (unlikely(rb == 31)) { - tcg_gen_movi_i64(cpu_fir[rc], 0); - } else { - TCGv tmp = tcg_temp_new(); + TCGv tmp = tcg_temp_new(); - /* The arithmetic right shift here, plus the sign-extended mask below - yields a sign-extended result without an explicit ext32s_i64. */ - tcg_gen_sari_i64(tmp, cpu_fir[rb], 32); - tcg_gen_shri_i64(cpu_fir[rc], cpu_fir[rb], 29); - tcg_gen_andi_i64(tmp, tmp, (int32_t)0xc0000000); - tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rc], 0x3fffffff); - tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp); + /* The arithmetic right shift here, plus the sign-extended mask below + yields a sign-extended result without an explicit ext32s_i64. */ + tcg_gen_sari_i64(tmp, vb, 32); + tcg_gen_shri_i64(vc, vb, 29); + tcg_gen_andi_i64(tmp, tmp, (int32_t)0xc0000000); + tcg_gen_andi_i64(vc, vc, 0x3fffffff); + tcg_gen_or_i64(vc, vc, tmp); - tcg_temp_free(tmp); - } + tcg_temp_free(tmp); } -static void gen_fcvtql(int rb, int rc) +static void gen_fcvtql(TCGv vc, TCGv vb) { - if (unlikely(rc == 31)) { - return; - } - if (unlikely(rb == 31)) { - tcg_gen_movi_i64(cpu_fir[rc], 0); - } else { - TCGv tmp = tcg_temp_new(); + TCGv tmp = tcg_temp_new(); - tcg_gen_andi_i64(tmp, cpu_fir[rb], 0xC0000000); - tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rb], 0x3FFFFFFF); - tcg_gen_shli_i64(tmp, tmp, 32); - tcg_gen_shli_i64(cpu_fir[rc], cpu_fir[rc], 29); - tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp); + tcg_gen_andi_i64(tmp, vb, (int32_t)0xc0000000); + tcg_gen_andi_i64(vc, vb, 0x3FFFFFFF); + tcg_gen_shli_i64(tmp, tmp, 32); + tcg_gen_shli_i64(vc, vc, 29); + tcg_gen_or_i64(vc, vc, tmp); - tcg_temp_free(tmp); - } -} - -static void gen_fcvtql_v(DisasContext *ctx, int rb, int rc) -{ - if (rb != 31) { - int lab = gen_new_label(); - TCGv tmp = tcg_temp_new(); - - tcg_gen_ext32s_i64(tmp, cpu_fir[rb]); - tcg_gen_brcond_i64(TCG_COND_EQ, tmp, cpu_fir[rb], lab); - gen_excp(ctx, EXCP_ARITH, EXC_M_IOV); - - gen_set_label(lab); - } - gen_fcvtql(rb, rc); + tcg_temp_free(tmp); } static void gen_ieee_arith2(DisasContext *ctx, @@ -2259,7 +2230,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) case 0x010: /* CVTLQ */ REQUIRE_REG_31(ra); - gen_fcvtlq(rb, rc); + vc = dest_fpr(ctx, rc); + vb = load_fpr(ctx, rb); + gen_fcvtlq(vc, vb); break; case 0x020: /* CPYS */ @@ -2323,7 +2296,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) case 0x030: /* CVTQL */ REQUIRE_REG_31(ra); - gen_fcvtql(rb, rc); + vc = dest_fpr(ctx, rc); + vb = load_fpr(ctx, rb); + gen_fcvtql(vc, vb); break; case 0x130: /* CVTQL/V */ @@ -2333,7 +2308,10 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) /* ??? I'm pretty sure there's nothing that /sv needs to do that /v doesn't do. The only thing I can think is that /sv is a valid instruction merely for completeness in the ISA. */ - gen_fcvtql_v(ctx, rb, rc); + vc = dest_fpr(ctx, rc); + vb = load_fpr(ctx, rb); + gen_helper_fcvtql_v_input(cpu_env, vb); + gen_fcvtql(vc, vb); break; default: goto invalid_opc;