diff --git a/exec.c b/exec.c
index 4289c87..c7d1284 100644
--- a/exec.c
+++ b/exec.c
@@ -458,10 +458,7 @@ 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->cond_exp);
 
     g_free(breakpoint);
 #endif
diff --git a/gdbstub.c b/gdbstub.c
index e2dac86..4d33568 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2095,7 +2095,6 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
 
     uint8_t *bp_cond_expr = NULL;
     int bp_cond_len = 0;
-    int i = 0 ;
 
 #ifdef DEBUG_GDB
     printf("command='%s'\n", line_buf);
@@ -2318,14 +2317,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
         if (*p == ',')
             p++;
         len = strtoull(p, (char **)&p, 16);
-        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);
@@ -2334,20 +2327,11 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
                     }
                     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);
+                        bp_cond_expr = 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;
-                                error_report("Error in breakpoint condition");
-                            } else {
-                                hextomem(bp_cond_expr+i, p, 1);
-                                p += 2;
-                            }
-                        }
+                        hextomem(bp_cond_expr, p, bp_cond_len);
+                        p += (bp_cond_len << 1);
                     }
 #ifdef DEBUG_GDB
                     bp_agent_dump_bytecode(bp_cond_len, bp_cond_expr);
-- 
1.7.9.5
 


[PATCH] PATCH1 - infrastructure for  Evaluate breakpoint condition
 on target.OPC_MAX_SIZE - size of translation buffer - was
 increased because condition translated bytecode should be
 executed in one block

Signed-off-by: Anna Neiman <anna_neiman@mentor.com>
---
 exec.c                  |   16 ++++++++++++-
 gdbstub.c               |   57 ++++++++++++++++++++++++++++++++++++++++++-----
 include/exec/cpu-all.h  |    1 +
 include/exec/cpu-defs.h |   20 +++++++++++++++++
 include/exec/exec-all.h |    2 +-
 target-i386/helper.c    |    2 +-
 tcg/tcg-op.h            |   10 +++++++++
 tcg/tcg.h               |    6 +++++
 8 files changed, 106 insertions(+), 8 deletions(-)

diff --git a/exec.c b/exec.c
index a41bcb8..4289c87 100644
--- a/exec.c
+++ b/exec.c
@@ -398,6 +398,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 +408,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 +458,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
 }
@@ -551,7 +564,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 32dfea9..814f596 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1941,7 +1941,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 +1954,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;
         }
@@ -2089,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
@@ -2310,16 +2316,54 @@ 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;
+                                error_report("Error in breakpoint condition");
+                            } else {
+                                hextomem(bp_cond_expr+i, p, 1);
+                                p += 2;
+                            }
+                        }
+                    }
+                }
+        }
+        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++;
@@ -2445,6 +2489,9 @@ 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 3dc9656..0bf63c2 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -136,9 +136,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;
@@ -146,6 +150,18 @@ typedef struct CPUWatchpoint {
     QTAILQ_ENTRY(CPUWatchpoint) entry;
 } CPUWatchpoint;
 
+
+
+typedef double target_double;
+
+typedef union BPAgentStackElementType {
+    target_long l;
+    target_double d;
+} BPAgentStackElementType;
+
+
+#define BP_AGENT_MAX_STACK_SIZE 1024
+
 #define CPU_TEMP_BUF_NLONGS 128
 #define CPU_COMMON                                                      \
     /* soft mmu support */                                              \
@@ -191,6 +207,10 @@ typedef struct CPUWatchpoint {
     /* user data */                                                     \
     void *opaque;                                                       \
                                                                         \
+    BPAgentStackElementType bp_agent_stack[BP_AGENT_MAX_STACK_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*/ \
     const char *cpu_model_str;
 
 #endif
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index e856191..db5a38c 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-i386/helper.c b/target-i386/helper.c
index 82a731c..a0d9e93 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -984,7 +984,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/tcg/tcg-op.h b/tcg/tcg-op.h
index d70b2eb..6c3353c 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);
@@ -2946,6 +2950,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), \
@@ -2953,5 +2959,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 b195396..b367406 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). */
@@ -690,4 +694,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__*/
-- 
