qemu/target/mips/op_helper.c
<<
>>
Prefs
   1/*
   2 *  MIPS emulation helpers for qemu.
   3 *
   4 *  Copyright (c) 2004-2005 Jocelyn Mayer
   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#include "qemu/osdep.h"
  20#include "qemu/main-loop.h"
  21#include "cpu.h"
  22#include "internal.h"
  23#include "qemu/host-utils.h"
  24#include "exec/helper-proto.h"
  25#include "exec/exec-all.h"
  26#include "exec/cpu_ldst.h"
  27#include "sysemu/kvm.h"
  28
  29/*****************************************************************************/
  30/* Exceptions processing helpers */
  31
  32void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception,
  33                                int error_code)
  34{
  35    do_raise_exception_err(env, exception, error_code, 0);
  36}
  37
  38void helper_raise_exception(CPUMIPSState *env, uint32_t exception)
  39{
  40    do_raise_exception(env, exception, GETPC());
  41}
  42
  43void helper_raise_exception_debug(CPUMIPSState *env)
  44{
  45    do_raise_exception(env, EXCP_DEBUG, 0);
  46}
  47
  48static void raise_exception(CPUMIPSState *env, uint32_t exception)
  49{
  50    do_raise_exception(env, exception, 0);
  51}
  52
  53#if defined(CONFIG_USER_ONLY)
  54#define HELPER_LD(name, insn, type)                                     \
  55static inline type do_##name(CPUMIPSState *env, target_ulong addr,      \
  56                             int mem_idx, uintptr_t retaddr)            \
  57{                                                                       \
  58    return (type) cpu_##insn##_data_ra(env, addr, retaddr);             \
  59}
  60#else
  61#define HELPER_LD(name, insn, type)                                     \
  62static inline type do_##name(CPUMIPSState *env, target_ulong addr,      \
  63                             int mem_idx, uintptr_t retaddr)            \
  64{                                                                       \
  65    switch (mem_idx)                                                    \
  66    {                                                                   \
  67    case 0: return (type) cpu_##insn##_kernel_ra(env, addr, retaddr);   \
  68    case 1: return (type) cpu_##insn##_super_ra(env, addr, retaddr);    \
  69    default:                                                            \
  70    case 2: return (type) cpu_##insn##_user_ra(env, addr, retaddr);     \
  71    case 3: return (type) cpu_##insn##_error_ra(env, addr, retaddr);    \
  72    }                                                                   \
  73}
  74#endif
  75HELPER_LD(lw, ldl, int32_t)
  76#if defined(TARGET_MIPS64)
  77HELPER_LD(ld, ldq, int64_t)
  78#endif
  79#undef HELPER_LD
  80
  81#if defined(CONFIG_USER_ONLY)
  82#define HELPER_ST(name, insn, type)                                     \
  83static inline void do_##name(CPUMIPSState *env, target_ulong addr,      \
  84                             type val, int mem_idx, uintptr_t retaddr)  \
  85{                                                                       \
  86    cpu_##insn##_data_ra(env, addr, val, retaddr);                      \
  87}
  88#else
  89#define HELPER_ST(name, insn, type)                                     \
  90static inline void do_##name(CPUMIPSState *env, target_ulong addr,      \
  91                             type val, int mem_idx, uintptr_t retaddr)  \
  92{                                                                       \
  93    switch (mem_idx)                                                    \
  94    {                                                                   \
  95    case 0: cpu_##insn##_kernel_ra(env, addr, val, retaddr); break;     \
  96    case 1: cpu_##insn##_super_ra(env, addr, val, retaddr); break;      \
  97    default:                                                            \
  98    case 2: cpu_##insn##_user_ra(env, addr, val, retaddr); break;       \
  99    case 3:                                                             \
 100        cpu_##insn##_error_ra(env, addr, val, retaddr);                 \
 101        break;                                                          \
 102    }                                                                   \
 103}
 104#endif
 105HELPER_ST(sb, stb, uint8_t)
 106HELPER_ST(sw, stl, uint32_t)
 107#if defined(TARGET_MIPS64)
 108HELPER_ST(sd, stq, uint64_t)
 109#endif
 110#undef HELPER_ST
 111
 112/* 64 bits arithmetic for 32 bits hosts */
 113static inline uint64_t get_HILO(CPUMIPSState *env)
 114{
 115    return ((uint64_t)(env->active_tc.HI[0]) << 32) | (uint32_t)env->active_tc.LO[0];
 116}
 117
 118static inline target_ulong set_HIT0_LO(CPUMIPSState *env, uint64_t HILO)
 119{
 120    env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
 121    return env->active_tc.HI[0] = (int32_t)(HILO >> 32);
 122}
 123
 124static inline target_ulong set_HI_LOT0(CPUMIPSState *env, uint64_t HILO)
 125{
 126    target_ulong tmp = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
 127    env->active_tc.HI[0] = (int32_t)(HILO >> 32);
 128    return tmp;
 129}
 130
 131/* Multiplication variants of the vr54xx. */
 132target_ulong helper_muls(CPUMIPSState *env, target_ulong arg1,
 133                         target_ulong arg2)
 134{
 135    return set_HI_LOT0(env, 0 - ((int64_t)(int32_t)arg1 *
 136                                 (int64_t)(int32_t)arg2));
 137}
 138
 139target_ulong helper_mulsu(CPUMIPSState *env, target_ulong arg1,
 140                          target_ulong arg2)
 141{
 142    return set_HI_LOT0(env, 0 - (uint64_t)(uint32_t)arg1 *
 143                       (uint64_t)(uint32_t)arg2);
 144}
 145
 146target_ulong helper_macc(CPUMIPSState *env, target_ulong arg1,
 147                         target_ulong arg2)
 148{
 149    return set_HI_LOT0(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 *
 150                       (int64_t)(int32_t)arg2);
 151}
 152
 153target_ulong helper_macchi(CPUMIPSState *env, target_ulong arg1,
 154                           target_ulong arg2)
 155{
 156    return set_HIT0_LO(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 *
 157                       (int64_t)(int32_t)arg2);
 158}
 159
 160target_ulong helper_maccu(CPUMIPSState *env, target_ulong arg1,
 161                          target_ulong arg2)
 162{
 163    return set_HI_LOT0(env, (uint64_t)get_HILO(env) +
 164                       (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
 165}
 166
 167target_ulong helper_macchiu(CPUMIPSState *env, target_ulong arg1,
 168                            target_ulong arg2)
 169{
 170    return set_HIT0_LO(env, (uint64_t)get_HILO(env) +
 171                       (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
 172}
 173
 174target_ulong helper_msac(CPUMIPSState *env, target_ulong arg1,
 175                         target_ulong arg2)
 176{
 177    return set_HI_LOT0(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 *
 178                       (int64_t)(int32_t)arg2);
 179}
 180
 181target_ulong helper_msachi(CPUMIPSState *env, target_ulong arg1,
 182                           target_ulong arg2)
 183{
 184    return set_HIT0_LO(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 *
 185                       (int64_t)(int32_t)arg2);
 186}
 187
 188target_ulong helper_msacu(CPUMIPSState *env, target_ulong arg1,
 189                          target_ulong arg2)
 190{
 191    return set_HI_LOT0(env, (uint64_t)get_HILO(env) -
 192                       (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
 193}
 194
 195target_ulong helper_msachiu(CPUMIPSState *env, target_ulong arg1,
 196                            target_ulong arg2)
 197{
 198    return set_HIT0_LO(env, (uint64_t)get_HILO(env) -
 199                       (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
 200}
 201
 202target_ulong helper_mulhi(CPUMIPSState *env, target_ulong arg1,
 203                          target_ulong arg2)
 204{
 205    return set_HIT0_LO(env, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2);
 206}
 207
 208target_ulong helper_mulhiu(CPUMIPSState *env, target_ulong arg1,
 209                           target_ulong arg2)
 210{
 211    return set_HIT0_LO(env, (uint64_t)(uint32_t)arg1 *
 212                       (uint64_t)(uint32_t)arg2);
 213}
 214
 215target_ulong helper_mulshi(CPUMIPSState *env, target_ulong arg1,
 216                           target_ulong arg2)
 217{
 218    return set_HIT0_LO(env, 0 - (int64_t)(int32_t)arg1 *
 219                       (int64_t)(int32_t)arg2);
 220}
 221
 222target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1,
 223                            target_ulong arg2)
 224{
 225    return set_HIT0_LO(env, 0 - (uint64_t)(uint32_t)arg1 *
 226                       (uint64_t)(uint32_t)arg2);
 227}
 228
 229static inline target_ulong bitswap(target_ulong v)
 230{
 231    v = ((v >> 1) & (target_ulong)0x5555555555555555ULL) |
 232              ((v & (target_ulong)0x5555555555555555ULL) << 1);
 233    v = ((v >> 2) & (target_ulong)0x3333333333333333ULL) |
 234              ((v & (target_ulong)0x3333333333333333ULL) << 2);
 235    v = ((v >> 4) & (target_ulong)0x0F0F0F0F0F0F0F0FULL) |
 236              ((v & (target_ulong)0x0F0F0F0F0F0F0F0FULL) << 4);
 237    return v;
 238}
 239
 240#ifdef TARGET_MIPS64
 241target_ulong helper_dbitswap(target_ulong rt)
 242{
 243    return bitswap(rt);
 244}
 245#endif
 246
 247target_ulong helper_bitswap(target_ulong rt)
 248{
 249    return (int32_t)bitswap(rt);
 250}
 251
 252target_ulong helper_rotx(target_ulong rs, uint32_t shift, uint32_t shiftx,
 253                        uint32_t stripe)
 254{
 255    int i;
 256    uint64_t tmp0 = ((uint64_t)rs) << 32 | ((uint64_t)rs & 0xffffffff);
 257    uint64_t tmp1 = tmp0;
 258    for (i = 0; i <= 46; i++) {
 259        int s;
 260        if (i & 0x8) {
 261            s = shift;
 262        } else {
 263            s = shiftx;
 264        }
 265
 266        if (stripe != 0 && !(i & 0x4)) {
 267            s = ~s;
 268        }
 269        if (s & 0x10) {
 270            if (tmp0 & (1LL << (i + 16))) {
 271                tmp1 |= 1LL << i;
 272            } else {
 273                tmp1 &= ~(1LL << i);
 274            }
 275        }
 276    }
 277
 278    uint64_t tmp2 = tmp1;
 279    for (i = 0; i <= 38; i++) {
 280        int s;
 281        if (i & 0x4) {
 282            s = shift;
 283        } else {
 284            s = shiftx;
 285        }
 286
 287        if (s & 0x8) {
 288            if (tmp1 & (1LL << (i + 8))) {
 289                tmp2 |= 1LL << i;
 290            } else {
 291                tmp2 &= ~(1LL << i);
 292            }
 293        }
 294    }
 295
 296    uint64_t tmp3 = tmp2;
 297    for (i = 0; i <= 34; i++) {
 298        int s;
 299        if (i & 0x2) {
 300            s = shift;
 301        } else {
 302            s = shiftx;
 303        }
 304        if (s & 0x4) {
 305            if (tmp2 & (1LL << (i + 4))) {
 306                tmp3 |= 1LL << i;
 307            } else {
 308                tmp3 &= ~(1LL << i);
 309            }
 310        }
 311    }
 312
 313    uint64_t tmp4 = tmp3;
 314    for (i = 0; i <= 32; i++) {
 315        int s;
 316        if (i & 0x1) {
 317            s = shift;
 318        } else {
 319            s = shiftx;
 320        }
 321        if (s & 0x2) {
 322            if (tmp3 & (1LL << (i + 2))) {
 323                tmp4 |= 1LL << i;
 324            } else {
 325                tmp4 &= ~(1LL << i);
 326            }
 327        }
 328    }
 329
 330    uint64_t tmp5 = tmp4;
 331    for (i = 0; i <= 31; i++) {
 332        int s;
 333        s = shift;
 334        if (s & 0x1) {
 335            if (tmp4 & (1LL << (i + 1))) {
 336                tmp5 |= 1LL << i;
 337            } else {
 338                tmp5 &= ~(1LL << i);
 339            }
 340        }
 341    }
 342
 343    return (int64_t)(int32_t)(uint32_t)tmp5;
 344}
 345
 346#ifndef CONFIG_USER_ONLY
 347
 348static inline hwaddr do_translate_address(CPUMIPSState *env,
 349                                                      target_ulong address,
 350                                                      int rw, uintptr_t retaddr)
 351{
 352    hwaddr paddr;
 353    CPUState *cs = env_cpu(env);
 354
 355    paddr = cpu_mips_translate_address(env, address, rw);
 356
 357    if (paddr == -1LL) {
 358        cpu_loop_exit_restore(cs, retaddr);
 359    } else {
 360        return paddr;
 361    }
 362}
 363
 364#define HELPER_LD_ATOMIC(name, insn, almask)                                  \
 365target_ulong helper_##name(CPUMIPSState *env, target_ulong arg, int mem_idx)  \
 366{                                                                             \
 367    if (arg & almask) {                                                       \
 368        if (!(env->hflags & MIPS_HFLAG_DM)) {                                 \
 369            env->CP0_BadVAddr = arg;                                          \
 370        }                                                                     \
 371        do_raise_exception(env, EXCP_AdEL, GETPC());                          \
 372    }                                                                         \
 373    env->CP0_LLAddr = do_translate_address(env, arg, 0, GETPC());             \
 374    env->lladdr = arg;                                                        \
 375    env->llval = do_##insn(env, arg, mem_idx, GETPC());                       \
 376    return env->llval;                                                        \
 377}
 378HELPER_LD_ATOMIC(ll, lw, 0x3)
 379#ifdef TARGET_MIPS64
 380HELPER_LD_ATOMIC(lld, ld, 0x7)
 381#endif
 382#undef HELPER_LD_ATOMIC
 383#endif
 384
 385#ifdef TARGET_WORDS_BIGENDIAN
 386#define GET_LMASK(v) ((v) & 3)
 387#define GET_OFFSET(addr, offset) (addr + (offset))
 388#else
 389#define GET_LMASK(v) (((v) & 3) ^ 3)
 390#define GET_OFFSET(addr, offset) (addr - (offset))
 391#endif
 392
 393void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
 394                int mem_idx)
 395{
 396    do_sb(env, arg2, (uint8_t)(arg1 >> 24), mem_idx, GETPC());
 397
 398    if (GET_LMASK(arg2) <= 2) {
 399        do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16), mem_idx,
 400              GETPC());
 401    }
 402
 403    if (GET_LMASK(arg2) <= 1) {
 404        do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8), mem_idx,
 405              GETPC());
 406    }
 407
 408    if (GET_LMASK(arg2) == 0) {
 409        do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)arg1, mem_idx,
 410              GETPC());
 411    }
 412}
 413
 414void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
 415                int mem_idx)
 416{
 417    do_sb(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
 418
 419    if (GET_LMASK(arg2) >= 1) {
 420        do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx,
 421              GETPC());
 422    }
 423
 424    if (GET_LMASK(arg2) >= 2) {
 425        do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx,
 426              GETPC());
 427    }
 428
 429    if (GET_LMASK(arg2) == 3) {
 430        do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx,
 431              GETPC());
 432    }
 433}
 434
 435#if defined(TARGET_MIPS64)
 436/* "half" load and stores.  We must do the memory access inline,
 437   or fault handling won't work.  */
 438
 439#ifdef TARGET_WORDS_BIGENDIAN
 440#define GET_LMASK64(v) ((v) & 7)
 441#else
 442#define GET_LMASK64(v) (((v) & 7) ^ 7)
 443#endif
 444
 445void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
 446                int mem_idx)
 447{
 448    do_sb(env, arg2, (uint8_t)(arg1 >> 56), mem_idx, GETPC());
 449
 450    if (GET_LMASK64(arg2) <= 6) {
 451        do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48), mem_idx,
 452              GETPC());
 453    }
 454
 455    if (GET_LMASK64(arg2) <= 5) {
 456        do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40), mem_idx,
 457              GETPC());
 458    }
 459
 460    if (GET_LMASK64(arg2) <= 4) {
 461        do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32), mem_idx,
 462              GETPC());
 463    }
 464
 465    if (GET_LMASK64(arg2) <= 3) {
 466        do_sb(env, GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24), mem_idx,
 467              GETPC());
 468    }
 469
 470    if (GET_LMASK64(arg2) <= 2) {
 471        do_sb(env, GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16), mem_idx,
 472              GETPC());
 473    }
 474
 475    if (GET_LMASK64(arg2) <= 1) {
 476        do_sb(env, GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8), mem_idx,
 477              GETPC());
 478    }
 479
 480    if (GET_LMASK64(arg2) <= 0) {
 481        do_sb(env, GET_OFFSET(arg2, 7), (uint8_t)arg1, mem_idx,
 482              GETPC());
 483    }
 484}
 485
 486void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
 487                int mem_idx)
 488{
 489    do_sb(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
 490
 491    if (GET_LMASK64(arg2) >= 1) {
 492        do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx,
 493              GETPC());
 494    }
 495
 496    if (GET_LMASK64(arg2) >= 2) {
 497        do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx,
 498              GETPC());
 499    }
 500
 501    if (GET_LMASK64(arg2) >= 3) {
 502        do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx,
 503              GETPC());
 504    }
 505
 506    if (GET_LMASK64(arg2) >= 4) {
 507        do_sb(env, GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32), mem_idx,
 508              GETPC());
 509    }
 510
 511    if (GET_LMASK64(arg2) >= 5) {
 512        do_sb(env, GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40), mem_idx,
 513              GETPC());
 514    }
 515
 516    if (GET_LMASK64(arg2) >= 6) {
 517        do_sb(env, GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48), mem_idx,
 518              GETPC());
 519    }
 520
 521    if (GET_LMASK64(arg2) == 7) {
 522        do_sb(env, GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56), mem_idx,
 523              GETPC());
 524    }
 525}
 526#endif /* TARGET_MIPS64 */
 527
 528static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 };
 529
 530void helper_lwm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
 531                uint32_t mem_idx)
 532{
 533    target_ulong base_reglist = reglist & 0xf;
 534    target_ulong do_r31 = reglist & 0x10;
 535
 536    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
 537        target_ulong i;
 538
 539        for (i = 0; i < base_reglist; i++) {
 540            env->active_tc.gpr[multiple_regs[i]] =
 541                (target_long)do_lw(env, addr, mem_idx, GETPC());
 542            addr += 4;
 543        }
 544    }
 545
 546    if (do_r31) {
 547        env->active_tc.gpr[31] = (target_long)do_lw(env, addr, mem_idx,
 548                                                    GETPC());
 549    }
 550}
 551
 552void helper_swm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
 553                uint32_t mem_idx)
 554{
 555    target_ulong base_reglist = reglist & 0xf;
 556    target_ulong do_r31 = reglist & 0x10;
 557
 558    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
 559        target_ulong i;
 560
 561        for (i = 0; i < base_reglist; i++) {
 562            do_sw(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx,
 563                  GETPC());
 564            addr += 4;
 565        }
 566    }
 567
 568    if (do_r31) {
 569        do_sw(env, addr, env->active_tc.gpr[31], mem_idx, GETPC());
 570    }
 571}
 572
 573#if defined(TARGET_MIPS64)
 574void helper_ldm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
 575                uint32_t mem_idx)
 576{
 577    target_ulong base_reglist = reglist & 0xf;
 578    target_ulong do_r31 = reglist & 0x10;
 579
 580    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
 581        target_ulong i;
 582
 583        for (i = 0; i < base_reglist; i++) {
 584            env->active_tc.gpr[multiple_regs[i]] = do_ld(env, addr, mem_idx,
 585                                                         GETPC());
 586            addr += 8;
 587        }
 588    }
 589
 590    if (do_r31) {
 591        env->active_tc.gpr[31] = do_ld(env, addr, mem_idx, GETPC());
 592    }
 593}
 594
 595void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
 596                uint32_t mem_idx)
 597{
 598    target_ulong base_reglist = reglist & 0xf;
 599    target_ulong do_r31 = reglist & 0x10;
 600
 601    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
 602        target_ulong i;
 603
 604        for (i = 0; i < base_reglist; i++) {
 605            do_sd(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx,
 606                  GETPC());
 607            addr += 8;
 608        }
 609    }
 610
 611    if (do_r31) {
 612        do_sd(env, addr, env->active_tc.gpr[31], mem_idx, GETPC());
 613    }
 614}
 615#endif
 616
 617#ifndef CONFIG_USER_ONLY
 618/* SMP helpers.  */
 619static bool mips_vpe_is_wfi(MIPSCPU *c)
 620{
 621    CPUState *cpu = CPU(c);
 622    CPUMIPSState *env = &c->env;
 623
 624    /* If the VPE is halted but otherwise active, it means it's waiting for
 625       an interrupt.  */
 626    return cpu->halted && mips_vpe_active(env);
 627}
 628
 629static bool mips_vp_is_wfi(MIPSCPU *c)
 630{
 631    CPUState *cpu = CPU(c);
 632    CPUMIPSState *env = &c->env;
 633
 634    return cpu->halted && mips_vp_active(env);
 635}
 636
 637static inline void mips_vpe_wake(MIPSCPU *c)
 638{
 639    /* Don't set ->halted = 0 directly, let it be done via cpu_has_work
 640       because there might be other conditions that state that c should
 641       be sleeping.  */
 642    qemu_mutex_lock_iothread();
 643    cpu_interrupt(CPU(c), CPU_INTERRUPT_WAKE);
 644    qemu_mutex_unlock_iothread();
 645}
 646
 647static inline void mips_vpe_sleep(MIPSCPU *cpu)
 648{
 649    CPUState *cs = CPU(cpu);
 650
 651    /* The VPE was shut off, really go to bed.
 652       Reset any old _WAKE requests.  */
 653    cs->halted = 1;
 654    cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
 655}
 656
 657static inline void mips_tc_wake(MIPSCPU *cpu, int tc)
 658{
 659    CPUMIPSState *c = &cpu->env;
 660
 661    /* FIXME: TC reschedule.  */
 662    if (mips_vpe_active(c) && !mips_vpe_is_wfi(cpu)) {
 663        mips_vpe_wake(cpu);
 664    }
 665}
 666
 667static inline void mips_tc_sleep(MIPSCPU *cpu, int tc)
 668{
 669    CPUMIPSState *c = &cpu->env;
 670
 671    /* FIXME: TC reschedule.  */
 672    if (!mips_vpe_active(c)) {
 673        mips_vpe_sleep(cpu);
 674    }
 675}
 676
 677/**
 678 * mips_cpu_map_tc:
 679 * @env: CPU from which mapping is performed.
 680 * @tc: Should point to an int with the value of the global TC index.
 681 *
 682 * This function will transform @tc into a local index within the
 683 * returned #CPUMIPSState.
 684 */
 685/* FIXME: This code assumes that all VPEs have the same number of TCs,
 686          which depends on runtime setup. Can probably be fixed by
 687          walking the list of CPUMIPSStates.  */
 688static CPUMIPSState *mips_cpu_map_tc(CPUMIPSState *env, int *tc)
 689{
 690    MIPSCPU *cpu;
 691    CPUState *cs;
 692    CPUState *other_cs;
 693    int vpe_idx;
 694    int tc_idx = *tc;
 695
 696    if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))) {
 697        /* Not allowed to address other CPUs.  */
 698        *tc = env->current_tc;
 699        return env;
 700    }
 701
 702    cs = env_cpu(env);
 703    vpe_idx = tc_idx / cs->nr_threads;
 704    *tc = tc_idx % cs->nr_threads;
 705    other_cs = qemu_get_cpu(vpe_idx);
 706    if (other_cs == NULL) {
 707        return env;
 708    }
 709    cpu = MIPS_CPU(other_cs);
 710    return &cpu->env;
 711}
 712
 713/* The per VPE CP0_Status register shares some fields with the per TC
 714   CP0_TCStatus registers. These fields are wired to the same registers,
 715   so changes to either of them should be reflected on both registers.
 716
 717   Also, EntryHi shares the bottom 8 bit ASID with TCStauts.
 718
 719   These helper call synchronizes the regs for a given cpu.  */
 720
 721/* Called for updates to CP0_Status.  Defined in "cpu.h" for gdbstub.c.  */
 722/* static inline void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu,
 723                                     int tc);  */
 724
 725/* Called for updates to CP0_TCStatus.  */
 726static void sync_c0_tcstatus(CPUMIPSState *cpu, int tc,
 727                             target_ulong v)
 728{
 729    uint32_t status;
 730    uint32_t tcu, tmx, tasid, tksu;
 731    uint32_t mask = ((1U << CP0St_CU3)
 732                       | (1 << CP0St_CU2)
 733                       | (1 << CP0St_CU1)
 734                       | (1 << CP0St_CU0)
 735                       | (1 << CP0St_MX)
 736                       | (3 << CP0St_KSU));
 737
 738    tcu = (v >> CP0TCSt_TCU0) & 0xf;
 739    tmx = (v >> CP0TCSt_TMX) & 0x1;
 740    tasid = v & cpu->CP0_EntryHi_ASID_mask;
 741    tksu = (v >> CP0TCSt_TKSU) & 0x3;
 742
 743    status = tcu << CP0St_CU0;
 744    status |= tmx << CP0St_MX;
 745    status |= tksu << CP0St_KSU;
 746
 747    cpu->CP0_Status &= ~mask;
 748    cpu->CP0_Status |= status;
 749
 750    /* Sync the TASID with EntryHi.  */
 751    cpu->CP0_EntryHi &= ~cpu->CP0_EntryHi_ASID_mask;
 752    cpu->CP0_EntryHi |= tasid;
 753
 754    compute_hflags(cpu);
 755}
 756
 757/* Called for updates to CP0_EntryHi.  */
 758static void sync_c0_entryhi(CPUMIPSState *cpu, int tc)
 759{
 760    int32_t *tcst;
 761    uint32_t asid, v = cpu->CP0_EntryHi;
 762
 763    asid = v & cpu->CP0_EntryHi_ASID_mask;
 764
 765    if (tc == cpu->current_tc) {
 766        tcst = &cpu->active_tc.CP0_TCStatus;
 767    } else {
 768        tcst = &cpu->tcs[tc].CP0_TCStatus;
 769    }
 770
 771    *tcst &= ~cpu->CP0_EntryHi_ASID_mask;
 772    *tcst |= asid;
 773}
 774
 775/* CP0 helpers */
 776target_ulong helper_mfc0_mvpcontrol(CPUMIPSState *env)
 777{
 778    return env->mvp->CP0_MVPControl;
 779}
 780
 781target_ulong helper_mfc0_mvpconf0(CPUMIPSState *env)
 782{
 783    return env->mvp->CP0_MVPConf0;
 784}
 785
 786target_ulong helper_mfc0_mvpconf1(CPUMIPSState *env)
 787{
 788    return env->mvp->CP0_MVPConf1;
 789}
 790
 791target_ulong helper_mfc0_random(CPUMIPSState *env)
 792{
 793    return (int32_t)cpu_mips_get_random(env);
 794}
 795
 796target_ulong helper_mfc0_tcstatus(CPUMIPSState *env)
 797{
 798    return env->active_tc.CP0_TCStatus;
 799}
 800
 801target_ulong helper_mftc0_tcstatus(CPUMIPSState *env)
 802{
 803    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 804    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
 805
 806    if (other_tc == other->current_tc)
 807        return other->active_tc.CP0_TCStatus;
 808    else
 809        return other->tcs[other_tc].CP0_TCStatus;
 810}
 811
 812target_ulong helper_mfc0_tcbind(CPUMIPSState *env)
 813{
 814    return env->active_tc.CP0_TCBind;
 815}
 816
 817target_ulong helper_mftc0_tcbind(CPUMIPSState *env)
 818{
 819    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 820    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
 821
 822    if (other_tc == other->current_tc)
 823        return other->active_tc.CP0_TCBind;
 824    else
 825        return other->tcs[other_tc].CP0_TCBind;
 826}
 827
 828target_ulong helper_mfc0_tcrestart(CPUMIPSState *env)
 829{
 830    return env->active_tc.PC;
 831}
 832
 833target_ulong helper_mftc0_tcrestart(CPUMIPSState *env)
 834{
 835    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 836    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
 837
 838    if (other_tc == other->current_tc)
 839        return other->active_tc.PC;
 840    else
 841        return other->tcs[other_tc].PC;
 842}
 843
 844target_ulong helper_mfc0_tchalt(CPUMIPSState *env)
 845{
 846    return env->active_tc.CP0_TCHalt;
 847}
 848
 849target_ulong helper_mftc0_tchalt(CPUMIPSState *env)
 850{
 851    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 852    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
 853
 854    if (other_tc == other->current_tc)
 855        return other->active_tc.CP0_TCHalt;
 856    else
 857        return other->tcs[other_tc].CP0_TCHalt;
 858}
 859
 860target_ulong helper_mfc0_tccontext(CPUMIPSState *env)
 861{
 862    return env->active_tc.CP0_TCContext;
 863}
 864
 865target_ulong helper_mftc0_tccontext(CPUMIPSState *env)
 866{
 867    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 868    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
 869
 870    if (other_tc == other->current_tc)
 871        return other->active_tc.CP0_TCContext;
 872    else
 873        return other->tcs[other_tc].CP0_TCContext;
 874}
 875
 876target_ulong helper_mfc0_tcschedule(CPUMIPSState *env)
 877{
 878    return env->active_tc.CP0_TCSchedule;
 879}
 880
 881target_ulong helper_mftc0_tcschedule(CPUMIPSState *env)
 882{
 883    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 884    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
 885
 886    if (other_tc == other->current_tc)
 887        return other->active_tc.CP0_TCSchedule;
 888    else
 889        return other->tcs[other_tc].CP0_TCSchedule;
 890}
 891
 892target_ulong helper_mfc0_tcschefback(CPUMIPSState *env)
 893{
 894    return env->active_tc.CP0_TCScheFBack;
 895}
 896
 897target_ulong helper_mftc0_tcschefback(CPUMIPSState *env)
 898{
 899    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 900    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
 901
 902    if (other_tc == other->current_tc)
 903        return other->active_tc.CP0_TCScheFBack;
 904    else
 905        return other->tcs[other_tc].CP0_TCScheFBack;
 906}
 907
 908target_ulong helper_mfc0_count(CPUMIPSState *env)
 909{
 910    return (int32_t)cpu_mips_get_count(env);
 911}
 912
 913target_ulong helper_mfc0_saar(CPUMIPSState *env)
 914{
 915    if ((env->CP0_SAARI & 0x3f) < 2) {
 916        return (int32_t) env->CP0_SAAR[env->CP0_SAARI & 0x3f];
 917    }
 918    return 0;
 919}
 920
 921target_ulong helper_mfhc0_saar(CPUMIPSState *env)
 922{
 923    if ((env->CP0_SAARI & 0x3f) < 2) {
 924        return env->CP0_SAAR[env->CP0_SAARI & 0x3f] >> 32;
 925    }
 926    return 0;
 927}
 928
 929target_ulong helper_mftc0_entryhi(CPUMIPSState *env)
 930{
 931    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 932    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
 933
 934    return other->CP0_EntryHi;
 935}
 936
 937target_ulong helper_mftc0_cause(CPUMIPSState *env)
 938{
 939    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 940    int32_t tccause;
 941    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
 942
 943    if (other_tc == other->current_tc) {
 944        tccause = other->CP0_Cause;
 945    } else {
 946        tccause = other->CP0_Cause;
 947    }
 948
 949    return tccause;
 950}
 951
 952target_ulong helper_mftc0_status(CPUMIPSState *env)
 953{
 954    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 955    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
 956
 957    return other->CP0_Status;
 958}
 959
 960target_ulong helper_mfc0_lladdr(CPUMIPSState *env)
 961{
 962    return (int32_t)(env->CP0_LLAddr >> env->CP0_LLAddr_shift);
 963}
 964
 965target_ulong helper_mfc0_maar(CPUMIPSState *env)
 966{
 967    return (int32_t) env->CP0_MAAR[env->CP0_MAARI];
 968}
 969
 970target_ulong helper_mfhc0_maar(CPUMIPSState *env)
 971{
 972    return env->CP0_MAAR[env->CP0_MAARI] >> 32;
 973}
 974
 975target_ulong helper_mfc0_watchlo(CPUMIPSState *env, uint32_t sel)
 976{
 977    return (int32_t)env->CP0_WatchLo[sel];
 978}
 979
 980target_ulong helper_mfc0_watchhi(CPUMIPSState *env, uint32_t sel)
 981{
 982    return env->CP0_WatchHi[sel];
 983}
 984
 985target_ulong helper_mfc0_debug(CPUMIPSState *env)
 986{
 987    target_ulong t0 = env->CP0_Debug;
 988    if (env->hflags & MIPS_HFLAG_DM)
 989        t0 |= 1 << CP0DB_DM;
 990
 991    return t0;
 992}
 993
 994target_ulong helper_mftc0_debug(CPUMIPSState *env)
 995{
 996    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 997    int32_t tcstatus;
 998    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
 999
1000    if (other_tc == other->current_tc)
1001        tcstatus = other->active_tc.CP0_Debug_tcstatus;
1002    else
1003        tcstatus = other->tcs[other_tc].CP0_Debug_tcstatus;
1004
1005    /* XXX: Might be wrong, check with EJTAG spec. */
1006    return (other->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1007            (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1008}
1009
1010#if defined(TARGET_MIPS64)
1011target_ulong helper_dmfc0_tcrestart(CPUMIPSState *env)
1012{
1013    return env->active_tc.PC;
1014}
1015
1016target_ulong helper_dmfc0_tchalt(CPUMIPSState *env)
1017{
1018    return env->active_tc.CP0_TCHalt;
1019}
1020
1021target_ulong helper_dmfc0_tccontext(CPUMIPSState *env)
1022{
1023    return env->active_tc.CP0_TCContext;
1024}
1025
1026target_ulong helper_dmfc0_tcschedule(CPUMIPSState *env)
1027{
1028    return env->active_tc.CP0_TCSchedule;
1029}
1030
1031target_ulong helper_dmfc0_tcschefback(CPUMIPSState *env)
1032{
1033    return env->active_tc.CP0_TCScheFBack;
1034}
1035
1036target_ulong helper_dmfc0_lladdr(CPUMIPSState *env)
1037{
1038    return env->CP0_LLAddr >> env->CP0_LLAddr_shift;
1039}
1040
1041target_ulong helper_dmfc0_maar(CPUMIPSState *env)
1042{
1043    return env->CP0_MAAR[env->CP0_MAARI];
1044}
1045
1046target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel)
1047{
1048    return env->CP0_WatchLo[sel];
1049}
1050
1051target_ulong helper_dmfc0_saar(CPUMIPSState *env)
1052{
1053    if ((env->CP0_SAARI & 0x3f) < 2) {
1054        return env->CP0_SAAR[env->CP0_SAARI & 0x3f];
1055    }
1056    return 0;
1057}
1058#endif /* TARGET_MIPS64 */
1059
1060void helper_mtc0_index(CPUMIPSState *env, target_ulong arg1)
1061{
1062    uint32_t index_p = env->CP0_Index & 0x80000000;
1063    uint32_t tlb_index = arg1 & 0x7fffffff;
1064    if (tlb_index < env->tlb->nb_tlb) {
1065        if (env->insn_flags & ISA_MIPS32R6) {
1066            index_p |= arg1 & 0x80000000;
1067        }
1068        env->CP0_Index = index_p | tlb_index;
1069    }
1070}
1071
1072void helper_mtc0_mvpcontrol(CPUMIPSState *env, target_ulong arg1)
1073{
1074    uint32_t mask = 0;
1075    uint32_t newval;
1076
1077    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
1078        mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
1079                (1 << CP0MVPCo_EVP);
1080    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1081        mask |= (1 << CP0MVPCo_STLB);
1082    newval = (env->mvp->CP0_MVPControl & ~mask) | (arg1 & mask);
1083
1084    // TODO: Enable/disable shared TLB, enable/disable VPEs.
1085
1086    env->mvp->CP0_MVPControl = newval;
1087}
1088
1089void helper_mtc0_vpecontrol(CPUMIPSState *env, target_ulong arg1)
1090{
1091    uint32_t mask;
1092    uint32_t newval;
1093
1094    mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1095           (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1096    newval = (env->CP0_VPEControl & ~mask) | (arg1 & mask);
1097
1098    /* Yield scheduler intercept not implemented. */
1099    /* Gating storage scheduler intercept not implemented. */
1100
1101    // TODO: Enable/disable TCs.
1102
1103    env->CP0_VPEControl = newval;
1104}
1105
1106void helper_mttc0_vpecontrol(CPUMIPSState *env, target_ulong arg1)
1107{
1108    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1109    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1110    uint32_t mask;
1111    uint32_t newval;
1112
1113    mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1114           (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1115    newval = (other->CP0_VPEControl & ~mask) | (arg1 & mask);
1116
1117    /* TODO: Enable/disable TCs.  */
1118
1119    other->CP0_VPEControl = newval;
1120}
1121
1122target_ulong helper_mftc0_vpecontrol(CPUMIPSState *env)
1123{
1124    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1125    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1126    /* FIXME: Mask away return zero on read bits.  */
1127    return other->CP0_VPEControl;
1128}
1129
1130target_ulong helper_mftc0_vpeconf0(CPUMIPSState *env)
1131{
1132    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1133    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1134
1135    return other->CP0_VPEConf0;
1136}
1137
1138void helper_mtc0_vpeconf0(CPUMIPSState *env, target_ulong arg1)
1139{
1140    uint32_t mask = 0;
1141    uint32_t newval;
1142
1143    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
1144        if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
1145            mask |= (0xff << CP0VPEC0_XTC);
1146        mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1147    }
1148    newval = (env->CP0_VPEConf0 & ~mask) | (arg1 & mask);
1149
1150    // TODO: TC exclusive handling due to ERL/EXL.
1151
1152    env->CP0_VPEConf0 = newval;
1153}
1154
1155void helper_mttc0_vpeconf0(CPUMIPSState *env, target_ulong arg1)
1156{
1157    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1158    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1159    uint32_t mask = 0;
1160    uint32_t newval;
1161
1162    mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1163    newval = (other->CP0_VPEConf0 & ~mask) | (arg1 & mask);
1164
1165    /* TODO: TC exclusive handling due to ERL/EXL.  */
1166    other->CP0_VPEConf0 = newval;
1167}
1168
1169void helper_mtc0_vpeconf1(CPUMIPSState *env, target_ulong arg1)
1170{
1171    uint32_t mask = 0;
1172    uint32_t newval;
1173
1174    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1175        mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
1176                (0xff << CP0VPEC1_NCP1);
1177    newval = (env->CP0_VPEConf1 & ~mask) | (arg1 & mask);
1178
1179    /* UDI not implemented. */
1180    /* CP2 not implemented. */
1181
1182    // TODO: Handle FPU (CP1) binding.
1183
1184    env->CP0_VPEConf1 = newval;
1185}
1186
1187void helper_mtc0_yqmask(CPUMIPSState *env, target_ulong arg1)
1188{
1189    /* Yield qualifier inputs not implemented. */
1190    env->CP0_YQMask = 0x00000000;
1191}
1192
1193void helper_mtc0_vpeopt(CPUMIPSState *env, target_ulong arg1)
1194{
1195    env->CP0_VPEOpt = arg1 & 0x0000ffff;
1196}
1197
1198#define MTC0_ENTRYLO_MASK(env) ((env->PAMask >> 6) & 0x3FFFFFFF)
1199
1200void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1)
1201{
1202    /* 1k pages not implemented */
1203    target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
1204    env->CP0_EntryLo0 = (arg1 & MTC0_ENTRYLO_MASK(env))
1205                        | (rxi << (CP0EnLo_XI - 30));
1206}
1207
1208#if defined(TARGET_MIPS64)
1209#define DMTC0_ENTRYLO_MASK(env) (env->PAMask >> 6)
1210
1211void helper_dmtc0_entrylo0(CPUMIPSState *env, uint64_t arg1)
1212{
1213    uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
1214    env->CP0_EntryLo0 = (arg1 & DMTC0_ENTRYLO_MASK(env)) | rxi;
1215}
1216#endif
1217
1218void helper_mtc0_tcstatus(CPUMIPSState *env, target_ulong arg1)
1219{
1220    uint32_t mask = env->CP0_TCStatus_rw_bitmask;
1221    uint32_t newval;
1222
1223    newval = (env->active_tc.CP0_TCStatus & ~mask) | (arg1 & mask);
1224
1225    env->active_tc.CP0_TCStatus = newval;
1226    sync_c0_tcstatus(env, env->current_tc, newval);
1227}
1228
1229void helper_mttc0_tcstatus(CPUMIPSState *env, target_ulong arg1)
1230{
1231    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1232    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1233
1234    if (other_tc == other->current_tc)
1235        other->active_tc.CP0_TCStatus = arg1;
1236    else
1237        other->tcs[other_tc].CP0_TCStatus = arg1;
1238    sync_c0_tcstatus(other, other_tc, arg1);
1239}
1240
1241void helper_mtc0_tcbind(CPUMIPSState *env, target_ulong arg1)
1242{
1243    uint32_t mask = (1 << CP0TCBd_TBE);
1244    uint32_t newval;
1245
1246    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1247        mask |= (1 << CP0TCBd_CurVPE);
1248    newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
1249    env->active_tc.CP0_TCBind = newval;
1250}
1251
1252void helper_mttc0_tcbind(CPUMIPSState *env, target_ulong arg1)
1253{
1254    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1255    uint32_t mask = (1 << CP0TCBd_TBE);
1256    uint32_t newval;
1257    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1258
1259    if (other->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1260        mask |= (1 << CP0TCBd_CurVPE);
1261    if (other_tc == other->current_tc) {
1262        newval = (other->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
1263        other->active_tc.CP0_TCBind = newval;
1264    } else {
1265        newval = (other->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask);
1266        other->tcs[other_tc].CP0_TCBind = newval;
1267    }
1268}
1269
1270void helper_mtc0_tcrestart(CPUMIPSState *env, target_ulong arg1)
1271{
1272    env->active_tc.PC = arg1;
1273    env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1274    env->CP0_LLAddr = 0;
1275    env->lladdr = 0;
1276    /* MIPS16 not implemented. */
1277}
1278
1279void helper_mttc0_tcrestart(CPUMIPSState *env, target_ulong arg1)
1280{
1281    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1282    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1283
1284    if (other_tc == other->current_tc) {
1285        other->active_tc.PC = arg1;
1286        other->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1287        other->CP0_LLAddr = 0;
1288        other->lladdr = 0;
1289        /* MIPS16 not implemented. */
1290    } else {
1291        other->tcs[other_tc].PC = arg1;
1292        other->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1293        other->CP0_LLAddr = 0;
1294        other->lladdr = 0;
1295        /* MIPS16 not implemented. */
1296    }
1297}
1298
1299void helper_mtc0_tchalt(CPUMIPSState *env, target_ulong arg1)
1300{
1301    MIPSCPU *cpu = env_archcpu(env);
1302
1303    env->active_tc.CP0_TCHalt = arg1 & 0x1;
1304
1305    // TODO: Halt TC / Restart (if allocated+active) TC.
1306    if (env->active_tc.CP0_TCHalt & 1) {
1307        mips_tc_sleep(cpu, env->current_tc);
1308    } else {
1309        mips_tc_wake(cpu, env->current_tc);
1310    }
1311}
1312
1313void helper_mttc0_tchalt(CPUMIPSState *env, target_ulong arg1)
1314{
1315    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1316    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1317    MIPSCPU *other_cpu = env_archcpu(other);
1318
1319    // TODO: Halt TC / Restart (if allocated+active) TC.
1320
1321    if (other_tc == other->current_tc)
1322        other->active_tc.CP0_TCHalt = arg1;
1323    else
1324        other->tcs[other_tc].CP0_TCHalt = arg1;
1325
1326    if (arg1 & 1) {
1327        mips_tc_sleep(other_cpu, other_tc);
1328    } else {
1329        mips_tc_wake(other_cpu, other_tc);
1330    }
1331}
1332
1333void helper_mtc0_tccontext(CPUMIPSState *env, target_ulong arg1)
1334{
1335    env->active_tc.CP0_TCContext = arg1;
1336}
1337
1338void helper_mttc0_tccontext(CPUMIPSState *env, target_ulong arg1)
1339{
1340    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1341    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1342
1343    if (other_tc == other->current_tc)
1344        other->active_tc.CP0_TCContext = arg1;
1345    else
1346        other->tcs[other_tc].CP0_TCContext = arg1;
1347}
1348
1349void helper_mtc0_tcschedule(CPUMIPSState *env, target_ulong arg1)
1350{
1351    env->active_tc.CP0_TCSchedule = arg1;
1352}
1353
1354void helper_mttc0_tcschedule(CPUMIPSState *env, target_ulong arg1)
1355{
1356    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1357    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1358
1359    if (other_tc == other->current_tc)
1360        other->active_tc.CP0_TCSchedule = arg1;
1361    else
1362        other->tcs[other_tc].CP0_TCSchedule = arg1;
1363}
1364
1365void helper_mtc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
1366{
1367    env->active_tc.CP0_TCScheFBack = arg1;
1368}
1369
1370void helper_mttc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
1371{
1372    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1373    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1374
1375    if (other_tc == other->current_tc)
1376        other->active_tc.CP0_TCScheFBack = arg1;
1377    else
1378        other->tcs[other_tc].CP0_TCScheFBack = arg1;
1379}
1380
1381void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1)
1382{
1383    /* 1k pages not implemented */
1384    target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
1385    env->CP0_EntryLo1 = (arg1 & MTC0_ENTRYLO_MASK(env))
1386                        | (rxi << (CP0EnLo_XI - 30));
1387}
1388
1389#if defined(TARGET_MIPS64)
1390void helper_dmtc0_entrylo1(CPUMIPSState *env, uint64_t arg1)
1391{
1392    uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
1393    env->CP0_EntryLo1 = (arg1 & DMTC0_ENTRYLO_MASK(env)) | rxi;
1394}
1395#endif
1396
1397void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
1398{
1399    env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
1400}
1401
1402void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
1403{
1404    uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
1405    if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) ||
1406        (mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
1407         mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
1408         mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) {
1409        env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1410    }
1411}
1412
1413void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
1414{
1415    update_pagemask(env, arg1, &env->CP0_PageMask);
1416}
1417
1418void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
1419{
1420    /* SmartMIPS not implemented */
1421    /* 1k pages not implemented */
1422    env->CP0_PageGrain = (arg1 & env->CP0_PageGrain_rw_bitmask) |
1423                         (env->CP0_PageGrain & ~env->CP0_PageGrain_rw_bitmask);
1424    compute_hflags(env);
1425    restore_pamask(env);
1426}
1427
1428void helper_mtc0_segctl0(CPUMIPSState *env, target_ulong arg1)
1429{
1430    CPUState *cs = env_cpu(env);
1431
1432    env->CP0_SegCtl0 = arg1 & CP0SC0_MASK;
1433    tlb_flush(cs);
1434}
1435
1436void helper_mtc0_segctl1(CPUMIPSState *env, target_ulong arg1)
1437{
1438    CPUState *cs = env_cpu(env);
1439
1440    env->CP0_SegCtl1 = arg1 & CP0SC1_MASK;
1441    tlb_flush(cs);
1442}
1443
1444void helper_mtc0_segctl2(CPUMIPSState *env, target_ulong arg1)
1445{
1446    CPUState *cs = env_cpu(env);
1447
1448    env->CP0_SegCtl2 = arg1 & CP0SC2_MASK;
1449    tlb_flush(cs);
1450}
1451
1452void helper_mtc0_pwfield(CPUMIPSState *env, target_ulong arg1)
1453{
1454#if defined(TARGET_MIPS64)
1455    uint64_t mask = 0x3F3FFFFFFFULL;
1456    uint32_t old_ptei = (env->CP0_PWField >> CP0PF_PTEI) & 0x3FULL;
1457    uint32_t new_ptei = (arg1 >> CP0PF_PTEI) & 0x3FULL;
1458
1459    if ((env->insn_flags & ISA_MIPS32R6)) {
1460        if (((arg1 >> CP0PF_BDI) & 0x3FULL) < 12) {
1461            mask &= ~(0x3FULL << CP0PF_BDI);
1462        }
1463        if (((arg1 >> CP0PF_GDI) & 0x3FULL) < 12) {
1464            mask &= ~(0x3FULL << CP0PF_GDI);
1465        }
1466        if (((arg1 >> CP0PF_UDI) & 0x3FULL) < 12) {
1467            mask &= ~(0x3FULL << CP0PF_UDI);
1468        }
1469        if (((arg1 >> CP0PF_MDI) & 0x3FULL) < 12) {
1470            mask &= ~(0x3FULL << CP0PF_MDI);
1471        }
1472        if (((arg1 >> CP0PF_PTI) & 0x3FULL) < 12) {
1473            mask &= ~(0x3FULL << CP0PF_PTI);
1474        }
1475    }
1476    env->CP0_PWField = arg1 & mask;
1477
1478    if ((new_ptei >= 32) ||
1479            ((env->insn_flags & ISA_MIPS32R6) &&
1480                    (new_ptei == 0 || new_ptei == 1))) {
1481        env->CP0_PWField = (env->CP0_PWField & ~0x3FULL) |
1482                (old_ptei << CP0PF_PTEI);
1483    }
1484#else
1485    uint32_t mask = 0x3FFFFFFF;
1486    uint32_t old_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F;
1487    uint32_t new_ptew = (arg1 >> CP0PF_PTEW) & 0x3F;
1488
1489    if ((env->insn_flags & ISA_MIPS32R6)) {
1490        if (((arg1 >> CP0PF_GDW) & 0x3F) < 12) {
1491            mask &= ~(0x3F << CP0PF_GDW);
1492        }
1493        if (((arg1 >> CP0PF_UDW) & 0x3F) < 12) {
1494            mask &= ~(0x3F << CP0PF_UDW);
1495        }
1496        if (((arg1 >> CP0PF_MDW) & 0x3F) < 12) {
1497            mask &= ~(0x3F << CP0PF_MDW);
1498        }
1499        if (((arg1 >> CP0PF_PTW) & 0x3F) < 12) {
1500            mask &= ~(0x3F << CP0PF_PTW);
1501        }
1502    }
1503    env->CP0_PWField = arg1 & mask;
1504
1505    if ((new_ptew >= 32) ||
1506            ((env->insn_flags & ISA_MIPS32R6) &&
1507                    (new_ptew == 0 || new_ptew == 1))) {
1508        env->CP0_PWField = (env->CP0_PWField & ~0x3F) |
1509                (old_ptew << CP0PF_PTEW);
1510    }
1511#endif
1512}
1513
1514void helper_mtc0_pwsize(CPUMIPSState *env, target_ulong arg1)
1515{
1516#if defined(TARGET_MIPS64)
1517    env->CP0_PWSize = arg1 & 0x3F7FFFFFFFULL;
1518#else
1519    env->CP0_PWSize = arg1 & 0x3FFFFFFF;
1520#endif
1521}
1522
1523void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
1524{
1525    if (env->insn_flags & ISA_MIPS32R6) {
1526        if (arg1 < env->tlb->nb_tlb) {
1527            env->CP0_Wired = arg1;
1528        }
1529    } else {
1530        env->CP0_Wired = arg1 % env->tlb->nb_tlb;
1531    }
1532}
1533
1534void helper_mtc0_pwctl(CPUMIPSState *env, target_ulong arg1)
1535{
1536#if defined(TARGET_MIPS64)
1537    /* PWEn = 0. Hardware page table walking is not implemented. */
1538    env->CP0_PWCtl = (env->CP0_PWCtl & 0x000000C0) | (arg1 & 0x5C00003F);
1539#else
1540    env->CP0_PWCtl = (arg1 & 0x800000FF);
1541#endif
1542}
1543
1544void helper_mtc0_srsconf0(CPUMIPSState *env, target_ulong arg1)
1545{
1546    env->CP0_SRSConf0 |= arg1 & env->CP0_SRSConf0_rw_bitmask;
1547}
1548
1549void helper_mtc0_srsconf1(CPUMIPSState *env, target_ulong arg1)
1550{
1551    env->CP0_SRSConf1 |= arg1 & env->CP0_SRSConf1_rw_bitmask;
1552}
1553
1554void helper_mtc0_srsconf2(CPUMIPSState *env, target_ulong arg1)
1555{
1556    env->CP0_SRSConf2 |= arg1 & env->CP0_SRSConf2_rw_bitmask;
1557}
1558
1559void helper_mtc0_srsconf3(CPUMIPSState *env, target_ulong arg1)
1560{
1561    env->CP0_SRSConf3 |= arg1 & env->CP0_SRSConf3_rw_bitmask;
1562}
1563
1564void helper_mtc0_srsconf4(CPUMIPSState *env, target_ulong arg1)
1565{
1566    env->CP0_SRSConf4 |= arg1 & env->CP0_SRSConf4_rw_bitmask;
1567}
1568
1569void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1)
1570{
1571    uint32_t mask = 0x0000000F;
1572
1573    if ((env->CP0_Config1 & (1 << CP0C1_PC)) &&
1574        (env->insn_flags & ISA_MIPS32R6)) {
1575        mask |= (1 << 4);
1576    }
1577    if (env->insn_flags & ISA_MIPS32R6) {
1578        mask |= (1 << 5);
1579    }
1580    if (env->CP0_Config3 & (1 << CP0C3_ULRI)) {
1581        mask |= (1 << 29);
1582
1583        if (arg1 & (1 << 29)) {
1584            env->hflags |= MIPS_HFLAG_HWRENA_ULR;
1585        } else {
1586            env->hflags &= ~MIPS_HFLAG_HWRENA_ULR;
1587        }
1588    }
1589
1590    env->CP0_HWREna = arg1 & mask;
1591}
1592
1593void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1)
1594{
1595    cpu_mips_store_count(env, arg1);
1596}
1597
1598void helper_mtc0_saari(CPUMIPSState *env, target_ulong arg1)
1599{
1600    uint32_t target = arg1 & 0x3f;
1601    if (target <= 1) {
1602        env->CP0_SAARI = target;
1603    }
1604}
1605
1606void helper_mtc0_saar(CPUMIPSState *env, target_ulong arg1)
1607{
1608    uint32_t target = env->CP0_SAARI & 0x3f;
1609    if (target < 2) {
1610        env->CP0_SAAR[target] = arg1 & 0x00000ffffffff03fULL;
1611        switch (target) {
1612        case 0:
1613            if (env->itu) {
1614                itc_reconfigure(env->itu);
1615            }
1616            break;
1617        }
1618    }
1619}
1620
1621void helper_mthc0_saar(CPUMIPSState *env, target_ulong arg1)
1622{
1623    uint32_t target = env->CP0_SAARI & 0x3f;
1624    if (target < 2) {
1625        env->CP0_SAAR[target] =
1626            (((uint64_t) arg1 << 32) & 0x00000fff00000000ULL) |
1627            (env->CP0_SAAR[target] & 0x00000000ffffffffULL);
1628        switch (target) {
1629        case 0:
1630            if (env->itu) {
1631                itc_reconfigure(env->itu);
1632            }
1633            break;
1634        }
1635    }
1636}
1637
1638void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
1639{
1640    target_ulong old, val, mask;
1641    mask = (TARGET_PAGE_MASK << 1) | env->CP0_EntryHi_ASID_mask;
1642    if (((env->CP0_Config4 >> CP0C4_IE) & 0x3) >= 2) {
1643        mask |= 1 << CP0EnHi_EHINV;
1644    }
1645
1646    /* 1k pages not implemented */
1647#if defined(TARGET_MIPS64)
1648    if (env->insn_flags & ISA_MIPS32R6) {
1649        int entryhi_r = extract64(arg1, 62, 2);
1650        int config0_at = extract32(env->CP0_Config0, 13, 2);
1651        bool no_supervisor = (env->CP0_Status_rw_bitmask & 0x8) == 0;
1652        if ((entryhi_r == 2) ||
1653            (entryhi_r == 1 && (no_supervisor || config0_at == 1))) {
1654            /* skip EntryHi.R field if new value is reserved */
1655            mask &= ~(0x3ull << 62);
1656        }
1657    }
1658    mask &= env->SEGMask;
1659#endif
1660    old = env->CP0_EntryHi;
1661    val = (arg1 & mask) | (old & ~mask);
1662    env->CP0_EntryHi = val;
1663    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1664        sync_c0_entryhi(env, env->current_tc);
1665    }
1666    /* If the ASID changes, flush qemu's TLB.  */
1667    if ((old & env->CP0_EntryHi_ASID_mask) !=
1668        (val & env->CP0_EntryHi_ASID_mask)) {
1669        tlb_flush(env_cpu(env));
1670    }
1671}
1672
1673void helper_mttc0_entryhi(CPUMIPSState *env, target_ulong arg1)
1674{
1675    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1676    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1677
1678    other->CP0_EntryHi = arg1;
1679    sync_c0_entryhi(other, other_tc);
1680}
1681
1682void helper_mtc0_compare(CPUMIPSState *env, target_ulong arg1)
1683{
1684    cpu_mips_store_compare(env, arg1);
1685}
1686
1687void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1)
1688{
1689    uint32_t val, old;
1690
1691    old = env->CP0_Status;
1692    cpu_mips_store_status(env, arg1);
1693    val = env->CP0_Status;
1694
1695    if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
1696        qemu_log("Status %08x (%08x) => %08x (%08x) Cause %08x",
1697                old, old & env->CP0_Cause & CP0Ca_IP_mask,
1698                val, val & env->CP0_Cause & CP0Ca_IP_mask,
1699                env->CP0_Cause);
1700        switch (cpu_mmu_index(env, false)) {
1701        case 3:
1702            qemu_log(", ERL\n");
1703            break;
1704        case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
1705        case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
1706        case MIPS_HFLAG_KM: qemu_log("\n"); break;
1707        default:
1708            cpu_abort(env_cpu(env), "Invalid MMU mode!\n");
1709            break;
1710        }
1711    }
1712}
1713
1714void helper_mttc0_status(CPUMIPSState *env, target_ulong arg1)
1715{
1716    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1717    uint32_t mask = env->CP0_Status_rw_bitmask & ~0xf1000018;
1718    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1719
1720    other->CP0_Status = (other->CP0_Status & ~mask) | (arg1 & mask);
1721    sync_c0_status(env, other, other_tc);
1722}
1723
1724void helper_mtc0_intctl(CPUMIPSState *env, target_ulong arg1)
1725{
1726    env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000003e0) | (arg1 & 0x000003e0);
1727}
1728
1729void helper_mtc0_srsctl(CPUMIPSState *env, target_ulong arg1)
1730{
1731    uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1732    env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask);
1733}
1734
1735void helper_mtc0_cause(CPUMIPSState *env, target_ulong arg1)
1736{
1737    cpu_mips_store_cause(env, arg1);
1738}
1739
1740void helper_mttc0_cause(CPUMIPSState *env, target_ulong arg1)
1741{
1742    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1743    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1744
1745    cpu_mips_store_cause(other, arg1);
1746}
1747
1748target_ulong helper_mftc0_epc(CPUMIPSState *env)
1749{
1750    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1751    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1752
1753    return other->CP0_EPC;
1754}
1755
1756target_ulong helper_mftc0_ebase(CPUMIPSState *env)
1757{
1758    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1759    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1760
1761    return other->CP0_EBase;
1762}
1763
1764void helper_mtc0_ebase(CPUMIPSState *env, target_ulong arg1)
1765{
1766    target_ulong mask = 0x3FFFF000 | env->CP0_EBaseWG_rw_bitmask;
1767    if (arg1 & env->CP0_EBaseWG_rw_bitmask) {
1768        mask |= ~0x3FFFFFFF;
1769    }
1770    env->CP0_EBase = (env->CP0_EBase & ~mask) | (arg1 & mask);
1771}
1772
1773void helper_mttc0_ebase(CPUMIPSState *env, target_ulong arg1)
1774{
1775    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1776    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1777    target_ulong mask = 0x3FFFF000 | env->CP0_EBaseWG_rw_bitmask;
1778    if (arg1 & env->CP0_EBaseWG_rw_bitmask) {
1779        mask |= ~0x3FFFFFFF;
1780    }
1781    other->CP0_EBase = (other->CP0_EBase & ~mask) | (arg1 & mask);
1782}
1783
1784target_ulong helper_mftc0_configx(CPUMIPSState *env, target_ulong idx)
1785{
1786    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1787    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1788
1789    switch (idx) {
1790    case 0: return other->CP0_Config0;
1791    case 1: return other->CP0_Config1;
1792    case 2: return other->CP0_Config2;
1793    case 3: return other->CP0_Config3;
1794    /* 4 and 5 are reserved.  */
1795    case 6: return other->CP0_Config6;
1796    case 7: return other->CP0_Config7;
1797    default:
1798        break;
1799    }
1800    return 0;
1801}
1802
1803void helper_mtc0_config0(CPUMIPSState *env, target_ulong arg1)
1804{
1805    env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007);
1806}
1807
1808void helper_mtc0_config2(CPUMIPSState *env, target_ulong arg1)
1809{
1810    /* tertiary/secondary caches not implemented */
1811    env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1812}
1813
1814void helper_mtc0_config3(CPUMIPSState *env, target_ulong arg1)
1815{
1816    if (env->insn_flags & ASE_MICROMIPS) {
1817        env->CP0_Config3 = (env->CP0_Config3 & ~(1 << CP0C3_ISA_ON_EXC)) |
1818                           (arg1 & (1 << CP0C3_ISA_ON_EXC));
1819    }
1820}
1821
1822void helper_mtc0_config4(CPUMIPSState *env, target_ulong arg1)
1823{
1824    env->CP0_Config4 = (env->CP0_Config4 & (~env->CP0_Config4_rw_bitmask)) |
1825                       (arg1 & env->CP0_Config4_rw_bitmask);
1826}
1827
1828void helper_mtc0_config5(CPUMIPSState *env, target_ulong arg1)
1829{
1830    env->CP0_Config5 = (env->CP0_Config5 & (~env->CP0_Config5_rw_bitmask)) |
1831                       (arg1 & env->CP0_Config5_rw_bitmask);
1832    compute_hflags(env);
1833}
1834
1835void helper_mtc0_lladdr(CPUMIPSState *env, target_ulong arg1)
1836{
1837    target_long mask = env->CP0_LLAddr_rw_bitmask;
1838    arg1 = arg1 << env->CP0_LLAddr_shift;
1839    env->CP0_LLAddr = (env->CP0_LLAddr & ~mask) | (arg1 & mask);
1840}
1841
1842#define MTC0_MAAR_MASK(env) \
1843        ((0x1ULL << 63) | ((env->PAMask >> 4) & ~0xFFFull) | 0x3)
1844
1845void helper_mtc0_maar(CPUMIPSState *env, target_ulong arg1)
1846{
1847    env->CP0_MAAR[env->CP0_MAARI] = arg1 & MTC0_MAAR_MASK(env);
1848}
1849
1850void helper_mthc0_maar(CPUMIPSState *env, target_ulong arg1)
1851{
1852    env->CP0_MAAR[env->CP0_MAARI] =
1853        (((uint64_t) arg1 << 32) & MTC0_MAAR_MASK(env)) |
1854        (env->CP0_MAAR[env->CP0_MAARI] & 0x00000000ffffffffULL);
1855}
1856
1857void helper_mtc0_maari(CPUMIPSState *env, target_ulong arg1)
1858{
1859    int index = arg1 & 0x3f;
1860    if (index == 0x3f) {
1861        /* Software may write all ones to INDEX to determine the
1862           maximum value supported. */
1863        env->CP0_MAARI = MIPS_MAAR_MAX - 1;
1864    } else if (index < MIPS_MAAR_MAX) {
1865        env->CP0_MAARI = index;
1866    }
1867    /* Other than the all ones, if the
1868       value written is not supported, then INDEX is unchanged
1869       from its previous value. */
1870}
1871
1872void helper_mtc0_watchlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1873{
1874    /* Watch exceptions for instructions, data loads, data stores
1875       not implemented. */
1876    env->CP0_WatchLo[sel] = (arg1 & ~0x7);
1877}
1878
1879void helper_mtc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
1880{
1881    int mask = 0x40000FF8 | (env->CP0_EntryHi_ASID_mask << CP0WH_ASID);
1882    env->CP0_WatchHi[sel] = arg1 & mask;
1883    env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
1884}
1885
1886void helper_mtc0_xcontext(CPUMIPSState *env, target_ulong arg1)
1887{
1888    target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1889    env->CP0_XContext = (env->CP0_XContext & mask) | (arg1 & ~mask);
1890}
1891
1892void helper_mtc0_framemask(CPUMIPSState *env, target_ulong arg1)
1893{
1894    env->CP0_Framemask = arg1; /* XXX */
1895}
1896
1897void helper_mtc0_debug(CPUMIPSState *env, target_ulong arg1)
1898{
1899    env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (arg1 & 0x13300120);
1900    if (arg1 & (1 << CP0DB_DM))
1901        env->hflags |= MIPS_HFLAG_DM;
1902    else
1903        env->hflags &= ~MIPS_HFLAG_DM;
1904}
1905
1906void helper_mttc0_debug(CPUMIPSState *env, target_ulong arg1)
1907{
1908    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1909    uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1910    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1911
1912    /* XXX: Might be wrong, check with EJTAG spec. */
1913    if (other_tc == other->current_tc)
1914        other->active_tc.CP0_Debug_tcstatus = val;
1915    else
1916        other->tcs[other_tc].CP0_Debug_tcstatus = val;
1917    other->CP0_Debug = (other->CP0_Debug &
1918                     ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1919                     (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1920}
1921
1922void helper_mtc0_performance0(CPUMIPSState *env, target_ulong arg1)
1923{
1924    env->CP0_Performance0 = arg1 & 0x000007ff;
1925}
1926
1927void helper_mtc0_errctl(CPUMIPSState *env, target_ulong arg1)
1928{
1929    int32_t wst = arg1 & (1 << CP0EC_WST);
1930    int32_t spr = arg1 & (1 << CP0EC_SPR);
1931    int32_t itc = env->itc_tag ? (arg1 & (1 << CP0EC_ITC)) : 0;
1932
1933    env->CP0_ErrCtl = wst | spr | itc;
1934
1935    if (itc && !wst && !spr) {
1936        env->hflags |= MIPS_HFLAG_ITC_CACHE;
1937    } else {
1938        env->hflags &= ~MIPS_HFLAG_ITC_CACHE;
1939    }
1940}
1941
1942void helper_mtc0_taglo(CPUMIPSState *env, target_ulong arg1)
1943{
1944    if (env->hflags & MIPS_HFLAG_ITC_CACHE) {
1945        /* If CACHE instruction is configured for ITC tags then make all
1946           CP0.TagLo bits writable. The actual write to ITC Configuration
1947           Tag will take care of the read-only bits. */
1948        env->CP0_TagLo = arg1;
1949    } else {
1950        env->CP0_TagLo = arg1 & 0xFFFFFCF6;
1951    }
1952}
1953
1954void helper_mtc0_datalo(CPUMIPSState *env, target_ulong arg1)
1955{
1956    env->CP0_DataLo = arg1; /* XXX */
1957}
1958
1959void helper_mtc0_taghi(CPUMIPSState *env, target_ulong arg1)
1960{
1961    env->CP0_TagHi = arg1; /* XXX */
1962}
1963
1964void helper_mtc0_datahi(CPUMIPSState *env, target_ulong arg1)
1965{
1966    env->CP0_DataHi = arg1; /* XXX */
1967}
1968
1969/* MIPS MT functions */
1970target_ulong helper_mftgpr(CPUMIPSState *env, uint32_t sel)
1971{
1972    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1973    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1974
1975    if (other_tc == other->current_tc)
1976        return other->active_tc.gpr[sel];
1977    else
1978        return other->tcs[other_tc].gpr[sel];
1979}
1980
1981target_ulong helper_mftlo(CPUMIPSState *env, uint32_t sel)
1982{
1983    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1984    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1985
1986    if (other_tc == other->current_tc)
1987        return other->active_tc.LO[sel];
1988    else
1989        return other->tcs[other_tc].LO[sel];
1990}
1991
1992target_ulong helper_mfthi(CPUMIPSState *env, uint32_t sel)
1993{
1994    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1995    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
1996
1997    if (other_tc == other->current_tc)
1998        return other->active_tc.HI[sel];
1999    else
2000        return other->tcs[other_tc].HI[sel];
2001}
2002
2003target_ulong helper_mftacx(CPUMIPSState *env, uint32_t sel)
2004{
2005    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2006    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
2007
2008    if (other_tc == other->current_tc)
2009        return other->active_tc.ACX[sel];
2010    else
2011        return other->tcs[other_tc].ACX[sel];
2012}
2013
2014target_ulong helper_mftdsp(CPUMIPSState *env)
2015{
2016    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2017    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
2018
2019    if (other_tc == other->current_tc)
2020        return other->active_tc.DSPControl;
2021    else
2022        return other->tcs[other_tc].DSPControl;
2023}
2024
2025void helper_mttgpr(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
2026{
2027    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2028    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
2029
2030    if (other_tc == other->current_tc)
2031        other->active_tc.gpr[sel] = arg1;
2032    else
2033        other->tcs[other_tc].gpr[sel] = arg1;
2034}
2035
2036void helper_mttlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
2037{
2038    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2039    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
2040
2041    if (other_tc == other->current_tc)
2042        other->active_tc.LO[sel] = arg1;
2043    else
2044        other->tcs[other_tc].LO[sel] = arg1;
2045}
2046
2047void helper_mtthi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
2048{
2049    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2050    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
2051
2052    if (other_tc == other->current_tc)
2053        other->active_tc.HI[sel] = arg1;
2054    else
2055        other->tcs[other_tc].HI[sel] = arg1;
2056}
2057
2058void helper_mttacx(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
2059{
2060    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2061    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
2062
2063    if (other_tc == other->current_tc)
2064        other->active_tc.ACX[sel] = arg1;
2065    else
2066        other->tcs[other_tc].ACX[sel] = arg1;
2067}
2068
2069void helper_mttdsp(CPUMIPSState *env, target_ulong arg1)
2070{
2071    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2072    CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
2073
2074    if (other_tc == other->current_tc)
2075        other->active_tc.DSPControl = arg1;
2076    else
2077        other->tcs[other_tc].DSPControl = arg1;
2078}
2079
2080/* MIPS MT functions */
2081target_ulong helper_dmt(void)
2082{
2083    // TODO
2084     return 0;
2085}
2086
2087target_ulong helper_emt(void)
2088{
2089    // TODO
2090    return 0;
2091}
2092
2093target_ulong helper_dvpe(CPUMIPSState *env)
2094{
2095    CPUState *other_cs = first_cpu;
2096    target_ulong prev = env->mvp->CP0_MVPControl;
2097
2098    CPU_FOREACH(other_cs) {
2099        MIPSCPU *other_cpu = MIPS_CPU(other_cs);
2100        /* Turn off all VPEs except the one executing the dvpe.  */
2101        if (&other_cpu->env != env) {
2102            other_cpu->env.mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP);
2103            mips_vpe_sleep(other_cpu);
2104        }
2105    }
2106    return prev;
2107}
2108
2109target_ulong helper_evpe(CPUMIPSState *env)
2110{
2111    CPUState *other_cs = first_cpu;
2112    target_ulong prev = env->mvp->CP0_MVPControl;
2113
2114    CPU_FOREACH(other_cs) {
2115        MIPSCPU *other_cpu = MIPS_CPU(other_cs);
2116
2117        if (&other_cpu->env != env
2118            /* If the VPE is WFI, don't disturb its sleep.  */
2119            && !mips_vpe_is_wfi(other_cpu)) {
2120            /* Enable the VPE.  */
2121            other_cpu->env.mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
2122            mips_vpe_wake(other_cpu); /* And wake it up.  */
2123        }
2124    }
2125    return prev;
2126}
2127#endif /* !CONFIG_USER_ONLY */
2128
2129void helper_fork(target_ulong arg1, target_ulong arg2)
2130{
2131    // arg1 = rt, arg2 = rs
2132    // TODO: store to TC register
2133}
2134
2135target_ulong helper_yield(CPUMIPSState *env, target_ulong arg)
2136{
2137    target_long arg1 = arg;
2138
2139    if (arg1 < 0) {
2140        /* No scheduling policy implemented. */
2141        if (arg1 != -2) {
2142            if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
2143                env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) {
2144                env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2145                env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
2146                do_raise_exception(env, EXCP_THREAD, GETPC());
2147            }
2148        }
2149    } else if (arg1 == 0) {
2150        if (0 /* TODO: TC underflow */) {
2151            env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2152            do_raise_exception(env, EXCP_THREAD, GETPC());
2153        } else {
2154            // TODO: Deallocate TC
2155        }
2156    } else if (arg1 > 0) {
2157        /* Yield qualifier inputs not implemented. */
2158        env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2159        env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
2160        do_raise_exception(env, EXCP_THREAD, GETPC());
2161    }
2162    return env->CP0_YQMask;
2163}
2164
2165/* R6 Multi-threading */
2166#ifndef CONFIG_USER_ONLY
2167target_ulong helper_dvp(CPUMIPSState *env)
2168{
2169    CPUState *other_cs = first_cpu;
2170    target_ulong prev = env->CP0_VPControl;
2171
2172    if (!((env->CP0_VPControl >> CP0VPCtl_DIS) & 1)) {
2173        CPU_FOREACH(other_cs) {
2174            MIPSCPU *other_cpu = MIPS_CPU(other_cs);
2175            /* Turn off all VPs except the one executing the dvp. */
2176            if (&other_cpu->env != env) {
2177                mips_vpe_sleep(other_cpu);
2178            }
2179        }
2180        env->CP0_VPControl |= (1 << CP0VPCtl_DIS);
2181    }
2182    return prev;
2183}
2184
2185target_ulong helper_evp(CPUMIPSState *env)
2186{
2187    CPUState *other_cs = first_cpu;
2188    target_ulong prev = env->CP0_VPControl;
2189
2190    if ((env->CP0_VPControl >> CP0VPCtl_DIS) & 1) {
2191        CPU_FOREACH(other_cs) {
2192            MIPSCPU *other_cpu = MIPS_CPU(other_cs);
2193            if ((&other_cpu->env != env) && !mips_vp_is_wfi(other_cpu)) {
2194                /* If the VP is WFI, don't disturb its sleep.
2195                 * Otherwise, wake it up. */
2196                mips_vpe_wake(other_cpu);
2197            }
2198        }
2199        env->CP0_VPControl &= ~(1 << CP0VPCtl_DIS);
2200    }
2201    return prev;
2202}
2203#endif /* !CONFIG_USER_ONLY */
2204
2205#ifndef CONFIG_USER_ONLY
2206/* TLB management */
2207static void r4k_mips_tlb_flush_extra (CPUMIPSState *env, int first)
2208{
2209    /* Discard entries from env->tlb[first] onwards.  */
2210    while (env->tlb->tlb_in_use > first) {
2211        r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
2212    }
2213}
2214
2215static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo)
2216{
2217#if defined(TARGET_MIPS64)
2218    return extract64(entrylo, 6, 54);
2219#else
2220    return extract64(entrylo, 6, 24) | /* PFN */
2221           (extract64(entrylo, 32, 32) << 24); /* PFNX */
2222#endif
2223}
2224
2225static void r4k_fill_tlb(CPUMIPSState *env, int idx)
2226{
2227    r4k_tlb_t *tlb;
2228    uint64_t mask = env->CP0_PageMask >> (TARGET_PAGE_BITS + 1);
2229
2230    /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
2231    tlb = &env->tlb->mmu.r4k.tlb[idx];
2232    if (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) {
2233        tlb->EHINV = 1;
2234        return;
2235    }
2236    tlb->EHINV = 0;
2237    tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
2238#if defined(TARGET_MIPS64)
2239    tlb->VPN &= env->SEGMask;
2240#endif
2241    tlb->ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
2242    tlb->PageMask = env->CP0_PageMask;
2243    tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
2244    tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
2245    tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
2246    tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
2247    tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1;
2248    tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1;
2249    tlb->PFN[0] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) & ~mask) << 12;
2250    tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
2251    tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
2252    tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
2253    tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1;
2254    tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1;
2255    tlb->PFN[1] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) & ~mask) << 12;
2256}
2257
2258void r4k_helper_tlbinv(CPUMIPSState *env)
2259{
2260    int idx;
2261    r4k_tlb_t *tlb;
2262    uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
2263
2264    for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
2265        tlb = &env->tlb->mmu.r4k.tlb[idx];
2266        if (!tlb->G && tlb->ASID == ASID) {
2267            tlb->EHINV = 1;
2268        }
2269    }
2270    cpu_mips_tlb_flush(env);
2271}
2272
2273void r4k_helper_tlbinvf(CPUMIPSState *env)
2274{
2275    int idx;
2276
2277    for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
2278        env->tlb->mmu.r4k.tlb[idx].EHINV = 1;
2279    }
2280    cpu_mips_tlb_flush(env);
2281}
2282
2283void r4k_helper_tlbwi(CPUMIPSState *env)
2284{
2285    r4k_tlb_t *tlb;
2286    int idx;
2287    target_ulong VPN;
2288    uint16_t ASID;
2289    bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1;
2290
2291    idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
2292    tlb = &env->tlb->mmu.r4k.tlb[idx];
2293    VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
2294#if defined(TARGET_MIPS64)
2295    VPN &= env->SEGMask;
2296#endif
2297    ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
2298    EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0;
2299    G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
2300    V0 = (env->CP0_EntryLo0 & 2) != 0;
2301    D0 = (env->CP0_EntryLo0 & 4) != 0;
2302    XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) &1;
2303    RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) &1;
2304    V1 = (env->CP0_EntryLo1 & 2) != 0;
2305    D1 = (env->CP0_EntryLo1 & 4) != 0;
2306    XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) &1;
2307    RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) &1;
2308
2309    /* Discard cached TLB entries, unless tlbwi is just upgrading access
2310       permissions on the current entry. */
2311    if (tlb->VPN != VPN || tlb->ASID != ASID || tlb->G != G ||
2312        (!tlb->EHINV && EHINV) ||
2313        (tlb->V0 && !V0) || (tlb->D0 && !D0) ||
2314        (!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) ||
2315        (tlb->V1 && !V1) || (tlb->D1 && !D1) ||
2316        (!tlb->XI1 && XI1) || (!tlb->RI1 && RI1)) {
2317        r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
2318    }
2319
2320    r4k_invalidate_tlb(env, idx, 0);
2321    r4k_fill_tlb(env, idx);
2322}
2323
2324void r4k_helper_tlbwr(CPUMIPSState *env)
2325{
2326    int r = cpu_mips_get_random(env);
2327
2328    r4k_invalidate_tlb(env, r, 1);
2329    r4k_fill_tlb(env, r);
2330}
2331
2332void r4k_helper_tlbp(CPUMIPSState *env)
2333{
2334    r4k_tlb_t *tlb;
2335    target_ulong mask;
2336    target_ulong tag;
2337    target_ulong VPN;
2338    uint16_t ASID;
2339    int i;
2340
2341    ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
2342    for (i = 0; i < env->tlb->nb_tlb; i++) {
2343        tlb = &env->tlb->mmu.r4k.tlb[i];
2344        /* 1k pages are not supported. */
2345        mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
2346        tag = env->CP0_EntryHi & ~mask;
2347        VPN = tlb->VPN & ~mask;
2348#if defined(TARGET_MIPS64)
2349        tag &= env->SEGMask;
2350#endif
2351        /* Check ASID, virtual page number & size */
2352        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) {
2353            /* TLB match */
2354            env->CP0_Index = i;
2355            break;
2356        }
2357    }
2358    if (i == env->tlb->nb_tlb) {
2359        /* No match.  Discard any shadow entries, if any of them match.  */
2360        for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
2361            tlb = &env->tlb->mmu.r4k.tlb[i];
2362            /* 1k pages are not supported. */
2363            mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
2364            tag = env->CP0_EntryHi & ~mask;
2365            VPN = tlb->VPN & ~mask;
2366#if defined(TARGET_MIPS64)
2367            tag &= env->SEGMask;
2368#endif
2369            /* Check ASID, virtual page number & size */
2370            if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
2371                r4k_mips_tlb_flush_extra (env, i);
2372                break;
2373            }
2374        }
2375
2376        env->CP0_Index |= 0x80000000;
2377    }
2378}
2379
2380static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn)
2381{
2382#if defined(TARGET_MIPS64)
2383    return tlb_pfn << 6;
2384#else
2385    return (extract64(tlb_pfn, 0, 24) << 6) | /* PFN */
2386           (extract64(tlb_pfn, 24, 32) << 32); /* PFNX */
2387#endif
2388}
2389
2390void r4k_helper_tlbr(CPUMIPSState *env)
2391{
2392    r4k_tlb_t *tlb;
2393    uint16_t ASID;
2394    int idx;
2395
2396    ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
2397    idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
2398    tlb = &env->tlb->mmu.r4k.tlb[idx];
2399
2400    /* If this will change the current ASID, flush qemu's TLB.  */
2401    if (ASID != tlb->ASID)
2402        cpu_mips_tlb_flush(env);
2403
2404    r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
2405
2406    if (tlb->EHINV) {
2407        env->CP0_EntryHi = 1 << CP0EnHi_EHINV;
2408        env->CP0_PageMask = 0;
2409        env->CP0_EntryLo0 = 0;
2410        env->CP0_EntryLo1 = 0;
2411    } else {
2412        env->CP0_EntryHi = tlb->VPN | tlb->ASID;
2413        env->CP0_PageMask = tlb->PageMask;
2414        env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
2415                        ((uint64_t)tlb->RI0 << CP0EnLo_RI) |
2416                        ((uint64_t)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3) |
2417                        get_entrylo_pfn_from_tlb(tlb->PFN[0] >> 12);
2418        env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
2419                        ((uint64_t)tlb->RI1 << CP0EnLo_RI) |
2420                        ((uint64_t)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3) |
2421                        get_entrylo_pfn_from_tlb(tlb->PFN[1] >> 12);
2422    }
2423}
2424
2425void helper_tlbwi(CPUMIPSState *env)
2426{
2427    env->tlb->helper_tlbwi(env);
2428}
2429
2430void helper_tlbwr(CPUMIPSState *env)
2431{
2432    env->tlb->helper_tlbwr(env);
2433}
2434
2435void helper_tlbp(CPUMIPSState *env)
2436{
2437    env->tlb->helper_tlbp(env);
2438}
2439
2440void helper_tlbr(CPUMIPSState *env)
2441{
2442    env->tlb->helper_tlbr(env);
2443}
2444
2445void helper_tlbinv(CPUMIPSState *env)
2446{
2447    env->tlb->helper_tlbinv(env);
2448}
2449
2450void helper_tlbinvf(CPUMIPSState *env)
2451{
2452    env->tlb->helper_tlbinvf(env);
2453}
2454
2455/* Specials */
2456target_ulong helper_di(CPUMIPSState *env)
2457{
2458    target_ulong t0 = env->CP0_Status;
2459
2460    env->CP0_Status = t0 & ~(1 << CP0St_IE);
2461    return t0;
2462}
2463
2464target_ulong helper_ei(CPUMIPSState *env)
2465{
2466    target_ulong t0 = env->CP0_Status;
2467
2468    env->CP0_Status = t0 | (1 << CP0St_IE);
2469    return t0;
2470}
2471
2472static void debug_pre_eret(CPUMIPSState *env)
2473{
2474    if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
2475        qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
2476                env->active_tc.PC, env->CP0_EPC);
2477        if (env->CP0_Status & (1 << CP0St_ERL))
2478            qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
2479        if (env->hflags & MIPS_HFLAG_DM)
2480            qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
2481        qemu_log("\n");
2482    }
2483}
2484
2485static void debug_post_eret(CPUMIPSState *env)
2486{
2487    if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
2488        qemu_log("  =>  PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
2489                env->active_tc.PC, env->CP0_EPC);
2490        if (env->CP0_Status & (1 << CP0St_ERL))
2491            qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
2492        if (env->hflags & MIPS_HFLAG_DM)
2493            qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
2494        switch (cpu_mmu_index(env, false)) {
2495        case 3:
2496            qemu_log(", ERL\n");
2497            break;
2498        case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
2499        case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
2500        case MIPS_HFLAG_KM: qemu_log("\n"); break;
2501        default:
2502            cpu_abort(env_cpu(env), "Invalid MMU mode!\n");
2503            break;
2504        }
2505    }
2506}
2507
2508static void set_pc(CPUMIPSState *env, target_ulong error_pc)
2509{
2510    env->active_tc.PC = error_pc & ~(target_ulong)1;
2511    if (error_pc & 1) {
2512        env->hflags |= MIPS_HFLAG_M16;
2513    } else {
2514        env->hflags &= ~(MIPS_HFLAG_M16);
2515    }
2516}
2517
2518static inline void exception_return(CPUMIPSState *env)
2519{
2520    debug_pre_eret(env);
2521    if (env->CP0_Status & (1 << CP0St_ERL)) {
2522        set_pc(env, env->CP0_ErrorEPC);
2523        env->CP0_Status &= ~(1 << CP0St_ERL);
2524    } else {
2525        set_pc(env, env->CP0_EPC);
2526        env->CP0_Status &= ~(1 << CP0St_EXL);
2527    }
2528    compute_hflags(env);
2529    debug_post_eret(env);
2530}
2531
2532void helper_eret(CPUMIPSState *env)
2533{
2534    exception_return(env);
2535    env->CP0_LLAddr = 1;
2536    env->lladdr = 1;
2537}
2538
2539void helper_eretnc(CPUMIPSState *env)
2540{
2541    exception_return(env);
2542}
2543
2544void helper_deret(CPUMIPSState *env)
2545{
2546    debug_pre_eret(env);
2547
2548    env->hflags &= ~MIPS_HFLAG_DM;
2549    compute_hflags(env);
2550
2551    set_pc(env, env->CP0_DEPC);
2552
2553    debug_post_eret(env);
2554}
2555#endif /* !CONFIG_USER_ONLY */
2556
2557static inline void check_hwrena(CPUMIPSState *env, int reg, uintptr_t pc)
2558{
2559    if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << reg))) {
2560        return;
2561    }
2562    do_raise_exception(env, EXCP_RI, pc);
2563}
2564
2565target_ulong helper_rdhwr_cpunum(CPUMIPSState *env)
2566{
2567    check_hwrena(env, 0, GETPC());
2568    return env->CP0_EBase & 0x3ff;
2569}
2570
2571target_ulong helper_rdhwr_synci_step(CPUMIPSState *env)
2572{
2573    check_hwrena(env, 1, GETPC());
2574    return env->SYNCI_Step;
2575}
2576
2577target_ulong helper_rdhwr_cc(CPUMIPSState *env)
2578{
2579    check_hwrena(env, 2, GETPC());
2580#ifdef CONFIG_USER_ONLY
2581    return env->CP0_Count;
2582#else
2583    return (int32_t)cpu_mips_get_count(env);
2584#endif
2585}
2586
2587target_ulong helper_rdhwr_ccres(CPUMIPSState *env)
2588{
2589    check_hwrena(env, 3, GETPC());
2590    return env->CCRes;
2591}
2592
2593target_ulong helper_rdhwr_performance(CPUMIPSState *env)
2594{
2595    check_hwrena(env, 4, GETPC());
2596    return env->CP0_Performance0;
2597}
2598
2599target_ulong helper_rdhwr_xnp(CPUMIPSState *env)
2600{
2601    check_hwrena(env, 5, GETPC());
2602    return (env->CP0_Config5 >> CP0C5_XNP) & 1;
2603}
2604
2605void helper_pmon(CPUMIPSState *env, int function)
2606{
2607    function /= 2;
2608    switch (function) {
2609    case 2: /* TODO: char inbyte(int waitflag); */
2610        if (env->active_tc.gpr[4] == 0)
2611            env->active_tc.gpr[2] = -1;
2612        /* Fall through */
2613    case 11: /* TODO: char inbyte (void); */
2614        env->active_tc.gpr[2] = -1;
2615        break;
2616    case 3:
2617    case 12:
2618        printf("%c", (char)(env->active_tc.gpr[4] & 0xFF));
2619        break;
2620    case 17:
2621        break;
2622    case 158:
2623        {
2624            unsigned char *fmt = (void *)(uintptr_t)env->active_tc.gpr[4];
2625            printf("%s", fmt);
2626        }
2627        break;
2628    }
2629}
2630
2631void helper_wait(CPUMIPSState *env)
2632{
2633    CPUState *cs = env_cpu(env);
2634
2635    cs->halted = 1;
2636    cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
2637    /* Last instruction in the block, PC was updated before
2638       - no need to recover PC and icount */
2639    raise_exception(env, EXCP_HLT);
2640}
2641
2642#if !defined(CONFIG_USER_ONLY)
2643
2644void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
2645                                  MMUAccessType access_type,
2646                                  int mmu_idx, uintptr_t retaddr)
2647{
2648    MIPSCPU *cpu = MIPS_CPU(cs);
2649    CPUMIPSState *env = &cpu->env;
2650    int error_code = 0;
2651    int excp;
2652
2653    if (!(env->hflags & MIPS_HFLAG_DM)) {
2654        env->CP0_BadVAddr = addr;
2655    }
2656
2657    if (access_type == MMU_DATA_STORE) {
2658        excp = EXCP_AdES;
2659    } else {
2660        excp = EXCP_AdEL;
2661        if (access_type == MMU_INST_FETCH) {
2662            error_code |= EXCP_INST_NOTAVAIL;
2663        }
2664    }
2665
2666    do_raise_exception_err(env, excp, error_code, retaddr);
2667}
2668
2669void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr,
2670                                bool is_write, bool is_exec, int unused,
2671                                unsigned size)
2672{
2673    MIPSCPU *cpu = MIPS_CPU(cs);
2674    CPUMIPSState *env = &cpu->env;
2675
2676    /*
2677     * Raising an exception with KVM enabled will crash because it won't be from
2678     * the main execution loop so the longjmp won't have a matching setjmp.
2679     * Until we can trigger a bus error exception through KVM lets just ignore
2680     * the access.
2681     */
2682    if (kvm_enabled()) {
2683        return;
2684    }
2685
2686    if (is_exec) {
2687        raise_exception(env, EXCP_IBE);
2688    } else {
2689        raise_exception(env, EXCP_DBE);
2690    }
2691}
2692#endif /* !CONFIG_USER_ONLY */
2693
2694/* Complex FPU operations which may need stack space. */
2695
2696#define FLOAT_TWO32 make_float32(1 << 30)
2697#define FLOAT_TWO64 make_float64(1ULL << 62)
2698
2699#define FP_TO_INT32_OVERFLOW 0x7fffffff
2700#define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL
2701
2702/* convert MIPS rounding mode in FCR31 to IEEE library */
2703unsigned int ieee_rm[] = {
2704    float_round_nearest_even,
2705    float_round_to_zero,
2706    float_round_up,
2707    float_round_down
2708};
2709
2710target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg)
2711{
2712    target_ulong arg1 = 0;
2713
2714    switch (reg) {
2715    case 0:
2716        arg1 = (int32_t)env->active_fpu.fcr0;
2717        break;
2718    case 1:
2719        /* UFR Support - Read Status FR */
2720        if (env->active_fpu.fcr0 & (1 << FCR0_UFRP)) {
2721            if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
2722                arg1 = (int32_t)
2723                       ((env->CP0_Status & (1  << CP0St_FR)) >> CP0St_FR);
2724            } else {
2725                do_raise_exception(env, EXCP_RI, GETPC());
2726            }
2727        }
2728        break;
2729    case 5:
2730        /* FRE Support - read Config5.FRE bit */
2731        if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
2732            if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
2733                arg1 = (env->CP0_Config5 >> CP0C5_FRE) & 1;
2734            } else {
2735                helper_raise_exception(env, EXCP_RI);
2736            }
2737        }
2738        break;
2739    case 25:
2740        arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
2741        break;
2742    case 26:
2743        arg1 = env->active_fpu.fcr31 & 0x0003f07c;
2744        break;
2745    case 28:
2746        arg1 = (env->active_fpu.fcr31 & 0x00000f83) | ((env->active_fpu.fcr31 >> 22) & 0x4);
2747        break;
2748    default:
2749        arg1 = (int32_t)env->active_fpu.fcr31;
2750        break;
2751    }
2752
2753    return arg1;
2754}
2755
2756void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
2757{
2758    switch (fs) {
2759    case 1:
2760        /* UFR Alias - Reset Status FR */
2761        if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) {
2762            return;
2763        }
2764        if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
2765            env->CP0_Status &= ~(1 << CP0St_FR);
2766            compute_hflags(env);
2767        } else {
2768            do_raise_exception(env, EXCP_RI, GETPC());
2769        }
2770        break;
2771    case 4:
2772        /* UNFR Alias - Set Status FR */
2773        if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) {
2774            return;
2775        }
2776        if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
2777            env->CP0_Status |= (1 << CP0St_FR);
2778            compute_hflags(env);
2779        } else {
2780            do_raise_exception(env, EXCP_RI, GETPC());
2781        }
2782        break;
2783    case 5:
2784        /* FRE Support - clear Config5.FRE bit */
2785        if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) {
2786            return;
2787        }
2788        if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
2789            env->CP0_Config5 &= ~(1 << CP0C5_FRE);
2790            compute_hflags(env);
2791        } else {
2792            helper_raise_exception(env, EXCP_RI);
2793        }
2794        break;
2795    case 6:
2796        /* FRE Support - set Config5.FRE bit */
2797        if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) {
2798            return;
2799        }
2800        if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
2801            env->CP0_Config5 |= (1 << CP0C5_FRE);
2802            compute_hflags(env);
2803        } else {
2804            helper_raise_exception(env, EXCP_RI);
2805        }
2806        break;
2807    case 25:
2808        if ((env->insn_flags & ISA_MIPS32R6) || (arg1 & 0xffffff00)) {
2809            return;
2810        }
2811        env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((arg1 & 0xfe) << 24) |
2812                     ((arg1 & 0x1) << 23);
2813        break;
2814    case 26:
2815        if (arg1 & 0x007c0000)
2816            return;
2817        env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) | (arg1 & 0x0003f07c);
2818        break;
2819    case 28:
2820        if (arg1 & 0x007c0000)
2821            return;
2822        env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) | (arg1 & 0x00000f83) |
2823                     ((arg1 & 0x4) << 22);
2824        break;
2825    case 31:
2826        env->active_fpu.fcr31 = (arg1 & env->active_fpu.fcr31_rw_bitmask) |
2827               (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask));
2828        break;
2829    default:
2830        if (env->insn_flags & ISA_MIPS32R6) {
2831            do_raise_exception(env, EXCP_RI, GETPC());
2832        }
2833        return;
2834    }
2835    restore_fp_status(env);
2836    set_float_exception_flags(0, &env->active_fpu.fp_status);
2837    if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31))
2838        do_raise_exception(env, EXCP_FPE, GETPC());
2839}
2840
2841int ieee_ex_to_mips(int xcpt)
2842{
2843    int ret = 0;
2844    if (xcpt) {
2845        if (xcpt & float_flag_invalid) {
2846            ret |= FP_INVALID;
2847        }
2848        if (xcpt & float_flag_overflow) {
2849            ret |= FP_OVERFLOW;
2850        }
2851        if (xcpt & float_flag_underflow) {
2852            ret |= FP_UNDERFLOW;
2853        }
2854        if (xcpt & float_flag_divbyzero) {
2855            ret |= FP_DIV0;
2856        }
2857        if (xcpt & float_flag_inexact) {
2858            ret |= FP_INEXACT;
2859        }
2860    }
2861    return ret;
2862}
2863
2864static inline void update_fcr31(CPUMIPSState *env, uintptr_t pc)
2865{
2866    int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status));
2867
2868    SET_FP_CAUSE(env->active_fpu.fcr31, tmp);
2869
2870    if (tmp) {
2871        set_float_exception_flags(0, &env->active_fpu.fp_status);
2872
2873        if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) {
2874            do_raise_exception(env, EXCP_FPE, pc);
2875        } else {
2876            UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
2877        }
2878    }
2879}
2880
2881/* Float support.
2882   Single precition routines have a "s" suffix, double precision a
2883   "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
2884   paired single lower "pl", paired single upper "pu".  */
2885
2886/* unary operations, modifying fp status  */
2887uint64_t helper_float_sqrt_d(CPUMIPSState *env, uint64_t fdt0)
2888{
2889    fdt0 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
2890    update_fcr31(env, GETPC());
2891    return fdt0;
2892}
2893
2894uint32_t helper_float_sqrt_s(CPUMIPSState *env, uint32_t fst0)
2895{
2896    fst0 = float32_sqrt(fst0, &env->active_fpu.fp_status);
2897    update_fcr31(env, GETPC());
2898    return fst0;
2899}
2900
2901uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0)
2902{
2903    uint64_t fdt2;
2904
2905    fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
2906    update_fcr31(env, GETPC());
2907    return fdt2;
2908}
2909
2910uint64_t helper_float_cvtd_w(CPUMIPSState *env, uint32_t wt0)
2911{
2912    uint64_t fdt2;
2913
2914    fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status);
2915    update_fcr31(env, GETPC());
2916    return fdt2;
2917}
2918
2919uint64_t helper_float_cvtd_l(CPUMIPSState *env, uint64_t dt0)
2920{
2921    uint64_t fdt2;
2922
2923    fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status);
2924    update_fcr31(env, GETPC());
2925    return fdt2;
2926}
2927
2928uint64_t helper_float_cvt_l_d(CPUMIPSState *env, uint64_t fdt0)
2929{
2930    uint64_t dt2;
2931
2932    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2933    if (get_float_exception_flags(&env->active_fpu.fp_status)
2934        & (float_flag_invalid | float_flag_overflow)) {
2935        dt2 = FP_TO_INT64_OVERFLOW;
2936    }
2937    update_fcr31(env, GETPC());
2938    return dt2;
2939}
2940
2941uint64_t helper_float_cvt_l_s(CPUMIPSState *env, uint32_t fst0)
2942{
2943    uint64_t dt2;
2944
2945    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2946    if (get_float_exception_flags(&env->active_fpu.fp_status)
2947        & (float_flag_invalid | float_flag_overflow)) {
2948        dt2 = FP_TO_INT64_OVERFLOW;
2949    }
2950    update_fcr31(env, GETPC());
2951    return dt2;
2952}
2953
2954uint64_t helper_float_cvtps_pw(CPUMIPSState *env, uint64_t dt0)
2955{
2956    uint32_t fst2;
2957    uint32_t fsth2;
2958
2959    fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2960    fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status);
2961    update_fcr31(env, GETPC());
2962    return ((uint64_t)fsth2 << 32) | fst2;
2963}
2964
2965uint64_t helper_float_cvtpw_ps(CPUMIPSState *env, uint64_t fdt0)
2966{
2967    uint32_t wt2;
2968    uint32_t wth2;
2969    int excp, excph;
2970
2971    wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2972    excp = get_float_exception_flags(&env->active_fpu.fp_status);
2973    if (excp & (float_flag_overflow | float_flag_invalid)) {
2974        wt2 = FP_TO_INT32_OVERFLOW;
2975    }
2976
2977    set_float_exception_flags(0, &env->active_fpu.fp_status);
2978    wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
2979    excph = get_float_exception_flags(&env->active_fpu.fp_status);
2980    if (excph & (float_flag_overflow | float_flag_invalid)) {
2981        wth2 = FP_TO_INT32_OVERFLOW;
2982    }
2983
2984    set_float_exception_flags(excp | excph, &env->active_fpu.fp_status);
2985    update_fcr31(env, GETPC());
2986
2987    return ((uint64_t)wth2 << 32) | wt2;
2988}
2989
2990uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t fdt0)
2991{
2992    uint32_t fst2;
2993
2994    fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
2995    update_fcr31(env, GETPC());
2996    return fst2;
2997}
2998
2999uint32_t helper_float_cvts_w(CPUMIPSState *env, uint32_t wt0)
3000{
3001    uint32_t fst2;
3002
3003    fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status);
3004    update_fcr31(env, GETPC());
3005    return fst2;
3006}
3007
3008uint32_t helper_float_cvts_l(CPUMIPSState *env, uint64_t dt0)
3009{
3010    uint32_t fst2;
3011
3012    fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status);
3013    update_fcr31(env, GETPC());
3014    return fst2;
3015}
3016
3017uint32_t helper_float_cvts_pl(CPUMIPSState *env, uint32_t wt0)
3018{
3019    uint32_t wt2;
3020
3021    wt2 = wt0;
3022    update_fcr31(env, GETPC());
3023    return wt2;
3024}
3025
3026uint32_t helper_float_cvts_pu(CPUMIPSState *env, uint32_t wth0)
3027{
3028    uint32_t wt2;
3029
3030    wt2 = wth0;
3031    update_fcr31(env, GETPC());
3032    return wt2;
3033}
3034
3035uint32_t helper_float_cvt_w_s(CPUMIPSState *env, uint32_t fst0)
3036{
3037    uint32_t wt2;
3038
3039    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
3040    if (get_float_exception_flags(&env->active_fpu.fp_status)
3041        & (float_flag_invalid | float_flag_overflow)) {
3042        wt2 = FP_TO_INT32_OVERFLOW;
3043    }
3044    update_fcr31(env, GETPC());
3045    return wt2;
3046}
3047
3048uint32_t helper_float_cvt_w_d(CPUMIPSState *env, uint64_t fdt0)
3049{
3050    uint32_t wt2;
3051
3052    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
3053    if (get_float_exception_flags(&env->active_fpu.fp_status)
3054        & (float_flag_invalid | float_flag_overflow)) {
3055        wt2 = FP_TO_INT32_OVERFLOW;
3056    }
3057    update_fcr31(env, GETPC());
3058    return wt2;
3059}
3060
3061uint64_t helper_float_round_l_d(CPUMIPSState *env, uint64_t fdt0)
3062{
3063    uint64_t dt2;
3064
3065    set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
3066    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
3067    restore_rounding_mode(env);
3068    if (get_float_exception_flags(&env->active_fpu.fp_status)
3069        & (float_flag_invalid | float_flag_overflow)) {
3070        dt2 = FP_TO_INT64_OVERFLOW;
3071    }
3072    update_fcr31(env, GETPC());
3073    return dt2;
3074}
3075
3076uint64_t helper_float_round_l_s(CPUMIPSState *env, uint32_t fst0)
3077{
3078    uint64_t dt2;
3079
3080    set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
3081    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
3082    restore_rounding_mode(env);
3083    if (get_float_exception_flags(&env->active_fpu.fp_status)
3084        & (float_flag_invalid | float_flag_overflow)) {
3085        dt2 = FP_TO_INT64_OVERFLOW;
3086    }
3087    update_fcr31(env, GETPC());
3088    return dt2;
3089}
3090
3091uint32_t helper_float_round_w_d(CPUMIPSState *env, uint64_t fdt0)
3092{
3093    uint32_t wt2;
3094
3095    set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
3096    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
3097    restore_rounding_mode(env);
3098    if (get_float_exception_flags(&env->active_fpu.fp_status)
3099        & (float_flag_invalid | float_flag_overflow)) {
3100        wt2 = FP_TO_INT32_OVERFLOW;
3101    }
3102    update_fcr31(env, GETPC());
3103    return wt2;
3104}
3105
3106uint32_t helper_float_round_w_s(CPUMIPSState *env, uint32_t fst0)
3107{
3108    uint32_t wt2;
3109
3110    set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
3111    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
3112    restore_rounding_mode(env);
3113    if (get_float_exception_flags(&env->active_fpu.fp_status)
3114        & (float_flag_invalid | float_flag_overflow)) {
3115        wt2 = FP_TO_INT32_OVERFLOW;
3116    }
3117    update_fcr31(env, GETPC());
3118    return wt2;
3119}
3120
3121uint64_t helper_float_trunc_l_d(CPUMIPSState *env, uint64_t fdt0)
3122{
3123    uint64_t dt2;
3124
3125    dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
3126    if (get_float_exception_flags(&env->active_fpu.fp_status)
3127        & (float_flag_invalid | float_flag_overflow)) {
3128        dt2 = FP_TO_INT64_OVERFLOW;
3129    }
3130    update_fcr31(env, GETPC());
3131    return dt2;
3132}
3133
3134uint64_t helper_float_trunc_l_s(CPUMIPSState *env, uint32_t fst0)
3135{
3136    uint64_t dt2;
3137
3138    dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
3139    if (get_float_exception_flags(&env->active_fpu.fp_status)
3140        & (float_flag_invalid | float_flag_overflow)) {
3141        dt2 = FP_TO_INT64_OVERFLOW;
3142    }
3143    update_fcr31(env, GETPC());
3144    return dt2;
3145}
3146
3147uint32_t helper_float_trunc_w_d(CPUMIPSState *env, uint64_t fdt0)
3148{
3149    uint32_t wt2;
3150
3151    wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
3152    if (get_float_exception_flags(&env->active_fpu.fp_status)
3153        & (float_flag_invalid | float_flag_overflow)) {
3154        wt2 = FP_TO_INT32_OVERFLOW;
3155    }
3156    update_fcr31(env, GETPC());
3157    return wt2;
3158}
3159
3160uint32_t helper_float_trunc_w_s(CPUMIPSState *env, uint32_t fst0)
3161{
3162    uint32_t wt2;
3163
3164    wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
3165    if (get_float_exception_flags(&env->active_fpu.fp_status)
3166        & (float_flag_invalid | float_flag_overflow)) {
3167        wt2 = FP_TO_INT32_OVERFLOW;
3168    }
3169    update_fcr31(env, GETPC());
3170    return wt2;
3171}
3172
3173uint64_t helper_float_ceil_l_d(CPUMIPSState *env, uint64_t fdt0)
3174{
3175    uint64_t dt2;
3176
3177    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3178    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
3179    restore_rounding_mode(env);
3180    if (get_float_exception_flags(&env->active_fpu.fp_status)
3181        & (float_flag_invalid | float_flag_overflow)) {
3182        dt2 = FP_TO_INT64_OVERFLOW;
3183    }
3184    update_fcr31(env, GETPC());
3185    return dt2;
3186}
3187
3188uint64_t helper_float_ceil_l_s(CPUMIPSState *env, uint32_t fst0)
3189{
3190    uint64_t dt2;
3191
3192    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3193    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
3194    restore_rounding_mode(env);
3195    if (get_float_exception_flags(&env->active_fpu.fp_status)
3196        & (float_flag_invalid | float_flag_overflow)) {
3197        dt2 = FP_TO_INT64_OVERFLOW;
3198    }
3199    update_fcr31(env, GETPC());
3200    return dt2;
3201}
3202
3203uint32_t helper_float_ceil_w_d(CPUMIPSState *env, uint64_t fdt0)
3204{
3205    uint32_t wt2;
3206
3207    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3208    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
3209    restore_rounding_mode(env);
3210    if (get_float_exception_flags(&env->active_fpu.fp_status)
3211        & (float_flag_invalid | float_flag_overflow)) {
3212        wt2 = FP_TO_INT32_OVERFLOW;
3213    }
3214    update_fcr31(env, GETPC());
3215    return wt2;
3216}
3217
3218uint32_t helper_float_ceil_w_s(CPUMIPSState *env, uint32_t fst0)
3219{
3220    uint32_t wt2;
3221
3222    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3223    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
3224    restore_rounding_mode(env);
3225    if (get_float_exception_flags(&env->active_fpu.fp_status)
3226        & (float_flag_invalid | float_flag_overflow)) {
3227        wt2 = FP_TO_INT32_OVERFLOW;
3228    }
3229    update_fcr31(env, GETPC());
3230    return wt2;
3231}
3232
3233uint64_t helper_float_floor_l_d(CPUMIPSState *env, uint64_t fdt0)
3234{
3235    uint64_t dt2;
3236
3237    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3238    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
3239    restore_rounding_mode(env);
3240    if (get_float_exception_flags(&env->active_fpu.fp_status)
3241        & (float_flag_invalid | float_flag_overflow)) {
3242        dt2 = FP_TO_INT64_OVERFLOW;
3243    }
3244    update_fcr31(env, GETPC());
3245    return dt2;
3246}
3247
3248uint64_t helper_float_floor_l_s(CPUMIPSState *env, uint32_t fst0)
3249{
3250    uint64_t dt2;
3251
3252    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3253    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
3254    restore_rounding_mode(env);
3255    if (get_float_exception_flags(&env->active_fpu.fp_status)
3256        & (float_flag_invalid | float_flag_overflow)) {
3257        dt2 = FP_TO_INT64_OVERFLOW;
3258    }
3259    update_fcr31(env, GETPC());
3260    return dt2;
3261}
3262
3263uint32_t helper_float_floor_w_d(CPUMIPSState *env, uint64_t fdt0)
3264{
3265    uint32_t wt2;
3266
3267    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3268    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
3269    restore_rounding_mode(env);
3270    if (get_float_exception_flags(&env->active_fpu.fp_status)
3271        & (float_flag_invalid | float_flag_overflow)) {
3272        wt2 = FP_TO_INT32_OVERFLOW;
3273    }
3274    update_fcr31(env, GETPC());
3275    return wt2;
3276}
3277
3278uint32_t helper_float_floor_w_s(CPUMIPSState *env, uint32_t fst0)
3279{
3280    uint32_t wt2;
3281
3282    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3283    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
3284    restore_rounding_mode(env);
3285    if (get_float_exception_flags(&env->active_fpu.fp_status)
3286        & (float_flag_invalid | float_flag_overflow)) {
3287        wt2 = FP_TO_INT32_OVERFLOW;
3288    }
3289    update_fcr31(env, GETPC());
3290    return wt2;
3291}
3292
3293uint64_t helper_float_cvt_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
3294{
3295    uint64_t dt2;
3296
3297    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
3298    if (get_float_exception_flags(&env->active_fpu.fp_status)
3299            & float_flag_invalid) {
3300        if (float64_is_any_nan(fdt0)) {
3301            dt2 = 0;
3302        }
3303    }
3304    update_fcr31(env, GETPC());
3305    return dt2;
3306}
3307
3308uint64_t helper_float_cvt_2008_l_s(CPUMIPSState *env, uint32_t fst0)
3309{
3310    uint64_t dt2;
3311
3312    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
3313    if (get_float_exception_flags(&env->active_fpu.fp_status)
3314            & float_flag_invalid) {
3315        if (float32_is_any_nan(fst0)) {
3316            dt2 = 0;
3317        }
3318    }
3319    update_fcr31(env, GETPC());
3320    return dt2;
3321}
3322
3323uint32_t helper_float_cvt_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
3324{
3325    uint32_t wt2;
3326
3327    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
3328    if (get_float_exception_flags(&env->active_fpu.fp_status)
3329            & float_flag_invalid) {
3330        if (float64_is_any_nan(fdt0)) {
3331            wt2 = 0;
3332        }
3333    }
3334    update_fcr31(env, GETPC());
3335    return wt2;
3336}
3337
3338uint32_t helper_float_cvt_2008_w_s(CPUMIPSState *env, uint32_t fst0)
3339{
3340    uint32_t wt2;
3341
3342    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
3343    if (get_float_exception_flags(&env->active_fpu.fp_status)
3344            & float_flag_invalid) {
3345        if (float32_is_any_nan(fst0)) {
3346            wt2 = 0;
3347        }
3348    }
3349    update_fcr31(env, GETPC());
3350    return wt2;
3351}
3352
3353uint64_t helper_float_round_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
3354{
3355    uint64_t dt2;
3356
3357    set_float_rounding_mode(float_round_nearest_even,
3358            &env->active_fpu.fp_status);
3359    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
3360    restore_rounding_mode(env);
3361    if (get_float_exception_flags(&env->active_fpu.fp_status)
3362            & float_flag_invalid) {
3363        if (float64_is_any_nan(fdt0)) {
3364            dt2 = 0;
3365        }
3366    }
3367    update_fcr31(env, GETPC());
3368    return dt2;
3369}
3370
3371uint64_t helper_float_round_2008_l_s(CPUMIPSState *env, uint32_t fst0)
3372{
3373    uint64_t dt2;
3374
3375    set_float_rounding_mode(float_round_nearest_even,
3376            &env->active_fpu.fp_status);
3377    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
3378    restore_rounding_mode(env);
3379    if (get_float_exception_flags(&env->active_fpu.fp_status)
3380            & float_flag_invalid) {
3381        if (float32_is_any_nan(fst0)) {
3382            dt2 = 0;
3383        }
3384    }
3385    update_fcr31(env, GETPC());
3386    return dt2;
3387}
3388
3389uint32_t helper_float_round_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
3390{
3391    uint32_t wt2;
3392
3393    set_float_rounding_mode(float_round_nearest_even,
3394            &env->active_fpu.fp_status);
3395    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
3396    restore_rounding_mode(env);
3397    if (get_float_exception_flags(&env->active_fpu.fp_status)
3398            & float_flag_invalid) {
3399        if (float64_is_any_nan(fdt0)) {
3400            wt2 = 0;
3401        }
3402    }
3403    update_fcr31(env, GETPC());
3404    return wt2;
3405}
3406
3407uint32_t helper_float_round_2008_w_s(CPUMIPSState *env, uint32_t fst0)
3408{
3409    uint32_t wt2;
3410
3411    set_float_rounding_mode(float_round_nearest_even,
3412            &env->active_fpu.fp_status);
3413    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
3414    restore_rounding_mode(env);
3415    if (get_float_exception_flags(&env->active_fpu.fp_status)
3416            & float_flag_invalid) {
3417        if (float32_is_any_nan(fst0)) {
3418            wt2 = 0;
3419        }
3420    }
3421    update_fcr31(env, GETPC());
3422    return wt2;
3423}
3424
3425uint64_t helper_float_trunc_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
3426{
3427    uint64_t dt2;
3428
3429    dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
3430    if (get_float_exception_flags(&env->active_fpu.fp_status)
3431            & float_flag_invalid) {
3432        if (float64_is_any_nan(fdt0)) {
3433            dt2 = 0;
3434        }
3435    }
3436    update_fcr31(env, GETPC());
3437    return dt2;
3438}
3439
3440uint64_t helper_float_trunc_2008_l_s(CPUMIPSState *env, uint32_t fst0)
3441{
3442    uint64_t dt2;
3443
3444    dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
3445    if (get_float_exception_flags(&env->active_fpu.fp_status)
3446            & float_flag_invalid) {
3447        if (float32_is_any_nan(fst0)) {
3448            dt2 = 0;
3449        }
3450    }
3451    update_fcr31(env, GETPC());
3452    return dt2;
3453}
3454
3455uint32_t helper_float_trunc_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
3456{
3457    uint32_t wt2;
3458
3459    wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
3460    if (get_float_exception_flags(&env->active_fpu.fp_status)
3461            & float_flag_invalid) {
3462        if (float64_is_any_nan(fdt0)) {
3463            wt2 = 0;
3464        }
3465    }
3466    update_fcr31(env, GETPC());
3467    return wt2;
3468}
3469
3470uint32_t helper_float_trunc_2008_w_s(CPUMIPSState *env, uint32_t fst0)
3471{
3472    uint32_t wt2;
3473
3474    wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
3475    if (get_float_exception_flags(&env->active_fpu.fp_status)
3476            & float_flag_invalid) {
3477        if (float32_is_any_nan(fst0)) {
3478            wt2 = 0;
3479        }
3480    }
3481    update_fcr31(env, GETPC());
3482    return wt2;
3483}
3484
3485uint64_t helper_float_ceil_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
3486{
3487    uint64_t dt2;
3488
3489    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3490    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
3491    restore_rounding_mode(env);
3492    if (get_float_exception_flags(&env->active_fpu.fp_status)
3493            & float_flag_invalid) {
3494        if (float64_is_any_nan(fdt0)) {
3495            dt2 = 0;
3496        }
3497    }
3498    update_fcr31(env, GETPC());
3499    return dt2;
3500}
3501
3502uint64_t helper_float_ceil_2008_l_s(CPUMIPSState *env, uint32_t fst0)
3503{
3504    uint64_t dt2;
3505
3506    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3507    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
3508    restore_rounding_mode(env);
3509    if (get_float_exception_flags(&env->active_fpu.fp_status)
3510            & float_flag_invalid) {
3511        if (float32_is_any_nan(fst0)) {
3512            dt2 = 0;
3513        }
3514    }
3515    update_fcr31(env, GETPC());
3516    return dt2;
3517}
3518
3519uint32_t helper_float_ceil_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
3520{
3521    uint32_t wt2;
3522
3523    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3524    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
3525    restore_rounding_mode(env);
3526    if (get_float_exception_flags(&env->active_fpu.fp_status)
3527            & float_flag_invalid) {
3528        if (float64_is_any_nan(fdt0)) {
3529            wt2 = 0;
3530        }
3531    }
3532    update_fcr31(env, GETPC());
3533    return wt2;
3534}
3535
3536uint32_t helper_float_ceil_2008_w_s(CPUMIPSState *env, uint32_t fst0)
3537{
3538    uint32_t wt2;
3539
3540    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3541    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
3542    restore_rounding_mode(env);
3543    if (get_float_exception_flags(&env->active_fpu.fp_status)
3544            & float_flag_invalid) {
3545        if (float32_is_any_nan(fst0)) {
3546            wt2 = 0;
3547        }
3548    }
3549    update_fcr31(env, GETPC());
3550    return wt2;
3551}
3552
3553uint64_t helper_float_floor_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
3554{
3555    uint64_t dt2;
3556
3557    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3558    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
3559    restore_rounding_mode(env);
3560    if (get_float_exception_flags(&env->active_fpu.fp_status)
3561            & float_flag_invalid) {
3562        if (float64_is_any_nan(fdt0)) {
3563            dt2 = 0;
3564        }
3565    }
3566    update_fcr31(env, GETPC());
3567    return dt2;
3568}
3569
3570uint64_t helper_float_floor_2008_l_s(CPUMIPSState *env, uint32_t fst0)
3571{
3572    uint64_t dt2;
3573
3574    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3575    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
3576    restore_rounding_mode(env);
3577    if (get_float_exception_flags(&env->active_fpu.fp_status)
3578            & float_flag_invalid) {
3579        if (float32_is_any_nan(fst0)) {
3580            dt2 = 0;
3581        }
3582    }
3583    update_fcr31(env, GETPC());
3584    return dt2;
3585}
3586
3587uint32_t helper_float_floor_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
3588{
3589    uint32_t wt2;
3590
3591    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3592    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
3593    restore_rounding_mode(env);
3594    if (get_float_exception_flags(&env->active_fpu.fp_status)
3595            & float_flag_invalid) {
3596        if (float64_is_any_nan(fdt0)) {
3597            wt2 = 0;
3598        }
3599    }
3600    update_fcr31(env, GETPC());
3601    return wt2;
3602}
3603
3604uint32_t helper_float_floor_2008_w_s(CPUMIPSState *env, uint32_t fst0)
3605{
3606    uint32_t wt2;
3607
3608    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3609    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
3610    restore_rounding_mode(env);
3611    if (get_float_exception_flags(&env->active_fpu.fp_status)
3612            & float_flag_invalid) {
3613        if (float32_is_any_nan(fst0)) {
3614            wt2 = 0;
3615        }
3616    }
3617    update_fcr31(env, GETPC());
3618    return wt2;
3619}
3620
3621/* unary operations, not modifying fp status  */
3622#define FLOAT_UNOP(name)                                       \
3623uint64_t helper_float_ ## name ## _d(uint64_t fdt0)                \
3624{                                                              \
3625    return float64_ ## name(fdt0);                             \
3626}                                                              \
3627uint32_t helper_float_ ## name ## _s(uint32_t fst0)                \
3628{                                                              \
3629    return float32_ ## name(fst0);                             \
3630}                                                              \
3631uint64_t helper_float_ ## name ## _ps(uint64_t fdt0)               \
3632{                                                              \
3633    uint32_t wt0;                                              \
3634    uint32_t wth0;                                             \
3635                                                               \
3636    wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF);                 \
3637    wth0 = float32_ ## name(fdt0 >> 32);                       \
3638    return ((uint64_t)wth0 << 32) | wt0;                       \
3639}
3640FLOAT_UNOP(abs)
3641FLOAT_UNOP(chs)
3642#undef FLOAT_UNOP
3643
3644/* MIPS specific unary operations */
3645uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0)
3646{
3647    uint64_t fdt2;
3648
3649    fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status);
3650    update_fcr31(env, GETPC());
3651    return fdt2;
3652}
3653
3654uint32_t helper_float_recip_s(CPUMIPSState *env, uint32_t fst0)
3655{
3656    uint32_t fst2;
3657
3658    fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status);
3659    update_fcr31(env, GETPC());
3660    return fst2;
3661}
3662
3663uint64_t helper_float_rsqrt_d(CPUMIPSState *env, uint64_t fdt0)
3664{
3665    uint64_t fdt2;
3666
3667    fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
3668    fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status);
3669    update_fcr31(env, GETPC());
3670    return fdt2;
3671}
3672
3673uint32_t helper_float_rsqrt_s(CPUMIPSState *env, uint32_t fst0)
3674{
3675    uint32_t fst2;
3676
3677    fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
3678    fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
3679    update_fcr31(env, GETPC());
3680    return fst2;
3681}
3682
3683uint64_t helper_float_recip1_d(CPUMIPSState *env, uint64_t fdt0)
3684{
3685    uint64_t fdt2;
3686
3687    fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status);
3688    update_fcr31(env, GETPC());
3689    return fdt2;
3690}
3691
3692uint32_t helper_float_recip1_s(CPUMIPSState *env, uint32_t fst0)
3693{
3694    uint32_t fst2;
3695
3696    fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status);
3697    update_fcr31(env, GETPC());
3698    return fst2;
3699}
3700
3701uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0)
3702{
3703    uint32_t fst2;
3704    uint32_t fsth2;
3705
3706    fst2 = float32_div(float32_one, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
3707    fsth2 = float32_div(float32_one, fdt0 >> 32, &env->active_fpu.fp_status);
3708    update_fcr31(env, GETPC());
3709    return ((uint64_t)fsth2 << 32) | fst2;
3710}
3711
3712uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0)
3713{
3714    uint64_t fdt2;
3715
3716    fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
3717    fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status);
3718    update_fcr31(env, GETPC());
3719    return fdt2;
3720}
3721
3722uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, uint32_t fst0)
3723{
3724    uint32_t fst2;
3725
3726    fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
3727    fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
3728    update_fcr31(env, GETPC());
3729    return fst2;
3730}
3731
3732uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0)
3733{
3734    uint32_t fst2;
3735    uint32_t fsth2;
3736
3737    fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
3738    fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status);
3739    fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
3740    fsth2 = float32_div(float32_one, fsth2, &env->active_fpu.fp_status);
3741    update_fcr31(env, GETPC());
3742    return ((uint64_t)fsth2 << 32) | fst2;
3743}
3744
3745#define FLOAT_RINT(name, bits)                                              \
3746uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env,                \
3747                                          uint ## bits ## _t fs)            \
3748{                                                                           \
3749    uint ## bits ## _t fdret;                                               \
3750                                                                            \
3751    fdret = float ## bits ## _round_to_int(fs, &env->active_fpu.fp_status); \
3752    update_fcr31(env, GETPC());                                             \
3753    return fdret;                                                           \
3754}
3755
3756FLOAT_RINT(rint_s, 32)
3757FLOAT_RINT(rint_d, 64)
3758#undef FLOAT_RINT
3759
3760#define FLOAT_CLASS_SIGNALING_NAN      0x001
3761#define FLOAT_CLASS_QUIET_NAN          0x002
3762#define FLOAT_CLASS_NEGATIVE_INFINITY  0x004
3763#define FLOAT_CLASS_NEGATIVE_NORMAL    0x008
3764#define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010
3765#define FLOAT_CLASS_NEGATIVE_ZERO      0x020
3766#define FLOAT_CLASS_POSITIVE_INFINITY  0x040
3767#define FLOAT_CLASS_POSITIVE_NORMAL    0x080
3768#define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100
3769#define FLOAT_CLASS_POSITIVE_ZERO      0x200
3770
3771#define FLOAT_CLASS(name, bits)                                      \
3772uint ## bits ## _t float_ ## name (uint ## bits ## _t arg,           \
3773                                   float_status *status)             \
3774{                                                                    \
3775    if (float ## bits ## _is_signaling_nan(arg, status)) {           \
3776        return FLOAT_CLASS_SIGNALING_NAN;                            \
3777    } else if (float ## bits ## _is_quiet_nan(arg, status)) {        \
3778        return FLOAT_CLASS_QUIET_NAN;                                \
3779    } else if (float ## bits ## _is_neg(arg)) {                      \
3780        if (float ## bits ## _is_infinity(arg)) {                    \
3781            return FLOAT_CLASS_NEGATIVE_INFINITY;                    \
3782        } else if (float ## bits ## _is_zero(arg)) {                 \
3783            return FLOAT_CLASS_NEGATIVE_ZERO;                        \
3784        } else if (float ## bits ## _is_zero_or_denormal(arg)) {     \
3785            return FLOAT_CLASS_NEGATIVE_SUBNORMAL;                   \
3786        } else {                                                     \
3787            return FLOAT_CLASS_NEGATIVE_NORMAL;                      \
3788        }                                                            \
3789    } else {                                                         \
3790        if (float ## bits ## _is_infinity(arg)) {                    \
3791            return FLOAT_CLASS_POSITIVE_INFINITY;                    \
3792        } else if (float ## bits ## _is_zero(arg)) {                 \
3793            return FLOAT_CLASS_POSITIVE_ZERO;                        \
3794        } else if (float ## bits ## _is_zero_or_denormal(arg)) {     \
3795            return FLOAT_CLASS_POSITIVE_SUBNORMAL;                   \
3796        } else {                                                     \
3797            return FLOAT_CLASS_POSITIVE_NORMAL;                      \
3798        }                                                            \
3799    }                                                                \
3800}                                                                    \
3801                                                                     \
3802uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env,         \
3803                                          uint ## bits ## _t arg)    \
3804{                                                                    \
3805    return float_ ## name(arg, &env->active_fpu.fp_status);          \
3806}
3807
3808FLOAT_CLASS(class_s, 32)
3809FLOAT_CLASS(class_d, 64)
3810#undef FLOAT_CLASS
3811
3812/* binary operations */
3813#define FLOAT_BINOP(name)                                          \
3814uint64_t helper_float_ ## name ## _d(CPUMIPSState *env,            \
3815                                     uint64_t fdt0, uint64_t fdt1) \
3816{                                                                  \
3817    uint64_t dt2;                                                  \
3818                                                                   \
3819    dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status);     \
3820    update_fcr31(env, GETPC());                                    \
3821    return dt2;                                                    \
3822}                                                                  \
3823                                                                   \
3824uint32_t helper_float_ ## name ## _s(CPUMIPSState *env,            \
3825                                     uint32_t fst0, uint32_t fst1) \
3826{                                                                  \
3827    uint32_t wt2;                                                  \
3828                                                                   \
3829    wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status);     \
3830    update_fcr31(env, GETPC());                                    \
3831    return wt2;                                                    \
3832}                                                                  \
3833                                                                   \
3834uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,           \
3835                                      uint64_t fdt0,               \
3836                                      uint64_t fdt1)               \
3837{                                                                  \
3838    uint32_t fst0 = fdt0 & 0XFFFFFFFF;                             \
3839    uint32_t fsth0 = fdt0 >> 32;                                   \
3840    uint32_t fst1 = fdt1 & 0XFFFFFFFF;                             \
3841    uint32_t fsth1 = fdt1 >> 32;                                   \
3842    uint32_t wt2;                                                  \
3843    uint32_t wth2;                                                 \
3844                                                                   \
3845    wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status);     \
3846    wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status);  \
3847    update_fcr31(env, GETPC());                                    \
3848    return ((uint64_t)wth2 << 32) | wt2;                           \
3849}
3850
3851FLOAT_BINOP(add)
3852FLOAT_BINOP(sub)
3853FLOAT_BINOP(mul)
3854FLOAT_BINOP(div)
3855#undef FLOAT_BINOP
3856
3857/* MIPS specific binary operations */
3858uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
3859{
3860    fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
3861    fdt2 = float64_chs(float64_sub(fdt2, float64_one, &env->active_fpu.fp_status));
3862    update_fcr31(env, GETPC());
3863    return fdt2;
3864}
3865
3866uint32_t helper_float_recip2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2)
3867{
3868    fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
3869    fst2 = float32_chs(float32_sub(fst2, float32_one, &env->active_fpu.fp_status));
3870    update_fcr31(env, GETPC());
3871    return fst2;
3872}
3873
3874uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
3875{
3876    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3877    uint32_t fsth0 = fdt0 >> 32;
3878    uint32_t fst2 = fdt2 & 0XFFFFFFFF;
3879    uint32_t fsth2 = fdt2 >> 32;
3880
3881    fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
3882    fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
3883    fst2 = float32_chs(float32_sub(fst2, float32_one, &env->active_fpu.fp_status));
3884    fsth2 = float32_chs(float32_sub(fsth2, float32_one, &env->active_fpu.fp_status));
3885    update_fcr31(env, GETPC());
3886    return ((uint64_t)fsth2 << 32) | fst2;
3887}
3888
3889uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
3890{
3891    fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
3892    fdt2 = float64_sub(fdt2, float64_one, &env->active_fpu.fp_status);
3893    fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status));
3894    update_fcr31(env, GETPC());
3895    return fdt2;
3896}
3897
3898uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2)
3899{
3900    fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
3901    fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status);
3902    fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
3903    update_fcr31(env, GETPC());
3904    return fst2;
3905}
3906
3907uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
3908{
3909    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3910    uint32_t fsth0 = fdt0 >> 32;
3911    uint32_t fst2 = fdt2 & 0XFFFFFFFF;
3912    uint32_t fsth2 = fdt2 >> 32;
3913
3914    fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
3915    fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
3916    fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status);
3917    fsth2 = float32_sub(fsth2, float32_one, &env->active_fpu.fp_status);
3918    fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
3919    fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status));
3920    update_fcr31(env, GETPC());
3921    return ((uint64_t)fsth2 << 32) | fst2;
3922}
3923
3924uint64_t helper_float_addr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
3925{
3926    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3927    uint32_t fsth0 = fdt0 >> 32;
3928    uint32_t fst1 = fdt1 & 0XFFFFFFFF;
3929    uint32_t fsth1 = fdt1 >> 32;
3930    uint32_t fst2;
3931    uint32_t fsth2;
3932
3933    fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status);
3934    fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status);
3935    update_fcr31(env, GETPC());
3936    return ((uint64_t)fsth2 << 32) | fst2;
3937}
3938
3939uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
3940{
3941    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3942    uint32_t fsth0 = fdt0 >> 32;
3943    uint32_t fst1 = fdt1 & 0XFFFFFFFF;
3944    uint32_t fsth1 = fdt1 >> 32;
3945    uint32_t fst2;
3946    uint32_t fsth2;
3947
3948    fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status);
3949    fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status);
3950    update_fcr31(env, GETPC());
3951    return ((uint64_t)fsth2 << 32) | fst2;
3952}
3953
3954#define FLOAT_MINMAX(name, bits, minmaxfunc)                            \
3955uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env,            \
3956                                          uint ## bits ## _t fs,        \
3957                                          uint ## bits ## _t ft)        \
3958{                                                                       \
3959    uint ## bits ## _t fdret;                                           \
3960                                                                        \
3961    fdret = float ## bits ## _ ## minmaxfunc(fs, ft,                    \
3962                                           &env->active_fpu.fp_status); \
3963    update_fcr31(env, GETPC());                                         \
3964    return fdret;                                                       \
3965}
3966
3967FLOAT_MINMAX(max_s, 32, maxnum)
3968FLOAT_MINMAX(max_d, 64, maxnum)
3969FLOAT_MINMAX(maxa_s, 32, maxnummag)
3970FLOAT_MINMAX(maxa_d, 64, maxnummag)
3971
3972FLOAT_MINMAX(min_s, 32, minnum)
3973FLOAT_MINMAX(min_d, 64, minnum)
3974FLOAT_MINMAX(mina_s, 32, minnummag)
3975FLOAT_MINMAX(mina_d, 64, minnummag)
3976#undef FLOAT_MINMAX
3977
3978/* ternary operations */
3979#define UNFUSED_FMA(prefix, a, b, c, flags)                          \
3980{                                                                    \
3981    a = prefix##_mul(a, b, &env->active_fpu.fp_status);              \
3982    if ((flags) & float_muladd_negate_c) {                           \
3983        a = prefix##_sub(a, c, &env->active_fpu.fp_status);          \
3984    } else {                                                         \
3985        a = prefix##_add(a, c, &env->active_fpu.fp_status);          \
3986    }                                                                \
3987    if ((flags) & float_muladd_negate_result) {                      \
3988        a = prefix##_chs(a);                                         \
3989    }                                                                \
3990}
3991
3992/* FMA based operations */
3993#define FLOAT_FMA(name, type)                                        \
3994uint64_t helper_float_ ## name ## _d(CPUMIPSState *env,              \
3995                                     uint64_t fdt0, uint64_t fdt1,   \
3996                                     uint64_t fdt2)                  \
3997{                                                                    \
3998    UNFUSED_FMA(float64, fdt0, fdt1, fdt2, type);                    \
3999    update_fcr31(env, GETPC());                                      \
4000    return fdt0;                                                     \
4001}                                                                    \
4002                                                                     \
4003uint32_t helper_float_ ## name ## _s(CPUMIPSState *env,              \
4004                                     uint32_t fst0, uint32_t fst1,   \
4005                                     uint32_t fst2)                  \
4006{                                                                    \
4007    UNFUSED_FMA(float32, fst0, fst1, fst2, type);                    \
4008    update_fcr31(env, GETPC());                                      \
4009    return fst0;                                                     \
4010}                                                                    \
4011                                                                     \
4012uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,             \
4013                                      uint64_t fdt0, uint64_t fdt1,  \
4014                                      uint64_t fdt2)                 \
4015{                                                                    \
4016    uint32_t fst0 = fdt0 & 0XFFFFFFFF;                               \
4017    uint32_t fsth0 = fdt0 >> 32;                                     \
4018    uint32_t fst1 = fdt1 & 0XFFFFFFFF;                               \
4019    uint32_t fsth1 = fdt1 >> 32;                                     \
4020    uint32_t fst2 = fdt2 & 0XFFFFFFFF;                               \
4021    uint32_t fsth2 = fdt2 >> 32;                                     \
4022                                                                     \
4023    UNFUSED_FMA(float32, fst0, fst1, fst2, type);                    \
4024    UNFUSED_FMA(float32, fsth0, fsth1, fsth2, type);                 \
4025    update_fcr31(env, GETPC());                                      \
4026    return ((uint64_t)fsth0 << 32) | fst0;                           \
4027}
4028FLOAT_FMA(madd, 0)
4029FLOAT_FMA(msub, float_muladd_negate_c)
4030FLOAT_FMA(nmadd, float_muladd_negate_result)
4031FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c)
4032#undef FLOAT_FMA
4033
4034#define FLOAT_FMADDSUB(name, bits, muladd_arg)                          \
4035uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env,            \
4036                                          uint ## bits ## _t fs,        \
4037                                          uint ## bits ## _t ft,        \
4038                                          uint ## bits ## _t fd)        \
4039{                                                                       \
4040    uint ## bits ## _t fdret;                                           \
4041                                                                        \
4042    fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg,            \
4043                                     &env->active_fpu.fp_status);       \
4044    update_fcr31(env, GETPC());                                         \
4045    return fdret;                                                       \
4046}
4047
4048FLOAT_FMADDSUB(maddf_s, 32, 0)
4049FLOAT_FMADDSUB(maddf_d, 64, 0)
4050FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_product)
4051FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_product)
4052#undef FLOAT_FMADDSUB
4053
4054/* compare operations */
4055#define FOP_COND_D(op, cond)                                   \
4056void helper_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0,     \
4057                         uint64_t fdt1, int cc)                \
4058{                                                              \
4059    int c;                                                     \
4060    c = cond;                                                  \
4061    update_fcr31(env, GETPC());                                \
4062    if (c)                                                     \
4063        SET_FP_COND(cc, env->active_fpu);                      \
4064    else                                                       \
4065        CLEAR_FP_COND(cc, env->active_fpu);                    \
4066}                                                              \
4067void helper_cmpabs_d_ ## op(CPUMIPSState *env, uint64_t fdt0,  \
4068                            uint64_t fdt1, int cc)             \
4069{                                                              \
4070    int c;                                                     \
4071    fdt0 = float64_abs(fdt0);                                  \
4072    fdt1 = float64_abs(fdt1);                                  \
4073    c = cond;                                                  \
4074    update_fcr31(env, GETPC());                                \
4075    if (c)                                                     \
4076        SET_FP_COND(cc, env->active_fpu);                      \
4077    else                                                       \
4078        CLEAR_FP_COND(cc, env->active_fpu);                    \
4079}
4080
4081/* NOTE: the comma operator will make "cond" to eval to false,
4082 * but float64_unordered_quiet() is still called. */
4083FOP_COND_D(f,   (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0))
4084FOP_COND_D(un,  float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status))
4085FOP_COND_D(eq,  float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
4086FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
4087FOP_COND_D(olt, float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
4088FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
4089FOP_COND_D(ole, float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
4090FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
4091/* NOTE: the comma operator will make "cond" to eval to false,
4092 * but float64_unordered() is still called. */
4093FOP_COND_D(sf,  (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0))
4094FOP_COND_D(ngle,float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status))
4095FOP_COND_D(seq, float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
4096FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
4097FOP_COND_D(lt,  float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
4098FOP_COND_D(nge, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
4099FOP_COND_D(le,  float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
4100FOP_COND_D(ngt, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
4101
4102#define FOP_COND_S(op, cond)                                   \
4103void helper_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0,     \
4104                         uint32_t fst1, int cc)                \
4105{                                                              \
4106    int c;                                                     \
4107    c = cond;                                                  \
4108    update_fcr31(env, GETPC());                                \
4109    if (c)                                                     \
4110        SET_FP_COND(cc, env->active_fpu);                      \
4111    else                                                       \
4112        CLEAR_FP_COND(cc, env->active_fpu);                    \
4113}                                                              \
4114void helper_cmpabs_s_ ## op(CPUMIPSState *env, uint32_t fst0,  \
4115                            uint32_t fst1, int cc)             \
4116{                                                              \
4117    int c;                                                     \
4118    fst0 = float32_abs(fst0);                                  \
4119    fst1 = float32_abs(fst1);                                  \
4120    c = cond;                                                  \
4121    update_fcr31(env, GETPC());                                \
4122    if (c)                                                     \
4123        SET_FP_COND(cc, env->active_fpu);                      \
4124    else                                                       \
4125        CLEAR_FP_COND(cc, env->active_fpu);                    \
4126}
4127
4128/* NOTE: the comma operator will make "cond" to eval to false,
4129 * but float32_unordered_quiet() is still called. */
4130FOP_COND_S(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0))
4131FOP_COND_S(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status))
4132FOP_COND_S(eq,  float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
4133FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
4134FOP_COND_S(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
4135FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
4136FOP_COND_S(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
4137FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
4138/* NOTE: the comma operator will make "cond" to eval to false,
4139 * but float32_unordered() is still called. */
4140FOP_COND_S(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0))
4141FOP_COND_S(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status))
4142FOP_COND_S(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status))
4143FOP_COND_S(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
4144FOP_COND_S(lt,  float32_lt(fst0, fst1, &env->active_fpu.fp_status))
4145FOP_COND_S(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
4146FOP_COND_S(le,  float32_le(fst0, fst1, &env->active_fpu.fp_status))
4147FOP_COND_S(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
4148
4149#define FOP_COND_PS(op, condl, condh)                           \
4150void helper_cmp_ps_ ## op(CPUMIPSState *env, uint64_t fdt0,     \
4151                          uint64_t fdt1, int cc)                \
4152{                                                               \
4153    uint32_t fst0, fsth0, fst1, fsth1;                          \
4154    int ch, cl;                                                 \
4155    fst0 = fdt0 & 0XFFFFFFFF;                                   \
4156    fsth0 = fdt0 >> 32;                                         \
4157    fst1 = fdt1 & 0XFFFFFFFF;                                   \
4158    fsth1 = fdt1 >> 32;                                         \
4159    cl = condl;                                                 \
4160    ch = condh;                                                 \
4161    update_fcr31(env, GETPC());                                 \
4162    if (cl)                                                     \
4163        SET_FP_COND(cc, env->active_fpu);                       \
4164    else                                                        \
4165        CLEAR_FP_COND(cc, env->active_fpu);                     \
4166    if (ch)                                                     \
4167        SET_FP_COND(cc + 1, env->active_fpu);                   \
4168    else                                                        \
4169        CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
4170}                                                               \
4171void helper_cmpabs_ps_ ## op(CPUMIPSState *env, uint64_t fdt0,  \
4172                             uint64_t fdt1, int cc)             \
4173{                                                               \
4174    uint32_t fst0, fsth0, fst1, fsth1;                          \
4175    int ch, cl;                                                 \
4176    fst0 = float32_abs(fdt0 & 0XFFFFFFFF);                      \
4177    fsth0 = float32_abs(fdt0 >> 32);                            \
4178    fst1 = float32_abs(fdt1 & 0XFFFFFFFF);                      \
4179    fsth1 = float32_abs(fdt1 >> 32);                            \
4180    cl = condl;                                                 \
4181    ch = condh;                                                 \
4182    update_fcr31(env, GETPC());                                 \
4183    if (cl)                                                     \
4184        SET_FP_COND(cc, env->active_fpu);                       \
4185    else                                                        \
4186        CLEAR_FP_COND(cc, env->active_fpu);                     \
4187    if (ch)                                                     \
4188        SET_FP_COND(cc + 1, env->active_fpu);                   \
4189    else                                                        \
4190        CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
4191}
4192
4193/* NOTE: the comma operator will make "cond" to eval to false,
4194 * but float32_unordered_quiet() is still called. */
4195FOP_COND_PS(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0),
4196                 (float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status), 0))
4197FOP_COND_PS(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status),
4198                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status))
4199FOP_COND_PS(eq,  float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
4200                 float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
4201FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
4202                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
4203FOP_COND_PS(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
4204                 float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
4205FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
4206                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
4207FOP_COND_PS(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
4208                 float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
4209FOP_COND_PS(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
4210                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
4211/* NOTE: the comma operator will make "cond" to eval to false,
4212 * but float32_unordered() is still called. */
4213FOP_COND_PS(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0),
4214                 (float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status), 0))
4215FOP_COND_PS(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status),
4216                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status))
4217FOP_COND_PS(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status),
4218                 float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
4219FOP_COND_PS(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
4220                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
4221FOP_COND_PS(lt,  float32_lt(fst0, fst1, &env->active_fpu.fp_status),
4222                 float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
4223FOP_COND_PS(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
4224                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
4225FOP_COND_PS(le,  float32_le(fst0, fst1, &env->active_fpu.fp_status),
4226                 float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
4227FOP_COND_PS(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
4228                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
4229
4230/* R6 compare operations */
4231#define FOP_CONDN_D(op, cond)                                       \
4232uint64_t helper_r6_cmp_d_ ## op(CPUMIPSState * env, uint64_t fdt0,  \
4233                         uint64_t fdt1)                             \
4234{                                                                   \
4235    uint64_t c;                                                     \
4236    c = cond;                                                       \
4237    update_fcr31(env, GETPC());                                     \
4238    if (c) {                                                        \
4239        return -1;                                                  \
4240    } else {                                                        \
4241        return 0;                                                   \
4242    }                                                               \
4243}
4244
4245/* NOTE: the comma operator will make "cond" to eval to false,
4246 * but float64_unordered_quiet() is still called. */
4247FOP_CONDN_D(af,  (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0))
4248FOP_CONDN_D(un,  (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)))
4249FOP_CONDN_D(eq,  (float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4250FOP_CONDN_D(ueq, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4251                  || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4252FOP_CONDN_D(lt,  (float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4253FOP_CONDN_D(ult, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4254                  || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4255FOP_CONDN_D(le,  (float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4256FOP_CONDN_D(ule, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4257                  || float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4258/* NOTE: the comma operator will make "cond" to eval to false,
4259 * but float64_unordered() is still called. */
4260FOP_CONDN_D(saf,  (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0))
4261FOP_CONDN_D(sun,  (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)))
4262FOP_CONDN_D(seq,  (float64_eq(fdt0, fdt1, &env->active_fpu.fp_status)))
4263FOP_CONDN_D(sueq, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)
4264                   || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status)))
4265FOP_CONDN_D(slt,  (float64_lt(fdt0, fdt1, &env->active_fpu.fp_status)))
4266FOP_CONDN_D(sult, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)
4267                   || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status)))
4268FOP_CONDN_D(sle,  (float64_le(fdt0, fdt1, &env->active_fpu.fp_status)))
4269FOP_CONDN_D(sule, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)
4270                   || float64_le(fdt0, fdt1, &env->active_fpu.fp_status)))
4271FOP_CONDN_D(or,   (float64_le_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4272                   || float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4273FOP_CONDN_D(une,  (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4274                   || float64_lt_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4275                   || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4276FOP_CONDN_D(ne,   (float64_lt_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4277                   || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4278FOP_CONDN_D(sor,  (float64_le(fdt1, fdt0, &env->active_fpu.fp_status)
4279                   || float64_le(fdt0, fdt1, &env->active_fpu.fp_status)))
4280FOP_CONDN_D(sune, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)
4281                   || float64_lt(fdt1, fdt0, &env->active_fpu.fp_status)
4282                   || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status)))
4283FOP_CONDN_D(sne,  (float64_lt(fdt1, fdt0, &env->active_fpu.fp_status)
4284                   || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status)))
4285
4286#define FOP_CONDN_S(op, cond)                                       \
4287uint32_t helper_r6_cmp_s_ ## op(CPUMIPSState * env, uint32_t fst0,  \
4288                         uint32_t fst1)                             \
4289{                                                                   \
4290    uint64_t c;                                                     \
4291    c = cond;                                                       \
4292    update_fcr31(env, GETPC());                                     \
4293    if (c) {                                                        \
4294        return -1;                                                  \
4295    } else {                                                        \
4296        return 0;                                                   \
4297    }                                                               \
4298}
4299
4300/* NOTE: the comma operator will make "cond" to eval to false,
4301 * but float32_unordered_quiet() is still called. */
4302FOP_CONDN_S(af,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0))
4303FOP_CONDN_S(un,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)))
4304FOP_CONDN_S(eq,   (float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4305FOP_CONDN_S(ueq,  (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)
4306                   || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4307FOP_CONDN_S(lt,   (float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4308FOP_CONDN_S(ult,  (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)
4309                   || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4310FOP_CONDN_S(le,   (float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4311FOP_CONDN_S(ule,  (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)
4312                   || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4313/* NOTE: the comma operator will make "cond" to eval to false,
4314 * but float32_unordered() is still called. */
4315FOP_CONDN_S(saf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0))
4316FOP_CONDN_S(sun,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)))
4317FOP_CONDN_S(seq,  (float32_eq(fst0, fst1, &env->active_fpu.fp_status)))
4318FOP_CONDN_S(sueq, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
4319                   || float32_eq(fst0, fst1, &env->active_fpu.fp_status)))
4320FOP_CONDN_S(slt,  (float32_lt(fst0, fst1, &env->active_fpu.fp_status)))
4321FOP_CONDN_S(sult, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
4322                   || float32_lt(fst0, fst1, &env->active_fpu.fp_status)))
4323FOP_CONDN_S(sle,  (float32_le(fst0, fst1, &env->active_fpu.fp_status)))
4324FOP_CONDN_S(sule, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
4325                   || float32_le(fst0, fst1, &env->active_fpu.fp_status)))
4326FOP_CONDN_S(or,   (float32_le_quiet(fst1, fst0, &env->active_fpu.fp_status)
4327                   || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4328FOP_CONDN_S(une,  (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)
4329                   || float32_lt_quiet(fst1, fst0, &env->active_fpu.fp_status)
4330                   || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4331FOP_CONDN_S(ne,   (float32_lt_quiet(fst1, fst0, &env->active_fpu.fp_status)
4332                   || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4333FOP_CONDN_S(sor,  (float32_le(fst1, fst0, &env->active_fpu.fp_status)
4334                   || float32_le(fst0, fst1, &env->active_fpu.fp_status)))
4335FOP_CONDN_S(sune, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
4336                   || float32_lt(fst1, fst0, &env->active_fpu.fp_status)
4337                   || float32_lt(fst0, fst1, &env->active_fpu.fp_status)))
4338FOP_CONDN_S(sne,  (float32_lt(fst1, fst0, &env->active_fpu.fp_status)
4339                   || float32_lt(fst0, fst1, &env->active_fpu.fp_status)))
4340
4341/* MSA */
4342/* Data format min and max values */
4343#define DF_BITS(df) (1 << ((df) + 3))
4344
4345/* Element-by-element access macros */
4346#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df))
4347
4348#if !defined(CONFIG_USER_ONLY)
4349#define MEMOP_IDX(DF)                                           \
4350        TCGMemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN,  \
4351                                        cpu_mmu_index(env, false));
4352#else
4353#define MEMOP_IDX(DF)
4354#endif
4355
4356void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd,
4357                     target_ulong addr)
4358{
4359    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4360    MEMOP_IDX(DF_BYTE)
4361#if !defined(CONFIG_USER_ONLY)
4362#if !defined(HOST_WORDS_BIGENDIAN)
4363    pwd->b[0]  = helper_ret_ldub_mmu(env, addr + (0  << DF_BYTE), oi, GETPC());
4364    pwd->b[1]  = helper_ret_ldub_mmu(env, addr + (1  << DF_BYTE), oi, GETPC());
4365    pwd->b[2]  = helper_ret_ldub_mmu(env, addr + (2  << DF_BYTE), oi, GETPC());
4366    pwd->b[3]  = helper_ret_ldub_mmu(env, addr + (3  << DF_BYTE), oi, GETPC());
4367    pwd->b[4]  = helper_ret_ldub_mmu(env, addr + (4  << DF_BYTE), oi, GETPC());
4368    pwd->b[5]  = helper_ret_ldub_mmu(env, addr + (5  << DF_BYTE), oi, GETPC());
4369    pwd->b[6]  = helper_ret_ldub_mmu(env, addr + (6  << DF_BYTE), oi, GETPC());
4370    pwd->b[7]  = helper_ret_ldub_mmu(env, addr + (7  << DF_BYTE), oi, GETPC());
4371    pwd->b[8]  = helper_ret_ldub_mmu(env, addr + (8  << DF_BYTE), oi, GETPC());
4372    pwd->b[9]  = helper_ret_ldub_mmu(env, addr + (9  << DF_BYTE), oi, GETPC());
4373    pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
4374    pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
4375    pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
4376    pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
4377    pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
4378    pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
4379#else
4380    pwd->b[0]  = helper_ret_ldub_mmu(env, addr + (7  << DF_BYTE), oi, GETPC());
4381    pwd->b[1]  = helper_ret_ldub_mmu(env, addr + (6  << DF_BYTE), oi, GETPC());
4382    pwd->b[2]  = helper_ret_ldub_mmu(env, addr + (5  << DF_BYTE), oi, GETPC());
4383    pwd->b[3]  = helper_ret_ldub_mmu(env, addr + (4  << DF_BYTE), oi, GETPC());
4384    pwd->b[4]  = helper_ret_ldub_mmu(env, addr + (3  << DF_BYTE), oi, GETPC());
4385    pwd->b[5]  = helper_ret_ldub_mmu(env, addr + (2  << DF_BYTE), oi, GETPC());
4386    pwd->b[6]  = helper_ret_ldub_mmu(env, addr + (1  << DF_BYTE), oi, GETPC());
4387    pwd->b[7]  = helper_ret_ldub_mmu(env, addr + (0  << DF_BYTE), oi, GETPC());
4388    pwd->b[8]  = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
4389    pwd->b[9]  = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
4390    pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
4391    pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
4392    pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
4393    pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
4394    pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9  << DF_BYTE), oi, GETPC());
4395    pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8  << DF_BYTE), oi, GETPC());
4396#endif
4397#else
4398#if !defined(HOST_WORDS_BIGENDIAN)
4399    pwd->b[0]  = cpu_ldub_data(env, addr + (0  << DF_BYTE));
4400    pwd->b[1]  = cpu_ldub_data(env, addr + (1  << DF_BYTE));
4401    pwd->b[2]  = cpu_ldub_data(env, addr + (2  << DF_BYTE));
4402    pwd->b[3]  = cpu_ldub_data(env, addr + (3  << DF_BYTE));
4403    pwd->b[4]  = cpu_ldub_data(env, addr + (4  << DF_BYTE));
4404    pwd->b[5]  = cpu_ldub_data(env, addr + (5  << DF_BYTE));
4405    pwd->b[6]  = cpu_ldub_data(env, addr + (6  << DF_BYTE));
4406    pwd->b[7]  = cpu_ldub_data(env, addr + (7  << DF_BYTE));
4407    pwd->b[8]  = cpu_ldub_data(env, addr + (8  << DF_BYTE));
4408    pwd->b[9]  = cpu_ldub_data(env, addr + (9  << DF_BYTE));
4409    pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
4410    pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
4411    pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
4412    pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
4413    pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
4414    pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
4415#else
4416    pwd->b[0]  = cpu_ldub_data(env, addr + (7  << DF_BYTE));
4417    pwd->b[1]  = cpu_ldub_data(env, addr + (6  << DF_BYTE));
4418    pwd->b[2]  = cpu_ldub_data(env, addr + (5  << DF_BYTE));
4419    pwd->b[3]  = cpu_ldub_data(env, addr + (4  << DF_BYTE));
4420    pwd->b[4]  = cpu_ldub_data(env, addr + (3  << DF_BYTE));
4421    pwd->b[5]  = cpu_ldub_data(env, addr + (2  << DF_BYTE));
4422    pwd->b[6]  = cpu_ldub_data(env, addr + (1  << DF_BYTE));
4423    pwd->b[7]  = cpu_ldub_data(env, addr + (0  << DF_BYTE));
4424    pwd->b[8]  = cpu_ldub_data(env, addr + (15 << DF_BYTE));
4425    pwd->b[9]  = cpu_ldub_data(env, addr + (14 << DF_BYTE));
4426    pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
4427    pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
4428    pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
4429    pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
4430    pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
4431    pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
4432#endif
4433#endif
4434}
4435
4436void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
4437                     target_ulong addr)
4438{
4439    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4440    MEMOP_IDX(DF_HALF)
4441#if !defined(CONFIG_USER_ONLY)
4442#if !defined(HOST_WORDS_BIGENDIAN)
4443    pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
4444    pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
4445    pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
4446    pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
4447    pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
4448    pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
4449    pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
4450    pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
4451#else
4452    pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
4453    pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
4454    pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
4455    pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
4456    pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
4457    pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
4458    pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
4459    pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
4460#endif
4461#else
4462#if !defined(HOST_WORDS_BIGENDIAN)
4463    pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF));
4464    pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF));
4465    pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF));
4466    pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF));
4467    pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF));
4468    pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF));
4469    pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF));
4470    pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF));
4471#else
4472    pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF));
4473    pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF));
4474    pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF));
4475    pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF));
4476    pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF));
4477    pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF));
4478    pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF));
4479    pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF));
4480#endif
4481#endif
4482}
4483
4484void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd,
4485                     target_ulong addr)
4486{
4487    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4488    MEMOP_IDX(DF_WORD)
4489#if !defined(CONFIG_USER_ONLY)
4490#if !defined(HOST_WORDS_BIGENDIAN)
4491    pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
4492    pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
4493    pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
4494    pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
4495#else
4496    pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
4497    pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
4498    pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
4499    pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
4500#endif
4501#else
4502#if !defined(HOST_WORDS_BIGENDIAN)
4503    pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD));
4504    pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD));
4505    pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD));
4506    pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD));
4507#else
4508    pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD));
4509    pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD));
4510    pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD));
4511    pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD));
4512#endif
4513#endif
4514}
4515
4516void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd,
4517                     target_ulong addr)
4518{
4519    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4520    MEMOP_IDX(DF_DOUBLE)
4521#if !defined(CONFIG_USER_ONLY)
4522    pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC());
4523    pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC());
4524#else
4525    pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE));
4526    pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE));
4527#endif
4528}
4529
4530#define MSA_PAGESPAN(x) \
4531        ((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN/8 - 1) >= TARGET_PAGE_SIZE)
4532
4533static inline void ensure_writable_pages(CPUMIPSState *env,
4534                                         target_ulong addr,
4535                                         int mmu_idx,
4536                                         uintptr_t retaddr)
4537{
4538#if !defined(CONFIG_USER_ONLY)
4539    target_ulong page_addr;
4540    if (unlikely(MSA_PAGESPAN(addr))) {
4541        /* first page */
4542        probe_write(env, addr, 0, mmu_idx, retaddr);
4543        /* second page */
4544        page_addr = (addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
4545        probe_write(env, page_addr, 0, mmu_idx, retaddr);
4546    }
4547#endif
4548}
4549
4550void helper_msa_st_b(CPUMIPSState *env, uint32_t wd,
4551                     target_ulong addr)
4552{
4553    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4554    int mmu_idx = cpu_mmu_index(env, false);
4555
4556    MEMOP_IDX(DF_BYTE)
4557    ensure_writable_pages(env, addr, mmu_idx, GETPC());
4558#if !defined(CONFIG_USER_ONLY)
4559#if !defined(HOST_WORDS_BIGENDIAN)
4560    helper_ret_stb_mmu(env, addr + (0  << DF_BYTE), pwd->b[0],  oi, GETPC());
4561    helper_ret_stb_mmu(env, addr + (1  << DF_BYTE), pwd->b[1],  oi, GETPC());
4562    helper_ret_stb_mmu(env, addr + (2  << DF_BYTE), pwd->b[2],  oi, GETPC());
4563    helper_ret_stb_mmu(env, addr + (3  << DF_BYTE), pwd->b[3],  oi, GETPC());
4564    helper_ret_stb_mmu(env, addr + (4  << DF_BYTE), pwd->b[4],  oi, GETPC());
4565    helper_ret_stb_mmu(env, addr + (5  << DF_BYTE), pwd->b[5],  oi, GETPC());
4566    helper_ret_stb_mmu(env, addr + (6  << DF_BYTE), pwd->b[6],  oi, GETPC());
4567    helper_ret_stb_mmu(env, addr + (7  << DF_BYTE), pwd->b[7],  oi, GETPC());
4568    helper_ret_stb_mmu(env, addr + (8  << DF_BYTE), pwd->b[8],  oi, GETPC());
4569    helper_ret_stb_mmu(env, addr + (9  << DF_BYTE), pwd->b[9],  oi, GETPC());
4570    helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[10], oi, GETPC());
4571    helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[11], oi, GETPC());
4572    helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[12], oi, GETPC());
4573    helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[13], oi, GETPC());
4574    helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[14], oi, GETPC());
4575    helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[15], oi, GETPC());
4576#else
4577    helper_ret_stb_mmu(env, addr + (7  << DF_BYTE), pwd->b[0],  oi, GETPC());
4578    helper_ret_stb_mmu(env, addr + (6  << DF_BYTE), pwd->b[1],  oi, GETPC());
4579    helper_ret_stb_mmu(env, addr + (5  << DF_BYTE), pwd->b[2],  oi, GETPC());
4580    helper_ret_stb_mmu(env, addr + (4  << DF_BYTE), pwd->b[3],  oi, GETPC());
4581    helper_ret_stb_mmu(env, addr + (3  << DF_BYTE), pwd->b[4],  oi, GETPC());
4582    helper_ret_stb_mmu(env, addr + (2  << DF_BYTE), pwd->b[5],  oi, GETPC());
4583    helper_ret_stb_mmu(env, addr + (1  << DF_BYTE), pwd->b[6],  oi, GETPC());
4584    helper_ret_stb_mmu(env, addr + (0  << DF_BYTE), pwd->b[7],  oi, GETPC());
4585    helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[8],  oi, GETPC());
4586    helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[9],  oi, GETPC());
4587    helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[10], oi, GETPC());
4588    helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[11], oi, GETPC());
4589    helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[12], oi, GETPC());
4590    helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[13], oi, GETPC());
4591    helper_ret_stb_mmu(env, addr + (9  << DF_BYTE), pwd->b[14], oi, GETPC());
4592    helper_ret_stb_mmu(env, addr + (8  << DF_BYTE), pwd->b[15], oi, GETPC());
4593#endif
4594#else
4595#if !defined(HOST_WORDS_BIGENDIAN)
4596    cpu_stb_data(env, addr + (0  << DF_BYTE), pwd->b[0]);
4597    cpu_stb_data(env, addr + (1  << DF_BYTE), pwd->b[1]);
4598    cpu_stb_data(env, addr + (2  << DF_BYTE), pwd->b[2]);
4599    cpu_stb_data(env, addr + (3  << DF_BYTE), pwd->b[3]);
4600    cpu_stb_data(env, addr + (4  << DF_BYTE), pwd->b[4]);
4601    cpu_stb_data(env, addr + (5  << DF_BYTE), pwd->b[5]);
4602    cpu_stb_data(env, addr + (6  << DF_BYTE), pwd->b[6]);
4603    cpu_stb_data(env, addr + (7  << DF_BYTE), pwd->b[7]);
4604    cpu_stb_data(env, addr + (8  << DF_BYTE), pwd->b[8]);
4605    cpu_stb_data(env, addr + (9  << DF_BYTE), pwd->b[9]);
4606    cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[10]);
4607    cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[11]);
4608    cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[12]);
4609    cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[13]);
4610    cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[14]);
4611    cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[15]);
4612#else
4613    cpu_stb_data(env, addr + (7  << DF_BYTE), pwd->b[0]);
4614    cpu_stb_data(env, addr + (6  << DF_BYTE), pwd->b[1]);
4615    cpu_stb_data(env, addr + (5  << DF_BYTE), pwd->b[2]);
4616    cpu_stb_data(env, addr + (4  << DF_BYTE), pwd->b[3]);
4617    cpu_stb_data(env, addr + (3  << DF_BYTE), pwd->b[4]);
4618    cpu_stb_data(env, addr + (2  << DF_BYTE), pwd->b[5]);
4619    cpu_stb_data(env, addr + (1  << DF_BYTE), pwd->b[6]);
4620    cpu_stb_data(env, addr + (0  << DF_BYTE), pwd->b[7]);
4621    cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[8]);
4622    cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[9]);
4623    cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[10]);
4624    cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[11]);
4625    cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[12]);
4626    cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[13]);
4627    cpu_stb_data(env, addr + (9  << DF_BYTE), pwd->b[14]);
4628    cpu_stb_data(env, addr + (8  << DF_BYTE), pwd->b[15]);
4629#endif
4630#endif
4631}
4632
4633void helper_msa_st_h(CPUMIPSState *env, uint32_t wd,
4634                     target_ulong addr)
4635{
4636    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4637    int mmu_idx = cpu_mmu_index(env, false);
4638
4639    MEMOP_IDX(DF_HALF)
4640    ensure_writable_pages(env, addr, mmu_idx, GETPC());
4641#if !defined(CONFIG_USER_ONLY)
4642#if !defined(HOST_WORDS_BIGENDIAN)
4643    helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC());
4644    helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], oi, GETPC());
4645    helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[2], oi, GETPC());
4646    helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[3], oi, GETPC());
4647    helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[4], oi, GETPC());
4648    helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[5], oi, GETPC());
4649    helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[6], oi, GETPC());
4650    helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[7], oi, GETPC());
4651#else
4652    helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC());
4653    helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC());
4654    helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC());
4655    helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[3], oi, GETPC());
4656    helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[4], oi, GETPC());
4657    helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[5], oi, GETPC());
4658    helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[6], oi, GETPC());
4659    helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[7], oi, GETPC());
4660#endif
4661#else
4662#if !defined(HOST_WORDS_BIGENDIAN)
4663    cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[0]);
4664    cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[1]);
4665    cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[2]);
4666    cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[3]);
4667    cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[4]);
4668    cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[5]);
4669    cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[6]);
4670    cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[7]);
4671#else
4672    cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[0]);
4673    cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[1]);
4674    cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[2]);
4675    cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[3]);
4676    cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[4]);
4677    cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[5]);
4678    cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[6]);
4679    cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[7]);
4680#endif
4681#endif
4682}
4683
4684void helper_msa_st_w(CPUMIPSState *env, uint32_t wd,
4685                     target_ulong addr)
4686{
4687    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4688    int mmu_idx = cpu_mmu_index(env, false);
4689
4690    MEMOP_IDX(DF_WORD)
4691    ensure_writable_pages(env, addr, mmu_idx, GETPC());
4692#if !defined(CONFIG_USER_ONLY)
4693#if !defined(HOST_WORDS_BIGENDIAN)
4694    helper_ret_stl_mmu(env, addr + (0 << DF_WORD), oi, GETPC(), pwd->w[0]);
4695    helper_ret_stl_mmu(env, addr + (1 << DF_WORD), oi, GETPC(), pwd->w[1]);
4696    helper_ret_stl_mmu(env, addr + (2 << DF_WORD), oi, GETPC(), pwd->w[2]);
4697    helper_ret_stl_mmu(env, addr + (3 << DF_WORD), oi, GETPC(), pwd->w[3]);
4698#else
4699    helper_ret_stl_mmu(env, addr + (1 << DF_WORD), oi, GETPC(), pwd->w[0]);
4700    helper_ret_stl_mmu(env, addr + (0 << DF_WORD), oi, GETPC(), pwd->w[1]);