From dc5905c3ab990c04f5f4868b66891bbbcbedaedd Mon Sep 17 00:00:00 2001 From: Denis Drakhnya Date: Sun, 22 Nov 2020 11:44:28 +0200 Subject: [PATCH] target: e2k: Fix call/return. --- target/e2k/cpu.c | 5 ++-- target/e2k/cpu.h | 9 +++--- target/e2k/helper.c | 66 +++++++++++++++++------------------------- target/e2k/translate.c | 4 +-- target/e2k/translate.h | 1 + 5 files changed, 37 insertions(+), 48 deletions(-) diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index 4787685cd5..ddac4e5bd6 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -45,8 +45,9 @@ static void e2k_cpu_reset(DeviceState *dev) memset(env, 0, offsetof(CPUE2KState, end_reset_fields)); env->wptr = &env->wregs[0]; - env->woff = 0; - env->wsize = 16; + env->wd_base = 0; + env->wd_size = 8; + env->wd_psize = 8; } #ifdef CONFIG_SOFTMMU diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index 9ae1e8c0a2..41d5e2a50a 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -228,8 +228,9 @@ typedef struct CPUArchState { uint64_t lsr; /* loop status register */ - uint32_t woff; /* holds wbs * 2 */ - uint32_t wsize; /* holds wsz * 2 */ + uint32_t wd_base; + uint32_t wd_size; + uint32_t wd_psize; uint32_t boff; /* holds rbs * 2 */ uint32_t bsize; /* holds rsz * 2 + 2 */ uint32_t bcur; /* holds rcur * 2 */ @@ -359,12 +360,12 @@ static inline void e2k_state_wbs_set(CPUE2KState *env, int wbs) CR1_LO_WBS_OFF, CR1_LO_WBS_LEN); } -static inline int e2k_state_wsz_get(CPUE2KState *env) +static inline int e2k_state_wpsz_get(CPUE2KState *env) { return GET_FIELD(env->cr1_lo, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_END); } -static inline void e2k_state_wsz_set(CPUE2KState *env, int wsz) +static inline void e2k_state_wpsz_set(CPUE2KState *env, int wsz) { env->cr1_lo = SET_FIELD(env->cr1_lo, wsz, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_LEN); diff --git a/target/e2k/helper.c b/target/e2k/helper.c index f9c13f2aa5..4a7e4cadad 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -11,7 +11,8 @@ static inline void reset_ctprs(CPUE2KState *env) unsigned int i; for (i = 0; i < 3; i++) { - env->ctprs[i] = 0; + env->ctprs[i] = SET_FIELD(env->ctprs[i], CTPR_TAG_NONE, + CTPR_TAG_OFF, CTPR_TAG_LEN); } } @@ -28,15 +29,16 @@ void helper_save_cpu_state(CPUE2KState *env) env->cr1_hi = SET_FIELD(env->cr1_hi, br, CR1_HI_BR_OFF + BR_BN_OFF, BR_BN_LEN); - env->cr1_lo = SET_FIELD(env->cr1_lo, env->wsize / 2, + env->cr1_lo = SET_FIELD(env->cr1_lo, env->wd_psize / 2, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_LEN); } -static inline void restore_state(CPUE2KState *env) +static inline void restore_br_state(CPUE2KState *env) { uint32_t br; - int rbs, rsz, rcur, psz, pcur, wsz, wbs; + int rbs, rsz, rcur, psz, pcur; + // FIXME: cr1_hi.br does not modified after return, find a way to restore it br = GET_FIELD(env->cr1_hi, CR1_HI_BR_OFF, CR1_HI_BR_LEN); rbs = GET_FIELD(br, BR_RBS_OFF, BR_RBS_END); rsz = GET_FIELD(br, BR_RSZ_OFF, BR_RSZ_END); @@ -44,17 +46,11 @@ static inline void restore_state(CPUE2KState *env) psz = GET_FIELD(br, BR_PSZ_OFF, BR_PSZ_END); pcur = GET_FIELD(br, BR_PCUR_OFF, BR_PCUR_END); - wbs = GET_FIELD(env->cr1_lo, CR1_LO_WBS_OFF, CR1_LO_WBS_END); - wsz = GET_FIELD(env->cr1_lo, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_END); - env->boff = rbs * 2; env->bsize = rsz * 2 + 2; env->bcur = rcur * 2; env->psize = psz; env->pcur = pcur; - - env->woff = wbs * 2; - env->wsize = wsz * 2; } void helper_unimpl(CPUE2KState *env) @@ -157,51 +153,41 @@ static void ps_pop(CPUE2KState *env, unsigned int wbs, size_t len) static inline void do_call(CPUE2KState *env, int call_wbs) { - int wbs, wsz, new_wbs, new_wsz; + int call_wpsz = env->wd_size / 2 - call_wbs; - wbs = e2k_state_wbs_get(env); - wsz = e2k_state_wsz_get(env); - new_wbs = (wbs + call_wbs) % (WREGS_SIZE / 2); - new_wsz = wsz - call_wbs; - - if (new_wsz < 0) { - /* TODO: SIGSEGV */ - abort(); - } - - /* save procedure chain info */ + helper_save_cpu_state(env); pcs_push(env); - /* save regs */ - ps_push(env, wbs * 2, call_wbs * 2); + ps_push(env, env->wd_base, call_wbs * 2); - e2k_state_wbs_set(env, new_wbs); - e2k_state_wsz_set(env, new_wsz); + e2k_state_wbs_set(env, call_wbs); + env->wd_base = (env->wd_base + call_wbs * 2) % WREGS_SIZE; + env->wd_size = env->wd_psize = call_wpsz * 2; - /* restore woff, wsize, etc */ - restore_state(env); reset_ctprs(env); } target_ulong helper_return(CPUE2KState *env) { - int new_wbs, old_wbs; + int new_wd_size, new_wd_base, wbs; target_ulong tgt; - old_wbs = e2k_state_wbs_get(env) * 2; + wbs = GET_FIELD(env->cr1_lo, CR1_LO_WBS_OFF, CR1_LO_WBS_END); + new_wd_size = env->wd_psize + wbs * 2; + new_wd_base = (env->wd_base - wbs * 2) % WREGS_SIZE; - /* restore procedure chain info */ - tgt = pcs_pop(env); - - new_wbs = e2k_state_wbs_get(env) * 2; - - if (old_wbs < new_wbs) { - old_wbs += WREGS_SIZE; + if (env->wd_base < new_wd_base) { + env->wd_base += WREGS_SIZE; } - ps_pop(env, new_wbs, old_wbs - new_wbs); + tgt = pcs_pop(env); - /* restore woff, wsize, etc */ - restore_state(env); + ps_pop(env, new_wd_base, env->wd_base - new_wd_base); + + env->wd_base = new_wd_base; + env->wd_size = new_wd_size; + env->wd_psize = GET_FIELD(env->cr1_lo, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_END) * 2; + + restore_br_state(env); reset_ctprs(env); return tgt; diff --git a/target/e2k/translate.c b/target/e2k/translate.c index 1c76de81db..d544975d64 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -478,8 +478,8 @@ void e2k_tcg_initialize(void) { char buf[16] = { 0 }; static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = { - { &e2k_cs.woff, offsetof(CPUE2KState, woff), "woff" }, - { &e2k_cs.wsize, offsetof(CPUE2KState, wsize), "wsize" }, + { &e2k_cs.woff, offsetof(CPUE2KState, wd_base), "woff" }, + { &e2k_cs.wsize, offsetof(CPUE2KState, wd_size), "wsize" }, { &e2k_cs.boff, offsetof(CPUE2KState, boff), "boff" }, { &e2k_cs.bsize, offsetof(CPUE2KState, bsize), "bsize" }, { &e2k_cs.bcur, offsetof(CPUE2KState, bcur), "bcur" }, diff --git a/target/e2k/translate.h b/target/e2k/translate.h index 3f3632de8b..b9635f85c9 100644 --- a/target/e2k/translate.h +++ b/target/e2k/translate.h @@ -38,6 +38,7 @@ #define GET_GLOBAL(i) ((i) & 0x1f) typedef enum { + CTPR_TAG_NONE = 0x0, CTPR_TAG_RETURN = 0x2, CTPR_TAG_DISP = 0x3, CTPR_TAG_LDISP = 0x3,