add MSA ELM format instructions Signed-off-by: Yongbok Kim <yongbok....@imgtec.com> --- target-mips/helper.h | 9 ++ target-mips/msa_helper.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++ target-mips/translate.c | 136 ++++++++++++++++++++++++++ 3 files changed, 384 insertions(+), 0 deletions(-)
diff --git a/target-mips/helper.h b/target-mips/helper.h index 00705c4..e13daec 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -720,6 +720,7 @@ DEF_HELPER_5(msa_bset_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_ceq_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s64) +DEF_HELPER_2(msa_cfcmsa, tl, env, i32) DEF_HELPER_5(msa_cle_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_cle_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s64) @@ -728,6 +729,9 @@ DEF_HELPER_5(msa_clt_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_clt_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s64) +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_3(msa_ctcmsa, void, env, tl, i32) DEF_HELPER_5(msa_div_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_div_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32) @@ -744,6 +748,8 @@ DEF_HELPER_5(msa_ilvev_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_ilvl_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_ilvod_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_ilvr_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_4(msa_ldi_df, void, env, i32, i32, i32) DEF_HELPER_5(msa_maddv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_max_a_df, void, env, i32, i32, i32, i32) @@ -758,6 +764,7 @@ DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_mod_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_mod_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_3(msa_move_v, void, env, i32, i32) DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32) DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) @@ -768,9 +775,11 @@ 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_shf_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sll_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sra_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_srar_df, void, env, i32, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index bb4ea65..220a0cd 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -1166,6 +1166,59 @@ void helper_msa_clti_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, } } +void helper_msa_copy_s_df(CPUMIPSState *env, uint32_t df, uint32_t rd, + uint32_t ws, uint32_t n) +{ + n %= DF_ELEMENTS(df, MSA_WRLEN); + msa_check_index(env, (uint32_t)df, (uint32_t)n); + switch (df) { + case DF_BYTE: /* b */ + env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n]; + break; + case DF_HALF: /* h */ + env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n]; + break; + case DF_WORD: /* w */ + env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n]; + break; +#ifdef TARGET_MIPS64 + case DF_DOUBLE: /* d */ + env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n]; + break; +#endif + default: + /* shouldn't get here */ + 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, MSA_WRLEN); + msa_check_index(env, (uint32_t)df, (uint32_t)n); + switch (df) { + case DF_BYTE: /* b */ + env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n]; + break; + case DF_HALF: /* h */ + env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n]; + break; + case DF_WORD: /* w */ + env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n]; + break; +#ifdef TARGET_MIPS64 + case DF_DOUBLE: /* d */ + env->active_tc.gpr[rd] = (uint64_t)env->active_fpu.fpr[ws].wr.d[n]; + break; +#endif + default: + /* shouldn't get here */ + assert(0); + } +} + + #define SIGNED_EVEN(a, df) \ ((((int64_t)(a)) << (64 - DF_BITS(df)/2)) >> (64 - DF_BITS(df)/2)) #define UNSIGNED_EVEN(a, df) \ @@ -2142,6 +2195,27 @@ void helper_msa_splat_df(CPUMIPSState *env, uint32_t df, uint32_t wd, } } +void helper_msa_splati_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t n) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + void *pws = &(env->active_fpu.fpr[ws]); + msa_splat_df(env, df, pwd, pws, n); + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +void helper_msa_move_v(CPUMIPSState *env, uint32_t wd, uint32_t ws) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + void *pws = &(env->active_fpu.fpr[ws]); + msa_move_v(pwd, pws); + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t s10) { @@ -2177,6 +2251,73 @@ void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, } } +static inline void msa_insert_df(CPUMIPSState *env, uint32_t df, void *pwd, + target_ulong rs, uint32_t n) +{ + msa_check_index(env, df, n); + switch (df) { + case DF_BYTE: + B(pwd, n) = (int8_t)rs; + break; + case DF_HALF: + H(pwd, n) = (int16_t)rs; + break; + case DF_WORD: + W(pwd, n) = (int32_t)rs; + break; + case DF_DOUBLE: + D(pwd, n) = (int64_t)rs; + break; + default: + /* shouldn't get here */ + assert(0); + } +} + +void helper_msa_insert_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t rs, uint32_t n) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + msa_insert_df(env, df, pwd, env->active_tc.gpr[rs], n); + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline void msa_insve_df(CPUMIPSState *env, uint32_t df, void *pwd, + void *pws, uint32_t n) +{ + msa_check_index(env, df, n); + switch (df) { + case DF_BYTE: + B(pwd, n) = (int8_t)B(pws, 0); + break; + case DF_HALF: + H(pwd, n) = (int16_t)H(pws, 0); + break; + case DF_WORD: + W(pwd, n) = (int32_t)W(pws, 0); + break; + case DF_DOUBLE: + D(pwd, n) = (int64_t)D(pws, 0); + break; + default: + /* shouldn't get here */ + assert(0); + } +} + +void helper_msa_insve_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t n) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + void *pws = &(env->active_fpu.fpr[ws]); + msa_insve_df(env, df, pwd, pws, n); + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + void helper_msa_mulv_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t ws, uint32_t wt) { @@ -2638,3 +2779,101 @@ void helper_msa_sld_df(CPUMIPSState *env, uint32_t df, uint32_t wd, env->active_msa.msamodify |= (1 << wd); } } + +void helper_msa_sldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t n) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + void *pws = &(env->active_fpu.fpr[ws]); + + msa_sld_df(env, df, pwd, pws, n); + + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +target_ulong helper_msa_cfcmsa(CPUMIPSState *env, uint32_t cs) +{ + switch (cs) { + case MSAIR_REGISTER: + return env->active_msa.msair; + case MSACSR_REGISTER: + return env->active_msa.msacsr & MSACSR_BITS; + } + + if (env->active_msa.msair & MSAIR_WRP_BIT) { + switch (cs) { + case MSAACCESS_REGISTER: + return env->active_msa.msaaccess; + case MSASAVE_REGISTER: + return env->active_msa.msasave; + case MSAMODIFY_REGISTER: + return env->active_msa.msamodify; + case MSAREQUEST_REGISTER: + return env->active_msa.msarequest; + case MSAMAP_REGISTER: + return env->active_msa.msamap; + case MSAUNMAP_REGISTER: + return env->active_msa.msaunmap; + } + } + return 0; +} + +void helper_msa_ctcmsa(CPUMIPSState *env, target_ulong elm, uint32_t cd) +{ + switch (cd) { + case MSAIR_REGISTER: + break; + case MSACSR_REGISTER: + env->active_msa.msacsr = (int32_t)elm & MSACSR_BITS; + + /* set float_status rounding mode */ + set_float_rounding_mode( + ieee_rm[(env->active_msa.msacsr & MSACSR_RM_MASK) >> MSACSR_RM_POS], + &env->active_msa.fp_status); + + /* set float_status flush modes */ + set_flush_to_zero( + (env->active_msa.msacsr & MSACSR_FS_BIT) != 0 ? 1 : 0, + &env->active_msa.fp_status); + set_flush_inputs_to_zero( + (env->active_msa.msacsr & MSACSR_FS_BIT) != 0 ? 1 : 0, + &env->active_msa.fp_status); + + /* check exception */ + if ((GET_FP_ENABLE(env->active_msa.msacsr) | FP_UNIMPLEMENTED) + & GET_FP_CAUSE(env->active_msa.msacsr)) { + helper_raise_exception(env, EXCP_MSAFPE); + } + break; + case MSAACCESS_REGISTER: + break; + case MSASAVE_REGISTER: + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msasave = (int32_t)elm; + } + break; + case MSAMODIFY_REGISTER: + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify = (int32_t)elm; + } + break; + case MSAREQUEST_REGISTER: + break; + case MSAMAP_REGISTER: + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamap = (int32_t)elm; + env->active_msa.msaaccess |= 1 << (int32_t)elm; + return; + } + break; + case MSAUNMAP_REGISTER: + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msaunmap = (int32_t)elm; + env->active_msa.msaaccess &= ~(1 << (int32_t)elm); + } + break; + } +} diff --git a/target-mips/translate.c b/target-mips/translate.c index e063531..6c8caa4 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -15319,6 +15319,139 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx) tcg_temp_free_i32(tdf); } +static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22))) +#define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16))) + uint32_t opcode = ctx->opcode; + + uint8_t dfn = (ctx->opcode >> 16) & 0x3f /* dfn [21:16] */; + + uint32_t df = 0, n = 0; + + if ((dfn & 0x20) == 0x00) { /* byte data format */ + n = dfn & 0x1f; + df = 0; + } else if ((dfn & 0x30) == 0x20) { /* half data format */ + n = dfn & 0x0f; + df = 1; + } else if ((dfn & 0x38) == 0x30) { /* word data format */ + n = dfn & 0x07; + df = 2; + } else if ((dfn & 0x3c) == 0x38) { /* double data format */ + n = dfn & 0x3; + df = 3; + } else if (dfn == 0x3E) { /* CTCMSA, CFCMSA, MOVE.V */ + df = 4; + } else { + if (check_msa_access(env, ctx, -1, -1, -1)) { + generate_exception(ctx, EXCP_RI); + } + return; + } + + if (df == 4) { + uint8_t source = (ctx->opcode >> 11) & 0x1f /* rs/cs/ws [15:11] */; + uint8_t dest = (ctx->opcode >> 6) & 0x1f /* cd/rd/wd [10:6] */; + TCGv telm = tcg_temp_new(); + TCGv_i32 tsr = tcg_const_i32(source); + TCGv_i32 tdt = tcg_const_i32(dest); + + switch (MASK_MSA_ELM_DF3E(opcode)) { + case OPC_MSA_CTCMSA: + { + check_msa_access(env, ctx, -1, -1, -1); + gen_load_gpr(telm, source); + gen_helper_msa_ctcmsa(cpu_env, telm, tdt); + } + break; + case OPC_MSA_CFCMSA: + { + check_msa_access(env, ctx, -1, -1, -1); + gen_helper_msa_cfcmsa(telm, cpu_env, tsr); + gen_store_gpr(telm, dest); + } + break; + case OPC_MSA_MOVE_V: + { + check_msa_access(env, ctx, -1, -1, -1); + 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); + } else { + int df_bits = 8 * (1 << df); + if (n >= MSA_WRLEN / df_bits) { + if (check_msa_access(env, ctx, -1, -1, -1)) { + generate_exception(ctx, EXCP_RI); + } + } else { + uint8_t ws = (ctx->opcode >> 11) & 0x1f /* ws [15:11] */; + uint8_t wd = (ctx->opcode >> 6) & 0x1f /* wd [10:6] */; + + 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(opcode)) { + case OPC_MSA_SLDI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn); + break; + case OPC_MSA_SPLATI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn); + break; + case OPC_MSA_INSVE_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn); + break; + case OPC_MSA_COPY_S_df: + case OPC_MSA_COPY_U_df: + case OPC_MSA_INSERT_df: +#if !defined(TARGET_MIPS64) + /* Double format valid only for MIPS64 */ + if (df == 3) { + if (check_msa_access(env, ctx, -1, -1, -1)) { + generate_exception(ctx, EXCP_RI); + } + break; + } +#endif + check_msa_access(env, ctx, -1, ws, wd); + switch (MASK_MSA_ELM(opcode)) { + case OPC_MSA_COPY_S_df: + gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn); + break; + case OPC_MSA_COPY_U_df: + gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn); + break; + case OPC_MSA_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(CPUMIPSState *env, DisasContext *ctx) { uint32_t opcode = ctx->opcode; @@ -15349,6 +15482,9 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx) case OPC_MSA_3R_15: gen_msa_3r(env, ctx); break; + case OPC_MSA_ELM: + gen_msa_elm(env, ctx); + break; default: MIPS_INVAL("MSA instruction"); generate_exception(ctx, EXCP_RI); -- 1.7.4