diff mbox

[v3] Execute _start and reach to the first function call successfully

Message ID BLU437-SMTP25F3E8ED2ECC012B08FFF5B9040@phx.gbl
State New
Headers show

Commit Message

Chen Gang March 14, 2015, 6:03 a.m. UTC
QEMU TILE-Gx can decode bundle, disassemble code, and generate tcg code
for 1st TB block (__start). Then directly jump to __libc_start_main (2nd
TB block).

In __libc_start_main, it can continue executing to the first function
call _dl_aux_init().

Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
---
 target-tilegx/cpu-qom.h   |   2 +
 target-tilegx/cpu.c       |   4 -
 target-tilegx/cpu.h       |  22 +-
 target-tilegx/translate.c | 790 +++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 798 insertions(+), 20 deletions(-)

Comments

Peter Maydell March 15, 2015, 11:45 p.m. UTC | #1
On 14 March 2015 at 06:03, Chen Gang <xili_gchen_5257@hotmail.com> wrote:
> QEMU TILE-Gx can decode bundle, disassemble code, and generate tcg code
> for 1st TB block (__start). Then directly jump to __libc_start_main (2nd
> TB block).
>
> In __libc_start_main, it can continue executing to the first function
> call _dl_aux_init().

>  /* TILE-Gx register alias */
> -#define TILEGX_R_RE  0   /*  0 register, for function/syscall return value */
> -#define TILEGX_R_NR  10  /* 10 register, for syscall number */
> -#define TILEGX_R_BP  52  /* 52 register, optional frame pointer */
> -#define TILEGX_R_TP  53  /* TP register, thread local storage data */
> -#define TILEGX_R_SP  54  /* SP register, stack pointer */
> -#define TILEGX_R_LR  55  /* LR register, may save pc, but it is not pc */
> +#define TILEGX_R_RE    0   /*  0 register, for function/syscall return value */
> +#define TILEGX_R_NR    10  /* 10 register, for syscall number */
> +#define TILEGX_R_BP    52  /* 52 register, optional frame pointer */
> +#define TILEGX_R_TP    53  /* TP register, thread local storage data */
> +#define TILEGX_R_SP    54  /* SP register, stack pointer */
> +#define TILEGX_R_LR    55  /* LR register, may save pc, but it is not pc */
> +#define TILEGX_R_ZERO  63  /* Zero register, always zero */
> +#define TILEGX_R_COUNT 56  /* Only 56 registers are really useful */
> +#define TILEGX_R_NOREG 255 /* Invalid register value */

This appears to be changing code that was introduced in
a previous patch (which one? this patch doesn't appear to be
part of a series). Don't do that -- just get it right in
the first place.

-- PMM
Chen Gang March 15, 2015, 11:57 p.m. UTC | #2
On 3/16/15 07:45, Peter Maydell wrote:
> On 14 March 2015 at 06:03, Chen Gang <xili_gchen_5257@hotmail.com> wrote:
>> QEMU TILE-Gx can decode bundle, disassemble code, and generate tcg code
>> for 1st TB block (__start). Then directly jump to __libc_start_main (2nd
>> TB block).
>>
>> In __libc_start_main, it can continue executing to the first function
>> call _dl_aux_init().
> 
>>  /* TILE-Gx register alias */
>> -#define TILEGX_R_RE  0   /*  0 register, for function/syscall return value */
>> -#define TILEGX_R_NR  10  /* 10 register, for syscall number */
>> -#define TILEGX_R_BP  52  /* 52 register, optional frame pointer */
>> -#define TILEGX_R_TP  53  /* TP register, thread local storage data */
>> -#define TILEGX_R_SP  54  /* SP register, stack pointer */
>> -#define TILEGX_R_LR  55  /* LR register, may save pc, but it is not pc */
>> +#define TILEGX_R_RE    0   /*  0 register, for function/syscall return value */
>> +#define TILEGX_R_NR    10  /* 10 register, for syscall number */
>> +#define TILEGX_R_BP    52  /* 52 register, optional frame pointer */
>> +#define TILEGX_R_TP    53  /* TP register, thread local storage data */
>> +#define TILEGX_R_SP    54  /* SP register, stack pointer */
>> +#define TILEGX_R_LR    55  /* LR register, may save pc, but it is not pc */
>> +#define TILEGX_R_ZERO  63  /* Zero register, always zero */
>> +#define TILEGX_R_COUNT 56  /* Only 56 registers are really useful */
>> +#define TILEGX_R_NOREG 255 /* Invalid register value */
> 
> This appears to be changing code that was introduced in
> a previous patch (which one? this patch doesn't appear to be
> part of a series). Don't do that -- just get it right in
> the first place.
> 

OK, thanks. And next, I shall try to send the whole tilegx patches again
(it is about 6-8 patches), within 2015-03-18.

Thanks.
Richard Henderson March 16, 2015, 3:31 p.m. UTC | #3
On 03/13/2015 11:03 PM, Chen Gang wrote:
> +static void decode_rrr_1_opcode_y0(struct DisasContext *dc,
> +                                   tilegx_bundle_bits bundle)
> +{
> +    switch (get_RRROpcodeExtension_Y0(bundle)) {
> +    case UNARY_RRR_1_OPCODE_Y0:
> +        switch (get_UnaryOpcodeExtension_Y0(bundle)) {
> +        case  FNOP_UNARY_OPCODE_Y0:
> +            if (!get_SrcA_Y0(bundle) && !get_Dest_Y0(bundle)) {
> +                gen_fnop();
> +                return;
> +            }
> +            break;
> +        default:
> +            break;
> +        }
> +        break;
> +    default:
> +        break;
> +    }
> +
> +    qemu_log_mask(LOG_UNIMP, "UNIMP rrr_1_opcode_y0, %16.16llx\n", bundle);
> +    dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
> +}

I think it would be helpful if, in the first patch, you put all of the opcode
symbols into the proper place in the switch statements.  That way it's easy to
tell at a glance what has yet to be implemented.  For instance, for this
function you'd put

$ grep _UNARY opcode_tilegx.h  | grep _Y0
  CNTLZ_UNARY_OPCODE_Y0 = 1,
  CNTTZ_UNARY_OPCODE_Y0 = 2,
  FNOP_UNARY_OPCODE_Y0 = 3,
  FSINGLE_PACK1_UNARY_OPCODE_Y0 = 4,
  NOP_UNARY_OPCODE_Y0 = 5,
  PCNT_UNARY_OPCODE_Y0 = 6,
  REVBITS_UNARY_OPCODE_Y0 = 7,
  REVBYTES_UNARY_OPCODE_Y0 = 8,
  TBLIDXB0_UNARY_OPCODE_Y0 = 9,
  TBLIDXB1_UNARY_OPCODE_Y0 = 10,
  TBLIDXB2_UNARY_OPCODE_Y0 = 11,
  TBLIDXB3_UNARY_OPCODE_Y0 = 12,

in the get_UnaryOpcodeExtension_Y0 switch statement and

$ grep _RRR_1 opcode_tilegx.h  | grep _Y0
  SHL1ADD_RRR_1_OPCODE_Y0 = 0,
  SHL2ADD_RRR_1_OPCODE_Y0 = 1,
  SHL3ADD_RRR_1_OPCODE_Y0 = 2,
  UNARY_RRR_1_OPCODE_Y0 = 3,

in the get_RRROpcodeExtension_Y0 switch statement.

Likewise with all of the other "decode" functions that contain a switch.

> +    qemu_log("fnop\n");
> +    qemu_log("addi r%d, r%d, %d\n", rdst, rsrc, imm8);

Again, use qemu_log_mask(CPU_LOG_TB_IN_ASM).



r~
Richard Henderson March 16, 2015, 3:37 p.m. UTC | #4
On 03/15/2015 04:57 PM, Chen Gang wrote:
> OK, thanks. And next, I shall try to send the whole tilegx patches again
> (it is about 6-8 patches), within 2015-03-18.

When you do so, make sure it's against the *current* master tree.

Your patch set doesn't compile at all at the moment, after


commit 2994fd96d986578a342f2342501b4ad30f6d0a85
Author: Eduardo Habkost <ehabkost@redhat.com>
Date:   Thu Feb 26 17:37:49 2015 -0300

    cpu: Make cpu_init() return QOM CPUState object


changed the return type of cpu_init.

In addition, one of your patches is going to need to copy over the linux
opcodes_tilegx.h header file.  Perhaps you forgot to "git add" the file when
you created this "v3 Execute" patch?


r~
Chen Gang March 17, 2015, 10:57 p.m. UTC | #5
On 3/16/15 23:31, Richard Henderson wrote:
> On 03/13/2015 11:03 PM, Chen Gang wrote:
>> +static void decode_rrr_1_opcode_y0(struct DisasContext *dc,
>> +                                   tilegx_bundle_bits bundle)
>> +{
>> +    switch (get_RRROpcodeExtension_Y0(bundle)) {
>> +    case UNARY_RRR_1_OPCODE_Y0:
>> +        switch (get_UnaryOpcodeExtension_Y0(bundle)) {
>> +        case  FNOP_UNARY_OPCODE_Y0:
>> +            if (!get_SrcA_Y0(bundle) && !get_Dest_Y0(bundle)) {
>> +                gen_fnop();
>> +                return;
>> +            }
>> +            break;
>> +        default:
>> +            break;
>> +        }
>> +        break;
>> +    default:
>> +        break;
>> +    }
>> +
>> +    qemu_log_mask(LOG_UNIMP, "UNIMP rrr_1_opcode_y0, %16.16llx\n", bundle);
>> +    dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
>> +}
> 
> I think it would be helpful if, in the first patch, you put all of the opcode
> symbols into the proper place in the switch statements.  That way it's easy to
> tell at a glance what has yet to be implemented.  For instance, for this
> function you'd put
> 
> $ grep _UNARY opcode_tilegx.h  | grep _Y0
>   CNTLZ_UNARY_OPCODE_Y0 = 1,
>   CNTTZ_UNARY_OPCODE_Y0 = 2,
>   FNOP_UNARY_OPCODE_Y0 = 3,
>   FSINGLE_PACK1_UNARY_OPCODE_Y0 = 4,
>   NOP_UNARY_OPCODE_Y0 = 5,
>   PCNT_UNARY_OPCODE_Y0 = 6,
>   REVBITS_UNARY_OPCODE_Y0 = 7,
>   REVBYTES_UNARY_OPCODE_Y0 = 8,
>   TBLIDXB0_UNARY_OPCODE_Y0 = 9,
>   TBLIDXB1_UNARY_OPCODE_Y0 = 10,
>   TBLIDXB2_UNARY_OPCODE_Y0 = 11,
>   TBLIDXB3_UNARY_OPCODE_Y0 = 12,
> 
> in the get_UnaryOpcodeExtension_Y0 switch statement and
> 
> $ grep _RRR_1 opcode_tilegx.h  | grep _Y0
>   SHL1ADD_RRR_1_OPCODE_Y0 = 0,
>   SHL2ADD_RRR_1_OPCODE_Y0 = 1,
>   SHL3ADD_RRR_1_OPCODE_Y0 = 2,
>   UNARY_RRR_1_OPCODE_Y0 = 3,
> 
> in the get_RRROpcodeExtension_Y0 switch statement.
> 
> Likewise with all of the other "decode" functions that contain a switch.
> 

OK, thanks. It is a good idea to me.


>> +    qemu_log("fnop\n");
>> +    qemu_log("addi r%d, r%d, %d\n", rdst, rsrc, imm8);
> 
> Again, use qemu_log_mask(CPU_LOG_TB_IN_ASM).
> 

OK, thanks. I shall use qemu_log_mask in all areas within tilegx.

Thanks.
Chen Gang March 17, 2015, 11:02 p.m. UTC | #6
On 3/16/15 23:37, Richard Henderson wrote:
> On 03/15/2015 04:57 PM, Chen Gang wrote:
>> OK, thanks. And next, I shall try to send the whole tilegx patches again
>> (it is about 6-8 patches), within 2015-03-18.
> 
> When you do so, make sure it's against the *current* master tree.
> 
> Your patch set doesn't compile at all at the moment, after
> 
> 
> commit 2994fd96d986578a342f2342501b4ad30f6d0a85
> Author: Eduardo Habkost <ehabkost@redhat.com>
> Date:   Thu Feb 26 17:37:49 2015 -0300
> 
>     cpu: Make cpu_init() return QOM CPUState object
> 
> 
> changed the return type of cpu_init.
> 

OK, thanks, I shall merge current code to the latest master version.

> In addition, one of your patches is going to need to copy over the linux
> opcodes_tilegx.h header file.  Perhaps you forgot to "git add" the file when
> you created this "v3 Execute" patch?

Oh, sorry, I forgot it in patch v3.

And I shall send the tilegx patches within today (2015-03-18).


Thanks.
diff mbox

Patch

diff --git a/target-tilegx/cpu-qom.h b/target-tilegx/cpu-qom.h
index 4ee11e1..5615c3b 100644
--- a/target-tilegx/cpu-qom.h
+++ b/target-tilegx/cpu-qom.h
@@ -68,4 +68,6 @@  static inline TileGXCPU *tilegx_env_get_cpu(CPUTLGState *env)
 
 #define ENV_GET_CPU(e) CPU(tilegx_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(TileGXCPU, env)
+
 #endif
diff --git a/target-tilegx/cpu.c b/target-tilegx/cpu.c
index cf46b8b..8255fdc 100644
--- a/target-tilegx/cpu.c
+++ b/target-tilegx/cpu.c
@@ -69,10 +69,6 @@  static void tilegx_cpu_realizefn(DeviceState *dev, Error **errp)
     tcc->parent_realize(dev, errp);
 }
 
-static void tilegx_tcg_init(void)
-{
-}
-
 static void tilegx_cpu_initfn(Object *obj)
 {
     CPUState *cs = CPU(obj);
diff --git a/target-tilegx/cpu.h b/target-tilegx/cpu.h
index 87dc56b..93e16c3 100644
--- a/target-tilegx/cpu.h
+++ b/target-tilegx/cpu.h
@@ -30,16 +30,21 @@ 
 #include "fpu/softfloat.h"
 
 /* TILE-Gx register alias */
-#define TILEGX_R_RE  0   /*  0 register, for function/syscall return value */
-#define TILEGX_R_NR  10  /* 10 register, for syscall number */
-#define TILEGX_R_BP  52  /* 52 register, optional frame pointer */
-#define TILEGX_R_TP  53  /* TP register, thread local storage data */
-#define TILEGX_R_SP  54  /* SP register, stack pointer */
-#define TILEGX_R_LR  55  /* LR register, may save pc, but it is not pc */
+#define TILEGX_R_RE    0   /*  0 register, for function/syscall return value */
+#define TILEGX_R_NR    10  /* 10 register, for syscall number */
+#define TILEGX_R_BP    52  /* 52 register, optional frame pointer */
+#define TILEGX_R_TP    53  /* TP register, thread local storage data */
+#define TILEGX_R_SP    54  /* SP register, stack pointer */
+#define TILEGX_R_LR    55  /* LR register, may save pc, but it is not pc */
+#define TILEGX_R_ZERO  63  /* Zero register, always zero */
+#define TILEGX_R_COUNT 56  /* Only 56 registers are really useful */
+#define TILEGX_R_NOREG 255 /* Invalid register value */
+
 
 typedef struct CPUTLGState {
-    uint64_t regs[56];
-    uint64_t pc;
+    uint64_t regs[TILEGX_R_COUNT]; /* Common used registers by outside */
+    uint64_t pc;                   /* Current pc */
+
     CPU_COMMON
 } CPUTLGState;
 
@@ -54,6 +59,7 @@  typedef struct CPUTLGState {
 
 #include "exec/cpu-all.h"
 
+void tilegx_tcg_init(void);
 int cpu_tilegx_exec(CPUTLGState *s);
 int cpu_tilegx_signal_handler(int host_signum, void *pinfo, void *puc);
 
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index 9aa82a9..a862006 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -23,19 +23,793 @@ 
 #include "disas/disas.h"
 #include "tcg-op.h"
 #include "exec/cpu_ldst.h"
+#include "opcode_tilegx.h"
+
+#define TILEGX_OPCODE_MAX_X0            164  /* include 164 */
+#define TILEGX_OPCODE_MAX_X1            107  /* include 107 */
+#define TILEGX_OPCODE_MAX_Y0             15  /* include 15 */
+#define TILEGX_OPCODE_MAX_Y1             15  /* include 15 */
+#define TILEGX_OPCODE_MAX_Y2              3  /* include 3 */
+
+#define TILEGX_EXCP_OPCODE_UNKNOWN      0x1
+#define TILEGX_EXCP_OPCODE_UNIMPLEMENT  0x2
+#define TILEGX_EXCP_REG_UNSUPPORTED     0x81
+
+static TCGv_ptr cpu_env;
+static TCGv cpu_pc;
+static TCGv cpu_regs[TILEGX_R_COUNT];
+
+static const char * const reg_names[] = {
+     "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
+     "r8",  "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+    "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
+    "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
+    "r48", "r49", "r50", "r51",  "bp",  "tp",  "sp",  "lr"
+};
+
+/* It is for temporary registers */
+typedef struct DisasContextTemp {
+    unsigned char idx;             /* index */
+    TCGv val;                      /* value */
+} DisasContextTemp;
+
+/* This is the state at translation time.  */
+typedef struct DisasContext {
+    uint64_t pc;                   /* Current pc */
+    uint64_t exception;            /* Current exception, 0 means empty */
+
+    TCGv zero;                     /* For zero register */
+
+    DisasContextTemp *tmp_regcur;  /* Current temporary registers */
+    DisasContextTemp tmp_regs[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
+                                   /* All temporary registers */
+
+    struct {
+        TCGCond cond;              /* Branch condition */
+        TCGv dest;                 /* pc jump destination, if will jump */
+        TCGv val1;                 /* Firt value for condition comparing */
+        TCGv val2;                 /* Second value for condition comparing */
+    } jmp;                         /* Jump object, only once in each TB block */
+} DisasContext;
+
+#include "exec/gen-icount.h"
+
+static TCGv load_zero(DisasContext *dc)
+{
+    if (TCGV_IS_UNUSED_I64(dc->zero)) {
+        dc->zero = tcg_const_i64(0);
+    }
+    return dc->zero;
+}
+
+static TCGv load_gr(DisasContext *dc, uint8_t reg)
+{
+    if (likely(reg < TILEGX_R_COUNT)) {
+        return cpu_regs[reg];
+    } else if (reg != TILEGX_R_ZERO) {
+        dc->exception = TILEGX_EXCP_REG_UNSUPPORTED;
+    }
+    return load_zero(dc);
+}
+
+static TCGv dest_gr(DisasContext *dc, uint8_t rdst)
+{
+    DisasContextTemp *tmp = dc->tmp_regcur;
+    tmp->idx = rdst;
+    tmp->val = tcg_temp_new_i64();
+    return tmp->val;
+}
+
+static void gen_fnop(void)
+{
+    qemu_log("fnop\n");
+}
+
+static void gen_addimm(struct DisasContext *dc,
+                       uint8_t rdst, uint8_t rsrc, int64_t imm)
+{
+    tcg_gen_addi_i64(dest_gr(dc, rdst), load_gr(dc, rsrc), imm);
+}
+
+static void gen_addi(struct DisasContext *dc,
+                     uint8_t rdst, uint8_t rsrc, char imm8)
+{
+    qemu_log("addi r%d, r%d, %d\n", rdst, rsrc, imm8);
+    gen_addimm(dc, rdst, rsrc, (int64_t)imm8);
+}
+
+static void gen_addli(struct DisasContext *dc,
+                      uint8_t rdst, uint8_t rsrc, int16_t im16)
+{
+    qemu_log("addli r%d, r%d, %d\n", rdst, rsrc, im16);
+    gen_addimm(dc, rdst, rsrc, (int64_t)im16);
+}
+
+static void gen_or(struct DisasContext *dc,
+                    uint8_t rdst, uint8_t rsrc, uint8_t rsrcb)
+{
+    qemu_log("or r%d, r%d, r%d\n", rdst, rsrc, rsrcb);
+    tcg_gen_or_i64(dest_gr(dc, rdst), load_gr(dc, rsrc), load_gr(dc, rsrcb));
+}
+
+static void gen_add(struct DisasContext *dc,
+                    uint8_t rdst, uint8_t rsrc, uint8_t rsrcb)
+{
+    qemu_log("add r%d, r%d, r%d\n", rdst, rsrc, rsrcb);
+    tcg_gen_add_i64(dest_gr(dc, rdst), load_gr(dc, rsrc), load_gr(dc, rsrcb));
+}
+
+static void gen_andimm(struct DisasContext *dc,
+                       uint8_t rdst, uint8_t rsrc, int64_t imm)
+{
+    tcg_gen_andi_i64(dest_gr(dc, rdst), load_gr(dc, rsrc), imm);
+}
+
+static void gen_andi(struct DisasContext *dc,
+                     uint8_t rdst, uint8_t rsrc, char imm8)
+{
+    qemu_log("andi r%d, r%d, %d\n", rdst, rsrc, imm8);
+    gen_andimm(dc, rdst, rsrc, (int64_t)imm8);
+}
+
+static void gen_shl3add(struct DisasContext *dc,
+                        uint8_t rdst, uint8_t rsrc, uint8_t rsrcb)
+{
+    TCGv tmp = dest_gr(dc, rdst);
+
+    qemu_log("shl3add r%d, r%d, r%d\n", rdst, rsrc, rsrcb);
+    tcg_gen_shli_i64(tmp, load_gr(dc, rsrc), 3);
+    tcg_gen_add_i64(tmp, tmp, load_gr(dc, rsrcb));
+}
+
+static void gen_shl16insli(struct DisasContext *dc,
+                           uint8_t rdst, uint8_t rsrc, uint16_t uimm16)
+{
+    TCGv tmp = dest_gr(dc, rdst);
+
+    qemu_log("shl16insli r%d, r%d, %llx\n", rdst, rsrc, (long long)uimm16);
+    tcg_gen_shli_i64(tmp, load_gr(dc, rsrc), 16);
+    tcg_gen_ori_i64(tmp, tmp, uimm16);
+}
+
+static void gen_lnk(struct DisasContext *dc, uint8_t rdst)
+{
+    qemu_log("lnk r%d\n", rdst);
+    tcg_gen_movi_i64(dest_gr(dc, rdst), dc->pc + TILEGX_BUNDLE_SIZE_IN_BYTES);
+}
+
+static int gen_beqz(struct DisasContext *dc, uint8_t rsrc, int32_t off)
+{
+    qemu_log("beqz r%d, %d\n", rsrc, off);
+
+    dc->jmp.dest = tcg_temp_new_i64();
+    dc->jmp.val1 = tcg_temp_new_i64();
+    dc->jmp.val2 = tcg_temp_new_i64();
+
+    dc->jmp.cond = TCG_COND_EQ;
+    tcg_gen_movi_i64(dc->jmp.dest,
+                     dc->pc + (int64_t)off * TILEGX_BUNDLE_SIZE_IN_BYTES);
+    tcg_gen_mov_i64(dc->jmp.val1, load_gr(dc, rsrc));
+    tcg_gen_movi_i64(dc->jmp.val2, 0);
+
+    return 0;
+}
+
+static int gen_bnezt(struct DisasContext *dc, uint8_t rsrc, int32_t off)
+{
+    qemu_log("bnezt r%d, %d\n", rsrc, off);
+
+    dc->jmp.dest = tcg_temp_new_i64();
+    dc->jmp.val1 = tcg_temp_new_i64();
+    dc->jmp.val2 = tcg_temp_new_i64();
+
+    dc->jmp.cond = TCG_COND_NE;
+    tcg_gen_movi_i64(dc->jmp.dest,
+                     dc->pc + (int64_t)off * TILEGX_BUNDLE_SIZE_IN_BYTES);
+    tcg_gen_mov_i64(dc->jmp.val1, load_gr(dc, rsrc));
+    tcg_gen_movi_i64(dc->jmp.val2, 0);
+
+    return 0;
+}
+
+static void gen_ld(struct DisasContext *dc, uint8_t rdst, uint8_t rsrc)
+{
+    qemu_log("ld r%d, r%d\n", rdst, rsrc);
+    tcg_gen_qemu_ld_i64(dest_gr(dc, rdst), load_gr(dc, rsrc),
+                        MMU_USER_IDX, MO_LEQ);
+}
+
+static void gen_st(struct DisasContext *dc, uint8_t rsrc, uint8_t rsrcb)
+{
+    qemu_log("st r%d, r%d\n", rsrc, rsrcb);
+    tcg_gen_qemu_st_i64(load_gr(dc, rsrcb), load_gr(dc, rsrc),
+                        MMU_USER_IDX, MO_LEQ);
+}
+
+static void gen_st4(struct DisasContext *dc, uint8_t rsrc, uint8_t rsrcb)
+{
+    qemu_log("st4 r%d, r%d\n", rsrc, rsrcb);
+    tcg_gen_qemu_st_i64(load_gr(dc, rsrcb), load_gr(dc, rsrc),
+                        MMU_USER_IDX, MO_LEUL);
+}
+
+static int gen_jr(struct DisasContext *dc, uint8_t rsrc)
+{
+    qemu_log("jr r%d\n", rsrc);
+
+    dc->jmp.dest = tcg_temp_new_i64();
+
+    dc->jmp.cond = TCG_COND_ALWAYS;
+    tcg_gen_mov_i64(dc->jmp.dest, load_gr(dc, rsrc));
+    return 0;
+}
+
+static void decode_addi_opcode_y0(struct DisasContext *dc,
+                                  tilegx_bundle_bits bundle)
+{
+    gen_addi(dc, (uint8_t)get_Dest_Y0(bundle),
+             (uint8_t)get_SrcA_Y0(bundle), (int8_t)get_Imm8_Y0(bundle));
+}
+
+static void decode_rrr_1_opcode_y0(struct DisasContext *dc,
+                                   tilegx_bundle_bits bundle)
+{
+    switch (get_RRROpcodeExtension_Y0(bundle)) {
+    case UNARY_RRR_1_OPCODE_Y0:
+        switch (get_UnaryOpcodeExtension_Y0(bundle)) {
+        case  FNOP_UNARY_OPCODE_Y0:
+            if (!get_SrcA_Y0(bundle) && !get_Dest_Y0(bundle)) {
+                gen_fnop();
+                return;
+            }
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+
+    qemu_log_mask(LOG_UNIMP, "UNIMP rrr_1_opcode_y0, %16.16llx\n", bundle);
+    dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+}
+
+static void decode_rrr_5_opcode_y0(struct DisasContext *dc,
+                                   tilegx_bundle_bits bundle)
+{
+    uint8_t rsrc = (uint8_t)get_SrcA_Y0(bundle);
+    uint8_t rsrcb = (uint8_t)get_SrcB_Y0(bundle);
+    uint8_t rdst = (uint8_t)get_Dest_Y0(bundle);
+
+    switch (get_RRROpcodeExtension_Y0(bundle)) {
+    case OR_RRR_5_OPCODE_Y0:
+        gen_or(dc, rdst, rsrc, rsrcb);
+        return;
+    default:
+        break;
+    }
+    qemu_log_mask(LOG_UNIMP, "UNIMP rrr_5_opcode_y0, %16.16llx\n", bundle);
+    dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+}
+
+static void decode_addi_opcode_y1(struct DisasContext *dc,
+                                  tilegx_bundle_bits bundle)
+{
+    uint8_t rsrc = (uint8_t)get_SrcA_Y1(bundle);
+    uint8_t rdst = (uint8_t)get_Dest_Y1(bundle);
+    int8_t imm8 = (int8_t)get_Imm8_Y1(bundle);
+
+    gen_addi(dc, rdst, rsrc, imm8);
+}
+
+static void decode_rrr_1_opcode_y1(struct DisasContext *dc,
+                                   tilegx_bundle_bits bundle)
+{
+    switch (get_RRROpcodeExtension_Y1(bundle)) {
+    case UNARY_RRR_1_OPCODE_Y1:
+        switch (get_UnaryOpcodeExtension_Y1(bundle)) {
+        case FNOP_UNARY_OPCODE_Y1:
+            if (!get_SrcA_Y1(bundle) && !get_Dest_Y1(bundle)) {
+                gen_fnop();
+                return;
+            }
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+    qemu_log_mask(LOG_UNIMP, "UNIMP rrr_1_opcode_y1, %16.16llx\n", bundle);
+    dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+}
+
+static void decode_rrr_5_opcode_y1(struct DisasContext *dc,
+                                   tilegx_bundle_bits bundle)
+{
+    uint8_t rsrc = (uint8_t)get_SrcA_Y1(bundle);
+    uint8_t rsrcb = (uint8_t)get_SrcB_Y1(bundle);
+    uint8_t rdst = (uint8_t)get_Dest_Y1(bundle);
+
+    switch (get_RRROpcodeExtension_Y1(bundle)) {
+    case OR_RRR_5_OPCODE_Y1:
+        gen_or(dc, rdst, rsrc, rsrcb);
+        return;
+    default:
+        break;
+    }
+    qemu_log_mask(LOG_UNIMP, "UNIMP rrr_5_opcode_y1, %16.16llx\n", bundle);
+    dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+}
+
+static void decode_ldst_opcode_y2(struct DisasContext *dc,
+                                  tilegx_bundle_bits bundle)
+{
+    uint8_t rsrca = (uint8_t)get_SrcA_Y2(bundle);
+    uint8_t rsrcbdst = (uint8_t)get_SrcBDest_Y2(bundle);
+
+    switch (get_Mode(bundle)) {
+    case MODE_OPCODE_YB2:
+        gen_ld(dc, rsrcbdst, rsrca);
+        return;
+    case MODE_OPCODE_YC2:
+        gen_st(dc, rsrca, rsrcbdst);
+        return;
+    default:
+        break;
+    }
+    qemu_log_mask(LOG_UNIMP, "UNIMP ldst_opcode_y2, %16.16llx\n", bundle);
+    dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+}
+
+static void decode_addli_opcode_x0(struct DisasContext *dc,
+                                   tilegx_bundle_bits bundle)
+{
+    uint8_t rsrc = (uint8_t)get_SrcA_X0(bundle);
+    uint8_t rdst = (uint8_t)get_Dest_X0(bundle);
+    int16_t imm16 = (int16_t)get_Imm16_X0(bundle);
+
+    gen_addli(dc, rdst, rsrc, imm16);
+}
+
+static void decode_imm8_opcode_x0(struct DisasContext *dc,
+                                  tilegx_bundle_bits bundle)
+{
+    uint8_t rsrc = (uint8_t)get_SrcA_X0(bundle);
+    uint8_t rdst = (uint8_t)get_Dest_X0(bundle);
+    int8_t imm8 = (int8_t)get_Imm8_X0(bundle);
+
+    switch (get_Imm8OpcodeExtension_X0(bundle)) {
+    case ADDI_IMM8_OPCODE_X0:
+        gen_addi(dc, rdst, rsrc, imm8);
+        return;
+    case ANDI_IMM8_OPCODE_X0:
+        gen_andi(dc, rdst, rsrc, imm8);
+        return;
+    default:
+        break;
+    }
+    qemu_log_mask(LOG_UNIMP, "UNIMP imm8_opcode_x0, %16.16llx\n", bundle);
+    dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+}
+
+static void decode_rrr_0_opcode_x0(struct DisasContext *dc,
+                                   tilegx_bundle_bits bundle)
+{
+    uint8_t rsrc = (uint8_t)get_SrcA_X0(bundle);
+    uint8_t rsrcb = (uint8_t)get_SrcB_X0(bundle);
+    uint8_t rdst = (uint8_t)get_Dest_X0(bundle);
+
+    switch (get_RRROpcodeExtension_X0(bundle)) {
+    case ADD_RRR_0_OPCODE_X0:
+        gen_add(dc, rdst, rsrc, (uint8_t)get_SrcB_X0(bundle));
+        return;
+    case OR_RRR_0_OPCODE_X0:
+        gen_or(dc, rdst, rsrc, rsrcb);
+        return;
+    case SHL3ADD_RRR_0_OPCODE_X0:
+        gen_shl3add(dc, rdst, rsrc, rsrcb);
+        return;
+    case UNARY_RRR_0_OPCODE_X0:
+        switch (get_UnaryOpcodeExtension_X0(bundle)) {
+        case FNOP_UNARY_OPCODE_X0:
+            if (!rsrc && !rdst) {
+                gen_fnop();
+                return;
+            }
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+    qemu_log_mask(LOG_UNIMP, "UNIMP rrr_0_opcode_x0, %16.16llx\n", bundle);
+    dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+}
+
+static void decode_shl16insli_opcode_x0(struct DisasContext *dc,
+                                        tilegx_bundle_bits bundle)
+{
+    uint8_t rsrc = (uint8_t)get_SrcA_X0(bundle);
+    uint8_t rdst = (uint8_t)get_Dest_X0(bundle);
+    uint16_t uimm16 = (uint16_t)get_Imm16_X0(bundle);
+
+    gen_shl16insli(dc, rdst, rsrc, uimm16);
+}
+
+static void decode_addli_opcode_x1(struct DisasContext *dc,
+                                   tilegx_bundle_bits bundle)
+{
+    uint8_t rsrc = (uint8_t)get_SrcA_X1(bundle);
+    uint8_t rdst = (uint8_t)get_Dest_X1(bundle);
+    int16_t imm16 = (int16_t)get_Imm16_X1(bundle);
+
+    gen_addli(dc, rdst, rsrc, imm16);
+}
+
+static void decode_branch_opcode_x1(struct DisasContext *dc,
+                                    tilegx_bundle_bits bundle)
+{
+    uint8_t src = (uint8_t)get_SrcA_X1(bundle);
+    int32_t off = get_BrOff_X1(bundle);
+
+    switch (get_BrType_X1(bundle)) {
+    case BEQZ_BRANCH_OPCODE_X1:
+        gen_beqz(dc, src, sign_extend(off, 17));
+        return;
+    case BNEZT_BRANCH_OPCODE_X1:
+        gen_bnezt(dc, src, sign_extend(off, 17));
+        return;
+    default:
+        break;
+    }
+    qemu_log_mask(LOG_UNIMP, "UNIMP branch_opcode_x1, %16.16llx\n", bundle);
+    dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+}
+
+static void decode_imm8_opcode_x1(struct DisasContext *dc,
+                                  tilegx_bundle_bits bundle)
+{
+    uint8_t rsrc = (uint8_t)get_SrcA_X1(bundle);
+    uint8_t rdst = (uint8_t)get_Dest_X1(bundle);
+    int8_t imm8 = (int8_t)get_Imm8_X1(bundle);
+
+    switch (get_Imm8OpcodeExtension_X1(bundle)) {
+    case ADDI_IMM8_OPCODE_X1:
+        gen_addi(dc, rdst, rsrc, imm8);
+        return;
+    default:
+        break;
+    }
+    qemu_log_mask(LOG_UNIMP, "UNIMP imm8_opcode_x1, %16.16llx\n", bundle);
+    dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+}
+
+static void decode_jump_opcode_x1(struct DisasContext *dc,
+                                  tilegx_bundle_bits bundle)
+{
+    qemu_log_mask(LOG_UNIMP, "UNIMP jump_opcode_x1, %16.16llx\n", bundle);
+    dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+}
+
+static void decode_rrr_0_opcode_x1(struct DisasContext *dc,
+                                   tilegx_bundle_bits bundle)
+{
+    uint8_t rsrc = (uint8_t)get_SrcA_X1(bundle);
+    uint8_t rsrcb = (uint8_t)get_SrcB_X1(bundle);
+    uint8_t rdst = (uint8_t)get_Dest_X1(bundle);
+
+    switch (get_RRROpcodeExtension_X1(bundle)) {
+    case ADD_RRR_0_OPCODE_X1:
+        gen_add(dc, rdst, rsrc, rsrcb);
+        return;
+    case ST4_RRR_0_OPCODE_X1:
+        if (!rdst) {
+            gen_st4(dc, rsrc, rsrcb);
+            return;
+        }
+        break;
+    case ST_RRR_0_OPCODE_X1:
+        if (!rdst) {
+            gen_st(dc, rsrc, rsrcb);
+            return;
+        }
+        break;
+    case UNARY_RRR_0_OPCODE_X1:
+        switch (get_UnaryOpcodeExtension_X1(bundle)) {
+        case JR_UNARY_OPCODE_X1:
+            if (!rdst) {
+                gen_jr(dc, rsrc);
+                return;
+            }
+            break;
+        case LD_UNARY_OPCODE_X1:
+            gen_ld(dc, rdst, rsrc);
+            return;
+        case LNK_UNARY_OPCODE_X1:
+            if (!rsrc) {
+                gen_lnk(dc, (uint8_t) get_Dest_X1(bundle));
+                return;
+            }
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+    qemu_log_mask(LOG_UNIMP, "UNIMP rrr_0_opcode_x1, %16.16llx\n", bundle);
+    dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+}
+
+static void decode_shl16insli_opcode_x1(struct DisasContext *dc,
+                                        tilegx_bundle_bits bundle)
+{
+    uint8_t rsrc = (uint8_t)get_SrcA_X1(bundle);
+    uint8_t rdst = (uint8_t)get_Dest_X1(bundle);
+    uint16_t uimm16 = (uint16_t)get_Imm16_X1(bundle);
+
+    gen_shl16insli(dc, rdst, rsrc, uimm16);
+}
+
+void tilegx_tcg_init(void)
+{
+    int i;
+
+    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    cpu_pc = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUTLGState, pc), "pc");
+    for (i = 0; i < TILEGX_R_COUNT; i++) {
+        cpu_regs[i] = tcg_global_mem_new_i64(TCG_AREG0,
+                                             offsetof(CPUTLGState, regs[i]),
+                                             reg_names[i]);
+    }
+}
+
+static void decode_y0(struct DisasContext *dc, tilegx_bundle_bits bundle)
+{
+    unsigned int opcode = get_Opcode_Y0(bundle);
+
+    dc->tmp_regcur = dc->tmp_regs + 0;
+
+    switch (opcode) {
+    case ADDI_OPCODE_Y0:
+        decode_addi_opcode_y0(dc, bundle);
+        return;
+    case RRR_1_OPCODE_Y0:
+        decode_rrr_1_opcode_y0(dc, bundle);
+        return;
+    case RRR_5_OPCODE_Y0:
+        decode_rrr_5_opcode_y0(dc, bundle);
+        return;
+    default:
+        qemu_log_mask(LOG_UNIMP, "UNIMP y0, opcode %d, bundle %16.16llx\n",
+                      opcode, bundle);
+        dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+        return;
+    }
+}
+
+static void decode_y1(struct DisasContext *dc, tilegx_bundle_bits bundle)
+{
+    unsigned int opcode = get_Opcode_Y1(bundle);
+
+    dc->tmp_regcur = dc->tmp_regs + 1;
+
+    switch (opcode) {
+    case ADDI_OPCODE_Y1:
+        decode_addi_opcode_y1(dc, bundle);
+        return;
+    case RRR_1_OPCODE_Y1:
+        decode_rrr_1_opcode_y1(dc, bundle);
+        return;
+    case RRR_5_OPCODE_Y1:
+        decode_rrr_5_opcode_y1(dc, bundle);
+        return;
+    default:
+        qemu_log_mask(LOG_UNIMP, "UNIMP y1, opcode %d, bundle %16.16llx\n",
+                      opcode, bundle);
+        dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+        return;
+    }
+}
+
+static void decode_y2(struct DisasContext *dc, tilegx_bundle_bits bundle)
+{
+    unsigned int opcode = get_Opcode_Y2(bundle);
+
+    dc->tmp_regcur = dc->tmp_regs + 2;
+
+    switch (opcode) {
+    case 3: /* LD_OPCODE_Y2, ST_OPCODE_Y2, LD2U_OPCODE_Y2 */
+        decode_ldst_opcode_y2(dc, bundle);
+        return;
+    default:
+        qemu_log_mask(LOG_UNIMP, "UNIMP y2, opcode %d, bundle %16.16llx\n",
+                      opcode, bundle);
+        dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+        return;
+    }
+}
+
+static void decode_x0(struct DisasContext *dc, tilegx_bundle_bits bundle)
+{
+    unsigned int opcode = get_Opcode_X0(bundle);
+
+    dc->tmp_regcur = dc->tmp_regs + 0;
+
+    switch (opcode) {
+    case ADDLI_OPCODE_X0:
+        decode_addli_opcode_x0(dc, bundle);
+        return;
+    case IMM8_OPCODE_X0:
+        decode_imm8_opcode_x0(dc, bundle);
+        return;
+    case RRR_0_OPCODE_X0:
+        decode_rrr_0_opcode_x0(dc, bundle);
+        return;
+    case SHL16INSLI_OPCODE_X0:
+        decode_shl16insli_opcode_x0(dc, bundle);
+        return;
+    default:
+        qemu_log_mask(LOG_UNIMP, "UNIMP x0, opcode %d, bundle %16.16llx\n",
+                      opcode, bundle);
+        dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+        return;
+    }
+}
+
+static void decode_x1(struct DisasContext *dc, tilegx_bundle_bits bundle)
+{
+    unsigned int opcode = get_Opcode_X1(bundle);
+
+    dc->tmp_regcur = dc->tmp_regs + 1;
+
+    switch (opcode) {
+    case ADDLI_OPCODE_X1:
+        decode_addli_opcode_x1(dc, bundle);
+        return;
+    case BRANCH_OPCODE_X1:
+        decode_branch_opcode_x1(dc, bundle);
+        return;
+    case IMM8_OPCODE_X1:
+        decode_imm8_opcode_x1(dc, bundle);
+        return;
+    case JUMP_OPCODE_X1:
+        decode_jump_opcode_x1(dc, bundle);
+        return;
+    case RRR_0_OPCODE_X1:
+        decode_rrr_0_opcode_x1(dc, bundle);
+        return;
+    case SHL16INSLI_OPCODE_X1:
+        decode_shl16insli_opcode_x1(dc, bundle);
+        return;
+    default:
+        qemu_log_mask(LOG_UNIMP, "UNIMP x1, opcode %d, bundle %16.16llx\n",
+                      opcode, bundle);
+        dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENT;
+        return;
+    }
+}
+
+static void translate_one_bundle(struct DisasContext *dc, uint64_t bundle)
+{
+    int i;
+    TCGv tmp;
+
+    for (i = 0; i < TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE; i++) {
+        dc->tmp_regs[i].idx = TILEGX_R_NOREG;
+        TCGV_UNUSED_I64(dc->tmp_regs[i].val);
+    }
+
+    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
+        tcg_gen_debug_insn_start(dc->pc);
+    }
+
+    if (get_Mode(bundle)) {
+        decode_y0(dc, bundle);
+        decode_y1(dc, bundle);
+        decode_y2(dc, bundle);
+    } else {
+        decode_x0(dc, bundle);
+        decode_x1(dc, bundle);
+    }
+
+    for (i = 0; i < TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE; i++) {
+        if (dc->tmp_regs[i].idx == TILEGX_R_NOREG) {
+            continue;
+        }
+        if (dc->tmp_regs[i].idx < TILEGX_R_COUNT) {
+            tcg_gen_mov_i64(cpu_regs[dc->tmp_regs[i].idx], dc->tmp_regs[i].val);
+        }
+        tcg_temp_free_i64(dc->tmp_regs[i].val);
+    }
+
+    if (dc->jmp.cond != TCG_COND_NEVER) {
+        if (dc->jmp.cond == TCG_COND_ALWAYS) {
+            tcg_gen_mov_i64(cpu_pc, dc->jmp.dest);
+        } else {
+            tmp = tcg_const_i64(dc->pc + TILEGX_BUNDLE_SIZE_IN_BYTES);
+            tcg_gen_movcond_i64(dc->jmp.cond, cpu_pc,
+                                dc->jmp.val1, dc->jmp.val2,
+                                dc->jmp.dest, tmp);
+            tcg_temp_free_i64(dc->jmp.val1);
+            tcg_temp_free_i64(dc->jmp.val2);
+            tcg_temp_free_i64(tmp);
+        }
+        tcg_temp_free_i64(dc->jmp.dest);
+        tcg_gen_exit_tb(0);
+    }
+}
 
 static inline void gen_intermediate_code_internal(TileGXCPU *cpu,
                                                   TranslationBlock *tb,
                                                   bool search_pc)
 {
-    /*
-     * FIXME: after load elf64 tilegx binary successfully, it will quit, at
-     * present, and will implement the related features next.
-     */
-    qemu_log("\nLoaded elf64 tilegx successfully\n");
-    qemu_log("reached code start position: [" TARGET_FMT_lx "] %s\n\n",
-             tb->pc, lookup_symbol(tb->pc));
-    exit(0);
+    DisasContext ctx;
+    DisasContext *dc = &ctx;
+
+    CPUTLGState *env = &cpu->env;
+    uint64_t pc_start = tb->pc;
+    uint64_t next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+    int j, lj = -1;
+    int num_insns = 0;
+    int max_insns = tb->cflags & CF_COUNT_MASK;
+
+    dc->pc = pc_start;
+    dc->exception = 0;
+    dc->jmp.cond = TCG_COND_NEVER;
+    TCGV_UNUSED_I64(dc->jmp.dest);
+    TCGV_UNUSED_I64(dc->jmp.val1);
+    TCGV_UNUSED_I64(dc->jmp.val2);
+
+    if (!max_insns) {
+        max_insns = CF_COUNT_MASK;
+    }
+    gen_tb_start(tb);
+
+    do {
+        TCGV_UNUSED_I64(dc->zero);
+        if (search_pc) {
+            j = tcg_op_buf_count();
+            if (lj < j) {
+                lj++;
+                while (lj < j) {
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
+                }
+            }
+            tcg_ctx.gen_opc_pc[lj] = dc->pc;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_icount[lj] = num_insns;
+        }
+        translate_one_bundle(dc, cpu_ldq_data(env, dc->pc));
+        if (dc->exception) {
+            exit(-1);
+        }
+        num_insns++;
+        dc->pc += TILEGX_BUNDLE_SIZE_IN_BYTES;
+    } while (dc->jmp.cond == TCG_COND_NEVER && dc->pc < next_page_start
+             && num_insns < max_insns && !tcg_op_buf_full());
+
+    gen_tb_end(tb, num_insns);
+    if (search_pc) {
+        j = tcg_op_buf_count();
+        lj++;
+        while (lj <= j) {
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
+        }
+    } else {
+        tb->size = dc->pc - pc_start;
+        tb->icount = num_insns;
+    }
+
+    return;
 }
 
 void gen_intermediate_code(CPUTLGState *env, struct TranslationBlock *tb)