qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 14/20] target-mips: add MSA ELM format instructions


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

add MSA ELM format instructions

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

diff --git a/target-mips/helper.h b/target-mips/helper.h
index 00705c4..e13daec 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -720,6 +720,7 @@ DEF_HELPER_5(msa_bset_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_ceq_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s64)
+DEF_HELPER_2(msa_cfcmsa, tl, env, i32)
 DEF_HELPER_5(msa_cle_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_cle_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s64)
@@ -728,6 +729,9 @@ DEF_HELPER_5(msa_clt_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_clt_u_df, void, env, i32, i32, i32, i32)
 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_5(msa_copy_s_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(msa_copy_u_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32)
 DEF_HELPER_5(msa_div_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_div_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32)
@@ -744,6 +748,8 @@ DEF_HELPER_5(msa_ilvev_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_ilvl_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_ilvod_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_ilvr_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(msa_insert_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, i32)
 DEF_HELPER_5(msa_maddv_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_max_a_df, void, env, i32, i32, i32, i32)
@@ -758,6 +764,7 @@ 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_5(msa_mod_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_mod_u_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_3(msa_move_v, void, env, i32, i32)
 DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32)
@@ -768,9 +775,11 @@ 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_sld_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_sll_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_sra_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_srar_df, void, env, i32, i32, i32, i32)
diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c
index bb4ea65..220a0cd 100644
--- a/target-mips/msa_helper.c
+++ b/target-mips/msa_helper.c
@@ -1166,6 +1166,59 @@ void helper_msa_clti_u_df(CPUMIPSState *env, uint32_t 
df, uint32_t wd,
     }
 }
 
+void helper_msa_copy_s_df(CPUMIPSState *env, uint32_t df, uint32_t rd,
+        uint32_t ws, uint32_t n)
+{
+    n %= DF_ELEMENTS(df, MSA_WRLEN);
+    msa_check_index(env, (uint32_t)df, (uint32_t)n);
+    switch (df) {
+    case DF_BYTE: /* b */
+        env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n];
+        break;
+    case DF_HALF: /* h */
+        env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n];
+        break;
+    case DF_WORD: /* w */
+        env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n];
+        break;
+#ifdef TARGET_MIPS64
+    case DF_DOUBLE: /* d */
+        env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n];
+        break;
+#endif
+    default:
+        /* shouldn't get here */
+        assert(0);
+    }
+}
+
+void helper_msa_copy_u_df(CPUMIPSState *env, uint32_t df, uint32_t rd,
+        uint32_t ws, uint32_t n)
+{
+    n %= DF_ELEMENTS(df, MSA_WRLEN);
+    msa_check_index(env, (uint32_t)df, (uint32_t)n);
+    switch (df) {
+    case DF_BYTE: /* b */
+        env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n];
+        break;
+    case DF_HALF: /* h */
+        env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n];
+        break;
+    case DF_WORD: /* w */
+        env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n];
+        break;
+#ifdef TARGET_MIPS64
+    case DF_DOUBLE: /* d */
+        env->active_tc.gpr[rd] = (uint64_t)env->active_fpu.fpr[ws].wr.d[n];
+        break;
+#endif
+    default:
+        /* shouldn't get here */
+        assert(0);
+    }
+}
+
+
 #define SIGNED_EVEN(a, df) \
         ((((int64_t)(a)) << (64 - DF_BITS(df)/2)) >> (64 - DF_BITS(df)/2))
 #define UNSIGNED_EVEN(a, df) \
@@ -2142,6 +2195,27 @@ void helper_msa_splat_df(CPUMIPSState *env, uint32_t df, 
uint32_t wd,
     }
 }
 
+void helper_msa_splati_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t n)
+{
+    void *pwd = &(env->active_fpu.fpr[wd]);
+    void *pws = &(env->active_fpu.fpr[ws]);
+    msa_splat_df(env, df, pwd, pws, n);
+    if (env->active_msa.msair & MSAIR_WRP_BIT) {
+        env->active_msa.msamodify |= (1 << wd);
+    }
+}
+
+void helper_msa_move_v(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+    void *pwd = &(env->active_fpu.fpr[wd]);
+    void *pws = &(env->active_fpu.fpr[ws]);
+    msa_move_v(pwd, pws);
+    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)
 {
@@ -2177,6 +2251,73 @@ void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, 
uint32_t wd,
     }
 }
 
+static inline void msa_insert_df(CPUMIPSState *env, uint32_t df, void *pwd,
+        target_ulong rs, uint32_t n)
+{
+    msa_check_index(env, df, n);
+    switch (df) {
+    case DF_BYTE:
+        B(pwd, n)   = (int8_t)rs;
+        break;
+    case DF_HALF:
+        H(pwd, n)   = (int16_t)rs;
+        break;
+    case DF_WORD:
+        W(pwd, n)   = (int32_t)rs;
+        break;
+    case DF_DOUBLE:
+        D(pwd, n)   = (int64_t)rs;
+        break;
+    default:
+        /* shouldn't get here */
+        assert(0);
+    }
+}
+
+void helper_msa_insert_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t rs, uint32_t n)
+{
+    void *pwd = &(env->active_fpu.fpr[wd]);
+    msa_insert_df(env, df, pwd, env->active_tc.gpr[rs], n);
+    if (env->active_msa.msair & MSAIR_WRP_BIT) {
+        env->active_msa.msamodify |= (1 << wd);
+    }
+}
+
+static inline void msa_insve_df(CPUMIPSState *env, uint32_t df, void *pwd,
+        void *pws, uint32_t n)
+{
+    msa_check_index(env, df, n);
+    switch (df) {
+    case DF_BYTE:
+        B(pwd, n)   = (int8_t)B(pws, 0);
+        break;
+    case DF_HALF:
+        H(pwd, n)   = (int16_t)H(pws, 0);
+        break;
+    case DF_WORD:
+        W(pwd, n)   = (int32_t)W(pws, 0);
+        break;
+    case DF_DOUBLE:
+        D(pwd, n)   = (int64_t)D(pws, 0);
+        break;
+    default:
+        /* shouldn't get here */
+        assert(0);
+    }
+}
+
+void helper_msa_insve_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t n)
+{
+    void *pwd = &(env->active_fpu.fpr[wd]);
+    void *pws = &(env->active_fpu.fpr[ws]);
+    msa_insve_df(env, df, pwd, pws, n);
+    if (env->active_msa.msair & MSAIR_WRP_BIT) {
+        env->active_msa.msamodify |= (1 << wd);
+    }
+}
+
 void helper_msa_mulv_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
         uint32_t ws, uint32_t wt)
 {
@@ -2638,3 +2779,101 @@ void helper_msa_sld_df(CPUMIPSState *env, uint32_t df, 
uint32_t wd,
         env->active_msa.msamodify |= (1 << wd);
     }
 }
+
+void helper_msa_sldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+        uint32_t ws, uint32_t n)
+{
+    void *pwd = &(env->active_fpu.fpr[wd]);
+    void *pws = &(env->active_fpu.fpr[ws]);
+
+    msa_sld_df(env, df, pwd, pws, n);
+
+    if (env->active_msa.msair & MSAIR_WRP_BIT) {
+        env->active_msa.msamodify |= (1 << wd);
+    }
+}
+
+target_ulong helper_msa_cfcmsa(CPUMIPSState *env, uint32_t cs)
+{
+    switch (cs) {
+    case MSAIR_REGISTER:
+        return env->active_msa.msair;
+    case MSACSR_REGISTER:
+        return env->active_msa.msacsr & MSACSR_BITS;
+    }
+
+    if (env->active_msa.msair & MSAIR_WRP_BIT) {
+        switch (cs) {
+        case MSAACCESS_REGISTER:
+            return env->active_msa.msaaccess;
+        case MSASAVE_REGISTER:
+            return env->active_msa.msasave;
+        case MSAMODIFY_REGISTER:
+            return env->active_msa.msamodify;
+        case MSAREQUEST_REGISTER:
+            return env->active_msa.msarequest;
+        case MSAMAP_REGISTER:
+            return env->active_msa.msamap;
+        case MSAUNMAP_REGISTER:
+            return env->active_msa.msaunmap;
+        }
+    }
+    return 0;
+}
+
+void helper_msa_ctcmsa(CPUMIPSState *env, target_ulong elm, uint32_t cd)
+{
+    switch (cd) {
+    case MSAIR_REGISTER:
+        break;
+    case MSACSR_REGISTER:
+        env->active_msa.msacsr = (int32_t)elm & MSACSR_BITS;
+
+        /* set float_status rounding mode */
+        set_float_rounding_mode(
+            ieee_rm[(env->active_msa.msacsr & MSACSR_RM_MASK) >> 
MSACSR_RM_POS],
+            &env->active_msa.fp_status);
+
+        /* set float_status flush modes */
+        set_flush_to_zero(
+          (env->active_msa.msacsr & MSACSR_FS_BIT) != 0 ? 1 : 0,
+          &env->active_msa.fp_status);
+        set_flush_inputs_to_zero(
+          (env->active_msa.msacsr & MSACSR_FS_BIT) != 0 ? 1 : 0,
+          &env->active_msa.fp_status);
+
+        /* check exception */
+        if ((GET_FP_ENABLE(env->active_msa.msacsr) | FP_UNIMPLEMENTED)
+            & GET_FP_CAUSE(env->active_msa.msacsr)) {
+            helper_raise_exception(env, EXCP_MSAFPE);
+        }
+        break;
+    case MSAACCESS_REGISTER:
+        break;
+    case MSASAVE_REGISTER:
+        if (env->active_msa.msair & MSAIR_WRP_BIT) {
+            env->active_msa.msasave = (int32_t)elm;
+        }
+        break;
+    case MSAMODIFY_REGISTER:
+        if (env->active_msa.msair & MSAIR_WRP_BIT) {
+            env->active_msa.msamodify = (int32_t)elm;
+        }
+        break;
+    case MSAREQUEST_REGISTER:
+        break;
+    case MSAMAP_REGISTER:
+        if (env->active_msa.msair & MSAIR_WRP_BIT) {
+            env->active_msa.msamap = (int32_t)elm;
+            env->active_msa.msaaccess |= 1 << (int32_t)elm;
+            return;
+        }
+        break;
+    case MSAUNMAP_REGISTER:
+        if (env->active_msa.msair & MSAIR_WRP_BIT) {
+            env->active_msa.msaunmap = (int32_t)elm;
+            env->active_msa.msaaccess &= ~(1 << (int32_t)elm);
+        }
+        break;
+    }
+}
diff --git a/target-mips/translate.c b/target-mips/translate.c
index e063531..6c8caa4 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15319,6 +15319,139 @@ static void gen_msa_3r(CPUMIPSState *env, 
DisasContext *ctx)
     tcg_temp_free_i32(tdf);
 }
 
+static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
+{
+#define MASK_MSA_ELM(op)    (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
+#define MASK_MSA_ELM_DF3E(op)   (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
+    uint32_t opcode = ctx->opcode;
+
+    uint8_t dfn = (ctx->opcode >> 16) & 0x3f /* dfn [21:16] */;
+
+    uint32_t df = 0, n = 0;
+
+    if ((dfn & 0x20) == 0x00) {         /* byte data format */
+        n = dfn & 0x1f;
+        df = 0;
+    } else if ((dfn & 0x30) == 0x20) {  /* half data format */
+        n = dfn & 0x0f;
+        df = 1;
+    } else if ((dfn & 0x38) == 0x30) {  /* word data format */
+        n = dfn & 0x07;
+        df = 2;
+    } else if ((dfn & 0x3c) == 0x38) {  /* double data format */
+        n = dfn & 0x3;
+        df = 3;
+    } else if (dfn == 0x3E) {  /* CTCMSA, CFCMSA, MOVE.V */
+        df = 4;
+    } else {
+        if (check_msa_access(env, ctx, -1, -1, -1)) {
+            generate_exception(ctx, EXCP_RI);
+        }
+        return;
+    }
+
+    if (df == 4) {
+        uint8_t source = (ctx->opcode >> 11) & 0x1f /* rs/cs/ws [15:11] */;
+        uint8_t dest = (ctx->opcode >> 6) & 0x1f /* cd/rd/wd [10:6] */;
+        TCGv telm = tcg_temp_new();
+        TCGv_i32 tsr = tcg_const_i32(source);
+        TCGv_i32 tdt = tcg_const_i32(dest);
+
+        switch (MASK_MSA_ELM_DF3E(opcode)) {
+        case OPC_MSA_CTCMSA:
+            {
+                check_msa_access(env, ctx, -1, -1, -1);
+                gen_load_gpr(telm, source);
+                gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
+            }
+            break;
+        case OPC_MSA_CFCMSA:
+            {
+                check_msa_access(env, ctx, -1, -1, -1);
+                gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
+                gen_store_gpr(telm, dest);
+            }
+            break;
+        case OPC_MSA_MOVE_V:
+            {
+                check_msa_access(env, ctx, -1, -1, -1);
+                gen_helper_msa_move_v(cpu_env, tdt, tsr);
+            }
+            break;
+        default:
+            MIPS_INVAL("MSA instruction");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
+
+        tcg_temp_free(telm);
+        tcg_temp_free_i32(tdt);
+        tcg_temp_free_i32(tsr);
+    } else {
+        int df_bits = 8 * (1 << df);
+        if (n >= MSA_WRLEN / df_bits) {
+            if (check_msa_access(env, ctx, -1, -1, -1)) {
+                generate_exception(ctx, EXCP_RI);
+            }
+        } else {
+            uint8_t ws = (ctx->opcode >> 11) & 0x1f /* ws [15:11] */;
+            uint8_t wd = (ctx->opcode >> 6) & 0x1f /* wd [10:6] */;
+
+            TCGv_i32 tws = tcg_const_i32(ws);
+            TCGv_i32 twd = tcg_const_i32(wd);
+            TCGv_i32 tn  = tcg_const_i32(n);
+            TCGv_i32 tdf = tcg_const_i32(df);
+
+            switch (MASK_MSA_ELM(opcode)) {
+            case OPC_MSA_SLDI_df:
+                check_msa_access(env, ctx, -1, ws, wd);
+                gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
+                break;
+            case OPC_MSA_SPLATI_df:
+                check_msa_access(env, ctx, -1, ws, wd);
+                gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
+                break;
+            case OPC_MSA_INSVE_df:
+                check_msa_access(env, ctx, -1, ws, wd);
+                gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
+                break;
+            case OPC_MSA_COPY_S_df:
+            case OPC_MSA_COPY_U_df:
+            case OPC_MSA_INSERT_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, ws, wd);
+                switch (MASK_MSA_ELM(opcode)) {
+                case OPC_MSA_COPY_S_df:
+                    gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
+                    break;
+                case OPC_MSA_COPY_U_df:
+                    gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
+                    break;
+                case OPC_MSA_INSERT_df:
+                    gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
+                    break;
+                }
+                break;
+            default:
+                MIPS_INVAL("MSA instruction");
+                generate_exception(ctx, EXCP_RI);
+            }
+            tcg_temp_free_i32(twd);
+            tcg_temp_free_i32(tws);
+            tcg_temp_free_i32(tn);
+            tcg_temp_free_i32(tdf);
+        }
+    }
+}
+
 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
 {
     uint32_t opcode = ctx->opcode;
@@ -15349,6 +15482,9 @@ static void gen_msa(CPUMIPSState *env, DisasContext 
*ctx)
     case OPC_MSA_3R_15:
         gen_msa_3r(env, ctx);
         break;
+    case OPC_MSA_ELM:
+        gen_msa_elm(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]