diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2012-01-29 05:28:21 +0400 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2012-02-20 20:07:12 +0400 |
commit | f14c4b5fb1e2509ad738afe491c099a84ca80749 (patch) | |
tree | ea29f0d42d72e406272c7b6854c3bf1b24413fd1 /target-xtensa/translate.c | |
parent | 0dc23828f1487a3e587f42a0630dd6879ab8f2bb (diff) | |
download | hqemu-f14c4b5fb1e2509ad738afe491c099a84ca80749.zip hqemu-f14c4b5fb1e2509ad738afe491c099a84ca80749.tar.gz |
target-xtensa: add DBREAK data breakpoints
Add DBREAKA/DBREAKC SRs and implement DBREAK breakpoints as debug
watchpoints.
This implementation is not fully compliant to ISA: when a breakpoint is
set to an unmapped/inaccessible memory address it generates TLB/memory
protection exception instead of debug exception.
See ISA, 4.7.7.3, 4.7.7.6 for more details.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'target-xtensa/translate.c')
-rw-r--r-- | target-xtensa/translate.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 3bf880f..9e8e20a 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -98,6 +98,10 @@ static const char * const sregnames[256] = { [IBREAKENABLE] = "IBREAKENABLE", [IBREAKA] = "IBREAKA0", [IBREAKA + 1] = "IBREAKA1", + [DBREAKA] = "DBREAKA0", + [DBREAKA + 1] = "DBREAKA1", + [DBREAKC] = "DBREAKC0", + [DBREAKC + 1] = "DBREAKC1", [EPC1] = "EPC1", [EPC1 + 1] = "EPC2", [EPC1 + 2] = "EPC3", @@ -536,6 +540,28 @@ static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) } } +static void gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) +{ + unsigned id = sr - DBREAKA; + + if (id < dc->config->ndbreak) { + TCGv_i32 tmp = tcg_const_i32(id); + gen_helper_wsr_dbreaka(tmp, v); + tcg_temp_free(tmp); + } +} + +static void gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v) +{ + unsigned id = sr - DBREAKC; + + if (id < dc->config->ndbreak) { + TCGv_i32 tmp = tcg_const_i32(id); + gen_helper_wsr_dbreakc(tmp, v); + tcg_temp_free(tmp); + } +} + static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_andi_i32(cpu_SR[sr], v, @@ -634,6 +660,10 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s) [IBREAKENABLE] = gen_wsr_ibreakenable, [IBREAKA] = gen_wsr_ibreaka, [IBREAKA + 1] = gen_wsr_ibreaka, + [DBREAKA] = gen_wsr_dbreaka, + [DBREAKA + 1] = gen_wsr_dbreaka, + [DBREAKC] = gen_wsr_dbreakc, + [DBREAKC + 1] = gen_wsr_dbreakc, [INTSET] = gen_wsr_intset, [INTCLEAR] = gen_wsr_intclear, [INTENABLE] = gen_wsr_intenable, |