diff mbox

[13/24] target-alpha: Swap shadow registers moving to/from PALmode.

Message ID 1303225501-12778-14-git-send-email-rth@twiddle.net
State New
Headers show

Commit Message

Richard Henderson April 19, 2011, 3:04 p.m. UTC
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-alpha/cpu.h       |    1 +
 target-alpha/helper.c    |   37 ++++++++++++++++++++++++++++++++++++-
 target-alpha/op_helper.c |    5 ++++-
 3 files changed, 41 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index dec8b26..f6549f9 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -380,6 +380,7 @@  void do_interrupt (CPUState *env);
 
 uint64_t cpu_alpha_load_fpcr (CPUState *env);
 void cpu_alpha_store_fpcr (CPUState *env, uint64_t val);
+extern void swap_shadow_regs(CPUState *env);
 
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index d5923e0..ce5f257 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -168,6 +168,38 @@  int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
     return 1;
 }
 #else
+void swap_shadow_regs(CPUState *env)
+{
+    uint64_t i0, i1, i2, i3, i4, i5, i6, i7;
+
+    i0 = env->ir[8];
+    i1 = env->ir[9];
+    i2 = env->ir[10];
+    i3 = env->ir[11];
+    i4 = env->ir[12];
+    i5 = env->ir[13];
+    i6 = env->ir[14];
+    i7 = env->ir[25];
+
+    env->ir[8]  = env->shadow[0];
+    env->ir[9]  = env->shadow[1];
+    env->ir[10] = env->shadow[2];
+    env->ir[11] = env->shadow[3];
+    env->ir[12] = env->shadow[4];
+    env->ir[13] = env->shadow[5];
+    env->ir[14] = env->shadow[6];
+    env->ir[25] = env->shadow[7];
+
+    env->shadow[0] = i0;
+    env->shadow[1] = i1;
+    env->shadow[2] = i2;
+    env->shadow[3] = i3;
+    env->shadow[4] = i4;
+    env->shadow[5] = i5;
+    env->shadow[6] = i6;
+    env->shadow[7] = i7;
+}
+
 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
 {
     return -1;
@@ -284,7 +316,10 @@  void do_interrupt (CPUState *env)
     env->pc = env->palbr + i;
 
     /* Switch to PALmode.  */
-    env->pal_mode = 1;
+    if (!env->pal_mode) {
+        env->pal_mode = 1;
+        swap_shadow_regs(env);
+    }
 #endif /* !USER_ONLY */
 }
 
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 9c19c96..d502bca 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1166,9 +1166,12 @@  uint64_t helper_cvtqg (uint64_t a)
 void helper_hw_ret (uint64_t a)
 {
     env->pc = a & ~3;
-    env->pal_mode = a & 1;
     env->intr_flag = 0;
     env->lock_addr = -1;
+    if ((a & 1) == 0) {
+        env->pal_mode = 0;
+        swap_shadow_regs(env);
+    }
 }
 #endif