e2k: Delete top CRs from cpu state.
Signed-off-by: Denis Drakhnya <numas13@gmail.com>
This commit is contained in:
parent
05304bd1f3
commit
5e66da5f7d
@ -129,6 +129,8 @@ void target_cpu_copy_regs(CPUE2KState *env, struct target_pt_regs *regs)
|
||||
env->sbr = regs->sbr;
|
||||
env->elf_flags = info->elf_flags;
|
||||
|
||||
// TODO: set a chain info to return to kernel
|
||||
|
||||
if (eflags & E2K_ELF_PM) {
|
||||
fprintf(stderr, "Protected mode is unsupported\n");
|
||||
exit(EXIT_FAILURE);
|
||||
@ -138,11 +140,6 @@ void target_cpu_copy_regs(CPUE2KState *env, struct target_pt_regs *regs)
|
||||
fprintf(stderr, "x86 recompiler is unsupported\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
e2k_break_save_state(env);
|
||||
|
||||
env->pcs_base = env->pcsp.base;
|
||||
env->ps_base = env->psp.base;
|
||||
}
|
||||
|
||||
const char *cpu_get_model(uint32_t eflags)
|
||||
|
@ -116,17 +116,25 @@ struct target_sigframe {
|
||||
void helper_signal_frame(CPUE2KState *env, int wbs, target_ulong ret_ip);
|
||||
void helper_signal_return(CPUE2KState *env);
|
||||
|
||||
static void setup_sigcontext(CPUE2KState *env,
|
||||
static abi_long setup_sigcontext(CPUE2KState *env,
|
||||
struct target_sigcontext *sc, struct target_extra_ucontext *extra)
|
||||
{
|
||||
int i;
|
||||
E2KCrs crs;
|
||||
int i, ret;
|
||||
|
||||
// TODO: save binary compiler state (uspr, rpr, MLT)
|
||||
__put_user(env->upsr, &sc->upsr);
|
||||
|
||||
ret = e2k_copy_from_user_crs(&crs, env->pcsp.base + env->pcsp.index);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
__put_user(crs.cr0_lo, &sc->cr0_lo);
|
||||
__put_user(crs.cr0_hi, &sc->cr0_hi);
|
||||
__put_user(crs.cr1.lo, &sc->cr1_lo);
|
||||
__put_user(crs.cr1.hi, &sc->cr1_hi);
|
||||
|
||||
__put_user(env->crs.cr0_lo, &sc->cr0_lo);
|
||||
__put_user(env->crs.cr0_hi, &sc->cr0_hi);
|
||||
__put_user(env->crs.cr1.lo, &sc->cr1_lo);
|
||||
__put_user(env->crs.cr1.hi, &sc->cr1_hi);
|
||||
__put_user(env->sbr, &sc->sbr);
|
||||
__put_user(env->usd.lo, &sc->usd_lo);
|
||||
__put_user(env->usd.hi, &sc->usd_hi);
|
||||
@ -156,15 +164,17 @@ static void setup_sigcontext(CPUE2KState *env,
|
||||
for (i = 0; i < DAM_ENTRIES_NUM; i++) {
|
||||
__put_user(env->dam[i].raw, &sc->dam[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setup_ucontext(struct target_ucontext *uc, CPUE2KState *env)
|
||||
static abi_long setup_ucontext(struct target_ucontext *uc, CPUE2KState *env)
|
||||
{
|
||||
__put_user(0, &uc->uc_flags);
|
||||
__put_user(0, &uc->uc_link);
|
||||
|
||||
target_save_altstack(&uc->uc_stack, env);
|
||||
setup_sigcontext(env, &uc->uc_mcontext, &uc->uc_extra);
|
||||
return setup_sigcontext(env, &uc->uc_mcontext, &uc->uc_extra);
|
||||
}
|
||||
|
||||
static abi_ulong get_sigframe(struct target_sigaction *ka, CPUE2KState *env,
|
||||
@ -192,8 +202,9 @@ static void target_setup_frame(int sig, struct target_sigaction *ka,
|
||||
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
|
||||
force_sigsegv(sig);
|
||||
}
|
||||
|
||||
setup_ucontext(&frame->uc, env);
|
||||
if (setup_ucontext(&frame->uc, env)) {
|
||||
goto fail;
|
||||
}
|
||||
copy_to_user((abi_ulong) &frame->uc.uc_sigmask, set, sizeof(*set));
|
||||
copy_to_user((abi_ulong) &frame->aau, &env->aau, sizeof(env->aau));
|
||||
|
||||
@ -227,12 +238,26 @@ static void target_setup_frame(int sig, struct target_sigaction *ka,
|
||||
}
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
return;
|
||||
|
||||
fail:
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
force_sigsegv(sig);
|
||||
}
|
||||
|
||||
static int target_restore_sigframe(CPUE2KState *env,
|
||||
static abi_long target_restore_sigframe(CPUE2KState *env,
|
||||
struct target_sigframe *frame)
|
||||
{
|
||||
__get_user(env->crs.cr0_hi, &frame->uc.uc_mcontext.cr0_hi);
|
||||
target_ulong crs_addr = env->pcsp.base + env->pcsp.index;
|
||||
E2KCrs crs, *p;
|
||||
|
||||
if (!lock_user_struct(VERIFY_WRITE, p, crs_addr, 0)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
__get_user(crs.cr0_hi, &frame->uc.uc_mcontext.cr0_hi);
|
||||
__put_user(crs.cr0_hi, &p->cr0_hi);
|
||||
unlock_user_struct(p, crs_addr, 1);
|
||||
|
||||
__get_user(env->ctprs[0].raw, &frame->uc.uc_extra.ctpr1);
|
||||
__get_user(env->ctprs[1].raw, &frame->uc.uc_extra.ctpr2);
|
||||
__get_user(env->ctprs[2].raw, &frame->uc.uc_extra.ctpr3);
|
||||
|
@ -18,12 +18,12 @@ static inline void cpu_clone_regs_child(CPUE2KState *env, target_ulong newsp,
|
||||
}
|
||||
|
||||
if (flags & CLONE_VM) {
|
||||
E2KPcsState pcs;
|
||||
E2KPsState ps;
|
||||
E2KCrs crs = { 0 };
|
||||
E2KPcsState pcs = { 0 };
|
||||
E2KPsState ps = { 0 };
|
||||
E2KCrs crs;
|
||||
uint64_t *ps_old, *ps_new;
|
||||
size_t frame_size;
|
||||
target_ulong pcs_base = env->pcsp.base + env->pcsp.index - sizeof(E2KCrs);
|
||||
target_ulong pcsp = env->pcsp.base + env->pcsp.index;
|
||||
target_ulong ps_base = env->psp.base + env->psp.index;
|
||||
int i;
|
||||
|
||||
@ -32,9 +32,11 @@ static inline void cpu_clone_regs_child(CPUE2KState *env, target_ulong newsp,
|
||||
|
||||
// TODO: size checks and a way to report errors
|
||||
|
||||
e2k_copy_from_user_crs(&crs, pcs_base);
|
||||
e2k_copy_to_user_crs(pcs.base, &crs);
|
||||
// TODO: set a chain info to return to kernel
|
||||
|
||||
pcs.index += sizeof(E2KCrs);
|
||||
e2k_copy_from_user_crs(&crs, pcsp);
|
||||
e2k_copy_to_user_crs(pcs.base + pcs.index, &crs);
|
||||
|
||||
frame_size = crs.cr1.wbs * (crs.cr1.wfx ? 32 : 16);
|
||||
ps_base -= frame_size;
|
||||
|
@ -7046,32 +7046,43 @@ abi_long e2k_copy_to_user_crs(abi_ulong target_crs_addr, E2KCrs *crs)
|
||||
static abi_long do_e2k_longjmp2(CPUE2KState *env, struct target_jmp_info *jmp_info)
|
||||
{
|
||||
E2KPcsState jmp_pcsp;
|
||||
E2KCrs crs = env->crs;
|
||||
E2KCrs crs;
|
||||
int level; /* how many CRs need to restore */
|
||||
int pcs_index = env->pcsp.index;
|
||||
int ps_index = env->psp.index;
|
||||
int psize = env->wd.psize;
|
||||
int ret, i;
|
||||
target_ulong pcsp = env->pcsp.base + env->pcsp.index;
|
||||
|
||||
jmp_pcsp.lo = jmp_info->pcsplo;
|
||||
jmp_pcsp.hi = jmp_info->pcsphi;
|
||||
|
||||
level = (env->pcsp.index - jmp_pcsp.index) / CRS_SIZE;
|
||||
for (i = 0; i < level; i++) {
|
||||
psize = crs.cr1.wpsz * 2;
|
||||
ps_index -= crs.cr1.wbs * E2K_REG_LEN * (crs.cr1.wfx ? 4 : 2);
|
||||
pcs_index -= CRS_SIZE;
|
||||
ret = e2k_copy_from_user_crs(&crs, env->pcsp.base + pcs_index);
|
||||
ret = e2k_copy_from_user_crs(&crs, pcsp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
psize = crs.cr1.wpsz * 2;
|
||||
ps_index -= crs.cr1.wbs * E2K_REG_LEN * (crs.cr1.wfx ? 4 : 2);
|
||||
pcsp -= CRS_SIZE;
|
||||
}
|
||||
|
||||
env->crs.cr0_hi = jmp_info->cr0hi;
|
||||
env->crs.cr1.lo = jmp_info->cr1lo;
|
||||
env->crs.cr1.br = jmp_info->br;
|
||||
env->crs.cr1.ussz = (env->sbr - extract64(jmp_info->usdlo, 0, 48)) >> 4;
|
||||
env->pcsp.index = pcs_index;
|
||||
ret = e2k_copy_from_user_crs(&crs, pcsp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
crs.cr0_hi = jmp_info->cr0hi;
|
||||
crs.cr1.lo = jmp_info->cr1lo;
|
||||
crs.cr1.br = jmp_info->br;
|
||||
crs.cr1.ussz = (env->sbr - extract64(jmp_info->usdlo, 0, 48)) >> 4;
|
||||
|
||||
ret = e2k_copy_to_user_crs(pcsp, &crs);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
env->pcsp.index = pcsp - env->pcsp.base;
|
||||
env->psp.index = ps_index;
|
||||
env->wd.psize = psize;
|
||||
|
||||
|
@ -44,8 +44,6 @@ static void e2k_cpu_reset(DeviceState *dev)
|
||||
|
||||
memset(env, 0, offsetof(CPUE2KState, end_reset_fields));
|
||||
|
||||
env->crs.cr1.wpsz = 4;
|
||||
env->crs.cr1.wbs = 4;
|
||||
env->wd.base = 0;
|
||||
env->wd.size = 16;
|
||||
env->wd.psize = 8;
|
||||
@ -155,10 +153,6 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
|
||||
qemu_fprintf(f, " ip = 0x%016lx\n", env->ip);
|
||||
qemu_fprintf(f, " pregs = 0x%016lx\n", env->pregs);
|
||||
qemu_fprintf(f, " cr0_lo = 0x%016lx\n", env->crs.cr0_lo);
|
||||
qemu_fprintf(f, " cr0_hi = 0x%016lx\n", env->crs.cr0_hi);
|
||||
qemu_fprintf(f, " cr1_lo = 0x%016lx\n", env->crs.cr1.lo);
|
||||
qemu_fprintf(f, " cr1_hi = 0x%016lx\n", env->crs.cr1.hi);
|
||||
qemu_fprintf(f, " pcsp_lo = 0x%016lx\n", e2k_state_pcsp_lo(env));
|
||||
qemu_fprintf(f, " pcsp_hi = 0x%016lx\n", e2k_state_pcsp_hi(env));
|
||||
qemu_fprintf(f, " psp_lo = 0x%016lx\n", e2k_state_psp_lo(env));
|
||||
|
@ -633,12 +633,8 @@ typedef struct CPUArchState {
|
||||
/* DAM */
|
||||
E2KDamEntry dam[32];
|
||||
|
||||
// TODO: DO NOT USE! Will be removed!
|
||||
E2KCrs crs;
|
||||
|
||||
/* Procedure chain info = cr0_lo, cr0_hi, cr1_lo, cr1_hi */
|
||||
E2KPcsState pcsp;
|
||||
uint64_t pcshtp;
|
||||
|
||||
/* Procedure stack pointer (for regs) */
|
||||
E2KPsState psp;
|
||||
@ -684,9 +680,6 @@ typedef struct CPUArchState {
|
||||
/* zeroing upper register half for 32-bit instructions */
|
||||
uint32_t wdbl;
|
||||
|
||||
target_ulong pcs_base;
|
||||
target_ulong ps_base;
|
||||
|
||||
/* Fields up to this point are cleared by a CPU reset */
|
||||
struct {} end_reset_fields;
|
||||
|
||||
@ -734,7 +727,6 @@ void e2k_cpu_list(void);
|
||||
int e2k_cpu_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||
int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n);
|
||||
int e2k_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n);
|
||||
void e2k_break_save_state(CPUE2KState *env);
|
||||
bool e2k_cpu_tlb_fill(CPUState *cpu, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr);
|
||||
|
@ -25,6 +25,14 @@
|
||||
|
||||
/* TODO: reverse engineer e2k-linux-gdb register ids */
|
||||
|
||||
static uint64_t cr_read(CPUState *cs, CPUE2KState *env, size_t offset)
|
||||
{
|
||||
target_ulong addr = env->pcsp.base + env->pcsp.index + offset;
|
||||
uint64_t r;
|
||||
cpu_memory_rw_debug(cs, addr, &r, sizeof(r), false);
|
||||
return r;
|
||||
}
|
||||
|
||||
int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
@ -62,12 +70,18 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
case 51: return gdb_get_reg64(mem_buf, 0); // pshtp
|
||||
case 52: return gdb_get_reg64(mem_buf, env->pregs); // pregs
|
||||
case 53: return gdb_get_reg64(mem_buf, env->ip); // ip
|
||||
case 54: return gdb_get_reg64(mem_buf, env->crs.cr1.lo); // cr1_lo
|
||||
case 55: return gdb_get_reg64(mem_buf, env->crs.cr1.hi); // cr1_hi
|
||||
case 54: { // cr1_lo
|
||||
uint64_t cr1_lo = cr_read(cs, env, offsetof(E2KCrs, cr1.lo));
|
||||
return gdb_get_reg64(mem_buf, cr1_lo);
|
||||
}
|
||||
case 55: { // cr1_hi
|
||||
uint64_t cr1_hi = cr_read(cs, env, offsetof(E2KCrs, cr1.hi));
|
||||
return gdb_get_reg64(mem_buf, cr1_hi);
|
||||
}
|
||||
case 56: return gdb_get_reg64(mem_buf, 0); // cwd
|
||||
case 57: return gdb_get_reg64(mem_buf, e2k_state_pcsp_lo(env)); // pcsp_lo
|
||||
case 58: return gdb_get_reg64(mem_buf, e2k_state_pcsp_hi(env)); // pcsp_hi
|
||||
case 59: return gdb_get_reg64(mem_buf, env->pcshtp); // pcshtp
|
||||
case 59: return gdb_get_reg64(mem_buf, 0); // pcshtp
|
||||
case 60: return gdb_get_reg64(mem_buf, 0); // cud_lo
|
||||
case 61: return gdb_get_reg64(mem_buf, 0); // cud_hi
|
||||
case 62: return gdb_get_reg64(mem_buf, 0); // gd_lo
|
||||
|
@ -41,9 +41,6 @@ static inline uint64_t stack_pop(CPUE2KState *env, E2KStackState *s)
|
||||
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)
|
||||
|
||||
static inline void ps_push(CPUE2KState *env, uint64_t value, uint8_t tag)
|
||||
{
|
||||
cpu_stb_data(env, env->psp.base_tag + env->psp.index / 8, tag);
|
||||
@ -59,48 +56,6 @@ static inline uint64_t ps_pop(CPUE2KState *env, uint8_t *ret_tag)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void proc_chain_save(CPUE2KState *env, int wd_base, target_ulong ret_ip)
|
||||
{
|
||||
pcs_push(env, env->crs.cr0_lo);
|
||||
pcs_push(env, env->crs.cr0_hi);
|
||||
pcs_push(env, env->crs.cr1.lo);
|
||||
pcs_push(env, env->crs.cr1.hi);
|
||||
|
||||
env->crs.cr0_lo = env->pregs;
|
||||
env->crs.cr0_hi = ret_ip & ~7;
|
||||
env->crs.cr1.wbs = wd_base / 2;
|
||||
env->crs.cr1.wpsz = env->wd.psize / 2;
|
||||
env->crs.cr1.wfx = env->wd.fx;
|
||||
env->crs.cr1.wdbl = env->wdbl;
|
||||
env->crs.cr1.br = e2k_state_br(env);
|
||||
env->crs.cr1.ussz = env->usd.size >> 4;
|
||||
|
||||
env->wd.fx = true;
|
||||
env->wd.size -= wd_base;
|
||||
env->wd.psize = env->wd.size;
|
||||
}
|
||||
|
||||
static void proc_chain_restore(CPUE2KState *env)
|
||||
{
|
||||
int wd_base;
|
||||
|
||||
env->pregs = env->crs.cr0_lo;
|
||||
env->ip = env->crs.cr0_hi & ~7;
|
||||
wd_base = env->crs.cr1.wbs * 2;
|
||||
e2k_state_br_set(env, env->crs.cr1.br);
|
||||
env->wd.size = env->wd.psize + wd_base;
|
||||
env->wd.psize = env->crs.cr1.wpsz * 2;
|
||||
env->wd.fx = env->crs.cr1.wfx;
|
||||
env->wdbl = env->crs.cr1.wdbl;
|
||||
env->usd.size = env->crs.cr1.ussz << 4;
|
||||
env->usd.base = env->sbr - env->usd.size;
|
||||
|
||||
env->crs.cr1.hi = pcs_pop(env);
|
||||
env->crs.cr1.lo = pcs_pop(env);
|
||||
env->crs.cr0_hi = pcs_pop(env);
|
||||
env->crs.cr0_lo = pcs_pop(env);
|
||||
}
|
||||
|
||||
static void ps_spill(CPUE2KState *env, int n, bool fx)
|
||||
{
|
||||
int i;
|
||||
@ -127,16 +82,6 @@ static void ps_fill(CPUE2KState *env, int n, bool fx)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ps_spill_all(CPUE2KState *env)
|
||||
{
|
||||
ps_spill(env, env->wd.size, true);
|
||||
}
|
||||
|
||||
static inline void ps_fill_all(CPUE2KState *env)
|
||||
{
|
||||
ps_fill(env, env->wd.size, true);
|
||||
}
|
||||
|
||||
static void move_regs(CPUE2KState *env, int dst, int src, int n)
|
||||
{
|
||||
memmove(&env->regs[dst], &env->regs[src], n * sizeof(env->regs[0]));
|
||||
@ -144,36 +89,114 @@ static void move_regs(CPUE2KState *env, int dst, int src, int n)
|
||||
memmove(&env->xregs[dst], &env->xregs[src], n * sizeof(env->xregs[0]));
|
||||
}
|
||||
|
||||
static void callee_window(CPUE2KState *env, int wbs)
|
||||
static void callee_window(CPUE2KState *env, int base, int size, bool fx)
|
||||
{
|
||||
int s = wbs * 2;
|
||||
ps_spill(env, s, env->wd.fx);
|
||||
move_regs(env, 0, s, env->wd.size - s);
|
||||
ps_spill(env, base, fx);
|
||||
move_regs(env, 0, base, size - base);
|
||||
}
|
||||
|
||||
static void caller_window(CPUE2KState *env)
|
||||
static void caller_window(CPUE2KState *env, int base, int params, bool fx)
|
||||
{
|
||||
int s = env->crs.cr1.wbs * 2;
|
||||
move_regs(env, s, 0, env->wd.psize);
|
||||
ps_fill(env, s, env->crs.cr1.wfx);
|
||||
move_regs(env, base, 0, params);
|
||||
ps_fill(env, base, fx);
|
||||
}
|
||||
|
||||
static void crs_write(CPUE2KState *env, target_ulong addr, E2KCrs *crs)
|
||||
{
|
||||
cpu_stq_le_data(env, addr + offsetof(E2KCrs, cr0_lo), crs->cr0_lo);
|
||||
cpu_stq_le_data(env, addr + offsetof(E2KCrs, cr0_hi), crs->cr0_hi);
|
||||
cpu_stq_le_data(env, addr + offsetof(E2KCrs, cr1.lo), crs->cr1.lo);
|
||||
cpu_stq_le_data(env, addr + offsetof(E2KCrs, cr1.hi), crs->cr1.hi);
|
||||
}
|
||||
|
||||
static void crs_read(CPUE2KState *env, target_ulong addr, E2KCrs *crs)
|
||||
{
|
||||
crs->cr0_lo = cpu_ldq_le_data(env, addr + offsetof(E2KCrs, cr0_lo));
|
||||
crs->cr0_hi = cpu_ldq_le_data(env, addr + offsetof(E2KCrs, cr0_hi));
|
||||
crs->cr1.lo = cpu_ldq_le_data(env, addr + offsetof(E2KCrs, cr1.lo));
|
||||
crs->cr1.hi = cpu_ldq_le_data(env, addr + offsetof(E2KCrs, cr1.hi));
|
||||
}
|
||||
|
||||
static void pcs_push(CPUE2KState *env, E2KCrs *crs)
|
||||
{
|
||||
if ((env->pcsp.index + sizeof(E2KCrs) * 2) > env->pcsp.size) {
|
||||
// TODO: stack expand (switch to next stack)
|
||||
qemu_log_mask(LOG_UNIMP, "e2k stack expand\n");
|
||||
helper_raise_exception(env, E2K_EXCP_MAPERR);
|
||||
}
|
||||
|
||||
env->pcsp.index += sizeof(E2KCrs);
|
||||
crs_write(env, env->pcsp.base + env->pcsp.index, crs);
|
||||
}
|
||||
|
||||
static void pcs_pop(CPUE2KState *env, E2KCrs *crs)
|
||||
{
|
||||
crs_read(env, env->pcsp.base + env->pcsp.index, crs);
|
||||
|
||||
if (env->pcsp.index < sizeof(E2KCrs)) {
|
||||
// TODO: stack shrink (switch to previous stack)
|
||||
qemu_log_mask(LOG_UNIMP, "e2k stack shrink\n");
|
||||
} else {
|
||||
env->pcsp.index -= sizeof(E2KCrs);
|
||||
}
|
||||
}
|
||||
|
||||
static void proc_call(CPUE2KState *env, int base, target_ulong ret_ip,
|
||||
bool force_fx)
|
||||
{
|
||||
E2KCrs crs;
|
||||
|
||||
crs.cr0_lo = env->pregs;
|
||||
crs.cr0_hi = ret_ip & ~7;
|
||||
crs.cr1.wbs = base / 2;
|
||||
crs.cr1.wpsz = env->wd.psize / 2;
|
||||
crs.cr1.wfx = env->wd.fx;
|
||||
crs.cr1.wdbl = env->wdbl;
|
||||
crs.cr1.br = e2k_state_br(env);
|
||||
crs.cr1.ussz = env->usd.size >> 4;
|
||||
|
||||
pcs_push(env, &crs);
|
||||
callee_window(env, base, env->wd.size, env->wd.fx || force_fx);
|
||||
|
||||
env->wd.fx = true;
|
||||
env->wd.size -= base;
|
||||
env->wd.psize = env->wd.size;
|
||||
}
|
||||
|
||||
static void proc_return(CPUE2KState *env, bool force_fx)
|
||||
{
|
||||
E2KCrs crs;
|
||||
int base;
|
||||
|
||||
pcs_pop(env, &crs);
|
||||
base = crs.cr1.wbs * 2;
|
||||
|
||||
caller_window(env, base, env->wd.psize, crs.cr1.wfx || force_fx);
|
||||
|
||||
env->pregs = crs.cr0_lo;
|
||||
env->ip = crs.cr0_hi & ~7;
|
||||
e2k_state_br_set(env, crs.cr1.br);
|
||||
env->wd.size = env->wd.psize + base;
|
||||
env->wd.psize = crs.cr1.wpsz * 2;
|
||||
env->wd.fx = crs.cr1.wfx;
|
||||
env->wdbl = crs.cr1.wdbl;
|
||||
env->usd.size = crs.cr1.ussz << 4;
|
||||
env->usd.base = env->sbr - env->usd.size;
|
||||
}
|
||||
|
||||
void HELPER(signal_frame)(CPUE2KState *env, int wd_size, target_ulong ret_ip)
|
||||
{
|
||||
callee_window(env, wd_size / 2);
|
||||
proc_chain_save(env, wd_size, ret_ip);
|
||||
proc_call(env, wd_size, ret_ip, false);
|
||||
}
|
||||
|
||||
void HELPER(signal_return)(CPUE2KState *env)
|
||||
{
|
||||
caller_window(env);
|
||||
proc_chain_restore(env);
|
||||
proc_return(env, false);
|
||||
}
|
||||
|
||||
static inline void do_call(CPUE2KState *env, int wbs, target_ulong ret_ip)
|
||||
{
|
||||
callee_window(env, wbs);
|
||||
proc_chain_save(env, wbs * 2, ret_ip);
|
||||
proc_call(env, wbs * 2, ret_ip, false);
|
||||
reset_ctprs(env);
|
||||
}
|
||||
|
||||
@ -204,17 +227,14 @@ void HELPER(call)(CPUE2KState *env, uint64_t ctpr_raw, int call_wbs,
|
||||
uint64_t HELPER(prep_return)(CPUE2KState *env, int ipd)
|
||||
{
|
||||
E2KCtpr ret = { 0 };
|
||||
target_ulong addr = env->pcsp.base + env->pcsp.index + offsetof(E2KCrs, cr0_hi);
|
||||
uint64_t cr0_hi = cpu_ldq_le_data(env, addr) & ~7;
|
||||
|
||||
if (env->pcsp.index < 32) {
|
||||
helper_raise_exception(env, E2K_EXCP_MAPERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (env->crs.cr0_hi == E2K_SYSRET_ADDR_CTPR) {
|
||||
if (cr0_hi == E2K_SYSRET_ADDR_CTPR) {
|
||||
ret.base = E2K_SIGRET_ADDR;
|
||||
ret.opc = CTPR_OPC_SIGRET;
|
||||
} else {
|
||||
ret.base = env->crs.cr0_hi;
|
||||
ret.base = cr0_hi;
|
||||
}
|
||||
|
||||
ret.tag = CTPR_TAG_RETURN;
|
||||
@ -239,8 +259,7 @@ void HELPER(return)(CPUE2KState *env)
|
||||
qemu_log("%#lx: unknown return ctpr opc %d\n", env->ip, opc);
|
||||
}
|
||||
|
||||
caller_window(env);
|
||||
proc_chain_restore(env);
|
||||
proc_return(env, false);
|
||||
reset_ctprs(env);
|
||||
}
|
||||
}
|
||||
@ -249,8 +268,7 @@ void HELPER(raise_exception)(CPUE2KState *env, int tt)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
cs->exception_index = tt;
|
||||
ps_spill_all(env);
|
||||
proc_chain_save(env, env->wd.size, env->ip);
|
||||
proc_call(env, env->wd.size, env->ip, true);
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
@ -267,7 +285,6 @@ void HELPER(setwd)(CPUE2KState *env, int wsz, int nfx, int dbl)
|
||||
|
||||
if (size < env->wd.psize) {
|
||||
helper_raise_exception(env, E2K_EXCP_ILLOPN);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = env->wd.size; i < size; i++) {
|
||||
@ -285,24 +302,15 @@ bool e2k_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
ps_spill_all(env);
|
||||
proc_chain_save(env, env->wd.size, env->ip);
|
||||
proc_call(env, env->wd.size, env->ip, true);
|
||||
|
||||
cs->exception_index = E2K_EXCP_MAPERR;
|
||||
cpu_loop_exit_restore(cs, retaddr);
|
||||
}
|
||||
|
||||
void e2k_break_save_state(CPUE2KState *env)
|
||||
{
|
||||
env->is_bp = true;
|
||||
ps_spill_all(env);
|
||||
proc_chain_save(env, env->wd.size, env->ip);
|
||||
}
|
||||
|
||||
void HELPER(break_restore_state)(CPUE2KState *env)
|
||||
{
|
||||
proc_chain_restore(env);
|
||||
ps_fill_all(env);
|
||||
proc_return(env, true);
|
||||
env->is_bp = false;
|
||||
}
|
||||
|
||||
|
@ -30,12 +30,10 @@ uint64_t helper_sxt(uint64_t x, uint32_t y)
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t* state_reg_ptr(CPUE2KState *env, int idx)
|
||||
static uint64_t cr_read(CPUE2KState *env, size_t offset)
|
||||
{
|
||||
switch (idx) {
|
||||
case 0x80: return &env->upsr; /* %upsr */
|
||||
default: return NULL;
|
||||
}
|
||||
target_ulong addr = env->pcsp.base + env->pcsp.index + offset;
|
||||
return cpu_ldq_le_data(env, addr);
|
||||
}
|
||||
|
||||
uint64_t helper_state_reg_read_i64(CPUE2KState *env, int idx)
|
||||
@ -44,28 +42,22 @@ uint64_t helper_state_reg_read_i64(CPUE2KState *env, int idx)
|
||||
case 0x01: return e2k_state_wd(env); /* %wd */
|
||||
case 0x0f: return e2k_state_pcsp_lo(env); /* %pcsp.lo */
|
||||
case 0x0d: return e2k_state_pcsp_hi(env); /* %pcsp.hi */
|
||||
case 0x13: return env->pcshtp; /* %pcshtp */
|
||||
case 0x13: return 0; /* %pcshtp */
|
||||
case 0x2c: return env->usd.hi; /* %usd.hi */
|
||||
case 0x2d: return env->usd.lo; /* %usd.lo */
|
||||
case 0x51: return env->crs.cr0_hi; /* %cr0.hi */
|
||||
case 0x53: return env->crs.cr0_lo; /* %cr0.lo */
|
||||
case 0x55: return env->crs.cr1.hi; /* %cr1.hi */
|
||||
case 0x57: return env->crs.cr1.lo; /* %cr1.lo */
|
||||
case 0x51: return cr_read(env, offsetof(E2KCrs, cr0_hi)); /* %cr0.hi */
|
||||
case 0x53: return cr_read(env, offsetof(E2KCrs, cr0_lo)); /* %cr0.lo */
|
||||
case 0x55: return cr_read(env, offsetof(E2KCrs, cr1.hi)); /* %cr1.hi */
|
||||
case 0x57: return cr_read(env, offsetof(E2KCrs, cr1.lo)); /* %cr1.lo */
|
||||
case 0x80: return env->upsr; /* %upsr */
|
||||
case 0x81: return env->ip; /* %ip */
|
||||
case 0x85: return env->fpcr.raw; /* %fpcr */
|
||||
case 0x86: return env->fpsr.raw; /* %fpsr */
|
||||
case 0x8a: return env->idr; /* %idr */
|
||||
case 0x90: return cpu_get_host_ticks(); /* %clkr */
|
||||
default: {
|
||||
uint64_t *p = state_reg_ptr(env, idx);
|
||||
|
||||
if (p != NULL) {
|
||||
return *p;
|
||||
} else {
|
||||
qemu_log_mask(LOG_UNIMP, "read unknown state register 0x%x\n", idx);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "read unknown state register 0x%x\n", idx);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,6 +69,9 @@ uint32_t helper_state_reg_read_i32(CPUE2KState *env, int idx)
|
||||
void helper_state_reg_write_i64(CPUE2KState *env, int idx, uint64_t val)
|
||||
{
|
||||
switch(idx) {
|
||||
case 0x80: /* %upsr */
|
||||
env->upsr = val;
|
||||
break;
|
||||
case 0x83: /* %lsr */
|
||||
env->lsr = val;
|
||||
env->lsr_lcnt = extract64(val, LSR_LCNT_OFF, LSR_LCNT_LEN);
|
||||
@ -94,23 +89,18 @@ void helper_state_reg_write_i64(CPUE2KState *env, int idx, uint64_t val)
|
||||
e2k_update_fp_status(env);
|
||||
break;
|
||||
case 0x86: env->fpsr.raw = val; break; /* %fpsr */
|
||||
default: {
|
||||
uint64_t *p = state_reg_ptr(env, idx);
|
||||
|
||||
if (p != NULL) {
|
||||
*p = val;
|
||||
} else {
|
||||
qemu_log_mask(LOG_UNIMP, "unknown state register 0x%x\n", idx);
|
||||
abort();
|
||||
}
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "rwd unknown state register 0x%x\n", idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void helper_state_reg_write_i32(CPUE2KState *env, int idx, uint32_t val)
|
||||
{
|
||||
switch (idx) {
|
||||
case 0x80: /* %upsr */
|
||||
env->upsr = deposit64(env->upsr, 0, 32, val);
|
||||
break;
|
||||
case 0x83: /* %lsr */
|
||||
env->lsr_lcnt = val;
|
||||
break;
|
||||
@ -122,18 +112,10 @@ void helper_state_reg_write_i32(CPUE2KState *env, int idx, uint32_t val)
|
||||
e2k_update_fp_status(env);
|
||||
break;
|
||||
case 0x86: env->fpsr.raw = val; break; /* %fpsr */
|
||||
default: {
|
||||
uint32_t *p = (uint32_t*) state_reg_ptr(env, idx);
|
||||
|
||||
if (p != NULL) {
|
||||
*p = val;
|
||||
} else {
|
||||
qemu_log_mask(LOG_UNIMP, "unknown state register 0x%x\n", idx);
|
||||
abort();
|
||||
}
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "rws unknown state register 0x%x\n", idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t helper_getsp(CPUE2KState *env, uint32_t src2)
|
||||
|
Loading…
Reference in New Issue
Block a user