From patchwork Mon Jul 14 09:55:54 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yongbok Kim X-Patchwork-Id: 369561 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 0B38414007D for ; Mon, 14 Jul 2014 20:02:49 +1000 (EST) Received: from localhost ([::1]:55559 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X6d5r-0004XN-7q for incoming@patchwork.ozlabs.org; Mon, 14 Jul 2014 06:02:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40348) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X6cze-0003Fa-ED for qemu-devel@nongnu.org; Mon, 14 Jul 2014 05:56:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X6czZ-0003eZ-8x for qemu-devel@nongnu.org; Mon, 14 Jul 2014 05:56:22 -0400 Received: from mailapp01.imgtec.com ([195.59.15.196]:6811) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X6czZ-0003eO-0J for qemu-devel@nongnu.org; Mon, 14 Jul 2014 05:56:17 -0400 Received: from KLMAIL01.kl.imgtec.org (unknown [192.168.5.35]) by Websense Email Security Gateway with ESMTPS id 89A013BBD29B7; Mon, 14 Jul 2014 10:56:11 +0100 (IST) Received: from localhost.localdomain (192.168.14.85) by KLMAIL01.kl.imgtec.org (192.168.5.35) with Microsoft SMTP Server (TLS) id 14.3.195.1; Mon, 14 Jul 2014 10:56:13 +0100 From: Yongbok Kim To: Date: Mon, 14 Jul 2014 10:55:54 +0100 Message-ID: <1405331763-57126-12-git-send-email-yongbok.kim@imgtec.com> X-Mailer: git-send-email 1.7.4 In-Reply-To: <1405331763-57126-1-git-send-email-yongbok.kim@imgtec.com> References: <1405331763-57126-1-git-send-email-yongbok.kim@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.14.85] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.59.15.196 Cc: yongbok.kim@imgtec.com, cristian.cuna@imgtec.com, leon.alrae@imgtec.com, aurelien@aurel32.net Subject: [Qemu-devel] [PATCH 11/20] target-mips: add MSA I5 format instructions 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 MSA I5 format instructions: Signed-off-by: Yongbok Kim --- target-mips/helper.h | 12 ++ target-mips/msa_helper.c | 273 ++++++++++++++++++++++++++++++++++++++++++++++ target-mips/translate.c | 91 +++++++++++++++ 3 files changed, 376 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 174bc62..fe0cf48 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -692,11 +692,23 @@ DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) /* MIPS SIMD Architecture */ +DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s64) DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32) +DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s64) +DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, i32) +DEF_HELPER_5(msa_maxi_s_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_maxi_u_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s64) DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32) DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s64) DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 2355809..00b6e77 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -195,6 +195,38 @@ static inline void msa_store_wr_elem(CPUMIPSState *env, uint64_t val, } } +void helper_msa_addvi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, int64_t u5) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = (int64_t) ts + u5; + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +void helper_msa_subvi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, int64_t u5) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = (int64_t) ts - u5; + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + void helper_msa_andi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t i8) { @@ -295,6 +327,120 @@ void helper_msa_bseli_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, } } +static inline int64_t msa_ceq_df(CPUMIPSState *env, uint32_t df, int64_t arg1, + int64_t arg2) +{ + return arg1 == arg2 ? -1 : 0; +} + +void helper_msa_ceqi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, int64_t i5) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_ceq_df(env, df, ts, i5); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_cle_s_df(CPUMIPSState *env, uint32_t df, + int64_t arg1, int64_t arg2) +{ + return arg1 <= arg2 ? -1 : 0; +} + +void helper_msa_clei_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, int64_t s5) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_cle_s_df(env, df, ts, s5); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_cle_u_df(CPUMIPSState *env, uint32_t df, + int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + return u_arg1 <= u_arg2 ? -1 : 0; +} + +void helper_msa_clei_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, int64_t u5) +{ + uint64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_i64(env, ws, df, i); + td = msa_cle_u_df(env, df, ts, u5); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_clt_s_df(CPUMIPSState *env, uint32_t df, + int64_t arg1, int64_t arg2) +{ + return arg1 < arg2 ? -1 : 0; +} + +void helper_msa_clti_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, int64_t s5) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_clt_s_df(env, df, ts, s5); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_clt_u_df(CPUMIPSState *env, uint32_t df, + int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + return u_arg1 < u_arg2 ? -1 : 0; +} + +void helper_msa_clti_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, int64_t u5) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_clt_u_df(env, df, ts, u5); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + #define SHF_POS(i, imm) ((i & 0xfc) + ((imm >> (2 * (i & 0x03))) & 0x03)) static inline void msa_shf_df(CPUMIPSState *env, uint32_t df, void *pwd, @@ -334,3 +480,130 @@ void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, env->active_msa.msamodify |= (1 << wd); } } + +static inline int64_t msa_max_s_df(CPUMIPSState *env, uint32_t df, + int64_t arg1, int64_t arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} + +void helper_msa_maxi_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, int64_t s5) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_max_s_df(env, df, ts, s5); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_max_u_df(CPUMIPSState *env, uint32_t df, + int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + return u_arg1 > u_arg2 ? arg1 : arg2; +} + +void helper_msa_maxi_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, int64_t u5) +{ + uint64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_i64(env, ws, df, i); + td = msa_max_u_df(env, df, ts, u5); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_min_s_df(CPUMIPSState *env, uint32_t df, + int64_t arg1, int64_t arg2) +{ + return arg1 < arg2 ? arg1 : arg2; +} + +void helper_msa_mini_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, int64_t s5) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_min_s_df(env, df, ts, s5); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_min_u_df(CPUMIPSState *env, uint32_t df, + int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + return u_arg1 < u_arg2 ? arg1 : arg2; +} + +void helper_msa_mini_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, int64_t u5) +{ + uint64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_i64(env, ws, df, i); + td = msa_min_u_df(env, df, ts, u5); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t s10) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + int64_t s64 = ((int64_t)s10 << 54) >> 54; + switch (df) { + case DF_BYTE: + ALL_B_ELEMENTS(i, MSA_WRLEN) { + B(pwd, i) = (int8_t)s10; + } DONE_ALL_ELEMENTS; + break; + case DF_HALF: + ALL_H_ELEMENTS(i, MSA_WRLEN) { + H(pwd, i) = (int16_t)s64; + } DONE_ALL_ELEMENTS; + break; + case DF_WORD: + ALL_W_ELEMENTS(i, MSA_WRLEN) { + W(pwd, i) = (int32_t)s64; + } DONE_ALL_ELEMENTS; + break; + case DF_DOUBLE: + ALL_D_ELEMENTS(i, MSA_WRLEN) { + D(pwd, i) = s64; + } DONE_ALL_ELEMENTS; + break; + default: + /* shouldn't get here */ + assert(0); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} diff --git a/target-mips/translate.c b/target-mips/translate.c index c241299..7fde3bb 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -14847,6 +14847,93 @@ static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx) tcg_temp_free_i32(ti8); } +static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23))) + uint32_t opcode = ctx->opcode; + + uint8_t df = (ctx->opcode >> 21) & 0x3 /* df [22:21] */; + int64_t s5 = (ctx->opcode >> 16) & 0x1f /* s5 [20:16] */; + s5 = (s5 << 59) >> 59; /* sign extend s5 to 64 bits*/ + uint8_t u5 = (ctx->opcode >> 16) & 0x1f /* u5 [20:16] */; + uint8_t ws = (ctx->opcode >> 11) & 0x1f /* ws [15:11] */; + uint8_t wd = (ctx->opcode >> 6) & 0x1f /* wd [10:6] */; + + TCGv_i32 tdf = tcg_const_i32(df); + TCGv_i32 twd = tcg_const_i32(wd); + TCGv_i32 tws = tcg_const_i32(ws); + TCGv_i64 tu5 = tcg_const_i64(u5); + TCGv_i64 ts5 = tcg_const_i64(s5); + + switch (MASK_MSA_I5(opcode)) { + case OPC_MSA_ADDVI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, tu5); + break; + case OPC_MSA_SUBVI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, tu5); + break; + case OPC_MSA_MAXI_S_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, ts5); + break; + case OPC_MSA_MAXI_U_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, tu5); + break; + case OPC_MSA_MINI_S_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, ts5); + break; + case OPC_MSA_MINI_U_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, tu5); + break; + case OPC_MSA_CEQI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, ts5); + break; + case OPC_MSA_CLTI_S_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, ts5); + break; + case OPC_MSA_CLTI_U_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, tu5); + break; + case OPC_MSA_CLEI_S_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, ts5); + break; + case OPC_MSA_CLEI_U_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, tu5); + break; + case OPC_MSA_LDI_df: + { + int64_t s10 = (ctx->opcode >> 11) & 0x3ff /* s10 [20:11] */; + s10 = (s10 << 54) >> 54; /* sign extend s10 to 64 bits*/ + + TCGv_i32 ts10 = tcg_const_i32(s10); + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_ldi_df(cpu_env, tdf, twd, ts10); + tcg_temp_free_i32(ts10); + } + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception(ctx, EXCP_RI); + break; + } + + tcg_temp_free_i32(tdf); + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); + tcg_temp_free_i64(tu5); + tcg_temp_free_i64(ts5); +} + static void gen_msa(CPUMIPSState *env, DisasContext *ctx) { uint32_t opcode = ctx->opcode; @@ -14858,6 +14945,10 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx) case OPC_MSA_I8_02: gen_msa_i8(env, ctx); break; + case OPC_MSA_I5_06: + case OPC_MSA_I5_07: + gen_msa_i5(env, ctx); + break; default: MIPS_INVAL("MSA instruction"); generate_exception(ctx, EXCP_RI);