diff --git a/linux-user/e2k/target_cpu.h b/linux-user/e2k/target_cpu.h index d5f45b487e..06f84403d0 100644 --- a/linux-user/e2k/target_cpu.h +++ b/linux-user/e2k/target_cpu.h @@ -43,7 +43,7 @@ static inline void cpu_clone_regs_child(CPUE2KState *env, target_ulong newsp, return; } - frame_size = crs.cr1.wbs * (crs.cr1.wfx || E2K_FORCE_FX ? 32 : 16); + frame_size = crs.cr1.wbs * 32; ps_base -= frame_size; ps.index += frame_size; ps_old = lock_user(VERIFY_READ, ps_base, frame_size, 1); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 599ca0d7bf..5131c3a5d2 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7074,8 +7074,7 @@ static abi_long do_e2k_longjmp2(CPUE2KState *env, struct target_jmp_info *jmp_in return ret; } psize = crs.cr1.wpsz * 2; - ps_index -= crs.cr1.wbs * E2K_REG_LEN * - (crs.cr1.wfx || E2K_FORCE_FX ? 4 : 2); + ps_index -= crs.cr1.wbs * E2K_REG_LEN * 4; pcsp -= CRS_SIZE; } diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index 618e922a48..73a3553989 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -20,14 +20,6 @@ void e2k_tcg_initialize(void); /* #define TARGET_E2K_PRECISE_FSQRTID */ - -/* FIXME: nfx window mode - * numas13: I don't know why elbrus always spill/fill in fx mode. - * If we enable 'nfx' mode It will break "finish" command in gdb because - * it will try to read registers from hell. - */ -#define E2K_FORCE_FX true - #define GEN_MASK(start, len) (((1ULL << (len)) - 1) << (start)) #define GET_BIT(v, index) (((v) >> (index)) & 1) diff --git a/target/e2k/helper.c b/target/e2k/helper.c index 018dedcd92..3d05592355 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -3,6 +3,8 @@ #include "qemu/host-utils.h" #include "exec/helper-proto.h" +#define FRAME_SIZE(NREGS) ((NREGS) * 16) + static inline void reset_ctprs(CPUE2KState *env) { unsigned int i; @@ -12,87 +14,97 @@ static inline void reset_ctprs(CPUE2KState *env) } } -static inline void ps_push(CPUE2KState *env, uint64_t value, uint8_t tag) +static inline void ps_write(CPUE2KState *env, uint64_t value, uint8_t tag, int32_t index) { -#ifndef CONFIG_USER_ONLY - if ((env->psp.index + 8) > env->psp.size) { - raise_exception(env, E2K_EXCP_PROC_STACK_BOUNDS); - } -#endif + cpu_stq_le_data(env, env->psp.base + index, value); - cpu_stq_le_data(env, env->psp.base + env->psp.index, value); if (env->enable_tags) { - cpu_stb_data(env, env->psp.base_tag + env->psp.index / 8, tag); + cpu_stb_data(env, env->psp.base_tag + index / 8, tag); } - env->psp.index += 8; } -static inline uint64_t ps_pop(CPUE2KState *env, uint8_t *ret_tag) +static inline uint64_t ps_read(CPUE2KState *env, uint8_t *ret_tag, int32_t index) { - if (env->psp.index < 8) { - raise_exception(env, E2K_EXCP_PROC_STACK_BOUNDS); - } - env->psp.index -= 8; if (ret_tag != NULL) { if (env->enable_tags) { - abi_ptr ptr = env->psp.base_tag + env->psp.index / 8; - *ret_tag = cpu_ldub_data(env, ptr); + *ret_tag = cpu_ldub_data(env, env->psp.base_tag + index / 8); } else { *ret_tag = 0; } } - return cpu_ldq_le_data(env, env->psp.base + env->psp.index); -} + return cpu_ldq_le_data(env, env->psp.base + index); +} static void ps_spill(CPUE2KState *env, int n, bool fx) { - int i; + int32_t index = env->psp.index; + + // XXX: psp.size is set to some random value and does not show real stack size +#ifndef CONFIG_USER_ONLY + if (env->psp.index + FRAME_SIZE(n) > env->psp.size) { + raise_exception(env, E2K_EXCP_PROC_STACK_BOUNDS); + } +#endif if (env->version >= 5) { - for (i = 0; i < n; i++) { - ps_push(env, env->regs[i].lo, env->tags[i]); - if (fx || E2K_FORCE_FX) { - ps_push(env, env->regs[i].hi, 0); + for (int i = 0; i < n; i++, index += 16) { + ps_write(env, env->regs[i].lo, env->tags[i], index); + + if (fx) { + ps_write(env, env->regs[i].hi, 0, index + 8); } } } else{ - for (i = 0; i < n; i += 2) { + for (int i = 0; i < n; i += 2, index += 32) { E2KReg r0 = env->regs[i + 0]; E2KReg r1 = env->regs[i + 1]; - ps_push(env, r0.lo, env->tags[i]); - ps_push(env, r1.lo, env->tags[i + 1]); - if (fx || E2K_FORCE_FX) { - ps_push(env, r0.hi, 0); - ps_push(env, r1.hi, 0); + + ps_write(env, r0.lo, env->tags[i], index); + ps_write(env, r1.lo, env->tags[i + 1], index + 8); + + if (fx) { + ps_write(env, r0.hi, 0, index + 16); + ps_write(env, r1.hi, 0, index + 24); } } } + + env->psp.index = index; } static void ps_fill(CPUE2KState *env, int n, bool fx) { - int i; + int32_t index = env->psp.index, frame_size = FRAME_SIZE(n); + + if (index < frame_size) { + raise_exception(env, E2K_EXCP_PROC_STACK_BOUNDS); + } if (env->version >= 5) { - for (i = n; i-- > 0;) { - if (fx || E2K_FORCE_FX) { - env->regs[i].hi = ps_pop(env, NULL); + for (int i = n; i-- > 0; index -= 16) { + if (fx) { + env->regs[i].hi = ps_read(env, NULL, index - 8); } - env->regs[i].lo = ps_pop(env, &env->tags[i]); + + env->regs[i].lo = ps_read(env, &env->tags[i], index - 16); } } else { - for (i = n; i > 0; i -= 2) { + for (int i = n; i > 0; i -= 2, index -= 32) { E2KReg *r0 = &env->regs[i - 1]; E2KReg *r1 = &env->regs[i - 2]; - if (fx || E2K_FORCE_FX) { - r0->hi = ps_pop(env, NULL); - r1->hi = ps_pop(env, NULL); + + if (fx) { + r0->hi = ps_read(env, NULL, index - 8); + r1->hi = ps_read(env, NULL, index - 16); } - r0->lo = ps_pop(env, &env->tags[i - 1]); - r1->lo = ps_pop(env, &env->tags[i - 2]); + + r0->lo = ps_read(env, &env->tags[i - 1], index - 24); + r1->lo = ps_read(env, &env->tags[i - 2], index - 32); } } + + env->psp.index = index; } static void move_regs(CPUE2KState *env, int dst, int src, int n) diff --git a/target/e2k/translate.c b/target/e2k/translate.c index 02acf24fef..0dd63b9524 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -94,7 +94,6 @@ typedef enum { } AlesFlag; static TCGv cpu_pc; -static TCGv cpu_npc; static TCGv_i64 cpu_ctprs[3]; static TCGv_i32 cpu_ct_cond; static TCGv_i32 cpu_boff; /* holds rbs * 2 */ @@ -7550,7 +7549,6 @@ void e2k_tcg_initialize(void) { static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { { &cpu_pc, offsetof(CPUE2KState, ip), "pc" }, - { &cpu_npc, offsetof(CPUE2KState, nip), "npc" }, }; unsigned int i;