add MSA VEC/2R format instructions Signed-off-by: Yongbok Kim <yongbok....@imgtec.com> --- target-mips/helper.h | 11 ++ target-mips/msa_helper.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++ target-mips/translate.c | 98 ++++++++++++++++++ 3 files changed, 353 insertions(+), 0 deletions(-)
diff --git a/target-mips/helper.h b/target-mips/helper.h index fec21b6..b87bb50 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -698,6 +698,7 @@ DEF_HELPER_5(msa_adds_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_adds_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_addv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s64) +DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32) DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32) DEF_HELPER_5(msa_asub_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_asub_u_df, void, env, i32, i32, i32, i32) @@ -711,10 +712,13 @@ DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32) DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32) DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32) DEF_HELPER_5(msa_bneg_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32) DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32) DEF_HELPER_5(msa_bset_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32) @@ -755,6 +759,7 @@ DEF_HELPER_5(msa_fcune_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fdiv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fexdo_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fexp2_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32) DEF_HELPER_5(msa_fmadd_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fmax_a_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fmax_df, void, env, i32, i32, i32, i32) @@ -808,10 +813,15 @@ DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_mul_q_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_mulv_df, void, env, i32, 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) +DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32) DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32) DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32) DEF_HELPER_5(msa_pckev_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_pckod_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_pcnt_df, 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) @@ -836,4 +846,5 @@ DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32) 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 bb4ab66..aa165ac 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -495,6 +495,22 @@ void helper_msa_subsus_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, } } +void helper_msa_and_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, + uint32_t wt) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + void *pws = &(env->active_fpu.fpr[ws]); + void *pwt = &(env->active_fpu.fpr[wt]); + + ALL_D_ELEMENTS(i, MSA_WRLEN) { + D(pwd, i) = D(pws, i) & D(pwt, i); + } DONE_ALL_ELEMENTS; + + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + void helper_msa_andi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t i8) { @@ -508,6 +524,22 @@ void helper_msa_andi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, } } +void helper_msa_or_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, + uint32_t wt) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + void *pws = &(env->active_fpu.fpr[ws]); + void *pwt = &(env->active_fpu.fpr[wt]); + + ALL_D_ELEMENTS(i, MSA_WRLEN) { + D(pwd, i) = D(pws, i) | D(pwt, i); + } DONE_ALL_ELEMENTS; + + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + void helper_msa_ori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t i8) { @@ -521,6 +553,22 @@ void helper_msa_ori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, } } +void helper_msa_nor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, + uint32_t wt) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + void *pws = &(env->active_fpu.fpr[ws]); + void *pwt = &(env->active_fpu.fpr[wt]); + + ALL_D_ELEMENTS(i, MSA_WRLEN) { + D(pwd, i) = ~(D(pws, i) | D(pwt, i)); + } DONE_ALL_ELEMENTS; + + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + void helper_msa_nori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t i8) { @@ -534,6 +582,22 @@ void helper_msa_nori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, } } +void helper_msa_xor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, + uint32_t wt) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + void *pws = &(env->active_fpu.fpr[ws]); + void *pwt = &(env->active_fpu.fpr[wt]); + + ALL_D_ELEMENTS(i, MSA_WRLEN) { + D(pwd, i) = D(pws, i) ^ D(pwt, i); + } DONE_ALL_ELEMENTS; + + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + void helper_msa_xori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t i8) { @@ -922,6 +986,22 @@ void helper_msa_binsri_df(CPUMIPSState *env, uint32_t df, uint32_t wd, #define BIT_MOVE_IF_NOT_ZERO(dest, arg1, arg2, df) \ dest = UNSIGNED(((dest & (~arg2)) | (arg1 & arg2)), df) +void helper_msa_bmnz_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, + uint32_t wt) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + void *pws = &(env->active_fpu.fpr[ws]); + void *pwt = &(env->active_fpu.fpr[wt]); + + ALL_D_ELEMENTS(i, MSA_WRLEN) { + BIT_MOVE_IF_NOT_ZERO(D(pwd, i), D(pws, i), D(pwt, i), DF_DOUBLE); + } DONE_ALL_ELEMENTS; + + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + void helper_msa_bmnzi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t i8) { @@ -938,6 +1018,22 @@ void helper_msa_bmnzi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, #define BIT_MOVE_IF_ZERO(dest, arg1, arg2, df) \ dest = UNSIGNED((dest & arg2) | (arg1 & (~arg2)), df) +void helper_msa_bmz_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, + uint32_t wt) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + void *pws = &(env->active_fpu.fpr[ws]); + void *pwt = &(env->active_fpu.fpr[wt]); + + ALL_D_ELEMENTS(i, MSA_WRLEN) { + BIT_MOVE_IF_ZERO(D(pwd, i), D(pws, i), D(pwt, i), DF_DOUBLE); + } DONE_ALL_ELEMENTS; + + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + void helper_msa_bmzi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t i8) { @@ -954,6 +1050,22 @@ void helper_msa_bmzi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, #define BIT_SELECT(dest, arg1, arg2, df) \ dest = UNSIGNED((arg1 & (~dest)) | (arg2 & dest), df) +void helper_msa_bsel_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, + uint32_t wt) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + void *pws = &(env->active_fpu.fpr[ws]); + void *pwt = &(env->active_fpu.fpr[wt]); + + ALL_D_ELEMENTS(i, MSA_WRLEN) { + BIT_SELECT(D(pwd, i), D(pws, i), D(pwt, i), DF_DOUBLE); + } DONE_ALL_ELEMENTS; + + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + void helper_msa_bseli_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t i8) { @@ -2251,6 +2363,42 @@ void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, } } +void helper_msa_fill_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t rs) +{ + void *pwd = &(env->active_fpu.fpr[wd]); + + switch (df) { + case DF_BYTE: + ALL_B_ELEMENTS(i, MSA_WRLEN) { + B(pwd, i) = (int8_t)env->active_tc.gpr[rs]; + } DONE_ALL_ELEMENTS; + break; + case DF_HALF: + ALL_H_ELEMENTS(i, MSA_WRLEN) { + H(pwd, i) = (int16_t)env->active_tc.gpr[rs]; + } DONE_ALL_ELEMENTS; + break; + case DF_WORD: + ALL_W_ELEMENTS(i, MSA_WRLEN) { + W(pwd, i) = (int32_t)env->active_tc.gpr[rs]; + } DONE_ALL_ELEMENTS; + break; + case DF_DOUBLE: + ALL_D_ELEMENTS(i, MSA_WRLEN) { + D(pwd, i) = (int64_t)env->active_tc.gpr[rs]; + } DONE_ALL_ELEMENTS; + break; + default: + /* shouldn't get here */ + assert(0); + } + + if (env->active_msa.msair & MSAIR_WRP_BIT) { + env->active_msa.msamodify |= (1 << wd); + } +} + static inline void msa_insert_df(CPUMIPSState *env, uint32_t df, void *pwd, target_ulong rs, uint32_t n) { @@ -2437,6 +2585,102 @@ void helper_msa_mod_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, } } +static inline int64_t msa_nlzc_df(CPUMIPSState *env, 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; +} + +void helper_msa_nlzc_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws) +{ + 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_s64(env, ws, df, i); + td = msa_nlzc_df(env, df, ts); + 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_nloc_df(CPUMIPSState *env, uint32_t df, int64_t arg) +{ + return msa_nlzc_df(env, df, UNSIGNED((~arg), df)); +} + +void helper_msa_nloc_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws) +{ + 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_s64(env, ws, df, i); + td = msa_nloc_df(env, df, ts); + 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_pcnt_df(CPUMIPSState *env, 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; +} + +void helper_msa_pcnt_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws) +{ + 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_s64(env, ws, df, i); + td = msa_pcnt_df(env, df, ts); + 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_u_df(CPUMIPSState *env, uint32_t df, int64_t arg, uint32_t m) { diff --git a/target-mips/translate.c b/target-mips/translate.c index 39caa6d..4185019 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -15650,6 +15650,101 @@ static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx) tcg_temp_free_i32(tdf1); } +static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21))) +#define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \ + (op & (0x7 << 18))) +#define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \ + (op & (0xf << 17))) + + uint32_t opcode = ctx->opcode; + + uint8_t wt = (ctx->opcode >> 16) & 0x1f /* wt [20:16] */; + uint8_t ws = (ctx->opcode >> 11) & 0x1f /* ws [15:11] */; + uint8_t wd = (ctx->opcode >> 6) & 0x1f /* wd [10:6] */; + + 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(opcode)) { + case OPC_MSA_AND_V: + check_msa_access(env, ctx, wt, ws, wd); + gen_helper_msa_and_v(cpu_env, twd, tws, twt); + break; + case OPC_MSA_OR_V: + check_msa_access(env, ctx, wt, ws, wd); + gen_helper_msa_or_v(cpu_env, twd, tws, twt); + break; + case OPC_MSA_NOR_V: + check_msa_access(env, ctx, wt, ws, wd); + gen_helper_msa_nor_v(cpu_env, twd, tws, twt); + break; + case OPC_MSA_XOR_V: + check_msa_access(env, ctx, wt, ws, wd); + gen_helper_msa_xor_v(cpu_env, twd, tws, twt); + break; + case OPC_MSA_BMNZ_V: + check_msa_access(env, ctx, wt, ws, wd); + gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt); + break; + case OPC_MSA_BMZ_V: + check_msa_access(env, ctx, wt, ws, wd); + gen_helper_msa_bmz_v(cpu_env, twd, tws, twt); + break; + case OPC_MSA_BSEL_V: + check_msa_access(env, ctx, wt, ws, wd); + gen_helper_msa_bsel_v(cpu_env, twd, tws, twt); + break; + + case OPC_MSA_2R: + { + uint8_t df = (ctx->opcode >> 16) & 0x3 /* df [17:16] */; + TCGv_i32 tdf = tcg_const_i32(df); + + switch (MASK_MSA_2R(opcode)) { + case OPC_MSA_FILL_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, -1, wd); + gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */ + break; + case OPC_MSA_PCNT_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws); + break; + case OPC_MSA_NLOC_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws); + break; + case OPC_MSA_NLZC_df: + check_msa_access(env, ctx, -1, ws, wd); + gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws); + break; + default: + break; + } + + tcg_temp_free_i32(tdf); + } + break; + case OPC_MSA_2RF: + default: + break; + } + + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); + tcg_temp_free_i32(twt); +} static void gen_msa(CPUMIPSState *env, DisasContext *ctx) { uint32_t opcode = ctx->opcode; @@ -15688,6 +15783,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); -- 1.7.4