diff --git a/target/e2k/translate.c b/target/e2k/translate.c index a6821c5f5e..a18833bcf0 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -310,10 +310,17 @@ static inline void do_commit(DisasContext *ctx) unsigned int i; for (i = 0; i < 6; i++) { + TCGLabel *l0 = gen_new_label(); Result *res = &ctx->alc[i]; + if (!ctx->bundle.als_present[i]) { continue; } + + if (res->has_cond) { + tcg_gen_brcondi_i64(TCG_COND_EQ, res->cond, 0, l0); + } + switch(res->tag) { case RESULT_BASED_REG: e2k_gen_store_breg(res->u.reg.i, res->u.reg.v); @@ -330,6 +337,8 @@ static inline void do_commit(DisasContext *ctx) default: break; } + + gen_set_label(l0); } e2k_plu_commit(ctx); diff --git a/target/e2k/translate.h b/target/e2k/translate.h index 3634ad1407..13aa597781 100644 --- a/target/e2k/translate.h +++ b/target/e2k/translate.h @@ -110,6 +110,8 @@ enum ResultType { typedef struct { enum ResultType tag; + bool has_cond; + TCGv_i64 cond; union { struct { unsigned int i; @@ -158,6 +160,7 @@ typedef struct DisasContext { int t64_len; int ttl_len; + TCGv_i64 cond[6]; Result alc[6]; PluResult plu[3]; ControlTransfer ct; @@ -220,6 +223,18 @@ TCGv_i64 e2k_get_breg(DisasContext *dc, int reg); void e2k_gen_store_breg(int reg, TCGv_i64 val); TCGv_i64 e2k_get_greg(DisasContext *dc, int reg); void e2k_gen_store_greg(int reg, TCGv_i64 val); +void e2k_gen_cond_i32(DisasContext *ctx, TCGv_i32 ret, uint8_t psrc); + +static inline void e2k_gen_cond_i64(DisasContext *ctx, TCGv_i64 ret, + uint8_t psrc) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + + e2k_gen_cond_i32(ctx, t0, psrc); + tcg_gen_extu_i32_i64(ret, t0); + + tcg_temp_free_i32(t0); +} void e2k_gen_exception(DisasContext *dc, int which); diff --git a/target/e2k/translate/alc.c b/target/e2k/translate/alc.c index 22cccf9136..9c01498e23 100644 --- a/target/e2k/translate/alc.c +++ b/target/e2k/translate/alc.c @@ -454,14 +454,34 @@ static uint16_t find_mrgc(DisasContext *dc, int chan) return 0; } -static inline void gen_cond_psrc(TCGv_i64 ret, uint8_t psrc) +static inline bool is_cond(uint16_t rlp, int chan) { - if ((psrc & 0xe0) == 0x60) { - e2k_gen_preg(ret, psrc & 0x1f); - } else { - /* TODO: lcntex, spred, pcnt */ - abort(); + int is_mrgc = GET_BIT(rlp, 15); + int cluster = GET_BIT(rlp, 14); + int alc_mask = GET_FIELD(rlp, 10, 3); + int alc = GET_BIT(alc_mask, chan % 3); + + return !is_mrgc && (cluster == (chan > 2)) && (alc != 0); +} + +static uint16_t find_cond(DisasContext *ctx, int chan) +{ + unsigned int i; + + for (i = 0; ctx->bundle.cds_present[i]; i++) { + uint32_t cds = ctx->bundle.cds[i]; + uint16_t rlp0 = cds >> 16; + uint16_t rlp1 = cds & 0xffff; + + if (is_cond(rlp0, chan)) { + return rlp0; + } + if (is_cond(rlp1, chan)) { + return rlp1; + } } + + return 0; } static inline void gen_mrgc_i64(DisasContext *dc, int chan, TCGv_i64 ret) @@ -480,7 +500,7 @@ static inline void gen_mrgc_i64(DisasContext *dc, int chan, TCGv_i64 ret) t1 = tcg_temp_new_i64(); inv = tcg_const_i64(GET_BIT(rlp, 7 + chan % 3)); - gen_cond_psrc(t0, rlp & 0x7f); + e2k_gen_cond_i64(dc, t0, rlp & 0x7f); tcg_gen_not_i64(t1, t0); tcg_gen_movcond_i64(TCG_COND_EQ, ret, t0, inv, t0, t1); @@ -848,22 +868,38 @@ static void execute_ext1(DisasContext *dc, int chan) } } -void e2k_execute_alc(DisasContext *ctx, int index) +void e2k_execute_alc(DisasContext *ctx, int chan) { const UnpackedBundle *bundle = &ctx->bundle; + uint16_t rlp = find_cond(ctx, chan); + TCGLabel *l0 = gen_new_label(); + TCGv_i64 cond = NULL; - switch(bundle->ales_present[index]) { + if (rlp != 0) { + TCGv_i64 t0 = tcg_temp_new_i64(); + uint8_t psrc = GET_FIELD(rlp, 0, 7); + bool neg = GET_BIT(rlp, 7 + chan % 3); + + e2k_gen_cond_i64(ctx, t0, psrc); + cond = e2k_get_temp_i64(ctx); + tcg_gen_xori_i64(cond, t0, neg); + tcg_gen_brcondi_i64(TCG_COND_EQ, cond, 0, l0); + + tcg_temp_free_i64(t0); + } + + switch(bundle->ales_present[chan]) { case ALES_NONE: - execute_alopf_simple(ctx, index); + execute_alopf_simple(ctx, chan); break; case ALES_ALLOCATED: // 2 or 5 channel e2k_gen_exception(ctx, E2K_EXCP_ILLOPC); break; case ALES_PRESENT: { - uint8_t opc = GET_FIELD(bundle->ales[index], 8, 8); + uint8_t opc = GET_FIELD(bundle->ales[chan], 8, 8); switch (opc) { case 0x01: - execute_ext1(ctx, index); + execute_ext1(ctx, chan); break; default: e2k_gen_exception(ctx, E2K_EXCP_ILLOPC); @@ -875,4 +911,9 @@ void e2k_execute_alc(DisasContext *ctx, int index) g_assert_not_reached(); break; } + + gen_set_label(l0); + + ctx->alc[chan].has_cond = rlp != 0; + ctx->alc[chan].cond = cond; } diff --git a/target/e2k/translate/plu.c b/target/e2k/translate/plu.c index d1eeaeeaff..27686a1341 100644 --- a/target/e2k/translate/plu.c +++ b/target/e2k/translate/plu.c @@ -11,17 +11,17 @@ static void gen_get_lp(TCGv_i32 ret, uint16_t clp, int offset, TCGv_i32 lp[7]) tcg_gen_xori_i32(ret, lp[p], neg); } -static void gen_elp(DisasContext *ctx, TCGv_i32 ret, uint8_t elp) +void e2k_gen_cond_i32(DisasContext *ctx, TCGv_i32 ret, uint8_t psrc) { - if (!GET_BIT(elp, 6)) { - if (GET_FIELD(elp, 0, 6) == 0) { + if (!GET_BIT(psrc, 6)) { + if (GET_FIELD(psrc, 0, 6) == 0) { e2k_gen_lcntex(ret); } else { // TODO: spred gen_helper_unimpl(cpu_env); } - } else if (GET_FIELD(elp, 5, 2) == 0x40) { - int val = GET_FIELD(elp, 0, 5); + } else if (GET_FIELD(psrc, 5, 2) == 0x40) { + int val = GET_FIELD(psrc, 0, 5); if (val == 0) { // TODO: bgrpred gen_helper_unimpl(cpu_env); @@ -32,7 +32,7 @@ static void gen_elp(DisasContext *ctx, TCGv_i32 ret, uint8_t elp) e2k_gen_exception(ctx, E2K_EXCP_ILLOPN); } } else { - int reg = GET_FIELD(elp, 0, 5); + int reg = GET_FIELD(psrc, 0, 5); TCGv_i64 t0 = tcg_temp_new_i64(); e2k_gen_preg(t0, reg); @@ -111,12 +111,12 @@ void e2k_plu_execute(DisasContext *ctx) if (i < 2) { if (need[i * 2]) { int elp = GET_FIELD(bundle->pls[i], 24, 7); - gen_elp(ctx, lp[i * 2], elp); + e2k_gen_cond_i32(ctx, lp[i * 2], elp); } if (need[i * 2 + 1]) { int elp = GET_FIELD(bundle->pls[i], 16, 7); - gen_elp(ctx, lp[i * 2 + 1], elp); + e2k_gen_cond_i32(ctx, lp[i * 2 + 1], elp); } }