summary refs log tree commit diff stats
path: root/target/sparc/win_helper.c
diff options
context:
space:
mode:
authorArtyom Tarasenko <atar4qemu@gmail.com>2016-06-07 18:34:49 +0200
committerArtyom Tarasenko <atar4qemu@gmail.com>2017-01-18 22:03:44 +0100
commitcbc3a6a4cc675516328a2b0d3602355d68b6302d (patch)
tree837af98184dabc03c037428d2cfd8f0bf6248df6 /target/sparc/win_helper.c
parent6e040755f12eba34d2fa3d56b18de32d63fea631 (diff)
downloadfocaccia-qemu-cbc3a6a4cc675516328a2b0d3602355d68b6302d.tar.gz
focaccia-qemu-cbc3a6a4cc675516328a2b0d3602355d68b6302d.zip
target-sparc: implement UA2005 GL register
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
Diffstat (limited to 'target/sparc/win_helper.c')
-rw-r--r--target/sparc/win_helper.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/target/sparc/win_helper.c b/target/sparc/win_helper.c
index 45ee4e643e..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;
@@ -367,7 +397,10 @@ void helper_done(CPUSPARCState *env)
     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--;
 
@@ -391,7 +424,10 @@ void helper_retry(CPUSPARCState *env)
     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--;