target/hppa: Use delay_excp for conditional traps
Reviewed-by: Helge Deller <deller@gmx.de> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
806030074b
commit
269ca0a9cc
@ -1,6 +1,5 @@
|
|||||||
DEF_HELPER_2(excp, noreturn, env, int)
|
DEF_HELPER_2(excp, noreturn, env, int)
|
||||||
DEF_HELPER_FLAGS_2(tsv, TCG_CALL_NO_WG, void, env, tl)
|
DEF_HELPER_FLAGS_2(tsv, TCG_CALL_NO_WG, void, env, tl)
|
||||||
DEF_HELPER_FLAGS_2(tcond, TCG_CALL_NO_WG, void, env, tl)
|
|
||||||
|
|
||||||
DEF_HELPER_FLAGS_3(stby_b, TCG_CALL_NO_WG, void, env, tl, tl)
|
DEF_HELPER_FLAGS_3(stby_b, TCG_CALL_NO_WG, void, env, tl, tl)
|
||||||
DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, env, tl, tl)
|
DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, env, tl, tl)
|
||||||
|
@ -134,13 +134,13 @@ void hppa_cpu_do_interrupt(CPUState *cs)
|
|||||||
switch (i) {
|
switch (i) {
|
||||||
case EXCP_ILL:
|
case EXCP_ILL:
|
||||||
case EXCP_BREAK:
|
case EXCP_BREAK:
|
||||||
|
case EXCP_COND:
|
||||||
case EXCP_PRIV_REG:
|
case EXCP_PRIV_REG:
|
||||||
case EXCP_PRIV_OPR:
|
case EXCP_PRIV_OPR:
|
||||||
/* IIR set via translate.c. */
|
/* IIR set via translate.c. */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXCP_OVERFLOW:
|
case EXCP_OVERFLOW:
|
||||||
case EXCP_COND:
|
|
||||||
case EXCP_ASSIST:
|
case EXCP_ASSIST:
|
||||||
case EXCP_DTLB_MISS:
|
case EXCP_DTLB_MISS:
|
||||||
case EXCP_NA_ITLB_MISS:
|
case EXCP_NA_ITLB_MISS:
|
||||||
|
@ -49,13 +49,6 @@ void HELPER(tsv)(CPUHPPAState *env, target_ulong cond)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HELPER(tcond)(CPUHPPAState *env, target_ulong cond)
|
|
||||||
{
|
|
||||||
if (unlikely(cond)) {
|
|
||||||
hppa_dynamic_excp(env, EXCP_COND, GETPC());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void atomic_store_mask32(CPUHPPAState *env, target_ulong addr,
|
static void atomic_store_mask32(CPUHPPAState *env, target_ulong addr,
|
||||||
uint32_t val, uint32_t mask, uintptr_t ra)
|
uint32_t val, uint32_t mask, uintptr_t ra)
|
||||||
{
|
{
|
||||||
|
@ -1117,6 +1117,25 @@ static TCGv_i64 do_sub_sv(DisasContext *ctx, TCGv_i64 res,
|
|||||||
return sv;
|
return sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen_tc(DisasContext *ctx, DisasCond *cond)
|
||||||
|
{
|
||||||
|
DisasDelayException *e;
|
||||||
|
|
||||||
|
switch (cond->c) {
|
||||||
|
case TCG_COND_NEVER:
|
||||||
|
break;
|
||||||
|
case TCG_COND_ALWAYS:
|
||||||
|
gen_excp_iir(ctx, EXCP_COND);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
e = delay_excp(ctx, EXCP_COND);
|
||||||
|
tcg_gen_brcond_i64(cond->c, cond->a0, cond->a1, e->lab);
|
||||||
|
/* In the non-trap path, the condition is known false. */
|
||||||
|
*cond = cond_make_f();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void do_add(DisasContext *ctx, unsigned rt, TCGv_i64 orig_in1,
|
static void do_add(DisasContext *ctx, unsigned rt, TCGv_i64 orig_in1,
|
||||||
TCGv_i64 in2, unsigned shift, bool is_l,
|
TCGv_i64 in2, unsigned shift, bool is_l,
|
||||||
bool is_tsv, bool is_tc, bool is_c, unsigned cf, bool d)
|
bool is_tsv, bool is_tc, bool is_c, unsigned cf, bool d)
|
||||||
@ -1175,9 +1194,7 @@ static void do_add(DisasContext *ctx, unsigned rt, TCGv_i64 orig_in1,
|
|||||||
/* Emit any conditional trap before any writeback. */
|
/* Emit any conditional trap before any writeback. */
|
||||||
cond = do_cond(ctx, cf, d, dest, uv, sv);
|
cond = do_cond(ctx, cf, d, dest, uv, sv);
|
||||||
if (is_tc) {
|
if (is_tc) {
|
||||||
tmp = tcg_temp_new_i64();
|
gen_tc(ctx, &cond);
|
||||||
tcg_gen_setcond_i64(cond.c, tmp, cond.a0, cond.a1);
|
|
||||||
gen_helper_tcond(tcg_env, tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write back the result. */
|
/* Write back the result. */
|
||||||
@ -1196,6 +1213,10 @@ static bool do_add_reg(DisasContext *ctx, arg_rrr_cf_d_sh *a,
|
|||||||
{
|
{
|
||||||
TCGv_i64 tcg_r1, tcg_r2;
|
TCGv_i64 tcg_r1, tcg_r2;
|
||||||
|
|
||||||
|
if (unlikely(is_tc && a->cf == 1)) {
|
||||||
|
/* Unconditional trap on condition. */
|
||||||
|
return gen_excp_iir(ctx, EXCP_COND);
|
||||||
|
}
|
||||||
if (a->cf) {
|
if (a->cf) {
|
||||||
nullify_over(ctx);
|
nullify_over(ctx);
|
||||||
}
|
}
|
||||||
@ -1211,6 +1232,10 @@ static bool do_add_imm(DisasContext *ctx, arg_rri_cf *a,
|
|||||||
{
|
{
|
||||||
TCGv_i64 tcg_im, tcg_r2;
|
TCGv_i64 tcg_im, tcg_r2;
|
||||||
|
|
||||||
|
if (unlikely(is_tc && a->cf == 1)) {
|
||||||
|
/* Unconditional trap on condition. */
|
||||||
|
return gen_excp_iir(ctx, EXCP_COND);
|
||||||
|
}
|
||||||
if (a->cf) {
|
if (a->cf) {
|
||||||
nullify_over(ctx);
|
nullify_over(ctx);
|
||||||
}
|
}
|
||||||
@ -1225,7 +1250,7 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
|
|||||||
TCGv_i64 in2, bool is_tsv, bool is_b,
|
TCGv_i64 in2, bool is_tsv, bool is_b,
|
||||||
bool is_tc, unsigned cf, bool d)
|
bool is_tc, unsigned cf, bool d)
|
||||||
{
|
{
|
||||||
TCGv_i64 dest, sv, cb, cb_msb, tmp;
|
TCGv_i64 dest, sv, cb, cb_msb;
|
||||||
unsigned c = cf >> 1;
|
unsigned c = cf >> 1;
|
||||||
DisasCond cond;
|
DisasCond cond;
|
||||||
|
|
||||||
@ -1273,9 +1298,7 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
|
|||||||
|
|
||||||
/* Emit any conditional trap before any writeback. */
|
/* Emit any conditional trap before any writeback. */
|
||||||
if (is_tc) {
|
if (is_tc) {
|
||||||
tmp = tcg_temp_new_i64();
|
gen_tc(ctx, &cond);
|
||||||
tcg_gen_setcond_i64(cond.c, tmp, cond.a0, cond.a1);
|
|
||||||
gen_helper_tcond(tcg_env, tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write back the result. */
|
/* Write back the result. */
|
||||||
@ -1441,9 +1464,7 @@ static void do_unit_addsub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_tc) {
|
if (is_tc) {
|
||||||
TCGv_i64 tmp = tcg_temp_new_i64();
|
gen_tc(ctx, &cond);
|
||||||
tcg_gen_setcond_i64(cond.c, tmp, cond.a0, cond.a1);
|
|
||||||
gen_helper_tcond(tcg_env, tmp);
|
|
||||||
}
|
}
|
||||||
save_gpr(ctx, rt, dest);
|
save_gpr(ctx, rt, dest);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user