From patchwork Sat Mar 21 10:27:20 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen Gang X-Patchwork-Id: 452925 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 975241400DE for ; Sat, 21 Mar 2015 21:27:55 +1100 (AEDT) Received: from localhost ([::1]:47325 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YZGdF-00081g-R1 for incoming@patchwork.ozlabs.org; Sat, 21 Mar 2015 06:27:53 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52572) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YZGcu-0007WU-BD for qemu-devel@nongnu.org; Sat, 21 Mar 2015 06:27:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YZGcq-0002kX-8x for qemu-devel@nongnu.org; Sat, 21 Mar 2015 06:27:32 -0400 Received: from blu004-omc1s37.hotmail.com ([65.55.116.48]:51026) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YZGcq-0002kR-3J for qemu-devel@nongnu.org; Sat, 21 Mar 2015 06:27:28 -0400 Received: from BLU437-SMTP62 ([65.55.116.8]) by BLU004-OMC1S37.hotmail.com over TLS secured channel with Microsoft SMTPSVC(7.5.7601.22751); Sat, 21 Mar 2015 03:27:28 -0700 X-TMN: [b+pkB7XIRJhjI+1j+KYIfVxB4srYvu7B] X-Originating-Email: [xili_gchen_5257@hotmail.com] Message-ID: Date: Sat, 21 Mar 2015 18:27:20 +0800 From: Chen Gang User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:31.0) Gecko/20100101 Thunderbird/31.5.0 MIME-Version: 1.0 To: "rth@twiddle.net" , Peter Maydell , =?UTF-8?B?QW5kcmVhcyBGw6RyYmVy?= , Chris Metcalf , Riku Voipio , "walt@tilera.com" References: <550D455B.8000004@hotmail.com> In-Reply-To: <550D455B.8000004@hotmail.com> X-OriginalArrivalTime: 21 Mar 2015 10:27:26.0128 (UTC) FILETIME=[A0330300:01D063C1] X-detected-operating-system: by eggs.gnu.org: Windows 7 or 8 [fuzzy] X-Received-From: 65.55.116.48 Cc: qemu-devel Subject: [Qemu-devel] [PATCH 10/12 v8] target-tilegx: Finish processing bundle and preparing decoding pipes X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Finish processing tilegx bundle, and reach to related pipes. At present, the qemu tilegx can pass building. Signed-off-by: Chen Gang --- target-tilegx/translate.c | 515 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 515 insertions(+) create mode 100644 target-tilegx/translate.c diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c new file mode 100644 index 0000000..0ac7e11 --- /dev/null +++ b/target-tilegx/translate.c @@ -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 + * + */ + +#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]); + } +}