diff --git a/linux-user/main.c b/linux-user/main.c index bc903dec0a3ee5aea7b6f06de4a5b4d8e30185e4..aa381f60d277d0b838260b663d3c71d9eaccd034 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -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; diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 490fd7b57f281d35a49670741d1277743cfb5755..2428bb292781505fc5b3a254695ccd0824ea871b 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -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) diff --git a/target-sparc/helper.c b/target-sparc/helper.c index 70343e30524ef6de8bcdc08e45afd4d8f0471a2e..31b61bc42f04ddb913a8a3fe87ccc37cec7ed546 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -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); diff --git a/target-sparc/machine.c b/target-sparc/machine.c index 3d196eedc935460843340fe2e347c6fe9a23c0b0..c7c03b63c53fc0d0fa68741e990ee554b0497780 100644 --- a/target-sparc/machine.c +++ b/target-sparc/machine.c @@ -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); diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 0234e519ec4e81f0b600893e0c06ebbb8f94c6f6..a9558dad85e89ea5488faa5dce63165b4ae57693 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -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: diff --git a/target-sparc/translate.c b/target-sparc/translate.c index d7894f1644f0cfb899e525ddcb6db6dd5a36d956..5ef543a1e9c5104fa4489375a475bba30b557be9 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -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));