qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 24028/24028] Evaluate breakpoint condition on target


From: Anna Neiman
Subject: [Qemu-devel] [PATCH 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
Date: Thu, 21 Feb 2013 16:02:51 +0200

Signed-off-by: Anna Neiman <address@hidden>
---
 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

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 <address@hidden>
+ * 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 <address@hidden>
+ * 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
-- 
1.7.9.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]