diff options
Diffstat (limited to 'target-mips/msa_helper.c')
-rw-r--r-- | target-mips/msa_helper.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index b65fb271a9..bae86d4e05 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -47,3 +47,69 @@ static inline void msa_move_v(wr_t *pwd, wr_t *pws) pwd->d[i] = pws->d[i]; } } + +#define MSA_FN_IMM8(FUNC, DEST, OPERATION) \ +void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \ + uint32_t i8) \ +{ \ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ + wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ + uint32_t i; \ + for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \ + DEST = OPERATION; \ + } \ +} + +MSA_FN_IMM8(andi_b, pwd->b[i], pws->b[i] & i8) +MSA_FN_IMM8(ori_b, pwd->b[i], pws->b[i] | i8) +MSA_FN_IMM8(nori_b, pwd->b[i], ~(pws->b[i] | i8)) +MSA_FN_IMM8(xori_b, pwd->b[i], pws->b[i] ^ i8) + +#define BIT_MOVE_IF_NOT_ZERO(dest, arg1, arg2, df) \ + UNSIGNED(((dest & (~arg2)) | (arg1 & arg2)), df) +MSA_FN_IMM8(bmnzi_b, pwd->b[i], + BIT_MOVE_IF_NOT_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE)) + +#define BIT_MOVE_IF_ZERO(dest, arg1, arg2, df) \ + UNSIGNED((dest & arg2) | (arg1 & (~arg2)), df) +MSA_FN_IMM8(bmzi_b, pwd->b[i], + BIT_MOVE_IF_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE)) + +#define BIT_SELECT(dest, arg1, arg2, df) \ + UNSIGNED((arg1 & (~dest)) | (arg2 & dest), df) +MSA_FN_IMM8(bseli_b, pwd->b[i], + BIT_SELECT(pwd->b[i], pws->b[i], i8, DF_BYTE)) + +#undef MSA_FN_IMM8 + +#define SHF_POS(i, imm) (((i) & 0xfc) + (((imm) >> (2 * ((i) & 0x03))) & 0x03)) + +void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t imm) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t wx, *pwx = &wx; + uint32_t i; + + switch (df) { + case DF_BYTE: + for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { + pwx->b[i] = pws->b[SHF_POS(i, imm)]; + } + break; + case DF_HALF: + for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { + pwx->h[i] = pws->h[SHF_POS(i, imm)]; + } + break; + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + pwx->w[i] = pws->w[SHF_POS(i, imm)]; + } + break; + default: + assert(0); + } + msa_move_v(pwd, pwx); +} |