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