e2k: signals: Save and restore more state.
Signed-off-by: Denis Drakhnya <numas13@gmail.com>
This commit is contained in:
parent
1d0e52b6a0
commit
ba89b350dc
|
@ -23,6 +23,7 @@
|
||||||
#include "user-internals.h"
|
#include "user-internals.h"
|
||||||
#include "signal-common.h"
|
#include "signal-common.h"
|
||||||
#include "linux-user/trace.h"
|
#include "linux-user/trace.h"
|
||||||
|
#include "target/e2k/helper-tcg.h"
|
||||||
|
|
||||||
#define MAX_TC_SIZE 10
|
#define MAX_TC_SIZE 10
|
||||||
|
|
||||||
|
@ -106,17 +107,18 @@ struct target_sigframe {
|
||||||
struct target_ucontext uc;
|
struct target_ucontext uc;
|
||||||
// TODO: ucontext_prot
|
// TODO: ucontext_prot
|
||||||
};
|
};
|
||||||
target_sigset_t saved_set;
|
|
||||||
|
|
||||||
// FIXME: find where AAU state is saved
|
/* FIXME: move this data to TaskState? */
|
||||||
E2KAauState aau;
|
E2KAauState aau;
|
||||||
|
uint64_t lsr;
|
||||||
|
uint64_t lsr_lcnt;
|
||||||
|
// FIXME: according to ABI only 16-31 must be saved
|
||||||
|
E2KReg gregs[16];
|
||||||
|
uint8_t gtags[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
|
#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
|
||||||
|
|
||||||
void helper_signal_frame(CPUE2KState *env, int wbs, target_ulong ret_ip);
|
|
||||||
void helper_signal_return(CPUE2KState *env);
|
|
||||||
|
|
||||||
static abi_long setup_sigcontext(CPUE2KState *env,
|
static abi_long setup_sigcontext(CPUE2KState *env,
|
||||||
struct target_sigcontext *sc, struct target_extra_ucontext *extra)
|
struct target_sigcontext *sc, struct target_extra_ucontext *extra)
|
||||||
{
|
{
|
||||||
|
@ -203,7 +205,7 @@ static void target_setup_frame(int sig, struct target_sigaction *ka,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* save current frame */
|
/* save current frame */
|
||||||
helper_signal_frame(env, env->wd.size, env->ip);
|
e2k_proc_call(env, env->wd.size, env->ip, false);
|
||||||
|
|
||||||
frame_addr = get_sigframe(ka, env, sizeof(*frame));
|
frame_addr = get_sigframe(ka, env, sizeof(*frame));
|
||||||
trace_user_setup_rt_frame(env, frame_addr);
|
trace_user_setup_rt_frame(env, frame_addr);
|
||||||
|
@ -213,8 +215,16 @@ static void target_setup_frame(int sig, struct target_sigaction *ka,
|
||||||
if (setup_ucontext(&frame->uc, env)) {
|
if (setup_ucontext(&frame->uc, env)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
copy_to_user((uintptr_t) &frame->uc.uc_sigmask, set, sizeof(*set));
|
copy_to_user(frame_addr + offsetof(struct target_sigframe, uc.uc_sigmask),
|
||||||
copy_to_user((uintptr_t) &frame->aau, &env->aau, sizeof(env->aau));
|
set, sizeof(*set));
|
||||||
|
copy_to_user(frame_addr + offsetof(struct target_sigframe, aau),
|
||||||
|
&env->aau, sizeof(env->aau));
|
||||||
|
__put_user(env_lsr_get(env), &frame->lsr);
|
||||||
|
__put_user(env->lsr_lcnt, &frame->lsr_lcnt);
|
||||||
|
copy_to_user(frame_addr + offsetof(struct target_sigframe, gregs),
|
||||||
|
&env->regs[E2K_NR_COUNT + 16], 16 * sizeof(E2KReg));
|
||||||
|
copy_to_user(frame_addr + offsetof(struct target_sigframe, gtags),
|
||||||
|
&env->tags[E2K_NR_COUNT + 16], 16);
|
||||||
|
|
||||||
if (ka->sa_flags & TARGET_SA_RESTORER) {
|
if (ka->sa_flags & TARGET_SA_RESTORER) {
|
||||||
// TODO: sa_restorer?
|
// TODO: sa_restorer?
|
||||||
|
@ -224,13 +234,11 @@ static void target_setup_frame(int sig, struct target_sigaction *ka,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fake kernel frame */
|
/* fake kernel frame */
|
||||||
env->regs[0].lo = frame_addr;
|
env->wd.size = 0;
|
||||||
env->tags[0] = E2K_TAG_NUMBER64;
|
|
||||||
env->wd.size = 2;
|
|
||||||
env->wd.psize = 0;
|
env->wd.psize = 0;
|
||||||
env->usd.size = env->sbr - frame_addr;
|
env->usd.size = env->sbr - frame_addr;
|
||||||
env->usd.base = frame_addr;
|
env->usd.base = frame_addr;
|
||||||
helper_signal_frame(env, 2, E2K_SIGRET_ADDR);
|
e2k_proc_call(env, 0, E2K_SIGRET_ADDR, false);
|
||||||
|
|
||||||
env->ip = ka->_sa_handler;
|
env->ip = ka->_sa_handler;
|
||||||
env->regs[0].lo = sig;
|
env->regs[0].lo = sig;
|
||||||
|
@ -245,10 +253,6 @@ static void target_setup_frame(int sig, struct target_sigaction *ka,
|
||||||
env->tags[2] = E2K_TAG_NUMBER64;
|
env->tags[2] = E2K_TAG_NUMBER64;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env->is_bp) {
|
|
||||||
e2k_proc_call(env, env->wd.size, env->ip, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock_user_struct(frame, frame_addr, 1);
|
unlock_user_struct(frame, frame_addr, 1);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -274,8 +278,6 @@ static abi_long target_restore_sigframe(CPUE2KState *env,
|
||||||
__get_user(env->ctprs[1].raw, &frame->uc.uc_extra.ctpr2);
|
__get_user(env->ctprs[1].raw, &frame->uc.uc_extra.ctpr2);
|
||||||
__get_user(env->ctprs[2].raw, &frame->uc.uc_extra.ctpr3);
|
__get_user(env->ctprs[2].raw, &frame->uc.uc_extra.ctpr3);
|
||||||
|
|
||||||
copy_from_user(&env->aau, (uintptr_t) &frame->aau, sizeof(env->aau));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,8 +305,8 @@ long do_rt_sigreturn(CPUE2KState *env)
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
|
|
||||||
/* restore fake kernel frame */
|
/* restore fake kernel frame */
|
||||||
helper_signal_return(env);
|
e2k_proc_return(env, false);
|
||||||
frame_addr = env->regs[0].lo;
|
frame_addr = env->usd.base;
|
||||||
|
|
||||||
trace_user_do_rt_sigreturn(env, frame_addr);
|
trace_user_do_rt_sigreturn(env, frame_addr);
|
||||||
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
|
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
|
||||||
|
@ -317,6 +319,14 @@ long do_rt_sigreturn(CPUE2KState *env)
|
||||||
if (target_restore_sigframe(env, frame)) {
|
if (target_restore_sigframe(env, frame)) {
|
||||||
goto badframe;
|
goto badframe;
|
||||||
}
|
}
|
||||||
|
copy_from_user(&env->aau, frame_addr
|
||||||
|
+ offsetof(struct target_sigframe, aau), sizeof(env->aau));
|
||||||
|
__get_user(env->lsr, &frame->lsr);
|
||||||
|
__get_user(env->lsr_lcnt, &frame->lsr_lcnt);
|
||||||
|
copy_from_user(&env->regs[E2K_NR_COUNT + 16], frame_addr
|
||||||
|
+ offsetof(struct target_sigframe, gregs), 16 * sizeof(E2KReg));
|
||||||
|
copy_from_user(&env->tags[E2K_NR_COUNT + 16], frame_addr
|
||||||
|
+ offsetof(struct target_sigframe, gtags), 16);
|
||||||
|
|
||||||
if (do_sigaltstack(frame_addr +
|
if (do_sigaltstack(frame_addr +
|
||||||
offsetof(struct target_sigframe, uc.uc_stack),
|
offsetof(struct target_sigframe, uc.uc_stack),
|
||||||
|
@ -325,7 +335,8 @@ long do_rt_sigreturn(CPUE2KState *env)
|
||||||
goto badframe;
|
goto badframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
env->ip = E2K_SIGRET_ADDR;
|
/* restore user */
|
||||||
|
e2k_proc_return(env, false);
|
||||||
|
|
||||||
unlock_user_struct(frame, frame_addr, 0);
|
unlock_user_struct(frame, frame_addr, 0);
|
||||||
return -QEMU_ESIGRETURN;
|
return -QEMU_ESIGRETURN;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "helper-tcg.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "qemu/qemu-print.h"
|
#include "qemu/qemu-print.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
|
@ -136,7 +137,7 @@ static const struct e2k_def_t e2k_defs[] = {
|
||||||
|
|
||||||
static inline void cpu_dump_state_br(CPUE2KState *env, FILE *f, int flags)
|
static inline void cpu_dump_state_br(CPUE2KState *env, FILE *f, int flags)
|
||||||
{
|
{
|
||||||
uint32_t br = e2k_state_br(env);
|
uint32_t br = env_br_get(env);
|
||||||
E2KBnState *bn = &env->bn;
|
E2KBnState *bn = &env->bn;
|
||||||
E2KBpState *bp = &env->bp;
|
E2KBpState *bp = &env->bp;
|
||||||
|
|
||||||
|
@ -156,10 +157,10 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||||
|
|
||||||
qemu_fprintf(f, " ip = " TARGET_FMT_lx "\n", env->ip);
|
qemu_fprintf(f, " ip = " TARGET_FMT_lx "\n", env->ip);
|
||||||
qemu_fprintf(f, " pregs = 0x%016lx\n", env->pregs);
|
qemu_fprintf(f, " pregs = 0x%016lx\n", env->pregs);
|
||||||
qemu_fprintf(f, " pcsp_lo = 0x%016lx\n", e2k_state_pcsp_lo(env));
|
qemu_fprintf(f, " pcsp_lo = 0x%016lx\n", env_pcsp_lo_get(env));
|
||||||
qemu_fprintf(f, " pcsp_hi = 0x%016lx\n", e2k_state_pcsp_hi(env));
|
qemu_fprintf(f, " pcsp_hi = 0x%016lx\n", env_pcsp_hi_get(env));
|
||||||
qemu_fprintf(f, " psp_lo = 0x%016lx\n", e2k_state_psp_lo(env));
|
qemu_fprintf(f, " psp_lo = 0x%016lx\n", env_psp_lo_get(env));
|
||||||
qemu_fprintf(f, " psp_hi = 0x%016lx\n", e2k_state_psp_hi(env));
|
qemu_fprintf(f, " psp_hi = 0x%016lx\n", env_psp_hi_get(env));
|
||||||
qemu_fprintf(f, " usd_lo = 0x%016lx\n", env->usd.lo);
|
qemu_fprintf(f, " usd_lo = 0x%016lx\n", env->usd.lo);
|
||||||
qemu_fprintf(f, " usd_hi = 0x%016lx\n", env->usd.hi);
|
qemu_fprintf(f, " usd_hi = 0x%016lx\n", env->usd.hi);
|
||||||
qemu_fprintf(f, " lsr = 0x%016lx\n", env->lsr);
|
qemu_fprintf(f, " lsr = 0x%016lx\n", env->lsr);
|
||||||
|
|
|
@ -841,81 +841,6 @@ void e2k_proc_return(CPUE2KState *env, bool force_fx);
|
||||||
#define cpu_signal_handler e2k_cpu_signal_handler
|
#define cpu_signal_handler e2k_cpu_signal_handler
|
||||||
#define cpu_list e2k_cpu_list
|
#define cpu_list e2k_cpu_list
|
||||||
|
|
||||||
static inline uint64_t e2k_state_desc_lo(E2KStackState *desc)
|
|
||||||
{
|
|
||||||
uint64_t lo = 0;
|
|
||||||
|
|
||||||
lo = deposit64(lo, DESC_LO_BASE_OFF, DESC_LO_BASE_LEN,
|
|
||||||
(uint64_t) desc->base);
|
|
||||||
lo = deposit64(lo, DESC_LO_READ_OFF, 1, desc->is_readable);
|
|
||||||
lo = deposit64(lo, DESC_LO_WRITE_OFF, 1, desc->is_writable);
|
|
||||||
|
|
||||||
return lo;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint64_t e2k_state_desc_hi(E2KStackState *env)
|
|
||||||
{
|
|
||||||
uint64_t hi = 0;
|
|
||||||
|
|
||||||
hi = deposit64(hi, DESC_HI_IND_OFF, DESC_HI_IND_LEN, env->index);
|
|
||||||
hi = deposit64(hi, DESC_HI_SIZE_OFF, DESC_HI_SIZE_OFF, env->size);
|
|
||||||
|
|
||||||
return hi;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define e2k_state_pcsp_lo(env) e2k_state_desc_lo(&(env)->pcsp)
|
|
||||||
#define e2k_state_pcsp_hi(env) e2k_state_desc_hi(&(env)->pcsp)
|
|
||||||
#define e2k_state_psp_lo(env) e2k_state_desc_lo(&(env)->psp)
|
|
||||||
#define e2k_state_psp_hi(env) e2k_state_desc_hi(&(env)->psp)
|
|
||||||
|
|
||||||
static inline uint64_t e2k_state_wd(CPUE2KState *env)
|
|
||||||
{
|
|
||||||
E2KWdState *wd = &env->wd;
|
|
||||||
uint64_t ret = 0;
|
|
||||||
|
|
||||||
ret = deposit64(ret, WD_SIZE_OFF, WD_SIZE_LEN, wd->size * 8);
|
|
||||||
ret = deposit64(ret, WD_PSIZE_OFF, WD_PSIZE_LEN, wd->psize * 8);
|
|
||||||
ret = deposit64(ret, WD_FX_OFF, 1, wd->fx);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void e2k_state_wd_set(CPUE2KState *env, uint64_t raw)
|
|
||||||
{
|
|
||||||
env->wd.size = extract64(raw, WD_SIZE_OFF, WD_SIZE_LEN) / 8;
|
|
||||||
env->wd.psize = extract64(raw, WD_PSIZE_OFF, WD_PSIZE_LEN) / 8;
|
|
||||||
env->wd.fx = extract64(raw, WD_FX_OFF, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t e2k_state_br(CPUE2KState *env)
|
|
||||||
{
|
|
||||||
E2KBnState *bn = &env->bn;
|
|
||||||
E2KBpState *bp = &env->bp;
|
|
||||||
uint32_t ret = 0;
|
|
||||||
|
|
||||||
ret = deposit32(ret, BR_RBS_OFF, BR_RBS_LEN, bn->base / 2);
|
|
||||||
ret = deposit32(ret, BR_RSZ_OFF, BR_RSZ_LEN, bn->size / 2 - 1);
|
|
||||||
ret = deposit32(ret, BR_RCUR_OFF, BR_RCUR_LEN, bn->cur / 2);
|
|
||||||
|
|
||||||
ret = deposit32(ret, BR_PSZ_OFF, BR_PSZ_LEN, bp->size - 1);
|
|
||||||
ret = deposit32(ret, BR_PCUR_OFF, BR_PCUR_LEN, bp->cur);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void e2k_state_br_set(CPUE2KState *env, uint32_t br)
|
|
||||||
{
|
|
||||||
E2KBnState *bn = &env->bn;
|
|
||||||
E2KBpState *bp = &env->bp;
|
|
||||||
|
|
||||||
bn->base = extract32(br, BR_RBS_OFF, BR_RBS_LEN) * 2;
|
|
||||||
bn->size = extract32(br, BR_RSZ_OFF, BR_RSZ_LEN) * 2 + 2;
|
|
||||||
bn->cur = extract32(br, BR_RCUR_OFF, BR_RCUR_LEN) * 2;
|
|
||||||
|
|
||||||
bp->size = extract32(br, BR_PSZ_OFF, BR_PSZ_LEN) + 1;
|
|
||||||
bp->cur = extract32(br, BR_PCUR_OFF, BR_PCUR_LEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "exec/cpu-all.h"
|
#include "exec/cpu-all.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "helper-tcg.h"
|
||||||
#include "exec/gdbstub.h"
|
#include "exec/gdbstub.h"
|
||||||
|
|
||||||
/* TODO: reverse engineer e2k-linux-gdb register ids */
|
/* TODO: reverse engineer e2k-linux-gdb register ids */
|
||||||
|
@ -65,8 +66,8 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||||
case 46: return gdb_get_reg64(mem_buf, 0); // usbr
|
case 46: return gdb_get_reg64(mem_buf, 0); // usbr
|
||||||
case 47: return gdb_get_reg64(mem_buf, env->usd.lo); // usd_lo
|
case 47: return gdb_get_reg64(mem_buf, env->usd.lo); // usd_lo
|
||||||
case 48: return gdb_get_reg64(mem_buf, env->usd.hi); // usd_hi
|
case 48: return gdb_get_reg64(mem_buf, env->usd.hi); // usd_hi
|
||||||
case 49: return gdb_get_reg64(mem_buf, e2k_state_psp_lo(env)); // psp_lo
|
case 49: return gdb_get_reg64(mem_buf, env_psp_lo_get(env)); // psp_lo
|
||||||
case 50: return gdb_get_reg64(mem_buf, e2k_state_psp_hi(env)); // psp_hi
|
case 50: return gdb_get_reg64(mem_buf, env_psp_hi_get(env)); // psp_hi
|
||||||
case 51: return gdb_get_reg64(mem_buf, 0); // pshtp
|
case 51: return gdb_get_reg64(mem_buf, 0); // pshtp
|
||||||
case 52: return gdb_get_reg64(mem_buf, env->pregs); // pregs
|
case 52: return gdb_get_reg64(mem_buf, env->pregs); // pregs
|
||||||
case 53: return gdb_get_reg64(mem_buf, env->ip); // ip
|
case 53: return gdb_get_reg64(mem_buf, env->ip); // ip
|
||||||
|
@ -79,8 +80,8 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||||
return gdb_get_reg64(mem_buf, cr1_hi);
|
return gdb_get_reg64(mem_buf, cr1_hi);
|
||||||
}
|
}
|
||||||
case 56: return gdb_get_reg64(mem_buf, 0); // cwd
|
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 57: return gdb_get_reg64(mem_buf, env_pcsp_lo_get(env)); // pcsp_lo
|
||||||
case 58: return gdb_get_reg64(mem_buf, e2k_state_pcsp_hi(env)); // pcsp_hi
|
case 58: return gdb_get_reg64(mem_buf, env_pcsp_hi_get(env)); // pcsp_hi
|
||||||
case 59: return gdb_get_reg64(mem_buf, 0); // pcshtp
|
case 59: return gdb_get_reg64(mem_buf, 0); // pcshtp
|
||||||
case 60: return gdb_get_reg64(mem_buf, 0); // cud_lo
|
case 60: return gdb_get_reg64(mem_buf, 0); // cud_lo
|
||||||
case 61: return gdb_get_reg64(mem_buf, 0); // cud_hi
|
case 61: return gdb_get_reg64(mem_buf, 0); // cud_hi
|
||||||
|
@ -175,7 +176,7 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||||
case 331: return gdb_get_reg64(mem_buf, 0); // dtcr
|
case 331: return gdb_get_reg64(mem_buf, 0); // dtcr
|
||||||
case 332: return gdb_get_reg64(mem_buf, 0); // dtarf
|
case 332: return gdb_get_reg64(mem_buf, 0); // dtarf
|
||||||
case 333: return gdb_get_reg64(mem_buf, 0); // dtart
|
case 333: return gdb_get_reg64(mem_buf, 0); // dtart
|
||||||
case 334: return gdb_get_reg64(mem_buf, e2k_state_wd(env)); // wd
|
case 334: return gdb_get_reg64(mem_buf, env_wd_get(env)); // wd
|
||||||
case 335: return gdb_get_reg64(mem_buf, 0); // unk
|
case 335: return gdb_get_reg64(mem_buf, 0); // unk
|
||||||
case 336: return gdb_get_reg64(mem_buf, 0); // bgr
|
case 336: return gdb_get_reg64(mem_buf, 0); // bgr
|
||||||
case 337: return gdb_get_reg64(mem_buf, 0); // unk
|
case 337: return gdb_get_reg64(mem_buf, 0); // unk
|
||||||
|
|
|
@ -39,4 +39,102 @@ void G_NORETURN raise_exception(CPUE2KState *env, int exception_index);
|
||||||
void G_NORETURN raise_exception_ra(CPUE2KState *env, int exception_index,
|
void G_NORETURN raise_exception_ra(CPUE2KState *env, int exception_index,
|
||||||
uintptr_t retaddr);
|
uintptr_t retaddr);
|
||||||
|
|
||||||
|
static inline uint64_t stack_desc_lo(E2KStackState *desc)
|
||||||
|
{
|
||||||
|
uint64_t lo = 0;
|
||||||
|
|
||||||
|
lo = deposit64(lo, DESC_LO_BASE_OFF, DESC_LO_BASE_LEN,
|
||||||
|
(uint64_t) desc->base);
|
||||||
|
lo = deposit64(lo, DESC_LO_READ_OFF, 1, desc->is_readable);
|
||||||
|
lo = deposit64(lo, DESC_LO_WRITE_OFF, 1, desc->is_writable);
|
||||||
|
|
||||||
|
return lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t stack_desc_hi(E2KStackState *env)
|
||||||
|
{
|
||||||
|
uint64_t hi = 0;
|
||||||
|
|
||||||
|
hi = deposit64(hi, DESC_HI_IND_OFF, DESC_HI_IND_LEN, env->index);
|
||||||
|
hi = deposit64(hi, DESC_HI_SIZE_OFF, DESC_HI_SIZE_OFF, env->size);
|
||||||
|
|
||||||
|
return hi;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define env_pcsp_lo_get(env) stack_desc_lo(&(env)->pcsp)
|
||||||
|
#define env_pcsp_hi_get(env) stack_desc_hi(&(env)->pcsp)
|
||||||
|
#define env_psp_lo_get(env) stack_desc_lo(&(env)->psp)
|
||||||
|
#define env_psp_hi_get(env) stack_desc_hi(&(env)->psp)
|
||||||
|
|
||||||
|
static inline uint64_t env_wd_get(CPUE2KState *env)
|
||||||
|
{
|
||||||
|
E2KWdState *wd = &env->wd;
|
||||||
|
uint64_t ret = 0;
|
||||||
|
|
||||||
|
ret = deposit64(ret, WD_SIZE_OFF, WD_SIZE_LEN, wd->size * 8);
|
||||||
|
ret = deposit64(ret, WD_PSIZE_OFF, WD_PSIZE_LEN, wd->psize * 8);
|
||||||
|
ret = deposit64(ret, WD_FX_OFF, 1, wd->fx);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void env_wd_set(CPUE2KState *env, uint64_t raw)
|
||||||
|
{
|
||||||
|
env->wd.size = extract64(raw, WD_SIZE_OFF, WD_SIZE_LEN) / 8;
|
||||||
|
env->wd.psize = extract64(raw, WD_PSIZE_OFF, WD_PSIZE_LEN) / 8;
|
||||||
|
env->wd.fx = extract64(raw, WD_FX_OFF, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t env_br_get(CPUE2KState *env)
|
||||||
|
{
|
||||||
|
E2KBnState *bn = &env->bn;
|
||||||
|
E2KBpState *bp = &env->bp;
|
||||||
|
uint32_t ret = 0;
|
||||||
|
|
||||||
|
ret = deposit32(ret, BR_RBS_OFF, BR_RBS_LEN, bn->base / 2);
|
||||||
|
ret = deposit32(ret, BR_RSZ_OFF, BR_RSZ_LEN, bn->size / 2 - 1);
|
||||||
|
ret = deposit32(ret, BR_RCUR_OFF, BR_RCUR_LEN, bn->cur / 2);
|
||||||
|
|
||||||
|
ret = deposit32(ret, BR_PSZ_OFF, BR_PSZ_LEN, bp->size - 1);
|
||||||
|
ret = deposit32(ret, BR_PCUR_OFF, BR_PCUR_LEN, bp->cur);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void env_br_set(CPUE2KState *env, uint32_t br)
|
||||||
|
{
|
||||||
|
E2KBnState *bn = &env->bn;
|
||||||
|
E2KBpState *bp = &env->bp;
|
||||||
|
|
||||||
|
bn->base = extract32(br, BR_RBS_OFF, BR_RBS_LEN) * 2;
|
||||||
|
bn->size = extract32(br, BR_RSZ_OFF, BR_RSZ_LEN) * 2 + 2;
|
||||||
|
bn->cur = extract32(br, BR_RCUR_OFF, BR_RCUR_LEN) * 2;
|
||||||
|
|
||||||
|
bp->size = extract32(br, BR_PSZ_OFF, BR_PSZ_LEN) + 1;
|
||||||
|
bp->cur = extract32(br, BR_PCUR_OFF, BR_PCUR_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t env_lsr_get(CPUE2KState *env)
|
||||||
|
{
|
||||||
|
uint64_t lsr = env->lsr;
|
||||||
|
lsr = deposit64(lsr, LSR_LCNT_OFF, LSR_LCNT_LEN, env->lsr_lcnt);
|
||||||
|
lsr = deposit64(lsr, LSR_ECNT_OFF, LSR_ECNT_LEN, env->lsr_ecnt);
|
||||||
|
lsr = deposit64(lsr, LSR_VLC_OFF, 1, env->lsr_vlc);
|
||||||
|
lsr = deposit64(lsr, LSR_OVER_OFF, 1, env->lsr_over);
|
||||||
|
lsr = deposit64(lsr, LSR_PCNT_OFF, LSR_PCNT_LEN, env->lsr_pcnt);
|
||||||
|
lsr = deposit64(lsr, LSR_STRMD_OFF, LSR_STRMD_LEN, env->lsr_strmd);
|
||||||
|
return lsr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void env_lsr_set(CPUE2KState *env, uint64_t val)
|
||||||
|
{
|
||||||
|
env->lsr = val;
|
||||||
|
env->lsr_lcnt = extract64(val, LSR_LCNT_OFF, LSR_LCNT_LEN);
|
||||||
|
env->lsr_ecnt = extract64(val, LSR_ECNT_OFF, LSR_ECNT_LEN);
|
||||||
|
env->lsr_vlc = extract64(val, LSR_VLC_OFF, 1);
|
||||||
|
env->lsr_over = extract64(val, LSR_OVER_OFF, 1);
|
||||||
|
env->lsr_pcnt = extract64(val, LSR_PCNT_OFF, LSR_PCNT_LEN);
|
||||||
|
env->lsr_strmd = extract64(val, LSR_STRMD_OFF, LSR_STRMD_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* E2K_HELPER_TCG_H */
|
#endif /* E2K_HELPER_TCG_H */
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
#include "qemu/host-utils.h"
|
#include "qemu/host-utils.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
|
|
||||||
void helper_signal_frame(CPUE2KState *env, int wbs, target_ulong ret_ip);
|
|
||||||
|
|
||||||
static inline void reset_ctprs(CPUE2KState *env)
|
static inline void reset_ctprs(CPUE2KState *env)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
@ -166,7 +164,7 @@ void e2k_proc_call(CPUE2KState *env, int base, target_ulong ret_ip,
|
||||||
crs.cr1.wpsz = env->wd.psize / 2;
|
crs.cr1.wpsz = env->wd.psize / 2;
|
||||||
crs.cr1.wfx = env->wd.fx;
|
crs.cr1.wfx = env->wd.fx;
|
||||||
crs.cr1.wdbl = env->wdbl;
|
crs.cr1.wdbl = env->wdbl;
|
||||||
crs.cr1.br = e2k_state_br(env);
|
crs.cr1.br = env_br_get(env);
|
||||||
crs.cr1.ussz = env->usd.size >> 4;
|
crs.cr1.ussz = env->usd.size >> 4;
|
||||||
|
|
||||||
pcs_push(env, &crs);
|
pcs_push(env, &crs);
|
||||||
|
@ -189,7 +187,7 @@ void e2k_proc_return(CPUE2KState *env, bool force_fx)
|
||||||
|
|
||||||
env->pregs = crs.cr0_lo;
|
env->pregs = crs.cr0_lo;
|
||||||
env->ip = crs.cr0_hi & ~7;
|
env->ip = crs.cr0_hi & ~7;
|
||||||
e2k_state_br_set(env, crs.cr1.br);
|
env_br_set(env, crs.cr1.br);
|
||||||
env->wd.size = env->wd.psize + base;
|
env->wd.size = env->wd.psize + base;
|
||||||
env->wd.psize = crs.cr1.wpsz * 2;
|
env->wd.psize = crs.cr1.wpsz * 2;
|
||||||
env->wd.fx = crs.cr1.wfx;
|
env->wd.fx = crs.cr1.wfx;
|
||||||
|
@ -198,16 +196,6 @@ void e2k_proc_return(CPUE2KState *env, bool force_fx)
|
||||||
env->usd.base = env->sbr - env->usd.size;
|
env->usd.base = env->sbr - env->usd.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HELPER(signal_frame)(CPUE2KState *env, int wd_size, target_ulong ret_ip)
|
|
||||||
{
|
|
||||||
e2k_proc_call(env, wd_size, ret_ip, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HELPER(signal_return)(CPUE2KState *env)
|
|
||||||
{
|
|
||||||
e2k_proc_return(env, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void do_call(CPUE2KState *env, int wbs, target_ulong ret_ip)
|
static inline void do_call(CPUE2KState *env, int wbs, target_ulong ret_ip)
|
||||||
{
|
{
|
||||||
e2k_proc_call(env, wbs * 2, ret_ip, false);
|
e2k_proc_call(env, wbs * 2, ret_ip, false);
|
||||||
|
|
|
@ -15,7 +15,6 @@ DEF_HELPER_1(expand_stacks, void, env)
|
||||||
DEF_HELPER_4(call, void, env, i64, int, tl)
|
DEF_HELPER_4(call, void, env, i64, int, tl)
|
||||||
DEF_HELPER_2(prep_return, i64, env, int)
|
DEF_HELPER_2(prep_return, i64, env, int)
|
||||||
DEF_HELPER_1(return, void, env)
|
DEF_HELPER_1(return, void, env)
|
||||||
DEF_HELPER_1(signal_return, void, env)
|
|
||||||
|
|
||||||
DEF_HELPER_4(setwd, void, env, int, int, int)
|
DEF_HELPER_4(setwd, void, env, int, int, int)
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "helper-tcg.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "qemu/host-utils.h"
|
#include "qemu/host-utils.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
|
@ -38,11 +39,11 @@ static uint64_t cr_read(CPUE2KState *env, size_t offset)
|
||||||
uint64_t HELPER(rrd)(CPUE2KState *env, int idx)
|
uint64_t HELPER(rrd)(CPUE2KState *env, int idx)
|
||||||
{
|
{
|
||||||
switch (idx) {
|
switch (idx) {
|
||||||
case 0x01: return e2k_state_wd(env); /* %wd */
|
case 0x01: return env_wd_get(env); /* %wd */
|
||||||
case 0x07: return e2k_state_psp_hi(env); /* %psp.hi */
|
case 0x07: return env_psp_hi_get(env); /* %psp.hi */
|
||||||
case 0x09: return e2k_state_psp_lo(env); /* %psp.lo */
|
case 0x09: return env_psp_lo_get(env); /* %psp.lo */
|
||||||
case 0x0d: return e2k_state_pcsp_hi(env); /* %pcsp.hi */
|
case 0x0d: return env_pcsp_hi_get(env); /* %pcsp.hi */
|
||||||
case 0x0f: return e2k_state_pcsp_lo(env); /* %pcsp.lo */
|
case 0x0f: return env_pcsp_lo_get(env); /* %pcsp.lo */
|
||||||
case 0x13: return 0; /* %pcshtp */
|
case 0x13: return 0; /* %pcshtp */
|
||||||
case 0x2c: return env->usd.hi; /* %usd.hi */
|
case 0x2c: return env->usd.hi; /* %usd.hi */
|
||||||
case 0x2d: return env->usd.lo; /* %usd.lo */
|
case 0x2d: return env->usd.lo; /* %usd.lo */
|
||||||
|
@ -52,17 +53,7 @@ uint64_t HELPER(rrd)(CPUE2KState *env, int idx)
|
||||||
case 0x57: return cr_read(env, offsetof(E2KCrs, cr1.lo)); /* %cr1.lo */
|
case 0x57: return cr_read(env, offsetof(E2KCrs, cr1.lo)); /* %cr1.lo */
|
||||||
case 0x80: return env->upsr; /* %upsr */
|
case 0x80: return env->upsr; /* %upsr */
|
||||||
case 0x81: return env->ip; /* %ip */
|
case 0x81: return env->ip; /* %ip */
|
||||||
case 0x83: /* %lsr */
|
case 0x83: return env_lsr_get(env); /* %lsr */
|
||||||
{
|
|
||||||
uint64_t lsr = env->lsr;
|
|
||||||
lsr = deposit64(lsr, LSR_LCNT_OFF, LSR_LCNT_LEN, env->lsr_lcnt);
|
|
||||||
lsr = deposit64(lsr, LSR_ECNT_OFF, LSR_ECNT_LEN, env->lsr_ecnt);
|
|
||||||
lsr = deposit64(lsr, LSR_VLC_OFF, 1, env->lsr_vlc);
|
|
||||||
lsr = deposit64(lsr, LSR_OVER_OFF, 1, env->lsr_over);
|
|
||||||
lsr = deposit64(lsr, LSR_PCNT_OFF, LSR_PCNT_LEN, env->lsr_pcnt);
|
|
||||||
lsr = deposit64(lsr, LSR_STRMD_OFF, LSR_STRMD_LEN, env->lsr_strmd);
|
|
||||||
return lsr;
|
|
||||||
}
|
|
||||||
case 0x84: return env->pfpfr.raw; /* %pfpfr */
|
case 0x84: return env->pfpfr.raw; /* %pfpfr */
|
||||||
case 0x85: return env->fpcr.raw; /* %fpcr */
|
case 0x85: return env->fpcr.raw; /* %fpcr */
|
||||||
case 0x86: return env->fpsr.raw; /* %fpsr */
|
case 0x86: return env->fpsr.raw; /* %fpsr */
|
||||||
|
@ -82,13 +73,7 @@ void HELPER(rwd)(CPUE2KState *env, int idx, uint64_t val)
|
||||||
env->upsr = val;
|
env->upsr = val;
|
||||||
break;
|
break;
|
||||||
case 0x83: /* %lsr */
|
case 0x83: /* %lsr */
|
||||||
env->lsr = val;
|
env_lsr_set(env, val);
|
||||||
env->lsr_lcnt = extract64(val, LSR_LCNT_OFF, LSR_LCNT_LEN);
|
|
||||||
env->lsr_ecnt = extract64(val, LSR_ECNT_OFF, LSR_ECNT_LEN);
|
|
||||||
env->lsr_vlc = extract64(val, LSR_VLC_OFF, 1);
|
|
||||||
env->lsr_over = extract64(val, LSR_OVER_OFF, 1);
|
|
||||||
env->lsr_pcnt = extract64(val, LSR_PCNT_OFF, LSR_PCNT_LEN);
|
|
||||||
env->lsr_strmd = extract64(val, LSR_STRMD_OFF, LSR_STRMD_LEN);
|
|
||||||
break;
|
break;
|
||||||
case 0x84: /* %pfpfr */
|
case 0x84: /* %pfpfr */
|
||||||
env->pfpfr.raw = val;
|
env->pfpfr.raw = val;
|
||||||
|
|
|
@ -1407,7 +1407,7 @@ static int64_t get_literal(DisasContext *ctx, uint8_t arg)
|
||||||
if (!ctx->bundle.lts_present[i + 1]) {
|
if (!ctx->bundle.lts_present[i + 1]) {
|
||||||
gen_tr_excp_illopc(ctx);
|
gen_tr_excp_illopc(ctx);
|
||||||
}
|
}
|
||||||
lit = *(uint64_t *) &ctx->bundle.lts[i];
|
lit = ((uint64_t) ctx->bundle.lts[i + 1] << 32) | ctx->bundle.lts[i];
|
||||||
} else {
|
} else {
|
||||||
gen_tr_excp_illopc(ctx);
|
gen_tr_excp_illopc(ctx);
|
||||||
}
|
}
|
||||||
|
@ -7658,11 +7658,6 @@ static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs)
|
||||||
tcg_temp_free_i32(t0);
|
tcg_temp_free_i32(t0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E2K_SIGRET_ADDR:
|
|
||||||
/* fake return from signal handler */
|
|
||||||
gen_helper_signal_return(cpu_env);
|
|
||||||
tcg_gen_exit_tb(NULL, TB_EXIT_IDX0);
|
|
||||||
break;
|
|
||||||
#endif /* CONFIG_USER_ONLY */
|
#endif /* CONFIG_USER_ONLY */
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue