From patchwork Mon Nov 3 16:11:40 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Alrae X-Patchwork-Id: 406285 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 AFB4214007F for ; Tue, 4 Nov 2014 03:29:36 +1100 (AEDT) Received: from localhost ([::1]:35861 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XlKVa-00024d-Pl for incoming@patchwork.ozlabs.org; Mon, 03 Nov 2014 11:29:34 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46506) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XlKFO-0004lB-C1 for qemu-devel@nongnu.org; Mon, 03 Nov 2014 11:12:56 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XlKFI-0005co-TU for qemu-devel@nongnu.org; Mon, 03 Nov 2014 11:12:50 -0500 Received: from mailapp01.imgtec.com ([195.59.15.196]:16908) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XlKFI-0005ce-Cc for qemu-devel@nongnu.org; Mon, 03 Nov 2014 11:12:44 -0500 Received: from KLMAIL01.kl.imgtec.org (unknown [192.168.5.35]) by Websense Email Security Gateway with ESMTPS id 6AED423FE1807 for ; Mon, 3 Nov 2014 16:12:39 +0000 (GMT) Received: from virtUbuntuLTP.kl.imgtec.org (192.168.14.163) by KLMAIL01.kl.imgtec.org (192.168.5.35) with Microsoft SMTP Server (TLS) id 14.3.195.1; Mon, 3 Nov 2014 16:12:41 +0000 From: Leon Alrae To: Date: Mon, 3 Nov 2014 16:11:40 +0000 Message-ID: <1415031108-15039-27-git-send-email-leon.alrae@imgtec.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1415031108-15039-1-git-send-email-leon.alrae@imgtec.com> References: <1415031108-15039-1-git-send-email-leon.alrae@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.14.163] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.59.15.196 Cc: Yongbok Kim Subject: [Qemu-devel] [PULL 26/34] target-mips: add MSA BIT 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 From: Yongbok Kim add MSA BIT format instructions Reviewed-by: Leon Alrae Signed-off-by: Yongbok Kim Signed-off-by: Leon Alrae --- target-mips/helper.h | 13 ++++ target-mips/msa_helper.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++ target-mips/translate.c | 88 +++++++++++++++++++++ 3 files changed, 297 insertions(+) diff --git a/target-mips/helper.h b/target-mips/helper.h index 4f03545..2167c4a 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -771,3 +771,16 @@ DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s32) DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s32) DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s32) DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, s32) + +DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bclri_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sat_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srari_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 7b577e7..114008f 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -255,3 +255,199 @@ void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } } + +/* Data format bit position and unsigned values */ +#define BIT_POSITION(x, df) ((uint64_t)(x) % DF_BITS(df)) + +static inline int64_t msa_sll_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + int32_t b_arg2 = BIT_POSITION(arg2, df); + return arg1 << b_arg2; +} + +static inline int64_t msa_sra_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + int32_t b_arg2 = BIT_POSITION(arg2, df); + return arg1 >> b_arg2; +} + +static inline int64_t msa_srl_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + int32_t b_arg2 = BIT_POSITION(arg2, df); + return u_arg1 >> b_arg2; +} + +static inline int64_t msa_bclr_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + int32_t b_arg2 = BIT_POSITION(arg2, df); + return UNSIGNED(arg1 & (~(1LL << b_arg2)), df); +} + +static inline int64_t msa_bset_df(uint32_t df, int64_t arg1, + int64_t arg2) +{ + int32_t b_arg2 = BIT_POSITION(arg2, df); + return UNSIGNED(arg1 | (1LL << b_arg2), df); +} + +static inline int64_t msa_bneg_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + int32_t b_arg2 = BIT_POSITION(arg2, df); + return UNSIGNED(arg1 ^ (1LL << b_arg2), df); +} + +static inline int64_t msa_binsl_df(uint32_t df, int64_t dest, int64_t arg1, + int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_dest = UNSIGNED(dest, df); + int32_t sh_d = BIT_POSITION(arg2, df) + 1; + int32_t sh_a = DF_BITS(df) - sh_d; + if (sh_d == DF_BITS(df)) { + return u_arg1; + } else { + return UNSIGNED(UNSIGNED(u_dest << sh_d, df) >> sh_d, df) | + UNSIGNED(UNSIGNED(u_arg1 >> sh_a, df) << sh_a, df); + } +} + +static inline int64_t msa_binsr_df(uint32_t df, int64_t dest, int64_t arg1, + int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_dest = UNSIGNED(dest, df); + int32_t sh_d = BIT_POSITION(arg2, df) + 1; + int32_t sh_a = DF_BITS(df) - sh_d; + if (sh_d == DF_BITS(df)) { + return u_arg1; + } else { + return UNSIGNED(UNSIGNED(u_dest >> sh_d, df) << sh_d, df) | + UNSIGNED(UNSIGNED(u_arg1 << sh_a, df) >> sh_a, df); + } +} + +static inline int64_t msa_sat_s_df(uint32_t df, int64_t arg, uint32_t m) +{ + return arg < M_MIN_INT(m+1) ? M_MIN_INT(m+1) : + arg > M_MAX_INT(m+1) ? M_MAX_INT(m+1) : + arg; +} + +static inline int64_t msa_sat_u_df(uint32_t df, int64_t arg, uint32_t m) +{ + uint64_t u_arg = UNSIGNED(arg, df); + return u_arg < M_MAX_UINT(m+1) ? u_arg : + M_MAX_UINT(m+1); +} + +static inline int64_t msa_srar_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + int32_t b_arg2 = BIT_POSITION(arg2, df); + if (b_arg2 == 0) { + return arg1; + } else { + int64_t r_bit = (arg1 >> (b_arg2 - 1)) & 1; + return (arg1 >> b_arg2) + r_bit; + } +} + +static inline int64_t msa_srlr_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + int32_t b_arg2 = BIT_POSITION(arg2, df); + if (b_arg2 == 0) { + return u_arg1; + } else { + uint64_t r_bit = (u_arg1 >> (b_arg2 - 1)) & 1; + return (u_arg1 >> b_arg2) + r_bit; + } +} + +#define MSA_BINOP_IMMU_DF(helper, func) \ +void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, uint32_t wd, \ + uint32_t ws, uint32_t u5) \ +{ \ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ + wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ + uint32_t i; \ + \ + switch (df) { \ + case DF_BYTE: \ + for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \ + pwd->b[i] = msa_ ## func ## _df(df, pws->b[i], u5); \ + } \ + break; \ + case DF_HALF: \ + for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \ + pwd->h[i] = msa_ ## func ## _df(df, pws->h[i], u5); \ + } \ + break; \ + case DF_WORD: \ + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \ + pwd->w[i] = msa_ ## func ## _df(df, pws->w[i], u5); \ + } \ + break; \ + case DF_DOUBLE: \ + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \ + pwd->d[i] = msa_ ## func ## _df(df, pws->d[i], u5); \ + } \ + break; \ + default: \ + assert(0); \ + } \ +} + +MSA_BINOP_IMMU_DF(slli, sll) +MSA_BINOP_IMMU_DF(srai, sra) +MSA_BINOP_IMMU_DF(srli, srl) +MSA_BINOP_IMMU_DF(bclri, bclr) +MSA_BINOP_IMMU_DF(bseti, bset) +MSA_BINOP_IMMU_DF(bnegi, bneg) +MSA_BINOP_IMMU_DF(sat_s, sat_s) +MSA_BINOP_IMMU_DF(sat_u, sat_u) +MSA_BINOP_IMMU_DF(srari, srar) +MSA_BINOP_IMMU_DF(srlri, srlr) +#undef MSA_BINOP_IMMU_DF + +#define MSA_TEROP_IMMU_DF(helper, func) \ +void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, \ + uint32_t wd, uint32_t ws, uint32_t u5) \ +{ \ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ + wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ + uint32_t i; \ + \ + switch (df) { \ + case DF_BYTE: \ + for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \ + pwd->b[i] = msa_ ## func ## _df(df, pwd->b[i], pws->b[i], \ + u5); \ + } \ + break; \ + case DF_HALF: \ + for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \ + pwd->h[i] = msa_ ## func ## _df(df, pwd->h[i], pws->h[i], \ + u5); \ + } \ + break; \ + case DF_WORD: \ + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \ + pwd->w[i] = msa_ ## func ## _df(df, pwd->w[i], pws->w[i], \ + u5); \ + } \ + break; \ + case DF_DOUBLE: \ + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \ + pwd->d[i] = msa_ ## func ## _df(df, pwd->d[i], pws->d[i], \ + u5); \ + } \ + break; \ + default: \ + assert(0); \ + } \ +} + +MSA_TEROP_IMMU_DF(binsli, binsl) +MSA_TEROP_IMMU_DF(binsri, binsr) +#undef MSA_TEROP_IMMU_DF diff --git a/target-mips/translate.c b/target-mips/translate.c index e75b864..1f3bd72 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -17465,6 +17465,90 @@ static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx) tcg_temp_free_i32(timm); } +static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23))) + uint8_t dfm = (ctx->opcode >> 16) & 0x7f; + uint32_t df = 0, m = 0; + uint8_t ws = (ctx->opcode >> 11) & 0x1f; + uint8_t wd = (ctx->opcode >> 6) & 0x1f; + + TCGv_i32 tdf; + TCGv_i32 tm; + TCGv_i32 twd; + TCGv_i32 tws; + + if ((dfm & 0x40) == 0x00) { + m = dfm & 0x3f; + df = DF_DOUBLE; + } else if ((dfm & 0x60) == 0x40) { + m = dfm & 0x1f; + df = DF_WORD; + } else if ((dfm & 0x70) == 0x60) { + m = dfm & 0x0f; + df = DF_HALF; + } else if ((dfm & 0x78) == 0x70) { + m = dfm & 0x7; + df = DF_BYTE; + } else { + generate_exception(ctx, EXCP_RI); + return; + } + + tdf = tcg_const_i32(df); + tm = tcg_const_i32(m); + twd = tcg_const_i32(wd); + tws = tcg_const_i32(ws); + + switch (MASK_MSA_BIT(ctx->opcode)) { + case OPC_SLLI_df: + gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_SRAI_df: + gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_SRLI_df: + gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_BCLRI_df: + gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_BSETI_df: + gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_BNEGI_df: + gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_BINSLI_df: + gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_BINSRI_df: + gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_SAT_S_df: + gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_SAT_U_df: + gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_SRARI_df: + gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_SRLRI_df: + gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm); + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception(ctx, EXCP_RI); + break; + } + + tcg_temp_free_i32(tdf); + tcg_temp_free_i32(tm); + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); +} + static void gen_msa(CPUMIPSState *env, DisasContext *ctx) { uint32_t opcode = ctx->opcode; @@ -17481,6 +17565,10 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx) case OPC_MSA_I5_07: gen_msa_i5(env, ctx); break; + case OPC_MSA_BIT_09: + case OPC_MSA_BIT_0A: + gen_msa_bit(env, ctx); + break; default: MIPS_INVAL("MSA instruction"); generate_exception(ctx, EXCP_RI);