cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

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