target: e2k: Add xregs.
This commit is contained in:
parent
676b4a2388
commit
1887af755a
@ -1530,13 +1530,13 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
|
||||
regs->pcsp.is_writable = true;
|
||||
regs->pcsp.index = 0;
|
||||
regs->pcsp.size = TARGET_PAGE_SIZE;
|
||||
regs->pcsp.base = (void *) e2k_mmap(regs->pcsp.size);
|
||||
regs->pcsp.base = e2k_mmap(regs->pcsp.size);
|
||||
|
||||
regs->psp.is_readable = true;
|
||||
regs->psp.is_writable = true;
|
||||
regs->psp.index = 0;
|
||||
regs->psp.size = TARGET_PAGE_SIZE * 8;
|
||||
regs->psp.base = (void *) e2k_mmap(regs->psp.size);
|
||||
regs->psp.base = e2k_mmap(regs->psp.size);
|
||||
}
|
||||
|
||||
static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUE2KState *env)
|
||||
|
@ -287,12 +287,12 @@ typedef struct {
|
||||
} E2KCr1State;
|
||||
|
||||
typedef struct {
|
||||
void *base;
|
||||
target_ulong base;
|
||||
uint32_t index;
|
||||
uint32_t size;
|
||||
bool is_readable;
|
||||
bool is_writable;
|
||||
} E2KDescState, E2KPsState, E2KPcsState;
|
||||
} E2KStackState, E2KPsState, E2KPcsState;
|
||||
|
||||
typedef struct {
|
||||
int16_t index;
|
||||
@ -302,7 +302,7 @@ typedef struct {
|
||||
} E2KPshtpState;
|
||||
|
||||
typedef struct {
|
||||
uint32_t base;
|
||||
int32_t base;
|
||||
uint32_t size;
|
||||
uint32_t psize;
|
||||
bool fx;
|
||||
@ -454,6 +454,7 @@ typedef union {
|
||||
typedef struct {
|
||||
/* register file */
|
||||
uint64_t regs[E2K_REG_COUNT]; /* registers */
|
||||
uint16_t xregs[E2K_REG_COUNT]; /* x part of registers */
|
||||
uint64_t tags[E2K_TAGS_REG_COUNT]; /* registers tags */
|
||||
uint64_t *rptr; /* pointer to regs */
|
||||
uint64_t *tptr; /* pointer to tags */
|
||||
@ -546,7 +547,7 @@ void e2k_break_save_state(CPUE2KState *env);
|
||||
#define cpu_signal_handler e2k_cpu_signal_handler
|
||||
#define cpu_list e2k_cpu_list
|
||||
|
||||
static inline uint64_t e2k_state_desc_lo(E2KDescState *desc)
|
||||
static inline uint64_t e2k_state_desc_lo(E2KStackState *desc)
|
||||
{
|
||||
uint64_t lo = 0;
|
||||
|
||||
@ -558,7 +559,7 @@ static inline uint64_t e2k_state_desc_lo(E2KDescState *desc)
|
||||
return lo;
|
||||
}
|
||||
|
||||
static inline uint64_t e2k_state_desc_hi(E2KDescState *env)
|
||||
static inline uint64_t e2k_state_desc_hi(E2KStackState *env)
|
||||
{
|
||||
uint64_t hi = 0;
|
||||
|
||||
@ -680,6 +681,14 @@ static inline void e2k_state_cr1_hi_set(CPUE2KState *env, uint64_t hi)
|
||||
cr1->ussz = extract64(hi, CR1_HI_USSZ_OFF, CR1_HI_USSZ_LEN);
|
||||
}
|
||||
|
||||
static inline void e2k_state_reg_tag_set_i64(CPUE2KState *env, int tag, int idx)
|
||||
{
|
||||
int i = idx / E2K_TAGS_PER_REG, offset;
|
||||
|
||||
offset = (idx & (E2K_TAGS_PER_REG - 1)) * E2K_REG_TAGS_SIZE;
|
||||
env->tags[i] = deposit64(env->tags[i], offset, E2K_REG_TAGS_SIZE, tag);
|
||||
}
|
||||
|
||||
typedef CPUE2KState CPUArchState;
|
||||
typedef E2KCPU ArchCPU;
|
||||
|
||||
|
@ -15,197 +15,146 @@ static inline void reset_ctprs(CPUE2KState *env)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void save_proc_chain_info(CPUE2KState *env, uint64_t buf[4],
|
||||
int wbs)
|
||||
static inline void stack_push(CPUE2KState *env, E2KStackState *s, uint64_t value)
|
||||
{
|
||||
env->cr1.br = e2k_state_br(env);
|
||||
env->cr1.wpsz = env->wd.psize / 2;
|
||||
if ((s->index + 8) > s->size) {
|
||||
helper_raise_exception(env, E2K_EXCP_MAPERR);
|
||||
return;
|
||||
}
|
||||
|
||||
buf[0] = env->cr0_lo;
|
||||
buf[1] = env->cr0_hi;
|
||||
buf[2] = e2k_state_cr1_lo(env);
|
||||
buf[3] = e2k_state_cr1_hi(env);
|
||||
|
||||
env->cr1.wfx = env->wd.fx;
|
||||
env->cr1.wbs = wbs;
|
||||
env->wd.base = (env->wd.base + wbs * 2) % E2K_NR_COUNT;
|
||||
env->wd.psize = env->wd.size -= wbs * 2;
|
||||
cpu_stq_le_data_ra(env, s->base + s->index, value, GETPC());
|
||||
s->index += 8;
|
||||
}
|
||||
|
||||
static inline void restore_proc_chain_info(CPUE2KState *env, uint64_t buf[4])
|
||||
static inline uint64_t stack_pop(CPUE2KState *env, E2KStackState *s)
|
||||
{
|
||||
if (s->index < 8) {
|
||||
helper_raise_exception(env, E2K_EXCP_MAPERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->index -= 8;
|
||||
return cpu_ldq_le_data(env, s->base + s->index);
|
||||
}
|
||||
|
||||
#define pcs_push(env, value) stack_push(env, &env->pcsp, (value))
|
||||
#define pcs_pop(env) stack_pop(env, &env->pcsp)
|
||||
#define ps_push(env, value) stack_push(env, &env->psp, (value))
|
||||
#define ps_pop(env) stack_pop(env, &env->psp)
|
||||
|
||||
static void proc_chain_save(CPUE2KState *env, int wbs)
|
||||
{
|
||||
env->pshtp.index += wbs * 2;
|
||||
|
||||
env->cr1.wbs = wbs;
|
||||
env->cr1.wpsz = env->wd.psize / 2;
|
||||
env->cr1.wfx = env->wd.fx;
|
||||
env->cr1.br = e2k_state_br(env);
|
||||
|
||||
pcs_push(env, env->cr0_lo);
|
||||
pcs_push(env, env->cr0_hi);
|
||||
pcs_push(env, e2k_state_cr1_lo(env));
|
||||
pcs_push(env, e2k_state_cr1_hi(env));
|
||||
|
||||
env->wd.fx = true;
|
||||
env->wd.base = (E2K_NR_COUNT + env->wd.base + wbs * 2) % E2K_NR_COUNT;
|
||||
env->wd.size -= wbs * 2;
|
||||
env->wd.psize = env->wd.size;
|
||||
}
|
||||
|
||||
static inline void proc_chain_restore(CPUE2KState *env)
|
||||
{
|
||||
int wbs;
|
||||
|
||||
e2k_state_cr1_hi_set(env, pcs_pop(env));
|
||||
e2k_state_cr1_lo_set(env, pcs_pop(env));
|
||||
env->cr0_hi = pcs_pop(env); // FIXME: is it necessary to restore ip?
|
||||
env->cr0_lo = pcs_pop(env);
|
||||
|
||||
wbs = env->cr1.wbs;
|
||||
e2k_state_br_set(env, env->cr1.br);
|
||||
env->wd.size = env->wd.psize + wbs * 2;
|
||||
env->wd.psize = env->cr1.wpsz * 2;
|
||||
env->wd.base = (E2K_NR_COUNT + env->wd.base - wbs * 2) % E2K_NR_COUNT;
|
||||
env->wd.fx = env->cr1.wfx;
|
||||
|
||||
e2k_state_cr1_hi_set(env, buf[3]);
|
||||
e2k_state_cr1_lo_set(env, buf[2]);
|
||||
env->cr0_hi = buf[1]; // FIXME: is it necessary to restore ip?
|
||||
env->cr0_lo = buf[0];
|
||||
|
||||
env->wd.psize = env->cr1.wpsz * 2;
|
||||
e2k_state_br_set(env, env->cr1.br);
|
||||
env->pshtp.index -= wbs * 2;
|
||||
}
|
||||
|
||||
static void pcs_push(CPUE2KState *env, int wbs)
|
||||
static inline void ps_spill(CPUE2KState *env, bool force, bool force_fx)
|
||||
{
|
||||
uint64_t buf[4];
|
||||
|
||||
if (env->pcsp.size < (env->pcsp.index + 32)) {
|
||||
helper_raise_exception(env, E2K_EXCP_MAPERR);
|
||||
return;
|
||||
}
|
||||
|
||||
save_proc_chain_info(env, buf, wbs);
|
||||
memcpy(env->pcsp.base + env->pcsp.index, buf, 32);
|
||||
env->pcsp.index += 32;
|
||||
}
|
||||
|
||||
static void pcs_pop(CPUE2KState *env)
|
||||
{
|
||||
uint64_t buf[4];
|
||||
|
||||
if (env->pcsp.index < 32) {
|
||||
helper_raise_exception(env, E2K_EXCP_MAPERR);
|
||||
return;
|
||||
}
|
||||
|
||||
env->pcsp.index -= 32;
|
||||
memcpy(buf, env->pcsp.base + env->pcsp.index, 32);
|
||||
restore_proc_chain_info(env, buf);
|
||||
}
|
||||
|
||||
static void ps_push_nfx(CPUE2KState *env, unsigned int base, size_t len)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t size = len * sizeof(uint64_t);
|
||||
uint64_t *p;
|
||||
|
||||
if (env->psp.size < (env->psp.index + size)) {
|
||||
helper_raise_exception(env, E2K_EXCP_MAPERR);
|
||||
return;
|
||||
}
|
||||
|
||||
p = (uint64_t *) (env->psp.base + env->psp.index);
|
||||
for (i = 0; i < len; i++) {
|
||||
int idx = (base + i) % E2K_NR_COUNT;
|
||||
memcpy(p + i, &env->regs[idx], sizeof(uint64_t));
|
||||
}
|
||||
|
||||
env->psp.index += size;
|
||||
}
|
||||
|
||||
static void ps_pop_nfx(CPUE2KState *env, unsigned int base, size_t len)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t size = len * sizeof(uint64_t);
|
||||
uint64_t *p;
|
||||
|
||||
if (env->psp.index < size) {
|
||||
// TODO: check where to raise exception
|
||||
helper_raise_exception(env, E2K_EXCP_MAPERR);
|
||||
return;
|
||||
}
|
||||
|
||||
env->psp.index -= size;
|
||||
p = (uint64_t *) (env->psp.base + env->psp.index);
|
||||
for (i = 0; i < len; i++) {
|
||||
int idx = (base + i) % E2K_NR_COUNT;
|
||||
memcpy(&env->regs[idx], p + i, sizeof(uint64_t));
|
||||
}
|
||||
}
|
||||
|
||||
static void ps_push_fx(CPUE2KState *env, unsigned int base, size_t len)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t size = len * 2 * sizeof(uint64_t);
|
||||
uint64_t *p, zeros[2] = { 0 };
|
||||
|
||||
if (env->psp.size < (env->psp.index + size)) {
|
||||
helper_raise_exception(env, E2K_EXCP_MAPERR);
|
||||
return;
|
||||
}
|
||||
|
||||
p = (uint64_t *) (env->psp.base + env->psp.index);
|
||||
for (i = 0; i < len; i += 2) {
|
||||
int idx = (base + i) % E2K_NR_COUNT;
|
||||
memcpy(p + i * 2, &env->regs[idx], 2 * sizeof(uint64_t));
|
||||
// TODO: save fx part
|
||||
memcpy(p + i * 2 + 2, zeros, 2 * sizeof(uint64_t));
|
||||
}
|
||||
|
||||
env->psp.index += size;
|
||||
}
|
||||
|
||||
static void ps_pop_fx(CPUE2KState *env, unsigned int base, size_t len)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t size = len * 2 * sizeof(uint64_t);
|
||||
uint64_t *p;
|
||||
|
||||
if (env->psp.index < size) {
|
||||
// TODO: check where to raise exception
|
||||
helper_raise_exception(env, E2K_EXCP_MAPERR);
|
||||
return;
|
||||
}
|
||||
|
||||
env->psp.index -= size;
|
||||
p = (uint64_t *) (env->psp.base + env->psp.index);
|
||||
for (i = 0; i < len; i += 2) {
|
||||
int idx = (base + i) % E2K_NR_COUNT;
|
||||
memcpy(&env->regs[idx], p + i * 2, sizeof(uint64_t));
|
||||
// TODO: restore fx part
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ps_push(CPUE2KState *env)
|
||||
{
|
||||
int occupied = env->wd.size + env->pshtp.index;
|
||||
if (E2K_NR_COUNT < occupied) {
|
||||
int len = occupied - E2K_NR_COUNT;
|
||||
int base = (int) env->wd.base - env->pshtp.index;
|
||||
if (base < 0) {
|
||||
base += E2K_NR_COUNT;
|
||||
while (E2K_NR_COUNT < env->pshtp.index + env->wd.size ||
|
||||
(force && env->pshtp.index))
|
||||
{
|
||||
int i = (E2K_NR_COUNT + env->wd.base - env->pshtp.index) % E2K_NR_COUNT;
|
||||
// TODO: push tags
|
||||
ps_push(env, env->regs[i]);
|
||||
ps_push(env, env->regs[i + 1]);
|
||||
env->regs[i] = 0;
|
||||
env->regs[i + 1] = 0;
|
||||
// TODO: set invalid reg tags
|
||||
// e2k_state_reg_tag_set_i64(env, E2K_TAG_NON_NUMBER64, i);
|
||||
// e2k_state_reg_tag_set_i64(env, E2K_TAG_NON_NUMBER64, i + 1);
|
||||
// TODO: push fx
|
||||
if (force_fx) {
|
||||
ps_push(env, env->xregs[i]);
|
||||
ps_push(env, env->xregs[i + 1]);
|
||||
}
|
||||
// TODO: ps_push_fx
|
||||
ps_push_nfx(env, base, len);
|
||||
env->pshtp.index -= len;
|
||||
env->pshtp.index -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ps_pop(CPUE2KState *env, int base, int required)
|
||||
static inline void ps_fill(CPUE2KState *env, bool force_fx)
|
||||
{
|
||||
if (env->pshtp.index < required) {
|
||||
int len = required - env->pshtp.index;
|
||||
// TODO: ps_pop_fx
|
||||
ps_pop_nfx(env, base, len);
|
||||
env->pshtp.index = 0;
|
||||
} else {
|
||||
env->pshtp.index -= required;
|
||||
while(env->pshtp.index < 0) {
|
||||
env->pshtp.index += 2;
|
||||
int i = (E2K_NR_COUNT + env->wd.base - env->pshtp.index) % E2K_NR_COUNT;
|
||||
// TODO: pop fx
|
||||
if (force_fx) {
|
||||
env->xregs[i + 1] = ps_pop(env);
|
||||
env->xregs[i] = ps_pop(env);
|
||||
}
|
||||
// TODO: restore tags
|
||||
env->regs[i + 1] = ps_pop(env);
|
||||
env->regs[i] = ps_pop(env);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void do_call(CPUE2KState *env, int wbs, target_ulong pc_next)
|
||||
{
|
||||
env->ip = pc_next;
|
||||
env->pshtp.index += wbs * 2; // add old window to allocated registers
|
||||
pcs_push(env, wbs);
|
||||
proc_chain_save(env, wbs);
|
||||
reset_ctprs(env);
|
||||
}
|
||||
|
||||
void helper_setwd(CPUE2KState *env, uint32_t lts)
|
||||
{
|
||||
env->wd.size = extract32(lts, 5, 7) * 2;
|
||||
env->wd.fx = extract32(lts, 4, 1) == 0;
|
||||
|
||||
if (env->version >= 3) {
|
||||
bool dbl = extract32(lts, 3, 1);
|
||||
// TODO: set dbl
|
||||
if (dbl != false) {
|
||||
qemu_log_mask(LOG_UNIMP, "0x%lx: dbl is not implemented!\n",
|
||||
env->ip);
|
||||
}
|
||||
env->cr1.wdbl = dbl;
|
||||
}
|
||||
|
||||
ps_spill(env, false, true);
|
||||
}
|
||||
|
||||
uint64_t helper_prep_return(CPUE2KState *env, int ipd)
|
||||
{
|
||||
uint64_t pc;
|
||||
E2KCtpr ret = { 0 };
|
||||
void *p;
|
||||
|
||||
if (env->pcsp.index < 32) {
|
||||
helper_raise_exception(env, E2K_EXCP_MAPERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = (void *) env->pcsp.base + env->pcsp.index - 24;
|
||||
memcpy(&pc, p, 8);
|
||||
|
||||
ret.base = pc;
|
||||
ret.base = cpu_ldq_le_data(env, env->pcsp.base + env->pcsp.index - 24);
|
||||
ret.tag = CTPR_TAG_RETURN;
|
||||
ret.ipd = ipd;
|
||||
|
||||
@ -214,21 +163,8 @@ uint64_t helper_prep_return(CPUE2KState *env, int ipd)
|
||||
|
||||
void helper_return(CPUE2KState *env)
|
||||
{
|
||||
uint32_t new_wd_size, new_wd_base, offset;
|
||||
|
||||
offset = env->cr1.wbs * 2;
|
||||
new_wd_size = env->wd.psize + offset;
|
||||
new_wd_base = env->wd.base;
|
||||
if (new_wd_base < offset) {
|
||||
new_wd_base += E2K_NR_COUNT;
|
||||
}
|
||||
new_wd_base = (new_wd_base - offset) % E2K_NR_COUNT;
|
||||
|
||||
ps_pop(env, new_wd_base, offset);
|
||||
pcs_pop(env);
|
||||
env->wd.base = new_wd_base;
|
||||
env->wd.size = new_wd_size;
|
||||
|
||||
proc_chain_restore(env);
|
||||
ps_fill(env, false);
|
||||
reset_ctprs(env);
|
||||
}
|
||||
|
||||
@ -269,29 +205,18 @@ void helper_raise_exception(CPUE2KState *env, int tt)
|
||||
|
||||
void e2k_break_save_state(CPUE2KState *env)
|
||||
{
|
||||
int wbs;
|
||||
|
||||
wbs = env->wd.size / 2;
|
||||
ps_push_fx(env, env->wd.base, env->wd.size);
|
||||
pcs_push(env, wbs);
|
||||
|
||||
env->wd.base = (env->wd.base + env->wd.size) % E2K_NR_COUNT;
|
||||
env->is_bp = true;
|
||||
proc_chain_save(env, env->wd.size / 2);
|
||||
env->wd.size = 0;
|
||||
env->wd.psize = 0;
|
||||
|
||||
env->is_bp = true;
|
||||
ps_spill(env, true, true);
|
||||
}
|
||||
|
||||
void helper_break_restore_state(CPUE2KState *env)
|
||||
{
|
||||
int wbs = env->cr1.wbs;
|
||||
|
||||
pcs_pop(env);
|
||||
env->wd.size = wbs * 2;
|
||||
env->wd.base = (env->wd.base - env->wd.size) % E2K_NR_COUNT;
|
||||
ps_pop_fx(env, env->wd.base, env->wd.size);
|
||||
|
||||
env->is_bp = false;
|
||||
proc_chain_restore(env);
|
||||
ps_fill(env, true);
|
||||
}
|
||||
|
||||
void helper_debug(CPUE2KState *env)
|
||||
@ -316,26 +241,3 @@ void helper_debug_ptr(void *x)
|
||||
{
|
||||
qemu_log_mask(LOG_UNIMP, "log %#lx\n", (uint64_t) x);
|
||||
}
|
||||
|
||||
void helper_setwd(CPUE2KState *env, uint32_t lts)
|
||||
{
|
||||
env->wd.size = extract32(lts, 5, 7) * 2;
|
||||
env->wd.fx = extract32(lts, 4, 1) == 0;
|
||||
|
||||
if (env->wd.fx) {
|
||||
qemu_log_mask(LOG_UNIMP, "0x%lx: wd.fx is not implemented!\n",
|
||||
env->ip);
|
||||
}
|
||||
|
||||
if (env->version >= 3) {
|
||||
bool dbl = extract32(lts, 3, 1);
|
||||
// TODO: set dbl
|
||||
if (dbl != false) {
|
||||
qemu_log_mask(LOG_UNIMP, "0x%lx: dbl is not implemented!\n",
|
||||
env->ip);
|
||||
}
|
||||
env->cr1.wdbl = dbl;
|
||||
}
|
||||
|
||||
ps_push(env);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user