add MSA BIT format instructions Signed-off-by: Yongbok Kim <yongbok....@imgtec.com> --- target-mips/helper.h | 12 ++ target-mips/msa_helper.c | 292 ++++++++++++++++++++++++++++++++++++++++++++++ target-mips/translate.c | 100 ++++++++++++++++ 3 files changed, 404 insertions(+), 0 deletions(-)
diff --git a/target-mips/helper.h b/target-mips/helper.h index fe0cf48..f9406d6 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -694,9 +694,14 @@ DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s64) DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32) +DEF_HELPER_5(msa_bclri_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_4(msa_bmnzi_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32) +DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32) DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32) +DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s64) @@ -709,6 +714,13 @@ 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_4(msa_nori_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_ori_b, void, env, 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_shf_df, void, env, i32, i32, i32, i32) +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_srari_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s64) DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 00b6e77..39377d6 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -279,6 +279,140 @@ void helper_msa_xori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, } } +static inline int64_t msa_bclr_df(CPUMIPSState *env, uint32_t df, int64_t arg1, + int64_t arg2) +{ + int32_t b_arg2 = BIT_POSITION(arg2, df); + + return UNSIGNED(arg1 & (~(1LL << b_arg2)), df); +} + +void helper_msa_bclri_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t m) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_bclr_df(env, df, ts, m); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_bneg_df(CPUMIPSState *env, uint32_t df, int64_t arg1, + int64_t arg2) +{ + int32_t b_arg2 = BIT_POSITION(arg2, df); + return UNSIGNED(arg1 ^ (1LL << b_arg2), df); +} + +void helper_msa_bnegi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t m) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_bneg_df(env, df, ts, m); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_bset_df(CPUMIPSState *env, uint32_t df, int64_t arg1, + int64_t arg2) +{ + int32_t b_arg2 = BIT_POSITION(arg2, df); + return UNSIGNED(arg1 | (1LL << b_arg2), df); +} + +void helper_msa_bseti_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t m) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_bset_df(env, df, ts, m); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_binsl_df(CPUMIPSState *env, 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); + } +} + +void helper_msa_binsli_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t m) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_load_wr_elem_s64(env, wd, df, i); + td = msa_binsl_df(env, df, td, ts, m); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_binsr_df(CPUMIPSState *env, 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); + } +} + +void helper_msa_binsri_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t m) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_load_wr_elem_s64(env, wd, df, i); + td = msa_binsr_df(env, df, td, ts, m); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + #define BIT_MOVE_IF_NOT_ZERO(dest, arg1, arg2, df) \ dest = UNSIGNED(((dest & (~arg2)) | (arg1 & arg2)), df) @@ -607,3 +741,161 @@ void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, env->active_msa.msamodify |= (1 << wd); } } + +static inline int64_t msa_sat_u_df(CPUMIPSState *env, 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); +} + +void helper_msa_sat_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t m) +{ + uint64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_i64(env, ws, df, i); + td = msa_sat_u_df(env, df, ts, m); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_sat_s_df(CPUMIPSState *env, 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; +} + +void helper_msa_sat_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t m) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_sat_s_df(env, df, ts, m); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +void helper_msa_slli_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t m) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = ts << m; + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +void helper_msa_srai_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t m) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = ts >> m; + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_srli_df(CPUMIPSState *env, uint32_t df, int64_t arg, + uint32_t m) +{ + uint64_t u_arg = UNSIGNED(arg, df); + return u_arg >> m; +} + +void helper_msa_srli_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t m) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_srli_df(env, df, ts, m); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_srari_df(CPUMIPSState *env, uint32_t df, int64_t arg, + uint32_t m) +{ + if (m == 0) { + return arg; + } else { + int64_t r_bit = (arg >> (m - 1)) & 1; + return (arg >> m) + r_bit; + } +} + +void helper_msa_srari_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t m) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_srari_df(env, df, ts, m); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + +static inline int64_t msa_srlri_df(CPUMIPSState *env, uint32_t df, int64_t arg, + uint32_t m) +{ + uint64_t u_arg = UNSIGNED(arg, df); + if (m == 0) { + return u_arg; + } else { + uint64_t r_bit = (u_arg >> (m - 1)) & 1; + return (u_arg >> m) + r_bit; + } +} + +void helper_msa_srlri_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t m) +{ + int64_t td, ts; + int i; + int df_bits = 8 * (1 << df); + for (i = 0; i < MSA_WRLEN / df_bits; i++) { + ts = msa_load_wr_elem_s64(env, ws, df, i); + td = msa_srlri_df(env, df, ts, m); + msa_store_wr_elem(env, td, wd, df, i); + } + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} diff --git a/target-mips/translate.c b/target-mips/translate.c index 7fde3bb..f97d3a9 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -14934,6 +14934,102 @@ static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx) tcg_temp_free_i64(ts5); } +static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23))) + uint32_t opcode = ctx->opcode; + + uint8_t dfm = (ctx->opcode >> 16) & 0x7f /* dfm [22:16] */; + uint32_t df = 0, m = 0; + + if ((dfm & 0x40) == 0x00) { /* double data format */ + m = dfm & 0x3f; + df = 3; + } else if ((dfm & 0x60) == 0x40) { /* word data format */ + m = dfm & 0x1f; + df = 2; + } else if ((dfm & 0x70) == 0x60) { /* half data format */ + m = dfm & 0x0f; + df = 1; + } else if ((dfm & 0x78) == 0x70) { /* byte data format */ + m = dfm & 0x7; + df = 0; + } else { + if (check_msa_access(env, ctx, -1, -1, -1)) { + generate_exception(ctx, EXCP_RI); + } + return; + } + + uint8_t ws = (ctx->opcode >> 11) & 0x1f /* ws [15:11] */; + uint8_t wd = (ctx->opcode >> 6) & 0x1f /* wd [10:6] */; + + TCGv_i32 tdf = tcg_const_i32(df); + TCGv_i32 tm = tcg_const_i32(m); + TCGv_i32 twd = tcg_const_i32(wd); + TCGv_i32 tws = tcg_const_i32(ws); + + switch (MASK_MSA_BIT(opcode)) { + case OPC_MSA_SLLI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_MSA_SRAI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_MSA_SRLI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_MSA_BCLRI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_MSA_BSETI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_MSA_BNEGI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_MSA_BINSLI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_MSA_BINSRI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_MSA_SAT_S_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_MSA_SAT_U_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_MSA_SRARI_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm); + break; + case OPC_MSA_SRLRI_df: + check_msa_access(env, ctx, -1, ws, wd); + 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; @@ -14949,6 +15045,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); -- 1.7.4