diff options
author | edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-10-07 22:48:41 +0000 |
---|---|---|
committer | edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-10-07 22:48:41 +0000 |
commit | a1aebcb8e68a90b9fe130aef6b2667e4369574b4 (patch) | |
tree | 34bc04c2812ed7a197fbbe7992736691306eb384 | |
parent | 890b165890e2d0eede89800a760d5341c5e7ff06 (diff) |
CRIS: Fix brk 8 and add S-flag emulation.
* break 8 sets ERP to the current insn.
* First shot at S flag single-stepping.
* Make it easier to use the local disasm.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5445 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | cpu-exec.c | 2 | ||||
-rw-r--r-- | target-cris/helper.c | 2 | ||||
-rw-r--r-- | target-cris/helper.h | 1 | ||||
-rw-r--r-- | target-cris/op_helper.c | 8 | ||||
-rw-r--r-- | target-cris/translate.c | 56 |
5 files changed, 51 insertions, 18 deletions
diff --git a/cpu-exec.c b/cpu-exec.c index 8637e2a3cf..6d4dcdd168 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -220,7 +220,7 @@ static inline TranslationBlock *tb_find_fast(void) cs_base = 0; pc = env->pc; #elif defined(TARGET_CRIS) - flags = env->pregs[PR_CCS] & (P_FLAG | U_FLAG | X_FLAG); + flags = env->pregs[PR_CCS] & (S_FLAG | P_FLAG | U_FLAG | X_FLAG); flags |= env->dslot; cs_base = 0; pc = env->pc; diff --git a/target-cris/helper.c b/target-cris/helper.c index 4f5ffba1ec..7770403ace 100644 --- a/target-cris/helper.c +++ b/target-cris/helper.c @@ -119,7 +119,7 @@ void do_interrupt(CPUState *env) /* These exceptions are genereated by the core itself. ERP should point to the insn following the brk. */ ex_vec = env->trap_vector; - env->pregs[PR_ERP] = env->pc + 2; + env->pregs[PR_ERP] = env->pc; break; case EXCP_NMI: diff --git a/target-cris/helper.h b/target-cris/helper.h index 517e8f8bf5..3a8e2094c9 100644 --- a/target-cris/helper.h +++ b/target-cris/helper.h @@ -2,6 +2,7 @@ void TCG_HELPER_PROTO helper_raise_exception(uint32_t index); void TCG_HELPER_PROTO helper_tlb_flush_pid(uint32_t pid); +void TCG_HELPER_PROTO helper_spc_write(uint32_t pid); void TCG_HELPER_PROTO helper_dump(uint32_t a0, uint32_t a1, uint32_t a2); void TCG_HELPER_PROTO helper_rfe(void); void TCG_HELPER_PROTO helper_rfn(void); diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index bcdaf7e951..49bcebc4b9 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -97,6 +97,14 @@ void helper_tlb_flush_pid(uint32_t pid) #endif } +void helper_spc_write(uint32_t new_spc) +{ +#if !defined(CONFIG_USER_ONLY) + tlb_flush_page(env, env->pregs[PR_SPC]); + tlb_flush_page(env, new_spc); +#endif +} + void helper_dump(uint32_t a0, uint32_t a1, uint32_t a2) { (fprintf(logfile, "%s: a0=%x a1=%x\n", __func__, a0, a1)); diff --git a/target-cris/translate.c b/target-cris/translate.c index 8b8ab8326b..9a3e7fd476 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -41,7 +41,7 @@ #define DISAS_CRIS 0 #if DISAS_CRIS -#define DIS(x) x +#define DIS(x) if (loglevel & CPU_LOG_TB_IN_ASM) x #else #define DIS(x) #endif @@ -218,6 +218,8 @@ static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn) else { if (r == PR_PID) tcg_gen_helper_0_1(helper_tlb_flush_pid, tn); + if (dc->tb_flags & S_FLAG && r == PR_SPC) + tcg_gen_helper_0_1(helper_spc_write, tn); else if (r == PR_CCS) dc->cpustate_changed = 1; tcg_gen_mov_tl(cpu_PR[r], tn); @@ -1377,8 +1379,6 @@ static int dec_prep_move_m(DisasContext *dc, int s_ext, int memsize, } else imm = ldl_code(dc->pc + 2); - DIS(fprintf (logfile, "imm=%x rd=%d sext=%d ms=%d\n", - imm, rd, s_ext, memsize)); tcg_gen_movi_tl(dst, imm); dc->postinc = 0; } else { @@ -2063,7 +2063,7 @@ static unsigned int dec_setclrf(DisasContext *dc) /* User space is not allowed to touch these. Silently ignore. */ if (dc->tb_flags & U_FLAG) { - flags &= ~(I_FLAG | U_FLAG); + flags &= ~(S_FLAG | I_FLAG | U_FLAG); } if (flags & X_FLAG) { @@ -2083,6 +2083,9 @@ static unsigned int dec_setclrf(DisasContext *dc) dc->cpustate_changed = 1; } } + if (flags & S_FLAG) { + dc->cpustate_changed = 1; + } /* Simply decode the flags. */ @@ -2784,9 +2787,6 @@ static unsigned int dec_basc_im(DisasContext *dc) static unsigned int dec_rfe_etc(DisasContext *dc) { - DIS(fprintf (logfile, "rfe_etc opc=%x pc=0x%x op1=%d op2=%d\n", - dc->opcode, dc->pc, dc->op1, dc->op2)); - cris_cc_mask(dc, 0); if (dc->op2 == 15) /* ignore halt. */ @@ -2795,19 +2795,29 @@ static unsigned int dec_rfe_etc(DisasContext *dc) switch (dc->op2 & 7) { case 2: /* rfe. */ + DIS(fprintf(logfile, "rfe\n")); cris_evaluate_flags(dc); tcg_gen_helper_0_0(helper_rfe); dc->is_jmp = DISAS_UPDATE; break; case 5: /* rfn. */ + DIS(fprintf(logfile, "rfn\n")); cris_evaluate_flags(dc); tcg_gen_helper_0_0(helper_rfn); dc->is_jmp = DISAS_UPDATE; break; case 6: + DIS(fprintf(logfile, "break %d\n", dc->op1)); + cris_evaluate_flags (dc); /* break. */ - tcg_gen_movi_tl(env_pc, dc->pc); + if (dc->op1 == 8) { + /* TODO: Find out whats special with brk8. */ + tcg_gen_movi_tl(env_pc, dc->pc); + } + else + tcg_gen_movi_tl(env_pc, dc->pc + 2); + /* Breaks start at 16 in the exception vector. */ t_gen_mov_env_TN(trap_vector, tcg_const_tl(dc->op1 + 16)); @@ -2984,6 +2994,22 @@ cris_decoder(DisasContext *dc) } } +#if defined(CONFIG_USER_ONLY) + /* Single-stepping ? */ + if (dc->tb_flags & S_FLAG) { + int l1; + + l1 = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_NE, + cpu_PR[PR_SPC], tcg_const_tl(dc->pc), l1); + /* We treat SPC as a break with an odd trap vector. */ + cris_evaluate_flags (dc); + t_gen_mov_env_TN(trap_vector, tcg_const_tl(3)); + tcg_gen_movi_tl(env_pc, dc->pc + insn_len); + t_gen_raise_exception(EXCP_BREAK); + gen_set_label(l1); + } +#endif return insn_len; } @@ -3080,7 +3106,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, dc->cc_size_uptodate = -1; /* Decode TB flags. */ - dc->tb_flags = tb->flags & (P_FLAG | U_FLAG | X_FLAG); + dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG | X_FLAG); dc->delayed_branch = !!(tb->flags & 7); if (dc->delayed_branch) dc->jmp = JMP_INDIRECT; @@ -3108,7 +3134,8 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, env->regs[10], env->regs[11], env->regs[12], env->regs[13], env->regs[14], env->regs[15]); - + fprintf(logfile, "--------------\n"); + fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); } next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; @@ -3139,10 +3166,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, } /* Pretty disas. */ - DIS(fprintf(logfile, "%x ", dc->pc)); - if (search_pc) { - DIS(fprintf(logfile, "%x ", dc->pc)); - } + DIS(fprintf(logfile, "%8.8x:\t", dc->pc)); if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) gen_io_start(); @@ -3241,14 +3265,14 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, } #ifdef DEBUG_DISAS +#if !DISAS_CRIS if (loglevel & CPU_LOG_TB_IN_ASM) { - fprintf(logfile, "--------------\n"); - fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); target_disas(logfile, pc_start, dc->pc - pc_start, 0); fprintf(logfile, "\nisize=%d osize=%zd\n", dc->pc - pc_start, gen_opc_ptr - gen_opc_buf); } #endif +#endif } void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb) |