From patchwork Mon Jul 7 18:13:37 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Bastian Koppelmann X-Patchwork-Id: 367659 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 8E77A140085 for ; Tue, 8 Jul 2014 03:17:32 +1000 (EST) Received: from localhost ([::1]:51910 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X4CXi-0003rU-OZ for incoming@patchwork.ozlabs.org; Mon, 07 Jul 2014 13:17:30 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47529) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X4CRB-0004Rf-Vy for qemu-devel@nongnu.org; Mon, 07 Jul 2014 13:10:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X4CR5-0005YB-0c for qemu-devel@nongnu.org; Mon, 07 Jul 2014 13:10:45 -0400 Received: from mail.uni-paderborn.de ([131.234.142.9]:38347) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X4CR4-0005Xv-N0 for qemu-devel@nongnu.org; Mon, 07 Jul 2014 13:10:38 -0400 From: Bastian Koppelmann To: qemu-devel@nongnu.org Date: Mon, 7 Jul 2014 19:13:37 +0100 Message-Id: <1404756822-3253-11-git-send-email-kbastian@mail.uni-paderborn.de> X-Mailer: git-send-email 2.0.1 In-Reply-To: <1404756822-3253-1-git-send-email-kbastian@mail.uni-paderborn.de> References: <1404756822-3253-1-git-send-email-kbastian@mail.uni-paderborn.de> MIME-Version: 1.0 X-IMT-Spam-Score: 0.0 () X-PMX-Version: 6.1.0.2415318, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2014.7.7.170318 X-IMT-Authenticated-Sender: uid=kbastian,ou=People,o=upb,c=de X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 131.234.142.9 Cc: peter.maydell@linaro.org, rth@twiddle.net Subject: [Qemu-devel] [PATCH 10/15] target-tricore: Add instructions of SB opcode format 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 Add instructions of SB opcode format. Add helper call/ret. Add micro-op generator functions for branches. Add makro to generate helper functions. Signed-off-by: Bastian Koppelmann --- target-tricore/helper.h | 5 ++ target-tricore/op_helper.c | 192 +++++++++++++++++++++++++++++++++++++++++++++ target-tricore/translate.c | 85 ++++++++++++++++++++ 3 files changed, 282 insertions(+) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index acea104..0d79d1d 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -17,3 +17,8 @@ /* Arithmetic */ DEF_HELPER_3(shac, i32, env, i32, i32) + +/* CSA */ +DEF_HELPER_3(call, void, env, i32, i32) +DEF_HELPER_1(ret, void, env) + diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index b9fbfad..5267fd0 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -56,6 +56,198 @@ target_ulong helper_shac(CPUTRICOREState *env, target_ulong r1, return ret; } +/* context save area (CSA) related helpers */ + +enum { + CONTEXT_LOWER = 0, + CONTEXT_UPPER = 1, +}; + +static int cdc_increment(TCState *tc) +{ + tc->PSW++; + return 0; +} + +static int cdc_decrement(TCState *tc) +{ + tc->PSW--; + return 0; +} + +static void save_context(CPUTRICOREState *env, int ea, int ul, + target_ulong *new_FCX) +{ + *new_FCX = cpu_ldl_data(env, ea); + cpu_stl_data(env, ea, env->active_tc.PCXI); + if (ul == CONTEXT_UPPER) { + cpu_stl_data(env, ea+4, env->active_tc.PSW); + cpu_stl_data(env, ea+8, env->active_tc.gpr_a[10]); + cpu_stl_data(env, ea+12, env->active_tc.gpr_a[11]); + cpu_stl_data(env, ea+16, env->active_tc.gpr_d[8]); + cpu_stl_data(env, ea+20, env->active_tc.gpr_d[9]); + cpu_stl_data(env, ea+24, env->active_tc.gpr_d[10]); + cpu_stl_data(env, ea+28, env->active_tc.gpr_d[11]); + cpu_stl_data(env, ea+32, env->active_tc.gpr_a[12]); + cpu_stl_data(env, ea+36, env->active_tc.gpr_a[13]); + cpu_stl_data(env, ea+40, env->active_tc.gpr_a[14]); + cpu_stl_data(env, ea+44, env->active_tc.gpr_a[15]); + cpu_stl_data(env, ea+48, env->active_tc.gpr_d[12]); + cpu_stl_data(env, ea+52, env->active_tc.gpr_d[13]); + cpu_stl_data(env, ea+56, env->active_tc.gpr_d[14]); + cpu_stl_data(env, ea+60, env->active_tc.gpr_d[15]); + } else { + cpu_stl_data(env, ea+4, env->active_tc.gpr_a[11]); + cpu_stl_data(env, ea+8, env->active_tc.gpr_a[2]); + cpu_stl_data(env, ea+12, env->active_tc.gpr_a[3]); + cpu_stl_data(env, ea+16, env->active_tc.gpr_d[0]); + cpu_stl_data(env, ea+20, env->active_tc.gpr_d[1]); + cpu_stl_data(env, ea+24, env->active_tc.gpr_d[2]); + cpu_stl_data(env, ea+28, env->active_tc.gpr_d[3]); + cpu_stl_data(env, ea+32, env->active_tc.gpr_a[4]); + cpu_stl_data(env, ea+36, env->active_tc.gpr_a[5]); + cpu_stl_data(env, ea+40, env->active_tc.gpr_a[6]); + cpu_stl_data(env, ea+44, env->active_tc.gpr_a[7]); + cpu_stl_data(env, ea+48, env->active_tc.gpr_d[4]); + cpu_stl_data(env, ea+52, env->active_tc.gpr_d[5]); + cpu_stl_data(env, ea+56, env->active_tc.gpr_d[6]); + cpu_stl_data(env, ea+60, env->active_tc.gpr_d[7]); + } +} + +static void restore_context(CPUTRICOREState *env, int ea, int ul, + target_ulong *new_PCXI, target_ulong *new_PSW) +{ + *new_PCXI = cpu_ldl_data(env, ea); + if (ul == CONTEXT_UPPER) { + *new_PSW = cpu_ldl_data(env, ea+4); + env->active_tc.gpr_a[10] = cpu_ldl_data(env, ea+8); + env->active_tc.gpr_a[11] = cpu_ldl_data(env, ea+12); + env->active_tc.gpr_d[8] = cpu_ldl_data(env, ea+16); + env->active_tc.gpr_d[9] = cpu_ldl_data(env, ea+20); + env->active_tc.gpr_d[10] = cpu_ldl_data(env, ea+24); + env->active_tc.gpr_d[11] = cpu_ldl_data(env, ea+28); + env->active_tc.gpr_a[12] = cpu_ldl_data(env, ea+32); + env->active_tc.gpr_a[13] = cpu_ldl_data(env, ea+36); + env->active_tc.gpr_a[14] = cpu_ldl_data(env, ea+40); + env->active_tc.gpr_a[15] = cpu_ldl_data(env, ea+44); + env->active_tc.gpr_d[12] = cpu_ldl_data(env, ea+48); + env->active_tc.gpr_d[13] = cpu_ldl_data(env, ea+52); + env->active_tc.gpr_d[14] = cpu_ldl_data(env, ea+56); + env->active_tc.gpr_d[15] = cpu_ldl_data(env, ea+60); + } else { + env->active_tc.gpr_a[11] = cpu_ldl_data(env, ea+4); + env->active_tc.gpr_a[2] = cpu_ldl_data(env, ea+8); + env->active_tc.gpr_a[3] = cpu_ldl_data(env, ea+12); + env->active_tc.gpr_d[0] = cpu_ldl_data(env, ea+16); + env->active_tc.gpr_d[1] = cpu_ldl_data(env, ea+20); + env->active_tc.gpr_d[2] = cpu_ldl_data(env, ea+24); + env->active_tc.gpr_d[3] = cpu_ldl_data(env, ea+28); + env->active_tc.gpr_a[4] = cpu_ldl_data(env, ea+32); + env->active_tc.gpr_a[5] = cpu_ldl_data(env, ea+36); + env->active_tc.gpr_a[6] = cpu_ldl_data(env, ea+40); + env->active_tc.gpr_a[7] = cpu_ldl_data(env, ea+44); + env->active_tc.gpr_d[4] = cpu_ldl_data(env, ea+48); + env->active_tc.gpr_d[5] = cpu_ldl_data(env, ea+52); + env->active_tc.gpr_d[6] = cpu_ldl_data(env, ea+56); + env->active_tc.gpr_d[7] = cpu_ldl_data(env, ea+60); + } + cpu_stl_data(env, ea, env->active_tc.FCX); +} + +void helper_call(CPUTRICOREState *env, uint32_t pc, + uint32_t insnsize) +{ + target_ulong ret_address; + target_ulong tmp_FCX; + target_ulong ea; + target_ulong new_FCX; + + /* if (FCX == 0) trap(FCU); */ + if (env->active_tc.FCX == 0) { + printf("FCU trap"); + } + /* if (PSW.CDE) then if (cdc_increment()) then trap(CDO); */ + if (env->active_tc.PSW & MASK_PSW_CDE) { + if (cdc_increment(&(env->active_tc))) { + printf("CDO trap\n"); + } + } + /* PSW.CDE = 1;*/ + env->active_tc.PSW |= MASK_PSW_CDE; + /* ret_addr = PC + 4; */ + ret_address = pc + insnsize; + /* tmp_FCX = FCX; */ + tmp_FCX = env->active_tc.FCX; + /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */ + ea = ((env->active_tc.FCX & MASK_FCX_FCXS) << 12) + + ((env->active_tc.FCX & MASK_FCX_FCXO) << 6); + /* new_FCX = M(EA, word); + M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], + A[12], A[13], A[14], A[15], D[12], D[13], D[14], + D[15]}; */ + save_context(env, ea, 1, &new_FCX); + + /* PCXI.PCPN = ICR.CCPN; */ + env->active_tc.PCXI = (env->active_tc.PCXI & 0xffffff) + + ((env->active_tc.ICR & MASK_ICR_CCPN) << 24); + /* PCXI.PIE = ICR.IE; */ + env->active_tc.PCXI = ((env->active_tc.PCXI & ~MASK_PCXI_PIE) + + ((env->active_tc.ICR & MASK_ICR_IE) << 15)); + /* PCXI.UL = 1; */ + env->active_tc.PCXI |= MASK_PCXI_UL; + + /* PCXI[19: 0] = FCX[19: 0]; */ + env->active_tc.PCXI = (env->active_tc.PCXI & 0xfff00000) + + (env->active_tc.FCX & 0xfffff); + /* FCX[19: 0] = new_FCX[19: 0]; */ + env->active_tc.FCX = (env->active_tc.FCX & 0xfff00000) + + (new_FCX & 0xfffff); + /* A[11] = ret_addr[31: 0]; */ + env->active_tc.gpr_a[11] = ret_address; + + /* if (tmp_FCX == LCX) trap(FCD);*/ + if (tmp_FCX == env->active_tc.LCX) { + printf("FCD trap\n"); + } +} + +void helper_ret(CPUTRICOREState *env) +{ + target_ulong ea; + target_ulong new_PCXI; + target_ulong new_PSW; + /* if (PSW.CDE) then if (cdc_decrement()) then trap(CDU);*/ + if (env->active_tc.PSW & MASK_PSW_CDE) { + if (cdc_decrement(&(env->active_tc))) { + printf("CDU trap\n"); + } + } + /* if (PCXI[19: 0] == 0) then trap(CSU); */ + if ((env->active_tc.PCXI & 0xfffff) == 0) { + printf("CSU trap\n"); + } + /* if (PCXI.UL == 0) then trap(CTYP); */ + if ((env->active_tc.PCXI & MASK_PCXI_UL) == 0) { + printf("CTYP trap\n"); + } + /* PC = {A11 [31: 1], 1’b0}; */ + env->active_tc.PC = env->active_tc.gpr_a[11] & 0xfffffffe; + + /* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */ + ea = ((env->active_tc.PCXI & MASK_PCXI_PCXS) << 12) + + ((env->active_tc.PCXI & MASK_PCXI_PCXO) << 6); + /* {new_PCXI, new_PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12], + A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); + M(EA, word) = FCX; */ + restore_context(env, ea, CONTEXT_UPPER, &new_PCXI, &new_PSW); + /* FCX[19: 0] = PCXI[19: 0]; */ + env->active_tc.FCX = (env->active_tc.FCX & 0xfff00000) + + (env->active_tc.PCXI & 0x000fffff); + /* PCXI = new_PCXI; */ + env->active_tc.PCXI = new_PCXI; +} + static inline void QEMU_NORETURN do_raise_exception_err(CPUTRICOREState *env, uint32_t exception, int error_code, diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 39f29bb..f32e1d1 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -117,6 +117,15 @@ static int sign_extend(uint32_t val, uint32_t width) * Functions to generate micro-ops */ +/* Makros for generating helpers */ +#define gen_helper_2arg(name, arg0, arg1) do { \ + TCGv_i32 helper_tmp0 = tcg_const_i32(arg0); \ + TCGv_i32 helper_tmp1 = tcg_const_i32(arg1); \ + gen_helper_##name(cpu_env, helper_tmp0, helper_tmp1); \ + tcg_temp_free_i32(helper_tmp0); \ + tcg_temp_free_i32(helper_tmp1); \ + } while (0) + /* Functions for load/save to/from memory */ #define OP_MEM_INDIRECT(insn) \ static inline void gen_indirect_##insn(DisasContext *ctx, TCGv r1, TCGv r2, \ @@ -241,6 +250,64 @@ static inline void gen_ssov(TCGv ret, TCGv arg, int32_t cons) tcg_temp_free(temp); } +/* helpers for generating program flow micro-ops */ + +static inline void gen_save_pc(target_ulong pc) +{ + tcg_gen_movi_tl(cpu_PC, pc); +} + +static inline void gen_branch_cond(DisasContext *ctx, int cond, TCGv r1, + TCGv r2, int16_t address) +{ + int jumpLabel; + jumpLabel = gen_new_label(); + tcg_gen_brcond_tl(cond, r1, r2, jumpLabel); + + gen_save_pc(ctx->pc + insn_bytes); + tcg_gen_exit_tb(0); + + gen_set_label(jumpLabel); + gen_save_pc(ctx->pc + address * 2); + tcg_gen_exit_tb(0); + +} + +static inline void gen_branch_condi(DisasContext *ctx, int cond, TCGv r1, + int r2, int16_t address) +{ + TCGv temp = tcg_const_i32(r2); + gen_branch_cond(ctx, cond, r1, temp, address); + tcg_temp_free(temp); +} + +static void gen_compute_branch(DisasContext *ctx, uint32_t opc, + int r1, int r2 , int32_t constant , int32_t offset) +{ + + switch (opc) { +/* SB-format jumps */ + case OPC1_16_SB_J: + case OPC1_32_B_J: + gen_save_pc(ctx->pc+offset*2); + tcg_gen_exit_tb(0); + break; + case OPC1_16_SB_CALL: + gen_helper_2arg(call, ctx->pc, insn_bytes); + gen_save_pc(ctx->pc+sign_extend(offset, 7)*2); + tcg_gen_exit_tb(0); + case OPC1_16_SB_JZ: + gen_branch_condi(ctx, TCG_COND_EQ, cpu_gpr_d[15], 0, offset); + break; + case OPC1_16_SB_JNZ: + gen_branch_condi(ctx, TCG_COND_NE, cpu_gpr_d[15], 0, offset); + break; + default: + printf("Branch Error at %x\n", ctx->pc); + } + ctx->bstate = BS_BRANCH; +} + /* * Functions for decoding instructions */ @@ -249,6 +316,7 @@ static void decode_16Bit_opc(CPUTRICOREState *env, DisasContext *ctx) target_ulong op1; int r1, r2; uint16_t const16; + int32_t address; TCGv temp; op1 = MASK_OP_MAJOR(ctx->opcode); @@ -541,6 +609,23 @@ static void decode_16Bit_opc(CPUTRICOREState *env, DisasContext *ctx) const16 = MASK_OP_SLRO_OFF4(ctx->opcode); gen_indirect_ld32s(ctx, cpu_gpr_d[r1], cpu_gpr_a[15], const16 * 4); break; +/* SB-format */ + case OPC1_16_SB_CALL: + address = MASK_OP_SB_DISP8(ctx->opcode); + gen_compute_branch(ctx, op1, 0, 0, 0, address); + break; + case OPC1_16_SB_J: + address = MASK_OP_SB_DISP8(ctx->opcode); + gen_compute_branch(ctx, op1, 0, 0, 0, address); + break; + case OPC1_16_SB_JNZ: + address = sign_extend(MASK_OP_SB_DISP8(ctx->opcode), 7); + gen_compute_branch(ctx, op1, 0, 0, 0, address); + break; + case OPC1_16_SB_JZ: + address = sign_extend(MASK_OP_SB_DISP8(ctx->opcode), 7); + gen_compute_branch(ctx, op1, 0, 0, 0, address); + break; } }