new file mode 100644
@@ -0,0 +1,515 @@
+/*
+ * QEMU TILE-Gx CPU
+ *
+ * Copyright (c) 2015 Chen Gang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "cpu.h"
+#include "qemu/log.h"
+#include "disas/disas.h"
+#include "tcg-op.h"
+#include "exec/cpu_ldst.h"
+#include "opcode_tilegx.h"
+
+#define FMT64X "%016" PRIx64
+
+#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 */
+
+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 {
+ uint8_t 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 */
+
+ 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 void gen_exception(DisasContext *dc, int num)
+{
+ TCGv_i32 tmp = tcg_const_i32(num);
+
+ gen_helper_exception(cpu_env, tmp);
+ tcg_temp_free_i32(tmp);
+}
+
+static void decode_addi_opcode_y0(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_rrr_1_opcode_y0(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_rrr_5_opcode_y0(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_addi_opcode_y1(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_rrr_1_opcode_y1(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_rrr_5_opcode_y1(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_ldst0_opcode_y2(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_ldst1_opcode_y2(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_ldst2_opcode_y2(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_ldst3_opcode_y2(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_addli_opcode_x0(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_bf_opcode_x0(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_imm8_opcode_x0(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_rrr_0_opcode_x0(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_shift_opcode_x0(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_shl16insli_opcode_x0(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_addli_opcode_x1(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_branch_opcode_x1(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_imm8_opcode_x1(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_jump_opcode_x1(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_rrr_0_opcode_x1(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_shift_opcode_x1(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+static void decode_shl16insli_opcode_x1(struct DisasContext *dc,
+ tilegx_bundle_bits bundle)
+{
+}
+
+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;
+ case ADDXI_OPCODE_Y0:
+ case ANDI_OPCODE_Y0:
+ case CMPEQI_OPCODE_Y0:
+ case CMPLTSI_OPCODE_Y0:
+ case RRR_0_OPCODE_Y0:
+ case RRR_2_OPCODE_Y0:
+ case RRR_3_OPCODE_Y0:
+ case RRR_4_OPCODE_Y0:
+ case RRR_6_OPCODE_Y0:
+ case RRR_7_OPCODE_Y0:
+ case RRR_8_OPCODE_Y0:
+ case RRR_9_OPCODE_Y0:
+ case SHIFT_OPCODE_Y0:
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "UNIMP y0, opcode %d, bundle [" FMT64X "]\n",
+ opcode, (uint64_t)bundle);
+ dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ 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;
+ case ADDXI_OPCODE_Y1:
+ case ANDI_OPCODE_Y1:
+ case CMPEQI_OPCODE_Y1:
+ case CMPLTSI_OPCODE_Y1:
+ case RRR_0_OPCODE_Y1:
+ case RRR_2_OPCODE_Y1:
+ case RRR_3_OPCODE_Y1:
+ case RRR_4_OPCODE_Y1:
+ case RRR_6_OPCODE_Y1:
+ case RRR_7_OPCODE_Y1:
+ case SHIFT_OPCODE_Y1:
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "UNIMP y1, opcode %d, bundle [" FMT64X "]\n",
+ opcode, (uint64_t)bundle);
+ dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ 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 0: /* LD1S_OPCODE_Y2, ST1_OPCODE_Y2 */
+ decode_ldst0_opcode_y2(dc, bundle);
+ return;
+ case 1: /* LD4S_OPCODE_Y2, LD1U_OPCODE_Y2, ST2_OPCODE_Y2 */
+ decode_ldst1_opcode_y2(dc, bundle);
+ return;
+ case 2: /* LD2S_OPCODE_Y2, LD4U_OPCODE_Y2, ST4_OPCODE_Y2 */
+ decode_ldst2_opcode_y2(dc, bundle);
+ return;
+ case 3: /* LD_OPCODE_Y2, ST_OPCODE_Y2, LD2U_OPCODE_Y2 */
+ decode_ldst3_opcode_y2(dc, bundle);
+ return;
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "UNIMP y2, opcode %d, bundle [" FMT64X "]\n",
+ opcode, (uint64_t)bundle);
+ dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ 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 BF_OPCODE_X0:
+ decode_bf_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 SHIFT_OPCODE_X0:
+ decode_shift_opcode_x0(dc, bundle);
+ return;
+ case SHL16INSLI_OPCODE_X0:
+ decode_shl16insli_opcode_x0(dc, bundle);
+ return;
+ case ADDXLI_OPCODE_X0:
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "UNIMP x0, opcode %d, bundle [" FMT64X "]\n",
+ opcode, (uint64_t)bundle);
+ dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ 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 SHIFT_OPCODE_X1:
+ decode_shift_opcode_x1(dc, bundle);
+ return;
+ case SHL16INSLI_OPCODE_X1:
+ decode_shl16insli_opcode_x1(dc, bundle);
+ return;
+ case ADDXLI_OPCODE_X1:
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "UNIMP x1, opcode %d, bundle [" FMT64X "]\n",
+ opcode, (uint64_t)bundle);
+ dc->exception = TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ 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)
+{
+ 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 = TILEGX_EXCP_NONE;
+ 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));
+ num_insns++;
+ dc->pc += TILEGX_BUNDLE_SIZE_IN_BYTES;
+ if (dc->exception != TILEGX_EXCP_NONE) {
+ gen_exception(dc, dc->exception);
+ break;
+ }
+ } 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)
+{
+ gen_intermediate_code_internal(tilegx_env_get_cpu(env), tb, false);
+}
+
+void gen_intermediate_code_pc(CPUTLGState *env, struct TranslationBlock *tb)
+{
+ gen_intermediate_code_internal(tilegx_env_get_cpu(env), tb, true);
+}
+
+void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb, int pc_pos)
+{
+ env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+}
+
+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]);
+ }
+}
Finish processing tilegx bundle, and reach to related pipes. Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com> --- target-tilegx/translate.c | 515 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 515 insertions(+) create mode 100644 target-tilegx/translate.c