qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

dsp_helper.c (138436B)


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