aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2015-09-15 11:45:06 -0700
committerEduardo Habkost <ehabkost@redhat.com>2015-10-02 16:22:01 -0300
commitba4b5c65a98ea91dc3b13e42dd9404808c999dda (patch)
tree99eeeb2892e34a462f7885f21767468c38125bf1
parent5114e8422201190c3e2e1a4d77e38ad70cf001d2 (diff)
target-i386: Move breakpoint related functions to new file
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> Signed-off-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
-rw-r--r--target-i386/Makefile.objs2
-rw-r--r--target-i386/bpt_helper.c182
-rw-r--r--target-i386/helper.c128
-rw-r--r--target-i386/misc_helper.c34
4 files changed, 183 insertions, 163 deletions
diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs
index 3da413e8bd..437d9975b9 100644
--- a/target-i386/Makefile.objs
+++ b/target-i386/Makefile.objs
@@ -1,4 +1,4 @@
-obj-y += translate.o helper.o cpu.o
+obj-y += translate.o helper.o cpu.o bpt_helper.o
obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o
obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o
obj-y += gdbstub.o
diff --git a/target-i386/bpt_helper.c b/target-i386/bpt_helper.c
new file mode 100644
index 0000000000..6f6537d58c
--- /dev/null
+++ b/target-i386/bpt_helper.c
@@ -0,0 +1,182 @@
+/*
+ * i386 breakpoint helpers
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "exec/helper-proto.h"
+
+
+void hw_breakpoint_insert(CPUX86State *env, int index)
+{
+ CPUState *cs = CPU(x86_env_get_cpu(env));
+ int type = 0, err = 0;
+
+ switch (hw_breakpoint_type(env->dr[7], index)) {
+ case DR7_TYPE_BP_INST:
+ if (hw_breakpoint_enabled(env->dr[7], index)) {
+ err = cpu_breakpoint_insert(cs, env->dr[index], BP_CPU,
+ &env->cpu_breakpoint[index]);
+ }
+ break;
+ case DR7_TYPE_DATA_WR:
+ type = BP_CPU | BP_MEM_WRITE;
+ break;
+ case DR7_TYPE_IO_RW:
+ /* No support for I/O watchpoints yet */
+ break;
+ case DR7_TYPE_DATA_RW:
+ type = BP_CPU | BP_MEM_ACCESS;
+ break;
+ }
+
+ if (type != 0) {
+ err = cpu_watchpoint_insert(cs, env->dr[index],
+ hw_breakpoint_len(env->dr[7], index),
+ type, &env->cpu_watchpoint[index]);
+ }
+
+ if (err) {
+ env->cpu_breakpoint[index] = NULL;
+ }
+}
+
+void hw_breakpoint_remove(CPUX86State *env, int index)
+{
+ CPUState *cs;
+
+ if (!env->cpu_breakpoint[index]) {
+ return;
+ }
+ cs = CPU(x86_env_get_cpu(env));
+ switch (hw_breakpoint_type(env->dr[7], index)) {
+ case DR7_TYPE_BP_INST:
+ if (hw_breakpoint_enabled(env->dr[7], index)) {
+ cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[index]);
+ }
+ break;
+ case DR7_TYPE_DATA_WR:
+ case DR7_TYPE_DATA_RW:
+ cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]);
+ break;
+ case DR7_TYPE_IO_RW:
+ /* No support for I/O watchpoints yet */
+ break;
+ }
+}
+
+bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update)
+{
+ target_ulong dr6;
+ int reg;
+ bool hit_enabled = false;
+
+ dr6 = env->dr[6] & ~0xf;
+ for (reg = 0; reg < DR7_MAX_BP; reg++) {
+ bool bp_match = false;
+ bool wp_match = false;
+
+ switch (hw_breakpoint_type(env->dr[7], reg)) {
+ case DR7_TYPE_BP_INST:
+ if (env->dr[reg] == env->eip) {
+ bp_match = true;
+ }
+ break;
+ case DR7_TYPE_DATA_WR:
+ case DR7_TYPE_DATA_RW:
+ if (env->cpu_watchpoint[reg] &&
+ env->cpu_watchpoint[reg]->flags & BP_WATCHPOINT_HIT) {
+ wp_match = true;
+ }
+ break;
+ case DR7_TYPE_IO_RW:
+ break;
+ }
+ if (bp_match || wp_match) {
+ dr6 |= 1 << reg;
+ if (hw_breakpoint_enabled(env->dr[7], reg)) {
+ hit_enabled = true;
+ }
+ }
+ }
+
+ if (hit_enabled || force_dr6_update) {
+ env->dr[6] = dr6;
+ }
+
+ return hit_enabled;
+}
+
+void breakpoint_handler(CPUState *cs)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+ CPUBreakpoint *bp;
+
+ if (cs->watchpoint_hit) {
+ if (cs->watchpoint_hit->flags & BP_CPU) {
+ cs->watchpoint_hit = NULL;
+ if (check_hw_breakpoints(env, false)) {
+ raise_exception(env, EXCP01_DB);
+ } else {
+ cpu_resume_from_signal(cs, NULL);
+ }
+ }
+ } else {
+ QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
+ if (bp->pc == env->eip) {
+ if (bp->flags & BP_CPU) {
+ check_hw_breakpoints(env, true);
+ raise_exception(env, EXCP01_DB);
+ }
+ break;
+ }
+ }
+ }
+}
+
+void helper_single_step(CPUX86State *env)
+{
+#ifndef CONFIG_USER_ONLY
+ check_hw_breakpoints(env, true);
+ env->dr[6] |= DR6_BS;
+#endif
+ raise_exception(env, EXCP01_DB);
+}
+
+void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0)
+{
+#ifndef CONFIG_USER_ONLY
+ int i;
+
+ if (reg < 4) {
+ hw_breakpoint_remove(env, reg);
+ env->dr[reg] = t0;
+ hw_breakpoint_insert(env, reg);
+ } else if (reg == 7) {
+ for (i = 0; i < DR7_MAX_BP; i++) {
+ hw_breakpoint_remove(env, i);
+ }
+ env->dr[7] = t0;
+ for (i = 0; i < DR7_MAX_BP; i++) {
+ hw_breakpoint_insert(env, i);
+ }
+ } else {
+ env->dr[reg] = t0;
+ }
+#endif
+}
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 9364d96f96..d18be95c3f 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1096,134 +1096,6 @@ out:
return pte | page_offset;
}
-void hw_breakpoint_insert(CPUX86State *env, int index)
-{
- CPUState *cs = CPU(x86_env_get_cpu(env));
- int type = 0, err = 0;
-
- switch (hw_breakpoint_type(env->dr[7], index)) {
- case DR7_TYPE_BP_INST:
- if (hw_breakpoint_enabled(env->dr[7], index)) {
- err = cpu_breakpoint_insert(cs, env->dr[index], BP_CPU,
- &env->cpu_breakpoint[index]);
- }
- break;
- case DR7_TYPE_DATA_WR:
- type = BP_CPU | BP_MEM_WRITE;
- break;
- case DR7_TYPE_IO_RW:
- /* No support for I/O watchpoints yet */
- break;
- case DR7_TYPE_DATA_RW:
- type = BP_CPU | BP_MEM_ACCESS;
- break;
- }
-
- if (type != 0) {
- err = cpu_watchpoint_insert(cs, env->dr[index],
- hw_breakpoint_len(env->dr[7], index),
- type, &env->cpu_watchpoint[index]);
- }
-
- if (err) {
- env->cpu_breakpoint[index] = NULL;
- }
-}
-
-void hw_breakpoint_remove(CPUX86State *env, int index)
-{
- CPUState *cs;
-
- if (!env->cpu_breakpoint[index]) {
- return;
- }
- cs = CPU(x86_env_get_cpu(env));
- switch (hw_breakpoint_type(env->dr[7], index)) {
- case DR7_TYPE_BP_INST:
- if (hw_breakpoint_enabled(env->dr[7], index)) {
- cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[index]);
- }
- break;
- case DR7_TYPE_DATA_WR:
- case DR7_TYPE_DATA_RW:
- cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]);
- break;
- case DR7_TYPE_IO_RW:
- /* No support for I/O watchpoints yet */
- break;
- }
-}
-
-bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update)
-{
- target_ulong dr6;
- int reg;
- bool hit_enabled = false;
-
- dr6 = env->dr[6] & ~0xf;
- for (reg = 0; reg < DR7_MAX_BP; reg++) {
- bool bp_match = false;
- bool wp_match = false;
-
- switch (hw_breakpoint_type(env->dr[7], reg)) {
- case DR7_TYPE_BP_INST:
- if (env->dr[reg] == env->eip) {
- bp_match = true;
- }
- break;
- case DR7_TYPE_DATA_WR:
- case DR7_TYPE_DATA_RW:
- if (env->cpu_watchpoint[reg] &&
- env->cpu_watchpoint[reg]->flags & BP_WATCHPOINT_HIT) {
- wp_match = true;
- }
- break;
- case DR7_TYPE_IO_RW:
- break;
- }
- if (bp_match || wp_match) {
- dr6 |= 1 << reg;
- if (hw_breakpoint_enabled(env->dr[7], reg)) {
- hit_enabled = true;
- }
- }
- }
-
- if (hit_enabled || force_dr6_update) {
- env->dr[6] = dr6;
- }
-
- return hit_enabled;
-}
-
-void breakpoint_handler(CPUState *cs)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- CPUBreakpoint *bp;
-
- if (cs->watchpoint_hit) {
- if (cs->watchpoint_hit->flags & BP_CPU) {
- cs->watchpoint_hit = NULL;
- if (check_hw_breakpoints(env, false)) {
- raise_exception(env, EXCP01_DB);
- } else {
- cpu_resume_from_signal(cs, NULL);
- }
- }
- } else {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == env->eip) {
- if (bp->flags & BP_CPU) {
- check_hw_breakpoints(env, true);
- raise_exception(env, EXCP01_DB);
- }
- break;
- }
- }
- }
-}
-
typedef struct MCEInjectionParams {
Monitor *mon;
X86CPU *cpu;
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index 6bfc7dd24e..13bd4f5eec 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -95,15 +95,6 @@ void helper_into(CPUX86State *env, int next_eip_addend)
}
}
-void helper_single_step(CPUX86State *env)
-{
-#ifndef CONFIG_USER_ONLY
- check_hw_breakpoints(env, true);
- env->dr[6] |= DR6_BS;
-#endif
- raise_exception(env, EXCP01_DB);
-}
-
void helper_cpuid(CPUX86State *env)
{
uint32_t eax, ebx, ecx, edx;
@@ -127,10 +118,6 @@ target_ulong helper_read_crN(CPUX86State *env, int reg)
void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
{
}
-
-void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0)
-{
-}
#else
target_ulong helper_read_crN(CPUX86State *env, int reg)
{
@@ -176,27 +163,6 @@ void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
break;
}
}
-
-void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0)
-{
- int i;
-
- if (reg < 4) {
- hw_breakpoint_remove(env, reg);
- env->dr[reg] = t0;
- hw_breakpoint_insert(env, reg);
- } else if (reg == 7) {
- for (i = 0; i < DR7_MAX_BP; i++) {
- hw_breakpoint_remove(env, i);
- }
- env->dr[7] = t0;
- for (i = 0; i < DR7_MAX_BP; i++) {
- hw_breakpoint_insert(env, i);
- }
- } else {
- env->dr[reg] = t0;
- }
-}
#endif
void helper_lmsw(CPUX86State *env, target_ulong t0)