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 <kbast...@mail.uni-paderborn.de> --- 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 <http://www.gnu.org/licenses/>. + */ + +/* 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