From patchwork Sat Sep 27 14:58:08 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bastian Koppelmann X-Patchwork-Id: 394068 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 30B1C140119 for ; Sun, 28 Sep 2014 00:01:42 +1000 (EST) Received: from localhost ([::1]:55940 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XXsZ9-0006sc-Od for incoming@patchwork.ozlabs.org; Sat, 27 Sep 2014 10:01:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40981) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XXsWa-0002Ql-5O for qemu-devel@nongnu.org; Sat, 27 Sep 2014 09:59:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XXsWO-0001Qo-49 for qemu-devel@nongnu.org; Sat, 27 Sep 2014 09:59:00 -0400 Received: from mail.uni-paderborn.de ([131.234.142.9]:39108) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XXsWN-0001IT-Ik for qemu-devel@nongnu.org; Sat, 27 Sep 2014 09:58:47 -0400 From: Bastian Koppelmann To: qemu-devel@nongnu.org Date: Sat, 27 Sep 2014 15:58:08 +0100 Message-Id: <1411829891-24866-3-git-send-email-kbastian@mail.uni-paderborn.de> X-Mailer: git-send-email 2.1.1 In-Reply-To: <1411829891-24866-1-git-send-email-kbastian@mail.uni-paderborn.de> References: <1411829891-24866-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.9.27.134522 X-IMT-Authenticated-Sender: uid=kbastian,ou=People,o=upb,c=de X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 131.234.142.9 Cc: peter.maydell@linaro.org, rth@twiddle.net Subject: [Qemu-devel] [PATCH 2/5] target-tricore: Add instructions of ABS, ABSB 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 ABS, ABSB opcode format. Add microcode generator functions for ld/st of two 32bit reg as one 64bit value. Add microcode generator functions for ldmst and swap. Add helper ldlcx, lducx, stlcx and stucx. Signed-off-by: Bastian Koppelmann --- target-tricore/helper.h | 4 + target-tricore/op_helper.c | 45 +++++++ target-tricore/translate.c | 303 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 352 insertions(+) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 7b7d74b..fbabbd5 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -23,3 +23,7 @@ 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) +DEF_HELPER_2(ldlcx, void, env, i32) +DEF_HELPER_2(lducx, void, env, i32) +DEF_HELPER_2(stlcx, void, env, i32) +DEF_HELPER_2(stucx, void, env, i32) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index f2a5cbc..7a33afd 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -175,6 +175,27 @@ static void restore_context_upper(CPUTriCoreState *env, int ea, env->gpr_d[15] = cpu_ldl_data(env, ea+60); } +static void restore_context_lower(CPUTriCoreState *env, int ea, + target_ulong *ra, target_ulong *pcxi) +{ + *pcxi = cpu_ldl_data(env, ea); + *ra = cpu_ldl_data(env, ea+4); + env->gpr_a[2] = cpu_ldl_data(env, ea+8); + env->gpr_a[3] = cpu_ldl_data(env, ea+12); + env->gpr_d[0] = cpu_ldl_data(env, ea+16); + env->gpr_d[1] = cpu_ldl_data(env, ea+20); + env->gpr_d[2] = cpu_ldl_data(env, ea+24); + env->gpr_d[3] = cpu_ldl_data(env, ea+28); + env->gpr_a[4] = cpu_ldl_data(env, ea+32); + env->gpr_a[5] = cpu_ldl_data(env, ea+36); + env->gpr_a[6] = cpu_ldl_data(env, ea+40); + env->gpr_a[7] = cpu_ldl_data(env, ea+44); + env->gpr_d[4] = cpu_ldl_data(env, ea+48); + env->gpr_d[5] = cpu_ldl_data(env, ea+52); + env->gpr_d[6] = cpu_ldl_data(env, ea+56); + env->gpr_d[7] = cpu_ldl_data(env, ea+60); +} + void helper_call(CPUTriCoreState *env, uint32_t next_pc) { target_ulong tmp_FCX; @@ -356,6 +377,30 @@ void helper_rfe(CPUTriCoreState *env) psw_write(env, new_PSW); } +void helper_ldlcx(CPUTriCoreState *env, uint32_t ea) +{ + uint32_t dummy; + /* insn doesn't load PCXI and RA */ + restore_context_lower(env, ea, &dummy, &dummy); +} + +void helper_lducx(CPUTriCoreState *env, uint32_t ea) +{ + uint32_t dummy; + /* insn doesn't load PCXI and PSW */ + restore_context_upper(env, ea, &dummy, &dummy); +} + +void helper_stlcx(CPUTriCoreState *env, uint32_t ea) +{ + save_context_lower(env, ea); +} + +void helper_stucx(CPUTriCoreState *env, uint32_t ea) +{ + save_context_upper(env, ea); +} + 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 4f654de..3ec5ca7 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -115,6 +115,8 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f, tcg_temp_free_i32(helper_tmp); \ } while (0) +#define EA_ABS_FORMAT(con) (((con & 0x3C000) << 14) + (con & 0x3FFF)) + /* Functions for load/save to/from memory */ static inline void gen_offset_ld(DisasContext *ctx, TCGv r1, TCGv r2, @@ -135,6 +137,64 @@ static inline void gen_offset_st(DisasContext *ctx, TCGv r1, TCGv r2, tcg_temp_free(temp); } +static void gen_st_2regs_64(TCGv rh, TCGv rl, TCGv address, DisasContext *ctx) +{ + TCGv_i64 temp = tcg_temp_new_i64(); + + tcg_gen_concat_i32_i64(temp, rl, rh); + tcg_gen_qemu_st_i64(temp, address, ctx->mem_idx, MO_LEQ); + + tcg_temp_free_i64(temp); +} + +static void gen_ld_2regs_64(TCGv rh, TCGv rl, TCGv address, DisasContext *ctx) +{ + TCGv_i64 temp = tcg_temp_new_i64(); + + tcg_gen_qemu_ld_i64(temp, address, ctx->mem_idx, MO_LEQ); + /* write back to two 32 bit regs */ + tcg_gen_trunc_i64_i32(rl, temp); + tcg_gen_shri_i64(temp, temp, 32); + tcg_gen_trunc_i64_i32(rh, temp); + + tcg_temp_free_i64(temp); +} + +/* M(EA, word) = (M(EA, word) & ~E[a][63:32]) | (E[a][31:0] & E[a][63:32]); */ +static void gen_ldmst(DisasContext *ctx, int ereg, TCGv ea) +{ + TCGv temp = tcg_temp_new(); + TCGv temp2 = tcg_temp_new(); + + /* temp = (M(EA, word) */ + tcg_gen_qemu_ld_tl(temp, ea, ctx->mem_idx, MO_LEUL); + /* temp = temp & ~E[a][63:32]) */ + tcg_gen_andc_tl(temp, temp, cpu_gpr_d[ereg+1]); + /* temp2 = (E[a][31:0] & E[a][63:32]); */ + tcg_gen_and_tl(temp2, cpu_gpr_d[ereg], cpu_gpr_d[ereg+1]); + /* temp = temp | temp2; */ + tcg_gen_or_tl(temp, temp, temp2); + /* M(EA, word) = temp; */ + tcg_gen_qemu_st_tl(temp, ea, ctx->mem_idx, MO_LEUL); + + tcg_temp_free(temp); + tcg_temp_free(temp2); +} + +/* tmp = M(EA, word); + M(EA, word) = D[a]; + D[a] = tmp[31:0];*/ +static void gen_swap(DisasContext *ctx, int reg, TCGv ea) +{ + TCGv temp = tcg_temp_new(); + + tcg_gen_qemu_ld_tl(temp, ea, ctx->mem_idx, MO_LEUL); + tcg_gen_qemu_st_tl(cpu_gpr_d[reg], ea, ctx->mem_idx, MO_LEUL); + tcg_gen_mov_tl(cpu_gpr_d[reg], temp); + + tcg_temp_free(temp); +} + /* Functions for arithmetic instructions */ static inline void gen_add_d(TCGv ret, TCGv r1, TCGv r2) @@ -1099,8 +1159,251 @@ static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx) } } +/* + * 32 bit instructions + */ + +/* ABS-format */ +static void decode_abs_ldw(CPUTriCoreState *env, DisasContext *ctx) +{ + int32_t op2; + int32_t r1; + uint32_t address; + TCGv temp; + + r1 = MASK_OP_ABS_S1D(ctx->opcode); + address = MASK_OP_ABS_OFF18(ctx->opcode); + op2 = MASK_OP_ABS_OP2(ctx->opcode); + + temp = tcg_const_i32(EA_ABS_FORMAT(address)); + + switch (op2) { + case OPC2_32_ABS_LD_A: + tcg_gen_qemu_ld_tl(cpu_gpr_a[r1], temp, ctx->mem_idx, MO_LESL); + break; + case OPC2_32_ABS_LD_D: + gen_ld_2regs_64(cpu_gpr_d[r1+1], cpu_gpr_d[r1], temp, ctx); + break; + case OPC2_32_ABS_LD_DA: + gen_ld_2regs_64(cpu_gpr_a[r1+1], cpu_gpr_a[r1], temp, ctx); + break; + case OPC2_32_ABS_LD_W: + tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LESL); + break; + } + + tcg_temp_free(temp); +} + +static void decode_abs_ldb(CPUTriCoreState *env, DisasContext *ctx) +{ + int32_t op2; + int32_t r1; + uint32_t address; + TCGv temp; + + r1 = MASK_OP_ABS_S1D(ctx->opcode); + address = MASK_OP_ABS_OFF18(ctx->opcode); + op2 = MASK_OP_ABS_OP2(ctx->opcode); + + temp = tcg_const_i32(EA_ABS_FORMAT(address)); + + switch (op2) { + case OPC2_32_ABS_LD_B: + tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_SB); + break; + case OPC2_32_ABS_LD_BU: + tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_UB); + break; + case OPC2_32_ABS_LD_H: + tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LESW); + break; + case OPC2_32_ABS_LD_HU: + tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LEUW); + break; + } + + tcg_temp_free(temp); +} + +static void decode_abs_ldst_swap(CPUTriCoreState *env, DisasContext *ctx) +{ + int32_t op2; + int32_t r1; + uint32_t address; + TCGv temp; + + r1 = MASK_OP_ABS_S1D(ctx->opcode); + address = MASK_OP_ABS_OFF18(ctx->opcode); + op2 = MASK_OP_ABS_OP2(ctx->opcode); + + temp = tcg_const_i32(EA_ABS_FORMAT(address)); + + switch (op2) { + case OPC2_32_ABS_LDMST: + gen_ldmst(ctx, r1, temp); + break; + case OPC2_32_ABS_SWAP_W: + gen_swap(ctx, r1, temp); + break; + } + + tcg_temp_free(temp); +} + +static void decode_abs_ldst_context(CPUTriCoreState *env, DisasContext *ctx) +{ + uint32_t op2; + int32_t off18; + + off18 = MASK_OP_ABS_OFF18(ctx->opcode); + op2 = MASK_OP_ABS_OP2(ctx->opcode); + + switch (op2) { + case OPC2_32_ABS_LDLCX: + gen_helper_1arg(ldlcx, EA_ABS_FORMAT(off18)); + break; + case OPC2_32_ABS_LDUCX: + gen_helper_1arg(lducx, EA_ABS_FORMAT(off18)); + break; + case OPC2_32_ABS_STLCX: + gen_helper_1arg(stlcx, EA_ABS_FORMAT(off18)); + break; + case OPC2_32_ABS_STUCX: + gen_helper_1arg(stucx, EA_ABS_FORMAT(off18)); + break; + } +} + +static void decode_abs_store(CPUTriCoreState *env, DisasContext *ctx) +{ + int32_t op2; + int32_t r1; + uint32_t address; + TCGv temp; + + r1 = MASK_OP_ABS_S1D(ctx->opcode); + address = MASK_OP_ABS_OFF18(ctx->opcode); + op2 = MASK_OP_ABS_OP2(ctx->opcode); + + temp = tcg_const_i32(EA_ABS_FORMAT(address)); + + switch (op2) { + case OPC2_32_ABS_ST_A: + tcg_gen_qemu_st_tl(cpu_gpr_a[r1], temp, ctx->mem_idx, MO_LESL); + break; + case OPC2_32_ABS_ST_D: + gen_st_2regs_64(cpu_gpr_d[r1+1], cpu_gpr_d[r1], temp, ctx); + break; + case OPC2_32_ABS_ST_DA: + gen_st_2regs_64(cpu_gpr_a[r1+1], cpu_gpr_a[r1], temp, ctx); + break; + case OPC2_32_ABS_ST_W: + tcg_gen_qemu_st_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LESL); + break; + + } + tcg_temp_free(temp); +} + +static void decode_abs_storeb_h(CPUTriCoreState *env, DisasContext *ctx) +{ + int32_t op2; + int32_t r1; + uint32_t address; + TCGv temp; + + r1 = MASK_OP_ABS_S1D(ctx->opcode); + address = MASK_OP_ABS_OFF18(ctx->opcode); + op2 = MASK_OP_ABS_OP2(ctx->opcode); + + temp = tcg_const_i32(EA_ABS_FORMAT(address)); + + switch (op2) { + case OPC2_32_ABS_ST_B: + tcg_gen_qemu_st_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_UB); + break; + case OPC2_32_ABS_ST_H: + tcg_gen_qemu_st_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LEUW); + break; + } + tcg_temp_free(temp); +} + static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) { + int op1; + int32_t r1; + int32_t address; + TCGv temp, temp2; + + op1 = MASK_OP_MAJOR(ctx->opcode); + + switch (op1) { +/* ABS-format */ + case OPCM_32_ABS_LDW: + decode_abs_ldw(env, ctx); + break; + case OPCM_32_ABS_LDB: + decode_abs_ldb(env, ctx); + break; + case OPCM_32_ABS_LDMST_SWAP: + decode_abs_ldst_swap(env, ctx); + break; + case OPCM_32_ABS_LDST_CONTEXT: + decode_abs_ldst_context(env, ctx); + break; + case OPCM_32_ABS_STORE: + decode_abs_store(env, ctx); + break; + case OPCM_32_ABS_STOREB_H: + decode_abs_storeb_h(env, ctx); + break; + case OPC1_32_ABS_STOREQ: + address = MASK_OP_ABS_OFF18(ctx->opcode); + r1 = MASK_OP_ABS_S1D(ctx->opcode); + temp = tcg_const_i32(EA_ABS_FORMAT(address)); + temp2 = tcg_temp_new(); + + tcg_gen_shri_tl(temp2, cpu_gpr_d[r1], 16); + tcg_gen_qemu_st_tl(temp2, temp, ctx->mem_idx, MO_LEUW); + + tcg_temp_free(temp2); + tcg_temp_free(temp); + break; + case OPC1_32_ABS_LD_Q: + address = MASK_OP_ABS_OFF18(ctx->opcode); + r1 = MASK_OP_ABS_S1D(ctx->opcode); + temp = tcg_const_i32(EA_ABS_FORMAT(address)); + + tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LEUW); + tcg_gen_shli_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], 16); + + tcg_temp_free(temp); + break; + case OPC1_32_ABS_LEA: + address = MASK_OP_ABS_OFF18(ctx->opcode); + r1 = MASK_OP_ABS_S1D(ctx->opcode); + tcg_gen_movi_tl(cpu_gpr_a[r1], EA_ABS_FORMAT(address)); + break; +/* ABSB-format */ + case OPC1_32_ABSB_ST_T: + address = MASK_OP_ABS_OFF18(ctx->opcode); + int8_t b = MASK_OP_ABSB_B(ctx->opcode); + int32_t bpos = MASK_OP_ABSB_BPOS(ctx->opcode); + + temp = tcg_const_i32(EA_ABS_FORMAT(address)); + temp2 = tcg_temp_new(); + + tcg_gen_qemu_ld_tl(temp2, temp, ctx->mem_idx, MO_UB); + tcg_gen_andi_tl(temp2, temp2, ~(0x1u << bpos)); + tcg_gen_ori_tl(temp2, temp2, (b << bpos)); + tcg_gen_qemu_st_tl(temp2, temp, ctx->mem_idx, MO_UB); + + tcg_temp_free(temp); + tcg_temp_free(temp2); + break; + } } static void decode_opc(CPUTriCoreState *env, DisasContext *ctx, int *is_branch)