target: e2k: Delete hack for saving USD registers on proc call/ret.
This commit is contained in:
parent
76ebaa78bd
commit
74f2385990
@ -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;
|
||||
|
@ -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));
|
||||
|
109
target/e2k/cpu.h
109
target/e2k/cpu.h
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user