Patchwork PATCH2 - evaluate breakpoint condition on target - functionality core ( without usage yet ) - translate gdb bytecode to TCG code for add to the translation block

login
register
mail settings
Submitter Anna Neiman
Date Feb. 26, 2013, 1:51 p.m.
Message ID <1361886716-10965-1-git-send-email-anna_neiman@mentor.com>
Download mbox | patch
Permalink /patch/223223/
State New
Headers show

Comments

Anna Neiman - Feb. 26, 2013, 1:51 p.m.
Signed-off-by: Anna Neiman <anna_neiman@mentor.com>
---
 Makefile.target      |    2 +-
 translate-gdbagent.c |  919 ++++++++++++++++++++++++++++++++++++++++++++++++++
 translate-gdbagent.h |   55 +++
 3 files changed, 975 insertions(+), 1 deletion(-)
 create mode 100644 translate-gdbagent.c
 create mode 100644 translate-gdbagent.h

Patch

diff --git a/Makefile.target b/Makefile.target
index ca657b3..e2df631 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/translate-gdbagent.c b/translate-gdbagent.c
new file mode 100644
index 0000000..d959a47
--- /dev/null
+++ b/translate-gdbagent.c
@@ -0,0 +1,919 @@ 
+/*
+ * 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"
+#include "qemu/error-report.h"
+
+#if defined(TARGET_HAS_ICE)
+
+static TCGv_ptr bp_agent_stack_current_tcg ;
+static TCGv bp_agent_error_tcg  ;
+
+
+/* functions for retrieve register contents - platform depend
+should be initialized inside gen_intermediate_code_internal
+for each supported platform*/
+CPUGetRegVarFuncType cpu_get_reg_var_func;
+CPUSetVarToEnvPtrFuncType cpu_set_var_to_env_ptr_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");
+        bp_agent_error_tcg =
+          tcg_global_mem_new(TCG_AREG0,
+                             offsetof(CPUArchState, bp_agent_error),
+                             "bp_agent_error");
+     }
+}
+static void bp_agent_init_local(CPUArchState *env, int len)
+{
+    if (len > BP_AGENT_MAX_STACK_SIZE) {
+        fprintf(stderr,
+                "GDB agent: Condition length more then %d is unsupported.\n",
+                BP_AGENT_MAX_STACK_SIZE);
+    }
+
+    cpu_set_var_to_env_ptr_func ( bp_agent_stack_current_tcg, offsetof(CPUArchState, bp_agent_stack));
+}
+
+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);
+
+    /* 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++;
+            bswap32(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: /* shouldn't occur*/
+        {
+            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*/
+            {
+                val = bp_agent_get_arg(cond_exp, &i, 2) ;
+                if ( val < 0 || val >= 15 ) {
+                    ret = 0;
+                } else {
+                    TCGv tmp1 = tcg_temp_new();
+                    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, tmp2, 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.
+      For example, it can be situation when goto operator
+      to the label "x" was generated,
+      but the error occured before generation label "x" itself*/
+    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 || cpu_set_var_to_env_ptr_func == NULL)  {
+        error_report(ERR_OS, MSG_PRFX, COND_EXP, NOT_SUPPORT);
+        return 0;
+    }
+    if (bp->cond_len > BP_AGENT_MAX_STACK_SIZE)  {
+        error_report(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)) {
+            error_report(ERR_BIG, MSG_PRFX, GDB_AG_TRANS, COND_EXP);
+        } else {
+            error_report(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..76db4d2
--- /dev/null
+++ b/translate-gdbagent.h
@@ -0,0 +1,55 @@ 
+
+/*
+ * 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);
+
+typedef void(*CPUGetRegVarFuncType)(TCGv var, int reg);
+typedef void(*CPUSetVarToEnvPtrFuncType)
+  (TCGv_ptr var_ptr, int offset);
+
+/* functions for retrieve register contents - platform depend
+should be initialized inside gen_intermediate_code_internal
+for each supported platform*/
+extern CPUGetRegVarFuncType cpu_get_reg_var_func;
+extern CPUSetVarToEnvPtrFuncType cpu_set_var_to_env_ptr_func;
+
+#endif