Skip to content

Commit

Permalink
target-mips: add MSA VEC/2R format instructions
Browse files Browse the repository at this point in the history
add MSA VEC/2R format instructions

Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
  • Loading branch information
yongbok authored and Leon Alrae committed Nov 3, 2014
1 parent 7d05b9c commit cbe50b9
Show file tree
Hide file tree
Showing 3 changed files with 265 additions and 0 deletions.
12 changes: 12 additions & 0 deletions target-mips/helper.h
Expand Up @@ -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)
140 changes: 140 additions & 0 deletions target-mips/msa_helper.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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)

Expand Down
113 changes: 113 additions & 0 deletions target-mips/translate.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit cbe50b9

Please sign in to comment.