At present, I finished the first system call successfully (it is uname called by glibc).
If no additional reply of this thread within 3 days, I shall send a new patch which will include system call implementation. Thanks. On 3/14/15 14:03, Chen Gang 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(). > > Signed-off-by: Chen Gang <gang.chen.5...@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(-) > > 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) > -- Chen Gang Open, share, and attitude like air, water, and life which God blessed