diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index de9c99888b..02fab30a0d 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -45,6 +45,7 @@ static void e2k_cpu_reset(DeviceState *dev) memset(env, 0, offsetof(CPUE2KState, end_reset_fields)); env->wptr = &env->wregs[0]; + env->tptr = &env->wtags[0]; env->cr1.wpsz = 4; env->cr1.wbs = 4; env->wd.base = 0; @@ -111,6 +112,13 @@ static inline void cpu_dump_state_br(CPUE2KState *env, FILE *f, int flags) qemu_fprintf(f, " pcur %d\n", bp->cur); } +static inline int extract_tag(uint64_t *tags, int idx) +{ + uint64_t tmp = tags[idx / TAGS_PER_REG]; + int offset = (idx & GEN_MASK(0, TAG_BITS)) * TAG_BITS; + return extract64(tmp, offset, TAG_BITS); +} + void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags) { E2KCPU *cpu = E2K_CPU(cs); @@ -131,11 +139,17 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags) cpu_dump_state_br(env, f, flags); for (i = 0; i < WREGS_SIZE; i++) { - qemu_fprintf(f, "%%r%d\t0x%lx\n", i, env->wregs[i]); + int tag = extract_tag(env->wtags, i); + int tl = tag & 3; + int th = tag >> 2; + qemu_fprintf(f, "%%r%d\t<%d%d> 0x%lx\n", i, th, tl, env->wregs[i]); } for (i = 0; i < 32; i++) { - qemu_fprintf(f, "%%g%d\t0x%lx\n", i, env->gregs[i]); + int tag = extract_tag(env->gtags, i); + int tl = tag & 3; + int th = tag >> 2; + qemu_fprintf(f, "%%g%d\t<%d%d> 0x%lx\n", i, th, tl, env->gregs[i]); } for (i = 0; i < 32; i++) { diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index 2c2d3ab609..ac0d3c11ce 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -19,9 +19,14 @@ void e2k_tcg_initialize(void); #define MMU_USER_IDX 1 #define CPU_RESOLVING_TYPE TYPE_E2K_CPU -#define REG_SIZE (sizeof(uint64_t)) +#define REG_SIZE sizeof(uint64_t) +#define TAG_BITS 4 /* 2 bit per 32-bit half */ +/* how many tags can be packed into register */ +#define TAGS_PER_REG (REG_SIZE * 8 / TAG_BITS) #define WREGS_SIZE 192 +#define WTAGS_SIZE (WREGS_SIZE / TAGS_PER_REG) #define GREGS_SIZE 32 +#define GTAGS_SIZE (GREGS_SIZE / TAGS_PER_REG) #define WREGS_MAX 64 #define BREGS_MAX 128 #define GREGS_MAX 24 @@ -279,8 +284,11 @@ typedef struct { typedef struct CPUArchState { /* register file */ uint64_t gregs[GREGS_SIZE]; /* global registers */ + uint64_t gtags[GTAGS_SIZE]; /* global registers tags */ uint64_t wregs[WREGS_SIZE]; /* window registers */ - uint64_t *wptr; + uint64_t wtags[WTAGS_SIZE]; /* window registers tags */ + uint64_t *wptr; /* pointer to wregs */ + uint64_t *tptr; /* pointer to wtags */ E2KCr1State cr1; diff --git a/target/e2k/helper.c b/target/e2k/helper.c index 8fa7c86230..ad2e85e744 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -304,6 +304,11 @@ void helper_debug_i64(uint64_t x) qemu_log_mask(LOG_UNIMP, "log %#lx\n", x); } +void helper_debug_ptr(void *x) +{ + qemu_log_mask(LOG_UNIMP, "log %#lx\n", (uint64_t) x); +} + void helper_setwd(CPUE2KState *env, uint32_t lts) { env->wd.size = extract32(lts, 5, 7) * 2; diff --git a/target/e2k/helper.h b/target/e2k/helper.h index 9991b9aceb..b20dc9e4a9 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -5,6 +5,7 @@ DEF_HELPER_4(call, void, env, i64, int, tl) DEF_HELPER_2(sxt, i64, i64, i64) DEF_HELPER_1(debug_i32, void, i32) DEF_HELPER_1(debug_i64, void, i64) +DEF_HELPER_1(debug_ptr, void, ptr) DEF_HELPER_2(state_reg_get, i64, env, int) DEF_HELPER_3(state_reg_set, void, env, int, i64) DEF_HELPER_2(getsp, i64, env, i64) /* FIXME: return tl? */ diff --git a/target/e2k/translate.c b/target/e2k/translate.c index 566af52292..4ab9806ffb 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -273,6 +273,15 @@ static inline void do_execute(DisasContext *ctx) e2k_plu_execute(ctx); e2k_control_gen(ctx); + /* allocate storage for tags if needed */ + for (i = 0; i < 6; i++) { + if (ctx->bundle.als_present[i]) { + ctx->alc_tags = e2k_get_temp_i64(ctx); + tcg_gen_movi_i64(ctx->alc_tags, 0); + break; + } + } + for (i = 0; i < 6; i++) { if (ctx->bundle.als_present[i]) { ctx->alc[i].tag = RESULT_NONE; @@ -295,12 +304,15 @@ static inline void do_commit(DisasContext *ctx) for (i = 0; i < 6; i++) { TCGLabel *l0 = gen_new_label(); + TCGv_i64 t0; Result *res = &ctx->alc[i]; if (!ctx->bundle.als_present[i]) { continue; } + t0 = tcg_temp_new_i64(); + if (res->has_cond) { tcg_gen_brcondi_i64(TCG_COND_EQ, res->cond, 0, l0); } @@ -308,12 +320,18 @@ static inline void do_commit(DisasContext *ctx) switch(res->tag) { case RESULT_BASED_REG: e2k_gen_store_breg(ctx, res->u.reg.i, res->u.reg.v); + tcg_gen_extract_i64(t0, ctx->alc_tags, i * TAG_BITS, TAG_BITS); + e2k_gen_btag_set(res->u.reg.i, t0); break; case RESULT_REGULAR_REG: e2k_gen_store_wreg(ctx, res->u.reg.i, res->u.reg.v); + tcg_gen_extract_i64(t0, ctx->alc_tags, i * TAG_BITS, TAG_BITS); + e2k_gen_wtagi_set(res->u.reg.i, t0); break; case RESULT_GLOBAL_REG: e2k_gen_store_greg(res->u.reg.i, res->u.reg.v); + tcg_gen_extract_i64(t0, ctx->alc_tags, i * TAG_BITS, TAG_BITS); + e2k_gen_gtag_set(res->u.reg.i, t0); break; case RESULT_PREG: e2k_gen_store_preg(res->u.reg.i, res->u.reg.v); @@ -323,6 +341,7 @@ static inline void do_commit(DisasContext *ctx) } gen_set_label(l0); + tcg_temp_free_i64(t0); } e2k_plu_commit(ctx); @@ -533,6 +552,8 @@ void e2k_tcg_initialize(void) { e2k_cs.wptr = tcg_global_mem_new_ptr(cpu_env, offsetof(CPUE2KState, wptr), "wptr"); + e2k_cs.tptr = tcg_global_mem_new_ptr(cpu_env, + offsetof(CPUE2KState, tptr), "tptr"); for (i = 0; i < WREGS_SIZE; i++) { snprintf(buf, ARRAY_SIZE(buf), "%%r%d", i); @@ -540,12 +561,24 @@ void e2k_tcg_initialize(void) { i * REG_SIZE, buf); } + for (i = 0; i < WTAGS_SIZE; i++) { + snprintf(buf, ARRAY_SIZE(buf), "%%wtags%d", i); + e2k_cs.wtags[i] = tcg_global_mem_new_i64(e2k_cs.tptr, + i * REG_SIZE, buf); + } + for (i = 0; i < GREGS_SIZE; i++) { snprintf(buf, ARRAY_SIZE(buf), "%%g%d", i); e2k_cs.gregs[i] = tcg_global_mem_new_i64(cpu_env, offsetof(CPUE2KState, gregs[i]), buf); } + for (i = 0; i < GTAGS_SIZE; i++) { + snprintf(buf, ARRAY_SIZE(buf), "%%gtags%d", i); + e2k_cs.gtags[i] = tcg_global_mem_new_i64(cpu_env, + offsetof(CPUE2KState, gtags[i]), buf); + } + for (i = 0; i < 3; i++) { snprintf(buf, ARRAY_SIZE(buf), "%%ctpr%d", i + 1); e2k_cs.ctprs[i] = tcg_global_mem_new(cpu_env, diff --git a/target/e2k/translate.h b/target/e2k/translate.h index 43ec52bc3c..47c28f7c64 100644 --- a/target/e2k/translate.h +++ b/target/e2k/translate.h @@ -63,8 +63,11 @@ typedef struct CPUE2KStateTCG { TCGv_i32 is_bp; /* breakpoint flag */ TCGv_i64 lsr; TCGv_i64 wregs[WREGS_SIZE]; + TCGv_i64 wtags[WTAGS_SIZE]; TCGv_i64 gregs[GREGS_SIZE]; + TCGv_i64 gtags[GTAGS_SIZE]; TCGv_ptr wptr; /* pointer to wregs */ + TCGv_ptr tptr; /* pointer to wtags */ TCGv_i32 wd_base; /* holds wbs * 2 */ TCGv_i32 wd_size; /* holds wsz * 2 */ TCGv_i32 boff; /* holds rbs * 2 */ @@ -162,10 +165,80 @@ typedef struct DisasContext { TCGv_i64 cond[6]; Result alc[6]; + TCGv_i64 alc_tags; PluResult plu[3]; ControlTransfer ct; } DisasContext; +static inline void e2k_gen_mask_i64(TCGv_i64 ret, TCGv_i64 len) +{ + TCGv_i64 one = tcg_const_i64(1); + TCGv_i64 t0 = tcg_temp_new_i64(); + + tcg_gen_shl_i64(t0, one, len); + tcg_gen_subi_i64(ret, t0, 1); + + tcg_temp_free_i64(t0); + tcg_temp_free_i64(one); +} + +static inline void e2k_gen_maski_i64(TCGv_i64 ret, int len) +{ + TCGv_i64 t0 = tcg_const_i64(len); + e2k_gen_mask_i64(ret, t0); + tcg_temp_free_i64(t0); +} + +static inline void e2k_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg1, + TCGv_i64 offset, TCGv_i64 len) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + + tcg_gen_shr_i64(t0, arg1, offset); + e2k_gen_mask_i64(t1, len); + tcg_gen_and_i64(ret, t0, t1); + + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t0); +} + +static inline void e2k_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, + TCGv_i64 arg2, TCGv_i64 offset, TCGv_i64 len) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + TCGv_i64 t4 = tcg_temp_new_i64(); + TCGv_i64 t5 = tcg_temp_new_i64(); + + e2k_gen_mask_i64(t0, len); + tcg_gen_shl_i64(t1, t0, offset); + tcg_gen_not_i64(t2, t1); + tcg_gen_and_i64(t3, arg1, t2); + tcg_gen_and_i64(t4, arg2, t0); + tcg_gen_shl_i64(t5, t4, offset); + tcg_gen_or_i64(ret, t3, t5); + + tcg_temp_free_i64(t5); + tcg_temp_free_i64(t4); + tcg_temp_free_i64(t3); + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t0); +} + +/* register index must be valid */ +void e2k_gen_wtag_get(TCGv_i64 ret, TCGv_i32 idx); +void e2k_gen_wtagi_get(TCGv_i64 ret, int reg); +void e2k_gen_wtag_set(TCGv_i32 idx, TCGv_i64 tag); +void e2k_gen_wtagi_set(int reg, TCGv_i64 tag); +void e2k_gen_btag_get(TCGv_i64 ret, int reg); +void e2k_gen_btag_set(int reg, TCGv_i64 tag); +void e2k_gen_gtag_get(TCGv_i64 ret, int reg); +void e2k_gen_gtag_set(int reg, TCGv_i64 tag); + static inline TCGv_i32 e2k_get_temp_i32(DisasContext *dc) { assert(dc->t32_len < ARRAY_SIZE(dc->t32)); diff --git a/target/e2k/translate/alc.c b/target/e2k/translate/alc.c index 531262d5e5..9f9ec49e42 100644 --- a/target/e2k/translate/alc.c +++ b/target/e2k/translate/alc.c @@ -93,6 +93,12 @@ static void store_reg_alc_result(DisasContext *dc, int chan, TCGv_i64 val) Result *res = &dc->alc[chan]; res->u.reg.v = val; + // TODO: write tag to temp storage + TCGv_i64 tag = tcg_const_i64(dst % 15); + tcg_gen_deposit_i64(dc->alc_tags, dc->alc_tags, tag, chan * TAG_BITS, + TAG_BITS); + tcg_temp_free_i64(tag); + if (IS_BASED(dst)) { res->tag = RESULT_BASED_REG; res->u.reg.i = GET_BASED(dst); diff --git a/target/e2k/translate/state.c b/target/e2k/translate/state.c index 61cbadee75..d0bb0bab1e 100644 --- a/target/e2k/translate/state.c +++ b/target/e2k/translate/state.c @@ -3,6 +3,104 @@ #include "exec/log.h" #include "translate.h" +#define TAG_MASK GEN_MASK(0, TAG_BITS) + +static inline void gen_tag_group_index(TCGv_i64 ret, TCGv_i64 idx) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + tcg_gen_shri_i64(t0, idx, 4); + tcg_gen_shli_i64(ret, t0, 3); + tcg_temp_free_i64(t0); +} + +static inline void gen_tag_offset_in_group(TCGv_i64 ret, TCGv_i64 idx) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + + tcg_gen_andi_i64(t0, idx, TAG_MASK); + tcg_gen_muli_i64(ret, t0, TAG_BITS); + + tcg_temp_free_i64(t0); +} + +static inline void gen_tag_group_get(TCGv_i64 ret, TCGv_ptr tags, TCGv_i64 idx) +{ + TCGv_ptr t0 = tcg_temp_new_ptr(); + TCGv_ptr t1 = tcg_temp_new_ptr(); + + tcg_gen_trunc_i64_ptr(t0, idx); + tcg_gen_add_ptr(t1, tags, t0); + tcg_gen_ld_i64(ret, t1, 0); + + tcg_temp_free_ptr(t1); + tcg_temp_free_ptr(t0); +} + +static inline void get_tag_group_set(TCGv_ptr tags, TCGv_i64 idx, + TCGv_i64 group) +{ + TCGv_ptr t0 = tcg_temp_new_ptr(); + TCGv_ptr t1 = tcg_temp_new_ptr(); + + tcg_gen_trunc_i64_ptr(t0, idx); + tcg_gen_add_ptr(t1, tags, t0); + tcg_gen_st_i64(group, t1, 0); + + tcg_temp_free_ptr(t1); + tcg_temp_free_ptr(t0); +} + +static inline void gen_tag_group_extract(TCGv_i64 ret, TCGv_i64 group, + TCGv_i64 offset) +{ + TCGv_i64 t0 = tcg_const_i64(TAG_BITS); + e2k_gen_extract_i64(ret, group, offset, t0); + tcg_temp_free_i64(t0); +} + +static inline void gen_tag_group_deposit(TCGv_i64 ret, TCGv_i64 group, + TCGv_i64 tag, TCGv_i64 offset) +{ + TCGv_i64 t0 = tcg_const_i64(TAG_BITS); + e2k_gen_deposit_i64(ret, group, tag, offset, t0); + tcg_temp_free_i64(t0); +} + +static inline void gen_tag_get(TCGv_i64 ret, TCGv_ptr tags, TCGv_i64 idx) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + gen_tag_group_index(t0, idx); + gen_tag_group_get(t1, tags, t0); + gen_tag_offset_in_group(t2, idx); + gen_tag_group_extract(ret, t1, t2); + + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t0); +} + +static inline void gen_tag_set(TCGv_ptr tags, TCGv_i64 idx, TCGv_i64 tag) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + TCGv_i64 t3 = tcg_temp_new_i64(); + + gen_tag_group_index(t0, idx); + gen_tag_group_get(t1, tags, t0); + gen_tag_offset_in_group(t2, idx); + gen_tag_group_deposit(t3, t1, tag, t2); + get_tag_group_set(tags, t0, t3); + + tcg_temp_free_i64(t3); + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t0); +} + static void gen_preg_offset(TCGv_i64 ret, int reg) { assert(reg < 32); @@ -161,6 +259,48 @@ void e2k_gen_store_wreg(DisasContext *ctx, int reg, TCGv_i64 val) tcg_temp_free_ptr(t0); } +void e2k_gen_wtag_get(TCGv_i64 ret, TCGv_i32 idx) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i64 t1 = tcg_temp_new_i64(); + + gen_wreg_index(t0, idx); + tcg_gen_extu_i32_i64(t1, t0); + gen_tag_get(ret, e2k_cs.wptr, t1); + + tcg_temp_free_i64(t1); + tcg_temp_free_i32(t0); +} + +void e2k_gen_wtagi_get(TCGv_i64 ret, int reg) +{ + TCGv_i32 t0 = tcg_const_i32(reg); + e2k_gen_wtag_get(ret, t0); + tcg_temp_free_i32(t0); +} + +/* register index must be valid */ +void e2k_gen_wtag_set(TCGv_i32 idx, TCGv_i64 tag) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i64 t1 = tcg_temp_new_i64(); + + gen_wreg_index(t0, idx); + tcg_gen_extu_i32_i64(t1, t0); + gen_tag_set(e2k_cs.tptr, t1, tag); + + tcg_temp_free_i64(t1); + tcg_temp_free_i32(t0); +} + +/* register index must be valid */ +void e2k_gen_wtagi_set(int reg, TCGv_i64 tag) +{ + TCGv_i32 t0 = tcg_const_i32(reg); + e2k_gen_wtag_set(t0, tag); + tcg_temp_free_i32(t0); +} + static inline void gen_breg_index(TCGv_i32 ret, int idx) { TCGv_i32 t0 = tcg_temp_new_i32(); @@ -214,6 +354,28 @@ void e2k_gen_store_breg(DisasContext *ctx, int reg, TCGv_i64 val) tcg_temp_free_ptr(ptr); } +/* register index must be valid */ +void e2k_gen_btag_get(TCGv_i64 ret, int reg) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + + gen_breg_index(t0, reg); + e2k_gen_wtag_get(ret, t0); + + tcg_temp_free_i32(t0); +} + +/* register index must be valid */ +void e2k_gen_btag_set(int reg, TCGv_i64 tag) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + + gen_breg_index(t0, reg); + e2k_gen_wtag_set(t0, tag); + + tcg_temp_free_i32(t0); +} + TCGv_i64 e2k_get_greg(DisasContext *dc, int reg) { assert(reg < GREGS_MAX + BGREGS_MAX); @@ -225,3 +387,19 @@ void e2k_gen_store_greg(int reg, TCGv_i64 val) assert(reg < GREGS_MAX + BGREGS_MAX); tcg_gen_mov_i64(e2k_cs.gregs[reg], val); } + +void e2k_gen_gtag_get(TCGv_i64 ret, int reg) +{ + TCGv_i64 group = e2k_cs.gtags[reg / TAGS_PER_REG]; + TCGv_i64 t0 = tcg_const_i64((reg & TAG_MASK) * TAG_BITS); + gen_tag_group_extract(ret, group, t0); + tcg_temp_free_i64(t0); +} + +void e2k_gen_gtag_set(int reg, TCGv_i64 tag) +{ + TCGv_i64 group = e2k_cs.gtags[reg / TAGS_PER_REG]; + TCGv_i64 t0 = tcg_const_i64((reg & TAG_MASK) * TAG_BITS); + gen_tag_group_deposit(group, group, tag, t0); + tcg_temp_free_i64(t0); +}