From 37acf287ad81a5a0716eaade859622b8239ee76f Mon Sep 17 00:00:00 2001 From: Denis Drakhnya Date: Fri, 13 Nov 2020 16:49:28 +0200 Subject: [PATCH] target: e2k: Impl rotated pregs. --- linux-user/e2k/cpu_loop.c | 2 + linux-user/e2k/signal.c | 8 +++- linux-user/e2k/target_cpu.h | 16 ++++++-- linux-user/elfload.c | 3 ++ target/e2k/cpu.c | 8 ++-- target/e2k/cpu.h | 9 ++++- target/e2k/helper.c | 11 ++++++ target/e2k/helper.h | 2 + target/e2k/translate.c | 3 +- target/e2k/translate.h | 16 +++++++- target/e2k/translate/control.c | 4 +- target/e2k/translate/state.c | 71 ++++++++++++++++++++++++++-------- target/e2k/translate/win.c | 22 ++++++++++- 13 files changed, 139 insertions(+), 36 deletions(-) diff --git a/linux-user/e2k/cpu_loop.c b/linux-user/e2k/cpu_loop.c index fafc7018e5..5c71a5f36f 100644 --- a/linux-user/e2k/cpu_loop.c +++ b/linux-user/e2k/cpu_loop.c @@ -65,4 +65,6 @@ void cpu_loop(CPUE2KState *env) void target_cpu_copy_regs(CPUE2KState *env, struct target_pt_regs *regs) { env->ip = regs->ip; + env->usd_hi = regs->usd_hi; + env->usd_lo = regs->usd_lo; } diff --git a/linux-user/e2k/signal.c b/linux-user/e2k/signal.c index 4bfcfe2c53..7ead4c8951 100644 --- a/linux-user/e2k/signal.c +++ b/linux-user/e2k/signal.c @@ -77,6 +77,7 @@ struct target_sigcontext { void setup_frame(int sig, struct target_sigaction *ka, target_sigset_t *set, CPUE2KState *env) { + /* TODO */ qemu_log_mask(LOG_UNIMP, "setup_frame: not implemented\n"); } @@ -84,18 +85,21 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, target_siginfo_t *info, target_sigset_t *set, CPUE2KState *env) { + /* TODO */ qemu_log_mask(LOG_UNIMP, "setup_rt_frame: not implemented\n"); } long do_sigreturn(CPUE2KState *env) { - // TODO + /* TODO */ + qemu_log_mask(LOG_UNIMP, "do_sigreturn: not implemented\n"); return 0; } long do_rt_sigreturn(CPUE2KState *env) { trace_user_do_rt_sigreturn(env, 0); + /* TODO */ qemu_log_mask(LOG_UNIMP, "do_rt_sigreturn: not implemented\n"); return -TARGET_ENOSYS; } @@ -103,7 +107,7 @@ long do_rt_sigreturn(CPUE2KState *env) abi_long do_swapcontext(CPUArchState *env, abi_ulong uold_ctx, abi_ulong unew_ctx, abi_long ctx_size) { - // TODO + /* TODO */ qemu_log_mask(LOG_UNIMP, "do_swapcontext: not implemented\n"); return 0; } diff --git a/linux-user/e2k/target_cpu.h b/linux-user/e2k/target_cpu.h index 3f19fec363..059fc40cba 100644 --- a/linux-user/e2k/target_cpu.h +++ b/linux-user/e2k/target_cpu.h @@ -1,32 +1,40 @@ #ifndef E2K_TARGET_CPU_H #define E2K_TARGET_CPU_H +#include "qemu/log.h" + static inline void cpu_clone_regs_child(CPUE2KState *env, target_ulong newsp, unsigned flags) { - // TODO + if (newsp) { + uint64_t size = 0x20000UL; + env->usd_hi = size << 32; + env->usd_lo = (0x1800UL << 48) | newsp; + } } static inline void cpu_clone_regs_parent(CPUE2KState *env, unsigned flags) { + qemu_log_mask(LOG_UNIMP, "cpu_clone_regs_parent: unimplemented\n"); // TODO } static inline void cpu_set_tls(CPUE2KState *env, target_ulong newtls) { + qemu_log_mask(LOG_UNIMP, "cpu_set_tls: unimplemented\n"); // TODO } static inline target_ulong cpu_get_tls(CPUE2KState *env) { // TODO + qemu_log_mask(LOG_UNIMP, "cpu_get_tls: unimplemented\n"); return 0; } -static inline abi_ulong get_sp_from_cpustate(CPUE2KState *state) +static inline abi_ulong get_sp_from_cpustate(CPUE2KState *env) { - // TODO - return 0; + return env->usd_lo & ((1UL << 48) - 1); } #endif /* E2K_TARGET_CPU_H */ diff --git a/linux-user/elfload.c b/linux-user/elfload.c index bb6bde5648..36053765c3 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1616,7 +1616,10 @@ typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) { + uint64_t size = infop->start_stack - infop->stack_limit; regs->ip = infop->entry; + regs->usd_hi = size << 32; + regs->usd_lo = (0x1800UL << 48) | infop->start_stack; // TODO qemu_log_mask(LOG_UNIMP, "init_thread: not implemented\n"); } diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index 3c71ebb654..aa12686d03 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -45,9 +45,6 @@ static void e2k_cpu_reset(DeviceState *dev) memset(env, 0, offsetof(CPUE2KState, end_reset_fields)); env->win_ptr = env->wregs; - - env->usd_hi = 0x2088000000000UL; - env->usd_lo = 0x1800c2dfffffe880UL; } #ifdef CONFIG_SOFTMMU @@ -84,8 +81,9 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags) qemu_fprintf(f, "ip: " TARGET_FMT_lx "\n", env->ip); qemu_fprintf(f, "pregs: %016lx\n", env->pregs); - qemu_fprintf(f, "%%usd.hi: %016lx\n", env->usd_hi); - qemu_fprintf(f, "%%usd.lo: %016lx\n", env->usd_lo); + qemu_fprintf(f, "usd_hi: %016lx, usd_lo: %016lx\n", + env->usd_hi, env->usd_lo); + qemu_fprintf(f, "psz: %d, pcur: %d\n", (int) env->psz, (int) env->pcur); for (i = 0; i < 192; i += 4) { const char *s1 = i < 10 ? " " : (i < 100 ? " " : ""); diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index 1d60038f59..126badac09 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -30,14 +30,19 @@ typedef struct CPUArchState { target_ulong wregs[WREGS_SIZE]; // window regs target_ulong *win_ptr; uint64_t pregs; + uint32_t wbs; // Real window regs offset, in bundle it comes divided by 2 uint32_t wsz; // Real window regs size, in bundle it comes divided by 2 uint32_t nfx; // TODO uint32_t dbl; // TODO + + /* TODO: move them to %br? */ uint32_t rbs; // Real based regs offset, in bundle it comes divided by 2 uint32_t rsz; // Real based regs size, in bundle it comes divided by 2 minus 2 - uint32_t rcur; // Real based regs current index, in bundle it comes divided by 2 - uint32_t psz; // pred regs window size + uint32_t rcur; // Real based regs current offset, in bundle it comes divided by 2 + uint64_t psz; // pred regs window size + uint64_t pcur; // pred regs current offset + uint32_t syscall_wbs; uint64_t usd_lo; diff --git a/target/e2k/helper.c b/target/e2k/helper.c index 8fe3990621..054341a8e6 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -1,4 +1,5 @@ #include "qemu/osdep.h" +#include "qemu/log.h" #include "cpu.h" #include "exec/exec-all.h" #include "qemu/host-utils.h" @@ -52,3 +53,13 @@ uint64_t helper_sxt(uint64_t x, uint64_t y) return (((int64_t) y) << (64 - size) >> (64 - size)); } } + +void helper_debug_i32(uint32_t x) +{ + qemu_log_mask(LOG_UNIMP, "log %#x\n", x); +} + +void helper_debug_i64(uint64_t x) +{ + qemu_log_mask(LOG_UNIMP, "log %#lx\n", x); +} diff --git a/target/e2k/helper.h b/target/e2k/helper.h index 6b781ec2df..be9e7ca65e 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -1,3 +1,5 @@ DEF_HELPER_2(raise_exception, noreturn, env, int) DEF_HELPER_3(call, void, env, i64, i64) DEF_HELPER_2(sxt, i64, i64, i64) +DEF_HELPER_1(debug_i32, void, i32) +DEF_HELPER_1(debug_i64, void, i64) diff --git a/target/e2k/translate.c b/target/e2k/translate.c index f15d925f07..0d186599cb 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -428,12 +428,13 @@ void e2k_tcg_initialize(void) { { &e2k_cs.rbs, offsetof(CPUE2KState, rbs), "rbs" }, { &e2k_cs.rsz, offsetof(CPUE2KState, rsz), "rsz" }, { &e2k_cs.rcur, offsetof(CPUE2KState, rcur), "rcur" }, - { &e2k_cs.psz, offsetof(CPUE2KState, psz), "psz" }, { &e2k_cs.syscall_wbs, offsetof(CPUE2KState, syscall_wbs), "syscall_wbs" }, }; static const struct { TCGv_i64 *ptr; int off; const char *name; } r64[] = { { &e2k_cs.pregs, offsetof(CPUE2KState, pregs), "pregs" }, + { &e2k_cs.psz, offsetof(CPUE2KState, psz), "psz" }, + { &e2k_cs.pcur, offsetof(CPUE2KState, pcur), "pcur" }, { &e2k_cs.usd_lo, offsetof(CPUE2KState, usd_lo), "%usd.lo" }, { &e2k_cs.usd_hi, offsetof(CPUE2KState, usd_hi), "%usd.hi" }, }; diff --git a/target/e2k/translate.h b/target/e2k/translate.h index 61086ac61c..984dbe6b44 100644 --- a/target/e2k/translate.h +++ b/target/e2k/translate.h @@ -68,7 +68,8 @@ typedef struct CPUE2KStateTCG { TCGv_i32 rbs; TCGv_i32 rsz; TCGv_i32 rcur; - TCGv_i32 psz; + TCGv_i64 psz; + TCGv_i64 pcur; TCGv_i32 syscall_wbs; TCGv_ptr win_ptr; TCGv_i64 wregs[WREGS_SIZE]; @@ -177,6 +178,17 @@ static inline void e2k_gen_wrap_i32(TCGv_i32 ret, TCGv_i32 x, TCGv_i32 y) tcg_temp_free_i32(t0); } +// FIXME: x must not be greater than y * 2 +static inline void e2k_gen_wrap_i64(TCGv_i64 ret, TCGv_i64 x, TCGv_i64 y) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + + tcg_gen_sub_i64(t0, x, y); + tcg_gen_movcond_i64(TCG_COND_LTU, ret, x, y, x, t0); + + tcg_temp_free_i64(t0); +} + static inline void e2k_gen_get_field_i64(TCGv_i64 ret, TCGv_i64 val, unsigned int start, unsigned int end) { @@ -204,7 +216,7 @@ static inline void e2k_gen_set_field_i64(TCGv_i64 ret, TCGv_i64 val, tcg_temp_free_i64(t0); } -TCGv_i64 e2k_gen_preg(TCGv_i64 ret, int reg); +void e2k_gen_preg(TCGv_i64 ret, int reg); TCGv_i64 e2k_get_preg(DisasContext *dc, int reg); void e2k_gen_store_preg(int reg, TCGv_i64 val); TCGv_i64 e2k_get_wreg(DisasContext *dc, int reg); diff --git a/target/e2k/translate/control.c b/target/e2k/translate/control.c index 362928b7bc..8903607128 100644 --- a/target/e2k/translate/control.c +++ b/target/e2k/translate/control.c @@ -211,9 +211,7 @@ static void gen_cs1(DisasContext *dc) } if (setbp) { - unsigned int psz = (cs1 & 0x007c0000) >> 18; - - tcg_gen_movi_i32(e2k_cs.psz, psz); + tcg_gen_movi_i64(e2k_cs.psz, GET_FIELD(cs1, 18, 23)); } } else if (opc == SETEI) { /* Verify that CS1.param.sft = CS1.param[27] is equal to zero as required diff --git a/target/e2k/translate/state.c b/target/e2k/translate/state.c index 36f58f14f2..c847bacc6f 100644 --- a/target/e2k/translate/state.c +++ b/target/e2k/translate/state.c @@ -3,6 +3,52 @@ #include "exec/log.h" #include "translate.h" +static void gen_preg_offset(TCGv_i64 ret, int reg) +{ + assert(reg < 32); + + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_addi_i64(t0, e2k_cs.pcur, reg); + tcg_gen_addi_i64(t1, e2k_cs.psz, 1); + e2k_gen_wrap_i64(t2, t0, t1); + tcg_gen_shli_i64(ret, t2, 1); + + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t0); +} + +static void gen_preg_clear(TCGv_i64 ret, TCGv_i64 offset) +{ + TCGv_i64 t0 = tcg_const_i64(3); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_shr_i64(t1, t0, offset); + tcg_gen_not_i64(t2, t1); + tcg_gen_and_i64(ret, t2, e2k_cs.pregs); + + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t0); +} + +void e2k_gen_preg(TCGv_i64 ret, int reg) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + + gen_preg_offset(t0, reg); + tcg_gen_shri_i64(t1, e2k_cs.pregs, reg * 2); + tcg_gen_andi_i64(ret, t1, 0x01); + + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t0); +} + TCGv_i64 e2k_get_preg(DisasContext *dc, int reg) { TCGv_i64 ret = e2k_get_temp_i64(dc); @@ -10,26 +56,19 @@ TCGv_i64 e2k_get_preg(DisasContext *dc, int reg) return ret; } -TCGv_i64 e2k_gen_preg(TCGv_i64 ret, int reg) -{ - TCGv_i64 tmp = tcg_temp_new_i64(); - assert(reg < 32); - tcg_gen_shri_i64(tmp, e2k_cs.pregs, reg * 2); - // TODO: should return preg tag? - tcg_gen_andi_i64(ret, tmp, 0x01); - tcg_temp_free_i64(tmp); - return ret; -} - void e2k_gen_store_preg(int reg, TCGv_i64 val) { TCGv_i64 t0 = tcg_temp_new_i64(); TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - tcg_gen_andi_i64(t0, e2k_cs.pregs, ~(3 << (reg * 2))); - tcg_gen_andi_i64(t1, val, 0x03); - tcg_gen_shli_i64(t2, t1, reg * 2); - tcg_gen_or_i64(e2k_cs.pregs, t0, t2); + TCGv_i64 t2 = tcg_const_i64(1); + TCGv_i64 t3 = tcg_temp_new_i64(); + + gen_preg_offset(t0, reg); + gen_preg_clear(t1, t0); + tcg_gen_shl_i64(t3, t2, t0); + tcg_gen_or_i64(e2k_cs.pregs, t1, t3); + + tcg_temp_free_i64(t3); tcg_temp_free_i64(t2); tcg_temp_free_i64(t1); tcg_temp_free_i64(t0); diff --git a/target/e2k/translate/win.c b/target/e2k/translate/win.c index e039cdb65a..68605626bf 100644 --- a/target/e2k/translate/win.c +++ b/target/e2k/translate/win.c @@ -3,6 +3,21 @@ #include "exec/log.h" #include "translate.h" +static inline void gen_abp_inc(DisasContext *dc, TCGCond cond) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 one = tcg_const_i64(1); + + tcg_gen_subi_i64(t0, e2k_cs.pcur, 1); + tcg_gen_umin_i64(t1, t0, e2k_cs.psz); + tcg_gen_movcond_i64(cond, e2k_cs.pcur, dc->jmp.cond, one, t1, e2k_cs.pcur); + + tcg_temp_free_i64(one); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t0); +} + static inline void gen_abn_inc(DisasContext *dc, TCGCond cond) { TCGv_i32 t0 = tcg_temp_new_i32(); @@ -29,7 +44,6 @@ void e2k_win_commit(DisasContext *dc) uint32_t ss = dc->bundle.ss; // unsigned int vfdi = (ss & 0x04000000) >> 26; // unsigned int abg = (ss & 0x01800000) >> 23; -// unsigned int abp = (ss & 0x000c0000) >> 18; // unsigned int alc = (ss & 0x00030000) >> 16; if (GET_BIT(ss, 21)) { @@ -38,4 +52,10 @@ void e2k_win_commit(DisasContext *dc) if (GET_BIT(ss, 22)) { gen_abn_inc(dc, TCG_COND_NE); } + if (GET_BIT(ss, 18)) { + gen_abp_inc(dc, TCG_COND_EQ); + } + if (GET_BIT(ss, 19)) { + gen_abp_inc(dc, TCG_COND_NE); + } }