e2k: Delete top CRs from cpu state.

Signed-off-by: Denis Drakhnya <numas13@gmail.com>
This commit is contained in:
Denis Drakhnia 2021-02-12 11:15:58 +02:00 committed by Denis Drakhnia
parent 05304bd1f3
commit 5e66da5f7d
9 changed files with 208 additions and 183 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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)