From 21b39b82065b49b6f58cee53cc2bcae48b8e533f Mon Sep 17 00:00:00 2001 From: Denis Drakhnya Date: Tue, 15 Dec 2020 00:12:18 +0200 Subject: [PATCH] target: e2k: Delete hack for saving USD registers on proc call/ret. --- linux-user/elfload.c | 9 ++-- target/e2k/cpu.c | 4 +- target/e2k/cpu.h | 109 +++++++++++++++++----------------------- target/e2k/gdbstub.c | 4 +- target/e2k/helper.c | 43 ++++++---------- target/e2k/helper_int.c | 44 ++++++---------- target/e2k/translate.c | 1 + 7 files changed, 84 insertions(+), 130 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 3a12e0dbf1..77d66569ce 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1639,13 +1639,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; diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index 16ab0dc83f..3157e45a75 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -153,8 +153,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)); diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index af99baf673..043ebef9ff 100644 --- a/target/e2k/cpu.h +++ b/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 { @@ -576,6 +609,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; @@ -658,58 +693,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); -} - #include "exec/cpu-all.h" #endif diff --git a/target/e2k/gdbstub.c b/target/e2k/gdbstub.c index 31913f9d0c..d053804b1a 100644 --- a/target/e2k/gdbstub.c +++ b/target/e2k/gdbstub.c @@ -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 diff --git a/target/e2k/helper.c b/target/e2k/helper.c index 57e2cd572e..26d1f2399e 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -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; } @@ -307,5 +292,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); } diff --git a/target/e2k/helper_int.c b/target/e2k/helper_int.c index 96e735f6aa..a77fec933a 100644 --- a/target/e2k/helper_int.c +++ b/target/e2k/helper_int.c @@ -33,12 +33,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; @@ -48,24 +42,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); @@ -111,14 +100,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; } diff --git a/target/e2k/translate.c b/target/e2k/translate.c index 9f2fd3aece..c3b4c86006 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -303,6 +303,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; }