diff --git a/linux-user/e2k/cpu_loop.c b/linux-user/e2k/cpu_loop.c index b1c7a47214..ecf941b863 100644 --- a/linux-user/e2k/cpu_loop.c +++ b/linux-user/e2k/cpu_loop.c @@ -122,6 +122,7 @@ void target_cpu_copy_regs(CPUE2KState *env, struct target_pt_regs *regs) env->psp = regs->psp; env->usd_lo = regs->usd_lo; env->usd_hi = regs->usd_hi; + env->sbr = regs->sbr; e2k_break_save_state(env); } diff --git a/linux-user/e2k/target_syscall.h b/linux-user/e2k/target_syscall.h index 5e5611e538..213f16c2de 100644 --- a/linux-user/e2k/target_syscall.h +++ b/linux-user/e2k/target_syscall.h @@ -23,7 +23,7 @@ struct target_pt_regs { /* special registers */ uint64_t wd; // Current window descriptor (WD) - uint32_t sbr; // User Stack Base Register (USBR/SBR) + uint64_t sbr; // User Stack Base Register (USBR/SBR) // SBR - contains the base (top) virtual address of the current User Stack area. // uint64_t tr; // current type register diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 6deaeb3086..dfbef86f34 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1642,6 +1642,8 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i abi_ulong stack_size = infop->start_stack - infop->stack_limit; regs->ip = infop->entry; + + regs->sbr = e2k_mmap(TARGET_PAGE_SIZE); regs->usd_hi = stack_size << 32; regs->usd_lo = (0x1800UL << 48) | infop->start_stack; diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index c46fb35f3c..3d942f12a5 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -476,6 +476,7 @@ typedef struct CPUArchState { uint64_t lsr; /* loop status register */ + uint64_t sbr; uint64_t usd_lo; uint64_t usd_hi; diff --git a/target/e2k/helper.c b/target/e2k/helper.c index 9f6c7dd8a5..8d1a88a635 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -44,8 +44,25 @@ static inline uint64_t stack_pop(CPUE2KState *env, E2KStackState *s) #define ps_push(env, value) stack_push(env, &env->psp, (value)) #define ps_pop(env) stack_pop(env, &env->psp) +/* FIXME: I don't know how exactly it should works. */ +static inline void sbr_push(CPUE2KState *env) +{ + cpu_stq_le_data(env, env->sbr, env->usd_lo); + cpu_stq_le_data(env, env->sbr + 8, env->usd_hi); + env->sbr += 16; +} + +static inline void sbr_pop(CPUE2KState *env) +{ + env->sbr -= 16; + env->usd_hi = cpu_ldq_le_data(env, env->sbr + 8); + env->usd_lo = cpu_ldq_le_data(env, env->sbr); +} + static void proc_chain_save(CPUE2KState *env, int wbs) { + sbr_push(env); + env->pshtp.index += wbs * 2; env->cr1.wbs = wbs; @@ -81,6 +98,8 @@ static inline void proc_chain_restore(CPUE2KState *env) env->wd.fx = env->cr1.wfx; env->pshtp.index -= wbs * 2; + + sbr_pop(env); } static inline void ps_spill(CPUE2KState *env, bool force, bool force_fx)