Sparc64: replace tsptr with helper routine
authorIgor Kovalenko <igor.v.kovalenko@gmail.com>
Mon, 3 Aug 2009 19:15:02 +0000 (23:15 +0400)
committerBlue Swirl <blauwirbel@gmail.com>
Tue, 4 Aug 2009 20:22:10 +0000 (20:22 +0000)
tl and tsptr of members sparc64 cpu state must be changed
simultaneously to keep trap state window in sync with current
trap level. Currently translation of store to tl does not change
tsptr, which leads to corrupt trap state on corresponding
trap level.

This patch removes tsptr from sparc64 cpu state and replaces
all uses with call to helper routine.

Changes v0->v1:
- reimplemented helper routine with tcg generator
- on cpu reset trap type and pstate are populated with power-on reset
values, including tl=maxtl

Signed-off-by: igor.v.kovalenko@gmail.com
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
linux-user/main.c
target-sparc/cpu.h
target-sparc/helper.c
target-sparc/machine.c
target-sparc/op_helper.c
target-sparc/translate.c

index bc903dec0a3ee5aea7b6f06de4a5b4d8e30185e4..aa381f60d277d0b838260b663d3c71d9eaccd034 100644 (file)
@@ -962,7 +962,7 @@ void cpu_loop (CPUSPARCState *env)
                 if (trapnr == TT_DFAULT)
                     info._sifields._sigfault._addr = env->dmmuregs[4];
                 else
-                    info._sifields._sigfault._addr = env->tsptr->tpc;
+                    info._sifields._sigfault._addr = cpu_tsptr(env)->tpc;
                 queue_signal(env, info.si_signo, &info);
             }
             break;
index 490fd7b57f281d35a49670741d1277743cfb5755..2428bb292781505fc5b3a254695ccd0824ea871b 100644 (file)
@@ -49,6 +49,7 @@
 #define TT_NCP_INSN 0x24
 #define TT_TRAP     0x80
 #else
+#define TT_POWER_ON_RESET 0x01
 #define TT_TFAULT   0x08
 #define TT_CODE_ACCESS 0x0a
 #define TT_ILL_INSN 0x10
@@ -377,7 +378,6 @@ typedef struct CPUSPARCState {
 #if defined(TARGET_SPARC64)
 #define MAXTL_MAX 8
 #define MAXTL_MASK (MAXTL_MAX - 1)
-    trap_state *tsptr;
     trap_state ts[MAXTL_MAX];
     uint32_t xcc;               /* Extended integer condition codes */
     uint32_t asi;
@@ -593,6 +593,7 @@ void cpu_check_irqs(CPUSPARCState *env);
 void cpu_tick_set_count(void *opaque, uint64_t count);
 uint64_t cpu_tick_get_count(void *opaque);
 void cpu_tick_set_limit(void *opaque, uint64_t limit);
+trap_state* cpu_tsptr(CPUState* env);
 #endif
 
 static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
index 70343e30524ef6de8bcdc08e45afd4d8f0471a2e..31b61bc42f04ddb913a8a3fe87ccc37cec7ed546 100644 (file)
@@ -699,9 +699,10 @@ void cpu_reset(CPUSPARCState *env)
     env->psrps = 1;
     CC_OP = CC_OP_FLAGS;
 #ifdef TARGET_SPARC64
-    env->pstate = PS_PRIV;
+    env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
     env->hpstate = HS_PRIV;
-    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
+    env->tl = env->maxtl;
+    cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
     env->lsu = 0;
 #else
     env->mmuregs[0] &= ~(MMU_E | MMU_NF);
index 3d196eedc935460843340fe2e347c6fe9a23c0b0..c7c03b63c53fc0d0fa68741e990ee554b0497780 100644 (file)
@@ -164,7 +164,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_be32s(f, &env->asi);
     qemu_get_be32s(f, &env->pstate);
     qemu_get_be32s(f, &env->tl);
-    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
     qemu_get_be32s(f, &env->cansave);
     qemu_get_be32s(f, &env->canrestore);
     qemu_get_be32s(f, &env->otherwin);
index 0234e519ec4e81f0b600893e0c06ebbb8f94c6f6..a9558dad85e89ea5488faa5dce63165b4ae57693 100644 (file)
@@ -3311,26 +3311,28 @@ void helper_wrpstate(target_ulong new_state)
 
 void helper_done(void)
 {
-    env->pc = env->tsptr->tpc;
-    env->npc = env->tsptr->tnpc + 4;
-    PUT_CCR(env, env->tsptr->tstate >> 32);
-    env->asi = (env->tsptr->tstate >> 24) & 0xff;
-    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
-    PUT_CWP64(env, env->tsptr->tstate & 0xff);
+    trap_state* tsptr = cpu_tsptr(env);
+
+    env->pc = tsptr->tpc;
+    env->npc = tsptr->tnpc + 4;
+    PUT_CCR(env, tsptr->tstate >> 32);
+    env->asi = (tsptr->tstate >> 24) & 0xff;
+    change_pstate((tsptr->tstate >> 8) & 0xf3f);
+    PUT_CWP64(env, tsptr->tstate & 0xff);
     env->tl--;
-    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
 }
 
 void helper_retry(void)
 {
-    env->pc = env->tsptr->tpc;
-    env->npc = env->tsptr->tnpc;
-    PUT_CCR(env, env->tsptr->tstate >> 32);
-    env->asi = (env->tsptr->tstate >> 24) & 0xff;
-    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
-    PUT_CWP64(env, env->tsptr->tstate & 0xff);
+    trap_state* tsptr = cpu_tsptr(env);
+
+    env->pc = tsptr->tpc;
+    env->npc = tsptr->tnpc;
+    PUT_CCR(env, tsptr->tstate >> 32);
+    env->asi = (tsptr->tstate >> 24) & 0xff;
+    change_pstate((tsptr->tstate >> 8) & 0xf3f);
+    PUT_CWP64(env, tsptr->tstate & 0xff);
     env->tl--;
-    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
 }
 
 void helper_set_softint(uint64_t value)
@@ -3392,9 +3394,15 @@ static const char * const excp_names[0x80] = {
 };
 #endif
 
+trap_state* cpu_tsptr(CPUState* env)
+{
+    return &env->ts[env->tl & MAXTL_MASK];
+}
+
 void do_interrupt(CPUState *env)
 {
     int intno = env->exception_index;
+    trap_state* tsptr;
 
 #ifdef DEBUG_PCALL
     if (qemu_loglevel_mask(CPU_LOG_INT)) {
@@ -3451,13 +3459,14 @@ void do_interrupt(CPUState *env)
         if (env->tl < env->maxtl)
             env->tl++;
     }
-    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
-    env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
+    tsptr = cpu_tsptr(env);
+
+    tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
         ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
         GET_CWP64(env);
-    env->tsptr->tpc = env->pc;
-    env->tsptr->tnpc = env->npc;
-    env->tsptr->tt = intno;
+    tsptr->tpc = env->pc;
+    tsptr->tnpc = env->npc;
+    tsptr->tt = intno;
 
     switch (intno) {
     case TT_IVEC:
index d7894f1644f0cfb899e525ddcb6db6dd5a36d956..5ef543a1e9c5104fa4489375a475bba30b557be9 100644 (file)
@@ -1653,6 +1653,33 @@ static inline TCGv get_src2(unsigned int insn, TCGv def)
     return r_rs2;
 }
 
+#ifdef TARGET_SPARC64
+static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_ptr cpu_env)
+{
+    TCGv r_tl = tcg_temp_new();
+
+    /* load env->tl into r_tl */
+    {
+        TCGv_i32 r_tl_tmp = tcg_temp_new_i32();
+        tcg_gen_ld_i32(r_tl_tmp, cpu_env, offsetof(CPUSPARCState, tl));
+        tcg_gen_ext_i32_tl(r_tl, r_tl_tmp);
+        tcg_temp_free_i32(r_tl_tmp);
+    }
+
+    /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
+    tcg_gen_andi_tl(r_tl, r_tl, MAXTL_MASK);
+
+    /* calculate offset to current trap state from env->ts, reuse r_tl */
+    tcg_gen_muli_tl(r_tl, r_tl, sizeof (trap_state));
+    tcg_gen_addi_ptr(r_tsptr, cpu_env, offsetof(CPUState, ts));
+
+    /* tsptr = env->ts[env->tl & MAXTL_MASK] */
+    tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl);
+
+    tcg_temp_free(r_tl);
+}
+#endif
+
 #define CHECK_IU_FEATURE(dc, FEATURE)                      \
     if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE))  \
         goto illegal_insn;
@@ -1978,8 +2005,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         TCGv_ptr r_tsptr;
 
                         r_tsptr = tcg_temp_new_ptr();
-                        tcg_gen_ld_ptr(r_tsptr, cpu_env,
-                                       offsetof(CPUState, tsptr));
+                        gen_load_trap_state_at_tl(r_tsptr, cpu_env);
                         tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
                                       offsetof(trap_state, tpc));
                         tcg_temp_free_ptr(r_tsptr);
@@ -1990,8 +2016,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         TCGv_ptr r_tsptr;
 
                         r_tsptr = tcg_temp_new_ptr();
-                        tcg_gen_ld_ptr(r_tsptr, cpu_env,
-                                       offsetof(CPUState, tsptr));
+                        gen_load_trap_state_at_tl(r_tsptr, cpu_env);
                         tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
                                       offsetof(trap_state, tnpc));
                         tcg_temp_free_ptr(r_tsptr);
@@ -2002,8 +2027,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         TCGv_ptr r_tsptr;
 
                         r_tsptr = tcg_temp_new_ptr();
-                        tcg_gen_ld_ptr(r_tsptr, cpu_env,
-                                       offsetof(CPUState, tsptr));
+                        gen_load_trap_state_at_tl(r_tsptr, cpu_env);
                         tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
                                       offsetof(trap_state, tstate));
                         tcg_temp_free_ptr(r_tsptr);
@@ -2014,8 +2038,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         TCGv_ptr r_tsptr;
 
                         r_tsptr = tcg_temp_new_ptr();
-                        tcg_gen_ld_ptr(r_tsptr, cpu_env,
-                                       offsetof(CPUState, tsptr));
+                        gen_load_trap_state_at_tl(r_tsptr, cpu_env);
                         tcg_gen_ld_i32(cpu_tmp32, r_tsptr,
                                        offsetof(trap_state, tt));
                         tcg_temp_free_ptr(r_tsptr);
@@ -3271,8 +3294,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                     TCGv_ptr r_tsptr;
 
                                     r_tsptr = tcg_temp_new_ptr();
-                                    tcg_gen_ld_ptr(r_tsptr, cpu_env,
-                                                   offsetof(CPUState, tsptr));
+                                    gen_load_trap_state_at_tl(r_tsptr, cpu_env);
                                     tcg_gen_st_tl(cpu_tmp0, r_tsptr,
                                                   offsetof(trap_state, tpc));
                                     tcg_temp_free_ptr(r_tsptr);
@@ -3283,8 +3305,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                     TCGv_ptr r_tsptr;
 
                                     r_tsptr = tcg_temp_new_ptr();
-                                    tcg_gen_ld_ptr(r_tsptr, cpu_env,
-                                                   offsetof(CPUState, tsptr));
+                                    gen_load_trap_state_at_tl(r_tsptr, cpu_env);
                                     tcg_gen_st_tl(cpu_tmp0, r_tsptr,
                                                   offsetof(trap_state, tnpc));
                                     tcg_temp_free_ptr(r_tsptr);
@@ -3295,8 +3316,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                     TCGv_ptr r_tsptr;
 
                                     r_tsptr = tcg_temp_new_ptr();
-                                    tcg_gen_ld_ptr(r_tsptr, cpu_env,
-                                                   offsetof(CPUState, tsptr));
+                                    gen_load_trap_state_at_tl(r_tsptr, cpu_env);
                                     tcg_gen_st_tl(cpu_tmp0, r_tsptr,
                                                   offsetof(trap_state,
                                                            tstate));
@@ -3308,8 +3328,7 @@ static void disas_sparc_insn(DisasContext * dc)
                                     TCGv_ptr r_tsptr;
 
                                     r_tsptr = tcg_temp_new_ptr();
-                                    tcg_gen_ld_ptr(r_tsptr, cpu_env,
-                                                   offsetof(CPUState, tsptr));
+                                    gen_load_trap_state_at_tl(r_tsptr, cpu_env);
                                     tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
                                     tcg_gen_st_i32(cpu_tmp32, r_tsptr,
                                                    offsetof(trap_state, tt));