target: e2k: Add pcs_{push,pop}.
This commit is contained in:
parent
d495f0ffb3
commit
a23305afc0
@ -17,7 +17,7 @@ void e2k_tcg_initialize(void);
|
||||
#define SET_FIELD(v, f, s, l) \
|
||||
( \
|
||||
((v) & ~GEN_MASK_LEN((s), (l))) | \
|
||||
((((typeof(v)) (f)) << (s)) & GEN_MASK_LEN((s), (l))) \
|
||||
((((typeof((v))) (f)) << (s)) & GEN_MASK_LEN((s), (l))) \
|
||||
)
|
||||
|
||||
#define MMU_USER_IDX 1
|
||||
@ -229,6 +229,39 @@ int e2k_cpu_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||
|
||||
#define cpu_signal_handler e2k_cpu_signal_handler
|
||||
|
||||
static inline target_ulong e2k_state_pcs_base_get(CPUE2KState *env)
|
||||
{
|
||||
return GET_FIELD(env->pcsp_lo, PCSP_LO_BASE_OFF, PCSP_LO_BASE_END);
|
||||
}
|
||||
|
||||
static inline void e2k_state_pcs_base_set(CPUE2KState *env, target_ulong pcsp)
|
||||
{
|
||||
env->pcsp_lo = SET_FIELD(env->pcsp_lo, pcsp, PCSP_LO_BASE_OFF,
|
||||
PCSP_LO_BASE_LEN);
|
||||
}
|
||||
|
||||
static inline size_t e2k_state_pcs_index_get(CPUE2KState *env)
|
||||
{
|
||||
return GET_FIELD(env->pcsp_hi, PCSP_HI_IND_OFF, PCSP_HI_IND_END);
|
||||
}
|
||||
|
||||
static inline void e2k_state_pcs_index_set(CPUE2KState *env, size_t ind)
|
||||
{
|
||||
env->pcsp_hi = SET_FIELD(env->pcsp_hi, ind, PCSP_HI_IND_OFF,
|
||||
PCSP_HI_IND_LEN);
|
||||
}
|
||||
|
||||
static inline size_t e2k_state_pcs_size_get(CPUE2KState *env)
|
||||
{
|
||||
return GET_FIELD(env->pcsp_hi, PCSP_HI_SIZE_OFF, PCSP_HI_SIZE_END);
|
||||
}
|
||||
|
||||
static inline void e2k_state_pcs_size_set(CPUE2KState *env, size_t size)
|
||||
{
|
||||
env->pcsp_hi = SET_FIELD(env->pcsp_hi, size, PCSP_HI_SIZE_OFF,
|
||||
PCSP_HI_SIZE_LEN);
|
||||
}
|
||||
|
||||
static inline int e2k_state_wbs_get(CPUE2KState *env)
|
||||
{
|
||||
return GET_FIELD(env->cr1_lo, CR1_LO_WBS_OFF, CR1_LO_WBS_END);
|
||||
|
@ -14,48 +14,73 @@ void helper_raise_exception(CPUE2KState *env, int tt)
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
static void pcs_push(CPUE2KState *env)
|
||||
{
|
||||
size_t size = e2k_state_pcs_size_get(env);
|
||||
size_t offset = e2k_state_pcs_index_get(env);
|
||||
uint64_t *pcsp = (uint64_t *) (e2k_state_pcs_base_get(env) + offset);
|
||||
|
||||
if (offset + 32 > size) {
|
||||
/* TODO: allocate more memory */
|
||||
abort();
|
||||
}
|
||||
|
||||
memcpy(pcsp, &env->pf, 8);
|
||||
memcpy(pcsp + 1, &env->nip, 8);
|
||||
memcpy(pcsp + 2, &env->cr1_lo, 8);
|
||||
memcpy(pcsp + 3, &env->cr1_hi, 8);
|
||||
|
||||
e2k_state_pcs_index_set(env, offset + 32);
|
||||
}
|
||||
|
||||
static void pcs_pop(CPUE2KState *env)
|
||||
{
|
||||
size_t offset = e2k_state_pcs_index_get(env);
|
||||
uint64_t *pcsp = (uint64_t *) (e2k_state_pcs_base_get(env) + offset - 32);
|
||||
|
||||
if (offset < 32) {
|
||||
/* TODO: SIGKILL */
|
||||
abort();
|
||||
}
|
||||
|
||||
memcpy(&env->pf, pcsp, 8);
|
||||
memcpy(&env->ip, pcsp + 1, 8);
|
||||
memcpy(&env->cr1_lo, pcsp + 2, 8);
|
||||
memcpy(&env->cr1_hi, pcsp + 3, 8);
|
||||
|
||||
e2k_state_pcs_index_set(env, offset - 32);
|
||||
}
|
||||
|
||||
static inline void do_call(CPUE2KState *env, target_ulong ctpr)
|
||||
{
|
||||
unsigned int offset, wbs, wsz, new_wbs, new_wsz;
|
||||
uint64_t *pcsp = (uint64_t *)
|
||||
GET_FIELD(env->pcsp_lo, PCSP_LO_BASE_OFF, PCSP_LO_BASE_END);
|
||||
int wbs, wsz, new_wbs, new_wsz;
|
||||
|
||||
wbs = e2k_state_wbs_get(env);
|
||||
wsz = e2k_state_wsz_get(env);
|
||||
new_wbs = (wbs + env->call_wbs) % WREGS_SIZE;
|
||||
new_wsz = wsz - env->call_wbs;
|
||||
|
||||
/* save procedure chain */
|
||||
offset = (env->pcsp_hi & GEN_MASK(0, 31)) / 8;
|
||||
pcsp[offset + 0] = env->pf;
|
||||
pcsp[offset + 1] = env->nip;
|
||||
pcsp[offset + 2] = env->cr1_lo;
|
||||
pcsp[offset + 3] = env->cr1_hi;
|
||||
/* TODO: check stack overflow */
|
||||
env->pcsp_hi = env->pcsp_hi + 32;
|
||||
if (wsz < 0) {
|
||||
/* TODO: SIGSEGV */
|
||||
abort();
|
||||
}
|
||||
|
||||
/* save procedure chain info */
|
||||
pcs_push(env);
|
||||
|
||||
/* TODO: check if call_wbs is less or equal then wsz */
|
||||
e2k_state_wbs_set(env, new_wbs);
|
||||
e2k_state_wsz_set(env, new_wsz);
|
||||
/* TODO: check rbs/rsz after call */
|
||||
|
||||
env->ip = GET_FIELD(ctpr, CTPR_BASE_OFF, CTPR_BASE_END);
|
||||
}
|
||||
|
||||
static void do_return(CPUE2KState *env)
|
||||
{
|
||||
unsigned int offset = env->pcsp_hi & GEN_MASK(0, 31);
|
||||
uint64_t *pcsp = (uint64_t *) (GET_FIELD(env->pcsp_lo, PCSP_LO_BASE_OFF,
|
||||
PCSP_LO_BASE_END) + offset - 32);
|
||||
// uint64_t *psp = (uint64_t *) GET_FIELD(env->psp_lo, PSP_LO_BASE_OFF,
|
||||
// PSP_LO_BASE_END);
|
||||
|
||||
env->pf = pcsp[0];
|
||||
env->ip = pcsp[1];
|
||||
env->nip = env->ip + 8;
|
||||
env->cr1_lo = pcsp[2];
|
||||
env->cr1_hi = pcsp[3];
|
||||
/* TODO: check stack overflow */
|
||||
env->pcsp_hi = env->pcsp_hi - 32;
|
||||
/* restore procedure chain info */
|
||||
pcs_pop(env);
|
||||
|
||||
// TODO: restore regs
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user