qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 12/20] target-mips: add MSA BIT format instructions


From: Yongbok Kim
Subject: [Qemu-devel] [PATCH 12/20] target-mips: add MSA BIT format instructions
Date: Mon, 14 Jul 2014 10:55:55 +0100

add MSA BIT format instructions

Signed-off-by: Yongbok Kim <address@hidden>
---
 target-mips/helper.h     |   12 ++
 target-mips/msa_helper.c |  292 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/translate.c  |  100 ++++++++++++++++
 3 files changed, 404 insertions(+), 0 deletions(-)

diff --git a/target-mips/helper.h b/target-mips/helper.h
index fe0cf48..f9406d6 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -694,9 +694,14 @@ DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env)
 
 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_5(msa_bclri_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_4(msa_bmnzi_b, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32)
+DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32)
+DEF_HELPER_5(msa_bseti_df, void, env, i32, 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)
@@ -709,6 +714,13 @@ 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_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_shf_df, void, env, i32, i32, i32, i32)
+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_srari_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(msa_srlri_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 00b6e77..39377d6 100644
--- a/target-mips/msa_helper.c
+++ b/target-mips/msa_helper.c
@@ -279,6 +279,140 @@ void helper_msa_xori_b(CPUMIPSState *env, uint32_t wd, 
uint32_t ws,
     }
 }
 
+static inline int64_t msa_bclr_df(CPUMIPSState *env, uint32_t df, int64_t arg1,
+        int64_t arg2)
+{
+    int32_t b_arg2 = BIT_POSITION(arg2, df);
+
+    return UNSIGNED(arg1 & (~(1LL << b_arg2)), df);
+}
+
+void helper_msa_bclri_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t m)
+{
+    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_bclr_df(env, df, ts, m);
+        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_bneg_df(CPUMIPSState *env, uint32_t df, int64_t arg1,
+        int64_t arg2)
+{
+    int32_t b_arg2 = BIT_POSITION(arg2, df);
+    return UNSIGNED(arg1 ^ (1LL << b_arg2), df);
+}
+
+void helper_msa_bnegi_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t m)
+{
+    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_bneg_df(env, df, ts, m);
+        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_bset_df(CPUMIPSState *env, uint32_t df, int64_t arg1,
+        int64_t arg2)
+{
+    int32_t b_arg2 = BIT_POSITION(arg2, df);
+    return UNSIGNED(arg1 | (1LL << b_arg2), df);
+}
+
+void helper_msa_bseti_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t m)
+{
+    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_bset_df(env, df, ts, m);
+        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_binsl_df(CPUMIPSState *env, 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);
+    }
+}
+
+void helper_msa_binsli_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t m)
+{
+    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_load_wr_elem_s64(env, wd, df, i);
+        td = msa_binsl_df(env, df, td, ts, m);
+        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_binsr_df(CPUMIPSState *env, 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);
+    }
+}
+
+void helper_msa_binsri_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t m)
+{
+    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_load_wr_elem_s64(env, wd, df, i);
+        td = msa_binsr_df(env, df, td, ts, m);
+        msa_store_wr_elem(env, td, wd, df, i);
+    }
+    if (env->active_msa.msair & MSAIR_WRP_BIT) {
+        env->active_msa.msamodify |= (1 << wd);
+    }
+}
+
 #define BIT_MOVE_IF_NOT_ZERO(dest, arg1, arg2, df) \
             dest = UNSIGNED(((dest & (~arg2)) | (arg1 & arg2)), df)
 
@@ -607,3 +741,161 @@ void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, 
uint32_t wd,
         env->active_msa.msamodify |= (1 << wd);
     }
 }
+
+static inline int64_t msa_sat_u_df(CPUMIPSState *env, 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);
+}
+
+void helper_msa_sat_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t m)
+{
+    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_sat_u_df(env, df, ts, m);
+        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_sat_s_df(CPUMIPSState *env, 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;
+}
+
+void helper_msa_sat_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t m)
+{
+    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_sat_s_df(env, df, ts, m);
+        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_slli_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t m)
+{
+    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 = ts << m;
+        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_srai_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t m)
+{
+    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 = ts >> m;
+        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_srli_df(CPUMIPSState *env, uint32_t df, int64_t arg,
+        uint32_t m)
+{
+    uint64_t u_arg = UNSIGNED(arg, df);
+    return u_arg >> m;
+}
+
+void helper_msa_srli_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t m)
+{
+    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_srli_df(env, df, ts, m);
+        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_srari_df(CPUMIPSState *env, uint32_t df, int64_t arg,
+        uint32_t m)
+{
+    if (m == 0) {
+        return arg;
+    } else {
+        int64_t r_bit = (arg >> (m - 1)) & 1;
+        return (arg >> m) + r_bit;
+    }
+}
+
+void helper_msa_srari_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t m)
+{
+    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_srari_df(env, df, ts, m);
+        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_srlri_df(CPUMIPSState *env, uint32_t df, int64_t arg,
+        uint32_t m)
+{
+    uint64_t u_arg = UNSIGNED(arg, df);
+    if (m == 0) {
+        return u_arg;
+    } else {
+        uint64_t r_bit = (u_arg >> (m - 1)) & 1;
+        return (u_arg >> m) + r_bit;
+    }
+}
+
+void helper_msa_srlri_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t m)
+{
+    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_srlri_df(env, df, ts, m);
+        msa_store_wr_elem(env, td, wd, df, i);
+    }
+    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 7fde3bb..f97d3a9 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -14934,6 +14934,102 @@ static void gen_msa_i5(CPUMIPSState *env, 
DisasContext *ctx)
     tcg_temp_free_i64(ts5);
 }
 
+static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
+{
+#define MASK_MSA_BIT(op)    (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
+    uint32_t opcode = ctx->opcode;
+
+    uint8_t dfm = (ctx->opcode >> 16) & 0x7f /* dfm [22:16] */;
+    uint32_t df = 0, m = 0;
+
+    if ((dfm & 0x40) == 0x00) {         /* double data format */
+        m = dfm & 0x3f;
+        df = 3;
+    } else if ((dfm & 0x60) == 0x40) {  /* word data format */
+        m = dfm & 0x1f;
+        df = 2;
+    } else if ((dfm & 0x70) == 0x60) {  /* half data format */
+        m = dfm & 0x0f;
+        df = 1;
+    } else if ((dfm & 0x78) == 0x70) {  /* byte data format */
+        m = dfm & 0x7;
+        df = 0;
+    } else {
+        if (check_msa_access(env, ctx, -1, -1, -1)) {
+            generate_exception(ctx, EXCP_RI);
+        }
+        return;
+    }
+
+    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 tm  = tcg_const_i32(m);
+    TCGv_i32 twd = tcg_const_i32(wd);
+    TCGv_i32 tws = tcg_const_i32(ws);
+
+    switch (MASK_MSA_BIT(opcode)) {
+    case OPC_MSA_SLLI_df:
+        check_msa_access(env, ctx, -1, ws, wd);
+        gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
+        break;
+    case OPC_MSA_SRAI_df:
+        check_msa_access(env, ctx, -1, ws, wd);
+        gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
+        break;
+    case OPC_MSA_SRLI_df:
+        check_msa_access(env, ctx, -1, ws, wd);
+        gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
+        break;
+    case OPC_MSA_BCLRI_df:
+        check_msa_access(env, ctx, -1, ws, wd);
+        gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
+        break;
+    case OPC_MSA_BSETI_df:
+        check_msa_access(env, ctx, -1, ws, wd);
+        gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
+        break;
+    case OPC_MSA_BNEGI_df:
+        check_msa_access(env, ctx, -1, ws, wd);
+        gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
+        break;
+    case OPC_MSA_BINSLI_df:
+        check_msa_access(env, ctx, -1, ws, wd);
+        gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
+        break;
+    case OPC_MSA_BINSRI_df:
+        check_msa_access(env, ctx, -1, ws, wd);
+        gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
+        break;
+    case OPC_MSA_SAT_S_df:
+        check_msa_access(env, ctx, -1, ws, wd);
+        gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
+        break;
+    case OPC_MSA_SAT_U_df:
+        check_msa_access(env, ctx, -1, ws, wd);
+        gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
+        break;
+    case OPC_MSA_SRARI_df:
+        check_msa_access(env, ctx, -1, ws, wd);
+        gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
+        break;
+    case OPC_MSA_SRLRI_df:
+        check_msa_access(env, ctx, -1, ws, wd);
+        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;
@@ -14949,6 +15045,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);
-- 
1.7.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]