Translate most conditions to TCG conditions and avoid the helper for most of the common cases.
Signed-off-by: Benjamin Herrenschmidt <b...@kernel.crashing.org> --- target-ppc/translate.c | 168 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 132 insertions(+), 36 deletions(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 47eb9ed..561976f 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -3639,82 +3639,178 @@ static void gen_sc(DisasContext *ctx) /*** Trap ***/ -/* Check for unconditional traps (always or never) */ -static bool check_unconditional_trap(DisasContext *ctx) +static int TO2tcg[32] = { + TCG_COND_NEVER, /* no condition */ + TCG_COND_GTU, /* 0x01 u> */ + TCG_COND_LTU, /* 0x02 u< */ + TCG_COND_NE, /* 0x03 u< or u> -> NE */ + TCG_COND_EQ, /* 0x04 = */ + TCG_COND_GEU, /* 0x05 u> or = */ + TCG_COND_LEU, /* 0x06 u< or = */ + TCG_COND_ALWAYS,/* 0x07 u< or u> or = -> ALWAYS */ + TCG_COND_GT, /* 0x08 > */ + -1, /* 0x09 > or u> -> weird */ + -1, /* 0x0a > or u< -> weird */ + -1, /* 0x0b > or u< or u> -> weird */ + TCG_COND_GE, /* 0x0c > or = */ + -1, /* 0x0d > or = or u> */ + -1, /* 0x0e > or = or u< */ + -1, /* 0x0f > or = or u> or u< */ + TCG_COND_LT, /* 0x10 < */ + -1, /* 0x11 < or u> -> weird */ + -1, /* 0x12 < or u< -> weird */ + -1, /* 0x13 < or u< or u> -> weird */ + TCG_COND_LE, /* 0x14 < or = */ + -1, /* 0x15 < or = or u> -> weird */ + -1, /* 0x16 < or = or u< -> weird */ + TCG_COND_ALWAYS,/* 0x17 < or = or u< or u> -> ALWAYS */ + TCG_COND_NE, /* 0x18 < or > -> NE */ + -1, /* 0x19 < or > or u> -> weird */ + -1, /* 0x1a < or > or u< -> weird */ + -1, /* 0x1b < or > or u> or u< -> weird */ + TCG_COND_ALWAYS,/* 0x1c < or > or = -> ALWAYS */ + TCG_COND_ALWAYS,/* 0x1d < or > or = or u> -> ALWAYS */ + TCG_COND_ALWAYS,/* 0x1e < or > or = or u< -> ALWAYS */ + TCG_COND_ALWAYS,/* 0x1f < or > or = or u< -> ALWAYS */ +}; + +#define TRAP_UNCOND (-1) +#define TRAP_HELPER (-2) + +static int precheck_trap(DisasContext *ctx) { - /* Trap never */ - if (TO(ctx->opcode) == 0) { - return true; + int cond = TO2tcg[TO(ctx->opcode)]; + + /* Weird traps go to helper */ + if (cond < 0) { + return TRAP_HELPER; } - /* Trap always */ - if (TO(ctx->opcode) == 31) { + /* Unconditionals */ + if (cond == TCG_COND_ALWAYS) { gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP); - return true; + return TRAP_UNCOND; } - return false; + if (cond == TCG_COND_NEVER) { + return TRAP_UNCOND; + } + /* Invert the condition as we branch over the exception when the + * condition is *not* met + */ + return tcg_invert_cond(cond); +} + +static void gen_trap(DisasContext *ctx) +{ + TCGv_i32 t0, t1; + + t0 = tcg_const_i32(POWERPC_EXCP_PROGRAM); + t1 = tcg_const_i32(POWERPC_EXCP_TRAP); + gen_update_nip(ctx, ctx->nip - 4); + gen_helper_raise_exception_err(cpu_env, t0, t1); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(t1); } /* tw */ static void gen_tw(DisasContext *ctx) { - TCGv_i32 t0; + int cond = precheck_trap(ctx); + TCGLabel *l1; + TCGv t0; + TCGv t1; - if (check_unconditional_trap(ctx)) { + if (cond == TRAP_UNCOND) { + return; + } else if (cond == TRAP_HELPER) { + TCGv_i32 trapop = tcg_const_i32(TO(ctx->opcode)); + gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], + cpu_gpr[rB(ctx->opcode)], trapop); + tcg_temp_free_i32(trapop); return; } - t0 = tcg_const_i32(TO(ctx->opcode)); - gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], - t0); - tcg_temp_free_i32(t0); + l1 = gen_new_label(); + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]); + tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]); + tcg_gen_brcond_tl(cond, t0, t1, l1); + gen_trap(ctx); + gen_set_label(l1); + tcg_temp_free(t0); + tcg_temp_free(t1); } /* twi */ static void gen_twi(DisasContext *ctx) { + int cond = precheck_trap(ctx); + TCGLabel *l1; TCGv t0; - TCGv_i32 t1; - if (check_unconditional_trap(ctx)) { + if (cond == TRAP_UNCOND) { + return; + } else if (cond == TRAP_HELPER) { + TCGv_i32 trapop = tcg_const_i32(TO(ctx->opcode)); + t0 = tcg_const_tl(SIMM(ctx->opcode)); + gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, trapop); + tcg_temp_free_i32(trapop); + tcg_temp_free(t0); return; } - t0 = tcg_const_tl(SIMM(ctx->opcode)); - t1 = tcg_const_i32(TO(ctx->opcode)); - gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1); + l1 = gen_new_label(); + t0 = tcg_temp_new(); + tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]); + tcg_gen_brcondi_tl(cond, t0, SIMM(ctx->opcode), l1); + gen_trap(ctx); + gen_set_label(l1); tcg_temp_free(t0); - tcg_temp_free_i32(t1); } #if defined(TARGET_PPC64) /* td */ static void gen_td(DisasContext *ctx) { - TCGv_i32 t0; + int cond = precheck_trap(ctx); + TCGLabel *l1; - if (check_unconditional_trap(ctx)) { + if (cond == TRAP_UNCOND) { + return; + } else if (cond == TRAP_HELPER) { + TCGv_i32 trapop = tcg_const_i32(TO(ctx->opcode)); + gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], + cpu_gpr[rB(ctx->opcode)], trapop); + tcg_temp_free_i32(trapop); return; } - t0 = tcg_const_i32(TO(ctx->opcode)); - gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], - t0); - tcg_temp_free_i32(t0); + l1 = gen_new_label(); + tcg_gen_brcond_tl(cond, cpu_gpr[rA(ctx->opcode)], + cpu_gpr[rB(ctx->opcode)], l1); + gen_trap(ctx); + gen_set_label(l1); } /* tdi */ static void gen_tdi(DisasContext *ctx) { - TCGv t0; - TCGv_i32 t1; + int cond = precheck_trap(ctx); + TCGLabel *l1; - if (check_unconditional_trap(ctx)) { + if (cond == TRAP_UNCOND) { + return; + } else if (cond == TRAP_HELPER) { + TCGv_i32 trapop = tcg_const_i32(TO(ctx->opcode)); + TCGv t0 = tcg_const_tl(SIMM(ctx->opcode)); + gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, trapop); + tcg_temp_free_i32(trapop); + tcg_temp_free(t0); return; } - t0 = tcg_const_tl(SIMM(ctx->opcode)); - t1 = tcg_const_i32(TO(ctx->opcode)); - gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1); - tcg_temp_free(t0); - tcg_temp_free_i32(t1); + l1 = gen_new_label(); + tcg_gen_brcondi_tl(cond, cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode), l1); + gen_trap(ctx); + gen_set_label(l1); } -#endif +#endif /* defined(TARGET_PPC64) */ /*** Processor control ***/ -- 2.7.4