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