qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 16/20] target-mips: add MSA VEC/2R format instructio


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

add MSA VEC/2R format instructions

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

diff --git a/target-mips/helper.h b/target-mips/helper.h
index fec21b6..b87bb50 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -698,6 +698,7 @@ DEF_HELPER_5(msa_adds_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_adds_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_addv_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s64)
+DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32)
 DEF_HELPER_5(msa_asub_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_asub_u_df, void, env, i32, i32, i32, i32)
@@ -711,10 +712,13 @@ DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32)
 DEF_HELPER_5(msa_bneg_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32)
 DEF_HELPER_5(msa_bset_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32)
@@ -755,6 +759,7 @@ DEF_HELPER_5(msa_fcune_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_fdiv_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_fexdo_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_fexp2_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32)
 DEF_HELPER_5(msa_fmadd_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_fmax_a_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_fmax_df, void, env, i32, i32, i32, i32)
@@ -808,10 +813,15 @@ DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_mul_q_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32)
 DEF_HELPER_5(msa_pckev_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_pckod_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_pcnt_df, 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)
@@ -836,4 +846,5 @@ DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s64)
 DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32)
 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 bb4ab66..aa165ac 100644
--- a/target-mips/msa_helper.c
+++ b/target-mips/msa_helper.c
@@ -495,6 +495,22 @@ void helper_msa_subsus_u_df(CPUMIPSState *env, uint32_t 
df, uint32_t wd,
     }
 }
 
+void helper_msa_and_v(CPUMIPSState *env, uint32_t wd, uint32_t ws,
+        uint32_t wt)
+{
+    void *pwd = &(env->active_fpu.fpr[wd]);
+    void *pws = &(env->active_fpu.fpr[ws]);
+    void *pwt = &(env->active_fpu.fpr[wt]);
+
+    ALL_D_ELEMENTS(i, MSA_WRLEN) {
+        D(pwd, i) = D(pws, i) & D(pwt, i);
+    } DONE_ALL_ELEMENTS;
+
+    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)
 {
@@ -508,6 +524,22 @@ void helper_msa_andi_b(CPUMIPSState *env, uint32_t wd, 
uint32_t ws,
     }
 }
 
+void helper_msa_or_v(CPUMIPSState *env, uint32_t wd, uint32_t ws,
+        uint32_t wt)
+{
+    void *pwd = &(env->active_fpu.fpr[wd]);
+    void *pws = &(env->active_fpu.fpr[ws]);
+    void *pwt = &(env->active_fpu.fpr[wt]);
+
+    ALL_D_ELEMENTS(i, MSA_WRLEN) {
+        D(pwd, i) = D(pws, i) | D(pwt, i);
+    } DONE_ALL_ELEMENTS;
+
+    if (env->active_msa.msair & MSAIR_WRP_BIT) {
+        env->active_msa.msamodify |= (1 << wd);
+    }
+}
+
 void helper_msa_ori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws,
         uint32_t i8)
 {
@@ -521,6 +553,22 @@ void helper_msa_ori_b(CPUMIPSState *env, uint32_t wd, 
uint32_t ws,
     }
 }
 
+void helper_msa_nor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws,
+        uint32_t wt)
+{
+    void *pwd = &(env->active_fpu.fpr[wd]);
+    void *pws = &(env->active_fpu.fpr[ws]);
+    void *pwt = &(env->active_fpu.fpr[wt]);
+
+    ALL_D_ELEMENTS(i, MSA_WRLEN) {
+        D(pwd, i) = ~(D(pws, i) | D(pwt, i));
+    } DONE_ALL_ELEMENTS;
+
+    if (env->active_msa.msair & MSAIR_WRP_BIT) {
+        env->active_msa.msamodify |= (1 << wd);
+    }
+}
+
 void helper_msa_nori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws,
         uint32_t i8)
 {
@@ -534,6 +582,22 @@ void helper_msa_nori_b(CPUMIPSState *env, uint32_t wd, 
uint32_t ws,
     }
 }
 
+void helper_msa_xor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws,
+        uint32_t wt)
+{
+    void *pwd = &(env->active_fpu.fpr[wd]);
+    void *pws = &(env->active_fpu.fpr[ws]);
+    void *pwt = &(env->active_fpu.fpr[wt]);
+
+    ALL_D_ELEMENTS(i, MSA_WRLEN) {
+        D(pwd, i) = D(pws, i) ^ D(pwt, i);
+    } DONE_ALL_ELEMENTS;
+
+    if (env->active_msa.msair & MSAIR_WRP_BIT) {
+        env->active_msa.msamodify |= (1 << wd);
+    }
+}
+
 void helper_msa_xori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws,
         uint32_t i8)
 {
@@ -922,6 +986,22 @@ void helper_msa_binsri_df(CPUMIPSState *env, uint32_t df, 
uint32_t wd,
 #define BIT_MOVE_IF_NOT_ZERO(dest, arg1, arg2, df) \
             dest = UNSIGNED(((dest & (~arg2)) | (arg1 & arg2)), df)
 
+void helper_msa_bmnz_v(CPUMIPSState *env, uint32_t wd, uint32_t ws,
+        uint32_t wt)
+{
+    void *pwd = &(env->active_fpu.fpr[wd]);
+    void *pws = &(env->active_fpu.fpr[ws]);
+    void *pwt = &(env->active_fpu.fpr[wt]);
+
+    ALL_D_ELEMENTS(i, MSA_WRLEN) {
+        BIT_MOVE_IF_NOT_ZERO(D(pwd, i), D(pws, i), D(pwt, i), DF_DOUBLE);
+    } DONE_ALL_ELEMENTS;
+
+    if (env->active_msa.msair & MSAIR_WRP_BIT) {
+        env->active_msa.msamodify |= (1 << wd);
+    }
+}
+
 void helper_msa_bmnzi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws,
         uint32_t i8)
 {
@@ -938,6 +1018,22 @@ void helper_msa_bmnzi_b(CPUMIPSState *env, uint32_t wd, 
uint32_t ws,
 #define BIT_MOVE_IF_ZERO(dest, arg1, arg2, df) \
             dest = UNSIGNED((dest & arg2) | (arg1 & (~arg2)), df)
 
+void helper_msa_bmz_v(CPUMIPSState *env, uint32_t wd, uint32_t ws,
+        uint32_t wt)
+{
+    void *pwd = &(env->active_fpu.fpr[wd]);
+    void *pws = &(env->active_fpu.fpr[ws]);
+    void *pwt = &(env->active_fpu.fpr[wt]);
+
+    ALL_D_ELEMENTS(i, MSA_WRLEN) {
+        BIT_MOVE_IF_ZERO(D(pwd, i), D(pws, i), D(pwt, i), DF_DOUBLE);
+    } DONE_ALL_ELEMENTS;
+
+    if (env->active_msa.msair & MSAIR_WRP_BIT) {
+        env->active_msa.msamodify |= (1 << wd);
+    }
+}
+
 void helper_msa_bmzi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws,
         uint32_t i8)
 {
@@ -954,6 +1050,22 @@ void helper_msa_bmzi_b(CPUMIPSState *env, uint32_t wd, 
uint32_t ws,
 #define BIT_SELECT(dest, arg1, arg2, df) \
             dest = UNSIGNED((arg1 & (~dest)) | (arg2 & dest), df)
 
+void helper_msa_bsel_v(CPUMIPSState *env, uint32_t wd, uint32_t ws,
+        uint32_t wt)
+{
+    void *pwd = &(env->active_fpu.fpr[wd]);
+    void *pws = &(env->active_fpu.fpr[ws]);
+    void *pwt = &(env->active_fpu.fpr[wt]);
+
+    ALL_D_ELEMENTS(i, MSA_WRLEN) {
+        BIT_SELECT(D(pwd, i), D(pws, i), D(pwt, i), DF_DOUBLE);
+    } DONE_ALL_ELEMENTS;
+
+    if (env->active_msa.msair & MSAIR_WRP_BIT) {
+        env->active_msa.msamodify |= (1 << wd);
+    }
+}
+
 void helper_msa_bseli_b(CPUMIPSState *env, uint32_t wd, uint32_t ws,
         uint32_t i8)
 {
@@ -2251,6 +2363,42 @@ void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, 
uint32_t wd,
     }
 }
 
+void helper_msa_fill_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t rs)
+{
+    void *pwd = &(env->active_fpu.fpr[wd]);
+
+    switch (df) {
+    case DF_BYTE:
+        ALL_B_ELEMENTS(i, MSA_WRLEN) {
+            B(pwd, i)   = (int8_t)env->active_tc.gpr[rs];
+        } DONE_ALL_ELEMENTS;
+        break;
+    case DF_HALF:
+        ALL_H_ELEMENTS(i, MSA_WRLEN) {
+            H(pwd, i)   = (int16_t)env->active_tc.gpr[rs];
+        } DONE_ALL_ELEMENTS;
+        break;
+    case DF_WORD:
+        ALL_W_ELEMENTS(i, MSA_WRLEN) {
+            W(pwd, i)   = (int32_t)env->active_tc.gpr[rs];
+        } DONE_ALL_ELEMENTS;
+        break;
+    case DF_DOUBLE:
+        ALL_D_ELEMENTS(i, MSA_WRLEN) {
+            D(pwd, i)   = (int64_t)env->active_tc.gpr[rs];
+        } 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);
+    }
+}
+
 static inline void msa_insert_df(CPUMIPSState *env, uint32_t df, void *pwd,
         target_ulong rs, uint32_t n)
 {
@@ -2437,6 +2585,102 @@ void helper_msa_mod_u_df(CPUMIPSState *env, uint32_t 
df, uint32_t wd,
     }
 }
 
+static inline int64_t msa_nlzc_df(CPUMIPSState *env, uint32_t df, int64_t arg)
+{
+    uint64_t x, y;
+    int n, c;
+
+    x = UNSIGNED(arg, df);
+    n = DF_BITS(df);
+    c = DF_BITS(df) / 2;
+
+    do {
+        y = x >> c;
+        if (y != 0) {
+            n = n - c;
+            x = y;
+        }
+        c = c >> 1;
+    } while (c != 0);
+
+    return n - x;
+}
+
+void helper_msa_nlzc_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws)
+{
+    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_s64(env, ws, df, i);
+        td = msa_nlzc_df(env, df, ts);
+        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_nloc_df(CPUMIPSState *env, uint32_t df, int64_t arg)
+{
+    return msa_nlzc_df(env, df, UNSIGNED((~arg), df));
+}
+
+void helper_msa_nloc_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws)
+{
+    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_s64(env, ws, df, i);
+        td = msa_nloc_df(env, df, ts);
+        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_pcnt_df(CPUMIPSState *env, uint32_t df, int64_t arg)
+{
+    uint64_t x;
+
+    x = UNSIGNED(arg, df);
+
+    x = (x & 0x5555555555555555ULL) + ((x >>  1) & 0x5555555555555555ULL);
+    x = (x & 0x3333333333333333ULL) + ((x >>  2) & 0x3333333333333333ULL);
+    x = (x & 0x0F0F0F0F0F0F0F0FULL) + ((x >>  4) & 0x0F0F0F0F0F0F0F0FULL);
+    x = (x & 0x00FF00FF00FF00FFULL) + ((x >>  8) & 0x00FF00FF00FF00FFULL);
+    x = (x & 0x0000FFFF0000FFFFULL) + ((x >> 16) & 0x0000FFFF0000FFFFULL);
+    x = (x & 0x00000000FFFFFFFFULL) + ((x >> 32));
+
+    return x;
+}
+
+void helper_msa_pcnt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws)
+{
+    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_s64(env, ws, df, i);
+        td = msa_pcnt_df(env, df, ts);
+        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_u_df(CPUMIPSState *env, uint32_t df, int64_t arg,
         uint32_t m)
 {
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 39caa6d..4185019 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15650,6 +15650,101 @@ static void gen_msa_3rf(CPUMIPSState *env, 
DisasContext *ctx)
     tcg_temp_free_i32(tdf1);
 }
 
+static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
+{
+#define MASK_MSA_VEC(op)    (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
+#define MASK_MSA_2R(op)     (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
+                            (op & (0x7 << 18)))
+#define MASK_MSA_2RF(op)    (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
+                            (op & (0xf << 17)))
+
+    uint32_t opcode = ctx->opcode;
+
+    uint8_t wt = (ctx->opcode >> 16) & 0x1f /* wt [20:16] */;
+    uint8_t ws = (ctx->opcode >> 11) & 0x1f /* ws [15:11] */;
+    uint8_t wd = (ctx->opcode >> 6) & 0x1f /* wd [10:6] */;
+
+    TCGv_i32 twd = tcg_const_i32(wd);
+    TCGv_i32 tws = tcg_const_i32(ws);
+    TCGv_i32 twt = tcg_const_i32(wt);
+
+    switch (MASK_MSA_VEC(opcode)) {
+    case OPC_MSA_AND_V:
+        check_msa_access(env, ctx, wt, ws, wd);
+        gen_helper_msa_and_v(cpu_env, twd, tws, twt);
+        break;
+    case OPC_MSA_OR_V:
+        check_msa_access(env, ctx, wt, ws, wd);
+        gen_helper_msa_or_v(cpu_env, twd, tws, twt);
+        break;
+    case OPC_MSA_NOR_V:
+        check_msa_access(env, ctx, wt, ws, wd);
+        gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
+        break;
+    case OPC_MSA_XOR_V:
+        check_msa_access(env, ctx, wt, ws, wd);
+        gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
+        break;
+    case OPC_MSA_BMNZ_V:
+        check_msa_access(env, ctx, wt, ws, wd);
+        gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
+        break;
+    case OPC_MSA_BMZ_V:
+        check_msa_access(env, ctx, wt, ws, wd);
+        gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
+        break;
+    case OPC_MSA_BSEL_V:
+        check_msa_access(env, ctx, wt, ws, wd);
+        gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
+        break;
+
+    case OPC_MSA_2R:
+        {
+            uint8_t df = (ctx->opcode >> 16) & 0x3 /* df [17:16] */;
+            TCGv_i32 tdf = tcg_const_i32(df);
+
+            switch (MASK_MSA_2R(opcode)) {
+            case OPC_MSA_FILL_df:
+#if !defined(TARGET_MIPS64)
+                /* Double format valid only for MIPS64 */
+                if (df == 3) {
+                    if (check_msa_access(env, ctx, -1, -1, -1)) {
+                        generate_exception(ctx, EXCP_RI);
+                    }
+                    break;
+                }
+#endif
+                check_msa_access(env, ctx, -1, -1, wd);
+                gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
+                break;
+            case OPC_MSA_PCNT_df:
+                check_msa_access(env, ctx, -1, ws, wd);
+                gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
+                break;
+            case OPC_MSA_NLOC_df:
+                check_msa_access(env, ctx, -1, ws, wd);
+                gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
+                break;
+            case OPC_MSA_NLZC_df:
+                check_msa_access(env, ctx, -1, ws, wd);
+                gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
+                break;
+            default:
+                break;
+            }
+
+            tcg_temp_free_i32(tdf);
+        }
+        break;
+    case OPC_MSA_2RF:
+    default:
+        break;
+    }
+
+    tcg_temp_free_i32(twd);
+    tcg_temp_free_i32(tws);
+    tcg_temp_free_i32(twt);
+}
 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
 {
     uint32_t opcode = ctx->opcode;
@@ -15688,6 +15783,9 @@ static void gen_msa(CPUMIPSState *env, DisasContext 
*ctx)
     case OPC_MSA_3RF_1C:
         gen_msa_3rf(env, ctx);
         break;
+    case OPC_MSA_VEC:
+        gen_msa_vec(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]