qemu/target-mips/dsp_helper.c
<<
>>
Prefs
   1/*
   2 * MIPS ASE DSP Instruction emulation helpers for QEMU.
   3 *
   4 * Copyright (c) 2012  Jia Liu <proljc@gmail.com>
   5 *                     Dongxue Zhang <elta.era@gmail.com>
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include "cpu.h"
  21#include "helper.h"
  22
  23/* As the byte ordering doesn't matter, i.e. all columns are treated
  24   identically, these unions can be used directly.  */
  25typedef union {
  26    uint8_t  ub[4];
  27    int8_t   sb[4];
  28    uint16_t uh[2];
  29    int16_t  sh[2];
  30    uint32_t uw[1];
  31    int32_t  sw[1];
  32} DSP32Value;
  33
  34typedef union {
  35    uint8_t  ub[8];
  36    int8_t   sb[8];
  37    uint16_t uh[4];
  38    int16_t  sh[4];
  39    uint32_t uw[2];
  40    int32_t  sw[2];
  41    uint64_t ul[1];
  42    int64_t  sl[1];
  43} DSP64Value;
  44
  45/*** MIPS DSP internal functions begin ***/
  46#define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x)
  47#define MIPSDSP_OVERFLOW(a, b, c, d) (!(!((a ^ b ^ -1) & (a ^ c) & d)))
  48
  49static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
  50                                                CPUMIPSState *env)
  51{
  52    env->active_tc.DSPControl |= (target_ulong)flag << position;
  53}
  54
  55static inline void set_DSPControl_carryflag(uint32_t flag, CPUMIPSState *env)
  56{
  57    env->active_tc.DSPControl |= (target_ulong)flag << 13;
  58}
  59
  60static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
  61{
  62    return (env->active_tc.DSPControl >> 13) & 0x01;
  63}
  64
  65static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env)
  66{
  67  uint32_t filter;
  68
  69  filter = ((0x01 << len) - 1) << 24;
  70  filter = ~filter;
  71
  72  env->active_tc.DSPControl &= filter;
  73  env->active_tc.DSPControl |= (target_ulong)flag << 24;
  74}
  75
  76static inline uint32_t get_DSPControl_24(int len, CPUMIPSState *env)
  77{
  78  uint32_t filter;
  79
  80  filter = (0x01 << len) - 1;
  81
  82  return (env->active_tc.DSPControl >> 24) & filter;
  83}
  84
  85static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env)
  86{
  87    target_ulong dspc;
  88
  89    dspc = env->active_tc.DSPControl;
  90#ifndef TARGET_MIPS64
  91    dspc = dspc & 0xFFFFFFC0;
  92    dspc |= pos;
  93#else
  94    dspc = dspc & 0xFFFFFF80;
  95    dspc |= pos;
  96#endif
  97    env->active_tc.DSPControl = dspc;
  98}
  99
 100static inline uint32_t get_DSPControl_pos(CPUMIPSState *env)
 101{
 102    target_ulong dspc;
 103    uint32_t pos;
 104
 105    dspc = env->active_tc.DSPControl;
 106
 107#ifndef TARGET_MIPS64
 108    pos = dspc & 0x3F;
 109#else
 110    pos = dspc & 0x7F;
 111#endif
 112
 113    return pos;
 114}
 115
 116static inline void set_DSPControl_efi(uint32_t flag, CPUMIPSState *env)
 117{
 118    env->active_tc.DSPControl &= 0xFFFFBFFF;
 119    env->active_tc.DSPControl |= (target_ulong)flag << 14;
 120}
 121
 122#define DO_MIPS_SAT_ABS(size)                                          \
 123static inline int##size##_t mipsdsp_sat_abs##size(int##size##_t a,         \
 124                                                  CPUMIPSState *env)   \
 125{                                                                      \
 126    if (a == INT##size##_MIN) {                                        \
 127        set_DSPControl_overflow_flag(1, 20, env);                      \
 128        return INT##size##_MAX;                                        \
 129    } else {                                                           \
 130        return MIPSDSP_ABS(a);                                         \
 131    }                                                                  \
 132}
 133DO_MIPS_SAT_ABS(8)
 134DO_MIPS_SAT_ABS(16)
 135DO_MIPS_SAT_ABS(32)
 136#undef DO_MIPS_SAT_ABS
 137
 138/* get sum value */
 139static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env)
 140{
 141    int16_t tempI;
 142
 143    tempI = a + b;
 144
 145    if (MIPSDSP_OVERFLOW(a, b, tempI, 0x8000)) {
 146        set_DSPControl_overflow_flag(1, 20, env);
 147    }
 148
 149    return tempI;
 150}
 151
 152static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b,
 153                                          CPUMIPSState *env)
 154{
 155    int16_t tempS;
 156
 157    tempS = a + b;
 158
 159    if (MIPSDSP_OVERFLOW(a, b, tempS, 0x8000)) {
 160        if (a > 0) {
 161            tempS = 0x7FFF;
 162        } else {
 163            tempS = 0x8000;
 164        }
 165        set_DSPControl_overflow_flag(1, 20, env);
 166    }
 167
 168    return tempS;
 169}
 170
 171static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b,
 172                                          CPUMIPSState *env)
 173{
 174    int32_t tempI;
 175
 176    tempI = a + b;
 177
 178    if (MIPSDSP_OVERFLOW(a, b, tempI, 0x80000000)) {
 179        if (a > 0) {
 180            tempI = 0x7FFFFFFF;
 181        } else {
 182            tempI = 0x80000000;
 183        }
 184        set_DSPControl_overflow_flag(1, 20, env);
 185    }
 186
 187    return tempI;
 188}
 189
 190static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
 191{
 192    uint16_t temp;
 193
 194    temp = (uint16_t)a + (uint16_t)b;
 195
 196    if (temp & 0x0100) {
 197        set_DSPControl_overflow_flag(1, 20, env);
 198    }
 199
 200    return temp & 0xFF;
 201}
 202
 203static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b,
 204                                       CPUMIPSState *env)
 205{
 206    uint32_t temp;
 207
 208    temp = (uint32_t)a + (uint32_t)b;
 209
 210    if (temp & 0x00010000) {
 211        set_DSPControl_overflow_flag(1, 20, env);
 212    }
 213
 214    return temp & 0xFFFF;
 215}
 216
 217static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b,
 218                                         CPUMIPSState *env)
 219{
 220    uint8_t  result;
 221    uint16_t temp;
 222
 223    temp = (uint16_t)a + (uint16_t)b;
 224    result = temp & 0xFF;
 225
 226    if (0x0100 & temp) {
 227        result = 0xFF;
 228        set_DSPControl_overflow_flag(1, 20, env);
 229    }
 230
 231    return result;
 232}
 233
 234static inline uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b,
 235                                           CPUMIPSState *env)
 236{
 237    uint16_t result;
 238    uint32_t temp;
 239
 240    temp = (uint32_t)a + (uint32_t)b;
 241    result = temp & 0xFFFF;
 242
 243    if (0x00010000 & temp) {
 244        result = 0xFFFF;
 245        set_DSPControl_overflow_flag(1, 20, env);
 246    }
 247
 248    return result;
 249}
 250
 251static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a,
 252                                            CPUMIPSState *env)
 253{
 254    int64_t temp;
 255    int32_t temp32, temp31, result;
 256    int64_t temp_sum;
 257
 258#ifndef TARGET_MIPS64
 259    temp = ((uint64_t)env->active_tc.HI[acc] << 32) |
 260           (uint64_t)env->active_tc.LO[acc];
 261#else
 262    temp = (uint64_t)env->active_tc.LO[acc];
 263#endif
 264
 265    temp_sum = (int64_t)a + temp;
 266
 267    temp32 = (temp_sum >> 32) & 0x01;
 268    temp31 = (temp_sum >> 31) & 0x01;
 269    result = temp_sum & 0xFFFFFFFF;
 270
 271    /* FIXME
 272       This sat function may wrong, because user manual wrote:
 273       temp127..0 ← temp + ( (signA) || a31..0
 274       if ( temp32 ≠ temp31 ) then
 275           if ( temp32 = 0 ) then
 276               temp31..0 ← 0x80000000
 277           else
 278                temp31..0 ← 0x7FFFFFFF
 279           endif
 280           DSPControlouflag:16+acc ← 1
 281       endif
 282     */
 283    if (temp32 != temp31) {
 284        if (temp32 == 0) {
 285            result = 0x7FFFFFFF;
 286        } else {
 287            result = 0x80000000;
 288        }
 289        set_DSPControl_overflow_flag(1, 16 + acc, env);
 290    }
 291
 292    return result;
 293}
 294
 295/* a[0] is LO, a[1] is HI. */
 296static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret,
 297                                             int32_t ac,
 298                                             int64_t *a,
 299                                             CPUMIPSState *env)
 300{
 301    bool temp64;
 302
 303    ret[0] = env->active_tc.LO[ac] + a[0];
 304    ret[1] = env->active_tc.HI[ac] + a[1];
 305
 306    if (((uint64_t)ret[0] < (uint64_t)env->active_tc.LO[ac]) &&
 307        ((uint64_t)ret[0] < (uint64_t)a[0])) {
 308        ret[1] += 1;
 309    }
 310    temp64 = ret[1] & 1;
 311    if (temp64 != ((ret[0] >> 63) & 0x01)) {
 312        if (temp64) {
 313            ret[0] = (0x01ull << 63);
 314            ret[1] = ~0ull;
 315        } else {
 316            ret[0] = (0x01ull << 63) - 1;
 317            ret[1] = 0x00;
 318        }
 319        set_DSPControl_overflow_flag(1, 16 + ac, env);
 320    }
 321}
 322
 323static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
 324                                             int32_t ac,
 325                                             int64_t *a,
 326                                             CPUMIPSState *env)
 327{
 328    bool temp64;
 329
 330    ret[0] = env->active_tc.LO[ac] - a[0];
 331    ret[1] = env->active_tc.HI[ac] - a[1];
 332
 333    if ((uint64_t)ret[0] > (uint64_t)env->active_tc.LO[ac]) {
 334        ret[1] -= 1;
 335    }
 336    temp64 = ret[1] & 1;
 337    if (temp64 != ((ret[0] >> 63) & 0x01)) {
 338        if (temp64) {
 339            ret[0] = (0x01ull << 63);
 340            ret[1] = ~0ull;
 341        } else {
 342            ret[0] = (0x01ull << 63) - 1;
 343            ret[1] = 0x00;
 344        }
 345        set_DSPControl_overflow_flag(1, 16 + ac, env);
 346    }
 347}
 348
 349static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b,
 350                                          CPUMIPSState *env)
 351{
 352    int32_t temp;
 353
 354    temp = (int32_t)a * (int32_t)b;
 355
 356    if ((temp > (int)0x7FFF) || (temp < (int)0xFFFF8000)) {
 357        set_DSPControl_overflow_flag(1, 21, env);
 358    }
 359    temp &= 0x0000FFFF;
 360
 361    return temp;
 362}
 363
 364static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b)
 365{
 366    return a * b;
 367}
 368
 369static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b)
 370{
 371    return a * b;
 372}
 373
 374static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b,
 375                                                CPUMIPSState *env)
 376{
 377    int32_t temp;
 378
 379    temp = (int32_t)a * (int32_t)b;
 380
 381    if (temp > (int)0x7FFF) {
 382        temp = 0x00007FFF;
 383        set_DSPControl_overflow_flag(1, 21, env);
 384    } else if (temp < (int)0xffff8000) {
 385        temp = 0xFFFF8000;
 386        set_DSPControl_overflow_flag(1, 21, env);
 387    }
 388    temp &= 0x0000FFFF;
 389
 390    return temp;
 391}
 392
 393static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b,
 394                                                         CPUMIPSState *env)
 395{
 396    int32_t temp;
 397
 398    if ((a == 0x8000) && (b == 0x8000)) {
 399        temp = 0x7FFFFFFF;
 400        set_DSPControl_overflow_flag(1, 21, env);
 401    } else {
 402        temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1;
 403    }
 404
 405    return temp;
 406}
 407
 408/* right shift */
 409static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov)
 410{
 411    return a >> mov;
 412}
 413
 414static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov)
 415{
 416    return a >> mov;
 417}
 418
 419static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov)
 420{
 421    return a >> mov;
 422}
 423
 424static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov)
 425{
 426    return a >> mov;
 427}
 428
 429static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov)
 430{
 431    return a >> mov;
 432}
 433
 434static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
 435{
 436    int32_t temp;
 437
 438    temp = (int32_t)a + (int32_t)b;
 439
 440    return (temp >> 1) & 0xFFFF;
 441}
 442
 443/* round right shift */
 444static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b)
 445{
 446    int32_t temp;
 447
 448    temp = (int32_t)a + (int32_t)b;
 449    temp += 1;
 450
 451    return (temp >> 1) & 0xFFFF;
 452}
 453
 454static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b)
 455{
 456    int64_t temp;
 457
 458    temp = (int64_t)a + (int64_t)b;
 459
 460    return (temp >> 1) & 0xFFFFFFFF;
 461}
 462
 463static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b)
 464{
 465    int64_t temp;
 466
 467    temp = (int64_t)a + (int64_t)b;
 468    temp += 1;
 469
 470    return (temp >> 1) & 0xFFFFFFFF;
 471}
 472
 473static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b)
 474{
 475    uint16_t temp;
 476
 477    temp = (uint16_t)a + (uint16_t)b;
 478
 479    return (temp >> 1) & 0x00FF;
 480}
 481
 482static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b)
 483{
 484    uint16_t temp;
 485
 486    temp = (uint16_t)a + (uint16_t)b + 1;
 487
 488    return (temp >> 1) & 0x00FF;
 489}
 490
 491static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b)
 492{
 493    uint16_t temp;
 494
 495    temp = (uint16_t)a - (uint16_t)b;
 496
 497    return (temp >> 1) & 0x00FF;
 498}
 499
 500static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b)
 501{
 502    uint16_t temp;
 503
 504    temp = (uint16_t)a - (uint16_t)b + 1;
 505
 506    return (temp >> 1) & 0x00FF;
 507}
 508
 509/*  128 bits long. p[0] is LO, p[1] is HI. */
 510static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
 511                                                int32_t ac,
 512                                                int32_t shift,
 513                                                CPUMIPSState *env)
 514{
 515    int64_t acc;
 516
 517    acc = ((int64_t)env->active_tc.HI[ac] << 32) |
 518          ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
 519    if (shift == 0) {
 520        p[0] = acc << 1;
 521        p[1] = (acc >> 63) & 0x01;
 522    } else {
 523        p[0] = acc >> (shift - 1);
 524        p[1] = 0;
 525    }
 526}
 527
 528/* 128 bits long. p[0] is LO, p[1] is HI */
 529static inline void mipsdsp_rashift_acc(uint64_t *p,
 530                                       uint32_t ac,
 531                                       uint32_t shift,
 532                                       CPUMIPSState *env)
 533{
 534    uint64_t tempB, tempA;
 535
 536    tempB = env->active_tc.HI[ac];
 537    tempA = env->active_tc.LO[ac];
 538    shift = shift & 0x1F;
 539
 540    if (shift == 0) {
 541        p[1] = tempB;
 542        p[0] = tempA;
 543    } else {
 544        p[0] = (tempB << (64 - shift)) | (tempA >> shift);
 545        p[1] = (int64_t)tempB >> shift;
 546    }
 547}
 548
 549/* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/
 550static inline void mipsdsp_rndrashift_acc(uint64_t *p,
 551                                          uint32_t ac,
 552                                          uint32_t shift,
 553                                          CPUMIPSState *env)
 554{
 555    int64_t tempB, tempA;
 556
 557    tempB = env->active_tc.HI[ac];
 558    tempA = env->active_tc.LO[ac];
 559    shift = shift & 0x3F;
 560
 561    if (shift == 0) {
 562        p[2] = tempB >> 63;
 563        p[1] = (tempB << 1) | (tempA >> 63);
 564        p[0] = tempA << 1;
 565    } else {
 566        p[0] = (tempB << (65 - shift)) | (tempA >> (shift - 1));
 567        p[1] = (int64_t)tempB >> (shift - 1);
 568        if (tempB >= 0) {
 569            p[2] = 0x0;
 570        } else {
 571            p[2] = ~0ull;
 572        }
 573    }
 574}
 575
 576static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b,
 577                                          CPUMIPSState *env)
 578{
 579    int32_t temp;
 580
 581    if ((a == 0x8000) && (b == 0x8000)) {
 582        temp = 0x7FFFFFFF;
 583        set_DSPControl_overflow_flag(1, 16 + ac, env);
 584    } else {
 585        temp = ((uint32_t)a * (uint32_t)b) << 1;
 586    }
 587
 588    return temp;
 589}
 590
 591static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b,
 592                                          CPUMIPSState *env)
 593{
 594    uint64_t temp;
 595
 596    if ((a == 0x80000000) && (b == 0x80000000)) {
 597        temp = (0x01ull << 63) - 1;
 598        set_DSPControl_overflow_flag(1, 16 + ac, env);
 599    } else {
 600        temp = ((uint64_t)a * (uint64_t)b) << 1;
 601    }
 602
 603    return temp;
 604}
 605
 606static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b)
 607{
 608    return (uint16_t)a * (uint16_t)b;
 609}
 610
 611static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b,
 612                                          CPUMIPSState *env)
 613{
 614    uint32_t tempI;
 615
 616    tempI = (uint32_t)a * (uint32_t)b;
 617    if (tempI > 0x0000FFFF) {
 618        tempI = 0x0000FFFF;
 619        set_DSPControl_overflow_flag(1, 21, env);
 620    }
 621
 622    return tempI & 0x0000FFFF;
 623}
 624
 625static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b)
 626{
 627    return (uint64_t)a * (uint64_t)b;
 628}
 629
 630static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b,
 631                                                 CPUMIPSState *env)
 632{
 633    uint32_t temp;
 634
 635    if ((a == 0x8000) && (b == 0x8000)) {
 636        temp = 0x7FFF0000;
 637        set_DSPControl_overflow_flag(1, 21, env);
 638    } else {
 639        temp = (a * b) << 1;
 640        temp = temp + 0x00008000;
 641    }
 642
 643    return (temp & 0xFFFF0000) >> 16;
 644}
 645
 646static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b,
 647                                                CPUMIPSState *env)
 648{
 649    int32_t temp;
 650
 651    if ((a == 0x8000) && (b == 0x8000)) {
 652        temp = 0x7FFF0000;
 653        set_DSPControl_overflow_flag(1, 21, env);
 654    } else {
 655        temp = ((uint32_t)a * (uint32_t)b);
 656        temp = temp << 1;
 657    }
 658
 659    return (temp >> 16) & 0x0000FFFF;
 660}
 661
 662static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a,
 663                                                   CPUMIPSState *env)
 664{
 665    int64_t temp;
 666
 667    temp = (int32_t)a + 0x00008000;
 668
 669    if (a > (int)0x7fff8000) {
 670        temp = 0x7FFFFFFF;
 671        set_DSPControl_overflow_flag(1, 22, env);
 672    }
 673
 674    return (temp >> 16) & 0xFFFF;
 675}
 676
 677static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
 678                                                    CPUMIPSState *env)
 679{
 680    uint16_t mag;
 681    uint32_t sign;
 682
 683    sign = (a >> 15) & 0x01;
 684    mag = a & 0x7FFF;
 685
 686    if (sign == 0) {
 687        if (mag > 0x7F80) {
 688            set_DSPControl_overflow_flag(1, 22, env);
 689            return 0xFF;
 690        } else {
 691            return (mag >> 7) & 0xFFFF;
 692        }
 693    } else {
 694        set_DSPControl_overflow_flag(1, 22, env);
 695        return 0x00;
 696    }
 697}
 698
 699static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env)
 700{
 701    uint8_t sign;
 702    uint8_t discard;
 703
 704    if (s == 0) {
 705        return a;
 706    } else {
 707        sign = (a >> 7) & 0x01;
 708        if (sign != 0) {
 709            discard = (((0x01 << (8 - s)) - 1) << s) |
 710                      ((a >> (6 - (s - 1))) & ((0x01 << s) - 1));
 711        } else {
 712            discard = a >> (6 - (s - 1));
 713        }
 714
 715        if (discard != 0x00) {
 716            set_DSPControl_overflow_flag(1, 22, env);
 717        }
 718        return a << s;
 719    }
 720}
 721
 722static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
 723                                        CPUMIPSState *env)
 724{
 725    uint8_t  sign;
 726    uint16_t discard;
 727
 728    if (s == 0) {
 729        return a;
 730    } else {
 731        sign = (a >> 15) & 0x01;
 732        if (sign != 0) {
 733            discard = (((0x01 << (16 - s)) - 1) << s) |
 734                      ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
 735        } else {
 736            discard = a >> (14 - (s - 1));
 737        }
 738
 739        if ((discard != 0x0000) && (discard != 0xFFFF)) {
 740            set_DSPControl_overflow_flag(1, 22, env);
 741        }
 742        return a << s;
 743    }
 744}
 745
 746
 747static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s,
 748                                        CPUMIPSState *env)
 749{
 750    uint32_t discard;
 751
 752    if (s == 0) {
 753        return a;
 754    } else {
 755        discard = (int32_t)a >> (31 - (s - 1));
 756
 757        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
 758            set_DSPControl_overflow_flag(1, 22, env);
 759        }
 760        return a << s;
 761    }
 762}
 763
 764static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s,
 765                                            CPUMIPSState *env)
 766{
 767    uint8_t  sign;
 768    uint16_t discard;
 769
 770    if (s == 0) {
 771        return a;
 772    } else {
 773        sign = (a >> 15) & 0x01;
 774        if (sign != 0) {
 775            discard = (((0x01 << (16 - s)) - 1) << s) |
 776                      ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
 777        } else {
 778            discard = a >> (14 - (s - 1));
 779        }
 780
 781        if ((discard != 0x0000) && (discard != 0xFFFF)) {
 782            set_DSPControl_overflow_flag(1, 22, env);
 783            return (sign == 0) ? 0x7FFF : 0x8000;
 784        } else {
 785            return a << s;
 786        }
 787    }
 788}
 789
 790static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s,
 791                                            CPUMIPSState *env)
 792{
 793    uint8_t  sign;
 794    uint32_t discard;
 795
 796    if (s == 0) {
 797        return a;
 798    } else {
 799        sign = (a >> 31) & 0x01;
 800        if (sign != 0) {
 801            discard = (((0x01 << (32 - s)) - 1) << s) |
 802                      ((a >> (30 - (s - 1))) & ((0x01 << s) - 1));
 803        } else {
 804            discard = a >> (30 - (s - 1));
 805        }
 806
 807        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
 808            set_DSPControl_overflow_flag(1, 22, env);
 809            return (sign == 0) ? 0x7FFFFFFF : 0x80000000;
 810        } else {
 811            return a << s;
 812        }
 813    }
 814}
 815
 816static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a, uint8_t s)
 817{
 818    uint32_t temp;
 819
 820    if (s == 0) {
 821        temp = (uint32_t)a << 1;
 822    } else {
 823        temp = (int32_t)(int8_t)a >> (s - 1);
 824    }
 825
 826    return (temp + 1) >> 1;
 827}
 828
 829static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s)
 830{
 831    uint32_t temp;
 832
 833    if (s == 0) {
 834        temp = (uint32_t)a << 1;
 835    } else {
 836        temp = (int32_t)(int16_t)a >> (s - 1);
 837    }
 838
 839    return (temp + 1) >> 1;
 840}
 841
 842static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s)
 843{
 844    int64_t temp;
 845
 846    if (s == 0) {
 847        temp = (uint64_t)a << 1;
 848    } else {
 849        temp = (int64_t)(int32_t)a >> (s - 1);
 850    }
 851    temp += 1;
 852
 853    return (temp >> 1) & 0xFFFFFFFFull;
 854}
 855
 856static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env)
 857{
 858    int16_t  temp;
 859
 860    temp = a - b;
 861    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
 862        set_DSPControl_overflow_flag(1, 20, env);
 863    }
 864
 865    return temp;
 866}
 867
 868static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b,
 869                                         CPUMIPSState *env)
 870{
 871    int16_t  temp;
 872
 873    temp = a - b;
 874    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
 875        if (a > 0) {
 876            temp = 0x7FFF;
 877        } else {
 878            temp = 0x8000;
 879        }
 880        set_DSPControl_overflow_flag(1, 20, env);
 881    }
 882
 883    return temp;
 884}
 885
 886static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b,
 887                                         CPUMIPSState *env)
 888{
 889    int32_t  temp;
 890
 891    temp = a - b;
 892    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
 893        if (a > 0) {
 894            temp = 0x7FFFFFFF;
 895        } else {
 896            temp = 0x80000000;
 897        }
 898        set_DSPControl_overflow_flag(1, 20, env);
 899    }
 900
 901    return temp & 0xFFFFFFFFull;
 902}
 903
 904static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b)
 905{
 906    int32_t  temp;
 907
 908    temp = (int32_t)a - (int32_t)b;
 909
 910    return (temp >> 1) & 0x0000FFFF;
 911}
 912
 913static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b)
 914{
 915    int32_t  temp;
 916
 917    temp = (int32_t)a - (int32_t)b;
 918    temp += 1;
 919
 920    return (temp >> 1) & 0x0000FFFF;
 921}
 922
 923static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b)
 924{
 925    int64_t  temp;
 926
 927    temp = (int64_t)a - (int64_t)b;
 928
 929    return (temp >> 1) & 0xFFFFFFFFull;
 930}
 931
 932static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b)
 933{
 934    int64_t  temp;
 935
 936    temp = (int64_t)a - (int64_t)b;
 937    temp += 1;
 938
 939    return (temp >> 1) & 0xFFFFFFFFull;
 940}
 941
 942static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b,
 943                                           CPUMIPSState *env)
 944{
 945    uint8_t  temp16;
 946    uint32_t temp;
 947
 948    temp = (uint32_t)a - (uint32_t)b;
 949    temp16 = (temp >> 16) & 0x01;
 950    if (temp16 == 1) {
 951        set_DSPControl_overflow_flag(1, 20, env);
 952    }
 953    return temp & 0x0000FFFF;
 954}
 955
 956static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b,
 957                                                  CPUMIPSState *env)
 958{
 959    uint8_t  temp16;
 960    uint32_t temp;
 961
 962    temp   = (uint32_t)a - (uint32_t)b;
 963    temp16 = (temp >> 16) & 0x01;
 964
 965    if (temp16 == 1) {
 966        temp = 0x0000;
 967        set_DSPControl_overflow_flag(1, 20, env);
 968    }
 969
 970    return temp & 0x0000FFFF;
 971}
 972
 973static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
 974{
 975    uint8_t  temp8;
 976    uint16_t temp;
 977
 978    temp = (uint16_t)a - (uint16_t)b;
 979    temp8 = (temp >> 8) & 0x01;
 980    if (temp8 == 1) {
 981        set_DSPControl_overflow_flag(1, 20, env);
 982    }
 983
 984    return temp & 0x00FF;
 985}
 986
 987static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env)
 988{
 989    uint8_t  temp8;
 990    uint16_t temp;
 991
 992    temp = (uint16_t)a - (uint16_t)b;
 993    temp8 = (temp >> 8) & 0x01;
 994    if (temp8 == 1) {
 995        temp = 0x00;
 996        set_DSPControl_overflow_flag(1, 20, env);
 997    }
 998
 999    return temp & 0x00FF;
1000}
1001
1002static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
1003{
1004    int32_t temp;
1005
1006    temp = a - b;
1007    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
1008        set_DSPControl_overflow_flag(1, 20, env);
1009    }
1010
1011    return temp;
1012}
1013
1014static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env)
1015{
1016    int32_t temp;
1017
1018    temp = a + b;
1019
1020    if (MIPSDSP_OVERFLOW(a, b, temp, 0x80000000)) {
1021        set_DSPControl_overflow_flag(1, 20, env);
1022    }
1023
1024    return temp;
1025}
1026
1027static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b)
1028{
1029    return a == b;
1030}
1031
1032static inline int32_t mipsdsp_cmp_le(int32_t a, int32_t b)
1033{
1034    return a <= b;
1035}
1036
1037static inline int32_t mipsdsp_cmp_lt(int32_t a, int32_t b)
1038{
1039    return a < b;
1040}
1041
1042static inline int32_t mipsdsp_cmpu_eq(uint32_t a, uint32_t b)
1043{
1044    return a == b;
1045}
1046
1047static inline int32_t mipsdsp_cmpu_le(uint32_t a, uint32_t b)
1048{
1049    return a <= b;
1050}
1051
1052static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b)
1053{
1054    return a < b;
1055}
1056/*** MIPS DSP internal functions end ***/
1057
1058#define MIPSDSP_LHI 0xFFFFFFFF00000000ull
1059#define MIPSDSP_LLO 0x00000000FFFFFFFFull
1060#define MIPSDSP_HI  0xFFFF0000
1061#define MIPSDSP_LO  0x0000FFFF
1062#define MIPSDSP_Q3  0xFF000000
1063#define MIPSDSP_Q2  0x00FF0000
1064#define MIPSDSP_Q1  0x0000FF00
1065#define MIPSDSP_Q0  0x000000FF
1066
1067#define MIPSDSP_SPLIT32_8(num, a, b, c, d)  \
1068    do {                                    \
1069        a = (num >> 24) & MIPSDSP_Q0;       \
1070        b = (num >> 16) & MIPSDSP_Q0;       \
1071        c = (num >> 8) & MIPSDSP_Q0;        \
1072        d = num & MIPSDSP_Q0;               \
1073    } while (0)
1074
1075#define MIPSDSP_SPLIT32_16(num, a, b)       \
1076    do {                                    \
1077        a = (num >> 16) & MIPSDSP_LO;       \
1078        b = num & MIPSDSP_LO;               \
1079    } while (0)
1080
1081#define MIPSDSP_RETURN32_8(a, b, c, d)  ((target_long)(int32_t) \
1082                                         (((uint32_t)a << 24) | \
1083                                         (((uint32_t)b << 16) | \
1084                                         (((uint32_t)c << 8) |  \
1085                                          ((uint32_t)d & 0xFF)))))
1086#define MIPSDSP_RETURN32_16(a, b)       ((target_long)(int32_t) \
1087                                         (((uint32_t)a << 16) | \
1088                                          ((uint32_t)b & 0xFFFF)))
1089
1090#ifdef TARGET_MIPS64
1091#define MIPSDSP_SPLIT64_16(num, a, b, c, d)  \
1092    do {                                     \
1093        a = (num >> 48) & MIPSDSP_LO;        \
1094        b = (num >> 32) & MIPSDSP_LO;        \
1095        c = (num >> 16) & MIPSDSP_LO;        \
1096        d = num & MIPSDSP_LO;                \
1097    } while (0)
1098
1099#define MIPSDSP_SPLIT64_32(num, a, b)       \
1100    do {                                    \
1101        a = (num >> 32) & MIPSDSP_LLO;      \
1102        b = num & MIPSDSP_LLO;              \
1103    } while (0)
1104
1105#define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)a << 48) | \
1106                                         ((uint64_t)b << 32) | \
1107                                         ((uint64_t)c << 16) | \
1108                                         (uint64_t)d)
1109#define MIPSDSP_RETURN64_32(a, b)       (((uint64_t)a << 32) | (uint64_t)b)
1110#endif
1111
1112/** DSP Arithmetic Sub-class insns **/
1113#define MIPSDSP32_UNOP_ENV(name, func, element)                            \
1114target_ulong helper_##name(target_ulong rt, CPUMIPSState *env)             \
1115{                                                                          \
1116    DSP32Value dt;                                                         \
1117    unsigned int i, n;                                                     \
1118                                                                           \
1119    n = sizeof(DSP32Value) / sizeof(dt.element[0]);                        \
1120    dt.sw[0] = rt;                                                         \
1121                                                                           \
1122    for (i = 0; i < n; i++) {                                              \
1123        dt.element[i] = mipsdsp_##func(dt.element[i], env);                \
1124    }                                                                      \
1125                                                                           \
1126    return (target_long)dt.sw[0];                                          \
1127}
1128MIPSDSP32_UNOP_ENV(absq_s_ph, sat_abs16, sh)
1129MIPSDSP32_UNOP_ENV(absq_s_qb, sat_abs8, sb)
1130MIPSDSP32_UNOP_ENV(absq_s_w, sat_abs32, sw)
1131#undef MIPSDSP32_UNOP_ENV
1132
1133#if defined(TARGET_MIPS64)
1134#define MIPSDSP64_UNOP_ENV(name, func, element)                            \
1135target_ulong helper_##name(target_ulong rt, CPUMIPSState *env)             \
1136{                                                                          \
1137    DSP64Value dt;                                                         \
1138    unsigned int i, n;                                                     \
1139                                                                           \
1140    n = sizeof(DSP64Value) / sizeof(dt.element[0]);                        \
1141    dt.sl[0] = rt;                                                         \
1142                                                                           \
1143    for (i = 0; i < n; i++) {                                              \
1144        dt.element[i] = mipsdsp_##func(dt.element[i], env);                \
1145    }                                                                      \
1146                                                                           \
1147    return dt.sl[0];                                                       \
1148}
1149MIPSDSP64_UNOP_ENV(absq_s_ob, sat_abs8, sb)
1150MIPSDSP64_UNOP_ENV(absq_s_qh, sat_abs16, sh)
1151MIPSDSP64_UNOP_ENV(absq_s_pw, sat_abs32, sw)
1152#undef MIPSDSP64_UNOP_ENV
1153#endif
1154
1155#define MIPSDSP32_BINOP(name, func, element)                               \
1156target_ulong helper_##name(target_ulong rs, target_ulong rt)               \
1157{                                                                          \
1158    DSP32Value ds, dt;                                                     \
1159    unsigned int i, n;                                                     \
1160                                                                           \
1161    n = sizeof(DSP32Value) / sizeof(ds.element[0]);                        \
1162    ds.sw[0] = rs;                                                         \
1163    dt.sw[0] = rt;                                                         \
1164                                                                           \
1165    for (i = 0; i < n; i++) {                                              \
1166        ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]);      \
1167    }                                                                      \
1168                                                                           \
1169    return (target_long)ds.sw[0];                                          \
1170}
1171MIPSDSP32_BINOP(addqh_ph, rshift1_add_q16, sh);
1172MIPSDSP32_BINOP(addqh_r_ph, rrshift1_add_q16, sh);
1173MIPSDSP32_BINOP(addqh_r_w, rrshift1_add_q32, sw);
1174MIPSDSP32_BINOP(addqh_w, rshift1_add_q32, sw);
1175MIPSDSP32_BINOP(adduh_qb, rshift1_add_u8, ub);
1176MIPSDSP32_BINOP(adduh_r_qb, rrshift1_add_u8, ub);
1177MIPSDSP32_BINOP(subqh_ph, rshift1_sub_q16, sh);
1178MIPSDSP32_BINOP(subqh_r_ph, rrshift1_sub_q16, sh);
1179MIPSDSP32_BINOP(subqh_r_w, rrshift1_sub_q32, sw);
1180MIPSDSP32_BINOP(subqh_w, rshift1_sub_q32, sw);
1181#undef MIPSDSP32_BINOP
1182
1183#define MIPSDSP32_BINOP_ENV(name, func, element)                           \
1184target_ulong helper_##name(target_ulong rs, target_ulong rt,               \
1185                           CPUMIPSState *env)                              \
1186{                                                                          \
1187    DSP32Value ds, dt;                                                     \
1188    unsigned int i, n;                                                     \
1189                                                                           \
1190    n = sizeof(DSP32Value) / sizeof(ds.element[0]);                        \
1191    ds.sw[0] = rs;                                                         \
1192    dt.sw[0] = rt;                                                         \
1193                                                                           \
1194    for (i = 0 ; i < n ; i++) {                                            \
1195        ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
1196    }                                                                      \
1197                                                                           \
1198    return (target_long)ds.sw[0];                                          \
1199}
1200MIPSDSP32_BINOP_ENV(addq_ph, add_i16, sh)
1201MIPSDSP32_BINOP_ENV(addq_s_ph, sat_add_i16, sh)
1202MIPSDSP32_BINOP_ENV(addq_s_w, sat_add_i32, sw);
1203MIPSDSP32_BINOP_ENV(addu_ph, add_u16, sh)
1204MIPSDSP32_BINOP_ENV(addu_qb, add_u8, ub);
1205MIPSDSP32_BINOP_ENV(addu_s_ph, sat_add_u16, sh)
1206MIPSDSP32_BINOP_ENV(addu_s_qb, sat_add_u8, ub);
1207MIPSDSP32_BINOP_ENV(subq_ph, sub_i16, sh);
1208MIPSDSP32_BINOP_ENV(subq_s_ph, sat16_sub, sh);
1209MIPSDSP32_BINOP_ENV(subq_s_w, sat32_sub, sw);
1210MIPSDSP32_BINOP_ENV(subu_ph, sub_u16_u16, sh);
1211MIPSDSP32_BINOP_ENV(subu_qb, sub_u8, ub);
1212MIPSDSP32_BINOP_ENV(subu_s_ph, satu16_sub_u16_u16, sh);
1213MIPSDSP32_BINOP_ENV(subu_s_qb, satu8_sub, ub);
1214#undef MIPSDSP32_BINOP_ENV
1215
1216#ifdef TARGET_MIPS64
1217#define MIPSDSP64_BINOP(name, func, element)                               \
1218target_ulong helper_##name(target_ulong rs, target_ulong rt)               \
1219{                                                                          \
1220    DSP64Value ds, dt;                                                     \
1221    unsigned int i, n;                                                     \
1222                                                                           \
1223    n = sizeof(DSP64Value) / sizeof(ds.element[0]);                        \
1224    ds.sl[0] = rs;                                                         \
1225    dt.sl[0] = rt;                                                         \
1226                                                                           \
1227    for (i = 0 ; i < n ; i++) {                                            \
1228        ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]);      \
1229    }                                                                      \
1230                                                                           \
1231    return ds.sl[0];                                                       \
1232}
1233MIPSDSP64_BINOP(adduh_ob, rshift1_add_u8, ub);
1234MIPSDSP64_BINOP(adduh_r_ob, rrshift1_add_u8, ub);
1235MIPSDSP64_BINOP(subuh_ob, rshift1_sub_u8, ub);
1236MIPSDSP64_BINOP(subuh_r_ob, rrshift1_sub_u8, ub);
1237#undef MIPSDSP64_BINOP
1238
1239#define MIPSDSP64_BINOP_ENV(name, func, element)                           \
1240target_ulong helper_##name(target_ulong rs, target_ulong rt,               \
1241                           CPUMIPSState *env)                              \
1242{                                                                          \
1243    DSP64Value ds, dt;                                                     \
1244    unsigned int i, n;                                                     \
1245                                                                           \
1246    n = sizeof(DSP64Value) / sizeof(ds.element[0]);                        \
1247    ds.sl[0] = rs;                                                         \
1248    dt.sl[0] = rt;                                                         \
1249                                                                           \
1250    for (i = 0 ; i < n ; i++) {                                            \
1251        ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
1252    }                                                                      \
1253                                                                           \
1254    return ds.sl[0];                                                       \
1255}
1256MIPSDSP64_BINOP_ENV(addq_pw, add_i32, sw);
1257MIPSDSP64_BINOP_ENV(addq_qh, add_i16, sh);
1258MIPSDSP64_BINOP_ENV(addq_s_pw, sat_add_i32, sw);
1259MIPSDSP64_BINOP_ENV(addq_s_qh, sat_add_i16, sh);
1260MIPSDSP64_BINOP_ENV(addu_ob, add_u8, uh);
1261MIPSDSP64_BINOP_ENV(addu_qh, add_u16, uh);
1262MIPSDSP64_BINOP_ENV(addu_s_ob, sat_add_u8, uh);
1263MIPSDSP64_BINOP_ENV(addu_s_qh, sat_add_u16, uh);
1264MIPSDSP64_BINOP_ENV(subq_pw, sub32, sw);
1265MIPSDSP64_BINOP_ENV(subq_qh, sub_i16, sh);
1266MIPSDSP64_BINOP_ENV(subq_s_pw, sat32_sub, sw);
1267MIPSDSP64_BINOP_ENV(subq_s_qh, sat16_sub, sh);
1268MIPSDSP64_BINOP_ENV(subu_ob, sub_u8, uh);
1269MIPSDSP64_BINOP_ENV(subu_qh, sub_u16_u16, uh);
1270MIPSDSP64_BINOP_ENV(subu_s_ob, satu8_sub, uh);
1271MIPSDSP64_BINOP_ENV(subu_s_qh, satu16_sub_u16_u16, uh);
1272#undef MIPSDSP64_BINOP_ENV
1273
1274#endif
1275
1276#define SUBUH_QB(name, var) \
1277target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \
1278{                                                                 \
1279    uint8_t rs3, rs2, rs1, rs0;                                   \
1280    uint8_t rt3, rt2, rt1, rt0;                                   \
1281    uint8_t tempD, tempC, tempB, tempA;                           \
1282                                                                  \
1283    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                    \
1284    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                    \
1285                                                                  \
1286    tempD = ((uint16_t)rs3 - (uint16_t)rt3 + var) >> 1;           \
1287    tempC = ((uint16_t)rs2 - (uint16_t)rt2 + var) >> 1;           \
1288    tempB = ((uint16_t)rs1 - (uint16_t)rt1 + var) >> 1;           \
1289    tempA = ((uint16_t)rs0 - (uint16_t)rt0 + var) >> 1;           \
1290                                                                  \
1291    return ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |    \
1292        ((uint32_t)tempB << 8) | ((uint32_t)tempA);               \
1293}
1294
1295SUBUH_QB(subuh, 0);
1296SUBUH_QB(subuh_r, 1);
1297
1298#undef SUBUH_QB
1299
1300target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
1301{
1302    uint64_t temp, tempRs, tempRt;
1303    int32_t flag;
1304
1305    tempRs = (uint64_t)rs & MIPSDSP_LLO;
1306    tempRt = (uint64_t)rt & MIPSDSP_LLO;
1307
1308    temp = tempRs + tempRt;
1309    flag = (temp & 0x0100000000ull) >> 32;
1310    set_DSPControl_carryflag(flag, env);
1311
1312    return (target_long)(int32_t)(temp & MIPSDSP_LLO);
1313}
1314
1315target_ulong helper_addwc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
1316{
1317    uint32_t rd;
1318    int32_t temp32, temp31;
1319    int64_t tempL;
1320
1321    tempL = (int64_t)(int32_t)rs + (int64_t)(int32_t)rt +
1322        get_DSPControl_carryflag(env);
1323    temp31 = (tempL >> 31) & 0x01;
1324    temp32 = (tempL >> 32) & 0x01;
1325
1326    if (temp31 != temp32) {
1327        set_DSPControl_overflow_flag(1, 20, env);
1328    }
1329
1330    rd = tempL & MIPSDSP_LLO;
1331
1332    return (target_long)(int32_t)rd;
1333}
1334
1335target_ulong helper_modsub(target_ulong rs, target_ulong rt)
1336{
1337    int32_t decr;
1338    uint16_t lastindex;
1339    target_ulong rd;
1340
1341    decr = rt & MIPSDSP_Q0;
1342    lastindex = (rt >> 8) & MIPSDSP_LO;
1343
1344    if ((rs & MIPSDSP_LLO) == 0x00000000) {
1345        rd = (target_ulong)lastindex;
1346    } else {
1347        rd = rs - decr;
1348    }
1349
1350    return rd;
1351}
1352
1353target_ulong helper_raddu_w_qb(target_ulong rs)
1354{
1355    target_ulong ret = 0;
1356    DSP32Value ds;
1357    unsigned int i;
1358
1359    ds.uw[0] = rs;
1360    for (i = 0; i < 4; i++) {
1361        ret += ds.ub[i];
1362    }
1363    return ret;
1364}
1365
1366#if defined(TARGET_MIPS64)
1367target_ulong helper_raddu_l_ob(target_ulong rs)
1368{
1369    target_ulong ret = 0;
1370    DSP64Value ds;
1371    unsigned int i;
1372
1373    ds.ul[0] = rs;
1374    for (i = 0; i < 8; i++) {
1375        ret += ds.ub[i];
1376    }
1377    return ret;
1378}
1379#endif
1380
1381#define PRECR_QB_PH(name, a, b)\
1382target_ulong helper_##name##_qb_ph(target_ulong rs, target_ulong rt) \
1383{                                                                    \
1384    uint8_t tempD, tempC, tempB, tempA;                              \
1385                                                                     \
1386    tempD = (rs >> a) & MIPSDSP_Q0;                                  \
1387    tempC = (rs >> b) & MIPSDSP_Q0;                                  \
1388    tempB = (rt >> a) & MIPSDSP_Q0;                                  \
1389    tempA = (rt >> b) & MIPSDSP_Q0;                                  \
1390                                                                     \
1391    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);           \
1392}
1393
1394PRECR_QB_PH(precr, 16, 0);
1395PRECR_QB_PH(precrq, 24, 8);
1396
1397#undef PRECR_QB_OH
1398
1399target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs,
1400                                   target_ulong rt)
1401{
1402    uint16_t tempB, tempA;
1403
1404    tempB = ((int32_t)rt >> sa) & MIPSDSP_LO;
1405    tempA = ((int32_t)rs >> sa) & MIPSDSP_LO;
1406
1407    return MIPSDSP_RETURN32_16(tempB, tempA);
1408}
1409
1410target_ulong helper_precr_sra_r_ph_w(uint32_t sa,
1411                                     target_ulong rs, target_ulong rt)
1412{
1413    uint64_t tempB, tempA;
1414
1415    /* If sa = 0, then (sa - 1) = -1 will case shift error, so we need else. */
1416    if (sa == 0) {
1417        tempB = (rt & MIPSDSP_LO) << 1;
1418        tempA = (rs & MIPSDSP_LO) << 1;
1419    } else {
1420        tempB = ((int32_t)rt >> (sa - 1)) + 1;
1421        tempA = ((int32_t)rs >> (sa - 1)) + 1;
1422    }
1423    rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO);
1424
1425    return (target_long)(int32_t)rt;
1426}
1427
1428target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt)
1429{
1430    uint16_t tempB, tempA;
1431
1432    tempB = (rs & MIPSDSP_HI) >> 16;
1433    tempA = (rt & MIPSDSP_HI) >> 16;
1434
1435    return MIPSDSP_RETURN32_16(tempB, tempA);
1436}
1437
1438target_ulong helper_precrq_rs_ph_w(target_ulong rs, target_ulong rt,
1439                                   CPUMIPSState *env)
1440{
1441    uint16_t tempB, tempA;
1442
1443    tempB = mipsdsp_trunc16_sat16_round(rs, env);
1444    tempA = mipsdsp_trunc16_sat16_round(rt, env);
1445
1446    return MIPSDSP_RETURN32_16(tempB, tempA);
1447}
1448
1449#if defined(TARGET_MIPS64)
1450target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt)
1451{
1452    uint8_t rs6, rs4, rs2, rs0;
1453    uint8_t rt6, rt4, rt2, rt0;
1454    uint64_t temp;
1455
1456    rs6 = (rs >> 48) & MIPSDSP_Q0;
1457    rs4 = (rs >> 32) & MIPSDSP_Q0;
1458    rs2 = (rs >> 16) & MIPSDSP_Q0;
1459    rs0 = rs & MIPSDSP_Q0;
1460    rt6 = (rt >> 48) & MIPSDSP_Q0;
1461    rt4 = (rt >> 32) & MIPSDSP_Q0;
1462    rt2 = (rt >> 16) & MIPSDSP_Q0;
1463    rt0 = rt & MIPSDSP_Q0;
1464
1465    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
1466           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
1467           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
1468           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
1469
1470    return temp;
1471}
1472
1473#define PRECR_QH_PW(name, var) \
1474target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \
1475                                    uint32_t sa)                      \
1476{                                                                     \
1477    uint16_t rs3, rs2, rs1, rs0;                                      \
1478    uint16_t rt3, rt2, rt1, rt0;                                      \
1479    uint16_t tempD, tempC, tempB, tempA;                              \
1480                                                                      \
1481    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);                       \
1482    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                       \
1483                                                                      \
1484    /* When sa = 0, we use rt2, rt0, rs2, rs0;                        \
1485     * when sa != 0, we use rt3, rt1, rs3, rs1. */                    \
1486    if (sa == 0) {                                                    \
1487        tempD = rt2 << var;                                           \
1488        tempC = rt0 << var;                                           \
1489        tempB = rs2 << var;                                           \
1490        tempA = rs0 << var;                                           \
1491    } else {                                                          \
1492        tempD = (((int16_t)rt3 >> sa) + var) >> var;                  \
1493        tempC = (((int16_t)rt1 >> sa) + var) >> var;                  \
1494        tempB = (((int16_t)rs3 >> sa) + var) >> var;                  \
1495        tempA = (((int16_t)rs1 >> sa) + var) >> var;                  \
1496    }                                                                 \
1497                                                                      \
1498    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);           \
1499}
1500
1501PRECR_QH_PW(sra, 0);
1502PRECR_QH_PW(sra_r, 1);
1503
1504#undef PRECR_QH_PW
1505
1506target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt)
1507{
1508    uint8_t rs6, rs4, rs2, rs0;
1509    uint8_t rt6, rt4, rt2, rt0;
1510    uint64_t temp;
1511
1512    rs6 = (rs >> 56) & MIPSDSP_Q0;
1513    rs4 = (rs >> 40) & MIPSDSP_Q0;
1514    rs2 = (rs >> 24) & MIPSDSP_Q0;
1515    rs0 = (rs >> 8) & MIPSDSP_Q0;
1516    rt6 = (rt >> 56) & MIPSDSP_Q0;
1517    rt4 = (rt >> 40) & MIPSDSP_Q0;
1518    rt2 = (rt >> 24) & MIPSDSP_Q0;
1519    rt0 = (rt >> 8) & MIPSDSP_Q0;
1520
1521    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
1522           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
1523           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
1524           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
1525
1526    return temp;
1527}
1528
1529target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt)
1530{
1531    uint16_t tempD, tempC, tempB, tempA;
1532
1533    tempD = (rs >> 48) & MIPSDSP_LO;
1534    tempC = (rs >> 16) & MIPSDSP_LO;
1535    tempB = (rt >> 48) & MIPSDSP_LO;
1536    tempA = (rt >> 16) & MIPSDSP_LO;
1537
1538    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1539}
1540
1541target_ulong helper_precrq_rs_qh_pw(target_ulong rs, target_ulong rt,
1542                                    CPUMIPSState *env)
1543{
1544    uint32_t rs2, rs0;
1545    uint32_t rt2, rt0;
1546    uint16_t tempD, tempC, tempB, tempA;
1547
1548    rs2 = (rs >> 32) & MIPSDSP_LLO;
1549    rs0 = rs & MIPSDSP_LLO;
1550    rt2 = (rt >> 32) & MIPSDSP_LLO;
1551    rt0 = rt & MIPSDSP_LLO;
1552
1553    tempD = mipsdsp_trunc16_sat16_round(rs2, env);
1554    tempC = mipsdsp_trunc16_sat16_round(rs0, env);
1555    tempB = mipsdsp_trunc16_sat16_round(rt2, env);
1556    tempA = mipsdsp_trunc16_sat16_round(rt0, env);
1557
1558    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1559}
1560
1561target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt)
1562{
1563    uint32_t tempB, tempA;
1564
1565    tempB = (rs >> 32) & MIPSDSP_LLO;
1566    tempA = (rt >> 32) & MIPSDSP_LLO;
1567
1568    return MIPSDSP_RETURN64_32(tempB, tempA);
1569}
1570#endif
1571
1572target_ulong helper_precrqu_s_qb_ph(target_ulong rs, target_ulong rt,
1573                                    CPUMIPSState *env)
1574{
1575    uint8_t  tempD, tempC, tempB, tempA;
1576    uint16_t rsh, rsl, rth, rtl;
1577
1578    rsh = (rs & MIPSDSP_HI) >> 16;
1579    rsl =  rs & MIPSDSP_LO;
1580    rth = (rt & MIPSDSP_HI) >> 16;
1581    rtl =  rt & MIPSDSP_LO;
1582
1583    tempD = mipsdsp_sat8_reduce_precision(rsh, env);
1584    tempC = mipsdsp_sat8_reduce_precision(rsl, env);
1585    tempB = mipsdsp_sat8_reduce_precision(rth, env);
1586    tempA = mipsdsp_sat8_reduce_precision(rtl, env);
1587
1588    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);
1589}
1590
1591#if defined(TARGET_MIPS64)
1592target_ulong helper_precrqu_s_ob_qh(target_ulong rs, target_ulong rt,
1593                                    CPUMIPSState *env)
1594{
1595    int i;
1596    uint16_t rs3, rs2, rs1, rs0;
1597    uint16_t rt3, rt2, rt1, rt0;
1598    uint8_t temp[8];
1599    uint64_t result;
1600
1601    result = 0;
1602
1603    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
1604    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
1605
1606    temp[7] = mipsdsp_sat8_reduce_precision(rs3, env);
1607    temp[6] = mipsdsp_sat8_reduce_precision(rs2, env);
1608    temp[5] = mipsdsp_sat8_reduce_precision(rs1, env);
1609    temp[4] = mipsdsp_sat8_reduce_precision(rs0, env);
1610    temp[3] = mipsdsp_sat8_reduce_precision(rt3, env);
1611    temp[2] = mipsdsp_sat8_reduce_precision(rt2, env);
1612    temp[1] = mipsdsp_sat8_reduce_precision(rt1, env);
1613    temp[0] = mipsdsp_sat8_reduce_precision(rt0, env);
1614
1615    for (i = 0; i < 8; i++) {
1616        result |= (uint64_t)temp[i] << (8 * i);
1617    }
1618
1619    return result;
1620}
1621
1622#define PRECEQ_PW(name, a, b) \
1623target_ulong helper_preceq_pw_##name(target_ulong rt) \
1624{                                                       \
1625    uint16_t tempB, tempA;                              \
1626    uint32_t tempBI, tempAI;                            \
1627                                                        \
1628    tempB = (rt >> a) & MIPSDSP_LO;                     \
1629    tempA = (rt >> b) & MIPSDSP_LO;                     \
1630                                                        \
1631    tempBI = (uint32_t)tempB << 16;                     \
1632    tempAI = (uint32_t)tempA << 16;                     \
1633                                                        \
1634    return MIPSDSP_RETURN64_32(tempBI, tempAI);         \
1635}
1636
1637PRECEQ_PW(qhl, 48, 32);
1638PRECEQ_PW(qhr, 16, 0);
1639PRECEQ_PW(qhla, 48, 16);
1640PRECEQ_PW(qhra, 32, 0);
1641
1642#undef PRECEQ_PW
1643
1644#endif
1645
1646#define PRECEQU_PH(name, a, b) \
1647target_ulong helper_precequ_ph_##name(target_ulong rt) \
1648{                                                        \
1649    uint16_t tempB, tempA;                               \
1650                                                         \
1651    tempB = (rt >> a) & MIPSDSP_Q0;                      \
1652    tempA = (rt >> b) & MIPSDSP_Q0;                      \
1653                                                         \
1654    tempB = tempB << 7;                                  \
1655    tempA = tempA << 7;                                  \
1656                                                         \
1657    return MIPSDSP_RETURN32_16(tempB, tempA);            \
1658}
1659
1660PRECEQU_PH(qbl, 24, 16);
1661PRECEQU_PH(qbr, 8, 0);
1662PRECEQU_PH(qbla, 24, 8);
1663PRECEQU_PH(qbra, 16, 0);
1664
1665#undef PRECEQU_PH
1666
1667#if defined(TARGET_MIPS64)
1668#define PRECEQU_QH(name, a, b, c, d) \
1669target_ulong helper_precequ_qh_##name(target_ulong rt)       \
1670{                                                            \
1671    uint16_t tempD, tempC, tempB, tempA;                     \
1672                                                             \
1673    tempD = (rt >> a) & MIPSDSP_Q0;                          \
1674    tempC = (rt >> b) & MIPSDSP_Q0;                          \
1675    tempB = (rt >> c) & MIPSDSP_Q0;                          \
1676    tempA = (rt >> d) & MIPSDSP_Q0;                          \
1677                                                             \
1678    tempD = tempD << 7;                                      \
1679    tempC = tempC << 7;                                      \
1680    tempB = tempB << 7;                                      \
1681    tempA = tempA << 7;                                      \
1682                                                             \
1683    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
1684}
1685
1686PRECEQU_QH(obl, 56, 48, 40, 32);
1687PRECEQU_QH(obr, 24, 16, 8, 0);
1688PRECEQU_QH(obla, 56, 40, 24, 8);
1689PRECEQU_QH(obra, 48, 32, 16, 0);
1690
1691#undef PRECEQU_QH
1692
1693#endif
1694
1695#define PRECEU_PH(name, a, b) \
1696target_ulong helper_preceu_ph_##name(target_ulong rt) \
1697{                                                     \
1698    uint16_t tempB, tempA;                            \
1699                                                      \
1700    tempB = (rt >> a) & MIPSDSP_Q0;                   \
1701    tempA = (rt >> b) & MIPSDSP_Q0;                   \
1702                                                      \
1703    return MIPSDSP_RETURN32_16(tempB, tempA);         \
1704}
1705
1706PRECEU_PH(qbl, 24, 16);
1707PRECEU_PH(qbr, 8, 0);
1708PRECEU_PH(qbla, 24, 8);
1709PRECEU_PH(qbra, 16, 0);
1710
1711#undef PRECEU_PH
1712
1713#if defined(TARGET_MIPS64)
1714#define PRECEU_QH(name, a, b, c, d) \
1715target_ulong helper_preceu_qh_##name(target_ulong rt)        \
1716{                                                            \
1717    uint16_t tempD, tempC, tempB, tempA;                     \
1718                                                             \
1719    tempD = (rt >> a) & MIPSDSP_Q0;                          \
1720    tempC = (rt >> b) & MIPSDSP_Q0;                          \
1721    tempB = (rt >> c) & MIPSDSP_Q0;                          \
1722    tempA = (rt >> d) & MIPSDSP_Q0;                          \
1723                                                             \
1724    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
1725}
1726
1727PRECEU_QH(obl, 56, 48, 40, 32);
1728PRECEU_QH(obr, 24, 16, 8, 0);
1729PRECEU_QH(obla, 56, 40, 24, 8);
1730PRECEU_QH(obra, 48, 32, 16, 0);
1731
1732#undef PRECEU_QH
1733
1734#endif
1735
1736/** DSP GPR-Based Shift Sub-class insns **/
1737#define SHIFT_QB(name, func) \
1738target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt) \
1739{                                                                    \
1740    uint8_t rt3, rt2, rt1, rt0;                                      \
1741                                                                     \
1742    sa = sa & 0x07;                                                  \
1743                                                                     \
1744    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                       \
1745                                                                     \
1746    rt3 = mipsdsp_##func(rt3, sa);                                   \
1747    rt2 = mipsdsp_##func(rt2, sa);                                   \
1748    rt1 = mipsdsp_##func(rt1, sa);                                   \
1749    rt0 = mipsdsp_##func(rt0, sa);                                   \
1750                                                                     \
1751    return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0);                   \
1752}
1753
1754#define SHIFT_QB_ENV(name, func) \
1755target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt,\
1756                                CPUMIPSState *env) \
1757{                                                                    \
1758    uint8_t rt3, rt2, rt1, rt0;                                      \
1759                                                                     \
1760    sa = sa & 0x07;                                                  \
1761                                                                     \
1762    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                       \
1763                                                                     \
1764    rt3 = mipsdsp_##func(rt3, sa, env);                              \
1765    rt2 = mipsdsp_##func(rt2, sa, env);                              \
1766    rt1 = mipsdsp_##func(rt1, sa, env);                              \
1767    rt0 = mipsdsp_##func(rt0, sa, env);                              \
1768                                                                     \
1769    return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0);                   \
1770}
1771
1772SHIFT_QB_ENV(shll, lshift8);
1773SHIFT_QB(shrl, rshift_u8);
1774
1775SHIFT_QB(shra, rashift8);
1776SHIFT_QB(shra_r, rnd8_rashift);
1777
1778#undef SHIFT_QB
1779#undef SHIFT_QB_ENV
1780
1781#if defined(TARGET_MIPS64)
1782#define SHIFT_OB(name, func) \
1783target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \
1784{                                                                        \
1785    int i;                                                               \
1786    uint8_t rt_t[8];                                                     \
1787    uint64_t temp;                                                       \
1788                                                                         \
1789    sa = sa & 0x07;                                                      \
1790    temp = 0;                                                            \
1791                                                                         \
1792    for (i = 0; i < 8; i++) {                                            \
1793        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                          \
1794        rt_t[i] = mipsdsp_##func(rt_t[i], sa);                           \
1795        temp |= (uint64_t)rt_t[i] << (8 * i);                            \
1796    }                                                                    \
1797                                                                         \
1798    return temp;                                                         \
1799}
1800
1801#define SHIFT_OB_ENV(name, func) \
1802target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \
1803                                CPUMIPSState *env)                       \
1804{                                                                        \
1805    int i;                                                               \
1806    uint8_t rt_t[8];                                                     \
1807    uint64_t temp;                                                       \
1808                                                                         \
1809    sa = sa & 0x07;                                                      \
1810    temp = 0;                                                            \
1811                                                                         \
1812    for (i = 0; i < 8; i++) {                                            \
1813        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                          \
1814        rt_t[i] = mipsdsp_##func(rt_t[i], sa, env);                      \
1815        temp |= (uint64_t)rt_t[i] << (8 * i);                            \
1816    }                                                                    \
1817                                                                         \
1818    return temp;                                                         \
1819}
1820
1821SHIFT_OB_ENV(shll, lshift8);
1822SHIFT_OB(shrl, rshift_u8);
1823
1824SHIFT_OB(shra, rashift8);
1825SHIFT_OB(shra_r, rnd8_rashift);
1826
1827#undef SHIFT_OB
1828#undef SHIFT_OB_ENV
1829
1830#endif
1831
1832#define SHIFT_PH(name, func) \
1833target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt, \
1834                                CPUMIPSState *env)                \
1835{                                                                 \
1836    uint16_t rth, rtl;                                            \
1837                                                                  \
1838    sa = sa & 0x0F;                                               \
1839                                                                  \
1840    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
1841                                                                  \
1842    rth = mipsdsp_##func(rth, sa, env);                           \
1843    rtl = mipsdsp_##func(rtl, sa, env);                           \
1844                                                                  \
1845    return MIPSDSP_RETURN32_16(rth, rtl);                         \
1846}
1847
1848SHIFT_PH(shll, lshift16);
1849SHIFT_PH(shll_s, sat16_lshift);
1850
1851#undef SHIFT_PH
1852
1853#if defined(TARGET_MIPS64)
1854#define SHIFT_QH(name, func) \
1855target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa) \
1856{                                                                 \
1857    uint16_t rt3, rt2, rt1, rt0;                                  \
1858                                                                  \
1859    sa = sa & 0x0F;                                               \
1860                                                                  \
1861    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                   \
1862                                                                  \
1863    rt3 = mipsdsp_##func(rt3, sa);                                \
1864    rt2 = mipsdsp_##func(rt2, sa);                                \
1865    rt1 = mipsdsp_##func(rt1, sa);                                \
1866    rt0 = mipsdsp_##func(rt0, sa);                                \
1867                                                                  \
1868    return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0);               \
1869}
1870
1871#define SHIFT_QH_ENV(name, func) \
1872target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa, \
1873                                CPUMIPSState *env)                \
1874{                                                                 \
1875    uint16_t rt3, rt2, rt1, rt0;                                  \
1876                                                                  \
1877    sa = sa & 0x0F;                                               \
1878                                                                  \
1879    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                   \
1880                                                                  \
1881    rt3 = mipsdsp_##func(rt3, sa, env);                           \
1882    rt2 = mipsdsp_##func(rt2, sa, env);                           \
1883    rt1 = mipsdsp_##func(rt1, sa, env);                           \
1884    rt0 = mipsdsp_##func(rt0, sa, env);                           \
1885                                                                  \
1886    return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0);               \
1887}
1888
1889SHIFT_QH_ENV(shll, lshift16);
1890SHIFT_QH_ENV(shll_s, sat16_lshift);
1891
1892SHIFT_QH(shrl, rshift_u16);
1893SHIFT_QH(shra, rashift16);
1894SHIFT_QH(shra_r, rnd16_rashift);
1895
1896#undef SHIFT_QH
1897#undef SHIFT_QH_ENV
1898
1899#endif
1900
1901#define SHIFT_W(name, func) \
1902target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \
1903{                                                                       \
1904    uint32_t temp;                                                      \
1905                                                                        \
1906    sa = sa & 0x1F;                                                     \
1907    temp = mipsdsp_##func(rt, sa);                                      \
1908                                                                        \
1909    return (target_long)(int32_t)temp;                                  \
1910}
1911
1912#define SHIFT_W_ENV(name, func) \
1913target_ulong helper_##name##_w(target_ulong sa, target_ulong rt, \
1914                               CPUMIPSState *env) \
1915{                                                                       \
1916    uint32_t temp;                                                      \
1917                                                                        \
1918    sa = sa & 0x1F;                                                     \
1919    temp = mipsdsp_##func(rt, sa, env);                                 \
1920                                                                        \
1921    return (target_long)(int32_t)temp;                                  \
1922}
1923
1924SHIFT_W_ENV(shll_s, sat32_lshift);
1925SHIFT_W(shra_r, rnd32_rashift);
1926
1927#undef SHIFT_W
1928#undef SHIFT_W_ENV
1929
1930#if defined(TARGET_MIPS64)
1931#define SHIFT_PW(name, func) \
1932target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa) \
1933{                                                                 \
1934    uint32_t rt1, rt0;                                            \
1935                                                                  \
1936    sa = sa & 0x1F;                                               \
1937    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
1938                                                                  \
1939    rt1 = mipsdsp_##func(rt1, sa);                                \
1940    rt0 = mipsdsp_##func(rt0, sa);                                \
1941                                                                  \
1942    return MIPSDSP_RETURN64_32(rt1, rt0);                         \
1943}
1944
1945#define SHIFT_PW_ENV(name, func) \
1946target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa, \
1947                                CPUMIPSState *env)                \
1948{                                                                 \
1949    uint32_t rt1, rt0;                                            \
1950                                                                  \
1951    sa = sa & 0x1F;                                               \
1952    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
1953                                                                  \
1954    rt1 = mipsdsp_##func(rt1, sa, env);                           \
1955    rt0 = mipsdsp_##func(rt0, sa, env);                           \
1956                                                                  \
1957    return MIPSDSP_RETURN64_32(rt1, rt0);                         \
1958}
1959
1960SHIFT_PW_ENV(shll, lshift32);
1961SHIFT_PW_ENV(shll_s, sat32_lshift);
1962
1963SHIFT_PW(shra, rashift32);
1964SHIFT_PW(shra_r, rnd32_rashift);
1965
1966#undef SHIFT_PW
1967#undef SHIFT_PW_ENV
1968
1969#endif
1970
1971#define SHIFT_PH(name, func) \
1972target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \
1973{                                                                    \
1974    uint16_t rth, rtl;                                               \
1975                                                                     \
1976    sa = sa & 0x0F;                                                  \
1977                                                                     \
1978    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                \
1979                                                                     \
1980    rth = mipsdsp_##func(rth, sa);                                   \
1981    rtl = mipsdsp_##func(rtl, sa);                                   \
1982                                                                     \
1983    return MIPSDSP_RETURN32_16(rth, rtl);                            \
1984}
1985
1986SHIFT_PH(shrl, rshift_u16);
1987SHIFT_PH(shra, rashift16);
1988SHIFT_PH(shra_r, rnd16_rashift);
1989
1990#undef SHIFT_PH
1991
1992/** DSP Multiply Sub-class insns **/
1993/* Return value made up by two 16bits value.
1994 * FIXME give the macro a better name.
1995 */
1996#define MUL_RETURN32_16_PH(name, func, \
1997                           rsmov1, rsmov2, rsfilter, \
1998                           rtmov1, rtmov2, rtfilter) \
1999target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2000                           CPUMIPSState *env)                \
2001{                                                            \
2002    uint16_t rsB, rsA, rtB, rtA;                             \
2003                                                             \
2004    rsB = (rs >> rsmov1) & rsfilter;                         \
2005    rsA = (rs >> rsmov2) & rsfilter;                         \
2006    rtB = (rt >> rtmov1) & rtfilter;                         \
2007    rtA = (rt >> rtmov2) & rtfilter;                         \
2008                                                             \
2009    rsB = mipsdsp_##func(rsB, rtB, env);                     \
2010    rsA = mipsdsp_##func(rsA, rtA, env);                     \
2011                                                             \
2012    return MIPSDSP_RETURN32_16(rsB, rsA);                    \
2013}
2014
2015MUL_RETURN32_16_PH(muleu_s_ph_qbl, mul_u8_u16, \
2016                      24, 16, MIPSDSP_Q0, \
2017                      16, 0, MIPSDSP_LO);
2018MUL_RETURN32_16_PH(muleu_s_ph_qbr, mul_u8_u16, \
2019                      8, 0, MIPSDSP_Q0, \
2020                      16, 0, MIPSDSP_LO);
2021MUL_RETURN32_16_PH(mulq_rs_ph, rndq15_mul_q15_q15, \
2022                      16, 0, MIPSDSP_LO, \
2023                      16, 0, MIPSDSP_LO);
2024MUL_RETURN32_16_PH(mul_ph, mul_i16_i16, \
2025                      16, 0, MIPSDSP_LO, \
2026                      16, 0, MIPSDSP_LO);
2027MUL_RETURN32_16_PH(mul_s_ph, sat16_mul_i16_i16, \
2028                      16, 0, MIPSDSP_LO, \
2029                      16, 0, MIPSDSP_LO);
2030MUL_RETURN32_16_PH(mulq_s_ph, sat16_mul_q15_q15, \
2031                      16, 0, MIPSDSP_LO, \
2032                      16, 0, MIPSDSP_LO);
2033
2034#undef MUL_RETURN32_16_PH
2035
2036#define MUL_RETURN32_32_ph(name, func, movbits) \
2037target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2038                                  CPUMIPSState *env)         \
2039{                                                            \
2040    int16_t rsh, rth;                                        \
2041    int32_t temp;                                            \
2042                                                             \
2043    rsh = (rs >> movbits) & MIPSDSP_LO;                      \
2044    rth = (rt >> movbits) & MIPSDSP_LO;                      \
2045    temp = mipsdsp_##func(rsh, rth, env);                    \
2046                                                             \
2047    return (target_long)(int32_t)temp;                       \
2048}
2049
2050MUL_RETURN32_32_ph(muleq_s_w_phl, mul_q15_q15_overflowflag21, 16);
2051MUL_RETURN32_32_ph(muleq_s_w_phr, mul_q15_q15_overflowflag21, 0);
2052
2053#undef MUL_RETURN32_32_ph
2054
2055#define MUL_VOID_PH(name, use_ac_env) \
2056void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
2057                          CPUMIPSState *env)                             \
2058{                                                                        \
2059    int16_t rsh, rsl, rth, rtl;                                          \
2060    int32_t tempB, tempA;                                                \
2061    int64_t acc, dotp;                                                   \
2062                                                                         \
2063    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                                    \
2064    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                    \
2065                                                                         \
2066    if (use_ac_env == 1) {                                               \
2067        tempB = mipsdsp_mul_q15_q15(ac, rsh, rth, env);                  \
2068        tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl, env);                  \
2069    } else {                                                             \
2070        tempB = mipsdsp_mul_u16_u16(rsh, rth);                           \
2071        tempA = mipsdsp_mul_u16_u16(rsl, rtl);                           \
2072    }                                                                    \
2073                                                                         \
2074    dotp = (int64_t)tempB - (int64_t)tempA;                              \
2075    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                      \
2076          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);               \
2077    dotp = dotp + acc;                                                   \
2078    env->active_tc.HI[ac] = (target_long)(int32_t)                       \
2079                            ((dotp & MIPSDSP_LHI) >> 32);                \
2080    env->active_tc.LO[ac] = (target_long)(int32_t)(dotp & MIPSDSP_LLO);  \
2081}
2082
2083MUL_VOID_PH(mulsaq_s_w_ph, 1);
2084MUL_VOID_PH(mulsa_w_ph, 0);
2085
2086#undef MUL_VOID_PH
2087
2088#if defined(TARGET_MIPS64)
2089#define MUL_RETURN64_16_QH(name, func, \
2090                           rsmov1, rsmov2, rsmov3, rsmov4, rsfilter, \
2091                           rtmov1, rtmov2, rtmov3, rtmov4, rtfilter) \
2092target_ulong helper_##name(target_ulong rs, target_ulong rt,         \
2093                           CPUMIPSState *env)                        \
2094{                                                                    \
2095    uint16_t rs3, rs2, rs1, rs0;                                     \
2096    uint16_t rt3, rt2, rt1, rt0;                                     \
2097    uint16_t tempD, tempC, tempB, tempA;                             \
2098                                                                     \
2099    rs3 = (rs >> rsmov1) & rsfilter;                                 \
2100    rs2 = (rs >> rsmov2) & rsfilter;                                 \
2101    rs1 = (rs >> rsmov3) & rsfilter;                                 \
2102    rs0 = (rs >> rsmov4) & rsfilter;                                 \
2103    rt3 = (rt >> rtmov1) & rtfilter;                                 \
2104    rt2 = (rt >> rtmov2) & rtfilter;                                 \
2105    rt1 = (rt >> rtmov3) & rtfilter;                                 \
2106    rt0 = (rt >> rtmov4) & rtfilter;                                 \
2107                                                                     \
2108    tempD = mipsdsp_##func(rs3, rt3, env);                           \
2109    tempC = mipsdsp_##func(rs2, rt2, env);                           \
2110    tempB = mipsdsp_##func(rs1, rt1, env);                           \
2111    tempA = mipsdsp_##func(rs0, rt0, env);                           \
2112                                                                     \
2113    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);          \
2114}
2115
2116MUL_RETURN64_16_QH(muleu_s_qh_obl, mul_u8_u16, \
2117                   56, 48, 40, 32, MIPSDSP_Q0, \
2118                   48, 32, 16, 0, MIPSDSP_LO);
2119MUL_RETURN64_16_QH(muleu_s_qh_obr, mul_u8_u16, \
2120                   24, 16, 8, 0, MIPSDSP_Q0, \
2121                   48, 32, 16, 0, MIPSDSP_LO);
2122MUL_RETURN64_16_QH(mulq_rs_qh, rndq15_mul_q15_q15, \
2123                   48, 32, 16, 0, MIPSDSP_LO, \
2124                   48, 32, 16, 0, MIPSDSP_LO);
2125
2126#undef MUL_RETURN64_16_QH
2127
2128#define MUL_RETURN64_32_QH(name, \
2129                           rsmov1, rsmov2, \
2130                           rtmov1, rtmov2) \
2131target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2132                           CPUMIPSState *env)                \
2133{                                                            \
2134    uint16_t rsB, rsA;                                       \
2135    uint16_t rtB, rtA;                                       \
2136    uint32_t tempB, tempA;                                   \
2137                                                             \
2138    rsB = (rs >> rsmov1) & MIPSDSP_LO;                       \
2139    rsA = (rs >> rsmov2) & MIPSDSP_LO;                       \
2140    rtB = (rt >> rtmov1) & MIPSDSP_LO;                       \
2141    rtA = (rt >> rtmov2) & MIPSDSP_LO;                       \
2142                                                             \
2143    tempB = mipsdsp_mul_q15_q15(5, rsB, rtB, env);           \
2144    tempA = mipsdsp_mul_q15_q15(5, rsA, rtA, env);           \
2145                                                             \
2146    return ((uint64_t)tempB << 32) | (uint64_t)tempA;        \
2147}
2148
2149MUL_RETURN64_32_QH(muleq_s_pw_qhl, 48, 32, 48, 32);
2150MUL_RETURN64_32_QH(muleq_s_pw_qhr, 16, 0, 16, 0);
2151
2152#undef MUL_RETURN64_32_QH
2153
2154void helper_mulsaq_s_w_qh(target_ulong rs, target_ulong rt, uint32_t ac,
2155                          CPUMIPSState *env)
2156{
2157    int16_t rs3, rs2, rs1, rs0;
2158    int16_t rt3, rt2, rt1, rt0;
2159    int32_t tempD, tempC, tempB, tempA;
2160    int64_t acc[2];
2161    int64_t temp[2];
2162    int64_t temp_sum;
2163
2164    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
2165    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
2166
2167    tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env);
2168    tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env);
2169    tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env);
2170    tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env);
2171
2172    temp[0] = ((int32_t)tempD - (int32_t)tempC) +
2173              ((int32_t)tempB - (int32_t)tempA);
2174    temp[0] = (int64_t)(temp[0] << 30) >> 30;
2175    if (((temp[0] >> 33) & 0x01) == 0) {
2176        temp[1] = 0x00;
2177    } else {
2178        temp[1] = ~0ull;
2179    }
2180
2181    acc[0] = env->active_tc.LO[ac];
2182    acc[1] = env->active_tc.HI[ac];
2183
2184    temp_sum = acc[0] + temp[0];
2185    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
2186       ((uint64_t)temp_sum < (uint64_t)temp[0])) {
2187        acc[1] += 1;
2188    }
2189    acc[0] = temp_sum;
2190    acc[1] += temp[1];
2191
2192    env->active_tc.HI[ac] = acc[1];
2193    env->active_tc.LO[ac] = acc[0];
2194}
2195#endif
2196
2197#define DP_QB(name, func, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
2198void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
2199                   CPUMIPSState *env)                                    \
2200{                                                                        \
2201    uint8_t rs3, rs2;                                                    \
2202    uint8_t rt3, rt2;                                                    \
2203    uint16_t tempB, tempA;                                               \
2204    uint64_t tempC, dotp;                                                \
2205                                                                         \
2206    rs3 = (rs >> rsmov1) & MIPSDSP_Q0;                                   \
2207    rs2 = (rs >> rsmov2) & MIPSDSP_Q0;                                   \
2208    rt3 = (rt >> rtmov1) & MIPSDSP_Q0;                                   \
2209    rt2 = (rt >> rtmov2) & MIPSDSP_Q0;                                   \
2210    tempB = mipsdsp_##func(rs3, rt3);                                    \
2211    tempA = mipsdsp_##func(rs2, rt2);                                    \
2212    dotp = (int64_t)tempB + (int64_t)tempA;                              \
2213    if (is_add) {                                                        \
2214        tempC = (((uint64_t)env->active_tc.HI[ac] << 32) |               \
2215                 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO))        \
2216            + dotp;                                                      \
2217    } else {                                                             \
2218        tempC = (((uint64_t)env->active_tc.HI[ac] << 32) |               \
2219                 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO))        \
2220            - dotp;                                                      \
2221    }                                                                    \
2222                                                                         \
2223    env->active_tc.HI[ac] = (target_long)(int32_t)                       \
2224                            ((tempC & MIPSDSP_LHI) >> 32);               \
2225    env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO); \
2226}
2227
2228DP_QB(dpau_h_qbl, mul_u8_u8, 1, 24, 16, 24, 16);
2229DP_QB(dpau_h_qbr, mul_u8_u8, 1, 8, 0, 8, 0);
2230DP_QB(dpsu_h_qbl, mul_u8_u8, 0, 24, 16, 24, 16);
2231DP_QB(dpsu_h_qbr, mul_u8_u8, 0, 8, 0, 8, 0);
2232
2233#undef DP_QB
2234
2235#if defined(TARGET_MIPS64)
2236#define DP_OB(name, add_sub, \
2237              rsmov1, rsmov2, rsmov3, rsmov4, \
2238              rtmov1, rtmov2, rtmov3, rtmov4) \
2239void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,       \
2240                       CPUMIPSState *env)                               \
2241{                                                                       \
2242    uint8_t rsD, rsC, rsB, rsA;                                         \
2243    uint8_t rtD, rtC, rtB, rtA;                                         \
2244    uint16_t tempD, tempC, tempB, tempA;                                \
2245    uint64_t temp[2];                                                   \
2246    uint64_t acc[2];                                                    \
2247    uint64_t temp_sum;                                                  \
2248                                                                        \
2249    temp[0] = 0;                                                        \
2250    temp[1] = 0;                                                        \
2251                                                                        \
2252    rsD = (rs >> rsmov1) & MIPSDSP_Q0;                                  \
2253    rsC = (rs >> rsmov2) & MIPSDSP_Q0;                                  \
2254    rsB = (rs >> rsmov3) & MIPSDSP_Q0;                                  \
2255    rsA = (rs >> rsmov4) & MIPSDSP_Q0;                                  \
2256    rtD = (rt >> rtmov1) & MIPSDSP_Q0;                                  \
2257    rtC = (rt >> rtmov2) & MIPSDSP_Q0;                                  \
2258    rtB = (rt >> rtmov3) & MIPSDSP_Q0;                                  \
2259    rtA = (rt >> rtmov4) & MIPSDSP_Q0;                                  \
2260                                                                        \
2261    tempD = mipsdsp_mul_u8_u8(rsD, rtD);                                \
2262    tempC = mipsdsp_mul_u8_u8(rsC, rtC);                                \
2263    tempB = mipsdsp_mul_u8_u8(rsB, rtB);                                \
2264    tempA = mipsdsp_mul_u8_u8(rsA, rtA);                                \
2265                                                                        \
2266    temp[0] = (uint64_t)tempD + (uint64_t)tempC +                       \
2267      (uint64_t)tempB + (uint64_t)tempA;                                \
2268                                                                        \
2269    acc[0] = env->active_tc.LO[ac];                                     \
2270    acc[1] = env->active_tc.HI[ac];                                     \
2271                                                                        \
2272    if (add_sub) {                                                      \
2273        temp_sum = acc[0] + temp[0];                                    \
2274        if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&                  \
2275            ((uint64_t)temp_sum < (uint64_t)temp[0])) {                 \
2276            acc[1] += 1;                                                \
2277        }                                                               \
2278        temp[0] = temp_sum;                                             \
2279        temp[1] = acc[1] + temp[1];                                     \
2280    } else {                                                            \
2281        temp_sum = acc[0] - temp[0];                                    \
2282        if ((uint64_t)temp_sum > (uint64_t)acc[0]) {                    \
2283            acc[1] -= 1;                                                \
2284        }                                                               \
2285        temp[0] = temp_sum;                                             \
2286        temp[1] = acc[1] - temp[1];                                     \
2287    }                                                                   \
2288                                                                        \
2289    env->active_tc.HI[ac] = temp[1];                                    \
2290    env->active_tc.LO[ac] = temp[0];                                    \
2291}
2292
2293DP_OB(dpau_h_obl, 1, 56, 48, 40, 32, 56, 48, 40, 32);
2294DP_OB(dpau_h_obr, 1, 24, 16, 8, 0, 24, 16, 8, 0);
2295DP_OB(dpsu_h_obl, 0, 56, 48, 40, 32, 56, 48, 40, 32);
2296DP_OB(dpsu_h_obr, 0, 24, 16, 8, 0, 24, 16, 8, 0);
2297
2298#undef DP_OB
2299#endif
2300
2301#define DP_NOFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2)             \
2302void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,              \
2303                   CPUMIPSState *env)                                          \
2304{                                                                              \
2305    int16_t rsB, rsA, rtB, rtA;                                                \
2306    int32_t  tempA, tempB;                                                     \
2307    int64_t  acc;                                                              \
2308                                                                               \
2309    rsB = (rs >> rsmov1) & MIPSDSP_LO;                                         \
2310    rsA = (rs >> rsmov2) & MIPSDSP_LO;                                         \
2311    rtB = (rt >> rtmov1) & MIPSDSP_LO;                                         \
2312    rtA = (rt >> rtmov2) & MIPSDSP_LO;                                         \
2313                                                                               \
2314    tempB = (int32_t)rsB * (int32_t)rtB;                                       \
2315    tempA = (int32_t)rsA * (int32_t)rtA;                                       \
2316                                                                               \
2317    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                            \
2318          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);                     \
2319                                                                               \
2320    if (is_add) {                                                              \
2321        acc = acc + ((int64_t)tempB + (int64_t)tempA);                         \
2322    } else {                                                                   \
2323        acc = acc - ((int64_t)tempB + (int64_t)tempA);                         \
2324    }                                                                          \
2325                                                                               \
2326    env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32); \
2327    env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO);         \
2328}
2329
2330DP_NOFUNC_PH(dpa_w_ph, 1, 16, 0, 16, 0);
2331DP_NOFUNC_PH(dpax_w_ph, 1, 16, 0, 0, 16);
2332DP_NOFUNC_PH(dps_w_ph, 0, 16, 0, 16, 0);
2333DP_NOFUNC_PH(dpsx_w_ph, 0, 16, 0, 0, 16);
2334#undef DP_NOFUNC_PH
2335
2336#define DP_HASFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
2337void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,   \
2338                   CPUMIPSState *env)                      \
2339{                                                          \
2340    int16_t rsB, rsA, rtB, rtA;                            \
2341    int32_t tempB, tempA;                                  \
2342    int64_t acc, dotp;                                     \
2343                                                           \
2344    rsB = (rs >> rsmov1) & MIPSDSP_LO;                     \
2345    rsA = (rs >> rsmov2) & MIPSDSP_LO;                     \
2346    rtB = (rt >> rtmov1) & MIPSDSP_LO;                     \
2347    rtA = (rt >> rtmov2) & MIPSDSP_LO;                     \
2348                                                           \
2349    tempB = mipsdsp_mul_q15_q15(ac, rsB, rtB, env);        \
2350    tempA = mipsdsp_mul_q15_q15(ac, rsA, rtA, env);        \
2351                                                           \
2352    dotp = (int64_t)tempB + (int64_t)tempA;                \
2353    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |        \
2354          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
2355                                                           \
2356    if (is_add) {                                          \
2357        acc = acc + dotp;                                  \
2358    } else {                                               \
2359        acc = acc - dotp;                                  \
2360    }                                                      \
2361                                                           \
2362    env->active_tc.HI[ac] = (target_long)(int32_t)         \
2363        ((acc & MIPSDSP_LHI) >> 32);                       \
2364    env->active_tc.LO[ac] = (target_long)(int32_t)         \
2365        (acc & MIPSDSP_LLO);                               \
2366}
2367
2368DP_HASFUNC_PH(dpaq_s_w_ph, 1, 16, 0, 16, 0);
2369DP_HASFUNC_PH(dpaqx_s_w_ph, 1, 16, 0, 0, 16);
2370DP_HASFUNC_PH(dpsq_s_w_ph, 0, 16, 0, 16, 0);
2371DP_HASFUNC_PH(dpsqx_s_w_ph, 0, 16, 0, 0, 16);
2372
2373#undef DP_HASFUNC_PH
2374
2375#define DP_128OPERATION_PH(name, is_add) \
2376void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2377                          CPUMIPSState *env)                             \
2378{                                                                        \
2379    int16_t rsh, rsl, rth, rtl;                                          \
2380    int32_t tempB, tempA, tempC62_31, tempC63;                           \
2381    int64_t acc, dotp, tempC;                                            \
2382                                                                         \
2383    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                                    \
2384    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                    \
2385                                                                         \
2386    tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl, env);                      \
2387    tempA = mipsdsp_mul_q15_q15(ac, rsl, rth, env);                      \
2388                                                                         \
2389    dotp = (int64_t)tempB + (int64_t)tempA;                              \
2390    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                      \
2391          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);               \
2392    if (is_add) {                                                        \
2393        tempC = acc + dotp;                                              \
2394    } else {                                                             \
2395        tempC = acc - dotp;                                              \
2396    }                                                                    \
2397    tempC63 = (tempC >> 63) & 0x01;                                      \
2398    tempC62_31 = (tempC >> 31) & 0xFFFFFFFF;                             \
2399                                                                         \
2400    if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) {                  \
2401        tempC = 0x7FFFFFFF;                                              \
2402        set_DSPControl_overflow_flag(1, 16 + ac, env);                   \
2403    }                                                                    \
2404                                                                         \
2405    if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) {                  \
2406        tempC = (int64_t)(int32_t)0x80000000;                            \
2407        set_DSPControl_overflow_flag(1, 16 + ac, env);                   \
2408    }                                                                    \
2409                                                                         \
2410    env->active_tc.HI[ac] = (target_long)(int32_t)                       \
2411        ((tempC & MIPSDSP_LHI) >> 32);                                   \
2412    env->active_tc.LO[ac] = (target_long)(int32_t)                       \
2413        (tempC & MIPSDSP_LLO);                                           \
2414}
2415
2416DP_128OPERATION_PH(dpaqx_sa_w_ph, 1);
2417DP_128OPERATION_PH(dpsqx_sa_w_ph, 0);
2418
2419#undef DP_128OPERATION_HP
2420
2421#if defined(TARGET_MIPS64)
2422#define DP_QH(name, is_add, use_ac_env) \
2423void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,    \
2424                   CPUMIPSState *env)                                \
2425{                                                                    \
2426    int32_t rs3, rs2, rs1, rs0;                                      \
2427    int32_t rt3, rt2, rt1, rt0;                                      \
2428    int32_t tempD, tempC, tempB, tempA;                              \
2429    int64_t acc[2];                                                  \
2430    int64_t temp[2];                                                 \
2431    int64_t temp_sum;                                                \
2432                                                                     \
2433    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);                      \
2434    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                      \
2435                                                                     \
2436    if (use_ac_env) {                                                \
2437        tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env);              \
2438        tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env);              \
2439        tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env);              \
2440        tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env);              \
2441    } else {                                                         \
2442        tempD = mipsdsp_mul_u16_u16(rs3, rt3);                       \
2443        tempC = mipsdsp_mul_u16_u16(rs2, rt2);                       \
2444        tempB = mipsdsp_mul_u16_u16(rs1, rt1);                       \
2445        tempA = mipsdsp_mul_u16_u16(rs0, rt0);                       \
2446    }                                                                \
2447                                                                     \
2448    temp[0] = (int64_t)tempD + (int64_t)tempC +                      \
2449              (int64_t)tempB + (int64_t)tempA;                       \
2450                                                                     \
2451    if (temp[0] >= 0) {                                              \
2452        temp[1] = 0;                                                 \
2453    } else {                                                         \
2454        temp[1] = ~0ull;                                             \
2455    }                                                                \
2456                                                                     \
2457    acc[1] = env->active_tc.HI[ac];                                  \
2458    acc[0] = env->active_tc.LO[ac];                                  \
2459                                                                     \
2460    if (is_add) {                                                    \
2461        temp_sum = acc[0] + temp[0];                                 \
2462        if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&               \
2463            ((uint64_t)temp_sum < (uint64_t)temp[0])) {              \
2464            acc[1] = acc[1] + 1;                                     \
2465        }                                                            \
2466        temp[0] = temp_sum;                                          \
2467        temp[1] = acc[1] + temp[1];                                  \
2468    } else {                                                         \
2469        temp_sum = acc[0] - temp[0];                                 \
2470        if ((uint64_t)temp_sum > (uint64_t)acc[0]) {                 \
2471            acc[1] = acc[1] - 1;                                     \
2472        }                                                            \
2473        temp[0] = temp_sum;                                          \
2474        temp[1] = acc[1] - temp[1];                                  \
2475    }                                                                \
2476                                                                     \
2477    env->active_tc.HI[ac] = temp[1];                                 \
2478    env->active_tc.LO[ac] = temp[0];                                 \
2479}
2480
2481DP_QH(dpa_w_qh, 1, 0);
2482DP_QH(dpaq_s_w_qh, 1, 1);
2483DP_QH(dps_w_qh, 0, 0);
2484DP_QH(dpsq_s_w_qh, 0, 1);
2485
2486#undef DP_QH
2487
2488#endif
2489
2490#define DP_L_W(name, is_add) \
2491void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,     \
2492                   CPUMIPSState *env)                                 \
2493{                                                                     \
2494    int32_t temp63;                                                   \
2495    int64_t dotp, acc;                                                \
2496    uint64_t temp;                                                    \
2497                                                                      \
2498    dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env);                      \
2499    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                   \
2500          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);            \
2501    if (!is_add) {                                                    \
2502        dotp = -dotp;                                                 \
2503    }                                                                 \
2504                                                                      \
2505    temp = acc + dotp;                                                \
2506    if (MIPSDSP_OVERFLOW((uint64_t)acc, (uint64_t)dotp, temp,         \
2507                         (0x01ull << 63))) {                          \
2508        temp63 = (temp >> 63) & 0x01;                                 \
2509        if (temp63 == 1) {                                            \
2510            temp = (0x01ull << 63) - 1;                               \
2511        } else {                                                      \
2512            temp = 0x01ull << 63;                                     \
2513        }                                                             \
2514                                                                      \
2515        set_DSPControl_overflow_flag(1, 16 + ac, env);                \
2516    }                                                                 \
2517                                                                      \
2518    env->active_tc.HI[ac] = (target_long)(int32_t)                    \
2519        ((temp & MIPSDSP_LHI) >> 32);                                 \
2520    env->active_tc.LO[ac] = (target_long)(int32_t)                    \
2521        (temp & MIPSDSP_LLO);                                         \
2522}
2523
2524DP_L_W(dpaq_sa_l_w, 1);
2525DP_L_W(dpsq_sa_l_w, 0);
2526
2527#undef DP_L_W
2528
2529#if defined(TARGET_MIPS64)
2530#define DP_L_PW(name, func) \
2531void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2532                   CPUMIPSState *env)                             \
2533{                                                                 \
2534    int32_t rs1, rs0;                                             \
2535    int32_t rt1, rt0;                                             \
2536    int64_t tempB[2], tempA[2];                                   \
2537    int64_t temp[2];                                              \
2538    int64_t acc[2];                                               \
2539    int64_t temp_sum;                                             \
2540                                                                  \
2541    temp[0] = 0;                                                  \
2542    temp[1] = 0;                                                  \
2543                                                                  \
2544    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                             \
2545    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
2546                                                                  \
2547    tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env);            \
2548    tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);            \
2549                                                                  \
2550    if (tempB[0] >= 0) {                                          \
2551        tempB[1] = 0x00;                                          \
2552    } else {                                                      \
2553        tempB[1] = ~0ull;                                         \
2554    }                                                             \
2555                                                                  \
2556    if (tempA[0] >= 0) {                                          \
2557        tempA[1] = 0x00;                                          \
2558    } else {                                                      \
2559        tempA[1] = ~0ull;                                         \
2560    }                                                             \
2561                                                                  \
2562    temp_sum = tempB[0] + tempA[0];                               \
2563    if (((uint64_t)temp_sum < (uint64_t)tempB[0]) &&              \
2564        ((uint64_t)temp_sum < (uint64_t)tempA[0])) {              \
2565        temp[1] += 1;                                             \
2566    }                                                             \
2567    temp[0] = temp_sum;                                           \
2568    temp[1] += tempB[1] + tempA[1];                               \
2569                                                                  \
2570    mipsdsp_##func(acc, ac, temp, env);                           \
2571                                                                  \
2572    env->active_tc.HI[ac] = acc[1];                               \
2573    env->active_tc.LO[ac] = acc[0];                               \
2574}
2575
2576DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63);
2577DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63);
2578
2579#undef DP_L_PW
2580
2581void helper_mulsaq_s_l_pw(target_ulong rs, target_ulong rt, uint32_t ac,
2582                          CPUMIPSState *env)
2583{
2584    int32_t rs1, rs0;
2585    int32_t rt1, rt0;
2586    int64_t tempB[2], tempA[2];
2587    int64_t temp[2];
2588    int64_t acc[2];
2589    int64_t temp_sum;
2590
2591    rs1 = (rs >> 32) & MIPSDSP_LLO;
2592    rs0 = rs & MIPSDSP_LLO;
2593    rt1 = (rt >> 32) & MIPSDSP_LLO;
2594    rt0 = rt & MIPSDSP_LLO;
2595
2596    tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env);
2597    tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);
2598
2599    if (tempB[0] >= 0) {
2600        tempB[1] = 0x00;
2601    } else {
2602        tempB[1] = ~0ull;
2603    }
2604
2605    if (tempA[0] >= 0) {
2606        tempA[1] = 0x00;
2607    } else {
2608        tempA[1] = ~0ull;
2609    }
2610
2611    acc[0] = env->active_tc.LO[ac];
2612    acc[1] = env->active_tc.HI[ac];
2613
2614    temp_sum = tempB[0] - tempA[0];
2615    if ((uint64_t)temp_sum > (uint64_t)tempB[0]) {
2616        tempB[1] -= 1;
2617    }
2618    temp[0] = temp_sum;
2619    temp[1] = tempB[1] - tempA[1];
2620
2621    if ((temp[1] & 0x01) == 0) {
2622        temp[1] = 0x00;
2623    } else {
2624        temp[1] = ~0ull;
2625    }
2626
2627    temp_sum = acc[0] + temp[0];
2628    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
2629       ((uint64_t)temp_sum < (uint64_t)temp[0])) {
2630        acc[1] += 1;
2631    }
2632    acc[0] = temp_sum;
2633    acc[1] += temp[1];
2634
2635    env->active_tc.HI[ac] = acc[1];
2636    env->active_tc.LO[ac] = acc[0];
2637}
2638#endif
2639
2640#define MAQ_S_W(name, mov) \
2641void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2642                   CPUMIPSState *env)                             \
2643{                                                                 \
2644    int16_t rsh, rth;                                             \
2645    int32_t tempA;                                                \
2646    int64_t tempL, acc;                                           \
2647                                                                  \
2648    rsh = (rs >> mov) & MIPSDSP_LO;                               \
2649    rth = (rt >> mov) & MIPSDSP_LO;                               \
2650    tempA  = mipsdsp_mul_q15_q15(ac, rsh, rth, env);              \
2651    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |               \
2652          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);        \
2653    tempL  = (int64_t)tempA + acc;                                \
2654    env->active_tc.HI[ac] = (target_long)(int32_t)                \
2655        ((tempL & MIPSDSP_LHI) >> 32);                            \
2656    env->active_tc.LO[ac] = (target_long)(int32_t)                \
2657        (tempL & MIPSDSP_LLO);                                    \
2658}
2659
2660MAQ_S_W(maq_s_w_phl, 16);
2661MAQ_S_W(maq_s_w_phr, 0);
2662
2663#undef MAQ_S_W
2664
2665#define MAQ_SA_W(name, mov) \
2666void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
2667                   CPUMIPSState *env)                                    \
2668{                                                                        \
2669    int16_t rsh, rth;                                                    \
2670    int32_t tempA;                                                       \
2671                                                                         \
2672    rsh = (rs >> mov) & MIPSDSP_LO;                                      \
2673    rth = (rt >> mov) & MIPSDSP_LO;                                      \
2674    tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env);                      \
2675    tempA = mipsdsp_sat32_acc_q31(ac, tempA, env);                       \
2676                                                                         \
2677    env->active_tc.HI[ac] = (target_long)(int32_t)(((int64_t)tempA &     \
2678                                                    MIPSDSP_LHI) >> 32); \
2679    env->active_tc.LO[ac] = (target_long)(int32_t)((int64_t)tempA &      \
2680                                                   MIPSDSP_LLO);         \
2681}
2682
2683MAQ_SA_W(maq_sa_w_phl, 16);
2684MAQ_SA_W(maq_sa_w_phr, 0);
2685
2686#undef MAQ_SA_W
2687
2688#define MULQ_W(name, addvar) \
2689target_ulong helper_##name(target_ulong rs, target_ulong rt,   \
2690                           CPUMIPSState *env)                  \
2691{                                                              \
2692    uint32_t rs_t, rt_t;                                       \
2693    int32_t tempI;                                             \
2694    int64_t tempL;                                             \
2695                                                               \
2696    rs_t = rs & MIPSDSP_LLO;                                   \
2697    rt_t = rt & MIPSDSP_LLO;                                   \
2698                                                               \
2699    if ((rs_t == 0x80000000) && (rt_t == 0x80000000)) {        \
2700        tempL = 0x7FFFFFFF00000000ull;                         \
2701        set_DSPControl_overflow_flag(1, 21, env);              \
2702    } else {                                                   \
2703        tempL  = ((int64_t)rs_t * (int64_t)rt_t) << 1;         \
2704        tempL += addvar;                                       \
2705    }                                                          \
2706    tempI = (tempL & MIPSDSP_LHI) >> 32;                       \
2707                                                               \
2708    return (target_long)(int32_t)tempI;                        \
2709}
2710
2711MULQ_W(mulq_s_w, 0);
2712MULQ_W(mulq_rs_w, 0x80000000ull);
2713
2714#undef MULQ_W
2715
2716#if defined(TARGET_MIPS64)
2717
2718#define MAQ_S_W_QH(name, mov) \
2719void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2720                   CPUMIPSState *env)                             \
2721{                                                                 \
2722    int16_t rs_t, rt_t;                                           \
2723    int32_t temp_mul;                                             \
2724    int64_t temp[2];                                              \
2725    int64_t acc[2];                                               \
2726    int64_t temp_sum;                                             \
2727                                                                  \
2728    temp[0] = 0;                                                  \
2729    temp[1] = 0;                                                  \
2730                                                                  \
2731    rs_t = (rs >> mov) & MIPSDSP_LO;                              \
2732    rt_t = (rt >> mov) & MIPSDSP_LO;                              \
2733    temp_mul = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env);          \
2734                                                                  \
2735    temp[0] = (int64_t)temp_mul;                                  \
2736    if (temp[0] >= 0) {                                           \
2737        temp[1] = 0x00;                                           \
2738    } else {                                                      \
2739        temp[1] = ~0ull;                                          \
2740    }                                                             \
2741                                                                  \
2742    acc[0] = env->active_tc.LO[ac];                               \
2743    acc[1] = env->active_tc.HI[ac];                               \
2744                                                                  \
2745    temp_sum = acc[0] + temp[0];                                  \
2746    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&                \
2747        ((uint64_t)temp_sum < (uint64_t)temp[0])) {               \
2748        acc[1] += 1;                                              \
2749    }                                                             \
2750    acc[0] = temp_sum;                                            \
2751    acc[1] += temp[1];                                            \
2752                                                                  \
2753    env->active_tc.HI[ac] = acc[1];                               \
2754    env->active_tc.LO[ac] = acc[0];                               \
2755}
2756
2757MAQ_S_W_QH(maq_s_w_qhll, 48);
2758MAQ_S_W_QH(maq_s_w_qhlr, 32);
2759MAQ_S_W_QH(maq_s_w_qhrl, 16);
2760MAQ_S_W_QH(maq_s_w_qhrr, 0);
2761
2762#undef MAQ_S_W_QH
2763
2764#define MAQ_SA_W(name, mov) \
2765void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2766                   CPUMIPSState *env)                             \
2767{                                                                 \
2768    int16_t rs_t, rt_t;                                           \
2769    int32_t temp;                                                 \
2770    int64_t acc[2];                                               \
2771                                                                  \
2772    rs_t = (rs >> mov) & MIPSDSP_LO;                              \
2773    rt_t = (rt >> mov) & MIPSDSP_LO;                              \
2774    temp = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env);              \
2775    temp = mipsdsp_sat32_acc_q31(ac, temp, env);                  \
2776                                                                  \
2777    acc[0] = (int64_t)(int32_t)temp;                              \
2778    if (acc[0] >= 0) {                                            \
2779        acc[1] = 0x00;                                            \
2780    } else {                                                      \
2781        acc[1] = ~0ull;                                           \
2782    }                                                             \
2783                                                                  \
2784    env->active_tc.HI[ac] = acc[1];                               \
2785    env->active_tc.LO[ac] = acc[0];                               \
2786}
2787
2788MAQ_SA_W(maq_sa_w_qhll, 48);
2789MAQ_SA_W(maq_sa_w_qhlr, 32);
2790MAQ_SA_W(maq_sa_w_qhrl, 16);
2791MAQ_SA_W(maq_sa_w_qhrr, 0);
2792
2793#undef MAQ_SA_W
2794
2795#define MAQ_S_L_PW(name, mov) \
2796void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2797                   CPUMIPSState *env)                             \
2798{                                                                 \
2799    int32_t rs_t, rt_t;                                           \
2800    int64_t temp[2];                                              \
2801    int64_t acc[2];                                               \
2802    int64_t temp_sum;                                             \
2803                                                                  \
2804    temp[0] = 0;                                                  \
2805    temp[1] = 0;                                                  \
2806                                                                  \
2807    rs_t = (rs >> mov) & MIPSDSP_LLO;                             \
2808    rt_t = (rt >> mov) & MIPSDSP_LLO;                             \
2809                                                                  \
2810    temp[0] = mipsdsp_mul_q31_q31(ac, rs_t, rt_t, env);           \
2811    if (temp[0] >= 0) {                                           \
2812        temp[1] = 0x00;                                           \
2813    } else {                                                      \
2814        temp[1] = ~0ull;                                          \
2815    }                                                             \
2816                                                                  \
2817    acc[0] = env->active_tc.LO[ac];                               \
2818    acc[1] = env->active_tc.HI[ac];                               \
2819                                                                  \
2820    temp_sum = acc[0] + temp[0];                                  \
2821    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&                \
2822        ((uint64_t)temp_sum < (uint64_t)temp[0])) {               \
2823        acc[1] += 1;                                              \
2824    }                                                             \
2825    acc[0] = temp_sum;                                            \
2826    acc[1] += temp[1];                                            \
2827                                                                  \
2828    env->active_tc.HI[ac] = acc[1];                               \
2829    env->active_tc.LO[ac] = acc[0];                               \
2830}
2831
2832MAQ_S_L_PW(maq_s_l_pwl, 32);
2833MAQ_S_L_PW(maq_s_l_pwr, 0);
2834
2835#undef MAQ_S_L_PW
2836
2837#define DM_OPERATE(name, func, is_add, sigext) \
2838void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,    \
2839                  CPUMIPSState *env)                                 \
2840{                                                                    \
2841    int32_t rs1, rs0;                                                \
2842    int32_t rt1, rt0;                                                \
2843    int64_t tempBL[2], tempAL[2];                                    \
2844    int64_t acc[2];                                                  \
2845    int64_t temp[2];                                                 \
2846    int64_t temp_sum;                                                \
2847                                                                     \
2848    temp[0] = 0x00;                                                  \
2849    temp[1] = 0x00;                                                  \
2850                                                                     \
2851    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                                \
2852    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                                \
2853                                                                     \
2854    if (sigext) {                                                    \
2855        tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1);               \
2856        tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0);               \
2857                                                                     \
2858        if (tempBL[0] >= 0) {                                        \
2859            tempBL[1] = 0x0;                                         \
2860        } else {                                                     \
2861            tempBL[1] = ~0ull;                                       \
2862        }                                                            \
2863                                                                     \
2864        if (tempAL[0] >= 0) {                                        \
2865            tempAL[1] = 0x0;                                         \
2866        } else {                                                     \
2867            tempAL[1] = ~0ull;                                       \
2868        }                                                            \
2869    } else {                                                         \
2870        tempBL[0] = mipsdsp_##func(rs1, rt1);                        \
2871        tempAL[0] = mipsdsp_##func(rs0, rt0);                        \
2872        tempBL[1] = 0;                                               \
2873        tempAL[1] = 0;                                               \
2874    }                                                                \
2875                                                                     \
2876    acc[1] = env->active_tc.HI[ac];                                  \
2877    acc[0] = env->active_tc.LO[ac];                                  \
2878                                                                     \
2879    temp_sum = tempBL[0] + tempAL[0];                                \
2880    if (((uint64_t)temp_sum < (uint64_t)tempBL[0]) &&                \
2881        ((uint64_t)temp_sum < (uint64_t)tempAL[0])) {                \
2882        temp[1] += 1;                                                \
2883    }                                                                \
2884    temp[0] = temp_sum;                                              \
2885    temp[1] += tempBL[1] + tempAL[1];                                \
2886                                                                     \
2887    if (is_add) {                                                    \
2888        temp_sum = acc[0] + temp[0];                                 \
2889        if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&               \
2890            ((uint64_t)temp_sum < (uint64_t)temp[0])) {              \
2891            acc[1] += 1;                                             \
2892        }                                                            \
2893        temp[0] = temp_sum;                                          \
2894        temp[1] = acc[1] + temp[1];                                  \
2895    } else {                                                         \
2896        temp_sum = acc[0] - temp[0];                                 \
2897        if ((uint64_t)temp_sum > (uint64_t)acc[0]) {                 \
2898            acc[1] -= 1;                                             \
2899        }                                                            \
2900        temp[0] = temp_sum;                                          \
2901        temp[1] = acc[1] - temp[1];                                  \
2902    }                                                                \
2903                                                                     \
2904    env->active_tc.HI[ac] = temp[1];                                 \
2905    env->active_tc.LO[ac] = temp[0];                                 \
2906}
2907
2908DM_OPERATE(dmadd, mul_i32_i32, 1, 1);
2909DM_OPERATE(dmaddu, mul_u32_u32, 1, 0);
2910DM_OPERATE(dmsub, mul_i32_i32, 0, 1);
2911DM_OPERATE(dmsubu, mul_u32_u32, 0, 0);
2912#undef DM_OPERATE
2913#endif
2914
2915/** DSP Bit/Manipulation Sub-class insns **/
2916target_ulong helper_bitrev(target_ulong rt)
2917{
2918    int32_t temp;
2919    uint32_t rd;
2920    int i;
2921
2922    temp = rt & MIPSDSP_LO;
2923    rd = 0;
2924    for (i = 0; i < 16; i++) {
2925        rd = (rd << 1) | (temp & 1);
2926        temp = temp >> 1;
2927    }
2928
2929    return (target_ulong)rd;
2930}
2931
2932#define BIT_INSV(name, posfilter, sizefilter, ret_type)         \
2933target_ulong helper_##name(CPUMIPSState *env, target_ulong rs,  \
2934                           target_ulong rt)                     \
2935{                                                               \
2936    uint32_t pos, size, msb, lsb;                               \
2937    target_ulong filter;                                        \
2938    target_ulong temp, temprs, temprt;                          \
2939    target_ulong dspc;                                          \
2940                                                                \
2941    dspc = env->active_tc.DSPControl;                           \
2942                                                                \
2943    pos  = dspc & posfilter;                                    \
2944    size = (dspc >> 7) & sizefilter;                            \
2945                                                                \
2946    msb  = pos + size - 1;                                      \
2947    lsb  = pos;                                                 \
2948                                                                \
2949    if (lsb > msb || (msb > TARGET_LONG_BITS)) {                \
2950        return rt;                                              \
2951    }                                                           \
2952                                                                \
2953    filter = ((int32_t)0x01 << size) - 1;                       \
2954    filter = filter << pos;                                     \
2955    temprs = (rs << pos) & filter;                              \
2956    temprt = rt & ~filter;                                      \
2957    temp = temprs | temprt;                                     \
2958                                                                \
2959    return (target_long)(ret_type)temp;                         \
2960}
2961
2962BIT_INSV(insv, 0x1F, 0x1F, int32_t);
2963#ifdef TARGET_MIPS64
2964BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
2965#endif
2966
2967#undef BIT_INSV
2968
2969
2970/** DSP Compare-Pick Sub-class insns **/
2971#define CMP_HAS_RET(name, func, split_num, filter, bit_size) \
2972target_ulong helper_##name(target_ulong rs, target_ulong rt) \
2973{                                                       \
2974    uint32_t rs_t, rt_t;                                \
2975    uint8_t cc;                                         \
2976    uint32_t temp = 0;                                  \
2977    int i;                                              \
2978                                                        \
2979    for (i = 0; i < split_num; i++) {                   \
2980        rs_t = (rs >> (bit_size * i)) & filter;         \
2981        rt_t = (rt >> (bit_size * i)) & filter;         \
2982        cc = mipsdsp_##func(rs_t, rt_t);                \
2983        temp |= cc << i;                                \
2984    }                                                   \
2985                                                        \
2986    return (target_ulong)temp;                          \
2987}
2988
2989CMP_HAS_RET(cmpgu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8);
2990CMP_HAS_RET(cmpgu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8);
2991CMP_HAS_RET(cmpgu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8);
2992
2993#ifdef TARGET_MIPS64
2994CMP_HAS_RET(cmpgu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8);
2995CMP_HAS_RET(cmpgu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8);
2996CMP_HAS_RET(cmpgu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8);
2997#endif
2998
2999#undef CMP_HAS_RET
3000
3001
3002#define CMP_NO_RET(name, func, split_num, filter, bit_size) \
3003void helper_##name(target_ulong rs, target_ulong rt,        \
3004                            CPUMIPSState *env)              \
3005{                                                           \
3006    int##bit_size##_t rs_t, rt_t;                           \
3007    int##bit_size##_t flag = 0;                             \
3008    int##bit_size##_t cc;                                   \
3009    int i;                                                  \
3010                                                            \
3011    for (i = 0; i < split_num; i++) {                       \
3012        rs_t = (rs >> (bit_size * i)) & filter;             \
3013        rt_t = (rt >> (bit_size * i)) & filter;             \
3014                                                            \
3015        cc = mipsdsp_##func((int32_t)rs_t, (int32_t)rt_t);  \
3016        flag |= cc << i;                                    \
3017    }                                                       \
3018                                                            \
3019    set_DSPControl_24(flag, split_num, env);                \
3020}
3021
3022CMP_NO_RET(cmpu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8);
3023CMP_NO_RET(cmpu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8);
3024CMP_NO_RET(cmpu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8);
3025
3026CMP_NO_RET(cmp_eq_ph, cmp_eq, 2, MIPSDSP_LO, 16);
3027CMP_NO_RET(cmp_lt_ph, cmp_lt, 2, MIPSDSP_LO, 16);
3028CMP_NO_RET(cmp_le_ph, cmp_le, 2, MIPSDSP_LO, 16);
3029
3030#ifdef TARGET_MIPS64
3031CMP_NO_RET(cmpu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8);
3032CMP_NO_RET(cmpu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8);
3033CMP_NO_RET(cmpu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8);
3034
3035CMP_NO_RET(cmp_eq_qh, cmp_eq, 4, MIPSDSP_LO, 16);
3036CMP_NO_RET(cmp_lt_qh, cmp_lt, 4, MIPSDSP_LO, 16);
3037CMP_NO_RET(cmp_le_qh, cmp_le, 4, MIPSDSP_LO, 16);
3038
3039CMP_NO_RET(cmp_eq_pw, cmp_eq, 2, MIPSDSP_LLO, 32);
3040CMP_NO_RET(cmp_lt_pw, cmp_lt, 2, MIPSDSP_LLO, 32);
3041CMP_NO_RET(cmp_le_pw, cmp_le, 2, MIPSDSP_LLO, 32);
3042#endif
3043#undef CMP_NO_RET
3044
3045#if defined(TARGET_MIPS64)
3046
3047#define CMPGDU_OB(name) \
3048target_ulong helper_cmpgdu_##name##_ob(target_ulong rs, target_ulong rt, \
3049                                       CPUMIPSState *env)  \
3050{                                                     \
3051    int i;                                            \
3052    uint8_t rs_t, rt_t;                               \
3053    uint32_t cond;                                    \
3054                                                      \
3055    cond = 0;                                         \
3056                                                      \
3057    for (i = 0; i < 8; i++) {                         \
3058        rs_t = (rs >> (8 * i)) & MIPSDSP_Q0;          \
3059        rt_t = (rt >> (8 * i)) & MIPSDSP_Q0;          \
3060                                                      \
3061        if (mipsdsp_cmpu_##name(rs_t, rt_t)) {        \
3062            cond |= 0x01 << i;                        \
3063        }                                             \
3064    }                                                 \
3065                                                      \
3066    set_DSPControl_24(cond, 8, env);                  \
3067                                                      \
3068    return (uint64_t)cond;                            \
3069}
3070
3071CMPGDU_OB(eq)
3072CMPGDU_OB(lt)
3073CMPGDU_OB(le)
3074#undef CMPGDU_OB
3075#endif
3076
3077#define PICK_INSN(name, split_num, filter, bit_size, ret32bit) \
3078target_ulong helper_##name(target_ulong rs, target_ulong rt,   \
3079                            CPUMIPSState *env)                 \
3080{                                                              \
3081    uint32_t rs_t, rt_t;                                       \
3082    uint32_t cc;                                               \
3083    target_ulong dsp;                                          \
3084    int i;                                                     \
3085    target_ulong result = 0;                                   \
3086                                                               \
3087    dsp = env->active_tc.DSPControl;                           \
3088    for (i = 0; i < split_num; i++) {                          \
3089        rs_t = (rs >> (bit_size * i)) & filter;                \
3090        rt_t = (rt >> (bit_size * i)) & filter;                \
3091        cc = (dsp >> (24 + i)) & 0x01;                         \
3092        cc = cc == 1 ? rs_t : rt_t;                            \
3093                                                               \
3094        result |= (target_ulong)cc << (bit_size * i);          \
3095    }                                                          \
3096                                                               \
3097    if (ret32bit) {                                            \
3098        result = (target_long)(int32_t)(result & MIPSDSP_LLO); \
3099    }                                                          \
3100                                                               \
3101    return result;                                             \
3102}
3103
3104PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1);
3105PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1);
3106
3107#ifdef TARGET_MIPS64
3108PICK_INSN(pick_ob, 8, MIPSDSP_Q0, 8, 0);
3109PICK_INSN(pick_qh, 4, MIPSDSP_LO, 16, 0);
3110PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0);
3111#endif
3112#undef PICK_INSN
3113
3114target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt)
3115{
3116    uint32_t rsl, rth;
3117
3118    rsl =  rs & MIPSDSP_LO;
3119    rth = (rt & MIPSDSP_HI) >> 16;
3120
3121    return (target_long)(int32_t)((rsl << 16) | rth);
3122}
3123
3124#if defined(TARGET_MIPS64)
3125target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt)
3126{
3127    uint32_t rs0, rt1;
3128
3129    rs0 = rs & MIPSDSP_LLO;
3130    rt1 = (rt >> 32) & MIPSDSP_LLO;
3131
3132    return ((uint64_t)rs0 << 32) | (uint64_t)rt1;
3133}
3134#endif
3135
3136/** DSP Accumulator and DSPControl Access Sub-class insns **/
3137target_ulong helper_extr_w(target_ulong ac, target_ulong shift,
3138                           CPUMIPSState *env)
3139{
3140    int32_t tempI;
3141    int64_t tempDL[2];
3142
3143    shift = shift & 0x1F;
3144
3145    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
3146    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3147        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3148        set_DSPControl_overflow_flag(1, 23, env);
3149    }
3150
3151    tempI = (tempDL[0] >> 1) & MIPSDSP_LLO;
3152
3153    tempDL[0] += 1;
3154    if (tempDL[0] == 0) {
3155        tempDL[1] += 1;
3156    }
3157
3158    if ((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) &&
3159        (!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI))) {
3160        set_DSPControl_overflow_flag(1, 23, env);
3161    }
3162
3163    return (target_long)tempI;
3164}
3165
3166target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
3167                             CPUMIPSState *env)
3168{
3169    int64_t tempDL[2];
3170
3171    shift = shift & 0x1F;
3172
3173    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
3174    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3175        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3176        set_DSPControl_overflow_flag(1, 23, env);
3177    }
3178
3179    tempDL[0] += 1;
3180    if (tempDL[0] == 0) {
3181        tempDL[1] += 1;
3182    }
3183
3184    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3185        (tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3186        set_DSPControl_overflow_flag(1, 23, env);
3187    }
3188
3189    return (target_long)(int32_t)(tempDL[0] >> 1);
3190}
3191
3192target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
3193                              CPUMIPSState *env)
3194{
3195    int32_t tempI, temp64;
3196    int64_t tempDL[2];
3197
3198    shift = shift & 0x1F;
3199
3200    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
3201    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3202        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3203        set_DSPControl_overflow_flag(1, 23, env);
3204    }
3205    tempDL[0] += 1;
3206    if (tempDL[0] == 0) {
3207        tempDL[1] += 1;
3208    }
3209    tempI = tempDL[0] >> 1;
3210
3211    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3212        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3213        temp64 = tempDL[1];
3214        if (temp64 == 0) {
3215            tempI = 0x7FFFFFFF;
3216        } else {
3217            tempI = 0x80000000;
3218        }
3219        set_DSPControl_overflow_flag(1, 23, env);
3220    }
3221
3222    return (target_long)tempI;
3223}
3224
3225#if defined(TARGET_MIPS64)
3226target_ulong helper_dextr_w(target_ulong ac, target_ulong shift,
3227                            CPUMIPSState *env)
3228{
3229    uint64_t temp[3];
3230
3231    shift = shift & 0x3F;
3232
3233    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3234
3235    return (int64_t)(int32_t)(temp[0] >> 1);
3236}
3237
3238target_ulong helper_dextr_r_w(target_ulong ac, target_ulong shift,
3239                              CPUMIPSState *env)
3240{
3241    uint64_t temp[3];
3242    uint32_t temp128;
3243
3244    shift = shift & 0x3F;
3245    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3246
3247    temp[0] += 1;
3248    if (temp[0] == 0) {
3249        temp[1] += 1;
3250        if (temp[1] == 0) {
3251            temp[2] += 1;
3252        }
3253    }
3254
3255    temp128 = temp[2] & 0x01;
3256
3257    if ((temp128 != 0 || temp[1] != 0) &&
3258       (temp128 != 1 || temp[1] != ~0ull)) {
3259        set_DSPControl_overflow_flag(1, 23, env);
3260    }
3261
3262    return (int64_t)(int32_t)(temp[0] >> 1);
3263}
3264
3265target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift,
3266                               CPUMIPSState *env)
3267{
3268    uint64_t temp[3];
3269    uint32_t temp128;
3270
3271    shift = shift & 0x3F;
3272    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3273
3274    temp[0] += 1;
3275    if (temp[0] == 0) {
3276        temp[1] += 1;
3277        if (temp[1] == 0) {
3278            temp[2] += 1;
3279        }
3280    }
3281
3282    temp128 = temp[2] & 0x01;
3283
3284    if ((temp128 != 0 || temp[1] != 0) &&
3285       (temp128 != 1 || temp[1] != ~0ull)) {
3286        if (temp128 == 0) {
3287            temp[0] = 0x0FFFFFFFF;
3288        } else {
3289            temp[0] = 0x0100000000ULL;
3290        }
3291        set_DSPControl_overflow_flag(1, 23, env);
3292    }
3293
3294    return (int64_t)(int32_t)(temp[0] >> 1);
3295}
3296
3297target_ulong helper_dextr_l(target_ulong ac, target_ulong shift,
3298                            CPUMIPSState *env)
3299{
3300    uint64_t temp[3];
3301    target_ulong result;
3302
3303    shift = shift & 0x3F;
3304
3305    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3306    result = (temp[1] << 63) | (temp[0] >> 1);
3307
3308    return result;
3309}
3310
3311target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift,
3312                              CPUMIPSState *env)
3313{
3314    uint64_t temp[3];
3315    uint32_t temp128;
3316    target_ulong result;
3317
3318    shift = shift & 0x3F;
3319    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3320
3321    temp[0] += 1;
3322    if (temp[0] == 0) {
3323        temp[1] += 1;
3324        if (temp[1] == 0) {
3325            temp[2] += 1;
3326        }
3327    }
3328
3329    temp128 = temp[2] & 0x01;
3330
3331    if ((temp128 != 0 || temp[1] != 0) &&
3332       (temp128 != 1 || temp[1] != ~0ull)) {
3333        set_DSPControl_overflow_flag(1, 23, env);
3334    }
3335
3336    result = (temp[1] << 63) | (temp[0] >> 1);
3337
3338    return result;
3339}
3340
3341target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift,
3342                               CPUMIPSState *env)
3343{
3344    uint64_t temp[3];
3345    uint32_t temp128;
3346    target_ulong result;
3347
3348    shift = shift & 0x3F;
3349    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3350
3351    temp[0] += 1;
3352    if (temp[0] == 0) {
3353        temp[1] += 1;
3354        if (temp[1] == 0) {
3355            temp[2] += 1;
3356        }
3357    }
3358
3359    temp128 = temp[2] & 0x01;
3360
3361    if ((temp128 != 0 || temp[1] != 0) &&
3362       (temp128 != 1 || temp[1] != ~0ull)) {
3363        if (temp128 == 0) {
3364            temp[1] &= ~0x00ull - 1;
3365            temp[0] |= ~0x00ull - 1;
3366        } else {
3367            temp[1] |= 0x01;
3368            temp[0] &= 0x01;
3369        }
3370        set_DSPControl_overflow_flag(1, 23, env);
3371    }
3372    result = (temp[1] << 63) | (temp[0] >> 1);
3373
3374    return result;
3375}
3376#endif
3377
3378target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift,
3379                             CPUMIPSState *env)
3380{
3381    int64_t temp, acc;
3382
3383    shift = shift & 0x1F;
3384
3385    acc = ((int64_t)env->active_tc.HI[ac] << 32) |
3386          ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
3387
3388    temp = acc >> shift;
3389
3390    if (temp > (int64_t)0x7FFF) {
3391        temp = 0x00007FFF;
3392        set_DSPControl_overflow_flag(1, 23, env);
3393    } else if (temp < (int64_t)0xFFFFFFFFFFFF8000ULL) {
3394        temp = 0xFFFF8000;
3395        set_DSPControl_overflow_flag(1, 23, env);
3396    }
3397
3398    return (target_long)(int32_t)(temp & 0xFFFFFFFF);
3399}
3400
3401
3402#if defined(TARGET_MIPS64)
3403target_ulong helper_dextr_s_h(target_ulong ac, target_ulong shift,
3404                              CPUMIPSState *env)
3405{
3406    int64_t temp[2];
3407    uint32_t temp127;
3408
3409    shift = shift & 0x1F;
3410
3411    mipsdsp_rashift_acc((uint64_t *)temp, ac, shift, env);
3412
3413    temp127 = (temp[1] >> 63) & 0x01;
3414
3415    if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) {
3416        temp[0] &= 0xFFFF0000;
3417        temp[0] |= 0x00007FFF;
3418        set_DSPControl_overflow_flag(1, 23, env);
3419    } else if ((temp127 == 1) &&
3420            (temp[1] < 0xFFFFFFFFFFFFFFFFll
3421             || temp[0] < 0xFFFFFFFFFFFF1000ll)) {
3422        temp[0] &= 0xFFFF0000;
3423        temp[0] |= 0x00008000;
3424        set_DSPControl_overflow_flag(1, 23, env);
3425    }
3426
3427    return (int64_t)(int16_t)(temp[0] & MIPSDSP_LO);
3428}
3429
3430#endif
3431
3432target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState *env)
3433{
3434    int32_t start_pos;
3435    int sub;
3436    uint32_t temp;
3437    uint64_t acc;
3438
3439    size = size & 0x1F;
3440
3441    temp = 0;
3442    start_pos = get_DSPControl_pos(env);
3443    sub = start_pos - (size + 1);
3444    if (sub >= -1) {
3445        acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
3446              ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
3447        temp = (acc >> (start_pos - size)) &
3448               (((uint32_t)0x01 << (size + 1)) - 1);
3449        set_DSPControl_efi(0, env);
3450    } else {
3451        set_DSPControl_efi(1, env);
3452    }
3453
3454    return (target_ulong)temp;
3455}
3456
3457target_ulong helper_extpdp(target_ulong ac, target_ulong size,
3458                           CPUMIPSState *env)
3459{
3460    int32_t start_pos;
3461    int sub;
3462    uint32_t temp;
3463    uint64_t acc;
3464
3465    size = size & 0x1F;
3466    temp = 0;
3467    start_pos = get_DSPControl_pos(env);
3468    sub = start_pos - (size + 1);
3469    if (sub >= -1) {
3470        acc  = ((uint64_t)env->active_tc.HI[ac] << 32) |
3471               ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
3472        temp = (acc >> (start_pos - size)) &
3473               (((uint32_t)0x01 << (size + 1)) - 1);
3474
3475        set_DSPControl_pos(start_pos - (size + 1), env);
3476        set_DSPControl_efi(0, env);
3477    } else {
3478        set_DSPControl_efi(1, env);
3479    }
3480
3481    return (target_ulong)temp;
3482}
3483
3484
3485#if defined(TARGET_MIPS64)
3486target_ulong helper_dextp(target_ulong ac, target_ulong size, CPUMIPSState *env)
3487{
3488    int start_pos;
3489    int len;
3490    int sub;
3491    uint64_t tempB, tempA;
3492    uint64_t temp;
3493
3494    temp = 0;
3495
3496    size = size & 0x3F;
3497    start_pos = get_DSPControl_pos(env);
3498    len = start_pos - size;
3499    tempB = env->active_tc.HI[ac];
3500    tempA = env->active_tc.LO[ac];
3501
3502    sub = start_pos - (size + 1);
3503
3504    if (sub >= -1) {
3505        temp = (tempB << (64 - len)) | (tempA >> len);
3506        temp = temp & ((0x01 << (size + 1)) - 1);
3507        set_DSPControl_efi(0, env);
3508    } else {
3509        set_DSPControl_efi(1, env);
3510    }
3511
3512    return temp;
3513}
3514
3515target_ulong helper_dextpdp(target_ulong ac, target_ulong size,
3516                            CPUMIPSState *env)
3517{
3518    int start_pos;
3519    int len;
3520    int sub;
3521    uint64_t tempB, tempA;
3522    uint64_t temp;
3523
3524    temp = 0;
3525    size = size & 0x3F;
3526    start_pos = get_DSPControl_pos(env);
3527    len = start_pos - size;
3528    tempB = env->active_tc.HI[ac];
3529    tempA = env->active_tc.LO[ac];
3530
3531    sub = start_pos - (size + 1);
3532
3533    if (sub >= -1) {
3534        temp = (tempB << (64 - len)) | (tempA >> len);
3535        temp = temp & ((0x01 << (size + 1)) - 1);
3536        set_DSPControl_pos(sub, env);
3537        set_DSPControl_efi(0, env);
3538    } else {
3539        set_DSPControl_efi(1, env);
3540    }
3541
3542    return temp;
3543}
3544
3545#endif
3546
3547void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env)
3548{
3549    int8_t  rs5_0;
3550    uint64_t temp, acc;
3551
3552    rs5_0 = rs & 0x3F;
3553    rs5_0 = (int8_t)(rs5_0 << 2) >> 2;
3554
3555    if (unlikely(rs5_0 == 0)) {
3556        return;
3557    }
3558
3559    acc   = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) |
3560            ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
3561
3562    if (rs5_0 > 0) {
3563        temp = acc >> rs5_0;
3564    } else {
3565        temp = acc << -rs5_0;
3566    }
3567
3568    env->active_tc.HI[ac] = (target_ulong)(int32_t)((temp & MIPSDSP_LHI) >> 32);
3569    env->active_tc.LO[ac] = (target_ulong)(int32_t)(temp & MIPSDSP_LLO);
3570}
3571
3572#if defined(TARGET_MIPS64)
3573void helper_dshilo(target_ulong shift, target_ulong ac, CPUMIPSState *env)
3574{
3575    int8_t shift_t;
3576    uint64_t tempB, tempA;
3577
3578    shift_t = (int8_t)(shift << 1) >> 1;
3579
3580    tempB = env->active_tc.HI[ac];
3581    tempA = env->active_tc.LO[ac];
3582
3583    if (shift_t != 0) {
3584        if (shift_t >= 0) {
3585            tempA = (tempB << (64 - shift_t)) | (tempA >> shift_t);
3586            tempB = tempB >> shift_t;
3587        } else {
3588            shift_t = -shift_t;
3589            tempB = (tempB << shift_t) | (tempA >> (64 - shift_t));
3590            tempA = tempA << shift_t;
3591        }
3592    }
3593
3594    env->active_tc.HI[ac] = tempB;
3595    env->active_tc.LO[ac] = tempA;
3596}
3597
3598#endif
3599void helper_mthlip(target_ulong ac, target_ulong rs, CPUMIPSState *env)
3600{
3601    int32_t tempA, tempB, pos;
3602
3603    tempA = rs;
3604    tempB = env->active_tc.LO[ac];
3605    env->active_tc.HI[ac] = (target_long)tempB;
3606    env->active_tc.LO[ac] = (target_long)tempA;
3607    pos = get_DSPControl_pos(env);
3608
3609    if (pos > 32) {
3610        return;
3611    } else {
3612        set_DSPControl_pos(pos + 32, env);
3613    }
3614}
3615
3616#if defined(TARGET_MIPS64)
3617void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env)
3618{
3619    uint8_t ac_t;
3620    uint8_t pos;
3621    uint64_t tempB, tempA;
3622
3623    ac_t = ac & 0x3;
3624
3625    tempA = rs;
3626    tempB = env->active_tc.LO[ac_t];
3627
3628    env->active_tc.HI[ac_t] = tempB;
3629    env->active_tc.LO[ac_t] = tempA;
3630
3631    pos = get_DSPControl_pos(env);
3632
3633    if (pos <= 64) {
3634        pos = pos + 64;
3635        set_DSPControl_pos(pos, env);
3636    }
3637}
3638#endif
3639
3640void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
3641{
3642    uint8_t  mask[6];
3643    uint8_t  i;
3644    uint32_t newbits, overwrite;
3645    target_ulong dsp;
3646
3647    newbits   = 0x00;
3648    overwrite = 0xFFFFFFFF;
3649    dsp = env->active_tc.DSPControl;
3650
3651    for (i = 0; i < 6; i++) {
3652        mask[i] = (mask_num >> i) & 0x01;
3653    }
3654
3655    if (mask[0] == 1) {
3656#if defined(TARGET_MIPS64)
3657        overwrite &= 0xFFFFFF80;
3658        newbits   &= 0xFFFFFF80;
3659        newbits   |= 0x0000007F & rs;
3660#else
3661        overwrite &= 0xFFFFFFC0;
3662        newbits   &= 0xFFFFFFC0;
3663        newbits   |= 0x0000003F & rs;
3664#endif
3665    }
3666
3667    if (mask[1] == 1) {
3668        overwrite &= 0xFFFFE07F;
3669        newbits   &= 0xFFFFE07F;
3670        newbits   |= 0x00001F80 & rs;
3671    }
3672
3673    if (mask[2] == 1) {
3674        overwrite &= 0xFFFFDFFF;
3675        newbits   &= 0xFFFFDFFF;
3676        newbits   |= 0x00002000 & rs;
3677    }
3678
3679    if (mask[3] == 1) {
3680        overwrite &= 0xFF00FFFF;
3681        newbits   &= 0xFF00FFFF;
3682        newbits   |= 0x00FF0000 & rs;
3683    }
3684
3685    if (mask[4] == 1) {
3686        overwrite &= 0x00FFFFFF;
3687        newbits   &= 0x00FFFFFF;
3688#if defined(TARGET_MIPS64)
3689        newbits   |= 0xFF000000 & rs;
3690#else
3691        newbits   |= 0x0F000000 & rs;
3692#endif
3693    }
3694
3695    if (mask[5] == 1) {
3696        overwrite &= 0xFFFFBFFF;
3697        newbits   &= 0xFFFFBFFF;
3698        newbits   |= 0x00004000 & rs;
3699    }
3700
3701    dsp = dsp & overwrite;
3702    dsp = dsp | newbits;
3703    env->active_tc.DSPControl = dsp;
3704}
3705
3706target_ulong helper_rddsp(target_ulong masknum, CPUMIPSState *env)
3707{
3708    uint8_t  mask[6];
3709    uint32_t ruler, i;
3710    target_ulong temp;
3711    target_ulong dsp;
3712
3713    ruler = 0x01;
3714    for (i = 0; i < 6; i++) {
3715        mask[i] = (masknum & ruler) >> i ;
3716        ruler = ruler << 1;
3717    }
3718
3719    temp  = 0x00;
3720    dsp = env->active_tc.DSPControl;
3721
3722    if (mask[0] == 1) {
3723#if defined(TARGET_MIPS64)
3724        temp |= dsp & 0x7F;
3725#else
3726        temp |= dsp & 0x3F;
3727#endif
3728    }
3729
3730    if (mask[1] == 1) {
3731        temp |= dsp & 0x1F80;
3732    }
3733
3734    if (mask[2] == 1) {
3735        temp |= dsp & 0x2000;
3736    }
3737
3738    if (mask[3] == 1) {
3739        temp |= dsp & 0x00FF0000;
3740    }
3741
3742    if (mask[4] == 1) {
3743#if defined(TARGET_MIPS64)
3744        temp |= dsp & 0xFF000000;
3745#else
3746        temp |= dsp & 0x0F000000;
3747#endif
3748    }
3749
3750    if (mask[5] == 1) {
3751        temp |= dsp & 0x4000;
3752    }
3753
3754    return temp;
3755}
3756
3757
3758#undef MIPSDSP_LHI
3759#undef MIPSDSP_LLO
3760#undef MIPSDSP_HI
3761#undef MIPSDSP_LO
3762#undef MIPSDSP_Q3
3763#undef MIPSDSP_Q2
3764#undef MIPSDSP_Q1
3765#undef MIPSDSP_Q0
3766
3767#undef MIPSDSP_SPLIT32_8
3768#undef MIPSDSP_SPLIT32_16
3769
3770#undef MIPSDSP_RETURN32_8
3771#undef MIPSDSP_RETURN32_16
3772
3773#ifdef TARGET_MIPS64
3774#undef MIPSDSP_SPLIT64_16
3775#undef MIPSDSP_SPLIT64_32
3776#undef MIPSDSP_RETURN64_16
3777#undef MIPSDSP_RETURN64_32
3778#endif
3779