From c8ed74f6265ec23b1887ab246610bf3cb44888b6 Mon Sep 17 00:00:00 2001 From: Denis Drakhnya Date: Thu, 25 Mar 2021 11:48:23 +0200 Subject: [PATCH] e2k: Add tags and force_save_alc_dst properties. Signed-off-by: Denis Drakhnya --- target/e2k/cpu.c | 22 +++++++++- target/e2k/cpu.h | 8 +++- target/e2k/helper.c | 29 +++++++------ target/e2k/translate.c | 99 +++++++++++++++++++----------------------- 4 files changed, 86 insertions(+), 72 deletions(-) diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index b283b5e84e..f74644c4c8 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -277,6 +277,12 @@ static struct TCGCPUOps e2k_tcg_ops = { #endif }; +static Property e2k_cpu_properties[] = { + DEFINE_PROP_BOOL("force_save_alc_dst", E2KCPU, env.force_save_alc_dst, false), + DEFINE_PROP_BOOL("tags", E2KCPU, env.enable_tags, false), + DEFINE_PROP_END_OF_LIST() +}; + static void e2k_cpu_class_init(ObjectClass *oc, void *data) { E2KCPUClass *ecc = E2K_CPU_CLASS(oc); @@ -285,7 +291,7 @@ static void e2k_cpu_class_init(ObjectClass *oc, void *data) device_class_set_parent_realize(dc, e2k_cpu_realizefn, &ecc->parent_realize); - + device_class_set_props(dc, e2k_cpu_properties); device_class_set_parent_reset(dc, e2k_cpu_reset, &ecc->parent_reset); cc->has_work = e2k_cpu_has_work; @@ -348,6 +354,8 @@ type_init(e2k_cpu_register_types) void e2k_cpu_list(void) { unsigned int i; + Property* prop; + size_t len = 0; for (i = 0; i < ARRAY_SIZE(e2k_defs); i++) { qemu_printf("%6s (%-30s) ISA version: v%d\n", @@ -356,4 +364,16 @@ void e2k_cpu_list(void) e2k_defs[i].isa_version ); } + + qemu_printf("\nFeatures:\n"); + for (prop = e2k_cpu_properties; prop->name != 0; prop++) { + size_t l = strlen(prop->name) + 1; + if (len + l >= 75) { + qemu_printf("\n"); + len = 0; + } + qemu_printf("%s%s", len ? " " : " ", prop->name); + len += l; + } + qemu_printf("\n"); } diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index d7747c35fd..a0e17d4837 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -28,8 +28,6 @@ void e2k_tcg_initialize(void); */ #define E2K_FORCE_FX true -//#define E2K_TAGS_ENABLE - #define GEN_MASK(start, len) (((1UL << (len)) - 1) << (start)) #define GET_BIT(v, index) (((v) >> (index)) & 1) @@ -785,6 +783,12 @@ typedef struct CPUArchState { struct {} end_reset_fields; uint32_t version; + /* Force alop to preserve the destination register before writing to it. + * Default: false */ + bool force_save_alc_dst; + /* Enable tags handling. + * Default: false */ + bool enable_tags; struct e2k_def_t def; diff --git a/target/e2k/helper.c b/target/e2k/helper.c index ffa2aafca0..19fe8577b4 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -21,9 +21,9 @@ static inline void ps_push(CPUE2KState *env, uint64_t value, uint8_t tag) #endif cpu_stq_le_data(env, env->psp.base + env->psp.index, value); -#ifdef E2K_TAGS_ENABLE - cpu_stb_data(env, env->psp.base_tag + env->psp.index / 8, tag); -#endif + if (env->enable_tags) { + cpu_stb_data(env, env->psp.base_tag + env->psp.index / 8, tag); + } env->psp.index += 8; } @@ -34,11 +34,12 @@ static inline uint64_t ps_pop(CPUE2KState *env, uint8_t *ret_tag) } env->psp.index -= 8; if (ret_tag != NULL) { -#ifdef E2K_TAGS_ENABLE - *ret_tag = cpu_ldub_data(env, env->psp.base_tag + env->psp.index / 8); -#else - *ret_tag = 0; -#endif + if (env->enable_tags) { + abi_ptr ptr = env->psp.base_tag + env->psp.index / 8; + *ret_tag = cpu_ldub_data(env, ptr); + } else { + *ret_tag = 0; + } } return cpu_ldq_le_data(env, env->psp.base + env->psp.index); } @@ -97,9 +98,9 @@ static void ps_fill(CPUE2KState *env, int n, bool fx) static void move_regs(CPUE2KState *env, int dst, int src, int n) { memmove(&env->regs[dst], &env->regs[src], n * sizeof(env->regs[0])); -#ifdef E2K_TAGS_ENABLE - memmove(&env->tags[dst], &env->tags[src], n * sizeof(env->tags[0])); -#endif + if (env->enable_tags) { + memmove(&env->tags[dst], &env->tags[src], n * sizeof(env->tags[0])); + } } static void callee_window(CPUE2KState *env, int base, int size, bool fx) @@ -317,9 +318,9 @@ void HELPER(setwd)(CPUE2KState *env, int wsz, int nfx, int dbl) #if 0 memset(&env->regs[env->wd.size], 0, diff * sizeof(env->regs[0])); #endif -#ifdef E2K_TAGS_ENABLE - memset(&env->tags[env->wd.size], E2K_TAG_NON_NUMBER128, diff); -#endif + if (env->enable_tags) { + memset(&env->tags[env->wd.size], E2K_TAG_NON_NUMBER128, diff); + } } env->wd.size = size; diff --git a/target/e2k/translate.c b/target/e2k/translate.c index 5dcda27e9c..a00a2a692f 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -6,7 +6,6 @@ #include "tcg/tcg-op-gvec.h" //#define FORCE_SAVE_PLU_PREG -//#define FORCE_SAVE_ALC_REG //#define FORCE_SAVE_ALC_PREG #define glue3(a, b, c) glue(glue(a, b), c) @@ -504,11 +503,11 @@ typedef struct DisasContext { /* optional, can be NULL */ TCGv_i32 mlock; TCGv_i32 loop_end; -#ifdef E2K_TAGS_ENABLE TCGv_i32 delayed_illop; -#endif int version; + bool enable_tags; + bool force_save_alc_dst; /* Force ILLOP for bad instruction format for cases where real CPU do not generate it. */ bool strict; @@ -1261,7 +1260,6 @@ static void gen_preg_set_i32(int index, TCGv_i32 val) tcg_temp_free_i64(t0); } -#ifdef E2K_TAGS_ENABLE static void gen_reg_tag_ptr(TCGv_ptr ret, TCGv_i32 idx) { TCGv_ptr t0 = tcg_temp_new_ptr(); @@ -1287,30 +1285,28 @@ static inline bool is_tag_mask_all(DisasContext *ctx, uint8_t mask) static void gen_reg_tag_mask(DisasContext *ctx, TCGv_i32 ret, TCGv_i32 index, uint8_t mask) { - TCGv_ptr t0 = tcg_temp_new_ptr(); + if (ctx->enable_tags) { + TCGv_ptr t0 = tcg_temp_new_ptr(); - gen_reg_tag_ptr(t0, index); - if (is_tag_mask_all(ctx, mask)) { - tcg_gen_ld8u_i32(ret, t0, 0); + gen_reg_tag_ptr(t0, index); + + if (is_tag_mask_all(ctx, mask)) { + tcg_gen_ld8u_i32(ret, t0, 0); + } else { + TCGv_i32 t1 = tcg_temp_new_i32(); + + tcg_gen_ld8u_i32(t1, t0, 0); + tcg_gen_andi_i32(ret, t1, mask); + + tcg_temp_free_i32(t1); + } + + tcg_temp_free_ptr(t0); } else { - TCGv_i32 t1 = tcg_temp_new_i32(); - - tcg_gen_ld8u_i32(t1, t0, 0); - tcg_gen_andi_i32(ret, t1, mask); - - tcg_temp_free_i32(t1); + tcg_gen_movi_i32(ret, 0); } - - tcg_temp_free_ptr(t0); } -#else -static void gen_reg_tag_mask(DisasContext *ctx, TCGv_i32 ret, - TCGv_i32 index, uint8_t mask) -{ - tcg_gen_movi_i32(ret, 0); -} -#endif #define gen_reg_tag_i32(c, r, i) \ gen_reg_tag_mask(c, r, i, E2K_TAG_MASK_32) @@ -1324,12 +1320,16 @@ static void gen_reg_tag_mask(DisasContext *ctx, TCGv_i32 ret, #define gen_reg_tag_i128(c, r, i) \ gen_reg_tag_mask(c, r, i, E2K_TAG_MASK_128) -#ifdef E2K_TAGS_ENABLE static void gen_reg_tag_mask_set(DisasContext *ctx, TCGv_i32 tag, TCGv_i32 index, uint8_t mask) { - TCGv_ptr t0 = tcg_temp_new_ptr(); + TCGv_ptr t0; + if (!ctx->enable_tags) { + return; + } + + t0 = tcg_temp_new_ptr(); gen_reg_tag_ptr(t0, index); if (mask == E2K_TAG_MASK_128) { @@ -1361,13 +1361,6 @@ static void gen_reg_tag_mask_set(DisasContext *ctx, TCGv_i32 tag, tcg_temp_free_ptr(t0); } -#else -static void gen_reg_tag_mask_set(DisasContext *ctx, TCGv_i32 tag, - TCGv_i32 index, uint8_t mask) -{ - tcg_gen_discard_i32(tag); -} -#endif #define gen_reg_tag_set_i32(c, t, i) \ gen_reg_tag_mask_set(c, t, i, E2K_TAG_MASK_32) @@ -1879,7 +1872,6 @@ static bool is_alop_affected_by_dbl(Alop *alop) return true; } -#ifdef E2K_TAGS_ENABLE static bool is_alop_check_tag(Alop *alop) { if (alop->format == ALOPF2) { @@ -1900,7 +1892,6 @@ static bool is_alop_check_tag(Alop *alop) return true; } -#endif #if 0 static bool is_alop_poison_result(Alop *alop) @@ -2128,7 +2119,6 @@ static void gen_plu(DisasContext *ctx) } } -#ifndef FORCE_SAVE_ALC_REG static inline ArgSize alop_reg_max_size(uint8_t src1, ArgSize size1, uint8_t src2, ArgSize size2) { @@ -2191,7 +2181,6 @@ static ArgSize alop_opn_max_size(Alop *alop, uint8_t src) return r; } -#endif static bool is_reg_saved(DisasContext *ctx, uint8_t dst) { @@ -2312,8 +2301,7 @@ static void gen_alop_save_dst(Alop *alop) int chan = alop->chan; ArgSize size; -#ifndef FORCE_SAVE_ALC_REG - if (IS_REG_SAVE_SAFE(dst)) { + if (!ctx->force_save_alc_dst && IS_REG_SAVE_SAFE(dst)) { int i; size = alop_opn_max_size(alop, dst); @@ -2327,9 +2315,6 @@ static void gen_alop_save_dst(Alop *alop) } else { size = ctx->version >= 5 ? ARG_SIZE_P : ARG_SIZE_X; } -#else - size = ctx->version >= 5 ? ARG_SIZE_P : ARG_SIZE_X; -#endif gen_save_reg(ctx, chan, size, dst); } break; @@ -2470,11 +2455,11 @@ static void gen_reg_set_s(DisasContext *ctx, bool is_dbl, } } -#ifdef E2K_TAGS_ENABLE static void gen_delayed_tag_check(DisasContext *ctx, TCGv_i32 tag) { TCGv_i32 t0 = tcg_temp_new_i32(); + assert(ctx->delayed_illop); tcg_gen_setcondi_i32(TCG_COND_NE, t0, tag, 0); tcg_gen_or_i32(ctx->delayed_illop, ctx->delayed_illop, t0); tcg_temp_free_i32(t0); @@ -2482,15 +2467,10 @@ static void gen_delayed_tag_check(DisasContext *ctx, TCGv_i32 tag) static inline void gen_delayed_alop_tag_check(Alop *alop, TCGv_i32 tag) { - if (!alop->als.sm && is_alop_check_tag(alop)) { + if (alop->ctx->enable_tags && !alop->als.sm && is_alop_check_tag(alop)) { gen_delayed_tag_check(alop->ctx, tag); } } -#else -static inline void gen_delayed_alop_tag_check(Alop *alop, TCGv_i32 tag) -{ -} -#endif static void gen_al_result_q(Alop *alop, Tagged_ptr arg) { @@ -7035,6 +7015,18 @@ static void gen_alc(DisasContext *ctx) { int i; + if (ctx->enable_tags) { + for (i = 0; i < 6; i++) { + Alop *alop = &ctx->alops[i]; + + if (!alop->als.sm && is_alop_check_tag(alop)) { + ctx->delayed_illop = e2k_get_temp_i32(ctx); + tcg_gen_movi_i32(ctx->delayed_illop, 0); + break; + } + } + } + for (i = 0; i < 6; i++) { gen_alop(&ctx->alops[i]); } @@ -7804,14 +7796,12 @@ static void do_branch(DisasContext *ctx, target_ulong pc_next) /* FIXME: save PC only when necessary. */ gen_save_pc(ctx->base.pc_next); -#ifdef E2K_TAGS_ENABLE - { + if (ctx->enable_tags && ctx->delayed_illop) { TCGLabel *l0 = gen_new_label(); tcg_gen_brcondi_i32(TCG_COND_EQ, ctx->delayed_illop, 0, l0); gen_excp_illopc(); gen_set_label(l0); } -#endif if (ctx->ct.type == CT_NONE) { return; @@ -7874,6 +7864,8 @@ static void e2k_tr_init_disas_context(DisasContextBase *db, CPUState *cs) CPUE2KState *env = &cpu->env; ctx->version = env->version; + ctx->enable_tags = env->enable_tags; + ctx->force_save_alc_dst = env->force_save_alc_dst; if (version != ctx->version) { if (version > 0) { @@ -7915,10 +7907,7 @@ static void e2k_tr_insn_start(DisasContextBase *db, CPUState *cs) ctx->cs0.type = CS0_NONE; ctx->cs1.type = CS1_NONE; ctx->mlock = NULL; -#ifdef E2K_TAGS_ENABLE - ctx->delayed_illop = e2k_get_temp_i32(ctx); - tcg_gen_movi_i32(ctx->delayed_illop, 0); -#endif + ctx->delayed_illop = NULL; ctx->saved_reg_len = 0; ctx->saved_preg_len = 0; }