From 1c03415d9eb1d455f3e33bb386cfc0eded282586 Mon Sep 17 00:00:00 2001 From: Denis Drakhnya Date: Wed, 9 Dec 2020 00:08:55 +0200 Subject: [PATCH] target: e2k: Restricted loop_mode implementation. --- target/e2k/cpu.h | 1 + target/e2k/translate.c | 6 +- target/e2k/translate.h | 109 +++++++++++--- target/e2k/translate/aau.c | 5 +- target/e2k/translate/alc.c | 14 ++ target/e2k/translate/control.c | 264 ++++++++++++++++----------------- target/e2k/translate/plu.c | 4 +- target/e2k/translate/state.c | 13 +- 8 files changed, 249 insertions(+), 167 deletions(-) diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index 3a0a8677e3..61007fb77a 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -186,6 +186,7 @@ typedef enum { #define LSR_ECNT_END 36 #define LSR_ECNT_LEN (LSR_ECNT_END - LSR_ECNT_OFF + 1) #define LSR_VLC_OFF 37 /* loop count valid bit */ +#define LSR_VLC_BIT (1UL << LSR_VLC_OFF) #define LSR_OVER_OFF 38 /* loop count overflow */ #define LSR_LDMC_OFF 39 /* loads manual control */ #define LSR_LDOVL_OFF 40 /* load overlap */ diff --git a/target/e2k/translate.c b/target/e2k/translate.c index 1abea1b3c3..cec0fa4f26 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -311,7 +311,7 @@ static inline void do_branch(DisasContext *ctx, target_ulong pc_next) if (ctx->ct.is_branch) { TCGLabel *l0 = gen_new_label(); - tcg_gen_brcondi_tl(TCG_COND_NE, e2k_cs.ct_cond, 0, l0); + tcg_gen_brcondi_i32(TCG_COND_NE, e2k_cs.ct_cond, 0, l0); gen_goto_tb(ctx, TB_EXIT_IDX1, pc_next); gen_set_label(l0); } @@ -369,7 +369,7 @@ static void e2k_tr_tb_start(DisasContextBase *db, CPUState *cs) { // DisasContext *ctx = container_of(db, DisasContext, base); - tcg_gen_movi_tl(e2k_cs.ct_cond, 0); + tcg_gen_movi_i32(e2k_cs.ct_cond, 0); } static void e2k_tr_insn_start(DisasContextBase *db, CPUState *cs) @@ -467,6 +467,7 @@ void e2k_tcg_initialize(void) { { &e2k_cs.aasti_tags, offsetof(CPUE2KState, aau.sti_tags), "aasti_tags" }, { &e2k_cs.aaind_tags, offsetof(CPUE2KState, aau.ind_tags), "aaind_tags" }, { &e2k_cs.aaincr_tags, offsetof(CPUE2KState, aau.incr_tags), "aaincr_tags" }, + { &e2k_cs.ct_cond, offsetof(CPUE2KState, ct_cond), "cond" }, }; static const struct { TCGv_i64 *ptr; int off; const char *name; } r64[] = { @@ -477,7 +478,6 @@ void e2k_tcg_initialize(void) { static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { { &e2k_cs.pc, offsetof(CPUE2KState, ip), "pc" }, { &e2k_cs.npc, offsetof(CPUE2KState, nip), "npc" }, - { &e2k_cs.ct_cond, offsetof(CPUE2KState, ct_cond), "cond" }, }; unsigned int i; diff --git a/target/e2k/translate.h b/target/e2k/translate.h index e4b65ab833..ff9c024a15 100644 --- a/target/e2k/translate.h +++ b/target/e2k/translate.h @@ -4,21 +4,6 @@ #include "tcg/tcg-op.h" #include "exec/translator.h" -/* ibranch disp */ -#define DISAS_JUMP_STATIC DISAS_TARGET_0 -/* ibranch disp ? cond */ -#define DISAS_BRANCH_STATIC DISAS_TARGET_1 -/* - * ct %ctprN - * call %ctprN, wbs=M - * */ -#define DISAS_JUMP DISAS_TARGET_2 -/* - * ct %ctprN ? cond - * call %ctprN, wbs=M ? cond - */ -#define DISAS_BRANCH DISAS_TARGET_3 - #define IS_BASED(i) (((i) & 0x80) == 0) #define IS_REGULAR(i) (((i) & 0xc0) == 0x80) #define IS_IMM5(i) (((i) & 0xe0) == 0xc0) @@ -52,7 +37,7 @@ typedef struct CPUE2KStateTCG { TCGv pc; TCGv npc; TCGv_i64 ctprs[3]; - TCGv ct_cond; + TCGv_i32 ct_cond; TCGv_i32 is_bp; /* breakpoint flag */ TCGv_i64 lsr; TCGv_i64 regs[E2K_REG_COUNT]; @@ -186,6 +171,9 @@ typedef struct DisasContext { int jump_ctpr; int mmuidx; uint8_t mas[6]; + bool loop_mode; + TCGv_i32 is_prologue; + TCGv_i32 is_epilogue; int version; @@ -312,23 +300,67 @@ static inline TCGv e2k_get_temp(DisasContext *dc) return dc->ttl[dc->ttl_len++] = tcg_temp_local_new(); } -static inline void e2k_gen_lcnt(TCGv_i64 ret) +static inline void e2k_gen_lcnt_i64(TCGv_i64 ret) { tcg_gen_andi_i64(ret, e2k_cs.lsr, (1UL << 32) - 1); } -static inline void e2k_gen_ecnt(TCGv_i64 ret) +static inline void e2k_gen_lcnt_i32(TCGv_i32 ret) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + + e2k_gen_lcnt_i64(t0); + tcg_gen_extrl_i64_i32(ret, t0); + tcg_temp_free_i64(t0); +} + +static inline void e2k_gen_lcnt_set_i32(TCGv_i32 value) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + + tcg_gen_extu_i32_i64(t0, value); + tcg_gen_deposit_i64(e2k_cs.lsr, e2k_cs.lsr, t0, LSR_LCNT_OFF, LSR_LCNT_LEN); + tcg_temp_free_i64(t0); +} + +static inline void e2k_gen_ecnt_i64(TCGv_i64 ret) { tcg_gen_extract_i64(ret, e2k_cs.lsr, LSR_ECNT_OFF, LSR_ECNT_LEN); } -static inline void e2k_gen_pcnt(TCGv_i32 ret) +static inline void e2k_gen_ecnt_i32(TCGv_i32 ret) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + + e2k_gen_ecnt_i64(t0); + tcg_gen_extrl_i64_i32(ret, t0); + tcg_temp_free_i64(t0); +} + +static inline void e2k_gen_ecnt_set_i32(TCGv_i32 value) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + + tcg_gen_extu_i32_i64(t0, value); + tcg_gen_deposit_i64(e2k_cs.lsr, e2k_cs.lsr, t0, LSR_ECNT_OFF, LSR_ECNT_LEN); + tcg_temp_free_i64(t0); +} + +static inline void e2k_gen_pcnt_i32(TCGv_i32 ret) { TCGv_i64 t0 = tcg_temp_new_i64(); tcg_gen_extract_i64(t0, e2k_cs.lsr, LSR_PCNT_OFF, LSR_PCNT_LEN); tcg_gen_extrl_i64_i32(ret, t0); + tcg_temp_free_i64(t0); +} +static inline void e2k_gen_pcnt_set_i32(TCGv_i32 value) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + + tcg_gen_extu_i32_i64(t0, value); + tcg_gen_deposit_i64(e2k_cs.lsr, e2k_cs.lsr, t0, LSR_PCNT_OFF, LSR_PCNT_LEN); tcg_temp_free_i64(t0); } @@ -397,7 +429,8 @@ void e2k_gen_reg_read_i32(TCGv_i32 ret, TCGv_i32 idx); void e2k_gen_reg_write_i64(TCGv_i64 value, TCGv_i32 idx); void e2k_gen_reg_write_i32(TCGv_i32 value, TCGv_i32 idx); -void e2k_gen_preg(TCGv_i64 ret, int reg); +void e2k_gen_preg_i64(TCGv_i64 ret, int reg); +void e2k_gen_preg_i32(TCGv_i32 ret, int reg); TCGv_i64 e2k_get_preg(DisasContext *dc, int reg); void e2k_gen_cond_i32(DisasContext *ctx, TCGv_i32 ret, uint8_t psrc); @@ -412,6 +445,42 @@ static inline void e2k_gen_cond_i64(DisasContext *ctx, TCGv_i64 ret, tcg_temp_free_i32(t0); } +static inline void e2k_gen_is_last_iter(TCGv_i32 ret) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i32 t3 = tcg_temp_new_i32(); + + e2k_gen_lcnt_i32(t0); + tcg_gen_setcondi_i32(TCG_COND_LTU, t1, t0, 2); + tcg_gen_andi_i64(t2, e2k_cs.lsr, LSR_VLC_BIT); + tcg_gen_setcondi_i64(TCG_COND_NE, t2, t2, 0); + tcg_gen_extrl_i64_i32(t3, t2); + tcg_gen_and_i32(ret, t1, t3); + + tcg_temp_free_i32(t3); + tcg_temp_free_i64(t2); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); +} + +static inline void e2k_gen_is_loop_end_i32(TCGv_i32 ret) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + e2k_gen_ecnt_i32(t0); + tcg_gen_setcondi_i32(TCG_COND_EQ, t1, t0, 0); + e2k_gen_is_last_iter(t2); + tcg_gen_and_i32(ret, t1, t2); + + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); +} + void e2k_control_execute(DisasContext *ctx); void e2k_control_window_change(DisasContext *ctx); void e2k_stubs_commit(DisasContext *ctx); diff --git a/target/e2k/translate/aau.c b/target/e2k/translate/aau.c index 24ffffec33..0f85ae258c 100644 --- a/target/e2k/translate/aau.c +++ b/target/e2k/translate/aau.c @@ -97,7 +97,8 @@ static void gen_mova(DisasContext *ctx, Instr *instr) TCGv t5 = tcg_temp_new(); ctx->aau_am[instr->chan] = instr->am ? instr->area : -1; - // TODO: check ind + // TODO: check ind has proper alignment + // TODO: check ind is less than mrng gen_mova_ptr(t5, instr); switch(instr->opc) { @@ -110,9 +111,11 @@ static void gen_mova(DisasContext *ctx, Instr *instr) gen_mova_i64(ctx, instr, t5); break; case 5: /* movaq */ + qemu_log_mask(LOG_UNIMP, "0x%lx: movaq is not implemented\n", ctx->pc); abort(); break; case 7: /* movaqp */ + qemu_log_mask(LOG_UNIMP, "0x%lx: movaqp is not implemented\n", ctx->pc); abort(); break; default: diff --git a/target/e2k/translate/alc.c b/target/e2k/translate/alc.c index 21cc61edae..e06885dce2 100644 --- a/target/e2k/translate/alc.c +++ b/target/e2k/translate/alc.c @@ -1506,8 +1506,13 @@ static void gen_aad_ptr(DisasContext *ctx, TCGv ret, Instr *instr) static void gen_staa_i64(DisasContext *ctx, Instr *instr) { uint8_t mas = ctx->mas[instr->chan]; + TCGLabel *l0 = gen_new_label(); Src64 s4 = get_src4_i64(ctx, instr->chan); + if (ctx->loop_mode) { + tcg_gen_brcondi_i32(TCG_COND_EQ, ctx->is_prologue, 1, l0); + } + gen_tag_check(ctx, instr->sm, s4.tag); if (mas == 0x3f) { /* aaurwd */ @@ -1545,13 +1550,20 @@ static void gen_staa_i64(DisasContext *ctx, Instr *instr) gen_aasti_incr(ctx, instr, 8); } } + + gen_set_label(l0); } static void gen_staa_i32(DisasContext *ctx, Instr *instr, MemOp memop) { uint8_t mas = ctx->mas[instr->chan]; + TCGLabel *l0 = gen_new_label(); Src32 s4 = get_src4_i32(ctx, instr->chan); + if (ctx->loop_mode) { + tcg_gen_brcondi_i32(TCG_COND_EQ, ctx->is_prologue, 1, l0); + } + gen_tag_check(ctx, instr->sm, s4.tag); if (mas == 0x3f) { /* aaurw */ @@ -1608,6 +1620,8 @@ static void gen_staa_i32(DisasContext *ctx, Instr *instr, MemOp memop) gen_aasti_incr(ctx, instr, len); } } + + gen_set_label(l0); } static void gen_alopf1_i64(DisasContext *ctx, int chan, diff --git a/target/e2k/translate/control.c b/target/e2k/translate/control.c index 45cd3db31e..e4da1435d1 100644 --- a/target/e2k/translate/control.c +++ b/target/e2k/translate/control.c @@ -3,97 +3,26 @@ #include "exec/log.h" #include "translate.h" -static inline void gen_lcnt_dec(TCGv_i64 ret, TCGv_i64 lsr) +static inline TCGCond cond_from_advance(int advance) { - TCGv_i32 zero = tcg_const_i32(0); - TCGv_i32 lcnt = tcg_temp_new_i32(); - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i32 t1 = tcg_temp_new_i32(); - TCGv_i32 t2 = tcg_temp_new_i32(); - TCGv_i32 t3 = tcg_temp_new_i32(); - TCGv_i32 t4 = tcg_temp_new_i32(); - TCGv_i32 t5 = tcg_temp_new_i32(); - - tcg_gen_extrl_i64_i32(lcnt, lsr); - tcg_gen_subi_i32(t0, lcnt, 1); - tcg_gen_movcond_i32(TCG_COND_EQ, t1, lcnt, zero, zero, t0); - - /* overflow bit */ - tcg_gen_extrh_i64_i32(t2, lsr); - tcg_gen_setcondi_i32(TCG_COND_EQ, t3, lcnt, 1); - tcg_gen_shli_i32(t4, t3, LSR_OVER_OFF - 32); - tcg_gen_or_i32(t5, t2, t4); - - tcg_gen_concat_i32_i64(ret, t1, t5); - - tcg_temp_free_i32(t5); - tcg_temp_free_i32(t4); - tcg_temp_free_i32(t3); - tcg_temp_free_i32(t2); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t0); - tcg_temp_free_i32(lcnt); - tcg_temp_free_i32(zero); + switch (advance) { + case 0x01: return TCG_COND_EQ; + case 0x02: return TCG_COND_NE; + case 0x03: return TCG_COND_ALWAYS; + default: return TCG_COND_NEVER; + } } static void gen_movcond_flag_i32(TCGv_i32 ret, int flag, TCGv_i32 cond, TCGv_i32 v1, TCGv_i32 v2) { TCGv_i32 one = tcg_const_i32(1); - TCGCond c; - - switch (flag) { - case 0x00: - c = TCG_COND_NEVER; - break; - case 0x01: - c = TCG_COND_EQ; - break; - case 0x02: - c = TCG_COND_NE; - break; - case 0x03: - c = TCG_COND_ALWAYS; - break; - default: - g_assert_not_reached(); - break; - } + TCGCond c = cond_from_advance(flag); tcg_gen_movcond_i32(c, ret, cond, one, v1, v2); - tcg_temp_free_i32(one); } -static inline void gen_movcond_flag_i64(TCGv_i64 ret, int flag, TCGv_i64 cond, - TCGv_i64 v1, TCGv_i64 v2) -{ - TCGv_i64 one = tcg_const_i64(1); - TCGCond c; - - switch (flag) { - case 0x00: - c = TCG_COND_NEVER; - break; - case 0x01: - c = TCG_COND_EQ; - break; - case 0x02: - c = TCG_COND_NE; - break; - case 0x03: - c = TCG_COND_ALWAYS; - break; - default: - g_assert_not_reached(); - break; - } - - tcg_gen_movcond_i64(c, ret, cond, one, v1, v2); - - tcg_temp_free_i64(one); -} - static inline void gen_dec_wrap(TCGv_i32 ret, TCGv_i32 cur, int n, TCGv_i32 size) { @@ -112,18 +41,92 @@ static inline void gen_cur_dec(DisasContext *ctx, TCGv_i32 ret, int cond, { TCGLabel *l0 = gen_new_label(); TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i32 t1 = tcg_temp_new_i32(); tcg_gen_brcondi_i32(TCG_COND_EQ, size, 0, l0); - tcg_gen_trunc_tl_i32(t0, e2k_cs.ct_cond); - gen_dec_wrap(t1, cur, n, size); - gen_movcond_flag_i32(ret, cond, t0, t1, cur); + gen_dec_wrap(t0, cur, n, size); + gen_movcond_flag_i32(ret, cond, e2k_cs.ct_cond, t0, cur); + gen_set_label(l0); + + tcg_temp_free_i32(t0); +} + +static void gen_advance_pcnt(void) +{ + TCGLabel *l0 = gen_new_label(); + TCGv_i32 t0 = tcg_temp_local_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + + e2k_gen_pcnt_i32(t0); + tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); + tcg_gen_subi_i32(t1, t0, 1); + e2k_gen_pcnt_set_i32(t1); gen_set_label(l0); tcg_temp_free_i32(t1); tcg_temp_free_i32(t0); } +static inline void gen_lcnt_overflow(TCGv_i32 lcnt) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + + tcg_gen_extu_i32_i64(t0, lcnt); + tcg_gen_setcondi_i64(TCG_COND_EQ, t1, t0, 0); + tcg_gen_shli_i64(t1, t1, LSR_OVER_OFF); + tcg_gen_or_i64(e2k_cs.lsr, e2k_cs.lsr, t1); + + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t0); +} + +static void gen_advance_lcnt(TCGv_i32 ret) +{ + TCGLabel *l0 = gen_new_label(); + TCGv_i32 t0 = tcg_temp_local_new_i32(); + + e2k_gen_lcnt_i32(t0); + tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); + tcg_gen_subi_i32(t0, t0, 1); + e2k_gen_lcnt_set_i32(t0); + + gen_set_label(l0); + gen_lcnt_overflow(t0); + tcg_gen_mov_i32(ret, t0); + + tcg_temp_free_i32(t0); +} + +static void gen_advance_ecnt(void) +{ + TCGLabel *l0 = gen_new_label(); + TCGv_i32 t0 = tcg_temp_local_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + + e2k_gen_ecnt_i32(t0); + tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); + tcg_gen_subi_i32(t1, t0, 1); + e2k_gen_ecnt_set_i32(t1); + gen_set_label(l0); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); +} + +static void gen_advance_loop_counters(void) +{ + TCGLabel *l0 = gen_new_label(); + TCGv_i32 t0 = tcg_temp_new_i32(); + + gen_advance_pcnt(); + gen_advance_lcnt(t0); + tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l0); + gen_advance_ecnt(); + gen_set_label(l0); + + tcg_temp_free_i32(t0); +} + void e2k_stubs_commit(DisasContext *ctx) { uint32_t ss = ctx->bundle.ss; @@ -135,11 +138,12 @@ void e2k_stubs_commit(DisasContext *ctx) int abg = GET_FIELD(ss, 23, 2); if (alc) { - TCGv_i64 t0 = tcg_temp_new_i64(); + TCGLabel *l0 = gen_new_label(); + TCGCond cond = cond_from_advance(alc); - gen_lcnt_dec(t0, e2k_cs.lsr); - gen_movcond_flag_i64(e2k_cs.lsr, alc, e2k_cs.ct_cond, t0, e2k_cs.lsr); - tcg_temp_free_i64(t0); + tcg_gen_brcondi_i32(tcg_invert_cond(cond), e2k_cs.ct_cond, 1, l0); + gen_advance_loop_counters(); + gen_set_label(l0); } if (abp) { @@ -170,38 +174,6 @@ void e2k_stubs_commit(DisasContext *ctx) } } -static inline void gen_is_last_iter(TCGv ret) -{ - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - TCGv t2 = tcg_temp_new(); - - e2k_gen_lcnt(t0); - tcg_gen_setcondi_tl(TCG_COND_LTU, t1, t0, 2); - tcg_gen_extract_tl(t2, e2k_cs.lsr, LSR_VLC_OFF, 1); - tcg_gen_and_tl(ret, t1, t2); - - tcg_temp_free(t2); - tcg_temp_free(t1); - tcg_temp_free(t0); -} - -static inline void gen_is_loop_end(TCGv ret) -{ - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - TCGv t2 = tcg_temp_new(); - - e2k_gen_ecnt(t0); - tcg_gen_setcondi_tl(TCG_COND_EQ, t1, t0, 0); - gen_is_last_iter(t2); - tcg_gen_and_tl(ret, t1, t2); - - tcg_temp_free(t2); - tcg_temp_free(t1); - tcg_temp_free(t0); -} - static void gen_cs0(DisasContext *dc) { typedef enum { @@ -469,30 +441,28 @@ static void gen_jmp(DisasContext *dc) } if (cond_type == 1) { - tcg_gen_movi_tl(e2k_cs.ct_cond, 1); + tcg_gen_movi_i32(e2k_cs.ct_cond, 1); } else if (cond_type > 1) { - TCGv preg = tcg_temp_new(); - TCGv loop_end = tcg_temp_new(); - TCGv not_loop_end = tcg_temp_new(); - TCGv cond = e2k_cs.ct_cond; - TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i32 preg = tcg_temp_new_i32(); + TCGv_i32 loop_end = tcg_temp_new_i32(); + TCGv_i32 not_loop_end = tcg_temp_new_i32(); + TCGv_i32 cond = e2k_cs.ct_cond; dc->ct.is_branch = true; - e2k_gen_preg(t0, psrc); - tcg_gen_trunc_i64_tl(preg, t0); - gen_is_loop_end(loop_end); - tcg_gen_setcondi_tl(TCG_COND_NE, not_loop_end, loop_end, 1); + e2k_gen_preg_i32(preg, psrc); + e2k_gen_is_loop_end_i32(loop_end); + tcg_gen_setcondi_i32(TCG_COND_NE, not_loop_end, loop_end, 1); switch (cond_type) { case 0x2: case 0x6: case 0xf: - tcg_gen_mov_tl(cond, preg); + tcg_gen_mov_i32(cond, preg); break; case 0x3: case 0x7: case 0xe: - tcg_gen_setcondi_tl(TCG_COND_NE, cond, preg, 1); + tcg_gen_setcondi_i32(TCG_COND_NE, cond, preg, 1); break; default: break; @@ -500,24 +470,25 @@ static void gen_jmp(DisasContext *dc) switch (cond_type) { case 0x4: - tcg_gen_mov_tl(cond, loop_end); + tcg_gen_mov_i32(cond, loop_end); break; case 0x5: - tcg_gen_mov_tl(cond, not_loop_end); + tcg_gen_mov_i32(cond, not_loop_end); break; case 0x6: case 0xe: - tcg_gen_or_tl(cond, cond, loop_end); + tcg_gen_or_i32(cond, cond, loop_end); break; case 0x7: case 0xf: - tcg_gen_and_tl(cond, cond, not_loop_end); + tcg_gen_and_i32(cond, cond, not_loop_end); break; default: break; } if (cond_type == 8) { + qemu_log_mask(LOG_UNIMP, "0x%lx: ct cond is not implemented!\n", dc->pc); // %MLOCK /* It's not clearly said in C.17.1.2 of iset-vX.single if the uppermost fourth bit in `psrc' has any meaning at all. */ @@ -536,6 +507,7 @@ static void gen_jmp(DisasContext *dc) /* `lock_cond || pl_cond' control transfer conditions. */ if (cond_type == 9) { + qemu_log_mask(LOG_UNIMP, "0x%lx: ct cond is not implemented!\n", dc->pc); unsigned int type = (psrc & 0x18) >> 3; if (type == 0) { // static const int cmp_num_to_alc[] = {0, 1, 3, 4}; @@ -567,10 +539,9 @@ static void gen_jmp(DisasContext *dc) } - tcg_temp_free_i64(t0); - tcg_temp_free(not_loop_end); - tcg_temp_free(loop_end); - tcg_temp_free(preg); + tcg_temp_free_i32(not_loop_end); + tcg_temp_free_i32(loop_end); + tcg_temp_free_i32(preg); } } @@ -647,6 +618,21 @@ void e2k_control_execute(DisasContext *ctx) { ctx->ct.type = CT_NONE; + ctx->loop_mode = (ctx->bundle.hs & (1 << 10)) != 0; + if (ctx->loop_mode) { + TCGv_i32 t0 = tcg_temp_new_i32(); + + ctx->is_prologue = e2k_get_temp_i32(ctx); + e2k_gen_pcnt_i32(t0); + tcg_gen_setcondi_i32(TCG_COND_NE, ctx->is_prologue, t0, 0); + + ctx->is_epilogue = e2k_get_temp_i32(ctx); + e2k_gen_lcnt_i32(t0); + tcg_gen_setcondi_i32(TCG_COND_EQ, ctx->is_epilogue, t0, 0); + + tcg_temp_free_i32(t0); + } + if (ctx->bundle.ss_present) { gen_jmp(ctx); } diff --git a/target/e2k/translate/plu.c b/target/e2k/translate/plu.c index 2f0b40daee..859f92711d 100644 --- a/target/e2k/translate/plu.c +++ b/target/e2k/translate/plu.c @@ -35,7 +35,7 @@ void e2k_gen_cond_i32(DisasContext *ctx, TCGv_i32 ret, uint8_t psrc) int reg = GET_FIELD(psrc, 0, 5); TCGv_i64 t0 = tcg_temp_new_i64(); - e2k_gen_preg(t0, reg); + e2k_gen_preg_i64(t0, reg); tcg_gen_extrl_i64_i32(ret, t0); tcg_temp_free_i64(t0); @@ -161,7 +161,7 @@ void e2k_plu_execute(DisasContext *ctx) TCGv_i64 t0 = tcg_temp_new_i64(); TCGv_i32 t1 = tcg_temp_new_i32(); - e2k_gen_preg(t0, pdst); + e2k_gen_preg_i64(t0, pdst); tcg_gen_extrl_i64_i32(t1, t0); tcg_gen_movcond_i32(TCG_COND_EQ, ctx->pl_results[i].value, p0, one, p1, t1); diff --git a/target/e2k/translate/state.c b/target/e2k/translate/state.c index ee1dc81d41..b84e70c12c 100644 --- a/target/e2k/translate/state.c +++ b/target/e2k/translate/state.c @@ -54,7 +54,7 @@ static void gen_preg_clear(TCGv_i64 ret, TCGv_i64 offset) tcg_temp_free_i64(t0); } -void e2k_gen_preg(TCGv_i64 ret, int reg) +void e2k_gen_preg_i64(TCGv_i64 ret, int reg) { TCGv_i64 one = tcg_const_i64(1); TCGv_i64 t0 = tcg_temp_new_i64(); @@ -72,10 +72,19 @@ void e2k_gen_preg(TCGv_i64 ret, int reg) tcg_temp_free_i64(one); } +void e2k_gen_preg_i32(TCGv_i32 ret, int reg) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + + e2k_gen_preg_i64(t0, reg); + tcg_gen_extrl_i64_i32(ret, t0); + tcg_temp_free_i64(t0); +} + TCGv_i64 e2k_get_preg(DisasContext *dc, int reg) { TCGv_i64 ret = e2k_get_temp_i64(dc); - e2k_gen_preg(ret, reg); + e2k_gen_preg_i64(ret, reg); return ret; }