1 | This is fixing #404 ("windows xp boot takes much longer...") | 1 | This is fixing #404 ("windows xp boot takes much longer...") |
---|---|---|---|
2 | and several other similar reports. | 2 | and several other similar reports. |
3 | 3 | ||
4 | For v2, all prerequisites and 7 of the patches from v1 with | 4 | Changes for v5: |
5 | reviews are now upstream. | 5 | * Include missing hunk in tb_gen_code, as noted in reply to v4. |
6 | * Remove helper_check_breakpoints from target/arm/. | ||
7 | * Reorg cflags_for_breakpoints into check_for_breakpoints; | ||
8 | reorg cpu_exec to use a break instead of a longjmp. | ||
9 | * Move singlestep_enabled check from cflags_for_breakpoints | ||
10 | to curr_cflags, which makes cpu_exec_step_atomic cleaner. | ||
6 | 11 | ||
7 | Mark Cave-Ayland reported success with WinXP with v1, with | 12 | Changes for v4: |
8 | this patch set being even faster than b55f54bc~1. Which was | 13 | * Issue breakpoints directly from cflags_for_breakpoints. |
9 | a bit of a surprise, but I'll take it. It means that it's | 14 | Do not generate code for a TB beginning with a BP at all. |
10 | probably not worth making the breakpoint detection scheme | 15 | * Drop the problematic TranslatorOps.breakpoint_check hook entirely. |
11 | any more complicated. | ||
12 | 16 | ||
13 | I'd still like some more feedback. Given this is fixing a | 17 | Changes for v3: |
14 | regression from qemu 5.2 I feel comfortable delaying this | 18 | * Map CF_COUNT_MASK == 0 -> TCG_MAX_INSNS. |
15 | past soft freeze, but not past hard freeze on the 20th. | 19 | * Split out *_breakpoint_check fixes for avr, mips, riscv. |
20 | |||
21 | Changes for v2: | ||
22 | * All prerequisites and 7 of the patches from v1 with are merged. | ||
23 | |||
24 | Patches lacking review are all new: | ||
25 | 03-target-alpha-Drop-goto_tb-path-in-gen_call_pal.patch | ||
26 | 08-hw-core-Introduce-TCGCPUOps.debug_check_breakpoin.patch | ||
27 | 09-target-arm-Implement-debug_check_breakpoint.patch | ||
28 | 10-target-i386-Implement-debug_check_breakpoint.patch | ||
29 | 11-accel-tcg-Merge-tb_find-into-its-only-caller.patch | ||
30 | 12-accel-tcg-Move-breakpoint-recognition-outside-tra.patch | ||
31 | 13-accel-tcg-Remove-TranslatorOps.breakpoint_check.patch | ||
32 | 15-accel-tcg-Record-singlestep_enabled-in-tb-cflags.patch | ||
16 | 33 | ||
17 | 34 | ||
18 | r~ | 35 | r~ |
19 | 36 | ||
20 | 37 | ||
21 | Richard Henderson (10): | 38 | Richard Henderson (15): |
22 | accel/tcg: Reduce CF_COUNT_MASK to match TCG_MAX_INSNS | 39 | accel/tcg: Reduce CF_COUNT_MASK to match TCG_MAX_INSNS |
23 | accel/tcg: Move curr_cflags into cpu-exec.c | 40 | accel/tcg: Move curr_cflags into cpu-exec.c |
41 | target/alpha: Drop goto_tb path in gen_call_pal | ||
24 | accel/tcg: Add CF_NO_GOTO_TB and CF_NO_GOTO_PTR | 42 | accel/tcg: Add CF_NO_GOTO_TB and CF_NO_GOTO_PTR |
25 | accel/tcg: Drop CF_NO_GOTO_PTR from -d nochain | 43 | accel/tcg: Drop CF_NO_GOTO_PTR from -d nochain |
26 | accel/tcg: Handle -singlestep in curr_cflags | 44 | accel/tcg: Handle -singlestep in curr_cflags |
27 | accel/tcg: Use CF_NO_GOTO_{TB,PTR} in cpu_exec_step_atomic | 45 | accel/tcg: Use CF_NO_GOTO_{TB, PTR} in cpu_exec_step_atomic |
28 | accel/tcg: Move cflags lookup into tb_find | 46 | hw/core: Introduce TCGCPUOps.debug_check_breakpoint |
29 | accel/tcg: Adjust interface of TranslatorOps.breakpoint_check | 47 | target/arm: Implement debug_check_breakpoint |
48 | target/i386: Implement debug_check_breakpoint | ||
49 | accel/tcg: Merge tb_find into its only caller | ||
50 | accel/tcg: Move breakpoint recognition outside translation | ||
51 | accel/tcg: Remove TranslatorOps.breakpoint_check | ||
30 | accel/tcg: Hoist tb_cflags to a local in translator_loop | 52 | accel/tcg: Hoist tb_cflags to a local in translator_loop |
31 | accel/tcg: Encode breakpoint info into tb->cflags | 53 | accel/tcg: Record singlestep_enabled in tb->cflags |
32 | 54 | ||
33 | include/exec/exec-all.h | 30 +++++--- | 55 | include/exec/exec-all.h | 24 +++-- |
34 | include/exec/translator.h | 17 +++-- | 56 | include/exec/translator.h | 11 -- |
35 | accel/tcg/cpu-exec.c | 130 ++++++++++++++++++++++++++++------ | 57 | include/hw/core/tcg-cpu-ops.h | 6 ++ |
58 | target/arm/helper.h | 2 - | ||
59 | target/arm/internals.h | 3 + | ||
60 | accel/tcg/cpu-exec.c | 192 +++++++++++++++++++++++++--------- | ||
36 | accel/tcg/translate-all.c | 7 +- | 61 | accel/tcg/translate-all.c | 7 +- |
37 | accel/tcg/translator.c | 79 ++++++++++++++------- | 62 | accel/tcg/translator.c | 39 ++----- |
38 | cpu.c | 24 ------- | 63 | cpu.c | 24 ----- |
39 | target/alpha/translate.c | 12 +--- | 64 | target/alpha/translate.c | 31 +----- |
40 | target/arm/translate-a64.c | 14 ++-- | 65 | target/arm/cpu.c | 1 + |
41 | target/arm/translate.c | 20 +++--- | 66 | target/arm/cpu_tcg.c | 1 + |
42 | target/avr/translate.c | 6 +- | 67 | target/arm/debug_helper.c | 12 +-- |
43 | target/cris/translate.c | 14 ++-- | 68 | target/arm/translate-a64.c | 25 ----- |
44 | target/hexagon/translate.c | 13 +--- | 69 | target/arm/translate.c | 29 ----- |
45 | target/hppa/translate.c | 7 +- | 70 | target/avr/translate.c | 10 -- |
46 | target/i386/tcg/translate.c | 15 ++-- | 71 | target/cris/translate.c | 20 ---- |
47 | target/m68k/translate.c | 14 +--- | 72 | target/hexagon/translate.c | 17 --- |
48 | target/microblaze/translate.c | 14 +--- | 73 | target/hppa/translate.c | 11 -- |
49 | target/mips/tcg/translate.c | 14 ++-- | 74 | target/i386/tcg/tcg-cpu.c | 12 +++ |
50 | target/nios2/translate.c | 13 +--- | 75 | target/i386/tcg/translate.c | 28 ----- |
51 | target/openrisc/translate.c | 11 +-- | 76 | target/m68k/translate.c | 18 ---- |
52 | target/ppc/translate.c | 13 +--- | 77 | target/microblaze/translate.c | 18 ---- |
53 | target/riscv/translate.c | 11 +-- | 78 | target/mips/tcg/translate.c | 19 ---- |
54 | target/rx/translate.c | 8 +-- | 79 | target/nios2/translate.c | 27 ----- |
55 | target/s390x/translate.c | 12 ++-- | 80 | target/openrisc/translate.c | 17 --- |
56 | target/sh4/translate.c | 12 ++-- | 81 | target/ppc/translate.c | 18 ---- |
57 | target/sparc/translate.c | 9 ++- | 82 | target/riscv/translate.c | 17 --- |
58 | target/tricore/translate.c | 13 +--- | 83 | target/rx/translate.c | 14 --- |
59 | target/xtensa/translate.c | 12 ++-- | 84 | target/s390x/tcg/translate.c | 24 ----- |
60 | tcg/tcg-op.c | 28 ++++---- | 85 | target/sh4/translate.c | 18 ---- |
61 | 28 files changed, 280 insertions(+), 292 deletions(-) | 86 | target/sparc/translate.c | 17 --- |
87 | target/tricore/translate.c | 16 --- | ||
88 | target/xtensa/translate.c | 17 --- | ||
89 | tcg/tcg-op.c | 28 +++-- | ||
90 | 35 files changed, 206 insertions(+), 567 deletions(-) | ||
62 | 91 | ||
63 | -- | 92 | -- |
64 | 2.25.1 | 93 | 2.25.1 |
65 | 94 | ||
66 | 95 | diff view generated by jsdifflib |
1 | The space reserved for CF_COUNT_MASK was overly large. | 1 | The space reserved for CF_COUNT_MASK was overly large. |
---|---|---|---|
2 | Reduce to free up cflags bits and eliminate an extra test. | 2 | Reduce to free up cflags bits and eliminate an extra test. |
3 | 3 | ||
4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
5 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
6 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | Message-Id: <20210717221851.2124573-2-richard.henderson@linaro.org> | ||
5 | --- | 8 | --- |
6 | include/exec/exec-all.h | 4 +++- | 9 | include/exec/exec-all.h | 4 +++- |
7 | accel/tcg/translate-all.c | 5 ++--- | 10 | accel/tcg/translate-all.c | 5 ++--- |
8 | 2 files changed, 5 insertions(+), 4 deletions(-) | 11 | 2 files changed, 5 insertions(+), 4 deletions(-) |
9 | 12 | ||
... | ... | ||
25 | diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c | 28 | diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c |
26 | index XXXXXXX..XXXXXXX 100644 | 29 | index XXXXXXX..XXXXXXX 100644 |
27 | --- a/accel/tcg/translate-all.c | 30 | --- a/accel/tcg/translate-all.c |
28 | +++ b/accel/tcg/translate-all.c | 31 | +++ b/accel/tcg/translate-all.c |
29 | @@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu, | 32 | @@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu, |
33 | |||
34 | max_insns = cflags & CF_COUNT_MASK; | ||
30 | if (max_insns == 0) { | 35 | if (max_insns == 0) { |
31 | max_insns = CF_COUNT_MASK; | 36 | - max_insns = CF_COUNT_MASK; |
37 | - } | ||
38 | - if (max_insns > TCG_MAX_INSNS) { | ||
39 | max_insns = TCG_MAX_INSNS; | ||
32 | } | 40 | } |
33 | - if (max_insns > TCG_MAX_INSNS) { | ||
34 | - max_insns = TCG_MAX_INSNS; | ||
35 | - } | ||
36 | + QEMU_BUILD_BUG_ON(CF_COUNT_MASK + 1 != TCG_MAX_INSNS); | 41 | + QEMU_BUILD_BUG_ON(CF_COUNT_MASK + 1 != TCG_MAX_INSNS); |
37 | + | 42 | + |
38 | if (cpu->singlestep_enabled || singlestep) { | 43 | if (cpu->singlestep_enabled || singlestep) { |
39 | max_insns = 1; | 44 | max_insns = 1; |
40 | } | 45 | } |
41 | -- | 46 | -- |
42 | 2.25.1 | 47 | 2.25.1 |
43 | 48 | ||
44 | 49 | diff view generated by jsdifflib |
1 | We will shortly have more than a simple member read here, | 1 | We will shortly have more than a simple member read here, |
---|---|---|---|
2 | with stuff not necessarily exposed to exec/exec-all.h. | 2 | with stuff not necessarily exposed to exec/exec-all.h. |
3 | 3 | ||
4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
5 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
6 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
7 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
8 | Message-Id: <20210717221851.2124573-3-richard.henderson@linaro.org> | ||
5 | --- | 9 | --- |
6 | include/exec/exec-all.h | 5 +---- | 10 | include/exec/exec-all.h | 5 +---- |
7 | accel/tcg/cpu-exec.c | 5 +++++ | 11 | accel/tcg/cpu-exec.c | 5 +++++ |
8 | 2 files changed, 6 insertions(+), 4 deletions(-) | 12 | 2 files changed, 6 insertions(+), 4 deletions(-) |
9 | 13 | ||
... | ... | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | We are certain of a page crossing here, entering the | ||
2 | PALcode image, so the call to use_goto_tb that should | ||
3 | have been here will never succeed. | ||
1 | 4 | ||
5 | We are shortly going to add an assert to tcg_gen_goto_tb | ||
6 | that would trigger for this case. | ||
7 | |||
8 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
9 | --- | ||
10 | target/alpha/translate.c | 15 ++------------- | ||
11 | 1 file changed, 2 insertions(+), 13 deletions(-) | ||
12 | |||
13 | diff --git a/target/alpha/translate.c b/target/alpha/translate.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/target/alpha/translate.c | ||
16 | +++ b/target/alpha/translate.c | ||
17 | @@ -XXX,XX +XXX,XX @@ static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode) | ||
18 | ? 0x2000 + (palcode - 0x80) * 64 | ||
19 | : 0x1000 + palcode * 64); | ||
20 | |||
21 | - /* Since the destination is running in PALmode, we don't really | ||
22 | - need the page permissions check. We'll see the existence of | ||
23 | - the page when we create the TB, and we'll flush all TBs if | ||
24 | - we change the PAL base register. */ | ||
25 | - if (!ctx->base.singlestep_enabled) { | ||
26 | - tcg_gen_goto_tb(0); | ||
27 | - tcg_gen_movi_i64(cpu_pc, entry); | ||
28 | - tcg_gen_exit_tb(ctx->base.tb, 0); | ||
29 | - return DISAS_NORETURN; | ||
30 | - } else { | ||
31 | - tcg_gen_movi_i64(cpu_pc, entry); | ||
32 | - return DISAS_PC_UPDATED; | ||
33 | - } | ||
34 | + tcg_gen_movi_i64(cpu_pc, entry); | ||
35 | + return DISAS_PC_UPDATED; | ||
36 | } | ||
37 | #endif | ||
38 | } | ||
39 | -- | ||
40 | 2.25.1 | ||
41 | |||
42 | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
4 | Set bits during curr_cflags, test them in translator_use_goto_tb, | 4 | Set bits during curr_cflags, test them in translator_use_goto_tb, |
5 | assert we're not doing anything odd in tcg_gen_goto_tb. The test | 5 | assert we're not doing anything odd in tcg_gen_goto_tb. The test |
6 | in tcg_gen_exit_tb is redundant with the assert for goto_tb_issue_mask. | 6 | in tcg_gen_exit_tb is redundant with the assert for goto_tb_issue_mask. |
7 | 7 | ||
8 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 8 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
9 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
10 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
11 | Message-Id: <20210717221851.2124573-4-richard.henderson@linaro.org> | ||
9 | --- | 12 | --- |
10 | include/exec/exec-all.h | 16 +++++++++------- | 13 | include/exec/exec-all.h | 16 +++++++++------- |
11 | accel/tcg/cpu-exec.c | 8 +++++++- | 14 | accel/tcg/cpu-exec.c | 8 +++++++- |
12 | accel/tcg/translator.c | 5 +++++ | 15 | accel/tcg/translator.c | 5 +++++ |
13 | tcg/tcg-op.c | 28 ++++++++++++---------------- | 16 | tcg/tcg-op.c | 28 ++++++++++++---------------- |
... | ... | diff view generated by jsdifflib |
1 | The purpose of suppressing goto_ptr from -d nochain had been | 1 | The purpose of suppressing goto_ptr from -d nochain had been |
---|---|---|---|
2 | to return to the main loop so that -d cpu would be recognized. | 2 | to return to the main loop so that -d cpu would be recognized. |
3 | But we now include -d cpu logging in helper_lookup_tb_ptr so | 3 | But we now include -d cpu logging in helper_lookup_tb_ptr so |
4 | there is no need to exclude goto_ptr. | 4 | there is no need to exclude goto_ptr. |
5 | 5 | ||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Message-Id: <20210717221851.2124573-5-richard.henderson@linaro.org> | ||
7 | --- | 9 | --- |
8 | accel/tcg/cpu-exec.c | 2 +- | 10 | accel/tcg/cpu-exec.c | 2 +- |
9 | 1 file changed, 1 insertion(+), 1 deletion(-) | 11 | 1 file changed, 1 insertion(+), 1 deletion(-) |
10 | 12 | ||
11 | diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c | 13 | diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c |
... | ... | diff view generated by jsdifflib |
1 | Exchange the test in translator_use_goto_tb for CF_NO_GOTO_TB, | 1 | Exchange the test in translator_use_goto_tb for CF_NO_GOTO_TB, |
---|---|---|---|
2 | and the test in tb_gen_code for setting CF_COUNT_MASK to 1. | 2 | and the test in tb_gen_code for setting CF_COUNT_MASK to 1. |
3 | 3 | ||
4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
5 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
6 | Message-Id: <20210717221851.2124573-6-richard.henderson@linaro.org> | ||
5 | --- | 7 | --- |
6 | accel/tcg/cpu-exec.c | 8 +++++++- | 8 | accel/tcg/cpu-exec.c | 8 +++++++- |
7 | accel/tcg/translate-all.c | 2 +- | 9 | accel/tcg/translate-all.c | 2 +- |
8 | accel/tcg/translator.c | 2 +- | 10 | accel/tcg/translator.c | 2 +- |
9 | 3 files changed, 9 insertions(+), 3 deletions(-) | 11 | 3 files changed, 9 insertions(+), 3 deletions(-) |
... | ... | diff view generated by jsdifflib |
1 | Request that the one TB returns immediately, so that | 1 | Request that the one TB returns immediately, so that |
---|---|---|---|
2 | we release the exclusive lock as soon as possible. | 2 | we release the exclusive lock as soon as possible. |
3 | 3 | ||
4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
5 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
6 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
7 | Message-Id: <20210717221851.2124573-7-richard.henderson@linaro.org> | ||
5 | --- | 8 | --- |
6 | accel/tcg/cpu-exec.c | 11 ++++++++--- | 9 | accel/tcg/cpu-exec.c | 11 ++++++++--- |
7 | 1 file changed, 8 insertions(+), 3 deletions(-) | 10 | 1 file changed, 8 insertions(+), 3 deletions(-) |
8 | 11 | ||
9 | diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c | 12 | diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c |
... | ... | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | New hook to return true when an architectural breakpoint is | ||
2 | to be recognized and false when it should be suppressed. | ||
1 | 3 | ||
4 | First use must wait until other pieces are in place. | ||
5 | |||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
7 | --- | ||
8 | include/hw/core/tcg-cpu-ops.h | 6 ++++++ | ||
9 | 1 file changed, 6 insertions(+) | ||
10 | |||
11 | diff --git a/include/hw/core/tcg-cpu-ops.h b/include/hw/core/tcg-cpu-ops.h | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/include/hw/core/tcg-cpu-ops.h | ||
14 | +++ b/include/hw/core/tcg-cpu-ops.h | ||
15 | @@ -XXX,XX +XXX,XX @@ struct TCGCPUOps { | ||
16 | */ | ||
17 | bool (*debug_check_watchpoint)(CPUState *cpu, CPUWatchpoint *wp); | ||
18 | |||
19 | + /** | ||
20 | + * @debug_check_breakpoint: return true if the architectural | ||
21 | + * breakpoint whose PC has matched should really fire. | ||
22 | + */ | ||
23 | + bool (*debug_check_breakpoint)(CPUState *cpu); | ||
24 | + | ||
25 | /** | ||
26 | * @io_recompile_replay_branch: Callback for cpu_io_recompile. | ||
27 | * | ||
28 | -- | ||
29 | 2.25.1 | ||
30 | |||
31 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | Reuse the code at the bottom of helper_check_breakpoints, | ||
2 | which is what we currently call from *_tr_breakpoint_check. | ||
1 | 3 | ||
4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
5 | --- | ||
6 | target/arm/internals.h | 3 +++ | ||
7 | target/arm/cpu.c | 1 + | ||
8 | target/arm/cpu_tcg.c | 1 + | ||
9 | target/arm/debug_helper.c | 7 +++---- | ||
10 | 4 files changed, 8 insertions(+), 4 deletions(-) | ||
11 | |||
12 | diff --git a/target/arm/internals.h b/target/arm/internals.h | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/target/arm/internals.h | ||
15 | +++ b/target/arm/internals.h | ||
16 | @@ -XXX,XX +XXX,XX @@ void hw_breakpoint_update(ARMCPU *cpu, int n); | ||
17 | */ | ||
18 | void hw_breakpoint_update_all(ARMCPU *cpu); | ||
19 | |||
20 | +/* Callback function for checking if a breakpoint should trigger. */ | ||
21 | +bool arm_debug_check_breakpoint(CPUState *cs); | ||
22 | + | ||
23 | /* Callback function for checking if a watchpoint should trigger. */ | ||
24 | bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp); | ||
25 | |||
26 | diff --git a/target/arm/cpu.c b/target/arm/cpu.c | ||
27 | index XXXXXXX..XXXXXXX 100644 | ||
28 | --- a/target/arm/cpu.c | ||
29 | +++ b/target/arm/cpu.c | ||
30 | @@ -XXX,XX +XXX,XX @@ static const struct TCGCPUOps arm_tcg_ops = { | ||
31 | .do_unaligned_access = arm_cpu_do_unaligned_access, | ||
32 | .adjust_watchpoint_address = arm_adjust_watchpoint_address, | ||
33 | .debug_check_watchpoint = arm_debug_check_watchpoint, | ||
34 | + .debug_check_breakpoint = arm_debug_check_breakpoint, | ||
35 | #endif /* !CONFIG_USER_ONLY */ | ||
36 | }; | ||
37 | #endif /* CONFIG_TCG */ | ||
38 | diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c | ||
39 | index XXXXXXX..XXXXXXX 100644 | ||
40 | --- a/target/arm/cpu_tcg.c | ||
41 | +++ b/target/arm/cpu_tcg.c | ||
42 | @@ -XXX,XX +XXX,XX @@ static const struct TCGCPUOps arm_v7m_tcg_ops = { | ||
43 | .do_unaligned_access = arm_cpu_do_unaligned_access, | ||
44 | .adjust_watchpoint_address = arm_adjust_watchpoint_address, | ||
45 | .debug_check_watchpoint = arm_debug_check_watchpoint, | ||
46 | + .debug_check_breakpoint = arm_debug_check_breakpoint, | ||
47 | #endif /* !CONFIG_USER_ONLY */ | ||
48 | }; | ||
49 | #endif /* CONFIG_TCG */ | ||
50 | diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c | ||
51 | index XXXXXXX..XXXXXXX 100644 | ||
52 | --- a/target/arm/debug_helper.c | ||
53 | +++ b/target/arm/debug_helper.c | ||
54 | @@ -XXX,XX +XXX,XX @@ static bool check_watchpoints(ARMCPU *cpu) | ||
55 | return false; | ||
56 | } | ||
57 | |||
58 | -static bool check_breakpoints(ARMCPU *cpu) | ||
59 | +bool arm_debug_check_breakpoint(CPUState *cs) | ||
60 | { | ||
61 | + ARMCPU *cpu = ARM_CPU(cs); | ||
62 | CPUARMState *env = &cpu->env; | ||
63 | int n; | ||
64 | |||
65 | @@ -XXX,XX +XXX,XX @@ static bool check_breakpoints(ARMCPU *cpu) | ||
66 | |||
67 | void HELPER(check_breakpoints)(CPUARMState *env) | ||
68 | { | ||
69 | - ARMCPU *cpu = env_archcpu(env); | ||
70 | - | ||
71 | - if (check_breakpoints(cpu)) { | ||
72 | + if (arm_debug_check_breakpoint(env_cpu(env))) { | ||
73 | HELPER(exception_internal(env, EXCP_DEBUG)); | ||
74 | } | ||
75 | } | ||
76 | -- | ||
77 | 2.25.1 | ||
78 | |||
79 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | Return false for RF set, as we do in i386_tr_breakpoint_check. | ||
1 | 2 | ||
3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
4 | --- | ||
5 | target/i386/tcg/tcg-cpu.c | 12 ++++++++++++ | ||
6 | 1 file changed, 12 insertions(+) | ||
7 | |||
8 | diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c | ||
9 | index XXXXXXX..XXXXXXX 100644 | ||
10 | --- a/target/i386/tcg/tcg-cpu.c | ||
11 | +++ b/target/i386/tcg/tcg-cpu.c | ||
12 | @@ -XXX,XX +XXX,XX @@ static void x86_cpu_synchronize_from_tb(CPUState *cs, | ||
13 | cpu->env.eip = tb->pc - tb->cs_base; | ||
14 | } | ||
15 | |||
16 | +#ifndef CONFIG_USER_ONLY | ||
17 | +static bool x86_debug_check_breakpoint(CPUState *cs) | ||
18 | +{ | ||
19 | + X86CPU *cpu = X86_CPU(cs); | ||
20 | + CPUX86State *env = &cpu->env; | ||
21 | + | ||
22 | + /* RF disables all architectural breakpoints. */ | ||
23 | + return !(env->eflags & RF_MASK); | ||
24 | +} | ||
25 | +#endif | ||
26 | + | ||
27 | #include "hw/core/tcg-cpu-ops.h" | ||
28 | |||
29 | static const struct TCGCPUOps x86_tcg_ops = { | ||
30 | @@ -XXX,XX +XXX,XX @@ static const struct TCGCPUOps x86_tcg_ops = { | ||
31 | .tlb_fill = x86_cpu_tlb_fill, | ||
32 | #ifndef CONFIG_USER_ONLY | ||
33 | .debug_excp_handler = breakpoint_handler, | ||
34 | + .debug_check_breakpoint = x86_debug_check_breakpoint, | ||
35 | #endif /* !CONFIG_USER_ONLY */ | ||
36 | }; | ||
37 | |||
38 | -- | ||
39 | 2.25.1 | ||
40 | |||
41 | diff view generated by jsdifflib |
1 | We will shortly require the guest pc for computing cflags, | 1 | We are going to want two things: |
---|---|---|---|
2 | so move the choice just after cpu_get_tb_cpu_state. | 2 | (1) check for breakpoints will want to break out of the loop here, |
3 | (2) cflags can only be calculated with pc in hand. | ||
3 | 4 | ||
4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
5 | --- | 6 | --- |
6 | accel/tcg/cpu-exec.c | 34 +++++++++++++++++----------------- | 7 | accel/tcg/cpu-exec.c | 83 ++++++++++++++++++++++---------------------- |
7 | 1 file changed, 17 insertions(+), 17 deletions(-) | 8 | 1 file changed, 41 insertions(+), 42 deletions(-) |
8 | 9 | ||
9 | diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c | 10 | diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c |
10 | index XXXXXXX..XXXXXXX 100644 | 11 | index XXXXXXX..XXXXXXX 100644 |
11 | --- a/accel/tcg/cpu-exec.c | 12 | --- a/accel/tcg/cpu-exec.c |
12 | +++ b/accel/tcg/cpu-exec.c | 13 | +++ b/accel/tcg/cpu-exec.c |
13 | @@ -XXX,XX +XXX,XX @@ static inline void tb_add_jump(TranslationBlock *tb, int n, | 14 | @@ -XXX,XX +XXX,XX @@ static inline void tb_add_jump(TranslationBlock *tb, int n, |
14 | 15 | return; | |
15 | static inline TranslationBlock *tb_find(CPUState *cpu, | 16 | } |
16 | TranslationBlock *last_tb, | 17 | |
18 | -static inline TranslationBlock *tb_find(CPUState *cpu, | ||
19 | - TranslationBlock *last_tb, | ||
17 | - int tb_exit, uint32_t cflags) | 20 | - int tb_exit, uint32_t cflags) |
18 | + int tb_exit) | 21 | -{ |
22 | - CPUArchState *env = (CPUArchState *)cpu->env_ptr; | ||
23 | - TranslationBlock *tb; | ||
24 | - target_ulong cs_base, pc; | ||
25 | - uint32_t flags; | ||
26 | - | ||
27 | - cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); | ||
28 | - | ||
29 | - tb = tb_lookup(cpu, pc, cs_base, flags, cflags); | ||
30 | - if (tb == NULL) { | ||
31 | - mmap_lock(); | ||
32 | - tb = tb_gen_code(cpu, pc, cs_base, flags, cflags); | ||
33 | - mmap_unlock(); | ||
34 | - /* We add the TB in the virtual pc hash table for the fast lookup */ | ||
35 | - qatomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb); | ||
36 | - } | ||
37 | -#ifndef CONFIG_USER_ONLY | ||
38 | - /* We don't take care of direct jumps when address mapping changes in | ||
39 | - * system emulation. So it's not safe to make a direct jump to a TB | ||
40 | - * spanning two pages because the mapping for the second page can change. | ||
41 | - */ | ||
42 | - if (tb->page_addr[1] != -1) { | ||
43 | - last_tb = NULL; | ||
44 | - } | ||
45 | -#endif | ||
46 | - /* See if we can patch the calling TB. */ | ||
47 | - if (last_tb) { | ||
48 | - tb_add_jump(last_tb, tb_exit, tb); | ||
49 | - } | ||
50 | - return tb; | ||
51 | -} | ||
52 | - | ||
53 | static inline bool cpu_handle_halt(CPUState *cpu) | ||
19 | { | 54 | { |
20 | CPUArchState *env = (CPUArchState *)cpu->env_ptr; | 55 | if (cpu->halted) { |
21 | TranslationBlock *tb; | ||
22 | target_ulong cs_base, pc; | ||
23 | - uint32_t flags; | ||
24 | + uint32_t flags, cflags; | ||
25 | |||
26 | cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); | ||
27 | |||
28 | + /* | ||
29 | + * When requested, use an exact setting for cflags for the next | ||
30 | + * execution. This is used for icount, precise smc, and stop- | ||
31 | + * after-access watchpoints. Since this request should never | ||
32 | + * have CF_INVALID set, -1 is a convenient invalid value that | ||
33 | + * does not require tcg headers for cpu_common_reset. | ||
34 | + */ | ||
35 | + cflags = cpu->cflags_next_tb; | ||
36 | + if (cflags == -1) { | ||
37 | + cflags = curr_cflags(cpu); | ||
38 | + } else { | ||
39 | + cpu->cflags_next_tb = -1; | ||
40 | + } | ||
41 | + | ||
42 | tb = tb_lookup(cpu, pc, cs_base, flags, cflags); | ||
43 | if (tb == NULL) { | ||
44 | mmap_lock(); | ||
45 | @@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu) | 56 | @@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu) |
46 | int tb_exit = 0; | 57 | int tb_exit = 0; |
47 | 58 | ||
48 | while (!cpu_handle_interrupt(cpu, &last_tb)) { | 59 | while (!cpu_handle_interrupt(cpu, &last_tb)) { |
49 | - uint32_t cflags = cpu->cflags_next_tb; | 60 | - uint32_t cflags = cpu->cflags_next_tb; |
50 | - TranslationBlock *tb; | 61 | TranslationBlock *tb; |
51 | - | 62 | + target_ulong cs_base, pc; |
63 | + uint32_t flags, cflags; | ||
64 | |||
52 | - /* When requested, use an exact setting for cflags for the next | 65 | - /* When requested, use an exact setting for cflags for the next |
53 | - execution. This is used for icount, precise smc, and stop- | 66 | - execution. This is used for icount, precise smc, and stop- |
54 | - after-access watchpoints. Since this request should never | 67 | - after-access watchpoints. Since this request should never |
55 | - have CF_INVALID set, -1 is a convenient invalid value that | 68 | - have CF_INVALID set, -1 is a convenient invalid value that |
56 | - does not require tcg headers for cpu_common_reset. */ | 69 | - does not require tcg headers for cpu_common_reset. */ |
57 | - if (cflags == -1) { | 70 | + /* |
58 | - cflags = curr_cflags(cpu); | 71 | + * When requested, use an exact setting for cflags for the next |
59 | - } else { | 72 | + * execution. This is used for icount, precise smc, and stop- |
60 | - cpu->cflags_next_tb = -1; | 73 | + * after-access watchpoints. Since this request should never |
61 | - } | 74 | + * have CF_INVALID set, -1 is a convenient invalid value that |
62 | - | 75 | + * does not require tcg headers for cpu_common_reset. |
76 | + */ | ||
77 | + cflags = cpu->cflags_next_tb; | ||
78 | if (cflags == -1) { | ||
79 | cflags = curr_cflags(cpu); | ||
80 | } else { | ||
81 | cpu->cflags_next_tb = -1; | ||
82 | } | ||
83 | |||
63 | - tb = tb_find(cpu, last_tb, tb_exit, cflags); | 84 | - tb = tb_find(cpu, last_tb, tb_exit, cflags); |
64 | + TranslationBlock *tb = tb_find(cpu, last_tb, tb_exit); | 85 | + cpu_get_tb_cpu_state(cpu->env_ptr, &pc, &cs_base, &flags); |
86 | + | ||
87 | + tb = tb_lookup(cpu, pc, cs_base, flags, cflags); | ||
88 | + if (tb == NULL) { | ||
89 | + mmap_lock(); | ||
90 | + tb = tb_gen_code(cpu, pc, cs_base, flags, cflags); | ||
91 | + mmap_unlock(); | ||
92 | + /* | ||
93 | + * We add the TB in the virtual pc hash table | ||
94 | + * for the fast lookup | ||
95 | + */ | ||
96 | + qatomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb); | ||
97 | + } | ||
98 | + | ||
99 | +#ifndef CONFIG_USER_ONLY | ||
100 | + /* | ||
101 | + * We don't take care of direct jumps when address mapping | ||
102 | + * changes in system emulation. So it's not safe to make a | ||
103 | + * direct jump to a TB spanning two pages because the mapping | ||
104 | + * for the second page can change. | ||
105 | + */ | ||
106 | + if (tb->page_addr[1] != -1) { | ||
107 | + last_tb = NULL; | ||
108 | + } | ||
109 | +#endif | ||
110 | + /* See if we can patch the calling TB. */ | ||
111 | + if (last_tb) { | ||
112 | + tb_add_jump(last_tb, tb_exit, tb); | ||
113 | + } | ||
114 | + | ||
65 | cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit); | 115 | cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit); |
116 | + | ||
66 | /* Try to align the host and virtual clocks | 117 | /* Try to align the host and virtual clocks |
67 | if the guest is in advance */ | 118 | if the guest is in advance */ |
119 | align_clocks(&sc, cpu); | ||
68 | -- | 120 | -- |
69 | 2.25.1 | 121 | 2.25.1 |
70 | 122 | ||
71 | 123 | diff view generated by jsdifflib |
1 | Having this data in cflags means that hashing takes care | 1 | Trigger breakpoints before beginning translation of a TB |
---|---|---|---|
2 | of selecting a TB with or without exceptions built in. | 2 | that would begin with a BP. Thus we never generate code |
3 | Which means that we no longer need to flush all TBs. | 3 | for the BP at all. |
4 | 4 | ||
5 | This does require that we single-step while we're within a page | 5 | Single-step instructions within a page containing a BP so |
6 | that contains a breakpoint, so it's not yet ideal, but should be | 6 | that we are sure to check each insn for the BP as above. |
7 | an improvement over some corner-case slowdowns. | 7 | |
8 | 8 | We no longer need to flush any TBs when changing BPs. | |
9 | |||
10 | Resolves: https://gitlab.com/qemu-project/qemu/-/issues/286 | ||
9 | Resolves: https://gitlab.com/qemu-project/qemu/-/issues/404 | 11 | Resolves: https://gitlab.com/qemu-project/qemu/-/issues/404 |
12 | Resolves: https://gitlab.com/qemu-project/qemu/-/issues/489 | ||
10 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 13 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
11 | --- | 14 | --- |
12 | include/exec/exec-all.h | 7 ++++ | 15 | accel/tcg/cpu-exec.c | 78 ++++++++++++++++++++++++++++++++++++++++-- |
13 | accel/tcg/cpu-exec.c | 68 ++++++++++++++++++++++++++++++- | 16 | accel/tcg/translator.c | 24 +------------ |
14 | accel/tcg/translate-all.c | 4 -- | 17 | cpu.c | 20 ----------- |
15 | accel/tcg/translator.c | 85 +++++++++++++++++++++------------------ | 18 | 3 files changed, 76 insertions(+), 46 deletions(-) |
16 | cpu.c | 24 ----------- | 19 | |
17 | 5 files changed, 119 insertions(+), 69 deletions(-) | ||
18 | |||
19 | diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/include/exec/exec-all.h | ||
22 | +++ b/include/exec/exec-all.h | ||
23 | @@ -XXX,XX +XXX,XX @@ struct TranslationBlock { | ||
24 | #define CF_USE_ICOUNT 0x00020000 | ||
25 | #define CF_INVALID 0x00040000 /* TB is stale. Set with @jmp_lock held */ | ||
26 | #define CF_PARALLEL 0x00080000 /* Generate code for a parallel context */ | ||
27 | +#define CF_BP_MASK 0x00300000 /* See below */ | ||
28 | +#define CF_BP_SHIFT 20 | ||
29 | #define CF_CLUSTER_MASK 0xff000000 /* Top 8 bits are cluster ID */ | ||
30 | #define CF_CLUSTER_SHIFT 24 | ||
31 | |||
32 | +#define CF_BP_NONE (0 << CF_BP_SHIFT) /* TB does not interact with BPs */ | ||
33 | +#define CF_BP_SSTEP (1 << CF_BP_SHIFT) /* gdbstub single-step in effect */ | ||
34 | +#define CF_BP_GDB (2 << CF_BP_SHIFT) /* gdbstub breakpoint at tb->pc */ | ||
35 | +#define CF_BP_CPU (3 << CF_BP_SHIFT) /* arch breakpoint at tb->pc */ | ||
36 | + | ||
37 | /* Per-vCPU dynamic tracing state used to generate this TB */ | ||
38 | uint32_t trace_vcpu_dstate; | ||
39 | |||
40 | diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c | 20 | diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c |
41 | index XXXXXXX..XXXXXXX 100644 | 21 | index XXXXXXX..XXXXXXX 100644 |
42 | --- a/accel/tcg/cpu-exec.c | 22 | --- a/accel/tcg/cpu-exec.c |
43 | +++ b/accel/tcg/cpu-exec.c | 23 | +++ b/accel/tcg/cpu-exec.c |
44 | @@ -XXX,XX +XXX,XX @@ static inline void log_cpu_exec(target_ulong pc, CPUState *cpu, | 24 | @@ -XXX,XX +XXX,XX @@ static inline void log_cpu_exec(target_ulong pc, CPUState *cpu, |
45 | } | 25 | } |
46 | } | 26 | } |
47 | 27 | ||
48 | +static uint32_t cflags_for_breakpoints(CPUState *cpu, target_ulong pc, | 28 | +static bool check_for_breakpoints(CPUState *cpu, target_ulong pc, |
49 | + uint32_t cflags) | 29 | + uint32_t *cflags) |
50 | +{ | 30 | +{ |
51 | + uint32_t bflags = 0; | 31 | + CPUBreakpoint *bp; |
52 | + | 32 | + bool match_page = false; |
53 | + if (unlikely(cpu->singlestep_enabled)) { | 33 | + |
54 | + bflags = CF_BP_SSTEP; | 34 | + if (likely(QTAILQ_EMPTY(&cpu->breakpoints))) { |
55 | + } else { | 35 | + return false; |
56 | + bool match_page = false; | 36 | + } |
57 | + CPUBreakpoint *bp; | 37 | + |
58 | + | 38 | + QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { |
59 | + QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { | 39 | + /* |
60 | + /* Note exact pc matches */ | 40 | + * If we have an exact pc match, trigger the breakpoint. |
61 | + if (pc == bp->pc) { | 41 | + * Otherwise, note matches within the page. |
62 | + if (bp->flags & BP_GDB) { | 42 | + */ |
63 | + bflags = CF_BP_GDB; | 43 | + if (pc == bp->pc) { |
64 | + break; | 44 | + bool match_bp = false; |
65 | + } | 45 | + |
66 | + if (bp->flags & BP_CPU) { | 46 | + if (bp->flags & BP_GDB) { |
67 | + bflags = CF_BP_CPU; | 47 | + match_bp = true; |
68 | + break; | 48 | + } else if (bp->flags & BP_CPU) { |
69 | + } | 49 | +#ifdef CONFIG_USER_ONLY |
50 | + g_assert_not_reached(); | ||
51 | +#else | ||
52 | + CPUClass *cc = CPU_GET_CLASS(cpu); | ||
53 | + assert(cc->tcg_ops->debug_check_breakpoint); | ||
54 | + match_bp = cc->tcg_ops->debug_check_breakpoint(cpu); | ||
55 | +#endif | ||
70 | + } | 56 | + } |
71 | + /* Note page matches */ | 57 | + |
72 | + if (((pc ^ bp->pc) & TARGET_PAGE_MASK) == 0) { | 58 | + if (match_bp) { |
73 | + match_page = true; | 59 | + cpu->exception_index = EXCP_DEBUG; |
60 | + return true; | ||
74 | + } | 61 | + } |
62 | + } else if (((pc ^ bp->pc) & TARGET_PAGE_MASK) == 0) { | ||
63 | + match_page = true; | ||
75 | + } | 64 | + } |
76 | + | ||
77 | + if (likely(!bflags)) { | ||
78 | + if (likely(!match_page)) { | ||
79 | + return cflags; | ||
80 | + } | ||
81 | + | ||
82 | + /* | ||
83 | + * Within the same page as a breakpoint, single-step, | ||
84 | + * returning to helper_lookup_tb_ptr after each looking | ||
85 | + * for the actual breakpoint. | ||
86 | + * | ||
87 | + * TODO: Perhaps better to record all of the TBs associated | ||
88 | + * with a given virtual page that contains a breakpoint, and | ||
89 | + * then invalidate them when a new overlapping breakpoint is | ||
90 | + * set on the page. Non-overlapping TBs would not be | ||
91 | + * invalidated, nor would any TB need to be invalidated as | ||
92 | + * breakpoints are removed. | ||
93 | + */ | ||
94 | + bflags = CF_NO_GOTO_TB; | ||
95 | + } | ||
96 | + } | 65 | + } |
97 | + | 66 | + |
98 | + /* | 67 | + /* |
99 | + * Reduce the TB to one insn. | 68 | + * Within the same page as a breakpoint, single-step, |
100 | + * In the case of a BP hit, we will be raising an exception anyway. | 69 | + * returning to helper_lookup_tb_ptr after each looking |
101 | + * In the case of a page hit, return to helper_lookup_tb_ptr after | 70 | + * for the actual breakpoint. |
102 | + * every insn to look for the breakpoint. | 71 | + * |
72 | + * TODO: Perhaps better to record all of the TBs associated | ||
73 | + * with a given virtual page that contains a breakpoint, and | ||
74 | + * then invalidate them when a new overlapping breakpoint is | ||
75 | + * set on the page. Non-overlapping TBs would not be | ||
76 | + * invalidated, nor would any TB need to be invalidated as | ||
77 | + * breakpoints are removed. | ||
103 | + */ | 78 | + */ |
104 | + return (cflags & ~CF_COUNT_MASK) | 1 | bflags; | 79 | + if (match_page) { |
80 | + *cflags = (*cflags & ~CF_COUNT_MASK) | CF_NO_GOTO_TB | 1; | ||
81 | + } | ||
82 | + return false; | ||
105 | +} | 83 | +} |
106 | + | 84 | + |
107 | /** | 85 | /** |
108 | * helper_lookup_tb_ptr: quick check for next tb | 86 | * helper_lookup_tb_ptr: quick check for next tb |
109 | * @env: current cpu state | 87 | * @env: current cpu state |
... | ... | ||
115 | + uint32_t flags, cflags; | 93 | + uint32_t flags, cflags; |
116 | 94 | ||
117 | cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); | 95 | cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); |
118 | 96 | ||
119 | - tb = tb_lookup(cpu, pc, cs_base, flags, curr_cflags(cpu)); | 97 | - tb = tb_lookup(cpu, pc, cs_base, flags, curr_cflags(cpu)); |
120 | + cflags = cflags_for_breakpoints(cpu, pc, curr_cflags(cpu)); | 98 | + cflags = curr_cflags(cpu); |
99 | + if (check_for_breakpoints(cpu, pc, &cflags)) { | ||
100 | + cpu_loop_exit(cpu); | ||
101 | + } | ||
121 | + | 102 | + |
122 | + tb = tb_lookup(cpu, pc, cs_base, flags, cflags); | 103 | + tb = tb_lookup(cpu, pc, cs_base, flags, cflags); |
123 | if (tb == NULL) { | 104 | if (tb == NULL) { |
124 | return tcg_code_gen_epilogue; | 105 | return tcg_code_gen_epilogue; |
125 | } | 106 | } |
126 | @@ -XXX,XX +XXX,XX @@ void cpu_exec_step_atomic(CPUState *cpu) | 107 | @@ -XXX,XX +XXX,XX @@ void cpu_exec_step_atomic(CPUState *cpu) |
127 | cflags &= ~CF_PARALLEL; | 108 | cflags &= ~CF_PARALLEL; |
128 | /* After 1 insn, return and release the exclusive lock. */ | 109 | /* After 1 insn, return and release the exclusive lock. */ |
129 | cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR | 1; | 110 | cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR | 1; |
130 | + /* Raise any post-instruction debug exceptions. */ | 111 | + /* |
131 | + cflags = cflags_for_breakpoints(cpu, pc, cflags); | 112 | + * No need to check_for_breakpoints here. |
113 | + * We only arrive in cpu_exec_step_atomic after beginning execution | ||
114 | + * of an insn that includes an atomic operation we can't handle. | ||
115 | + * Any breakpoint for this insn will have been recognized earlier. | ||
116 | + */ | ||
132 | 117 | ||
133 | tb = tb_lookup(cpu, pc, cs_base, flags, cflags); | 118 | tb = tb_lookup(cpu, pc, cs_base, flags, cflags); |
134 | if (tb == NULL) { | 119 | if (tb == NULL) { |
135 | @@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_find(CPUState *cpu, | 120 | @@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu) |
136 | } else { | 121 | target_ulong cs_base, pc; |
137 | cpu->cflags_next_tb = -1; | 122 | uint32_t flags, cflags; |
138 | } | 123 | |
139 | + cflags = cflags_for_breakpoints(cpu, pc, cflags); | 124 | + cpu_get_tb_cpu_state(cpu->env_ptr, &pc, &cs_base, &flags); |
140 | 125 | + | |
141 | tb = tb_lookup(cpu, pc, cs_base, flags, cflags); | 126 | /* |
142 | if (tb == NULL) { | 127 | * When requested, use an exact setting for cflags for the next |
143 | diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c | 128 | * execution. This is used for icount, precise smc, and stop- |
144 | index XXXXXXX..XXXXXXX 100644 | 129 | @@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu) |
145 | --- a/accel/tcg/translate-all.c | 130 | cpu->cflags_next_tb = -1; |
146 | +++ b/accel/tcg/translate-all.c | 131 | } |
147 | @@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu, | 132 | |
148 | } | 133 | - cpu_get_tb_cpu_state(cpu->env_ptr, &pc, &cs_base, &flags); |
149 | QEMU_BUILD_BUG_ON(CF_COUNT_MASK + 1 != TCG_MAX_INSNS); | 134 | + if (check_for_breakpoints(cpu, pc, &cflags)) { |
150 | 135 | + break; | |
151 | - if (cpu->singlestep_enabled) { | 136 | + } |
152 | - max_insns = 1; | 137 | |
153 | - } | 138 | tb = tb_lookup(cpu, pc, cs_base, flags, cflags); |
154 | - | 139 | if (tb == NULL) { |
155 | buffer_overflow: | ||
156 | tb = tcg_tb_alloc(tcg_ctx); | ||
157 | if (unlikely(!tb)) { | ||
158 | diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c | 140 | diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c |
159 | index XXXXXXX..XXXXXXX 100644 | 141 | index XXXXXXX..XXXXXXX 100644 |
160 | --- a/accel/tcg/translator.c | 142 | --- a/accel/tcg/translator.c |
161 | +++ b/accel/tcg/translator.c | 143 | +++ b/accel/tcg/translator.c |
162 | @@ -XXX,XX +XXX,XX @@ void translator_loop_temp_check(DisasContextBase *db) | 144 | @@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest) |
163 | 145 | void translator_loop(const TranslatorOps *ops, DisasContextBase *db, | |
164 | bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest) | ||
165 | { | ||
166 | - /* Suppress goto_tb if requested. */ | ||
167 | - if (tb_cflags(db->tb) & CF_NO_GOTO_TB) { | ||
168 | - return false; | ||
169 | - } | ||
170 | - | ||
171 | - /* Suppress goto_tb in the case of single-steping. */ | ||
172 | - if (db->singlestep_enabled) { | ||
173 | + /* Suppress goto_tb if requested, or required by breakpoints. */ | ||
174 | + if (tb_cflags(db->tb) & (CF_NO_GOTO_TB | CF_BP_MASK)) { | ||
175 | return false; | ||
176 | } | ||
177 | |||
178 | @@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, | ||
179 | CPUState *cpu, TranslationBlock *tb, int max_insns) | 146 | CPUState *cpu, TranslationBlock *tb, int max_insns) |
180 | { | 147 | { |
181 | uint32_t cflags = tb_cflags(tb); | 148 | - int bp_insn = 0; |
182 | + int bp_flags = 0; | ||
183 | bool plugin_enabled; | 149 | bool plugin_enabled; |
184 | 150 | ||
185 | /* Initialize DisasContext */ | 151 | /* Initialize DisasContext */ |
186 | @@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, | 152 | @@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, |
187 | db->is_jmp = DISAS_NEXT; | 153 | plugin_gen_insn_start(cpu, db); |
188 | db->num_insns = 0; | ||
189 | db->max_insns = max_insns; | ||
190 | - db->singlestep_enabled = cpu->singlestep_enabled; | ||
191 | + db->singlestep_enabled = false; | ||
192 | + | ||
193 | + switch (cflags & CF_BP_MASK) { | ||
194 | + case CF_BP_NONE: | ||
195 | + break; | ||
196 | + case CF_BP_SSTEP: | ||
197 | + db->singlestep_enabled = true; | ||
198 | + break; | ||
199 | + case CF_BP_GDB: | ||
200 | + bp_flags = BP_GDB; | ||
201 | + break; | ||
202 | + case CF_BP_CPU: | ||
203 | + bp_flags = BP_CPU; | ||
204 | + break; | ||
205 | + default: | ||
206 | + g_assert_not_reached(); | ||
207 | + } | ||
208 | |||
209 | ops->init_disas_context(db, cpu); | ||
210 | tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ | ||
211 | @@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, | ||
212 | } | 154 | } |
213 | 155 | ||
214 | /* Pass breakpoint hits to target for further processing */ | 156 | - /* Pass breakpoint hits to target for further processing */ |
215 | - if (!db->singlestep_enabled | 157 | - if (!db->singlestep_enabled |
216 | - && unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) { | 158 | - && unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) { |
217 | - CPUBreakpoint *bp; | 159 | - CPUBreakpoint *bp; |
218 | - QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { | 160 | - QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { |
219 | - if (bp->pc == db->pc_next) { | 161 | - if (bp->pc == db->pc_next) { |
220 | - int len = ops->breakpoint_check(db, cpu, bp->flags); | 162 | - if (ops->breakpoint_check(db, cpu, bp)) { |
221 | + if (unlikely(bp_flags)) { | 163 | - bp_insn = 1; |
222 | + int len = ops->breakpoint_check(db, cpu, bp_flags); | 164 | - break; |
223 | |||
224 | - /* | ||
225 | - * The breakpoint_check hook may use DISAS_TOO_MANY | ||
226 | - * to indicate that only one more instruction is to | ||
227 | - * be executed. Otherwise it should use DISAS_NORETURN | ||
228 | - * when generating an exception, but may use a | ||
229 | - * DISAS_TARGET_* value for Something Else. | ||
230 | - */ | ||
231 | - if (db->is_jmp > DISAS_TOO_MANY) { | ||
232 | - /* | ||
233 | - * The address covered by the breakpoint must be | ||
234 | - * included in [tb->pc, tb->pc + tb->size) in order | ||
235 | - * to for it to be properly cleared. Thus we | ||
236 | - * increment the PC here so that the logic setting | ||
237 | - * tb->size below does the right thing. | ||
238 | - */ | ||
239 | - tcg_debug_assert(len > 0); | ||
240 | - db->pc_next += len; | ||
241 | + /* | ||
242 | + * When there is a bp hit, we're going to execute a maximum | ||
243 | + * of one instruction. The breakpoint_check hook may use | ||
244 | + * DISAS_NEXT or DISAS_TOO_MANY to indicate that the current | ||
245 | + * instruction should be translated. Anything else is taken | ||
246 | + * to mean that an exception has been raised and that zero | ||
247 | + * instructions will be executed. | ||
248 | + */ | ||
249 | + if (db->is_jmp > DISAS_TOO_MANY) { | ||
250 | + /* | ||
251 | + * The address covered by the breakpoint must be | ||
252 | + * included in [tb->pc, tb->pc + tb->size) in order | ||
253 | + * to for it to be properly cleared. Thus we | ||
254 | + * increment the PC here so that the logic setting | ||
255 | + * tb->size below does the right thing. | ||
256 | + */ | ||
257 | + tcg_debug_assert(len > 0); | ||
258 | + db->pc_next += len; | ||
259 | |||
260 | - /* | ||
261 | - * The breakpoint definitely hit, so decrement the | ||
262 | - * number of instructions completed for icount. | ||
263 | - */ | ||
264 | - db->num_insns--; | ||
265 | - goto done; | ||
266 | - } | 165 | - } |
267 | - } | 166 | - } |
268 | + /* | 167 | - } |
269 | + * The breakpoint definitely hit, so decrement the | 168 | - /* The breakpoint_check hook may use DISAS_TOO_MANY to indicate |
270 | + * number of instructions completed for icount. | 169 | - that only one more instruction is to be executed. Otherwise |
271 | + */ | 170 | - it should use DISAS_NORETURN when generating an exception, |
272 | + db->num_insns--; | 171 | - but may use a DISAS_TARGET_* value for Something Else. */ |
273 | + goto done; | 172 | - if (db->is_jmp > DISAS_TOO_MANY) { |
274 | } | 173 | - break; |
275 | } | 174 | - } |
276 | 175 | - } | |
176 | - | ||
177 | /* Disassemble one instruction. The translate_insn hook should | ||
178 | update db->pc_next and db->is_jmp to indicate what should be | ||
179 | done next -- either exiting this loop or locate the start of | ||
180 | @@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, | ||
181 | |||
182 | /* Emit code to exit the TB, as indicated by db->is_jmp. */ | ||
183 | ops->tb_stop(db, cpu); | ||
184 | - gen_tb_end(db->tb, db->num_insns - bp_insn); | ||
185 | + gen_tb_end(db->tb, db->num_insns); | ||
186 | |||
187 | if (plugin_enabled) { | ||
188 | plugin_gen_tb_end(cpu); | ||
277 | diff --git a/cpu.c b/cpu.c | 189 | diff --git a/cpu.c b/cpu.c |
278 | index XXXXXXX..XXXXXXX 100644 | 190 | index XXXXXXX..XXXXXXX 100644 |
279 | --- a/cpu.c | 191 | --- a/cpu.c |
280 | +++ b/cpu.c | 192 | +++ b/cpu.c |
281 | @@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_addr(target_ulong addr) | 193 | @@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_addr(target_ulong addr) |
... | ... | ||
324 | - breakpoint_invalidate(cpu, bp->pc); | 236 | - breakpoint_invalidate(cpu, bp->pc); |
325 | - | 237 | - |
326 | trace_breakpoint_remove(cpu->cpu_index, bp->pc, bp->flags); | 238 | trace_breakpoint_remove(cpu->cpu_index, bp->pc, bp->flags); |
327 | g_free(bp); | 239 | g_free(bp); |
328 | } | 240 | } |
329 | @@ -XXX,XX +XXX,XX @@ void cpu_single_step(CPUState *cpu, int enabled) | ||
330 | cpu->singlestep_enabled = enabled; | ||
331 | if (kvm_enabled()) { | ||
332 | kvm_update_guest_debug(cpu, 0); | ||
333 | - } else { | ||
334 | - /* must flush all the translated code to avoid inconsistencies */ | ||
335 | - /* XXX: only flush what is necessary */ | ||
336 | - tb_flush(cpu); | ||
337 | } | ||
338 | trace_breakpoint_singlestep(cpu->cpu_index, enabled); | ||
339 | } | ||
340 | -- | 241 | -- |
341 | 2.25.1 | 242 | 2.25.1 |
342 | 243 | ||
343 | 244 | diff view generated by jsdifflib |
1 | We don't need the whole CPUBreakpoint structure in the check, | 1 | The hook is now unused, with breakpoints checked outside translation. |
---|---|---|---|
2 | only the flags. Return the instruction length to consolidate | ||
3 | the adjustment of db->pc_next. | ||
4 | 2 | ||
5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
6 | --- | 4 | --- |
7 | include/exec/translator.h | 17 +++++++++------ | 5 | include/exec/translator.h | 11 ----------- |
8 | accel/tcg/translator.c | 40 ++++++++++++++++++++++++----------- | 6 | target/arm/helper.h | 2 -- |
9 | target/alpha/translate.c | 12 +++-------- | 7 | target/alpha/translate.c | 16 ---------------- |
10 | target/arm/translate-a64.c | 14 ++++-------- | 8 | target/arm/debug_helper.c | 7 ------- |
11 | target/arm/translate.c | 20 +++++++----------- | 9 | target/arm/translate-a64.c | 25 ------------------------- |
12 | target/avr/translate.c | 6 +++--- | 10 | target/arm/translate.c | 29 ----------------------------- |
13 | target/cris/translate.c | 14 ++++-------- | 11 | target/avr/translate.c | 10 ---------- |
14 | target/hexagon/translate.c | 13 +++--------- | 12 | target/cris/translate.c | 20 -------------------- |
15 | target/hppa/translate.c | 7 +++--- | 13 | target/hexagon/translate.c | 17 ----------------- |
16 | target/i386/tcg/translate.c | 15 ++++--------- | 14 | target/hppa/translate.c | 11 ----------- |
17 | target/m68k/translate.c | 14 +++--------- | 15 | target/i386/tcg/translate.c | 28 ---------------------------- |
18 | target/microblaze/translate.c | 14 +++--------- | 16 | target/m68k/translate.c | 18 ------------------ |
19 | target/mips/tcg/translate.c | 14 ++++-------- | 17 | target/microblaze/translate.c | 18 ------------------ |
20 | target/nios2/translate.c | 13 +++--------- | 18 | target/mips/tcg/translate.c | 19 ------------------- |
21 | target/openrisc/translate.c | 11 +++------- | 19 | target/nios2/translate.c | 27 --------------------------- |
22 | target/ppc/translate.c | 13 +++--------- | 20 | target/openrisc/translate.c | 17 ----------------- |
23 | target/riscv/translate.c | 11 +++------- | 21 | target/ppc/translate.c | 18 ------------------ |
24 | target/rx/translate.c | 8 +++---- | 22 | target/riscv/translate.c | 17 ----------------- |
25 | target/s390x/translate.c | 12 ++++------- | 23 | target/rx/translate.c | 14 -------------- |
26 | target/sh4/translate.c | 12 ++++------- | 24 | target/s390x/tcg/translate.c | 24 ------------------------ |
27 | target/sparc/translate.c | 9 ++++---- | 25 | target/sh4/translate.c | 18 ------------------ |
28 | target/tricore/translate.c | 13 +++--------- | 26 | target/sparc/translate.c | 17 ----------------- |
29 | target/xtensa/translate.c | 12 ++++------- | 27 | target/tricore/translate.c | 16 ---------------- |
30 | 23 files changed, 115 insertions(+), 199 deletions(-) | 28 | target/xtensa/translate.c | 17 ----------------- |
29 | 24 files changed, 416 deletions(-) | ||
31 | 30 | ||
32 | diff --git a/include/exec/translator.h b/include/exec/translator.h | 31 | diff --git a/include/exec/translator.h b/include/exec/translator.h |
33 | index XXXXXXX..XXXXXXX 100644 | 32 | index XXXXXXX..XXXXXXX 100644 |
34 | --- a/include/exec/translator.h | 33 | --- a/include/exec/translator.h |
35 | +++ b/include/exec/translator.h | 34 | +++ b/include/exec/translator.h |
36 | @@ -XXX,XX +XXX,XX @@ typedef struct DisasContextBase { | 35 | @@ -XXX,XX +XXX,XX @@ typedef struct DisasContextBase { |
37 | * @breakpoint_check: | 36 | * @insn_start: |
38 | * When called, the breakpoint has already been checked to match the PC, | 37 | * Emit the tcg_gen_insn_start opcode. |
39 | * but the target may decide the breakpoint missed the address | 38 | * |
39 | - * @breakpoint_check: | ||
40 | - * When called, the breakpoint has already been checked to match the PC, | ||
41 | - * but the target may decide the breakpoint missed the address | ||
40 | - * (e.g., due to conditions encoded in their flags). Return true to | 42 | - * (e.g., due to conditions encoded in their flags). Return true to |
41 | - * indicate that the breakpoint did hit, in which case no more breakpoints | 43 | - * indicate that the breakpoint did hit, in which case no more breakpoints |
42 | - * are checked. If the breakpoint did hit, emit any code required to | 44 | - * are checked. If the breakpoint did hit, emit any code required to |
43 | - * signal the exception, and set db->is_jmp as necessary to terminate | 45 | - * signal the exception, and set db->is_jmp as necessary to terminate |
44 | - * the main loop. | 46 | - * the main loop. |
45 | + * (e.g., due to conditions encoded in their flags), in which case | 47 | - * |
46 | + * db->is_jmp may be left as DISAS_NEXT or DISAS_TOO_MANY to indicate | ||
47 | + * that the insn should be translated. Anything other than those two | ||
48 | + * will be taken to indicate an exception has been raised, but in most | ||
49 | + * cases db->is_jmp should be set to DISAS_NORETURN. | ||
50 | + * | ||
51 | + * Return the minimum instruction size that should be applied to the TB. | ||
52 | + * The size of any TB cannot be zero, as that breaks the math used to | ||
53 | + * invalidate TBs. | ||
54 | * | ||
55 | * @translate_insn: | 48 | * @translate_insn: |
56 | * Disassemble one instruction and set db->pc_next for the start | 49 | * Disassemble one instruction and set db->pc_next for the start |
50 | * of the following instruction. Set db->is_jmp as necessary to | ||
57 | @@ -XXX,XX +XXX,XX @@ typedef struct TranslatorOps { | 51 | @@ -XXX,XX +XXX,XX @@ typedef struct TranslatorOps { |
58 | void (*init_disas_context)(DisasContextBase *db, CPUState *cpu); | 52 | void (*init_disas_context)(DisasContextBase *db, CPUState *cpu); |
59 | void (*tb_start)(DisasContextBase *db, CPUState *cpu); | 53 | void (*tb_start)(DisasContextBase *db, CPUState *cpu); |
60 | void (*insn_start)(DisasContextBase *db, CPUState *cpu); | 54 | void (*insn_start)(DisasContextBase *db, CPUState *cpu); |
61 | - bool (*breakpoint_check)(DisasContextBase *db, CPUState *cpu, | 55 | - bool (*breakpoint_check)(DisasContextBase *db, CPUState *cpu, |
62 | - const CPUBreakpoint *bp); | 56 | - const CPUBreakpoint *bp); |
63 | + int (*breakpoint_check)(DisasContextBase *db, CPUState *cpu, int flags); | ||
64 | void (*translate_insn)(DisasContextBase *db, CPUState *cpu); | 57 | void (*translate_insn)(DisasContextBase *db, CPUState *cpu); |
65 | void (*tb_stop)(DisasContextBase *db, CPUState *cpu); | 58 | void (*tb_stop)(DisasContextBase *db, CPUState *cpu); |
66 | void (*disas_log)(const DisasContextBase *db, CPUState *cpu); | 59 | void (*disas_log)(const DisasContextBase *db, CPUState *cpu); |
67 | diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c | 60 | diff --git a/target/arm/helper.h b/target/arm/helper.h |
68 | index XXXXXXX..XXXXXXX 100644 | 61 | index XXXXXXX..XXXXXXX 100644 |
69 | --- a/accel/tcg/translator.c | 62 | --- a/target/arm/helper.h |
70 | +++ b/accel/tcg/translator.c | 63 | +++ b/target/arm/helper.h |
71 | @@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest) | 64 | @@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(yield, void, env) |
72 | void translator_loop(const TranslatorOps *ops, DisasContextBase *db, | 65 | DEF_HELPER_1(pre_hvc, void, env) |
73 | CPUState *cpu, TranslationBlock *tb, int max_insns) | 66 | DEF_HELPER_2(pre_smc, void, env, i32) |
74 | { | 67 | |
75 | - int bp_insn = 0; | 68 | -DEF_HELPER_1(check_breakpoints, void, env) |
76 | bool plugin_enabled; | 69 | - |
77 | 70 | DEF_HELPER_3(cpsr_write, void, env, i32, i32) | |
78 | /* Initialize DisasContext */ | 71 | DEF_HELPER_2(cpsr_write_eret, void, env, i32) |
79 | @@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, | 72 | DEF_HELPER_1(cpsr_read, i32, env) |
80 | CPUBreakpoint *bp; | ||
81 | QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { | ||
82 | if (bp->pc == db->pc_next) { | ||
83 | - if (ops->breakpoint_check(db, cpu, bp)) { | ||
84 | - bp_insn = 1; | ||
85 | - break; | ||
86 | + int len = ops->breakpoint_check(db, cpu, bp->flags); | ||
87 | + | ||
88 | + /* | ||
89 | + * The breakpoint_check hook may use DISAS_TOO_MANY | ||
90 | + * to indicate that only one more instruction is to | ||
91 | + * be executed. Otherwise it should use DISAS_NORETURN | ||
92 | + * when generating an exception, but may use a | ||
93 | + * DISAS_TARGET_* value for Something Else. | ||
94 | + */ | ||
95 | + if (db->is_jmp > DISAS_TOO_MANY) { | ||
96 | + /* | ||
97 | + * The address covered by the breakpoint must be | ||
98 | + * included in [tb->pc, tb->pc + tb->size) in order | ||
99 | + * to for it to be properly cleared. Thus we | ||
100 | + * increment the PC here so that the logic setting | ||
101 | + * tb->size below does the right thing. | ||
102 | + */ | ||
103 | + tcg_debug_assert(len > 0); | ||
104 | + db->pc_next += len; | ||
105 | + | ||
106 | + /* | ||
107 | + * The breakpoint definitely hit, so decrement the | ||
108 | + * number of instructions completed for icount. | ||
109 | + */ | ||
110 | + db->num_insns--; | ||
111 | + goto done; | ||
112 | } | ||
113 | } | ||
114 | } | ||
115 | - /* The breakpoint_check hook may use DISAS_TOO_MANY to indicate | ||
116 | - that only one more instruction is to be executed. Otherwise | ||
117 | - it should use DISAS_NORETURN when generating an exception, | ||
118 | - but may use a DISAS_TARGET_* value for Something Else. */ | ||
119 | - if (db->is_jmp > DISAS_TOO_MANY) { | ||
120 | - break; | ||
121 | - } | ||
122 | } | ||
123 | |||
124 | /* Disassemble one instruction. The translate_insn hook should | ||
125 | @@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, | ||
126 | } | ||
127 | } | ||
128 | |||
129 | + done: | ||
130 | /* Emit code to exit the TB, as indicated by db->is_jmp. */ | ||
131 | ops->tb_stop(db, cpu); | ||
132 | - gen_tb_end(db->tb, db->num_insns - bp_insn); | ||
133 | + gen_tb_end(db->tb, db->num_insns); | ||
134 | |||
135 | if (plugin_enabled) { | ||
136 | plugin_gen_tb_end(cpu); | ||
137 | diff --git a/target/alpha/translate.c b/target/alpha/translate.c | 73 | diff --git a/target/alpha/translate.c b/target/alpha/translate.c |
138 | index XXXXXXX..XXXXXXX 100644 | 74 | index XXXXXXX..XXXXXXX 100644 |
139 | --- a/target/alpha/translate.c | 75 | --- a/target/alpha/translate.c |
140 | +++ b/target/alpha/translate.c | 76 | +++ b/target/alpha/translate.c |
141 | @@ -XXX,XX +XXX,XX @@ static void alpha_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) | 77 | @@ -XXX,XX +XXX,XX @@ static void alpha_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) |
142 | tcg_gen_insn_start(dcbase->pc_next); | 78 | tcg_gen_insn_start(dcbase->pc_next); |
143 | } | 79 | } |
144 | 80 | ||
145 | -static bool alpha_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 81 | -static bool alpha_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, |
146 | - const CPUBreakpoint *bp) | 82 | - const CPUBreakpoint *bp) |
147 | +static int alpha_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 83 | -{ |
148 | + int bp_flags) | 84 | - DisasContext *ctx = container_of(dcbase, DisasContext, base); |
149 | { | 85 | - |
150 | DisasContext *ctx = container_of(dcbase, DisasContext, base); | 86 | - ctx->base.is_jmp = gen_excp(ctx, EXCP_DEBUG, 0); |
151 | |||
152 | ctx->base.is_jmp = gen_excp(ctx, EXCP_DEBUG, 0); | ||
153 | - | 87 | - |
154 | - /* The address covered by the breakpoint must be included in | 88 | - /* The address covered by the breakpoint must be included in |
155 | - [tb->pc, tb->pc + tb->size) in order to for it to be | 89 | - [tb->pc, tb->pc + tb->size) in order to for it to be |
156 | - properly cleared -- thus we increment the PC here so that | 90 | - properly cleared -- thus we increment the PC here so that |
157 | - the logic setting tb->size below does the right thing. */ | 91 | - the logic setting tb->size below does the right thing. */ |
158 | - ctx->base.pc_next += 4; | 92 | - ctx->base.pc_next += 4; |
159 | - return true; | 93 | - return true; |
160 | + return 4; /* minimum instruction length */ | 94 | -} |
161 | } | 95 | - |
162 | |||
163 | static void alpha_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) | 96 | static void alpha_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) |
97 | { | ||
98 | DisasContext *ctx = container_of(dcbase, DisasContext, base); | ||
99 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps alpha_tr_ops = { | ||
100 | .init_disas_context = alpha_tr_init_disas_context, | ||
101 | .tb_start = alpha_tr_tb_start, | ||
102 | .insn_start = alpha_tr_insn_start, | ||
103 | - .breakpoint_check = alpha_tr_breakpoint_check, | ||
104 | .translate_insn = alpha_tr_translate_insn, | ||
105 | .tb_stop = alpha_tr_tb_stop, | ||
106 | .disas_log = alpha_tr_disas_log, | ||
107 | diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c | ||
108 | index XXXXXXX..XXXXXXX 100644 | ||
109 | --- a/target/arm/debug_helper.c | ||
110 | +++ b/target/arm/debug_helper.c | ||
111 | @@ -XXX,XX +XXX,XX @@ bool arm_debug_check_breakpoint(CPUState *cs) | ||
112 | return false; | ||
113 | } | ||
114 | |||
115 | -void HELPER(check_breakpoints)(CPUARMState *env) | ||
116 | -{ | ||
117 | - if (arm_debug_check_breakpoint(env_cpu(env))) { | ||
118 | - HELPER(exception_internal(env, EXCP_DEBUG)); | ||
119 | - } | ||
120 | -} | ||
121 | - | ||
122 | bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) | ||
123 | { | ||
124 | /* | ||
164 | diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c | 125 | diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c |
165 | index XXXXXXX..XXXXXXX 100644 | 126 | index XXXXXXX..XXXXXXX 100644 |
166 | --- a/target/arm/translate-a64.c | 127 | --- a/target/arm/translate-a64.c |
167 | +++ b/target/arm/translate-a64.c | 128 | +++ b/target/arm/translate-a64.c |
168 | @@ -XXX,XX +XXX,XX @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) | 129 | @@ -XXX,XX +XXX,XX @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) |
169 | dc->insn_start = tcg_last_op(); | 130 | dc->insn_start = tcg_last_op(); |
170 | } | 131 | } |
171 | 132 | ||
172 | -static bool aarch64_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 133 | -static bool aarch64_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, |
173 | - const CPUBreakpoint *bp) | 134 | - const CPUBreakpoint *bp) |
174 | +static int aarch64_tr_breakpoint_check(DisasContextBase *dcbase, | 135 | -{ |
175 | + CPUState *cpu, int bp_flags) | 136 | - DisasContext *dc = container_of(dcbase, DisasContext, base); |
176 | { | 137 | - |
177 | DisasContext *dc = container_of(dcbase, DisasContext, base); | ||
178 | |||
179 | - if (bp->flags & BP_CPU) { | 138 | - if (bp->flags & BP_CPU) { |
180 | + if (bp_flags & BP_CPU) { | 139 | - gen_a64_set_pc_im(dc->base.pc_next); |
181 | gen_a64_set_pc_im(dc->base.pc_next); | 140 | - gen_helper_check_breakpoints(cpu_env); |
182 | gen_helper_check_breakpoints(cpu_env); | 141 | - /* End the TB early; it likely won't be executed */ |
183 | /* End the TB early; it likely won't be executed */ | 142 | - dc->base.is_jmp = DISAS_TOO_MANY; |
184 | dc->base.is_jmp = DISAS_TOO_MANY; | 143 | - } else { |
185 | } else { | 144 | - gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG); |
186 | gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG); | ||
187 | - /* The address covered by the breakpoint must be | 145 | - /* The address covered by the breakpoint must be |
188 | - included in [tb->pc, tb->pc + tb->size) in order | 146 | - included in [tb->pc, tb->pc + tb->size) in order |
189 | - to for it to be properly cleared -- thus we | 147 | - to for it to be properly cleared -- thus we |
190 | - increment the PC here so that the logic setting | 148 | - increment the PC here so that the logic setting |
191 | - tb->size below does the right thing. */ | 149 | - tb->size below does the right thing. */ |
192 | - dc->base.pc_next += 4; | 150 | - dc->base.pc_next += 4; |
193 | dc->base.is_jmp = DISAS_NORETURN; | 151 | - dc->base.is_jmp = DISAS_NORETURN; |
194 | } | 152 | - } |
195 | 153 | - | |
196 | - return true; | 154 | - return true; |
197 | + return 4; /* minimum instruction length */ | 155 | -} |
198 | } | 156 | - |
199 | |||
200 | static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) | 157 | static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) |
158 | { | ||
159 | DisasContext *dc = container_of(dcbase, DisasContext, base); | ||
160 | @@ -XXX,XX +XXX,XX @@ const TranslatorOps aarch64_translator_ops = { | ||
161 | .init_disas_context = aarch64_tr_init_disas_context, | ||
162 | .tb_start = aarch64_tr_tb_start, | ||
163 | .insn_start = aarch64_tr_insn_start, | ||
164 | - .breakpoint_check = aarch64_tr_breakpoint_check, | ||
165 | .translate_insn = aarch64_tr_translate_insn, | ||
166 | .tb_stop = aarch64_tr_tb_stop, | ||
167 | .disas_log = aarch64_tr_disas_log, | ||
201 | diff --git a/target/arm/translate.c b/target/arm/translate.c | 168 | diff --git a/target/arm/translate.c b/target/arm/translate.c |
202 | index XXXXXXX..XXXXXXX 100644 | 169 | index XXXXXXX..XXXXXXX 100644 |
203 | --- a/target/arm/translate.c | 170 | --- a/target/arm/translate.c |
204 | +++ b/target/arm/translate.c | 171 | +++ b/target/arm/translate.c |
205 | @@ -XXX,XX +XXX,XX @@ static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) | 172 | @@ -XXX,XX +XXX,XX @@ static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) |
206 | dc->insn_start = tcg_last_op(); | 173 | dc->insn_start = tcg_last_op(); |
207 | } | 174 | } |
208 | 175 | ||
209 | -static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 176 | -static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, |
210 | - const CPUBreakpoint *bp) | 177 | - const CPUBreakpoint *bp) |
211 | +static int arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 178 | -{ |
212 | + int bp_flags) | 179 | - DisasContext *dc = container_of(dcbase, DisasContext, base); |
213 | { | 180 | - |
214 | DisasContext *dc = container_of(dcbase, DisasContext, base); | ||
215 | |||
216 | - if (bp->flags & BP_CPU) { | 181 | - if (bp->flags & BP_CPU) { |
217 | + if (bp_flags & BP_CPU) { | 182 | - gen_set_condexec(dc); |
218 | gen_set_condexec(dc); | 183 | - gen_set_pc_im(dc, dc->base.pc_next); |
219 | gen_set_pc_im(dc, dc->base.pc_next); | 184 | - gen_helper_check_breakpoints(cpu_env); |
220 | gen_helper_check_breakpoints(cpu_env); | 185 | - /* End the TB early; it's likely not going to be executed */ |
221 | @@ -XXX,XX +XXX,XX @@ static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 186 | - dc->base.is_jmp = DISAS_TOO_MANY; |
222 | dc->base.is_jmp = DISAS_TOO_MANY; | 187 | - } else { |
223 | } else { | 188 | - gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG); |
224 | gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG); | ||
225 | - /* The address covered by the breakpoint must be | 189 | - /* The address covered by the breakpoint must be |
226 | - included in [tb->pc, tb->pc + tb->size) in order | 190 | - included in [tb->pc, tb->pc + tb->size) in order |
227 | - to for it to be properly cleared -- thus we | 191 | - to for it to be properly cleared -- thus we |
228 | - increment the PC here so that the logic setting | 192 | - increment the PC here so that the logic setting |
229 | - tb->size below does the right thing. */ | 193 | - tb->size below does the right thing. */ |
230 | - /* TODO: Advance PC by correct instruction length to | 194 | - /* TODO: Advance PC by correct instruction length to |
231 | - * avoid disassembler error messages */ | 195 | - * avoid disassembler error messages */ |
232 | - dc->base.pc_next += 2; | 196 | - dc->base.pc_next += 2; |
233 | dc->base.is_jmp = DISAS_NORETURN; | 197 | - dc->base.is_jmp = DISAS_NORETURN; |
234 | } | 198 | - } |
235 | 199 | - | |
236 | - return true; | 200 | - return true; |
237 | + /* | 201 | -} |
238 | + * TODO: Advance PC by correct instruction length to avoid disassembler | 202 | - |
239 | + * error messages. In the meantime, minimum instruction length. | ||
240 | + */ | ||
241 | + return 2; | ||
242 | } | ||
243 | |||
244 | static bool arm_pre_translate_insn(DisasContext *dc) | 203 | static bool arm_pre_translate_insn(DisasContext *dc) |
204 | { | ||
205 | #ifdef CONFIG_USER_ONLY | ||
206 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps arm_translator_ops = { | ||
207 | .init_disas_context = arm_tr_init_disas_context, | ||
208 | .tb_start = arm_tr_tb_start, | ||
209 | .insn_start = arm_tr_insn_start, | ||
210 | - .breakpoint_check = arm_tr_breakpoint_check, | ||
211 | .translate_insn = arm_tr_translate_insn, | ||
212 | .tb_stop = arm_tr_tb_stop, | ||
213 | .disas_log = arm_tr_disas_log, | ||
214 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps thumb_translator_ops = { | ||
215 | .init_disas_context = arm_tr_init_disas_context, | ||
216 | .tb_start = arm_tr_tb_start, | ||
217 | .insn_start = arm_tr_insn_start, | ||
218 | - .breakpoint_check = arm_tr_breakpoint_check, | ||
219 | .translate_insn = thumb_tr_translate_insn, | ||
220 | .tb_stop = arm_tr_tb_stop, | ||
221 | .disas_log = arm_tr_disas_log, | ||
245 | diff --git a/target/avr/translate.c b/target/avr/translate.c | 222 | diff --git a/target/avr/translate.c b/target/avr/translate.c |
246 | index XXXXXXX..XXXXXXX 100644 | 223 | index XXXXXXX..XXXXXXX 100644 |
247 | --- a/target/avr/translate.c | 224 | --- a/target/avr/translate.c |
248 | +++ b/target/avr/translate.c | 225 | +++ b/target/avr/translate.c |
249 | @@ -XXX,XX +XXX,XX @@ static void avr_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) | 226 | @@ -XXX,XX +XXX,XX @@ static void avr_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) |
250 | tcg_gen_insn_start(ctx->npc); | 227 | tcg_gen_insn_start(ctx->npc); |
251 | } | 228 | } |
252 | 229 | ||
253 | -static bool avr_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 230 | -static bool avr_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, |
254 | - const CPUBreakpoint *bp) | 231 | - const CPUBreakpoint *bp) |
255 | +static int avr_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 232 | -{ |
256 | + int bp_flags) | 233 | - DisasContext *ctx = container_of(dcbase, DisasContext, base); |
234 | - | ||
235 | - gen_breakpoint(ctx); | ||
236 | - return true; | ||
237 | -} | ||
238 | - | ||
239 | static void avr_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) | ||
257 | { | 240 | { |
258 | DisasContext *ctx = container_of(dcbase, DisasContext, base); | 241 | DisasContext *ctx = container_of(dcbase, DisasContext, base); |
259 | 242 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps avr_tr_ops = { | |
260 | gen_breakpoint(ctx); | 243 | .init_disas_context = avr_tr_init_disas_context, |
261 | - return true; | 244 | .tb_start = avr_tr_tb_start, |
262 | + return 2; /* minimum instruction length */ | 245 | .insn_start = avr_tr_insn_start, |
263 | } | 246 | - .breakpoint_check = avr_tr_breakpoint_check, |
264 | 247 | .translate_insn = avr_tr_translate_insn, | |
265 | static void avr_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) | 248 | .tb_stop = avr_tr_tb_stop, |
249 | .disas_log = avr_tr_disas_log, | ||
266 | diff --git a/target/cris/translate.c b/target/cris/translate.c | 250 | diff --git a/target/cris/translate.c b/target/cris/translate.c |
267 | index XXXXXXX..XXXXXXX 100644 | 251 | index XXXXXXX..XXXXXXX 100644 |
268 | --- a/target/cris/translate.c | 252 | --- a/target/cris/translate.c |
269 | +++ b/target/cris/translate.c | 253 | +++ b/target/cris/translate.c |
270 | @@ -XXX,XX +XXX,XX @@ static void cris_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) | 254 | @@ -XXX,XX +XXX,XX @@ static void cris_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) |
271 | tcg_gen_insn_start(dc->delayed_branch == 1 ? dc->ppc | 1 : dc->pc); | 255 | tcg_gen_insn_start(dc->delayed_branch == 1 ? dc->ppc | 1 : dc->pc); |
272 | } | 256 | } |
273 | 257 | ||
274 | -static bool cris_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 258 | -static bool cris_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, |
275 | - const CPUBreakpoint *bp) | 259 | - const CPUBreakpoint *bp) |
276 | +static int cris_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 260 | -{ |
277 | + int bp_flags) | 261 | - DisasContext *dc = container_of(dcbase, DisasContext, base); |
278 | { | 262 | - |
279 | DisasContext *dc = container_of(dcbase, DisasContext, base); | 263 | - cris_evaluate_flags(dc); |
280 | 264 | - tcg_gen_movi_tl(env_pc, dc->pc); | |
281 | @@ -XXX,XX +XXX,XX @@ static bool cris_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 265 | - t_gen_raise_exception(EXCP_DEBUG); |
282 | tcg_gen_movi_tl(env_pc, dc->pc); | 266 | - dc->base.is_jmp = DISAS_NORETURN; |
283 | t_gen_raise_exception(EXCP_DEBUG); | ||
284 | dc->base.is_jmp = DISAS_NORETURN; | ||
285 | - /* | 267 | - /* |
286 | - * The address covered by the breakpoint must be included in | 268 | - * The address covered by the breakpoint must be included in |
287 | - * [tb->pc, tb->pc + tb->size) in order to for it to be | 269 | - * [tb->pc, tb->pc + tb->size) in order to for it to be |
288 | - * properly cleared -- thus we increment the PC here so that | 270 | - * properly cleared -- thus we increment the PC here so that |
289 | - * the logic setting tb->size below does the right thing. | 271 | - * the logic setting tb->size below does the right thing. |
290 | - */ | 272 | - */ |
291 | - dc->pc += 2; | 273 | - dc->pc += 2; |
292 | - return true; | 274 | - return true; |
293 | + | 275 | -} |
294 | + return 2; /* minimum instruction length */ | 276 | - |
295 | } | ||
296 | |||
297 | static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) | 277 | static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) |
278 | { | ||
279 | DisasContext *dc = container_of(dcbase, DisasContext, base); | ||
280 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps cris_tr_ops = { | ||
281 | .init_disas_context = cris_tr_init_disas_context, | ||
282 | .tb_start = cris_tr_tb_start, | ||
283 | .insn_start = cris_tr_insn_start, | ||
284 | - .breakpoint_check = cris_tr_breakpoint_check, | ||
285 | .translate_insn = cris_tr_translate_insn, | ||
286 | .tb_stop = cris_tr_tb_stop, | ||
287 | .disas_log = cris_tr_disas_log, | ||
298 | diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c | 288 | diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c |
299 | index XXXXXXX..XXXXXXX 100644 | 289 | index XXXXXXX..XXXXXXX 100644 |
300 | --- a/target/hexagon/translate.c | 290 | --- a/target/hexagon/translate.c |
301 | +++ b/target/hexagon/translate.c | 291 | +++ b/target/hexagon/translate.c |
302 | @@ -XXX,XX +XXX,XX @@ static void hexagon_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) | 292 | @@ -XXX,XX +XXX,XX @@ static void hexagon_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) |
303 | tcg_gen_insn_start(ctx->base.pc_next); | 293 | tcg_gen_insn_start(ctx->base.pc_next); |
304 | } | 294 | } |
305 | 295 | ||
306 | -static bool hexagon_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 296 | -static bool hexagon_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, |
307 | - const CPUBreakpoint *bp) | 297 | - const CPUBreakpoint *bp) |
308 | +static int hexagon_tr_breakpoint_check(DisasContextBase *dcbase, | 298 | -{ |
309 | + CPUState *cpu, int bp_flags) | 299 | - DisasContext *ctx = container_of(dcbase, DisasContext, base); |
310 | { | 300 | - |
311 | DisasContext *ctx = container_of(dcbase, DisasContext, base); | 301 | - gen_exception_end_tb(ctx, EXCP_DEBUG); |
312 | |||
313 | gen_exception_end_tb(ctx, EXCP_DEBUG); | ||
314 | - /* | 302 | - /* |
315 | - * The address covered by the breakpoint must be included in | 303 | - * The address covered by the breakpoint must be included in |
316 | - * [tb->pc, tb->pc + tb->size) in order to for it to be | 304 | - * [tb->pc, tb->pc + tb->size) in order to for it to be |
317 | - * properly cleared -- thus we increment the PC here so that | 305 | - * properly cleared -- thus we increment the PC here so that |
318 | - * the logic setting tb->size below does the right thing. | 306 | - * the logic setting tb->size below does the right thing. |
319 | - */ | 307 | - */ |
320 | - ctx->base.pc_next += 4; | 308 | - ctx->base.pc_next += 4; |
321 | - return true; | 309 | - return true; |
322 | + return 4; /* minimum packet length */ | 310 | -} |
323 | } | 311 | - |
324 | |||
325 | static bool pkt_crosses_page(CPUHexagonState *env, DisasContext *ctx) | 312 | static bool pkt_crosses_page(CPUHexagonState *env, DisasContext *ctx) |
313 | { | ||
314 | target_ulong page_start = ctx->base.pc_first & TARGET_PAGE_MASK; | ||
315 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps hexagon_tr_ops = { | ||
316 | .init_disas_context = hexagon_tr_init_disas_context, | ||
317 | .tb_start = hexagon_tr_tb_start, | ||
318 | .insn_start = hexagon_tr_insn_start, | ||
319 | - .breakpoint_check = hexagon_tr_breakpoint_check, | ||
320 | .translate_insn = hexagon_tr_translate_packet, | ||
321 | .tb_stop = hexagon_tr_tb_stop, | ||
322 | .disas_log = hexagon_tr_disas_log, | ||
326 | diff --git a/target/hppa/translate.c b/target/hppa/translate.c | 323 | diff --git a/target/hppa/translate.c b/target/hppa/translate.c |
327 | index XXXXXXX..XXXXXXX 100644 | 324 | index XXXXXXX..XXXXXXX 100644 |
328 | --- a/target/hppa/translate.c | 325 | --- a/target/hppa/translate.c |
329 | +++ b/target/hppa/translate.c | 326 | +++ b/target/hppa/translate.c |
330 | @@ -XXX,XX +XXX,XX @@ static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) | 327 | @@ -XXX,XX +XXX,XX @@ static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) |
331 | tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b); | 328 | tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b); |
332 | } | 329 | } |
333 | 330 | ||
334 | -static bool hppa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 331 | -static bool hppa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, |
335 | - const CPUBreakpoint *bp) | 332 | - const CPUBreakpoint *bp) |
336 | +static int hppa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 333 | -{ |
337 | + int bp_flags) | 334 | - DisasContext *ctx = container_of(dcbase, DisasContext, base); |
335 | - | ||
336 | - gen_excp(ctx, EXCP_DEBUG); | ||
337 | - ctx->base.pc_next += 4; | ||
338 | - return true; | ||
339 | -} | ||
340 | - | ||
341 | static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) | ||
338 | { | 342 | { |
339 | DisasContext *ctx = container_of(dcbase, DisasContext, base); | 343 | DisasContext *ctx = container_of(dcbase, DisasContext, base); |
340 | 344 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps hppa_tr_ops = { | |
341 | gen_excp(ctx, EXCP_DEBUG); | 345 | .init_disas_context = hppa_tr_init_disas_context, |
342 | - ctx->base.pc_next += 4; | 346 | .tb_start = hppa_tr_tb_start, |
343 | - return true; | 347 | .insn_start = hppa_tr_insn_start, |
344 | + return 4; /* minimum instruction length */ | 348 | - .breakpoint_check = hppa_tr_breakpoint_check, |
345 | } | 349 | .translate_insn = hppa_tr_translate_insn, |
346 | 350 | .tb_stop = hppa_tr_tb_stop, | |
347 | static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) | 351 | .disas_log = hppa_tr_disas_log, |
348 | diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c | 352 | diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c |
349 | index XXXXXXX..XXXXXXX 100644 | 353 | index XXXXXXX..XXXXXXX 100644 |
350 | --- a/target/i386/tcg/translate.c | 354 | --- a/target/i386/tcg/translate.c |
351 | +++ b/target/i386/tcg/translate.c | 355 | +++ b/target/i386/tcg/translate.c |
356 | @@ -XXX,XX +XXX,XX @@ static void gen_interrupt(DisasContext *s, int intno, | ||
357 | s->base.is_jmp = DISAS_NORETURN; | ||
358 | } | ||
359 | |||
360 | -static void gen_debug(DisasContext *s) | ||
361 | -{ | ||
362 | - gen_update_cc_op(s); | ||
363 | - gen_jmp_im(s, s->base.pc_next - s->cs_base); | ||
364 | - gen_helper_debug(cpu_env); | ||
365 | - s->base.is_jmp = DISAS_NORETURN; | ||
366 | -} | ||
367 | - | ||
368 | static void gen_set_hflag(DisasContext *s, uint32_t mask) | ||
369 | { | ||
370 | if ((s->flags & mask) == 0) { | ||
352 | @@ -XXX,XX +XXX,XX @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) | 371 | @@ -XXX,XX +XXX,XX @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) |
353 | tcg_gen_insn_start(dc->base.pc_next, dc->cc_op); | 372 | tcg_gen_insn_start(dc->base.pc_next, dc->cc_op); |
354 | } | 373 | } |
355 | 374 | ||
356 | -static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 375 | -static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, |
357 | - const CPUBreakpoint *bp) | 376 | - const CPUBreakpoint *bp) |
358 | +static int i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 377 | -{ |
359 | + int bp_flags) | 378 | - DisasContext *dc = container_of(dcbase, DisasContext, base); |
360 | { | 379 | - /* If RF is set, suppress an internally generated breakpoint. */ |
361 | DisasContext *dc = container_of(dcbase, DisasContext, base); | 380 | - int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY; |
362 | /* If RF is set, suppress an internally generated breakpoint. */ | ||
363 | int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY; | ||
364 | - if (bp->flags & flags) { | 381 | - if (bp->flags & flags) { |
365 | + if (bp_flags & flags) { | 382 | - gen_debug(dc); |
366 | gen_debug(dc); | ||
367 | - /* The address covered by the breakpoint must be included in | 383 | - /* The address covered by the breakpoint must be included in |
368 | - [tb->pc, tb->pc + tb->size) in order to for it to be | 384 | - [tb->pc, tb->pc + tb->size) in order to for it to be |
369 | - properly cleared -- thus we increment the PC here so that | 385 | - properly cleared -- thus we increment the PC here so that |
370 | - the generic logic setting tb->size later does the right thing. */ | 386 | - the generic logic setting tb->size later does the right thing. */ |
371 | - dc->base.pc_next += 1; | 387 | - dc->base.pc_next += 1; |
372 | - return true; | 388 | - return true; |
373 | - } else { | 389 | - } else { |
374 | - return false; | 390 | - return false; |
375 | } | 391 | - } |
376 | + return 1; /* minimum instruction length */ | 392 | -} |
377 | } | 393 | - |
378 | |||
379 | static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) | 394 | static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) |
395 | { | ||
396 | DisasContext *dc = container_of(dcbase, DisasContext, base); | ||
397 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps i386_tr_ops = { | ||
398 | .init_disas_context = i386_tr_init_disas_context, | ||
399 | .tb_start = i386_tr_tb_start, | ||
400 | .insn_start = i386_tr_insn_start, | ||
401 | - .breakpoint_check = i386_tr_breakpoint_check, | ||
402 | .translate_insn = i386_tr_translate_insn, | ||
403 | .tb_stop = i386_tr_tb_stop, | ||
404 | .disas_log = i386_tr_disas_log, | ||
380 | diff --git a/target/m68k/translate.c b/target/m68k/translate.c | 405 | diff --git a/target/m68k/translate.c b/target/m68k/translate.c |
381 | index XXXXXXX..XXXXXXX 100644 | 406 | index XXXXXXX..XXXXXXX 100644 |
382 | --- a/target/m68k/translate.c | 407 | --- a/target/m68k/translate.c |
383 | +++ b/target/m68k/translate.c | 408 | +++ b/target/m68k/translate.c |
384 | @@ -XXX,XX +XXX,XX @@ static void m68k_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) | 409 | @@ -XXX,XX +XXX,XX @@ static void m68k_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) |
385 | tcg_gen_insn_start(dc->base.pc_next, dc->cc_op); | 410 | tcg_gen_insn_start(dc->base.pc_next, dc->cc_op); |
386 | } | 411 | } |
387 | 412 | ||
388 | -static bool m68k_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 413 | -static bool m68k_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, |
389 | - const CPUBreakpoint *bp) | 414 | - const CPUBreakpoint *bp) |
390 | +static int m68k_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 415 | -{ |
391 | + int bp_flags) | 416 | - DisasContext *dc = container_of(dcbase, DisasContext, base); |
392 | { | 417 | - |
393 | DisasContext *dc = container_of(dcbase, DisasContext, base); | 418 | - gen_exception(dc, dc->base.pc_next, EXCP_DEBUG); |
394 | |||
395 | gen_exception(dc, dc->base.pc_next, EXCP_DEBUG); | ||
396 | - /* | 419 | - /* |
397 | - * The address covered by the breakpoint must be included in | 420 | - * The address covered by the breakpoint must be included in |
398 | - * [tb->pc, tb->pc + tb->size) in order to for it to be | 421 | - * [tb->pc, tb->pc + tb->size) in order to for it to be |
399 | - * properly cleared -- thus we increment the PC here so that | 422 | - * properly cleared -- thus we increment the PC here so that |
400 | - * the logic setting tb->size below does the right thing. | 423 | - * the logic setting tb->size below does the right thing. |
401 | - */ | 424 | - */ |
402 | - dc->base.pc_next += 2; | 425 | - dc->base.pc_next += 2; |
403 | - | 426 | - |
404 | - return true; | 427 | - return true; |
405 | + return 2; /* minimum instruction length */ | 428 | -} |
406 | } | 429 | - |
407 | |||
408 | static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) | 430 | static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) |
431 | { | ||
432 | DisasContext *dc = container_of(dcbase, DisasContext, base); | ||
433 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps m68k_tr_ops = { | ||
434 | .init_disas_context = m68k_tr_init_disas_context, | ||
435 | .tb_start = m68k_tr_tb_start, | ||
436 | .insn_start = m68k_tr_insn_start, | ||
437 | - .breakpoint_check = m68k_tr_breakpoint_check, | ||
438 | .translate_insn = m68k_tr_translate_insn, | ||
439 | .tb_stop = m68k_tr_tb_stop, | ||
440 | .disas_log = m68k_tr_disas_log, | ||
409 | diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c | 441 | diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c |
410 | index XXXXXXX..XXXXXXX 100644 | 442 | index XXXXXXX..XXXXXXX 100644 |
411 | --- a/target/microblaze/translate.c | 443 | --- a/target/microblaze/translate.c |
412 | +++ b/target/microblaze/translate.c | 444 | +++ b/target/microblaze/translate.c |
413 | @@ -XXX,XX +XXX,XX @@ static void mb_tr_insn_start(DisasContextBase *dcb, CPUState *cs) | 445 | @@ -XXX,XX +XXX,XX @@ static void mb_tr_insn_start(DisasContextBase *dcb, CPUState *cs) |
414 | dc->insn_start = tcg_last_op(); | 446 | dc->insn_start = tcg_last_op(); |
415 | } | 447 | } |
416 | 448 | ||
417 | -static bool mb_tr_breakpoint_check(DisasContextBase *dcb, CPUState *cs, | 449 | -static bool mb_tr_breakpoint_check(DisasContextBase *dcb, CPUState *cs, |
418 | - const CPUBreakpoint *bp) | 450 | - const CPUBreakpoint *bp) |
419 | +static int mb_tr_breakpoint_check(DisasContextBase *dcb, CPUState *cs, | 451 | -{ |
420 | + int bp_flags) | 452 | - DisasContext *dc = container_of(dcb, DisasContext, base); |
421 | { | 453 | - |
422 | DisasContext *dc = container_of(dcb, DisasContext, base); | 454 | - gen_raise_exception_sync(dc, EXCP_DEBUG); |
423 | |||
424 | gen_raise_exception_sync(dc, EXCP_DEBUG); | ||
425 | - | 455 | - |
426 | - /* | 456 | - /* |
427 | - * The address covered by the breakpoint must be included in | 457 | - * The address covered by the breakpoint must be included in |
428 | - * [tb->pc, tb->pc + tb->size) in order to for it to be | 458 | - * [tb->pc, tb->pc + tb->size) in order to for it to be |
429 | - * properly cleared -- thus we increment the PC here so that | 459 | - * properly cleared -- thus we increment the PC here so that |
430 | - * the logic setting tb->size below does the right thing. | 460 | - * the logic setting tb->size below does the right thing. |
431 | - */ | 461 | - */ |
432 | - dc->base.pc_next += 4; | 462 | - dc->base.pc_next += 4; |
433 | - return true; | 463 | - return true; |
434 | + return 4; /* minimum instruction length */ | 464 | -} |
435 | } | 465 | - |
436 | |||
437 | static void mb_tr_translate_insn(DisasContextBase *dcb, CPUState *cs) | 466 | static void mb_tr_translate_insn(DisasContextBase *dcb, CPUState *cs) |
467 | { | ||
468 | DisasContext *dc = container_of(dcb, DisasContext, base); | ||
469 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps mb_tr_ops = { | ||
470 | .init_disas_context = mb_tr_init_disas_context, | ||
471 | .tb_start = mb_tr_tb_start, | ||
472 | .insn_start = mb_tr_insn_start, | ||
473 | - .breakpoint_check = mb_tr_breakpoint_check, | ||
474 | .translate_insn = mb_tr_translate_insn, | ||
475 | .tb_stop = mb_tr_tb_stop, | ||
476 | .disas_log = mb_tr_disas_log, | ||
438 | diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c | 477 | diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c |
439 | index XXXXXXX..XXXXXXX 100644 | 478 | index XXXXXXX..XXXXXXX 100644 |
440 | --- a/target/mips/tcg/translate.c | 479 | --- a/target/mips/tcg/translate.c |
441 | +++ b/target/mips/tcg/translate.c | 480 | +++ b/target/mips/tcg/translate.c |
442 | @@ -XXX,XX +XXX,XX @@ static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) | 481 | @@ -XXX,XX +XXX,XX @@ static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) |
443 | ctx->btarget); | 482 | ctx->btarget); |
444 | } | 483 | } |
445 | 484 | ||
446 | -static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 485 | -static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, |
447 | - const CPUBreakpoint *bp) | 486 | - const CPUBreakpoint *bp) |
448 | +static int mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 487 | -{ |
449 | + int bp_flags) | 488 | - DisasContext *ctx = container_of(dcbase, DisasContext, base); |
450 | { | 489 | - |
451 | DisasContext *ctx = container_of(dcbase, DisasContext, base); | 490 | - save_cpu_state(ctx, 1); |
452 | 491 | - ctx->base.is_jmp = DISAS_NORETURN; | |
453 | save_cpu_state(ctx, 1); | 492 | - gen_helper_raise_exception_debug(cpu_env); |
454 | ctx->base.is_jmp = DISAS_NORETURN; | ||
455 | gen_helper_raise_exception_debug(cpu_env); | ||
456 | - /* | 493 | - /* |
457 | - * The address covered by the breakpoint must be included in | 494 | - * The address covered by the breakpoint must be included in |
458 | - * [tb->pc, tb->pc + tb->size) in order to for it to be | 495 | - * [tb->pc, tb->pc + tb->size) in order to for it to be |
459 | - * properly cleared -- thus we increment the PC here so that | 496 | - * properly cleared -- thus we increment the PC here so that |
460 | - * the logic setting tb->size below does the right thing. | 497 | - * the logic setting tb->size below does the right thing. |
461 | - */ | 498 | - */ |
462 | - ctx->base.pc_next += 4; | 499 | - ctx->base.pc_next += 4; |
463 | - return true; | 500 | - return true; |
464 | + | 501 | -} |
465 | + return 2; /* minimum instruction length */ | 502 | - |
466 | } | ||
467 | |||
468 | static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) | 503 | static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) |
504 | { | ||
505 | CPUMIPSState *env = cs->env_ptr; | ||
506 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps mips_tr_ops = { | ||
507 | .init_disas_context = mips_tr_init_disas_context, | ||
508 | .tb_start = mips_tr_tb_start, | ||
509 | .insn_start = mips_tr_insn_start, | ||
510 | - .breakpoint_check = mips_tr_breakpoint_check, | ||
511 | .translate_insn = mips_tr_translate_insn, | ||
512 | .tb_stop = mips_tr_tb_stop, | ||
513 | .disas_log = mips_tr_disas_log, | ||
469 | diff --git a/target/nios2/translate.c b/target/nios2/translate.c | 514 | diff --git a/target/nios2/translate.c b/target/nios2/translate.c |
470 | index XXXXXXX..XXXXXXX 100644 | 515 | index XXXXXXX..XXXXXXX 100644 |
471 | --- a/target/nios2/translate.c | 516 | --- a/target/nios2/translate.c |
472 | +++ b/target/nios2/translate.c | 517 | +++ b/target/nios2/translate.c |
518 | @@ -XXX,XX +XXX,XX @@ static const char * const regnames[] = { | ||
519 | |||
520 | #include "exec/gen-icount.h" | ||
521 | |||
522 | -static void gen_exception(DisasContext *dc, uint32_t excp) | ||
523 | -{ | ||
524 | - TCGv_i32 tmp = tcg_const_i32(excp); | ||
525 | - | ||
526 | - tcg_gen_movi_tl(cpu_R[R_PC], dc->pc); | ||
527 | - gen_helper_raise_exception(cpu_env, tmp); | ||
528 | - tcg_temp_free_i32(tmp); | ||
529 | - dc->base.is_jmp = DISAS_NORETURN; | ||
530 | -} | ||
531 | - | ||
532 | /* generate intermediate code for basic block 'tb'. */ | ||
533 | static void nios2_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) | ||
534 | { | ||
473 | @@ -XXX,XX +XXX,XX @@ static void nios2_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) | 535 | @@ -XXX,XX +XXX,XX @@ static void nios2_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) |
474 | tcg_gen_insn_start(dcbase->pc_next); | 536 | tcg_gen_insn_start(dcbase->pc_next); |
475 | } | 537 | } |
476 | 538 | ||
477 | -static bool nios2_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 539 | -static bool nios2_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, |
478 | - const CPUBreakpoint *bp) | 540 | - const CPUBreakpoint *bp) |
479 | +static int nios2_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 541 | -{ |
480 | + int bp_flags) | 542 | - DisasContext *dc = container_of(dcbase, DisasContext, base); |
481 | { | 543 | - |
482 | DisasContext *dc = container_of(dcbase, DisasContext, base); | 544 | - gen_exception(dc, EXCP_DEBUG); |
483 | |||
484 | gen_exception(dc, EXCP_DEBUG); | ||
485 | - /* | 545 | - /* |
486 | - * The address covered by the breakpoint must be included in | 546 | - * The address covered by the breakpoint must be included in |
487 | - * [tb->pc, tb->pc + tb->size) in order to for it to be | 547 | - * [tb->pc, tb->pc + tb->size) in order to for it to be |
488 | - * properly cleared -- thus we increment the PC here so that | 548 | - * properly cleared -- thus we increment the PC here so that |
489 | - * the logic setting tb->size below does the right thing. | 549 | - * the logic setting tb->size below does the right thing. |
490 | - */ | 550 | - */ |
491 | - dc->base.pc_next += 4; | 551 | - dc->base.pc_next += 4; |
492 | - return true; | 552 | - return true; |
493 | + return 4; /* minimum instruction length */ | 553 | -} |
494 | } | 554 | - |
495 | |||
496 | static void nios2_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) | 555 | static void nios2_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) |
556 | { | ||
557 | DisasContext *dc = container_of(dcbase, DisasContext, base); | ||
558 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps nios2_tr_ops = { | ||
559 | .init_disas_context = nios2_tr_init_disas_context, | ||
560 | .tb_start = nios2_tr_tb_start, | ||
561 | .insn_start = nios2_tr_insn_start, | ||
562 | - .breakpoint_check = nios2_tr_breakpoint_check, | ||
563 | .translate_insn = nios2_tr_translate_insn, | ||
564 | .tb_stop = nios2_tr_tb_stop, | ||
565 | .disas_log = nios2_tr_disas_log, | ||
497 | diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c | 566 | diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c |
498 | index XXXXXXX..XXXXXXX 100644 | 567 | index XXXXXXX..XXXXXXX 100644 |
499 | --- a/target/openrisc/translate.c | 568 | --- a/target/openrisc/translate.c |
500 | +++ b/target/openrisc/translate.c | 569 | +++ b/target/openrisc/translate.c |
501 | @@ -XXX,XX +XXX,XX @@ static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) | 570 | @@ -XXX,XX +XXX,XX @@ static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) |
502 | | (dc->base.num_insns > 1 ? 2 : 0)); | 571 | | (dc->base.num_insns > 1 ? 2 : 0)); |
503 | } | 572 | } |
504 | 573 | ||
505 | -static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 574 | -static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, |
506 | - const CPUBreakpoint *bp) | 575 | - const CPUBreakpoint *bp) |
507 | +static int openrisc_tr_breakpoint_check(DisasContextBase *dcbase, | 576 | -{ |
508 | + CPUState *cs, int bp_flags) | 577 | - DisasContext *dc = container_of(dcbase, DisasContext, base); |
509 | { | 578 | - |
510 | DisasContext *dc = container_of(dcbase, DisasContext, base); | 579 | - tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); |
511 | 580 | - gen_exception(dc, EXCP_DEBUG); | |
512 | tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); | 581 | - dc->base.is_jmp = DISAS_NORETURN; |
513 | gen_exception(dc, EXCP_DEBUG); | ||
514 | dc->base.is_jmp = DISAS_NORETURN; | ||
515 | - /* The address covered by the breakpoint must be included in | 582 | - /* The address covered by the breakpoint must be included in |
516 | - [tb->pc, tb->pc + tb->size) in order to for it to be | 583 | - [tb->pc, tb->pc + tb->size) in order to for it to be |
517 | - properly cleared -- thus we increment the PC here so that | 584 | - properly cleared -- thus we increment the PC here so that |
518 | - the logic setting tb->size below does the right thing. */ | 585 | - the logic setting tb->size below does the right thing. */ |
519 | - dc->base.pc_next += 4; | 586 | - dc->base.pc_next += 4; |
520 | - return true; | 587 | - return true; |
521 | + return 4; /* minimum instruction length */ | 588 | -} |
522 | } | 589 | - |
523 | |||
524 | static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) | 590 | static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) |
591 | { | ||
592 | DisasContext *dc = container_of(dcbase, DisasContext, base); | ||
593 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps openrisc_tr_ops = { | ||
594 | .init_disas_context = openrisc_tr_init_disas_context, | ||
595 | .tb_start = openrisc_tr_tb_start, | ||
596 | .insn_start = openrisc_tr_insn_start, | ||
597 | - .breakpoint_check = openrisc_tr_breakpoint_check, | ||
598 | .translate_insn = openrisc_tr_translate_insn, | ||
599 | .tb_stop = openrisc_tr_tb_stop, | ||
600 | .disas_log = openrisc_tr_disas_log, | ||
525 | diff --git a/target/ppc/translate.c b/target/ppc/translate.c | 601 | diff --git a/target/ppc/translate.c b/target/ppc/translate.c |
526 | index XXXXXXX..XXXXXXX 100644 | 602 | index XXXXXXX..XXXXXXX 100644 |
527 | --- a/target/ppc/translate.c | 603 | --- a/target/ppc/translate.c |
528 | +++ b/target/ppc/translate.c | 604 | +++ b/target/ppc/translate.c |
529 | @@ -XXX,XX +XXX,XX @@ static void ppc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) | 605 | @@ -XXX,XX +XXX,XX @@ static void ppc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) |
530 | tcg_gen_insn_start(dcbase->pc_next); | 606 | tcg_gen_insn_start(dcbase->pc_next); |
531 | } | 607 | } |
532 | 608 | ||
533 | -static bool ppc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 609 | -static bool ppc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, |
534 | - const CPUBreakpoint *bp) | 610 | - const CPUBreakpoint *bp) |
535 | +static int ppc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 611 | -{ |
536 | + int bp_flags) | 612 | - DisasContext *ctx = container_of(dcbase, DisasContext, base); |
537 | { | 613 | - |
538 | DisasContext *ctx = container_of(dcbase, DisasContext, base); | 614 | - gen_update_nip(ctx, ctx->base.pc_next); |
539 | 615 | - gen_debug_exception(ctx); | |
540 | gen_update_nip(ctx, ctx->base.pc_next); | ||
541 | gen_debug_exception(ctx); | ||
542 | - /* | 616 | - /* |
543 | - * The address covered by the breakpoint must be included in | 617 | - * The address covered by the breakpoint must be included in |
544 | - * [tb->pc, tb->pc + tb->size) in order to for it to be properly | 618 | - * [tb->pc, tb->pc + tb->size) in order to for it to be properly |
545 | - * cleared -- thus we increment the PC here so that the logic | 619 | - * cleared -- thus we increment the PC here so that the logic |
546 | - * setting tb->size below does the right thing. | 620 | - * setting tb->size below does the right thing. |
547 | - */ | 621 | - */ |
548 | - ctx->base.pc_next += 4; | 622 | - ctx->base.pc_next += 4; |
549 | - return true; | 623 | - return true; |
550 | + return 4; /* minimum instruction length */ | 624 | -} |
551 | } | 625 | - |
552 | |||
553 | static bool is_prefix_insn(DisasContext *ctx, uint32_t insn) | 626 | static bool is_prefix_insn(DisasContext *ctx, uint32_t insn) |
627 | { | ||
628 | REQUIRE_INSNS_FLAGS2(ctx, ISA310); | ||
629 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps ppc_tr_ops = { | ||
630 | .init_disas_context = ppc_tr_init_disas_context, | ||
631 | .tb_start = ppc_tr_tb_start, | ||
632 | .insn_start = ppc_tr_insn_start, | ||
633 | - .breakpoint_check = ppc_tr_breakpoint_check, | ||
634 | .translate_insn = ppc_tr_translate_insn, | ||
635 | .tb_stop = ppc_tr_tb_stop, | ||
636 | .disas_log = ppc_tr_disas_log, | ||
554 | diff --git a/target/riscv/translate.c b/target/riscv/translate.c | 637 | diff --git a/target/riscv/translate.c b/target/riscv/translate.c |
555 | index XXXXXXX..XXXXXXX 100644 | 638 | index XXXXXXX..XXXXXXX 100644 |
556 | --- a/target/riscv/translate.c | 639 | --- a/target/riscv/translate.c |
557 | +++ b/target/riscv/translate.c | 640 | +++ b/target/riscv/translate.c |
558 | @@ -XXX,XX +XXX,XX @@ static void riscv_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) | 641 | @@ -XXX,XX +XXX,XX @@ static void riscv_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) |
559 | tcg_gen_insn_start(ctx->base.pc_next); | 642 | tcg_gen_insn_start(ctx->base.pc_next); |
560 | } | 643 | } |
561 | 644 | ||
562 | -static bool riscv_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 645 | -static bool riscv_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, |
563 | - const CPUBreakpoint *bp) | 646 | - const CPUBreakpoint *bp) |
564 | +static int riscv_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 647 | -{ |
565 | + int bp_flags) | 648 | - DisasContext *ctx = container_of(dcbase, DisasContext, base); |
566 | { | 649 | - |
567 | DisasContext *ctx = container_of(dcbase, DisasContext, base); | 650 | - tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); |
568 | 651 | - ctx->base.is_jmp = DISAS_NORETURN; | |
569 | tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); | 652 | - gen_exception_debug(); |
570 | ctx->base.is_jmp = DISAS_NORETURN; | ||
571 | gen_exception_debug(); | ||
572 | - /* The address covered by the breakpoint must be included in | 653 | - /* The address covered by the breakpoint must be included in |
573 | - [tb->pc, tb->pc + tb->size) in order to for it to be | 654 | - [tb->pc, tb->pc + tb->size) in order to for it to be |
574 | - properly cleared -- thus we increment the PC here so that | 655 | - properly cleared -- thus we increment the PC here so that |
575 | - the logic setting tb->size below does the right thing. */ | 656 | - the logic setting tb->size below does the right thing. */ |
576 | - ctx->base.pc_next += 4; | 657 | - ctx->base.pc_next += 4; |
577 | - return true; | 658 | - return true; |
578 | + return 2; /* minimum instruction length */ | 659 | -} |
579 | } | 660 | - |
580 | |||
581 | static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) | 661 | static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) |
662 | { | ||
663 | DisasContext *ctx = container_of(dcbase, DisasContext, base); | ||
664 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps riscv_tr_ops = { | ||
665 | .init_disas_context = riscv_tr_init_disas_context, | ||
666 | .tb_start = riscv_tr_tb_start, | ||
667 | .insn_start = riscv_tr_insn_start, | ||
668 | - .breakpoint_check = riscv_tr_breakpoint_check, | ||
669 | .translate_insn = riscv_tr_translate_insn, | ||
670 | .tb_stop = riscv_tr_tb_stop, | ||
671 | .disas_log = riscv_tr_disas_log, | ||
582 | diff --git a/target/rx/translate.c b/target/rx/translate.c | 672 | diff --git a/target/rx/translate.c b/target/rx/translate.c |
583 | index XXXXXXX..XXXXXXX 100644 | 673 | index XXXXXXX..XXXXXXX 100644 |
584 | --- a/target/rx/translate.c | 674 | --- a/target/rx/translate.c |
585 | +++ b/target/rx/translate.c | 675 | +++ b/target/rx/translate.c |
586 | @@ -XXX,XX +XXX,XX @@ static void rx_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) | 676 | @@ -XXX,XX +XXX,XX @@ static void rx_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) |
587 | tcg_gen_insn_start(ctx->base.pc_next); | 677 | tcg_gen_insn_start(ctx->base.pc_next); |
588 | } | 678 | } |
589 | 679 | ||
590 | -static bool rx_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 680 | -static bool rx_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, |
591 | - const CPUBreakpoint *bp) | 681 | - const CPUBreakpoint *bp) |
592 | +static int rx_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 682 | -{ |
593 | + int bp_flags) | 683 | - DisasContext *ctx = container_of(dcbase, DisasContext, base); |
684 | - | ||
685 | - /* We have hit a breakpoint - make sure PC is up-to-date */ | ||
686 | - tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next); | ||
687 | - gen_helper_debug(cpu_env); | ||
688 | - ctx->base.is_jmp = DISAS_NORETURN; | ||
689 | - ctx->base.pc_next += 1; | ||
690 | - return true; | ||
691 | -} | ||
692 | - | ||
693 | static void rx_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) | ||
594 | { | 694 | { |
595 | DisasContext *ctx = container_of(dcbase, DisasContext, base); | 695 | DisasContext *ctx = container_of(dcbase, DisasContext, base); |
596 | 696 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps rx_tr_ops = { | |
597 | @@ -XXX,XX +XXX,XX @@ static bool rx_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 697 | .init_disas_context = rx_tr_init_disas_context, |
598 | tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next); | 698 | .tb_start = rx_tr_tb_start, |
599 | gen_helper_debug(cpu_env); | 699 | .insn_start = rx_tr_insn_start, |
600 | ctx->base.is_jmp = DISAS_NORETURN; | 700 | - .breakpoint_check = rx_tr_breakpoint_check, |
601 | - ctx->base.pc_next += 1; | 701 | .translate_insn = rx_tr_translate_insn, |
602 | - return true; | 702 | .tb_stop = rx_tr_tb_stop, |
603 | + | 703 | .disas_log = rx_tr_disas_log, |
604 | + return 1; /* minimum instruction length */ | 704 | diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c |
605 | } | 705 | index XXXXXXX..XXXXXXX 100644 |
606 | 706 | --- a/target/s390x/tcg/translate.c | |
607 | static void rx_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) | 707 | +++ b/target/s390x/tcg/translate.c |
608 | diff --git a/target/s390x/translate.c b/target/s390x/translate.c | ||
609 | index XXXXXXX..XXXXXXX 100644 | ||
610 | --- a/target/s390x/translate.c | ||
611 | +++ b/target/s390x/translate.c | ||
612 | @@ -XXX,XX +XXX,XX @@ static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) | 708 | @@ -XXX,XX +XXX,XX @@ static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) |
613 | { | 709 | { |
614 | } | 710 | } |
615 | 711 | ||
616 | -static bool s390x_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 712 | -static bool s390x_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, |
617 | - const CPUBreakpoint *bp) | 713 | - const CPUBreakpoint *bp) |
618 | +static int s390x_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 714 | -{ |
619 | + int bp_flags) | 715 | - DisasContext *dc = container_of(dcbase, DisasContext, base); |
620 | { | 716 | - |
621 | DisasContext *dc = container_of(dcbase, DisasContext, base); | 717 | - /* |
622 | 718 | - * Emit an insn_start to accompany the breakpoint exception. | |
623 | @@ -XXX,XX +XXX,XX @@ static bool s390x_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 719 | - * The ILEN value is a dummy, since this does not result in |
624 | 720 | - * an s390x exception, but an internal qemu exception which | |
625 | dc->base.is_jmp = DISAS_PC_STALE; | 721 | - * brings us back to interact with the gdbstub. |
626 | dc->do_debug = true; | 722 | - */ |
723 | - tcg_gen_insn_start(dc->base.pc_next, dc->cc_op, 2); | ||
724 | - | ||
725 | - dc->base.is_jmp = DISAS_PC_STALE; | ||
726 | - dc->do_debug = true; | ||
627 | - /* The address covered by the breakpoint must be included in | 727 | - /* The address covered by the breakpoint must be included in |
628 | - [tb->pc, tb->pc + tb->size) in order to for it to be | 728 | - [tb->pc, tb->pc + tb->size) in order to for it to be |
629 | - properly cleared -- thus we increment the PC here so that | 729 | - properly cleared -- thus we increment the PC here so that |
630 | - the logic setting tb->size does the right thing. */ | 730 | - the logic setting tb->size does the right thing. */ |
631 | - dc->base.pc_next += 2; | 731 | - dc->base.pc_next += 2; |
632 | - return true; | 732 | - return true; |
633 | + | 733 | -} |
634 | + return 2; /* minimum instruction length */ | 734 | - |
635 | } | ||
636 | |||
637 | static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) | 735 | static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) |
736 | { | ||
737 | CPUS390XState *env = cs->env_ptr; | ||
738 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps s390x_tr_ops = { | ||
739 | .init_disas_context = s390x_tr_init_disas_context, | ||
740 | .tb_start = s390x_tr_tb_start, | ||
741 | .insn_start = s390x_tr_insn_start, | ||
742 | - .breakpoint_check = s390x_tr_breakpoint_check, | ||
743 | .translate_insn = s390x_tr_translate_insn, | ||
744 | .tb_stop = s390x_tr_tb_stop, | ||
745 | .disas_log = s390x_tr_disas_log, | ||
638 | diff --git a/target/sh4/translate.c b/target/sh4/translate.c | 746 | diff --git a/target/sh4/translate.c b/target/sh4/translate.c |
639 | index XXXXXXX..XXXXXXX 100644 | 747 | index XXXXXXX..XXXXXXX 100644 |
640 | --- a/target/sh4/translate.c | 748 | --- a/target/sh4/translate.c |
641 | +++ b/target/sh4/translate.c | 749 | +++ b/target/sh4/translate.c |
642 | @@ -XXX,XX +XXX,XX @@ static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) | 750 | @@ -XXX,XX +XXX,XX @@ static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) |
643 | tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags); | 751 | tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags); |
644 | } | 752 | } |
645 | 753 | ||
646 | -static bool sh4_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 754 | -static bool sh4_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, |
647 | - const CPUBreakpoint *bp) | 755 | - const CPUBreakpoint *bp) |
648 | +static int sh4_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 756 | -{ |
649 | + int bp_flags) | 757 | - DisasContext *ctx = container_of(dcbase, DisasContext, base); |
650 | { | 758 | - |
651 | DisasContext *ctx = container_of(dcbase, DisasContext, base); | 759 | - /* We have hit a breakpoint - make sure PC is up-to-date */ |
652 | 760 | - gen_save_cpu_state(ctx, true); | |
653 | @@ -XXX,XX +XXX,XX @@ static bool sh4_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 761 | - gen_helper_debug(cpu_env); |
654 | gen_save_cpu_state(ctx, true); | 762 | - ctx->base.is_jmp = DISAS_NORETURN; |
655 | gen_helper_debug(cpu_env); | ||
656 | ctx->base.is_jmp = DISAS_NORETURN; | ||
657 | - /* The address covered by the breakpoint must be included in | 763 | - /* The address covered by the breakpoint must be included in |
658 | - [tb->pc, tb->pc + tb->size) in order to for it to be | 764 | - [tb->pc, tb->pc + tb->size) in order to for it to be |
659 | - properly cleared -- thus we increment the PC here so that | 765 | - properly cleared -- thus we increment the PC here so that |
660 | - the logic setting tb->size below does the right thing. */ | 766 | - the logic setting tb->size below does the right thing. */ |
661 | - ctx->base.pc_next += 2; | 767 | - ctx->base.pc_next += 2; |
662 | - return true; | 768 | - return true; |
663 | + | 769 | -} |
664 | + return 2; /* minimum instruction length */ | 770 | - |
665 | } | ||
666 | |||
667 | static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) | 771 | static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) |
772 | { | ||
773 | CPUSH4State *env = cs->env_ptr; | ||
774 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps sh4_tr_ops = { | ||
775 | .init_disas_context = sh4_tr_init_disas_context, | ||
776 | .tb_start = sh4_tr_tb_start, | ||
777 | .insn_start = sh4_tr_insn_start, | ||
778 | - .breakpoint_check = sh4_tr_breakpoint_check, | ||
779 | .translate_insn = sh4_tr_translate_insn, | ||
780 | .tb_stop = sh4_tr_tb_stop, | ||
781 | .disas_log = sh4_tr_disas_log, | ||
668 | diff --git a/target/sparc/translate.c b/target/sparc/translate.c | 782 | diff --git a/target/sparc/translate.c b/target/sparc/translate.c |
669 | index XXXXXXX..XXXXXXX 100644 | 783 | index XXXXXXX..XXXXXXX 100644 |
670 | --- a/target/sparc/translate.c | 784 | --- a/target/sparc/translate.c |
671 | +++ b/target/sparc/translate.c | 785 | +++ b/target/sparc/translate.c |
672 | @@ -XXX,XX +XXX,XX @@ static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) | 786 | @@ -XXX,XX +XXX,XX @@ static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) |
673 | } | 787 | } |
674 | } | 788 | } |
675 | 789 | ||
676 | -static bool sparc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 790 | -static bool sparc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, |
677 | - const CPUBreakpoint *bp) | 791 | - const CPUBreakpoint *bp) |
678 | +static int sparc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 792 | -{ |
679 | + int bp_flags) | 793 | - DisasContext *dc = container_of(dcbase, DisasContext, base); |
680 | { | 794 | - |
681 | DisasContext *dc = container_of(dcbase, DisasContext, base); | 795 | - if (dc->pc != dc->base.pc_first) { |
682 | 796 | - save_state(dc); | |
683 | @@ -XXX,XX +XXX,XX @@ static bool sparc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, | 797 | - } |
684 | gen_helper_debug(cpu_env); | 798 | - gen_helper_debug(cpu_env); |
685 | tcg_gen_exit_tb(NULL, 0); | 799 | - tcg_gen_exit_tb(NULL, 0); |
686 | dc->base.is_jmp = DISAS_NORETURN; | 800 | - dc->base.is_jmp = DISAS_NORETURN; |
687 | - /* update pc_next so that the current instruction is included in tb->size */ | 801 | - /* update pc_next so that the current instruction is included in tb->size */ |
688 | - dc->base.pc_next += 4; | 802 | - dc->base.pc_next += 4; |
689 | - return true; | 803 | - return true; |
690 | + | 804 | -} |
691 | + return 4; /* minimum instruction length */ | 805 | - |
692 | } | ||
693 | |||
694 | static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) | 806 | static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) |
807 | { | ||
808 | DisasContext *dc = container_of(dcbase, DisasContext, base); | ||
809 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps sparc_tr_ops = { | ||
810 | .init_disas_context = sparc_tr_init_disas_context, | ||
811 | .tb_start = sparc_tr_tb_start, | ||
812 | .insn_start = sparc_tr_insn_start, | ||
813 | - .breakpoint_check = sparc_tr_breakpoint_check, | ||
814 | .translate_insn = sparc_tr_translate_insn, | ||
815 | .tb_stop = sparc_tr_tb_stop, | ||
816 | .disas_log = sparc_tr_disas_log, | ||
695 | diff --git a/target/tricore/translate.c b/target/tricore/translate.c | 817 | diff --git a/target/tricore/translate.c b/target/tricore/translate.c |
696 | index XXXXXXX..XXXXXXX 100644 | 818 | index XXXXXXX..XXXXXXX 100644 |
697 | --- a/target/tricore/translate.c | 819 | --- a/target/tricore/translate.c |
698 | +++ b/target/tricore/translate.c | 820 | +++ b/target/tricore/translate.c |
699 | @@ -XXX,XX +XXX,XX @@ static void tricore_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) | 821 | @@ -XXX,XX +XXX,XX @@ static void tricore_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) |
700 | tcg_gen_insn_start(ctx->base.pc_next); | 822 | tcg_gen_insn_start(ctx->base.pc_next); |
701 | } | 823 | } |
702 | 824 | ||
703 | -static bool tricore_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 825 | -static bool tricore_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, |
704 | - const CPUBreakpoint *bp) | 826 | - const CPUBreakpoint *bp) |
705 | +static int tricore_tr_breakpoint_check(DisasContextBase *dcbase, | 827 | -{ |
706 | + CPUState *cpu, int bp_flags) | 828 | - DisasContext *ctx = container_of(dcbase, DisasContext, base); |
707 | { | 829 | - generate_qemu_excp(ctx, EXCP_DEBUG); |
708 | DisasContext *ctx = container_of(dcbase, DisasContext, base); | ||
709 | generate_qemu_excp(ctx, EXCP_DEBUG); | ||
710 | - /* | 830 | - /* |
711 | - * The address covered by the breakpoint must be included in | 831 | - * The address covered by the breakpoint must be included in |
712 | - * [tb->pc, tb->pc + tb->size) in order to for it to be | 832 | - * [tb->pc, tb->pc + tb->size) in order to for it to be |
713 | - * properly cleared -- thus we increment the PC here so that | 833 | - * properly cleared -- thus we increment the PC here so that |
714 | - * the logic setting tb->size below does the right thing. | 834 | - * the logic setting tb->size below does the right thing. |
715 | - */ | 835 | - */ |
716 | - ctx->base.pc_next += 4; | 836 | - ctx->base.pc_next += 4; |
717 | - return true; | 837 | - return true; |
718 | + return 4; /* minimum instruction length */ | 838 | -} |
719 | } | 839 | - |
720 | |||
721 | static bool insn_crosses_page(CPUTriCoreState *env, DisasContext *ctx) | 840 | static bool insn_crosses_page(CPUTriCoreState *env, DisasContext *ctx) |
841 | { | ||
842 | /* | ||
843 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps tricore_tr_ops = { | ||
844 | .init_disas_context = tricore_tr_init_disas_context, | ||
845 | .tb_start = tricore_tr_tb_start, | ||
846 | .insn_start = tricore_tr_insn_start, | ||
847 | - .breakpoint_check = tricore_tr_breakpoint_check, | ||
848 | .translate_insn = tricore_tr_translate_insn, | ||
849 | .tb_stop = tricore_tr_tb_stop, | ||
850 | .disas_log = tricore_tr_disas_log, | ||
722 | diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c | 851 | diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c |
723 | index XXXXXXX..XXXXXXX 100644 | 852 | index XXXXXXX..XXXXXXX 100644 |
724 | --- a/target/xtensa/translate.c | 853 | --- a/target/xtensa/translate.c |
725 | +++ b/target/xtensa/translate.c | 854 | +++ b/target/xtensa/translate.c |
726 | @@ -XXX,XX +XXX,XX @@ static void xtensa_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) | 855 | @@ -XXX,XX +XXX,XX @@ static void xtensa_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) |
727 | tcg_gen_insn_start(dcbase->pc_next); | 856 | tcg_gen_insn_start(dcbase->pc_next); |
728 | } | 857 | } |
729 | 858 | ||
730 | -static bool xtensa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 859 | -static bool xtensa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, |
731 | - const CPUBreakpoint *bp) | 860 | - const CPUBreakpoint *bp) |
732 | +static int xtensa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, | 861 | -{ |
733 | + int bp_flags) | 862 | - DisasContext *dc = container_of(dcbase, DisasContext, base); |
734 | { | 863 | - |
735 | DisasContext *dc = container_of(dcbase, DisasContext, base); | 864 | - tcg_gen_movi_i32(cpu_pc, dc->base.pc_next); |
736 | 865 | - gen_exception(dc, EXCP_DEBUG); | |
737 | tcg_gen_movi_i32(cpu_pc, dc->base.pc_next); | 866 | - dc->base.is_jmp = DISAS_NORETURN; |
738 | gen_exception(dc, EXCP_DEBUG); | ||
739 | dc->base.is_jmp = DISAS_NORETURN; | ||
740 | - /* The address covered by the breakpoint must be included in | 867 | - /* The address covered by the breakpoint must be included in |
741 | - [tb->pc, tb->pc + tb->size) in order to for it to be | 868 | - [tb->pc, tb->pc + tb->size) in order to for it to be |
742 | - properly cleared -- thus we increment the PC here so that | 869 | - properly cleared -- thus we increment the PC here so that |
743 | - the logic setting tb->size below does the right thing. */ | 870 | - the logic setting tb->size below does the right thing. */ |
744 | - dc->base.pc_next += 2; | 871 | - dc->base.pc_next += 2; |
745 | - return true; | 872 | - return true; |
746 | + | 873 | -} |
747 | + return 2; /* minimum instruction length */ | 874 | - |
748 | } | ||
749 | |||
750 | static void xtensa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) | 875 | static void xtensa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) |
876 | { | ||
877 | DisasContext *dc = container_of(dcbase, DisasContext, base); | ||
878 | @@ -XXX,XX +XXX,XX @@ static const TranslatorOps xtensa_translator_ops = { | ||
879 | .init_disas_context = xtensa_tr_init_disas_context, | ||
880 | .tb_start = xtensa_tr_tb_start, | ||
881 | .insn_start = xtensa_tr_insn_start, | ||
882 | - .breakpoint_check = xtensa_tr_breakpoint_check, | ||
883 | .translate_insn = xtensa_tr_translate_insn, | ||
884 | .tb_stop = xtensa_tr_tb_stop, | ||
885 | .disas_log = xtensa_tr_disas_log, | ||
751 | -- | 886 | -- |
752 | 2.25.1 | 887 | 2.25.1 |
753 | 888 | ||
754 | 889 | diff view generated by jsdifflib |
1 | The access internal to tb_cflags() is atomic. | 1 | The access internal to tb_cflags() is atomic. |
---|---|---|---|
2 | Avoid re-reading it as such for the multiple uses. | 2 | Avoid re-reading it as such for the multiple uses. |
3 | 3 | ||
4 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
5 | --- | 6 | --- |
6 | accel/tcg/translator.c | 9 ++++----- | 7 | accel/tcg/translator.c | 9 ++++----- |
7 | 1 file changed, 4 insertions(+), 5 deletions(-) | 8 | 1 file changed, 4 insertions(+), 5 deletions(-) |
8 | 9 | ||
... | ... | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | Set CF_SINGLE_STEP when single-stepping is enabled. | ||
2 | This avoids the need to flush all tb's when turning | ||
3 | single-stepping on or off. | ||
1 | 4 | ||
5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
6 | --- | ||
7 | include/exec/exec-all.h | 1 + | ||
8 | accel/tcg/cpu-exec.c | 7 ++++++- | ||
9 | accel/tcg/translate-all.c | 4 ---- | ||
10 | accel/tcg/translator.c | 7 +------ | ||
11 | cpu.c | 4 ---- | ||
12 | 5 files changed, 8 insertions(+), 15 deletions(-) | ||
13 | |||
14 | diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/include/exec/exec-all.h | ||
17 | +++ b/include/exec/exec-all.h | ||
18 | @@ -XXX,XX +XXX,XX @@ struct TranslationBlock { | ||
19 | #define CF_COUNT_MASK 0x000001ff | ||
20 | #define CF_NO_GOTO_TB 0x00000200 /* Do not chain with goto_tb */ | ||
21 | #define CF_NO_GOTO_PTR 0x00000400 /* Do not chain with goto_ptr */ | ||
22 | +#define CF_SINGLE_STEP 0x00000800 /* gdbstub single-step in effect */ | ||
23 | #define CF_LAST_IO 0x00008000 /* Last insn may be an IO access. */ | ||
24 | #define CF_MEMI_ONLY 0x00010000 /* Only instrument memory ops */ | ||
25 | #define CF_USE_ICOUNT 0x00020000 | ||
26 | diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c | ||
27 | index XXXXXXX..XXXXXXX 100644 | ||
28 | --- a/accel/tcg/cpu-exec.c | ||
29 | +++ b/accel/tcg/cpu-exec.c | ||
30 | @@ -XXX,XX +XXX,XX @@ uint32_t curr_cflags(CPUState *cpu) | ||
31 | uint32_t cflags = cpu->tcg_cflags; | ||
32 | |||
33 | /* | ||
34 | + * Record gdb single-step. We should be exiting the TB by raising | ||
35 | + * EXCP_DEBUG, but to simplify other tests, disable chaining too. | ||
36 | + * | ||
37 | * For singlestep and -d nochain, suppress goto_tb so that | ||
38 | * we can log -d cpu,exec after every TB. | ||
39 | */ | ||
40 | - if (singlestep) { | ||
41 | + if (unlikely(cpu->singlestep_enabled)) { | ||
42 | + cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR | CF_SINGLE_STEP | 1; | ||
43 | + } else if (singlestep) { | ||
44 | cflags |= CF_NO_GOTO_TB | 1; | ||
45 | } else if (qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) { | ||
46 | cflags |= CF_NO_GOTO_TB; | ||
47 | diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c | ||
48 | index XXXXXXX..XXXXXXX 100644 | ||
49 | --- a/accel/tcg/translate-all.c | ||
50 | +++ b/accel/tcg/translate-all.c | ||
51 | @@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu, | ||
52 | } | ||
53 | QEMU_BUILD_BUG_ON(CF_COUNT_MASK + 1 != TCG_MAX_INSNS); | ||
54 | |||
55 | - if (cpu->singlestep_enabled) { | ||
56 | - max_insns = 1; | ||
57 | - } | ||
58 | - | ||
59 | buffer_overflow: | ||
60 | tb = tcg_tb_alloc(tcg_ctx); | ||
61 | if (unlikely(!tb)) { | ||
62 | diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c | ||
63 | index XXXXXXX..XXXXXXX 100644 | ||
64 | --- a/accel/tcg/translator.c | ||
65 | +++ b/accel/tcg/translator.c | ||
66 | @@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest) | ||
67 | return false; | ||
68 | } | ||
69 | |||
70 | - /* Suppress goto_tb in the case of single-steping. */ | ||
71 | - if (db->singlestep_enabled) { | ||
72 | - return false; | ||
73 | - } | ||
74 | - | ||
75 | /* Check for the dest on the same page as the start of the TB. */ | ||
76 | return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0; | ||
77 | } | ||
78 | @@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, | ||
79 | db->is_jmp = DISAS_NEXT; | ||
80 | db->num_insns = 0; | ||
81 | db->max_insns = max_insns; | ||
82 | - db->singlestep_enabled = cpu->singlestep_enabled; | ||
83 | + db->singlestep_enabled = cflags & CF_SINGLE_STEP; | ||
84 | |||
85 | ops->init_disas_context(db, cpu); | ||
86 | tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ | ||
87 | diff --git a/cpu.c b/cpu.c | ||
88 | index XXXXXXX..XXXXXXX 100644 | ||
89 | --- a/cpu.c | ||
90 | +++ b/cpu.c | ||
91 | @@ -XXX,XX +XXX,XX @@ void cpu_single_step(CPUState *cpu, int enabled) | ||
92 | cpu->singlestep_enabled = enabled; | ||
93 | if (kvm_enabled()) { | ||
94 | kvm_update_guest_debug(cpu, 0); | ||
95 | - } else { | ||
96 | - /* must flush all the translated code to avoid inconsistencies */ | ||
97 | - /* XXX: only flush what is necessary */ | ||
98 | - tb_flush(cpu); | ||
99 | } | ||
100 | trace_breakpoint_singlestep(cpu->cpu_index, enabled); | ||
101 | } | ||
102 | -- | ||
103 | 2.25.1 | ||
104 | |||
105 | diff view generated by jsdifflib |