target: e2k: Add registers tags.

This commit is contained in:
Denis Drakhnia 2020-11-28 18:43:24 +02:00
parent 9399581696
commit 7475849453
8 changed files with 322 additions and 4 deletions

View File

@ -43,6 +43,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;
@ -105,6 +106,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);
@ -125,11 +133,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++) {

View File

@ -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 {
/* 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;

View File

@ -311,6 +311,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;

View File

@ -6,6 +6,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? */

View File

@ -287,6 +287,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;
@ -309,12 +318,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);
}
@ -322,12 +334,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);
@ -337,6 +355,7 @@ static inline void do_commit(DisasContext *ctx)
}
gen_set_label(l0);
tcg_temp_free_i64(t0);
}
e2k_plu_commit(ctx);
@ -566,6 +585,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);
@ -573,12 +594,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,

View File

@ -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));

View File

@ -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);

View File

@ -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);
}