mirror of https://github.com/xemu-project/xemu.git
target-mips: add MSA ELM format instructions
add MSA ELM 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
28f99f08cf
commit
1e608ec14e
|
@ -848,3 +848,13 @@ DEF_HELPER_5(msa_hadd_s_df, void, env, i32, i32, i32, i32)
|
||||||
DEF_HELPER_5(msa_hadd_u_df, void, env, i32, i32, i32, i32)
|
DEF_HELPER_5(msa_hadd_u_df, void, env, i32, i32, i32, i32)
|
||||||
DEF_HELPER_5(msa_hsub_s_df, void, env, i32, i32, i32, i32)
|
DEF_HELPER_5(msa_hsub_s_df, void, env, i32, i32, i32, i32)
|
||||||
DEF_HELPER_5(msa_hsub_u_df, void, env, i32, i32, i32, i32)
|
DEF_HELPER_5(msa_hsub_u_df, void, env, i32, i32, i32, i32)
|
||||||
|
|
||||||
|
DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32)
|
||||||
|
DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32)
|
||||||
|
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_5(msa_insert_df, void, env, i32, i32, i32, i32)
|
||||||
|
DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32)
|
||||||
|
DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32)
|
||||||
|
DEF_HELPER_2(msa_cfcmsa, tl, env, i32)
|
||||||
|
DEF_HELPER_3(msa_move_v, void, env, i32, i32)
|
||||||
|
|
|
@ -1108,3 +1108,165 @@ MSA_FN_DF(vshf_df)
|
||||||
#undef MSA_DO
|
#undef MSA_DO
|
||||||
#undef MSA_LOOP_COND
|
#undef MSA_LOOP_COND
|
||||||
#undef MSA_FN_DF
|
#undef MSA_FN_DF
|
||||||
|
|
||||||
|
void helper_msa_sldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||||
|
uint32_t ws, uint32_t n)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
wr_t *pws = &(env->active_fpu.fpr[ws].wr);
|
||||||
|
|
||||||
|
msa_sld_df(df, pwd, pws, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_splati_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||||
|
uint32_t ws, uint32_t n)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
wr_t *pws = &(env->active_fpu.fpr[ws].wr);
|
||||||
|
|
||||||
|
msa_splat_df(df, pwd, pws, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_copy_s_df(CPUMIPSState *env, uint32_t df, uint32_t rd,
|
||||||
|
uint32_t ws, uint32_t n)
|
||||||
|
{
|
||||||
|
n %= DF_ELEMENTS(df);
|
||||||
|
|
||||||
|
switch (df) {
|
||||||
|
case DF_BYTE:
|
||||||
|
env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n];
|
||||||
|
break;
|
||||||
|
case DF_HALF:
|
||||||
|
env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n];
|
||||||
|
break;
|
||||||
|
case DF_WORD:
|
||||||
|
env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n];
|
||||||
|
break;
|
||||||
|
#ifdef TARGET_MIPS64
|
||||||
|
case DF_DOUBLE:
|
||||||
|
env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n];
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
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);
|
||||||
|
|
||||||
|
switch (df) {
|
||||||
|
case DF_BYTE:
|
||||||
|
env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n];
|
||||||
|
break;
|
||||||
|
case DF_HALF:
|
||||||
|
env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n];
|
||||||
|
break;
|
||||||
|
case DF_WORD:
|
||||||
|
env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n];
|
||||||
|
break;
|
||||||
|
#ifdef TARGET_MIPS64
|
||||||
|
case DF_DOUBLE:
|
||||||
|
env->active_tc.gpr[rd] = (uint64_t)env->active_fpu.fpr[ws].wr.d[n];
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_insert_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||||
|
uint32_t rs_num, uint32_t n)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
target_ulong rs = env->active_tc.gpr[rs_num];
|
||||||
|
|
||||||
|
switch (df) {
|
||||||
|
case DF_BYTE:
|
||||||
|
pwd->b[n] = (int8_t)rs;
|
||||||
|
break;
|
||||||
|
case DF_HALF:
|
||||||
|
pwd->h[n] = (int16_t)rs;
|
||||||
|
break;
|
||||||
|
case DF_WORD:
|
||||||
|
pwd->w[n] = (int32_t)rs;
|
||||||
|
break;
|
||||||
|
case DF_DOUBLE:
|
||||||
|
pwd->d[n] = (int64_t)rs;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_insve_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||||
|
uint32_t ws, uint32_t n)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
wr_t *pws = &(env->active_fpu.fpr[ws].wr);
|
||||||
|
|
||||||
|
switch (df) {
|
||||||
|
case DF_BYTE:
|
||||||
|
pwd->b[n] = (int8_t)pws->b[0];
|
||||||
|
break;
|
||||||
|
case DF_HALF:
|
||||||
|
pwd->h[n] = (int16_t)pws->h[0];
|
||||||
|
break;
|
||||||
|
case DF_WORD:
|
||||||
|
pwd->w[n] = (int32_t)pws->w[0];
|
||||||
|
break;
|
||||||
|
case DF_DOUBLE:
|
||||||
|
pwd->d[n] = (int64_t)pws->d[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_ctcmsa(CPUMIPSState *env, target_ulong elm, uint32_t cd)
|
||||||
|
{
|
||||||
|
switch (cd) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
env->active_tc.msacsr = (int32_t)elm & MSACSR_MASK;
|
||||||
|
/* set float_status rounding mode */
|
||||||
|
set_float_rounding_mode(
|
||||||
|
ieee_rm[(env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM],
|
||||||
|
&env->active_tc.msa_fp_status);
|
||||||
|
/* set float_status flush modes */
|
||||||
|
set_flush_to_zero(
|
||||||
|
(env->active_tc.msacsr & MSACSR_FS_MASK) != 0 ? 1 : 0,
|
||||||
|
&env->active_tc.msa_fp_status);
|
||||||
|
set_flush_inputs_to_zero(
|
||||||
|
(env->active_tc.msacsr & MSACSR_FS_MASK) != 0 ? 1 : 0,
|
||||||
|
&env->active_tc.msa_fp_status);
|
||||||
|
/* check exception */
|
||||||
|
if ((GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED)
|
||||||
|
& GET_FP_CAUSE(env->active_tc.msacsr)) {
|
||||||
|
helper_raise_exception(env, EXCP_MSAFPE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_msa_cfcmsa(CPUMIPSState *env, uint32_t cs)
|
||||||
|
{
|
||||||
|
switch (cs) {
|
||||||
|
case 0:
|
||||||
|
return env->msair;
|
||||||
|
case 1:
|
||||||
|
return env->active_tc.msacsr & MSACSR_MASK;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_move_v(CPUMIPSState *env, uint32_t wd, uint32_t ws)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
wr_t *pws = &(env->active_fpu.fpr[ws].wr);
|
||||||
|
|
||||||
|
msa_move_v(pwd, pws);
|
||||||
|
}
|
||||||
|
|
|
@ -17780,6 +17780,121 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
|
||||||
tcg_temp_free_i32(tdf);
|
tcg_temp_free_i32(tdf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
|
||||||
|
{
|
||||||
|
#define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
|
||||||
|
uint8_t source = (ctx->opcode >> 11) & 0x1f;
|
||||||
|
uint8_t dest = (ctx->opcode >> 6) & 0x1f;
|
||||||
|
TCGv telm = tcg_temp_new();
|
||||||
|
TCGv_i32 tsr = tcg_const_i32(source);
|
||||||
|
TCGv_i32 tdt = tcg_const_i32(dest);
|
||||||
|
|
||||||
|
switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
|
||||||
|
case OPC_CTCMSA:
|
||||||
|
gen_load_gpr(telm, source);
|
||||||
|
gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
|
||||||
|
break;
|
||||||
|
case OPC_CFCMSA:
|
||||||
|
gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
|
||||||
|
gen_store_gpr(telm, dest);
|
||||||
|
break;
|
||||||
|
case OPC_MOVE_V:
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
|
||||||
|
uint32_t n)
|
||||||
|
{
|
||||||
|
#define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
|
||||||
|
uint8_t ws = (ctx->opcode >> 11) & 0x1f;
|
||||||
|
uint8_t wd = (ctx->opcode >> 6) & 0x1f;
|
||||||
|
|
||||||
|
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(ctx->opcode)) {
|
||||||
|
case OPC_SLDI_df:
|
||||||
|
gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
case OPC_SPLATI_df:
|
||||||
|
gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
case OPC_INSVE_df:
|
||||||
|
gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
case OPC_COPY_S_df:
|
||||||
|
case OPC_COPY_U_df:
|
||||||
|
case OPC_INSERT_df:
|
||||||
|
#if !defined(TARGET_MIPS64)
|
||||||
|
/* Double format valid only for MIPS64 */
|
||||||
|
if (df == DF_DOUBLE) {
|
||||||
|
generate_exception(ctx, EXCP_RI);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
switch (MASK_MSA_ELM(ctx->opcode)) {
|
||||||
|
case OPC_COPY_S_df:
|
||||||
|
gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
case OPC_COPY_U_df:
|
||||||
|
gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
case OPC_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_elm(CPUMIPSState *env, DisasContext *ctx)
|
||||||
|
{
|
||||||
|
uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
|
||||||
|
uint32_t df = 0, n = 0;
|
||||||
|
|
||||||
|
if ((dfn & 0x30) == 0x00) {
|
||||||
|
n = dfn & 0x0f;
|
||||||
|
df = DF_BYTE;
|
||||||
|
} else if ((dfn & 0x38) == 0x20) {
|
||||||
|
n = dfn & 0x07;
|
||||||
|
df = DF_HALF;
|
||||||
|
} else if ((dfn & 0x3c) == 0x30) {
|
||||||
|
n = dfn & 0x03;
|
||||||
|
df = DF_WORD;
|
||||||
|
} else if ((dfn & 0x3e) == 0x38) {
|
||||||
|
n = dfn & 0x01;
|
||||||
|
df = DF_DOUBLE;
|
||||||
|
} else if (dfn == 0x3E) {
|
||||||
|
/* CTCMSA, CFCMSA, MOVE.V */
|
||||||
|
gen_msa_elm_3e(env, ctx);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
generate_exception(ctx, EXCP_RI);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_msa_elm_df(env, ctx, df, n);
|
||||||
|
}
|
||||||
|
|
||||||
static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
|
static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
|
||||||
{
|
{
|
||||||
uint32_t opcode = ctx->opcode;
|
uint32_t opcode = ctx->opcode;
|
||||||
|
@ -17811,6 +17926,9 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
|
||||||
case OPC_MSA_3R_15:
|
case OPC_MSA_3R_15:
|
||||||
gen_msa_3r(env, ctx);
|
gen_msa_3r(env, ctx);
|
||||||
break;
|
break;
|
||||||
|
case OPC_MSA_ELM:
|
||||||
|
gen_msa_elm(env, ctx);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
MIPS_INVAL("MSA instruction");
|
MIPS_INVAL("MSA instruction");
|
||||||
generate_exception(ctx, EXCP_RI);
|
generate_exception(ctx, EXCP_RI);
|
||||||
|
|
Loading…
Reference in New Issue