target: e2k: HACK: Tag storage for procedure stack.

This commit is contained in:
Denis Drakhnia 2020-12-13 11:07:42 +02:00
parent e5021e1b70
commit ed29047cd7
9 changed files with 85 additions and 126 deletions

View File

@ -2280,15 +2280,22 @@ static void handle_set_qemu_phy_mem_mode(GdbCmdContext *gdb_ctx, void *user_ctx)
#ifdef TARGET_E2K
static void handle_query_e2k_tags_read(GdbCmdContext *gdb_ctx, void *user_ctx)
{
// unsigned long long addr = gdb_ctx->params[0].val_ull;
E2KCPU *cpu = E2K_CPU(gdbserver_state.g_cpu);
CPUE2KState *env = &cpu->env;
target_ulong addr = gdb_ctx->params[0].val_ull;
unsigned long len = gdb_ctx->params[1].val_ul;
unsigned int i;
// TODO: handle_query_e2k_tags_read
int tags = 0;
g_string_assign(gdbserver_state.str_buf, "l");
if (env->psp.base <= addr && addr < (env->psp.base + env->psp.size)) {
target_ulong offset = addr - env->psp.base;
tags = cpu_ldub_data(env, env->psp.base_tag + offset / 8);
}
for (i = 0; i < len; i++) {
g_string_append_c(gdbserver_state.str_buf, 0);
int tag = (tags >> i * E2K_TAG_SIZE) & 0x3;
g_string_append_c(gdbserver_state.str_buf, tag);
}
put_packet_binary(gdbserver_state.str_buf->str,

View File

@ -36,7 +36,7 @@ void cpu_loop(CPUE2KState *env)
switch (trapnr) {
case E2K_EXCP_SYSCALL: {
int offset = env->wd.base + env->syscall_wbs * 2;
int offset = E2K_NR_COUNT + env->wd.base + env->syscall_wbs * 2;
uint64_t *regs = env->regs;
abi_ulong ret = do_syscall(env,
regs[(0 + offset) % E2K_NR_COUNT],
@ -55,9 +55,13 @@ void cpu_loop(CPUE2KState *env)
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
unsigned int i;
regs[offset % E2K_NR_COUNT] = ret;
env->regs[offset % E2K_NR_COUNT] = ret;
env->tags[offset % E2K_NR_COUNT] = 0;
for (i = 1; i < 8; i++) {
regs[(i + offset) % E2K_NR_COUNT] = 0;
int idx = (offset + i) % E2K_NR_COUNT;
env->regs[idx] = 0;
env->tags[idx] = E2K_TAG_NON_NUMBER64;
}
}
break;

View File

@ -1539,6 +1539,7 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
regs->psp.index = 0;
regs->psp.size = TARGET_PAGE_SIZE * 8;
regs->psp.base = e2k_mmap(regs->psp.size);
regs->psp.base_tag = e2k_mmap(regs->psp.size / 8);
}
static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUE2KState *env)

View File

@ -137,13 +137,6 @@ 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 / E2K_TAGS_PER_REG];
int offset = (idx & GEN_MASK(0, E2K_REG_TAGS_SIZE)) * E2K_REG_TAGS_SIZE;
return extract64(tmp, offset, E2K_REG_TAGS_SIZE);
}
void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
{
E2KCPU *cpu = E2K_CPU(cs);
@ -165,7 +158,7 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
for (i = 0; i < E2K_REG_COUNT; i++) {
char name = i < E2K_NR_COUNT ? 'r' : 'g';
int tag = extract_tag(env->tags, i);
int tag = env->tags[i];
qemu_fprintf(f, "%%%c%d\t<%d%d> 0x%lx\n", name, i, tag >> 2, tag & 3,
env->regs[i]);
}

View File

@ -31,11 +31,6 @@ void e2k_tcg_initialize(void);
#define E2K_BGR_COUNT 8 /* %gN [24, 32) */
#define E2K_REG_COUNT (E2K_NR_COUNT + E2K_GR_COUNT)
/* how many tags can be packed into a register */
#define E2K_TAGS_PER_REG (E2K_REG_LEN * 8 / E2K_REG_TAGS_SIZE)
/* packed tags registers count */
#define E2K_TAGS_REG_COUNT (E2K_REG_COUNT / E2K_TAGS_PER_REG)
#define E2K_PR_COUNT 32 /* %predN [0, 32) */
typedef enum {
@ -288,6 +283,7 @@ typedef struct {
typedef struct {
target_ulong base;
target_ulong base_tag;
uint32_t index;
uint32_t size;
bool is_readable;
@ -476,9 +472,9 @@ typedef struct {
/* register file */
uint64_t regs[E2K_REG_COUNT]; /* registers */
uint16_t xregs[E2K_REG_COUNT]; /* x part of registers */
uint64_t tags[E2K_TAGS_REG_COUNT]; /* registers tags */
uint8_t tags[E2K_REG_COUNT]; /* registers tags */
uint64_t *rptr; /* pointer to regs */
uint64_t *tptr; /* pointer to tags */
uint8_t *tptr; /* pointer to tags */
union {
uint64_t pregs; /* predicate file */
@ -705,14 +701,6 @@ static inline void e2k_state_cr1_hi_set(CPUE2KState *env, uint64_t hi)
cr1->ussz = extract64(hi, CR1_HI_USSZ_OFF, CR1_HI_USSZ_LEN);
}
static inline void e2k_state_reg_tag_set_i64(CPUE2KState *env, int tag, int idx)
{
int i = idx / E2K_TAGS_PER_REG, offset;
offset = (idx & (E2K_TAGS_PER_REG - 1)) * E2K_REG_TAGS_SIZE;
env->tags[i] = deposit64(env->tags[i], offset, E2K_REG_TAGS_SIZE, tag);
}
typedef CPUE2KState CPUArchState;
typedef E2KCPU ArchCPU;

View File

@ -41,8 +41,21 @@ static inline uint64_t stack_pop(CPUE2KState *env, E2KStackState *s)
#define pcs_push(env, value) stack_push(env, &env->pcsp, (value))
#define pcs_pop(env) stack_pop(env, &env->pcsp)
#define ps_push(env, value) stack_push(env, &env->psp, (value))
#define ps_pop(env) stack_pop(env, &env->psp)
static inline void ps_push(CPUE2KState *env, uint64_t value, uint8_t tag)
{
cpu_stb_data(env, env->psp.base_tag + env->psp.index / 8, tag);
stack_push(env, &env->psp, value);
}
static inline uint64_t ps_pop(CPUE2KState *env, uint8_t *ret_tag)
{
uint64_t ret = stack_pop(env, &env->psp);
if (ret_tag != NULL) {
*ret_tag = cpu_ldub_data(env, env->psp.base_tag + env->psp.index / 8);
}
return ret;
}
/* FIXME: I don't know how exactly it should works. */
static inline void sbr_push(CPUE2KState *env)
@ -109,19 +122,20 @@ static inline void ps_spill(CPUE2KState *env, bool force, bool force_fx)
(force && env->pshtp.index))
{
int i = (E2K_NR_COUNT + env->wd.base - env->pshtp.index) % E2K_NR_COUNT;
// TODO: push tags
ps_push(env, env->regs[i]);
ps_push(env, env->regs[i + 1]);
env->regs[i] = 0;
env->regs[i + 1] = 0;
// TODO: set invalid reg tags
// e2k_state_reg_tag_set_i64(env, E2K_TAG_NON_NUMBER64, i);
// e2k_state_reg_tag_set_i64(env, E2K_TAG_NON_NUMBER64, i + 1);
ps_push(env, env->regs[i], env->tags[i]);
ps_push(env, env->regs[i + 1], env->tags[i + 1]);
// TODO: push fx
if (force_fx) {
ps_push(env, env->xregs[i]);
ps_push(env, env->xregs[i + 1]);
ps_push(env, env->xregs[i], 0);
ps_push(env, env->xregs[i + 1], 0);
}
env->regs[i] = 0;
env->tags[i] = E2K_TAG_NON_NUMBER64;
env->regs[i + 1] = 0;
env->tags[i + 1] = E2K_TAG_NON_NUMBER64;
env->pshtp.index -= 2;
}
}
@ -131,14 +145,12 @@ static inline void ps_fill(CPUE2KState *env, bool force_fx)
while(env->pshtp.index < 0) {
env->pshtp.index += 2;
int i = (E2K_NR_COUNT + env->wd.base - env->pshtp.index) % E2K_NR_COUNT;
// TODO: pop fx
if (force_fx) {
env->xregs[i + 1] = ps_pop(env);
env->xregs[i] = ps_pop(env);
env->xregs[i + 1] = ps_pop(env, NULL);
env->xregs[i] = ps_pop(env, NULL);
}
// TODO: restore tags
env->regs[i + 1] = ps_pop(env);
env->regs[i] = ps_pop(env);
env->regs[i + 1] = ps_pop(env, &env->tags[i + 1]);
env->regs[i] = ps_pop(env, &env->tags[i]);
}
}

View File

@ -528,13 +528,6 @@ void e2k_tcg_initialize(void) {
i * E2K_REG_LEN, buf);
}
for (i = 0; i < E2K_TAGS_REG_COUNT; i++) {
char name = i < E2K_NR_COUNT ? 'r' : 'g';
snprintf(buf, ARRAY_SIZE(buf), "%%%c_tags%d", name, i);
e2k_cs.tags[i] = tcg_global_mem_new_i64(e2k_cs.tptr,
i * E2K_REG_LEN, buf);
}
for (i = 0; i < 3; i++) {
snprintf(buf, ARRAY_SIZE(buf), "%%ctpr%d", i + 1);
e2k_cs.ctprs[i] = tcg_global_mem_new_i64(cpu_env,

View File

@ -42,7 +42,6 @@ typedef struct CPUE2KStateTCG {
TCGv_i32 wdbl;
TCGv_i64 lsr;
TCGv_i64 regs[E2K_REG_COUNT];
TCGv_i64 tags[E2K_TAGS_REG_COUNT];
TCGv_ptr rptr; /* pointer to wregs */
TCGv_ptr tptr; /* pointer to wtags */
TCGv_i32 wd_base; /* holds wbs * 2 */

View File

@ -107,63 +107,33 @@ void e2k_gen_store_preg(int idx, TCGv_i64 val)
tcg_temp_free_i64(t0);
}
static inline void gen_reg_tags_group_ptr(TCGv_ptr ret, TCGv_i32 idx)
{
TCGv_i32 t0 = tcg_const_i32(E2K_TAGS_PER_REG);
TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 t2 = tcg_temp_new_i32();
TCGv_ptr t3 = tcg_temp_new_ptr();
tcg_gen_divu_i32(t1, idx, t0);
tcg_temp_free_i32(t0);
tcg_gen_muli_i32(t2, t1, E2K_REG_LEN);
tcg_temp_free_i32(t1);
tcg_gen_ext_i32_ptr(t3, t2);
tcg_temp_free_i32(t2);
tcg_gen_add_ptr(ret, e2k_cs.tptr, t3);
tcg_temp_free_ptr(t3);
}
static inline void gen_reg_tags_group_offset(TCGv_i64 ret, TCGv_i32 idx)
{
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
tcg_gen_extu_i32_i64(t0, idx);
tcg_gen_andi_i64(t1, t0, E2K_TAGS_PER_REG - 1);
tcg_temp_free_i64(t0);
tcg_gen_muli_i64(ret, t1, E2K_REG_TAGS_SIZE);
tcg_temp_free_i64(t1);
}
static inline void gen_reg_tags_read(TCGv_i32 ret, TCGv_i32 idx, int len)
static inline void gen_reg_tag_ptr(TCGv_ptr ret, TCGv_i32 idx)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
TCGv_i64 t1 = tcg_temp_new_i64();
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_const_i64(len);
TCGv_i64 t4 = tcg_temp_new_i64();
gen_reg_tags_group_ptr(t0, idx);
tcg_gen_ld_i64(t1, t0, 0);
tcg_gen_ext_i32_ptr(t0, idx);
tcg_gen_add_ptr(ret, e2k_cs.tptr, t0);
tcg_temp_free_ptr(t0);
gen_reg_tags_group_offset(t2, idx);
e2k_gen_extract_i64(t4, t1, t2, t3);
tcg_temp_free_i64(t1);
tcg_temp_free_i64(t2);
tcg_temp_free_i64(t3);
tcg_gen_extrl_i64_i32(ret, t4);
tcg_temp_free_i64(t4);
}
void e2k_gen_reg_tag_read_i64(TCGv_i32 ret, TCGv_i32 idx)
{
gen_reg_tags_read(ret, idx, E2K_REG_TAGS_SIZE);
TCGv_ptr t0 = tcg_temp_new_ptr();
gen_reg_tag_ptr(t0, idx);
tcg_gen_ld8u_i32(ret, t0, 0);
tcg_temp_free_ptr(t0);
}
void e2k_gen_reg_tag_read_i32(TCGv_i32 ret, TCGv_i32 idx)
{
gen_reg_tags_read(ret, idx, E2K_TAG_SIZE);
TCGv_ptr t0 = tcg_temp_new_ptr();
TCGv_i32 t1 = tcg_temp_new_i32();
gen_reg_tag_ptr(t0, idx);
tcg_gen_ld8u_i32(t1, t0, 0);
tcg_gen_andi_i32(ret, t1, GEN_MASK(0, E2K_TAG_SIZE));
tcg_temp_free_ptr(t0);
}
static inline void gen_tag_check(TCGv_i32 ret, TCGv_i32 tag)
@ -186,37 +156,29 @@ void e2k_gen_reg_tag_check_i32(TCGv_i32 ret, TCGv_i32 tag)
tcg_temp_free_i32(t0);
}
static inline void gen_reg_tags_write(TCGv_i32 value, TCGv_i32 idx, int len)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
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_const_i64(len);
TCGv_i64 t5 = tcg_temp_new_i64();
gen_reg_tags_group_ptr(t0, idx);
tcg_gen_ld_i64(t1, t0, 0);
tcg_gen_extu_i32_i64(t2, value);
gen_reg_tags_group_offset(t3, idx);
e2k_gen_deposit_i64(t5, t1, t2, t3, t4);
tcg_temp_free_i64(t1);
tcg_temp_free_i64(t2);
tcg_temp_free_i64(t3);
tcg_temp_free_i64(t4);
tcg_gen_st_i64(t5, t0, 0);
tcg_temp_free_ptr(t0);
tcg_temp_free_i64(t5);
}
void e2k_gen_reg_tag_write_i64(TCGv_i32 value, TCGv_i32 idx)
{
gen_reg_tags_write(value, idx, E2K_REG_TAGS_SIZE);
TCGv_ptr t0 = tcg_temp_new_ptr();
gen_reg_tag_ptr(t0, idx);
tcg_gen_st8_i32(value, t0, 0);
tcg_temp_free_ptr(t0);
}
void e2k_gen_reg_tag_write_i32(TCGv_i32 value, TCGv_i32 idx)
{
gen_reg_tags_write(value, idx, E2K_TAG_SIZE);
TCGv_ptr t0 = tcg_temp_new_ptr();
TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 t2 = tcg_temp_new_i32();
gen_reg_tag_ptr(t0, idx);
tcg_gen_ld8u_i32(t1, t0, 0);
tcg_gen_deposit_i32(t2, t1, value, 0, E2K_TAG_SIZE);
tcg_gen_st8_i32(t2, t0, 0);
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t1);
tcg_temp_free_ptr(t0);
}
static inline void gen_reg_index_from_wreg(TCGv_i32 ret, TCGv_i32 idx)