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