[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 15/19] target-mips: add MSA VEC/2R format instruc
From: |
Yongbok Kim |
Subject: |
[Qemu-devel] [PATCH v3 15/19] target-mips: add MSA VEC/2R format instructions |
Date: |
Sat, 1 Nov 2014 05:28:49 +0000 |
add MSA VEC/2R format instructions
Signed-off-by: Yongbok Kim <address@hidden>
---
target-mips/helper.h | 12 ++++
target-mips/msa_helper.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++
target-mips/translate.c | 113 +++++++++++++++++++++++++++++++++++++
3 files changed, 265 insertions(+), 0 deletions(-)
diff --git a/target-mips/helper.h b/target-mips/helper.h
index cee4eb4..3185c1d 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -900,3 +900,15 @@ DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_msubr_q_df, void, env, i32, i32, i32, i32)
+
+DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_pcnt_df, void, env, 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)
diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c
index cba7439..db7b7a1 100644
--- a/target-mips/msa_helper.c
+++ b/target-mips/msa_helper.c
@@ -114,6 +114,34 @@ void helper_msa_shf_df(CPUMIPSState *env, uint32_t df,
uint32_t wd,
msa_move_v(pwd, pwx);
}
+#define MSA_FN_VECTOR(FUNC, DEST, OPERATION) \
+void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \
+ uint32_t wt) \
+{ \
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \
+ uint32_t i; \
+ for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \
+ DEST = OPERATION; \
+ } \
+}
+
+MSA_FN_VECTOR(and_v, pwd->d[i], pws->d[i] & pwt->d[i])
+MSA_FN_VECTOR(or_v, pwd->d[i], pws->d[i] | pwt->d[i])
+MSA_FN_VECTOR(nor_v, pwd->d[i], ~(pws->d[i] | pwt->d[i]))
+MSA_FN_VECTOR(xor_v, pwd->d[i], pws->d[i] ^ pwt->d[i])
+MSA_FN_VECTOR(bmnz_v, pwd->d[i],
+ BIT_MOVE_IF_NOT_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE))
+MSA_FN_VECTOR(bmz_v, pwd->d[i],
+ BIT_MOVE_IF_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE))
+MSA_FN_VECTOR(bsel_v, pwd->d[i],
+ BIT_SELECT(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE))
+#undef BIT_MOVE_IF_NOT_ZERO
+#undef BIT_MOVE_IF_ZERO
+#undef BIT_SELECT
+#undef MSA_FN_VECTOR
+
static inline int64_t msa_addv_df(uint32_t df, int64_t arg1, int64_t arg2)
{
return arg1 + arg2;
@@ -1359,6 +1387,118 @@ void helper_msa_move_v(CPUMIPSState *env, uint32_t wd,
uint32_t ws)
msa_move_v(pwd, pws);
}
+static inline int64_t msa_pcnt_df(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;
+}
+
+static inline int64_t msa_nlzc_df(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;
+}
+
+static inline int64_t msa_nloc_df(uint32_t df, int64_t arg)
+{
+ return msa_nlzc_df(df, UNSIGNED((~arg), df));
+}
+
+void helper_msa_fill_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
+ uint32_t rs)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ uint32_t i;
+
+ switch (df) {
+ case DF_BYTE:
+ for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {
+ pwd->b[i] = (int8_t)env->active_tc.gpr[rs];
+ }
+ break;
+ case DF_HALF:
+ for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {
+ pwd->h[i] = (int16_t)env->active_tc.gpr[rs];
+ }
+ break;
+ case DF_WORD:
+ for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
+ pwd->w[i] = (int32_t)env->active_tc.gpr[rs];
+ }
+ break;
+ case DF_DOUBLE:
+ for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
+ pwd->d[i] = (int64_t)env->active_tc.gpr[rs];
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+#define MSA_UNOP_DF(func) \
+void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \
+ uint32_t wd, uint32_t ws) \
+{ \
+ 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]); \
+ } \
+ break; \
+ case DF_HALF: \
+ for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \
+ pwd->h[i] = msa_ ## func ## _df(df, pws->h[i]); \
+ } \
+ break; \
+ case DF_WORD: \
+ for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \
+ pwd->w[i] = msa_ ## func ## _df(df, pws->w[i]); \
+ } \
+ break; \
+ case DF_DOUBLE: \
+ for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \
+ pwd->d[i] = msa_ ## func ## _df(df, pws->d[i]); \
+ } \
+ break; \
+ default: \
+ assert(0); \
+ } \
+}
+
+MSA_UNOP_DF(nlzc)
+MSA_UNOP_DF(nloc)
+MSA_UNOP_DF(pcnt)
+
#define FLOAT_ONE32 make_float32(0x3f8 << 20)
#define FLOAT_ONE64 make_float64(0x3ffULL << 52)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index aae023c..acaf5a3 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -18053,6 +18053,116 @@ static void gen_msa_3rf(CPUMIPSState *env,
DisasContext *ctx)
tcg_temp_free_i32(tdf);
}
+static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
+{
+#define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
+ (op & (0x7 << 18)))
+ uint8_t wt = (ctx->opcode >> 16) & 0x1f;
+ uint8_t ws = (ctx->opcode >> 11) & 0x1f;
+ uint8_t wd = (ctx->opcode >> 6) & 0x1f;
+ uint8_t df = (ctx->opcode >> 16) & 0x3;
+ TCGv_i32 twd = tcg_const_i32(wd);
+ TCGv_i32 tws = tcg_const_i32(ws);
+ TCGv_i32 twt = tcg_const_i32(wt);
+ TCGv_i32 tdf = tcg_const_i32(df);
+
+ switch (MASK_MSA_2R(ctx->opcode)) {
+ case OPC_FILL_df:
+#if !defined(TARGET_MIPS64)
+ /* Double format valid only for MIPS64 */
+ if (df == DF_DOUBLE) {
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+#endif
+ gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
+ break;
+ case OPC_PCNT_df:
+ gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_NLOC_df:
+ gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
+ break;
+ case OPC_NLZC_df:
+ gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
+ break;
+ default:
+ MIPS_INVAL("MSA instruction");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+
+ tcg_temp_free_i32(twd);
+ tcg_temp_free_i32(tws);
+ tcg_temp_free_i32(twt);
+ tcg_temp_free_i32(tdf);
+}
+
+static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
+{
+#define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
+ uint8_t wt = (ctx->opcode >> 16) & 0x1f;
+ uint8_t ws = (ctx->opcode >> 11) & 0x1f;
+ uint8_t wd = (ctx->opcode >> 6) & 0x1f;
+ 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(ctx->opcode)) {
+ case OPC_AND_V:
+ gen_helper_msa_and_v(cpu_env, twd, tws, twt);
+ break;
+ case OPC_OR_V:
+ gen_helper_msa_or_v(cpu_env, twd, tws, twt);
+ break;
+ case OPC_NOR_V:
+ gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
+ break;
+ case OPC_XOR_V:
+ gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
+ break;
+ case OPC_BMNZ_V:
+ gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
+ break;
+ case OPC_BMZ_V:
+ gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
+ break;
+ case OPC_BSEL_V:
+ gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
+ break;
+ default:
+ MIPS_INVAL("MSA instruction");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+
+ tcg_temp_free_i32(twd);
+ tcg_temp_free_i32(tws);
+ tcg_temp_free_i32(twt);
+}
+
+static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
+{
+ switch (MASK_MSA_VEC(ctx->opcode)) {
+ case OPC_AND_V:
+ case OPC_OR_V:
+ case OPC_NOR_V:
+ case OPC_XOR_V:
+ case OPC_BMNZ_V:
+ case OPC_BMZ_V:
+ case OPC_BSEL_V:
+ gen_msa_vec_v(env, ctx);
+ break;
+ case OPC_MSA_2R:
+ gen_msa_2r(env, ctx);
+ break;
+ default:
+ MIPS_INVAL("MSA instruction");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+}
+
static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
{
uint32_t opcode = ctx->opcode;
@@ -18092,6 +18202,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
- [Qemu-devel] [PATCH v3 06/19] target-mips: add msa_reset(), global msa register, (continued)
- [Qemu-devel] [PATCH v3 06/19] target-mips: add msa_reset(), global msa register, Yongbok Kim, 2014/11/01
- [Qemu-devel] [PATCH v3 07/19] target-mips: add msa_helper.c, Yongbok Kim, 2014/11/01
- [Qemu-devel] [PATCH v3 08/19] target-mips: add MSA branch instructions, Yongbok Kim, 2014/11/01
- [Qemu-devel] [PATCH v3 09/19] target-mips: add MSA I8 format instructions, Yongbok Kim, 2014/11/01
- [Qemu-devel] [PATCH v3 10/19] target-mips: add MSA I5 format instruction, Yongbok Kim, 2014/11/01
- [Qemu-devel] [PATCH v3 11/19] target-mips: add MSA BIT format instructions, Yongbok Kim, 2014/11/01
- [Qemu-devel] [PATCH v3 12/19] target-mips: add MSA 3R format instructions, Yongbok Kim, 2014/11/01
- [Qemu-devel] [PATCH v3 13/19] target-mips: add MSA ELM format instructions, Yongbok Kim, 2014/11/01
- [Qemu-devel] [PATCH v3 14/19] target-mips: add MSA 3RF format instructions, Yongbok Kim, 2014/11/01
- [Qemu-devel] [PATCH v3 15/19] target-mips: add MSA VEC/2R format instructions,
Yongbok Kim <=
- [Qemu-devel] [PATCH v3 16/19] target-mips: add MSA 2RF format instructions, Yongbok Kim, 2014/11/01
- [Qemu-devel] [PATCH v3 17/19] target-mips: add MSA MI10 format instructions, Yongbok Kim, 2014/11/01
- [Qemu-devel] [PATCH v3 18/19] disas/mips.c: disassemble MSA instructions, Yongbok Kim, 2014/11/01
- [Qemu-devel] [PATCH v3 19/19] target-mips: add MSA support to mips32r5-generic, Yongbok Kim, 2014/11/01
- Re: [Qemu-devel] [PATCH v3 00/19] target-mips: add MSA module, Leon Alrae, 2014/11/02