diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index 8ac6ee872f..769be4a174 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -36,12 +36,16 @@ void e2k_tcg_initialize(void); #define CTPR_BASE_OFF 0 #define CTPR_BASE_END 47 +#define CTPR_BASE_LEN (CTPR_BASE_END - CTPR_BASE_OFF + 1) #define CTPR_TAG_OFF 54 #define CTPR_TAG_END 56 +#define CTPR_TAG_LEN (CTPR_TAG_END - CTPR_TAG_OFF + 1) #define CTPR_OPC_OFF 57 #define CTPR_OPC_END 58 +#define CTPR_OPC_LEN (CTPR_OPC_END - CTPR_OPC_OFF + 1) #define CTPR_IPD_OFF 59 #define CTPR_IPD_END 60 +#define CTPR_IPD_LEN (CTPR_IPD_END - CTPR_IPD_OFF + 1) #define WD_BASE_OFF 0 #define WD_BASE_END 10 diff --git a/target/e2k/helper.c b/target/e2k/helper.c index a3e8672978..cacc0c45f7 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -182,10 +182,10 @@ static inline void do_call(CPUE2KState *env, int call_wbs) reset_ctprs(env); } -static uint64_t do_return(CPUE2KState *env) +target_ulong helper_return(CPUE2KState *env) { int new_wbs, old_wbs; - uint64_t tgt; + target_ulong tgt; old_wbs = e2k_state_wbs_get(env) * 2; @@ -211,28 +211,10 @@ static inline void do_syscall(CPUE2KState *env, int call_wbs) { do_call(env, call_wbs); helper_raise_exception(env, E2K_EXCP_SYSCALL); - do_return(env); + helper_return(env); reset_ctprs(env); } -target_ulong helper_jump(CPUE2KState *env, uint64_t ctpr) -{ - int ctpr_tag = GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END); - - helper_save_cpu_state(env); - - switch (ctpr_tag) { - case CTPR_TAG_RETURN: - return do_return(env); - case CTPR_TAG_DISP: - /* TODO: ldisp */ - return GET_FIELD(ctpr, CTPR_BASE_OFF, CTPR_BASE_END); - default: - helper_raise_exception(env, E2K_EXCP_UNIMPL); - return env->nip; - } -} - target_ulong helper_call(CPUE2KState *env, uint64_t ctpr, int call_wbs) { diff --git a/target/e2k/helper.h b/target/e2k/helper.h index a5770a14ed..204a2ef3f4 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -2,7 +2,7 @@ DEF_HELPER_1(save_cpu_state, void, env) DEF_HELPER_1(unimpl, noreturn, env) DEF_HELPER_2(raise_exception, noreturn, env, int) DEF_HELPER_1(debug, void, env) -DEF_HELPER_2(jump, tl, env, i64) +DEF_HELPER_1(return, tl, env) DEF_HELPER_3(call, tl, env, i64, int) DEF_HELPER_2(sxt, i64, i64, i64) DEF_HELPER_1(debug_i32, void, i32) diff --git a/target/e2k/translate.c b/target/e2k/translate.c index 598be3ca51..b5b8b0cf15 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -246,6 +246,26 @@ void e2k_gen_exception(DisasContext *ctx, int which) tcg_temp_free_i32(t); } +static inline void gen_ctpr_tag(TCGv_i64 ret, TCGv_i64 ctpr) +{ + tcg_gen_extract_i64(ret, ctpr, CTPR_TAG_OFF, CTPR_TAG_LEN); +} + +static inline void gen_goto_ctpr_disp(TCGv_i64 ctpr) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv t1 = tcg_temp_new(); + + tcg_gen_extract_i64(t0, ctpr, CTPR_BASE_OFF, CTPR_BASE_LEN); + tcg_gen_trunc_i64_tl(t1, t0); + // FIXME: save state here? + tcg_gen_mov_tl(e2k_cs.pc, t1); + tcg_gen_lookup_and_goto_ptr(); + + tcg_temp_free(t1); + tcg_temp_free_i64(t0); +} + static inline void do_decode(DisasContext *ctx, CPUState *cs) { E2KCPU *cpu = E2K_CPU(cs); @@ -334,14 +354,31 @@ static inline void do_branch(DisasContext *ctx) switch(ctx->ct.type) { case CT_IBRANCH: // TODO: goto_tb - tcg_gen_movi_tl(e2k_cs.pc, ctx->ct.u.target); - tcg_gen_exit_tb(NULL, 0); + gen_goto_tb(ctx, 0, ctx->pc, ctx->ct.u.target); break; - case CT_JUMP: + case CT_JUMP: { + TCGLabel *l0 = gen_new_label(); + TCGLabel *l1 = gen_new_label(); + TCGv_i64 t0 = tcg_temp_new_i64(); + + gen_ctpr_tag(t0, ctx->ct.u.ctpr); + tcg_gen_brcondi_i64(TCG_COND_EQ, t0, CTPR_TAG_DISP, l0); + gen_ctpr_tag(t0, ctx->ct.u.ctpr); + tcg_gen_brcondi_i64(TCG_COND_EQ, t0, CTPR_TAG_RETURN, l1); + // TODO: ldisp, sdisp + e2k_gen_exception(ctx, E2K_EXCP_UNIMPL); + + gen_set_label(l0); + gen_goto_ctpr_disp(ctx->ct.u.ctpr); + + gen_set_label(l1); gen_save_cpu_state(ctx); - gen_helper_jump(e2k_cs.pc, cpu_env, ctx->ct.u.ctpr); + gen_helper_return(e2k_cs.pc, cpu_env); tcg_gen_lookup_and_goto_ptr(); + + tcg_temp_free_i64(t0); break; + } case CT_CALL: { TCGv_i32 wbs = tcg_const_i32(ctx->ct.wbs); gen_save_cpu_state(ctx);