[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC 3/9] target-xtensa: add ICOUNT SR and debug exception
From: |
Max Filippov |
Subject: |
[Qemu-devel] [RFC 3/9] target-xtensa: add ICOUNT SR and debug exception |
Date: |
Sun, 29 Jan 2012 06:19:25 +0400 |
ICOUNT SR gets incremented on every instruction completion provided that
CINTLEVEL at the beginning of the instruction execution is lower than
ICOUNTLEVEL.
When ICOUNT would increment to 0 a debug exception is raised if
CINTLEVEL is lower than DEBUGLEVEL.
See ISA, 4.7.7.5 for more details.
Signed-off-by: Max Filippov <address@hidden>
---
target-xtensa/cpu.h | 6 +++++
target-xtensa/translate.c | 49 ++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 54 insertions(+), 1 deletions(-)
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 2875197..fbe5d15 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -142,6 +142,8 @@ enum {
DEBUGCAUSE = 233,
CCOUNT = 234,
PRID = 235,
+ ICOUNT = 236,
+ ICOUNTLEVEL = 237,
EXCVADDR = 238,
CCOMPARE = 240,
};
@@ -428,6 +430,7 @@ static inline int cpu_mmu_index(CPUState *env)
#define XTENSA_TBFLAG_EXCM 0x4
#define XTENSA_TBFLAG_LITBASE 0x8
#define XTENSA_TBFLAG_DEBUG 0x10
+#define XTENSA_TBFLAG_ICOUNT 0x20
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
@@ -447,6 +450,9 @@ static inline void cpu_get_tb_cpu_state(CPUState *env,
target_ulong *pc,
if (xtensa_get_cintlevel(env) < env->config->debug_level) {
*flags |= XTENSA_TBFLAG_DEBUG;
}
+ if (xtensa_get_cintlevel(env) < env->sregs[ICOUNTLEVEL]) {
+ *flags |= XTENSA_TBFLAG_ICOUNT;
+ }
}
}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 71fbf34..85f41a7 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -63,6 +63,8 @@ typedef struct DisasContext {
unsigned used_window;
bool debug;
+ bool icount;
+ TCGv_i32 next_icount;
} DisasContext;
static TCGv_ptr cpu_env;
@@ -127,6 +129,8 @@ static const char * const sregnames[256] = {
[DEBUGCAUSE] = "DEBUGCAUSE",
[CCOUNT] = "CCOUNT",
[PRID] = "PRID",
+ [ICOUNT] = "ICOUNT",
+ [ICOUNTLEVEL] = "ICOUNTLEVEL",
[EXCVADDR] = "EXCVADDR",
[CCOMPARE] = "CCOMPARE0",
[CCOMPARE + 1] = "CCOMPARE1",
@@ -313,10 +317,13 @@ static void gen_check_privilege(DisasContext *dc)
static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
{
tcg_gen_mov_i32(cpu_pc, dest);
+ gen_advance_ccount(dc);
+ if (dc->icount) {
+ tcg_gen_mov_i32(cpu_SR[ICOUNT], dc->next_icount);
+ }
if (dc->singlestep_enabled) {
gen_exception(dc, EXCP_DEBUG);
} else {
- gen_advance_ccount(dc);
if (slot >= 0) {
tcg_gen_goto_tb(slot);
tcg_gen_exit_tb((tcg_target_long)dc->tb + slot);
@@ -580,6 +587,22 @@ static void gen_wsr_prid(DisasContext *dc, uint32_t sr,
TCGv_i32 v)
{
}
+static void gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+ if (dc->icount) {
+ tcg_gen_mov_i32(dc->next_icount, v);
+ } else {
+ tcg_gen_mov_i32(cpu_SR[sr], v);
+ }
+}
+
+static void gen_wsr_icountlevel(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+ tcg_gen_andi_i32(cpu_SR[sr], v, 0xf);
+ /* This can change tb->flags, so exit tb */
+ gen_jumpi_check_loop_end(dc, -1);
+}
+
static void gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v)
{
uint32_t id = sr - CCOMPARE;
@@ -617,6 +640,8 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32
s)
[PS] = gen_wsr_ps,
[DEBUGCAUSE] = gen_wsr_debugcause,
[PRID] = gen_wsr_prid,
+ [ICOUNT] = gen_wsr_icount,
+ [ICOUNTLEVEL] = gen_wsr_icountlevel,
[CCOMPARE] = gen_wsr_ccompare,
[CCOMPARE + 1] = gen_wsr_ccompare,
[CCOMPARE + 2] = gen_wsr_ccompare,
@@ -2492,10 +2517,14 @@ static void gen_intermediate_code_internal(
dc.is_jmp = DISAS_NEXT;
dc.ccount_delta = 0;
dc.debug = tb->flags & XTENSA_TBFLAG_DEBUG;
+ dc.icount = tb->flags & XTENSA_TBFLAG_ICOUNT;
init_litbase(&dc);
init_sar_tracker(&dc);
reset_used_window(&dc);
+ if (dc.icount) {
+ dc.next_icount = tcg_temp_local_new_i32();
+ }
gen_icount_start();
@@ -2531,12 +2560,27 @@ static void gen_intermediate_code_internal(
gen_io_start();
}
+ if (dc.icount) {
+ int label = gen_new_label();
+
+ tcg_gen_addi_i32(dc.next_icount, cpu_SR[ICOUNT], 1);
+ tcg_gen_brcondi_i32(TCG_COND_NE, dc.next_icount, 0, label);
+ tcg_gen_mov_i32(dc.next_icount, cpu_SR[ICOUNT]);
+ if (dc.debug) {
+ gen_debug_exception(&dc, DEBUGCAUSE_IC);
+ }
+ gen_set_label(label);
+ }
+
if (dc.debug) {
gen_ibreak_check(env, &dc);
}
disas_xtensa_insn(&dc);
++insn_count;
+ if (dc.icount) {
+ tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount);
+ }
if (env->singlestep_enabled) {
tcg_gen_movi_i32(cpu_pc, dc.pc);
gen_exception(&dc, EXCP_DEBUG);
@@ -2549,6 +2593,9 @@ static void gen_intermediate_code_internal(
reset_litbase(&dc);
reset_sar_tracker(&dc);
+ if (dc.icount) {
+ tcg_temp_free(dc.next_icount);
+ }
if (tb->cflags & CF_LAST_IO) {
gen_io_end();
--
1.7.7.6
- [Qemu-devel] [RFC 0/9] target-xtensa: implement debug option, Max Filippov, 2012/01/28
- [Qemu-devel] [RFC 1/9] target-xtensa: add DEBUGCAUSE SR and configuration, Max Filippov, 2012/01/28
- [Qemu-devel] [RFC 2/9] target-xtensa: implement instruction breakpoints, Max Filippov, 2012/01/28
- [Qemu-devel] [RFC 3/9] target-xtensa: add ICOUNT SR and debug exception,
Max Filippov <=
- [Qemu-devel] [RFC 5/9] exec: fix check_watchpoint exiting cpu_loop, Max Filippov, 2012/01/28
- [Qemu-devel] [RFC 6/9] exec: let cpu_watchpoint_insert accept larger watchpoints, Max Filippov, 2012/01/28
- [Qemu-devel] [RFC 4/9] exec: add missing breaks to the watch_mem_write, Max Filippov, 2012/01/28
- [Qemu-devel] [RFC 8/9] target-xtensa: add DEBUG_SECTION to overlay tool, Max Filippov, 2012/01/28
- [Qemu-devel] [RFC 7/9] target-xtensa: add DBREAK data breakpoints, Max Filippov, 2012/01/28
- [Qemu-devel] [RFC 9/9] target-xtensa: add breakpoint tests, Max Filippov, 2012/01/28