From: Chen Gang S <gang.chen@sunrus.com.cn>
To: Peter Maydell <peter.maydell@linaro.org>,
Richard Henderson <rth@redhat.com>,
Chris Metcalf <cmetcalf@ezchip.com>,
"walt@tilera.com" <walt@tilera.com>,
Riku Voipio <riku.voipio@iki.fi>
Cc: qemu-devel <qemu-devel@nongnu.org>
Subject: [Qemu-devel] [PATCH] target-tilegx: Execute _start and reach to __libc_start_main successfully
Date: Tue, 24 Feb 2015 15:53:18 +0800 [thread overview]
Message-ID: <54EC2DEE.8050809@sunrus.com.cn> (raw)
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 <gang.chen.5i5j@gmail.com>
---
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
next reply other threads:[~2015-02-24 7:45 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-24 7:53 Chen Gang S [this message]
2015-02-24 8:07 ` [Qemu-devel] [PATCH] target-tilegx: Execute _start and reach to __libc_start_main successfully Chen Gang S
2015-02-24 14:21 ` Chris Metcalf
2015-02-24 14:38 ` Peter Maydell
2015-02-24 15:39 ` Chen Gang S
2015-02-24 16:42 ` Richard Henderson
2015-02-24 17:08 ` Chen Gang S
2015-02-24 16:31 ` Chen Gang S
2015-02-24 16:46 ` Chris Metcalf
2015-02-24 17:25 ` Chen Gang S
2015-02-24 18:18 ` Chris Metcalf
2015-02-25 1:01 ` Chen Gang S
2015-02-24 17:55 ` Richard Henderson
2015-02-25 3:40 ` Chen Gang S
2015-02-25 17:19 ` Richard Henderson
2015-02-26 1:44 ` Chen Gang S
2015-02-26 16:31 ` Richard Henderson
2015-02-26 23:30 ` Chen Gang S
2015-02-27 3:01 ` Chris Metcalf
2015-02-27 3:41 ` Chen Gang S
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=54EC2DEE.8050809@sunrus.com.cn \
--to=gang.chen@sunrus.com.cn \
--cc=cmetcalf@ezchip.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=riku.voipio@iki.fi \
--cc=rth@redhat.com \
--cc=walt@tilera.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.