[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] target-tilegx: Execute _start and reach to __libc_s
From: |
Chen Gang S |
Subject: |
[Qemu-devel] [PATCH] target-tilegx: Execute _start and reach to __libc_start_main successfully |
Date: |
Tue, 24 Feb 2015 15:53:18 +0800 |
User-agent: |
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 |
Tilegx Qemu 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, tilegx qemu continues executing, and reach to the
indirectly jump statement, and jump to 3rd TB block correctly.
The related test/output for 1st TB block is:
The disassembly code (have compared with objdump):
TB block start position: [0000000000010f60] _start
y0: 00000000500bfdb4 move r52, r54
y1: 1c06400000000000 fnop
y2: 0208000007600000 ld r1, r54
x0: 0000000051483000 fnop
x1: 180f86c600000000 addi r12, r54, -16
x0: 00000000403f8336 andi r54, r12, -8
x1: 286af00680000000 lnk r13
y0: 00000000500bf005 move r5, r0
y1: 040046c600000000 addi r12, r54, 8
y2: 03f8000007600000 st r54, r63
y0: 00000000500bfff7 move r55, r63
y1: 0400468100000000 addi r2, r52, 8
y2: 03f8000004c00000 st r12, r63
x0: 0000000040110d86 addi r6, r54, 16
x1: 07ffffe000000000 moveli r0, -1
x0: 000000007ffff000 shl16insli r0, r0, -1
x1: 000007e180000000 moveli r3, 0
x0: 000000007ffa8000 shl16insli r0, r0, -88
x1: 3800006180000000 shl16insli r3, r3, 0
x0: 00000000500cd000 add r0, r0, r13
x1: 3877406180000000 shl16insli r3, r3, 3816
x0: 0000000010000fcc moveli r12, 0
x1: 2806686180000000 add r3, r3, r13
x0: 000000007000030c shl16insli r12, r12, 0
x1: 000007e200000000 moveli r4, 0
x0: 000000007039030c shl16insli r12, r12, 912
x1: 3800008200000000 shl16insli r4, r4, 0
x0: 00000000500cd30c add r12, r12, r13
x1: 3881808200000000 shl16insli r4, r4, 4144
x0: 00000000500cd104 add r4, r4, r13
x1: 286a718000000000 jr r12
The tcg code before optimization is:
ld_i32 tmp0,env,$0xfffffffffffffff4
movi_i32 tmp1,$0x0
brcond_i32 tmp0,tmp1,ne,$0x0
mov_i64 tmp2,sp
ld_i64 tmp3,env,$0x1b0
mov_i64 bp,tmp2
mov_i64 r1,tmp3
movi_i64 tmp3,$0xfffffffffffffff0
add_i64 tmp2,sp,tmp3
mov_i64 r12,tmp2
movi_i64 tmp3,$0xfffffffffffffff8
and_i64 tmp2,r12,tmp3
movi_i64 tmp3,$0x10f78
mov_i64 sp,tmp2
mov_i64 r13,tmp3
mov_i64 tmp2,r0
movi_i64 tmp4,$0x8
add_i64 tmp3,sp,tmp4
st_i64 sp,env,$0x1c0
mov_i64 r5,tmp2
mov_i64 r12,tmp3
movi_i64 tmp2,$0x0
movi_i64 tmp4,$0x8
add_i64 tmp3,bp,tmp4
st_i64 r12,env,$0x1c0
mov_i64 lr,tmp2
mov_i64 r2,tmp3
movi_i64 tmp3,$0x10
add_i64 tmp2,sp,tmp3
movi_i64 tmp3,$0xffffffffffffffff
mov_i64 r6,tmp2
mov_i64 r0,tmp3
movi_i64 tmp3,$0x10
shl_i64 tmp2,r0,tmp3
movi_i64 tmp4,$0xffff
or_i64 tmp3,tmp2,tmp4
movi_i64 tmp2,$0x0
mov_i64 r0,tmp3
mov_i64 r3,tmp2
movi_i64 tmp3,$0x10
shl_i64 tmp2,r0,tmp3
movi_i64 tmp4,$0xffa8
or_i64 tmp3,tmp2,tmp4
movi_i64 tmp4,$0x10
shl_i64 tmp2,r3,tmp4
mov_i64 tmp4,tmp2
mov_i64 r0,tmp3
mov_i64 r3,tmp4
add_i64 tmp2,r0,r13
movi_i64 tmp4,$0x10
shl_i64 tmp3,r3,tmp4
movi_i64 tmp5,$0xee8
or_i64 tmp4,tmp3,tmp5
mov_i64 r0,tmp2
mov_i64 r3,tmp4
movi_i64 tmp2,$0x0
add_i64 tmp3,r3,r13
mov_i64 r12,tmp2
mov_i64 r3,tmp3
movi_i64 tmp3,$0x10
shl_i64 tmp2,r12,tmp3
mov_i64 tmp3,tmp2
movi_i64 tmp2,$0x0
mov_i64 r12,tmp3
mov_i64 r4,tmp2
movi_i64 tmp3,$0x10
shl_i64 tmp2,r12,tmp3
movi_i64 tmp4,$0x390
or_i64 tmp3,tmp2,tmp4
movi_i64 tmp4,$0x10
shl_i64 tmp2,r4,tmp4
mov_i64 tmp4,tmp2
mov_i64 r12,tmp3
mov_i64 r4,tmp4
add_i64 tmp2,r12,r13
movi_i64 tmp4,$0x10
shl_i64 tmp3,r4,tmp4
movi_i64 tmp5,$0x1030
or_i64 tmp4,tmp3,tmp5
mov_i64 r12,tmp2
mov_i64 r4,tmp4
add_i64 tmp2,r4,r13
mov_i64 tmp3,r12
mov_i64 r4,tmp2
mov_i64 pc,tmp3
exit_tb $0x0
set_label $0x0
exit_tb $0x7fd21f340013
Signed-off-by: Chen Gang <address@hidden>
---
linux-user/main.c | 1 +
target-tilegx/cpu-qom.h | 2 +
target-tilegx/cpu.c | 4 -
target-tilegx/cpu.h | 21 +-
target-tilegx/translate.c | 876 +++++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 885 insertions(+), 19 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index 76e5e80..ef89bfd 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4464,6 +4464,7 @@ int main(int argc, char **argv, char **envp)
env->regs[53] = regs->tp; /* TILEGX_R_TP */
env->regs[54] = regs->sp; /* TILEGX_R_SP */
env->regs[55] = regs->lr; /* TILEGX_R_LR */
+ env->zero = 0;
env->pc = regs->lr;
}
#else
diff --git a/target-tilegx/cpu-qom.h b/target-tilegx/cpu-qom.h
index e15a8b8..866a77d 100644
--- a/target-tilegx/cpu-qom.h
+++ b/target-tilegx/cpu-qom.h
@@ -69,4 +69,6 @@ static inline TilegxCPU *tilegx_env_get_cpu(CPUTLState *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 3dd66b5..a10cc24 100644
--- a/target-tilegx/cpu.c
+++ b/target-tilegx/cpu.c
@@ -69,10 +69,6 @@ static void tilegx_cpu_realizefn(DeviceState *dev, Error
**errp)
mcc->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 09a2b26..73794ab 100644
--- a/target-tilegx/cpu.h
+++ b/target-tilegx/cpu.h
@@ -30,16 +30,20 @@
#include "fpu/softfloat.h"
/* Tilegx 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 CPUTLState {
- uint64_t regs[56];
- uint64_t pc;
+ uint64_t regs[TILEGX_R_COUNT]; /* Common used registers by outside */
+ uint64_t zero; /* Zero register */
+ uint64_t pc; /* Current pc */
CPU_COMMON
} CPUTLState;
@@ -54,6 +58,7 @@ typedef struct CPUTLState {
#include "exec/cpu-all.h"
+void tilegx_tcg_init(void);
int cpu_tilegx_exec(CPUTLState *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 5131fa7..82c751e 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -25,18 +25,880 @@
#include "exec/cpu_ldst.h"
#include "exec/helper-gen.h"
+#define TILEGX_BUNDLE_SIZE 8 /* Each bundle size in bytes */
+#define TILEGX_BUNDLE_INSNS 3 /* Maximized insns per bundle */
+#define TILEGX_BUNDLE_OPCS 10 /* Assume maximized opcs per bundle */
+
+/* Check Bundle whether is Y type, else is X type */
+#define TILEGX_BUNDLE_TYPE_MASK 0xc000000000000000ULL
+#define TILEGX_BUNDLE_TYPE_Y(bundle) ((bundle) & TILEGX_BUNDLE_TYPE_MASK)
+#define TILEGX_BUNDLE_TYPE_X(bundle) (!TILEGX_BUNDLE_TYPE_Y(bundle))
+
+/* Bundle pipe mask, still remain the bundle type */
+#define TILEGX_PIPE_X0(bundle) ((bundle) & 0x000000007fffffffULL)
+#define TILEGX_PIPE_X1(bundle) ((bundle) & 0x3fffffff80000000ULL)
+#define TILEGX_PIPE_Y0(bundle) ((bundle) & 0x00000000780fffffULL)
+#define TILEGX_PIPE_Y1(bundle) ((bundle) & 0x3c07ffff80000000ULL)
+#define TILEGX_PIPE_Y2(bundle) ((bundle) & 0x03f8000007f00000ULL)
+
+/* Code mask */
+#define TILEGX_CODE_X0(bundle) ((bundle) & 0x0000000070000000ULL)
+#define TILEGX_CODE_X0_18(bundle) ((bundle) & 0x000000000ffc0000ULL)
+#define TILEGX_CODE_X0_20(bundle) ((bundle) & 0x000000000ff00000ULL)
+#define TILEGX_CODE_X1(bundle) ((bundle) & 0x3800000000000000ULL)
+#define TILEGX_CODE_X1_49(bundle) ((bundle) & 0x07fe000000000000ULL)
+#define TILEGX_CODE_X1_49_43(bundle) ((bundle) & 0x0001f80000000000ULL)
+#define TILEGX_CODE_X1_51(bundle) ((bundle) & 0x07f8000000000000ULL)
+#define TILEGX_CODE_X1_54(bundle) ((bundle) & 0x07c0000000000000ULL)
+#define TILEGX_CODE_Y0(bundle) ((bundle) & 0x0000000078000000ULL)
+#define TILEGX_CODE_Y0_E(bundle) ((bundle) & 0x00000000000c0000ULL)
+#define TILEGX_CODE_Y1(bundle) ((bundle) & 0x3c00000000000000ULL)
+#define TILEGX_CODE_Y1_E(bundle) ((bundle) & 0x0006000000000000ULL)
+#define TILEGX_CODE_Y2(bundle) ((bundle) & 0x0200000004000000ULL)
+/* No Y2_E */
+
+/* (F)Nop operation, only have effect within their own pipe */
+#define TILEGX_OPCX0_FNOP 0x0000000051483000ULL
+#define TILEGX_OPCX0_NOP 0x0000000051485000ULL
+#define TILEGX_OPCX1_FNOP 0x286a300000000000ULL
+#define TILEGX_OPCX1_NOP 0x286b080000000000ULL
+#define TILEGX_OPCY0_FNOP 0x00000000300c3000ULL
+#define TILEGX_OPCY0_NOP 0x00000000300c5000ULL
+#define TILEGX_OPCY1_FNOP 0x1c06400000000000ULL
+#define TILEGX_OPCY1_NOP 0x1c06780000000000ULL
+/* No Y2 (F)NOP */
+
+/* Data width mask */
+#define TILEGX_DATA_REGISTER 0x3f /* Register data width mask */
+#define TILEGX_DATA_IMM6 0x3f /* Imm6 data width mask */
+#define TILEGX_DATA_IMM8 0xff /* Imm8 data width mask */
+#define TILEGX_DATA_IMM11 0x7ff /* Imm11 data width mask */
+#define TILEGX_DATA_IMM16 0xffff /* Imm16 data width mask */
+
+#define TILEGX_GEN_CHK_BEGIN(x) \
+ if ((x) == TILEGX_R_ZERO) {
+#define TILEGX_GEN_CHK_END(x) \
+ return 0; \
+ } \
+ if ((x) >= TILEGX_R_COUNT) { \
+ return -1; \
+ }
+
+#define TILEGX_GEN_CHK_SIMPLE(x) \
+ TILEGX_GEN_CHK_BEGIN(x) \
+ TILEGX_GEN_CHK_END(x)
+
+#define TILEGX_GEN_SAVE_PREP(rdst) \
+ dc->tmp_regcur->idx = rdst; \
+ dc->tmp_regcur->val = tcg_temp_new_i64();
+
+#define TILEGX_GEN_SAVE_TMP_1(func, rdst, x1) \
+ TILEGX_GEN_SAVE_PREP(rdst) \
+ func(dc->tmp_regcur->val, x1);
+
+#define TILEGX_GEN_SAVE_TMP_2(func, rdst, x1, x2) \
+ TILEGX_GEN_SAVE_PREP(rdst) \
+ func(dc->tmp_regcur->val, x1, x2);
+
+static TCGv_ptr cpu_env;
+static TCGv_i64 cpu_pc;
+static TCGv_i64 cpu_regs[TILEGX_R_COUNT];
+
+static const char *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"
+};
+
+#include "exec/gen-icount.h"
+
+/* This is the state at translation time. */
+struct DisasContext {
+ uint64_t pc; /* Current pc */
+ unsigned int cpustate_changed; /* Whether cpu state changed */
+
+ struct {
+ unsigned char idx; /* index */
+ TCGv val; /* value */
+ } *tmp_regcur, /* Current temporary registers */
+ tmp_regs[TILEGX_BUNDLE_INSNS]; /* 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
*/
+};
+
+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(CPUTLState, pc), "pc");
+ for (i = 0; i < TILEGX_R_COUNT; i++) {
+ cpu_regs[i] = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUTLState, regs[i]),
+ reg_names[i]);
+ }
+}
+
+static int gen_move(struct DisasContext *dc,
+ unsigned char rdst, unsigned char rsrc)
+{
+ qemu_log("move r%d, r%d", rdst, rsrc);
+ TILEGX_GEN_CHK_SIMPLE(rdst);
+ TILEGX_GEN_CHK_BEGIN(rsrc);
+ TILEGX_GEN_SAVE_TMP_1(tcg_gen_movi_i64, rdst, 0);
+ TILEGX_GEN_CHK_END(rsrc);
+
+ TILEGX_GEN_SAVE_TMP_1(tcg_gen_mov_i64, rdst, cpu_regs[rsrc]);
+ return 0;
+}
+
+static int gen_move_imm(struct DisasContext *dc,
+ unsigned char rdst, int64_t imm)
+{
+ TILEGX_GEN_CHK_SIMPLE(rdst);
+ TILEGX_GEN_SAVE_TMP_1(tcg_gen_movi_i64, rdst, imm);
+ return 0;
+}
+
+static int gen_moveli(struct DisasContext *dc, unsigned char rdst, short im16)
+{
+ qemu_log("moveli r%d, %d", rdst, im16);
+ return gen_move_imm(dc, rdst, (int64_t)im16);
+}
+
+static int gen_movei(struct DisasContext *dc, unsigned char rdst, char im8)
+{
+ qemu_log("movei r%d, %d", rdst, im8);
+ return gen_move_imm(dc, rdst, (int64_t)im8);
+}
+
+static int gen_ld(struct DisasContext *dc,
+ unsigned char rdst, unsigned char rsrc)
+{
+ qemu_log("ld r%d, r%d", rdst, rsrc);
+ TILEGX_GEN_CHK_SIMPLE(rdst);
+ TILEGX_GEN_CHK_BEGIN(rsrc);
+ TILEGX_GEN_SAVE_TMP_2(tcg_gen_ld_i64, rdst, cpu_env, 0);
+ TILEGX_GEN_CHK_END(rsrc);
+
+ TILEGX_GEN_SAVE_TMP_2(tcg_gen_ld_i64, rdst, cpu_env,
+ offsetof(CPUTLState, regs[rsrc]));
+ return 0;
+}
+
+static int gen_st(struct DisasContext *dc,
+ unsigned char rdst, unsigned char rsrc)
+{
+ qemu_log("st r%d, r%d", rdst, rsrc);
+ TILEGX_GEN_CHK_SIMPLE(rdst);
+ TILEGX_GEN_CHK_BEGIN(rsrc);
+ tcg_gen_st_i64(cpu_regs[rdst], cpu_env, offsetof(CPUTLState, zero));
+ TILEGX_GEN_CHK_END(rsrc);
+
+ tcg_gen_st_i64(cpu_regs[rdst], cpu_env, offsetof(CPUTLState, regs[rsrc]));
+ return 0;
+}
+
+static int gen_addimm(struct DisasContext *dc,
+ unsigned char rdst, unsigned char rsrc, int64_t imm)
+{
+ TILEGX_GEN_CHK_SIMPLE(rdst);
+ TILEGX_GEN_CHK_BEGIN(rsrc);
+ TILEGX_GEN_SAVE_TMP_1(tcg_gen_movi_i64, rdst, imm);
+ TILEGX_GEN_CHK_END(rsrc);
+
+ TILEGX_GEN_SAVE_TMP_2(tcg_gen_addi_i64, rdst, cpu_regs[rsrc], imm);
+ return 0;
+}
+
+static int gen_addi(struct DisasContext *dc,
+ unsigned char rdst, unsigned char rsrc, char im8)
+{
+ qemu_log("addi r%d, r%d, %d", rdst, rsrc, im8);
+ return gen_addimm(dc, rdst, rsrc, (int64_t)im8);
+}
+
+static int gen_addli(struct DisasContext *dc,
+ unsigned char rdst, unsigned char rsrc, short im16)
+{
+ qemu_log("addli r%d, r%d, %d", rdst, rsrc, im16);
+ return gen_addimm(dc, rdst, rsrc, (int64_t)im16);
+}
+
+static int gen_add(struct DisasContext *dc,
+ unsigned char rdst, unsigned char rsrc, unsigned char rsrcb)
+{
+ qemu_log("add r%d, r%d, r%d", rdst, rsrc, rsrcb);
+ TILEGX_GEN_CHK_SIMPLE(rdst);
+ TILEGX_GEN_CHK_BEGIN(rsrc);
+ TILEGX_GEN_CHK_BEGIN(rsrcb);
+ TILEGX_GEN_SAVE_TMP_1(tcg_gen_movi_i64, rdst, 0);
+ TILEGX_GEN_CHK_END(rsrcb);
+ TILEGX_GEN_SAVE_TMP_1(tcg_gen_mov_i64, rdst, cpu_regs[rsrcb]);
+ TILEGX_GEN_CHK_END(rsrc);
+
+ TILEGX_GEN_CHK_BEGIN(rsrcb);
+ TILEGX_GEN_SAVE_TMP_1(tcg_gen_mov_i64, rdst, cpu_regs[rsrc]);
+ TILEGX_GEN_CHK_END(rsrcb);
+
+ TILEGX_GEN_SAVE_TMP_2(tcg_gen_add_i64, rdst,
+ cpu_regs[rsrc], cpu_regs[rsrcb]);
+ return 0;
+}
+
+static int gen_andimm(struct DisasContext *dc,
+ unsigned char rdst, unsigned char rsrc, int64_t imm)
+{
+ TILEGX_GEN_CHK_SIMPLE(rdst);
+ TILEGX_GEN_CHK_BEGIN(rsrc);
+ TILEGX_GEN_SAVE_TMP_1(tcg_gen_movi_i64, rdst, 0);
+ TILEGX_GEN_CHK_END(rsrc);
+
+ TILEGX_GEN_SAVE_TMP_2(tcg_gen_andi_i64, rdst,
+ cpu_regs[rsrc], (uint64_t)imm);
+ return 0;
+}
+
+static int gen_andi(struct DisasContext *dc,
+ unsigned char rdst, unsigned char rsrc, char im8)
+{
+ qemu_log("andi r%d, r%d, %d", rdst, rsrc, im8);
+ return gen_andimm(dc, rdst, rsrc, (int64_t)im8);
+}
+
+static int gen_lnk(struct DisasContext *dc, unsigned char rdst)
+{
+ qemu_log("lnk r%d", rdst);
+ TILEGX_GEN_CHK_SIMPLE(rdst);
+ TILEGX_GEN_SAVE_TMP_1(tcg_gen_movi_i64, rdst, dc->pc + TILEGX_BUNDLE_SIZE);
+ return 0;
+}
+
+static int gen_shl16insli(struct DisasContext *dc,
+ unsigned char rdst, unsigned char rsrc, short im16)
+{
+ int64_t imm;
+ TCGv_i64 tmp;
+
+ qemu_log("shl16insli r%d, r%d, %d", rdst, rsrc, im16);
+ TILEGX_GEN_CHK_SIMPLE(rdst);
+
+ imm = (int64_t)im16 & 0x000000000000ffffLL;
+
+ TILEGX_GEN_CHK_BEGIN(rsrc);
+ TILEGX_GEN_SAVE_TMP_1(tcg_gen_movi_i64, rdst, imm);
+ TILEGX_GEN_CHK_END(rsrc);
+
+ tmp = tcg_temp_new_i64();
+ tcg_gen_shli_i64(tmp, cpu_regs[rsrc], 16);
+ TILEGX_GEN_SAVE_TMP_2(tcg_gen_ori_i64, rdst, tmp, imm);
+ tcg_temp_free_i64(tmp);
+ return 0;
+}
+
+static int gen_jr(struct DisasContext *dc, unsigned char rsrc)
+{
+ qemu_log("jr r%d", rsrc);
+ TILEGX_GEN_CHK_SIMPLE(rsrc);
+
+ dc->jmp.dest = tcg_temp_new_i64();
+
+ dc->jmp.cond = TCG_COND_ALWAYS;
+ tcg_gen_mov_i64(dc->jmp.dest, cpu_regs[rsrc]);
+ return 0;
+}
+
+static int gen_beqz(struct DisasContext *dc, unsigned char rsrc, int off)
+{
+ qemu_log("beqz r%d, %d", rsrc, off);
+ TILEGX_GEN_CHK_SIMPLE(rsrc);
+
+ 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);
+ tcg_gen_mov_i64(dc->jmp.val1, cpu_regs[rsrc]);
+ tcg_gen_movi_i64(dc->jmp.val2, 0);
+
+ return 0;
+}
+
+static int translate_x0_bundle(struct DisasContext *dc, uint64_t bundle)
+{
+ unsigned char rdst, rsrc, rsrcb;
+ char im8;
+ short im16;
+
+ qemu_log("\nx0: %16.16lx\t", bundle);
+ if (bundle == TILEGX_OPCX0_FNOP) {
+ qemu_log("fnop");
+ return 0;
+ }
+
+ if (bundle == TILEGX_OPCX0_NOP) {
+ qemu_log("nop");
+ return 0;
+ }
+
+ switch (TILEGX_CODE_X0(bundle)) {
+ case 0x0000000010000000ULL:
+ rdst = (unsigned char)(bundle & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER);
+ im16 = (short)((bundle >> 12) & TILEGX_DATA_IMM16);
+ if (rsrc == 0x3f) {
+ /* moveli Dest, Imm16 */
+ if (gen_moveli(dc, rdst, im16)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ } else {
+ /* addli Dest, SrcA, Imm16 */
+ if (gen_addli(dc, rdst, rsrc, im16)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ }
+ break;
+
+ case 0x0000000040000000ULL:
+ switch (TILEGX_CODE_X0_20(bundle)) {
+ /* andi Dest, SrcA, Imm8 */
+ case 0x0000000000300000ULL:
+ rdst = (unsigned char)(bundle & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER);
+ im8 = (char)((bundle >> 12) & TILEGX_DATA_IMM8);
+ if (gen_andi(dc, rdst, rsrc, im8)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ /* addi Dest, SrcA, Imm8 */
+ case 0x0000000000100000ULL:
+ rdst = (unsigned char)(bundle & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER);
+ im8 = (char)((bundle >> 12) & TILEGX_DATA_IMM8);
+ if (gen_addi(dc, rdst, rsrc, im8)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ qemu_log("20 bundle value: %16.16llx", TILEGX_CODE_X0_20(bundle));
+ return -1;
+ }
+ break;
+
+ case 0x0000000050000000ULL:
+ switch (TILEGX_CODE_X0_18(bundle)) {
+ /* add Dest, SrcA, SrcB */
+ case 0x00000000000c0000ULL:
+ rdst = (unsigned char)(bundle & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER);
+ rsrcb = (unsigned char)((bundle >> 12) & TILEGX_DATA_REGISTER);
+ if (gen_add(dc, rdst, rsrc, rsrcb)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ case 0x0000000001040000ULL:
+ rdst = (unsigned char)(bundle & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER);
+ rsrcb = (unsigned char)((bundle >> 12) & TILEGX_DATA_REGISTER);
+ /* move Dest, Src */
+ if (rsrcb == 0x3f) {
+ if (gen_move(dc, rdst, rsrc)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ } else {
+ qemu_log("invalid rsrcb, not 0x3f for move in x0");
+ }
+ break;
+
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ qemu_log("18 bundle value: %16.16llx", TILEGX_CODE_X0_18(bundle));
+ return -1;
+ }
+ break;
+
+ /* shl16insli Dest, SrcA, Imm16 */
+ case 0x0000000070000000ULL:
+ rdst = (unsigned char)(bundle & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER);
+ im16 = (short)((bundle >> 12) & TILEGX_DATA_IMM16);
+ if (gen_shl16insli(dc, rdst, rsrc, im16)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ qemu_log("bundle value: %16.16llx", TILEGX_CODE_X0(bundle));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int translate_x1_bundle(struct DisasContext *dc, uint64_t bundle)
+{
+ unsigned char rdst, rsrc, rsrcb;
+ char im8;
+ short im16;
+ struct {
+ int v :17;
+ } off17;
+
+ qemu_log("\nx1: %16.16lx\t", bundle);
+ if (bundle == TILEGX_OPCX1_FNOP) {
+ qemu_log("fnop");
+ return 0;
+ }
+
+ if (bundle == TILEGX_OPCX1_NOP) {
+ qemu_log("nop");
+ return 0;
+ }
+
+ switch (TILEGX_CODE_X1(bundle)) {
+ case 0x0000000000000000ULL:
+ rdst = (unsigned char)((bundle >> 31) & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER);
+ im16 = (short)((bundle >> 43) & TILEGX_DATA_IMM16);
+ if (rsrc == 0x3f) {
+ /* moveli Dest, Imm16 */
+ if (gen_moveli(dc, rdst, im16)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ } else {
+ /* addli Dest, SrcA, Imm16 */
+ if (gen_addli(dc, rdst, rsrc, im16)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ }
+ break;
+
+ case 0x1000000000000000ULL:
+ switch (TILEGX_CODE_X1_54(bundle)) {
+ /* beqz Src, Broff */
+ case 0x0440000000000000ULL:
+ off17.v = (int)((bundle >> 31) & TILEGX_DATA_IMM6);
+ rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER);
+ off17.v |= (int)((bundle >> 37) & (TILEGX_DATA_IMM11 << 6));
+ if (gen_beqz(dc, rsrc, (int)off17.v)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ qemu_log("54 bundle value: %llx", TILEGX_CODE_X1_51(bundle));
+ return -1;
+ }
+ break;
+
+ case 0x1800000000000000ULL:
+ switch (TILEGX_CODE_X1_51(bundle)) {
+ /* addi Dest, SrcA, Imm8 */
+ case 0x0008000000000000ULL:
+ rdst = (unsigned char)((bundle >> 31) & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER);
+ im8 = (char)((bundle >> 43) & TILEGX_DATA_IMM8);
+ if (rsrc == 0x3f) {
+ if (gen_movei(dc, rdst, im8)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ } else {
+ if (gen_addi(dc, rdst, rsrc, im8)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ }
+ break;
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ qemu_log("51 bundle value: %llx", TILEGX_CODE_X1_51(bundle));
+ return -1;
+ }
+ break;
+
+ case 0x2800000000000000ULL:
+ switch (TILEGX_CODE_X1_49(bundle)) {
+ /* add Dest, SrcA, SrcB */
+ case 0x0006000000000000ULL:
+ rdst = (unsigned char)((bundle >> 31) & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER);
+ rsrcb = (unsigned char)((bundle >> 43) & TILEGX_DATA_REGISTER);
+ if (gen_add(dc, rdst, rsrc, rsrcb)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ /* store Dest, Src */
+ case 0x0062000000000000ULL:
+ rdst = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 43) & TILEGX_DATA_REGISTER);
+ if (gen_st(dc, rdst, rsrc)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ case 0x006a000000000000ULL:
+ switch (TILEGX_CODE_X1_49_43(bundle)) {
+ /* lnk Dest */
+ case 0x0000f00000000000ULL:
+ rdst = (unsigned char)((bundle >> 31) & TILEGX_DATA_REGISTER);
+ if (gen_lnk(dc, rdst)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ /* jr SrcA */
+ case 0x0000700000000000ULL:
+ rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER);
+ if (gen_jr(dc, rsrc)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ qemu_log("49_43 bundle value: %16.16llx",
+ TILEGX_CODE_X1_49_43(bundle));
+ return -1;
+ }
+ break;
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ qemu_log("49 bundle value: %16.16llx", TILEGX_CODE_X1_49(bundle));
+ return -1;
+ }
+ break;
+
+ /* shl16insli Dest, SrcA, Imm16 */
+ case 0x3800000000000000ULL:
+ rdst = (unsigned char)((bundle >> 31) & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER);
+ im16 = (short)((bundle >> 43) & TILEGX_DATA_IMM16);
+ if (gen_shl16insli(dc, rdst, rsrc, im16)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ qemu_log("bundle value: %16.16llx", TILEGX_CODE_X1(bundle));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int translate_y0_bundle(struct DisasContext *dc, uint64_t bundle)
+{
+ unsigned char rsrc, rdst;
+ char im8;
+
+ qemu_log("\ny0: %16.16lx\t", bundle);
+ if (bundle == TILEGX_OPCY0_FNOP) {
+ qemu_log("fnop");
+ return 0;
+ }
+
+ if (bundle == TILEGX_OPCY0_NOP) {
+ qemu_log("nop");
+ return 0;
+ }
+
+ switch (TILEGX_CODE_Y0(bundle)) {
+ /* addi Dest, SrcA, Imm8 */
+ case 0x0000000000000000ULL:
+ rdst = (unsigned char)(bundle & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER);
+ im8 = (char)((bundle >> 12) & TILEGX_DATA_IMM8);
+ if (gen_addi(dc, rdst, rsrc, im8)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ case 0x0000000050000000ULL:
+ switch (TILEGX_CODE_Y0_E(bundle)) {
+ /* move Dest, SrcA */
+ case 0x0000000000080000ULL:
+ rdst = (unsigned char)(bundle & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER);
+ if (gen_move(dc, rdst, rsrc)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ qemu_log("bundle value: %16.16llx", TILEGX_CODE_Y0(bundle));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int translate_y1_bundle(struct DisasContext *dc, uint64_t bundle)
+{
+ unsigned char rdst, rsrc, rsrcb;
+ char im8;
+
+ qemu_log("\ny1: %16.16lx\t", bundle);
+ if (bundle == TILEGX_OPCY1_FNOP) {
+ qemu_log("fnop");
+ return 0;
+ }
+
+ if (bundle == TILEGX_OPCY1_NOP) {
+ qemu_log("nop");
+ return 0;
+ }
+
+ switch (TILEGX_CODE_Y1(bundle)) {
+ /* addi Dest, SrcA, Imm8 */
+ case 0x0400000000000000ULL:
+ rdst = (unsigned char)((bundle >> 31) & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER);
+ im8 = (char)((bundle >> 43) & TILEGX_DATA_IMM8);
+ if (gen_addi(dc, rdst, rsrc, im8)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+
+ case 0x2c00000000000000ULL:
+ switch(TILEGX_CODE_Y1_E(bundle)) {
+ case 0x0004000000000000ULL:
+ rdst = (unsigned char)((bundle >> 31) & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER);
+ rsrcb = (unsigned char)((bundle >> 43) & TILEGX_DATA_REGISTER);
+ /* move Dest, Src */
+ if (rsrcb == 0x3f) {
+ if (gen_move(dc, rdst, rsrc)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ } else {
+ qemu_log("invalid rsrcb, not 0x3f for move in y1");
+ }
+ break;
+
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ qemu_log("y1 E bundle value: %16.16llx", TILEGX_CODE_Y1_E(bundle));
+ break;
+ }
+ break;
+
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ qemu_log("bundle value: %16.16llx", TILEGX_CODE_Y1(bundle));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int translate_y2_bundle(struct DisasContext *dc, uint64_t bundle,
+ uint64_t mode)
+{
+ unsigned char rsrc, rdst;
+
+ qemu_log("\ny2: %16.16lx\t", bundle);
+ switch (TILEGX_CODE_Y2(bundle)) {
+ case 0x0200000004000000ULL:
+ switch (mode) {
+ /* ld Dest, Src */
+ case 0x8000000000000000ULL:
+ rdst = (unsigned char)((bundle >> 51) & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 20) & TILEGX_DATA_REGISTER);
+ if (gen_ld(dc, rdst, rsrc)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+ /* st Dest, Src */
+ case 0xc000000000000000ULL:
+ rdst = (unsigned char)((bundle >> 20) & TILEGX_DATA_REGISTER);
+ rsrc = (unsigned char)((bundle >> 51) & TILEGX_DATA_REGISTER);
+ if (gen_st(dc, rdst, rsrc)) {
+ /* FIXME: raise an exception for invalid instruction */
+ return -1;
+ }
+ break;
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ qemu_log("bundle value: %16.16llx, mode: %16.16lx",
+ TILEGX_CODE_Y2(bundle), mode);
+ return -1;
+ }
+ break;
+
+ default:
+ /* FIXME: raise an exception for invalid instruction */
+ qemu_log("bundle value: %16.16llx", TILEGX_CODE_Y2(bundle));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int translate_one_bundle(struct DisasContext *dc, uint64_t bundle)
+{
+ int i, ret = 0;
+ TCGv tmp;
+
+ for (i = 0; i < TILEGX_BUNDLE_INSNS; i++) {
+ dc->tmp_regs[i].idx = TILEGX_R_NOREG;
+ TCGV_UNUSED_I64(dc->tmp_regs[i].val);
+ }
+
+ /* For can regress completely, it must be y0 -> y1 -> y2, or x0 -> x1. */
+ if (TILEGX_BUNDLE_TYPE_Y(bundle)) {
+ dc->tmp_regcur = dc->tmp_regs + 0;
+ ret = translate_y0_bundle(dc, TILEGX_PIPE_Y0(bundle));
+ if (ret) {
+ goto err;
+ }
+ dc->tmp_regcur = dc->tmp_regs + 1;
+ ret = translate_y1_bundle(dc, TILEGX_PIPE_Y1(bundle));
+ if (ret) {
+ goto err;
+ }
+ dc->tmp_regcur = dc->tmp_regs + 2;
+ ret = translate_y2_bundle(dc, TILEGX_PIPE_Y2(bundle),
+ bundle & TILEGX_BUNDLE_TYPE_MASK);
+ if (ret) {
+ goto err;
+ }
+ } else {
+ dc->tmp_regcur = dc->tmp_regs + 0;
+ ret = translate_x0_bundle(dc, TILEGX_PIPE_X0(bundle));
+ if (ret) {
+ goto err;
+ }
+ dc->tmp_regcur = dc->tmp_regs + 1;
+ ret = translate_x1_bundle(dc, TILEGX_PIPE_X1(bundle));
+ if (ret) {
+ goto err;
+ }
+ }
+
+ for (i = 0; i < TILEGX_BUNDLE_INSNS; i++) {
+ if (dc->tmp_regs[i].idx == TILEGX_R_NOREG) {
+ continue;
+ }
+ 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);
+ 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);
+ }
+
+err:
+ return ret;
+}
+
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.
- */
- fprintf(stderr, "\nLoad elf64 tilegx successfully\n");
- fprintf(stderr, "reach code start position: [" TARGET_FMT_lx "] %s\n\n",
+ int ret = 0;
+ struct DisasContext ctx;
+ struct DisasContext *dc = &ctx;
+
+ CPUTLState *env = &cpu->env;
+ uint64_t pc_start = tb->pc;
+ uint64_t next_page_start = (pc_start & TARGET_PAGE_MASK) +
TARGET_PAGE_SIZE;
+ int num_insns = 0;
+ int max_insns = tb->cflags & CF_COUNT_MASK;
+
+ /* FIXME: do not consider about search_pc firstly. */
+ qemu_log("TB block start position: [" TARGET_FMT_lx "] %s\n\n",
tb->pc, lookup_symbol(tb->pc));
- exit(0);
+
+ dc->pc = pc_start;
+ dc->cpustate_changed = 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 {
+ ret = translate_one_bundle(dc, cpu_ldq_data(env, dc->pc));
+ if (ret) {
+ goto err;
+ }
+ num_insns++;
+ dc->pc += TILEGX_BUNDLE_SIZE;
+ } while (tcg_op_buf_count() <= OPC_MAX_SIZE - TILEGX_BUNDLE_OPCS
+ && num_insns <= max_insns - TILEGX_BUNDLE_INSNS
+ && dc->pc <= next_page_start - TILEGX_BUNDLE_SIZE
+ && dc->jmp.cond == TCG_COND_NEVER
+ && !dc->cpustate_changed);
+ gen_tb_end(tb, num_insns);
+
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
+
+ return;
+err:
+ exit(-1);
}
void gen_intermediate_code(CPUTLState *env, struct TranslationBlock *tb)
--
1.9.3