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