diff mbox

[24028/24028] Evaluate breakpoint condition on target.Mechanism: translate gdb bytecode to TCG code and add to the translation block. Most of code is located in the new file translate-gdbagent.*. OPC_MAX_SIZE - size of translation buffer - was increased

Message ID 1361455371-31255-1-git-send-email-anna_neiman@mentor.com
State New
Headers show

Commit Message

Anna Neiman Feb. 21, 2013, 2:02 p.m. UTC
Signed-off-by: Anna Neiman <anna_neiman@mentor.com>
---
 Makefile.target               |    2 +-
 cpu-exec.c                    |   19 +-
 exec.c                        |   17 +-
 gdbstub.c                     |   63 ++-
 include/exec/cpu-all.h        |    1 +
 include/exec/cpu-defs.h       |   24 ++
 include/exec/exec-all.h       |    2 +-
 target-alpha/translate.c      |    2 +-
 target-arm/translate.c        |   31 +-
 target-cris/translate.c       |    2 +-
 target-i386/helper.c          |    2 +-
 target-i386/translate.c       |    2 +-
 target-lm32/translate.c       |    2 +-
 target-m68k/translate.c       |    2 +-
 target-microblaze/translate.c |    2 +-
 target-mips/translate.c       |    2 +-
 target-openrisc/translate.c   |    2 +-
 target-ppc/translate.c        |    2 +-
 target-s390x/translate.c      |    2 +-
 target-sh4/translate.c        |    2 +-
 target-sparc/translate.c      |    3 +-
 target-unicore32/translate.c  |    2 +-
 target-xtensa/translate.c     |    2 +-
 tcg/tcg-op.h                  |   10 +
 tcg/tcg.h                     |    6 +
 translate-all.c               |    7 +
 translate-all.h               |    2 +
 translate-gdbagent.c          |  922 +++++++++++++++++++++++++++++++++++++++++
 translate-gdbagent.h          |   49 +++
 29 files changed, 1155 insertions(+), 31 deletions(-)
 create mode 100644 translate-gdbagent.c
 create mode 100644 translate-gdbagent.h

Comments

Jan Kiszka Feb. 21, 2013, 2:29 p.m. UTC | #1
<snip very long patch>

I just hope the other 24027 patches won't come over us in the next
second. ;)

Please split the patch, at least into
 - prepare infrastructure for feature (that might also be several steps)
 - add feature (or features, then also in several steps)

Thanks,
Jan
Markus Armbruster Feb. 21, 2013, 2:49 p.m. UTC | #2
Jan Kiszka <jan.kiszka@siemens.com> writes:

> <snip very long patch>
>
> I just hope the other 24027 patches won't come over us in the next
> second. ;)
>
> Please split the patch, at least into
>  - prepare infrastructure for feature (that might also be several steps)
>  - add feature (or features, then also in several steps)

Additionally, please write commit messages in the standard format.

See http://wiki.qemu.org/Contribute/SubmitAPatch
and section "The canonical patch format" in
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob_plain;f=Documentation/SubmittingPatches;hb=HEAD
Andreas Färber Feb. 21, 2013, 5:06 p.m. UTC | #3
Anna,

Am 21.02.2013 15:29, schrieb Jan Kiszka:
> <snip very long patch>
> 
> I just hope the other 24027 patches won't come over us in the next
> second. ;)
> 
> Please split the patch, at least into
>  - prepare infrastructure for feature (that might also be several steps)
>  - add feature (or features, then also in several steps)

+1

Further please be aware that there are ongoing CPUState refactorings:
- Adding target-independent fields to CPU_COMMON is undesired. Please
add to include/qom/cpu.h CPUState whenever possible.
- We are targetting to allow compiling multiple targets into one
executable, so exposing static cpu_env variables per target is a
"regression". Please rather move cpu_env to one central file
(qom/cpu.c?) and let targets access it as extern (reverse direction).
- Your patch will not apply to qemu.git, current_tb for instance was
moved from CPU_COMMON to CPUState on Monday. Please always rebase before
sending.

I don't see a need to name fields in either CPU_COMMON or CPUState
qemu_something.

Identifiers starting with underscore are reserved in C99 and should not
be used (translate-gdbagent.h guard).

Please CC me on v2, part of this should go through my qom-cpu queue or
at least be coordinated.

Thanks,
Andreas
Paul Brook Feb. 21, 2013, 8:10 p.m. UTC | #4
In addition to the comments others made about patch formatting, etc:

> +            /* conditional breakpoint evaluation on target*/
> +            pstrcat(buf, sizeof(buf), ";ConditionalBreakpoints+");

I'm pretty sure this is a lie for most targets, given later on we have:

> +#if defined(TARGET_ARM)
> +    cpu_get_reg_var_func = cpu_get_reg_var_arm;
> +#else
> +    cpu_get_reg_var_func = 0;
> +#endif

> +                        for (i = 0 ; i < bp_cond_len ; i++) {
> +                            if (!isxdigit(*p) || !isxdigit(*(p + 1))) {
> +                                bp_cond_len = 0 ;
> +                                g_free(bp_cond_expr);
> +                                bp_cond_expr = NULL;
> +                                perror("Error in breakpoint condition");

perror is the wrong way to report a malformed gdb command.

> +#if TARGET_LONG_SIZE == 4
> +typedef float target_double;
> +#else /* TARGET_LONG_SIZE == 8 */
> +typedef double target_double;
> +#endif

This clearly has nothing to do with the target double precision floating point 
type.

> +    int qemu_rw_debug_flag;

This appears to be a write-only variable.

> +#define BP_AGENT_MAX_COND_SIZE 1024

By my reading this isn't the maximim size, it's the maximum stack depth.

> +void cpu_get_reg_var_arm(TCGv var, int reg)
> +{
> +    tcg_gen_mov_i32(var, cpu_R[reg]);
> +}

Looks like it will break horribly when the user requests anything other than 
r0-r15.  And r15 is probably also wrong.

> +            bswap16(val);

Clearly wrong.

> +            fprintf(stderr,
> +                    "GDB agent: const 64 is not supported for 32 bit

This is not a good way to report user errors.  Several other occurances.

> +static target_long bp_agent_get_arg(const uint8_t *cond_exp,
>...
> +    case 4:
> +    default:

I'd be amazed if this default case is correct.

> +    /*for case error , ex.buffer overloading -
> +      need to set labels anyway in order to avoid segmentation fault  */

Sounds like you're failing to check for errors somewhere else.
Peter Maydell Feb. 21, 2013, 9:28 p.m. UTC | #5
On 21 February 2013 14:02, Anna Neiman <anna_neiman@mentor.com> wrote:
> +#if defined(TARGET_ARM)
> +    cpu_get_reg_var_func = cpu_get_reg_var_arm;
> +#else
> +    cpu_get_reg_var_func = 0;
> +#endif

No new for-each-target #ifdef ladders, please.
Consider also whether you can abstract away some of the
TARGET_LONG ifdefs.

You need to look up what the C spec says about local variable
values after longjmp() :-)

Some of this patch is touching parts of QEMU which are critical
and hard to understand, so you'll need to provide good patch
commit messages to convince us that your changes are correct
and safe.

Strong agreement with other review comments about splitting the
patch and that just exposing every target's cpu_env local variable
is a really bad idea.

thanks
-- PMM
diff mbox

Patch

diff --git a/Makefile.target b/Makefile.target
index 760da1e..ed31f24 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -66,7 +66,7 @@  all: $(PROGS) stap
 
 #########################################################
 # cpu emulator library
-obj-y = exec.o translate-all.o cpu-exec.o
+obj-y = exec.o translate-all.o translate-gdbagent.o  cpu-exec.o
 obj-y += tcg/tcg.o tcg/optimize.o
 obj-$(CONFIG_TCG_INTERPRETER) += tci.o
 obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o
diff --git a/cpu-exec.c b/cpu-exec.c
index ff9a884..9347791 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -52,7 +52,8 @@  void cpu_resume_from_signal(CPUArchState *env, void *puc)
 /* Execute the code without caching the generated code. An interpreter
    could be used if available. */
 static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
-                             TranslationBlock *orig_tb)
+                             TranslationBlock *orig_tb,
+                             int prev_rw_debug_flag)
 {
     tcg_target_ulong next_tb;
     TranslationBlock *tb;
@@ -66,8 +67,10 @@  static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
                      max_cycles);
     env->current_tb = tb;
     /* execute the generated code */
+    env->qemu_rw_debug_flag = 0;
     next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
     env->current_tb = NULL;
+    env->qemu_rw_debug_flag = prev_rw_debug_flag;
 
     if ((next_tb & 3) == 2) {
         /* Restore PC.  This may happen if async event occurs before
@@ -184,6 +187,7 @@  int cpu_exec(CPUArchState *env)
     TranslationBlock *tb;
     uint8_t *tc_ptr;
     tcg_target_ulong next_tb;
+    int prev_rw_debug_flag = env->qemu_rw_debug_flag;
 
     if (env->halted) {
         if (!cpu_has_work(cpu)) {
@@ -348,7 +352,10 @@  int cpu_exec(CPUArchState *env)
                     }
 #elif defined(TARGET_PPC)
                     if ((interrupt_request & CPU_INTERRUPT_RESET)) {
+                        int saved_debug_flag = env->qemu_rw_debug_flag;
+                        env->qemu_rw_debug_flag = 0;
                         cpu_reset(cpu);
+                        env->qemu_rw_debug_flag = saved_debug_flag;
                     }
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                         ppc_hw_interrupt(env);
@@ -594,7 +601,13 @@  int cpu_exec(CPUArchState *env)
                 if (likely(!env->exit_request)) {
                     tc_ptr = tb->tc_ptr;
                     /* execute the generated code */
+
+                    prev_rw_debug_flag = env->qemu_rw_debug_flag;
+                    env->qemu_rw_debug_flag = 0;
+
                     next_tb = tcg_qemu_tb_exec(env, tc_ptr);
+                    env->qemu_rw_debug_flag = prev_rw_debug_flag;
+
                     if ((next_tb & 3) == 2) {
                         /* Instruction counter expired.  */
                         int insns_left;
@@ -615,7 +628,8 @@  int cpu_exec(CPUArchState *env)
                         } else {
                             if (insns_left > 0) {
                                 /* Execute remaining instructions.  */
-                                cpu_exec_nocache(env, insns_left, tb);
+                                cpu_exec_nocache(env, insns_left, tb,
+                                                 prev_rw_debug_flag);
                             }
                             env->exception_index = EXCP_INTERRUPT;
                             next_tb = 0;
@@ -631,6 +645,7 @@  int cpu_exec(CPUArchState *env)
             /* Reload env after longjmp - the compiler may have smashed all
              * local variables as longjmp is marked 'noreturn'. */
             env = cpu_single_env;
+            env->qemu_rw_debug_flag = prev_rw_debug_flag;
         }
     } /* for(;;) */
 
diff --git a/exec.c b/exec.c
index b85508b..d96815b 100644
--- a/exec.c
+++ b/exec.c
@@ -295,6 +295,7 @@  void cpu_exec_init(CPUArchState *env)
     register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
                     cpu_save, cpu_load, env);
 #endif
+    env->qemu_rw_debug_flag = 1;
 }
 
 #if defined(TARGET_HAS_ICE)
@@ -398,6 +399,7 @@  void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
 
 /* Add a breakpoint.  */
 int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
+                          long cond_len, uint8_t *cond_exp,
                           CPUBreakpoint **breakpoint)
 {
 #if defined(TARGET_HAS_ICE)
@@ -407,6 +409,13 @@  int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
 
     bp->pc = pc;
     bp->flags = flags;
+    bp->cond_len = cond_len;
+    if (cond_exp == NULL || cond_len == 0) {
+        bp->cond_exp = NULL;
+    } else {
+        bp->cond_exp = g_malloc(sizeof(uint8_t) *  cond_len);
+        memcpy(bp->cond_exp, cond_exp, sizeof(uint8_t) *  cond_len);
+    }
 
     /* keep all GDB-injected breakpoints in front */
     if (flags & BP_GDB)
@@ -450,6 +459,11 @@  void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
 
     breakpoint_invalidate(env, breakpoint->pc);
 
+    if (breakpoint->cond_len != 0 && breakpoint->cond_exp != NULL) {
+        g_free(breakpoint->cond_exp);
+    }
+
+
     g_free(breakpoint);
 #endif
 }
@@ -549,7 +563,8 @@  CPUArchState *cpu_copy(CPUArchState *env)
     QTAILQ_INIT(&env->watchpoints);
 #if defined(TARGET_HAS_ICE)
     QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
-        cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
+        cpu_breakpoint_insert(new_env, bp->pc, bp->flags,
+                              bp->cond_len, bp->cond_exp, NULL);
     }
     QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
         cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
diff --git a/gdbstub.c b/gdbstub.c
index 6cd26f1..c709154 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -42,6 +42,8 @@ 
 #include "sysemu/kvm.h"
 #include "qemu/bitops.h"
 
+#include "translate-gdbagent.h"
+
 #ifndef TARGET_CPU_MEMORY_RW_DEBUG
 static inline int target_memory_rw_debug(CPUArchState *env, target_ulong addr,
                                          uint8_t *buf, int len, int is_write)
@@ -1941,7 +1943,8 @@  static const int xlat_gdb_type[] = {
 };
 #endif
 
-static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
+static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type,
+                                 long cond_len, uint8_t *cond_exp)
 {
     CPUArchState *env;
     int err = 0;
@@ -1953,7 +1956,8 @@  static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
     case GDB_BREAKPOINT_SW:
     case GDB_BREAKPOINT_HW:
         for (env = first_cpu; env != NULL; env = env->next_cpu) {
-            err = cpu_breakpoint_insert(env, addr, BP_GDB, NULL);
+            err = cpu_breakpoint_insert(env, addr, BP_GDB,
+                                        cond_len,  cond_exp,  NULL);
             if (err)
                 break;
         }
@@ -2087,6 +2091,10 @@  static int gdb_handle_packet(GDBState *s, const char *line_buf)
     uint8_t *registers;
     target_ulong addr, len;
 
+    uint8_t *bp_cond_expr = NULL;
+    int bp_cond_len = 0;
+    int i = 0 ;
+
 #ifdef DEBUG_GDB
     printf("command='%s'\n", line_buf);
 #endif
@@ -2308,16 +2316,57 @@  static int gdb_handle_packet(GDBState *s, const char *line_buf)
         if (*p == ',')
             p++;
         len = strtoull(p, (char **)&p, 16);
-        if (ch == 'Z')
-            res = gdb_breakpoint_insert(addr, len, type);
-        else
+        while (isspace(*p)) {
+            p++;
+        }
+        if (ch == 'Z' && *p == ';') {
+                p++;
+                while (isspace(*p)) {
+                    p++;
+                }
+                if (*p == 'X') {
+                    p++;
+                    bp_cond_len = strtoul(p, (char **)&p, 16);
+                    if (*p == ',') {
+                        p++;
+                    }
+                    if (bp_cond_len > 0) {
+                        int bp_cond_size = sizeof(uint8_t) * bp_cond_len;
+                        bp_cond_expr = (uint8_t *)g_malloc(bp_cond_size);
+                        memset(bp_cond_expr, 0, bp_cond_size);
+
+                        for (i = 0 ; i < bp_cond_len ; i++) {
+                            if (!isxdigit(*p) || !isxdigit(*(p + 1))) {
+                                bp_cond_len = 0 ;
+                                g_free(bp_cond_expr);
+                                bp_cond_expr = NULL;
+                                perror("Error in breakpoint condition");
+                            } else {
+                                hextomem(bp_cond_expr+i, p, 1);
+                                p += 2;
+                            }
+                        }
+                    }
+#ifdef DEBUG_GDB
+                    bp_agent_dump_bytecode(bp_cond_len, bp_cond_expr);
+#endif
+                }
+        }
+        if (ch == 'Z') {
+            res = gdb_breakpoint_insert(addr, len, type,
+                                        bp_cond_len, bp_cond_expr);
+        } else {
             res = gdb_breakpoint_remove(addr, len, type);
+        }
         if (res >= 0)
              put_packet(s, "OK");
         else if (res == -ENOSYS)
             put_packet(s, "");
         else
             put_packet(s, "E22");
+        if (bp_cond_expr != NULL) {
+            g_free(bp_cond_expr);
+        }
         break;
     case 'H':
         type = *p++;
@@ -2442,6 +2491,10 @@  static int gdb_handle_packet(GDBState *s, const char *line_buf)
 #endif /* !CONFIG_USER_ONLY */
         if (strncmp(p, "Supported", 9) == 0) {
             snprintf(buf, sizeof(buf), "PacketSize=%x", MAX_PACKET_LENGTH);
+
+            /* conditional breakpoint evaluation on target*/
+            pstrcat(buf, sizeof(buf), ";ConditionalBreakpoints+");
+
 #ifdef GDB_CORE_XML
             pstrcat(buf, sizeof(buf), ";qXfer:features:read+");
 #endif
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 249e046..383c4c1 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -448,6 +448,7 @@  void cpu_exit(CPUArchState *s);
 #define BP_CPU                0x20
 
 int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
+                          long cond_len, uint8_t *cond_exp,
                           CPUBreakpoint **breakpoint);
 int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags);
 void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint);
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index 2911b9f..a1bbde3 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -137,9 +137,13 @@  typedef struct icount_decr_u16 {
 typedef struct CPUBreakpoint {
     target_ulong pc;
     int flags; /* BP_* */
+    int cond_len;
+    uint8_t *cond_exp;
     QTAILQ_ENTRY(CPUBreakpoint) entry;
 } CPUBreakpoint;
 
+int bp_has_cond(CPUBreakpoint *bp);
+
 typedef struct CPUWatchpoint {
     target_ulong vaddr;
     target_ulong len_mask;
@@ -147,6 +151,21 @@  typedef struct CPUWatchpoint {
     QTAILQ_ENTRY(CPUWatchpoint) entry;
 } CPUWatchpoint;
 
+
+#if TARGET_LONG_SIZE == 4
+typedef float target_double;
+#else /* TARGET_LONG_SIZE == 8 */
+typedef double target_double;
+#endif
+
+typedef union BPAgentStackElementType {
+    target_long l;
+    target_double d;
+} BPAgentStackElementType;
+
+
+#define BP_AGENT_MAX_COND_SIZE 1024
+
 #define CPU_TEMP_BUF_NLONGS 128
 #define CPU_COMMON                                                      \
     struct TranslationBlock *current_tb; /* currently executing TB  */  \
@@ -196,6 +215,11 @@  typedef struct CPUWatchpoint {
     /* user data */                                                     \
     void *opaque;                                                       \
                                                                         \
+    BPAgentStackElementType bp_agent_stack[BP_AGENT_MAX_COND_SIZE];     \
+    BPAgentStackElementType *bp_agent_stack_current;                    \
+    /*bp_agent_stack_current is the current location in bp_agent_stack */   \
+    int  bp_agent_error; /* error in evaluation - ex., divide by zero*/ \
+    int qemu_rw_debug_flag;                                             \
     const char *cpu_model_str;
 
 #endif
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index f685c28..afe4701 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -59,7 +59,7 @@  typedef struct TranslationBlock TranslationBlock;
  * and up to 4 + N parameters on 64-bit archs
  * (N = number of input arguments + output arguments).  */
 #define MAX_OPC_PARAM (4 + (MAX_OPC_PARAM_PER_ARG * MAX_OPC_PARAM_ARGS))
-#define OPC_BUF_SIZE 640
+#define OPC_BUF_SIZE 2560
 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
 
 /* Maximum size a TCG op can expand to.  This is complicated because a
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index f687b95..b5d6e0c 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -72,7 +72,7 @@  typedef enum {
 } ExitStatus;
 
 /* global register indexes */
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 static TCGv cpu_ir[31];
 static TCGv cpu_fir[31];
 static TCGv cpu_pc;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index a8893f7..d1d8f7d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -32,6 +32,7 @@ 
 #include "helper.h"
 #define GEN_HELPER 1
 #include "helper.h"
+#include "translate-gdbagent.h"
 
 #define ENABLE_ARCH_4T    arm_feature(env, ARM_FEATURE_V4T)
 #define ENABLE_ARCH_5     arm_feature(env, ARM_FEATURE_V5)
@@ -81,7 +82,7 @@  static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
 #define DISAS_WFI 4
 #define DISAS_SWI 5
 
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 /* We reuse the same 64-bit temporaries for efficiency.  */
 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
 static TCGv_i32 cpu_R[16];
@@ -153,6 +154,11 @@  static inline void store_cpu_offset(TCGv var, int offset)
     tcg_temp_free_i32(var);
 }
 
+void cpu_get_reg_var_arm(TCGv var, int reg)
+{
+    tcg_gen_mov_i32(var, cpu_R[reg]);
+}
+
 #define store_cpu_field(var, name) \
     store_cpu_offset(var, offsetof(CPUARMState, name))
 
@@ -9827,11 +9833,24 @@  static inline void gen_intermediate_code_internal(CPUARMState *env,
         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
                 if (bp->pc == dc->pc) {
-                    gen_exception_insn(dc, 0, EXCP_DEBUG);
-                    /* Advance PC so that clearing the breakpoint will
-                       invalidate this TB.  */
-                    dc->pc += 2;
-                    goto done_generating;
+                    if (bp_has_cond(bp)) {
+                        int bp_condlabel = gen_new_label();
+                        int res = tcg_gen_bp_cond
+                          (env, &tcg_ctx, bp, bp_condlabel);
+                        /* tcg_gen_bp_cond can return 0
+                           in case internal error,
+                           in particular gen_opc_buf overload */
+                        gen_exception(EXCP_DEBUG);
+                        if (res) {
+                            gen_set_label(bp_condlabel);
+                        }
+                    } else {
+                        gen_exception_insn(dc, 0, EXCP_DEBUG);
+                        /* Advance PC so that clearing the breakpoint will
+                           invalidate this TB.  */
+                        dc->pc += 2;
+                        goto done_generating;
+                    }
                     break;
                 }
             }
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 09e6011..077f714 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -55,7 +55,7 @@ 
 #define CC_MASK_NZVC 0xf
 #define CC_MASK_RNZV 0x10e
 
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 static TCGv cpu_R[16];
 static TCGv cpu_PR[16];
 static TCGv cc_x;
diff --git a/target-i386/helper.c b/target-i386/helper.c
index d1cb4e2..e23b2f4 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -973,7 +973,7 @@  void hw_breakpoint_insert(CPUX86State *env, int index)
     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(env, env->dr[index], BP_CPU,
+            err = cpu_breakpoint_insert(env, env->dr[index], BP_CPU, 0, NULL,
                                         &env->cpu_breakpoint[index]);
         }
         break;
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 112c310..760b206 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -50,7 +50,7 @@ 
 //#define MACRO_TEST   1
 
 /* global register indexes */
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 static TCGv cpu_A0, cpu_cc_src, cpu_cc_dst, cpu_cc_tmp;
 static TCGv_i32 cpu_cc_op;
 static TCGv cpu_regs[CPU_NB_REGS];
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index 6b87340..7f4bc7d 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -39,7 +39,7 @@ 
 
 #define MEM_INDEX 0
 
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 static TCGv cpu_R[32];
 static TCGv cpu_pc;
 static TCGv cpu_ie;
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 3f1478c..07647d3 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -42,7 +42,7 @@ 
 #undef DEFO64
 #undef DEFF64
 
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 
 static char cpu_reg_names[3*8*3 + 5*4];
 static TCGv cpu_dregs[8];
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 58ce712..d0b92db 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -42,7 +42,7 @@ 
             (((src) >> start) & ((1 << (end - start + 1)) - 1))
 
 static TCGv env_debug;
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 static TCGv cpu_R[32];
 static TCGv cpu_SR[18];
 static TCGv env_imm;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 3b77b53..2e20707 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1006,7 +1006,7 @@  enum {
 };
 
 /* global register indices */
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 static TCGv cpu_gpr[32], cpu_PC;
 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
 static TCGv cpu_dspctrl, btarget, bcond;
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 1e1b30c..32e5e08 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -49,7 +49,7 @@  typedef struct DisasContext {
     uint32_t delayed_branch;
 } DisasContext;
 
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 static TCGv cpu_sr;
 static TCGv cpu_R[32];
 static TCGv cpu_pc;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 2ac5794..24ce440 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -44,7 +44,7 @@ 
 /* Code translation helpers                                                  */
 
 /* global register indexes */
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 static char cpu_reg_names[10*3 + 22*4 /* GPR */
 #if !defined(TARGET_PPC64)
     + 10*4 + 22*5 /* SPE GPRh */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index a57296c..3bdfc28 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -35,7 +35,7 @@ 
 #include "qemu/host-utils.h"
 
 /* global register indexes */
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 
 #include "exec/gen-icount.h"
 #include "helper.h"
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 260aaab..9ee093c 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -57,7 +57,7 @@  enum {
 };
 
 /* global register indexes */
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 static TCGv cpu_gregs[24];
 static TCGv cpu_pc, cpu_sr, cpu_ssr, cpu_spc, cpu_gbr;
 static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index ca75e1a..de4eaad 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -39,7 +39,8 @@ 
                          according to jump_pc[T2] */
 
 /* global register indexes */
-static TCGv_ptr cpu_env, cpu_regwptr;
+TCGv_ptr cpu_env;
+static TCGv_ptr cpu_regwptr;
 static TCGv cpu_cc_src, cpu_cc_src2, cpu_cc_dst;
 static TCGv_i32 cpu_cc_op;
 static TCGv_i32 cpu_psr;
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index f4498bc..32c2172 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -48,7 +48,7 @@  typedef struct DisasContext {
    conditional executions state has been updated.  */
 #define DISAS_SYSCALL 5
 
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 static TCGv_i32 cpu_R[32];
 
 /* FIXME:  These should be removed.  */
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 7029ac4..dad1f7a 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -69,7 +69,7 @@  typedef struct DisasContext {
     unsigned cpenable;
 } DisasContext;
 
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 static TCGv_i32 cpu_pc;
 static TCGv_i32 cpu_R[16];
 static TCGv_i32 cpu_FR[16];
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 91c9d80..03f66e9 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -21,6 +21,10 @@ 
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
+
+#ifndef __TCG_OP_H__
+#define __TCG_OP_H__
 #include "tcg.h"
 
 int gen_new_label(void);
@@ -2718,6 +2722,8 @@  static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
                                                TCGV_PTR_TO_NAT(B))
 #define tcg_gen_addi_ptr(R, A, B) tcg_gen_addi_i32(TCGV_PTR_TO_NAT(R), \
                                                  TCGV_PTR_TO_NAT(A), (B))
+#define tcg_gen_subi_ptr(R, A, B) tcg_gen_subi_i32(TCGV_PTR_TO_NAT(R), \
+                                                 TCGV_PTR_TO_NAT(A), (B))
 #define tcg_gen_ext_i32_ptr(R, A) tcg_gen_mov_i32(TCGV_PTR_TO_NAT(R), (A))
 #else /* TCG_TARGET_REG_BITS == 32 */
 #define tcg_gen_add_ptr(R, A, B) tcg_gen_add_i64(TCGV_PTR_TO_NAT(R), \
@@ -2725,5 +2731,9 @@  static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
                                                TCGV_PTR_TO_NAT(B))
 #define tcg_gen_addi_ptr(R, A, B) tcg_gen_addi_i64(TCGV_PTR_TO_NAT(R),   \
                                                  TCGV_PTR_TO_NAT(A), (B))
+#define tcg_gen_subi_ptr(R, A, B) tcg_gen_subi_i64(TCGV_PTR_TO_NAT(R),   \
+                                                 TCGV_PTR_TO_NAT(A), (B))
 #define tcg_gen_ext_i32_ptr(R, A) tcg_gen_ext_i32_i64(TCGV_PTR_TO_NAT(R), (A))
 #endif /* TCG_TARGET_REG_BITS != 32 */
+
+#endif /* __TCG_OP_H__ */
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 51c8176..8158e3c 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -21,6 +21,10 @@ 
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
+#ifndef __TCG_H__
+#define __TCG_H__
+
 #include "qemu-common.h"
 
 /* Target word size (must be identical to pointer size). */
@@ -682,3 +686,5 @@  void tcg_register_jit(void *buf, size_t buf_size);
 /* Generate TB finalization at the end of block */
 void tcg_out_tb_finalize(TCGContext *s);
 #endif
+
+#endif /* __TCG_H__*/
diff --git a/translate-all.c b/translate-all.c
index efeb247..5f10984 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -59,6 +59,7 @@ 
 
 #include "exec/cputlb.h"
 #include "translate-all.h"
+#include "translate-gdbagent.h"
 
 //#define DEBUG_TB_INVALIDATE
 //#define DEBUG_FLUSH
@@ -150,6 +151,8 @@  int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr
                        exceptions */
     ti = profile_getclock();
 #endif
+    bp_agent_init();
+
     tcg_func_start(s);
 
     gen_intermediate_code(env, tb);
@@ -199,6 +202,7 @@  static int cpu_restore_state_from_tb(TranslationBlock *tb, CPUArchState *env,
     TCGContext *s = &tcg_ctx;
     int j;
     uintptr_t tc_ptr;
+    int prev_rw_debug_flag;
 #ifdef CONFIG_PROFILER
     int64_t ti;
 #endif
@@ -208,7 +212,10 @@  static int cpu_restore_state_from_tb(TranslationBlock *tb, CPUArchState *env,
 #endif
     tcg_func_start(s);
 
+    prev_rw_debug_flag = env->qemu_rw_debug_flag;
+    env->qemu_rw_debug_flag = 1;
     gen_intermediate_code_pc(env, tb);
+    env->qemu_rw_debug_flag = prev_rw_debug_flag;
 
     if (use_icount) {
         /* Reset the cycle counter to the start of the block.  */
diff --git a/translate-all.h b/translate-all.h
index b181fb4..5e883b1 100644
--- a/translate-all.h
+++ b/translate-all.h
@@ -31,4 +31,6 @@  void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len);
 void cpu_unlink_tb(CPUArchState *env);
 void tb_check_watchpoint(CPUArchState *env);
 
+extern TCGv_ptr cpu_env;
+
 #endif /* TRANSLATE_ALL_H */
diff --git a/translate-gdbagent.c b/translate-gdbagent.c
new file mode 100644
index 0000000..e868ced
--- /dev/null
+++ b/translate-gdbagent.c
@@ -0,0 +1,922 @@ 
+/*
+ * Translation GDB bytecode to TCG.
+ * Used for evaluation breakpoint condition on host.
+ *
+ * Copyright (c) 2013 Anna Neiman <anna_neiman@mentor.com>
+ * Copyright (c) 2012 Mentor Graphics Corp.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "config.h"
+
+#define NO_CPU_IO_DEFS
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "translate-gdbagent.h"
+#include "translate-all.h"
+
+#if defined(TARGET_HAS_ICE)
+
+static TCGv_ptr bp_agent_stack_current_tcg ;
+static TCGv qemu_rw_debug_flag_tcg  ;
+static TCGv bp_agent_error_tcg  ;
+
+typedef void(*CPUGetRegVarFuncType)(TCGv var, int reg);
+
+/* function for retrieve register contents - platform depend*/
+static CPUGetRegVarFuncType cpu_get_reg_var_func;
+
+
+static int inited;
+
+void bp_agent_init(void)
+{
+    if (!inited) {
+        inited = 1;
+        bp_agent_stack_current_tcg =
+          tcg_global_mem_new_ptr(TCG_AREG0,
+                                 offsetof(CPUArchState, bp_agent_stack_current),
+                                 "bp_agent_stack_current");
+        qemu_rw_debug_flag_tcg =
+          tcg_global_mem_new(TCG_AREG0,
+                             offsetof(CPUArchState, qemu_rw_debug_flag),
+                             "qemu_rw_debug_flag");
+        bp_agent_error_tcg =
+          tcg_global_mem_new(TCG_AREG0,
+                             offsetof(CPUArchState, bp_agent_error),
+                             "bp_agent_error");
+     }
+#if defined(TARGET_ARM)
+    cpu_get_reg_var_func = cpu_get_reg_var_arm;
+#else
+    cpu_get_reg_var_func = 0;
+#endif
+}
+static void bp_agent_init_local(CPUArchState *env, int len)
+{
+    if (len > BP_AGENT_MAX_COND_SIZE) {
+        fprintf(stderr,
+                "GDB agent: Condition length more then %d is unsupported.\n",
+                BP_AGENT_MAX_COND_SIZE);
+    }
+
+    tcg_gen_addi_ptr(bp_agent_stack_current_tcg, cpu_env,
+                     offsetof(CPUArchState, bp_agent_stack));
+    tcg_gen_movi_tl(qemu_rw_debug_flag_tcg, 1);
+}
+
+static void increment_stack_ptr(CPUArchState *env)
+{
+  tcg_gen_addi_ptr(bp_agent_stack_current_tcg,
+                   bp_agent_stack_current_tcg,
+                   TARGET_LONG_SIZE);
+
+}
+static void decrement_stack_ptr(CPUArchState *env)
+{
+    tcg_gen_subi_ptr(bp_agent_stack_current_tcg,
+                     bp_agent_stack_current_tcg,
+                     TARGET_LONG_SIZE);
+}
+
+static int check_max_instr_num(TCGContext *s, int labels_num)
+{
+    return ((s->gen_opc_ptr - s->gen_opc_buf) <=
+            (OPC_MAX_SIZE - 20 - labels_num)) ;
+}
+
+static int bp_agent_stack_set_const(CPUArchState *env, target_long tmp)
+{
+    TCGv tmp2 = tcg_temp_new();
+    tcg_gen_movi_tl(tmp2, tmp);
+    tcg_gen_st_tl(tmp2, bp_agent_stack_current_tcg, 0);
+
+    tcg_temp_free(tmp2);
+    return 1;
+}
+static int bp_agent_stack_push_const(CPUArchState *env, target_long tmp)
+{
+    bp_agent_stack_set_const(env, tmp);
+
+    increment_stack_ptr(env);
+    return 1;
+}
+static int bp_agent_stack_push(CPUArchState *env, TCGv tmp)
+{
+    tcg_gen_st_tl(tmp, bp_agent_stack_current_tcg, 0);
+
+    increment_stack_ptr(env);
+    return 1;
+}
+
+static int bp_agent_stack_pop(CPUArchState *env, TCGv tmp)
+{
+    decrement_stack_ptr(env);
+    tcg_gen_ld_tl(tmp, bp_agent_stack_current_tcg, 0);
+    return 1;
+}
+
+static int bp_agent_brcond_top(CPUArchState *env, int condlabel)
+{
+    TCGv tmp = tcg_temp_local_new();
+    int loc_err_label = gen_new_label();
+
+    bp_agent_stack_pop(env, tmp);
+    tcg_gen_movi_tl(qemu_rw_debug_flag_tcg, 0);
+
+    /* if error - evaluate on host */
+    tcg_gen_brcondi_tl(TCG_COND_NE, bp_agent_error_tcg, 0, loc_err_label);
+
+    tcg_gen_brcondi_tl(TCG_COND_EQ, tmp, 0, condlabel);
+
+    gen_set_label(loc_err_label);
+
+    tcg_temp_free(tmp);
+
+    return 1;
+}
+
+typedef enum {
+    BYTECODE_FLOAT = 0x01,
+    BYTECODE_ADD = 0x02,
+    BYTECODE_SUB = 0x03,
+    BYTECODE_MUL = 0x04,
+    BYTECODE_DIV_SIGNED = 0x05,
+    BYTECODE_DIV_UNSIGNED = 0x06,
+    BYTECODE_REM_SIGNED = 0x07,
+    BYTECODE_REM_UNSIGNED = 0x08,
+    BYTECODE_LSH = 0x09,
+    BYTECODE_RSH_SIGNED = 0x0a,
+    BYTECODE_RSH_UNSIGNED = 0x0b,
+    BYTECODE_TRACE = 0x0c,
+    BYTECODE_TRACE_QUICK = 0x0d,
+    BYTECODE_LOG_NOT = 0x0e,
+    BYTECODE_BIT_AND = 0x0f,
+    BYTECODE_BIT_OR = 0x10,
+    BYTECODE_BIT_XOR = 0x11,
+    BYTECODE_BIT_NOT  = 0x12,
+    BYTECODE_EQUAL = 0x13,
+    BYTECODE_LESS_SIGNED = 0x14,
+    BYTECODE_LESS_UNSIGNED = 0x15,
+    BYTECODE_EXT = 0x16,
+    BYTECODE_REF8 = 0x17,
+    BYTECODE_REF16 = 0x18,
+    BYTECODE_REF32 = 0x19,
+    BYTECODE_REF64 = 0x1a,
+    BYTECODE_REF_FLOAT = 0x1b,
+    BYTECODE_REF_DOUBLE = 0x1c,
+    BYTECODE_REF_LONG_DOUBLE = 0x1d,
+    BYTECODE_L_TO_D = 0x1e,
+    BYTECODE_D_TO_L = 0x1f,
+    BYTECODE_IF_GOTO = 0x20,
+    BYTECODE_GOTO = 0x21,
+    BYTECODE_CONST8 = 0x22,
+    BYTECODE_CONST16 = 0x23,
+    BYTECODE_CONST32 = 0x24,
+    BYTECODE_CONST64 = 0x25,
+    BYTECODE_REG = 0x26,
+    BYTECODE_END = 0x27,
+    BYTECODE_DUP = 0x28,
+    BYTECODE_POP = 0x29,
+    BYTECODE_ZERO_EXT = 0x2a,
+    BYTECODE_SWAP = 0x2b,
+    BYTECODE_TRACE16 = 0x30
+} BytecodeCommandsType;
+
+static const char *bytecode_commands_names[] = {
+    "", /*0x00*/
+    "float", /*0x01*/
+    "add", /*0x02*/
+    "sub", /*0x03*/
+    "mul",  /*0x04*/
+    "div_signed", /*0x05*/
+    "div_unsigned", /*0x06*/
+    "rem_signed", /*0x07*/
+    "rem_unsigned", /*0x08*/
+    "lsh", /*0x09*/
+    "rsh_signed", /*0x0a*/
+    "rsh_unsigned", /*0x0b*/
+    "trace", /*0x0c*/
+    "trace_quick", /*0x0d*/
+    "log_not", /*0x0e*/
+    "bit_and", /*0x0f*/
+    "bit_or", /*0x10*/
+    "bit_xor", /*0x11*/
+    "bit_not ", /*0x12*/
+    "equal", /*0x13*/
+    "less_signed", /*0x14*/
+    "less_unsigned", /*0x15*/
+    "ext", /*0x16*/
+    "ref8", /*0x17*/
+    "ref16", /*0x18*/
+    "ref32", /*0x19*/
+    "ref64", /*0x1a*/
+    "ref_float", /*0x1b*/
+    "ref_double", /*0x1c*/
+    "ref_long_double", /*0x1d*/
+    "l_to_d", /*0x1e*/
+    "d_to_l", /*0x1f*/
+    "if_goto", /*0x20*/
+    "goto", /*0x21*/
+    "const8", /*0x22*/
+    "const16", /*0x23*/
+    "const32", /*0x24*/
+    "const64", /*0x25*/
+    "reg", /*0x26*/
+    "end", /*0x27*/
+    "dup", /*0x28*/
+    "pop", /*0x29*/
+    "zero_ext", /*0x2a*/
+    "swap", /*0x2b*/
+    "", /*0x2c*/
+    "", /*0x2d*/
+    "", /*0x2e*/
+    "", /*0x2f*/
+    "trace16" /*0x30*/
+};
+
+static target_long bp_agent_get_arg(const uint8_t *cond_exp,
+                                    int *bp_agent_instr_cnt, int num_bytes)
+{
+    target_long res = 0 ;
+    int ind = *bp_agent_instr_cnt;
+    switch (num_bytes) {
+    case 1:
+        ind++;
+        res = cond_exp[ind];
+        break;
+    case 2:
+        {
+            uint16_t val;
+            ind++;
+            val = (cond_exp[ind] << 8) + cond_exp[ind+1];
+            ind++;
+            bswap16(val);
+            res = val;
+        }
+        break;
+    case 8:
+        {
+#if TARGET_LONG_SIZE == 8
+            uint64_t val = 0;
+            int i = 0;
+            for (i = 0; i < 8; i++) {
+                ind++;
+                val = val + cond_exp[ind];
+                val = val << 8;
+            }
+            bswap64(val);
+            res = val;
+#else
+            fprintf(stderr,
+                    "GDB agent: const 64 is not supported for 32 bit target architecture.\n");
+#endif
+            break;
+        }
+    case 4:
+    default:
+        {
+            uint32_t val;
+            ind++;
+            val =
+              (cond_exp[ind] << 24) + (cond_exp[ind+1] << 16) +
+              (cond_exp[ind+2] << 8) + cond_exp[ind+3];
+            ind += 3;
+            bswap32(val);
+            res = val;
+        }
+        break;
+    }
+    *bp_agent_instr_cnt = ind;
+    return res;
+}
+typedef int(*PrintFuncType)(const char *, ...)
+  __attribute__((__format__(__printf__, 1, 2)));
+
+static int bp_agent_pass_bytecode(int cond_len, const uint8_t *cond_exp,
+                                  int *label_tab, PrintFuncType prnt)
+/* returns number of labels */
+{
+    int ret = 0 ;
+    int i = 0 ;
+    target_long val = 0;
+    for (i = 0 ; i < cond_len; i++) {
+        BytecodeCommandsType command_type = (BytecodeCommandsType)(cond_exp[i]);
+        switch (command_type) {
+        case BYTECODE_FLOAT: /*0x01*/
+        case BYTECODE_REF_FLOAT: /*0x1b */
+        case BYTECODE_REF_DOUBLE: /*0x1c */
+        case BYTECODE_REF_LONG_DOUBLE: /*0x1d */
+        case BYTECODE_L_TO_D: /*0x1e*/
+        case BYTECODE_D_TO_L: /*0x1f*/
+        case BYTECODE_TRACE: /*0x0c*/
+            if (prnt) {
+                prnt("\n\t%s",
+                     bytecode_commands_names[(int)command_type]);
+            }
+            break;
+        case BYTECODE_TRACE_QUICK: /*0x0d*/
+            val = bp_agent_get_arg(cond_exp, &i, 1);
+            if (prnt) {
+                prnt("\n\t%s %x",
+                     bytecode_commands_names[(int)command_type],
+                     (unsigned int)val);
+            }
+            break;
+        case BYTECODE_TRACE16: /*0x30*/
+            val = bp_agent_get_arg(cond_exp, &i, 2);
+            if (prnt) {
+                prnt("\n\t%s %x",
+                     bytecode_commands_names[(int)command_type],
+                     (unsigned int)val);
+            }
+            break;
+        case BYTECODE_END: /*0x27*/
+        case BYTECODE_DUP: /*0x28*/
+        case BYTECODE_POP: /*0x29*/
+        case BYTECODE_SWAP: /*0x2b */
+        case BYTECODE_REF8: /*0x17*/
+        case BYTECODE_REF16: /*0x18 */
+        case BYTECODE_REF64: /*0x1a */
+        case BYTECODE_REF32: /*0x19*/
+            if (prnt) {
+                prnt("\n\t%s",
+                     bytecode_commands_names[(int)command_type]);
+            }
+            break;
+        case BYTECODE_IF_GOTO: /*0x20*/
+        case BYTECODE_GOTO: /*0x21*/
+            val = bp_agent_get_arg(cond_exp, &i, 2);
+            if (prnt) {
+                prnt("\n\t%s %x",
+                     bytecode_commands_names[(int)command_type],
+                     (unsigned int)val);
+            }
+            if (label_tab != NULL  && label_tab[val] == -1) {
+                    label_tab[val]  = gen_new_label();
+                    ret++;
+            }
+            break;
+        case BYTECODE_CONST8: /*0x22*/
+            val = bp_agent_get_arg(cond_exp, &i, 1);
+            if (prnt) {
+                prnt("\n\t%s %x",
+                     bytecode_commands_names[(int)command_type],
+                     (unsigned int)val);
+            }
+            break;
+        case BYTECODE_CONST16: /*0x23*/
+            val = bp_agent_get_arg(cond_exp, &i, 2);
+            if (prnt) {
+                prnt("\n\t%s %x",
+                     bytecode_commands_names[(int)command_type],
+                     (unsigned int)val);
+            }
+            break;
+        case BYTECODE_CONST64: /*0x25*/
+            val = bp_agent_get_arg(cond_exp, &i, 8);
+#if TARGET_LONG_SIZE == 8
+            if (prnt) {
+                prnt("\n\t%s %llx",
+                     bytecode_commands_names[(int)command_type],
+                     (unsigned long long)val);
+            }
+#endif
+            break;
+        case BYTECODE_CONST32: /*0x24*/
+            val = bp_agent_get_arg(cond_exp, &i, 4);
+            if (prnt) {
+                prnt("\n\t%s %lx",
+                     bytecode_commands_names[(int)command_type],
+                     (unsigned long)val);
+            }
+            break;
+        case BYTECODE_REG: /*0x26*/
+            val = bp_agent_get_arg(cond_exp, &i, 2);
+            if (prnt) {
+                prnt("\n\t%s %x",
+                     bytecode_commands_names[(int)command_type],
+                     (unsigned int)val);
+            }
+            break;
+
+        case BYTECODE_LOG_NOT:/*0x0e*/
+        case BYTECODE_BIT_NOT: /*0x12*/
+            if (prnt) {
+                prnt("\n\t%s",
+                     bytecode_commands_names[(int)command_type]);
+            }
+            break;
+        case BYTECODE_EXT: /*0x16*/
+            val = bp_agent_get_arg(cond_exp, &i, 1);
+            if (prnt) {
+                prnt("\n\text %x", (unsigned int) val);
+            }
+            break;
+        case BYTECODE_ZERO_EXT: /*0x2a */
+            val = bp_agent_get_arg(cond_exp, &i, 1);
+            if (prnt) {
+                prnt("\n\t%s %x",
+                     bytecode_commands_names[(int)command_type],
+                     (unsigned int)val);
+            }
+            break;
+        case BYTECODE_ADD: /*0x02*/
+        case BYTECODE_SUB: /*0x03*/
+        case BYTECODE_MUL: /*0x04*/
+        case BYTECODE_DIV_SIGNED: /*0x05*/
+        case BYTECODE_DIV_UNSIGNED: /*0x06*/
+        case BYTECODE_REM_SIGNED: /*0x07*/
+        case BYTECODE_REM_UNSIGNED: /*0x08*/
+        case BYTECODE_LSH: /*0x09*/
+        case BYTECODE_RSH_SIGNED: /*0x0a*/
+        case BYTECODE_RSH_UNSIGNED: /*0x0b*/
+        case BYTECODE_BIT_AND: /*0x0f*/
+        case BYTECODE_BIT_OR: /*0x10*/
+        case BYTECODE_BIT_XOR: /*0x11*/
+        case BYTECODE_EQUAL: /*0x13*/
+        case BYTECODE_LESS_SIGNED: /*0x14*/
+        case BYTECODE_LESS_UNSIGNED: /*0x15*/
+            if (prnt) {
+                prnt("\n\t%s",
+                     bytecode_commands_names[(int)command_type]);
+            }
+            break;
+        default:
+            break;
+        }
+    }
+    return ret;
+}
+void bp_agent_dump_bytecode(int cond_len, const uint8_t *cond_exp)
+/*called from gdbstub in debug mode */
+{
+    printf("\nBytecode :");
+    bp_agent_pass_bytecode(cond_len, cond_exp, NULL, printf);
+    printf("\nEnd of Bytecode :");
+}
+static int bp_agent_tcg_gen(CPUArchState *env, TCGContext *s,
+                            int cond_len, const uint8_t *cond_exp)
+{
+    int i = 0 ;
+    target_long val = 0 ;
+
+    int ret = 1 ;
+    int labels_num =  0 ;
+
+
+    int *label_tab = (int *)g_malloc(sizeof(int) * cond_len);
+    for (i = 0; i < cond_len ; i++) {
+        label_tab[i] = -1; /* real label value can be 0*/
+    }
+
+    labels_num = bp_agent_pass_bytecode(cond_len, cond_exp, label_tab, NULL);
+    for (i = 0;
+         (i < cond_len)  && (ret == 1) && check_max_instr_num(s, labels_num);
+         i++) {
+        BytecodeCommandsType command_type = (BytecodeCommandsType)(cond_exp[i]);
+        if (label_tab[i]  != -1) {
+            gen_set_label(label_tab[i]);
+            labels_num--;
+        }
+        switch (command_type) {
+        case BYTECODE_FLOAT: /*0x01 */
+        case BYTECODE_REF_FLOAT: /*0x1b */
+        case BYTECODE_REF_DOUBLE: /*0x1c */
+        case BYTECODE_REF_LONG_DOUBLE: /*0x1d */
+        case BYTECODE_L_TO_D: /*0x1e */
+        case BYTECODE_D_TO_L: /*0x1f */
+            printf("\n Command is not implemented in BP agent");
+            break;
+        case BYTECODE_TRACE: /*0x0c not need for bp condition */
+            break;
+        case BYTECODE_TRACE_QUICK: /*0x0d    not need for bp condition   */
+            val = bp_agent_get_arg(cond_exp, &i, 1);
+            break;
+        case BYTECODE_TRACE16: /*0x30  not need for bp condition */
+            val = bp_agent_get_arg(cond_exp, &i, 2);
+            break;
+        case BYTECODE_END: /*0x27 */
+            i = cond_len;
+            break;
+        case BYTECODE_DUP: /*0x28*/
+            {
+                TCGv tmp1 = tcg_temp_new();
+                ret = bp_agent_stack_pop(env, tmp1);
+                if (ret) {
+                    ret = bp_agent_stack_push(env, tmp1);
+                }
+                if (ret) {
+                    ret = bp_agent_stack_push(env, tmp1);
+                }
+                tcg_temp_free(tmp1);
+            }
+            break;
+        case BYTECODE_POP: /*0x29*/
+            decrement_stack_ptr(env);
+            break;
+        case BYTECODE_SWAP: /*0x2b*/
+            {
+                TCGv tmp1 = tcg_temp_new();
+                TCGv tmp2 = tcg_temp_new();
+                ret = bp_agent_stack_pop(env, tmp1);
+                if (ret) {
+                    ret = bp_agent_stack_pop(env, tmp2);
+                }
+                if (ret) {
+                    ret = bp_agent_stack_push(env, tmp1);
+                }
+                if (ret) {
+                    ret = bp_agent_stack_push(env, tmp2);
+                }
+                tcg_temp_free(tmp1);
+                tcg_temp_free(tmp2);
+            }
+            break;
+        case BYTECODE_REF8: /*0x17*/
+        case BYTECODE_REF16: /*0x18*/
+        case BYTECODE_REF64: /*0x1a*/
+        case BYTECODE_REF32: /*0x19*/
+            {
+                TCGv tmp1 = tcg_temp_new();
+                TCGv tmp2 = tcg_temp_new();
+                ret = bp_agent_stack_pop(env, tmp1);
+                if (ret) {
+                    switch (command_type) {
+                    case BYTECODE_REF8: /*0x17*/
+                        tcg_gen_qemu_ld8u(tmp2, tmp1,  0);
+                        break;
+                    case BYTECODE_REF16: /*0x18*/
+                        tcg_gen_qemu_ld16u(tmp2, tmp1, 0);
+                        break;
+                    case BYTECODE_REF64: /*0x1a*/
+#if TARGET_LONG_SIZE == 8
+                        tcg_gen_qemu_ld64(tmp2, tmp1,  0);
+#else
+                        tcg_gen_qemu_ld32u(tmp2, tmp1, 0);
+#endif
+                        break;
+                    case BYTECODE_REF32: /*0x19*/
+                        tcg_gen_qemu_ld32u(tmp2, tmp1, 0);
+                        break;
+                    default:
+                        break;
+                    }
+                }
+                if (ret) {
+                    ret = bp_agent_stack_push(env, tmp2);
+                }
+                tcg_temp_free(tmp1);
+                tcg_temp_free(tmp2);
+            }
+            break;
+        case BYTECODE_IF_GOTO: /*0x20*/
+            {
+                TCGv tmp1 = tcg_temp_new();
+                val = bp_agent_get_arg(cond_exp, &i, 2);
+                ret = bp_agent_stack_pop(env, tmp1);
+                if (ret) {
+                    tcg_gen_brcondi_tl(TCG_COND_NE, tmp1, 0, label_tab[val]);
+                }
+                tcg_temp_free(tmp1);
+            }
+            break;
+        case BYTECODE_GOTO: /*0x21*/
+            val = bp_agent_get_arg(cond_exp, &i, 2);
+            tcg_gen_br(label_tab[val]);
+            break;
+        case BYTECODE_CONST8: /*0x22*/
+            val = bp_agent_get_arg(cond_exp, &i, 1);
+            ret = bp_agent_stack_push_const(env, val);
+            break;
+        case BYTECODE_CONST16: /*0x23*/
+            val = bp_agent_get_arg(cond_exp, &i, 2) ;
+            ret = bp_agent_stack_push_const(env, val);
+            break;
+        case BYTECODE_CONST64: /*0x25*/
+            val = bp_agent_get_arg(cond_exp, &i, 8);
+#if TARGET_LONG_SIZE == 8
+            ret = bp_agent_stack_push_const(env, val);
+#endif
+            break;
+        case BYTECODE_CONST32: /*0x24*/
+            val = bp_agent_get_arg(cond_exp, &i, 4);
+            ret = bp_agent_stack_push_const(env, val);
+            break;
+        case BYTECODE_REG: /*0x26*/
+            {
+                TCGv tmp1 = tcg_temp_new();
+                val = bp_agent_get_arg(cond_exp, &i, 2) ;
+                cpu_get_reg_var_func(tmp1, val);
+                ret = bp_agent_stack_push(env, tmp1);
+                tcg_temp_free(tmp1);
+            }
+            break;
+        case BYTECODE_LOG_NOT:/*0x0e*/
+            {
+                TCGv tmp1 = tcg_temp_new();
+                TCGv tmp = tcg_temp_local_new();
+
+                ret = bp_agent_stack_pop(env, tmp1);
+                if (!ret) {
+                    tcg_temp_free(tmp1);
+                    tcg_temp_free(tmp);
+                    break;
+                }
+                tcg_gen_setcondi_tl(TCG_COND_EQ, tmp, tmp1, 0);
+
+                ret = bp_agent_stack_push(env, tmp);
+                tcg_temp_free(tmp1);
+                tcg_temp_free(tmp);
+            }
+            break;
+        case BYTECODE_BIT_NOT: /*0x12*/
+            {
+                TCGv tmp1 = tcg_temp_new();
+                ret = bp_agent_stack_pop(env, tmp1);
+                if (ret) {
+                    tcg_gen_not_tl(tmp1, tmp1);
+                    ret = bp_agent_stack_push(env, tmp1);
+                }
+                tcg_temp_free(tmp1);
+            }
+            break;
+        case BYTECODE_EXT: /*0x16*/
+        case BYTECODE_ZERO_EXT: /*0x2a*/
+            val = bp_agent_get_arg(cond_exp, &i, 1) ;
+            if (val != 8 && val != 16 && val != 32) {
+                fprintf(stderr,
+                        "\n GDB agent: non-aligned bit extension is not supported.");
+            } else {
+                TCGv tmp = tcg_temp_new();
+                ret = bp_agent_stack_pop(env, tmp);
+                if (!ret) {
+                    tcg_temp_free(tmp);
+                    break;
+                }
+                switch (val) {
+                case 8:
+                    if (command_type == BYTECODE_EXT) {
+                        tcg_gen_ext8s_tl(tmp, tmp);
+                    } else {
+                        tcg_gen_ext8u_tl(tmp, tmp);
+                    }
+                    break;
+                case 16:
+                    if (command_type == BYTECODE_EXT) {
+                        tcg_gen_ext16s_tl(tmp, tmp);
+                    } else {
+                        tcg_gen_ext16u_tl(tmp, tmp);
+                    }
+                    break;
+                case 32:
+                    if (command_type == BYTECODE_EXT) {
+                        tcg_gen_ext32s_tl(tmp, tmp);
+                    } else {
+                        tcg_gen_ext32u_tl(tmp, tmp);
+                    }
+                    break;
+                }
+                ret = bp_agent_stack_push(env, tmp);
+                tcg_temp_free(tmp);
+            }
+            break;
+        case BYTECODE_SUB: /*0x03*/
+        case BYTECODE_ADD: /*0x02*/
+        case BYTECODE_MUL: /*0x04*/
+        case BYTECODE_DIV_SIGNED: /*0x05*/
+        case BYTECODE_REM_SIGNED: /*0x07*/
+        case BYTECODE_REM_UNSIGNED: /*0x08*/
+        case BYTECODE_BIT_AND: /*0x0f*/
+        case BYTECODE_BIT_OR: /*0x10*/
+        case BYTECODE_BIT_XOR: /*0x11*/
+        case BYTECODE_LSH: /*0x09*/
+        case BYTECODE_RSH_SIGNED: /*0x0a*/
+        case BYTECODE_RSH_UNSIGNED: /*0x0b*/
+            {
+                int is_divide_command =
+                    (command_type ==  BYTECODE_DIV_SIGNED ||
+                     command_type ==  BYTECODE_DIV_UNSIGNED ||
+                     command_type ==  BYTECODE_REM_SIGNED ||
+                     command_type ==  BYTECODE_REM_UNSIGNED);
+                int my_div_label1 = -1;
+                int my_div_label2 = -1;
+                TCGv tmp1 = (is_divide_command ?
+                             tcg_temp_local_new() : tcg_temp_new());
+                TCGv tmp2 = (is_divide_command ?
+                             tcg_temp_local_new() : tcg_temp_new());
+                ret = bp_agent_stack_pop(env, tmp1);
+                if (!ret) {
+                    tcg_temp_free(tmp1);
+                    tcg_temp_free(tmp2);
+                    break;
+                }
+                if (is_divide_command) { /* check for divide by zero*/
+                    my_div_label1 = gen_new_label();
+                    my_div_label2 = gen_new_label();
+                    tcg_gen_brcondi_tl(TCG_COND_NE, tmp1, 0,
+                                       my_div_label1);
+                    tcg_gen_movi_tl(bp_agent_error_tcg , 1);
+                    tcg_gen_br(my_div_label2);
+                    gen_set_label(my_div_label1);
+                }
+                ret = bp_agent_stack_pop(env, tmp2);
+                if (!ret) {
+                    tcg_temp_free(tmp1);
+                    tcg_temp_free(tmp2);
+                    break;
+                }
+                switch (command_type) {
+                case BYTECODE_ADD:
+                    tcg_gen_add_tl(tmp2, tmp2, tmp1);
+                    break;
+                case BYTECODE_SUB:
+                    tcg_gen_sub_tl(tmp2, tmp2, tmp1);
+                    break;
+                case BYTECODE_MUL:
+                    tcg_gen_mul_tl(tmp2, tmp2, tmp1);
+                    break;
+                case BYTECODE_DIV_SIGNED:
+                    tcg_gen_div_tl(tmp2, tmp2, tmp1);
+                    break;
+                case BYTECODE_DIV_UNSIGNED:
+                    tcg_gen_divu_tl(tmp2, tmp2, tmp1);
+                    break;
+                case BYTECODE_REM_SIGNED:
+                    tcg_gen_rem_tl(tmp2, tmp2, tmp1);
+                    break;
+                case BYTECODE_REM_UNSIGNED:
+                    tcg_gen_remu_tl(tmp2, tmp2, tmp1);
+                    break;
+                case BYTECODE_BIT_AND:
+                    tcg_gen_and_tl(tmp2, tmp2, tmp1);
+                    break;
+                case BYTECODE_BIT_OR:
+                    tcg_gen_or_tl(tmp2, tmp2, tmp1);
+                    break;
+                case BYTECODE_BIT_XOR:
+                    tcg_gen_xor_tl(tmp2, tmp2, tmp1);
+                    break;
+                case BYTECODE_LSH:
+                    tcg_gen_shl_tl(tmp2, tmp2, tmp1);
+                    break;
+                case BYTECODE_RSH_SIGNED:
+                    tcg_gen_sar_tl(tmp2, tmp2, tmp1);
+                    break;
+                case BYTECODE_RSH_UNSIGNED:
+                    tcg_gen_shr_tl(tmp2, tmp2, tmp1);
+                    break;
+                default:
+                    break;
+                }
+                ret = bp_agent_stack_push(env, tmp2);
+                if (is_divide_command) {
+                        gen_set_label(my_div_label2);
+                    }
+                tcg_temp_free(tmp1);
+                tcg_temp_free(tmp2);
+            }
+            break;
+        case BYTECODE_EQUAL: /*0x13*/
+        case BYTECODE_LESS_UNSIGNED: /*0x15*/
+        case BYTECODE_LESS_SIGNED: /*0x14*/
+            {
+                TCGv tmp1 = tcg_temp_new();
+                TCGv tmp2 = tcg_temp_new();
+                TCGv tmp  = tcg_temp_local_new();
+
+                ret = bp_agent_stack_pop(env, tmp1);
+                if (!ret) {
+                    tcg_temp_free(tmp1);
+                    tcg_temp_free(tmp2);
+                    tcg_temp_free(tmp);
+                    break;
+                }
+                ret = bp_agent_stack_pop(env, tmp2);
+                if (!ret) {
+                    tcg_temp_free(tmp1);
+                    tcg_temp_free(tmp2);
+                    tcg_temp_free(tmp);
+                    break;
+                }
+                TCGCond cond ;
+                switch (command_type) {
+                case BYTECODE_EQUAL:
+                    cond = TCG_COND_EQ;
+                    break;
+                case BYTECODE_LESS_UNSIGNED:
+                    cond = TCG_COND_LTU;
+                    break;
+                case BYTECODE_LESS_SIGNED:
+                    cond = TCG_COND_LT;
+                    break;
+                default:
+                    break;
+                }
+                tcg_gen_setcond_tl(cond, tmp, tmp, tmp1);
+                ret = bp_agent_stack_push(env, tmp);
+
+                tcg_temp_free(tmp1);
+                tcg_temp_free(tmp2);
+                tcg_temp_free(tmp);
+            }
+            break;
+        default:
+            break;
+        }
+    }
+    /*for case error , ex.buffer overloading -
+      need to set labels anyway in order to avoid segmentation fault  */
+    while (i < cond_len &&  labels_num > 0) {
+        if (label_tab[i]  != -1) {
+            gen_set_label(label_tab[i]);
+            labels_num--;
+        }
+        i++;
+    }
+    g_free(label_tab);
+    return ret;
+}
+
+#define MSG_PRFX      "qemu note:  "
+#define GDB_AG_TRANS  "GDB agent expression translation"
+#define COND_EXP      "Conditional expression"
+#define NOT_SUPPORT   "is not supported"
+
+#define ERR_OS  "%s%s target evaluation %s for the current platform.\n"
+#define ERR_BIG "%sError in %s: %s is too big and will be evaluated on host.\n"
+#define ERR_INTERN  "%sInternal error in %s - %s will be evaluated on host.\n"
+
+int tcg_gen_bp_cond(CPUArchState *env,
+                    TCGContext *s,
+                    CPUBreakpoint *bp,
+                    int condlabel)
+/* returns 1 if OK, 0 in case error */
+{
+    int res = 1;
+    if (!bp_has_cond(bp)) {
+        return 0;
+    }
+    if (cpu_get_reg_var_func  == NULL)  {
+        fprintf(stderr, ERR_OS, MSG_PRFX, COND_EXP, NOT_SUPPORT);
+        return 0;
+    }
+    if (bp->cond_len > BP_AGENT_MAX_COND_SIZE)  {
+        fprintf(stderr, ERR_BIG, MSG_PRFX, GDB_AG_TRANS, COND_EXP);
+        return 0;
+    }
+    bp_agent_init_local(env, bp->cond_len);
+    res = bp_agent_tcg_gen(env, s, bp->cond_len, bp->cond_exp);
+    if (!res || !check_max_instr_num(s, 0)) {
+        if (!check_max_instr_num(s, 0)) {
+            fprintf(stderr, ERR_BIG, MSG_PRFX, GDB_AG_TRANS, COND_EXP);
+        } else {
+            fprintf(stderr, ERR_INTERN, MSG_PRFX, GDB_AG_TRANS, COND_EXP);
+        }
+        return 0;
+    } else {
+        bp_agent_brcond_top(env, condlabel);
+        return 1;
+    }
+}
+
+#else
+int tcg_gen_bp_cond(CPUArchState *env,
+                    TCGContext *s,
+                    CPUBreakpoint *bp,
+                    int condlabel)
+{
+    return 1;
+}
+void bp_agent_init(void)
+{
+}
+#endif
+int bp_has_cond(CPUBreakpoint *bp)
+{
+    return (bp != NULL && bp->cond_exp != NULL &&  bp->cond_len != 0);
+}
diff --git a/translate-gdbagent.h b/translate-gdbagent.h
new file mode 100644
index 0000000..de1f7fc
--- /dev/null
+++ b/translate-gdbagent.h
@@ -0,0 +1,49 @@ 
+
+/*
+ * Translation GDB bytecode to TCG.
+ * Used for evaluation breakpoint condition on host.
+ *
+ * Copyright (c) 2013 Anna Neiman <anna_neiman@mentor.com>
+ * Copyright (c) 2012 Mentor Graphics Corp.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef __TRANSLATE_GDBAGENT_H__
+#define __TRANSLATE_GDBAGENT_H__
+
+#include "tcg-op.h"
+
+struct TCGContext;
+int tcg_gen_bp_cond(CPUArchState *env,
+                    struct TCGContext *s,
+                    CPUBreakpoint *bp,
+                    int condlabel);
+
+extern void cpu_get_reg_var(TCGv var, int reg);
+
+void bp_agent_dump_bytecode(int cond_len, const uint8_t *cond_exp);
+
+void bp_agent_init(void);
+
+#if defined(TARGET_ARM)
+extern void cpu_get_reg_var_arm(TCGv var, int reg);
+#endif
+
+#endif