From patchwork Mon Aug 4 17:38:52 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bastian Koppelmann X-Patchwork-Id: 376372 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 2ACF014008F for ; Tue, 5 Aug 2014 02:38:47 +1000 (EST) Received: from localhost ([::1]:53502 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XELHZ-0003nT-4b for incoming@patchwork.ozlabs.org; Mon, 04 Aug 2014 12:38:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60122) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XELEP-000731-12 for qemu-devel@nongnu.org; Mon, 04 Aug 2014 12:35:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XELEG-0002Ib-OM for qemu-devel@nongnu.org; Mon, 04 Aug 2014 12:35:28 -0400 Received: from mail.uni-paderborn.de ([131.234.142.9]:19300) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XELEG-0002IP-ED for qemu-devel@nongnu.org; Mon, 04 Aug 2014 12:35:20 -0400 From: Bastian Koppelmann To: qemu-devel@nongnu.org Date: Mon, 4 Aug 2014 18:38:52 +0100 Message-Id: <1407173932-969-16-git-send-email-kbastian@mail.uni-paderborn.de> X-Mailer: git-send-email 2.0.4 In-Reply-To: <1407173932-969-1-git-send-email-kbastian@mail.uni-paderborn.de> References: <1407173932-969-1-git-send-email-kbastian@mail.uni-paderborn.de> X-IMT-Spam-Score: 0.0 () X-PMX-Version: 6.1.1.2430161, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2014.8.4.162721 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 v3 15/15] target-tricore: Add instructions of SR 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 SR opcode format. Add micro-op generator functions for saturate. Add helper return from exception (rfe). Signed-off-by: Bastian Koppelmann --- v2 -> v3: - Fix CDC.COUNT calculation in cdc_zero. - helper_ret now uses psw_write. - Add missing temp_free to gen_saturate. - RSUB: replace tcg_gen_subfi_tl with tcg_gen_net_tl. target-tricore/helper.h | 1 + target-tricore/op_helper.c | 52 +++++++++++++++++++++ target-tricore/translate.c | 110 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+) -- 2.0.4 diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 3c73234..7b7d74b 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -22,3 +22,4 @@ DEF_HELPER_3(sub_ssov, i32, env, i32, i32) DEF_HELPER_2(call, void, env, 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 a4a6802..d0ca92a 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -95,6 +95,21 @@ static int cdc_decrement(target_ulong *psw) return 0; } +static bool cdc_zero(target_ulong *psw) +{ + int cdc = *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 */ + int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); + int mask = (1u << (7 - lo)) - 1; + int count = *psw & mask; + return count == 0; +} + static void save_context_upper(CPUTRICOREState *env, int ea, target_ulong *new_FCX) { @@ -298,6 +313,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->PCXI & 0xfffff) == 0) { + /* raise csu trap */ + } + /* if (PCXI.UL == 0) then trap(CTYP); */ + if ((env->PCXI & MASK_PCXI_UL) == 0) { + /* raise CTYP trap */ + } + /* if (!cdc_zero() AND PSW.CDE) then trap(NEST); */ + if (!cdc_zero(&(env->PSW)) && (env->PSW & MASK_PSW_CDE)) { + /* raise MNG trap */ + } + /* ICR.IE = PCXI.PIE; */ + env->ICR = (env->ICR & ~MASK_ICR_IE) + ((env->PCXI & MASK_PCXI_PIE) >> 15); + /* ICR.CCPN = PCXI.PCPN; */ + env->ICR = (env->ICR & ~MASK_ICR_CCPN) + + ((env->PCXI & MASK_PCXI_PCPN) >> 24); + /*EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0};*/ + ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + + ((env->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_upper(env, ea, &new_PCXI, &new_PSW); + /* FCX[19: 0] = PCXI[19: 0]; */ + env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); + /* PCXI = new_PCXI; */ + env->PCXI = new_PCXI; + /* write psw */ + psw_write(env, new_PSW); +} + 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 1ff0bbf..1e251da 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -201,6 +201,29 @@ static inline void gen_mul_i32s(TCGv ret, TCGv r1, TCGv r2) gen_calc_psw_sav_i32(cpu_PSW_SAV, cpu_PSW_AV); } +static void gen_saturate(TCGv ret, TCGv arg, int32_t up, int32_t low) +{ + TCGv sat_neg = tcg_const_i32(low); + TCGv temp = tcg_const_i32(up); + + /* sat_neg = (arg < low ) ? low : arg; */ + tcg_gen_movcond_tl(TCG_COND_LT, sat_neg, arg, sat_neg, arg, sat_neg); + + /* ret = (sat_neg > up ) ? up : sat_neg; */ + tcg_gen_movcond_tl(TCG_COND_GT, ret, sat_neg, temp, temp, sat_neg); + + tcg_temp_free(sat_neg); + tcg_temp_free(temp); +} + +static void gen_saturate_u(TCGv ret, TCGv arg, int32_t up) +{ + TCGv temp = tcg_const_i32(up); + /* sat_neg = (arg > up ) ? up : arg; */ + tcg_gen_movcond_tl(TCG_COND_GTU, ret, arg, temp, temp, arg); + tcg_temp_free(temp); +} + #define OP_COND(insn)\ static inline void gen_cond_##insn(int cond, TCGv r1, TCGv r2, TCGv r3, \ TCGv r4) \ @@ -450,6 +473,15 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1, case OPC1_16_SBR_LOOP: gen_loop(ctx, r1, offset * 2 - 32); break; +/* SR-format jumps */ + case OPC1_16_SR_JI: + tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], 0xfffffffe); + 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); } @@ -766,6 +798,66 @@ static void decode_sro_opc(DisasContext *ctx, int op1) } } +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: + 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); + tcg_gen_exit_tb(0); + ctx->bstate = BS_BRANCH; + break; + case OPC2_16_SR_DEBUG: + /* raise EXCP_DEBUG */ + break; + } +} + +static void decode_sr_accu(CPUTRICOREState *env, DisasContext *ctx) +{ + uint32_t op2; + uint32_t r1; + TCGv temp, t0, t1; + + r1 = MASK_OP_SR_S1D(ctx->opcode); + op2 = MASK_OP_SR_OP2(ctx->opcode); + + switch (op2) { + case OPC2_16_SR_RSUB: + /* overflow only if r1 = -0x80000000 */ + temp = tcg_const_i32(-0x80000000); + t0 = tcg_const_i32(0); + t1 = tcg_const_i32(1); + tcg_gen_movcond_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r1], temp, t1, t0); + tcg_gen_movcond_tl(TCG_COND_EQ, cpu_PSW_SV, cpu_gpr_d[r1], temp, + t1, cpu_PSW_SV); + tcg_gen_neg_tl(cpu_gpr_d[r1], cpu_gpr_d[r1]); + tcg_temp_free(temp); + tcg_temp_free(t0); + tcg_temp_free(t1); + 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; + } +} + static void decode_16Bit_opc(CPUTRICOREState *env, DisasContext *ctx) { int op1; @@ -952,6 +1044,24 @@ static void decode_16Bit_opc(CPUTRICOREState *env, DisasContext *ctx) const16 = MASK_OP_SSRO_OFF4(ctx->opcode); gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[15], const16 * 4, MO_LESL); break; +/* SR-format */ + case OPCM_16_SR_SYSTEM: + decode_sr_system(env, ctx); + break; + case OPCM_16_SR_ACCU: + decode_sr_accu(env, ctx); + break; + 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_SR_NOT: + if (MASK_OP_SR_OP2(ctx->opcode) == 0x0) { + break; + } + r1 = MASK_OP_SR_S1D(ctx->opcode); + tcg_gen_not_tl(cpu_gpr_d[r1], cpu_gpr_d[r1]); + break; } }