diff options
Diffstat (limited to 'target/sparc/win_helper.c')
| -rw-r--r-- | target/sparc/win_helper.c | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/target/sparc/win_helper.c b/target/sparc/win_helper.c index 2d5b5469a9..71b3dd37e8 100644 --- a/target/sparc/win_helper.c +++ b/target/sparc/win_helper.c @@ -290,6 +290,10 @@ void helper_wrcwp(CPUSPARCState *env, target_ulong new_cwp) static inline uint64_t *get_gregset(CPUSPARCState *env, uint32_t pstate) { + if (env->def->features & CPU_FEATURE_GL) { + return env->glregs + (env->gl & 7) * 8; + } + switch (pstate) { default: trace_win_helper_gregset_error(pstate); @@ -305,14 +309,40 @@ static inline uint64_t *get_gregset(CPUSPARCState *env, uint32_t pstate) } } +static inline uint64_t *get_gl_gregset(CPUSPARCState *env, uint32_t gl) +{ + return env->glregs + (gl & 7) * 8; +} + +/* Switch global register bank */ +void cpu_gl_switch_gregs(CPUSPARCState *env, uint32_t new_gl) +{ + uint64_t *src, *dst; + src = get_gl_gregset(env, new_gl); + dst = get_gl_gregset(env, env->gl); + + if (src != dst) { + memcpy32(dst, env->gregs); + memcpy32(env->gregs, src); + } +} + +void helper_wrgl(CPUSPARCState *env, target_ulong new_gl) +{ + cpu_gl_switch_gregs(env, new_gl & 7); + env->gl = new_gl & 7; +} + void cpu_change_pstate(CPUSPARCState *env, uint32_t new_pstate) { uint32_t pstate_regs, new_pstate_regs; uint64_t *src, *dst; if (env->def->features & CPU_FEATURE_GL) { - /* PS_AG is not implemented in this case */ - new_pstate &= ~PS_AG; + /* PS_AG, IG and MG are not implemented in this case */ + new_pstate &= ~(PS_AG | PS_IG | PS_MG); + env->pstate = new_pstate; + return; } pstate_regs = env->pstate & 0xc01; @@ -366,6 +396,12 @@ void helper_done(CPUSPARCState *env) env->asi = (tsptr->tstate >> 24) & 0xff; cpu_change_pstate(env, (tsptr->tstate >> 8) & 0xf3f); cpu_put_cwp64(env, tsptr->tstate & 0xff); + if (cpu_has_hypervisor(env)) { + uint32_t new_gl = (tsptr->tstate >> 40) & 7; + env->hpstate = env->htstate[env->tl]; + cpu_gl_switch_gregs(env, new_gl); + env->gl = new_gl; + } env->tl--; trace_win_helper_done(env->tl); @@ -387,6 +423,12 @@ void helper_retry(CPUSPARCState *env) env->asi = (tsptr->tstate >> 24) & 0xff; cpu_change_pstate(env, (tsptr->tstate >> 8) & 0xf3f); cpu_put_cwp64(env, tsptr->tstate & 0xff); + if (cpu_has_hypervisor(env)) { + uint32_t new_gl = (tsptr->tstate >> 40) & 7; + env->hpstate = env->htstate[env->tl]; + cpu_gl_switch_gregs(env, new_gl); + env->gl = new_gl; + } env->tl--; trace_win_helper_retry(env->tl); |