target: e2k: Fix call/return.
This commit is contained in:
parent
3b5241ad15
commit
dc5905c3ab
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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" },
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue