From 80e7159184fadfc2dee3b6cc92013d4c4c58348a Mon Sep 17 00:00:00 2001 From: Yongbok Kim Date: Sat, 1 Nov 2014 05:28:44 +0000 Subject: target-mips: add MSA I5 format instruction add MSA I5 format instructions Signed-off-by: Yongbok Kim Reviewed-by: Leon Alrae Signed-off-by: Leon Alrae --- target-mips/helper.h | 13 +++++ target-mips/msa_helper.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++ target-mips/translate.c | 77 +++++++++++++++++++++++++ 3 files changed, 232 insertions(+) (limited to 'target-mips') diff --git a/target-mips/helper.h b/target-mips/helper.h index 5fd627ea17..4f0354532f 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -758,3 +758,16 @@ DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32) DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32) + +DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_maxi_s_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_maxi_u_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s32) +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) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index bae86d4e05..7b577e715e 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -113,3 +113,145 @@ void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, } msa_move_v(pwd, pwx); } + +static inline int64_t msa_addv_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + return arg1 + arg2; +} + +static inline int64_t msa_subv_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + return arg1 - arg2; +} + +static inline int64_t msa_ceq_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + return arg1 == arg2 ? -1 : 0; +} + +static inline int64_t msa_cle_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + return arg1 <= arg2 ? -1 : 0; +} + +static inline int64_t msa_cle_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + return u_arg1 <= u_arg2 ? -1 : 0; +} + +static inline int64_t msa_clt_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + return arg1 < arg2 ? -1 : 0; +} + +static inline int64_t msa_clt_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + return u_arg1 < u_arg2 ? -1 : 0; +} + +static inline int64_t msa_max_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} + +static inline int64_t msa_max_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + return u_arg1 > u_arg2 ? arg1 : arg2; +} + +static inline int64_t msa_min_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + return arg1 < arg2 ? arg1 : arg2; +} + +static inline int64_t msa_min_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ + uint64_t u_arg1 = UNSIGNED(arg1, df); + uint64_t u_arg2 = UNSIGNED(arg2, df); + return u_arg1 < u_arg2 ? arg1 : arg2; +} + +#define MSA_BINOP_IMM_DF(helper, func) \ +void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, \ + uint32_t wd, uint32_t ws, int32_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_IMM_DF(addvi, addv) +MSA_BINOP_IMM_DF(subvi, subv) +MSA_BINOP_IMM_DF(ceqi, ceq) +MSA_BINOP_IMM_DF(clei_s, cle_s) +MSA_BINOP_IMM_DF(clei_u, cle_u) +MSA_BINOP_IMM_DF(clti_s, clt_s) +MSA_BINOP_IMM_DF(clti_u, clt_u) +MSA_BINOP_IMM_DF(maxi_s, max_s) +MSA_BINOP_IMM_DF(maxi_u, max_u) +MSA_BINOP_IMM_DF(mini_s, min_s) +MSA_BINOP_IMM_DF(mini_u, min_u) +#undef MSA_BINOP_IMM_DF + +void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + int32_t s10) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + uint32_t i; + + switch (df) { + case DF_BYTE: + for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { + pwd->b[i] = (int8_t)s10; + } + break; + case DF_HALF: + for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { + pwd->h[i] = (int16_t)s10; + } + break; + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + pwd->w[i] = (int32_t)s10; + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + pwd->d[i] = (int64_t)s10; + } + break; + default: + assert(0); + } +} diff --git a/target-mips/translate.c b/target-mips/translate.c index aba3ccb0b3..e75b864b3b 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -17392,6 +17392,79 @@ static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx) tcg_temp_free_i32(ti8); } +static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23))) + uint8_t df = (ctx->opcode >> 21) & 0x3; + int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5); + uint8_t u5 = (ctx->opcode >> 16) & 0x1f; + uint8_t ws = (ctx->opcode >> 11) & 0x1f; + uint8_t wd = (ctx->opcode >> 6) & 0x1f; + + TCGv_i32 tdf = tcg_const_i32(df); + TCGv_i32 twd = tcg_const_i32(wd); + TCGv_i32 tws = tcg_const_i32(ws); + TCGv_i32 timm = tcg_temp_new_i32(); + tcg_gen_movi_i32(timm, u5); + + switch (MASK_MSA_I5(ctx->opcode)) { + case OPC_ADDVI_df: + gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_SUBVI_df: + gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_MAXI_S_df: + tcg_gen_movi_i32(timm, s5); + gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_MAXI_U_df: + gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_MINI_S_df: + tcg_gen_movi_i32(timm, s5); + gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_MINI_U_df: + gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_CEQI_df: + tcg_gen_movi_i32(timm, s5); + gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_CLTI_S_df: + tcg_gen_movi_i32(timm, s5); + gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_CLTI_U_df: + gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_CLEI_S_df: + tcg_gen_movi_i32(timm, s5); + gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_CLEI_U_df: + gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm); + break; + case OPC_LDI_df: + { + int32_t s10 = sextract32(ctx->opcode, 11, 10); + tcg_gen_movi_i32(timm, s10); + gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm); + } + break; + default: + MIPS_INVAL("MSA instruction"); + generate_exception(ctx, EXCP_RI); + break; + } + + tcg_temp_free_i32(tdf); + tcg_temp_free_i32(twd); + tcg_temp_free_i32(tws); + tcg_temp_free_i32(timm); +} + static void gen_msa(CPUMIPSState *env, DisasContext *ctx) { uint32_t opcode = ctx->opcode; @@ -17404,6 +17477,10 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx) case OPC_MSA_I8_02: gen_msa_i8(env, ctx); break; + case OPC_MSA_I5_06: + case OPC_MSA_I5_07: + gen_msa_i5(env, ctx); + break; default: MIPS_INVAL("MSA instruction"); generate_exception(ctx, EXCP_RI); -- cgit v1.2.1