mirror of
https://github.com/qemu/qemu.git
synced 2024-11-25 20:03:37 +08:00
target-mips: add MSA BIT format instructions
add MSA BIT format instructions Reviewed-by: Leon Alrae <leon.alrae@imgtec.com> Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
This commit is contained in:
parent
80e7159184
commit
d4cf28dec2
@ -771,3 +771,16 @@ DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s32)
|
||||
DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, s32)
|
||||
|
||||
DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_bclri_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32)
|
||||
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_srari_df, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32)
|
||||
|
@ -255,3 +255,199 @@ void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Data format bit position and unsigned values */
|
||||
#define BIT_POSITION(x, df) ((uint64_t)(x) % DF_BITS(df))
|
||||
|
||||
static inline int64_t msa_sll_df(uint32_t df, int64_t arg1, int64_t arg2)
|
||||
{
|
||||
int32_t b_arg2 = BIT_POSITION(arg2, df);
|
||||
return arg1 << b_arg2;
|
||||
}
|
||||
|
||||
static inline int64_t msa_sra_df(uint32_t df, int64_t arg1, int64_t arg2)
|
||||
{
|
||||
int32_t b_arg2 = BIT_POSITION(arg2, df);
|
||||
return arg1 >> b_arg2;
|
||||
}
|
||||
|
||||
static inline int64_t msa_srl_df(uint32_t df, int64_t arg1, int64_t arg2)
|
||||
{
|
||||
uint64_t u_arg1 = UNSIGNED(arg1, df);
|
||||
int32_t b_arg2 = BIT_POSITION(arg2, df);
|
||||
return u_arg1 >> b_arg2;
|
||||
}
|
||||
|
||||
static inline int64_t msa_bclr_df(uint32_t df, int64_t arg1, int64_t arg2)
|
||||
{
|
||||
int32_t b_arg2 = BIT_POSITION(arg2, df);
|
||||
return UNSIGNED(arg1 & (~(1LL << b_arg2)), df);
|
||||
}
|
||||
|
||||
static inline int64_t msa_bset_df(uint32_t df, int64_t arg1,
|
||||
int64_t arg2)
|
||||
{
|
||||
int32_t b_arg2 = BIT_POSITION(arg2, df);
|
||||
return UNSIGNED(arg1 | (1LL << b_arg2), df);
|
||||
}
|
||||
|
||||
static inline int64_t msa_bneg_df(uint32_t df, int64_t arg1, int64_t arg2)
|
||||
{
|
||||
int32_t b_arg2 = BIT_POSITION(arg2, df);
|
||||
return UNSIGNED(arg1 ^ (1LL << b_arg2), df);
|
||||
}
|
||||
|
||||
static inline int64_t msa_binsl_df(uint32_t df, int64_t dest, int64_t arg1,
|
||||
int64_t arg2)
|
||||
{
|
||||
uint64_t u_arg1 = UNSIGNED(arg1, df);
|
||||
uint64_t u_dest = UNSIGNED(dest, df);
|
||||
int32_t sh_d = BIT_POSITION(arg2, df) + 1;
|
||||
int32_t sh_a = DF_BITS(df) - sh_d;
|
||||
if (sh_d == DF_BITS(df)) {
|
||||
return u_arg1;
|
||||
} else {
|
||||
return UNSIGNED(UNSIGNED(u_dest << sh_d, df) >> sh_d, df) |
|
||||
UNSIGNED(UNSIGNED(u_arg1 >> sh_a, df) << sh_a, df);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int64_t msa_binsr_df(uint32_t df, int64_t dest, int64_t arg1,
|
||||
int64_t arg2)
|
||||
{
|
||||
uint64_t u_arg1 = UNSIGNED(arg1, df);
|
||||
uint64_t u_dest = UNSIGNED(dest, df);
|
||||
int32_t sh_d = BIT_POSITION(arg2, df) + 1;
|
||||
int32_t sh_a = DF_BITS(df) - sh_d;
|
||||
if (sh_d == DF_BITS(df)) {
|
||||
return u_arg1;
|
||||
} else {
|
||||
return UNSIGNED(UNSIGNED(u_dest >> sh_d, df) << sh_d, df) |
|
||||
UNSIGNED(UNSIGNED(u_arg1 << sh_a, df) >> sh_a, df);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int64_t msa_sat_s_df(uint32_t df, int64_t arg, uint32_t m)
|
||||
{
|
||||
return arg < M_MIN_INT(m+1) ? M_MIN_INT(m+1) :
|
||||
arg > M_MAX_INT(m+1) ? M_MAX_INT(m+1) :
|
||||
arg;
|
||||
}
|
||||
|
||||
static inline int64_t msa_sat_u_df(uint32_t df, int64_t arg, uint32_t m)
|
||||
{
|
||||
uint64_t u_arg = UNSIGNED(arg, df);
|
||||
return u_arg < M_MAX_UINT(m+1) ? u_arg :
|
||||
M_MAX_UINT(m+1);
|
||||
}
|
||||
|
||||
static inline int64_t msa_srar_df(uint32_t df, int64_t arg1, int64_t arg2)
|
||||
{
|
||||
int32_t b_arg2 = BIT_POSITION(arg2, df);
|
||||
if (b_arg2 == 0) {
|
||||
return arg1;
|
||||
} else {
|
||||
int64_t r_bit = (arg1 >> (b_arg2 - 1)) & 1;
|
||||
return (arg1 >> b_arg2) + r_bit;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int64_t msa_srlr_df(uint32_t df, int64_t arg1, int64_t arg2)
|
||||
{
|
||||
uint64_t u_arg1 = UNSIGNED(arg1, df);
|
||||
int32_t b_arg2 = BIT_POSITION(arg2, df);
|
||||
if (b_arg2 == 0) {
|
||||
return u_arg1;
|
||||
} else {
|
||||
uint64_t r_bit = (u_arg1 >> (b_arg2 - 1)) & 1;
|
||||
return (u_arg1 >> b_arg2) + r_bit;
|
||||
}
|
||||
}
|
||||
|
||||
#define MSA_BINOP_IMMU_DF(helper, func) \
|
||||
void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, uint32_t wd, \
|
||||
uint32_t ws, uint32_t u5) \
|
||||
{ \
|
||||
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], u5); \
|
||||
} \
|
||||
break; \
|
||||
case DF_HALF: \
|
||||
for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \
|
||||
pwd->h[i] = msa_ ## func ## _df(df, pws->h[i], u5); \
|
||||
} \
|
||||
break; \
|
||||
case DF_WORD: \
|
||||
for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \
|
||||
pwd->w[i] = msa_ ## func ## _df(df, pws->w[i], u5); \
|
||||
} \
|
||||
break; \
|
||||
case DF_DOUBLE: \
|
||||
for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \
|
||||
pwd->d[i] = msa_ ## func ## _df(df, pws->d[i], u5); \
|
||||
} \
|
||||
break; \
|
||||
default: \
|
||||
assert(0); \
|
||||
} \
|
||||
}
|
||||
|
||||
MSA_BINOP_IMMU_DF(slli, sll)
|
||||
MSA_BINOP_IMMU_DF(srai, sra)
|
||||
MSA_BINOP_IMMU_DF(srli, srl)
|
||||
MSA_BINOP_IMMU_DF(bclri, bclr)
|
||||
MSA_BINOP_IMMU_DF(bseti, bset)
|
||||
MSA_BINOP_IMMU_DF(bnegi, bneg)
|
||||
MSA_BINOP_IMMU_DF(sat_s, sat_s)
|
||||
MSA_BINOP_IMMU_DF(sat_u, sat_u)
|
||||
MSA_BINOP_IMMU_DF(srari, srar)
|
||||
MSA_BINOP_IMMU_DF(srlri, srlr)
|
||||
#undef MSA_BINOP_IMMU_DF
|
||||
|
||||
#define MSA_TEROP_IMMU_DF(helper, func) \
|
||||
void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, \
|
||||
uint32_t wd, uint32_t ws, uint32_t u5) \
|
||||
{ \
|
||||
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, pwd->b[i], pws->b[i], \
|
||||
u5); \
|
||||
} \
|
||||
break; \
|
||||
case DF_HALF: \
|
||||
for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \
|
||||
pwd->h[i] = msa_ ## func ## _df(df, pwd->h[i], pws->h[i], \
|
||||
u5); \
|
||||
} \
|
||||
break; \
|
||||
case DF_WORD: \
|
||||
for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \
|
||||
pwd->w[i] = msa_ ## func ## _df(df, pwd->w[i], pws->w[i], \
|
||||
u5); \
|
||||
} \
|
||||
break; \
|
||||
case DF_DOUBLE: \
|
||||
for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \
|
||||
pwd->d[i] = msa_ ## func ## _df(df, pwd->d[i], pws->d[i], \
|
||||
u5); \
|
||||
} \
|
||||
break; \
|
||||
default: \
|
||||
assert(0); \
|
||||
} \
|
||||
}
|
||||
|
||||
MSA_TEROP_IMMU_DF(binsli, binsl)
|
||||
MSA_TEROP_IMMU_DF(binsri, binsr)
|
||||
#undef MSA_TEROP_IMMU_DF
|
||||
|
@ -17465,6 +17465,90 @@ static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
|
||||
tcg_temp_free_i32(timm);
|
||||
}
|
||||
|
||||
static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
|
||||
{
|
||||
#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
|
||||
uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
|
||||
uint32_t df = 0, m = 0;
|
||||
uint8_t ws = (ctx->opcode >> 11) & 0x1f;
|
||||
uint8_t wd = (ctx->opcode >> 6) & 0x1f;
|
||||
|
||||
TCGv_i32 tdf;
|
||||
TCGv_i32 tm;
|
||||
TCGv_i32 twd;
|
||||
TCGv_i32 tws;
|
||||
|
||||
if ((dfm & 0x40) == 0x00) {
|
||||
m = dfm & 0x3f;
|
||||
df = DF_DOUBLE;
|
||||
} else if ((dfm & 0x60) == 0x40) {
|
||||
m = dfm & 0x1f;
|
||||
df = DF_WORD;
|
||||
} else if ((dfm & 0x70) == 0x60) {
|
||||
m = dfm & 0x0f;
|
||||
df = DF_HALF;
|
||||
} else if ((dfm & 0x78) == 0x70) {
|
||||
m = dfm & 0x7;
|
||||
df = DF_BYTE;
|
||||
} else {
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
return;
|
||||
}
|
||||
|
||||
tdf = tcg_const_i32(df);
|
||||
tm = tcg_const_i32(m);
|
||||
twd = tcg_const_i32(wd);
|
||||
tws = tcg_const_i32(ws);
|
||||
|
||||
switch (MASK_MSA_BIT(ctx->opcode)) {
|
||||
case OPC_SLLI_df:
|
||||
gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
|
||||
break;
|
||||
case OPC_SRAI_df:
|
||||
gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
|
||||
break;
|
||||
case OPC_SRLI_df:
|
||||
gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
|
||||
break;
|
||||
case OPC_BCLRI_df:
|
||||
gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
|
||||
break;
|
||||
case OPC_BSETI_df:
|
||||
gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
|
||||
break;
|
||||
case OPC_BNEGI_df:
|
||||
gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
|
||||
break;
|
||||
case OPC_BINSLI_df:
|
||||
gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
|
||||
break;
|
||||
case OPC_BINSRI_df:
|
||||
gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
|
||||
break;
|
||||
case OPC_SAT_S_df:
|
||||
gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
|
||||
break;
|
||||
case OPC_SAT_U_df:
|
||||
gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
|
||||
break;
|
||||
case OPC_SRARI_df:
|
||||
gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
|
||||
break;
|
||||
case OPC_SRLRI_df:
|
||||
gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
|
||||
break;
|
||||
default:
|
||||
MIPS_INVAL("MSA instruction");
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
break;
|
||||
}
|
||||
|
||||
tcg_temp_free_i32(tdf);
|
||||
tcg_temp_free_i32(tm);
|
||||
tcg_temp_free_i32(twd);
|
||||
tcg_temp_free_i32(tws);
|
||||
}
|
||||
|
||||
static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
|
||||
{
|
||||
uint32_t opcode = ctx->opcode;
|
||||
@ -17481,6 +17565,10 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
|
||||
case OPC_MSA_I5_07:
|
||||
gen_msa_i5(env, ctx);
|
||||
break;
|
||||
case OPC_MSA_BIT_09:
|
||||
case OPC_MSA_BIT_0A:
|
||||
gen_msa_bit(env, ctx);
|
||||
break;
|
||||
default:
|
||||
MIPS_INVAL("MSA instruction");
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
|
Loading…
Reference in New Issue
Block a user