[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
- [Qemu-devel] [PATCH 04/20] target-mips: add 8, 16, 32, 64 bits load and store, (continued)
- [Qemu-devel] [PATCH 04/20] target-mips: add 8, 16, 32, 64 bits load and store, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 08/20] target-mips: add msa_helper.c, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 07/20] target-mips: add msa_reset(), global msa register, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 03/20] target-mips: move common funcs to cpu.h, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 09/20] target-mips: add MSA branch instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 02/20] target-mips: add MSA exceptions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 06/20] target-mips: add MSA opcode enum, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 10/20] target-mips: add MSA I8 format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 11/20] target-mips: add MSA I5 format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 12/20] target-mips: add MSA BIT format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 14/20] target-mips: add MSA ELM format instructions,
Yongbok Kim <=
- [Qemu-devel] [PATCH 16/20] target-mips: add MSA VEC/2R format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 18/20] target-mips: add MSA MI10 format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 15/20] target-mips: add MSA 3RF format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 20/20] target-mips: add MSA support to mips32r5-generic, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 13/20] target-mips: add MSA 3R format instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 19/20] disas/mips.c: disassemble MSA instructions, Yongbok Kim, 2014/07/14
- [Qemu-devel] [PATCH 17/20] target-mips: add MSA 2RF format instructions, Yongbok Kim, 2014/07/14