target: e2k: Delete hack for saving USD registers on proc call/ret.

This commit is contained in:
Denis Drakhnia 2020-12-15 00:12:18 +02:00
parent 76ebaa78bd
commit 74f2385990
7 changed files with 84 additions and 130 deletions

View File

@ -1520,13 +1520,14 @@ static inline abi_ulong e2k_mmap(abi_ulong size)
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
abi_ulong stack_size = infop->start_stack - infop->stack_limit;
abi_ulong start_stack = infop->start_stack & ~0xf;
regs->ip = infop->entry;
regs->sbr = e2k_mmap(TARGET_PAGE_SIZE);
regs->usd_hi = stack_size << 32;
regs->usd_lo = (0x1800UL << 48) | infop->start_stack;
// FIXME: set real start stack address
regs->sbr = infop->arg_strings & ~0xf;
regs->usd_lo = (0x1800UL << 48) | start_stack;
regs->usd_hi = (regs->sbr - start_stack) << 32;
regs->pcsp.is_readable = true;
regs->pcsp.is_writable = true;

View File

@ -147,8 +147,8 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
qemu_fprintf(f, " pregs = 0x%016lx\n", env->pregs);
qemu_fprintf(f, " cr0_lo = 0x%016lx\n", env->cr0_lo);
qemu_fprintf(f, " cr0_hi = 0x%016lx\n", env->cr0_hi);
qemu_fprintf(f, " cr1_lo = 0x%016lx\n", e2k_state_cr1_lo(env));
qemu_fprintf(f, " cr1_hi = 0x%016lx\n", e2k_state_cr1_hi(env));
qemu_fprintf(f, " cr1_lo = 0x%016lx\n", env->cr1.lo);
qemu_fprintf(f, " cr1_hi = 0x%016lx\n", env->cr1.hi);
qemu_fprintf(f, " pcsp_lo = 0x%016lx\n", e2k_state_pcsp_lo(env));
qemu_fprintf(f, " pcsp_hi = 0x%016lx\n", e2k_state_pcsp_hi(env));
qemu_fprintf(f, " psp_lo = 0x%016lx\n", e2k_state_psp_lo(env));

View File

@ -268,17 +268,50 @@ typedef struct {
} E2KBpState;
typedef struct {
uint32_t br;
uint32_t cuir;
uint32_t ussz;
uint16_t tr;
uint8_t ein;
bool ss;
bool wfx;
uint8_t wpsz;
uint8_t wbs;
uint8_t psr;
bool wdbl;
union {
struct {
uint64_t tr: 15;
uint64_t unused1: 1;
uint64_t ein: 8;
uint64_t ss: 1;
uint64_t wfx: 1;
uint64_t wpsz: 7;
uint64_t wbs: 7;
uint64_t cuir: 17;
uint64_t psr: 7;
};
struct {
uint64_t unused2: 40;
uint64_t cui: 16;
uint64_t ic: 1;
uint64_t pm: 1;
uint64_t ie: 1;
uint64_t sge: 1;
uint64_t lw: 1;
uint64_t uie: 1;
uint64_t nmie: 1;
uint64_t unmie: 1;
};
uint64_t lo;
};
union {
struct {
uint64_t br: 28;
uint64_t unused3: 7;
uint64_t wdbl: 1;
/* user stack size */
uint64_t ussz: 28;
};
struct {
uint64_t rbs: 6;
uint64_t rsz: 6;
uint64_t rcur: 6;
uint64_t psz: 5;
uint64_t pcur: 5;
uint64_t unused4: 36;
};
uint64_t hi;
};
} E2KCr1State;
typedef struct {
@ -567,6 +600,8 @@ bool e2k_cpu_tlb_fill(CPUState *cpu, vaddr address, int size,
#define cpu_signal_handler e2k_cpu_signal_handler
#define cpu_list e2k_cpu_list
#define e2k_wrap_reg_index(i) (E2K_NR_COUNT + i) % E2K_NR_COUNT
static inline uint64_t e2k_state_desc_lo(E2KStackState *desc)
{
uint64_t lo = 0;
@ -649,58 +684,6 @@ static inline void e2k_state_br_set(CPUE2KState *env, uint32_t br)
bp->cur = extract32(br, BR_PCUR_OFF, BR_PCUR_LEN);
}
static inline uint64_t e2k_state_cr1_lo(CPUE2KState *env)
{
E2KCr1State *cr1 = &env->cr1;
uint64_t ret = 0;
ret = deposit64(ret, CR1_LO_TR_OFF, CR1_LO_TR_LEN, cr1->tr);
ret = deposit64(ret, CR1_LO_EIN_OFF, CR1_LO_EIN_LEN, cr1->ein);
ret = deposit64(ret, CR1_LO_SS_OFF, 1, cr1->ss);
ret = deposit64(ret, CR1_LO_WFX_OFF, 1, cr1->wfx);
ret = deposit64(ret, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_LEN, cr1->wpsz);
ret = deposit64(ret, CR1_LO_WBS_OFF, CR1_LO_WBS_LEN, cr1->wbs);
ret = deposit64(ret, CR1_LO_CUIR_OFF, CR1_LO_CUIR_LEN, cr1->cuir);
ret = deposit64(ret, CR1_LO_PSR_OFF, CR1_LO_PSR_LEN, cr1->psr);
return ret;
}
static inline void e2k_state_cr1_lo_set(CPUE2KState *env, uint64_t lo)
{
E2KCr1State *cr1 = &env->cr1;
cr1->tr = extract64(lo, CR1_LO_TR_OFF, CR1_LO_TR_LEN);
cr1->ein = extract64(lo, CR1_LO_EIN_OFF, CR1_LO_EIN_LEN);
cr1->ss = extract64(lo, CR1_LO_SS_OFF, 1);
cr1->wfx = extract64(lo, CR1_LO_WFX_OFF, 1);
cr1->wpsz = extract64(lo, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_LEN);
cr1->wbs = extract64(lo, CR1_LO_WBS_OFF, CR1_LO_WBS_LEN);
cr1->cuir = extract64(lo, CR1_LO_CUIR_OFF, CR1_LO_CUIR_LEN);
cr1->psr = extract64(lo, CR1_LO_PSR_OFF, CR1_LO_PSR_LEN);
}
static inline uint64_t e2k_state_cr1_hi(CPUE2KState *env)
{
E2KCr1State *cr1 = &env->cr1;
uint64_t ret = 0;
ret = deposit64(ret, CR1_HI_BR_OFF, CR1_HI_BR_LEN, cr1->br);
ret = deposit64(ret, CR1_HI_WDBL_OFF, 1, cr1->wdbl);
ret = deposit64(ret, CR1_HI_USSZ_OFF, CR1_HI_USSZ_LEN, cr1->ussz);
return ret;
}
static inline void e2k_state_cr1_hi_set(CPUE2KState *env, uint64_t hi)
{
E2KCr1State *cr1 = &env->cr1;
cr1->br = extract64(hi, CR1_HI_BR_OFF, CR1_HI_BR_LEN);
cr1->wdbl = extract64(hi, CR1_HI_WDBL_OFF, 1);
cr1->ussz = extract64(hi, CR1_HI_USSZ_OFF, CR1_HI_USSZ_LEN);
}
typedef CPUE2KState CPUArchState;
typedef E2KCPU ArchCPU;

View File

@ -62,8 +62,8 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
case 51: return gdb_get_reg64(mem_buf, e2k_state_pshtp(env)); // pshtp
case 52: return gdb_get_reg64(mem_buf, env->pregs); // pregs
case 53: return gdb_get_reg64(mem_buf, env->ip); // ip
case 54: return gdb_get_reg64(mem_buf, e2k_state_cr1_lo(env)); // cr1_lo
case 55: return gdb_get_reg64(mem_buf, e2k_state_cr1_hi(env)); // cr1_hi
case 54: return gdb_get_reg64(mem_buf, env->cr1.lo); // cr1_lo
case 55: return gdb_get_reg64(mem_buf, env->cr1.hi); // cr1_hi
case 56: return gdb_get_reg64(mem_buf, 0); // cwd
case 57: return gdb_get_reg64(mem_buf, e2k_state_pcsp_lo(env)); // pcsp_lo
case 58: return gdb_get_reg64(mem_buf, e2k_state_pcsp_hi(env)); // pcsp_hi

View File

@ -57,28 +57,12 @@ static inline uint64_t ps_pop(CPUE2KState *env, uint8_t *ret_tag)
return ret;
}
/* FIXME: I don't know how exactly it should works. */
static inline void sbr_push(CPUE2KState *env)
{
cpu_stq_le_data(env, env->sbr, env->usd.lo);
cpu_stq_le_data(env, env->sbr + 8, env->usd.hi);
env->sbr += 16;
}
static inline void sbr_pop(CPUE2KState *env)
{
env->sbr -= 16;
env->usd.hi = cpu_ldq_le_data(env, env->sbr + 8);
env->usd.lo = cpu_ldq_le_data(env, env->sbr);
}
static void proc_chain_save(CPUE2KState *env, int wbs)
{
sbr_push(env);
pcs_push(env, env->cr0_lo);
pcs_push(env, env->cr0_hi);
pcs_push(env, e2k_state_cr1_lo(env));
pcs_push(env, e2k_state_cr1_hi(env));
pcs_push(env, env->cr1.lo);
pcs_push(env, env->cr1.hi);
env->pshtp.index += wbs * 2;
@ -88,9 +72,10 @@ static void proc_chain_save(CPUE2KState *env, int wbs)
env->cr1.wpsz = env->wd.psize / 2;
env->cr1.wfx = env->wd.fx;
env->cr1.br = e2k_state_br(env);
env->cr1.ussz = env->usd.size >> 4;
env->wd.fx = true;
env->wd.base = (E2K_NR_COUNT + env->wd.base + wbs * 2) % E2K_NR_COUNT;
env->wd.base = e2k_wrap_reg_index(env->wd.base + wbs * 2);
env->wd.size -= wbs * 2;
env->wd.psize = env->wd.size;
}
@ -105,17 +90,18 @@ static inline void proc_chain_restore(CPUE2KState *env)
e2k_state_br_set(env, env->cr1.br);
env->wd.size = env->wd.psize + wbs * 2;
env->wd.psize = env->cr1.wpsz * 2;
env->wd.base = (E2K_NR_COUNT + env->wd.base - wbs * 2) % E2K_NR_COUNT;
env->wd.base = e2k_wrap_reg_index(env->wd.base - wbs * 2);
env->wd.fx = env->cr1.wfx;
env->wdbl = env->cr1.wdbl;
env->usd.size = env->cr1.ussz << 4;
env->usd.base = env->sbr - env->usd.size;
env->pshtp.index -= wbs * 2;
e2k_state_cr1_hi_set(env, pcs_pop(env));
e2k_state_cr1_lo_set(env, pcs_pop(env));
env->cr1.hi = pcs_pop(env);
env->cr1.lo = pcs_pop(env);
env->cr0_hi = pcs_pop(env);
env->cr0_lo = pcs_pop(env);
sbr_pop(env);
}
static inline void ps_spill(CPUE2KState *env, bool force, bool force_fx)
@ -123,7 +109,7 @@ static inline void ps_spill(CPUE2KState *env, bool force, bool force_fx)
while (E2K_NR_COUNT < env->pshtp.index + env->wd.size ||
(force && env->wd.size + env->pshtp.index))
{
int i = (E2K_NR_COUNT + env->wd.base - env->pshtp.index) % E2K_NR_COUNT;
int i = e2k_wrap_reg_index(env->wd.base - env->pshtp.index);
ps_push(env, env->regs[i], env->tags[i]);
ps_push(env, env->regs[i + 1], env->tags[i + 1]);
@ -146,7 +132,7 @@ 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;
int i = e2k_wrap_reg_index(env->wd.base - env->pshtp.index);
if (force_fx) {
env->xregs[i + 1] = ps_pop(env, NULL);
env->xregs[i] = ps_pop(env, NULL);
@ -184,11 +170,10 @@ void helper_setwd(CPUE2KState *env, uint32_t lts)
ps_spill(env, false, PS_FORCE_FX);
if (old_size < size) {
unsigned int i, offset;
unsigned int i, offset = env->wd.base + old_size;
offset = env->wd.base + old_size + E2K_NR_COUNT;
for (i = 0; i < size - old_size; i++) {
unsigned int idx = (offset + i) % E2K_NR_COUNT;
int idx = e2k_wrap_reg_index(offset + i);
env->regs[idx] = 0;
env->tags[idx] = E2K_TAG_NON_NUMBER64;
}
@ -315,5 +300,5 @@ void helper_debug_i64(uint64_t x)
void helper_debug_ptr(void *x)
{
qemu_log_mask(LOG_UNIMP, "log %#lx\n", (uint64_t) x);
qemu_log_mask(LOG_UNIMP, "log %p\n", x);
}

View File

@ -32,12 +32,6 @@ uint64_t helper_sxt(uint64_t x, uint32_t y)
static uint64_t* state_reg_ptr(CPUE2KState *env, int idx)
{
switch (idx) {
/* FIXME: user cannot write */
case 0x2c: return &env->usd.hi; /* %usd.hi */
/* FIXME: user cannot write */
case 0x2d: return &env->usd.lo; /* %usd.lo */
case 0x51: return &env->ip; /* %cr1.hi */
case 0x53: return &env->pregs; /* %cr1.lo */
case 0x80: return &env->upsr; /* %upsr */
case 0x83: return &env->lsr; /* %lsr */
default: return NULL;
@ -47,24 +41,19 @@ static uint64_t* state_reg_ptr(CPUE2KState *env, int idx)
uint64_t helper_state_reg_read_i64(CPUE2KState *env, int idx)
{
switch (idx) {
case 0x01:
return e2k_state_wd(env); /* %wd */
case 0x0f:
return e2k_state_pcsp_lo(env); /* %pcsp.lo */
case 0x0d:
return e2k_state_pcsp_hi(env); /* %pcsp.hi */
case 0x13:
return env->pcshtp; /* %pcshtp */
case 0x55:
return e2k_state_cr1_hi(env); /* %cr1.hi */
case 0x57:
return e2k_state_cr1_lo(env); /* %cr1.lo */
case 0x81: /* %ip */
return env->ip;
case 0x8a: /* %idr */
return env->idr;
case 0x90: /* %clkr */
return cpu_get_host_ticks();
case 0x01: return e2k_state_wd(env); /* %wd */
case 0x0f: return e2k_state_pcsp_lo(env); /* %pcsp.lo */
case 0x0d: return e2k_state_pcsp_hi(env); /* %pcsp.hi */
case 0x13: return env->pcshtp; /* %pcshtp */
case 0x2c: return env->usd.hi; /* %usd.hi */
case 0x2d: return env->usd.lo; /* %usd.lo */
case 0x51: return env->cr0_hi; /* %cr0.hi */
case 0x53: return env->cr0_lo; /* %cr0.lo */
case 0x55: return env->cr1.hi; /* %cr1.hi */
case 0x57: return env->cr1.lo; /* %cr1.lo */
case 0x81: return env->ip; /* %ip */
case 0x8a: return env->idr; /* %idr */
case 0x90: return cpu_get_host_ticks(); /* %clkr */
default: {
uint64_t *p = state_reg_ptr(env, idx);
@ -110,14 +99,9 @@ void helper_state_reg_write_i32(CPUE2KState *env, int idx, uint32_t val)
uint64_t helper_getsp(CPUE2KState *env, uint32_t src2)
{
int32_t s2 = src2 & ~0xf;
uint32_t size = s2 >= 0 ? s2 : -s2;
if (size > env->usd.size) {
helper_raise_exception(env, E2K_EXCP_MAPERR);
}
env->usd.base += s2;
env->usd.size -= size;
env->usd.size -= s2;
return env->usd.base;
}

View File

@ -317,6 +317,7 @@ static inline void do_branch(DisasContext *ctx, target_ulong pc_next)
gen_set_label(l0);
if (ctx->ct.type == CT_NONE) {
e2k_gen_save_pc(ctx->base.pc_next);
return;
}