From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47517) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X4CRB-0004RP-1Y for qemu-devel@nongnu.org; Mon, 07 Jul 2014 13:10:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X4CR3-0005XF-JJ for qemu-devel@nongnu.org; Mon, 07 Jul 2014 13:10:44 -0400 Received: from mail.uni-paderborn.de ([131.234.142.9]:10601) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X4CR3-0005Wm-18 for qemu-devel@nongnu.org; Mon, 07 Jul 2014 13:10:37 -0400 From: Bastian Koppelmann Date: Mon, 7 Jul 2014 19:13:33 +0100 Message-Id: <1404756822-3253-7-git-send-email-kbastian@mail.uni-paderborn.de> 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> Subject: [Qemu-devel] [PATCH 06/15] target-tricore: Add instructions of SRC opcode format List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, rth@twiddle.net Add instructions of SRC opcode format. Add helper for sh arithmetic carry. Add micro-op generator functions for conditional add/sub/mov and sh. Signed-off-by: Bastian Koppelmann --- target-tricore/helper.h | 19 +++++ target-tricore/op_helper.c | 36 +++++++++ target-tricore/translate.c | 197 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 251 insertions(+), 1 deletion(-) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index e69de29..acea104 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn + * + * 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 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 . + */ + +/* Arithmetic */ +DEF_HELPER_3(shac, i32, env, i32, i32) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 2e5981f..b9fbfad 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -20,6 +20,42 @@ #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" + +target_ulong helper_shac(CPUTRICOREState *env, target_ulong r1, + target_ulong r2) +{ + target_ulong carry_out, msk, msk_start, msk_len, cond, shift_count, ret; + int const6; + const6 = r2 & 0x3f; + + if (const6 >= 0) { + if (const6 != 0) { + msk_start = 32 - const6; + msk_len = 31-msk_start; + msk = ((1 << msk_len) - 1) << msk_start; + carry_out = ((r1 & msk) != 0); + } else { + carry_out = 0; + } + ret = r1 << const6; + } else { + shift_count = 0 - const6; + cond = r1 & 0x80000000; + if (cond != 0) { + msk = (((1 << shift_count) - 1) << (32 - shift_count)); + } else { + msk = 0; + } + ret = msk | (r1 >> shift_count); + msk = (1 << (shift_count - 1)) - 1; + carry_out = ((r1 & msk) != 0); + } + if (carry_out) { + /* TODO: carry out */ + } + return ret; +} + 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 e0de874..ad595b2 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -27,6 +27,8 @@ #include "exec/helper-gen.h" #include "tricore-opcodes.h" + +static int insn_bytes; /* * TCG registers */ @@ -96,10 +98,203 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f, } -static int insn_bytes; +/* + * Helper functions for translation + */ + +static int sign_extend(uint32_t val, uint32_t width) +{ + int sval; + /* LSL. */ + val <<= 31 - width; + sval = val; + /* ASR. */ + sval >>= 31 - width; + return sval; +} + +/* + * Functions to generate micro-ops + */ +/* Functions for arithmetic instructions */ + +#define OP_COND(insn)\ +static inline void gen_cond_##insn(int cond, TCGv r1, TCGv r2, TCGv r3, \ + TCGv r4) \ +{ \ + int label = gen_new_label(); \ + int label2 = gen_new_label(); \ + \ + tcg_gen_brcondi_tl(cond, r4, 0, label); \ + tcg_gen_mov_tl(r3, r1); \ + tcg_gen_br(label2); \ + gen_set_label(label); \ + tcg_gen_##insn ## _tl(r3, r1, r2); \ + gen_set_label(label2); \ +} \ + \ +static inline void gen_condi_##insn(int cond, TCGv r1, int32_t r2, \ + TCGv r3, TCGv r4) \ +{ \ + TCGv temp = tcg_const_i32(r2); \ + gen_cond_##insn(cond, r1, temp, r3, r4); \ + tcg_temp_free(temp); \ +} + + +static inline void gen_cond_mov(int cond, TCGv r1, TCGv r2, TCGv r3, + TCGv r4) +{ + int label = gen_new_label(); + int label2 = gen_new_label(); + + tcg_gen_brcondi_tl(cond, r4, 0, label); + tcg_gen_mov_tl(r3, r1); + tcg_gen_br(label2); + gen_set_label(label); + tcg_gen_mov_tl(r3, r2); + gen_set_label(label2); +} + +static inline void gen_condi_mov(int cond, TCGv r1, int32_t r2, TCGv r3, + TCGv r4) +{ + TCGv temp = tcg_const_i32(r2); + gen_cond_mov(cond, r1, temp , r3, r4); + tcg_temp_free(temp); +} +OP_COND(add) +OP_COND(sub) + +static void gen_sh(TCGv ret, TCGv r1, TCGv r2) +{ + int label, label2; + label = gen_new_label(); + label2 = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_GE, r2, 0, label); + /* r1 >>(-r2) */ + tcg_gen_shr_tl(ret, r1, r2); + tcg_gen_brcond_tl(TCG_COND_EQ, r2, r2, label2); + gen_set_label(label); + /* r1 << r2 */ + tcg_gen_shl_tl(ret, r1, r2); + gen_set_label(label2); +} + +static void gen_shi(TCGv ret, TCGv r1, int32_t r2) +{ + TCGv temp = tcg_const_i32(r2); + gen_sh(ret, r1, temp); + tcg_temp_free(temp); +} + +static void gen_shac(TCGv ret, TCGv r1, TCGv r2) +{ + gen_helper_shac(ret, cpu_env, r1, r2); +} + +static void gen_shaci(TCGv ret, TCGv r1, int32_t con) +{ + TCGv temp = tcg_const_i32(con); + + gen_shac(ret, r1, temp); + + tcg_temp_free(temp); +} + +/* + * Functions for decoding instructions + */ static void decode_16Bit_opc(CPUTRICOREState *env, DisasContext *ctx) { + target_ulong op1; + int r1; + uint16_t const16; + op1 = MASK_OP_MAJOR(ctx->opcode); + + switch (op1) { + + case OPC1_16_SRC_ADD: + const16 = sign_extend(MASK_OP_SRC_CONST4(ctx->opcode), 3); + r1 = MASK_OP_SRC_S1D(ctx->opcode); + tcg_gen_addi_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], const16); + break; + case OPC1_16_SRC_ADD_A15: + r1 = MASK_OP_SRC_S1D(ctx->opcode); + const16 = MASK_OP_SRC_CONST4(ctx->opcode); + tcg_gen_addi_tl(cpu_gpr_d[15], cpu_gpr_d[r1], + sign_extend(const16, 3)); + break; + case OPC1_16_SRC_ADD_15A: + r1 = MASK_OP_SRC_S1D(ctx->opcode); + const16 = MASK_OP_SRC_CONST4(ctx->opcode); + tcg_gen_addi_tl(cpu_gpr_d[r1], cpu_gpr_d[15], + sign_extend(const16, 3)); + break; + case OPC1_16_SRC_ADD_A: + r1 = MASK_OP_SRC_S1D(ctx->opcode); + const16 = sign_extend(MASK_OP_SRC_CONST4(ctx->opcode), 3); + tcg_gen_addi_tl(cpu_gpr_a[r1], cpu_gpr_a[r1], const16); + break; + case OPC1_16_SRC_CADD: + r1 = MASK_OP_SRC_S1D(ctx->opcode); + const16 = sign_extend(MASK_OP_SRC_CONST4(ctx->opcode), 3); + gen_condi_add(TCG_COND_EQ, cpu_gpr_d[r1], const16, cpu_gpr_d[r1], + cpu_gpr_d[15]); + break; + case OPC1_16_SRC_CADDN: + r1 = MASK_OP_SRC_S1D(ctx->opcode); + const16 = sign_extend(MASK_OP_SRC_CONST4(ctx->opcode), 3); + gen_condi_add(TCG_COND_NE, cpu_gpr_d[r1], const16, cpu_gpr_d[r1], + cpu_gpr_d[15]); + break; + case OPC1_16_SRC_CMOV: + r1 = MASK_OP_SRC_S1D(ctx->opcode); + const16 = sign_extend(MASK_OP_SRC_CONST4(ctx->opcode), 3); + gen_condi_mov(TCG_COND_EQ, cpu_gpr_d[r1], const16, cpu_gpr_d[r1], + cpu_gpr_d[15]); + break; + case OPC1_16_SRC_CMOVN: + r1 = MASK_OP_SRC_S1D(ctx->opcode); + const16 = sign_extend(MASK_OP_SRC_CONST4(ctx->opcode), 3); + gen_condi_mov(TCG_COND_NE, cpu_gpr_d[r1], const16, cpu_gpr_d[r1], + cpu_gpr_d[15]); + break; + case OPC1_16_SRC_EQ: + r1 = MASK_OP_SRC_S1D(ctx->opcode); + const16 = sign_extend(MASK_OP_SRC_CONST4(ctx->opcode), 3); + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr_d[15], cpu_gpr_d[r1], + const16); + break; + case OPC1_16_SRC_LT: + r1 = MASK_OP_SRC_S1D(ctx->opcode); + const16 = sign_extend(MASK_OP_SRC_CONST4(ctx->opcode), 3); + tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr_d[15], cpu_gpr_d[r1], + const16); + break; + case OPC1_16_SRC_MOV: + r1 = MASK_OP_SRC_S1D(ctx->opcode); + const16 = MASK_OP_SRC_CONST4(ctx->opcode); + tcg_gen_movi_tl(cpu_gpr_d[r1], const16); + break; + case OPC1_16_SRC_MOV_A: + r1 = MASK_OP_SRC_S1D(ctx->opcode); + const16 = MASK_OP_SRC_CONST4(ctx->opcode); + tcg_gen_movi_tl(cpu_gpr_a[r1], const16); + break; + case OPC1_16_SRC_SH: + const16 = sign_extend(MASK_OP_SRC_CONST4(ctx->opcode), 3); + r1 = MASK_OP_SRC_S1D(ctx->opcode); + gen_shi(cpu_gpr_d[r1], cpu_gpr_d[r1], const16); + break; + case OPC1_16_SRC_SHA: + r1 = MASK_OP_SRC_S1D(ctx->opcode); + const16 = MASK_OP_SRC_CONST4(ctx->opcode); + /* FIXME: const too long */ + gen_shaci(cpu_gpr_d[r1], cpu_gpr_d[r1], const16 & 0x1f); + break; + } } static void decode_32Bit_opc(CPUTRICOREState *env, DisasContext *ctx) -- 2.0.1