#include "internal.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
+#include "fpu/softfloat.h"
/* Data format min and max values */
#define DF_BITS(df) (1 << ((df) + 3))
* +---------------+----------------------------------------------------------+
*/
-/* TODO: insert Bit Count group helpers here */
+static inline int64_t msa_nlzc_df(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;
+}
+
+static inline int64_t msa_nloc_df(uint32_t df, int64_t arg)
+{
+ return msa_nlzc_df(df, UNSIGNED((~arg), df));
+}
+
+void helper_msa_nloc_b(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+
+ pwd->b[0] = msa_nloc_df(DF_BYTE, pws->b[0]);
+ pwd->b[1] = msa_nloc_df(DF_BYTE, pws->b[1]);
+ pwd->b[2] = msa_nloc_df(DF_BYTE, pws->b[2]);
+ pwd->b[3] = msa_nloc_df(DF_BYTE, pws->b[3]);
+ pwd->b[4] = msa_nloc_df(DF_BYTE, pws->b[4]);
+ pwd->b[5] = msa_nloc_df(DF_BYTE, pws->b[5]);
+ pwd->b[6] = msa_nloc_df(DF_BYTE, pws->b[6]);
+ pwd->b[7] = msa_nloc_df(DF_BYTE, pws->b[7]);
+ pwd->b[8] = msa_nloc_df(DF_BYTE, pws->b[8]);
+ pwd->b[9] = msa_nloc_df(DF_BYTE, pws->b[9]);
+ pwd->b[10] = msa_nloc_df(DF_BYTE, pws->b[10]);
+ pwd->b[11] = msa_nloc_df(DF_BYTE, pws->b[11]);
+ pwd->b[12] = msa_nloc_df(DF_BYTE, pws->b[12]);
+ pwd->b[13] = msa_nloc_df(DF_BYTE, pws->b[13]);
+ pwd->b[14] = msa_nloc_df(DF_BYTE, pws->b[14]);
+ pwd->b[15] = msa_nloc_df(DF_BYTE, pws->b[15]);
+}
+
+void helper_msa_nloc_h(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+
+ pwd->h[0] = msa_nloc_df(DF_HALF, pws->h[0]);
+ pwd->h[1] = msa_nloc_df(DF_HALF, pws->h[1]);
+ pwd->h[2] = msa_nloc_df(DF_HALF, pws->h[2]);
+ pwd->h[3] = msa_nloc_df(DF_HALF, pws->h[3]);
+ pwd->h[4] = msa_nloc_df(DF_HALF, pws->h[4]);
+ pwd->h[5] = msa_nloc_df(DF_HALF, pws->h[5]);
+ pwd->h[6] = msa_nloc_df(DF_HALF, pws->h[6]);
+ pwd->h[7] = msa_nloc_df(DF_HALF, pws->h[7]);
+}
+
+void helper_msa_nloc_w(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+
+ pwd->w[0] = msa_nloc_df(DF_WORD, pws->w[0]);
+ pwd->w[1] = msa_nloc_df(DF_WORD, pws->w[1]);
+ pwd->w[2] = msa_nloc_df(DF_WORD, pws->w[2]);
+ pwd->w[3] = msa_nloc_df(DF_WORD, pws->w[3]);
+}
+
+void helper_msa_nloc_d(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+
+ pwd->d[0] = msa_nloc_df(DF_DOUBLE, pws->d[0]);
+ pwd->d[1] = msa_nloc_df(DF_DOUBLE, pws->d[1]);
+}
+
+void helper_msa_nlzc_b(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+
+ pwd->b[0] = msa_nlzc_df(DF_BYTE, pws->b[0]);
+ pwd->b[1] = msa_nlzc_df(DF_BYTE, pws->b[1]);
+ pwd->b[2] = msa_nlzc_df(DF_BYTE, pws->b[2]);
+ pwd->b[3] = msa_nlzc_df(DF_BYTE, pws->b[3]);
+ pwd->b[4] = msa_nlzc_df(DF_BYTE, pws->b[4]);
+ pwd->b[5] = msa_nlzc_df(DF_BYTE, pws->b[5]);
+ pwd->b[6] = msa_nlzc_df(DF_BYTE, pws->b[6]);
+ pwd->b[7] = msa_nlzc_df(DF_BYTE, pws->b[7]);
+ pwd->b[8] = msa_nlzc_df(DF_BYTE, pws->b[8]);
+ pwd->b[9] = msa_nlzc_df(DF_BYTE, pws->b[9]);
+ pwd->b[10] = msa_nlzc_df(DF_BYTE, pws->b[10]);
+ pwd->b[11] = msa_nlzc_df(DF_BYTE, pws->b[11]);
+ pwd->b[12] = msa_nlzc_df(DF_BYTE, pws->b[12]);
+ pwd->b[13] = msa_nlzc_df(DF_BYTE, pws->b[13]);
+ pwd->b[14] = msa_nlzc_df(DF_BYTE, pws->b[14]);
+ pwd->b[15] = msa_nlzc_df(DF_BYTE, pws->b[15]);
+}
+
+void helper_msa_nlzc_h(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+
+ pwd->h[0] = msa_nlzc_df(DF_HALF, pws->h[0]);
+ pwd->h[1] = msa_nlzc_df(DF_HALF, pws->h[1]);
+ pwd->h[2] = msa_nlzc_df(DF_HALF, pws->h[2]);
+ pwd->h[3] = msa_nlzc_df(DF_HALF, pws->h[3]);
+ pwd->h[4] = msa_nlzc_df(DF_HALF, pws->h[4]);
+ pwd->h[5] = msa_nlzc_df(DF_HALF, pws->h[5]);
+ pwd->h[6] = msa_nlzc_df(DF_HALF, pws->h[6]);
+ pwd->h[7] = msa_nlzc_df(DF_HALF, pws->h[7]);
+}
+
+void helper_msa_nlzc_w(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+
+ pwd->w[0] = msa_nlzc_df(DF_WORD, pws->w[0]);
+ pwd->w[1] = msa_nlzc_df(DF_WORD, pws->w[1]);
+ pwd->w[2] = msa_nlzc_df(DF_WORD, pws->w[2]);
+ pwd->w[3] = msa_nlzc_df(DF_WORD, pws->w[3]);
+}
+
+void helper_msa_nlzc_d(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+
+ pwd->d[0] = msa_nlzc_df(DF_DOUBLE, pws->d[0]);
+ pwd->d[1] = msa_nlzc_df(DF_DOUBLE, pws->d[1]);
+}
+
+static inline int64_t msa_pcnt_df(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_b(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+
+ pwd->b[0] = msa_pcnt_df(DF_BYTE, pws->b[0]);
+ pwd->b[1] = msa_pcnt_df(DF_BYTE, pws->b[1]);
+ pwd->b[2] = msa_pcnt_df(DF_BYTE, pws->b[2]);
+ pwd->b[3] = msa_pcnt_df(DF_BYTE, pws->b[3]);
+ pwd->b[4] = msa_pcnt_df(DF_BYTE, pws->b[4]);
+ pwd->b[5] = msa_pcnt_df(DF_BYTE, pws->b[5]);
+ pwd->b[6] = msa_pcnt_df(DF_BYTE, pws->b[6]);
+ pwd->b[7] = msa_pcnt_df(DF_BYTE, pws->b[7]);
+ pwd->b[8] = msa_pcnt_df(DF_BYTE, pws->b[8]);
+ pwd->b[9] = msa_pcnt_df(DF_BYTE, pws->b[9]);
+ pwd->b[10] = msa_pcnt_df(DF_BYTE, pws->b[10]);
+ pwd->b[11] = msa_pcnt_df(DF_BYTE, pws->b[11]);
+ pwd->b[12] = msa_pcnt_df(DF_BYTE, pws->b[12]);
+ pwd->b[13] = msa_pcnt_df(DF_BYTE, pws->b[13]);
+ pwd->b[14] = msa_pcnt_df(DF_BYTE, pws->b[14]);
+ pwd->b[15] = msa_pcnt_df(DF_BYTE, pws->b[15]);
+}
+
+void helper_msa_pcnt_h(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+
+ pwd->h[0] = msa_pcnt_df(DF_HALF, pws->h[0]);
+ pwd->h[1] = msa_pcnt_df(DF_HALF, pws->h[1]);
+ pwd->h[2] = msa_pcnt_df(DF_HALF, pws->h[2]);
+ pwd->h[3] = msa_pcnt_df(DF_HALF, pws->h[3]);
+ pwd->h[4] = msa_pcnt_df(DF_HALF, pws->h[4]);
+ pwd->h[5] = msa_pcnt_df(DF_HALF, pws->h[5]);
+ pwd->h[6] = msa_pcnt_df(DF_HALF, pws->h[6]);
+ pwd->h[7] = msa_pcnt_df(DF_HALF, pws->h[7]);
+}
+
+void helper_msa_pcnt_w(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+
+ pwd->w[0] = msa_pcnt_df(DF_WORD, pws->w[0]);
+ pwd->w[1] = msa_pcnt_df(DF_WORD, pws->w[1]);
+ pwd->w[2] = msa_pcnt_df(DF_WORD, pws->w[2]);
+ pwd->w[3] = msa_pcnt_df(DF_WORD, pws->w[3]);
+}
+
+void helper_msa_pcnt_d(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+
+ pwd->d[0] = msa_pcnt_df(DF_DOUBLE, pws->d[0]);
+ pwd->d[1] = msa_pcnt_df(DF_DOUBLE, pws->d[1]);
+}
/*
* +---------------+----------------------------------------------------------+
*/
-/* TODO: insert Bit Move group helpers here */
+/* Data format bit position and unsigned values */
+#define BIT_POSITION(x, df) ((uint64_t)(x) % DF_BITS(df))
+
+static inline int64_t msa_binsl_df(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_binsl_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_binsl_df(DF_BYTE, pwd->b[0], pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_binsl_df(DF_BYTE, pwd->b[1], pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_binsl_df(DF_BYTE, pwd->b[2], pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_binsl_df(DF_BYTE, pwd->b[3], pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_binsl_df(DF_BYTE, pwd->b[4], pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_binsl_df(DF_BYTE, pwd->b[5], pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_binsl_df(DF_BYTE, pwd->b[6], pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_binsl_df(DF_BYTE, pwd->b[7], pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_binsl_df(DF_BYTE, pwd->b[8], pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_binsl_df(DF_BYTE, pwd->b[9], pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_binsl_df(DF_BYTE, pwd->b[10], pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_binsl_df(DF_BYTE, pwd->b[11], pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_binsl_df(DF_BYTE, pwd->b[12], pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_binsl_df(DF_BYTE, pwd->b[13], pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_binsl_df(DF_BYTE, pwd->b[14], pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_binsl_df(DF_BYTE, pwd->b[15], pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_binsl_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_binsl_df(DF_HALF, pwd->h[0], pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_binsl_df(DF_HALF, pwd->h[1], pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_binsl_df(DF_HALF, pwd->h[2], pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_binsl_df(DF_HALF, pwd->h[3], pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_binsl_df(DF_HALF, pwd->h[4], pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_binsl_df(DF_HALF, pwd->h[5], pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_binsl_df(DF_HALF, pwd->h[6], pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_binsl_df(DF_HALF, pwd->h[7], pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_binsl_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_binsl_df(DF_WORD, pwd->w[0], pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_binsl_df(DF_WORD, pwd->w[1], pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_binsl_df(DF_WORD, pwd->w[2], pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_binsl_df(DF_WORD, pwd->w[3], pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_binsl_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_binsl_df(DF_DOUBLE, pwd->d[0], pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_binsl_df(DF_DOUBLE, pwd->d[1], pws->d[1], pwt->d[1]);
+}
+
+static inline int64_t msa_binsr_df(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_binsr_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_binsr_df(DF_BYTE, pwd->b[0], pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_binsr_df(DF_BYTE, pwd->b[1], pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_binsr_df(DF_BYTE, pwd->b[2], pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_binsr_df(DF_BYTE, pwd->b[3], pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_binsr_df(DF_BYTE, pwd->b[4], pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_binsr_df(DF_BYTE, pwd->b[5], pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_binsr_df(DF_BYTE, pwd->b[6], pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_binsr_df(DF_BYTE, pwd->b[7], pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_binsr_df(DF_BYTE, pwd->b[8], pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_binsr_df(DF_BYTE, pwd->b[9], pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_binsr_df(DF_BYTE, pwd->b[10], pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_binsr_df(DF_BYTE, pwd->b[11], pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_binsr_df(DF_BYTE, pwd->b[12], pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_binsr_df(DF_BYTE, pwd->b[13], pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_binsr_df(DF_BYTE, pwd->b[14], pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_binsr_df(DF_BYTE, pwd->b[15], pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_binsr_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_binsr_df(DF_HALF, pwd->h[0], pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_binsr_df(DF_HALF, pwd->h[1], pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_binsr_df(DF_HALF, pwd->h[2], pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_binsr_df(DF_HALF, pwd->h[3], pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_binsr_df(DF_HALF, pwd->h[4], pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_binsr_df(DF_HALF, pwd->h[5], pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_binsr_df(DF_HALF, pwd->h[6], pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_binsr_df(DF_HALF, pwd->h[7], pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_binsr_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_binsr_df(DF_WORD, pwd->w[0], pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_binsr_df(DF_WORD, pwd->w[1], pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_binsr_df(DF_WORD, pwd->w[2], pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_binsr_df(DF_WORD, pwd->w[3], pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_binsr_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_binsr_df(DF_DOUBLE, pwd->d[0], pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_binsr_df(DF_DOUBLE, pwd->d[1], pws->d[1], pwt->d[1]);
+}
+
+void helper_msa_bmnz_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = UNSIGNED( \
+ ((pwd->d[0] & (~pwt->d[0])) | (pws->d[0] & pwt->d[0])), DF_DOUBLE);
+ pwd->d[1] = UNSIGNED( \
+ ((pwd->d[1] & (~pwt->d[1])) | (pws->d[1] & pwt->d[1])), DF_DOUBLE);
+}
+
+void helper_msa_bmz_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = UNSIGNED( \
+ ((pwd->d[0] & pwt->d[0]) | (pws->d[0] & (~pwt->d[0]))), DF_DOUBLE);
+ pwd->d[1] = UNSIGNED( \
+ ((pwd->d[1] & pwt->d[1]) | (pws->d[1] & (~pwt->d[1]))), DF_DOUBLE);
+}
+
+void helper_msa_bsel_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = UNSIGNED( \
+ (pws->d[0] & (~pwd->d[0])) | (pwt->d[0] & pwd->d[0]), DF_DOUBLE);
+ pwd->d[1] = UNSIGNED( \
+ (pws->d[1] & (~pwd->d[1])) | (pwt->d[1] & pwd->d[1]), DF_DOUBLE);
+}
/*
* +---------------+----------------------------------------------------------+
*/
-/* TODO: insert Bit Set group helpers here */
+static inline int64_t msa_bclr_df(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_bclr_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-/*
- * Fixed Multiply
- * --------------
- *
- * +---------------+----------------------------------------------------------+
- * | MADD_Q.H | Vector Fixed-Point Multiply and Add (halfword) |
- * | MADD_Q.W | Vector Fixed-Point Multiply and Add (word) |
- * | MADDR_Q.H | Vector Fixed-Point Multiply and Add Rounded (halfword) |
- * | MADDR_Q.W | Vector Fixed-Point Multiply and Add Rounded (word) |
- * | MSUB_Q.H | Vector Fixed-Point Multiply and Subtr. (halfword) |
- * | MSUB_Q.W | Vector Fixed-Point Multiply and Subtr. (word) |
- * | MSUBR_Q.H | Vector Fixed-Point Multiply and Subtr. Rounded (halfword)|
- * | MSUBR_Q.W | Vector Fixed-Point Multiply and Subtr. Rounded (word) |
- * | MUL_Q.H | Vector Fixed-Point Multiply (halfword) |
- * | MUL_Q.W | Vector Fixed-Point Multiply (word) |
- * | MULR_Q.H | Vector Fixed-Point Multiply Rounded (halfword) |
- * | MULR_Q.W | Vector Fixed-Point Multiply Rounded (word) |
- * +---------------+----------------------------------------------------------+
- */
+ pwd->b[0] = msa_bclr_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_bclr_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_bclr_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_bclr_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_bclr_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_bclr_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_bclr_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_bclr_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_bclr_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_bclr_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_bclr_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_bclr_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_bclr_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_bclr_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_bclr_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_bclr_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_bclr_h(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-/* TODO: insert Fixed Multiply group helpers here */
+ pwd->h[0] = msa_bclr_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_bclr_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_bclr_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_bclr_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_bclr_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_bclr_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_bclr_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_bclr_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+void helper_msa_bclr_w(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-/*
- * Float Max Min
- * -------------
- *
- * +---------------+----------------------------------------------------------+
- * | FMAX_A.W | Vector Floating-Point Maximum (Absolute) (word) |
- * | FMAX_A.D | Vector Floating-Point Maximum (Absolute) (doubleword) |
- * | FMAX.W | Vector Floating-Point Maximum (word) |
- * | FMAX.D | Vector Floating-Point Maximum (doubleword) |
- * | FMIN_A.W | Vector Floating-Point Minimum (Absolute) (word) |
+ pwd->w[0] = msa_bclr_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_bclr_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_bclr_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_bclr_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_bclr_d(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_bclr_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_bclr_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+static inline int64_t msa_bneg_df(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_bneg_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_bneg_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_bneg_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_bneg_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_bneg_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_bneg_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_bneg_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_bneg_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_bneg_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_bneg_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_bneg_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_bneg_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_bneg_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_bneg_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_bneg_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_bneg_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_bneg_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_bneg_h(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_bneg_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_bneg_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_bneg_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_bneg_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_bneg_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_bneg_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_bneg_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_bneg_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_bneg_w(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_bneg_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_bneg_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_bneg_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_bneg_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_bneg_d(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_bneg_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_bneg_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+static inline int64_t msa_bset_df(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_bset_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_bset_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_bset_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_bset_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_bset_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_bset_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_bset_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_bset_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_bset_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_bset_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_bset_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_bset_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_bset_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_bset_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_bset_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_bset_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_bset_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_bset_h(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_bset_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_bset_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_bset_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_bset_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_bset_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_bset_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_bset_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_bset_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_bset_w(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_bset_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_bset_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_bset_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_bset_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_bset_d(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_bset_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_bset_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+/*
+ * Fixed Multiply
+ * --------------
+ *
+ * +---------------+----------------------------------------------------------+
+ * | MADD_Q.H | Vector Fixed-Point Multiply and Add (halfword) |
+ * | MADD_Q.W | Vector Fixed-Point Multiply and Add (word) |
+ * | MADDR_Q.H | Vector Fixed-Point Multiply and Add Rounded (halfword) |
+ * | MADDR_Q.W | Vector Fixed-Point Multiply and Add Rounded (word) |
+ * | MSUB_Q.H | Vector Fixed-Point Multiply and Subtr. (halfword) |
+ * | MSUB_Q.W | Vector Fixed-Point Multiply and Subtr. (word) |
+ * | MSUBR_Q.H | Vector Fixed-Point Multiply and Subtr. Rounded (halfword)|
+ * | MSUBR_Q.W | Vector Fixed-Point Multiply and Subtr. Rounded (word) |
+ * | MUL_Q.H | Vector Fixed-Point Multiply (halfword) |
+ * | MUL_Q.W | Vector Fixed-Point Multiply (word) |
+ * | MULR_Q.H | Vector Fixed-Point Multiply Rounded (halfword) |
+ * | MULR_Q.W | Vector Fixed-Point Multiply Rounded (word) |
+ * +---------------+----------------------------------------------------------+
+ */
+
+/* TODO: insert Fixed Multiply group helpers here */
+
+
+/*
+ * Float Max Min
+ * -------------
+ *
+ * +---------------+----------------------------------------------------------+
+ * | FMAX_A.W | Vector Floating-Point Maximum (Absolute) (word) |
+ * | FMAX_A.D | Vector Floating-Point Maximum (Absolute) (doubleword) |
+ * | FMAX.W | Vector Floating-Point Maximum (word) |
+ * | FMAX.D | Vector Floating-Point Maximum (doubleword) |
+ * | FMIN_A.W | Vector Floating-Point Minimum (Absolute) (word) |
* | FMIN_A.D | Vector Floating-Point Minimum (Absolute) (doubleword) |
* | FMIN.W | Vector Floating-Point Minimum (word) |
* | FMIN.D | Vector Floating-Point Minimum (doubleword) |
* +---------------+----------------------------------------------------------+
*/
-/* TODO: insert Int Add group helpers here */
+static inline int64_t msa_add_a_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
+ uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
+ return abs_arg1 + abs_arg2;
+}
-/*
- * Int Average
- * -----------
- *
- * +---------------+----------------------------------------------------------+
- * | AVE_S.B | Vector Signed Average (byte) |
- * | AVE_S.H | Vector Signed Average (halfword) |
- * | AVE_S.W | Vector Signed Average (word) |
- * | AVE_S.D | Vector Signed Average (doubleword) |
- * | AVE_U.B | Vector Unsigned Average (byte) |
- * | AVE_U.H | Vector Unsigned Average (halfword) |
- * | AVE_U.W | Vector Unsigned Average (word) |
- * | AVE_U.D | Vector Unsigned Average (doubleword) |
- * | AVER_S.B | Vector Signed Average Rounded (byte) |
- * | AVER_S.H | Vector Signed Average Rounded (halfword) |
- * | AVER_S.W | Vector Signed Average Rounded (word) |
- * | AVER_S.D | Vector Signed Average Rounded (doubleword) |
- * | AVER_U.B | Vector Unsigned Average Rounded (byte) |
- * | AVER_U.H | Vector Unsigned Average Rounded (halfword) |
- * | AVER_U.W | Vector Unsigned Average Rounded (word) |
- * | AVER_U.D | Vector Unsigned Average Rounded (doubleword) |
- * +---------------+----------------------------------------------------------+
- */
+void helper_msa_add_a_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-/* TODO: insert Int Average group helpers here */
+ pwd->b[0] = msa_add_a_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_add_a_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_add_a_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_add_a_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_add_a_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_add_a_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_add_a_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_add_a_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_add_a_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_add_a_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_add_a_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_add_a_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_add_a_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_add_a_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_add_a_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_add_a_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_add_a_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+ pwd->h[0] = msa_add_a_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_add_a_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_add_a_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_add_a_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_add_a_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_add_a_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_add_a_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_add_a_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
-/*
- * Int Compare
- * -----------
- *
- * +---------------+----------------------------------------------------------+
- * | CEQ.B | Vector Compare Equal (byte) |
- * | CEQ.H | Vector Compare Equal (halfword) |
- * | CEQ.W | Vector Compare Equal (word) |
- * | CEQ.D | Vector Compare Equal (doubleword) |
- * | CLE_S.B | Vector Compare Signed Less Than or Equal (byte) |
- * | CLE_S.H | Vector Compare Signed Less Than or Equal (halfword) |
- * | CLE_S.W | Vector Compare Signed Less Than or Equal (word) |
- * | CLE_S.D | Vector Compare Signed Less Than or Equal (doubleword) |
- * | CLE_U.B | Vector Compare Unsigned Less Than or Equal (byte) |
- * | CLE_U.H | Vector Compare Unsigned Less Than or Equal (halfword) |
- * | CLE_U.W | Vector Compare Unsigned Less Than or Equal (word) |
- * | CLE_U.D | Vector Compare Unsigned Less Than or Equal (doubleword) |
- * | CLT_S.B | Vector Compare Signed Less Than (byte) |
- * | CLT_S.H | Vector Compare Signed Less Than (halfword) |
- * | CLT_S.W | Vector Compare Signed Less Than (word) |
- * | CLT_S.D | Vector Compare Signed Less Than (doubleword) |
- * | CLT_U.B | Vector Compare Unsigned Less Than (byte) |
- * | CLT_U.H | Vector Compare Unsigned Less Than (halfword) |
- * | CLT_U.W | Vector Compare Unsigned Less Than (word) |
- * | CLT_U.D | Vector Compare Unsigned Less Than (doubleword) |
- * +---------------+----------------------------------------------------------+
- */
+void helper_msa_add_a_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-/* TODO: insert Int Compare group helpers here */
+ pwd->w[0] = msa_add_a_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_add_a_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_add_a_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_add_a_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+void helper_msa_add_a_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-/*
- * Int Divide
- * ----------
- *
- * +---------------+----------------------------------------------------------+
- * | DIV_S.B | Vector Signed Divide (byte) |
- * | DIV_S.H | Vector Signed Divide (halfword) |
- * | DIV_S.W | Vector Signed Divide (word) |
- * | DIV_S.D | Vector Signed Divide (doubleword) |
- * | DIV_U.B | Vector Unsigned Divide (byte) |
- * | DIV_U.H | Vector Unsigned Divide (halfword) |
- * | DIV_U.W | Vector Unsigned Divide (word) |
- * | DIV_U.D | Vector Unsigned Divide (doubleword) |
- * +---------------+----------------------------------------------------------+
- */
+ pwd->d[0] = msa_add_a_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_add_a_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
-/* TODO: insert Int Divide group helpers here */
+static inline int64_t msa_adds_a_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ uint64_t max_int = (uint64_t)DF_MAX_INT(df);
+ uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
+ uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
+ if (abs_arg1 > max_int || abs_arg2 > max_int) {
+ return (int64_t)max_int;
+ } else {
+ return (abs_arg1 < max_int - abs_arg2) ? abs_arg1 + abs_arg2 : max_int;
+ }
+}
-/*
- * Int Dot Product
- * ---------------
- *
- * +---------------+----------------------------------------------------------+
- * | DOTP_S.H | Vector Signed Dot Product (halfword) |
- * | DOTP_S.W | Vector Signed Dot Product (word) |
- * | DOTP_S.D | Vector Signed Dot Product (doubleword) |
- * | DOTP_U.H | Vector Unsigned Dot Product (halfword) |
- * | DOTP_U.W | Vector Unsigned Dot Product (word) |
- * | DOTP_U.D | Vector Unsigned Dot Product (doubleword) |
- * | DPADD_S.H | Vector Signed Dot Product (halfword) |
- * | DPADD_S.W | Vector Signed Dot Product (word) |
- * | DPADD_S.D | Vector Signed Dot Product (doubleword) |
- * | DPADD_U.H | Vector Unsigned Dot Product (halfword) |
- * | DPADD_U.W | Vector Unsigned Dot Product (word) |
- * | DPADD_U.D | Vector Unsigned Dot Product (doubleword) |
- * | DPSUB_S.H | Vector Signed Dot Product (halfword) |
- * | DPSUB_S.W | Vector Signed Dot Product (word) |
- * | DPSUB_S.D | Vector Signed Dot Product (doubleword) |
- * | DPSUB_U.H | Vector Unsigned Dot Product (halfword) |
- * | DPSUB_U.W | Vector Unsigned Dot Product (word) |
- * | DPSUB_U.D | Vector Unsigned Dot Product (doubleword) |
- * +---------------+----------------------------------------------------------+
- */
+void helper_msa_adds_a_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-/* TODO: insert Int Dot Product group helpers here */
+ pwd->b[0] = msa_adds_a_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_adds_a_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_adds_a_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_adds_a_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_adds_a_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_adds_a_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_adds_a_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_adds_a_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_adds_a_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_adds_a_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_adds_a_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_adds_a_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_adds_a_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_adds_a_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_adds_a_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_adds_a_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_adds_a_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+ pwd->h[0] = msa_adds_a_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_adds_a_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_adds_a_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_adds_a_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_adds_a_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_adds_a_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_adds_a_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_adds_a_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
-/*
- * Int Max Min
- * -----------
- *
- * +---------------+----------------------------------------------------------+
- * | MAX_A.B | Vector Maximum Based on Absolute Value (byte) |
- * | MAX_A.H | Vector Maximum Based on Absolute Value (halfword) |
- * | MAX_A.W | Vector Maximum Based on Absolute Value (word) |
- * | MAX_A.D | Vector Maximum Based on Absolute Value (doubleword) |
- * | MAX_S.B | Vector Signed Maximum (byte) |
- * | MAX_S.H | Vector Signed Maximum (halfword) |
- * | MAX_S.W | Vector Signed Maximum (word) |
+void helper_msa_adds_a_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_adds_a_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_adds_a_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_adds_a_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_adds_a_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_adds_a_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_adds_a_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_adds_a_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+static inline int64_t msa_adds_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ int64_t max_int = DF_MAX_INT(df);
+ int64_t min_int = DF_MIN_INT(df);
+ if (arg1 < 0) {
+ return (min_int - arg1 < arg2) ? arg1 + arg2 : min_int;
+ } else {
+ return (arg2 < max_int - arg1) ? arg1 + arg2 : max_int;
+ }
+}
+
+void helper_msa_adds_s_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_adds_s_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_adds_s_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_adds_s_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_adds_s_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_adds_s_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_adds_s_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_adds_s_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_adds_s_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_adds_s_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_adds_s_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_adds_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_adds_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_adds_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_adds_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_adds_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_adds_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_adds_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_adds_s_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_adds_s_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_adds_s_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_adds_s_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_adds_s_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_adds_s_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_adds_s_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_adds_s_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_adds_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_adds_s_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_adds_s_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_adds_s_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_adds_s_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_adds_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_adds_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_adds_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+static inline uint64_t msa_adds_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
+{
+ uint64_t max_uint = DF_MAX_UINT(df);
+ uint64_t u_arg1 = UNSIGNED(arg1, df);
+ uint64_t u_arg2 = UNSIGNED(arg2, df);
+ return (u_arg1 < max_uint - u_arg2) ? u_arg1 + u_arg2 : max_uint;
+}
+
+void helper_msa_adds_u_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_adds_u_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_adds_u_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_adds_u_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_adds_u_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_adds_u_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_adds_u_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_adds_u_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_adds_u_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_adds_u_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_adds_u_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_adds_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_adds_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_adds_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_adds_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_adds_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_adds_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_adds_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_adds_u_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_adds_u_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_adds_u_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_adds_u_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_adds_u_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_adds_u_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_adds_u_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_adds_u_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_adds_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_adds_u_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_adds_u_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_adds_u_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_adds_u_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_adds_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_adds_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_adds_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+static inline int64_t msa_addv_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ return arg1 + arg2;
+}
+
+void helper_msa_addv_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_addv_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_addv_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_addv_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_addv_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_addv_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_addv_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_addv_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_addv_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_addv_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_addv_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_addv_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_addv_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_addv_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_addv_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_addv_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_addv_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_addv_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_addv_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_addv_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_addv_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_addv_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_addv_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_addv_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_addv_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_addv_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_addv_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_addv_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_addv_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_addv_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_addv_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_addv_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_addv_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_addv_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+#define SIGNED_EVEN(a, df) \
+ ((((int64_t)(a)) << (64 - DF_BITS(df) / 2)) >> (64 - DF_BITS(df) / 2))
+
+#define UNSIGNED_EVEN(a, df) \
+ ((((uint64_t)(a)) << (64 - DF_BITS(df) / 2)) >> (64 - DF_BITS(df) / 2))
+
+#define SIGNED_ODD(a, df) \
+ ((((int64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df) / 2))
+
+#define UNSIGNED_ODD(a, df) \
+ ((((uint64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df) / 2))
+
+
+static inline int64_t msa_hadd_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ return SIGNED_ODD(arg1, df) + SIGNED_EVEN(arg2, df);
+}
+
+void helper_msa_hadd_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_hadd_s_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_hadd_s_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_hadd_s_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_hadd_s_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_hadd_s_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_hadd_s_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_hadd_s_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_hadd_s_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_hadd_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_hadd_s_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_hadd_s_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_hadd_s_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_hadd_s_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_hadd_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_hadd_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_hadd_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+static inline int64_t msa_hadd_u_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ return UNSIGNED_ODD(arg1, df) + UNSIGNED_EVEN(arg2, df);
+}
+
+void helper_msa_hadd_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_hadd_u_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_hadd_u_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_hadd_u_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_hadd_u_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_hadd_u_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_hadd_u_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_hadd_u_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_hadd_u_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_hadd_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_hadd_u_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_hadd_u_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_hadd_u_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_hadd_u_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_hadd_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_hadd_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_hadd_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+/*
+ * Int Average
+ * -----------
+ *
+ * +---------------+----------------------------------------------------------+
+ * | AVE_S.B | Vector Signed Average (byte) |
+ * | AVE_S.H | Vector Signed Average (halfword) |
+ * | AVE_S.W | Vector Signed Average (word) |
+ * | AVE_S.D | Vector Signed Average (doubleword) |
+ * | AVE_U.B | Vector Unsigned Average (byte) |
+ * | AVE_U.H | Vector Unsigned Average (halfword) |
+ * | AVE_U.W | Vector Unsigned Average (word) |
+ * | AVE_U.D | Vector Unsigned Average (doubleword) |
+ * | AVER_S.B | Vector Signed Average Rounded (byte) |
+ * | AVER_S.H | Vector Signed Average Rounded (halfword) |
+ * | AVER_S.W | Vector Signed Average Rounded (word) |
+ * | AVER_S.D | Vector Signed Average Rounded (doubleword) |
+ * | AVER_U.B | Vector Unsigned Average Rounded (byte) |
+ * | AVER_U.H | Vector Unsigned Average Rounded (halfword) |
+ * | AVER_U.W | Vector Unsigned Average Rounded (word) |
+ * | AVER_U.D | Vector Unsigned Average Rounded (doubleword) |
+ * +---------------+----------------------------------------------------------+
+ */
+
+static inline int64_t msa_ave_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ /* signed shift */
+ return (arg1 >> 1) + (arg2 >> 1) + (arg1 & arg2 & 1);
+}
+
+void helper_msa_ave_s_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_ave_s_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_ave_s_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_ave_s_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_ave_s_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_ave_s_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_ave_s_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_ave_s_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_ave_s_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_ave_s_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_ave_s_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_ave_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_ave_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_ave_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_ave_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_ave_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_ave_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_ave_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_ave_s_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_ave_s_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_ave_s_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_ave_s_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_ave_s_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_ave_s_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_ave_s_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_ave_s_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_ave_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_ave_s_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_ave_s_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_ave_s_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_ave_s_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_ave_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_ave_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_ave_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+static inline uint64_t msa_ave_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
+{
+ uint64_t u_arg1 = UNSIGNED(arg1, df);
+ uint64_t u_arg2 = UNSIGNED(arg2, df);
+ /* unsigned shift */
+ return (u_arg1 >> 1) + (u_arg2 >> 1) + (u_arg1 & u_arg2 & 1);
+}
+
+void helper_msa_ave_u_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_ave_u_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_ave_u_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_ave_u_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_ave_u_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_ave_u_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_ave_u_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_ave_u_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_ave_u_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_ave_u_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_ave_u_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_ave_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_ave_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_ave_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_ave_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_ave_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_ave_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_ave_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_ave_u_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_ave_u_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_ave_u_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_ave_u_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_ave_u_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_ave_u_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_ave_u_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_ave_u_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_ave_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_ave_u_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_ave_u_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_ave_u_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_ave_u_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_ave_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_ave_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_ave_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+static inline int64_t msa_aver_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ /* signed shift */
+ return (arg1 >> 1) + (arg2 >> 1) + ((arg1 | arg2) & 1);
+}
+
+void helper_msa_aver_s_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_aver_s_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_aver_s_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_aver_s_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_aver_s_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_aver_s_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_aver_s_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_aver_s_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_aver_s_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_aver_s_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_aver_s_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_aver_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_aver_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_aver_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_aver_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_aver_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_aver_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_aver_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_aver_s_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_aver_s_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_aver_s_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_aver_s_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_aver_s_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_aver_s_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_aver_s_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_aver_s_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_aver_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_aver_s_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_aver_s_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_aver_s_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_aver_s_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_aver_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_aver_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_aver_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+static inline uint64_t msa_aver_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
+{
+ uint64_t u_arg1 = UNSIGNED(arg1, df);
+ uint64_t u_arg2 = UNSIGNED(arg2, df);
+ /* unsigned shift */
+ return (u_arg1 >> 1) + (u_arg2 >> 1) + ((u_arg1 | u_arg2) & 1);
+}
+
+void helper_msa_aver_u_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_aver_u_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_aver_u_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_aver_u_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_aver_u_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_aver_u_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_aver_u_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_aver_u_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_aver_u_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_aver_u_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_aver_u_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_aver_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_aver_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_aver_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_aver_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_aver_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_aver_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_aver_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_aver_u_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_aver_u_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_aver_u_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_aver_u_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_aver_u_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_aver_u_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_aver_u_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_aver_u_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_aver_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_aver_u_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_aver_u_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_aver_u_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_aver_u_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_aver_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_aver_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_aver_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+/*
+ * Int Compare
+ * -----------
+ *
+ * +---------------+----------------------------------------------------------+
+ * | CEQ.B | Vector Compare Equal (byte) |
+ * | CEQ.H | Vector Compare Equal (halfword) |
+ * | CEQ.W | Vector Compare Equal (word) |
+ * | CEQ.D | Vector Compare Equal (doubleword) |
+ * | CLE_S.B | Vector Compare Signed Less Than or Equal (byte) |
+ * | CLE_S.H | Vector Compare Signed Less Than or Equal (halfword) |
+ * | CLE_S.W | Vector Compare Signed Less Than or Equal (word) |
+ * | CLE_S.D | Vector Compare Signed Less Than or Equal (doubleword) |
+ * | CLE_U.B | Vector Compare Unsigned Less Than or Equal (byte) |
+ * | CLE_U.H | Vector Compare Unsigned Less Than or Equal (halfword) |
+ * | CLE_U.W | Vector Compare Unsigned Less Than or Equal (word) |
+ * | CLE_U.D | Vector Compare Unsigned Less Than or Equal (doubleword) |
+ * | CLT_S.B | Vector Compare Signed Less Than (byte) |
+ * | CLT_S.H | Vector Compare Signed Less Than (halfword) |
+ * | CLT_S.W | Vector Compare Signed Less Than (word) |
+ * | CLT_S.D | Vector Compare Signed Less Than (doubleword) |
+ * | CLT_U.B | Vector Compare Unsigned Less Than (byte) |
+ * | CLT_U.H | Vector Compare Unsigned Less Than (halfword) |
+ * | CLT_U.W | Vector Compare Unsigned Less Than (word) |
+ * | CLT_U.D | Vector Compare Unsigned Less Than (doubleword) |
+ * +---------------+----------------------------------------------------------+
+ */
+
+static inline int64_t msa_ceq_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ return arg1 == arg2 ? -1 : 0;
+}
+
+static inline int8_t msa_ceq_b(int8_t arg1, int8_t arg2)
+{
+ return arg1 == arg2 ? -1 : 0;
+}
+
+void helper_msa_ceq_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_ceq_b(pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_ceq_b(pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_ceq_b(pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_ceq_b(pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_ceq_b(pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_ceq_b(pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_ceq_b(pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_ceq_b(pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_ceq_b(pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_ceq_b(pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_ceq_b(pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_ceq_b(pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_ceq_b(pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_ceq_b(pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_ceq_b(pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_ceq_b(pws->b[15], pwt->b[15]);
+}
+
+static inline int16_t msa_ceq_h(int16_t arg1, int16_t arg2)
+{
+ return arg1 == arg2 ? -1 : 0;
+}
+
+void helper_msa_ceq_h(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_ceq_h(pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_ceq_h(pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_ceq_h(pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_ceq_h(pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_ceq_h(pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_ceq_h(pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_ceq_h(pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_ceq_h(pws->h[7], pwt->h[7]);
+}
+
+static inline int32_t msa_ceq_w(int32_t arg1, int32_t arg2)
+{
+ return arg1 == arg2 ? -1 : 0;
+}
+
+void helper_msa_ceq_w(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_ceq_w(pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_ceq_w(pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_ceq_w(pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_ceq_w(pws->w[3], pwt->w[3]);
+}
+
+static inline int64_t msa_ceq_d(int64_t arg1, int64_t arg2)
+{
+ return arg1 == arg2 ? -1 : 0;
+}
+
+void helper_msa_ceq_d(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_ceq_d(pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_ceq_d(pws->d[1], pwt->d[1]);
+}
+
+static inline int64_t msa_cle_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ return arg1 <= arg2 ? -1 : 0;
+}
+
+void helper_msa_cle_s_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_cle_s_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_cle_s_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_cle_s_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_cle_s_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_cle_s_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_cle_s_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_cle_s_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_cle_s_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_cle_s_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_cle_s_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_cle_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_cle_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_cle_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_cle_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_cle_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_cle_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_cle_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_cle_s_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_cle_s_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_cle_s_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_cle_s_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_cle_s_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_cle_s_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_cle_s_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_cle_s_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_cle_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_cle_s_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_cle_s_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_cle_s_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_cle_s_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_cle_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_cle_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_cle_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+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;
+}
+
+void helper_msa_cle_u_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_cle_u_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_cle_u_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_cle_u_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_cle_u_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_cle_u_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_cle_u_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_cle_u_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_cle_u_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_cle_u_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_cle_u_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_cle_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_cle_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_cle_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_cle_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_cle_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_cle_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_cle_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_cle_u_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_cle_u_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_cle_u_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_cle_u_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_cle_u_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_cle_u_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_cle_u_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_cle_u_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_cle_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_cle_u_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_cle_u_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_cle_u_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_cle_u_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_cle_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_cle_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_cle_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+static inline int64_t msa_clt_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ return arg1 < arg2 ? -1 : 0;
+}
+
+static inline int8_t msa_clt_s_b(int8_t arg1, int8_t arg2)
+{
+ return arg1 < arg2 ? -1 : 0;
+}
+
+void helper_msa_clt_s_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_clt_s_b(pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_clt_s_b(pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_clt_s_b(pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_clt_s_b(pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_clt_s_b(pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_clt_s_b(pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_clt_s_b(pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_clt_s_b(pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_clt_s_b(pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_clt_s_b(pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_clt_s_b(pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_clt_s_b(pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_clt_s_b(pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_clt_s_b(pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_clt_s_b(pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_clt_s_b(pws->b[15], pwt->b[15]);
+}
+
+static inline int16_t msa_clt_s_h(int16_t arg1, int16_t arg2)
+{
+ return arg1 < arg2 ? -1 : 0;
+}
+
+void helper_msa_clt_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_clt_s_h(pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_clt_s_h(pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_clt_s_h(pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_clt_s_h(pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_clt_s_h(pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_clt_s_h(pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_clt_s_h(pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_clt_s_h(pws->h[7], pwt->h[7]);
+}
+
+static inline int32_t msa_clt_s_w(int32_t arg1, int32_t arg2)
+{
+ return arg1 < arg2 ? -1 : 0;
+}
+
+void helper_msa_clt_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_clt_s_w(pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_clt_s_w(pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_clt_s_w(pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_clt_s_w(pws->w[3], pwt->w[3]);
+}
+
+static inline int64_t msa_clt_s_d(int64_t arg1, int64_t arg2)
+{
+ return arg1 < arg2 ? -1 : 0;
+}
+
+void helper_msa_clt_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_clt_s_d(pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_clt_s_d(pws->d[1], pwt->d[1]);
+}
+
+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;
+}
+
+void helper_msa_clt_u_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_clt_u_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_clt_u_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_clt_u_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_clt_u_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_clt_u_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_clt_u_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_clt_u_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_clt_u_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_clt_u_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_clt_u_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_clt_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_clt_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_clt_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_clt_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_clt_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_clt_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_clt_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_clt_u_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_clt_u_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_clt_u_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_clt_u_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_clt_u_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_clt_u_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_clt_u_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_clt_u_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_clt_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_clt_u_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_clt_u_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_clt_u_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_clt_u_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_clt_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_clt_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_clt_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+/*
+ * Int Divide
+ * ----------
+ *
+ * +---------------+----------------------------------------------------------+
+ * | DIV_S.B | Vector Signed Divide (byte) |
+ * | DIV_S.H | Vector Signed Divide (halfword) |
+ * | DIV_S.W | Vector Signed Divide (word) |
+ * | DIV_S.D | Vector Signed Divide (doubleword) |
+ * | DIV_U.B | Vector Unsigned Divide (byte) |
+ * | DIV_U.H | Vector Unsigned Divide (halfword) |
+ * | DIV_U.W | Vector Unsigned Divide (word) |
+ * | DIV_U.D | Vector Unsigned Divide (doubleword) |
+ * +---------------+----------------------------------------------------------+
+ */
+
+
+static inline int64_t msa_div_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ if (arg1 == DF_MIN_INT(df) && arg2 == -1) {
+ return DF_MIN_INT(df);
+ }
+ return arg2 ? arg1 / arg2
+ : arg1 >= 0 ? -1 : 1;
+}
+
+void helper_msa_div_s_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_div_s_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_div_s_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_div_s_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_div_s_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_div_s_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_div_s_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_div_s_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_div_s_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_div_s_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_div_s_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_div_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_div_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_div_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_div_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_div_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_div_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_div_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_div_s_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_div_s_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_div_s_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_div_s_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_div_s_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_div_s_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_div_s_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_div_s_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_div_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_div_s_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_div_s_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_div_s_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_div_s_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_div_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_div_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_div_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+static inline int64_t msa_div_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 arg2 ? u_arg1 / u_arg2 : -1;
+}
+
+void helper_msa_div_u_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_div_u_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_div_u_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_div_u_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_div_u_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_div_u_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_div_u_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_div_u_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_div_u_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_div_u_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_div_u_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_div_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_div_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_div_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_div_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_div_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_div_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_div_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_div_u_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_div_u_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_div_u_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_div_u_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_div_u_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_div_u_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_div_u_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_div_u_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_div_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_div_u_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_div_u_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_div_u_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_div_u_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_div_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_div_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_div_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+/*
+ * Int Dot Product
+ * ---------------
+ *
+ * +---------------+----------------------------------------------------------+
+ * | DOTP_S.H | Vector Signed Dot Product (halfword) |
+ * | DOTP_S.W | Vector Signed Dot Product (word) |
+ * | DOTP_S.D | Vector Signed Dot Product (doubleword) |
+ * | DOTP_U.H | Vector Unsigned Dot Product (halfword) |
+ * | DOTP_U.W | Vector Unsigned Dot Product (word) |
+ * | DOTP_U.D | Vector Unsigned Dot Product (doubleword) |
+ * | DPADD_S.H | Vector Signed Dot Product (halfword) |
+ * | DPADD_S.W | Vector Signed Dot Product (word) |
+ * | DPADD_S.D | Vector Signed Dot Product (doubleword) |
+ * | DPADD_U.H | Vector Unsigned Dot Product (halfword) |
+ * | DPADD_U.W | Vector Unsigned Dot Product (word) |
+ * | DPADD_U.D | Vector Unsigned Dot Product (doubleword) |
+ * | DPSUB_S.H | Vector Signed Dot Product (halfword) |
+ * | DPSUB_S.W | Vector Signed Dot Product (word) |
+ * | DPSUB_S.D | Vector Signed Dot Product (doubleword) |
+ * | DPSUB_U.H | Vector Unsigned Dot Product (halfword) |
+ * | DPSUB_U.W | Vector Unsigned Dot Product (word) |
+ * | DPSUB_U.D | Vector Unsigned Dot Product (doubleword) |
+ * +---------------+----------------------------------------------------------+
+ */
+
+/* TODO: insert Int Dot Product group helpers here */
+
+
+/*
+ * Int Max Min
+ * -----------
+ *
+ * +---------------+----------------------------------------------------------+
+ * | MAX_A.B | Vector Maximum Based on Absolute Value (byte) |
+ * | MAX_A.H | Vector Maximum Based on Absolute Value (halfword) |
+ * | MAX_A.W | Vector Maximum Based on Absolute Value (word) |
+ * | MAX_A.D | Vector Maximum Based on Absolute Value (doubleword) |
+ * | MAX_S.B | Vector Signed Maximum (byte) |
+ * | MAX_S.H | Vector Signed Maximum (halfword) |
+ * | MAX_S.W | Vector Signed Maximum (word) |
* | MAX_S.D | Vector Signed Maximum (doubleword) |
* | MAX_U.B | Vector Unsigned Maximum (byte) |
* | MAX_U.H | Vector Unsigned Maximum (halfword) |
* +---------------+----------------------------------------------------------+
*/
-/* TODO: insert Int Max Min group helpers here */
+static inline int64_t msa_max_a_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
+ uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
+ return abs_arg1 > abs_arg2 ? arg1 : arg2;
+}
+
+void helper_msa_max_a_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_max_a_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_max_a_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_max_a_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_max_a_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_max_a_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_max_a_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_max_a_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_max_a_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_max_a_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_max_a_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_max_a_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_max_a_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_max_a_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_max_a_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_max_a_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_max_a_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_max_a_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_max_a_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_max_a_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_max_a_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_max_a_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_max_a_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_max_a_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_max_a_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_max_a_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_max_a_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_max_a_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_max_a_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_max_a_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_max_a_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_max_a_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_max_a_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_max_a_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+static inline int64_t msa_max_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ return arg1 > arg2 ? arg1 : arg2;
+}
+
+void helper_msa_max_s_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_max_s_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_max_s_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_max_s_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_max_s_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_max_s_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_max_s_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_max_s_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_max_s_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_max_s_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_max_s_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_max_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_max_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_max_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_max_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_max_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_max_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_max_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_max_s_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_max_s_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_max_s_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_max_s_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_max_s_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_max_s_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_max_s_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_max_s_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_max_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_max_s_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_max_s_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_max_s_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_max_s_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_max_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_max_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_max_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+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;
+}
+
+void helper_msa_max_u_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_max_u_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_max_u_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_max_u_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_max_u_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_max_u_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_max_u_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_max_u_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_max_u_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_max_u_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_max_u_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_max_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_max_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_max_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_max_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_max_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_max_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_max_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_max_u_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_max_u_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_max_u_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_max_u_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_max_u_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_max_u_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_max_u_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_max_u_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_max_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_max_u_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_max_u_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_max_u_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_max_u_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_max_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_max_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_max_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+static inline int64_t msa_min_a_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
+ uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
+ return abs_arg1 < abs_arg2 ? arg1 : arg2;
+}
+
+void helper_msa_min_a_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_min_a_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_min_a_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_min_a_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_min_a_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_min_a_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_min_a_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_min_a_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_min_a_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_min_a_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_min_a_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_min_a_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_min_a_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_min_a_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_min_a_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_min_a_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_min_a_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_min_a_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_min_a_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_min_a_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_min_a_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_min_a_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_min_a_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_min_a_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_min_a_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_min_a_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_min_a_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_min_a_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_min_a_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_min_a_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_min_a_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_min_a_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_min_a_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_min_a_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+static inline int64_t msa_min_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ return arg1 < arg2 ? arg1 : arg2;
+}
+
+void helper_msa_min_s_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_min_s_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_min_s_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_min_s_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_min_s_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_min_s_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_min_s_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_min_s_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_min_s_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_min_s_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_min_s_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_min_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_min_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_min_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_min_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_min_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_min_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_min_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_min_s_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_min_s_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_min_s_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_min_s_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_min_s_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_min_s_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_min_s_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_min_s_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_min_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_min_s_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_min_s_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_min_s_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_min_s_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_min_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_min_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_min_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+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;
+}
+
+void helper_msa_min_u_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_min_u_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_min_u_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_min_u_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_min_u_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_min_u_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_min_u_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_min_u_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_min_u_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_min_u_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_min_u_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_min_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_min_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_min_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_min_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_min_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_min_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_min_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_min_u_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_min_u_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_min_u_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_min_u_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_min_u_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_min_u_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_min_u_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_min_u_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_min_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_min_u_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_min_u_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_min_u_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_min_u_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_min_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_min_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_min_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
/*
* +---------------+----------------------------------------------------------+
*/
-/* TODO: insert Int Modulo group helpers here */
+static inline int64_t msa_mod_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ if (arg1 == DF_MIN_INT(df) && arg2 == -1) {
+ return 0;
+ }
+ return arg2 ? arg1 % arg2 : arg1;
+}
+
+void helper_msa_mod_s_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_mod_s_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_mod_s_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_mod_s_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_mod_s_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_mod_s_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_mod_s_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_mod_s_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_mod_s_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_mod_s_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_mod_s_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_mod_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_mod_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_mod_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_mod_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_mod_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_mod_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_mod_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_mod_s_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_mod_s_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_mod_s_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_mod_s_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_mod_s_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_mod_s_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_mod_s_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_mod_s_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_mod_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_mod_s_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_mod_s_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_mod_s_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_mod_s_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_mod_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_mod_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_mod_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+static inline int64_t msa_mod_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_arg2 ? u_arg1 % u_arg2 : u_arg1;
+}
+
+void helper_msa_mod_u_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_mod_u_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_mod_u_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_mod_u_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_mod_u_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_mod_u_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_mod_u_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_mod_u_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_mod_u_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_mod_u_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_mod_u_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_mod_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_mod_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_mod_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_mod_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_mod_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_mod_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_mod_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_mod_u_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_mod_u_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_mod_u_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_mod_u_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_mod_u_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_mod_u_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_mod_u_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_mod_u_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_mod_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_mod_u_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_mod_u_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_mod_u_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_mod_u_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_mod_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_mod_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_mod_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
/*
* +---------------+----------------------------------------------------------+
*/
-/* TODO: insert Int Multiply group helpers here */
+/* TODO: insert Int Multiply group helpers here */
+
+
+/*
+ * Int Subtract
+ * ------------
+ *
+ * +---------------+----------------------------------------------------------+
+ * | ASUB_S.B | Vector Absolute Values of Signed Subtract (byte) |
+ * | ASUB_S.H | Vector Absolute Values of Signed Subtract (halfword) |
+ * | ASUB_S.W | Vector Absolute Values of Signed Subtract (word) |
+ * | ASUB_S.D | Vector Absolute Values of Signed Subtract (doubleword) |
+ * | ASUB_U.B | Vector Absolute Values of Unsigned Subtract (byte) |
+ * | ASUB_U.H | Vector Absolute Values of Unsigned Subtract (halfword) |
+ * | ASUB_U.W | Vector Absolute Values of Unsigned Subtract (word) |
+ * | ASUB_U.D | Vector Absolute Values of Unsigned Subtract (doubleword) |
+ * | HSUB_S.H | Vector Signed Horizontal Subtract (halfword) |
+ * | HSUB_S.W | Vector Signed Horizontal Subtract (word) |
+ * | HSUB_S.D | Vector Signed Horizontal Subtract (doubleword) |
+ * | HSUB_U.H | Vector Unigned Horizontal Subtract (halfword) |
+ * | HSUB_U.W | Vector Unigned Horizontal Subtract (word) |
+ * | HSUB_U.D | Vector Unigned Horizontal Subtract (doubleword) |
+ * | SUBS_S.B | Vector Signed Saturated Subtract (of Signed) (byte) |
+ * | SUBS_S.H | Vector Signed Saturated Subtract (of Signed) (halfword) |
+ * | SUBS_S.W | Vector Signed Saturated Subtract (of Signed) (word) |
+ * | SUBS_S.D | Vector Signed Saturated Subtract (of Signed) (doubleword)|
+ * | SUBS_U.B | Vector Unsigned Saturated Subtract (of Uns.) (byte) |
+ * | SUBS_U.H | Vector Unsigned Saturated Subtract (of Uns.) (halfword) |
+ * | SUBS_U.W | Vector Unsigned Saturated Subtract (of Uns.) (word) |
+ * | SUBS_U.D | Vector Unsigned Saturated Subtract (of Uns.) (doubleword)|
+ * | SUBSUS_U.B | Vector Uns. Sat. Subtract (of S. from Uns.) (byte) |
+ * | SUBSUS_U.H | Vector Uns. Sat. Subtract (of S. from Uns.) (halfword) |
+ * | SUBSUS_U.W | Vector Uns. Sat. Subtract (of S. from Uns.) (word) |
+ * | SUBSUS_U.D | Vector Uns. Sat. Subtract (of S. from Uns.) (doubleword) |
+ * | SUBSUU_S.B | Vector Signed Saturated Subtract (of Uns.) (byte) |
+ * | SUBSUU_S.H | Vector Signed Saturated Subtract (of Uns.) (halfword) |
+ * | SUBSUU_S.W | Vector Signed Saturated Subtract (of Uns.) (word) |
+ * | SUBSUU_S.D | Vector Signed Saturated Subtract (of Uns.) (doubleword) |
+ * | SUBV.B | Vector Subtract (byte) |
+ * | SUBV.H | Vector Subtract (halfword) |
+ * | SUBV.W | Vector Subtract (word) |
+ * | SUBV.D | Vector Subtract (doubleword) |
+ * +---------------+----------------------------------------------------------+
+ */
+
+
+static inline int64_t msa_asub_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ /* signed compare */
+ return (arg1 < arg2) ?
+ (uint64_t)(arg2 - arg1) : (uint64_t)(arg1 - arg2);
+}
+
+void helper_msa_asub_s_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_asub_s_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_asub_s_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_asub_s_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_asub_s_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_asub_s_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_asub_s_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_asub_s_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_asub_s_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_asub_s_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_asub_s_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_asub_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_asub_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_asub_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_asub_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_asub_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_asub_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_asub_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_asub_s_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_asub_s_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_asub_s_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_asub_s_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_asub_s_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_asub_s_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_asub_s_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_asub_s_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_asub_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_asub_s_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_asub_s_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_asub_s_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_asub_s_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_asub_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_asub_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_asub_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+static inline uint64_t msa_asub_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
+{
+ uint64_t u_arg1 = UNSIGNED(arg1, df);
+ uint64_t u_arg2 = UNSIGNED(arg2, df);
+ /* unsigned compare */
+ return (u_arg1 < u_arg2) ?
+ (uint64_t)(u_arg2 - u_arg1) : (uint64_t)(u_arg1 - u_arg2);
+}
+
+void helper_msa_asub_u_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_asub_u_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_asub_u_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_asub_u_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_asub_u_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_asub_u_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_asub_u_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_asub_u_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_asub_u_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_asub_u_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_asub_u_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_asub_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_asub_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_asub_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_asub_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_asub_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_asub_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_asub_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_asub_u_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_asub_u_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_asub_u_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_asub_u_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_asub_u_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_asub_u_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_asub_u_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_asub_u_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_asub_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_asub_u_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_asub_u_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_asub_u_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_asub_u_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_asub_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_asub_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_asub_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+/* TODO: insert the rest of Int Subtract group helpers here */
+
+
+static inline int64_t msa_hsub_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ return SIGNED_ODD(arg1, df) - SIGNED_EVEN(arg2, df);
+}
+
+void helper_msa_hsub_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_hsub_s_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_hsub_s_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_hsub_s_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_hsub_s_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_hsub_s_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_hsub_s_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_hsub_s_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_hsub_s_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_hsub_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_hsub_s_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_hsub_s_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_hsub_s_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_hsub_s_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_hsub_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_hsub_s_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_hsub_s_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
-/*
- * Int Subtract
- * ------------
- *
- * +---------------+----------------------------------------------------------+
- * | ASUB_S.B | Vector Absolute Values of Signed Subtract (byte) |
- * | ASUB_S.H | Vector Absolute Values of Signed Subtract (halfword) |
- * | ASUB_S.W | Vector Absolute Values of Signed Subtract (word) |
- * | ASUB_S.D | Vector Absolute Values of Signed Subtract (doubleword) |
- * | ASUB_U.B | Vector Absolute Values of Unsigned Subtract (byte) |
- * | ASUB_U.H | Vector Absolute Values of Unsigned Subtract (halfword) |
- * | ASUB_U.W | Vector Absolute Values of Unsigned Subtract (word) |
- * | ASUB_U.D | Vector Absolute Values of Unsigned Subtract (doubleword) |
- * | HSUB_S.H | Vector Signed Horizontal Subtract (halfword) |
- * | HSUB_S.W | Vector Signed Horizontal Subtract (word) |
- * | HSUB_S.D | Vector Signed Horizontal Subtract (doubleword) |
- * | HSUB_U.H | Vector Unigned Horizontal Subtract (halfword) |
- * | HSUB_U.W | Vector Unigned Horizontal Subtract (word) |
- * | HSUB_U.D | Vector Unigned Horizontal Subtract (doubleword) |
- * | SUBS_S.B | Vector Signed Saturated Subtract (of Signed) (byte) |
- * | SUBS_S.H | Vector Signed Saturated Subtract (of Signed) (halfword) |
- * | SUBS_S.W | Vector Signed Saturated Subtract (of Signed) (word) |
- * | SUBS_S.D | Vector Signed Saturated Subtract (of Signed) (doubleword)|
- * | SUBS_U.B | Vector Unsigned Saturated Subtract (of Uns.) (byte) |
- * | SUBS_U.H | Vector Unsigned Saturated Subtract (of Uns.) (halfword) |
- * | SUBS_U.W | Vector Unsigned Saturated Subtract (of Uns.) (word) |
- * | SUBS_U.D | Vector Unsigned Saturated Subtract (of Uns.) (doubleword)|
- * | SUBSUS_U.B | Vector Uns. Sat. Subtract (of S. from Uns.) (byte) |
- * | SUBSUS_U.H | Vector Uns. Sat. Subtract (of S. from Uns.) (halfword) |
- * | SUBSUS_U.W | Vector Uns. Sat. Subtract (of S. from Uns.) (word) |
- * | SUBSUS_U.D | Vector Uns. Sat. Subtract (of S. from Uns.) (doubleword) |
- * | SUBSUU_S.B | Vector Signed Saturated Subtract (of Uns.) (byte) |
- * | SUBSUU_S.H | Vector Signed Saturated Subtract (of Uns.) (halfword) |
- * | SUBSUU_S.W | Vector Signed Saturated Subtract (of Uns.) (word) |
- * | SUBSUU_S.D | Vector Signed Saturated Subtract (of Uns.) (doubleword) |
- * | SUBV.B | Vector Subtract (byte) |
- * | SUBV.H | Vector Subtract (halfword) |
- * | SUBV.W | Vector Subtract (word) |
- * | SUBV.D | Vector Subtract (doubleword) |
- * +---------------+----------------------------------------------------------+
- */
+static inline int64_t msa_hsub_u_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ return UNSIGNED_ODD(arg1, df) - UNSIGNED_EVEN(arg2, df);
+}
+
+void helper_msa_hsub_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_hsub_u_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_hsub_u_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_hsub_u_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_hsub_u_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_hsub_u_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_hsub_u_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_hsub_u_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_hsub_u_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_hsub_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_hsub_u_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_hsub_u_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_hsub_u_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_hsub_u_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_hsub_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-/* TODO: insert Int Subtract group helpers here */
+ pwd->d[0] = msa_hsub_u_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_hsub_u_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
/*
* +---------------+----------------------------------------------------------+
*/
-/* TODO: insert Interleave group helpers here */
+void helper_msa_ilvev_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->b[8] = pws->b[9];
+ pwd->b[9] = pwt->b[9];
+ pwd->b[10] = pws->b[11];
+ pwd->b[11] = pwt->b[11];
+ pwd->b[12] = pws->b[13];
+ pwd->b[13] = pwt->b[13];
+ pwd->b[14] = pws->b[15];
+ pwd->b[15] = pwt->b[15];
+ pwd->b[0] = pws->b[1];
+ pwd->b[1] = pwt->b[1];
+ pwd->b[2] = pws->b[3];
+ pwd->b[3] = pwt->b[3];
+ pwd->b[4] = pws->b[5];
+ pwd->b[5] = pwt->b[5];
+ pwd->b[6] = pws->b[7];
+ pwd->b[7] = pwt->b[7];
+#else
+ pwd->b[15] = pws->b[14];
+ pwd->b[14] = pwt->b[14];
+ pwd->b[13] = pws->b[12];
+ pwd->b[12] = pwt->b[12];
+ pwd->b[11] = pws->b[10];
+ pwd->b[10] = pwt->b[10];
+ pwd->b[9] = pws->b[8];
+ pwd->b[8] = pwt->b[8];
+ pwd->b[7] = pws->b[6];
+ pwd->b[6] = pwt->b[6];
+ pwd->b[5] = pws->b[4];
+ pwd->b[4] = pwt->b[4];
+ pwd->b[3] = pws->b[2];
+ pwd->b[2] = pwt->b[2];
+ pwd->b[1] = pws->b[0];
+ pwd->b[0] = pwt->b[0];
+#endif
+}
+
+void helper_msa_ilvev_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->h[4] = pws->h[5];
+ pwd->h[5] = pwt->h[5];
+ pwd->h[6] = pws->h[7];
+ pwd->h[7] = pwt->h[7];
+ pwd->h[0] = pws->h[1];
+ pwd->h[1] = pwt->h[1];
+ pwd->h[2] = pws->h[3];
+ pwd->h[3] = pwt->h[3];
+#else
+ pwd->h[7] = pws->h[6];
+ pwd->h[6] = pwt->h[6];
+ pwd->h[5] = pws->h[4];
+ pwd->h[4] = pwt->h[4];
+ pwd->h[3] = pws->h[2];
+ pwd->h[2] = pwt->h[2];
+ pwd->h[1] = pws->h[0];
+ pwd->h[0] = pwt->h[0];
+#endif
+}
+
+void helper_msa_ilvev_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->w[2] = pws->w[3];
+ pwd->w[3] = pwt->w[3];
+ pwd->w[0] = pws->w[1];
+ pwd->w[1] = pwt->w[1];
+#else
+ pwd->w[3] = pws->w[2];
+ pwd->w[2] = pwt->w[2];
+ pwd->w[1] = pws->w[0];
+ pwd->w[0] = pwt->w[0];
+#endif
+}
+
+void helper_msa_ilvev_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[1] = pws->d[0];
+ pwd->d[0] = pwt->d[0];
+}
+
+
+void helper_msa_ilvod_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->b[7] = pwt->b[6];
+ pwd->b[6] = pws->b[6];
+ pwd->b[5] = pwt->b[4];
+ pwd->b[4] = pws->b[4];
+ pwd->b[3] = pwt->b[2];
+ pwd->b[2] = pws->b[2];
+ pwd->b[1] = pwt->b[0];
+ pwd->b[0] = pws->b[0];
+ pwd->b[15] = pwt->b[14];
+ pwd->b[14] = pws->b[14];
+ pwd->b[13] = pwt->b[12];
+ pwd->b[12] = pws->b[12];
+ pwd->b[11] = pwt->b[10];
+ pwd->b[10] = pws->b[10];
+ pwd->b[9] = pwt->b[8];
+ pwd->b[8] = pws->b[8];
+#else
+ pwd->b[0] = pwt->b[1];
+ pwd->b[1] = pws->b[1];
+ pwd->b[2] = pwt->b[3];
+ pwd->b[3] = pws->b[3];
+ pwd->b[4] = pwt->b[5];
+ pwd->b[5] = pws->b[5];
+ pwd->b[6] = pwt->b[7];
+ pwd->b[7] = pws->b[7];
+ pwd->b[8] = pwt->b[9];
+ pwd->b[9] = pws->b[9];
+ pwd->b[10] = pwt->b[11];
+ pwd->b[11] = pws->b[11];
+ pwd->b[12] = pwt->b[13];
+ pwd->b[13] = pws->b[13];
+ pwd->b[14] = pwt->b[15];
+ pwd->b[15] = pws->b[15];
+#endif
+}
+
+void helper_msa_ilvod_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->h[3] = pwt->h[2];
+ pwd->h[2] = pws->h[2];
+ pwd->h[1] = pwt->h[0];
+ pwd->h[0] = pws->h[0];
+ pwd->h[7] = pwt->h[6];
+ pwd->h[6] = pws->h[6];
+ pwd->h[5] = pwt->h[4];
+ pwd->h[4] = pws->h[4];
+#else
+ pwd->h[0] = pwt->h[1];
+ pwd->h[1] = pws->h[1];
+ pwd->h[2] = pwt->h[3];
+ pwd->h[3] = pws->h[3];
+ pwd->h[4] = pwt->h[5];
+ pwd->h[5] = pws->h[5];
+ pwd->h[6] = pwt->h[7];
+ pwd->h[7] = pws->h[7];
+#endif
+}
+
+void helper_msa_ilvod_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->w[1] = pwt->w[0];
+ pwd->w[0] = pws->w[0];
+ pwd->w[3] = pwt->w[2];
+ pwd->w[2] = pws->w[2];
+#else
+ pwd->w[0] = pwt->w[1];
+ pwd->w[1] = pws->w[1];
+ pwd->w[2] = pwt->w[3];
+ pwd->w[3] = pws->w[3];
+#endif
+}
+
+void helper_msa_ilvod_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = pwt->d[1];
+ pwd->d[1] = pws->d[1];
+}
+
+
+void helper_msa_ilvl_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->b[7] = pwt->b[15];
+ pwd->b[6] = pws->b[15];
+ pwd->b[5] = pwt->b[14];
+ pwd->b[4] = pws->b[14];
+ pwd->b[3] = pwt->b[13];
+ pwd->b[2] = pws->b[13];
+ pwd->b[1] = pwt->b[12];
+ pwd->b[0] = pws->b[12];
+ pwd->b[15] = pwt->b[11];
+ pwd->b[14] = pws->b[11];
+ pwd->b[13] = pwt->b[10];
+ pwd->b[12] = pws->b[10];
+ pwd->b[11] = pwt->b[9];
+ pwd->b[10] = pws->b[9];
+ pwd->b[9] = pwt->b[8];
+ pwd->b[8] = pws->b[8];
+#else
+ pwd->b[0] = pwt->b[8];
+ pwd->b[1] = pws->b[8];
+ pwd->b[2] = pwt->b[9];
+ pwd->b[3] = pws->b[9];
+ pwd->b[4] = pwt->b[10];
+ pwd->b[5] = pws->b[10];
+ pwd->b[6] = pwt->b[11];
+ pwd->b[7] = pws->b[11];
+ pwd->b[8] = pwt->b[12];
+ pwd->b[9] = pws->b[12];
+ pwd->b[10] = pwt->b[13];
+ pwd->b[11] = pws->b[13];
+ pwd->b[12] = pwt->b[14];
+ pwd->b[13] = pws->b[14];
+ pwd->b[14] = pwt->b[15];
+ pwd->b[15] = pws->b[15];
+#endif
+}
+
+void helper_msa_ilvl_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->h[3] = pwt->h[7];
+ pwd->h[2] = pws->h[7];
+ pwd->h[1] = pwt->h[6];
+ pwd->h[0] = pws->h[6];
+ pwd->h[7] = pwt->h[5];
+ pwd->h[6] = pws->h[5];
+ pwd->h[5] = pwt->h[4];
+ pwd->h[4] = pws->h[4];
+#else
+ pwd->h[0] = pwt->h[4];
+ pwd->h[1] = pws->h[4];
+ pwd->h[2] = pwt->h[5];
+ pwd->h[3] = pws->h[5];
+ pwd->h[4] = pwt->h[6];
+ pwd->h[5] = pws->h[6];
+ pwd->h[6] = pwt->h[7];
+ pwd->h[7] = pws->h[7];
+#endif
+}
+
+void helper_msa_ilvl_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->w[1] = pwt->w[3];
+ pwd->w[0] = pws->w[3];
+ pwd->w[3] = pwt->w[2];
+ pwd->w[2] = pws->w[2];
+#else
+ pwd->w[0] = pwt->w[2];
+ pwd->w[1] = pws->w[2];
+ pwd->w[2] = pwt->w[3];
+ pwd->w[3] = pws->w[3];
+#endif
+}
+
+void helper_msa_ilvl_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = pwt->d[1];
+ pwd->d[1] = pws->d[1];
+}
+
+
+void helper_msa_ilvr_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->b[8] = pws->b[0];
+ pwd->b[9] = pwt->b[0];
+ pwd->b[10] = pws->b[1];
+ pwd->b[11] = pwt->b[1];
+ pwd->b[12] = pws->b[2];
+ pwd->b[13] = pwt->b[2];
+ pwd->b[14] = pws->b[3];
+ pwd->b[15] = pwt->b[3];
+ pwd->b[0] = pws->b[4];
+ pwd->b[1] = pwt->b[4];
+ pwd->b[2] = pws->b[5];
+ pwd->b[3] = pwt->b[5];
+ pwd->b[4] = pws->b[6];
+ pwd->b[5] = pwt->b[6];
+ pwd->b[6] = pws->b[7];
+ pwd->b[7] = pwt->b[7];
+#else
+ pwd->b[15] = pws->b[7];
+ pwd->b[14] = pwt->b[7];
+ pwd->b[13] = pws->b[6];
+ pwd->b[12] = pwt->b[6];
+ pwd->b[11] = pws->b[5];
+ pwd->b[10] = pwt->b[5];
+ pwd->b[9] = pws->b[4];
+ pwd->b[8] = pwt->b[4];
+ pwd->b[7] = pws->b[3];
+ pwd->b[6] = pwt->b[3];
+ pwd->b[5] = pws->b[2];
+ pwd->b[4] = pwt->b[2];
+ pwd->b[3] = pws->b[1];
+ pwd->b[2] = pwt->b[1];
+ pwd->b[1] = pws->b[0];
+ pwd->b[0] = pwt->b[0];
+#endif
+}
+
+void helper_msa_ilvr_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->h[4] = pws->h[0];
+ pwd->h[5] = pwt->h[0];
+ pwd->h[6] = pws->h[1];
+ pwd->h[7] = pwt->h[1];
+ pwd->h[0] = pws->h[2];
+ pwd->h[1] = pwt->h[2];
+ pwd->h[2] = pws->h[3];
+ pwd->h[3] = pwt->h[3];
+#else
+ pwd->h[7] = pws->h[3];
+ pwd->h[6] = pwt->h[3];
+ pwd->h[5] = pws->h[2];
+ pwd->h[4] = pwt->h[2];
+ pwd->h[3] = pws->h[1];
+ pwd->h[2] = pwt->h[1];
+ pwd->h[1] = pws->h[0];
+ pwd->h[0] = pwt->h[0];
+#endif
+}
+
+void helper_msa_ilvr_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->w[2] = pws->w[0];
+ pwd->w[3] = pwt->w[0];
+ pwd->w[0] = pws->w[1];
+ pwd->w[1] = pwt->w[1];
+#else
+ pwd->w[3] = pws->w[1];
+ pwd->w[2] = pwt->w[1];
+ pwd->w[1] = pws->w[0];
+ pwd->w[0] = pwt->w[0];
+#endif
+}
+
+void helper_msa_ilvr_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[1] = pws->d[0];
+ pwd->d[0] = pwt->d[0];
+}
+
+
+/*
+ * Logic
+ * -----
+ *
+ * +---------------+----------------------------------------------------------+
+ * | AND.V | Vector Logical And |
+ * | NOR.V | Vector Logical Negated Or |
+ * | OR.V | Vector Logical Or |
+ * | XOR.V | Vector Logical Exclusive Or |
+ * +---------------+----------------------------------------------------------+
+ */
+
+
+void helper_msa_and_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = pws->d[0] & pwt->d[0];
+ pwd->d[1] = pws->d[1] & pwt->d[1];
+}
+
+void helper_msa_nor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = ~(pws->d[0] | pwt->d[0]);
+ pwd->d[1] = ~(pws->d[1] | pwt->d[1]);
+}
+
+void helper_msa_or_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = pws->d[0] | pwt->d[0];
+ pwd->d[1] = pws->d[1] | pwt->d[1];
+}
-/*
- * Logic
- * -----
- *
- * +---------------+----------------------------------------------------------+
- * | AND.V | Vector Logical And |
- * | NOR.V | Vector Logical Negated Or |
- * | OR.V | Vector Logical Or |
- * | XOR.V | Vector Logical Exclusive Or |
- * +---------------+----------------------------------------------------------+
- */
+void helper_msa_xor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-/* TODO: insert Logic group helpers here */
+ pwd->d[0] = pws->d[0] ^ pwt->d[0];
+ pwd->d[1] = pws->d[1] ^ pwt->d[1];
+}
/*
* +---------------+----------------------------------------------------------+
*/
-/* TODO: insert Move group helpers here */
+static inline void msa_move_v(wr_t *pwd, wr_t *pws)
+{
+ pwd->d[0] = pws->d[0];
+ pwd->d[1] = pws->d[1];
+}
+
+void helper_msa_move_v(CPUMIPSState *env, uint32_t wd, uint32_t ws)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+
+ msa_move_v(pwd, pws);
+}
/*
* +---------------+----------------------------------------------------------+
*/
-/* TODO: insert Pack group helpers here */
+
+void helper_msa_pckev_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->b[8] = pws->b[9];
+ pwd->b[10] = pws->b[13];
+ pwd->b[12] = pws->b[1];
+ pwd->b[14] = pws->b[5];
+ pwd->b[0] = pwt->b[9];
+ pwd->b[2] = pwt->b[13];
+ pwd->b[4] = pwt->b[1];
+ pwd->b[6] = pwt->b[5];
+ pwd->b[9] = pws->b[11];
+ pwd->b[13] = pws->b[3];
+ pwd->b[1] = pwt->b[11];
+ pwd->b[5] = pwt->b[3];
+ pwd->b[11] = pws->b[15];
+ pwd->b[3] = pwt->b[15];
+ pwd->b[15] = pws->b[7];
+ pwd->b[7] = pwt->b[7];
+#else
+ pwd->b[15] = pws->b[14];
+ pwd->b[13] = pws->b[10];
+ pwd->b[11] = pws->b[6];
+ pwd->b[9] = pws->b[2];
+ pwd->b[7] = pwt->b[14];
+ pwd->b[5] = pwt->b[10];
+ pwd->b[3] = pwt->b[6];
+ pwd->b[1] = pwt->b[2];
+ pwd->b[14] = pws->b[12];
+ pwd->b[10] = pws->b[4];
+ pwd->b[6] = pwt->b[12];
+ pwd->b[2] = pwt->b[4];
+ pwd->b[12] = pws->b[8];
+ pwd->b[4] = pwt->b[8];
+ pwd->b[8] = pws->b[0];
+ pwd->b[0] = pwt->b[0];
+#endif
+}
+
+void helper_msa_pckev_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->h[4] = pws->h[5];
+ pwd->h[6] = pws->h[1];
+ pwd->h[0] = pwt->h[5];
+ pwd->h[2] = pwt->h[1];
+ pwd->h[5] = pws->h[7];
+ pwd->h[1] = pwt->h[7];
+ pwd->h[7] = pws->h[3];
+ pwd->h[3] = pwt->h[3];
+#else
+ pwd->h[7] = pws->h[6];
+ pwd->h[5] = pws->h[2];
+ pwd->h[3] = pwt->h[6];
+ pwd->h[1] = pwt->h[2];
+ pwd->h[6] = pws->h[4];
+ pwd->h[2] = pwt->h[4];
+ pwd->h[4] = pws->h[0];
+ pwd->h[0] = pwt->h[0];
+#endif
+}
+
+void helper_msa_pckev_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->w[2] = pws->w[3];
+ pwd->w[0] = pwt->w[3];
+ pwd->w[3] = pws->w[1];
+ pwd->w[1] = pwt->w[1];
+#else
+ pwd->w[3] = pws->w[2];
+ pwd->w[1] = pwt->w[2];
+ pwd->w[2] = pws->w[0];
+ pwd->w[0] = pwt->w[0];
+#endif
+}
+
+void helper_msa_pckev_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[1] = pws->d[0];
+ pwd->d[0] = pwt->d[0];
+}
+
+
+void helper_msa_pckod_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->b[7] = pwt->b[6];
+ pwd->b[5] = pwt->b[2];
+ pwd->b[3] = pwt->b[14];
+ pwd->b[1] = pwt->b[10];
+ pwd->b[15] = pws->b[6];
+ pwd->b[13] = pws->b[2];
+ pwd->b[11] = pws->b[14];
+ pwd->b[9] = pws->b[10];
+ pwd->b[6] = pwt->b[4];
+ pwd->b[2] = pwt->b[12];
+ pwd->b[14] = pws->b[4];
+ pwd->b[10] = pws->b[12];
+ pwd->b[4] = pwt->b[0];
+ pwd->b[12] = pws->b[0];
+ pwd->b[0] = pwt->b[8];
+ pwd->b[8] = pws->b[8];
+#else
+ pwd->b[0] = pwt->b[1];
+ pwd->b[2] = pwt->b[5];
+ pwd->b[4] = pwt->b[9];
+ pwd->b[6] = pwt->b[13];
+ pwd->b[8] = pws->b[1];
+ pwd->b[10] = pws->b[5];
+ pwd->b[12] = pws->b[9];
+ pwd->b[14] = pws->b[13];
+ pwd->b[1] = pwt->b[3];
+ pwd->b[5] = pwt->b[11];
+ pwd->b[9] = pws->b[3];
+ pwd->b[13] = pws->b[11];
+ pwd->b[3] = pwt->b[7];
+ pwd->b[11] = pws->b[7];
+ pwd->b[7] = pwt->b[15];
+ pwd->b[15] = pws->b[15];
+#endif
+
+}
+
+void helper_msa_pckod_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->h[3] = pwt->h[2];
+ pwd->h[1] = pwt->h[6];
+ pwd->h[7] = pws->h[2];
+ pwd->h[5] = pws->h[6];
+ pwd->h[2] = pwt->h[0];
+ pwd->h[6] = pws->h[0];
+ pwd->h[0] = pwt->h[4];
+ pwd->h[4] = pws->h[4];
+#else
+ pwd->h[0] = pwt->h[1];
+ pwd->h[2] = pwt->h[5];
+ pwd->h[4] = pws->h[1];
+ pwd->h[6] = pws->h[5];
+ pwd->h[1] = pwt->h[3];
+ pwd->h[5] = pws->h[3];
+ pwd->h[3] = pwt->h[7];
+ pwd->h[7] = pws->h[7];
+#endif
+}
+
+void helper_msa_pckod_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+#if defined(HOST_WORDS_BIGENDIAN)
+ pwd->w[1] = pwt->w[0];
+ pwd->w[3] = pws->w[0];
+ pwd->w[0] = pwt->w[2];
+ pwd->w[2] = pws->w[2];
+#else
+ pwd->w[0] = pwt->w[1];
+ pwd->w[2] = pws->w[1];
+ pwd->w[1] = pwt->w[3];
+ pwd->w[3] = pws->w[3];
+#endif
+}
+
+void helper_msa_pckod_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = pwt->d[1];
+ pwd->d[1] = pws->d[1];
+}
/*
* +---------------+----------------------------------------------------------+
*/
-/* TODO: insert Shift group helpers here */
+static inline int64_t msa_sll_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ int32_t b_arg2 = BIT_POSITION(arg2, df);
+ return arg1 << b_arg2;
+}
+
+void helper_msa_sll_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_sll_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_sll_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_sll_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_sll_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_sll_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_sll_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_sll_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_sll_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_sll_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_sll_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_sll_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_sll_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_sll_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_sll_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_sll_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_sll_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_sll_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_sll_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_sll_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_sll_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_sll_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_sll_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_sll_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_sll_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_sll_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_sll_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_sll_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_sll_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_sll_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_sll_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_sll_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_sll_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_sll_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+static inline int64_t msa_sra_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ int32_t b_arg2 = BIT_POSITION(arg2, df);
+ return arg1 >> b_arg2;
+}
+
+void helper_msa_sra_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_sra_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_sra_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_sra_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_sra_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_sra_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_sra_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_sra_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_sra_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_sra_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_sra_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_sra_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_sra_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_sra_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_sra_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_sra_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_sra_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_sra_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_sra_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_sra_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_sra_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_sra_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_sra_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_sra_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_sra_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_sra_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_sra_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_sra_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_sra_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_sra_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_sra_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_sra_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_sra_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_sra_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+static inline int64_t msa_srar_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ int32_t b_arg2 = BIT_POSITION(arg2, df);
+ if (b_arg2 == 0) {
+ return arg1;
+ } else {
+ int64_t r_bit = (arg1 >> (b_arg2 - 1)) & 1;
+ return (arg1 >> b_arg2) + r_bit;
+ }
+}
+
+void helper_msa_srar_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_srar_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_srar_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_srar_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_srar_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_srar_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_srar_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_srar_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_srar_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_srar_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_srar_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_srar_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_srar_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_srar_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_srar_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_srar_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_srar_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_srar_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_srar_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_srar_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_srar_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_srar_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_srar_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_srar_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_srar_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_srar_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_srar_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_srar_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_srar_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_srar_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_srar_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_srar_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_srar_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_srar_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+static inline int64_t msa_srl_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ uint64_t u_arg1 = UNSIGNED(arg1, df);
+ int32_t b_arg2 = BIT_POSITION(arg2, df);
+ return u_arg1 >> b_arg2;
+}
+
+void helper_msa_srl_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_srl_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_srl_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_srl_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_srl_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_srl_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_srl_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_srl_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_srl_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_srl_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_srl_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_srl_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_srl_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_srl_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_srl_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_srl_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_srl_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_srl_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->h[0] = msa_srl_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_srl_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_srl_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_srl_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_srl_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_srl_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_srl_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_srl_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_srl_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->w[0] = msa_srl_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_srl_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_srl_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_srl_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_srl_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_srl_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_srl_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
+}
+
+
+static inline int64_t msa_srlr_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+ uint64_t u_arg1 = UNSIGNED(arg1, df);
+ int32_t b_arg2 = BIT_POSITION(arg2, df);
+ if (b_arg2 == 0) {
+ return u_arg1;
+ } else {
+ uint64_t r_bit = (u_arg1 >> (b_arg2 - 1)) & 1;
+ return (u_arg1 >> b_arg2) + r_bit;
+ }
+}
+
+void helper_msa_srlr_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->b[0] = msa_srlr_df(DF_BYTE, pws->b[0], pwt->b[0]);
+ pwd->b[1] = msa_srlr_df(DF_BYTE, pws->b[1], pwt->b[1]);
+ pwd->b[2] = msa_srlr_df(DF_BYTE, pws->b[2], pwt->b[2]);
+ pwd->b[3] = msa_srlr_df(DF_BYTE, pws->b[3], pwt->b[3]);
+ pwd->b[4] = msa_srlr_df(DF_BYTE, pws->b[4], pwt->b[4]);
+ pwd->b[5] = msa_srlr_df(DF_BYTE, pws->b[5], pwt->b[5]);
+ pwd->b[6] = msa_srlr_df(DF_BYTE, pws->b[6], pwt->b[6]);
+ pwd->b[7] = msa_srlr_df(DF_BYTE, pws->b[7], pwt->b[7]);
+ pwd->b[8] = msa_srlr_df(DF_BYTE, pws->b[8], pwt->b[8]);
+ pwd->b[9] = msa_srlr_df(DF_BYTE, pws->b[9], pwt->b[9]);
+ pwd->b[10] = msa_srlr_df(DF_BYTE, pws->b[10], pwt->b[10]);
+ pwd->b[11] = msa_srlr_df(DF_BYTE, pws->b[11], pwt->b[11]);
+ pwd->b[12] = msa_srlr_df(DF_BYTE, pws->b[12], pwt->b[12]);
+ pwd->b[13] = msa_srlr_df(DF_BYTE, pws->b[13], pwt->b[13]);
+ pwd->b[14] = msa_srlr_df(DF_BYTE, pws->b[14], pwt->b[14]);
+ pwd->b[15] = msa_srlr_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_srlr_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-static inline void msa_move_v(wr_t *pwd, wr_t *pws)
+ pwd->h[0] = msa_srlr_df(DF_HALF, pws->h[0], pwt->h[0]);
+ pwd->h[1] = msa_srlr_df(DF_HALF, pws->h[1], pwt->h[1]);
+ pwd->h[2] = msa_srlr_df(DF_HALF, pws->h[2], pwt->h[2]);
+ pwd->h[3] = msa_srlr_df(DF_HALF, pws->h[3], pwt->h[3]);
+ pwd->h[4] = msa_srlr_df(DF_HALF, pws->h[4], pwt->h[4]);
+ pwd->h[5] = msa_srlr_df(DF_HALF, pws->h[5], pwt->h[5]);
+ pwd->h[6] = msa_srlr_df(DF_HALF, pws->h[6], pwt->h[6]);
+ pwd->h[7] = msa_srlr_df(DF_HALF, pws->h[7], pwt->h[7]);
+}
+
+void helper_msa_srlr_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
{
- uint32_t i;
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
- for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
- pwd->d[i] = pws->d[i];
- }
+ pwd->w[0] = msa_srlr_df(DF_WORD, pws->w[0], pwt->w[0]);
+ pwd->w[1] = msa_srlr_df(DF_WORD, pws->w[1], pwt->w[1]);
+ pwd->w[2] = msa_srlr_df(DF_WORD, pws->w[2], pwt->w[2]);
+ pwd->w[3] = msa_srlr_df(DF_WORD, pws->w[3], pwt->w[3]);
+}
+
+void helper_msa_srlr_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+ wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+ pwd->d[0] = msa_srlr_df(DF_DOUBLE, pws->d[0], pwt->d[0]);
+ pwd->d[1] = msa_srlr_df(DF_DOUBLE, pws->d[1], pwt->d[1]);
}
+
#define MSA_FN_IMM8(FUNC, DEST, OPERATION) \
void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \
uint32_t i8) \
MSA_FN_IMM8(bseli_b, pwd->b[i],
BIT_SELECT(pwd->b[i], pws->b[i], i8, DF_BYTE))
+#undef BIT_SELECT
+#undef BIT_MOVE_IF_ZERO
+#undef BIT_MOVE_IF_NOT_ZERO
#undef MSA_FN_IMM8
#define SHF_POS(i, imm) (((i) & 0xfc) + (((imm) >> (2 * ((i) & 0x03))) & 0x03))
msa_move_v(pwd, pwx);
}
-#define MSA_FN_VECTOR(FUNC, DEST, OPERATION) \
-void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \
- uint32_t wt) \
-{ \
- wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
- wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
- wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \
- uint32_t i; \
- for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \
- DEST = OPERATION; \
- } \
-}
-
-MSA_FN_VECTOR(bmnz_v, pwd->d[i],
- BIT_MOVE_IF_NOT_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE))
-MSA_FN_VECTOR(bmz_v, pwd->d[i],
- BIT_MOVE_IF_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE))
-MSA_FN_VECTOR(bsel_v, pwd->d[i],
- BIT_SELECT(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE))
-#undef BIT_MOVE_IF_NOT_ZERO
-#undef BIT_MOVE_IF_ZERO
-#undef BIT_SELECT
-#undef MSA_FN_VECTOR
-
-void helper_msa_and_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
-{
- wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- wr_t *pws = &(env->active_fpu.fpr[ws].wr);
- wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-
- pwd->d[0] = pws->d[0] & pwt->d[0];
- pwd->d[1] = pws->d[1] & pwt->d[1];
-}
-
-void helper_msa_or_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
-{
- wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- wr_t *pws = &(env->active_fpu.fpr[ws].wr);
- wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-
- pwd->d[0] = pws->d[0] | pwt->d[0];
- pwd->d[1] = pws->d[1] | pwt->d[1];
-}
-
-void helper_msa_nor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
-{
- wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- wr_t *pws = &(env->active_fpu.fpr[ws].wr);
- wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-
- pwd->d[0] = ~(pws->d[0] | pwt->d[0]);
- pwd->d[1] = ~(pws->d[1] | pwt->d[1]);
-}
-
-void helper_msa_xor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
-{
- wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- wr_t *pws = &(env->active_fpu.fpr[ws].wr);
- wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-
- pwd->d[0] = pws->d[0] ^ pwt->d[0];
- pwd->d[1] = pws->d[1] ^ pwt->d[1];
-}
-
-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) \
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);
- }
-}
-
-/* Data format bit position and unsigned values */
-#define BIT_POSITION(x, df) ((uint64_t)(x) % DF_BITS(df))
-
-static inline int64_t msa_sll_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- int32_t b_arg2 = BIT_POSITION(arg2, df);
- return arg1 << b_arg2;
-}
-
-static inline int64_t msa_sra_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- int32_t b_arg2 = BIT_POSITION(arg2, df);
- return arg1 >> b_arg2;
-}
-
-static inline int64_t msa_srl_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- uint64_t u_arg1 = UNSIGNED(arg1, df);
- int32_t b_arg2 = BIT_POSITION(arg2, df);
- return u_arg1 >> b_arg2;
-}
-
-static inline int64_t msa_bclr_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- int32_t b_arg2 = BIT_POSITION(arg2, df);
- return UNSIGNED(arg1 & (~(1LL << b_arg2)), df);
-}
-
-static inline int64_t msa_bset_df(uint32_t df, int64_t arg1,
- int64_t arg2)
-{
- int32_t b_arg2 = BIT_POSITION(arg2, df);
- return UNSIGNED(arg1 | (1LL << b_arg2), df);
-}
-
-static inline int64_t msa_bneg_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- int32_t b_arg2 = BIT_POSITION(arg2, df);
- return UNSIGNED(arg1 ^ (1LL << b_arg2), df);
-}
-
-static inline int64_t msa_binsl_df(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);
- }
+ 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); \
+ } \
}
-static inline int64_t msa_binsr_df(uint32_t df, int64_t dest, int64_t arg1,
- int64_t arg2)
+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)
{
- 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);
+ 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);
}
}
M_MAX_UINT(m + 1);
}
-static inline int64_t msa_srar_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- int32_t b_arg2 = BIT_POSITION(arg2, df);
- if (b_arg2 == 0) {
- return arg1;
- } else {
- int64_t r_bit = (arg1 >> (b_arg2 - 1)) & 1;
- return (arg1 >> b_arg2) + r_bit;
- }
-}
-
-static inline int64_t msa_srlr_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- uint64_t u_arg1 = UNSIGNED(arg1, df);
- int32_t b_arg2 = BIT_POSITION(arg2, df);
- if (b_arg2 == 0) {
- return u_arg1;
- } else {
- uint64_t r_bit = (u_arg1 >> (b_arg2 - 1)) & 1;
- return (u_arg1 >> b_arg2) + r_bit;
- }
-}
-
#define MSA_BINOP_IMMU_DF(helper, func) \
void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, uint32_t wd, \
uint32_t ws, uint32_t u5) \
MSA_TEROP_IMMU_DF(binsri, binsr)
#undef MSA_TEROP_IMMU_DF
-static inline int64_t msa_max_a_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
- uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
- return abs_arg1 > abs_arg2 ? arg1 : arg2;
-}
-
-static inline int64_t msa_min_a_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
- uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
- return abs_arg1 < abs_arg2 ? arg1 : arg2;
-}
-
-static inline int64_t msa_add_a_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
- uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
- return abs_arg1 + abs_arg2;
-}
-
-static inline int64_t msa_adds_a_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- uint64_t max_int = (uint64_t)DF_MAX_INT(df);
- uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
- uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
- if (abs_arg1 > max_int || abs_arg2 > max_int) {
- return (int64_t)max_int;
- } else {
- return (abs_arg1 < max_int - abs_arg2) ? abs_arg1 + abs_arg2 : max_int;
- }
-}
-
-static inline int64_t msa_adds_s_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- int64_t max_int = DF_MAX_INT(df);
- int64_t min_int = DF_MIN_INT(df);
- if (arg1 < 0) {
- return (min_int - arg1 < arg2) ? arg1 + arg2 : min_int;
- } else {
- return (arg2 < max_int - arg1) ? arg1 + arg2 : max_int;
- }
-}
-
-static inline uint64_t msa_adds_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
-{
- uint64_t max_uint = DF_MAX_UINT(df);
- uint64_t u_arg1 = UNSIGNED(arg1, df);
- uint64_t u_arg2 = UNSIGNED(arg2, df);
- return (u_arg1 < max_uint - u_arg2) ? u_arg1 + u_arg2 : max_uint;
-}
-
-static inline int64_t msa_ave_s_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- /* signed shift */
- return (arg1 >> 1) + (arg2 >> 1) + (arg1 & arg2 & 1);
-}
-
-static inline uint64_t msa_ave_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
-{
- uint64_t u_arg1 = UNSIGNED(arg1, df);
- uint64_t u_arg2 = UNSIGNED(arg2, df);
- /* unsigned shift */
- return (u_arg1 >> 1) + (u_arg2 >> 1) + (u_arg1 & u_arg2 & 1);
-}
-
-static inline int64_t msa_aver_s_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- /* signed shift */
- return (arg1 >> 1) + (arg2 >> 1) + ((arg1 | arg2) & 1);
-}
-
-static inline uint64_t msa_aver_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
-{
- uint64_t u_arg1 = UNSIGNED(arg1, df);
- uint64_t u_arg2 = UNSIGNED(arg2, df);
- /* unsigned shift */
- return (u_arg1 >> 1) + (u_arg2 >> 1) + ((u_arg1 | u_arg2) & 1);
-}
-
static inline int64_t msa_subs_s_df(uint32_t df, int64_t arg1, int64_t arg2)
{
int64_t max_int = DF_MAX_INT(df);
}
}
-static inline int64_t msa_asub_s_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- /* signed compare */
- return (arg1 < arg2) ?
- (uint64_t)(arg2 - arg1) : (uint64_t)(arg1 - arg2);
-}
-
-static inline uint64_t msa_asub_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
-{
- uint64_t u_arg1 = UNSIGNED(arg1, df);
- uint64_t u_arg2 = UNSIGNED(arg2, df);
- /* unsigned compare */
- return (u_arg1 < u_arg2) ?
- (uint64_t)(u_arg2 - u_arg1) : (uint64_t)(u_arg1 - u_arg2);
-}
-
static inline int64_t msa_mulv_df(uint32_t df, int64_t arg1, int64_t arg2)
{
return arg1 * arg2;
}
-static inline int64_t msa_div_s_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- if (arg1 == DF_MIN_INT(df) && arg2 == -1) {
- return DF_MIN_INT(df);
- }
- return arg2 ? arg1 / arg2
- : arg1 >= 0 ? -1 : 1;
-}
-
-static inline int64_t msa_div_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 arg2 ? u_arg1 / u_arg2 : -1;
-}
-
-static inline int64_t msa_mod_s_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- if (arg1 == DF_MIN_INT(df) && arg2 == -1) {
- return 0;
- }
- return arg2 ? arg1 % arg2 : arg1;
-}
-
-static inline int64_t msa_mod_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_arg2 ? u_arg1 % u_arg2 : u_arg1;
-}
-
-#define SIGNED_EVEN(a, df) \
- ((((int64_t)(a)) << (64 - DF_BITS(df) / 2)) >> (64 - DF_BITS(df) / 2))
-
-#define UNSIGNED_EVEN(a, df) \
- ((((uint64_t)(a)) << (64 - DF_BITS(df) / 2)) >> (64 - DF_BITS(df) / 2))
-
-#define SIGNED_ODD(a, df) \
- ((((int64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df) / 2))
-
-#define UNSIGNED_ODD(a, df) \
- ((((uint64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df) / 2))
-
#define SIGNED_EXTRACT(e, o, a, df) \
do { \
e = SIGNED_EVEN(a, df); \
}
break;
case DF_WORD:
- for (k = 0; k < 4; k++) {
- CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_WORD), k);
- }
- break;
- case DF_DOUBLE:
- for (k = 0; k < 8; k++) {
- CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_DOUBLE), k);
- }
- break;
- default:
- assert(0);
- }
-}
-
-static inline int64_t msa_hadd_s_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- return SIGNED_ODD(arg1, df) + SIGNED_EVEN(arg2, df);
-}
-
-static inline int64_t msa_hadd_u_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- return UNSIGNED_ODD(arg1, df) + UNSIGNED_EVEN(arg2, df);
-}
-
-static inline int64_t msa_hsub_s_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- return SIGNED_ODD(arg1, df) - SIGNED_EVEN(arg2, df);
-}
-
-static inline int64_t msa_hsub_u_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
- return UNSIGNED_ODD(arg1, df) - UNSIGNED_EVEN(arg2, df);
+ for (k = 0; k < 4; k++) {
+ CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_WORD), k);
+ }
+ break;
+ case DF_DOUBLE:
+ for (k = 0; k < 8; k++) {
+ CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_DOUBLE), k);
+ }
+ break;
+ default:
+ assert(0);
+ }
}
static inline int64_t msa_mul_q_df(uint32_t df, int64_t arg1, int64_t arg2)
} \
}
-MSA_BINOP_DF(sll)
-MSA_BINOP_DF(sra)
-MSA_BINOP_DF(srl)
-MSA_BINOP_DF(bclr)
-MSA_BINOP_DF(bset)
-MSA_BINOP_DF(bneg)
-MSA_BINOP_DF(addv)
MSA_BINOP_DF(subv)
-MSA_BINOP_DF(max_s)
-MSA_BINOP_DF(max_u)
-MSA_BINOP_DF(min_s)
-MSA_BINOP_DF(min_u)
-MSA_BINOP_DF(max_a)
-MSA_BINOP_DF(min_a)
-MSA_BINOP_DF(ceq)
-MSA_BINOP_DF(clt_s)
-MSA_BINOP_DF(clt_u)
-MSA_BINOP_DF(cle_s)
-MSA_BINOP_DF(cle_u)
-MSA_BINOP_DF(add_a)
-MSA_BINOP_DF(adds_a)
-MSA_BINOP_DF(adds_s)
-MSA_BINOP_DF(adds_u)
-MSA_BINOP_DF(ave_s)
-MSA_BINOP_DF(ave_u)
-MSA_BINOP_DF(aver_s)
-MSA_BINOP_DF(aver_u)
MSA_BINOP_DF(subs_s)
MSA_BINOP_DF(subs_u)
MSA_BINOP_DF(subsus_u)
MSA_BINOP_DF(subsuu_s)
-MSA_BINOP_DF(asub_s)
-MSA_BINOP_DF(asub_u)
MSA_BINOP_DF(mulv)
-MSA_BINOP_DF(div_s)
-MSA_BINOP_DF(div_u)
-MSA_BINOP_DF(mod_s)
-MSA_BINOP_DF(mod_u)
MSA_BINOP_DF(dotp_s)
MSA_BINOP_DF(dotp_u)
-MSA_BINOP_DF(srar)
-MSA_BINOP_DF(srlr)
-MSA_BINOP_DF(hadd_s)
-MSA_BINOP_DF(hadd_u)
-MSA_BINOP_DF(hsub_s)
-MSA_BINOP_DF(hsub_u)
MSA_BINOP_DF(mul_q)
MSA_BINOP_DF(mulr_q)
#undef MSA_FN_DF
-void helper_msa_ilvev_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
- uint32_t ws, uint32_t wt)
-{
- wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- wr_t *pws = &(env->active_fpu.fpr[ws].wr);
- wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-
- switch (df) {
- case DF_BYTE:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->b[8] = pws->b[9];
- pwd->b[9] = pwt->b[9];
- pwd->b[10] = pws->b[11];
- pwd->b[11] = pwt->b[11];
- pwd->b[12] = pws->b[13];
- pwd->b[13] = pwt->b[13];
- pwd->b[14] = pws->b[15];
- pwd->b[15] = pwt->b[15];
- pwd->b[0] = pws->b[1];
- pwd->b[1] = pwt->b[1];
- pwd->b[2] = pws->b[3];
- pwd->b[3] = pwt->b[3];
- pwd->b[4] = pws->b[5];
- pwd->b[5] = pwt->b[5];
- pwd->b[6] = pws->b[7];
- pwd->b[7] = pwt->b[7];
-#else
- pwd->b[15] = pws->b[14];
- pwd->b[14] = pwt->b[14];
- pwd->b[13] = pws->b[12];
- pwd->b[12] = pwt->b[12];
- pwd->b[11] = pws->b[10];
- pwd->b[10] = pwt->b[10];
- pwd->b[9] = pws->b[8];
- pwd->b[8] = pwt->b[8];
- pwd->b[7] = pws->b[6];
- pwd->b[6] = pwt->b[6];
- pwd->b[5] = pws->b[4];
- pwd->b[4] = pwt->b[4];
- pwd->b[3] = pws->b[2];
- pwd->b[2] = pwt->b[2];
- pwd->b[1] = pws->b[0];
- pwd->b[0] = pwt->b[0];
-#endif
- break;
- case DF_HALF:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->h[4] = pws->h[5];
- pwd->h[5] = pwt->h[5];
- pwd->h[6] = pws->h[7];
- pwd->h[7] = pwt->h[7];
- pwd->h[0] = pws->h[1];
- pwd->h[1] = pwt->h[1];
- pwd->h[2] = pws->h[3];
- pwd->h[3] = pwt->h[3];
-#else
- pwd->h[7] = pws->h[6];
- pwd->h[6] = pwt->h[6];
- pwd->h[5] = pws->h[4];
- pwd->h[4] = pwt->h[4];
- pwd->h[3] = pws->h[2];
- pwd->h[2] = pwt->h[2];
- pwd->h[1] = pws->h[0];
- pwd->h[0] = pwt->h[0];
-#endif
- break;
- case DF_WORD:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->w[2] = pws->w[3];
- pwd->w[3] = pwt->w[3];
- pwd->w[0] = pws->w[1];
- pwd->w[1] = pwt->w[1];
-#else
- pwd->w[3] = pws->w[2];
- pwd->w[2] = pwt->w[2];
- pwd->w[1] = pws->w[0];
- pwd->w[0] = pwt->w[0];
-#endif
- break;
- case DF_DOUBLE:
- pwd->d[1] = pws->d[0];
- pwd->d[0] = pwt->d[0];
- break;
- default:
- assert(0);
- }
-}
-
-void helper_msa_ilvod_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
- uint32_t ws, uint32_t wt)
-{
- wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- wr_t *pws = &(env->active_fpu.fpr[ws].wr);
- wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-
- switch (df) {
- case DF_BYTE:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->b[7] = pwt->b[6];
- pwd->b[6] = pws->b[6];
- pwd->b[5] = pwt->b[4];
- pwd->b[4] = pws->b[4];
- pwd->b[3] = pwt->b[2];
- pwd->b[2] = pws->b[2];
- pwd->b[1] = pwt->b[0];
- pwd->b[0] = pws->b[0];
- pwd->b[15] = pwt->b[14];
- pwd->b[14] = pws->b[14];
- pwd->b[13] = pwt->b[12];
- pwd->b[12] = pws->b[12];
- pwd->b[11] = pwt->b[10];
- pwd->b[10] = pws->b[10];
- pwd->b[9] = pwt->b[8];
- pwd->b[8] = pws->b[8];
-#else
- pwd->b[0] = pwt->b[1];
- pwd->b[1] = pws->b[1];
- pwd->b[2] = pwt->b[3];
- pwd->b[3] = pws->b[3];
- pwd->b[4] = pwt->b[5];
- pwd->b[5] = pws->b[5];
- pwd->b[6] = pwt->b[7];
- pwd->b[7] = pws->b[7];
- pwd->b[8] = pwt->b[9];
- pwd->b[9] = pws->b[9];
- pwd->b[10] = pwt->b[11];
- pwd->b[11] = pws->b[11];
- pwd->b[12] = pwt->b[13];
- pwd->b[13] = pws->b[13];
- pwd->b[14] = pwt->b[15];
- pwd->b[15] = pws->b[15];
-#endif
- break;
- case DF_HALF:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->h[3] = pwt->h[2];
- pwd->h[2] = pws->h[2];
- pwd->h[1] = pwt->h[0];
- pwd->h[0] = pws->h[0];
- pwd->h[7] = pwt->h[6];
- pwd->h[6] = pws->h[6];
- pwd->h[5] = pwt->h[4];
- pwd->h[4] = pws->h[4];
-#else
- pwd->h[0] = pwt->h[1];
- pwd->h[1] = pws->h[1];
- pwd->h[2] = pwt->h[3];
- pwd->h[3] = pws->h[3];
- pwd->h[4] = pwt->h[5];
- pwd->h[5] = pws->h[5];
- pwd->h[6] = pwt->h[7];
- pwd->h[7] = pws->h[7];
-#endif
- break;
- case DF_WORD:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->w[1] = pwt->w[0];
- pwd->w[0] = pws->w[0];
- pwd->w[3] = pwt->w[2];
- pwd->w[2] = pws->w[2];
-#else
- pwd->w[0] = pwt->w[1];
- pwd->w[1] = pws->w[1];
- pwd->w[2] = pwt->w[3];
- pwd->w[3] = pws->w[3];
-#endif
- break;
- case DF_DOUBLE:
- pwd->d[0] = pwt->d[1];
- pwd->d[1] = pws->d[1];
- break;
- default:
- assert(0);
- }
-}
-
-void helper_msa_ilvl_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
- uint32_t ws, uint32_t wt)
-{
- wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- wr_t *pws = &(env->active_fpu.fpr[ws].wr);
- wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-
- switch (df) {
- case DF_BYTE:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->b[7] = pwt->b[15];
- pwd->b[6] = pws->b[15];
- pwd->b[5] = pwt->b[14];
- pwd->b[4] = pws->b[14];
- pwd->b[3] = pwt->b[13];
- pwd->b[2] = pws->b[13];
- pwd->b[1] = pwt->b[12];
- pwd->b[0] = pws->b[12];
- pwd->b[15] = pwt->b[11];
- pwd->b[14] = pws->b[11];
- pwd->b[13] = pwt->b[10];
- pwd->b[12] = pws->b[10];
- pwd->b[11] = pwt->b[9];
- pwd->b[10] = pws->b[9];
- pwd->b[9] = pwt->b[8];
- pwd->b[8] = pws->b[8];
-#else
- pwd->b[0] = pwt->b[8];
- pwd->b[1] = pws->b[8];
- pwd->b[2] = pwt->b[9];
- pwd->b[3] = pws->b[9];
- pwd->b[4] = pwt->b[10];
- pwd->b[5] = pws->b[10];
- pwd->b[6] = pwt->b[11];
- pwd->b[7] = pws->b[11];
- pwd->b[8] = pwt->b[12];
- pwd->b[9] = pws->b[12];
- pwd->b[10] = pwt->b[13];
- pwd->b[11] = pws->b[13];
- pwd->b[12] = pwt->b[14];
- pwd->b[13] = pws->b[14];
- pwd->b[14] = pwt->b[15];
- pwd->b[15] = pws->b[15];
-#endif
- break;
- case DF_HALF:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->h[3] = pwt->h[7];
- pwd->h[2] = pws->h[7];
- pwd->h[1] = pwt->h[6];
- pwd->h[0] = pws->h[6];
- pwd->h[7] = pwt->h[5];
- pwd->h[6] = pws->h[5];
- pwd->h[5] = pwt->h[4];
- pwd->h[4] = pws->h[4];
-#else
- pwd->h[0] = pwt->h[4];
- pwd->h[1] = pws->h[4];
- pwd->h[2] = pwt->h[5];
- pwd->h[3] = pws->h[5];
- pwd->h[4] = pwt->h[6];
- pwd->h[5] = pws->h[6];
- pwd->h[6] = pwt->h[7];
- pwd->h[7] = pws->h[7];
-#endif
- break;
- case DF_WORD:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->w[1] = pwt->w[3];
- pwd->w[0] = pws->w[3];
- pwd->w[3] = pwt->w[2];
- pwd->w[2] = pws->w[2];
-#else
- pwd->w[0] = pwt->w[2];
- pwd->w[1] = pws->w[2];
- pwd->w[2] = pwt->w[3];
- pwd->w[3] = pws->w[3];
-#endif
- break;
- case DF_DOUBLE:
- pwd->d[0] = pwt->d[1];
- pwd->d[1] = pws->d[1];
- break;
- default:
- assert(0);
- }
-}
-
-void helper_msa_ilvr_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
- uint32_t ws, uint32_t wt)
-{
- wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- wr_t *pws = &(env->active_fpu.fpr[ws].wr);
- wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-
- switch (df) {
- case DF_BYTE:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->b[8] = pws->b[0];
- pwd->b[9] = pwt->b[0];
- pwd->b[10] = pws->b[1];
- pwd->b[11] = pwt->b[1];
- pwd->b[12] = pws->b[2];
- pwd->b[13] = pwt->b[2];
- pwd->b[14] = pws->b[3];
- pwd->b[15] = pwt->b[3];
- pwd->b[0] = pws->b[4];
- pwd->b[1] = pwt->b[4];
- pwd->b[2] = pws->b[5];
- pwd->b[3] = pwt->b[5];
- pwd->b[4] = pws->b[6];
- pwd->b[5] = pwt->b[6];
- pwd->b[6] = pws->b[7];
- pwd->b[7] = pwt->b[7];
-#else
- pwd->b[15] = pws->b[7];
- pwd->b[14] = pwt->b[7];
- pwd->b[13] = pws->b[6];
- pwd->b[12] = pwt->b[6];
- pwd->b[11] = pws->b[5];
- pwd->b[10] = pwt->b[5];
- pwd->b[9] = pws->b[4];
- pwd->b[8] = pwt->b[4];
- pwd->b[7] = pws->b[3];
- pwd->b[6] = pwt->b[3];
- pwd->b[5] = pws->b[2];
- pwd->b[4] = pwt->b[2];
- pwd->b[3] = pws->b[1];
- pwd->b[2] = pwt->b[1];
- pwd->b[1] = pws->b[0];
- pwd->b[0] = pwt->b[0];
-#endif
- break;
- case DF_HALF:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->h[4] = pws->h[0];
- pwd->h[5] = pwt->h[0];
- pwd->h[6] = pws->h[1];
- pwd->h[7] = pwt->h[1];
- pwd->h[0] = pws->h[2];
- pwd->h[1] = pwt->h[2];
- pwd->h[2] = pws->h[3];
- pwd->h[3] = pwt->h[3];
-#else
- pwd->h[7] = pws->h[3];
- pwd->h[6] = pwt->h[3];
- pwd->h[5] = pws->h[2];
- pwd->h[4] = pwt->h[2];
- pwd->h[3] = pws->h[1];
- pwd->h[2] = pwt->h[1];
- pwd->h[1] = pws->h[0];
- pwd->h[0] = pwt->h[0];
-#endif
- break;
- case DF_WORD:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->w[2] = pws->w[0];
- pwd->w[3] = pwt->w[0];
- pwd->w[0] = pws->w[1];
- pwd->w[1] = pwt->w[1];
-#else
- pwd->w[3] = pws->w[1];
- pwd->w[2] = pwt->w[1];
- pwd->w[1] = pws->w[0];
- pwd->w[0] = pwt->w[0];
-#endif
- break;
- case DF_DOUBLE:
- pwd->d[1] = pws->d[0];
- pwd->d[0] = pwt->d[0];
- break;
- default:
- assert(0);
- }
-}
-
-void helper_msa_pckev_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
- uint32_t ws, uint32_t wt)
-{
- wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- wr_t *pws = &(env->active_fpu.fpr[ws].wr);
- wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-
- switch (df) {
- case DF_BYTE:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->b[8] = pws->b[9];
- pwd->b[10] = pws->b[13];
- pwd->b[12] = pws->b[1];
- pwd->b[14] = pws->b[5];
- pwd->b[0] = pwt->b[9];
- pwd->b[2] = pwt->b[13];
- pwd->b[4] = pwt->b[1];
- pwd->b[6] = pwt->b[5];
- pwd->b[9] = pws->b[11];
- pwd->b[13] = pws->b[3];
- pwd->b[1] = pwt->b[11];
- pwd->b[5] = pwt->b[3];
- pwd->b[11] = pws->b[15];
- pwd->b[3] = pwt->b[15];
- pwd->b[15] = pws->b[7];
- pwd->b[7] = pwt->b[7];
-#else
- pwd->b[15] = pws->b[14];
- pwd->b[13] = pws->b[10];
- pwd->b[11] = pws->b[6];
- pwd->b[9] = pws->b[2];
- pwd->b[7] = pwt->b[14];
- pwd->b[5] = pwt->b[10];
- pwd->b[3] = pwt->b[6];
- pwd->b[1] = pwt->b[2];
- pwd->b[14] = pws->b[12];
- pwd->b[10] = pws->b[4];
- pwd->b[6] = pwt->b[12];
- pwd->b[2] = pwt->b[4];
- pwd->b[12] = pws->b[8];
- pwd->b[4] = pwt->b[8];
- pwd->b[8] = pws->b[0];
- pwd->b[0] = pwt->b[0];
-#endif
- break;
- case DF_HALF:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->h[4] = pws->h[5];
- pwd->h[6] = pws->h[1];
- pwd->h[0] = pwt->h[5];
- pwd->h[2] = pwt->h[1];
- pwd->h[5] = pws->h[7];
- pwd->h[1] = pwt->h[7];
- pwd->h[7] = pws->h[3];
- pwd->h[3] = pwt->h[3];
-#else
- pwd->h[7] = pws->h[6];
- pwd->h[5] = pws->h[2];
- pwd->h[3] = pwt->h[6];
- pwd->h[1] = pwt->h[2];
- pwd->h[6] = pws->h[4];
- pwd->h[2] = pwt->h[4];
- pwd->h[4] = pws->h[0];
- pwd->h[0] = pwt->h[0];
-#endif
- break;
- case DF_WORD:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->w[2] = pws->w[3];
- pwd->w[0] = pwt->w[3];
- pwd->w[3] = pws->w[1];
- pwd->w[1] = pwt->w[1];
-#else
- pwd->w[3] = pws->w[2];
- pwd->w[1] = pwt->w[2];
- pwd->w[2] = pws->w[0];
- pwd->w[0] = pwt->w[0];
-#endif
- break;
- case DF_DOUBLE:
- pwd->d[1] = pws->d[0];
- pwd->d[0] = pwt->d[0];
- break;
- default:
- assert(0);
- }
-}
-
-void helper_msa_pckod_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
- uint32_t ws, uint32_t wt)
-{
- wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- wr_t *pws = &(env->active_fpu.fpr[ws].wr);
- wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
-
- switch (df) {
- case DF_BYTE:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->b[7] = pwt->b[6];
- pwd->b[5] = pwt->b[2];
- pwd->b[3] = pwt->b[14];
- pwd->b[1] = pwt->b[10];
- pwd->b[15] = pws->b[6];
- pwd->b[13] = pws->b[2];
- pwd->b[11] = pws->b[14];
- pwd->b[9] = pws->b[10];
- pwd->b[6] = pwt->b[4];
- pwd->b[2] = pwt->b[12];
- pwd->b[14] = pws->b[4];
- pwd->b[10] = pws->b[12];
- pwd->b[4] = pwt->b[0];
- pwd->b[12] = pws->b[0];
- pwd->b[0] = pwt->b[8];
- pwd->b[8] = pws->b[8];
-#else
- pwd->b[0] = pwt->b[1];
- pwd->b[2] = pwt->b[5];
- pwd->b[4] = pwt->b[9];
- pwd->b[6] = pwt->b[13];
- pwd->b[8] = pws->b[1];
- pwd->b[10] = pws->b[5];
- pwd->b[12] = pws->b[9];
- pwd->b[14] = pws->b[13];
- pwd->b[1] = pwt->b[3];
- pwd->b[5] = pwt->b[11];
- pwd->b[9] = pws->b[3];
- pwd->b[13] = pws->b[11];
- pwd->b[3] = pwt->b[7];
- pwd->b[11] = pws->b[7];
- pwd->b[7] = pwt->b[15];
- pwd->b[15] = pws->b[15];
-#endif
- break;
- case DF_HALF:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->h[3] = pwt->h[2];
- pwd->h[1] = pwt->h[6];
- pwd->h[7] = pws->h[2];
- pwd->h[5] = pws->h[6];
- pwd->h[2] = pwt->h[0];
- pwd->h[6] = pws->h[0];
- pwd->h[0] = pwt->h[4];
- pwd->h[4] = pws->h[4];
-#else
- pwd->h[0] = pwt->h[1];
- pwd->h[2] = pwt->h[5];
- pwd->h[4] = pws->h[1];
- pwd->h[6] = pws->h[5];
- pwd->h[1] = pwt->h[3];
- pwd->h[5] = pws->h[3];
- pwd->h[3] = pwt->h[7];
- pwd->h[7] = pws->h[7];
-#endif
- break;
- case DF_WORD:
-#if defined(HOST_WORDS_BIGENDIAN)
- pwd->w[1] = pwt->w[0];
- pwd->w[3] = pws->w[0];
- pwd->w[0] = pwt->w[2];
- pwd->w[2] = pws->w[2];
-#else
- pwd->w[0] = pwt->w[1];
- pwd->w[2] = pws->w[1];
- pwd->w[1] = pwt->w[3];
- pwd->w[3] = pws->w[3];
-#endif
- break;
- case DF_DOUBLE:
- pwd->d[0] = pwt->d[1];
- pwd->d[1] = pws->d[1];
- break;
- default:
- assert(0);
- }
-}
-
-
void helper_msa_sldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
uint32_t ws, uint32_t n)
{
return 0;
}
-void helper_msa_move_v(CPUMIPSState *env, uint32_t wd, uint32_t ws)
-{
- wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
- wr_t *pws = &(env->active_fpu.fpr[ws].wr);
-
- msa_move_v(pwd, pws);
-}
-
-static inline int64_t msa_pcnt_df(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;
-}
-
-static inline int64_t msa_nlzc_df(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;
-}
-
-static inline int64_t msa_nloc_df(uint32_t df, int64_t arg)
-{
- return msa_nlzc_df(df, UNSIGNED((~arg), df));
-}
-
void helper_msa_fill_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
uint32_t rs)
{
}
}
-#define MSA_UNOP_DF(func) \
-void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \
- uint32_t wd, uint32_t ws) \
-{ \
- wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
- wr_t *pws = &(env->active_fpu.fpr[ws].wr); \
- \
- switch (df) { \
- case DF_BYTE: \
- pwd->b[0] = msa_ ## func ## _df(df, pws->b[0]); \
- pwd->b[1] = msa_ ## func ## _df(df, pws->b[1]); \
- pwd->b[2] = msa_ ## func ## _df(df, pws->b[2]); \
- pwd->b[3] = msa_ ## func ## _df(df, pws->b[3]); \
- pwd->b[4] = msa_ ## func ## _df(df, pws->b[4]); \
- pwd->b[5] = msa_ ## func ## _df(df, pws->b[5]); \
- pwd->b[6] = msa_ ## func ## _df(df, pws->b[6]); \
- pwd->b[7] = msa_ ## func ## _df(df, pws->b[7]); \
- pwd->b[8] = msa_ ## func ## _df(df, pws->b[8]); \
- pwd->b[9] = msa_ ## func ## _df(df, pws->b[9]); \
- pwd->b[10] = msa_ ## func ## _df(df, pws->b[10]); \
- pwd->b[11] = msa_ ## func ## _df(df, pws->b[11]); \
- pwd->b[12] = msa_ ## func ## _df(df, pws->b[12]); \
- pwd->b[13] = msa_ ## func ## _df(df, pws->b[13]); \
- pwd->b[14] = msa_ ## func ## _df(df, pws->b[14]); \
- pwd->b[15] = msa_ ## func ## _df(df, pws->b[15]); \
- break; \
- case DF_HALF: \
- pwd->h[0] = msa_ ## func ## _df(df, pws->h[0]); \
- pwd->h[1] = msa_ ## func ## _df(df, pws->h[1]); \
- pwd->h[2] = msa_ ## func ## _df(df, pws->h[2]); \
- pwd->h[3] = msa_ ## func ## _df(df, pws->h[3]); \
- pwd->h[4] = msa_ ## func ## _df(df, pws->h[4]); \
- pwd->h[5] = msa_ ## func ## _df(df, pws->h[5]); \
- pwd->h[6] = msa_ ## func ## _df(df, pws->h[6]); \
- pwd->h[7] = msa_ ## func ## _df(df, pws->h[7]); \
- break; \
- case DF_WORD: \
- pwd->w[0] = msa_ ## func ## _df(df, pws->w[0]); \
- pwd->w[1] = msa_ ## func ## _df(df, pws->w[1]); \
- pwd->w[2] = msa_ ## func ## _df(df, pws->w[2]); \
- pwd->w[3] = msa_ ## func ## _df(df, pws->w[3]); \
- break; \
- case DF_DOUBLE: \
- pwd->d[0] = msa_ ## func ## _df(df, pws->d[0]); \
- pwd->d[1] = msa_ ## func ## _df(df, pws->d[1]); \
- break; \
- default: \
- assert(0); \
- } \
-}
-
-MSA_UNOP_DF(nlzc)
-MSA_UNOP_DF(nloc)
-MSA_UNOP_DF(pcnt)
-#undef MSA_UNOP_DF
#define FLOAT_ONE32 make_float32(0x3f8 << 20)
#define FLOAT_ONE64 make_float64(0x3ffULL << 52)