mirror of https://gitee.com/openkylin/qemu.git
target-mips: add MSA VEC/2R format instructions
add MSA VEC/2R format instructions Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
This commit is contained in:
parent
7d05b9c86f
commit
cbe50b9a8e
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue