From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47545) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X4CRC-0004Rl-Cc for qemu-devel@nongnu.org; Mon, 07 Jul 2014 13:10:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X4CR7-0005Zy-1Q for qemu-devel@nongnu.org; Mon, 07 Jul 2014 13:10:46 -0400 Received: from mail.uni-paderborn.de ([131.234.142.9]:38362) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X4CR6-0005ZS-LG for qemu-devel@nongnu.org; Mon, 07 Jul 2014 13:10:40 -0400 From: Bastian Koppelmann Date: Mon, 7 Jul 2014 19:13:42 +0100 Message-Id: <1404756822-3253-16-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 15/15] target-tricore: Add instructions of SR 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 SR opcode format. Add micro-op generator functions for saturate and rsubi. Add helper return from exception (rfe). Signed-off-by: Bastian Koppelmann --- target-tricore/helper.h | 1 + target-tricore/op_helper.c | 58 ++++++++++++++++++ target-tricore/translate.c | 144 +++++++++++++++++++++++++++++++++++++-------- 3 files changed, 180 insertions(+), 23 deletions(-) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 8d70784..3595e38 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -22,3 +22,4 @@ DEF_HELPER_3(shac, i32, env, i32, i32) DEF_HELPER_3(call, void, env, i32, i32) DEF_HELPER_1(ret, void, env) DEF_HELPER_2(bisr, void, env, i32) +DEF_HELPER_1(rfe, void, env) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 499697b..dc7b9b5 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -75,6 +75,27 @@ static int cdc_decrement(TCState *tc) return 0; } +static bool cdc_zero(TCState *tc) +{ + int i; + int cdc = tc->PSW & MASK_PSW_CDC; + /* Returns TRUE if PSW.CDC.COUNT == 0 or if PSW.CDC == + 7'b1111111, otherwise returns FALSE. */ + if (cdc == 0x7f) { + return true; + } + /* find CDC.COUNT */ + for (i = 7; i > 0; i--) { + if ((cdc & (1 << i)) == 0) { + if ((cdc & ~(0x7f << i)) == 0) { + return true; + } + } + } + + return false; +} + static void save_context(CPUTRICOREState *env, int ea, int ul, target_ulong *new_FCX) { @@ -288,6 +309,43 @@ void helper_bisr(CPUTRICOREState *env, uint32_t const9) } } +void helper_rfe(CPUTRICOREState *env) +{ + target_ulong ea; + target_ulong new_PCXI; + target_ulong new_PSW; + /* 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"); + } + /* if (!cdc_zero() AND PSW.CDE) then trap(NEST); */ + if (!cdc_zero(&env->active_tc) && (env->active_tc.PSW & MASK_PSW_CDE)) { + printf("MNG trap\n"); + } + /* ICR.IE = PCXI.PIE; */ + env->active_tc.ICR = (env->active_tc.ICR & ~MASK_ICR_IE) + + ((env->active_tc.PCXI & MASK_PCXI_PIE) >> 15); + /* ICR.CCPN = PCXI.PCPN; */ + env->active_tc.ICR = (env->active_tc.ICR & ~MASK_ICR_CCPN) + + ((env->active_tc.PCXI & MASK_PCXI_PCPN) >> 24); + /*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, 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 628bd8b..44b9af6 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -156,6 +156,38 @@ OP_MEM_INDIRECT(st32) /* Functions for arithmetic instructions */ +static void gen_saturate(TCGv ret, TCGv arg, int32_t up, int32_t low) +{ + TCGv sat_neg = tcg_const_i32(low); + int l1 = gen_new_label(); + int l2 = gen_new_label(); + + /* sat_neg = (arg < low ) ? low : arg; */ + tcg_gen_brcondi_tl(TCG_COND_LT, arg, low, l1); + tcg_gen_mov_tl(sat_neg, arg); + gen_set_label(l1); + + /* ret = (sat_neg > up ) ? up : sat_neg; */ + tcg_gen_movi_tl(ret, up); + tcg_gen_brcondi_tl(TCG_COND_GT, sat_neg, up, l2); + tcg_gen_mov_tl(ret, sat_neg); + gen_set_label(l2); + + tcg_temp_free(sat_neg); +} + +static void gen_saturate_u(TCGv ret, TCGv arg, int32_t up) +{ + int l1 = gen_new_label(); + + /* sat_neg = (arg > up ) ? up : arg; */ + tcg_gen_movi_tl(ret, up); + tcg_gen_brcondi_tl(TCG_COND_GTU, arg, up, l1); + tcg_gen_mov_tl(ret, arg); + gen_set_label(l1); + +} + #define OP_COND(insn)\ static inline void gen_cond_##insn(int cond, TCGv r1, TCGv r2, TCGv r3, \ TCGv r4) \ @@ -205,6 +237,14 @@ static inline void gen_condi_mov(int cond, TCGv r1, int32_t r2, TCGv r3, OP_COND(add) OP_COND(sub) +static void gen_rsubi(TCGv ret, int32_t cons, TCGv r2) +{ + TCGv temp = tcg_temp_new(); + tcg_gen_movi_tl(temp, cons); + tcg_gen_sub_tl(ret, temp, r2); + tcg_temp_free(temp); +} + static void gen_sh(TCGv ret, TCGv r1, TCGv r2) { int label, label2; @@ -384,6 +424,15 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, case OPC1_16_SBR_LOOP: gen_loop(ctx, r1, 0xffffffe0+(offset<<1)); break; +/* SR-format jumps */ + case OPC1_16_SR_JI: + tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], 0xffffffff); + tcg_gen_exit_tb(0); + break; + case OPC2_16_SR_RET: + gen_helper_ret(cpu_env); + tcg_gen_exit_tb(0); + break; default: printf("Branch Error at %x\n", ctx->pc); } @@ -393,6 +442,63 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, /* * Functions for decoding instructions */ + +static void decode_sr_system(CPUTRICOREState *env, DisasContext *ctx) +{ + uint32_t op2; + op2 = MASK_OP_SR_OP2(ctx->opcode); + + switch (op2) { + case OPC2_16_SR_NOP: + printf("NOP Instruction at %08x\n", ctx->pc); + ctx->bstate = BS_STOP; + break; + case OPC2_16_SR_RET: + gen_compute_branch(ctx, op2, 0, 0, 0, 0); + break; + case OPC2_16_SR_RFE: + gen_helper_rfe(cpu_env); + break; + case OPC2_16_SR_DEBUG: + printf("DEBUG Instruction at %08x\n", ctx->pc); + ctx->bstate = BS_STOP; + break; + default: + printf("default sr_system Instruction at %08x\n", ctx->pc); + } +} + +static void decode_sr_accu(CPUTRICOREState *env, DisasContext *ctx) +{ + uint32_t op2; + uint32_t r1; + + r1 = MASK_OP_SR_S1D(ctx->opcode); + op2 = MASK_OP_SR_OP2(ctx->opcode); + + switch (op2) { + + case OPC2_16_SR_RSUB: + gen_rsubi(cpu_gpr_d[r1], 0, cpu_gpr_d[r1]); + break; + case OPC2_16_SR_SAT_B: + gen_saturate(cpu_gpr_d[r1], cpu_gpr_d[r1], 0x7f, -0x80); + break; + case OPC2_16_SR_SAT_BU: + gen_saturate_u(cpu_gpr_d[r1], cpu_gpr_d[r1], 0xff); + break; + case OPC2_16_SR_SAT_H: + gen_saturate(cpu_gpr_d[r1], cpu_gpr_d[r1], 0x7fff, -0x8000); + break; + case OPC2_16_SR_SAT_HU: + gen_saturate_u(cpu_gpr_d[r1], cpu_gpr_d[r1], 0xffff); + break; + default: + printf("default sr_accu Instruction at %08x\n", ctx->pc); + break; + } +} + static void decode_16Bit_opc(CPUTRICOREState *env, DisasContext *ctx) { target_ulong op1; @@ -905,32 +1011,24 @@ static void decode_16Bit_opc(CPUTRICOREState *env, DisasContext *ctx) const16 = MASK_OP_SSRO_OFF4(ctx->opcode); gen_indirect_st32(ctx, cpu_gpr_d[r1], cpu_gpr_a[15], const16 * 4); break; -/* SSRO-format */ - case OPC1_16_SSRO_ST_A: - r1 = MASK_OP_SSRO_S1(ctx->opcode); - const16 = MASK_OP_SSRO_OFF4(ctx->opcode); - gen_indirect_st32(ctx, cpu_gpr_a[r1], cpu_gpr_a[15], const16 * 4); +/* SR-format */ + case OPCM_16_SR_SYSTEM: + decode_sr_system(env, ctx); break; - case OPC1_16_SSRO_ST_B: - r1 = MASK_OP_SSRO_S1(ctx->opcode); - const16 = MASK_OP_SSRO_OFF4(ctx->opcode); - temp = tcg_temp_new(); - tcg_gen_andi_tl(temp, cpu_gpr_d[r1], 0xff); - gen_indirect_st8(ctx, temp, cpu_gpr_a[15], const16); - tcg_temp_free(temp); + case OPCM_16_SR_ACCU: + decode_sr_accu(env, ctx); break; - case OPC1_16_SSRO_ST_H: - r1 = MASK_OP_SSRO_S1(ctx->opcode); - const16 = MASK_OP_SSRO_OFF4(ctx->opcode); - temp = tcg_temp_new(); - tcg_gen_andi_tl(temp, cpu_gpr_d[r1], 0xffff); - gen_indirect_st16(ctx, temp, cpu_gpr_a[15], const16 * 2); - tcg_temp_free(temp); + case OPC1_16_SR_JI: + r1 = MASK_OP_SR_S1D(ctx->opcode); + gen_compute_branch(ctx, op1, r1, 0, 0, 0); break; - case OPC1_16_SSRO_ST_W: - r1 = MASK_OP_SSRO_S1(ctx->opcode); - const16 = MASK_OP_SSRO_OFF4(ctx->opcode); - gen_indirect_st32(ctx, cpu_gpr_d[r1], cpu_gpr_a[15], const16 * 4); + case OPC1_16_SR_NOT: + if (MASK_OP_SR_OP2(ctx->opcode) == 0x0) { + printf("Wrong OP2 at at %08x\n", ctx->pc); + break; + } + r1 = MASK_OP_SR_S1D(ctx->opcode); + tcg_gen_not_tl(cpu_gpr_d[r1], cpu_gpr_d[r1]); break; } } -- 2.0.1