qemu/target/mips/msa_helper.c
<<
>>
Prefs
   1/*
   2 * MIPS SIMD Architecture Module Instruction emulation helpers for QEMU.
   3 *
   4 * Copyright (c) 2014 Imagination Technologies
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include "qemu/osdep.h"
  21#include "cpu.h"
  22#include "internal.h"
  23#include "exec/exec-all.h"
  24#include "exec/helper-proto.h"
  25#include "fpu/softfloat.h"
  26
  27/* Data format min and max values */
  28#define DF_BITS(df) (1 << ((df) + 3))
  29
  30#define DF_MAX_INT(df)  (int64_t)((1LL << (DF_BITS(df) - 1)) - 1)
  31#define M_MAX_INT(m)    (int64_t)((1LL << ((m)         - 1)) - 1)
  32
  33#define DF_MIN_INT(df)  (int64_t)(-(1LL << (DF_BITS(df) - 1)))
  34#define M_MIN_INT(m)    (int64_t)(-(1LL << ((m)         - 1)))
  35
  36#define DF_MAX_UINT(df) (uint64_t)(-1ULL >> (64 - DF_BITS(df)))
  37#define M_MAX_UINT(m)   (uint64_t)(-1ULL >> (64 - (m)))
  38
  39#define UNSIGNED(x, df) ((x) & DF_MAX_UINT(df))
  40#define SIGNED(x, df)                                                   \
  41    ((((int64_t)x) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df)))
  42
  43/* Element-by-element access macros */
  44#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df))
  45
  46
  47
  48/*
  49 * Bit Count
  50 * ---------
  51 *
  52 * +---------------+----------------------------------------------------------+
  53 * | NLOC.B        | Vector Leading Ones Count (byte)                         |
  54 * | NLOC.H        | Vector Leading Ones Count (halfword)                     |
  55 * | NLOC.W        | Vector Leading Ones Count (word)                         |
  56 * | NLOC.D        | Vector Leading Ones Count (doubleword)                   |
  57 * | NLZC.B        | Vector Leading Zeros Count (byte)                        |
  58 * | NLZC.H        | Vector Leading Zeros Count (halfword)                    |
  59 * | NLZC.W        | Vector Leading Zeros Count (word)                        |
  60 * | NLZC.D        | Vector Leading Zeros Count (doubleword)                  |
  61 * | PCNT.B        | Vector Population Count (byte)                           |
  62 * | PCNT.H        | Vector Population Count (halfword)                       |
  63 * | PCNT.W        | Vector Population Count (word)                           |
  64 * | PCNT.D        | Vector Population Count (doubleword)                     |
  65 * +---------------+----------------------------------------------------------+
  66 */
  67
  68static inline int64_t msa_nlzc_df(uint32_t df, int64_t arg)
  69{
  70    uint64_t x, y;
  71    int n, c;
  72
  73    x = UNSIGNED(arg, df);
  74    n = DF_BITS(df);
  75    c = DF_BITS(df) / 2;
  76
  77    do {
  78        y = x >> c;
  79        if (y != 0) {
  80            n = n - c;
  81            x = y;
  82        }
  83        c = c >> 1;
  84    } while (c != 0);
  85
  86    return n - x;
  87}
  88
  89static inline int64_t msa_nloc_df(uint32_t df, int64_t arg)
  90{
  91    return msa_nlzc_df(df, UNSIGNED((~arg), df));
  92}
  93
  94void helper_msa_nloc_b(CPUMIPSState *env, uint32_t wd, uint32_t ws)
  95{
  96    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
  97    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
  98
  99    pwd->b[0]  = msa_nloc_df(DF_BYTE, pws->b[0]);
 100    pwd->b[1]  = msa_nloc_df(DF_BYTE, pws->b[1]);
 101    pwd->b[2]  = msa_nloc_df(DF_BYTE, pws->b[2]);
 102    pwd->b[3]  = msa_nloc_df(DF_BYTE, pws->b[3]);
 103    pwd->b[4]  = msa_nloc_df(DF_BYTE, pws->b[4]);
 104    pwd->b[5]  = msa_nloc_df(DF_BYTE, pws->b[5]);
 105    pwd->b[6]  = msa_nloc_df(DF_BYTE, pws->b[6]);
 106    pwd->b[7]  = msa_nloc_df(DF_BYTE, pws->b[7]);
 107    pwd->b[8]  = msa_nloc_df(DF_BYTE, pws->b[8]);
 108    pwd->b[9]  = msa_nloc_df(DF_BYTE, pws->b[9]);
 109    pwd->b[10] = msa_nloc_df(DF_BYTE, pws->b[10]);
 110    pwd->b[11] = msa_nloc_df(DF_BYTE, pws->b[11]);
 111    pwd->b[12] = msa_nloc_df(DF_BYTE, pws->b[12]);
 112    pwd->b[13] = msa_nloc_df(DF_BYTE, pws->b[13]);
 113    pwd->b[14] = msa_nloc_df(DF_BYTE, pws->b[14]);
 114    pwd->b[15] = msa_nloc_df(DF_BYTE, pws->b[15]);
 115}
 116
 117void helper_msa_nloc_h(CPUMIPSState *env, uint32_t wd, uint32_t ws)
 118{
 119    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 120    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 121
 122    pwd->h[0]  = msa_nloc_df(DF_HALF, pws->h[0]);
 123    pwd->h[1]  = msa_nloc_df(DF_HALF, pws->h[1]);
 124    pwd->h[2]  = msa_nloc_df(DF_HALF, pws->h[2]);
 125    pwd->h[3]  = msa_nloc_df(DF_HALF, pws->h[3]);
 126    pwd->h[4]  = msa_nloc_df(DF_HALF, pws->h[4]);
 127    pwd->h[5]  = msa_nloc_df(DF_HALF, pws->h[5]);
 128    pwd->h[6]  = msa_nloc_df(DF_HALF, pws->h[6]);
 129    pwd->h[7]  = msa_nloc_df(DF_HALF, pws->h[7]);
 130}
 131
 132void helper_msa_nloc_w(CPUMIPSState *env, uint32_t wd, uint32_t ws)
 133{
 134    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 135    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 136
 137    pwd->w[0]  = msa_nloc_df(DF_WORD, pws->w[0]);
 138    pwd->w[1]  = msa_nloc_df(DF_WORD, pws->w[1]);
 139    pwd->w[2]  = msa_nloc_df(DF_WORD, pws->w[2]);
 140    pwd->w[3]  = msa_nloc_df(DF_WORD, pws->w[3]);
 141}
 142
 143void helper_msa_nloc_d(CPUMIPSState *env, uint32_t wd, uint32_t ws)
 144{
 145    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 146    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 147
 148    pwd->d[0]  = msa_nloc_df(DF_DOUBLE, pws->d[0]);
 149    pwd->d[1]  = msa_nloc_df(DF_DOUBLE, pws->d[1]);
 150}
 151
 152void helper_msa_nlzc_b(CPUMIPSState *env, uint32_t wd, uint32_t ws)
 153{
 154    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 155    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 156
 157    pwd->b[0]  = msa_nlzc_df(DF_BYTE, pws->b[0]);
 158    pwd->b[1]  = msa_nlzc_df(DF_BYTE, pws->b[1]);
 159    pwd->b[2]  = msa_nlzc_df(DF_BYTE, pws->b[2]);
 160    pwd->b[3]  = msa_nlzc_df(DF_BYTE, pws->b[3]);
 161    pwd->b[4]  = msa_nlzc_df(DF_BYTE, pws->b[4]);
 162    pwd->b[5]  = msa_nlzc_df(DF_BYTE, pws->b[5]);
 163    pwd->b[6]  = msa_nlzc_df(DF_BYTE, pws->b[6]);
 164    pwd->b[7]  = msa_nlzc_df(DF_BYTE, pws->b[7]);
 165    pwd->b[8]  = msa_nlzc_df(DF_BYTE, pws->b[8]);
 166    pwd->b[9]  = msa_nlzc_df(DF_BYTE, pws->b[9]);
 167    pwd->b[10] = msa_nlzc_df(DF_BYTE, pws->b[10]);
 168    pwd->b[11] = msa_nlzc_df(DF_BYTE, pws->b[11]);
 169    pwd->b[12] = msa_nlzc_df(DF_BYTE, pws->b[12]);
 170    pwd->b[13] = msa_nlzc_df(DF_BYTE, pws->b[13]);
 171    pwd->b[14] = msa_nlzc_df(DF_BYTE, pws->b[14]);
 172    pwd->b[15] = msa_nlzc_df(DF_BYTE, pws->b[15]);
 173}
 174
 175void helper_msa_nlzc_h(CPUMIPSState *env, uint32_t wd, uint32_t ws)
 176{
 177    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 178    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 179
 180    pwd->h[0]  = msa_nlzc_df(DF_HALF, pws->h[0]);
 181    pwd->h[1]  = msa_nlzc_df(DF_HALF, pws->h[1]);
 182    pwd->h[2]  = msa_nlzc_df(DF_HALF, pws->h[2]);
 183    pwd->h[3]  = msa_nlzc_df(DF_HALF, pws->h[3]);
 184    pwd->h[4]  = msa_nlzc_df(DF_HALF, pws->h[4]);
 185    pwd->h[5]  = msa_nlzc_df(DF_HALF, pws->h[5]);
 186    pwd->h[6]  = msa_nlzc_df(DF_HALF, pws->h[6]);
 187    pwd->h[7]  = msa_nlzc_df(DF_HALF, pws->h[7]);
 188}
 189
 190void helper_msa_nlzc_w(CPUMIPSState *env, uint32_t wd, uint32_t ws)
 191{
 192    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 193    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 194
 195    pwd->w[0]  = msa_nlzc_df(DF_WORD, pws->w[0]);
 196    pwd->w[1]  = msa_nlzc_df(DF_WORD, pws->w[1]);
 197    pwd->w[2]  = msa_nlzc_df(DF_WORD, pws->w[2]);
 198    pwd->w[3]  = msa_nlzc_df(DF_WORD, pws->w[3]);
 199}
 200
 201void helper_msa_nlzc_d(CPUMIPSState *env, uint32_t wd, uint32_t ws)
 202{
 203    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 204    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 205
 206    pwd->d[0]  = msa_nlzc_df(DF_DOUBLE, pws->d[0]);
 207    pwd->d[1]  = msa_nlzc_df(DF_DOUBLE, pws->d[1]);
 208}
 209
 210static inline int64_t msa_pcnt_df(uint32_t df, int64_t arg)
 211{
 212    uint64_t x;
 213
 214    x = UNSIGNED(arg, df);
 215
 216    x = (x & 0x5555555555555555ULL) + ((x >>  1) & 0x5555555555555555ULL);
 217    x = (x & 0x3333333333333333ULL) + ((x >>  2) & 0x3333333333333333ULL);
 218    x = (x & 0x0F0F0F0F0F0F0F0FULL) + ((x >>  4) & 0x0F0F0F0F0F0F0F0FULL);
 219    x = (x & 0x00FF00FF00FF00FFULL) + ((x >>  8) & 0x00FF00FF00FF00FFULL);
 220    x = (x & 0x0000FFFF0000FFFFULL) + ((x >> 16) & 0x0000FFFF0000FFFFULL);
 221    x = (x & 0x00000000FFFFFFFFULL) + ((x >> 32));
 222
 223    return x;
 224}
 225
 226void helper_msa_pcnt_b(CPUMIPSState *env, uint32_t wd, uint32_t ws)
 227{
 228    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 229    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 230
 231    pwd->b[0]  = msa_pcnt_df(DF_BYTE, pws->b[0]);
 232    pwd->b[1]  = msa_pcnt_df(DF_BYTE, pws->b[1]);
 233    pwd->b[2]  = msa_pcnt_df(DF_BYTE, pws->b[2]);
 234    pwd->b[3]  = msa_pcnt_df(DF_BYTE, pws->b[3]);
 235    pwd->b[4]  = msa_pcnt_df(DF_BYTE, pws->b[4]);
 236    pwd->b[5]  = msa_pcnt_df(DF_BYTE, pws->b[5]);
 237    pwd->b[6]  = msa_pcnt_df(DF_BYTE, pws->b[6]);
 238    pwd->b[7]  = msa_pcnt_df(DF_BYTE, pws->b[7]);
 239    pwd->b[8]  = msa_pcnt_df(DF_BYTE, pws->b[8]);
 240    pwd->b[9]  = msa_pcnt_df(DF_BYTE, pws->b[9]);
 241    pwd->b[10] = msa_pcnt_df(DF_BYTE, pws->b[10]);
 242    pwd->b[11] = msa_pcnt_df(DF_BYTE, pws->b[11]);
 243    pwd->b[12] = msa_pcnt_df(DF_BYTE, pws->b[12]);
 244    pwd->b[13] = msa_pcnt_df(DF_BYTE, pws->b[13]);
 245    pwd->b[14] = msa_pcnt_df(DF_BYTE, pws->b[14]);
 246    pwd->b[15] = msa_pcnt_df(DF_BYTE, pws->b[15]);
 247}
 248
 249void helper_msa_pcnt_h(CPUMIPSState *env, uint32_t wd, uint32_t ws)
 250{
 251    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 252    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 253
 254    pwd->h[0]  = msa_pcnt_df(DF_HALF, pws->h[0]);
 255    pwd->h[1]  = msa_pcnt_df(DF_HALF, pws->h[1]);
 256    pwd->h[2]  = msa_pcnt_df(DF_HALF, pws->h[2]);
 257    pwd->h[3]  = msa_pcnt_df(DF_HALF, pws->h[3]);
 258    pwd->h[4]  = msa_pcnt_df(DF_HALF, pws->h[4]);
 259    pwd->h[5]  = msa_pcnt_df(DF_HALF, pws->h[5]);
 260    pwd->h[6]  = msa_pcnt_df(DF_HALF, pws->h[6]);
 261    pwd->h[7]  = msa_pcnt_df(DF_HALF, pws->h[7]);
 262}
 263
 264void helper_msa_pcnt_w(CPUMIPSState *env, uint32_t wd, uint32_t ws)
 265{
 266    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 267    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 268
 269    pwd->w[0]  = msa_pcnt_df(DF_WORD, pws->w[0]);
 270    pwd->w[1]  = msa_pcnt_df(DF_WORD, pws->w[1]);
 271    pwd->w[2]  = msa_pcnt_df(DF_WORD, pws->w[2]);
 272    pwd->w[3]  = msa_pcnt_df(DF_WORD, pws->w[3]);
 273}
 274
 275void helper_msa_pcnt_d(CPUMIPSState *env, uint32_t wd, uint32_t ws)
 276{
 277    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 278    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 279
 280    pwd->d[0]  = msa_pcnt_df(DF_DOUBLE, pws->d[0]);
 281    pwd->d[1]  = msa_pcnt_df(DF_DOUBLE, pws->d[1]);
 282}
 283
 284
 285/*
 286 * Bit Move
 287 * --------
 288 *
 289 * +---------------+----------------------------------------------------------+
 290 * | BINSL.B       | Vector Bit Insert Left (byte)                            |
 291 * | BINSL.H       | Vector Bit Insert Left (halfword)                        |
 292 * | BINSL.W       | Vector Bit Insert Left (word)                            |
 293 * | BINSL.D       | Vector Bit Insert Left (doubleword)                      |
 294 * | BINSR.B       | Vector Bit Insert Right (byte)                           |
 295 * | BINSR.H       | Vector Bit Insert Right (halfword)                       |
 296 * | BINSR.W       | Vector Bit Insert Right (word)                           |
 297 * | BINSR.D       | Vector Bit Insert Right (doubleword)                     |
 298 * | BMNZ.V        | Vector Bit Move If Not Zero                              |
 299 * | BMZ.V         | Vector Bit Move If Zero                                  |
 300 * | BSEL.V        | Vector Bit Select                                        |
 301 * +---------------+----------------------------------------------------------+
 302 */
 303
 304/* Data format bit position and unsigned values */
 305#define BIT_POSITION(x, df) ((uint64_t)(x) % DF_BITS(df))
 306
 307static inline int64_t msa_binsl_df(uint32_t df,
 308                                   int64_t dest, int64_t arg1, int64_t arg2)
 309{
 310    uint64_t u_arg1 = UNSIGNED(arg1, df);
 311    uint64_t u_dest = UNSIGNED(dest, df);
 312    int32_t sh_d = BIT_POSITION(arg2, df) + 1;
 313    int32_t sh_a = DF_BITS(df) - sh_d;
 314    if (sh_d == DF_BITS(df)) {
 315        return u_arg1;
 316    } else {
 317        return UNSIGNED(UNSIGNED(u_dest << sh_d, df) >> sh_d, df) |
 318               UNSIGNED(UNSIGNED(u_arg1 >> sh_a, df) << sh_a, df);
 319    }
 320}
 321
 322void helper_msa_binsl_b(CPUMIPSState *env,
 323                        uint32_t wd, uint32_t ws, uint32_t wt)
 324{
 325    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 326    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 327    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 328
 329    pwd->b[0]  = msa_binsl_df(DF_BYTE, pwd->b[0],  pws->b[0],  pwt->b[0]);
 330    pwd->b[1]  = msa_binsl_df(DF_BYTE, pwd->b[1],  pws->b[1],  pwt->b[1]);
 331    pwd->b[2]  = msa_binsl_df(DF_BYTE, pwd->b[2],  pws->b[2],  pwt->b[2]);
 332    pwd->b[3]  = msa_binsl_df(DF_BYTE, pwd->b[3],  pws->b[3],  pwt->b[3]);
 333    pwd->b[4]  = msa_binsl_df(DF_BYTE, pwd->b[4],  pws->b[4],  pwt->b[4]);
 334    pwd->b[5]  = msa_binsl_df(DF_BYTE, pwd->b[5],  pws->b[5],  pwt->b[5]);
 335    pwd->b[6]  = msa_binsl_df(DF_BYTE, pwd->b[6],  pws->b[6],  pwt->b[6]);
 336    pwd->b[7]  = msa_binsl_df(DF_BYTE, pwd->b[7],  pws->b[7],  pwt->b[7]);
 337    pwd->b[8]  = msa_binsl_df(DF_BYTE, pwd->b[8],  pws->b[8],  pwt->b[8]);
 338    pwd->b[9]  = msa_binsl_df(DF_BYTE, pwd->b[9],  pws->b[9],  pwt->b[9]);
 339    pwd->b[10] = msa_binsl_df(DF_BYTE, pwd->b[10], pws->b[10], pwt->b[10]);
 340    pwd->b[11] = msa_binsl_df(DF_BYTE, pwd->b[11], pws->b[11], pwt->b[11]);
 341    pwd->b[12] = msa_binsl_df(DF_BYTE, pwd->b[12], pws->b[12], pwt->b[12]);
 342    pwd->b[13] = msa_binsl_df(DF_BYTE, pwd->b[13], pws->b[13], pwt->b[13]);
 343    pwd->b[14] = msa_binsl_df(DF_BYTE, pwd->b[14], pws->b[14], pwt->b[14]);
 344    pwd->b[15] = msa_binsl_df(DF_BYTE, pwd->b[15], pws->b[15], pwt->b[15]);
 345}
 346
 347void helper_msa_binsl_h(CPUMIPSState *env,
 348                        uint32_t wd, uint32_t ws, uint32_t wt)
 349{
 350    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 351    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 352    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 353
 354    pwd->h[0]  = msa_binsl_df(DF_HALF, pwd->h[0],  pws->h[0],  pwt->h[0]);
 355    pwd->h[1]  = msa_binsl_df(DF_HALF, pwd->h[1],  pws->h[1],  pwt->h[1]);
 356    pwd->h[2]  = msa_binsl_df(DF_HALF, pwd->h[2],  pws->h[2],  pwt->h[2]);
 357    pwd->h[3]  = msa_binsl_df(DF_HALF, pwd->h[3],  pws->h[3],  pwt->h[3]);
 358    pwd->h[4]  = msa_binsl_df(DF_HALF, pwd->h[4],  pws->h[4],  pwt->h[4]);
 359    pwd->h[5]  = msa_binsl_df(DF_HALF, pwd->h[5],  pws->h[5],  pwt->h[5]);
 360    pwd->h[6]  = msa_binsl_df(DF_HALF, pwd->h[6],  pws->h[6],  pwt->h[6]);
 361    pwd->h[7]  = msa_binsl_df(DF_HALF, pwd->h[7],  pws->h[7],  pwt->h[7]);
 362}
 363
 364void helper_msa_binsl_w(CPUMIPSState *env,
 365                        uint32_t wd, uint32_t ws, uint32_t wt)
 366{
 367    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 368    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 369    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 370
 371    pwd->w[0]  = msa_binsl_df(DF_WORD, pwd->w[0],  pws->w[0],  pwt->w[0]);
 372    pwd->w[1]  = msa_binsl_df(DF_WORD, pwd->w[1],  pws->w[1],  pwt->w[1]);
 373    pwd->w[2]  = msa_binsl_df(DF_WORD, pwd->w[2],  pws->w[2],  pwt->w[2]);
 374    pwd->w[3]  = msa_binsl_df(DF_WORD, pwd->w[3],  pws->w[3],  pwt->w[3]);
 375}
 376
 377void helper_msa_binsl_d(CPUMIPSState *env,
 378                        uint32_t wd, uint32_t ws, uint32_t wt)
 379{
 380    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 381    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 382    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 383
 384    pwd->d[0]  = msa_binsl_df(DF_DOUBLE, pwd->d[0],  pws->d[0],  pwt->d[0]);
 385    pwd->d[1]  = msa_binsl_df(DF_DOUBLE, pwd->d[1],  pws->d[1],  pwt->d[1]);
 386}
 387
 388static inline int64_t msa_binsr_df(uint32_t df,
 389                                   int64_t dest, int64_t arg1, int64_t arg2)
 390{
 391    uint64_t u_arg1 = UNSIGNED(arg1, df);
 392    uint64_t u_dest = UNSIGNED(dest, df);
 393    int32_t sh_d = BIT_POSITION(arg2, df) + 1;
 394    int32_t sh_a = DF_BITS(df) - sh_d;
 395    if (sh_d == DF_BITS(df)) {
 396        return u_arg1;
 397    } else {
 398        return UNSIGNED(UNSIGNED(u_dest >> sh_d, df) << sh_d, df) |
 399               UNSIGNED(UNSIGNED(u_arg1 << sh_a, df) >> sh_a, df);
 400    }
 401}
 402
 403void helper_msa_binsr_b(CPUMIPSState *env,
 404                        uint32_t wd, uint32_t ws, uint32_t wt)
 405{
 406    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 407    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 408    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 409
 410    pwd->b[0]  = msa_binsr_df(DF_BYTE, pwd->b[0],  pws->b[0],  pwt->b[0]);
 411    pwd->b[1]  = msa_binsr_df(DF_BYTE, pwd->b[1],  pws->b[1],  pwt->b[1]);
 412    pwd->b[2]  = msa_binsr_df(DF_BYTE, pwd->b[2],  pws->b[2],  pwt->b[2]);
 413    pwd->b[3]  = msa_binsr_df(DF_BYTE, pwd->b[3],  pws->b[3],  pwt->b[3]);
 414    pwd->b[4]  = msa_binsr_df(DF_BYTE, pwd->b[4],  pws->b[4],  pwt->b[4]);
 415    pwd->b[5]  = msa_binsr_df(DF_BYTE, pwd->b[5],  pws->b[5],  pwt->b[5]);
 416    pwd->b[6]  = msa_binsr_df(DF_BYTE, pwd->b[6],  pws->b[6],  pwt->b[6]);
 417    pwd->b[7]  = msa_binsr_df(DF_BYTE, pwd->b[7],  pws->b[7],  pwt->b[7]);
 418    pwd->b[8]  = msa_binsr_df(DF_BYTE, pwd->b[8],  pws->b[8],  pwt->b[8]);
 419    pwd->b[9]  = msa_binsr_df(DF_BYTE, pwd->b[9],  pws->b[9],  pwt->b[9]);
 420    pwd->b[10] = msa_binsr_df(DF_BYTE, pwd->b[10], pws->b[10], pwt->b[10]);
 421    pwd->b[11] = msa_binsr_df(DF_BYTE, pwd->b[11], pws->b[11], pwt->b[11]);
 422    pwd->b[12] = msa_binsr_df(DF_BYTE, pwd->b[12], pws->b[12], pwt->b[12]);
 423    pwd->b[13] = msa_binsr_df(DF_BYTE, pwd->b[13], pws->b[13], pwt->b[13]);
 424    pwd->b[14] = msa_binsr_df(DF_BYTE, pwd->b[14], pws->b[14], pwt->b[14]);
 425    pwd->b[15] = msa_binsr_df(DF_BYTE, pwd->b[15], pws->b[15], pwt->b[15]);
 426}
 427
 428void helper_msa_binsr_h(CPUMIPSState *env,
 429                        uint32_t wd, uint32_t ws, uint32_t wt)
 430{
 431    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 432    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 433    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 434
 435    pwd->h[0]  = msa_binsr_df(DF_HALF, pwd->h[0],  pws->h[0],  pwt->h[0]);
 436    pwd->h[1]  = msa_binsr_df(DF_HALF, pwd->h[1],  pws->h[1],  pwt->h[1]);
 437    pwd->h[2]  = msa_binsr_df(DF_HALF, pwd->h[2],  pws->h[2],  pwt->h[2]);
 438    pwd->h[3]  = msa_binsr_df(DF_HALF, pwd->h[3],  pws->h[3],  pwt->h[3]);
 439    pwd->h[4]  = msa_binsr_df(DF_HALF, pwd->h[4],  pws->h[4],  pwt->h[4]);
 440    pwd->h[5]  = msa_binsr_df(DF_HALF, pwd->h[5],  pws->h[5],  pwt->h[5]);
 441    pwd->h[6]  = msa_binsr_df(DF_HALF, pwd->h[6],  pws->h[6],  pwt->h[6]);
 442    pwd->h[7]  = msa_binsr_df(DF_HALF, pwd->h[7],  pws->h[7],  pwt->h[7]);
 443}
 444
 445void helper_msa_binsr_w(CPUMIPSState *env,
 446                        uint32_t wd, uint32_t ws, uint32_t wt)
 447{
 448    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 449    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 450    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 451
 452    pwd->w[0]  = msa_binsr_df(DF_WORD, pwd->w[0],  pws->w[0],  pwt->w[0]);
 453    pwd->w[1]  = msa_binsr_df(DF_WORD, pwd->w[1],  pws->w[1],  pwt->w[1]);
 454    pwd->w[2]  = msa_binsr_df(DF_WORD, pwd->w[2],  pws->w[2],  pwt->w[2]);
 455    pwd->w[3]  = msa_binsr_df(DF_WORD, pwd->w[3],  pws->w[3],  pwt->w[3]);
 456}
 457
 458void helper_msa_binsr_d(CPUMIPSState *env,
 459                        uint32_t wd, uint32_t ws, uint32_t wt)
 460{
 461    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 462    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 463    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 464
 465    pwd->d[0]  = msa_binsr_df(DF_DOUBLE, pwd->d[0],  pws->d[0],  pwt->d[0]);
 466    pwd->d[1]  = msa_binsr_df(DF_DOUBLE, pwd->d[1],  pws->d[1],  pwt->d[1]);
 467}
 468
 469void helper_msa_bmnz_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 470{
 471    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 472    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 473    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 474
 475    pwd->d[0] = UNSIGNED(                                                     \
 476        ((pwd->d[0] & (~pwt->d[0])) | (pws->d[0] & pwt->d[0])), DF_DOUBLE);
 477    pwd->d[1] = UNSIGNED(                                                     \
 478        ((pwd->d[1] & (~pwt->d[1])) | (pws->d[1] & pwt->d[1])), DF_DOUBLE);
 479}
 480
 481void helper_msa_bmz_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 482{
 483    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 484    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 485    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 486
 487    pwd->d[0] = UNSIGNED(                                                     \
 488        ((pwd->d[0] & pwt->d[0]) | (pws->d[0] & (~pwt->d[0]))), DF_DOUBLE);
 489    pwd->d[1] = UNSIGNED(                                                     \
 490        ((pwd->d[1] & pwt->d[1]) | (pws->d[1] & (~pwt->d[1]))), DF_DOUBLE);
 491}
 492
 493void helper_msa_bsel_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 494{
 495    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 496    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 497    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 498
 499    pwd->d[0] = UNSIGNED(                                                     \
 500        (pws->d[0] & (~pwd->d[0])) | (pwt->d[0] & pwd->d[0]), DF_DOUBLE);
 501    pwd->d[1] = UNSIGNED(                                                     \
 502        (pws->d[1] & (~pwd->d[1])) | (pwt->d[1] & pwd->d[1]), DF_DOUBLE);
 503}
 504
 505
 506/*
 507 * Bit Set
 508 * -------
 509 *
 510 * +---------------+----------------------------------------------------------+
 511 * | BCLR.B        | Vector Bit Clear (byte)                                  |
 512 * | BCLR.H        | Vector Bit Clear (halfword)                              |
 513 * | BCLR.W        | Vector Bit Clear (word)                                  |
 514 * | BCLR.D        | Vector Bit Clear (doubleword)                            |
 515 * | BNEG.B        | Vector Bit Negate (byte)                                 |
 516 * | BNEG.H        | Vector Bit Negate (halfword)                             |
 517 * | BNEG.W        | Vector Bit Negate (word)                                 |
 518 * | BNEG.D        | Vector Bit Negate (doubleword)                           |
 519 * | BSET.B        | Vector Bit Set (byte)                                    |
 520 * | BSET.H        | Vector Bit Set (halfword)                                |
 521 * | BSET.W        | Vector Bit Set (word)                                    |
 522 * | BSET.D        | Vector Bit Set (doubleword)                              |
 523 * +---------------+----------------------------------------------------------+
 524 */
 525
 526static inline int64_t msa_bclr_df(uint32_t df, int64_t arg1, int64_t arg2)
 527{
 528    int32_t b_arg2 = BIT_POSITION(arg2, df);
 529    return UNSIGNED(arg1 & (~(1LL << b_arg2)), df);
 530}
 531
 532void helper_msa_bclr_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 533{
 534    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 535    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 536    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 537
 538    pwd->b[0]  = msa_bclr_df(DF_BYTE, pws->b[0],  pwt->b[0]);
 539    pwd->b[1]  = msa_bclr_df(DF_BYTE, pws->b[1],  pwt->b[1]);
 540    pwd->b[2]  = msa_bclr_df(DF_BYTE, pws->b[2],  pwt->b[2]);
 541    pwd->b[3]  = msa_bclr_df(DF_BYTE, pws->b[3],  pwt->b[3]);
 542    pwd->b[4]  = msa_bclr_df(DF_BYTE, pws->b[4],  pwt->b[4]);
 543    pwd->b[5]  = msa_bclr_df(DF_BYTE, pws->b[5],  pwt->b[5]);
 544    pwd->b[6]  = msa_bclr_df(DF_BYTE, pws->b[6],  pwt->b[6]);
 545    pwd->b[7]  = msa_bclr_df(DF_BYTE, pws->b[7],  pwt->b[7]);
 546    pwd->b[8]  = msa_bclr_df(DF_BYTE, pws->b[8],  pwt->b[8]);
 547    pwd->b[9]  = msa_bclr_df(DF_BYTE, pws->b[9],  pwt->b[9]);
 548    pwd->b[10] = msa_bclr_df(DF_BYTE, pws->b[10], pwt->b[10]);
 549    pwd->b[11] = msa_bclr_df(DF_BYTE, pws->b[11], pwt->b[11]);
 550    pwd->b[12] = msa_bclr_df(DF_BYTE, pws->b[12], pwt->b[12]);
 551    pwd->b[13] = msa_bclr_df(DF_BYTE, pws->b[13], pwt->b[13]);
 552    pwd->b[14] = msa_bclr_df(DF_BYTE, pws->b[14], pwt->b[14]);
 553    pwd->b[15] = msa_bclr_df(DF_BYTE, pws->b[15], pwt->b[15]);
 554}
 555
 556void helper_msa_bclr_h(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 557{
 558    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 559    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 560    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 561
 562    pwd->h[0]  = msa_bclr_df(DF_HALF, pws->h[0],  pwt->h[0]);
 563    pwd->h[1]  = msa_bclr_df(DF_HALF, pws->h[1],  pwt->h[1]);
 564    pwd->h[2]  = msa_bclr_df(DF_HALF, pws->h[2],  pwt->h[2]);
 565    pwd->h[3]  = msa_bclr_df(DF_HALF, pws->h[3],  pwt->h[3]);
 566    pwd->h[4]  = msa_bclr_df(DF_HALF, pws->h[4],  pwt->h[4]);
 567    pwd->h[5]  = msa_bclr_df(DF_HALF, pws->h[5],  pwt->h[5]);
 568    pwd->h[6]  = msa_bclr_df(DF_HALF, pws->h[6],  pwt->h[6]);
 569    pwd->h[7]  = msa_bclr_df(DF_HALF, pws->h[7],  pwt->h[7]);
 570}
 571
 572void helper_msa_bclr_w(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 573{
 574    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 575    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 576    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 577
 578    pwd->w[0]  = msa_bclr_df(DF_WORD, pws->w[0],  pwt->w[0]);
 579    pwd->w[1]  = msa_bclr_df(DF_WORD, pws->w[1],  pwt->w[1]);
 580    pwd->w[2]  = msa_bclr_df(DF_WORD, pws->w[2],  pwt->w[2]);
 581    pwd->w[3]  = msa_bclr_df(DF_WORD, pws->w[3],  pwt->w[3]);
 582}
 583
 584void helper_msa_bclr_d(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 585{
 586    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 587    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 588    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 589
 590    pwd->d[0]  = msa_bclr_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
 591    pwd->d[1]  = msa_bclr_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
 592}
 593
 594static inline int64_t msa_bneg_df(uint32_t df, int64_t arg1, int64_t arg2)
 595{
 596    int32_t b_arg2 = BIT_POSITION(arg2, df);
 597    return UNSIGNED(arg1 ^ (1LL << b_arg2), df);
 598}
 599
 600void helper_msa_bneg_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 601{
 602    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 603    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 604    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 605
 606    pwd->b[0]  = msa_bneg_df(DF_BYTE, pws->b[0],  pwt->b[0]);
 607    pwd->b[1]  = msa_bneg_df(DF_BYTE, pws->b[1],  pwt->b[1]);
 608    pwd->b[2]  = msa_bneg_df(DF_BYTE, pws->b[2],  pwt->b[2]);
 609    pwd->b[3]  = msa_bneg_df(DF_BYTE, pws->b[3],  pwt->b[3]);
 610    pwd->b[4]  = msa_bneg_df(DF_BYTE, pws->b[4],  pwt->b[4]);
 611    pwd->b[5]  = msa_bneg_df(DF_BYTE, pws->b[5],  pwt->b[5]);
 612    pwd->b[6]  = msa_bneg_df(DF_BYTE, pws->b[6],  pwt->b[6]);
 613    pwd->b[7]  = msa_bneg_df(DF_BYTE, pws->b[7],  pwt->b[7]);
 614    pwd->b[8]  = msa_bneg_df(DF_BYTE, pws->b[8],  pwt->b[8]);
 615    pwd->b[9]  = msa_bneg_df(DF_BYTE, pws->b[9],  pwt->b[9]);
 616    pwd->b[10] = msa_bneg_df(DF_BYTE, pws->b[10], pwt->b[10]);
 617    pwd->b[11] = msa_bneg_df(DF_BYTE, pws->b[11], pwt->b[11]);
 618    pwd->b[12] = msa_bneg_df(DF_BYTE, pws->b[12], pwt->b[12]);
 619    pwd->b[13] = msa_bneg_df(DF_BYTE, pws->b[13], pwt->b[13]);
 620    pwd->b[14] = msa_bneg_df(DF_BYTE, pws->b[14], pwt->b[14]);
 621    pwd->b[15] = msa_bneg_df(DF_BYTE, pws->b[15], pwt->b[15]);
 622}
 623
 624void helper_msa_bneg_h(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 625{
 626    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 627    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 628    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 629
 630    pwd->h[0]  = msa_bneg_df(DF_HALF, pws->h[0],  pwt->h[0]);
 631    pwd->h[1]  = msa_bneg_df(DF_HALF, pws->h[1],  pwt->h[1]);
 632    pwd->h[2]  = msa_bneg_df(DF_HALF, pws->h[2],  pwt->h[2]);
 633    pwd->h[3]  = msa_bneg_df(DF_HALF, pws->h[3],  pwt->h[3]);
 634    pwd->h[4]  = msa_bneg_df(DF_HALF, pws->h[4],  pwt->h[4]);
 635    pwd->h[5]  = msa_bneg_df(DF_HALF, pws->h[5],  pwt->h[5]);
 636    pwd->h[6]  = msa_bneg_df(DF_HALF, pws->h[6],  pwt->h[6]);
 637    pwd->h[7]  = msa_bneg_df(DF_HALF, pws->h[7],  pwt->h[7]);
 638}
 639
 640void helper_msa_bneg_w(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 641{
 642    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 643    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 644    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 645
 646    pwd->w[0]  = msa_bneg_df(DF_WORD, pws->w[0],  pwt->w[0]);
 647    pwd->w[1]  = msa_bneg_df(DF_WORD, pws->w[1],  pwt->w[1]);
 648    pwd->w[2]  = msa_bneg_df(DF_WORD, pws->w[2],  pwt->w[2]);
 649    pwd->w[3]  = msa_bneg_df(DF_WORD, pws->w[3],  pwt->w[3]);
 650}
 651
 652void helper_msa_bneg_d(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 653{
 654    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 655    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 656    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 657
 658    pwd->d[0]  = msa_bneg_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
 659    pwd->d[1]  = msa_bneg_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
 660}
 661
 662static inline int64_t msa_bset_df(uint32_t df, int64_t arg1,
 663        int64_t arg2)
 664{
 665    int32_t b_arg2 = BIT_POSITION(arg2, df);
 666    return UNSIGNED(arg1 | (1LL << b_arg2), df);
 667}
 668
 669void helper_msa_bset_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 670{
 671    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 672    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 673    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 674
 675    pwd->b[0]  = msa_bset_df(DF_BYTE, pws->b[0],  pwt->b[0]);
 676    pwd->b[1]  = msa_bset_df(DF_BYTE, pws->b[1],  pwt->b[1]);
 677    pwd->b[2]  = msa_bset_df(DF_BYTE, pws->b[2],  pwt->b[2]);
 678    pwd->b[3]  = msa_bset_df(DF_BYTE, pws->b[3],  pwt->b[3]);
 679    pwd->b[4]  = msa_bset_df(DF_BYTE, pws->b[4],  pwt->b[4]);
 680    pwd->b[5]  = msa_bset_df(DF_BYTE, pws->b[5],  pwt->b[5]);
 681    pwd->b[6]  = msa_bset_df(DF_BYTE, pws->b[6],  pwt->b[6]);
 682    pwd->b[7]  = msa_bset_df(DF_BYTE, pws->b[7],  pwt->b[7]);
 683    pwd->b[8]  = msa_bset_df(DF_BYTE, pws->b[8],  pwt->b[8]);
 684    pwd->b[9]  = msa_bset_df(DF_BYTE, pws->b[9],  pwt->b[9]);
 685    pwd->b[10] = msa_bset_df(DF_BYTE, pws->b[10], pwt->b[10]);
 686    pwd->b[11] = msa_bset_df(DF_BYTE, pws->b[11], pwt->b[11]);
 687    pwd->b[12] = msa_bset_df(DF_BYTE, pws->b[12], pwt->b[12]);
 688    pwd->b[13] = msa_bset_df(DF_BYTE, pws->b[13], pwt->b[13]);
 689    pwd->b[14] = msa_bset_df(DF_BYTE, pws->b[14], pwt->b[14]);
 690    pwd->b[15] = msa_bset_df(DF_BYTE, pws->b[15], pwt->b[15]);
 691}
 692
 693void helper_msa_bset_h(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 694{
 695    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 696    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 697    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 698
 699    pwd->h[0]  = msa_bset_df(DF_HALF, pws->h[0],  pwt->h[0]);
 700    pwd->h[1]  = msa_bset_df(DF_HALF, pws->h[1],  pwt->h[1]);
 701    pwd->h[2]  = msa_bset_df(DF_HALF, pws->h[2],  pwt->h[2]);
 702    pwd->h[3]  = msa_bset_df(DF_HALF, pws->h[3],  pwt->h[3]);
 703    pwd->h[4]  = msa_bset_df(DF_HALF, pws->h[4],  pwt->h[4]);
 704    pwd->h[5]  = msa_bset_df(DF_HALF, pws->h[5],  pwt->h[5]);
 705    pwd->h[6]  = msa_bset_df(DF_HALF, pws->h[6],  pwt->h[6]);
 706    pwd->h[7]  = msa_bset_df(DF_HALF, pws->h[7],  pwt->h[7]);
 707}
 708
 709void helper_msa_bset_w(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 710{
 711    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 712    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 713    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 714
 715    pwd->w[0]  = msa_bset_df(DF_WORD, pws->w[0],  pwt->w[0]);
 716    pwd->w[1]  = msa_bset_df(DF_WORD, pws->w[1],  pwt->w[1]);
 717    pwd->w[2]  = msa_bset_df(DF_WORD, pws->w[2],  pwt->w[2]);
 718    pwd->w[3]  = msa_bset_df(DF_WORD, pws->w[3],  pwt->w[3]);
 719}
 720
 721void helper_msa_bset_d(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
 722{
 723    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 724    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 725    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 726
 727    pwd->d[0]  = msa_bset_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
 728    pwd->d[1]  = msa_bset_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
 729}
 730
 731
 732/*
 733 * Fixed Multiply
 734 * --------------
 735 *
 736 * +---------------+----------------------------------------------------------+
 737 * | MADD_Q.H      | Vector Fixed-Point Multiply and Add (halfword)           |
 738 * | MADD_Q.W      | Vector Fixed-Point Multiply and Add (word)               |
 739 * | MADDR_Q.H     | Vector Fixed-Point Multiply and Add Rounded (halfword)   |
 740 * | MADDR_Q.W     | Vector Fixed-Point Multiply and Add Rounded (word)       |
 741 * | MSUB_Q.H      | Vector Fixed-Point Multiply and Subtr. (halfword)        |
 742 * | MSUB_Q.W      | Vector Fixed-Point Multiply and Subtr. (word)            |
 743 * | MSUBR_Q.H     | Vector Fixed-Point Multiply and Subtr. Rounded (halfword)|
 744 * | MSUBR_Q.W     | Vector Fixed-Point Multiply and Subtr. Rounded (word)    |
 745 * | MUL_Q.H       | Vector Fixed-Point Multiply (halfword)                   |
 746 * | MUL_Q.W       | Vector Fixed-Point Multiply (word)                       |
 747 * | MULR_Q.H      | Vector Fixed-Point Multiply Rounded (halfword)           |
 748 * | MULR_Q.W      | Vector Fixed-Point Multiply Rounded (word)               |
 749 * +---------------+----------------------------------------------------------+
 750 */
 751
 752/* TODO: insert Fixed Multiply group helpers here */
 753
 754
 755/*
 756 * Float Max Min
 757 * -------------
 758 *
 759 * +---------------+----------------------------------------------------------+
 760 * | FMAX_A.W      | Vector Floating-Point Maximum (Absolute) (word)          |
 761 * | FMAX_A.D      | Vector Floating-Point Maximum (Absolute) (doubleword)    |
 762 * | FMAX.W        | Vector Floating-Point Maximum (word)                     |
 763 * | FMAX.D        | Vector Floating-Point Maximum (doubleword)               |
 764 * | FMIN_A.W      | Vector Floating-Point Minimum (Absolute) (word)          |
 765 * | FMIN_A.D      | Vector Floating-Point Minimum (Absolute) (doubleword)    |
 766 * | FMIN.W        | Vector Floating-Point Minimum (word)                     |
 767 * | FMIN.D        | Vector Floating-Point Minimum (doubleword)               |
 768 * +---------------+----------------------------------------------------------+
 769 */
 770
 771/* TODO: insert Float Max Min group helpers here */
 772
 773
 774/*
 775 * Int Add
 776 * -------
 777 *
 778 * +---------------+----------------------------------------------------------+
 779 * | ADD_A.B       | Vector Add Absolute Values (byte)                        |
 780 * | ADD_A.H       | Vector Add Absolute Values (halfword)                    |
 781 * | ADD_A.W       | Vector Add Absolute Values (word)                        |
 782 * | ADD_A.D       | Vector Add Absolute Values (doubleword)                  |
 783 * | ADDS_A.B      | Vector Signed Saturated Add (of Absolute) (byte)         |
 784 * | ADDS_A.H      | Vector Signed Saturated Add (of Absolute) (halfword)     |
 785 * | ADDS_A.W      | Vector Signed Saturated Add (of Absolute) (word)         |
 786 * | ADDS_A.D      | Vector Signed Saturated Add (of Absolute) (doubleword)   |
 787 * | ADDS_S.B      | Vector Signed Saturated Add (of Signed) (byte)           |
 788 * | ADDS_S.H      | Vector Signed Saturated Add (of Signed) (halfword)       |
 789 * | ADDS_S.W      | Vector Signed Saturated Add (of Signed) (word)           |
 790 * | ADDS_S.D      | Vector Signed Saturated Add (of Signed) (doubleword)     |
 791 * | ADDS_U.B      | Vector Unsigned Saturated Add (of Unsigned) (byte)       |
 792 * | ADDS_U.H      | Vector Unsigned Saturated Add (of Unsigned) (halfword)   |
 793 * | ADDS_U.W      | Vector Unsigned Saturated Add (of Unsigned) (word)       |
 794 * | ADDS_U.D      | Vector Unsigned Saturated Add (of Unsigned) (doubleword) |
 795 * | ADDV.B        | Vector Add (byte)                                        |
 796 * | ADDV.H        | Vector Add (halfword)                                    |
 797 * | ADDV.W        | Vector Add (word)                                        |
 798 * | ADDV.D        | Vector Add (doubleword)                                  |
 799 * | HADD_S.H      | Vector Signed Horizontal Add (halfword)                  |
 800 * | HADD_S.W      | Vector Signed Horizontal Add (word)                      |
 801 * | HADD_S.D      | Vector Signed Horizontal Add (doubleword)                |
 802 * | HADD_U.H      | Vector Unigned Horizontal Add (halfword)                 |
 803 * | HADD_U.W      | Vector Unigned Horizontal Add (word)                     |
 804 * | HADD_U.D      | Vector Unigned Horizontal Add (doubleword)               |
 805 * +---------------+----------------------------------------------------------+
 806 */
 807
 808
 809static inline int64_t msa_add_a_df(uint32_t df, int64_t arg1, int64_t arg2)
 810{
 811    uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
 812    uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
 813    return abs_arg1 + abs_arg2;
 814}
 815
 816void helper_msa_add_a_b(CPUMIPSState *env,
 817                        uint32_t wd, uint32_t ws, uint32_t wt)
 818{
 819    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 820    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 821    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 822
 823    pwd->b[0]  = msa_add_a_df(DF_BYTE, pws->b[0],  pwt->b[0]);
 824    pwd->b[1]  = msa_add_a_df(DF_BYTE, pws->b[1],  pwt->b[1]);
 825    pwd->b[2]  = msa_add_a_df(DF_BYTE, pws->b[2],  pwt->b[2]);
 826    pwd->b[3]  = msa_add_a_df(DF_BYTE, pws->b[3],  pwt->b[3]);
 827    pwd->b[4]  = msa_add_a_df(DF_BYTE, pws->b[4],  pwt->b[4]);
 828    pwd->b[5]  = msa_add_a_df(DF_BYTE, pws->b[5],  pwt->b[5]);
 829    pwd->b[6]  = msa_add_a_df(DF_BYTE, pws->b[6],  pwt->b[6]);
 830    pwd->b[7]  = msa_add_a_df(DF_BYTE, pws->b[7],  pwt->b[7]);
 831    pwd->b[8]  = msa_add_a_df(DF_BYTE, pws->b[8],  pwt->b[8]);
 832    pwd->b[9]  = msa_add_a_df(DF_BYTE, pws->b[9],  pwt->b[9]);
 833    pwd->b[10] = msa_add_a_df(DF_BYTE, pws->b[10], pwt->b[10]);
 834    pwd->b[11] = msa_add_a_df(DF_BYTE, pws->b[11], pwt->b[11]);
 835    pwd->b[12] = msa_add_a_df(DF_BYTE, pws->b[12], pwt->b[12]);
 836    pwd->b[13] = msa_add_a_df(DF_BYTE, pws->b[13], pwt->b[13]);
 837    pwd->b[14] = msa_add_a_df(DF_BYTE, pws->b[14], pwt->b[14]);
 838    pwd->b[15] = msa_add_a_df(DF_BYTE, pws->b[15], pwt->b[15]);
 839}
 840
 841void helper_msa_add_a_h(CPUMIPSState *env,
 842                        uint32_t wd, uint32_t ws, uint32_t wt)
 843{
 844    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 845    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 846    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 847
 848    pwd->h[0]  = msa_add_a_df(DF_HALF, pws->h[0],  pwt->h[0]);
 849    pwd->h[1]  = msa_add_a_df(DF_HALF, pws->h[1],  pwt->h[1]);
 850    pwd->h[2]  = msa_add_a_df(DF_HALF, pws->h[2],  pwt->h[2]);
 851    pwd->h[3]  = msa_add_a_df(DF_HALF, pws->h[3],  pwt->h[3]);
 852    pwd->h[4]  = msa_add_a_df(DF_HALF, pws->h[4],  pwt->h[4]);
 853    pwd->h[5]  = msa_add_a_df(DF_HALF, pws->h[5],  pwt->h[5]);
 854    pwd->h[6]  = msa_add_a_df(DF_HALF, pws->h[6],  pwt->h[6]);
 855    pwd->h[7]  = msa_add_a_df(DF_HALF, pws->h[7],  pwt->h[7]);
 856}
 857
 858void helper_msa_add_a_w(CPUMIPSState *env,
 859                        uint32_t wd, uint32_t ws, uint32_t wt)
 860{
 861    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 862    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 863    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 864
 865    pwd->w[0]  = msa_add_a_df(DF_WORD, pws->w[0],  pwt->w[0]);
 866    pwd->w[1]  = msa_add_a_df(DF_WORD, pws->w[1],  pwt->w[1]);
 867    pwd->w[2]  = msa_add_a_df(DF_WORD, pws->w[2],  pwt->w[2]);
 868    pwd->w[3]  = msa_add_a_df(DF_WORD, pws->w[3],  pwt->w[3]);
 869}
 870
 871void helper_msa_add_a_d(CPUMIPSState *env,
 872                        uint32_t wd, uint32_t ws, uint32_t wt)
 873{
 874    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 875    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 876    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 877
 878    pwd->d[0]  = msa_add_a_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
 879    pwd->d[1]  = msa_add_a_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
 880}
 881
 882
 883static inline int64_t msa_adds_a_df(uint32_t df, int64_t arg1, int64_t arg2)
 884{
 885    uint64_t max_int = (uint64_t)DF_MAX_INT(df);
 886    uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
 887    uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
 888    if (abs_arg1 > max_int || abs_arg2 > max_int) {
 889        return (int64_t)max_int;
 890    } else {
 891        return (abs_arg1 < max_int - abs_arg2) ? abs_arg1 + abs_arg2 : max_int;
 892    }
 893}
 894
 895void helper_msa_adds_a_b(CPUMIPSState *env,
 896                         uint32_t wd, uint32_t ws, uint32_t wt)
 897{
 898    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 899    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 900    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 901
 902    pwd->b[0]  = msa_adds_a_df(DF_BYTE, pws->b[0],  pwt->b[0]);
 903    pwd->b[1]  = msa_adds_a_df(DF_BYTE, pws->b[1],  pwt->b[1]);
 904    pwd->b[2]  = msa_adds_a_df(DF_BYTE, pws->b[2],  pwt->b[2]);
 905    pwd->b[3]  = msa_adds_a_df(DF_BYTE, pws->b[3],  pwt->b[3]);
 906    pwd->b[4]  = msa_adds_a_df(DF_BYTE, pws->b[4],  pwt->b[4]);
 907    pwd->b[5]  = msa_adds_a_df(DF_BYTE, pws->b[5],  pwt->b[5]);
 908    pwd->b[6]  = msa_adds_a_df(DF_BYTE, pws->b[6],  pwt->b[6]);
 909    pwd->b[7]  = msa_adds_a_df(DF_BYTE, pws->b[7],  pwt->b[7]);
 910    pwd->b[8]  = msa_adds_a_df(DF_BYTE, pws->b[8],  pwt->b[8]);
 911    pwd->b[9]  = msa_adds_a_df(DF_BYTE, pws->b[9],  pwt->b[9]);
 912    pwd->b[10] = msa_adds_a_df(DF_BYTE, pws->b[10], pwt->b[10]);
 913    pwd->b[11] = msa_adds_a_df(DF_BYTE, pws->b[11], pwt->b[11]);
 914    pwd->b[12] = msa_adds_a_df(DF_BYTE, pws->b[12], pwt->b[12]);
 915    pwd->b[13] = msa_adds_a_df(DF_BYTE, pws->b[13], pwt->b[13]);
 916    pwd->b[14] = msa_adds_a_df(DF_BYTE, pws->b[14], pwt->b[14]);
 917    pwd->b[15] = msa_adds_a_df(DF_BYTE, pws->b[15], pwt->b[15]);
 918}
 919
 920void helper_msa_adds_a_h(CPUMIPSState *env,
 921                         uint32_t wd, uint32_t ws, uint32_t wt)
 922{
 923    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 924    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 925    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 926
 927    pwd->h[0]  = msa_adds_a_df(DF_HALF, pws->h[0],  pwt->h[0]);
 928    pwd->h[1]  = msa_adds_a_df(DF_HALF, pws->h[1],  pwt->h[1]);
 929    pwd->h[2]  = msa_adds_a_df(DF_HALF, pws->h[2],  pwt->h[2]);
 930    pwd->h[3]  = msa_adds_a_df(DF_HALF, pws->h[3],  pwt->h[3]);
 931    pwd->h[4]  = msa_adds_a_df(DF_HALF, pws->h[4],  pwt->h[4]);
 932    pwd->h[5]  = msa_adds_a_df(DF_HALF, pws->h[5],  pwt->h[5]);
 933    pwd->h[6]  = msa_adds_a_df(DF_HALF, pws->h[6],  pwt->h[6]);
 934    pwd->h[7]  = msa_adds_a_df(DF_HALF, pws->h[7],  pwt->h[7]);
 935}
 936
 937void helper_msa_adds_a_w(CPUMIPSState *env,
 938                         uint32_t wd, uint32_t ws, uint32_t wt)
 939{
 940    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 941    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 942    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 943
 944    pwd->w[0]  = msa_adds_a_df(DF_WORD, pws->w[0],  pwt->w[0]);
 945    pwd->w[1]  = msa_adds_a_df(DF_WORD, pws->w[1],  pwt->w[1]);
 946    pwd->w[2]  = msa_adds_a_df(DF_WORD, pws->w[2],  pwt->w[2]);
 947    pwd->w[3]  = msa_adds_a_df(DF_WORD, pws->w[3],  pwt->w[3]);
 948}
 949
 950void helper_msa_adds_a_d(CPUMIPSState *env,
 951                         uint32_t wd, uint32_t ws, uint32_t wt)
 952{
 953    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 954    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 955    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 956
 957    pwd->d[0]  = msa_adds_a_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
 958    pwd->d[1]  = msa_adds_a_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
 959}
 960
 961
 962static inline int64_t msa_adds_s_df(uint32_t df, int64_t arg1, int64_t arg2)
 963{
 964    int64_t max_int = DF_MAX_INT(df);
 965    int64_t min_int = DF_MIN_INT(df);
 966    if (arg1 < 0) {
 967        return (min_int - arg1 < arg2) ? arg1 + arg2 : min_int;
 968    } else {
 969        return (arg2 < max_int - arg1) ? arg1 + arg2 : max_int;
 970    }
 971}
 972
 973void helper_msa_adds_s_b(CPUMIPSState *env,
 974                         uint32_t wd, uint32_t ws, uint32_t wt)
 975{
 976    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 977    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
 978    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
 979
 980    pwd->b[0]  = msa_adds_s_df(DF_BYTE, pws->b[0],  pwt->b[0]);
 981    pwd->b[1]  = msa_adds_s_df(DF_BYTE, pws->b[1],  pwt->b[1]);
 982    pwd->b[2]  = msa_adds_s_df(DF_BYTE, pws->b[2],  pwt->b[2]);
 983    pwd->b[3]  = msa_adds_s_df(DF_BYTE, pws->b[3],  pwt->b[3]);
 984    pwd->b[4]  = msa_adds_s_df(DF_BYTE, pws->b[4],  pwt->b[4]);
 985    pwd->b[5]  = msa_adds_s_df(DF_BYTE, pws->b[5],  pwt->b[5]);
 986    pwd->b[6]  = msa_adds_s_df(DF_BYTE, pws->b[6],  pwt->b[6]);
 987    pwd->b[7]  = msa_adds_s_df(DF_BYTE, pws->b[7],  pwt->b[7]);
 988    pwd->b[8]  = msa_adds_s_df(DF_BYTE, pws->b[8],  pwt->b[8]);
 989    pwd->b[9]  = msa_adds_s_df(DF_BYTE, pws->b[9],  pwt->b[9]);
 990    pwd->b[10] = msa_adds_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
 991    pwd->b[11] = msa_adds_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
 992    pwd->b[12] = msa_adds_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
 993    pwd->b[13] = msa_adds_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
 994    pwd->b[14] = msa_adds_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
 995    pwd->b[15] = msa_adds_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
 996}
 997
 998void helper_msa_adds_s_h(CPUMIPSState *env,
 999                         uint32_t wd, uint32_t ws, uint32_t wt)
1000{
1001    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1002    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1003    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1004
1005    pwd->h[0]  = msa_adds_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
1006    pwd->h[1]  = msa_adds_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
1007    pwd->h[2]  = msa_adds_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
1008    pwd->h[3]  = msa_adds_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
1009    pwd->h[4]  = msa_adds_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
1010    pwd->h[5]  = msa_adds_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
1011    pwd->h[6]  = msa_adds_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
1012    pwd->h[7]  = msa_adds_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
1013}
1014
1015void helper_msa_adds_s_w(CPUMIPSState *env,
1016                         uint32_t wd, uint32_t ws, uint32_t wt)
1017{
1018    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1019    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1020    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1021
1022    pwd->w[0]  = msa_adds_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
1023    pwd->w[1]  = msa_adds_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
1024    pwd->w[2]  = msa_adds_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
1025    pwd->w[3]  = msa_adds_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
1026}
1027
1028void helper_msa_adds_s_d(CPUMIPSState *env,
1029                         uint32_t wd, uint32_t ws, uint32_t wt)
1030{
1031    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1032    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1033    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1034
1035    pwd->d[0]  = msa_adds_s_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
1036    pwd->d[1]  = msa_adds_s_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
1037}
1038
1039
1040static inline uint64_t msa_adds_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
1041{
1042    uint64_t max_uint = DF_MAX_UINT(df);
1043    uint64_t u_arg1 = UNSIGNED(arg1, df);
1044    uint64_t u_arg2 = UNSIGNED(arg2, df);
1045    return (u_arg1 < max_uint - u_arg2) ? u_arg1 + u_arg2 : max_uint;
1046}
1047
1048void helper_msa_adds_u_b(CPUMIPSState *env,
1049                         uint32_t wd, uint32_t ws, uint32_t wt)
1050{
1051    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1052    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1053    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1054
1055    pwd->b[0]  = msa_adds_u_df(DF_BYTE, pws->b[0],  pwt->b[0]);
1056    pwd->b[1]  = msa_adds_u_df(DF_BYTE, pws->b[1],  pwt->b[1]);
1057    pwd->b[2]  = msa_adds_u_df(DF_BYTE, pws->b[2],  pwt->b[2]);
1058    pwd->b[3]  = msa_adds_u_df(DF_BYTE, pws->b[3],  pwt->b[3]);
1059    pwd->b[4]  = msa_adds_u_df(DF_BYTE, pws->b[4],  pwt->b[4]);
1060    pwd->b[5]  = msa_adds_u_df(DF_BYTE, pws->b[5],  pwt->b[5]);
1061    pwd->b[6]  = msa_adds_u_df(DF_BYTE, pws->b[6],  pwt->b[6]);
1062    pwd->b[7]  = msa_adds_u_df(DF_BYTE, pws->b[7],  pwt->b[7]);
1063    pwd->b[8]  = msa_adds_u_df(DF_BYTE, pws->b[8],  pwt->b[8]);
1064    pwd->b[9]  = msa_adds_u_df(DF_BYTE, pws->b[9],  pwt->b[9]);
1065    pwd->b[10] = msa_adds_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
1066    pwd->b[11] = msa_adds_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
1067    pwd->b[12] = msa_adds_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
1068    pwd->b[13] = msa_adds_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
1069    pwd->b[14] = msa_adds_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
1070    pwd->b[15] = msa_adds_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
1071}
1072
1073void helper_msa_adds_u_h(CPUMIPSState *env,
1074                         uint32_t wd, uint32_t ws, uint32_t wt)
1075{
1076    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1077    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1078    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1079
1080    pwd->h[0]  = msa_adds_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
1081    pwd->h[1]  = msa_adds_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
1082    pwd->h[2]  = msa_adds_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
1083    pwd->h[3]  = msa_adds_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
1084    pwd->h[4]  = msa_adds_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
1085    pwd->h[5]  = msa_adds_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
1086    pwd->h[6]  = msa_adds_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
1087    pwd->h[7]  = msa_adds_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
1088}
1089
1090void helper_msa_adds_u_w(CPUMIPSState *env,
1091                         uint32_t wd, uint32_t ws, uint32_t wt)
1092{
1093    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1094    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1095    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1096
1097    pwd->w[0]  = msa_adds_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
1098    pwd->w[1]  = msa_adds_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
1099    pwd->w[2]  = msa_adds_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
1100    pwd->w[3]  = msa_adds_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
1101}
1102
1103void helper_msa_adds_u_d(CPUMIPSState *env,
1104                         uint32_t wd, uint32_t ws, uint32_t wt)
1105{
1106    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1107    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1108    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1109
1110    pwd->d[0]  = msa_adds_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
1111    pwd->d[1]  = msa_adds_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
1112}
1113
1114
1115static inline int64_t msa_addv_df(uint32_t df, int64_t arg1, int64_t arg2)
1116{
1117    return arg1 + arg2;
1118}
1119
1120void helper_msa_addv_b(CPUMIPSState *env,
1121                       uint32_t wd, uint32_t ws, uint32_t wt)
1122{
1123    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1124    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1125    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1126
1127    pwd->b[0]  = msa_addv_df(DF_BYTE, pws->b[0],  pwt->b[0]);
1128    pwd->b[1]  = msa_addv_df(DF_BYTE, pws->b[1],  pwt->b[1]);
1129    pwd->b[2]  = msa_addv_df(DF_BYTE, pws->b[2],  pwt->b[2]);
1130    pwd->b[3]  = msa_addv_df(DF_BYTE, pws->b[3],  pwt->b[3]);
1131    pwd->b[4]  = msa_addv_df(DF_BYTE, pws->b[4],  pwt->b[4]);
1132    pwd->b[5]  = msa_addv_df(DF_BYTE, pws->b[5],  pwt->b[5]);
1133    pwd->b[6]  = msa_addv_df(DF_BYTE, pws->b[6],  pwt->b[6]);
1134    pwd->b[7]  = msa_addv_df(DF_BYTE, pws->b[7],  pwt->b[7]);
1135    pwd->b[8]  = msa_addv_df(DF_BYTE, pws->b[8],  pwt->b[8]);
1136    pwd->b[9]  = msa_addv_df(DF_BYTE, pws->b[9],  pwt->b[9]);
1137    pwd->b[10] = msa_addv_df(DF_BYTE, pws->b[10], pwt->b[10]);
1138    pwd->b[11] = msa_addv_df(DF_BYTE, pws->b[11], pwt->b[11]);
1139    pwd->b[12] = msa_addv_df(DF_BYTE, pws->b[12], pwt->b[12]);
1140    pwd->b[13] = msa_addv_df(DF_BYTE, pws->b[13], pwt->b[13]);
1141    pwd->b[14] = msa_addv_df(DF_BYTE, pws->b[14], pwt->b[14]);
1142    pwd->b[15] = msa_addv_df(DF_BYTE, pws->b[15], pwt->b[15]);
1143}
1144
1145void helper_msa_addv_h(CPUMIPSState *env,
1146                       uint32_t wd, uint32_t ws, uint32_t wt)
1147{
1148    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1149    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1150    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1151
1152    pwd->h[0]  = msa_addv_df(DF_HALF, pws->h[0],  pwt->h[0]);
1153    pwd->h[1]  = msa_addv_df(DF_HALF, pws->h[1],  pwt->h[1]);
1154    pwd->h[2]  = msa_addv_df(DF_HALF, pws->h[2],  pwt->h[2]);
1155    pwd->h[3]  = msa_addv_df(DF_HALF, pws->h[3],  pwt->h[3]);
1156    pwd->h[4]  = msa_addv_df(DF_HALF, pws->h[4],  pwt->h[4]);
1157    pwd->h[5]  = msa_addv_df(DF_HALF, pws->h[5],  pwt->h[5]);
1158    pwd->h[6]  = msa_addv_df(DF_HALF, pws->h[6],  pwt->h[6]);
1159    pwd->h[7]  = msa_addv_df(DF_HALF, pws->h[7],  pwt->h[7]);
1160}
1161
1162void helper_msa_addv_w(CPUMIPSState *env,
1163                       uint32_t wd, uint32_t ws, uint32_t wt)
1164{
1165    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1166    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1167    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1168
1169    pwd->w[0]  = msa_addv_df(DF_WORD, pws->w[0],  pwt->w[0]);
1170    pwd->w[1]  = msa_addv_df(DF_WORD, pws->w[1],  pwt->w[1]);
1171    pwd->w[2]  = msa_addv_df(DF_WORD, pws->w[2],  pwt->w[2]);
1172    pwd->w[3]  = msa_addv_df(DF_WORD, pws->w[3],  pwt->w[3]);
1173}
1174
1175void helper_msa_addv_d(CPUMIPSState *env,
1176                       uint32_t wd, uint32_t ws, uint32_t wt)
1177{
1178    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1179    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1180    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1181
1182    pwd->d[0]  = msa_addv_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
1183    pwd->d[1]  = msa_addv_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
1184}
1185
1186
1187#define SIGNED_EVEN(a, df) \
1188        ((((int64_t)(a)) << (64 - DF_BITS(df) / 2)) >> (64 - DF_BITS(df) / 2))
1189
1190#define UNSIGNED_EVEN(a, df) \
1191        ((((uint64_t)(a)) << (64 - DF_BITS(df) / 2)) >> (64 - DF_BITS(df) / 2))
1192
1193#define SIGNED_ODD(a, df) \
1194        ((((int64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df) / 2))
1195
1196#define UNSIGNED_ODD(a, df) \
1197        ((((uint64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df) / 2))
1198
1199
1200static inline int64_t msa_hadd_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1201{
1202    return SIGNED_ODD(arg1, df) + SIGNED_EVEN(arg2, df);
1203}
1204
1205void helper_msa_hadd_s_h(CPUMIPSState *env,
1206                         uint32_t wd, uint32_t ws, uint32_t wt)
1207{
1208    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1209    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1210    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1211
1212    pwd->h[0]  = msa_hadd_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
1213    pwd->h[1]  = msa_hadd_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
1214    pwd->h[2]  = msa_hadd_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
1215    pwd->h[3]  = msa_hadd_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
1216    pwd->h[4]  = msa_hadd_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
1217    pwd->h[5]  = msa_hadd_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
1218    pwd->h[6]  = msa_hadd_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
1219    pwd->h[7]  = msa_hadd_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
1220}
1221
1222void helper_msa_hadd_s_w(CPUMIPSState *env,
1223                         uint32_t wd, uint32_t ws, uint32_t wt)
1224{
1225    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1226    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1227    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1228
1229    pwd->w[0]  = msa_hadd_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
1230    pwd->w[1]  = msa_hadd_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
1231    pwd->w[2]  = msa_hadd_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
1232    pwd->w[3]  = msa_hadd_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
1233}
1234
1235void helper_msa_hadd_s_d(CPUMIPSState *env,
1236                         uint32_t wd, uint32_t ws, uint32_t wt)
1237{
1238    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1239    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1240    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1241
1242    pwd->d[0]  = msa_hadd_s_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
1243    pwd->d[1]  = msa_hadd_s_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
1244}
1245
1246
1247static inline int64_t msa_hadd_u_df(uint32_t df, int64_t arg1, int64_t arg2)
1248{
1249    return UNSIGNED_ODD(arg1, df) + UNSIGNED_EVEN(arg2, df);
1250}
1251
1252void helper_msa_hadd_u_h(CPUMIPSState *env,
1253                         uint32_t wd, uint32_t ws, uint32_t wt)
1254{
1255    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1256    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1257    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1258
1259    pwd->h[0]  = msa_hadd_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
1260    pwd->h[1]  = msa_hadd_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
1261    pwd->h[2]  = msa_hadd_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
1262    pwd->h[3]  = msa_hadd_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
1263    pwd->h[4]  = msa_hadd_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
1264    pwd->h[5]  = msa_hadd_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
1265    pwd->h[6]  = msa_hadd_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
1266    pwd->h[7]  = msa_hadd_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
1267}
1268
1269void helper_msa_hadd_u_w(CPUMIPSState *env,
1270                         uint32_t wd, uint32_t ws, uint32_t wt)
1271{
1272    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1273    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1274    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1275
1276    pwd->w[0]  = msa_hadd_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
1277    pwd->w[1]  = msa_hadd_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
1278    pwd->w[2]  = msa_hadd_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
1279    pwd->w[3]  = msa_hadd_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
1280}
1281
1282void helper_msa_hadd_u_d(CPUMIPSState *env,
1283                         uint32_t wd, uint32_t ws, uint32_t wt)
1284{
1285    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1286    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1287    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1288
1289    pwd->d[0]  = msa_hadd_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
1290    pwd->d[1]  = msa_hadd_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
1291}
1292
1293
1294/*
1295 * Int Average
1296 * -----------
1297 *
1298 * +---------------+----------------------------------------------------------+
1299 * | AVE_S.B       | Vector Signed Average (byte)                             |
1300 * | AVE_S.H       | Vector Signed Average (halfword)                         |
1301 * | AVE_S.W       | Vector Signed Average (word)                             |
1302 * | AVE_S.D       | Vector Signed Average (doubleword)                       |
1303 * | AVE_U.B       | Vector Unsigned Average (byte)                           |
1304 * | AVE_U.H       | Vector Unsigned Average (halfword)                       |
1305 * | AVE_U.W       | Vector Unsigned Average (word)                           |
1306 * | AVE_U.D       | Vector Unsigned Average (doubleword)                     |
1307 * | AVER_S.B      | Vector Signed Average Rounded (byte)                     |
1308 * | AVER_S.H      | Vector Signed Average Rounded (halfword)                 |
1309 * | AVER_S.W      | Vector Signed Average Rounded (word)                     |
1310 * | AVER_S.D      | Vector Signed Average Rounded (doubleword)               |
1311 * | AVER_U.B      | Vector Unsigned Average Rounded (byte)                   |
1312 * | AVER_U.H      | Vector Unsigned Average Rounded (halfword)               |
1313 * | AVER_U.W      | Vector Unsigned Average Rounded (word)                   |
1314 * | AVER_U.D      | Vector Unsigned Average Rounded (doubleword)             |
1315 * +---------------+----------------------------------------------------------+
1316 */
1317
1318static inline int64_t msa_ave_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1319{
1320    /* signed shift */
1321    return (arg1 >> 1) + (arg2 >> 1) + (arg1 & arg2 & 1);
1322}
1323
1324void helper_msa_ave_s_b(CPUMIPSState *env,
1325                        uint32_t wd, uint32_t ws, uint32_t wt)
1326{
1327    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1328    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1329    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1330
1331    pwd->b[0]  = msa_ave_s_df(DF_BYTE, pws->b[0],  pwt->b[0]);
1332    pwd->b[1]  = msa_ave_s_df(DF_BYTE, pws->b[1],  pwt->b[1]);
1333    pwd->b[2]  = msa_ave_s_df(DF_BYTE, pws->b[2],  pwt->b[2]);
1334    pwd->b[3]  = msa_ave_s_df(DF_BYTE, pws->b[3],  pwt->b[3]);
1335    pwd->b[4]  = msa_ave_s_df(DF_BYTE, pws->b[4],  pwt->b[4]);
1336    pwd->b[5]  = msa_ave_s_df(DF_BYTE, pws->b[5],  pwt->b[5]);
1337    pwd->b[6]  = msa_ave_s_df(DF_BYTE, pws->b[6],  pwt->b[6]);
1338    pwd->b[7]  = msa_ave_s_df(DF_BYTE, pws->b[7],  pwt->b[7]);
1339    pwd->b[8]  = msa_ave_s_df(DF_BYTE, pws->b[8],  pwt->b[8]);
1340    pwd->b[9]  = msa_ave_s_df(DF_BYTE, pws->b[9],  pwt->b[9]);
1341    pwd->b[10] = msa_ave_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
1342    pwd->b[11] = msa_ave_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
1343    pwd->b[12] = msa_ave_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
1344    pwd->b[13] = msa_ave_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
1345    pwd->b[14] = msa_ave_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
1346    pwd->b[15] = msa_ave_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
1347}
1348
1349void helper_msa_ave_s_h(CPUMIPSState *env,
1350                        uint32_t wd, uint32_t ws, uint32_t wt)
1351{
1352    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1353    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1354    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1355
1356    pwd->h[0]  = msa_ave_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
1357    pwd->h[1]  = msa_ave_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
1358    pwd->h[2]  = msa_ave_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
1359    pwd->h[3]  = msa_ave_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
1360    pwd->h[4]  = msa_ave_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
1361    pwd->h[5]  = msa_ave_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
1362    pwd->h[6]  = msa_ave_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
1363    pwd->h[7]  = msa_ave_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
1364}
1365
1366void helper_msa_ave_s_w(CPUMIPSState *env,
1367                        uint32_t wd, uint32_t ws, uint32_t wt)
1368{
1369    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1370    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1371    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1372
1373    pwd->w[0]  = msa_ave_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
1374    pwd->w[1]  = msa_ave_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
1375    pwd->w[2]  = msa_ave_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
1376    pwd->w[3]  = msa_ave_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
1377}
1378
1379void helper_msa_ave_s_d(CPUMIPSState *env,
1380                        uint32_t wd, uint32_t ws, uint32_t wt)
1381{
1382    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1383    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1384    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1385
1386    pwd->d[0]  = msa_ave_s_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
1387    pwd->d[1]  = msa_ave_s_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
1388}
1389
1390static inline uint64_t msa_ave_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
1391{
1392    uint64_t u_arg1 = UNSIGNED(arg1, df);
1393    uint64_t u_arg2 = UNSIGNED(arg2, df);
1394    /* unsigned shift */
1395    return (u_arg1 >> 1) + (u_arg2 >> 1) + (u_arg1 & u_arg2 & 1);
1396}
1397
1398void helper_msa_ave_u_b(CPUMIPSState *env,
1399                        uint32_t wd, uint32_t ws, uint32_t wt)
1400{
1401    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1402    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1403    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1404
1405    pwd->b[0]  = msa_ave_u_df(DF_BYTE, pws->b[0],  pwt->b[0]);
1406    pwd->b[1]  = msa_ave_u_df(DF_BYTE, pws->b[1],  pwt->b[1]);
1407    pwd->b[2]  = msa_ave_u_df(DF_BYTE, pws->b[2],  pwt->b[2]);
1408    pwd->b[3]  = msa_ave_u_df(DF_BYTE, pws->b[3],  pwt->b[3]);
1409    pwd->b[4]  = msa_ave_u_df(DF_BYTE, pws->b[4],  pwt->b[4]);
1410    pwd->b[5]  = msa_ave_u_df(DF_BYTE, pws->b[5],  pwt->b[5]);
1411    pwd->b[6]  = msa_ave_u_df(DF_BYTE, pws->b[6],  pwt->b[6]);
1412    pwd->b[7]  = msa_ave_u_df(DF_BYTE, pws->b[7],  pwt->b[7]);
1413    pwd->b[8]  = msa_ave_u_df(DF_BYTE, pws->b[8],  pwt->b[8]);
1414    pwd->b[9]  = msa_ave_u_df(DF_BYTE, pws->b[9],  pwt->b[9]);
1415    pwd->b[10] = msa_ave_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
1416    pwd->b[11] = msa_ave_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
1417    pwd->b[12] = msa_ave_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
1418    pwd->b[13] = msa_ave_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
1419    pwd->b[14] = msa_ave_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
1420    pwd->b[15] = msa_ave_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
1421}
1422
1423void helper_msa_ave_u_h(CPUMIPSState *env,
1424                        uint32_t wd, uint32_t ws, uint32_t wt)
1425{
1426    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1427    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1428    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1429
1430    pwd->h[0]  = msa_ave_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
1431    pwd->h[1]  = msa_ave_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
1432    pwd->h[2]  = msa_ave_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
1433    pwd->h[3]  = msa_ave_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
1434    pwd->h[4]  = msa_ave_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
1435    pwd->h[5]  = msa_ave_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
1436    pwd->h[6]  = msa_ave_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
1437    pwd->h[7]  = msa_ave_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
1438}
1439
1440void helper_msa_ave_u_w(CPUMIPSState *env,
1441                        uint32_t wd, uint32_t ws, uint32_t wt)
1442{
1443    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1444    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1445    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1446
1447    pwd->w[0]  = msa_ave_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
1448    pwd->w[1]  = msa_ave_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
1449    pwd->w[2]  = msa_ave_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
1450    pwd->w[3]  = msa_ave_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
1451}
1452
1453void helper_msa_ave_u_d(CPUMIPSState *env,
1454                        uint32_t wd, uint32_t ws, uint32_t wt)
1455{
1456    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1457    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1458    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1459
1460    pwd->d[0]  = msa_ave_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
1461    pwd->d[1]  = msa_ave_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
1462}
1463
1464static inline int64_t msa_aver_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1465{
1466    /* signed shift */
1467    return (arg1 >> 1) + (arg2 >> 1) + ((arg1 | arg2) & 1);
1468}
1469
1470void helper_msa_aver_s_b(CPUMIPSState *env,
1471                         uint32_t wd, uint32_t ws, uint32_t wt)
1472{
1473    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1474    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1475    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1476
1477    pwd->b[0]  = msa_aver_s_df(DF_BYTE, pws->b[0],  pwt->b[0]);
1478    pwd->b[1]  = msa_aver_s_df(DF_BYTE, pws->b[1],  pwt->b[1]);
1479    pwd->b[2]  = msa_aver_s_df(DF_BYTE, pws->b[2],  pwt->b[2]);
1480    pwd->b[3]  = msa_aver_s_df(DF_BYTE, pws->b[3],  pwt->b[3]);
1481    pwd->b[4]  = msa_aver_s_df(DF_BYTE, pws->b[4],  pwt->b[4]);
1482    pwd->b[5]  = msa_aver_s_df(DF_BYTE, pws->b[5],  pwt->b[5]);
1483    pwd->b[6]  = msa_aver_s_df(DF_BYTE, pws->b[6],  pwt->b[6]);
1484    pwd->b[7]  = msa_aver_s_df(DF_BYTE, pws->b[7],  pwt->b[7]);
1485    pwd->b[8]  = msa_aver_s_df(DF_BYTE, pws->b[8],  pwt->b[8]);
1486    pwd->b[9]  = msa_aver_s_df(DF_BYTE, pws->b[9],  pwt->b[9]);
1487    pwd->b[10] = msa_aver_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
1488    pwd->b[11] = msa_aver_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
1489    pwd->b[12] = msa_aver_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
1490    pwd->b[13] = msa_aver_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
1491    pwd->b[14] = msa_aver_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
1492    pwd->b[15] = msa_aver_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
1493}
1494
1495void helper_msa_aver_s_h(CPUMIPSState *env,
1496                         uint32_t wd, uint32_t ws, uint32_t wt)
1497{
1498    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1499    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1500    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1501
1502    pwd->h[0]  = msa_aver_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
1503    pwd->h[1]  = msa_aver_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
1504    pwd->h[2]  = msa_aver_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
1505    pwd->h[3]  = msa_aver_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
1506    pwd->h[4]  = msa_aver_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
1507    pwd->h[5]  = msa_aver_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
1508    pwd->h[6]  = msa_aver_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
1509    pwd->h[7]  = msa_aver_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
1510}
1511
1512void helper_msa_aver_s_w(CPUMIPSState *env,
1513                         uint32_t wd, uint32_t ws, uint32_t wt)
1514{
1515    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1516    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1517    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1518
1519    pwd->w[0]  = msa_aver_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
1520    pwd->w[1]  = msa_aver_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
1521    pwd->w[2]  = msa_aver_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
1522    pwd->w[3]  = msa_aver_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
1523}
1524
1525void helper_msa_aver_s_d(CPUMIPSState *env,
1526                         uint32_t wd, uint32_t ws, uint32_t wt)
1527{
1528    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1529    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1530    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1531
1532    pwd->d[0]  = msa_aver_s_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
1533    pwd->d[1]  = msa_aver_s_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
1534}
1535
1536static inline uint64_t msa_aver_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
1537{
1538    uint64_t u_arg1 = UNSIGNED(arg1, df);
1539    uint64_t u_arg2 = UNSIGNED(arg2, df);
1540    /* unsigned shift */
1541    return (u_arg1 >> 1) + (u_arg2 >> 1) + ((u_arg1 | u_arg2) & 1);
1542}
1543
1544void helper_msa_aver_u_b(CPUMIPSState *env,
1545                         uint32_t wd, uint32_t ws, uint32_t wt)
1546{
1547    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1548    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1549    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1550
1551    pwd->b[0]  = msa_aver_u_df(DF_BYTE, pws->b[0],  pwt->b[0]);
1552    pwd->b[1]  = msa_aver_u_df(DF_BYTE, pws->b[1],  pwt->b[1]);
1553    pwd->b[2]  = msa_aver_u_df(DF_BYTE, pws->b[2],  pwt->b[2]);
1554    pwd->b[3]  = msa_aver_u_df(DF_BYTE, pws->b[3],  pwt->b[3]);
1555    pwd->b[4]  = msa_aver_u_df(DF_BYTE, pws->b[4],  pwt->b[4]);
1556    pwd->b[5]  = msa_aver_u_df(DF_BYTE, pws->b[5],  pwt->b[5]);
1557    pwd->b[6]  = msa_aver_u_df(DF_BYTE, pws->b[6],  pwt->b[6]);
1558    pwd->b[7]  = msa_aver_u_df(DF_BYTE, pws->b[7],  pwt->b[7]);
1559    pwd->b[8]  = msa_aver_u_df(DF_BYTE, pws->b[8],  pwt->b[8]);
1560    pwd->b[9]  = msa_aver_u_df(DF_BYTE, pws->b[9],  pwt->b[9]);
1561    pwd->b[10] = msa_aver_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
1562    pwd->b[11] = msa_aver_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
1563    pwd->b[12] = msa_aver_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
1564    pwd->b[13] = msa_aver_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
1565    pwd->b[14] = msa_aver_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
1566    pwd->b[15] = msa_aver_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
1567}
1568
1569void helper_msa_aver_u_h(CPUMIPSState *env,
1570                         uint32_t wd, uint32_t ws, uint32_t wt)
1571{
1572    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1573    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1574    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1575
1576    pwd->h[0]  = msa_aver_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
1577    pwd->h[1]  = msa_aver_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
1578    pwd->h[2]  = msa_aver_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
1579    pwd->h[3]  = msa_aver_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
1580    pwd->h[4]  = msa_aver_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
1581    pwd->h[5]  = msa_aver_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
1582    pwd->h[6]  = msa_aver_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
1583    pwd->h[7]  = msa_aver_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
1584}
1585
1586void helper_msa_aver_u_w(CPUMIPSState *env,
1587                         uint32_t wd, uint32_t ws, uint32_t wt)
1588{
1589    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1590    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1591    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1592
1593    pwd->w[0]  = msa_aver_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
1594    pwd->w[1]  = msa_aver_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
1595    pwd->w[2]  = msa_aver_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
1596    pwd->w[3]  = msa_aver_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
1597}
1598
1599void helper_msa_aver_u_d(CPUMIPSState *env,
1600                         uint32_t wd, uint32_t ws, uint32_t wt)
1601{
1602    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1603    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1604    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1605
1606    pwd->d[0]  = msa_aver_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
1607    pwd->d[1]  = msa_aver_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
1608}
1609
1610
1611/*
1612 * Int Compare
1613 * -----------
1614 *
1615 * +---------------+----------------------------------------------------------+
1616 * | CEQ.B         | Vector Compare Equal (byte)                              |
1617 * | CEQ.H         | Vector Compare Equal (halfword)                          |
1618 * | CEQ.W         | Vector Compare Equal (word)                              |
1619 * | CEQ.D         | Vector Compare Equal (doubleword)                        |
1620 * | CLE_S.B       | Vector Compare Signed Less Than or Equal (byte)          |
1621 * | CLE_S.H       | Vector Compare Signed Less Than or Equal (halfword)      |
1622 * | CLE_S.W       | Vector Compare Signed Less Than or Equal (word)          |
1623 * | CLE_S.D       | Vector Compare Signed Less Than or Equal (doubleword)    |
1624 * | CLE_U.B       | Vector Compare Unsigned Less Than or Equal (byte)        |
1625 * | CLE_U.H       | Vector Compare Unsigned Less Than or Equal (halfword)    |
1626 * | CLE_U.W       | Vector Compare Unsigned Less Than or Equal (word)        |
1627 * | CLE_U.D       | Vector Compare Unsigned Less Than or Equal (doubleword)  |
1628 * | CLT_S.B       | Vector Compare Signed Less Than (byte)                   |
1629 * | CLT_S.H       | Vector Compare Signed Less Than (halfword)               |
1630 * | CLT_S.W       | Vector Compare Signed Less Than (word)                   |
1631 * | CLT_S.D       | Vector Compare Signed Less Than (doubleword)             |
1632 * | CLT_U.B       | Vector Compare Unsigned Less Than (byte)                 |
1633 * | CLT_U.H       | Vector Compare Unsigned Less Than (halfword)             |
1634 * | CLT_U.W       | Vector Compare Unsigned Less Than (word)                 |
1635 * | CLT_U.D       | Vector Compare Unsigned Less Than (doubleword)           |
1636 * +---------------+----------------------------------------------------------+
1637 */
1638
1639static inline int64_t msa_ceq_df(uint32_t df, int64_t arg1, int64_t arg2)
1640{
1641    return arg1 == arg2 ? -1 : 0;
1642}
1643
1644static inline int8_t msa_ceq_b(int8_t arg1, int8_t arg2)
1645{
1646    return arg1 == arg2 ? -1 : 0;
1647}
1648
1649void helper_msa_ceq_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
1650{
1651    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1652    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1653    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1654
1655    pwd->b[0]  = msa_ceq_b(pws->b[0],  pwt->b[0]);
1656    pwd->b[1]  = msa_ceq_b(pws->b[1],  pwt->b[1]);
1657    pwd->b[2]  = msa_ceq_b(pws->b[2],  pwt->b[2]);
1658    pwd->b[3]  = msa_ceq_b(pws->b[3],  pwt->b[3]);
1659    pwd->b[4]  = msa_ceq_b(pws->b[4],  pwt->b[4]);
1660    pwd->b[5]  = msa_ceq_b(pws->b[5],  pwt->b[5]);
1661    pwd->b[6]  = msa_ceq_b(pws->b[6],  pwt->b[6]);
1662    pwd->b[7]  = msa_ceq_b(pws->b[7],  pwt->b[7]);
1663    pwd->b[8]  = msa_ceq_b(pws->b[8],  pwt->b[8]);
1664    pwd->b[9]  = msa_ceq_b(pws->b[9],  pwt->b[9]);
1665    pwd->b[10] = msa_ceq_b(pws->b[10], pwt->b[10]);
1666    pwd->b[11] = msa_ceq_b(pws->b[11], pwt->b[11]);
1667    pwd->b[12] = msa_ceq_b(pws->b[12], pwt->b[12]);
1668    pwd->b[13] = msa_ceq_b(pws->b[13], pwt->b[13]);
1669    pwd->b[14] = msa_ceq_b(pws->b[14], pwt->b[14]);
1670    pwd->b[15] = msa_ceq_b(pws->b[15], pwt->b[15]);
1671}
1672
1673static inline int16_t msa_ceq_h(int16_t arg1, int16_t arg2)
1674{
1675    return arg1 == arg2 ? -1 : 0;
1676}
1677
1678void helper_msa_ceq_h(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
1679{
1680    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1681    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1682    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1683
1684    pwd->h[0]  = msa_ceq_h(pws->h[0],  pwt->h[0]);
1685    pwd->h[1]  = msa_ceq_h(pws->h[1],  pwt->h[1]);
1686    pwd->h[2]  = msa_ceq_h(pws->h[2],  pwt->h[2]);
1687    pwd->h[3]  = msa_ceq_h(pws->h[3],  pwt->h[3]);
1688    pwd->h[4]  = msa_ceq_h(pws->h[4],  pwt->h[4]);
1689    pwd->h[5]  = msa_ceq_h(pws->h[5],  pwt->h[5]);
1690    pwd->h[6]  = msa_ceq_h(pws->h[6],  pwt->h[6]);
1691    pwd->h[7]  = msa_ceq_h(pws->h[7],  pwt->h[7]);
1692}
1693
1694static inline int32_t msa_ceq_w(int32_t arg1, int32_t arg2)
1695{
1696    return arg1 == arg2 ? -1 : 0;
1697}
1698
1699void helper_msa_ceq_w(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
1700{
1701    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1702    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1703    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1704
1705    pwd->w[0]  = msa_ceq_w(pws->w[0],  pwt->w[0]);
1706    pwd->w[1]  = msa_ceq_w(pws->w[1],  pwt->w[1]);
1707    pwd->w[2]  = msa_ceq_w(pws->w[2],  pwt->w[2]);
1708    pwd->w[3]  = msa_ceq_w(pws->w[3],  pwt->w[3]);
1709}
1710
1711static inline int64_t msa_ceq_d(int64_t arg1, int64_t arg2)
1712{
1713    return arg1 == arg2 ? -1 : 0;
1714}
1715
1716void helper_msa_ceq_d(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
1717{
1718    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1719    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1720    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1721
1722    pwd->d[0]  = msa_ceq_d(pws->d[0],  pwt->d[0]);
1723    pwd->d[1]  = msa_ceq_d(pws->d[1],  pwt->d[1]);
1724}
1725
1726static inline int64_t msa_cle_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1727{
1728    return arg1 <= arg2 ? -1 : 0;
1729}
1730
1731void helper_msa_cle_s_b(CPUMIPSState *env,
1732                        uint32_t wd, uint32_t ws, uint32_t wt)
1733{
1734    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1735    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1736    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1737
1738    pwd->b[0]  = msa_cle_s_df(DF_BYTE, pws->b[0],  pwt->b[0]);
1739    pwd->b[1]  = msa_cle_s_df(DF_BYTE, pws->b[1],  pwt->b[1]);
1740    pwd->b[2]  = msa_cle_s_df(DF_BYTE, pws->b[2],  pwt->b[2]);
1741    pwd->b[3]  = msa_cle_s_df(DF_BYTE, pws->b[3],  pwt->b[3]);
1742    pwd->b[4]  = msa_cle_s_df(DF_BYTE, pws->b[4],  pwt->b[4]);
1743    pwd->b[5]  = msa_cle_s_df(DF_BYTE, pws->b[5],  pwt->b[5]);
1744    pwd->b[6]  = msa_cle_s_df(DF_BYTE, pws->b[6],  pwt->b[6]);
1745    pwd->b[7]  = msa_cle_s_df(DF_BYTE, pws->b[7],  pwt->b[7]);
1746    pwd->b[8]  = msa_cle_s_df(DF_BYTE, pws->b[8],  pwt->b[8]);
1747    pwd->b[9]  = msa_cle_s_df(DF_BYTE, pws->b[9],  pwt->b[9]);
1748    pwd->b[10] = msa_cle_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
1749    pwd->b[11] = msa_cle_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
1750    pwd->b[12] = msa_cle_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
1751    pwd->b[13] = msa_cle_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
1752    pwd->b[14] = msa_cle_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
1753    pwd->b[15] = msa_cle_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
1754}
1755
1756void helper_msa_cle_s_h(CPUMIPSState *env,
1757                        uint32_t wd, uint32_t ws, uint32_t wt)
1758{
1759    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1760    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1761    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1762
1763    pwd->h[0]  = msa_cle_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
1764    pwd->h[1]  = msa_cle_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
1765    pwd->h[2]  = msa_cle_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
1766    pwd->h[3]  = msa_cle_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
1767    pwd->h[4]  = msa_cle_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
1768    pwd->h[5]  = msa_cle_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
1769    pwd->h[6]  = msa_cle_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
1770    pwd->h[7]  = msa_cle_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
1771}
1772
1773void helper_msa_cle_s_w(CPUMIPSState *env,
1774                        uint32_t wd, uint32_t ws, uint32_t wt)
1775{
1776    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1777    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1778    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1779
1780    pwd->w[0]  = msa_cle_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
1781    pwd->w[1]  = msa_cle_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
1782    pwd->w[2]  = msa_cle_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
1783    pwd->w[3]  = msa_cle_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
1784}
1785
1786void helper_msa_cle_s_d(CPUMIPSState *env,
1787                        uint32_t wd, uint32_t ws, uint32_t wt)
1788{
1789    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1790    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1791    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1792
1793    pwd->d[0]  = msa_cle_s_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
1794    pwd->d[1]  = msa_cle_s_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
1795}
1796
1797static inline int64_t msa_cle_u_df(uint32_t df, int64_t arg1, int64_t arg2)
1798{
1799    uint64_t u_arg1 = UNSIGNED(arg1, df);
1800    uint64_t u_arg2 = UNSIGNED(arg2, df);
1801    return u_arg1 <= u_arg2 ? -1 : 0;
1802}
1803
1804void helper_msa_cle_u_b(CPUMIPSState *env,
1805                        uint32_t wd, uint32_t ws, uint32_t wt)
1806{
1807    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1808    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1809    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1810
1811    pwd->b[0]  = msa_cle_u_df(DF_BYTE, pws->b[0],  pwt->b[0]);
1812    pwd->b[1]  = msa_cle_u_df(DF_BYTE, pws->b[1],  pwt->b[1]);
1813    pwd->b[2]  = msa_cle_u_df(DF_BYTE, pws->b[2],  pwt->b[2]);
1814    pwd->b[3]  = msa_cle_u_df(DF_BYTE, pws->b[3],  pwt->b[3]);
1815    pwd->b[4]  = msa_cle_u_df(DF_BYTE, pws->b[4],  pwt->b[4]);
1816    pwd->b[5]  = msa_cle_u_df(DF_BYTE, pws->b[5],  pwt->b[5]);
1817    pwd->b[6]  = msa_cle_u_df(DF_BYTE, pws->b[6],  pwt->b[6]);
1818    pwd->b[7]  = msa_cle_u_df(DF_BYTE, pws->b[7],  pwt->b[7]);
1819    pwd->b[8]  = msa_cle_u_df(DF_BYTE, pws->b[8],  pwt->b[8]);
1820    pwd->b[9]  = msa_cle_u_df(DF_BYTE, pws->b[9],  pwt->b[9]);
1821    pwd->b[10] = msa_cle_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
1822    pwd->b[11] = msa_cle_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
1823    pwd->b[12] = msa_cle_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
1824    pwd->b[13] = msa_cle_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
1825    pwd->b[14] = msa_cle_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
1826    pwd->b[15] = msa_cle_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
1827}
1828
1829void helper_msa_cle_u_h(CPUMIPSState *env,
1830                        uint32_t wd, uint32_t ws, uint32_t wt)
1831{
1832    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1833    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1834    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1835
1836    pwd->h[0]  = msa_cle_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
1837    pwd->h[1]  = msa_cle_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
1838    pwd->h[2]  = msa_cle_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
1839    pwd->h[3]  = msa_cle_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
1840    pwd->h[4]  = msa_cle_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
1841    pwd->h[5]  = msa_cle_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
1842    pwd->h[6]  = msa_cle_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
1843    pwd->h[7]  = msa_cle_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
1844}
1845
1846void helper_msa_cle_u_w(CPUMIPSState *env,
1847                        uint32_t wd, uint32_t ws, uint32_t wt)
1848{
1849    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1850    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1851    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1852
1853    pwd->w[0]  = msa_cle_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
1854    pwd->w[1]  = msa_cle_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
1855    pwd->w[2]  = msa_cle_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
1856    pwd->w[3]  = msa_cle_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
1857}
1858
1859void helper_msa_cle_u_d(CPUMIPSState *env,
1860                        uint32_t wd, uint32_t ws, uint32_t wt)
1861{
1862    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1863    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1864    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1865
1866    pwd->d[0]  = msa_cle_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
1867    pwd->d[1]  = msa_cle_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
1868}
1869
1870static inline int64_t msa_clt_s_df(uint32_t df, int64_t arg1, int64_t arg2)
1871{
1872    return arg1 < arg2 ? -1 : 0;
1873}
1874
1875static inline int8_t msa_clt_s_b(int8_t arg1, int8_t arg2)
1876{
1877    return arg1 < arg2 ? -1 : 0;
1878}
1879
1880void helper_msa_clt_s_b(CPUMIPSState *env,
1881                        uint32_t wd, uint32_t ws, uint32_t wt)
1882{
1883    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1884    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1885    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1886
1887    pwd->b[0]  = msa_clt_s_b(pws->b[0],  pwt->b[0]);
1888    pwd->b[1]  = msa_clt_s_b(pws->b[1],  pwt->b[1]);
1889    pwd->b[2]  = msa_clt_s_b(pws->b[2],  pwt->b[2]);
1890    pwd->b[3]  = msa_clt_s_b(pws->b[3],  pwt->b[3]);
1891    pwd->b[4]  = msa_clt_s_b(pws->b[4],  pwt->b[4]);
1892    pwd->b[5]  = msa_clt_s_b(pws->b[5],  pwt->b[5]);
1893    pwd->b[6]  = msa_clt_s_b(pws->b[6],  pwt->b[6]);
1894    pwd->b[7]  = msa_clt_s_b(pws->b[7],  pwt->b[7]);
1895    pwd->b[8]  = msa_clt_s_b(pws->b[8],  pwt->b[8]);
1896    pwd->b[9]  = msa_clt_s_b(pws->b[9],  pwt->b[9]);
1897    pwd->b[10] = msa_clt_s_b(pws->b[10], pwt->b[10]);
1898    pwd->b[11] = msa_clt_s_b(pws->b[11], pwt->b[11]);
1899    pwd->b[12] = msa_clt_s_b(pws->b[12], pwt->b[12]);
1900    pwd->b[13] = msa_clt_s_b(pws->b[13], pwt->b[13]);
1901    pwd->b[14] = msa_clt_s_b(pws->b[14], pwt->b[14]);
1902    pwd->b[15] = msa_clt_s_b(pws->b[15], pwt->b[15]);
1903}
1904
1905static inline int16_t msa_clt_s_h(int16_t arg1, int16_t arg2)
1906{
1907    return arg1 < arg2 ? -1 : 0;
1908}
1909
1910void helper_msa_clt_s_h(CPUMIPSState *env,
1911                        uint32_t wd, uint32_t ws, uint32_t wt)
1912{
1913    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1914    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1915    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1916
1917    pwd->h[0]  = msa_clt_s_h(pws->h[0],  pwt->h[0]);
1918    pwd->h[1]  = msa_clt_s_h(pws->h[1],  pwt->h[1]);
1919    pwd->h[2]  = msa_clt_s_h(pws->h[2],  pwt->h[2]);
1920    pwd->h[3]  = msa_clt_s_h(pws->h[3],  pwt->h[3]);
1921    pwd->h[4]  = msa_clt_s_h(pws->h[4],  pwt->h[4]);
1922    pwd->h[5]  = msa_clt_s_h(pws->h[5],  pwt->h[5]);
1923    pwd->h[6]  = msa_clt_s_h(pws->h[6],  pwt->h[6]);
1924    pwd->h[7]  = msa_clt_s_h(pws->h[7],  pwt->h[7]);
1925}
1926
1927static inline int32_t msa_clt_s_w(int32_t arg1, int32_t arg2)
1928{
1929    return arg1 < arg2 ? -1 : 0;
1930}
1931
1932void helper_msa_clt_s_w(CPUMIPSState *env,
1933                        uint32_t wd, uint32_t ws, uint32_t wt)
1934{
1935    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1936    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1937    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1938
1939    pwd->w[0]  = msa_clt_s_w(pws->w[0],  pwt->w[0]);
1940    pwd->w[1]  = msa_clt_s_w(pws->w[1],  pwt->w[1]);
1941    pwd->w[2]  = msa_clt_s_w(pws->w[2],  pwt->w[2]);
1942    pwd->w[3]  = msa_clt_s_w(pws->w[3],  pwt->w[3]);
1943}
1944
1945static inline int64_t msa_clt_s_d(int64_t arg1, int64_t arg2)
1946{
1947    return arg1 < arg2 ? -1 : 0;
1948}
1949
1950void helper_msa_clt_s_d(CPUMIPSState *env,
1951                        uint32_t wd, uint32_t ws, uint32_t wt)
1952{
1953    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1954    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1955    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1956
1957    pwd->d[0]  = msa_clt_s_d(pws->d[0],  pwt->d[0]);
1958    pwd->d[1]  = msa_clt_s_d(pws->d[1],  pwt->d[1]);
1959}
1960
1961static inline int64_t msa_clt_u_df(uint32_t df, int64_t arg1, int64_t arg2)
1962{
1963    uint64_t u_arg1 = UNSIGNED(arg1, df);
1964    uint64_t u_arg2 = UNSIGNED(arg2, df);
1965    return u_arg1 < u_arg2 ? -1 : 0;
1966}
1967
1968void helper_msa_clt_u_b(CPUMIPSState *env,
1969                        uint32_t wd, uint32_t ws, uint32_t wt)
1970{
1971    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1972    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1973    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1974
1975    pwd->b[0]  = msa_clt_u_df(DF_BYTE, pws->b[0],  pwt->b[0]);
1976    pwd->b[1]  = msa_clt_u_df(DF_BYTE, pws->b[1],  pwt->b[1]);
1977    pwd->b[2]  = msa_clt_u_df(DF_BYTE, pws->b[2],  pwt->b[2]);
1978    pwd->b[3]  = msa_clt_u_df(DF_BYTE, pws->b[3],  pwt->b[3]);
1979    pwd->b[4]  = msa_clt_u_df(DF_BYTE, pws->b[4],  pwt->b[4]);
1980    pwd->b[5]  = msa_clt_u_df(DF_BYTE, pws->b[5],  pwt->b[5]);
1981    pwd->b[6]  = msa_clt_u_df(DF_BYTE, pws->b[6],  pwt->b[6]);
1982    pwd->b[7]  = msa_clt_u_df(DF_BYTE, pws->b[7],  pwt->b[7]);
1983    pwd->b[8]  = msa_clt_u_df(DF_BYTE, pws->b[8],  pwt->b[8]);
1984    pwd->b[9]  = msa_clt_u_df(DF_BYTE, pws->b[9],  pwt->b[9]);
1985    pwd->b[10] = msa_clt_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
1986    pwd->b[11] = msa_clt_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
1987    pwd->b[12] = msa_clt_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
1988    pwd->b[13] = msa_clt_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
1989    pwd->b[14] = msa_clt_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
1990    pwd->b[15] = msa_clt_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
1991}
1992
1993void helper_msa_clt_u_h(CPUMIPSState *env,
1994                        uint32_t wd, uint32_t ws, uint32_t wt)
1995{
1996    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
1997    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
1998    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
1999
2000    pwd->h[0]  = msa_clt_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
2001    pwd->h[1]  = msa_clt_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
2002    pwd->h[2]  = msa_clt_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
2003    pwd->h[3]  = msa_clt_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
2004    pwd->h[4]  = msa_clt_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
2005    pwd->h[5]  = msa_clt_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
2006    pwd->h[6]  = msa_clt_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
2007    pwd->h[7]  = msa_clt_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
2008}
2009
2010void helper_msa_clt_u_w(CPUMIPSState *env,
2011                        uint32_t wd, uint32_t ws, uint32_t wt)
2012{
2013    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2014    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2015    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2016
2017    pwd->w[0]  = msa_clt_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
2018    pwd->w[1]  = msa_clt_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
2019    pwd->w[2]  = msa_clt_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
2020    pwd->w[3]  = msa_clt_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
2021}
2022
2023void helper_msa_clt_u_d(CPUMIPSState *env,
2024                        uint32_t wd, uint32_t ws, uint32_t wt)
2025{
2026    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2027    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2028    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2029
2030    pwd->d[0]  = msa_clt_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
2031    pwd->d[1]  = msa_clt_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
2032}
2033
2034
2035/*
2036 * Int Divide
2037 * ----------
2038 *
2039 * +---------------+----------------------------------------------------------+
2040 * | DIV_S.B       | Vector Signed Divide (byte)                              |
2041 * | DIV_S.H       | Vector Signed Divide (halfword)                          |
2042 * | DIV_S.W       | Vector Signed Divide (word)                              |
2043 * | DIV_S.D       | Vector Signed Divide (doubleword)                        |
2044 * | DIV_U.B       | Vector Unsigned Divide (byte)                            |
2045 * | DIV_U.H       | Vector Unsigned Divide (halfword)                        |
2046 * | DIV_U.W       | Vector Unsigned Divide (word)                            |
2047 * | DIV_U.D       | Vector Unsigned Divide (doubleword)                      |
2048 * +---------------+----------------------------------------------------------+
2049 */
2050
2051
2052static inline int64_t msa_div_s_df(uint32_t df, int64_t arg1, int64_t arg2)
2053{
2054    if (arg1 == DF_MIN_INT(df) && arg2 == -1) {
2055        return DF_MIN_INT(df);
2056    }
2057    return arg2 ? arg1 / arg2
2058                : arg1 >= 0 ? -1 : 1;
2059}
2060
2061void helper_msa_div_s_b(CPUMIPSState *env,
2062                        uint32_t wd, uint32_t ws, uint32_t wt)
2063{
2064    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2065    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2066    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2067
2068    pwd->b[0]  = msa_div_s_df(DF_BYTE, pws->b[0],  pwt->b[0]);
2069    pwd->b[1]  = msa_div_s_df(DF_BYTE, pws->b[1],  pwt->b[1]);
2070    pwd->b[2]  = msa_div_s_df(DF_BYTE, pws->b[2],  pwt->b[2]);
2071    pwd->b[3]  = msa_div_s_df(DF_BYTE, pws->b[3],  pwt->b[3]);
2072    pwd->b[4]  = msa_div_s_df(DF_BYTE, pws->b[4],  pwt->b[4]);
2073    pwd->b[5]  = msa_div_s_df(DF_BYTE, pws->b[5],  pwt->b[5]);
2074    pwd->b[6]  = msa_div_s_df(DF_BYTE, pws->b[6],  pwt->b[6]);
2075    pwd->b[7]  = msa_div_s_df(DF_BYTE, pws->b[7],  pwt->b[7]);
2076    pwd->b[8]  = msa_div_s_df(DF_BYTE, pws->b[8],  pwt->b[8]);
2077    pwd->b[9]  = msa_div_s_df(DF_BYTE, pws->b[9],  pwt->b[9]);
2078    pwd->b[10] = msa_div_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
2079    pwd->b[11] = msa_div_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
2080    pwd->b[12] = msa_div_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
2081    pwd->b[13] = msa_div_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
2082    pwd->b[14] = msa_div_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
2083    pwd->b[15] = msa_div_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
2084}
2085
2086void helper_msa_div_s_h(CPUMIPSState *env,
2087                        uint32_t wd, uint32_t ws, uint32_t wt)
2088{
2089    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2090    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2091    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2092
2093    pwd->h[0]  = msa_div_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
2094    pwd->h[1]  = msa_div_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
2095    pwd->h[2]  = msa_div_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
2096    pwd->h[3]  = msa_div_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
2097    pwd->h[4]  = msa_div_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
2098    pwd->h[5]  = msa_div_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
2099    pwd->h[6]  = msa_div_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
2100    pwd->h[7]  = msa_div_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
2101}
2102
2103void helper_msa_div_s_w(CPUMIPSState *env,
2104                        uint32_t wd, uint32_t ws, uint32_t wt)
2105{
2106    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2107    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2108    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2109
2110    pwd->w[0]  = msa_div_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
2111    pwd->w[1]  = msa_div_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
2112    pwd->w[2]  = msa_div_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
2113    pwd->w[3]  = msa_div_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
2114}
2115
2116void helper_msa_div_s_d(CPUMIPSState *env,
2117                        uint32_t wd, uint32_t ws, uint32_t wt)
2118{
2119    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2120    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2121    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2122
2123    pwd->d[0]  = msa_div_s_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
2124    pwd->d[1]  = msa_div_s_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
2125}
2126
2127static inline int64_t msa_div_u_df(uint32_t df, int64_t arg1, int64_t arg2)
2128{
2129    uint64_t u_arg1 = UNSIGNED(arg1, df);
2130    uint64_t u_arg2 = UNSIGNED(arg2, df);
2131    return arg2 ? u_arg1 / u_arg2 : -1;
2132}
2133
2134void helper_msa_div_u_b(CPUMIPSState *env,
2135                        uint32_t wd, uint32_t ws, uint32_t wt)
2136{
2137    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2138    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2139    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2140
2141    pwd->b[0]  = msa_div_u_df(DF_BYTE, pws->b[0],  pwt->b[0]);
2142    pwd->b[1]  = msa_div_u_df(DF_BYTE, pws->b[1],  pwt->b[1]);
2143    pwd->b[2]  = msa_div_u_df(DF_BYTE, pws->b[2],  pwt->b[2]);
2144    pwd->b[3]  = msa_div_u_df(DF_BYTE, pws->b[3],  pwt->b[3]);
2145    pwd->b[4]  = msa_div_u_df(DF_BYTE, pws->b[4],  pwt->b[4]);
2146    pwd->b[5]  = msa_div_u_df(DF_BYTE, pws->b[5],  pwt->b[5]);
2147    pwd->b[6]  = msa_div_u_df(DF_BYTE, pws->b[6],  pwt->b[6]);
2148    pwd->b[7]  = msa_div_u_df(DF_BYTE, pws->b[7],  pwt->b[7]);
2149    pwd->b[8]  = msa_div_u_df(DF_BYTE, pws->b[8],  pwt->b[8]);
2150    pwd->b[9]  = msa_div_u_df(DF_BYTE, pws->b[9],  pwt->b[9]);
2151    pwd->b[10] = msa_div_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
2152    pwd->b[11] = msa_div_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
2153    pwd->b[12] = msa_div_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
2154    pwd->b[13] = msa_div_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
2155    pwd->b[14] = msa_div_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
2156    pwd->b[15] = msa_div_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
2157}
2158
2159void helper_msa_div_u_h(CPUMIPSState *env,
2160                        uint32_t wd, uint32_t ws, uint32_t wt)
2161{
2162    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2163    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2164    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2165
2166    pwd->h[0]  = msa_div_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
2167    pwd->h[1]  = msa_div_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
2168    pwd->h[2]  = msa_div_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
2169    pwd->h[3]  = msa_div_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
2170    pwd->h[4]  = msa_div_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
2171    pwd->h[5]  = msa_div_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
2172    pwd->h[6]  = msa_div_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
2173    pwd->h[7]  = msa_div_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
2174}
2175
2176void helper_msa_div_u_w(CPUMIPSState *env,
2177                        uint32_t wd, uint32_t ws, uint32_t wt)
2178{
2179    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2180    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2181    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2182
2183    pwd->w[0]  = msa_div_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
2184    pwd->w[1]  = msa_div_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
2185    pwd->w[2]  = msa_div_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
2186    pwd->w[3]  = msa_div_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
2187}
2188
2189void helper_msa_div_u_d(CPUMIPSState *env,
2190                        uint32_t wd, uint32_t ws, uint32_t wt)
2191{
2192    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2193    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2194    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2195
2196    pwd->d[0]  = msa_div_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
2197    pwd->d[1]  = msa_div_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
2198}
2199
2200
2201/*
2202 * Int Dot Product
2203 * ---------------
2204 *
2205 * +---------------+----------------------------------------------------------+
2206 * | DOTP_S.H      | Vector Signed Dot Product (halfword)                     |
2207 * | DOTP_S.W      | Vector Signed Dot Product (word)                         |
2208 * | DOTP_S.D      | Vector Signed Dot Product (doubleword)                   |
2209 * | DOTP_U.H      | Vector Unsigned Dot Product (halfword)                   |
2210 * | DOTP_U.W      | Vector Unsigned Dot Product (word)                       |
2211 * | DOTP_U.D      | Vector Unsigned Dot Product (doubleword)                 |
2212 * | DPADD_S.H     | Vector Signed Dot Product (halfword)                     |
2213 * | DPADD_S.W     | Vector Signed Dot Product (word)                         |
2214 * | DPADD_S.D     | Vector Signed Dot Product (doubleword)                   |
2215 * | DPADD_U.H     | Vector Unsigned Dot Product (halfword)                   |
2216 * | DPADD_U.W     | Vector Unsigned Dot Product (word)                       |
2217 * | DPADD_U.D     | Vector Unsigned Dot Product (doubleword)                 |
2218 * | DPSUB_S.H     | Vector Signed Dot Product (halfword)                     |
2219 * | DPSUB_S.W     | Vector Signed Dot Product (word)                         |
2220 * | DPSUB_S.D     | Vector Signed Dot Product (doubleword)                   |
2221 * | DPSUB_U.H     | Vector Unsigned Dot Product (halfword)                   |
2222 * | DPSUB_U.W     | Vector Unsigned Dot Product (word)                       |
2223 * | DPSUB_U.D     | Vector Unsigned Dot Product (doubleword)                 |
2224 * +---------------+----------------------------------------------------------+
2225 */
2226
2227/* TODO: insert Int Dot Product group helpers here */
2228
2229
2230/*
2231 * Int Max Min
2232 * -----------
2233 *
2234 * +---------------+----------------------------------------------------------+
2235 * | MAX_A.B       | Vector Maximum Based on Absolute Value (byte)            |
2236 * | MAX_A.H       | Vector Maximum Based on Absolute Value (halfword)        |
2237 * | MAX_A.W       | Vector Maximum Based on Absolute Value (word)            |
2238 * | MAX_A.D       | Vector Maximum Based on Absolute Value (doubleword)      |
2239 * | MAX_S.B       | Vector Signed Maximum (byte)                             |
2240 * | MAX_S.H       | Vector Signed Maximum (halfword)                         |
2241 * | MAX_S.W       | Vector Signed Maximum (word)                             |
2242 * | MAX_S.D       | Vector Signed Maximum (doubleword)                       |
2243 * | MAX_U.B       | Vector Unsigned Maximum (byte)                           |
2244 * | MAX_U.H       | Vector Unsigned Maximum (halfword)                       |
2245 * | MAX_U.W       | Vector Unsigned Maximum (word)                           |
2246 * | MAX_U.D       | Vector Unsigned Maximum (doubleword)                     |
2247 * | MIN_A.B       | Vector Minimum Based on Absolute Value (byte)            |
2248 * | MIN_A.H       | Vector Minimum Based on Absolute Value (halfword)        |
2249 * | MIN_A.W       | Vector Minimum Based on Absolute Value (word)            |
2250 * | MIN_A.D       | Vector Minimum Based on Absolute Value (doubleword)      |
2251 * | MIN_S.B       | Vector Signed Minimum (byte)                             |
2252 * | MIN_S.H       | Vector Signed Minimum (halfword)                         |
2253 * | MIN_S.W       | Vector Signed Minimum (word)                             |
2254 * | MIN_S.D       | Vector Signed Minimum (doubleword)                       |
2255 * | MIN_U.B       | Vector Unsigned Minimum (byte)                           |
2256 * | MIN_U.H       | Vector Unsigned Minimum (halfword)                       |
2257 * | MIN_U.W       | Vector Unsigned Minimum (word)                           |
2258 * | MIN_U.D       | Vector Unsigned Minimum (doubleword)                     |
2259 * +---------------+----------------------------------------------------------+
2260 */
2261
2262static inline int64_t msa_max_a_df(uint32_t df, int64_t arg1, int64_t arg2)
2263{
2264    uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
2265    uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
2266    return abs_arg1 > abs_arg2 ? arg1 : arg2;
2267}
2268
2269void helper_msa_max_a_b(CPUMIPSState *env,
2270                        uint32_t wd, uint32_t ws, uint32_t wt)
2271{
2272    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2273    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2274    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2275
2276    pwd->b[0]  = msa_max_a_df(DF_BYTE, pws->b[0],  pwt->b[0]);
2277    pwd->b[1]  = msa_max_a_df(DF_BYTE, pws->b[1],  pwt->b[1]);
2278    pwd->b[2]  = msa_max_a_df(DF_BYTE, pws->b[2],  pwt->b[2]);
2279    pwd->b[3]  = msa_max_a_df(DF_BYTE, pws->b[3],  pwt->b[3]);
2280    pwd->b[4]  = msa_max_a_df(DF_BYTE, pws->b[4],  pwt->b[4]);
2281    pwd->b[5]  = msa_max_a_df(DF_BYTE, pws->b[5],  pwt->b[5]);
2282    pwd->b[6]  = msa_max_a_df(DF_BYTE, pws->b[6],  pwt->b[6]);
2283    pwd->b[7]  = msa_max_a_df(DF_BYTE, pws->b[7],  pwt->b[7]);
2284    pwd->b[8]  = msa_max_a_df(DF_BYTE, pws->b[8],  pwt->b[8]);
2285    pwd->b[9]  = msa_max_a_df(DF_BYTE, pws->b[9],  pwt->b[9]);
2286    pwd->b[10] = msa_max_a_df(DF_BYTE, pws->b[10], pwt->b[10]);
2287    pwd->b[11] = msa_max_a_df(DF_BYTE, pws->b[11], pwt->b[11]);
2288    pwd->b[12] = msa_max_a_df(DF_BYTE, pws->b[12], pwt->b[12]);
2289    pwd->b[13] = msa_max_a_df(DF_BYTE, pws->b[13], pwt->b[13]);
2290    pwd->b[14] = msa_max_a_df(DF_BYTE, pws->b[14], pwt->b[14]);
2291    pwd->b[15] = msa_max_a_df(DF_BYTE, pws->b[15], pwt->b[15]);
2292}
2293
2294void helper_msa_max_a_h(CPUMIPSState *env,
2295                        uint32_t wd, uint32_t ws, uint32_t wt)
2296{
2297    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2298    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2299    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2300
2301    pwd->h[0]  = msa_max_a_df(DF_HALF, pws->h[0],  pwt->h[0]);
2302    pwd->h[1]  = msa_max_a_df(DF_HALF, pws->h[1],  pwt->h[1]);
2303    pwd->h[2]  = msa_max_a_df(DF_HALF, pws->h[2],  pwt->h[2]);
2304    pwd->h[3]  = msa_max_a_df(DF_HALF, pws->h[3],  pwt->h[3]);
2305    pwd->h[4]  = msa_max_a_df(DF_HALF, pws->h[4],  pwt->h[4]);
2306    pwd->h[5]  = msa_max_a_df(DF_HALF, pws->h[5],  pwt->h[5]);
2307    pwd->h[6]  = msa_max_a_df(DF_HALF, pws->h[6],  pwt->h[6]);
2308    pwd->h[7]  = msa_max_a_df(DF_HALF, pws->h[7],  pwt->h[7]);
2309}
2310
2311void helper_msa_max_a_w(CPUMIPSState *env,
2312                        uint32_t wd, uint32_t ws, uint32_t wt)
2313{
2314    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2315    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2316    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2317
2318    pwd->w[0]  = msa_max_a_df(DF_WORD, pws->w[0],  pwt->w[0]);
2319    pwd->w[1]  = msa_max_a_df(DF_WORD, pws->w[1],  pwt->w[1]);
2320    pwd->w[2]  = msa_max_a_df(DF_WORD, pws->w[2],  pwt->w[2]);
2321    pwd->w[3]  = msa_max_a_df(DF_WORD, pws->w[3],  pwt->w[3]);
2322}
2323
2324void helper_msa_max_a_d(CPUMIPSState *env,
2325                        uint32_t wd, uint32_t ws, uint32_t wt)
2326{
2327    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2328    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2329    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2330
2331    pwd->d[0]  = msa_max_a_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
2332    pwd->d[1]  = msa_max_a_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
2333}
2334
2335
2336static inline int64_t msa_max_s_df(uint32_t df, int64_t arg1, int64_t arg2)
2337{
2338    return arg1 > arg2 ? arg1 : arg2;
2339}
2340
2341void helper_msa_max_s_b(CPUMIPSState *env,
2342                        uint32_t wd, uint32_t ws, uint32_t wt)
2343{
2344    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2345    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2346    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2347
2348    pwd->b[0]  = msa_max_s_df(DF_BYTE, pws->b[0],  pwt->b[0]);
2349    pwd->b[1]  = msa_max_s_df(DF_BYTE, pws->b[1],  pwt->b[1]);
2350    pwd->b[2]  = msa_max_s_df(DF_BYTE, pws->b[2],  pwt->b[2]);
2351    pwd->b[3]  = msa_max_s_df(DF_BYTE, pws->b[3],  pwt->b[3]);
2352    pwd->b[4]  = msa_max_s_df(DF_BYTE, pws->b[4],  pwt->b[4]);
2353    pwd->b[5]  = msa_max_s_df(DF_BYTE, pws->b[5],  pwt->b[5]);
2354    pwd->b[6]  = msa_max_s_df(DF_BYTE, pws->b[6],  pwt->b[6]);
2355    pwd->b[7]  = msa_max_s_df(DF_BYTE, pws->b[7],  pwt->b[7]);
2356    pwd->b[8]  = msa_max_s_df(DF_BYTE, pws->b[8],  pwt->b[8]);
2357    pwd->b[9]  = msa_max_s_df(DF_BYTE, pws->b[9],  pwt->b[9]);
2358    pwd->b[10] = msa_max_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
2359    pwd->b[11] = msa_max_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
2360    pwd->b[12] = msa_max_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
2361    pwd->b[13] = msa_max_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
2362    pwd->b[14] = msa_max_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
2363    pwd->b[15] = msa_max_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
2364}
2365
2366void helper_msa_max_s_h(CPUMIPSState *env,
2367                        uint32_t wd, uint32_t ws, uint32_t wt)
2368{
2369    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2370    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2371    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2372
2373    pwd->h[0]  = msa_max_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
2374    pwd->h[1]  = msa_max_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
2375    pwd->h[2]  = msa_max_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
2376    pwd->h[3]  = msa_max_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
2377    pwd->h[4]  = msa_max_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
2378    pwd->h[5]  = msa_max_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
2379    pwd->h[6]  = msa_max_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
2380    pwd->h[7]  = msa_max_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
2381}
2382
2383void helper_msa_max_s_w(CPUMIPSState *env,
2384                        uint32_t wd, uint32_t ws, uint32_t wt)
2385{
2386    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2387    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2388    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2389
2390    pwd->w[0]  = msa_max_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
2391    pwd->w[1]  = msa_max_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
2392    pwd->w[2]  = msa_max_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
2393    pwd->w[3]  = msa_max_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
2394}
2395
2396void helper_msa_max_s_d(CPUMIPSState *env,
2397                        uint32_t wd, uint32_t ws, uint32_t wt)
2398{
2399    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2400    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2401    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2402
2403    pwd->d[0]  = msa_max_s_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
2404    pwd->d[1]  = msa_max_s_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
2405}
2406
2407
2408static inline int64_t msa_max_u_df(uint32_t df, int64_t arg1, int64_t arg2)
2409{
2410    uint64_t u_arg1 = UNSIGNED(arg1, df);
2411    uint64_t u_arg2 = UNSIGNED(arg2, df);
2412    return u_arg1 > u_arg2 ? arg1 : arg2;
2413}
2414
2415void helper_msa_max_u_b(CPUMIPSState *env,
2416                        uint32_t wd, uint32_t ws, uint32_t wt)
2417{
2418    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2419    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2420    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2421
2422    pwd->b[0]  = msa_max_u_df(DF_BYTE, pws->b[0],  pwt->b[0]);
2423    pwd->b[1]  = msa_max_u_df(DF_BYTE, pws->b[1],  pwt->b[1]);
2424    pwd->b[2]  = msa_max_u_df(DF_BYTE, pws->b[2],  pwt->b[2]);
2425    pwd->b[3]  = msa_max_u_df(DF_BYTE, pws->b[3],  pwt->b[3]);
2426    pwd->b[4]  = msa_max_u_df(DF_BYTE, pws->b[4],  pwt->b[4]);
2427    pwd->b[5]  = msa_max_u_df(DF_BYTE, pws->b[5],  pwt->b[5]);
2428    pwd->b[6]  = msa_max_u_df(DF_BYTE, pws->b[6],  pwt->b[6]);
2429    pwd->b[7]  = msa_max_u_df(DF_BYTE, pws->b[7],  pwt->b[7]);
2430    pwd->b[8]  = msa_max_u_df(DF_BYTE, pws->b[8],  pwt->b[8]);
2431    pwd->b[9]  = msa_max_u_df(DF_BYTE, pws->b[9],  pwt->b[9]);
2432    pwd->b[10] = msa_max_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
2433    pwd->b[11] = msa_max_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
2434    pwd->b[12] = msa_max_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
2435    pwd->b[13] = msa_max_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
2436    pwd->b[14] = msa_max_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
2437    pwd->b[15] = msa_max_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
2438}
2439
2440void helper_msa_max_u_h(CPUMIPSState *env,
2441                        uint32_t wd, uint32_t ws, uint32_t wt)
2442{
2443    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2444    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2445    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2446
2447    pwd->h[0]  = msa_max_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
2448    pwd->h[1]  = msa_max_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
2449    pwd->h[2]  = msa_max_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
2450    pwd->h[3]  = msa_max_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
2451    pwd->h[4]  = msa_max_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
2452    pwd->h[5]  = msa_max_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
2453    pwd->h[6]  = msa_max_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
2454    pwd->h[7]  = msa_max_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
2455}
2456
2457void helper_msa_max_u_w(CPUMIPSState *env,
2458                        uint32_t wd, uint32_t ws, uint32_t wt)
2459{
2460    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2461    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2462    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2463
2464    pwd->w[0]  = msa_max_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
2465    pwd->w[1]  = msa_max_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
2466    pwd->w[2]  = msa_max_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
2467    pwd->w[3]  = msa_max_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
2468}
2469
2470void helper_msa_max_u_d(CPUMIPSState *env,
2471                        uint32_t wd, uint32_t ws, uint32_t wt)
2472{
2473    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2474    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2475    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2476
2477    pwd->d[0]  = msa_max_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
2478    pwd->d[1]  = msa_max_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
2479}
2480
2481
2482static inline int64_t msa_min_a_df(uint32_t df, int64_t arg1, int64_t arg2)
2483{
2484    uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1;
2485    uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2;
2486    return abs_arg1 < abs_arg2 ? arg1 : arg2;
2487}
2488
2489void helper_msa_min_a_b(CPUMIPSState *env,
2490                        uint32_t wd, uint32_t ws, uint32_t wt)
2491{
2492    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2493    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2494    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2495
2496    pwd->b[0]  = msa_min_a_df(DF_BYTE, pws->b[0],  pwt->b[0]);
2497    pwd->b[1]  = msa_min_a_df(DF_BYTE, pws->b[1],  pwt->b[1]);
2498    pwd->b[2]  = msa_min_a_df(DF_BYTE, pws->b[2],  pwt->b[2]);
2499    pwd->b[3]  = msa_min_a_df(DF_BYTE, pws->b[3],  pwt->b[3]);
2500    pwd->b[4]  = msa_min_a_df(DF_BYTE, pws->b[4],  pwt->b[4]);
2501    pwd->b[5]  = msa_min_a_df(DF_BYTE, pws->b[5],  pwt->b[5]);
2502    pwd->b[6]  = msa_min_a_df(DF_BYTE, pws->b[6],  pwt->b[6]);
2503    pwd->b[7]  = msa_min_a_df(DF_BYTE, pws->b[7],  pwt->b[7]);
2504    pwd->b[8]  = msa_min_a_df(DF_BYTE, pws->b[8],  pwt->b[8]);
2505    pwd->b[9]  = msa_min_a_df(DF_BYTE, pws->b[9],  pwt->b[9]);
2506    pwd->b[10] = msa_min_a_df(DF_BYTE, pws->b[10], pwt->b[10]);
2507    pwd->b[11] = msa_min_a_df(DF_BYTE, pws->b[11], pwt->b[11]);
2508    pwd->b[12] = msa_min_a_df(DF_BYTE, pws->b[12], pwt->b[12]);
2509    pwd->b[13] = msa_min_a_df(DF_BYTE, pws->b[13], pwt->b[13]);
2510    pwd->b[14] = msa_min_a_df(DF_BYTE, pws->b[14], pwt->b[14]);
2511    pwd->b[15] = msa_min_a_df(DF_BYTE, pws->b[15], pwt->b[15]);
2512}
2513
2514void helper_msa_min_a_h(CPUMIPSState *env,
2515                        uint32_t wd, uint32_t ws, uint32_t wt)
2516{
2517    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2518    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2519    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2520
2521    pwd->h[0]  = msa_min_a_df(DF_HALF, pws->h[0],  pwt->h[0]);
2522    pwd->h[1]  = msa_min_a_df(DF_HALF, pws->h[1],  pwt->h[1]);
2523    pwd->h[2]  = msa_min_a_df(DF_HALF, pws->h[2],  pwt->h[2]);
2524    pwd->h[3]  = msa_min_a_df(DF_HALF, pws->h[3],  pwt->h[3]);
2525    pwd->h[4]  = msa_min_a_df(DF_HALF, pws->h[4],  pwt->h[4]);
2526    pwd->h[5]  = msa_min_a_df(DF_HALF, pws->h[5],  pwt->h[5]);
2527    pwd->h[6]  = msa_min_a_df(DF_HALF, pws->h[6],  pwt->h[6]);
2528    pwd->h[7]  = msa_min_a_df(DF_HALF, pws->h[7],  pwt->h[7]);
2529}
2530
2531void helper_msa_min_a_w(CPUMIPSState *env,
2532                        uint32_t wd, uint32_t ws, uint32_t wt)
2533{
2534    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2535    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2536    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2537
2538    pwd->w[0]  = msa_min_a_df(DF_WORD, pws->w[0],  pwt->w[0]);
2539    pwd->w[1]  = msa_min_a_df(DF_WORD, pws->w[1],  pwt->w[1]);
2540    pwd->w[2]  = msa_min_a_df(DF_WORD, pws->w[2],  pwt->w[2]);
2541    pwd->w[3]  = msa_min_a_df(DF_WORD, pws->w[3],  pwt->w[3]);
2542}
2543
2544void helper_msa_min_a_d(CPUMIPSState *env,
2545                        uint32_t wd, uint32_t ws, uint32_t wt)
2546{
2547    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2548    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2549    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2550
2551    pwd->d[0]  = msa_min_a_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
2552    pwd->d[1]  = msa_min_a_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
2553}
2554
2555
2556static inline int64_t msa_min_s_df(uint32_t df, int64_t arg1, int64_t arg2)
2557{
2558    return arg1 < arg2 ? arg1 : arg2;
2559}
2560
2561void helper_msa_min_s_b(CPUMIPSState *env,
2562                        uint32_t wd, uint32_t ws, uint32_t wt)
2563{
2564    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2565    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2566    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2567
2568    pwd->b[0]  = msa_min_s_df(DF_BYTE, pws->b[0],  pwt->b[0]);
2569    pwd->b[1]  = msa_min_s_df(DF_BYTE, pws->b[1],  pwt->b[1]);
2570    pwd->b[2]  = msa_min_s_df(DF_BYTE, pws->b[2],  pwt->b[2]);
2571    pwd->b[3]  = msa_min_s_df(DF_BYTE, pws->b[3],  pwt->b[3]);
2572    pwd->b[4]  = msa_min_s_df(DF_BYTE, pws->b[4],  pwt->b[4]);
2573    pwd->b[5]  = msa_min_s_df(DF_BYTE, pws->b[5],  pwt->b[5]);
2574    pwd->b[6]  = msa_min_s_df(DF_BYTE, pws->b[6],  pwt->b[6]);
2575    pwd->b[7]  = msa_min_s_df(DF_BYTE, pws->b[7],  pwt->b[7]);
2576    pwd->b[8]  = msa_min_s_df(DF_BYTE, pws->b[8],  pwt->b[8]);
2577    pwd->b[9]  = msa_min_s_df(DF_BYTE, pws->b[9],  pwt->b[9]);
2578    pwd->b[10] = msa_min_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
2579    pwd->b[11] = msa_min_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
2580    pwd->b[12] = msa_min_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
2581    pwd->b[13] = msa_min_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
2582    pwd->b[14] = msa_min_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
2583    pwd->b[15] = msa_min_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
2584}
2585
2586void helper_msa_min_s_h(CPUMIPSState *env,
2587                        uint32_t wd, uint32_t ws, uint32_t wt)
2588{
2589    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2590    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2591    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2592
2593    pwd->h[0]  = msa_min_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
2594    pwd->h[1]  = msa_min_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
2595    pwd->h[2]  = msa_min_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
2596    pwd->h[3]  = msa_min_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
2597    pwd->h[4]  = msa_min_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
2598    pwd->h[5]  = msa_min_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
2599    pwd->h[6]  = msa_min_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
2600    pwd->h[7]  = msa_min_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
2601}
2602
2603void helper_msa_min_s_w(CPUMIPSState *env,
2604                        uint32_t wd, uint32_t ws, uint32_t wt)
2605{
2606    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2607    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2608    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2609
2610    pwd->w[0]  = msa_min_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
2611    pwd->w[1]  = msa_min_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
2612    pwd->w[2]  = msa_min_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
2613    pwd->w[3]  = msa_min_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
2614}
2615
2616void helper_msa_min_s_d(CPUMIPSState *env,
2617                        uint32_t wd, uint32_t ws, uint32_t wt)
2618{
2619    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2620    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2621    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2622
2623    pwd->d[0]  = msa_min_s_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
2624    pwd->d[1]  = msa_min_s_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
2625}
2626
2627
2628static inline int64_t msa_min_u_df(uint32_t df, int64_t arg1, int64_t arg2)
2629{
2630    uint64_t u_arg1 = UNSIGNED(arg1, df);
2631    uint64_t u_arg2 = UNSIGNED(arg2, df);
2632    return u_arg1 < u_arg2 ? arg1 : arg2;
2633}
2634
2635void helper_msa_min_u_b(CPUMIPSState *env,
2636                        uint32_t wd, uint32_t ws, uint32_t wt)
2637{
2638    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2639    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2640    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2641
2642    pwd->b[0]  = msa_min_u_df(DF_BYTE, pws->b[0],  pwt->b[0]);
2643    pwd->b[1]  = msa_min_u_df(DF_BYTE, pws->b[1],  pwt->b[1]);
2644    pwd->b[2]  = msa_min_u_df(DF_BYTE, pws->b[2],  pwt->b[2]);
2645    pwd->b[3]  = msa_min_u_df(DF_BYTE, pws->b[3],  pwt->b[3]);
2646    pwd->b[4]  = msa_min_u_df(DF_BYTE, pws->b[4],  pwt->b[4]);
2647    pwd->b[5]  = msa_min_u_df(DF_BYTE, pws->b[5],  pwt->b[5]);
2648    pwd->b[6]  = msa_min_u_df(DF_BYTE, pws->b[6],  pwt->b[6]);
2649    pwd->b[7]  = msa_min_u_df(DF_BYTE, pws->b[7],  pwt->b[7]);
2650    pwd->b[8]  = msa_min_u_df(DF_BYTE, pws->b[8],  pwt->b[8]);
2651    pwd->b[9]  = msa_min_u_df(DF_BYTE, pws->b[9],  pwt->b[9]);
2652    pwd->b[10] = msa_min_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
2653    pwd->b[11] = msa_min_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
2654    pwd->b[12] = msa_min_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
2655    pwd->b[13] = msa_min_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
2656    pwd->b[14] = msa_min_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
2657    pwd->b[15] = msa_min_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
2658}
2659
2660void helper_msa_min_u_h(CPUMIPSState *env,
2661                        uint32_t wd, uint32_t ws, uint32_t wt)
2662{
2663    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2664    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2665    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2666
2667    pwd->h[0]  = msa_min_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
2668    pwd->h[1]  = msa_min_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
2669    pwd->h[2]  = msa_min_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
2670    pwd->h[3]  = msa_min_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
2671    pwd->h[4]  = msa_min_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
2672    pwd->h[5]  = msa_min_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
2673    pwd->h[6]  = msa_min_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
2674    pwd->h[7]  = msa_min_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
2675}
2676
2677void helper_msa_min_u_w(CPUMIPSState *env,
2678                        uint32_t wd, uint32_t ws, uint32_t wt)
2679{
2680    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2681    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2682    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2683
2684    pwd->w[0]  = msa_min_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
2685    pwd->w[1]  = msa_min_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
2686    pwd->w[2]  = msa_min_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
2687    pwd->w[3]  = msa_min_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
2688}
2689
2690void helper_msa_min_u_d(CPUMIPSState *env,
2691                        uint32_t wd, uint32_t ws, uint32_t wt)
2692{
2693    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2694    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2695    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2696
2697    pwd->d[0]  = msa_min_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
2698    pwd->d[1]  = msa_min_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
2699}
2700
2701
2702/*
2703 * Int Modulo
2704 * ----------
2705 *
2706 * +---------------+----------------------------------------------------------+
2707 * | MOD_S.B       | Vector Signed Modulo (byte)                              |
2708 * | MOD_S.H       | Vector Signed Modulo (halfword)                          |
2709 * | MOD_S.W       | Vector Signed Modulo (word)                              |
2710 * | MOD_S.D       | Vector Signed Modulo (doubleword)                        |
2711 * | MOD_U.B       | Vector Unsigned Modulo (byte)                            |
2712 * | MOD_U.H       | Vector Unsigned Modulo (halfword)                        |
2713 * | MOD_U.W       | Vector Unsigned Modulo (word)                            |
2714 * | MOD_U.D       | Vector Unsigned Modulo (doubleword)                      |
2715 * +---------------+----------------------------------------------------------+
2716 */
2717
2718static inline int64_t msa_mod_s_df(uint32_t df, int64_t arg1, int64_t arg2)
2719{
2720    if (arg1 == DF_MIN_INT(df) && arg2 == -1) {
2721        return 0;
2722    }
2723    return arg2 ? arg1 % arg2 : arg1;
2724}
2725
2726void helper_msa_mod_s_b(CPUMIPSState *env,
2727                        uint32_t wd, uint32_t ws, uint32_t wt)
2728{
2729    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2730    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2731    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2732
2733    pwd->b[0]  = msa_mod_s_df(DF_BYTE, pws->b[0],  pwt->b[0]);
2734    pwd->b[1]  = msa_mod_s_df(DF_BYTE, pws->b[1],  pwt->b[1]);
2735    pwd->b[2]  = msa_mod_s_df(DF_BYTE, pws->b[2],  pwt->b[2]);
2736    pwd->b[3]  = msa_mod_s_df(DF_BYTE, pws->b[3],  pwt->b[3]);
2737    pwd->b[4]  = msa_mod_s_df(DF_BYTE, pws->b[4],  pwt->b[4]);
2738    pwd->b[5]  = msa_mod_s_df(DF_BYTE, pws->b[5],  pwt->b[5]);
2739    pwd->b[6]  = msa_mod_s_df(DF_BYTE, pws->b[6],  pwt->b[6]);
2740    pwd->b[7]  = msa_mod_s_df(DF_BYTE, pws->b[7],  pwt->b[7]);
2741    pwd->b[8]  = msa_mod_s_df(DF_BYTE, pws->b[8],  pwt->b[8]);
2742    pwd->b[9]  = msa_mod_s_df(DF_BYTE, pws->b[9],  pwt->b[9]);
2743    pwd->b[10] = msa_mod_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
2744    pwd->b[11] = msa_mod_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
2745    pwd->b[12] = msa_mod_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
2746    pwd->b[13] = msa_mod_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
2747    pwd->b[14] = msa_mod_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
2748    pwd->b[15] = msa_mod_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
2749}
2750
2751void helper_msa_mod_s_h(CPUMIPSState *env,
2752                        uint32_t wd, uint32_t ws, uint32_t wt)
2753{
2754    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2755    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2756    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2757
2758    pwd->h[0]  = msa_mod_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
2759    pwd->h[1]  = msa_mod_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
2760    pwd->h[2]  = msa_mod_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
2761    pwd->h[3]  = msa_mod_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
2762    pwd->h[4]  = msa_mod_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
2763    pwd->h[5]  = msa_mod_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
2764    pwd->h[6]  = msa_mod_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
2765    pwd->h[7]  = msa_mod_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
2766}
2767
2768void helper_msa_mod_s_w(CPUMIPSState *env,
2769                        uint32_t wd, uint32_t ws, uint32_t wt)
2770{
2771    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2772    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2773    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2774
2775    pwd->w[0]  = msa_mod_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
2776    pwd->w[1]  = msa_mod_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
2777    pwd->w[2]  = msa_mod_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
2778    pwd->w[3]  = msa_mod_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
2779}
2780
2781void helper_msa_mod_s_d(CPUMIPSState *env,
2782                        uint32_t wd, uint32_t ws, uint32_t wt)
2783{
2784    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2785    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2786    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2787
2788    pwd->d[0]  = msa_mod_s_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
2789    pwd->d[1]  = msa_mod_s_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
2790}
2791
2792static inline int64_t msa_mod_u_df(uint32_t df, int64_t arg1, int64_t arg2)
2793{
2794    uint64_t u_arg1 = UNSIGNED(arg1, df);
2795    uint64_t u_arg2 = UNSIGNED(arg2, df);
2796    return u_arg2 ? u_arg1 % u_arg2 : u_arg1;
2797}
2798
2799void helper_msa_mod_u_b(CPUMIPSState *env,
2800                        uint32_t wd, uint32_t ws, uint32_t wt)
2801{
2802    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2803    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2804    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2805
2806    pwd->b[0]  = msa_mod_u_df(DF_BYTE, pws->b[0],  pwt->b[0]);
2807    pwd->b[1]  = msa_mod_u_df(DF_BYTE, pws->b[1],  pwt->b[1]);
2808    pwd->b[2]  = msa_mod_u_df(DF_BYTE, pws->b[2],  pwt->b[2]);
2809    pwd->b[3]  = msa_mod_u_df(DF_BYTE, pws->b[3],  pwt->b[3]);
2810    pwd->b[4]  = msa_mod_u_df(DF_BYTE, pws->b[4],  pwt->b[4]);
2811    pwd->b[5]  = msa_mod_u_df(DF_BYTE, pws->b[5],  pwt->b[5]);
2812    pwd->b[6]  = msa_mod_u_df(DF_BYTE, pws->b[6],  pwt->b[6]);
2813    pwd->b[7]  = msa_mod_u_df(DF_BYTE, pws->b[7],  pwt->b[7]);
2814    pwd->b[8]  = msa_mod_u_df(DF_BYTE, pws->b[8],  pwt->b[8]);
2815    pwd->b[9]  = msa_mod_u_df(DF_BYTE, pws->b[9],  pwt->b[9]);
2816    pwd->b[10] = msa_mod_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
2817    pwd->b[11] = msa_mod_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
2818    pwd->b[12] = msa_mod_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
2819    pwd->b[13] = msa_mod_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
2820    pwd->b[14] = msa_mod_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
2821    pwd->b[15] = msa_mod_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
2822}
2823
2824void helper_msa_mod_u_h(CPUMIPSState *env,
2825                        uint32_t wd, uint32_t ws, uint32_t wt)
2826{
2827    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2828    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2829    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2830
2831    pwd->h[0]  = msa_mod_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
2832    pwd->h[1]  = msa_mod_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
2833    pwd->h[2]  = msa_mod_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
2834    pwd->h[3]  = msa_mod_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
2835    pwd->h[4]  = msa_mod_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
2836    pwd->h[5]  = msa_mod_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
2837    pwd->h[6]  = msa_mod_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
2838    pwd->h[7]  = msa_mod_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
2839}
2840
2841void helper_msa_mod_u_w(CPUMIPSState *env,
2842                        uint32_t wd, uint32_t ws, uint32_t wt)
2843{
2844    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2845    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2846    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2847
2848    pwd->w[0]  = msa_mod_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
2849    pwd->w[1]  = msa_mod_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
2850    pwd->w[2]  = msa_mod_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
2851    pwd->w[3]  = msa_mod_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
2852}
2853
2854void helper_msa_mod_u_d(CPUMIPSState *env,
2855                        uint32_t wd, uint32_t ws, uint32_t wt)
2856{
2857    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2858    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2859    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2860
2861    pwd->d[0]  = msa_mod_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
2862    pwd->d[1]  = msa_mod_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
2863}
2864
2865
2866/*
2867 * Int Multiply
2868 * ------------
2869 *
2870 * +---------------+----------------------------------------------------------+
2871 * | MADDV.B       | Vector Multiply and Add (byte)                           |
2872 * | MADDV.H       | Vector Multiply and Add (halfword)                       |
2873 * | MADDV.W       | Vector Multiply and Add (word)                           |
2874 * | MADDV.D       | Vector Multiply and Add (doubleword)                     |
2875 * | MSUBV.B       | Vector Multiply and Subtract (byte)                      |
2876 * | MSUBV.H       | Vector Multiply and Subtract (halfword)                  |
2877 * | MSUBV.W       | Vector Multiply and Subtract (word)                      |
2878 * | MSUBV.D       | Vector Multiply and Subtract (doubleword)                |
2879 * | MULV.B        | Vector Multiply (byte)                                   |
2880 * | MULV.H        | Vector Multiply (halfword)                               |
2881 * | MULV.W        | Vector Multiply (word)                                   |
2882 * | MULV.D        | Vector Multiply (doubleword)                             |
2883 * +---------------+----------------------------------------------------------+
2884 */
2885
2886/* TODO: insert Int Multiply group helpers here */
2887
2888
2889/*
2890 * Int Subtract
2891 * ------------
2892 *
2893 * +---------------+----------------------------------------------------------+
2894 * | ASUB_S.B      | Vector Absolute Values of Signed Subtract (byte)         |
2895 * | ASUB_S.H      | Vector Absolute Values of Signed Subtract (halfword)     |
2896 * | ASUB_S.W      | Vector Absolute Values of Signed Subtract (word)         |
2897 * | ASUB_S.D      | Vector Absolute Values of Signed Subtract (doubleword)   |
2898 * | ASUB_U.B      | Vector Absolute Values of Unsigned Subtract (byte)       |
2899 * | ASUB_U.H      | Vector Absolute Values of Unsigned Subtract (halfword)   |
2900 * | ASUB_U.W      | Vector Absolute Values of Unsigned Subtract (word)       |
2901 * | ASUB_U.D      | Vector Absolute Values of Unsigned Subtract (doubleword) |
2902 * | HSUB_S.H      | Vector Signed Horizontal Subtract (halfword)             |
2903 * | HSUB_S.W      | Vector Signed Horizontal Subtract (word)                 |
2904 * | HSUB_S.D      | Vector Signed Horizontal Subtract (doubleword)           |
2905 * | HSUB_U.H      | Vector Unigned Horizontal Subtract (halfword)            |
2906 * | HSUB_U.W      | Vector Unigned Horizontal Subtract (word)                |
2907 * | HSUB_U.D      | Vector Unigned Horizontal Subtract (doubleword)          |
2908 * | SUBS_S.B      | Vector Signed Saturated Subtract (of Signed) (byte)      |
2909 * | SUBS_S.H      | Vector Signed Saturated Subtract (of Signed) (halfword)  |
2910 * | SUBS_S.W      | Vector Signed Saturated Subtract (of Signed) (word)      |
2911 * | SUBS_S.D      | Vector Signed Saturated Subtract (of Signed) (doubleword)|
2912 * | SUBS_U.B      | Vector Unsigned Saturated Subtract (of Uns.) (byte)      |
2913 * | SUBS_U.H      | Vector Unsigned Saturated Subtract (of Uns.) (halfword)  |
2914 * | SUBS_U.W      | Vector Unsigned Saturated Subtract (of Uns.) (word)      |
2915 * | SUBS_U.D      | Vector Unsigned Saturated Subtract (of Uns.) (doubleword)|
2916 * | SUBSUS_U.B    | Vector Uns. Sat. Subtract (of S. from Uns.) (byte)       |
2917 * | SUBSUS_U.H    | Vector Uns. Sat. Subtract (of S. from Uns.) (halfword)   |
2918 * | SUBSUS_U.W    | Vector Uns. Sat. Subtract (of S. from Uns.) (word)       |
2919 * | SUBSUS_U.D    | Vector Uns. Sat. Subtract (of S. from Uns.) (doubleword) |
2920 * | SUBSUU_S.B    | Vector Signed Saturated Subtract (of Uns.) (byte)        |
2921 * | SUBSUU_S.H    | Vector Signed Saturated Subtract (of Uns.) (halfword)    |
2922 * | SUBSUU_S.W    | Vector Signed Saturated Subtract (of Uns.) (word)        |
2923 * | SUBSUU_S.D    | Vector Signed Saturated Subtract (of Uns.) (doubleword)  |
2924 * | SUBV.B        | Vector Subtract (byte)                                   |
2925 * | SUBV.H        | Vector Subtract (halfword)                               |
2926 * | SUBV.W        | Vector Subtract (word)                                   |
2927 * | SUBV.D        | Vector Subtract (doubleword)                             |
2928 * +---------------+----------------------------------------------------------+
2929 */
2930
2931
2932static inline int64_t msa_asub_s_df(uint32_t df, int64_t arg1, int64_t arg2)
2933{
2934    /* signed compare */
2935    return (arg1 < arg2) ?
2936        (uint64_t)(arg2 - arg1) : (uint64_t)(arg1 - arg2);
2937}
2938
2939void helper_msa_asub_s_b(CPUMIPSState *env,
2940                         uint32_t wd, uint32_t ws, uint32_t wt)
2941{
2942    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2943    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2944    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2945
2946    pwd->b[0]  = msa_asub_s_df(DF_BYTE, pws->b[0],  pwt->b[0]);
2947    pwd->b[1]  = msa_asub_s_df(DF_BYTE, pws->b[1],  pwt->b[1]);
2948    pwd->b[2]  = msa_asub_s_df(DF_BYTE, pws->b[2],  pwt->b[2]);
2949    pwd->b[3]  = msa_asub_s_df(DF_BYTE, pws->b[3],  pwt->b[3]);
2950    pwd->b[4]  = msa_asub_s_df(DF_BYTE, pws->b[4],  pwt->b[4]);
2951    pwd->b[5]  = msa_asub_s_df(DF_BYTE, pws->b[5],  pwt->b[5]);
2952    pwd->b[6]  = msa_asub_s_df(DF_BYTE, pws->b[6],  pwt->b[6]);
2953    pwd->b[7]  = msa_asub_s_df(DF_BYTE, pws->b[7],  pwt->b[7]);
2954    pwd->b[8]  = msa_asub_s_df(DF_BYTE, pws->b[8],  pwt->b[8]);
2955    pwd->b[9]  = msa_asub_s_df(DF_BYTE, pws->b[9],  pwt->b[9]);
2956    pwd->b[10] = msa_asub_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
2957    pwd->b[11] = msa_asub_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
2958    pwd->b[12] = msa_asub_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
2959    pwd->b[13] = msa_asub_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
2960    pwd->b[14] = msa_asub_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
2961    pwd->b[15] = msa_asub_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
2962}
2963
2964void helper_msa_asub_s_h(CPUMIPSState *env,
2965                         uint32_t wd, uint32_t ws, uint32_t wt)
2966{
2967    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2968    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2969    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2970
2971    pwd->h[0]  = msa_asub_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
2972    pwd->h[1]  = msa_asub_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
2973    pwd->h[2]  = msa_asub_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
2974    pwd->h[3]  = msa_asub_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
2975    pwd->h[4]  = msa_asub_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
2976    pwd->h[5]  = msa_asub_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
2977    pwd->h[6]  = msa_asub_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
2978    pwd->h[7]  = msa_asub_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
2979}
2980
2981void helper_msa_asub_s_w(CPUMIPSState *env,
2982                         uint32_t wd, uint32_t ws, uint32_t wt)
2983{
2984    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2985    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2986    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
2987
2988    pwd->w[0]  = msa_asub_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
2989    pwd->w[1]  = msa_asub_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
2990    pwd->w[2]  = msa_asub_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
2991    pwd->w[3]  = msa_asub_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
2992}
2993
2994void helper_msa_asub_s_d(CPUMIPSState *env,
2995                         uint32_t wd, uint32_t ws, uint32_t wt)
2996{
2997    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
2998    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
2999    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3000
3001    pwd->d[0]  = msa_asub_s_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
3002    pwd->d[1]  = msa_asub_s_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
3003}
3004
3005
3006static inline uint64_t msa_asub_u_df(uint32_t df, uint64_t arg1, uint64_t arg2)
3007{
3008    uint64_t u_arg1 = UNSIGNED(arg1, df);
3009    uint64_t u_arg2 = UNSIGNED(arg2, df);
3010    /* unsigned compare */
3011    return (u_arg1 < u_arg2) ?
3012        (uint64_t)(u_arg2 - u_arg1) : (uint64_t)(u_arg1 - u_arg2);
3013}
3014
3015void helper_msa_asub_u_b(CPUMIPSState *env,
3016                         uint32_t wd, uint32_t ws, uint32_t wt)
3017{
3018    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3019    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3020    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3021
3022    pwd->b[0]  = msa_asub_u_df(DF_BYTE, pws->b[0],  pwt->b[0]);
3023    pwd->b[1]  = msa_asub_u_df(DF_BYTE, pws->b[1],  pwt->b[1]);
3024    pwd->b[2]  = msa_asub_u_df(DF_BYTE, pws->b[2],  pwt->b[2]);
3025    pwd->b[3]  = msa_asub_u_df(DF_BYTE, pws->b[3],  pwt->b[3]);
3026    pwd->b[4]  = msa_asub_u_df(DF_BYTE, pws->b[4],  pwt->b[4]);
3027    pwd->b[5]  = msa_asub_u_df(DF_BYTE, pws->b[5],  pwt->b[5]);
3028    pwd->b[6]  = msa_asub_u_df(DF_BYTE, pws->b[6],  pwt->b[6]);
3029    pwd->b[7]  = msa_asub_u_df(DF_BYTE, pws->b[7],  pwt->b[7]);
3030    pwd->b[8]  = msa_asub_u_df(DF_BYTE, pws->b[8],  pwt->b[8]);
3031    pwd->b[9]  = msa_asub_u_df(DF_BYTE, pws->b[9],  pwt->b[9]);
3032    pwd->b[10] = msa_asub_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
3033    pwd->b[11] = msa_asub_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
3034    pwd->b[12] = msa_asub_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
3035    pwd->b[13] = msa_asub_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
3036    pwd->b[14] = msa_asub_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
3037    pwd->b[15] = msa_asub_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
3038}
3039
3040void helper_msa_asub_u_h(CPUMIPSState *env,
3041                         uint32_t wd, uint32_t ws, uint32_t wt)
3042{
3043    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3044    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3045    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3046
3047    pwd->h[0]  = msa_asub_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
3048    pwd->h[1]  = msa_asub_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
3049    pwd->h[2]  = msa_asub_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
3050    pwd->h[3]  = msa_asub_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
3051    pwd->h[4]  = msa_asub_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
3052    pwd->h[5]  = msa_asub_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
3053    pwd->h[6]  = msa_asub_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
3054    pwd->h[7]  = msa_asub_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
3055}
3056
3057void helper_msa_asub_u_w(CPUMIPSState *env,
3058                         uint32_t wd, uint32_t ws, uint32_t wt)
3059{
3060    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3061    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3062    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3063
3064    pwd->w[0]  = msa_asub_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
3065    pwd->w[1]  = msa_asub_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
3066    pwd->w[2]  = msa_asub_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
3067    pwd->w[3]  = msa_asub_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
3068}
3069
3070void helper_msa_asub_u_d(CPUMIPSState *env,
3071                         uint32_t wd, uint32_t ws, uint32_t wt)
3072{
3073    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3074    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3075    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3076
3077    pwd->d[0]  = msa_asub_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
3078    pwd->d[1]  = msa_asub_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
3079}
3080
3081
3082/* TODO: insert the rest of Int Subtract group helpers here */
3083
3084
3085static inline int64_t msa_hsub_s_df(uint32_t df, int64_t arg1, int64_t arg2)
3086{
3087    return SIGNED_ODD(arg1, df) - SIGNED_EVEN(arg2, df);
3088}
3089
3090void helper_msa_hsub_s_h(CPUMIPSState *env,
3091                         uint32_t wd, uint32_t ws, uint32_t wt)
3092{
3093    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3094    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3095    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3096
3097    pwd->h[0]  = msa_hsub_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
3098    pwd->h[1]  = msa_hsub_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
3099    pwd->h[2]  = msa_hsub_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
3100    pwd->h[3]  = msa_hsub_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
3101    pwd->h[4]  = msa_hsub_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
3102    pwd->h[5]  = msa_hsub_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
3103    pwd->h[6]  = msa_hsub_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
3104    pwd->h[7]  = msa_hsub_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
3105}
3106
3107void helper_msa_hsub_s_w(CPUMIPSState *env,
3108                         uint32_t wd, uint32_t ws, uint32_t wt)
3109{
3110    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3111    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3112    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3113
3114    pwd->w[0]  = msa_hsub_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
3115    pwd->w[1]  = msa_hsub_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
3116    pwd->w[2]  = msa_hsub_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
3117    pwd->w[3]  = msa_hsub_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
3118}
3119
3120void helper_msa_hsub_s_d(CPUMIPSState *env,
3121                         uint32_t wd, uint32_t ws, uint32_t wt)
3122{
3123    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3124    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3125    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3126
3127    pwd->d[0]  = msa_hsub_s_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
3128    pwd->d[1]  = msa_hsub_s_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
3129}
3130
3131
3132static inline int64_t msa_hsub_u_df(uint32_t df, int64_t arg1, int64_t arg2)
3133{
3134    return UNSIGNED_ODD(arg1, df) - UNSIGNED_EVEN(arg2, df);
3135}
3136
3137void helper_msa_hsub_u_h(CPUMIPSState *env,
3138                         uint32_t wd, uint32_t ws, uint32_t wt)
3139{
3140    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3141    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3142    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3143
3144    pwd->h[0]  = msa_hsub_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
3145    pwd->h[1]  = msa_hsub_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
3146    pwd->h[2]  = msa_hsub_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
3147    pwd->h[3]  = msa_hsub_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
3148    pwd->h[4]  = msa_hsub_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
3149    pwd->h[5]  = msa_hsub_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
3150    pwd->h[6]  = msa_hsub_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
3151    pwd->h[7]  = msa_hsub_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
3152}
3153
3154void helper_msa_hsub_u_w(CPUMIPSState *env,
3155                         uint32_t wd, uint32_t ws, uint32_t wt)
3156{
3157    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3158    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3159    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3160
3161    pwd->w[0]  = msa_hsub_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
3162    pwd->w[1]  = msa_hsub_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
3163    pwd->w[2]  = msa_hsub_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
3164    pwd->w[3]  = msa_hsub_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
3165}
3166
3167void helper_msa_hsub_u_d(CPUMIPSState *env,
3168                         uint32_t wd, uint32_t ws, uint32_t wt)
3169{
3170    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3171    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3172    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3173
3174    pwd->d[0]  = msa_hsub_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
3175    pwd->d[1]  = msa_hsub_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
3176}
3177
3178
3179/*
3180 * Interleave
3181 * ----------
3182 *
3183 * +---------------+----------------------------------------------------------+
3184 * | ILVEV.B       | Vector Interleave Even (byte)                            |
3185 * | ILVEV.H       | Vector Interleave Even (halfword)                        |
3186 * | ILVEV.W       | Vector Interleave Even (word)                            |
3187 * | ILVEV.D       | Vector Interleave Even (doubleword)                      |
3188 * | ILVOD.B       | Vector Interleave Odd (byte)                             |
3189 * | ILVOD.H       | Vector Interleave Odd (halfword)                         |
3190 * | ILVOD.W       | Vector Interleave Odd (word)                             |
3191 * | ILVOD.D       | Vector Interleave Odd (doubleword)                       |
3192 * | ILVL.B        | Vector Interleave Left (byte)                            |
3193 * | ILVL.H        | Vector Interleave Left (halfword)                        |
3194 * | ILVL.W        | Vector Interleave Left (word)                            |
3195 * | ILVL.D        | Vector Interleave Left (doubleword)                      |
3196 * | ILVR.B        | Vector Interleave Right (byte)                           |
3197 * | ILVR.H        | Vector Interleave Right (halfword)                       |
3198 * | ILVR.W        | Vector Interleave Right (word)                           |
3199 * | ILVR.D        | Vector Interleave Right (doubleword)                     |
3200 * +---------------+----------------------------------------------------------+
3201 */
3202
3203
3204void helper_msa_ilvev_b(CPUMIPSState *env,
3205                        uint32_t wd, uint32_t ws, uint32_t wt)
3206{
3207    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3208    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3209    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3210
3211#if defined(HOST_WORDS_BIGENDIAN)
3212    pwd->b[8]  = pws->b[9];
3213    pwd->b[9]  = pwt->b[9];
3214    pwd->b[10] = pws->b[11];
3215    pwd->b[11] = pwt->b[11];
3216    pwd->b[12] = pws->b[13];
3217    pwd->b[13] = pwt->b[13];
3218    pwd->b[14] = pws->b[15];
3219    pwd->b[15] = pwt->b[15];
3220    pwd->b[0]  = pws->b[1];
3221    pwd->b[1]  = pwt->b[1];
3222    pwd->b[2]  = pws->b[3];
3223    pwd->b[3]  = pwt->b[3];
3224    pwd->b[4]  = pws->b[5];
3225    pwd->b[5]  = pwt->b[5];
3226    pwd->b[6]  = pws->b[7];
3227    pwd->b[7]  = pwt->b[7];
3228#else
3229    pwd->b[15] = pws->b[14];
3230    pwd->b[14] = pwt->b[14];
3231    pwd->b[13] = pws->b[12];
3232    pwd->b[12] = pwt->b[12];
3233    pwd->b[11] = pws->b[10];
3234    pwd->b[10] = pwt->b[10];
3235    pwd->b[9]  = pws->b[8];
3236    pwd->b[8]  = pwt->b[8];
3237    pwd->b[7]  = pws->b[6];
3238    pwd->b[6]  = pwt->b[6];
3239    pwd->b[5]  = pws->b[4];
3240    pwd->b[4]  = pwt->b[4];
3241    pwd->b[3]  = pws->b[2];
3242    pwd->b[2]  = pwt->b[2];
3243    pwd->b[1]  = pws->b[0];
3244    pwd->b[0]  = pwt->b[0];
3245#endif
3246}
3247
3248void helper_msa_ilvev_h(CPUMIPSState *env,
3249                        uint32_t wd, uint32_t ws, uint32_t wt)
3250{
3251    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3252    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3253    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3254
3255#if defined(HOST_WORDS_BIGENDIAN)
3256    pwd->h[4] = pws->h[5];
3257    pwd->h[5] = pwt->h[5];
3258    pwd->h[6] = pws->h[7];
3259    pwd->h[7] = pwt->h[7];
3260    pwd->h[0] = pws->h[1];
3261    pwd->h[1] = pwt->h[1];
3262    pwd->h[2] = pws->h[3];
3263    pwd->h[3] = pwt->h[3];
3264#else
3265    pwd->h[7] = pws->h[6];
3266    pwd->h[6] = pwt->h[6];
3267    pwd->h[5] = pws->h[4];
3268    pwd->h[4] = pwt->h[4];
3269    pwd->h[3] = pws->h[2];
3270    pwd->h[2] = pwt->h[2];
3271    pwd->h[1] = pws->h[0];
3272    pwd->h[0] = pwt->h[0];
3273#endif
3274}
3275
3276void helper_msa_ilvev_w(CPUMIPSState *env,
3277                        uint32_t wd, uint32_t ws, uint32_t wt)
3278{
3279    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3280    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3281    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3282
3283#if defined(HOST_WORDS_BIGENDIAN)
3284    pwd->w[2] = pws->w[3];
3285    pwd->w[3] = pwt->w[3];
3286    pwd->w[0] = pws->w[1];
3287    pwd->w[1] = pwt->w[1];
3288#else
3289    pwd->w[3] = pws->w[2];
3290    pwd->w[2] = pwt->w[2];
3291    pwd->w[1] = pws->w[0];
3292    pwd->w[0] = pwt->w[0];
3293#endif
3294}
3295
3296void helper_msa_ilvev_d(CPUMIPSState *env,
3297                        uint32_t wd, uint32_t ws, uint32_t wt)
3298{
3299    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3300    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3301    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3302
3303    pwd->d[1] = pws->d[0];
3304    pwd->d[0] = pwt->d[0];
3305}
3306
3307
3308void helper_msa_ilvod_b(CPUMIPSState *env,
3309                        uint32_t wd, uint32_t ws, uint32_t wt)
3310{
3311    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3312    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3313    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3314
3315#if defined(HOST_WORDS_BIGENDIAN)
3316    pwd->b[7]  = pwt->b[6];
3317    pwd->b[6]  = pws->b[6];
3318    pwd->b[5]  = pwt->b[4];
3319    pwd->b[4]  = pws->b[4];
3320    pwd->b[3]  = pwt->b[2];
3321    pwd->b[2]  = pws->b[2];
3322    pwd->b[1]  = pwt->b[0];
3323    pwd->b[0]  = pws->b[0];
3324    pwd->b[15] = pwt->b[14];
3325    pwd->b[14] = pws->b[14];
3326    pwd->b[13] = pwt->b[12];
3327    pwd->b[12] = pws->b[12];
3328    pwd->b[11] = pwt->b[10];
3329    pwd->b[10] = pws->b[10];
3330    pwd->b[9]  = pwt->b[8];
3331    pwd->b[8]  = pws->b[8];
3332#else
3333    pwd->b[0]  = pwt->b[1];
3334    pwd->b[1]  = pws->b[1];
3335    pwd->b[2]  = pwt->b[3];
3336    pwd->b[3]  = pws->b[3];
3337    pwd->b[4]  = pwt->b[5];
3338    pwd->b[5]  = pws->b[5];
3339    pwd->b[6]  = pwt->b[7];
3340    pwd->b[7]  = pws->b[7];
3341    pwd->b[8]  = pwt->b[9];
3342    pwd->b[9]  = pws->b[9];
3343    pwd->b[10] = pwt->b[11];
3344    pwd->b[11] = pws->b[11];
3345    pwd->b[12] = pwt->b[13];
3346    pwd->b[13] = pws->b[13];
3347    pwd->b[14] = pwt->b[15];
3348    pwd->b[15] = pws->b[15];
3349#endif
3350}
3351
3352void helper_msa_ilvod_h(CPUMIPSState *env,
3353                        uint32_t wd, uint32_t ws, uint32_t wt)
3354{
3355    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3356    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3357    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3358
3359#if defined(HOST_WORDS_BIGENDIAN)
3360    pwd->h[3] = pwt->h[2];
3361    pwd->h[2] = pws->h[2];
3362    pwd->h[1] = pwt->h[0];
3363    pwd->h[0] = pws->h[0];
3364    pwd->h[7] = pwt->h[6];
3365    pwd->h[6] = pws->h[6];
3366    pwd->h[5] = pwt->h[4];
3367    pwd->h[4] = pws->h[4];
3368#else
3369    pwd->h[0] = pwt->h[1];
3370    pwd->h[1] = pws->h[1];
3371    pwd->h[2] = pwt->h[3];
3372    pwd->h[3] = pws->h[3];
3373    pwd->h[4] = pwt->h[5];
3374    pwd->h[5] = pws->h[5];
3375    pwd->h[6] = pwt->h[7];
3376    pwd->h[7] = pws->h[7];
3377#endif
3378}
3379
3380void helper_msa_ilvod_w(CPUMIPSState *env,
3381                        uint32_t wd, uint32_t ws, uint32_t wt)
3382{
3383    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3384    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3385    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3386
3387#if defined(HOST_WORDS_BIGENDIAN)
3388    pwd->w[1] = pwt->w[0];
3389    pwd->w[0] = pws->w[0];
3390    pwd->w[3] = pwt->w[2];
3391    pwd->w[2] = pws->w[2];
3392#else
3393    pwd->w[0] = pwt->w[1];
3394    pwd->w[1] = pws->w[1];
3395    pwd->w[2] = pwt->w[3];
3396    pwd->w[3] = pws->w[3];
3397#endif
3398}
3399
3400void helper_msa_ilvod_d(CPUMIPSState *env,
3401                        uint32_t wd, uint32_t ws, uint32_t wt)
3402{
3403    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3404    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3405    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3406
3407    pwd->d[0] = pwt->d[1];
3408    pwd->d[1] = pws->d[1];
3409}
3410
3411
3412void helper_msa_ilvl_b(CPUMIPSState *env,
3413                       uint32_t wd, uint32_t ws, uint32_t wt)
3414{
3415    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3416    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3417    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3418
3419#if defined(HOST_WORDS_BIGENDIAN)
3420    pwd->b[7]  = pwt->b[15];
3421    pwd->b[6]  = pws->b[15];
3422    pwd->b[5]  = pwt->b[14];
3423    pwd->b[4]  = pws->b[14];
3424    pwd->b[3]  = pwt->b[13];
3425    pwd->b[2]  = pws->b[13];
3426    pwd->b[1]  = pwt->b[12];
3427    pwd->b[0]  = pws->b[12];
3428    pwd->b[15] = pwt->b[11];
3429    pwd->b[14] = pws->b[11];
3430    pwd->b[13] = pwt->b[10];
3431    pwd->b[12] = pws->b[10];
3432    pwd->b[11] = pwt->b[9];
3433    pwd->b[10] = pws->b[9];
3434    pwd->b[9]  = pwt->b[8];
3435    pwd->b[8]  = pws->b[8];
3436#else
3437    pwd->b[0]  = pwt->b[8];
3438    pwd->b[1]  = pws->b[8];
3439    pwd->b[2]  = pwt->b[9];
3440    pwd->b[3]  = pws->b[9];
3441    pwd->b[4]  = pwt->b[10];
3442    pwd->b[5]  = pws->b[10];
3443    pwd->b[6]  = pwt->b[11];
3444    pwd->b[7]  = pws->b[11];
3445    pwd->b[8]  = pwt->b[12];
3446    pwd->b[9]  = pws->b[12];
3447    pwd->b[10] = pwt->b[13];
3448    pwd->b[11] = pws->b[13];
3449    pwd->b[12] = pwt->b[14];
3450    pwd->b[13] = pws->b[14];
3451    pwd->b[14] = pwt->b[15];
3452    pwd->b[15] = pws->b[15];
3453#endif
3454}
3455
3456void helper_msa_ilvl_h(CPUMIPSState *env,
3457                       uint32_t wd, uint32_t ws, uint32_t wt)
3458{
3459    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3460    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3461    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3462
3463#if defined(HOST_WORDS_BIGENDIAN)
3464    pwd->h[3] = pwt->h[7];
3465    pwd->h[2] = pws->h[7];
3466    pwd->h[1] = pwt->h[6];
3467    pwd->h[0] = pws->h[6];
3468    pwd->h[7] = pwt->h[5];
3469    pwd->h[6] = pws->h[5];
3470    pwd->h[5] = pwt->h[4];
3471    pwd->h[4] = pws->h[4];
3472#else
3473    pwd->h[0] = pwt->h[4];
3474    pwd->h[1] = pws->h[4];
3475    pwd->h[2] = pwt->h[5];
3476    pwd->h[3] = pws->h[5];
3477    pwd->h[4] = pwt->h[6];
3478    pwd->h[5] = pws->h[6];
3479    pwd->h[6] = pwt->h[7];
3480    pwd->h[7] = pws->h[7];
3481#endif
3482}
3483
3484void helper_msa_ilvl_w(CPUMIPSState *env,
3485                       uint32_t wd, uint32_t ws, uint32_t wt)
3486{
3487    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3488    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3489    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3490
3491#if defined(HOST_WORDS_BIGENDIAN)
3492    pwd->w[1] = pwt->w[3];
3493    pwd->w[0] = pws->w[3];
3494    pwd->w[3] = pwt->w[2];
3495    pwd->w[2] = pws->w[2];
3496#else
3497    pwd->w[0] = pwt->w[2];
3498    pwd->w[1] = pws->w[2];
3499    pwd->w[2] = pwt->w[3];
3500    pwd->w[3] = pws->w[3];
3501#endif
3502}
3503
3504void helper_msa_ilvl_d(CPUMIPSState *env,
3505                       uint32_t wd, uint32_t ws, uint32_t wt)
3506{
3507    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3508    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3509    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3510
3511    pwd->d[0] = pwt->d[1];
3512    pwd->d[1] = pws->d[1];
3513}
3514
3515
3516void helper_msa_ilvr_b(CPUMIPSState *env,
3517                       uint32_t wd, uint32_t ws, uint32_t wt)
3518{
3519    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3520    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3521    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3522
3523#if defined(HOST_WORDS_BIGENDIAN)
3524    pwd->b[8]  = pws->b[0];
3525    pwd->b[9]  = pwt->b[0];
3526    pwd->b[10] = pws->b[1];
3527    pwd->b[11] = pwt->b[1];
3528    pwd->b[12] = pws->b[2];
3529    pwd->b[13] = pwt->b[2];
3530    pwd->b[14] = pws->b[3];
3531    pwd->b[15] = pwt->b[3];
3532    pwd->b[0]  = pws->b[4];
3533    pwd->b[1]  = pwt->b[4];
3534    pwd->b[2]  = pws->b[5];
3535    pwd->b[3]  = pwt->b[5];
3536    pwd->b[4]  = pws->b[6];
3537    pwd->b[5]  = pwt->b[6];
3538    pwd->b[6]  = pws->b[7];
3539    pwd->b[7]  = pwt->b[7];
3540#else
3541    pwd->b[15] = pws->b[7];
3542    pwd->b[14] = pwt->b[7];
3543    pwd->b[13] = pws->b[6];
3544    pwd->b[12] = pwt->b[6];
3545    pwd->b[11] = pws->b[5];
3546    pwd->b[10] = pwt->b[5];
3547    pwd->b[9]  = pws->b[4];
3548    pwd->b[8]  = pwt->b[4];
3549    pwd->b[7]  = pws->b[3];
3550    pwd->b[6]  = pwt->b[3];
3551    pwd->b[5]  = pws->b[2];
3552    pwd->b[4]  = pwt->b[2];
3553    pwd->b[3]  = pws->b[1];
3554    pwd->b[2]  = pwt->b[1];
3555    pwd->b[1]  = pws->b[0];
3556    pwd->b[0]  = pwt->b[0];
3557#endif
3558}
3559
3560void helper_msa_ilvr_h(CPUMIPSState *env,
3561                       uint32_t wd, uint32_t ws, uint32_t wt)
3562{
3563    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3564    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3565    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3566
3567#if defined(HOST_WORDS_BIGENDIAN)
3568    pwd->h[4] = pws->h[0];
3569    pwd->h[5] = pwt->h[0];
3570    pwd->h[6] = pws->h[1];
3571    pwd->h[7] = pwt->h[1];
3572    pwd->h[0] = pws->h[2];
3573    pwd->h[1] = pwt->h[2];
3574    pwd->h[2] = pws->h[3];
3575    pwd->h[3] = pwt->h[3];
3576#else
3577    pwd->h[7] = pws->h[3];
3578    pwd->h[6] = pwt->h[3];
3579    pwd->h[5] = pws->h[2];
3580    pwd->h[4] = pwt->h[2];
3581    pwd->h[3] = pws->h[1];
3582    pwd->h[2] = pwt->h[1];
3583    pwd->h[1] = pws->h[0];
3584    pwd->h[0] = pwt->h[0];
3585#endif
3586}
3587
3588void helper_msa_ilvr_w(CPUMIPSState *env,
3589                       uint32_t wd, uint32_t ws, uint32_t wt)
3590{
3591    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3592    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3593    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3594
3595#if defined(HOST_WORDS_BIGENDIAN)
3596    pwd->w[2] = pws->w[0];
3597    pwd->w[3] = pwt->w[0];
3598    pwd->w[0] = pws->w[1];
3599    pwd->w[1] = pwt->w[1];
3600#else
3601    pwd->w[3] = pws->w[1];
3602    pwd->w[2] = pwt->w[1];
3603    pwd->w[1] = pws->w[0];
3604    pwd->w[0] = pwt->w[0];
3605#endif
3606}
3607
3608void helper_msa_ilvr_d(CPUMIPSState *env,
3609                       uint32_t wd, uint32_t ws, uint32_t wt)
3610{
3611    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3612    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3613    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3614
3615    pwd->d[1] = pws->d[0];
3616    pwd->d[0] = pwt->d[0];
3617}
3618
3619
3620/*
3621 * Logic
3622 * -----
3623 *
3624 * +---------------+----------------------------------------------------------+
3625 * | AND.V         | Vector Logical And                                       |
3626 * | NOR.V         | Vector Logical Negated Or                                |
3627 * | OR.V          | Vector Logical Or                                        |
3628 * | XOR.V         | Vector Logical Exclusive Or                              |
3629 * +---------------+----------------------------------------------------------+
3630 */
3631
3632
3633void helper_msa_and_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
3634{
3635    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3636    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3637    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3638
3639    pwd->d[0] = pws->d[0] & pwt->d[0];
3640    pwd->d[1] = pws->d[1] & pwt->d[1];
3641}
3642
3643void helper_msa_nor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
3644{
3645    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3646    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3647    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3648
3649    pwd->d[0] = ~(pws->d[0] | pwt->d[0]);
3650    pwd->d[1] = ~(pws->d[1] | pwt->d[1]);
3651}
3652
3653void helper_msa_or_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
3654{
3655    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3656    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3657    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3658
3659    pwd->d[0] = pws->d[0] | pwt->d[0];
3660    pwd->d[1] = pws->d[1] | pwt->d[1];
3661}
3662
3663void helper_msa_xor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt)
3664{
3665    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3666    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3667    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3668
3669    pwd->d[0] = pws->d[0] ^ pwt->d[0];
3670    pwd->d[1] = pws->d[1] ^ pwt->d[1];
3671}
3672
3673
3674/*
3675 * Move
3676 * ----
3677 *
3678 * +---------------+----------------------------------------------------------+
3679 * | MOVE.V        | Vector Move                                              |
3680 * +---------------+----------------------------------------------------------+
3681 */
3682
3683static inline void msa_move_v(wr_t *pwd, wr_t *pws)
3684{
3685    pwd->d[0] = pws->d[0];
3686    pwd->d[1] = pws->d[1];
3687}
3688
3689void helper_msa_move_v(CPUMIPSState *env, uint32_t wd, uint32_t ws)
3690{
3691    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3692    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3693
3694    msa_move_v(pwd, pws);
3695}
3696
3697
3698/*
3699 * Pack
3700 * ----
3701 *
3702 * +---------------+----------------------------------------------------------+
3703 * | PCKEV.B       | Vector Pack Even (byte)                                  |
3704 * | PCKEV.H       | Vector Pack Even (halfword)                              |
3705 * | PCKEV.W       | Vector Pack Even (word)                                  |
3706 * | PCKEV.D       | Vector Pack Even (doubleword)                            |
3707 * | PCKOD.B       | Vector Pack Odd (byte)                                   |
3708 * | PCKOD.H       | Vector Pack Odd (halfword)                               |
3709 * | PCKOD.W       | Vector Pack Odd (word)                                   |
3710 * | PCKOD.D       | Vector Pack Odd (doubleword)                             |
3711 * | VSHF.B        | Vector Data Preserving Shuffle (byte)                    |
3712 * | VSHF.H        | Vector Data Preserving Shuffle (halfword)                |
3713 * | VSHF.W        | Vector Data Preserving Shuffle (word)                    |
3714 * | VSHF.D        | Vector Data Preserving Shuffle (doubleword)              |
3715 * +---------------+----------------------------------------------------------+
3716 */
3717
3718
3719void helper_msa_pckev_b(CPUMIPSState *env,
3720                        uint32_t wd, uint32_t ws, uint32_t wt)
3721{
3722    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3723    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3724    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3725
3726#if defined(HOST_WORDS_BIGENDIAN)
3727    pwd->b[8]  = pws->b[9];
3728    pwd->b[10] = pws->b[13];
3729    pwd->b[12] = pws->b[1];
3730    pwd->b[14] = pws->b[5];
3731    pwd->b[0]  = pwt->b[9];
3732    pwd->b[2]  = pwt->b[13];
3733    pwd->b[4]  = pwt->b[1];
3734    pwd->b[6]  = pwt->b[5];
3735    pwd->b[9]  = pws->b[11];
3736    pwd->b[13] = pws->b[3];
3737    pwd->b[1]  = pwt->b[11];
3738    pwd->b[5]  = pwt->b[3];
3739    pwd->b[11] = pws->b[15];
3740    pwd->b[3]  = pwt->b[15];
3741    pwd->b[15] = pws->b[7];
3742    pwd->b[7]  = pwt->b[7];
3743#else
3744    pwd->b[15] = pws->b[14];
3745    pwd->b[13] = pws->b[10];
3746    pwd->b[11] = pws->b[6];
3747    pwd->b[9]  = pws->b[2];
3748    pwd->b[7]  = pwt->b[14];
3749    pwd->b[5]  = pwt->b[10];
3750    pwd->b[3]  = pwt->b[6];
3751    pwd->b[1]  = pwt->b[2];
3752    pwd->b[14] = pws->b[12];
3753    pwd->b[10] = pws->b[4];
3754    pwd->b[6]  = pwt->b[12];
3755    pwd->b[2]  = pwt->b[4];
3756    pwd->b[12] = pws->b[8];
3757    pwd->b[4]  = pwt->b[8];
3758    pwd->b[8]  = pws->b[0];
3759    pwd->b[0]  = pwt->b[0];
3760#endif
3761}
3762
3763void helper_msa_pckev_h(CPUMIPSState *env,
3764                        uint32_t wd, uint32_t ws, uint32_t wt)
3765{
3766    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3767    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3768    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3769
3770#if defined(HOST_WORDS_BIGENDIAN)
3771    pwd->h[4] = pws->h[5];
3772    pwd->h[6] = pws->h[1];
3773    pwd->h[0] = pwt->h[5];
3774    pwd->h[2] = pwt->h[1];
3775    pwd->h[5] = pws->h[7];
3776    pwd->h[1] = pwt->h[7];
3777    pwd->h[7] = pws->h[3];
3778    pwd->h[3] = pwt->h[3];
3779#else
3780    pwd->h[7] = pws->h[6];
3781    pwd->h[5] = pws->h[2];
3782    pwd->h[3] = pwt->h[6];
3783    pwd->h[1] = pwt->h[2];
3784    pwd->h[6] = pws->h[4];
3785    pwd->h[2] = pwt->h[4];
3786    pwd->h[4] = pws->h[0];
3787    pwd->h[0] = pwt->h[0];
3788#endif
3789}
3790
3791void helper_msa_pckev_w(CPUMIPSState *env,
3792                        uint32_t wd, uint32_t ws, uint32_t wt)
3793{
3794    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3795    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3796    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3797
3798#if defined(HOST_WORDS_BIGENDIAN)
3799    pwd->w[2] = pws->w[3];
3800    pwd->w[0] = pwt->w[3];
3801    pwd->w[3] = pws->w[1];
3802    pwd->w[1] = pwt->w[1];
3803#else
3804    pwd->w[3] = pws->w[2];
3805    pwd->w[1] = pwt->w[2];
3806    pwd->w[2] = pws->w[0];
3807    pwd->w[0] = pwt->w[0];
3808#endif
3809}
3810
3811void helper_msa_pckev_d(CPUMIPSState *env,
3812                        uint32_t wd, uint32_t ws, uint32_t wt)
3813{
3814    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3815    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3816    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3817
3818    pwd->d[1] = pws->d[0];
3819    pwd->d[0] = pwt->d[0];
3820}
3821
3822
3823void helper_msa_pckod_b(CPUMIPSState *env,
3824                        uint32_t wd, uint32_t ws, uint32_t wt)
3825{
3826    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3827    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3828    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3829
3830#if defined(HOST_WORDS_BIGENDIAN)
3831    pwd->b[7]  = pwt->b[6];
3832    pwd->b[5]  = pwt->b[2];
3833    pwd->b[3]  = pwt->b[14];
3834    pwd->b[1]  = pwt->b[10];
3835    pwd->b[15] = pws->b[6];
3836    pwd->b[13] = pws->b[2];
3837    pwd->b[11] = pws->b[14];
3838    pwd->b[9]  = pws->b[10];
3839    pwd->b[6]  = pwt->b[4];
3840    pwd->b[2]  = pwt->b[12];
3841    pwd->b[14] = pws->b[4];
3842    pwd->b[10] = pws->b[12];
3843    pwd->b[4]  = pwt->b[0];
3844    pwd->b[12] = pws->b[0];
3845    pwd->b[0]  = pwt->b[8];
3846    pwd->b[8]  = pws->b[8];
3847#else
3848    pwd->b[0]  = pwt->b[1];
3849    pwd->b[2]  = pwt->b[5];
3850    pwd->b[4]  = pwt->b[9];
3851    pwd->b[6]  = pwt->b[13];
3852    pwd->b[8]  = pws->b[1];
3853    pwd->b[10] = pws->b[5];
3854    pwd->b[12] = pws->b[9];
3855    pwd->b[14] = pws->b[13];
3856    pwd->b[1]  = pwt->b[3];
3857    pwd->b[5]  = pwt->b[11];
3858    pwd->b[9]  = pws->b[3];
3859    pwd->b[13] = pws->b[11];
3860    pwd->b[3]  = pwt->b[7];
3861    pwd->b[11] = pws->b[7];
3862    pwd->b[7]  = pwt->b[15];
3863    pwd->b[15] = pws->b[15];
3864#endif
3865
3866}
3867
3868void helper_msa_pckod_h(CPUMIPSState *env,
3869                        uint32_t wd, uint32_t ws, uint32_t wt)
3870{
3871    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3872    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3873    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3874
3875#if defined(HOST_WORDS_BIGENDIAN)
3876    pwd->h[3] = pwt->h[2];
3877    pwd->h[1] = pwt->h[6];
3878    pwd->h[7] = pws->h[2];
3879    pwd->h[5] = pws->h[6];
3880    pwd->h[2] = pwt->h[0];
3881    pwd->h[6] = pws->h[0];
3882    pwd->h[0] = pwt->h[4];
3883    pwd->h[4] = pws->h[4];
3884#else
3885    pwd->h[0] = pwt->h[1];
3886    pwd->h[2] = pwt->h[5];
3887    pwd->h[4] = pws->h[1];
3888    pwd->h[6] = pws->h[5];
3889    pwd->h[1] = pwt->h[3];
3890    pwd->h[5] = pws->h[3];
3891    pwd->h[3] = pwt->h[7];
3892    pwd->h[7] = pws->h[7];
3893#endif
3894}
3895
3896void helper_msa_pckod_w(CPUMIPSState *env,
3897                        uint32_t wd, uint32_t ws, uint32_t wt)
3898{
3899    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3900    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3901    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3902
3903#if defined(HOST_WORDS_BIGENDIAN)
3904    pwd->w[1] = pwt->w[0];
3905    pwd->w[3] = pws->w[0];
3906    pwd->w[0] = pwt->w[2];
3907    pwd->w[2] = pws->w[2];
3908#else
3909    pwd->w[0] = pwt->w[1];
3910    pwd->w[2] = pws->w[1];
3911    pwd->w[1] = pwt->w[3];
3912    pwd->w[3] = pws->w[3];
3913#endif
3914}
3915
3916void helper_msa_pckod_d(CPUMIPSState *env,
3917                        uint32_t wd, uint32_t ws, uint32_t wt)
3918{
3919    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3920    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3921    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3922
3923    pwd->d[0] = pwt->d[1];
3924    pwd->d[1] = pws->d[1];
3925}
3926
3927
3928/*
3929 * Shift
3930 * -----
3931 *
3932 * +---------------+----------------------------------------------------------+
3933 * | SLL.B         | Vector Shift Left (byte)                                 |
3934 * | SLL.H         | Vector Shift Left (halfword)                             |
3935 * | SLL.W         | Vector Shift Left (word)                                 |
3936 * | SLL.D         | Vector Shift Left (doubleword)                           |
3937 * | SRA.B         | Vector Shift Right Arithmetic (byte)                     |
3938 * | SRA.H         | Vector Shift Right Arithmetic (halfword)                 |
3939 * | SRA.W         | Vector Shift Right Arithmetic (word)                     |
3940 * | SRA.D         | Vector Shift Right Arithmetic (doubleword)               |
3941 * | SRAR.B        | Vector Shift Right Arithmetic Rounded (byte)             |
3942 * | SRAR.H        | Vector Shift Right Arithmetic Rounded (halfword)         |
3943 * | SRAR.W        | Vector Shift Right Arithmetic Rounded (word)             |
3944 * | SRAR.D        | Vector Shift Right Arithmetic Rounded (doubleword)       |
3945 * | SRL.B         | Vector Shift Right Logical (byte)                        |
3946 * | SRL.H         | Vector Shift Right Logical (halfword)                    |
3947 * | SRL.W         | Vector Shift Right Logical (word)                        |
3948 * | SRL.D         | Vector Shift Right Logical (doubleword)                  |
3949 * | SRLR.B        | Vector Shift Right Logical Rounded (byte)                |
3950 * | SRLR.H        | Vector Shift Right Logical Rounded (halfword)            |
3951 * | SRLR.W        | Vector Shift Right Logical Rounded (word)                |
3952 * | SRLR.D        | Vector Shift Right Logical Rounded (doubleword)          |
3953 * +---------------+----------------------------------------------------------+
3954 */
3955
3956
3957static inline int64_t msa_sll_df(uint32_t df, int64_t arg1, int64_t arg2)
3958{
3959    int32_t b_arg2 = BIT_POSITION(arg2, df);
3960    return arg1 << b_arg2;
3961}
3962
3963void helper_msa_sll_b(CPUMIPSState *env,
3964                      uint32_t wd, uint32_t ws, uint32_t wt)
3965{
3966    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3967    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3968    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3969
3970    pwd->b[0]  = msa_sll_df(DF_BYTE, pws->b[0],  pwt->b[0]);
3971    pwd->b[1]  = msa_sll_df(DF_BYTE, pws->b[1],  pwt->b[1]);
3972    pwd->b[2]  = msa_sll_df(DF_BYTE, pws->b[2],  pwt->b[2]);
3973    pwd->b[3]  = msa_sll_df(DF_BYTE, pws->b[3],  pwt->b[3]);
3974    pwd->b[4]  = msa_sll_df(DF_BYTE, pws->b[4],  pwt->b[4]);
3975    pwd->b[5]  = msa_sll_df(DF_BYTE, pws->b[5],  pwt->b[5]);
3976    pwd->b[6]  = msa_sll_df(DF_BYTE, pws->b[6],  pwt->b[6]);
3977    pwd->b[7]  = msa_sll_df(DF_BYTE, pws->b[7],  pwt->b[7]);
3978    pwd->b[8]  = msa_sll_df(DF_BYTE, pws->b[8],  pwt->b[8]);
3979    pwd->b[9]  = msa_sll_df(DF_BYTE, pws->b[9],  pwt->b[9]);
3980    pwd->b[10] = msa_sll_df(DF_BYTE, pws->b[10], pwt->b[10]);
3981    pwd->b[11] = msa_sll_df(DF_BYTE, pws->b[11], pwt->b[11]);
3982    pwd->b[12] = msa_sll_df(DF_BYTE, pws->b[12], pwt->b[12]);
3983    pwd->b[13] = msa_sll_df(DF_BYTE, pws->b[13], pwt->b[13]);
3984    pwd->b[14] = msa_sll_df(DF_BYTE, pws->b[14], pwt->b[14]);
3985    pwd->b[15] = msa_sll_df(DF_BYTE, pws->b[15], pwt->b[15]);
3986}
3987
3988void helper_msa_sll_h(CPUMIPSState *env,
3989                      uint32_t wd, uint32_t ws, uint32_t wt)
3990{
3991    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3992    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
3993    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
3994
3995    pwd->h[0]  = msa_sll_df(DF_HALF, pws->h[0],  pwt->h[0]);
3996    pwd->h[1]  = msa_sll_df(DF_HALF, pws->h[1],  pwt->h[1]);
3997    pwd->h[2]  = msa_sll_df(DF_HALF, pws->h[2],  pwt->h[2]);
3998    pwd->h[3]  = msa_sll_df(DF_HALF, pws->h[3],  pwt->h[3]);
3999    pwd->h[4]  = msa_sll_df(DF_HALF, pws->h[4],  pwt->h[4]);
4000    pwd->h[5]  = msa_sll_df(DF_HALF, pws->h[5],  pwt->h[5]);
4001    pwd->h[6]  = msa_sll_df(DF_HALF, pws->h[6],  pwt->h[6]);
4002    pwd->h[7]  = msa_sll_df(DF_HALF, pws->h[7],  pwt->h[7]);
4003}
4004
4005void helper_msa_sll_w(CPUMIPSState *env,
4006                      uint32_t wd, uint32_t ws, uint32_t wt)
4007{
4008    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4009    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4010    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4011
4012    pwd->w[0]  = msa_sll_df(DF_WORD, pws->w[0],  pwt->w[0]);
4013    pwd->w[1]  = msa_sll_df(DF_WORD, pws->w[1],  pwt->w[1]);
4014    pwd->w[2]  = msa_sll_df(DF_WORD, pws->w[2],  pwt->w[2]);
4015    pwd->w[3]  = msa_sll_df(DF_WORD, pws->w[3],  pwt->w[3]);
4016}
4017
4018void helper_msa_sll_d(CPUMIPSState *env,
4019                      uint32_t wd, uint32_t ws, uint32_t wt)
4020{
4021    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4022    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4023    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4024
4025    pwd->d[0]  = msa_sll_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
4026    pwd->d[1]  = msa_sll_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
4027}
4028
4029
4030static inline int64_t msa_sra_df(uint32_t df, int64_t arg1, int64_t arg2)
4031{
4032    int32_t b_arg2 = BIT_POSITION(arg2, df);
4033    return arg1 >> b_arg2;
4034}
4035
4036void helper_msa_sra_b(CPUMIPSState *env,
4037                      uint32_t wd, uint32_t ws, uint32_t wt)
4038{
4039    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4040    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4041    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4042
4043    pwd->b[0]  = msa_sra_df(DF_BYTE, pws->b[0],  pwt->b[0]);
4044    pwd->b[1]  = msa_sra_df(DF_BYTE, pws->b[1],  pwt->b[1]);
4045    pwd->b[2]  = msa_sra_df(DF_BYTE, pws->b[2],  pwt->b[2]);
4046    pwd->b[3]  = msa_sra_df(DF_BYTE, pws->b[3],  pwt->b[3]);
4047    pwd->b[4]  = msa_sra_df(DF_BYTE, pws->b[4],  pwt->b[4]);
4048    pwd->b[5]  = msa_sra_df(DF_BYTE, pws->b[5],  pwt->b[5]);
4049    pwd->b[6]  = msa_sra_df(DF_BYTE, pws->b[6],  pwt->b[6]);
4050    pwd->b[7]  = msa_sra_df(DF_BYTE, pws->b[7],  pwt->b[7]);
4051    pwd->b[8]  = msa_sra_df(DF_BYTE, pws->b[8],  pwt->b[8]);
4052    pwd->b[9]  = msa_sra_df(DF_BYTE, pws->b[9],  pwt->b[9]);
4053    pwd->b[10] = msa_sra_df(DF_BYTE, pws->b[10], pwt->b[10]);
4054    pwd->b[11] = msa_sra_df(DF_BYTE, pws->b[11], pwt->b[11]);
4055    pwd->b[12] = msa_sra_df(DF_BYTE, pws->b[12], pwt->b[12]);
4056    pwd->b[13] = msa_sra_df(DF_BYTE, pws->b[13], pwt->b[13]);
4057    pwd->b[14] = msa_sra_df(DF_BYTE, pws->b[14], pwt->b[14]);
4058    pwd->b[15] = msa_sra_df(DF_BYTE, pws->b[15], pwt->b[15]);
4059}
4060
4061void helper_msa_sra_h(CPUMIPSState *env,
4062                      uint32_t wd, uint32_t ws, uint32_t wt)
4063{
4064    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4065    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4066    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4067
4068    pwd->h[0]  = msa_sra_df(DF_HALF, pws->h[0],  pwt->h[0]);
4069    pwd->h[1]  = msa_sra_df(DF_HALF, pws->h[1],  pwt->h[1]);
4070    pwd->h[2]  = msa_sra_df(DF_HALF, pws->h[2],  pwt->h[2]);
4071    pwd->h[3]  = msa_sra_df(DF_HALF, pws->h[3],  pwt->h[3]);
4072    pwd->h[4]  = msa_sra_df(DF_HALF, pws->h[4],  pwt->h[4]);
4073    pwd->h[5]  = msa_sra_df(DF_HALF, pws->h[5],  pwt->h[5]);
4074    pwd->h[6]  = msa_sra_df(DF_HALF, pws->h[6],  pwt->h[6]);
4075    pwd->h[7]  = msa_sra_df(DF_HALF, pws->h[7],  pwt->h[7]);
4076}
4077
4078void helper_msa_sra_w(CPUMIPSState *env,
4079                      uint32_t wd, uint32_t ws, uint32_t wt)
4080{
4081    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4082    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4083    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4084
4085    pwd->w[0]  = msa_sra_df(DF_WORD, pws->w[0],  pwt->w[0]);
4086    pwd->w[1]  = msa_sra_df(DF_WORD, pws->w[1],  pwt->w[1]);
4087    pwd->w[2]  = msa_sra_df(DF_WORD, pws->w[2],  pwt->w[2]);
4088    pwd->w[3]  = msa_sra_df(DF_WORD, pws->w[3],  pwt->w[3]);
4089}
4090
4091void helper_msa_sra_d(CPUMIPSState *env,
4092                      uint32_t wd, uint32_t ws, uint32_t wt)
4093{
4094    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4095    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4096    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4097
4098    pwd->d[0]  = msa_sra_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
4099    pwd->d[1]  = msa_sra_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
4100}
4101
4102
4103static inline int64_t msa_srar_df(uint32_t df, int64_t arg1, int64_t arg2)
4104{
4105    int32_t b_arg2 = BIT_POSITION(arg2, df);
4106    if (b_arg2 == 0) {
4107        return arg1;
4108    } else {
4109        int64_t r_bit = (arg1 >> (b_arg2 - 1)) & 1;
4110        return (arg1 >> b_arg2) + r_bit;
4111    }
4112}
4113
4114void helper_msa_srar_b(CPUMIPSState *env,
4115                       uint32_t wd, uint32_t ws, uint32_t wt)
4116{
4117    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4118    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4119    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4120
4121    pwd->b[0]  = msa_srar_df(DF_BYTE, pws->b[0],  pwt->b[0]);
4122    pwd->b[1]  = msa_srar_df(DF_BYTE, pws->b[1],  pwt->b[1]);
4123    pwd->b[2]  = msa_srar_df(DF_BYTE, pws->b[2],  pwt->b[2]);
4124    pwd->b[3]  = msa_srar_df(DF_BYTE, pws->b[3],  pwt->b[3]);
4125    pwd->b[4]  = msa_srar_df(DF_BYTE, pws->b[4],  pwt->b[4]);
4126    pwd->b[5]  = msa_srar_df(DF_BYTE, pws->b[5],  pwt->b[5]);
4127    pwd->b[6]  = msa_srar_df(DF_BYTE, pws->b[6],  pwt->b[6]);
4128    pwd->b[7]  = msa_srar_df(DF_BYTE, pws->b[7],  pwt->b[7]);
4129    pwd->b[8]  = msa_srar_df(DF_BYTE, pws->b[8],  pwt->b[8]);
4130    pwd->b[9]  = msa_srar_df(DF_BYTE, pws->b[9],  pwt->b[9]);
4131    pwd->b[10] = msa_srar_df(DF_BYTE, pws->b[10], pwt->b[10]);
4132    pwd->b[11] = msa_srar_df(DF_BYTE, pws->b[11], pwt->b[11]);
4133    pwd->b[12] = msa_srar_df(DF_BYTE, pws->b[12], pwt->b[12]);
4134    pwd->b[13] = msa_srar_df(DF_BYTE, pws->b[13], pwt->b[13]);
4135    pwd->b[14] = msa_srar_df(DF_BYTE, pws->b[14], pwt->b[14]);
4136    pwd->b[15] = msa_srar_df(DF_BYTE, pws->b[15], pwt->b[15]);
4137}
4138
4139void helper_msa_srar_h(CPUMIPSState *env,
4140                       uint32_t wd, uint32_t ws, uint32_t wt)
4141{
4142    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4143    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4144    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4145
4146    pwd->h[0]  = msa_srar_df(DF_HALF, pws->h[0],  pwt->h[0]);
4147    pwd->h[1]  = msa_srar_df(DF_HALF, pws->h[1],  pwt->h[1]);
4148    pwd->h[2]  = msa_srar_df(DF_HALF, pws->h[2],  pwt->h[2]);
4149    pwd->h[3]  = msa_srar_df(DF_HALF, pws->h[3],  pwt->h[3]);
4150    pwd->h[4]  = msa_srar_df(DF_HALF, pws->h[4],  pwt->h[4]);
4151    pwd->h[5]  = msa_srar_df(DF_HALF, pws->h[5],  pwt->h[5]);
4152    pwd->h[6]  = msa_srar_df(DF_HALF, pws->h[6],  pwt->h[6]);
4153    pwd->h[7]  = msa_srar_df(DF_HALF, pws->h[7],  pwt->h[7]);
4154}
4155
4156void helper_msa_srar_w(CPUMIPSState *env,
4157                       uint32_t wd, uint32_t ws, uint32_t wt)
4158{
4159    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4160    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4161    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4162
4163    pwd->w[0]  = msa_srar_df(DF_WORD, pws->w[0],  pwt->w[0]);
4164    pwd->w[1]  = msa_srar_df(DF_WORD, pws->w[1],  pwt->w[1]);
4165    pwd->w[2]  = msa_srar_df(DF_WORD, pws->w[2],  pwt->w[2]);
4166    pwd->w[3]  = msa_srar_df(DF_WORD, pws->w[3],  pwt->w[3]);
4167}
4168
4169void helper_msa_srar_d(CPUMIPSState *env,
4170                       uint32_t wd, uint32_t ws, uint32_t wt)
4171{
4172    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4173    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4174    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4175
4176    pwd->d[0]  = msa_srar_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
4177    pwd->d[1]  = msa_srar_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
4178}
4179
4180
4181static inline int64_t msa_srl_df(uint32_t df, int64_t arg1, int64_t arg2)
4182{
4183    uint64_t u_arg1 = UNSIGNED(arg1, df);
4184    int32_t b_arg2 = BIT_POSITION(arg2, df);
4185    return u_arg1 >> b_arg2;
4186}
4187
4188void helper_msa_srl_b(CPUMIPSState *env,
4189                      uint32_t wd, uint32_t ws, uint32_t wt)
4190{
4191    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4192    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4193    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4194
4195    pwd->b[0]  = msa_srl_df(DF_BYTE, pws->b[0],  pwt->b[0]);
4196    pwd->b[1]  = msa_srl_df(DF_BYTE, pws->b[1],  pwt->b[1]);
4197    pwd->b[2]  = msa_srl_df(DF_BYTE, pws->b[2],  pwt->b[2]);
4198    pwd->b[3]  = msa_srl_df(DF_BYTE, pws->b[3],  pwt->b[3]);
4199    pwd->b[4]  = msa_srl_df(DF_BYTE, pws->b[4],  pwt->b[4]);
4200    pwd->b[5]  = msa_srl_df(DF_BYTE, pws->b[5],  pwt->b[5]);
4201    pwd->b[6]  = msa_srl_df(DF_BYTE, pws->b[6],  pwt->b[6]);
4202    pwd->b[7]  = msa_srl_df(DF_BYTE, pws->b[7],  pwt->b[7]);
4203    pwd->b[8]  = msa_srl_df(DF_BYTE, pws->b[8],  pwt->b[8]);
4204    pwd->b[9]  = msa_srl_df(DF_BYTE, pws->b[9],  pwt->b[9]);
4205    pwd->b[10] = msa_srl_df(DF_BYTE, pws->b[10], pwt->b[10]);
4206    pwd->b[11] = msa_srl_df(DF_BYTE, pws->b[11], pwt->b[11]);
4207    pwd->b[12] = msa_srl_df(DF_BYTE, pws->b[12], pwt->b[12]);
4208    pwd->b[13] = msa_srl_df(DF_BYTE, pws->b[13], pwt->b[13]);
4209    pwd->b[14] = msa_srl_df(DF_BYTE, pws->b[14], pwt->b[14]);
4210    pwd->b[15] = msa_srl_df(DF_BYTE, pws->b[15], pwt->b[15]);
4211}
4212
4213void helper_msa_srl_h(CPUMIPSState *env,
4214                      uint32_t wd, uint32_t ws, uint32_t wt)
4215{
4216    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4217    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4218    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4219
4220    pwd->h[0]  = msa_srl_df(DF_HALF, pws->h[0],  pwt->h[0]);
4221    pwd->h[1]  = msa_srl_df(DF_HALF, pws->h[1],  pwt->h[1]);
4222    pwd->h[2]  = msa_srl_df(DF_HALF, pws->h[2],  pwt->h[2]);
4223    pwd->h[3]  = msa_srl_df(DF_HALF, pws->h[3],  pwt->h[3]);
4224    pwd->h[4]  = msa_srl_df(DF_HALF, pws->h[4],  pwt->h[4]);
4225    pwd->h[5]  = msa_srl_df(DF_HALF, pws->h[5],  pwt->h[5]);
4226    pwd->h[6]  = msa_srl_df(DF_HALF, pws->h[6],  pwt->h[6]);
4227    pwd->h[7]  = msa_srl_df(DF_HALF, pws->h[7],  pwt->h[7]);
4228}
4229
4230void helper_msa_srl_w(CPUMIPSState *env,
4231                      uint32_t wd, uint32_t ws, uint32_t wt)
4232{
4233    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4234    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4235    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4236
4237    pwd->w[0]  = msa_srl_df(DF_WORD, pws->w[0],  pwt->w[0]);
4238    pwd->w[1]  = msa_srl_df(DF_WORD, pws->w[1],  pwt->w[1]);
4239    pwd->w[2]  = msa_srl_df(DF_WORD, pws->w[2],  pwt->w[2]);
4240    pwd->w[3]  = msa_srl_df(DF_WORD, pws->w[3],  pwt->w[3]);
4241}
4242
4243void helper_msa_srl_d(CPUMIPSState *env,
4244                      uint32_t wd, uint32_t ws, uint32_t wt)
4245{
4246    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4247    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4248    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4249
4250    pwd->d[0]  = msa_srl_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
4251    pwd->d[1]  = msa_srl_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
4252}
4253
4254
4255static inline int64_t msa_srlr_df(uint32_t df, int64_t arg1, int64_t arg2)
4256{
4257    uint64_t u_arg1 = UNSIGNED(arg1, df);
4258    int32_t b_arg2 = BIT_POSITION(arg2, df);
4259    if (b_arg2 == 0) {
4260        return u_arg1;
4261    } else {
4262        uint64_t r_bit = (u_arg1 >> (b_arg2 - 1)) & 1;
4263        return (u_arg1 >> b_arg2) + r_bit;
4264    }
4265}
4266
4267void helper_msa_srlr_b(CPUMIPSState *env,
4268                       uint32_t wd, uint32_t ws, uint32_t wt)
4269{
4270    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4271    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4272    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4273
4274    pwd->b[0]  = msa_srlr_df(DF_BYTE, pws->b[0],  pwt->b[0]);
4275    pwd->b[1]  = msa_srlr_df(DF_BYTE, pws->b[1],  pwt->b[1]);
4276    pwd->b[2]  = msa_srlr_df(DF_BYTE, pws->b[2],  pwt->b[2]);
4277    pwd->b[3]  = msa_srlr_df(DF_BYTE, pws->b[3],  pwt->b[3]);
4278    pwd->b[4]  = msa_srlr_df(DF_BYTE, pws->b[4],  pwt->b[4]);
4279    pwd->b[5]  = msa_srlr_df(DF_BYTE, pws->b[5],  pwt->b[5]);
4280    pwd->b[6]  = msa_srlr_df(DF_BYTE, pws->b[6],  pwt->b[6]);
4281    pwd->b[7]  = msa_srlr_df(DF_BYTE, pws->b[7],  pwt->b[7]);
4282    pwd->b[8]  = msa_srlr_df(DF_BYTE, pws->b[8],  pwt->b[8]);
4283    pwd->b[9]  = msa_srlr_df(DF_BYTE, pws->b[9],  pwt->b[9]);
4284    pwd->b[10] = msa_srlr_df(DF_BYTE, pws->b[10], pwt->b[10]);
4285    pwd->b[11] = msa_srlr_df(DF_BYTE, pws->b[11], pwt->b[11]);
4286    pwd->b[12] = msa_srlr_df(DF_BYTE, pws->b[12], pwt->b[12]);
4287    pwd->b[13] = msa_srlr_df(DF_BYTE, pws->b[13], pwt->b[13]);
4288    pwd->b[14] = msa_srlr_df(DF_BYTE, pws->b[14], pwt->b[14]);
4289    pwd->b[15] = msa_srlr_df(DF_BYTE, pws->b[15], pwt->b[15]);
4290}
4291
4292void helper_msa_srlr_h(CPUMIPSState *env,
4293                       uint32_t wd, uint32_t ws, uint32_t wt)
4294{
4295    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4296    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4297    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4298
4299    pwd->h[0]  = msa_srlr_df(DF_HALF, pws->h[0],  pwt->h[0]);
4300    pwd->h[1]  = msa_srlr_df(DF_HALF, pws->h[1],  pwt->h[1]);
4301    pwd->h[2]  = msa_srlr_df(DF_HALF, pws->h[2],  pwt->h[2]);
4302    pwd->h[3]  = msa_srlr_df(DF_HALF, pws->h[3],  pwt->h[3]);
4303    pwd->h[4]  = msa_srlr_df(DF_HALF, pws->h[4],  pwt->h[4]);
4304    pwd->h[5]  = msa_srlr_df(DF_HALF, pws->h[5],  pwt->h[5]);
4305    pwd->h[6]  = msa_srlr_df(DF_HALF, pws->h[6],  pwt->h[6]);
4306    pwd->h[7]  = msa_srlr_df(DF_HALF, pws->h[7],  pwt->h[7]);
4307}
4308
4309void helper_msa_srlr_w(CPUMIPSState *env,
4310                       uint32_t wd, uint32_t ws, uint32_t wt)
4311{
4312    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4313    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4314    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4315
4316    pwd->w[0]  = msa_srlr_df(DF_WORD, pws->w[0],  pwt->w[0]);
4317    pwd->w[1]  = msa_srlr_df(DF_WORD, pws->w[1],  pwt->w[1]);
4318    pwd->w[2]  = msa_srlr_df(DF_WORD, pws->w[2],  pwt->w[2]);
4319    pwd->w[3]  = msa_srlr_df(DF_WORD, pws->w[3],  pwt->w[3]);
4320}
4321
4322void helper_msa_srlr_d(CPUMIPSState *env,
4323                       uint32_t wd, uint32_t ws, uint32_t wt)
4324{
4325    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4326    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4327    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
4328
4329    pwd->d[0]  = msa_srlr_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
4330    pwd->d[1]  = msa_srlr_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
4331}
4332
4333
4334#define MSA_FN_IMM8(FUNC, DEST, OPERATION)                              \
4335void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws,   \
4336        uint32_t i8)                                                    \
4337{                                                                       \
4338    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);                          \
4339    wr_t *pws = &(env->active_fpu.fpr[ws].wr);                          \
4340    uint32_t i;                                                         \
4341    for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {                        \
4342        DEST = OPERATION;                                               \
4343    }                                                                   \
4344}
4345
4346MSA_FN_IMM8(andi_b, pwd->b[i], pws->b[i] & i8)
4347MSA_FN_IMM8(ori_b, pwd->b[i], pws->b[i] | i8)
4348MSA_FN_IMM8(nori_b, pwd->b[i], ~(pws->b[i] | i8))
4349MSA_FN_IMM8(xori_b, pwd->b[i], pws->b[i] ^ i8)
4350
4351#define BIT_MOVE_IF_NOT_ZERO(dest, arg1, arg2, df) \
4352            UNSIGNED(((dest & (~arg2)) | (arg1 & arg2)), df)
4353MSA_FN_IMM8(bmnzi_b, pwd->b[i],
4354        BIT_MOVE_IF_NOT_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE))
4355
4356#define BIT_MOVE_IF_ZERO(dest, arg1, arg2, df) \
4357            UNSIGNED((dest & arg2) | (arg1 & (~arg2)), df)
4358MSA_FN_IMM8(bmzi_b, pwd->b[i],
4359        BIT_MOVE_IF_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE))
4360
4361#define BIT_SELECT(dest, arg1, arg2, df) \
4362            UNSIGNED((arg1 & (~dest)) | (arg2 & dest), df)
4363MSA_FN_IMM8(bseli_b, pwd->b[i],
4364        BIT_SELECT(pwd->b[i], pws->b[i], i8, DF_BYTE))
4365
4366#undef BIT_SELECT
4367#undef BIT_MOVE_IF_ZERO
4368#undef BIT_MOVE_IF_NOT_ZERO
4369#undef MSA_FN_IMM8
4370
4371#define SHF_POS(i, imm) (((i) & 0xfc) + (((imm) >> (2 * ((i) & 0x03))) & 0x03))
4372
4373void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4374                       uint32_t ws, uint32_t imm)
4375{
4376    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4377    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4378    wr_t wx, *pwx = &wx;
4379    uint32_t i;
4380
4381    switch (df) {
4382    case DF_BYTE:
4383        for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {
4384            pwx->b[i] = pws->b[SHF_POS(i, imm)];
4385        }
4386        break;
4387    case DF_HALF:
4388        for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {
4389            pwx->h[i] = pws->h[SHF_POS(i, imm)];
4390        }
4391        break;
4392    case DF_WORD:
4393        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4394            pwx->w[i] = pws->w[SHF_POS(i, imm)];
4395        }
4396        break;
4397    default:
4398        assert(0);
4399    }
4400    msa_move_v(pwd, pwx);
4401}
4402
4403static inline int64_t msa_subv_df(uint32_t df, int64_t arg1, int64_t arg2)
4404{
4405    return arg1 - arg2;
4406}
4407
4408#define MSA_BINOP_IMM_DF(helper, func)                                  \
4409void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df,       \
4410                        uint32_t wd, uint32_t ws, int32_t u5)           \
4411{                                                                       \
4412    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);                          \
4413    wr_t *pws = &(env->active_fpu.fpr[ws].wr);                          \
4414    uint32_t i;                                                         \
4415                                                                        \
4416    switch (df) {                                                       \
4417    case DF_BYTE:                                                       \
4418        for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {                    \
4419            pwd->b[i] = msa_ ## func ## _df(df, pws->b[i], u5);         \
4420        }                                                               \
4421        break;                                                          \
4422    case DF_HALF:                                                       \
4423        for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {                    \
4424            pwd->h[i] = msa_ ## func ## _df(df, pws->h[i], u5);         \
4425        }                                                               \
4426        break;                                                          \
4427    case DF_WORD:                                                       \
4428        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {                    \
4429            pwd->w[i] = msa_ ## func ## _df(df, pws->w[i], u5);         \
4430        }                                                               \
4431        break;                                                          \
4432    case DF_DOUBLE:                                                     \
4433        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {                  \
4434            pwd->d[i] = msa_ ## func ## _df(df, pws->d[i], u5);         \
4435        }                                                               \
4436        break;                                                          \
4437    default:                                                            \
4438        assert(0);                                                      \
4439    }                                                                   \
4440}
4441
4442MSA_BINOP_IMM_DF(addvi, addv)
4443MSA_BINOP_IMM_DF(subvi, subv)
4444MSA_BINOP_IMM_DF(ceqi, ceq)
4445MSA_BINOP_IMM_DF(clei_s, cle_s)
4446MSA_BINOP_IMM_DF(clei_u, cle_u)
4447MSA_BINOP_IMM_DF(clti_s, clt_s)
4448MSA_BINOP_IMM_DF(clti_u, clt_u)
4449MSA_BINOP_IMM_DF(maxi_s, max_s)
4450MSA_BINOP_IMM_DF(maxi_u, max_u)
4451MSA_BINOP_IMM_DF(mini_s, min_s)
4452MSA_BINOP_IMM_DF(mini_u, min_u)
4453#undef MSA_BINOP_IMM_DF
4454
4455void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4456                       int32_t s10)
4457{
4458    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4459    uint32_t i;
4460
4461    switch (df) {
4462    case DF_BYTE:
4463        for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {
4464            pwd->b[i] = (int8_t)s10;
4465        }
4466        break;
4467    case DF_HALF:
4468        for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {
4469            pwd->h[i] = (int16_t)s10;
4470        }
4471        break;
4472    case DF_WORD:
4473        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
4474            pwd->w[i] = (int32_t)s10;
4475        }
4476        break;
4477    case DF_DOUBLE:
4478        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
4479            pwd->d[i] = (int64_t)s10;
4480        }
4481       break;
4482    default:
4483        assert(0);
4484    }
4485}
4486
4487static inline int64_t msa_sat_s_df(uint32_t df, int64_t arg, uint32_t m)
4488{
4489    return arg < M_MIN_INT(m + 1) ? M_MIN_INT(m + 1) :
4490                                    arg > M_MAX_INT(m + 1) ? M_MAX_INT(m + 1) :
4491                                                             arg;
4492}
4493
4494static inline int64_t msa_sat_u_df(uint32_t df, int64_t arg, uint32_t m)
4495{
4496    uint64_t u_arg = UNSIGNED(arg, df);
4497    return  u_arg < M_MAX_UINT(m + 1) ? u_arg :
4498                                        M_MAX_UINT(m + 1);
4499}
4500
4501#define MSA_BINOP_IMMU_DF(helper, func)                                  \
4502void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, uint32_t wd, \
4503                       uint32_t ws, uint32_t u5)                        \
4504{                                                                       \
4505    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);                          \
4506    wr_t *pws = &(env->active_fpu.fpr[ws].wr);                          \
4507    uint32_t i;                                                         \
4508                                                                        \
4509    switch (df) {                                                       \
4510    case DF_BYTE:                                                       \
4511        for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {                    \
4512            pwd->b[i] = msa_ ## func ## _df(df, pws->b[i], u5);         \
4513        }                                                               \
4514        break;                                                          \
4515    case DF_HALF:                                                       \
4516        for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {                    \
4517            pwd->h[i] = msa_ ## func ## _df(df, pws->h[i], u5);         \
4518        }                                                               \
4519        break;                                                          \
4520    case DF_WORD:                                                       \
4521        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {                    \
4522            pwd->w[i] = msa_ ## func ## _df(df, pws->w[i], u5);         \
4523        }                                                               \
4524        break;                                                          \
4525    case DF_DOUBLE:                                                     \
4526        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {                  \
4527            pwd->d[i] = msa_ ## func ## _df(df, pws->d[i], u5);         \
4528        }                                                               \
4529        break;                                                          \
4530    default:                                                            \
4531        assert(0);                                                      \
4532    }                                                                   \
4533}
4534
4535MSA_BINOP_IMMU_DF(slli, sll)
4536MSA_BINOP_IMMU_DF(srai, sra)
4537MSA_BINOP_IMMU_DF(srli, srl)
4538MSA_BINOP_IMMU_DF(bclri, bclr)
4539MSA_BINOP_IMMU_DF(bseti, bset)
4540MSA_BINOP_IMMU_DF(bnegi, bneg)
4541MSA_BINOP_IMMU_DF(sat_s, sat_s)
4542MSA_BINOP_IMMU_DF(sat_u, sat_u)
4543MSA_BINOP_IMMU_DF(srari, srar)
4544MSA_BINOP_IMMU_DF(srlri, srlr)
4545#undef MSA_BINOP_IMMU_DF
4546
4547#define MSA_TEROP_IMMU_DF(helper, func)                                  \
4548void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df,       \
4549                                  uint32_t wd, uint32_t ws, uint32_t u5) \
4550{                                                                       \
4551    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);                          \
4552    wr_t *pws = &(env->active_fpu.fpr[ws].wr);                          \
4553    uint32_t i;                                                         \
4554                                                                        \
4555    switch (df) {                                                       \
4556    case DF_BYTE:                                                       \
4557        for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {                    \
4558            pwd->b[i] = msa_ ## func ## _df(df, pwd->b[i], pws->b[i],   \
4559                                            u5);                        \
4560        }                                                               \
4561        break;                                                          \
4562    case DF_HALF:                                                       \
4563        for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {                    \
4564            pwd->h[i] = msa_ ## func ## _df(df, pwd->h[i], pws->h[i],   \
4565                                            u5);                        \
4566        }                                                               \
4567        break;                                                          \
4568    case DF_WORD:                                                       \
4569        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {                    \
4570            pwd->w[i] = msa_ ## func ## _df(df, pwd->w[i], pws->w[i],   \
4571                                            u5);                        \
4572        }                                                               \
4573        break;                                                          \
4574    case DF_DOUBLE:                                                     \
4575        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {                  \
4576            pwd->d[i] = msa_ ## func ## _df(df, pwd->d[i], pws->d[i],   \
4577                                            u5);                        \
4578        }                                                               \
4579        break;                                                          \
4580    default:                                                            \
4581        assert(0);                                                      \
4582    }                                                                   \
4583}
4584
4585MSA_TEROP_IMMU_DF(binsli, binsl)
4586MSA_TEROP_IMMU_DF(binsri, binsr)
4587#undef MSA_TEROP_IMMU_DF
4588
4589static inline int64_t msa_subs_s_df(uint32_t df, int64_t arg1, int64_t arg2)
4590{
4591    int64_t max_int = DF_MAX_INT(df);
4592    int64_t min_int = DF_MIN_INT(df);
4593    if (arg2 > 0) {
4594        return (min_int + arg2 < arg1) ? arg1 - arg2 : min_int;
4595    } else {
4596        return (arg1 < max_int + arg2) ? arg1 - arg2 : max_int;
4597    }
4598}
4599
4600static inline int64_t msa_subs_u_df(uint32_t df, int64_t arg1, int64_t arg2)
4601{
4602    uint64_t u_arg1 = UNSIGNED(arg1, df);
4603    uint64_t u_arg2 = UNSIGNED(arg2, df);
4604    return (u_arg1 > u_arg2) ? u_arg1 - u_arg2 : 0;
4605}
4606
4607static inline int64_t msa_subsus_u_df(uint32_t df, int64_t arg1, int64_t arg2)
4608{
4609    uint64_t u_arg1 = UNSIGNED(arg1, df);
4610    uint64_t max_uint = DF_MAX_UINT(df);
4611    if (arg2 >= 0) {
4612        uint64_t u_arg2 = (uint64_t)arg2;
4613        return (u_arg1 > u_arg2) ?
4614            (int64_t)(u_arg1 - u_arg2) :
4615            0;
4616    } else {
4617        uint64_t u_arg2 = (uint64_t)(-arg2);
4618        return (u_arg1 < max_uint - u_arg2) ?
4619            (int64_t)(u_arg1 + u_arg2) :
4620            (int64_t)max_uint;
4621    }
4622}
4623
4624static inline int64_t msa_subsuu_s_df(uint32_t df, int64_t arg1, int64_t arg2)
4625{
4626    uint64_t u_arg1 = UNSIGNED(arg1, df);
4627    uint64_t u_arg2 = UNSIGNED(arg2, df);
4628    int64_t max_int = DF_MAX_INT(df);
4629    int64_t min_int = DF_MIN_INT(df);
4630    if (u_arg1 > u_arg2) {
4631        return u_arg1 - u_arg2 < (uint64_t)max_int ?
4632            (int64_t)(u_arg1 - u_arg2) :
4633            max_int;
4634    } else {
4635        return u_arg2 - u_arg1 < (uint64_t)(-min_int) ?
4636            (int64_t)(u_arg1 - u_arg2) :
4637            min_int;
4638    }
4639}
4640
4641static inline int64_t msa_mulv_df(uint32_t df, int64_t arg1, int64_t arg2)
4642{
4643    return arg1 * arg2;
4644}
4645
4646#define SIGNED_EXTRACT(e, o, a, df)     \
4647    do {                                \
4648        e = SIGNED_EVEN(a, df);         \
4649        o = SIGNED_ODD(a, df);          \
4650    } while (0)
4651
4652#define UNSIGNED_EXTRACT(e, o, a, df)   \
4653    do {                                \
4654        e = UNSIGNED_EVEN(a, df);       \
4655        o = UNSIGNED_ODD(a, df);        \
4656    } while (0)
4657
4658static inline int64_t msa_dotp_s_df(uint32_t df, int64_t arg1, int64_t arg2)
4659{
4660    int64_t even_arg1;
4661    int64_t even_arg2;
4662    int64_t odd_arg1;
4663    int64_t odd_arg2;
4664    SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
4665    SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
4666    return (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
4667}
4668
4669static inline int64_t msa_dotp_u_df(uint32_t df, int64_t arg1, int64_t arg2)
4670{
4671    int64_t even_arg1;
4672    int64_t even_arg2;
4673    int64_t odd_arg1;
4674    int64_t odd_arg2;
4675    UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
4676    UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
4677    return (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
4678}
4679
4680#define CONCATENATE_AND_SLIDE(s, k)             \
4681    do {                                        \
4682        for (i = 0; i < s; i++) {               \
4683            v[i]     = pws->b[s * k + i];       \
4684            v[i + s] = pwd->b[s * k + i];       \
4685        }                                       \
4686        for (i = 0; i < s; i++) {               \
4687            pwd->b[s * k + i] = v[i + n];       \
4688        }                                       \
4689    } while (0)
4690
4691static inline void msa_sld_df(uint32_t df, wr_t *pwd,
4692                              wr_t *pws, target_ulong rt)
4693{
4694    uint32_t n = rt % DF_ELEMENTS(df);
4695    uint8_t v[64];
4696    uint32_t i, k;
4697
4698    switch (df) {
4699    case DF_BYTE:
4700        CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_BYTE), 0);
4701        break;
4702    case DF_HALF:
4703        for (k = 0; k < 2; k++) {
4704            CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_HALF), k);
4705        }
4706        break;
4707    case DF_WORD:
4708        for (k = 0; k < 4; k++) {
4709            CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_WORD), k);
4710        }
4711        break;
4712    case DF_DOUBLE:
4713        for (k = 0; k < 8; k++) {
4714            CONCATENATE_AND_SLIDE(DF_ELEMENTS(DF_DOUBLE), k);
4715        }
4716        break;
4717    default:
4718        assert(0);
4719    }
4720}
4721
4722static inline int64_t msa_mul_q_df(uint32_t df, int64_t arg1, int64_t arg2)
4723{
4724    int64_t q_min = DF_MIN_INT(df);
4725    int64_t q_max = DF_MAX_INT(df);
4726
4727    if (arg1 == q_min && arg2 == q_min) {
4728        return q_max;
4729    }
4730    return (arg1 * arg2) >> (DF_BITS(df) - 1);
4731}
4732
4733static inline int64_t msa_mulr_q_df(uint32_t df, int64_t arg1, int64_t arg2)
4734{
4735    int64_t q_min = DF_MIN_INT(df);
4736    int64_t q_max = DF_MAX_INT(df);
4737    int64_t r_bit = 1 << (DF_BITS(df) - 2);
4738
4739    if (arg1 == q_min && arg2 == q_min) {
4740        return q_max;
4741    }
4742    return (arg1 * arg2 + r_bit) >> (DF_BITS(df) - 1);
4743}
4744
4745#define MSA_BINOP_DF(func) \
4746void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df,         \
4747                                uint32_t wd, uint32_t ws, uint32_t wt)  \
4748{                                                                       \
4749    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);                          \
4750    wr_t *pws = &(env->active_fpu.fpr[ws].wr);                          \
4751    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);                          \
4752                                                                        \
4753    switch (df) {                                                       \
4754    case DF_BYTE:                                                       \
4755        pwd->b[0]  = msa_ ## func ## _df(df, pws->b[0],  pwt->b[0]);    \
4756        pwd->b[1]  = msa_ ## func ## _df(df, pws->b[1],  pwt->b[1]);    \
4757        pwd->b[2]  = msa_ ## func ## _df(df, pws->b[2],  pwt->b[2]);    \
4758        pwd->b[3]  = msa_ ## func ## _df(df, pws->b[3],  pwt->b[3]);    \
4759        pwd->b[4]  = msa_ ## func ## _df(df, pws->b[4],  pwt->b[4]);    \
4760        pwd->b[5]  = msa_ ## func ## _df(df, pws->b[5],  pwt->b[5]);    \
4761        pwd->b[6]  = msa_ ## func ## _df(df, pws->b[6],  pwt->b[6]);    \
4762        pwd->b[7]  = msa_ ## func ## _df(df, pws->b[7],  pwt->b[7]);    \
4763        pwd->b[8]  = msa_ ## func ## _df(df, pws->b[8],  pwt->b[8]);    \
4764        pwd->b[9]  = msa_ ## func ## _df(df, pws->b[9],  pwt->b[9]);    \
4765        pwd->b[10] = msa_ ## func ## _df(df, pws->b[10], pwt->b[10]);   \
4766        pwd->b[11] = msa_ ## func ## _df(df, pws->b[11], pwt->b[11]);   \
4767        pwd->b[12] = msa_ ## func ## _df(df, pws->b[12], pwt->b[12]);   \
4768        pwd->b[13] = msa_ ## func ## _df(df, pws->b[13], pwt->b[13]);   \
4769        pwd->b[14] = msa_ ## func ## _df(df, pws->b[14], pwt->b[14]);   \
4770        pwd->b[15] = msa_ ## func ## _df(df, pws->b[15], pwt->b[15]);   \
4771        break;                                                          \
4772    case DF_HALF:                                                       \
4773        pwd->h[0] = msa_ ## func ## _df(df, pws->h[0], pwt->h[0]);      \
4774        pwd->h[1] = msa_ ## func ## _df(df, pws->h[1], pwt->h[1]);      \
4775        pwd->h[2] = msa_ ## func ## _df(df, pws->h[2], pwt->h[2]);      \
4776        pwd->h[3] = msa_ ## func ## _df(df, pws->h[3], pwt->h[3]);      \
4777        pwd->h[4] = msa_ ## func ## _df(df, pws->h[4], pwt->h[4]);      \
4778        pwd->h[5] = msa_ ## func ## _df(df, pws->h[5], pwt->h[5]);      \
4779        pwd->h[6] = msa_ ## func ## _df(df, pws->h[6], pwt->h[6]);      \
4780        pwd->h[7] = msa_ ## func ## _df(df, pws->h[7], pwt->h[7]);      \
4781        break;                                                          \
4782    case DF_WORD:                                                       \
4783        pwd->w[0] = msa_ ## func ## _df(df, pws->w[0], pwt->w[0]);      \
4784        pwd->w[1] = msa_ ## func ## _df(df, pws->w[1], pwt->w[1]);      \
4785        pwd->w[2] = msa_ ## func ## _df(df, pws->w[2], pwt->w[2]);      \
4786        pwd->w[3] = msa_ ## func ## _df(df, pws->w[3], pwt->w[3]);      \
4787        break;                                                          \
4788    case DF_DOUBLE:                                                     \
4789        pwd->d[0] = msa_ ## func ## _df(df, pws->d[0], pwt->d[0]);      \
4790        pwd->d[1] = msa_ ## func ## _df(df, pws->d[1], pwt->d[1]);      \
4791        break;                                                          \
4792    default:                                                            \
4793        assert(0);                                                      \
4794    }                                                                   \
4795}
4796
4797MSA_BINOP_DF(subv)
4798MSA_BINOP_DF(subs_s)
4799MSA_BINOP_DF(subs_u)
4800MSA_BINOP_DF(subsus_u)
4801MSA_BINOP_DF(subsuu_s)
4802MSA_BINOP_DF(mulv)
4803MSA_BINOP_DF(dotp_s)
4804MSA_BINOP_DF(dotp_u)
4805
4806MSA_BINOP_DF(mul_q)
4807MSA_BINOP_DF(mulr_q)
4808#undef MSA_BINOP_DF
4809
4810void helper_msa_sld_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
4811                       uint32_t ws, uint32_t rt)
4812{
4813    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4814    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
4815
4816    msa_sld_df(df, pwd, pws, env->active_tc.gpr[rt]);
4817}
4818
4819static inline int64_t msa_maddv_df(uint32_t df, int64_t dest, int64_t arg1,
4820                                   int64_t arg2)
4821{
4822    return dest + arg1 * arg2;
4823}
4824
4825static inline int64_t msa_msubv_df(uint32_t df, int64_t dest, int64_t arg1,
4826                                   int64_t arg2)
4827{
4828    return dest - arg1 * arg2;
4829}
4830
4831static inline int64_t msa_dpadd_s_df(uint32_t df, int64_t dest, int64_t arg1,
4832                                     int64_t arg2)
4833{
4834    int64_t even_arg1;
4835    int64_t even_arg2;
4836    int64_t odd_arg1;
4837    int64_t odd_arg2;
4838    SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
4839    SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
4840    return dest + (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
4841}
4842
4843static inline int64_t msa_dpadd_u_df(uint32_t df, int64_t dest, int64_t arg1,
4844                                     int64_t arg2)
4845{
4846    int64_t even_arg1;
4847    int64_t even_arg2;
4848    int64_t odd_arg1;
4849    int64_t odd_arg2;
4850    UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
4851    UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
4852    return dest + (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
4853}
4854
4855static inline int64_t msa_dpsub_s_df(uint32_t df, int64_t dest, int64_t arg1,
4856                                     int64_t arg2)
4857{
4858    int64_t even_arg1;
4859    int64_t even_arg2;
4860    int64_t odd_arg1;
4861    int64_t odd_arg2;
4862    SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
4863    SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
4864    return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2));
4865}
4866
4867static inline int64_t msa_dpsub_u_df(uint32_t df, int64_t dest, int64_t arg1,
4868                                     int64_t arg2)
4869{
4870    int64_t even_arg1;
4871    int64_t even_arg2;
4872    int64_t odd_arg1;
4873    int64_t odd_arg2;
4874    UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
4875    UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
4876    return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2));
4877}
4878
4879static inline int64_t msa_madd_q_df(uint32_t df, int64_t dest, int64_t arg1,
4880                                    int64_t arg2)
4881{
4882    int64_t q_prod, q_ret;
4883
4884    int64_t q_max = DF_MAX_INT(df);
4885    int64_t q_min = DF_MIN_INT(df);
4886
4887    q_prod = arg1 * arg2;
4888    q_ret = ((dest << (DF_BITS(df) - 1)) + q_prod) >> (DF_BITS(df) - 1);
4889
4890    return (q_ret < q_min) ? q_min : (q_max < q_ret) ? q_max : q_ret;
4891}
4892
4893static inline int64_t msa_msub_q_df(uint32_t df, int64_t dest, int64_t arg1,
4894                                    int64_t arg2)
4895{
4896    int64_t q_prod, q_ret;
4897
4898    int64_t q_max = DF_MAX_INT(df);
4899    int64_t q_min = DF_MIN_INT(df);
4900
4901    q_prod = arg1 * arg2;
4902    q_ret = ((dest << (DF_BITS(df) - 1)) - q_prod) >> (DF_BITS(df) - 1);
4903
4904    return (q_ret < q_min) ? q_min : (q_max < q_ret) ? q_max : q_ret;
4905}
4906
4907static inline int64_t msa_maddr_q_df(uint32_t df, int64_t dest, int64_t arg1,
4908                                     int64_t arg2)
4909{
4910    int64_t q_prod, q_ret;
4911
4912    int64_t q_max = DF_MAX_INT(df);
4913    int64_t q_min = DF_MIN_INT(df);
4914    int64_t r_bit = 1 << (DF_BITS(df) - 2);
4915
4916    q_prod = arg1 * arg2;
4917    q_ret = ((dest << (DF_BITS(df) - 1)) + q_prod + r_bit) >> (DF_BITS(df) - 1);
4918
4919    return (q_ret < q_min) ? q_min : (q_max < q_ret) ? q_max : q_ret;
4920}
4921
4922static inline int64_t msa_msubr_q_df(uint32_t df, int64_t dest, int64_t arg1,
4923                                     int64_t arg2)
4924{
4925    int64_t q_prod, q_ret;
4926
4927    int64_t q_max = DF_MAX_INT(df);
4928    int64_t q_min = DF_MIN_INT(df);
4929    int64_t r_bit = 1 << (DF_BITS(df) - 2);
4930
4931    q_prod = arg1 * arg2;
4932    q_ret = ((dest << (DF_BITS(df) - 1)) - q_prod + r_bit) >> (DF_BITS(df) - 1);
4933
4934    return (q_ret < q_min) ? q_min : (q_max < q_ret) ? q_max : q_ret;
4935}
4936
4937#define MSA_TEROP_DF(func) \
4938void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, uint32_t wd,  \
4939                                uint32_t ws, uint32_t wt)                     \
4940{                                                                             \
4941    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);                                \
4942    wr_t *pws = &(env->active_fpu.fpr[ws].wr);                                \
4943    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);                                \
4944                                                                              \
4945    switch (df) {                                                             \
4946    case DF_BYTE:                                                             \
4947        pwd->b[0]  = msa_ ## func ## _df(df, pwd->b[0],  pws->b[0],           \
4948                                             pwt->b[0]);                      \
4949        pwd->b[1]  = msa_ ## func ## _df(df, pwd->b[1],  pws->b[1],           \
4950                                             pwt->b[1]);                      \
4951        pwd->b[2]  = msa_ ## func ## _df(df, pwd->b[2],  pws->b[2],           \
4952                                             pwt->b[2]);                      \
4953        pwd->b[3]  = msa_ ## func ## _df(df, pwd->b[3],  pws->b[3],           \
4954                                             pwt->b[3]);                      \
4955        pwd->b[4]  = msa_ ## func ## _df(df, pwd->b[4],  pws->b[4],           \
4956                                             pwt->b[4]);                      \
4957        pwd->b[5]  = msa_ ## func ## _df(df, pwd->b[5],  pws->b[5],           \
4958                                             pwt->b[5]);                      \
4959        pwd->b[6]  = msa_ ## func ## _df(df, pwd->b[6],  pws->b[6],           \
4960                                             pwt->b[6]);                      \
4961        pwd->b[7]  = msa_ ## func ## _df(df, pwd->b[7],  pws->b[7],           \
4962                                             pwt->b[7]);                      \
4963        pwd->b[8]  = msa_ ## func ## _df(df, pwd->b[8],  pws->b[8],           \
4964                                             pwt->b[8]);                      \
4965        pwd->b[9]  = msa_ ## func ## _df(df, pwd->b[9],  pws->b[9],           \
4966                                             pwt->b[9]);                      \
4967        pwd->b[10] = msa_ ## func ## _df(df, pwd->b[10], pws->b[10],          \
4968                                             pwt->b[10]);                     \
4969        pwd->b[11] = msa_ ## func ## _df(df, pwd->b[11], pws->b[11],          \
4970                                             pwt->b[11]);                     \
4971        pwd->b[12] = msa_ ## func ## _df(df, pwd->b[12], pws->b[12],          \
4972                                             pwt->b[12]);                     \
4973        pwd->b[13] = msa_ ## func ## _df(df, pwd->b[13], pws->b[13],          \
4974                                             pwt->b[13]);                     \
4975        pwd->b[14] = msa_ ## func ## _df(df, pwd->b[14], pws->b[14],          \
4976                                             pwt->b[14]);                     \
4977        pwd->b[15] = msa_ ## func ## _df(df, pwd->b[15], pws->b[15],          \
4978                                             pwt->b[15]);                     \
4979        break;                                                                \
4980    case DF_HALF:                                                             \
4981        pwd->h[0] = msa_ ## func ## _df(df, pwd->h[0], pws->h[0], pwt->h[0]); \
4982        pwd->h[1] = msa_ ## func ## _df(df, pwd->h[1], pws->h[1], pwt->h[1]); \
4983        pwd->h[2] = msa_ ## func ## _df(df, pwd->h[2], pws->h[2], pwt->h[2]); \
4984        pwd->h[3] = msa_ ## func ## _df(df, pwd->h[3], pws->h[3], pwt->h[3]); \
4985        pwd->h[4] = msa_ ## func ## _df(df, pwd->h[4], pws->h[4], pwt->h[4]); \
4986        pwd->h[5] = msa_ ## func ## _df(df, pwd->h[5], pws->h[5], pwt->h[5]); \
4987        pwd->h[6] = msa_ ## func ## _df(df, pwd->h[6], pws->h[6], pwt->h[6]); \
4988        pwd->h[7] = msa_ ## func ## _df(df, pwd->h[7], pws->h[7], pwt->h[7]); \
4989        break;                                                                \
4990    case DF_WORD:                                                             \
4991        pwd->w[0] = msa_ ## func ## _df(df, pwd->w[0], pws->w[0], pwt->w[0]); \
4992        pwd->w[1] = msa_ ## func ## _df(df, pwd->w[1], pws->w[1], pwt->w[1]); \
4993        pwd->w[2] = msa_ ## func ## _df(df, pwd->w[2], pws->w[2], pwt->w[2]); \
4994        pwd->w[3] = msa_ ## func ## _df(df, pwd->w[3], pws->w[3], pwt->w[3]); \
4995        break;                                                                \
4996    case DF_DOUBLE:                                                           \
4997        pwd->d[0] = msa_ ## func ## _df(df, pwd->d[0], pws->d[0], pwt->d[0]); \
4998        pwd->d[1] = msa_ ## func ## _df(df, pwd->d[1], pws->d[1], pwt->d[1]); \
4999        break;                                                                \
5000    default:                                                                  \
5001        assert(0);                                                            \
5002    }                                                                         \
5003}
5004
5005MSA_TEROP_DF(maddv)
5006MSA_TEROP_DF(msubv)
5007MSA_TEROP_DF(dpadd_s)
5008MSA_TEROP_DF(dpadd_u)
5009MSA_TEROP_DF(dpsub_s)
5010MSA_TEROP_DF(dpsub_u)
5011MSA_TEROP_DF(binsl)
5012MSA_TEROP_DF(binsr)
5013MSA_TEROP_DF(madd_q)
5014MSA_TEROP_DF(msub_q)
5015MSA_TEROP_DF(maddr_q)
5016MSA_TEROP_DF(msubr_q)
5017#undef MSA_TEROP_DF
5018
5019static inline void msa_splat_df(uint32_t df, wr_t *pwd,
5020                                wr_t *pws, target_ulong rt)
5021{
5022    uint32_t n = rt % DF_ELEMENTS(df);
5023    uint32_t i;
5024
5025    switch (df) {
5026    case DF_BYTE:
5027        for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {
5028            pwd->b[i] = pws->b[n];
5029        }
5030        break;
5031    case DF_HALF:
5032        for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {
5033            pwd->h[i] = pws->h[n];
5034        }
5035        break;
5036    case DF_WORD:
5037        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
5038            pwd->w[i] = pws->w[n];
5039        }
5040        break;
5041    case DF_DOUBLE:
5042        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
5043            pwd->d[i] = pws->d[n];
5044        }
5045       break;
5046    default:
5047        assert(0);
5048    }
5049}
5050
5051void helper_msa_splat_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
5052                         uint32_t ws, uint32_t rt)
5053{
5054    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
5055    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
5056
5057    msa_splat_df(df, pwd, pws, env->active_tc.gpr[rt]);
5058}
5059
5060#define MSA_DO_B MSA_DO(b)
5061#define MSA_DO_H MSA_DO(h)
5062#define MSA_DO_W MSA_DO(w)
5063#define MSA_DO_D MSA_DO(d)
5064
5065#define MSA_LOOP_B MSA_LOOP(B)
5066#define MSA_LOOP_H MSA_LOOP(H)
5067#define MSA_LOOP_W MSA_LOOP(W)
5068#define MSA_LOOP_D MSA_LOOP(D)
5069
5070#define MSA_LOOP_COND_B MSA_LOOP_COND(DF_BYTE)
5071#define MSA_LOOP_COND_H MSA_LOOP_COND(DF_HALF)
5072#define MSA_LOOP_COND_W MSA_LOOP_COND(DF_WORD)
5073#define MSA_LOOP_COND_D MSA_LOOP_COND(DF_DOUBLE)
5074
5075#define MSA_LOOP(DF) \
5076    do { \
5077        for (i = 0; i < (MSA_LOOP_COND_ ## DF) ; i++) { \
5078            MSA_DO_ ## DF; \
5079        } \
5080    } while (0)
5081
5082#define MSA_FN_DF(FUNC)                                             \
5083void helper_msa_##FUNC(CPUMIPSState *env, uint32_t df, uint32_t wd, \
5084        uint32_t ws, uint32_t wt)                                   \
5085{                                                                   \
5086    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);                      \
5087    wr_t *pws = &(env->active_fpu.fpr[ws].wr);                      \
5088    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);                      \
5089    wr_t wx, *pwx = &wx;                                            \
5090    uint32_t i;                                                     \
5091    switch (df) {                                                   \
5092    case DF_BYTE:                                                   \
5093        MSA_LOOP_B;                                                 \
5094        break;                                                      \
5095    case DF_HALF:                                                   \
5096        MSA_LOOP_H;                                                 \
5097        break;                                                      \
5098    case DF_WORD:                                                   \
5099        MSA_LOOP_W;                                                 \
5100        break;                                                      \
5101    case DF_DOUBLE:                                                 \
5102        MSA_LOOP_D;                                                 \
5103        break;                                                      \
5104    default:                                                        \
5105        assert(0);                                                  \
5106    }                                                               \
5107    msa_move_v(pwd, pwx);                                           \
5108}
5109
5110#define MSA_LOOP_COND(DF) \
5111            (DF_ELEMENTS(DF) / 2)
5112
5113#define Rb(pwr, i) (pwr->b[i])
5114#define Lb(pwr, i) (pwr->b[i + DF_ELEMENTS(DF_BYTE) / 2])
5115#define Rh(pwr, i) (pwr->h[i])
5116#define Lh(pwr, i) (pwr->h[i + DF_ELEMENTS(DF_HALF) / 2])
5117#define Rw(pwr, i) (pwr->w[i])
5118#define Lw(pwr, i) (pwr->w[i + DF_ELEMENTS(DF_WORD) / 2])
5119#define Rd(pwr, i) (pwr->d[i])
5120#define Ld(pwr, i) (pwr->d[i + DF_ELEMENTS(DF_DOUBLE) / 2])
5121
5122#undef MSA_LOOP_COND
5123
5124#define MSA_LOOP_COND(DF) \
5125            (DF_ELEMENTS(DF))
5126
5127#define MSA_DO(DF)                                                          \
5128    do {                                                                    \
5129        uint32_t n = DF_ELEMENTS(df);                                       \
5130        uint32_t k = (pwd->DF[i] & 0x3f) % (2 * n);                         \
5131        pwx->DF[i] =                                                        \
5132            (pwd->DF[i] & 0xc0) ? 0 : k < n ? pwt->DF[k] : pws->DF[k - n];  \
5133    } while (0)
5134MSA_FN_DF(vshf_df)
5135#undef MSA_DO
5136#undef MSA_LOOP_COND
5137#undef MSA_FN_DF
5138
5139
5140void helper_msa_sldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
5141                        uint32_t ws, uint32_t n)
5142{
5143    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
5144    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
5145
5146    msa_sld_df(df, pwd, pws, n);
5147}
5148
5149void helper_msa_splati_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
5150                          uint32_t ws, uint32_t n)
5151{
5152    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
5153    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
5154
5155    msa_splat_df(df, pwd, pws, n);
5156}
5157
5158void helper_msa_copy_s_b(CPUMIPSState *env, uint32_t rd,
5159                         uint32_t ws, uint32_t n)
5160{
5161    n %= 16;
5162#if defined(HOST_WORDS_BIGENDIAN)
5163    if (n < 8) {
5164        n = 8 - n - 1;
5165    } else {
5166        n = 24 - n - 1;
5167    }
5168#endif
5169    env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n];
5170}
5171
5172void helper_msa_copy_s_h(CPUMIPSState *env, uint32_t rd,
5173                         uint32_t ws, uint32_t n)
5174{
5175    n %= 8;
5176#if defined(HOST_WORDS_BIGENDIAN)
5177    if (n < 4) {
5178        n = 4 - n - 1;
5179    } else {
5180        n = 12 - n - 1;
5181    }
5182#endif
5183    env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n];
5184}
5185
5186void helper_msa_copy_s_w(CPUMIPSState *env, uint32_t rd,
5187                         uint32_t ws, uint32_t n)
5188{
5189    n %= 4;
5190#if defined(HOST_WORDS_BIGENDIAN)
5191    if (n < 2) {
5192        n = 2 - n - 1;
5193    } else {
5194        n = 6 - n - 1;
5195    }
5196#endif
5197    env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n];
5198}
5199
5200void helper_msa_copy_s_d(CPUMIPSState *env, uint32_t rd,
5201                         uint32_t ws, uint32_t n)
5202{
5203    n %= 2;
5204    env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n];
5205}
5206
5207void helper_msa_copy_u_b(CPUMIPSState *env, uint32_t rd,
5208                         uint32_t ws, uint32_t n)
5209{
5210    n %= 16;
5211#if defined(HOST_WORDS_BIGENDIAN)
5212    if (n < 8) {
5213        n = 8 - n - 1;
5214    } else {
5215        n = 24 - n - 1;
5216    }
5217#endif
5218    env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n];
5219}
5220
5221void helper_msa_copy_u_h(CPUMIPSState *env, uint32_t rd,
5222                         uint32_t ws, uint32_t n)
5223{
5224    n %= 8;
5225#if defined(HOST_WORDS_BIGENDIAN)
5226    if (n < 4) {
5227        n = 4 - n - 1;
5228    } else {
5229        n = 12 - n - 1;
5230    }
5231#endif
5232    env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n];
5233}
5234
5235void helper_msa_copy_u_w(CPUMIPSState *env, uint32_t rd,
5236                         uint32_t ws, uint32_t n)
5237{
5238    n %= 4;
5239#if defined(HOST_WORDS_BIGENDIAN)
5240    if (n < 2) {
5241        n = 2 - n - 1;
5242    } else {
5243        n = 6 - n - 1;
5244    }
5245#endif
5246    env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n];
5247}
5248
5249void helper_msa_insert_b(CPUMIPSState *env, uint32_t wd,
5250                          uint32_t rs_num, uint32_t n)
5251{
5252    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
5253    target_ulong rs = env->active_tc.gpr[rs_num];
5254    n %= 16;
5255#if defined(HOST_WORDS_BIGENDIAN)
5256    if (n < 8) {
5257        n = 8 - n - 1;
5258    } else {
5259        n = 24 - n - 1;
5260    }
5261#endif
5262    pwd->b[n] = (int8_t)rs;
5263}
5264
5265void helper_msa_insert_h(CPUMIPSState *env, uint32_t wd,
5266                          uint32_t rs_num, uint32_t n)
5267{
5268    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
5269    target_ulong rs = env->active_tc.gpr[rs_num];
5270    n %= 8;
5271#if defined(HOST_WORDS_BIGENDIAN)
5272    if (n < 4) {
5273        n = 4 - n - 1;
5274    } else {
5275        n = 12 - n - 1;
5276    }
5277#endif
5278    pwd->h[n] = (int16_t)rs;
5279}
5280
5281void helper_msa_insert_w(CPUMIPSState *env, uint32_t wd,
5282                          uint32_t rs_num, uint32_t n)
5283{
5284    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
5285    target_ulong rs = env->active_tc.gpr[rs_num];
5286    n %= 4;
5287#if defined(HOST_WORDS_BIGENDIAN)
5288    if (n < 2) {
5289        n = 2 - n - 1;
5290    } else {
5291        n = 6 - n - 1;
5292    }
5293#endif
5294    pwd->w[n] = (int32_t)rs;
5295}
5296
5297void helper_msa_insert_d(CPUMIPSState *env, uint32_t wd,
5298                          uint32_t rs_num, uint32_t n)
5299{
5300    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
5301    target_ulong rs = env->active_tc.gpr[rs_num];
5302    n %= 2;
5303    pwd->d[n] = (int64_t)rs;
5304}
5305
5306void helper_msa_insve_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
5307                         uint32_t ws, uint32_t n)
5308{
5309    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
5310    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
5311
5312    switch (df) {
5313    case DF_BYTE:
5314        pwd->b[n] = (int8_t)pws->b[0];
5315        break;
5316    case DF_HALF:
5317        pwd->h[n] = (int16_t)pws->h[0];
5318        break;
5319    case DF_WORD:
5320        pwd->w[n] = (int32_t)pws->w[0];
5321        break;
5322    case DF_DOUBLE:
5323        pwd->d[n] = (int64_t)pws->d[0];
5324        break;
5325    default:
5326        assert(0);
5327    }
5328}
5329
5330void helper_msa_ctcmsa(CPUMIPSState *env, target_ulong elm, uint32_t cd)
5331{
5332    switch (cd) {
5333    case 0:
5334        break;
5335    case 1:
5336        env->active_tc.msacsr = (int32_t)elm & MSACSR_MASK;
5337        restore_msa_fp_status(env);
5338        /* check exception */
5339        if ((GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED)
5340            & GET_FP_CAUSE(env->active_tc.msacsr)) {
5341            do_raise_exception(env, EXCP_MSAFPE, GETPC());
5342        }
5343        break;
5344    }
5345}
5346
5347target_ulong helper_msa_cfcmsa(CPUMIPSState *env, uint32_t cs)
5348{
5349    switch (cs) {
5350    case 0:
5351        return env->msair;
5352    case 1:
5353        return env->active_tc.msacsr & MSACSR_MASK;
5354    }
5355    return 0;
5356}
5357
5358void helper_msa_fill_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
5359                        uint32_t rs)
5360{
5361    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
5362    uint32_t i;
5363
5364    switch (df) {
5365    case DF_BYTE:
5366        for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {
5367            pwd->b[i] = (int8_t)env->active_tc.gpr[rs];
5368        }
5369        break;
5370    case DF_HALF:
5371        for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {
5372            pwd->h[i] = (int16_t)env->active_tc.gpr[rs];
5373        }
5374        break;
5375    case DF_WORD:
5376        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
5377            pwd->w[i] = (int32_t)env->active_tc.gpr[rs];
5378        }
5379        break;
5380    case DF_DOUBLE:
5381        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
5382            pwd->d[i] = (int64_t)env->active_tc.gpr[rs];
5383        }
5384       break;
5385    default:
5386        assert(0);
5387    }
5388}
5389
5390
5391#define FLOAT_ONE32 make_float32(0x3f8 << 20)
5392#define FLOAT_ONE64 make_float64(0x3ffULL << 52)
5393
5394#define FLOAT_SNAN16(s) (float16_default_nan(s) ^ 0x0220)
5395        /* 0x7c20 */
5396#define FLOAT_SNAN32(s) (float32_default_nan(s) ^ 0x00400020)
5397        /* 0x7f800020 */
5398#define FLOAT_SNAN64(s) (float64_default_nan(s) ^ 0x0008000000000020ULL)
5399        /* 0x7ff0000000000020 */
5400
5401static inline void clear_msacsr_cause(CPUMIPSState *env)
5402{
5403    SET_FP_CAUSE(env->active_tc.msacsr, 0);
5404}
5405
5406static inline void check_msacsr_cause(CPUMIPSState *env, uintptr_t retaddr)
5407{
5408    if ((GET_FP_CAUSE(env->active_tc.msacsr) &
5409            (GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED)) == 0) {
5410        UPDATE_FP_FLAGS(env->active_tc.msacsr,
5411                GET_FP_CAUSE(env->active_tc.msacsr));
5412    } else {
5413        do_raise_exception(env, EXCP_MSAFPE, retaddr);
5414    }
5415}
5416
5417/* Flush-to-zero use cases for update_msacsr() */
5418#define CLEAR_FS_UNDERFLOW 1
5419#define CLEAR_IS_INEXACT   2
5420#define RECIPROCAL_INEXACT 4
5421
5422static inline int update_msacsr(CPUMIPSState *env, int action, int denormal)
5423{
5424    int ieee_ex;
5425
5426    int c;
5427    int cause;
5428    int enable;
5429
5430    ieee_ex = get_float_exception_flags(&env->active_tc.msa_fp_status);
5431
5432    /* QEMU softfloat does not signal all underflow cases */
5433    if (denormal) {
5434        ieee_ex |= float_flag_underflow;
5435    }
5436
5437    c = ieee_ex_to_mips(ieee_ex);
5438    enable = GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED;
5439
5440    /* Set Inexact (I) when flushing inputs to zero */
5441    if ((ieee_ex & float_flag_input_denormal) &&
5442            (env->active_tc.msacsr & MSACSR_FS_MASK) != 0) {
5443        if (action & CLEAR_IS_INEXACT) {
5444            c &= ~FP_INEXACT;
5445        } else {
5446            c |=  FP_INEXACT;
5447        }
5448    }
5449
5450    /* Set Inexact (I) and Underflow (U) when flushing outputs to zero */
5451    if ((ieee_ex & float_flag_output_denormal) &&
5452            (env->active_tc.msacsr & MSACSR_FS_MASK) != 0) {
5453        c |= FP_INEXACT;
5454        if (action & CLEAR_FS_UNDERFLOW) {
5455            c &= ~FP_UNDERFLOW;
5456        } else {
5457            c |=  FP_UNDERFLOW;
5458        }
5459    }
5460
5461    /* Set Inexact (I) when Overflow (O) is not enabled */
5462    if ((c & FP_OVERFLOW) != 0 && (enable & FP_OVERFLOW) == 0) {
5463        c |= FP_INEXACT;
5464    }
5465
5466    /* Clear Exact Underflow when Underflow (U) is not enabled */
5467    if ((c & FP_UNDERFLOW) != 0 && (enable & FP_UNDERFLOW) == 0 &&
5468            (c & FP_INEXACT) == 0) {
5469        c &= ~FP_UNDERFLOW;
5470    }
5471
5472    /*
5473     * Reciprocal operations set only Inexact when valid and not
5474     * divide by zero
5475     */
5476    if ((action & RECIPROCAL_INEXACT) &&
5477            (c & (FP_INVALID | FP_DIV0)) == 0) {
5478        c = FP_INEXACT;
5479    }
5480
5481    cause = c & enable;    /* all current enabled exceptions */
5482
5483    if (cause == 0) {
5484        /*
5485         * No enabled exception, update the MSACSR Cause
5486         * with all current exceptions
5487         */
5488        SET_FP_CAUSE(env->active_tc.msacsr,
5489                (GET_FP_CAUSE(env->active_tc.msacsr) | c));
5490    } else {
5491        /* Current exceptions are enabled */
5492        if ((env->active_tc.msacsr & MSACSR_NX_MASK) == 0) {
5493            /*
5494             * Exception(s) will trap, update MSACSR Cause
5495             * with all enabled exceptions
5496             */
5497            SET_FP_CAUSE(env->active_tc.msacsr,
5498                    (GET_FP_CAUSE(env->active_tc.msacsr) | c));
5499        }
5500    }
5501
5502    return c;
5503}
5504
5505static inline int get_enabled_exceptions(const CPUMIPSState *env, int c)
5506{
5507    int enable = GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED;
5508    return c & enable;
5509}
5510
5511static inline float16 float16_from_float32(int32_t a, flag ieee,
5512                                           float_status *status)
5513{
5514      float16 f_val;
5515
5516      f_val = float32_to_float16((float32)a, ieee, status);
5517
5518      return a < 0 ? (f_val | (1 << 15)) : f_val;
5519}
5520
5521static inline float32 float32_from_float64(int64_t a, float_status *status)
5522{
5523      float32 f_val;
5524
5525      f_val = float64_to_float32((float64)a, status);
5526
5527      return a < 0 ? (f_val | (1 << 31)) : f_val;
5528}
5529
5530static inline float32 float32_from_float16(int16_t a, flag ieee,
5531                                           float_status *status)
5532{
5533      float32 f_val;
5534
5535      f_val = float16_to_float32((float16)a, ieee, status);
5536
5537      return a < 0 ? (f_val | (1 << 31)) : f_val;
5538}
5539
5540static inline float64 float64_from_float32(int32_t a, float_status *status)
5541{
5542      float64 f_val;
5543
5544      f_val = float32_to_float64((float64)a, status);
5545
5546      return a < 0 ? (f_val | (1ULL << 63)) : f_val;
5547}
5548
5549static inline float32 float32_from_q16(int16_t a, float_status *status)
5550{
5551    float32 f_val;
5552
5553    /* conversion as integer and scaling */
5554    f_val = int32_to_float32(a, status);
5555    f_val = float32_scalbn(f_val, -15, status);
5556
5557    return f_val;
5558}
5559
5560static inline float64 float64_from_q32(int32_t a, float_status *status)
5561{
5562    float64 f_val;
5563
5564    /* conversion as integer and scaling */
5565    f_val = int32_to_float64(a, status);
5566    f_val = float64_scalbn(f_val, -31, status);
5567
5568    return f_val;
5569}
5570
5571static inline int16_t float32_to_q16(float32 a, float_status *status)
5572{
5573    int32_t q_val;
5574    int32_t q_min = 0xffff8000;
5575    int32_t q_max = 0x00007fff;
5576
5577    int ieee_ex;
5578
5579    if (float32_is_any_nan(a)) {
5580        float_raise(float_flag_invalid, status);
5581        return 0;
5582    }
5583
5584    /* scaling */
5585    a = float32_scalbn(a, 15, status);
5586
5587    ieee_ex = get_float_exception_flags(status);
5588    set_float_exception_flags(ieee_ex & (~float_flag_underflow)
5589                             , status);
5590
5591    if (ieee_ex & float_flag_overflow) {
5592        float_raise(float_flag_inexact, status);
5593        return (int32_t)a < 0 ? q_min : q_max;
5594    }
5595
5596    /* conversion to int */
5597    q_val = float32_to_int32(a, status);
5598
5599    ieee_ex = get_float_exception_flags(status);
5600    set_float_exception_flags(ieee_ex & (~float_flag_underflow)
5601                             , status);
5602
5603    if (ieee_ex & float_flag_invalid) {
5604        set_float_exception_flags(ieee_ex & (~float_flag_invalid)
5605                               , status);
5606        float_raise(float_flag_overflow | float_flag_inexact, status);
5607        return (int32_t)a < 0 ? q_min : q_max;
5608    }
5609
5610    if (q_val < q_min) {
5611        float_raise(float_flag_overflow | float_flag_inexact, status);
5612        return (int16_t)q_min;
5613    }
5614
5615    if (q_max < q_val) {
5616        float_raise(float_flag_overflow | float_flag_inexact, status);
5617        return (int16_t)q_max;
5618    }
5619
5620    return (int16_t)q_val;
5621}
5622
5623static inline int32_t float64_to_q32(float64 a, float_status *status)
5624{
5625    int64_t q_val;
5626    int64_t q_min = 0xffffffff80000000LL;
5627    int64_t q_max = 0x000000007fffffffLL;
5628
5629    int ieee_ex;
5630
5631    if (float64_is_any_nan(a)) {
5632        float_raise(float_flag_invalid, status);
5633        return 0;
5634    }
5635
5636    /* scaling */
5637    a = float64_scalbn(a, 31, status);
5638
5639    ieee_ex = get_float_exception_flags(status);
5640    set_float_exception_flags(ieee_ex & (~float_flag_underflow)
5641           , status);
5642
5643    if (ieee_ex & float_flag_overflow) {
5644        float_raise(float_flag_inexact, status);
5645        return (int64_t)a < 0 ? q_min : q_max;
5646    }
5647
5648    /* conversion to integer */
5649    q_val = float64_to_int64(a, status);
5650
5651    ieee_ex = get_float_exception_flags(status);
5652    set_float_exception_flags(ieee_ex & (~float_flag_underflow)
5653           , status);
5654
5655    if (ieee_ex & float_flag_invalid) {
5656        set_float_exception_flags(ieee_ex & (~float_flag_invalid)
5657               , status);
5658        float_raise(float_flag_overflow | float_flag_inexact, status);
5659        return (int64_t)a < 0 ? q_min : q_max;
5660    }
5661
5662    if (q_val < q_min) {
5663        float_raise(float_flag_overflow | float_flag_inexact, status);
5664        return (int32_t)q_min;
5665    }
5666
5667    if (q_max < q_val) {
5668        float_raise(float_flag_overflow | float_flag_inexact, status);
5669        return (int32_t)q_max;
5670    }
5671
5672    return (int32_t)q_val;
5673}
5674
5675#define MSA_FLOAT_COND(DEST, OP, ARG1, ARG2, BITS, QUIET)                   \
5676    do {                                                                    \
5677        float_status *status = &env->active_tc.msa_fp_status;               \
5678        int c;                                                              \
5679        int64_t cond;                                                       \
5680        set_float_exception_flags(0, status);                               \
5681        if (!QUIET) {                                                       \
5682            cond = float ## BITS ## _ ## OP(ARG1, ARG2, status);            \
5683        } else {                                                            \
5684            cond = float ## BITS ## _ ## OP ## _quiet(ARG1, ARG2, status);  \
5685        }                                                                   \
5686        DEST = cond ? M_MAX_UINT(BITS) : 0;                                 \
5687        c = update_msacsr(env, CLEAR_IS_INEXACT, 0);                        \
5688                                                                            \
5689        if (get_enabled_exceptions(env, c)) {                               \
5690            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
5691        }                                                                   \
5692    } while (0)
5693
5694#define MSA_FLOAT_AF(DEST, ARG1, ARG2, BITS, QUIET)                 \
5695    do {                                                            \
5696        MSA_FLOAT_COND(DEST, eq, ARG1, ARG2, BITS, QUIET);          \
5697        if ((DEST & M_MAX_UINT(BITS)) == M_MAX_UINT(BITS)) {        \
5698            DEST = 0;                                               \
5699        }                                                           \
5700    } while (0)
5701
5702#define MSA_FLOAT_UEQ(DEST, ARG1, ARG2, BITS, QUIET)                \
5703    do {                                                            \
5704        MSA_FLOAT_COND(DEST, unordered, ARG1, ARG2, BITS, QUIET);   \
5705        if (DEST == 0) {                                            \
5706            MSA_FLOAT_COND(DEST, eq, ARG1, ARG2, BITS, QUIET);      \
5707        }                                                           \
5708    } while (0)
5709
5710#define MSA_FLOAT_NE(DEST, ARG1, ARG2, BITS, QUIET)                 \
5711    do {                                                            \
5712        MSA_FLOAT_COND(DEST, lt, ARG1, ARG2, BITS, QUIET);          \
5713        if (DEST == 0) {                                            \
5714            MSA_FLOAT_COND(DEST, lt, ARG2, ARG1, BITS, QUIET);      \
5715        }                                                           \
5716    } while (0)
5717
5718#define MSA_FLOAT_UNE(DEST, ARG1, ARG2, BITS, QUIET)                \
5719    do {                                                            \
5720        MSA_FLOAT_COND(DEST, unordered, ARG1, ARG2, BITS, QUIET);   \
5721        if (DEST == 0) {                                            \
5722            MSA_FLOAT_COND(DEST, lt, ARG1, ARG2, BITS, QUIET);      \
5723            if (DEST == 0) {                                        \
5724                MSA_FLOAT_COND(DEST, lt, ARG2, ARG1, BITS, QUIET);  \
5725            }                                                       \
5726        }                                                           \
5727    } while (0)
5728
5729#define MSA_FLOAT_ULE(DEST, ARG1, ARG2, BITS, QUIET)                \
5730    do {                                                            \
5731        MSA_FLOAT_COND(DEST, unordered, ARG1, ARG2, BITS, QUIET);   \
5732        if (DEST == 0) {                                            \
5733            MSA_FLOAT_COND(DEST, le, ARG1, ARG2, BITS, QUIET);      \
5734        }                                                           \
5735    } while (0)
5736
5737#define MSA_FLOAT_ULT(DEST, ARG1, ARG2, BITS, QUIET)                \
5738    do {                                                            \
5739        MSA_FLOAT_COND(DEST, unordered, ARG1, ARG2, BITS, QUIET);   \
5740        if (DEST == 0) {                                            \
5741            MSA_FLOAT_COND(DEST, lt, ARG1, ARG2, BITS, QUIET);      \
5742        }                                                           \
5743    } while (0)
5744
5745#define MSA_FLOAT_OR(DEST, ARG1, ARG2, BITS, QUIET)                 \
5746    do {                                                            \
5747        MSA_FLOAT_COND(DEST, le, ARG1, ARG2, BITS, QUIET);          \
5748        if (DEST == 0) {                                            \
5749            MSA_FLOAT_COND(DEST, le, ARG2, ARG1, BITS, QUIET);      \
5750        }                                                           \
5751    } while (0)
5752
5753static inline void compare_af(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
5754                              wr_t *pwt, uint32_t df, int quiet,
5755                              uintptr_t retaddr)
5756{
5757    wr_t wx, *pwx = &wx;
5758    uint32_t i;
5759
5760    clear_msacsr_cause(env);
5761
5762    switch (df) {
5763    case DF_WORD:
5764        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
5765            MSA_FLOAT_AF(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
5766        }
5767        break;
5768    case DF_DOUBLE:
5769        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
5770            MSA_FLOAT_AF(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
5771        }
5772        break;
5773    default:
5774        assert(0);
5775    }
5776
5777    check_msacsr_cause(env, retaddr);
5778
5779    msa_move_v(pwd, pwx);
5780}
5781
5782static inline void compare_un(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
5783                              wr_t *pwt, uint32_t df, int quiet,
5784                              uintptr_t retaddr)
5785{
5786    wr_t wx, *pwx = &wx;
5787    uint32_t i;
5788
5789    clear_msacsr_cause(env);
5790
5791    switch (df) {
5792    case DF_WORD:
5793        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
5794            MSA_FLOAT_COND(pwx->w[i], unordered, pws->w[i], pwt->w[i], 32,
5795                    quiet);
5796        }
5797        break;
5798    case DF_DOUBLE:
5799        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
5800            MSA_FLOAT_COND(pwx->d[i], unordered, pws->d[i], pwt->d[i], 64,
5801                    quiet);
5802        }
5803        break;
5804    default:
5805        assert(0);
5806    }
5807
5808    check_msacsr_cause(env, retaddr);
5809
5810    msa_move_v(pwd, pwx);
5811}
5812
5813static inline void compare_eq(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
5814                              wr_t *pwt, uint32_t df, int quiet,
5815                              uintptr_t retaddr)
5816{
5817    wr_t wx, *pwx = &wx;
5818    uint32_t i;
5819
5820    clear_msacsr_cause(env);
5821
5822    switch (df) {
5823    case DF_WORD:
5824        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
5825            MSA_FLOAT_COND(pwx->w[i], eq, pws->w[i], pwt->w[i], 32, quiet);
5826        }
5827        break;
5828    case DF_DOUBLE:
5829        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
5830            MSA_FLOAT_COND(pwx->d[i], eq, pws->d[i], pwt->d[i], 64, quiet);
5831        }
5832        break;
5833    default:
5834        assert(0);
5835    }
5836
5837    check_msacsr_cause(env, retaddr);
5838
5839    msa_move_v(pwd, pwx);
5840}
5841
5842static inline void compare_ueq(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
5843                               wr_t *pwt, uint32_t df, int quiet,
5844                               uintptr_t retaddr)
5845{
5846    wr_t wx, *pwx = &wx;
5847    uint32_t i;
5848
5849    clear_msacsr_cause(env);
5850
5851    switch (df) {
5852    case DF_WORD:
5853        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
5854            MSA_FLOAT_UEQ(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
5855        }
5856        break;
5857    case DF_DOUBLE:
5858        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
5859            MSA_FLOAT_UEQ(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
5860        }
5861        break;
5862    default:
5863        assert(0);
5864    }
5865
5866    check_msacsr_cause(env, retaddr);
5867
5868    msa_move_v(pwd, pwx);
5869}
5870
5871static inline void compare_lt(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
5872                              wr_t *pwt, uint32_t df, int quiet,
5873                              uintptr_t retaddr)
5874{
5875    wr_t wx, *pwx = &wx;
5876    uint32_t i;
5877
5878    clear_msacsr_cause(env);
5879
5880    switch (df) {
5881    case DF_WORD:
5882        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
5883            MSA_FLOAT_COND(pwx->w[i], lt, pws->w[i], pwt->w[i], 32, quiet);
5884        }
5885        break;
5886    case DF_DOUBLE:
5887        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
5888            MSA_FLOAT_COND(pwx->d[i], lt, pws->d[i], pwt->d[i], 64, quiet);
5889        }
5890        break;
5891    default:
5892        assert(0);
5893    }
5894
5895    check_msacsr_cause(env, retaddr);
5896
5897    msa_move_v(pwd, pwx);
5898}
5899
5900static inline void compare_ult(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
5901                               wr_t *pwt, uint32_t df, int quiet,
5902                               uintptr_t retaddr)
5903{
5904    wr_t wx, *pwx = &wx;
5905    uint32_t i;
5906
5907    clear_msacsr_cause(env);
5908
5909    switch (df) {
5910    case DF_WORD:
5911        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
5912            MSA_FLOAT_ULT(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
5913        }
5914        break;
5915    case DF_DOUBLE:
5916        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
5917            MSA_FLOAT_ULT(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
5918        }
5919        break;
5920    default:
5921        assert(0);
5922    }
5923
5924    check_msacsr_cause(env, retaddr);
5925
5926    msa_move_v(pwd, pwx);
5927}
5928
5929static inline void compare_le(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
5930                              wr_t *pwt, uint32_t df, int quiet,
5931                              uintptr_t retaddr)
5932{
5933    wr_t wx, *pwx = &wx;
5934    uint32_t i;
5935
5936    clear_msacsr_cause(env);
5937
5938    switch (df) {
5939    case DF_WORD:
5940        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
5941            MSA_FLOAT_COND(pwx->w[i], le, pws->w[i], pwt->w[i], 32, quiet);
5942        }
5943        break;
5944    case DF_DOUBLE:
5945        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
5946            MSA_FLOAT_COND(pwx->d[i], le, pws->d[i], pwt->d[i], 64, quiet);
5947        }
5948        break;
5949    default:
5950        assert(0);
5951    }
5952
5953    check_msacsr_cause(env, retaddr);
5954
5955    msa_move_v(pwd, pwx);
5956}
5957
5958static inline void compare_ule(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
5959                               wr_t *pwt, uint32_t df, int quiet,
5960                               uintptr_t retaddr)
5961{
5962    wr_t wx, *pwx = &wx;
5963    uint32_t i;
5964
5965    clear_msacsr_cause(env);
5966
5967    switch (df) {
5968    case DF_WORD:
5969        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
5970            MSA_FLOAT_ULE(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
5971        }
5972        break;
5973    case DF_DOUBLE:
5974        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
5975            MSA_FLOAT_ULE(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
5976        }
5977        break;
5978    default:
5979        assert(0);
5980    }
5981
5982    check_msacsr_cause(env, retaddr);
5983
5984    msa_move_v(pwd, pwx);
5985}
5986
5987static inline void compare_or(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
5988                              wr_t *pwt, uint32_t df, int quiet,
5989                              uintptr_t retaddr)
5990{
5991    wr_t wx, *pwx = &wx;
5992    uint32_t i;
5993
5994    clear_msacsr_cause(env);
5995
5996    switch (df) {
5997    case DF_WORD:
5998        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
5999            MSA_FLOAT_OR(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
6000        }
6001        break;
6002    case DF_DOUBLE:
6003        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6004            MSA_FLOAT_OR(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
6005        }
6006        break;
6007    default:
6008        assert(0);
6009    }
6010
6011    check_msacsr_cause(env, retaddr);
6012
6013    msa_move_v(pwd, pwx);
6014}
6015
6016static inline void compare_une(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
6017                               wr_t *pwt, uint32_t df, int quiet,
6018                               uintptr_t retaddr)
6019{
6020    wr_t wx, *pwx = &wx;
6021    uint32_t i;
6022
6023    clear_msacsr_cause(env);
6024
6025    switch (df) {
6026    case DF_WORD:
6027        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6028            MSA_FLOAT_UNE(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
6029        }
6030        break;
6031    case DF_DOUBLE:
6032        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6033            MSA_FLOAT_UNE(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
6034        }
6035        break;
6036    default:
6037        assert(0);
6038    }
6039
6040    check_msacsr_cause(env, retaddr);
6041
6042    msa_move_v(pwd, pwx);
6043}
6044
6045static inline void compare_ne(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
6046                              wr_t *pwt, uint32_t df, int quiet,
6047                              uintptr_t retaddr)
6048{
6049    wr_t wx, *pwx = &wx;
6050    uint32_t i;
6051
6052    clear_msacsr_cause(env);
6053
6054    switch (df) {
6055    case DF_WORD:
6056        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6057            MSA_FLOAT_NE(pwx->w[i], pws->w[i], pwt->w[i], 32, quiet);
6058        }
6059        break;
6060    case DF_DOUBLE:
6061        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6062            MSA_FLOAT_NE(pwx->d[i], pws->d[i], pwt->d[i], 64, quiet);
6063        }
6064        break;
6065    default:
6066        assert(0);
6067    }
6068
6069    check_msacsr_cause(env, retaddr);
6070
6071    msa_move_v(pwd, pwx);
6072}
6073
6074void helper_msa_fcaf_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6075                        uint32_t ws, uint32_t wt)
6076{
6077    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6078    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6079    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6080    compare_af(env, pwd, pws, pwt, df, 1, GETPC());
6081}
6082
6083void helper_msa_fcun_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6084                        uint32_t ws, uint32_t wt)
6085{
6086    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6087    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6088    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6089    compare_un(env, pwd, pws, pwt, df, 1, GETPC());
6090}
6091
6092void helper_msa_fceq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6093                        uint32_t ws, uint32_t wt)
6094{
6095    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6096    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6097    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6098    compare_eq(env, pwd, pws, pwt, df, 1, GETPC());
6099}
6100
6101void helper_msa_fcueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6102                         uint32_t ws, uint32_t wt)
6103{
6104    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6105    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6106    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6107    compare_ueq(env, pwd, pws, pwt, df, 1, GETPC());
6108}
6109
6110void helper_msa_fclt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6111                        uint32_t ws, uint32_t wt)
6112{
6113    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6114    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6115    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6116    compare_lt(env, pwd, pws, pwt, df, 1, GETPC());
6117}
6118
6119void helper_msa_fcult_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6120                         uint32_t ws, uint32_t wt)
6121{
6122    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6123    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6124    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6125    compare_ult(env, pwd, pws, pwt, df, 1, GETPC());
6126}
6127
6128void helper_msa_fcle_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6129                        uint32_t ws, uint32_t wt)
6130{
6131    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6132    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6133    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6134    compare_le(env, pwd, pws, pwt, df, 1, GETPC());
6135}
6136
6137void helper_msa_fcule_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6138                         uint32_t ws, uint32_t wt)
6139{
6140    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6141    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6142    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6143    compare_ule(env, pwd, pws, pwt, df, 1, GETPC());
6144}
6145
6146void helper_msa_fsaf_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6147                        uint32_t ws, uint32_t wt)
6148{
6149    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6150    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6151    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6152    compare_af(env, pwd, pws, pwt, df, 0, GETPC());
6153}
6154
6155void helper_msa_fsun_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6156                        uint32_t ws, uint32_t wt)
6157{
6158    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6159    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6160    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6161    compare_un(env, pwd, pws, pwt, df, 0, GETPC());
6162}
6163
6164void helper_msa_fseq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6165                        uint32_t ws, uint32_t wt)
6166{
6167    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6168    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6169    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6170    compare_eq(env, pwd, pws, pwt, df, 0, GETPC());
6171}
6172
6173void helper_msa_fsueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6174                         uint32_t ws, uint32_t wt)
6175{
6176    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6177    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6178    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6179    compare_ueq(env, pwd, pws, pwt, df, 0, GETPC());
6180}
6181
6182void helper_msa_fslt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6183                        uint32_t ws, uint32_t wt)
6184{
6185    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6186    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6187    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6188    compare_lt(env, pwd, pws, pwt, df, 0, GETPC());
6189}
6190
6191void helper_msa_fsult_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6192                         uint32_t ws, uint32_t wt)
6193{
6194    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6195    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6196    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6197    compare_ult(env, pwd, pws, pwt, df, 0, GETPC());
6198}
6199
6200void helper_msa_fsle_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6201                        uint32_t ws, uint32_t wt)
6202{
6203    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6204    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6205    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6206    compare_le(env, pwd, pws, pwt, df, 0, GETPC());
6207}
6208
6209void helper_msa_fsule_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6210                         uint32_t ws, uint32_t wt)
6211{
6212    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6213    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6214    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6215    compare_ule(env, pwd, pws, pwt, df, 0, GETPC());
6216}
6217
6218void helper_msa_fcor_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6219                        uint32_t ws, uint32_t wt)
6220{
6221    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6222    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6223    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6224    compare_or(env, pwd, pws, pwt, df, 1, GETPC());
6225}
6226
6227void helper_msa_fcune_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6228                         uint32_t ws, uint32_t wt)
6229{
6230    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6231    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6232    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6233    compare_une(env, pwd, pws, pwt, df, 1, GETPC());
6234}
6235
6236void helper_msa_fcne_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6237                        uint32_t ws, uint32_t wt)
6238{
6239    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6240    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6241    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6242    compare_ne(env, pwd, pws, pwt, df, 1, GETPC());
6243}
6244
6245void helper_msa_fsor_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6246                        uint32_t ws, uint32_t wt)
6247{
6248    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6249    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6250    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6251    compare_or(env, pwd, pws, pwt, df, 0, GETPC());
6252}
6253
6254void helper_msa_fsune_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6255                         uint32_t ws, uint32_t wt)
6256{
6257    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6258    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6259    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6260    compare_une(env, pwd, pws, pwt, df, 0, GETPC());
6261}
6262
6263void helper_msa_fsne_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6264                        uint32_t ws, uint32_t wt)
6265{
6266    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6267    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6268    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6269    compare_ne(env, pwd, pws, pwt, df, 0, GETPC());
6270}
6271
6272#define float16_is_zero(ARG) 0
6273#define float16_is_zero_or_denormal(ARG) 0
6274
6275#define IS_DENORMAL(ARG, BITS)                      \
6276    (!float ## BITS ## _is_zero(ARG)                \
6277    && float ## BITS ## _is_zero_or_denormal(ARG))
6278
6279#define MSA_FLOAT_BINOP(DEST, OP, ARG1, ARG2, BITS)                         \
6280    do {                                                                    \
6281        float_status *status = &env->active_tc.msa_fp_status;               \
6282        int c;                                                              \
6283                                                                            \
6284        set_float_exception_flags(0, status);                               \
6285        DEST = float ## BITS ## _ ## OP(ARG1, ARG2, status);                \
6286        c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS));                 \
6287                                                                            \
6288        if (get_enabled_exceptions(env, c)) {                               \
6289            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
6290        }                                                                   \
6291    } while (0)
6292
6293void helper_msa_fadd_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6294        uint32_t ws, uint32_t wt)
6295{
6296    wr_t wx, *pwx = &wx;
6297    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6298    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6299    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6300    uint32_t i;
6301
6302    clear_msacsr_cause(env);
6303
6304    switch (df) {
6305    case DF_WORD:
6306        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6307            MSA_FLOAT_BINOP(pwx->w[i], add, pws->w[i], pwt->w[i], 32);
6308        }
6309        break;
6310    case DF_DOUBLE:
6311        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6312            MSA_FLOAT_BINOP(pwx->d[i], add, pws->d[i], pwt->d[i], 64);
6313        }
6314        break;
6315    default:
6316        assert(0);
6317    }
6318
6319    check_msacsr_cause(env, GETPC());
6320    msa_move_v(pwd, pwx);
6321}
6322
6323void helper_msa_fsub_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6324        uint32_t ws, uint32_t wt)
6325{
6326    wr_t wx, *pwx = &wx;
6327    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6328    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6329    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6330    uint32_t i;
6331
6332    clear_msacsr_cause(env);
6333
6334    switch (df) {
6335    case DF_WORD:
6336        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6337            MSA_FLOAT_BINOP(pwx->w[i], sub, pws->w[i], pwt->w[i], 32);
6338        }
6339        break;
6340    case DF_DOUBLE:
6341        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6342            MSA_FLOAT_BINOP(pwx->d[i], sub, pws->d[i], pwt->d[i], 64);
6343        }
6344        break;
6345    default:
6346        assert(0);
6347    }
6348
6349    check_msacsr_cause(env, GETPC());
6350    msa_move_v(pwd, pwx);
6351}
6352
6353void helper_msa_fmul_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6354        uint32_t ws, uint32_t wt)
6355{
6356    wr_t wx, *pwx = &wx;
6357    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6358    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6359    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6360    uint32_t i;
6361
6362    clear_msacsr_cause(env);
6363
6364    switch (df) {
6365    case DF_WORD:
6366        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6367            MSA_FLOAT_BINOP(pwx->w[i], mul, pws->w[i], pwt->w[i], 32);
6368        }
6369        break;
6370    case DF_DOUBLE:
6371        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6372            MSA_FLOAT_BINOP(pwx->d[i], mul, pws->d[i], pwt->d[i], 64);
6373        }
6374        break;
6375    default:
6376        assert(0);
6377    }
6378
6379    check_msacsr_cause(env, GETPC());
6380
6381    msa_move_v(pwd, pwx);
6382}
6383
6384void helper_msa_fdiv_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6385        uint32_t ws, uint32_t wt)
6386{
6387    wr_t wx, *pwx = &wx;
6388    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6389    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6390    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6391    uint32_t i;
6392
6393    clear_msacsr_cause(env);
6394
6395    switch (df) {
6396    case DF_WORD:
6397        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6398            MSA_FLOAT_BINOP(pwx->w[i], div, pws->w[i], pwt->w[i], 32);
6399        }
6400        break;
6401    case DF_DOUBLE:
6402        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6403            MSA_FLOAT_BINOP(pwx->d[i], div, pws->d[i], pwt->d[i], 64);
6404        }
6405        break;
6406    default:
6407        assert(0);
6408    }
6409
6410    check_msacsr_cause(env, GETPC());
6411
6412    msa_move_v(pwd, pwx);
6413}
6414
6415#define MSA_FLOAT_MULADD(DEST, ARG1, ARG2, ARG3, NEGATE, BITS)              \
6416    do {                                                                    \
6417        float_status *status = &env->active_tc.msa_fp_status;               \
6418        int c;                                                              \
6419                                                                            \
6420        set_float_exception_flags(0, status);                               \
6421        DEST = float ## BITS ## _muladd(ARG2, ARG3, ARG1, NEGATE, status);  \
6422        c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS));                 \
6423                                                                            \
6424        if (get_enabled_exceptions(env, c)) {                               \
6425            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
6426        }                                                                   \
6427    } while (0)
6428
6429void helper_msa_fmadd_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6430        uint32_t ws, uint32_t wt)
6431{
6432    wr_t wx, *pwx = &wx;
6433    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6434    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6435    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6436    uint32_t i;
6437
6438    clear_msacsr_cause(env);
6439
6440    switch (df) {
6441    case DF_WORD:
6442        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6443            MSA_FLOAT_MULADD(pwx->w[i], pwd->w[i],
6444                           pws->w[i], pwt->w[i], 0, 32);
6445        }
6446        break;
6447    case DF_DOUBLE:
6448        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6449            MSA_FLOAT_MULADD(pwx->d[i], pwd->d[i],
6450                           pws->d[i], pwt->d[i], 0, 64);
6451        }
6452        break;
6453    default:
6454        assert(0);
6455    }
6456
6457    check_msacsr_cause(env, GETPC());
6458
6459    msa_move_v(pwd, pwx);
6460}
6461
6462void helper_msa_fmsub_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6463        uint32_t ws, uint32_t wt)
6464{
6465    wr_t wx, *pwx = &wx;
6466    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6467    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6468    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6469    uint32_t i;
6470
6471    clear_msacsr_cause(env);
6472
6473    switch (df) {
6474    case DF_WORD:
6475        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6476            MSA_FLOAT_MULADD(pwx->w[i], pwd->w[i],
6477                           pws->w[i], pwt->w[i],
6478                           float_muladd_negate_product, 32);
6479      }
6480      break;
6481    case DF_DOUBLE:
6482        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6483            MSA_FLOAT_MULADD(pwx->d[i], pwd->d[i],
6484                           pws->d[i], pwt->d[i],
6485                           float_muladd_negate_product, 64);
6486        }
6487        break;
6488    default:
6489        assert(0);
6490    }
6491
6492    check_msacsr_cause(env, GETPC());
6493
6494    msa_move_v(pwd, pwx);
6495}
6496
6497void helper_msa_fexp2_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6498        uint32_t ws, uint32_t wt)
6499{
6500    wr_t wx, *pwx = &wx;
6501    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6502    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6503    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6504    uint32_t i;
6505
6506    clear_msacsr_cause(env);
6507
6508    switch (df) {
6509    case DF_WORD:
6510        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6511            MSA_FLOAT_BINOP(pwx->w[i], scalbn, pws->w[i],
6512                            pwt->w[i] >  0x200 ?  0x200 :
6513                            pwt->w[i] < -0x200 ? -0x200 : pwt->w[i],
6514                            32);
6515        }
6516        break;
6517    case DF_DOUBLE:
6518        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6519            MSA_FLOAT_BINOP(pwx->d[i], scalbn, pws->d[i],
6520                            pwt->d[i] >  0x1000 ?  0x1000 :
6521                            pwt->d[i] < -0x1000 ? -0x1000 : pwt->d[i],
6522                            64);
6523        }
6524        break;
6525    default:
6526        assert(0);
6527    }
6528
6529    check_msacsr_cause(env, GETPC());
6530
6531    msa_move_v(pwd, pwx);
6532}
6533
6534#define MSA_FLOAT_UNOP(DEST, OP, ARG, BITS)                                 \
6535    do {                                                                    \
6536        float_status *status = &env->active_tc.msa_fp_status;               \
6537        int c;                                                              \
6538                                                                            \
6539        set_float_exception_flags(0, status);                               \
6540        DEST = float ## BITS ## _ ## OP(ARG, status);                       \
6541        c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS));                 \
6542                                                                            \
6543        if (get_enabled_exceptions(env, c)) {                               \
6544            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
6545        }                                                                   \
6546    } while (0)
6547
6548void helper_msa_fexdo_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6549                         uint32_t ws, uint32_t wt)
6550{
6551    wr_t wx, *pwx = &wx;
6552    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6553    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6554    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6555    uint32_t i;
6556
6557    clear_msacsr_cause(env);
6558
6559    switch (df) {
6560    case DF_WORD:
6561        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6562            /*
6563             * Half precision floats come in two formats: standard
6564             * IEEE and "ARM" format.  The latter gains extra exponent
6565             * range by omitting the NaN/Inf encodings.
6566             */
6567            flag ieee = 1;
6568
6569            MSA_FLOAT_BINOP(Lh(pwx, i), from_float32, pws->w[i], ieee, 16);
6570            MSA_FLOAT_BINOP(Rh(pwx, i), from_float32, pwt->w[i], ieee, 16);
6571        }
6572        break;
6573    case DF_DOUBLE:
6574        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6575            MSA_FLOAT_UNOP(Lw(pwx, i), from_float64, pws->d[i], 32);
6576            MSA_FLOAT_UNOP(Rw(pwx, i), from_float64, pwt->d[i], 32);
6577        }
6578        break;
6579    default:
6580        assert(0);
6581    }
6582
6583    check_msacsr_cause(env, GETPC());
6584    msa_move_v(pwd, pwx);
6585}
6586
6587#define MSA_FLOAT_UNOP_XD(DEST, OP, ARG, BITS, XBITS)                       \
6588    do {                                                                    \
6589        float_status *status = &env->active_tc.msa_fp_status;               \
6590        int c;                                                              \
6591                                                                            \
6592        set_float_exception_flags(0, status);                               \
6593        DEST = float ## BITS ## _ ## OP(ARG, status);                       \
6594        c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0);                      \
6595                                                                            \
6596        if (get_enabled_exceptions(env, c)) {                               \
6597            DEST = ((FLOAT_SNAN ## XBITS(status) >> 6) << 6) | c;           \
6598        }                                                                   \
6599    } while (0)
6600
6601void helper_msa_ftq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6602                       uint32_t ws, uint32_t wt)
6603{
6604    wr_t wx, *pwx = &wx;
6605    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6606    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6607    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6608    uint32_t i;
6609
6610    clear_msacsr_cause(env);
6611
6612    switch (df) {
6613    case DF_WORD:
6614        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6615            MSA_FLOAT_UNOP_XD(Lh(pwx, i), to_q16, pws->w[i], 32, 16);
6616            MSA_FLOAT_UNOP_XD(Rh(pwx, i), to_q16, pwt->w[i], 32, 16);
6617        }
6618        break;
6619    case DF_DOUBLE:
6620        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6621            MSA_FLOAT_UNOP_XD(Lw(pwx, i), to_q32, pws->d[i], 64, 32);
6622            MSA_FLOAT_UNOP_XD(Rw(pwx, i), to_q32, pwt->d[i], 64, 32);
6623        }
6624        break;
6625    default:
6626        assert(0);
6627    }
6628
6629    check_msacsr_cause(env, GETPC());
6630
6631    msa_move_v(pwd, pwx);
6632}
6633
6634#define NUMBER_QNAN_PAIR(ARG1, ARG2, BITS, STATUS)      \
6635    !float ## BITS ## _is_any_nan(ARG1)                 \
6636    && float ## BITS ## _is_quiet_nan(ARG2, STATUS)
6637
6638#define MSA_FLOAT_MAXOP(DEST, OP, ARG1, ARG2, BITS)                         \
6639    do {                                                                    \
6640        float_status *status = &env->active_tc.msa_fp_status;               \
6641        int c;                                                              \
6642                                                                            \
6643        set_float_exception_flags(0, status);                               \
6644        DEST = float ## BITS ## _ ## OP(ARG1, ARG2, status);                \
6645        c = update_msacsr(env, 0, 0);                                       \
6646                                                                            \
6647        if (get_enabled_exceptions(env, c)) {                               \
6648            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
6649        }                                                                   \
6650    } while (0)
6651
6652#define FMAXMIN_A(F, G, X, _S, _T, BITS, STATUS)                    \
6653    do {                                                            \
6654        uint## BITS ##_t S = _S, T = _T;                            \
6655        uint## BITS ##_t as, at, xs, xt, xd;                        \
6656        if (NUMBER_QNAN_PAIR(S, T, BITS, STATUS)) {                 \
6657            T = S;                                                  \
6658        }                                                           \
6659        else if (NUMBER_QNAN_PAIR(T, S, BITS, STATUS)) {            \
6660            S = T;                                                  \
6661        }                                                           \
6662        as = float## BITS ##_abs(S);                                \
6663        at = float## BITS ##_abs(T);                                \
6664        MSA_FLOAT_MAXOP(xs, F,  S,  T, BITS);                       \
6665        MSA_FLOAT_MAXOP(xt, G,  S,  T, BITS);                       \
6666        MSA_FLOAT_MAXOP(xd, F, as, at, BITS);                       \
6667        X = (as == at || xd == float## BITS ##_abs(xs)) ? xs : xt;  \
6668    } while (0)
6669
6670void helper_msa_fmin_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6671        uint32_t ws, uint32_t wt)
6672{
6673    float_status *status = &env->active_tc.msa_fp_status;
6674    wr_t wx, *pwx = &wx;
6675    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6676    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6677    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6678
6679    clear_msacsr_cause(env);
6680
6681    if (df == DF_WORD) {
6682
6683        if (NUMBER_QNAN_PAIR(pws->w[0], pwt->w[0], 32, status)) {
6684            MSA_FLOAT_MAXOP(pwx->w[0], min, pws->w[0], pws->w[0], 32);
6685        } else if (NUMBER_QNAN_PAIR(pwt->w[0], pws->w[0], 32, status)) {
6686            MSA_FLOAT_MAXOP(pwx->w[0], min, pwt->w[0], pwt->w[0], 32);
6687        } else {
6688            MSA_FLOAT_MAXOP(pwx->w[0], min, pws->w[0], pwt->w[0], 32);
6689        }
6690
6691        if (NUMBER_QNAN_PAIR(pws->w[1], pwt->w[1], 32, status)) {
6692            MSA_FLOAT_MAXOP(pwx->w[1], min, pws->w[1], pws->w[1], 32);
6693        } else if (NUMBER_QNAN_PAIR(pwt->w[1], pws->w[1], 32, status)) {
6694            MSA_FLOAT_MAXOP(pwx->w[1], min, pwt->w[1], pwt->w[1], 32);
6695        } else {
6696            MSA_FLOAT_MAXOP(pwx->w[1], min, pws->w[1], pwt->w[1], 32);
6697        }
6698
6699        if (NUMBER_QNAN_PAIR(pws->w[2], pwt->w[2], 32, status)) {
6700            MSA_FLOAT_MAXOP(pwx->w[2], min, pws->w[2], pws->w[2], 32);
6701        } else if (NUMBER_QNAN_PAIR(pwt->w[2], pws->w[2], 32, status)) {
6702            MSA_FLOAT_MAXOP(pwx->w[2], min, pwt->w[2], pwt->w[2], 32);
6703        } else {
6704            MSA_FLOAT_MAXOP(pwx->w[2], min, pws->w[2], pwt->w[2], 32);
6705        }
6706
6707        if (NUMBER_QNAN_PAIR(pws->w[3], pwt->w[3], 32, status)) {
6708            MSA_FLOAT_MAXOP(pwx->w[3], min, pws->w[3], pws->w[3], 32);
6709        } else if (NUMBER_QNAN_PAIR(pwt->w[3], pws->w[3], 32, status)) {
6710            MSA_FLOAT_MAXOP(pwx->w[3], min, pwt->w[3], pwt->w[3], 32);
6711        } else {
6712            MSA_FLOAT_MAXOP(pwx->w[3], min, pws->w[3], pwt->w[3], 32);
6713        }
6714
6715    } else if (df == DF_DOUBLE) {
6716
6717        if (NUMBER_QNAN_PAIR(pws->d[0], pwt->d[0], 64, status)) {
6718            MSA_FLOAT_MAXOP(pwx->d[0], min, pws->d[0], pws->d[0], 64);
6719        } else if (NUMBER_QNAN_PAIR(pwt->d[0], pws->d[0], 64, status)) {
6720            MSA_FLOAT_MAXOP(pwx->d[0], min, pwt->d[0], pwt->d[0], 64);
6721        } else {
6722            MSA_FLOAT_MAXOP(pwx->d[0], min, pws->d[0], pwt->d[0], 64);
6723        }
6724
6725        if (NUMBER_QNAN_PAIR(pws->d[1], pwt->d[1], 64, status)) {
6726            MSA_FLOAT_MAXOP(pwx->d[1], min, pws->d[1], pws->d[1], 64);
6727        } else if (NUMBER_QNAN_PAIR(pwt->d[1], pws->d[1], 64, status)) {
6728            MSA_FLOAT_MAXOP(pwx->d[1], min, pwt->d[1], pwt->d[1], 64);
6729        } else {
6730            MSA_FLOAT_MAXOP(pwx->d[1], min, pws->d[1], pwt->d[1], 64);
6731        }
6732
6733    } else {
6734
6735        assert(0);
6736
6737    }
6738
6739    check_msacsr_cause(env, GETPC());
6740
6741    msa_move_v(pwd, pwx);
6742}
6743
6744void helper_msa_fmin_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6745        uint32_t ws, uint32_t wt)
6746{
6747    float_status *status = &env->active_tc.msa_fp_status;
6748    wr_t wx, *pwx = &wx;
6749    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6750    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6751    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6752
6753    clear_msacsr_cause(env);
6754
6755    if (df == DF_WORD) {
6756        FMAXMIN_A(min, max, pwx->w[0], pws->w[0], pwt->w[0], 32, status);
6757        FMAXMIN_A(min, max, pwx->w[1], pws->w[1], pwt->w[1], 32, status);
6758        FMAXMIN_A(min, max, pwx->w[2], pws->w[2], pwt->w[2], 32, status);
6759        FMAXMIN_A(min, max, pwx->w[3], pws->w[3], pwt->w[3], 32, status);
6760    } else if (df == DF_DOUBLE) {
6761        FMAXMIN_A(min, max, pwx->d[0], pws->d[0], pwt->d[0], 64, status);
6762        FMAXMIN_A(min, max, pwx->d[1], pws->d[1], pwt->d[1], 64, status);
6763    } else {
6764        assert(0);
6765    }
6766
6767    check_msacsr_cause(env, GETPC());
6768
6769    msa_move_v(pwd, pwx);
6770}
6771
6772void helper_msa_fmax_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6773        uint32_t ws, uint32_t wt)
6774{
6775     float_status *status = &env->active_tc.msa_fp_status;
6776    wr_t wx, *pwx = &wx;
6777    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6778    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6779    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6780
6781    clear_msacsr_cause(env);
6782
6783    if (df == DF_WORD) {
6784
6785        if (NUMBER_QNAN_PAIR(pws->w[0], pwt->w[0], 32, status)) {
6786            MSA_FLOAT_MAXOP(pwx->w[0], max, pws->w[0], pws->w[0], 32);
6787        } else if (NUMBER_QNAN_PAIR(pwt->w[0], pws->w[0], 32, status)) {
6788            MSA_FLOAT_MAXOP(pwx->w[0], max, pwt->w[0], pwt->w[0], 32);
6789        } else {
6790            MSA_FLOAT_MAXOP(pwx->w[0], max, pws->w[0], pwt->w[0], 32);
6791        }
6792
6793        if (NUMBER_QNAN_PAIR(pws->w[1], pwt->w[1], 32, status)) {
6794            MSA_FLOAT_MAXOP(pwx->w[1], max, pws->w[1], pws->w[1], 32);
6795        } else if (NUMBER_QNAN_PAIR(pwt->w[1], pws->w[1], 32, status)) {
6796            MSA_FLOAT_MAXOP(pwx->w[1], max, pwt->w[1], pwt->w[1], 32);
6797        } else {
6798            MSA_FLOAT_MAXOP(pwx->w[1], max, pws->w[1], pwt->w[1], 32);
6799        }
6800
6801        if (NUMBER_QNAN_PAIR(pws->w[2], pwt->w[2], 32, status)) {
6802            MSA_FLOAT_MAXOP(pwx->w[2], max, pws->w[2], pws->w[2], 32);
6803        } else if (NUMBER_QNAN_PAIR(pwt->w[2], pws->w[2], 32, status)) {
6804            MSA_FLOAT_MAXOP(pwx->w[2], max, pwt->w[2], pwt->w[2], 32);
6805        } else {
6806            MSA_FLOAT_MAXOP(pwx->w[2], max, pws->w[2], pwt->w[2], 32);
6807        }
6808
6809        if (NUMBER_QNAN_PAIR(pws->w[3], pwt->w[3], 32, status)) {
6810            MSA_FLOAT_MAXOP(pwx->w[3], max, pws->w[3], pws->w[3], 32);
6811        } else if (NUMBER_QNAN_PAIR(pwt->w[3], pws->w[3], 32, status)) {
6812            MSA_FLOAT_MAXOP(pwx->w[3], max, pwt->w[3], pwt->w[3], 32);
6813        } else {
6814            MSA_FLOAT_MAXOP(pwx->w[3], max, pws->w[3], pwt->w[3], 32);
6815        }
6816
6817    } else if (df == DF_DOUBLE) {
6818
6819        if (NUMBER_QNAN_PAIR(pws->d[0], pwt->d[0], 64, status)) {
6820            MSA_FLOAT_MAXOP(pwx->d[0], max, pws->d[0], pws->d[0], 64);
6821        } else if (NUMBER_QNAN_PAIR(pwt->d[0], pws->d[0], 64, status)) {
6822            MSA_FLOAT_MAXOP(pwx->d[0], max, pwt->d[0], pwt->d[0], 64);
6823        } else {
6824            MSA_FLOAT_MAXOP(pwx->d[0], max, pws->d[0], pwt->d[0], 64);
6825        }
6826
6827        if (NUMBER_QNAN_PAIR(pws->d[1], pwt->d[1], 64, status)) {
6828            MSA_FLOAT_MAXOP(pwx->d[1], max, pws->d[1], pws->d[1], 64);
6829        } else if (NUMBER_QNAN_PAIR(pwt->d[1], pws->d[1], 64, status)) {
6830            MSA_FLOAT_MAXOP(pwx->d[1], max, pwt->d[1], pwt->d[1], 64);
6831        } else {
6832            MSA_FLOAT_MAXOP(pwx->d[1], max, pws->d[1], pwt->d[1], 64);
6833        }
6834
6835    } else {
6836
6837        assert(0);
6838
6839    }
6840
6841    check_msacsr_cause(env, GETPC());
6842
6843    msa_move_v(pwd, pwx);
6844}
6845
6846void helper_msa_fmax_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6847        uint32_t ws, uint32_t wt)
6848{
6849    float_status *status = &env->active_tc.msa_fp_status;
6850    wr_t wx, *pwx = &wx;
6851    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6852    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6853    wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
6854
6855    clear_msacsr_cause(env);
6856
6857    if (df == DF_WORD) {
6858        FMAXMIN_A(max, min, pwx->w[0], pws->w[0], pwt->w[0], 32, status);
6859        FMAXMIN_A(max, min, pwx->w[1], pws->w[1], pwt->w[1], 32, status);
6860        FMAXMIN_A(max, min, pwx->w[2], pws->w[2], pwt->w[2], 32, status);
6861        FMAXMIN_A(max, min, pwx->w[3], pws->w[3], pwt->w[3], 32, status);
6862    } else if (df == DF_DOUBLE) {
6863        FMAXMIN_A(max, min, pwx->d[0], pws->d[0], pwt->d[0], 64, status);
6864        FMAXMIN_A(max, min, pwx->d[1], pws->d[1], pwt->d[1], 64, status);
6865    } else {
6866        assert(0);
6867    }
6868
6869    check_msacsr_cause(env, GETPC());
6870
6871    msa_move_v(pwd, pwx);
6872}
6873
6874void helper_msa_fclass_df(CPUMIPSState *env, uint32_t df,
6875        uint32_t wd, uint32_t ws)
6876{
6877    float_status *status = &env->active_tc.msa_fp_status;
6878
6879    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6880    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6881    if (df == DF_WORD) {
6882        pwd->w[0] = float_class_s(pws->w[0], status);
6883        pwd->w[1] = float_class_s(pws->w[1], status);
6884        pwd->w[2] = float_class_s(pws->w[2], status);
6885        pwd->w[3] = float_class_s(pws->w[3], status);
6886    } else if (df == DF_DOUBLE) {
6887        pwd->d[0] = float_class_d(pws->d[0], status);
6888        pwd->d[1] = float_class_d(pws->d[1], status);
6889    } else {
6890        assert(0);
6891    }
6892}
6893
6894#define MSA_FLOAT_UNOP0(DEST, OP, ARG, BITS)                                \
6895    do {                                                                    \
6896        float_status *status = &env->active_tc.msa_fp_status;               \
6897        int c;                                                              \
6898                                                                            \
6899        set_float_exception_flags(0, status);                               \
6900        DEST = float ## BITS ## _ ## OP(ARG, status);                       \
6901        c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0);                      \
6902                                                                            \
6903        if (get_enabled_exceptions(env, c)) {                               \
6904            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
6905        } else if (float ## BITS ## _is_any_nan(ARG)) {                     \
6906            DEST = 0;                                                       \
6907        }                                                                   \
6908    } while (0)
6909
6910void helper_msa_ftrunc_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6911                            uint32_t ws)
6912{
6913    wr_t wx, *pwx = &wx;
6914    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6915    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6916    uint32_t i;
6917
6918    clear_msacsr_cause(env);
6919
6920    switch (df) {
6921    case DF_WORD:
6922        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6923            MSA_FLOAT_UNOP0(pwx->w[i], to_int32_round_to_zero, pws->w[i], 32);
6924        }
6925        break;
6926    case DF_DOUBLE:
6927        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6928            MSA_FLOAT_UNOP0(pwx->d[i], to_int64_round_to_zero, pws->d[i], 64);
6929        }
6930        break;
6931    default:
6932        assert(0);
6933    }
6934
6935    check_msacsr_cause(env, GETPC());
6936
6937    msa_move_v(pwd, pwx);
6938}
6939
6940void helper_msa_ftrunc_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6941                            uint32_t ws)
6942{
6943    wr_t wx, *pwx = &wx;
6944    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6945    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6946    uint32_t i;
6947
6948    clear_msacsr_cause(env);
6949
6950    switch (df) {
6951    case DF_WORD:
6952        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6953            MSA_FLOAT_UNOP0(pwx->w[i], to_uint32_round_to_zero, pws->w[i], 32);
6954        }
6955        break;
6956    case DF_DOUBLE:
6957        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6958            MSA_FLOAT_UNOP0(pwx->d[i], to_uint64_round_to_zero, pws->d[i], 64);
6959        }
6960        break;
6961    default:
6962        assert(0);
6963    }
6964
6965    check_msacsr_cause(env, GETPC());
6966
6967    msa_move_v(pwd, pwx);
6968}
6969
6970void helper_msa_fsqrt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
6971                         uint32_t ws)
6972{
6973    wr_t wx, *pwx = &wx;
6974    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
6975    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
6976    uint32_t i;
6977
6978    clear_msacsr_cause(env);
6979
6980    switch (df) {
6981    case DF_WORD:
6982        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
6983            MSA_FLOAT_UNOP(pwx->w[i], sqrt, pws->w[i], 32);
6984        }
6985        break;
6986    case DF_DOUBLE:
6987        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
6988            MSA_FLOAT_UNOP(pwx->d[i], sqrt, pws->d[i], 64);
6989        }
6990        break;
6991    default:
6992        assert(0);
6993    }
6994
6995    check_msacsr_cause(env, GETPC());
6996
6997    msa_move_v(pwd, pwx);
6998}
6999
7000#define MSA_FLOAT_RECIPROCAL(DEST, ARG, BITS)                               \
7001    do {                                                                    \
7002        float_status *status = &env->active_tc.msa_fp_status;               \
7003        int c;                                                              \
7004                                                                            \
7005        set_float_exception_flags(0, status);                               \
7006        DEST = float ## BITS ## _ ## div(FLOAT_ONE ## BITS, ARG, status);   \
7007        c = update_msacsr(env, float ## BITS ## _is_infinity(ARG) ||        \
7008                          float ## BITS ## _is_quiet_nan(DEST, status) ?    \
7009                          0 : RECIPROCAL_INEXACT,                           \
7010                          IS_DENORMAL(DEST, BITS));                         \
7011                                                                            \
7012        if (get_enabled_exceptions(env, c)) {                               \
7013            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
7014        }                                                                   \
7015    } while (0)
7016
7017void helper_msa_frsqrt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
7018                          uint32_t ws)
7019{
7020    wr_t wx, *pwx = &wx;
7021    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
7022    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
7023    uint32_t i;
7024
7025    clear_msacsr_cause(env);
7026
7027    switch (df) {
7028    case DF_WORD:
7029        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
7030            MSA_FLOAT_RECIPROCAL(pwx->w[i], float32_sqrt(pws->w[i],
7031                    &env->active_tc.msa_fp_status), 32);
7032        }
7033        break;
7034    case DF_DOUBLE:
7035        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
7036            MSA_FLOAT_RECIPROCAL(pwx->d[i], float64_sqrt(pws->d[i],
7037                    &env->active_tc.msa_fp_status), 64);
7038        }
7039        break;
7040    default:
7041        assert(0);
7042    }
7043
7044    check_msacsr_cause(env, GETPC());
7045
7046    msa_move_v(pwd, pwx);
7047}
7048
7049void helper_msa_frcp_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
7050                        uint32_t ws)
7051{
7052    wr_t wx, *pwx = &wx;
7053    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
7054    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
7055    uint32_t i;
7056
7057    clear_msacsr_cause(env);
7058
7059    switch (df) {
7060    case DF_WORD:
7061        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
7062            MSA_FLOAT_RECIPROCAL(pwx->w[i], pws->w[i], 32);
7063        }
7064        break;
7065    case DF_DOUBLE:
7066        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
7067            MSA_FLOAT_RECIPROCAL(pwx->d[i], pws->d[i], 64);
7068        }
7069        break;
7070    default:
7071        assert(0);
7072    }
7073
7074    check_msacsr_cause(env, GETPC());
7075
7076    msa_move_v(pwd, pwx);
7077}
7078
7079void helper_msa_frint_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
7080                         uint32_t ws)
7081{
7082    wr_t wx, *pwx = &wx;
7083    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
7084    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
7085    uint32_t i;
7086
7087    clear_msacsr_cause(env);
7088
7089    switch (df) {
7090    case DF_WORD:
7091        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
7092            MSA_FLOAT_UNOP(pwx->w[i], round_to_int, pws->w[i], 32);
7093        }
7094        break;
7095    case DF_DOUBLE:
7096        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
7097            MSA_FLOAT_UNOP(pwx->d[i], round_to_int, pws->d[i], 64);
7098        }
7099        break;
7100    default:
7101        assert(0);
7102    }
7103
7104    check_msacsr_cause(env, GETPC());
7105
7106    msa_move_v(pwd, pwx);
7107}
7108
7109#define MSA_FLOAT_LOGB(DEST, ARG, BITS)                                     \
7110    do {                                                                    \
7111        float_status *status = &env->active_tc.msa_fp_status;               \
7112        int c;                                                              \
7113                                                                            \
7114        set_float_exception_flags(0, status);                               \
7115        set_float_rounding_mode(float_round_down, status);                  \
7116        DEST = float ## BITS ## _ ## log2(ARG, status);                     \
7117        DEST = float ## BITS ## _ ## round_to_int(DEST, status);            \
7118        set_float_rounding_mode(ieee_rm[(env->active_tc.msacsr &            \
7119                                         MSACSR_RM_MASK) >> MSACSR_RM],     \
7120                                status);                                    \
7121                                                                            \
7122        set_float_exception_flags(get_float_exception_flags(status) &       \
7123                                  (~float_flag_inexact),                    \
7124                                  status);                                  \
7125                                                                            \
7126        c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS));                 \
7127                                                                            \
7128        if (get_enabled_exceptions(env, c)) {                               \
7129            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
7130        }                                                                   \
7131    } while (0)
7132
7133void helper_msa_flog2_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
7134                         uint32_t ws)
7135{
7136    wr_t wx, *pwx = &wx;
7137    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
7138    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
7139    uint32_t i;
7140
7141    clear_msacsr_cause(env);
7142
7143    switch (df) {
7144    case DF_WORD:
7145        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
7146            MSA_FLOAT_LOGB(pwx->w[i], pws->w[i], 32);
7147        }
7148        break;
7149    case DF_DOUBLE:
7150        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
7151            MSA_FLOAT_LOGB(pwx->d[i], pws->d[i], 64);
7152        }
7153        break;
7154    default:
7155        assert(0);
7156    }
7157
7158    check_msacsr_cause(env, GETPC());
7159
7160    msa_move_v(pwd, pwx);
7161}
7162
7163void helper_msa_fexupl_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
7164                          uint32_t ws)
7165{
7166    wr_t wx, *pwx = &wx;
7167    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
7168    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
7169    uint32_t i;
7170
7171    clear_msacsr_cause(env);
7172
7173    switch (df) {
7174    case DF_WORD:
7175        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
7176            /*
7177             * Half precision floats come in two formats: standard
7178             * IEEE and "ARM" format.  The latter gains extra exponent
7179             * range by omitting the NaN/Inf encodings.
7180             */
7181            flag ieee = 1;
7182
7183            MSA_FLOAT_BINOP(pwx->w[i], from_float16, Lh(pws, i), ieee, 32);
7184        }
7185        break;
7186    case DF_DOUBLE:
7187        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
7188            MSA_FLOAT_UNOP(pwx->d[i], from_float32, Lw(pws, i), 64);
7189        }
7190        break;
7191    default:
7192        assert(0);
7193    }
7194
7195    check_msacsr_cause(env, GETPC());
7196    msa_move_v(pwd, pwx);
7197}
7198
7199void helper_msa_fexupr_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
7200                          uint32_t ws)
7201{
7202    wr_t wx, *pwx = &wx;
7203    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
7204    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
7205    uint32_t i;
7206
7207    clear_msacsr_cause(env);
7208
7209    switch (df) {
7210    case DF_WORD:
7211        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
7212            /*
7213             * Half precision floats come in two formats: standard
7214             * IEEE and "ARM" format.  The latter gains extra exponent
7215             * range by omitting the NaN/Inf encodings.
7216             */
7217            flag ieee = 1;
7218
7219            MSA_FLOAT_BINOP(pwx->w[i], from_float16, Rh(pws, i), ieee, 32);
7220        }
7221        break;
7222    case DF_DOUBLE:
7223        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
7224            MSA_FLOAT_UNOP(pwx->d[i], from_float32, Rw(pws, i), 64);
7225        }
7226        break;
7227    default:
7228        assert(0);
7229    }
7230
7231    check_msacsr_cause(env, GETPC());
7232    msa_move_v(pwd, pwx);
7233}
7234
7235void helper_msa_ffql_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
7236                        uint32_t ws)
7237{
7238    wr_t wx, *pwx = &wx;
7239    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
7240    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
7241    uint32_t i;
7242
7243    switch (df) {
7244    case DF_WORD:
7245        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
7246            MSA_FLOAT_UNOP(pwx->w[i], from_q16, Lh(pws, i), 32);
7247        }
7248        break;
7249    case DF_DOUBLE:
7250        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
7251            MSA_FLOAT_UNOP(pwx->d[i], from_q32, Lw(pws, i), 64);
7252        }
7253        break;
7254    default:
7255        assert(0);
7256    }
7257
7258    msa_move_v(pwd, pwx);
7259}
7260
7261void helper_msa_ffqr_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
7262                        uint32_t ws)
7263{
7264    wr_t wx, *pwx = &wx;
7265    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
7266    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
7267    uint32_t i;
7268
7269    switch (df) {
7270    case DF_WORD:
7271        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
7272            MSA_FLOAT_UNOP(pwx->w[i], from_q16, Rh(pws, i), 32);
7273        }
7274        break;
7275    case DF_DOUBLE:
7276        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
7277            MSA_FLOAT_UNOP(pwx->d[i], from_q32, Rw(pws, i), 64);
7278        }
7279        break;
7280    default:
7281        assert(0);
7282    }
7283
7284    msa_move_v(pwd, pwx);
7285}
7286
7287void helper_msa_ftint_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
7288                           uint32_t ws)
7289{
7290    wr_t wx, *pwx = &wx;
7291    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
7292    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
7293    uint32_t i;
7294
7295    clear_msacsr_cause(env);
7296
7297    switch (df) {
7298    case DF_WORD:
7299        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
7300            MSA_FLOAT_UNOP0(pwx->w[i], to_int32, pws->w[i], 32);
7301        }
7302        break;
7303    case DF_DOUBLE:
7304        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
7305            MSA_FLOAT_UNOP0(pwx->d[i], to_int64, pws->d[i], 64);
7306        }
7307        break;
7308    default:
7309        assert(0);
7310    }
7311
7312    check_msacsr_cause(env, GETPC());
7313
7314    msa_move_v(pwd, pwx);
7315}
7316
7317void helper_msa_ftint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
7318                           uint32_t ws)
7319{
7320    wr_t wx, *pwx = &wx;
7321    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
7322    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
7323    uint32_t i;
7324
7325    clear_msacsr_cause(env);
7326
7327    switch (df) {
7328    case DF_WORD:
7329        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
7330            MSA_FLOAT_UNOP0(pwx->w[i], to_uint32, pws->w[i], 32);
7331        }
7332        break;
7333    case DF_DOUBLE:
7334        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
7335            MSA_FLOAT_UNOP0(pwx->d[i], to_uint64, pws->d[i], 64);
7336        }
7337        break;
7338    default:
7339        assert(0);
7340    }
7341
7342    check_msacsr_cause(env, GETPC());
7343
7344    msa_move_v(pwd, pwx);
7345}
7346
7347#define float32_from_int32 int32_to_float32
7348#define float32_from_uint32 uint32_to_float32
7349
7350#define float64_from_int64 int64_to_float64
7351#define float64_from_uint64 uint64_to_float64
7352
7353void helper_msa_ffint_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
7354                           uint32_t ws)
7355{
7356    wr_t wx, *pwx = &wx;
7357    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
7358    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
7359    uint32_t i;
7360
7361    clear_msacsr_cause(env);
7362
7363    switch (df) {
7364    case DF_WORD:
7365        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
7366            MSA_FLOAT_UNOP(pwx->w[i], from_int32, pws->w[i], 32);
7367        }
7368        break;
7369    case DF_DOUBLE:
7370        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
7371            MSA_FLOAT_UNOP(pwx->d[i], from_int64, pws->d[i], 64);
7372        }
7373        break;
7374    default:
7375        assert(0);
7376    }
7377
7378    check_msacsr_cause(env, GETPC());
7379
7380    msa_move_v(pwd, pwx);
7381}
7382
7383void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
7384                           uint32_t ws)
7385{
7386    wr_t wx, *pwx = &wx;
7387    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
7388    wr_t *pws = &(env->active_fpu.fpr[ws].wr);
7389    uint32_t i;
7390
7391    clear_msacsr_cause(env);
7392
7393    switch (df) {
7394    case DF_WORD:
7395        for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
7396            MSA_FLOAT_UNOP(pwx->w[i], from_uint32, pws->w[i], 32);
7397        }
7398        break;
7399    case DF_DOUBLE:
7400        for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
7401            MSA_FLOAT_UNOP(pwx->d[i], from_uint64, pws->d[i], 64);
7402        }
7403        break;
7404    default:
7405        assert(0);
7406    }
7407
7408    check_msacsr_cause(env, GETPC());
7409
7410    msa_move_v(pwd, pwx);
7411}
7412