From c50d7778b8f1102691dd66f8718b017268228120 Mon Sep 17 00:00:00 2001 From: Greg Onufer Date: Wed, 26 Apr 2017 21:48:45 -0700 Subject: [PATCH 1/4] Fix size of SPARC64 fprs register Some of the code was treating it as 32-bit, some as 64-bit. When qemu is run on a little-endian host that sort of works, the relevant 32-bits just happens to be in the right place. On a big-endian host that places the relevant bits in the wrong place, the register contains zeros. --- target/sparc/translate.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 655060cd9ac..e2c4f43cf3b 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -54,7 +54,8 @@ static TCGv cpu_tbr; #endif static TCGv cpu_cond; #ifdef TARGET_SPARC64 -static TCGv_i32 cpu_xcc, cpu_fprs; +static TCGv_i32 cpu_xcc; +static TCGv cpu_fprs; static TCGv cpu_gsr; static TCGv cpu_tick_cmpr, cpu_stick_cmpr, cpu_hstick_cmpr; static TCGv cpu_hintp, cpu_htba, cpu_hver, cpu_ssr, cpu_ver; @@ -156,7 +157,7 @@ static inline void gen_update_fprs_dirty(DisasContext *dc, int rd) we can avoid setting it again. */ if (!(dc->fprs_dirty & bit)) { dc->fprs_dirty |= bit; - tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit); + tcg_gen_ori_tl(cpu_fprs, cpu_fprs, bit); } #endif } @@ -3406,8 +3407,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } break; case 0x6: /* V9 rdfprs */ - tcg_gen_ext_i32_tl(cpu_dst, cpu_fprs); - gen_store_gpr(dc, rd, cpu_dst); + gen_store_gpr(dc, rd, cpu_fprs); break; case 0xf: /* V9 membar */ break; /* no effect */ @@ -4320,8 +4320,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) dc->is_br = 1; break; case 0x6: /* V9 wrfprs */ - tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); - tcg_gen_trunc_tl_i32(cpu_fprs, cpu_tmp0); + tcg_gen_xor_tl(cpu_fprs, cpu_src1, cpu_src2); dc->fprs_dirty = 0; save_state(dc); gen_op_next_insn(); @@ -5867,7 +5866,6 @@ void gen_intermediate_code_init(CPUSPARCState *env) static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = { #ifdef TARGET_SPARC64 { &cpu_xcc, offsetof(CPUSPARCState, xcc), "xcc" }, - { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" }, #else { &cpu_wim, offsetof(CPUSPARCState, wim), "wim" }, #endif @@ -5877,6 +5875,7 @@ void gen_intermediate_code_init(CPUSPARCState *env) static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { #ifdef TARGET_SPARC64 + { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" }, { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" }, { &cpu_tick_cmpr, offsetof(CPUSPARCState, tick_cmpr), "tick_cmpr" }, { &cpu_stick_cmpr, offsetof(CPUSPARCState, stick_cmpr), "stick_cmpr" }, From 04558cfbecab8c82067d59b66fcbe31d0d97985f Mon Sep 17 00:00:00 2001 From: Greg Onufer Date: Fri, 5 May 2017 17:20:30 -0700 Subject: [PATCH 2/4] Warm reset != XIR reset --- hw/sparc64/sparc64.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c index b3d219c7690..082d7dc3471 100644 --- a/hw/sparc64/sparc64.c +++ b/hw/sparc64/sparc64.c @@ -185,7 +185,6 @@ static void main_cpu_reset(void *opaque) { ResetData *s = (ResetData *)opaque; CPUSPARCState *env = &s->cpu->env; - static unsigned int nr_resets; cpu_reset(CPU(s->cpu)); @@ -196,12 +195,7 @@ static void main_cpu_reset(void *opaque) env->gregs[1] = 0; /* Memory start */ env->gregs[2] = ram_size; /* Memory size */ env->gregs[3] = 0; /* Machine description XXX */ - if (nr_resets++ == 0) { - /* Power on reset */ - env->pc = s->prom_addr + 0x20ULL; - } else { - env->pc = s->prom_addr + 0x40ULL; - } + env->pc = s->prom_addr + 0x20ULL; /* reset */ env->npc = env->pc + 4; } From 785a8eff0a7b6f8ba765726338474ccf90613678 Mon Sep 17 00:00:00 2001 From: Greg Onufer Date: Tue, 2 May 2017 18:31:45 -0700 Subject: [PATCH 3/4] Raise EXCP_DEBUG in gen_goto_tb so single-step works on SPARC --- target/sparc/translate.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index e2c4f43cf3b..2291d7ba44d 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -360,6 +360,8 @@ static inline bool use_goto_tb(DisasContext *s, target_ulong pc, #endif } +static void gen_exception(DisasContext *dc, int which); + static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc, target_ulong npc) { @@ -371,6 +373,9 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, tcg_gen_exit_tb((uintptr_t)s->tb + tb_num); } else { /* jump to another page: currently not optimized */ + if (s->singlestep) { + gen_exception(s, EXCP_DEBUG); + } tcg_gen_movi_tl(cpu_pc, pc); tcg_gen_movi_tl(cpu_npc, npc); tcg_gen_exit_tb(0); From 92f32d2f1f9267f29331ef42e6dea9eb0ebcd50d Mon Sep 17 00:00:00 2001 From: Greg Onufer Date: Fri, 5 May 2017 17:22:30 -0700 Subject: [PATCH 4/4] Single-stepping over wrhpr %pstate skips following instruction The debugger would not be entered for the instruction following the wrhpr %pstate, but rather the instruction after _that_. --- target/sparc/translate.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 2291d7ba44d..c6b76dc232f 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -1122,10 +1122,12 @@ static inline void gen_mov_pc_npc(DisasContext *dc) } } -static inline void gen_op_next_insn(void) +static inline void gen_op_next_insn(DisasContext *dc) { tcg_gen_mov_tl(cpu_pc, cpu_npc); tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); + if (dc->singlestep) + gen_helper_debug(cpu_env); } static void free_compare(DisasCompare *cmp) @@ -4320,7 +4322,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) offsetof(CPUSPARCState, asi)); /* End TB to notice changed ASI. */ save_state(dc); - gen_op_next_insn(); + gen_op_next_insn(dc); tcg_gen_exit_tb(0); dc->is_br = 1; break; @@ -4328,7 +4330,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_xor_tl(cpu_fprs, cpu_src1, cpu_src2); dc->fprs_dirty = 0; save_state(dc); - gen_op_next_insn(); + gen_op_next_insn(dc); tcg_gen_exit_tb(0); dc->is_br = 1; break; @@ -4456,7 +4458,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS); dc->cc_op = CC_OP_FLAGS; save_state(dc); - gen_op_next_insn(); + gen_op_next_insn(dc); tcg_gen_exit_tb(0); dc->is_br = 1; #endif @@ -4612,7 +4614,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) offsetof(CPUSPARCState, hpstate)); save_state(dc); - gen_op_next_insn(); + gen_op_next_insn(dc); tcg_gen_exit_tb(0); dc->is_br = 1; break; @@ -5676,7 +5678,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) /* default case for non jump instructions */ if (dc->npc == DYNAMIC_PC) { dc->pc = DYNAMIC_PC; - gen_op_next_insn(); + gen_op_next_insn(dc); } else if (dc->npc == JUMP_PC) { /* we can do a static jump */ gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);