Statistics
| Branch: | Revision:

root / target-mips / dsp_helper.c @ b53371ed

History | View | Annotate | Download (143.6 kB)

1
/*
2
 * MIPS ASE DSP Instruction emulation helpers for QEMU.
3
 *
4
 * Copyright (c) 2012  Jia Liu <proljc@gmail.com>
5
 *                     Dongxue Zhang <elat.era@gmail.com>
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19

    
20
#include "cpu.h"
21
#include "helper.h"
22

    
23
/*** MIPS DSP internal functions begin ***/
24
#define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x)
25
#define MIPSDSP_OVERFLOW(a, b, c, d) (!(!((a ^ b ^ -1) & (a ^ c) & d)))
26

    
27
static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
28
                                                CPUMIPSState *env)
29
{
30
    env->active_tc.DSPControl |= (target_ulong)flag << position;
31
}
32

    
33
static inline void set_DSPControl_carryflag(uint32_t flag, CPUMIPSState *env)
34
{
35
    env->active_tc.DSPControl |= (target_ulong)flag << 13;
36
}
37

    
38
static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
39
{
40
    return (env->active_tc.DSPControl >> 13) & 0x01;
41
}
42

    
43
static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env)
44
{
45
  uint32_t filter;
46

    
47
  filter = ((0x01 << len) - 1) << 24;
48
  filter = ~filter;
49

    
50
  env->active_tc.DSPControl &= filter;
51
  env->active_tc.DSPControl |= (target_ulong)flag << 24;
52
}
53

    
54
static inline uint32_t get_DSPControl_24(int len, CPUMIPSState *env)
55
{
56
  uint32_t filter;
57

    
58
  filter = (0x01 << len) - 1;
59

    
60
  return (env->active_tc.DSPControl >> 24) & filter;
61
}
62

    
63
static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env)
64
{
65
    target_ulong dspc;
66

    
67
    dspc = env->active_tc.DSPControl;
68
#ifndef TARGET_MIPS64
69
    dspc = dspc & 0xFFFFFFC0;
70
    dspc |= pos;
71
#else
72
    dspc = dspc & 0xFFFFFF80;
73
    dspc |= pos;
74
#endif
75
    env->active_tc.DSPControl = dspc;
76
}
77

    
78
static inline uint32_t get_DSPControl_pos(CPUMIPSState *env)
79
{
80
    target_ulong dspc;
81
    uint32_t pos;
82

    
83
    dspc = env->active_tc.DSPControl;
84

    
85
#ifndef TARGET_MIPS64
86
    pos = dspc & 0x3F;
87
#else
88
    pos = dspc & 0x7F;
89
#endif
90

    
91
    return pos;
92
}
93

    
94
static inline void set_DSPControl_efi(uint32_t flag, CPUMIPSState *env)
95
{
96
    env->active_tc.DSPControl &= 0xFFFFBFFF;
97
    env->active_tc.DSPControl |= (target_ulong)flag << 14;
98
}
99

    
100
#define DO_MIPS_SAT_ABS(size)                                          \
101
static inline int##size##_t mipsdsp_sat_abs##size(int##size##_t a,         \
102
                                                  CPUMIPSState *env)   \
103
{                                                                      \
104
    if (a == INT##size##_MIN) {                                        \
105
        set_DSPControl_overflow_flag(1, 20, env);                      \
106
        return INT##size##_MAX;                                        \
107
    } else {                                                           \
108
        return MIPSDSP_ABS(a);                                         \
109
    }                                                                  \
110
}
111
DO_MIPS_SAT_ABS(8)
112
DO_MIPS_SAT_ABS(16)
113
DO_MIPS_SAT_ABS(32)
114
#undef DO_MIPS_SAT_ABS
115

    
116
/* get sum value */
117
static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env)
118
{
119
    int16_t tempI;
120

    
121
    tempI = a + b;
122

    
123
    if (MIPSDSP_OVERFLOW(a, b, tempI, 0x8000)) {
124
        set_DSPControl_overflow_flag(1, 20, env);
125
    }
126

    
127
    return tempI;
128
}
129

    
130
static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b,
131
                                          CPUMIPSState *env)
132
{
133
    int16_t tempS;
134

    
135
    tempS = a + b;
136

    
137
    if (MIPSDSP_OVERFLOW(a, b, tempS, 0x8000)) {
138
        if (a > 0) {
139
            tempS = 0x7FFF;
140
        } else {
141
            tempS = 0x8000;
142
        }
143
        set_DSPControl_overflow_flag(1, 20, env);
144
    }
145

    
146
    return tempS;
147
}
148

    
149
static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b,
150
                                          CPUMIPSState *env)
151
{
152
    int32_t tempI;
153

    
154
    tempI = a + b;
155

    
156
    if (MIPSDSP_OVERFLOW(a, b, tempI, 0x80000000)) {
157
        if (a > 0) {
158
            tempI = 0x7FFFFFFF;
159
        } else {
160
            tempI = 0x80000000;
161
        }
162
        set_DSPControl_overflow_flag(1, 20, env);
163
    }
164

    
165
    return tempI;
166
}
167

    
168
static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
169
{
170
    uint16_t temp;
171

    
172
    temp = (uint16_t)a + (uint16_t)b;
173

    
174
    if (temp & 0x0100) {
175
        set_DSPControl_overflow_flag(1, 20, env);
176
    }
177

    
178
    return temp & 0xFF;
179
}
180

    
181
static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b,
182
                                       CPUMIPSState *env)
183
{
184
    uint32_t temp;
185

    
186
    temp = (uint32_t)a + (uint32_t)b;
187

    
188
    if (temp & 0x00010000) {
189
        set_DSPControl_overflow_flag(1, 20, env);
190
    }
191

    
192
    return temp & 0xFFFF;
193
}
194

    
195
static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b,
196
                                         CPUMIPSState *env)
197
{
198
    uint8_t  result;
199
    uint16_t temp;
200

    
201
    temp = (uint16_t)a + (uint16_t)b;
202
    result = temp & 0xFF;
203

    
204
    if (0x0100 & temp) {
205
        result = 0xFF;
206
        set_DSPControl_overflow_flag(1, 20, env);
207
    }
208

    
209
    return result;
210
}
211

    
212
static inline uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b,
213
                                           CPUMIPSState *env)
214
{
215
    uint16_t result;
216
    uint32_t temp;
217

    
218
    temp = (uint32_t)a + (uint32_t)b;
219
    result = temp & 0xFFFF;
220

    
221
    if (0x00010000 & temp) {
222
        result = 0xFFFF;
223
        set_DSPControl_overflow_flag(1, 20, env);
224
    }
225

    
226
    return result;
227
}
228

    
229
static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a,
230
                                            CPUMIPSState *env)
231
{
232
    int64_t temp;
233
    int32_t temp32, temp31, result;
234
    int64_t temp_sum;
235

    
236
#ifndef TARGET_MIPS64
237
    temp = ((uint64_t)env->active_tc.HI[acc] << 32) |
238
           (uint64_t)env->active_tc.LO[acc];
239
#else
240
    temp = (uint64_t)env->active_tc.LO[acc];
241
#endif
242

    
243
    temp_sum = (int64_t)a + temp;
244

    
245
    temp32 = (temp_sum >> 32) & 0x01;
246
    temp31 = (temp_sum >> 31) & 0x01;
247
    result = temp_sum & 0xFFFFFFFF;
248

    
249
    /* FIXME
250
       This sat function may wrong, because user manual wrote:
251
       temp127..0 ← temp + ( (signA) || a31..0
252
       if ( temp32 ≠ temp31 ) then
253
           if ( temp32 = 0 ) then
254
               temp31..0 ← 0x80000000
255
           else
256
                temp31..0 ← 0x7FFFFFFF
257
           endif
258
           DSPControlouflag:16+acc ← 1
259
       endif
260
     */
261
    if (temp32 != temp31) {
262
        if (temp32 == 0) {
263
            result = 0x7FFFFFFF;
264
        } else {
265
            result = 0x80000000;
266
        }
267
        set_DSPControl_overflow_flag(1, 16 + acc, env);
268
    }
269

    
270
    return result;
271
}
272

    
273
/* a[0] is LO, a[1] is HI. */
274
static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret,
275
                                             int32_t ac,
276
                                             int64_t *a,
277
                                             CPUMIPSState *env)
278
{
279
    bool temp64;
280

    
281
    ret[0] = env->active_tc.LO[ac] + a[0];
282
    ret[1] = env->active_tc.HI[ac] + a[1];
283

    
284
    if (((uint64_t)ret[0] < (uint64_t)env->active_tc.LO[ac]) &&
285
        ((uint64_t)ret[0] < (uint64_t)a[0])) {
286
        ret[1] += 1;
287
    }
288
    temp64 = ret[1] & 1;
289
    if (temp64 != ((ret[0] >> 63) & 0x01)) {
290
        if (temp64) {
291
            ret[0] = (0x01ull << 63);
292
            ret[1] = ~0ull;
293
        } else {
294
            ret[0] = (0x01ull << 63) - 1;
295
            ret[1] = 0x00;
296
        }
297
        set_DSPControl_overflow_flag(1, 16 + ac, env);
298
    }
299
}
300

    
301
static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
302
                                             int32_t ac,
303
                                             int64_t *a,
304
                                             CPUMIPSState *env)
305
{
306
    bool temp64;
307

    
308
    ret[0] = env->active_tc.LO[ac] - a[0];
309
    ret[1] = env->active_tc.HI[ac] - a[1];
310

    
311
    if ((uint64_t)ret[0] > (uint64_t)env->active_tc.LO[ac]) {
312
        ret[1] -= 1;
313
    }
314
    temp64 = ret[1] & 1;
315
    if (temp64 != ((ret[0] >> 63) & 0x01)) {
316
        if (temp64) {
317
            ret[0] = (0x01ull << 63);
318
            ret[1] = ~0ull;
319
        } else {
320
            ret[0] = (0x01ull << 63) - 1;
321
            ret[1] = 0x00;
322
        }
323
        set_DSPControl_overflow_flag(1, 16 + ac, env);
324
    }
325
}
326

    
327
static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b,
328
                                          CPUMIPSState *env)
329
{
330
    int32_t temp;
331

    
332
    temp = (int32_t)a * (int32_t)b;
333

    
334
    if ((temp > (int)0x7FFF) || (temp < (int)0xFFFF8000)) {
335
        set_DSPControl_overflow_flag(1, 21, env);
336
    }
337
    temp &= 0x0000FFFF;
338

    
339
    return temp;
340
}
341

    
342
static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b)
343
{
344
    return a * b;
345
}
346

    
347
static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b)
348
{
349
    return a * b;
350
}
351

    
352
static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b,
353
                                                CPUMIPSState *env)
354
{
355
    int32_t temp;
356

    
357
    temp = (int32_t)a * (int32_t)b;
358

    
359
    if (temp > (int)0x7FFF) {
360
        temp = 0x00007FFF;
361
        set_DSPControl_overflow_flag(1, 21, env);
362
    } else if (temp < (int)0xffff8000) {
363
        temp = 0xFFFF8000;
364
        set_DSPControl_overflow_flag(1, 21, env);
365
    }
366
    temp &= 0x0000FFFF;
367

    
368
    return temp;
369
}
370

    
371
static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b,
372
                                                         CPUMIPSState *env)
373
{
374
    int32_t temp;
375

    
376
    if ((a == 0x8000) && (b == 0x8000)) {
377
        temp = 0x7FFFFFFF;
378
        set_DSPControl_overflow_flag(1, 21, env);
379
    } else {
380
        temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1;
381
    }
382

    
383
    return temp;
384
}
385

    
386
/* right shift */
387
static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov)
388
{
389
    return a >> mov;
390
}
391

    
392
static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov)
393
{
394
    return a >> mov;
395
}
396

    
397
static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov)
398
{
399
    return a >> mov;
400
}
401

    
402
static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov)
403
{
404
    return a >> mov;
405
}
406

    
407
static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov)
408
{
409
    return a >> mov;
410
}
411

    
412
static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
413
{
414
    int32_t temp;
415

    
416
    temp = (int32_t)a + (int32_t)b;
417

    
418
    return (temp >> 1) & 0xFFFF;
419
}
420

    
421
/* round right shift */
422
static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b)
423
{
424
    int32_t temp;
425

    
426
    temp = (int32_t)a + (int32_t)b;
427
    temp += 1;
428

    
429
    return (temp >> 1) & 0xFFFF;
430
}
431

    
432
static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b)
433
{
434
    int64_t temp;
435

    
436
    temp = (int64_t)a + (int64_t)b;
437

    
438
    return (temp >> 1) & 0xFFFFFFFF;
439
}
440

    
441
static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b)
442
{
443
    int64_t temp;
444

    
445
    temp = (int64_t)a + (int64_t)b;
446
    temp += 1;
447

    
448
    return (temp >> 1) & 0xFFFFFFFF;
449
}
450

    
451
static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b)
452
{
453
    uint16_t temp;
454

    
455
    temp = (uint16_t)a + (uint16_t)b;
456

    
457
    return (temp >> 1) & 0x00FF;
458
}
459

    
460
static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b)
461
{
462
    uint16_t temp;
463

    
464
    temp = (uint16_t)a + (uint16_t)b + 1;
465

    
466
    return (temp >> 1) & 0x00FF;
467
}
468

    
469
static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b)
470
{
471
    uint16_t temp;
472

    
473
    temp = (uint16_t)a - (uint16_t)b;
474

    
475
    return (temp >> 1) & 0x00FF;
476
}
477

    
478
static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b)
479
{
480
    uint16_t temp;
481

    
482
    temp = (uint16_t)a - (uint16_t)b + 1;
483

    
484
    return (temp >> 1) & 0x00FF;
485
}
486

    
487
static inline int64_t mipsdsp_rashift_short_acc(int32_t ac,
488
                                                int32_t shift,
489
                                                CPUMIPSState *env)
490
{
491
    int32_t sign, temp31;
492
    int64_t temp, acc;
493

    
494
    sign = (env->active_tc.HI[ac] >> 31) & 0x01;
495
    acc = ((int64_t)env->active_tc.HI[ac] << 32) |
496
          ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
497
    if (shift == 0) {
498
        temp = acc;
499
    } else {
500
        if (sign == 0) {
501
            temp = (((int64_t)0x01 << (32 - shift + 1)) - 1) & (acc >> shift);
502
        } else {
503
            temp = ((((int64_t)0x01 << (shift + 1)) - 1) << (32 - shift)) |
504
                   (acc >> shift);
505
        }
506
    }
507

    
508
    temp31 = (temp >> 31) & 0x01;
509
    if (sign != temp31) {
510
        set_DSPControl_overflow_flag(1, 23, env);
511
    }
512

    
513
    return temp;
514
}
515

    
516
/*  128 bits long. p[0] is LO, p[1] is HI. */
517
static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
518
                                                int32_t ac,
519
                                                int32_t shift,
520
                                                CPUMIPSState *env)
521
{
522
    int64_t acc;
523

    
524
    acc = ((int64_t)env->active_tc.HI[ac] << 32) |
525
          ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
526
    if (shift == 0) {
527
        p[0] = acc << 1;
528
        p[1] = (acc >> 63) & 0x01;
529
    } else {
530
        p[0] = acc >> (shift - 1);
531
        p[1] = 0;
532
    }
533
}
534

    
535
/* 128 bits long. p[0] is LO, p[1] is HI */
536
static inline void mipsdsp_rashift_acc(uint64_t *p,
537
                                       uint32_t ac,
538
                                       uint32_t shift,
539
                                       CPUMIPSState *env)
540
{
541
    uint64_t tempB, tempA;
542

    
543
    tempB = env->active_tc.HI[ac];
544
    tempA = env->active_tc.LO[ac];
545
    shift = shift & 0x1F;
546

    
547
    if (shift == 0) {
548
        p[1] = tempB;
549
        p[0] = tempA;
550
    } else {
551
        p[0] = (tempB << (64 - shift)) | (tempA >> shift);
552
        p[1] = (int64_t)tempB >> shift;
553
    }
554
}
555

    
556
/* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/
557
static inline void mipsdsp_rndrashift_acc(uint64_t *p,
558
                                          uint32_t ac,
559
                                          uint32_t shift,
560
                                          CPUMIPSState *env)
561
{
562
    int64_t tempB, tempA;
563

    
564
    tempB = env->active_tc.HI[ac];
565
    tempA = env->active_tc.LO[ac];
566
    shift = shift & 0x3F;
567

    
568
    if (shift == 0) {
569
        p[2] = tempB >> 63;
570
        p[1] = (tempB << 1) | (tempA >> 63);
571
        p[0] = tempA << 1;
572
    } else {
573
        p[0] = (tempB << (65 - shift)) | (tempA >> (shift - 1));
574
        p[1] = (int64_t)tempB >> (shift - 1);
575
        if (tempB >= 0) {
576
            p[2] = 0x0;
577
        } else {
578
            p[2] = ~0ull;
579
        }
580
    }
581
}
582

    
583
static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b,
584
                                          CPUMIPSState *env)
585
{
586
    int32_t temp;
587

    
588
    if ((a == 0x8000) && (b == 0x8000)) {
589
        temp = 0x7FFFFFFF;
590
        set_DSPControl_overflow_flag(1, 16 + ac, env);
591
    } else {
592
        temp = ((uint32_t)a * (uint32_t)b) << 1;
593
    }
594

    
595
    return temp;
596
}
597

    
598
static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b,
599
                                          CPUMIPSState *env)
600
{
601
    uint64_t temp;
602

    
603
    if ((a == 0x80000000) && (b == 0x80000000)) {
604
        temp = (0x01ull << 63) - 1;
605
        set_DSPControl_overflow_flag(1, 16 + ac, env);
606
    } else {
607
        temp = ((uint64_t)a * (uint64_t)b) << 1;
608
    }
609

    
610
    return temp;
611
}
612

    
613
static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b)
614
{
615
    return (uint16_t)a * (uint16_t)b;
616
}
617

    
618
static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b,
619
                                          CPUMIPSState *env)
620
{
621
    uint32_t tempI;
622

    
623
    tempI = (uint32_t)a * (uint32_t)b;
624
    if (tempI > 0x0000FFFF) {
625
        tempI = 0x0000FFFF;
626
        set_DSPControl_overflow_flag(1, 21, env);
627
    }
628

    
629
    return tempI & 0x0000FFFF;
630
}
631

    
632
static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b)
633
{
634
    return (uint64_t)a * (uint64_t)b;
635
}
636

    
637
static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b,
638
                                                 CPUMIPSState *env)
639
{
640
    uint32_t temp;
641

    
642
    if ((a == 0x8000) && (b == 0x8000)) {
643
        temp = 0x7FFF0000;
644
        set_DSPControl_overflow_flag(1, 21, env);
645
    } else {
646
        temp = (a * b) << 1;
647
        temp = temp + 0x00008000;
648
    }
649

    
650
    return (temp & 0xFFFF0000) >> 16;
651
}
652

    
653
static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b,
654
                                                CPUMIPSState *env)
655
{
656
    int32_t temp;
657

    
658
    if ((a == 0x8000) && (b == 0x8000)) {
659
        temp = 0x7FFF0000;
660
        set_DSPControl_overflow_flag(1, 21, env);
661
    } else {
662
        temp = ((uint32_t)a * (uint32_t)b);
663
        temp = temp << 1;
664
    }
665

    
666
    return (temp >> 16) & 0x0000FFFF;
667
}
668

    
669
static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a,
670
                                                   CPUMIPSState *env)
671
{
672
    int64_t temp;
673

    
674
    temp = (int32_t)a + 0x00008000;
675

    
676
    if (a > (int)0x7fff8000) {
677
        temp = 0x7FFFFFFF;
678
        set_DSPControl_overflow_flag(1, 22, env);
679
    }
680

    
681
    return (temp >> 16) & 0xFFFF;
682
}
683

    
684
static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
685
                                                    CPUMIPSState *env)
686
{
687
    uint16_t mag;
688
    uint32_t sign;
689

    
690
    sign = (a >> 15) & 0x01;
691
    mag = a & 0x7FFF;
692

    
693
    if (sign == 0) {
694
        if (mag > 0x7F80) {
695
            set_DSPControl_overflow_flag(1, 22, env);
696
            return 0xFF;
697
        } else {
698
            return (mag >> 7) & 0xFFFF;
699
        }
700
    } else {
701
        set_DSPControl_overflow_flag(1, 22, env);
702
        return 0x00;
703
    }
704
}
705

    
706
static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env)
707
{
708
    uint8_t sign;
709
    uint8_t discard;
710

    
711
    if (s == 0) {
712
        return a;
713
    } else {
714
        sign = (a >> 7) & 0x01;
715
        if (sign != 0) {
716
            discard = (((0x01 << (8 - s)) - 1) << s) |
717
                      ((a >> (6 - (s - 1))) & ((0x01 << s) - 1));
718
        } else {
719
            discard = a >> (6 - (s - 1));
720
        }
721

    
722
        if (discard != 0x00) {
723
            set_DSPControl_overflow_flag(1, 22, env);
724
        }
725
        return a << s;
726
    }
727
}
728

    
729
static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
730
                                        CPUMIPSState *env)
731
{
732
    uint8_t  sign;
733
    uint16_t discard;
734

    
735
    if (s == 0) {
736
        return a;
737
    } else {
738
        sign = (a >> 15) & 0x01;
739
        if (sign != 0) {
740
            discard = (((0x01 << (16 - s)) - 1) << s) |
741
                      ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
742
        } else {
743
            discard = a >> (14 - (s - 1));
744
        }
745

    
746
        if ((discard != 0x0000) && (discard != 0xFFFF)) {
747
            set_DSPControl_overflow_flag(1, 22, env);
748
        }
749
        return a << s;
750
    }
751
}
752

    
753

    
754
static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s,
755
                                        CPUMIPSState *env)
756
{
757
    uint32_t discard;
758

    
759
    if (s == 0) {
760
        return a;
761
    } else {
762
        discard = (int32_t)a >> (31 - (s - 1));
763

    
764
        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
765
            set_DSPControl_overflow_flag(1, 22, env);
766
        }
767
        return a << s;
768
    }
769
}
770

    
771
static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s,
772
                                            CPUMIPSState *env)
773
{
774
    uint8_t  sign;
775
    uint16_t discard;
776

    
777
    if (s == 0) {
778
        return a;
779
    } else {
780
        sign = (a >> 15) & 0x01;
781
        if (sign != 0) {
782
            discard = (((0x01 << (16 - s)) - 1) << s) |
783
                      ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
784
        } else {
785
            discard = a >> (14 - (s - 1));
786
        }
787

    
788
        if ((discard != 0x0000) && (discard != 0xFFFF)) {
789
            set_DSPControl_overflow_flag(1, 22, env);
790
            return (sign == 0) ? 0x7FFF : 0x8000;
791
        } else {
792
            return a << s;
793
        }
794
    }
795
}
796

    
797
static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s,
798
                                            CPUMIPSState *env)
799
{
800
    uint8_t  sign;
801
    uint32_t discard;
802

    
803
    if (s == 0) {
804
        return a;
805
    } else {
806
        sign = (a >> 31) & 0x01;
807
        if (sign != 0) {
808
            discard = (((0x01 << (32 - s)) - 1) << s) |
809
                      ((a >> (30 - (s - 1))) & ((0x01 << s) - 1));
810
        } else {
811
            discard = a >> (30 - (s - 1));
812
        }
813

    
814
        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
815
            set_DSPControl_overflow_flag(1, 22, env);
816
            return (sign == 0) ? 0x7FFFFFFF : 0x80000000;
817
        } else {
818
            return a << s;
819
        }
820
    }
821
}
822

    
823
static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a, uint8_t s)
824
{
825
    uint32_t temp;
826

    
827
    if (s == 0) {
828
        temp = (uint32_t)a << 1;
829
    } else {
830
        temp = (int32_t)(int8_t)a >> (s - 1);
831
    }
832

    
833
    return (temp + 1) >> 1;
834
}
835

    
836
static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s)
837
{
838
    uint32_t temp;
839

    
840
    if (s == 0) {
841
        temp = (uint32_t)a << 1;
842
    } else {
843
        temp = (int32_t)(int16_t)a >> (s - 1);
844
    }
845

    
846
    return (temp + 1) >> 1;
847
}
848

    
849
static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s)
850
{
851
    int64_t temp;
852

    
853
    if (s == 0) {
854
        temp = (uint64_t)a << 1;
855
    } else {
856
        temp = (int64_t)(int32_t)a >> (s - 1);
857
    }
858
    temp += 1;
859

    
860
    return (temp >> 1) & 0xFFFFFFFFull;
861
}
862

    
863
static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env)
864
{
865
    int16_t  temp;
866

    
867
    temp = a - b;
868
    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
869
        set_DSPControl_overflow_flag(1, 20, env);
870
    }
871

    
872
    return temp;
873
}
874

    
875
static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b,
876
                                         CPUMIPSState *env)
877
{
878
    int16_t  temp;
879

    
880
    temp = a - b;
881
    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
882
        if (a > 0) {
883
            temp = 0x7FFF;
884
        } else {
885
            temp = 0x8000;
886
        }
887
        set_DSPControl_overflow_flag(1, 20, env);
888
    }
889

    
890
    return temp;
891
}
892

    
893
static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b,
894
                                         CPUMIPSState *env)
895
{
896
    int32_t  temp;
897

    
898
    temp = a - b;
899
    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
900
        if (a > 0) {
901
            temp = 0x7FFFFFFF;
902
        } else {
903
            temp = 0x80000000;
904
        }
905
        set_DSPControl_overflow_flag(1, 20, env);
906
    }
907

    
908
    return temp & 0xFFFFFFFFull;
909
}
910

    
911
static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b)
912
{
913
    int32_t  temp;
914

    
915
    temp = (int32_t)a - (int32_t)b;
916

    
917
    return (temp >> 1) & 0x0000FFFF;
918
}
919

    
920
static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b)
921
{
922
    int32_t  temp;
923

    
924
    temp = (int32_t)a - (int32_t)b;
925
    temp += 1;
926

    
927
    return (temp >> 1) & 0x0000FFFF;
928
}
929

    
930
static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b)
931
{
932
    int64_t  temp;
933

    
934
    temp = (int64_t)a - (int64_t)b;
935

    
936
    return (temp >> 1) & 0xFFFFFFFFull;
937
}
938

    
939
static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b)
940
{
941
    int64_t  temp;
942

    
943
    temp = (int64_t)a - (int64_t)b;
944
    temp += 1;
945

    
946
    return (temp >> 1) & 0xFFFFFFFFull;
947
}
948

    
949
static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b,
950
                                           CPUMIPSState *env)
951
{
952
    uint8_t  temp16;
953
    uint32_t temp;
954

    
955
    temp = (uint32_t)a - (uint32_t)b;
956
    temp16 = (temp >> 16) & 0x01;
957
    if (temp16 == 1) {
958
        set_DSPControl_overflow_flag(1, 20, env);
959
    }
960
    return temp & 0x0000FFFF;
961
}
962

    
963
static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b,
964
                                                  CPUMIPSState *env)
965
{
966
    uint8_t  temp16;
967
    uint32_t temp;
968

    
969
    temp   = (uint32_t)a - (uint32_t)b;
970
    temp16 = (temp >> 16) & 0x01;
971

    
972
    if (temp16 == 1) {
973
        temp = 0x0000;
974
        set_DSPControl_overflow_flag(1, 20, env);
975
    }
976

    
977
    return temp & 0x0000FFFF;
978
}
979

    
980
static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
981
{
982
    uint8_t  temp8;
983
    uint16_t temp;
984

    
985
    temp = (uint16_t)a - (uint16_t)b;
986
    temp8 = (temp >> 8) & 0x01;
987
    if (temp8 == 1) {
988
        set_DSPControl_overflow_flag(1, 20, env);
989
    }
990

    
991
    return temp & 0x00FF;
992
}
993

    
994
static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env)
995
{
996
    uint8_t  temp8;
997
    uint16_t temp;
998

    
999
    temp = (uint16_t)a - (uint16_t)b;
1000
    temp8 = (temp >> 8) & 0x01;
1001
    if (temp8 == 1) {
1002
        temp = 0x00;
1003
        set_DSPControl_overflow_flag(1, 20, env);
1004
    }
1005

    
1006
    return temp & 0x00FF;
1007
}
1008

    
1009
static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
1010
{
1011
    int32_t temp;
1012

    
1013
    temp = a - b;
1014
    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
1015
        set_DSPControl_overflow_flag(1, 20, env);
1016
    }
1017

    
1018
    return temp;
1019
}
1020

    
1021
static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env)
1022
{
1023
    int32_t temp;
1024

    
1025
    temp = a + b;
1026

    
1027
    if (MIPSDSP_OVERFLOW(a, b, temp, 0x80000000)) {
1028
        set_DSPControl_overflow_flag(1, 20, env);
1029
    }
1030

    
1031
    return temp;
1032
}
1033

    
1034
static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b)
1035
{
1036
    return a == b;
1037
}
1038

    
1039
static inline int32_t mipsdsp_cmp_le(int32_t a, int32_t b)
1040
{
1041
    return a <= b;
1042
}
1043

    
1044
static inline int32_t mipsdsp_cmp_lt(int32_t a, int32_t b)
1045
{
1046
    return a < b;
1047
}
1048

    
1049
static inline int32_t mipsdsp_cmpu_eq(uint32_t a, uint32_t b)
1050
{
1051
    return a == b;
1052
}
1053

    
1054
static inline int32_t mipsdsp_cmpu_le(uint32_t a, uint32_t b)
1055
{
1056
    return a <= b;
1057
}
1058

    
1059
static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b)
1060
{
1061
    return a < b;
1062
}
1063
/*** MIPS DSP internal functions end ***/
1064

    
1065
#define MIPSDSP_LHI 0xFFFFFFFF00000000ull
1066
#define MIPSDSP_LLO 0x00000000FFFFFFFFull
1067
#define MIPSDSP_HI  0xFFFF0000
1068
#define MIPSDSP_LO  0x0000FFFF
1069
#define MIPSDSP_Q3  0xFF000000
1070
#define MIPSDSP_Q2  0x00FF0000
1071
#define MIPSDSP_Q1  0x0000FF00
1072
#define MIPSDSP_Q0  0x000000FF
1073

    
1074
#define MIPSDSP_SPLIT32_8(num, a, b, c, d)  \
1075
    do {                                    \
1076
        a = (num >> 24) & MIPSDSP_Q0;       \
1077
        b = (num >> 16) & MIPSDSP_Q0;       \
1078
        c = (num >> 8) & MIPSDSP_Q0;        \
1079
        d = num & MIPSDSP_Q0;               \
1080
    } while (0)
1081

    
1082
#define MIPSDSP_SPLIT32_16(num, a, b)       \
1083
    do {                                    \
1084
        a = (num >> 16) & MIPSDSP_LO;       \
1085
        b = num & MIPSDSP_LO;               \
1086
    } while (0)
1087

    
1088
#define MIPSDSP_RETURN32(a)             ((target_long)(int32_t)a)
1089
#define MIPSDSP_RETURN32_8(a, b, c, d)  ((target_long)(int32_t) \
1090
                                         (((uint32_t)a << 24) | \
1091
                                         (((uint32_t)b << 16) | \
1092
                                         (((uint32_t)c << 8) |  \
1093
                                          ((uint32_t)d & 0xFF)))))
1094
#define MIPSDSP_RETURN32_16(a, b)       ((target_long)(int32_t) \
1095
                                         (((uint32_t)a << 16) | \
1096
                                          ((uint32_t)b & 0xFFFF)))
1097

    
1098
#ifdef TARGET_MIPS64
1099
#define MIPSDSP_SPLIT64_16(num, a, b, c, d)  \
1100
    do {                                     \
1101
        a = (num >> 48) & MIPSDSP_LO;        \
1102
        b = (num >> 32) & MIPSDSP_LO;        \
1103
        c = (num >> 16) & MIPSDSP_LO;        \
1104
        d = num & MIPSDSP_LO;                \
1105
    } while (0)
1106

    
1107
#define MIPSDSP_SPLIT64_32(num, a, b)       \
1108
    do {                                    \
1109
        a = (num >> 32) & MIPSDSP_LLO;      \
1110
        b = num & MIPSDSP_LLO;              \
1111
    } while (0)
1112

    
1113
#define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)a << 48) | \
1114
                                         ((uint64_t)b << 32) | \
1115
                                         ((uint64_t)c << 16) | \
1116
                                         (uint64_t)d)
1117
#define MIPSDSP_RETURN64_32(a, b)       (((uint64_t)a << 32) | (uint64_t)b)
1118
#endif
1119

    
1120
/** DSP Arithmetic Sub-class insns **/
1121
#define ARITH_PH(name, func)                                      \
1122
target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt) \
1123
{                                                                 \
1124
    uint16_t  rsh, rsl, rth, rtl, temph, templ;                   \
1125
                                                                  \
1126
    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                             \
1127
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
1128
                                                                  \
1129
    temph = mipsdsp_##func(rsh, rth);                             \
1130
    templ = mipsdsp_##func(rsl, rtl);                             \
1131
                                                                  \
1132
    return MIPSDSP_RETURN32_16(temph, templ);                     \
1133
}
1134

    
1135
#define ARITH_PH_ENV(name, func)                                  \
1136
target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt, \
1137
                                CPUMIPSState *env)                \
1138
{                                                                 \
1139
    uint16_t  rsh, rsl, rth, rtl, temph, templ;                   \
1140
                                                                  \
1141
    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                             \
1142
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
1143
                                                                  \
1144
    temph = mipsdsp_##func(rsh, rth, env);                        \
1145
    templ = mipsdsp_##func(rsl, rtl, env);                        \
1146
                                                                  \
1147
    return MIPSDSP_RETURN32_16(temph, templ);                     \
1148
}
1149

    
1150

    
1151
ARITH_PH_ENV(addq, add_i16);
1152
ARITH_PH_ENV(addq_s, sat_add_i16);
1153
ARITH_PH_ENV(addu, add_u16);
1154
ARITH_PH_ENV(addu_s, sat_add_u16);
1155

    
1156
ARITH_PH(addqh, rshift1_add_q16);
1157
ARITH_PH(addqh_r, rrshift1_add_q16);
1158

    
1159
ARITH_PH_ENV(subq, sub_i16);
1160
ARITH_PH_ENV(subq_s, sat16_sub);
1161
ARITH_PH_ENV(subu, sub_u16_u16);
1162
ARITH_PH_ENV(subu_s, satu16_sub_u16_u16);
1163

    
1164
ARITH_PH(subqh, rshift1_sub_q16);
1165
ARITH_PH(subqh_r, rrshift1_sub_q16);
1166

    
1167
#undef ARITH_PH
1168
#undef ARITH_PH_ENV
1169

    
1170
#ifdef TARGET_MIPS64
1171
#define ARITH_QH_ENV(name, func) \
1172
target_ulong helper_##name##_qh(target_ulong rs, target_ulong rt, \
1173
                                CPUMIPSState *env)           \
1174
{                                                            \
1175
    uint16_t rs3, rs2, rs1, rs0;                             \
1176
    uint16_t rt3, rt2, rt1, rt0;                             \
1177
    uint16_t tempD, tempC, tempB, tempA;                     \
1178
                                                             \
1179
    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);              \
1180
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);              \
1181
                                                             \
1182
    tempD = mipsdsp_##func(rs3, rt3, env);                   \
1183
    tempC = mipsdsp_##func(rs2, rt2, env);                   \
1184
    tempB = mipsdsp_##func(rs1, rt1, env);                   \
1185
    tempA = mipsdsp_##func(rs0, rt0, env);                   \
1186
                                                             \
1187
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
1188
}
1189

    
1190
ARITH_QH_ENV(addq, add_i16);
1191
ARITH_QH_ENV(addq_s, sat_add_i16);
1192
ARITH_QH_ENV(addu, add_u16);
1193
ARITH_QH_ENV(addu_s, sat_add_u16);
1194

    
1195
ARITH_QH_ENV(subq, sub_i16);
1196
ARITH_QH_ENV(subq_s, sat16_sub);
1197
ARITH_QH_ENV(subu, sub_u16_u16);
1198
ARITH_QH_ENV(subu_s, satu16_sub_u16_u16);
1199

    
1200
#undef ARITH_QH_ENV
1201

    
1202
#endif
1203

    
1204
#define ARITH_W(name, func) \
1205
target_ulong helper_##name##_w(target_ulong rs, target_ulong rt) \
1206
{                                                                \
1207
    uint32_t rd;                                                 \
1208
    rd = mipsdsp_##func(rs, rt);                                 \
1209
    return MIPSDSP_RETURN32(rd);                                 \
1210
}
1211

    
1212
#define ARITH_W_ENV(name, func) \
1213
target_ulong helper_##name##_w(target_ulong rs, target_ulong rt, \
1214
                               CPUMIPSState *env)                \
1215
{                                                                \
1216
    uint32_t rd;                                                 \
1217
    rd = mipsdsp_##func(rs, rt, env);                            \
1218
    return MIPSDSP_RETURN32(rd);                                 \
1219
}
1220

    
1221
ARITH_W_ENV(addq_s, sat_add_i32);
1222

    
1223
ARITH_W(addqh, rshift1_add_q32);
1224
ARITH_W(addqh_r, rrshift1_add_q32);
1225

    
1226
ARITH_W_ENV(subq_s, sat32_sub);
1227

    
1228
ARITH_W(subqh, rshift1_sub_q32);
1229
ARITH_W(subqh_r, rrshift1_sub_q32);
1230

    
1231
#undef ARITH_W
1232
#undef ARITH_W_ENV
1233

    
1234
target_ulong helper_absq_s_w(target_ulong rt, CPUMIPSState *env)
1235
{
1236
    uint32_t rd;
1237

    
1238
    rd = mipsdsp_sat_abs32(rt, env);
1239

    
1240
    return (target_ulong)rd;
1241
}
1242

    
1243

    
1244
#if defined(TARGET_MIPS64)
1245

    
1246
#define ARITH_PW_ENV(name, func) \
1247
target_ulong helper_##name##_pw(target_ulong rs, target_ulong rt, \
1248
                                CPUMIPSState *env)                \
1249
{                                                                 \
1250
    uint32_t rs1, rs0;                                            \
1251
    uint32_t rt1, rt0;                                            \
1252
    uint32_t tempB, tempA;                                        \
1253
                                                                  \
1254
    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                             \
1255
    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
1256
                                                                  \
1257
    tempB = mipsdsp_##func(rs1, rt1, env);                        \
1258
    tempA = mipsdsp_##func(rs0, rt0, env);                        \
1259
                                                                  \
1260
    return MIPSDSP_RETURN64_32(tempB, tempA);                     \
1261
}
1262

    
1263
ARITH_PW_ENV(addq, add_i32);
1264
ARITH_PW_ENV(addq_s, sat_add_i32);
1265
ARITH_PW_ENV(subq, sub32);
1266
ARITH_PW_ENV(subq_s, sat32_sub);
1267

    
1268
#undef ARITH_PW_ENV
1269

    
1270
#endif
1271

    
1272
#define ARITH_QB(name, func) \
1273
target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \
1274
{                                                                 \
1275
    uint8_t  rs0, rs1, rs2, rs3;                                  \
1276
    uint8_t  rt0, rt1, rt2, rt3;                                  \
1277
    uint8_t  temp0, temp1, temp2, temp3;                          \
1278
                                                                  \
1279
    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                    \
1280
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                    \
1281
                                                                  \
1282
    temp0 = mipsdsp_##func(rs0, rt0);                             \
1283
    temp1 = mipsdsp_##func(rs1, rt1);                             \
1284
    temp2 = mipsdsp_##func(rs2, rt2);                             \
1285
    temp3 = mipsdsp_##func(rs3, rt3);                             \
1286
                                                                  \
1287
    return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0);        \
1288
}
1289

    
1290
#define ARITH_QB_ENV(name, func) \
1291
target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt, \
1292
                                CPUMIPSState *env)          \
1293
{                                                           \
1294
    uint8_t  rs0, rs1, rs2, rs3;                            \
1295
    uint8_t  rt0, rt1, rt2, rt3;                            \
1296
    uint8_t  temp0, temp1, temp2, temp3;                    \
1297
                                                            \
1298
    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);              \
1299
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);              \
1300
                                                            \
1301
    temp0 = mipsdsp_##func(rs0, rt0, env);                  \
1302
    temp1 = mipsdsp_##func(rs1, rt1, env);                  \
1303
    temp2 = mipsdsp_##func(rs2, rt2, env);                  \
1304
    temp3 = mipsdsp_##func(rs3, rt3, env);                  \
1305
                                                            \
1306
    return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0);  \
1307
}
1308

    
1309
ARITH_QB(adduh, rshift1_add_u8);
1310
ARITH_QB(adduh_r, rrshift1_add_u8);
1311

    
1312
ARITH_QB_ENV(addu, add_u8);
1313
ARITH_QB_ENV(addu_s, sat_add_u8);
1314

    
1315
#undef ADDU_QB
1316
#undef ADDU_QB_ENV
1317

    
1318
#if defined(TARGET_MIPS64)
1319
#define ARITH_OB(name, func) \
1320
target_ulong helper_##name##_ob(target_ulong rs, target_ulong rt) \
1321
{                                                                 \
1322
    int i;                                                        \
1323
    uint8_t rs_t[8], rt_t[8];                                     \
1324
    uint8_t temp[8];                                              \
1325
    uint64_t result;                                              \
1326
                                                                  \
1327
    result = 0;                                                   \
1328
                                                                  \
1329
    for (i = 0; i < 8; i++) {                                     \
1330
        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;                   \
1331
        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                   \
1332
        temp[i] = mipsdsp_##func(rs_t[i], rt_t[i]);               \
1333
        result |= (uint64_t)temp[i] << (8 * i);                   \
1334
    }                                                             \
1335
                                                                  \
1336
    return result;                                                \
1337
}
1338

    
1339
#define ARITH_OB_ENV(name, func) \
1340
target_ulong helper_##name##_ob(target_ulong rs, target_ulong rt, \
1341
                                CPUMIPSState *env)                \
1342
{                                                                 \
1343
    int i;                                                        \
1344
    uint8_t rs_t[8], rt_t[8];                                     \
1345
    uint8_t temp[8];                                              \
1346
    uint64_t result;                                              \
1347
                                                                  \
1348
    result = 0;                                                   \
1349
                                                                  \
1350
    for (i = 0; i < 8; i++) {                                     \
1351
        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;                   \
1352
        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                   \
1353
        temp[i] = mipsdsp_##func(rs_t[i], rt_t[i], env);          \
1354
        result |= (uint64_t)temp[i] << (8 * i);                   \
1355
    }                                                             \
1356
                                                                  \
1357
    return result;                                                \
1358
}
1359

    
1360
ARITH_OB_ENV(addu, add_u8);
1361
ARITH_OB_ENV(addu_s, sat_add_u8);
1362

    
1363
ARITH_OB(adduh, rshift1_add_u8);
1364
ARITH_OB(adduh_r, rrshift1_add_u8);
1365

    
1366
ARITH_OB_ENV(subu, sub_u8);
1367
ARITH_OB_ENV(subu_s, satu8_sub);
1368

    
1369
ARITH_OB(subuh, rshift1_sub_u8);
1370
ARITH_OB(subuh_r, rrshift1_sub_u8);
1371

    
1372
#undef ARITH_OB
1373
#undef ARITH_OB_ENV
1374

    
1375
#endif
1376

    
1377
#define SUBU_QB(name, func) \
1378
target_ulong helper_##name##_qb(target_ulong rs,               \
1379
                                target_ulong rt,               \
1380
                                CPUMIPSState *env)             \
1381
{                                                              \
1382
    uint8_t rs3, rs2, rs1, rs0;                                \
1383
    uint8_t rt3, rt2, rt1, rt0;                                \
1384
    uint8_t tempD, tempC, tempB, tempA;                        \
1385
                                                               \
1386
    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                 \
1387
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                 \
1388
                                                               \
1389
    tempD = mipsdsp_##func(rs3, rt3, env);                     \
1390
    tempC = mipsdsp_##func(rs2, rt2, env);                     \
1391
    tempB = mipsdsp_##func(rs1, rt1, env);                     \
1392
    tempA = mipsdsp_##func(rs0, rt0, env);                     \
1393
                                                               \
1394
    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);     \
1395
}
1396

    
1397
SUBU_QB(subu, sub_u8);
1398
SUBU_QB(subu_s, satu8_sub);
1399

    
1400
#undef SUBU_QB
1401

    
1402
#define SUBUH_QB(name, var) \
1403
target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \
1404
{                                                                 \
1405
    uint8_t rs3, rs2, rs1, rs0;                                   \
1406
    uint8_t rt3, rt2, rt1, rt0;                                   \
1407
    uint8_t tempD, tempC, tempB, tempA;                           \
1408
                                                                  \
1409
    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                    \
1410
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                    \
1411
                                                                  \
1412
    tempD = ((uint16_t)rs3 - (uint16_t)rt3 + var) >> 1;           \
1413
    tempC = ((uint16_t)rs2 - (uint16_t)rt2 + var) >> 1;           \
1414
    tempB = ((uint16_t)rs1 - (uint16_t)rt1 + var) >> 1;           \
1415
    tempA = ((uint16_t)rs0 - (uint16_t)rt0 + var) >> 1;           \
1416
                                                                  \
1417
    return ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |    \
1418
        ((uint32_t)tempB << 8) | ((uint32_t)tempA);               \
1419
}
1420

    
1421
SUBUH_QB(subuh, 0);
1422
SUBUH_QB(subuh_r, 1);
1423

    
1424
#undef SUBUH_QB
1425

    
1426
target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
1427
{
1428
    uint64_t temp, tempRs, tempRt;
1429
    int32_t flag;
1430

    
1431
    tempRs = (uint64_t)rs & MIPSDSP_LLO;
1432
    tempRt = (uint64_t)rt & MIPSDSP_LLO;
1433

    
1434
    temp = tempRs + tempRt;
1435
    flag = (temp & 0x0100000000ull) >> 32;
1436
    set_DSPControl_carryflag(flag, env);
1437

    
1438
    return (target_long)(int32_t)(temp & MIPSDSP_LLO);
1439
}
1440

    
1441
target_ulong helper_addwc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
1442
{
1443
    uint32_t rd;
1444
    int32_t temp32, temp31;
1445
    int64_t tempL;
1446

    
1447
    tempL = (int64_t)(int32_t)rs + (int64_t)(int32_t)rt +
1448
        get_DSPControl_carryflag(env);
1449
    temp31 = (tempL >> 31) & 0x01;
1450
    temp32 = (tempL >> 32) & 0x01;
1451

    
1452
    if (temp31 != temp32) {
1453
        set_DSPControl_overflow_flag(1, 20, env);
1454
    }
1455

    
1456
    rd = tempL & MIPSDSP_LLO;
1457

    
1458
    return (target_long)(int32_t)rd;
1459
}
1460

    
1461
target_ulong helper_modsub(target_ulong rs, target_ulong rt)
1462
{
1463
    int32_t decr;
1464
    uint16_t lastindex;
1465
    target_ulong rd;
1466

    
1467
    decr = rt & MIPSDSP_Q0;
1468
    lastindex = (rt >> 8) & MIPSDSP_LO;
1469

    
1470
    if ((rs & MIPSDSP_LLO) == 0x00000000) {
1471
        rd = (target_ulong)lastindex;
1472
    } else {
1473
        rd = rs - decr;
1474
    }
1475

    
1476
    return rd;
1477
}
1478

    
1479
target_ulong helper_raddu_w_qb(target_ulong rs)
1480
{
1481
    uint8_t  rs3, rs2, rs1, rs0;
1482
    uint16_t temp;
1483

    
1484
    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);
1485

    
1486
    temp = (uint16_t)rs3 + (uint16_t)rs2 + (uint16_t)rs1 + (uint16_t)rs0;
1487

    
1488
    return (target_ulong)temp;
1489
}
1490

    
1491
#if defined(TARGET_MIPS64)
1492
target_ulong helper_raddu_l_ob(target_ulong rs)
1493
{
1494
    int i;
1495
    uint16_t rs_t[8];
1496
    uint64_t temp;
1497

    
1498
    temp = 0;
1499

    
1500
    for (i = 0; i < 8; i++) {
1501
        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
1502
        temp += (uint64_t)rs_t[i];
1503
    }
1504

    
1505
    return temp;
1506
}
1507
#endif
1508

    
1509
target_ulong helper_absq_s_qb(target_ulong rt, CPUMIPSState *env)
1510
{
1511
    uint8_t tempD, tempC, tempB, tempA;
1512

    
1513
    MIPSDSP_SPLIT32_8(rt, tempD, tempC, tempB, tempA);
1514

    
1515
    tempD = mipsdsp_sat_abs8(tempD, env);
1516
    tempC = mipsdsp_sat_abs8(tempC, env);
1517
    tempB = mipsdsp_sat_abs8(tempB, env);
1518
    tempA = mipsdsp_sat_abs8(tempA, env);
1519

    
1520
    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);
1521
}
1522

    
1523
target_ulong helper_absq_s_ph(target_ulong rt, CPUMIPSState *env)
1524
{
1525
    uint16_t tempB, tempA;
1526

    
1527
    MIPSDSP_SPLIT32_16(rt, tempB, tempA);
1528

    
1529
    tempB = mipsdsp_sat_abs16 (tempB, env);
1530
    tempA = mipsdsp_sat_abs16 (tempA, env);
1531

    
1532
    return MIPSDSP_RETURN32_16(tempB, tempA);
1533
}
1534

    
1535
#if defined(TARGET_MIPS64)
1536
target_ulong helper_absq_s_ob(target_ulong rt, CPUMIPSState *env)
1537
{
1538
    int i;
1539
    int8_t temp[8];
1540
    uint64_t result;
1541

    
1542
    for (i = 0; i < 8; i++) {
1543
        temp[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
1544
        temp[i] = mipsdsp_sat_abs8(temp[i], env);
1545
    }
1546

    
1547
    for (i = 0; i < 8; i++) {
1548
        result = (uint64_t)(uint8_t)temp[i] << (8 * i);
1549
    }
1550

    
1551
    return result;
1552
}
1553

    
1554
target_ulong helper_absq_s_qh(target_ulong rt, CPUMIPSState *env)
1555
{
1556
    int16_t tempD, tempC, tempB, tempA;
1557

    
1558
    MIPSDSP_SPLIT64_16(rt, tempD, tempC, tempB, tempA);
1559

    
1560
    tempD = mipsdsp_sat_abs16(tempD, env);
1561
    tempC = mipsdsp_sat_abs16(tempC, env);
1562
    tempB = mipsdsp_sat_abs16(tempB, env);
1563
    tempA = mipsdsp_sat_abs16(tempA, env);
1564

    
1565
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1566
}
1567

    
1568
target_ulong helper_absq_s_pw(target_ulong rt, CPUMIPSState *env)
1569
{
1570
    int32_t tempB, tempA;
1571

    
1572
    MIPSDSP_SPLIT64_32(rt, tempB, tempA);
1573

    
1574
    tempB = mipsdsp_sat_abs32(tempB, env);
1575
    tempA = mipsdsp_sat_abs32(tempA, env);
1576

    
1577
    return MIPSDSP_RETURN64_32(tempB, tempA);
1578
}
1579
#endif
1580

    
1581
#define PRECR_QB_PH(name, a, b)\
1582
target_ulong helper_##name##_qb_ph(target_ulong rs, target_ulong rt) \
1583
{                                                                    \
1584
    uint8_t tempD, tempC, tempB, tempA;                              \
1585
                                                                     \
1586
    tempD = (rs >> a) & MIPSDSP_Q0;                                  \
1587
    tempC = (rs >> b) & MIPSDSP_Q0;                                  \
1588
    tempB = (rt >> a) & MIPSDSP_Q0;                                  \
1589
    tempA = (rt >> b) & MIPSDSP_Q0;                                  \
1590
                                                                     \
1591
    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);           \
1592
}
1593

    
1594
PRECR_QB_PH(precr, 16, 0);
1595
PRECR_QB_PH(precrq, 24, 8);
1596

    
1597
#undef PRECR_QB_OH
1598

    
1599
target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs,
1600
                                   target_ulong rt)
1601
{
1602
    uint16_t tempB, tempA;
1603

    
1604
    tempB = ((int32_t)rt >> sa) & MIPSDSP_LO;
1605
    tempA = ((int32_t)rs >> sa) & MIPSDSP_LO;
1606

    
1607
    return MIPSDSP_RETURN32_16(tempB, tempA);
1608
}
1609

    
1610
target_ulong helper_precr_sra_r_ph_w(uint32_t sa,
1611
                                     target_ulong rs, target_ulong rt)
1612
{
1613
    uint64_t tempB, tempA;
1614

    
1615
    /* If sa = 0, then (sa - 1) = -1 will case shift error, so we need else. */
1616
    if (sa == 0) {
1617
        tempB = (rt & MIPSDSP_LO) << 1;
1618
        tempA = (rs & MIPSDSP_LO) << 1;
1619
    } else {
1620
        tempB = ((int32_t)rt >> (sa - 1)) + 1;
1621
        tempA = ((int32_t)rs >> (sa - 1)) + 1;
1622
    }
1623
    rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO);
1624

    
1625
    return (target_long)(int32_t)rt;
1626
}
1627

    
1628
target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt)
1629
{
1630
    uint16_t tempB, tempA;
1631

    
1632
    tempB = (rs & MIPSDSP_HI) >> 16;
1633
    tempA = (rt & MIPSDSP_HI) >> 16;
1634

    
1635
    return MIPSDSP_RETURN32_16(tempB, tempA);
1636
}
1637

    
1638
target_ulong helper_precrq_rs_ph_w(target_ulong rs, target_ulong rt,
1639
                                   CPUMIPSState *env)
1640
{
1641
    uint16_t tempB, tempA;
1642

    
1643
    tempB = mipsdsp_trunc16_sat16_round(rs, env);
1644
    tempA = mipsdsp_trunc16_sat16_round(rt, env);
1645

    
1646
    return MIPSDSP_RETURN32_16(tempB, tempA);
1647
}
1648

    
1649
#if defined(TARGET_MIPS64)
1650
target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt)
1651
{
1652
    uint8_t rs6, rs4, rs2, rs0;
1653
    uint8_t rt6, rt4, rt2, rt0;
1654
    uint64_t temp;
1655

    
1656
    rs6 = (rs >> 48) & MIPSDSP_Q0;
1657
    rs4 = (rs >> 32) & MIPSDSP_Q0;
1658
    rs2 = (rs >> 16) & MIPSDSP_Q0;
1659
    rs0 = rs & MIPSDSP_Q0;
1660
    rt6 = (rt >> 48) & MIPSDSP_Q0;
1661
    rt4 = (rt >> 32) & MIPSDSP_Q0;
1662
    rt2 = (rt >> 16) & MIPSDSP_Q0;
1663
    rt0 = rt & MIPSDSP_Q0;
1664

    
1665
    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
1666
           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
1667
           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
1668
           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
1669

    
1670
    return temp;
1671
}
1672

    
1673
#define PRECR_QH_PW(name, var) \
1674
target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \
1675
                                    uint32_t sa)                      \
1676
{                                                                     \
1677
    uint16_t rs3, rs2, rs1, rs0;                                      \
1678
    uint16_t rt3, rt2, rt1, rt0;                                      \
1679
    uint16_t tempD, tempC, tempB, tempA;                              \
1680
                                                                      \
1681
    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);                       \
1682
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                       \
1683
                                                                      \
1684
    /* When sa = 0, we use rt2, rt0, rs2, rs0;                        \
1685
     * when sa != 0, we use rt3, rt1, rs3, rs1. */                    \
1686
    if (sa == 0) {                                                    \
1687
        tempD = rt2 << var;                                           \
1688
        tempC = rt0 << var;                                           \
1689
        tempB = rs2 << var;                                           \
1690
        tempA = rs0 << var;                                           \
1691
    } else {                                                          \
1692
        tempD = (((int16_t)rt3 >> sa) + var) >> var;                  \
1693
        tempC = (((int16_t)rt1 >> sa) + var) >> var;                  \
1694
        tempB = (((int16_t)rs3 >> sa) + var) >> var;                  \
1695
        tempA = (((int16_t)rs1 >> sa) + var) >> var;                  \
1696
    }                                                                 \
1697
                                                                      \
1698
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);           \
1699
}
1700

    
1701
PRECR_QH_PW(sra, 0);
1702
PRECR_QH_PW(sra_r, 1);
1703

    
1704
#undef PRECR_QH_PW
1705

    
1706
target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt)
1707
{
1708
    uint8_t rs6, rs4, rs2, rs0;
1709
    uint8_t rt6, rt4, rt2, rt0;
1710
    uint64_t temp;
1711

    
1712
    rs6 = (rs >> 56) & MIPSDSP_Q0;
1713
    rs4 = (rs >> 40) & MIPSDSP_Q0;
1714
    rs2 = (rs >> 24) & MIPSDSP_Q0;
1715
    rs0 = (rs >> 8) & MIPSDSP_Q0;
1716
    rt6 = (rt >> 56) & MIPSDSP_Q0;
1717
    rt4 = (rt >> 40) & MIPSDSP_Q0;
1718
    rt2 = (rt >> 24) & MIPSDSP_Q0;
1719
    rt0 = (rt >> 8) & MIPSDSP_Q0;
1720

    
1721
    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
1722
           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
1723
           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
1724
           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
1725

    
1726
    return temp;
1727
}
1728

    
1729
target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt)
1730
{
1731
    uint16_t tempD, tempC, tempB, tempA;
1732

    
1733
    tempD = (rs >> 48) & MIPSDSP_LO;
1734
    tempC = (rs >> 16) & MIPSDSP_LO;
1735
    tempB = (rt >> 48) & MIPSDSP_LO;
1736
    tempA = (rt >> 16) & MIPSDSP_LO;
1737

    
1738
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1739
}
1740

    
1741
target_ulong helper_precrq_rs_qh_pw(target_ulong rs, target_ulong rt,
1742
                                    CPUMIPSState *env)
1743
{
1744
    uint32_t rs2, rs0;
1745
    uint32_t rt2, rt0;
1746
    uint16_t tempD, tempC, tempB, tempA;
1747

    
1748
    rs2 = (rs >> 32) & MIPSDSP_LLO;
1749
    rs0 = rs & MIPSDSP_LLO;
1750
    rt2 = (rt >> 32) & MIPSDSP_LLO;
1751
    rt0 = rt & MIPSDSP_LLO;
1752

    
1753
    tempD = mipsdsp_trunc16_sat16_round(rs2, env);
1754
    tempC = mipsdsp_trunc16_sat16_round(rs0, env);
1755
    tempB = mipsdsp_trunc16_sat16_round(rt2, env);
1756
    tempA = mipsdsp_trunc16_sat16_round(rt0, env);
1757

    
1758
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1759
}
1760

    
1761
target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt)
1762
{
1763
    uint32_t tempB, tempA;
1764

    
1765
    tempB = (rs >> 32) & MIPSDSP_LLO;
1766
    tempA = (rt >> 32) & MIPSDSP_LLO;
1767

    
1768
    return MIPSDSP_RETURN64_32(tempB, tempA);
1769
}
1770
#endif
1771

    
1772
target_ulong helper_precrqu_s_qb_ph(target_ulong rs, target_ulong rt,
1773
                                    CPUMIPSState *env)
1774
{
1775
    uint8_t  tempD, tempC, tempB, tempA;
1776
    uint16_t rsh, rsl, rth, rtl;
1777

    
1778
    rsh = (rs & MIPSDSP_HI) >> 16;
1779
    rsl =  rs & MIPSDSP_LO;
1780
    rth = (rt & MIPSDSP_HI) >> 16;
1781
    rtl =  rt & MIPSDSP_LO;
1782

    
1783
    tempD = mipsdsp_sat8_reduce_precision(rsh, env);
1784
    tempC = mipsdsp_sat8_reduce_precision(rsl, env);
1785
    tempB = mipsdsp_sat8_reduce_precision(rth, env);
1786
    tempA = mipsdsp_sat8_reduce_precision(rtl, env);
1787

    
1788
    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);
1789
}
1790

    
1791
#if defined(TARGET_MIPS64)
1792
target_ulong helper_precrqu_s_ob_qh(target_ulong rs, target_ulong rt,
1793
                                    CPUMIPSState *env)
1794
{
1795
    int i;
1796
    uint16_t rs3, rs2, rs1, rs0;
1797
    uint16_t rt3, rt2, rt1, rt0;
1798
    uint8_t temp[8];
1799
    uint64_t result;
1800

    
1801
    result = 0;
1802

    
1803
    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
1804
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
1805

    
1806
    temp[7] = mipsdsp_sat8_reduce_precision(rs3, env);
1807
    temp[6] = mipsdsp_sat8_reduce_precision(rs2, env);
1808
    temp[5] = mipsdsp_sat8_reduce_precision(rs1, env);
1809
    temp[4] = mipsdsp_sat8_reduce_precision(rs0, env);
1810
    temp[3] = mipsdsp_sat8_reduce_precision(rt3, env);
1811
    temp[2] = mipsdsp_sat8_reduce_precision(rt2, env);
1812
    temp[1] = mipsdsp_sat8_reduce_precision(rt1, env);
1813
    temp[0] = mipsdsp_sat8_reduce_precision(rt0, env);
1814

    
1815
    for (i = 0; i < 8; i++) {
1816
        result |= (uint64_t)temp[i] << (8 * i);
1817
    }
1818

    
1819
    return result;
1820
}
1821

    
1822
#define PRECEQ_PW(name, a, b) \
1823
target_ulong helper_preceq_pw_##name(target_ulong rt) \
1824
{                                                       \
1825
    uint16_t tempB, tempA;                              \
1826
    uint32_t tempBI, tempAI;                            \
1827
                                                        \
1828
    tempB = (rt >> a) & MIPSDSP_LO;                     \
1829
    tempA = (rt >> b) & MIPSDSP_LO;                     \
1830
                                                        \
1831
    tempBI = (uint32_t)tempB << 16;                     \
1832
    tempAI = (uint32_t)tempA << 16;                     \
1833
                                                        \
1834
    return MIPSDSP_RETURN64_32(tempBI, tempAI);         \
1835
}
1836

    
1837
PRECEQ_PW(qhl, 48, 32);
1838
PRECEQ_PW(qhr, 16, 0);
1839
PRECEQ_PW(qhla, 48, 16);
1840
PRECEQ_PW(qhra, 32, 0);
1841

    
1842
#undef PRECEQ_PW
1843

    
1844
#endif
1845

    
1846
#define PRECEQU_PH(name, a, b) \
1847
target_ulong helper_precequ_ph_##name(target_ulong rt) \
1848
{                                                        \
1849
    uint16_t tempB, tempA;                               \
1850
                                                         \
1851
    tempB = (rt >> a) & MIPSDSP_Q0;                      \
1852
    tempA = (rt >> b) & MIPSDSP_Q0;                      \
1853
                                                         \
1854
    tempB = tempB << 7;                                  \
1855
    tempA = tempA << 7;                                  \
1856
                                                         \
1857
    return MIPSDSP_RETURN32_16(tempB, tempA);            \
1858
}
1859

    
1860
PRECEQU_PH(qbl, 24, 16);
1861
PRECEQU_PH(qbr, 8, 0);
1862
PRECEQU_PH(qbla, 24, 8);
1863
PRECEQU_PH(qbra, 16, 0);
1864

    
1865
#undef PRECEQU_PH
1866

    
1867
#if defined(TARGET_MIPS64)
1868
#define PRECEQU_QH(name, a, b, c, d) \
1869
target_ulong helper_precequ_qh_##name(target_ulong rt)       \
1870
{                                                            \
1871
    uint16_t tempD, tempC, tempB, tempA;                     \
1872
                                                             \
1873
    tempD = (rt >> a) & MIPSDSP_Q0;                          \
1874
    tempC = (rt >> b) & MIPSDSP_Q0;                          \
1875
    tempB = (rt >> c) & MIPSDSP_Q0;                          \
1876
    tempA = (rt >> d) & MIPSDSP_Q0;                          \
1877
                                                             \
1878
    tempD = tempD << 7;                                      \
1879
    tempC = tempC << 7;                                      \
1880
    tempB = tempB << 7;                                      \
1881
    tempA = tempA << 7;                                      \
1882
                                                             \
1883
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
1884
}
1885

    
1886
PRECEQU_QH(obl, 56, 48, 40, 32);
1887
PRECEQU_QH(obr, 24, 16, 8, 0);
1888
PRECEQU_QH(obla, 56, 40, 24, 8);
1889
PRECEQU_QH(obra, 48, 32, 16, 0);
1890

    
1891
#undef PRECEQU_QH
1892

    
1893
#endif
1894

    
1895
#define PRECEU_PH(name, a, b) \
1896
target_ulong helper_preceu_ph_##name(target_ulong rt) \
1897
{                                                     \
1898
    uint16_t tempB, tempA;                            \
1899
                                                      \
1900
    tempB = (rt >> a) & MIPSDSP_Q0;                   \
1901
    tempA = (rt >> b) & MIPSDSP_Q0;                   \
1902
                                                      \
1903
    return MIPSDSP_RETURN32_16(tempB, tempA);         \
1904
}
1905

    
1906
PRECEU_PH(qbl, 24, 16);
1907
PRECEU_PH(qbr, 8, 0);
1908
PRECEU_PH(qbla, 24, 8);
1909
PRECEU_PH(qbra, 16, 0);
1910

    
1911
#undef PRECEU_PH
1912

    
1913
#if defined(TARGET_MIPS64)
1914
#define PRECEU_QH(name, a, b, c, d) \
1915
target_ulong helper_preceu_qh_##name(target_ulong rt)        \
1916
{                                                            \
1917
    uint16_t tempD, tempC, tempB, tempA;                     \
1918
                                                             \
1919
    tempD = (rt >> a) & MIPSDSP_Q0;                          \
1920
    tempC = (rt >> b) & MIPSDSP_Q0;                          \
1921
    tempB = (rt >> c) & MIPSDSP_Q0;                          \
1922
    tempA = (rt >> d) & MIPSDSP_Q0;                          \
1923
                                                             \
1924
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
1925
}
1926

    
1927
PRECEU_QH(obl, 56, 48, 40, 32);
1928
PRECEU_QH(obr, 24, 16, 8, 0);
1929
PRECEU_QH(obla, 56, 40, 24, 8);
1930
PRECEU_QH(obra, 48, 32, 16, 0);
1931

    
1932
#undef PRECEU_QH
1933

    
1934
#endif
1935

    
1936
/** DSP GPR-Based Shift Sub-class insns **/
1937
#define SHIFT_QB(name, func) \
1938
target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt) \
1939
{                                                                    \
1940
    uint8_t rt3, rt2, rt1, rt0;                                      \
1941
                                                                     \
1942
    sa = sa & 0x07;                                                  \
1943
                                                                     \
1944
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                       \
1945
                                                                     \
1946
    rt3 = mipsdsp_##func(rt3, sa);                                   \
1947
    rt2 = mipsdsp_##func(rt2, sa);                                   \
1948
    rt1 = mipsdsp_##func(rt1, sa);                                   \
1949
    rt0 = mipsdsp_##func(rt0, sa);                                   \
1950
                                                                     \
1951
    return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0);                   \
1952
}
1953

    
1954
#define SHIFT_QB_ENV(name, func) \
1955
target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt,\
1956
                                CPUMIPSState *env) \
1957
{                                                                    \
1958
    uint8_t rt3, rt2, rt1, rt0;                                      \
1959
                                                                     \
1960
    sa = sa & 0x07;                                                  \
1961
                                                                     \
1962
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                       \
1963
                                                                     \
1964
    rt3 = mipsdsp_##func(rt3, sa, env);                              \
1965
    rt2 = mipsdsp_##func(rt2, sa, env);                              \
1966
    rt1 = mipsdsp_##func(rt1, sa, env);                              \
1967
    rt0 = mipsdsp_##func(rt0, sa, env);                              \
1968
                                                                     \
1969
    return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0);                   \
1970
}
1971

    
1972
SHIFT_QB_ENV(shll, lshift8);
1973
SHIFT_QB(shrl, rshift_u8);
1974

    
1975
SHIFT_QB(shra, rashift8);
1976
SHIFT_QB(shra_r, rnd8_rashift);
1977

    
1978
#undef SHIFT_QB
1979
#undef SHIFT_QB_ENV
1980

    
1981
#if defined(TARGET_MIPS64)
1982
#define SHIFT_OB(name, func) \
1983
target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \
1984
{                                                                        \
1985
    int i;                                                               \
1986
    uint8_t rt_t[8];                                                     \
1987
    uint64_t temp;                                                       \
1988
                                                                         \
1989
    sa = sa & 0x07;                                                      \
1990
    temp = 0;                                                            \
1991
                                                                         \
1992
    for (i = 0; i < 8; i++) {                                            \
1993
        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                          \
1994
        rt_t[i] = mipsdsp_##func(rt_t[i], sa);                           \
1995
        temp |= (uint64_t)rt_t[i] << (8 * i);                            \
1996
    }                                                                    \
1997
                                                                         \
1998
    return temp;                                                         \
1999
}
2000

    
2001
#define SHIFT_OB_ENV(name, func) \
2002
target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \
2003
                                CPUMIPSState *env)                       \
2004
{                                                                        \
2005
    int i;                                                               \
2006
    uint8_t rt_t[8];                                                     \
2007
    uint64_t temp;                                                       \
2008
                                                                         \
2009
    sa = sa & 0x07;                                                      \
2010
    temp = 0;                                                            \
2011
                                                                         \
2012
    for (i = 0; i < 8; i++) {                                            \
2013
        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                          \
2014
        rt_t[i] = mipsdsp_##func(rt_t[i], sa, env);                      \
2015
        temp |= (uint64_t)rt_t[i] << (8 * i);                            \
2016
    }                                                                    \
2017
                                                                         \
2018
    return temp;                                                         \
2019
}
2020

    
2021
SHIFT_OB_ENV(shll, lshift8);
2022
SHIFT_OB(shrl, rshift_u8);
2023

    
2024
SHIFT_OB(shra, rashift8);
2025
SHIFT_OB(shra_r, rnd8_rashift);
2026

    
2027
#undef SHIFT_OB
2028
#undef SHIFT_OB_ENV
2029

    
2030
#endif
2031

    
2032
#define SHIFT_PH(name, func) \
2033
target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt, \
2034
                                CPUMIPSState *env)                \
2035
{                                                                 \
2036
    uint16_t rth, rtl;                                            \
2037
                                                                  \
2038
    sa = sa & 0x0F;                                               \
2039
                                                                  \
2040
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
2041
                                                                  \
2042
    rth = mipsdsp_##func(rth, sa, env);                           \
2043
    rtl = mipsdsp_##func(rtl, sa, env);                           \
2044
                                                                  \
2045
    return MIPSDSP_RETURN32_16(rth, rtl);                         \
2046
}
2047

    
2048
SHIFT_PH(shll, lshift16);
2049
SHIFT_PH(shll_s, sat16_lshift);
2050

    
2051
#undef SHIFT_PH
2052

    
2053
#if defined(TARGET_MIPS64)
2054
#define SHIFT_QH(name, func) \
2055
target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa) \
2056
{                                                                 \
2057
    uint16_t rt3, rt2, rt1, rt0;                                  \
2058
                                                                  \
2059
    sa = sa & 0x0F;                                               \
2060
                                                                  \
2061
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                   \
2062
                                                                  \
2063
    rt3 = mipsdsp_##func(rt3, sa);                                \
2064
    rt2 = mipsdsp_##func(rt2, sa);                                \
2065
    rt1 = mipsdsp_##func(rt1, sa);                                \
2066
    rt0 = mipsdsp_##func(rt0, sa);                                \
2067
                                                                  \
2068
    return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0);               \
2069
}
2070

    
2071
#define SHIFT_QH_ENV(name, func) \
2072
target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa, \
2073
                                CPUMIPSState *env)                \
2074
{                                                                 \
2075
    uint16_t rt3, rt2, rt1, rt0;                                  \
2076
                                                                  \
2077
    sa = sa & 0x0F;                                               \
2078
                                                                  \
2079
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                   \
2080
                                                                  \
2081
    rt3 = mipsdsp_##func(rt3, sa, env);                           \
2082
    rt2 = mipsdsp_##func(rt2, sa, env);                           \
2083
    rt1 = mipsdsp_##func(rt1, sa, env);                           \
2084
    rt0 = mipsdsp_##func(rt0, sa, env);                           \
2085
                                                                  \
2086
    return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0);               \
2087
}
2088

    
2089
SHIFT_QH_ENV(shll, lshift16);
2090
SHIFT_QH_ENV(shll_s, sat16_lshift);
2091

    
2092
SHIFT_QH(shrl, rshift_u16);
2093
SHIFT_QH(shra, rashift16);
2094
SHIFT_QH(shra_r, rnd16_rashift);
2095

    
2096
#undef SHIFT_QH
2097
#undef SHIFT_QH_ENV
2098

    
2099
#endif
2100

    
2101
#define SHIFT_W(name, func) \
2102
target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \
2103
{                                                                       \
2104
    uint32_t temp;                                                      \
2105
                                                                        \
2106
    sa = sa & 0x1F;                                                     \
2107
    temp = mipsdsp_##func(rt, sa);                                      \
2108
                                                                        \
2109
    return (target_long)(int32_t)temp;                                  \
2110
}
2111

    
2112
#define SHIFT_W_ENV(name, func) \
2113
target_ulong helper_##name##_w(target_ulong sa, target_ulong rt, \
2114
                               CPUMIPSState *env) \
2115
{                                                                       \
2116
    uint32_t temp;                                                      \
2117
                                                                        \
2118
    sa = sa & 0x1F;                                                     \
2119
    temp = mipsdsp_##func(rt, sa, env);                                 \
2120
                                                                        \
2121
    return (target_long)(int32_t)temp;                                  \
2122
}
2123

    
2124
SHIFT_W_ENV(shll_s, sat32_lshift);
2125
SHIFT_W(shra_r, rnd32_rashift);
2126

    
2127
#undef SHIFT_W
2128
#undef SHIFT_W_ENV
2129

    
2130
#if defined(TARGET_MIPS64)
2131
#define SHIFT_PW(name, func) \
2132
target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa) \
2133
{                                                                 \
2134
    uint32_t rt1, rt0;                                            \
2135
                                                                  \
2136
    sa = sa & 0x1F;                                               \
2137
    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
2138
                                                                  \
2139
    rt1 = mipsdsp_##func(rt1, sa);                                \
2140
    rt0 = mipsdsp_##func(rt0, sa);                                \
2141
                                                                  \
2142
    return MIPSDSP_RETURN64_32(rt1, rt0);                         \
2143
}
2144

    
2145
#define SHIFT_PW_ENV(name, func) \
2146
target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa, \
2147
                                CPUMIPSState *env)                \
2148
{                                                                 \
2149
    uint32_t rt1, rt0;                                            \
2150
                                                                  \
2151
    sa = sa & 0x1F;                                               \
2152
    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
2153
                                                                  \
2154
    rt1 = mipsdsp_##func(rt1, sa, env);                           \
2155
    rt0 = mipsdsp_##func(rt0, sa, env);                           \
2156
                                                                  \
2157
    return MIPSDSP_RETURN64_32(rt1, rt0);                         \
2158
}
2159

    
2160
SHIFT_PW_ENV(shll, lshift32);
2161
SHIFT_PW_ENV(shll_s, sat32_lshift);
2162

    
2163
SHIFT_PW(shra, rashift32);
2164
SHIFT_PW(shra_r, rnd32_rashift);
2165

    
2166
#undef SHIFT_PW
2167
#undef SHIFT_PW_ENV
2168

    
2169
#endif
2170

    
2171
#define SHIFT_PH(name, func) \
2172
target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \
2173
{                                                                    \
2174
    uint16_t rth, rtl;                                               \
2175
                                                                     \
2176
    sa = sa & 0x0F;                                                  \
2177
                                                                     \
2178
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                \
2179
                                                                     \
2180
    rth = mipsdsp_##func(rth, sa);                                   \
2181
    rtl = mipsdsp_##func(rtl, sa);                                   \
2182
                                                                     \
2183
    return MIPSDSP_RETURN32_16(rth, rtl);                            \
2184
}
2185

    
2186
SHIFT_PH(shrl, rshift_u16);
2187
SHIFT_PH(shra, rashift16);
2188
SHIFT_PH(shra_r, rnd16_rashift);
2189

    
2190
#undef SHIFT_PH
2191

    
2192
/** DSP Multiply Sub-class insns **/
2193
/* Return value made up by two 16bits value.
2194
 * FIXME give the macro a better name.
2195
 */
2196
#define MUL_RETURN32_16_PH(name, func, \
2197
                           rsmov1, rsmov2, rsfilter, \
2198
                           rtmov1, rtmov2, rtfilter) \
2199
target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2200
                           CPUMIPSState *env)                \
2201
{                                                            \
2202
    uint16_t rsB, rsA, rtB, rtA;                             \
2203
                                                             \
2204
    rsB = (rs >> rsmov1) & rsfilter;                         \
2205
    rsA = (rs >> rsmov2) & rsfilter;                         \
2206
    rtB = (rt >> rtmov1) & rtfilter;                         \
2207
    rtA = (rt >> rtmov2) & rtfilter;                         \
2208
                                                             \
2209
    rsB = mipsdsp_##func(rsB, rtB, env);                     \
2210
    rsA = mipsdsp_##func(rsA, rtA, env);                     \
2211
                                                             \
2212
    return MIPSDSP_RETURN32_16(rsB, rsA);                    \
2213
}
2214

    
2215
MUL_RETURN32_16_PH(muleu_s_ph_qbl, mul_u8_u16, \
2216
                      24, 16, MIPSDSP_Q0, \
2217
                      16, 0, MIPSDSP_LO);
2218
MUL_RETURN32_16_PH(muleu_s_ph_qbr, mul_u8_u16, \
2219
                      8, 0, MIPSDSP_Q0, \
2220
                      16, 0, MIPSDSP_LO);
2221
MUL_RETURN32_16_PH(mulq_rs_ph, rndq15_mul_q15_q15, \
2222
                      16, 0, MIPSDSP_LO, \
2223
                      16, 0, MIPSDSP_LO);
2224
MUL_RETURN32_16_PH(mul_ph, mul_i16_i16, \
2225
                      16, 0, MIPSDSP_LO, \
2226
                      16, 0, MIPSDSP_LO);
2227
MUL_RETURN32_16_PH(mul_s_ph, sat16_mul_i16_i16, \
2228
                      16, 0, MIPSDSP_LO, \
2229
                      16, 0, MIPSDSP_LO);
2230
MUL_RETURN32_16_PH(mulq_s_ph, sat16_mul_q15_q15, \
2231
                      16, 0, MIPSDSP_LO, \
2232
                      16, 0, MIPSDSP_LO);
2233

    
2234
#undef MUL_RETURN32_16_PH
2235

    
2236
#define MUL_RETURN32_32_ph(name, func, movbits) \
2237
target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2238
                                  CPUMIPSState *env)         \
2239
{                                                            \
2240
    int16_t rsh, rth;                                        \
2241
    int32_t temp;                                            \
2242
                                                             \
2243
    rsh = (rs >> movbits) & MIPSDSP_LO;                      \
2244
    rth = (rt >> movbits) & MIPSDSP_LO;                      \
2245
    temp = mipsdsp_##func(rsh, rth, env);                    \
2246
                                                             \
2247
    return (target_long)(int32_t)temp;                       \
2248
}
2249

    
2250
MUL_RETURN32_32_ph(muleq_s_w_phl, mul_q15_q15_overflowflag21, 16);
2251
MUL_RETURN32_32_ph(muleq_s_w_phr, mul_q15_q15_overflowflag21, 0);
2252

    
2253
#undef MUL_RETURN32_32_ph
2254

    
2255
#define MUL_VOID_PH(name, use_ac_env) \
2256
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
2257
                          CPUMIPSState *env)                             \
2258
{                                                                        \
2259
    int16_t rsh, rsl, rth, rtl;                                          \
2260
    int32_t tempB, tempA;                                                \
2261
    int64_t acc, dotp;                                                   \
2262
                                                                         \
2263
    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                                    \
2264
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                    \
2265
                                                                         \
2266
    if (use_ac_env == 1) {                                               \
2267
        tempB = mipsdsp_mul_q15_q15(ac, rsh, rth, env);                  \
2268
        tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl, env);                  \
2269
    } else {                                                             \
2270
        tempB = mipsdsp_mul_u16_u16(rsh, rth);                           \
2271
        tempA = mipsdsp_mul_u16_u16(rsl, rtl);                           \
2272
    }                                                                    \
2273
                                                                         \
2274
    dotp = (int64_t)tempB - (int64_t)tempA;                              \
2275
    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                      \
2276
          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);               \
2277
    dotp = dotp + acc;                                                   \
2278
    env->active_tc.HI[ac] = (target_long)(int32_t)                       \
2279
                            ((dotp & MIPSDSP_LHI) >> 32);                \
2280
    env->active_tc.LO[ac] = (target_long)(int32_t)(dotp & MIPSDSP_LLO);  \
2281
}
2282

    
2283
MUL_VOID_PH(mulsaq_s_w_ph, 1);
2284
MUL_VOID_PH(mulsa_w_ph, 0);
2285

    
2286
#undef MUL_VOID_PH
2287

    
2288
#if defined(TARGET_MIPS64)
2289
#define MUL_RETURN64_16_QH(name, func, \
2290
                           rsmov1, rsmov2, rsmov3, rsmov4, rsfilter, \
2291
                           rtmov1, rtmov2, rtmov3, rtmov4, rtfilter) \
2292
target_ulong helper_##name(target_ulong rs, target_ulong rt,         \
2293
                           CPUMIPSState *env)                        \
2294
{                                                                    \
2295
    uint16_t rs3, rs2, rs1, rs0;                                     \
2296
    uint16_t rt3, rt2, rt1, rt0;                                     \
2297
    uint16_t tempD, tempC, tempB, tempA;                             \
2298
                                                                     \
2299
    rs3 = (rs >> rsmov1) & rsfilter;                                 \
2300
    rs2 = (rs >> rsmov2) & rsfilter;                                 \
2301
    rs1 = (rs >> rsmov3) & rsfilter;                                 \
2302
    rs0 = (rs >> rsmov4) & rsfilter;                                 \
2303
    rt3 = (rt >> rtmov1) & rtfilter;                                 \
2304
    rt2 = (rt >> rtmov2) & rtfilter;                                 \
2305
    rt1 = (rt >> rtmov3) & rtfilter;                                 \
2306
    rt0 = (rt >> rtmov4) & rtfilter;                                 \
2307
                                                                     \
2308
    tempD = mipsdsp_##func(rs3, rt3, env);                           \
2309
    tempC = mipsdsp_##func(rs2, rt2, env);                           \
2310
    tempB = mipsdsp_##func(rs1, rt1, env);                           \
2311
    tempA = mipsdsp_##func(rs0, rt0, env);                           \
2312
                                                                     \
2313
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);          \
2314
}
2315

    
2316
MUL_RETURN64_16_QH(muleu_s_qh_obl, mul_u8_u16, \
2317
                   56, 48, 40, 32, MIPSDSP_Q0, \
2318
                   48, 32, 16, 0, MIPSDSP_LO);
2319
MUL_RETURN64_16_QH(muleu_s_qh_obr, mul_u8_u16, \
2320
                   24, 16, 8, 0, MIPSDSP_Q0, \
2321
                   48, 32, 16, 0, MIPSDSP_LO);
2322
MUL_RETURN64_16_QH(mulq_rs_qh, rndq15_mul_q15_q15, \
2323
                   48, 32, 16, 0, MIPSDSP_LO, \
2324
                   48, 32, 16, 0, MIPSDSP_LO);
2325

    
2326
#undef MUL_RETURN64_16_QH
2327

    
2328
#define MUL_RETURN64_32_QH(name, \
2329
                           rsmov1, rsmov2, \
2330
                           rtmov1, rtmov2) \
2331
target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2332
                           CPUMIPSState *env)                \
2333
{                                                            \
2334
    uint16_t rsB, rsA;                                       \
2335
    uint16_t rtB, rtA;                                       \
2336
    uint32_t tempB, tempA;                                   \
2337
                                                             \
2338
    rsB = (rs >> rsmov1) & MIPSDSP_LO;                       \
2339
    rsA = (rs >> rsmov2) & MIPSDSP_LO;                       \
2340
    rtB = (rt >> rtmov1) & MIPSDSP_LO;                       \
2341
    rtA = (rt >> rtmov2) & MIPSDSP_LO;                       \
2342
                                                             \
2343
    tempB = mipsdsp_mul_q15_q15(5, rsB, rtB, env);           \
2344
    tempA = mipsdsp_mul_q15_q15(5, rsA, rtA, env);           \
2345
                                                             \
2346
    return ((uint64_t)tempB << 32) | (uint64_t)tempA;        \
2347
}
2348

    
2349
MUL_RETURN64_32_QH(muleq_s_pw_qhl, 48, 32, 48, 32);
2350
MUL_RETURN64_32_QH(muleq_s_pw_qhr, 16, 0, 16, 0);
2351

    
2352
#undef MUL_RETURN64_32_QH
2353

    
2354
void helper_mulsaq_s_w_qh(target_ulong rs, target_ulong rt, uint32_t ac,
2355
                          CPUMIPSState *env)
2356
{
2357
    int16_t rs3, rs2, rs1, rs0;
2358
    int16_t rt3, rt2, rt1, rt0;
2359
    int32_t tempD, tempC, tempB, tempA;
2360
    int64_t acc[2];
2361
    int64_t temp[2];
2362
    int64_t temp_sum;
2363

    
2364
    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
2365
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
2366

    
2367
    tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env);
2368
    tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env);
2369
    tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env);
2370
    tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env);
2371

    
2372
    temp[0] = ((int32_t)tempD - (int32_t)tempC) +
2373
              ((int32_t)tempB - (int32_t)tempA);
2374
    temp[0] = (int64_t)(temp[0] << 30) >> 30;
2375
    if (((temp[0] >> 33) & 0x01) == 0) {
2376
        temp[1] = 0x00;
2377
    } else {
2378
        temp[1] = ~0ull;
2379
    }
2380

    
2381
    acc[0] = env->active_tc.LO[ac];
2382
    acc[1] = env->active_tc.HI[ac];
2383

    
2384
    temp_sum = acc[0] + temp[0];
2385
    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
2386
       ((uint64_t)temp_sum < (uint64_t)temp[0])) {
2387
        acc[1] += 1;
2388
    }
2389
    acc[0] = temp_sum;
2390
    acc[1] += temp[1];
2391

    
2392
    env->active_tc.HI[ac] = acc[1];
2393
    env->active_tc.LO[ac] = acc[0];
2394
}
2395
#endif
2396

    
2397
#define DP_QB(name, func, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
2398
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
2399
                   CPUMIPSState *env)                                    \
2400
{                                                                        \
2401
    uint8_t rs3, rs2;                                                    \
2402
    uint8_t rt3, rt2;                                                    \
2403
    uint16_t tempB, tempA;                                               \
2404
    uint64_t tempC, dotp;                                                \
2405
                                                                         \
2406
    rs3 = (rs >> rsmov1) & MIPSDSP_Q0;                                   \
2407
    rs2 = (rs >> rsmov2) & MIPSDSP_Q0;                                   \
2408
    rt3 = (rt >> rtmov1) & MIPSDSP_Q0;                                   \
2409
    rt2 = (rt >> rtmov2) & MIPSDSP_Q0;                                   \
2410
    tempB = mipsdsp_##func(rs3, rt3);                                    \
2411
    tempA = mipsdsp_##func(rs2, rt2);                                    \
2412
    dotp = (int64_t)tempB + (int64_t)tempA;                              \
2413
    if (is_add) {                                                        \
2414
        tempC = (((uint64_t)env->active_tc.HI[ac] << 32) |               \
2415
                 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO))        \
2416
            + dotp;                                                      \
2417
    } else {                                                             \
2418
        tempC = (((uint64_t)env->active_tc.HI[ac] << 32) |               \
2419
                 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO))        \
2420
            - dotp;                                                      \
2421
    }                                                                    \
2422
                                                                         \
2423
    env->active_tc.HI[ac] = (target_long)(int32_t)                       \
2424
                            ((tempC & MIPSDSP_LHI) >> 32);               \
2425
    env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO); \
2426
}
2427

    
2428
DP_QB(dpau_h_qbl, mul_u8_u8, 1, 24, 16, 24, 16);
2429
DP_QB(dpau_h_qbr, mul_u8_u8, 1, 8, 0, 8, 0);
2430
DP_QB(dpsu_h_qbl, mul_u8_u8, 0, 24, 16, 24, 16);
2431
DP_QB(dpsu_h_qbr, mul_u8_u8, 0, 8, 0, 8, 0);
2432

    
2433
#undef DP_QB
2434

    
2435
#if defined(TARGET_MIPS64)
2436
#define DP_OB(name, add_sub, \
2437
              rsmov1, rsmov2, rsmov3, rsmov4, \
2438
              rtmov1, rtmov2, rtmov3, rtmov4) \
2439
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,       \
2440
                       CPUMIPSState *env)                               \
2441
{                                                                       \
2442
    uint8_t rsD, rsC, rsB, rsA;                                         \
2443
    uint8_t rtD, rtC, rtB, rtA;                                         \
2444
    uint16_t tempD, tempC, tempB, tempA;                                \
2445
    uint64_t temp[2];                                                   \
2446
    uint64_t acc[2];                                                    \
2447
    uint64_t temp_sum;                                                  \
2448
                                                                        \
2449
    temp[0] = 0;                                                        \
2450
    temp[1] = 0;                                                        \
2451
                                                                        \
2452
    rsD = (rs >> rsmov1) & MIPSDSP_Q0;                                  \
2453
    rsC = (rs >> rsmov2) & MIPSDSP_Q0;                                  \
2454
    rsB = (rs >> rsmov3) & MIPSDSP_Q0;                                  \
2455
    rsA = (rs >> rsmov4) & MIPSDSP_Q0;                                  \
2456
    rtD = (rt >> rtmov1) & MIPSDSP_Q0;                                  \
2457
    rtC = (rt >> rtmov2) & MIPSDSP_Q0;                                  \
2458
    rtB = (rt >> rtmov3) & MIPSDSP_Q0;                                  \
2459
    rtA = (rt >> rtmov4) & MIPSDSP_Q0;                                  \
2460
                                                                        \
2461
    tempD = mipsdsp_mul_u8_u8(rsD, rtD);                                \
2462
    tempC = mipsdsp_mul_u8_u8(rsC, rtC);                                \
2463
    tempB = mipsdsp_mul_u8_u8(rsB, rtB);                                \
2464
    tempA = mipsdsp_mul_u8_u8(rsA, rtA);                                \
2465
                                                                        \
2466
    temp[0] = (uint64_t)tempD + (uint64_t)tempC +                       \
2467
      (uint64_t)tempB + (uint64_t)tempA;                                \
2468
                                                                        \
2469
    acc[0] = env->active_tc.LO[ac];                                     \
2470
    acc[1] = env->active_tc.HI[ac];                                     \
2471
                                                                        \
2472
    if (add_sub) {                                                      \
2473
        temp_sum = acc[0] + temp[0];                                    \
2474
        if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&                  \
2475
            ((uint64_t)temp_sum < (uint64_t)temp[0])) {                 \
2476
            acc[1] += 1;                                                \
2477
        }                                                               \
2478
        temp[0] = temp_sum;                                             \
2479
        temp[1] = acc[1] + temp[1];                                     \
2480
    } else {                                                            \
2481
        temp_sum = acc[0] - temp[0];                                    \
2482
        if ((uint64_t)temp_sum > (uint64_t)acc[0]) {                    \
2483
            acc[1] -= 1;                                                \
2484
        }                                                               \
2485
        temp[0] = temp_sum;                                             \
2486
        temp[1] = acc[1] - temp[1];                                     \
2487
    }                                                                   \
2488
                                                                        \
2489
    env->active_tc.HI[ac] = temp[1];                                    \
2490
    env->active_tc.LO[ac] = temp[0];                                    \
2491
}
2492

    
2493
DP_OB(dpau_h_obl, 1, 56, 48, 40, 32, 56, 48, 40, 32);
2494
DP_OB(dpau_h_obr, 1, 24, 16, 8, 0, 24, 16, 8, 0);
2495
DP_OB(dpsu_h_obl, 0, 56, 48, 40, 32, 56, 48, 40, 32);
2496
DP_OB(dpsu_h_obr, 0, 24, 16, 8, 0, 24, 16, 8, 0);
2497

    
2498
#undef DP_OB
2499
#endif
2500

    
2501
#define DP_NOFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2)             \
2502
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,              \
2503
                   CPUMIPSState *env)                                          \
2504
{                                                                              \
2505
    uint16_t rsB, rsA, rtB, rtA;                                               \
2506
    int32_t  tempA, tempB;                                                     \
2507
    int64_t  acc;                                                              \
2508
                                                                               \
2509
    rsB = (rs >> rsmov1) & MIPSDSP_LO;                                         \
2510
    rsA = (rs >> rsmov2) & MIPSDSP_LO;                                         \
2511
    rtB = (rt >> rtmov1) & MIPSDSP_LO;                                         \
2512
    rtA = (rt >> rtmov2) & MIPSDSP_LO;                                         \
2513
                                                                               \
2514
    tempB = (int32_t)rsB * (int32_t)rtB;                                       \
2515
    tempA = (int32_t)rsA * (int32_t)rtA;                                       \
2516
                                                                               \
2517
    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                            \
2518
          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);                     \
2519
                                                                               \
2520
    if (is_add) {                                                              \
2521
        acc = acc + ((int64_t)tempB + (int64_t)tempA);                         \
2522
    } else {                                                                   \
2523
        acc = acc - ((int64_t)tempB + (int64_t)tempA);                         \
2524
    }                                                                          \
2525
                                                                               \
2526
    env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32); \
2527
    env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO);         \
2528
}
2529

    
2530
DP_NOFUNC_PH(dpa_w_ph, 1, 16, 0, 16, 0);
2531
DP_NOFUNC_PH(dpax_w_ph, 1, 16, 0, 0, 16);
2532
DP_NOFUNC_PH(dps_w_ph, 0, 16, 0, 16, 0);
2533
DP_NOFUNC_PH(dpsx_w_ph, 0, 16, 0, 0, 16);
2534
#undef DP_NOFUNC_PH
2535

    
2536
#define DP_HASFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
2537
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,   \
2538
                   CPUMIPSState *env)                      \
2539
{                                                          \
2540
    int16_t rsB, rsA, rtB, rtA;                            \
2541
    int32_t tempB, tempA;                                  \
2542
    int64_t acc, dotp;                                     \
2543
                                                           \
2544
    rsB = (rs >> rsmov1) & MIPSDSP_LO;                     \
2545
    rsA = (rs >> rsmov2) & MIPSDSP_LO;                     \
2546
    rtB = (rt >> rtmov1) & MIPSDSP_LO;                     \
2547
    rtA = (rt >> rtmov2) & MIPSDSP_LO;                     \
2548
                                                           \
2549
    tempB = mipsdsp_mul_q15_q15(ac, rsB, rtB, env);        \
2550
    tempA = mipsdsp_mul_q15_q15(ac, rsA, rtA, env);        \
2551
                                                           \
2552
    dotp = (int64_t)tempB + (int64_t)tempA;                \
2553
    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |        \
2554
          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
2555
                                                           \
2556
    if (is_add) {                                          \
2557
        acc = acc + dotp;                                  \
2558
    } else {                                               \
2559
        acc = acc - dotp;                                  \
2560
    }                                                      \
2561
                                                           \
2562
    env->active_tc.HI[ac] = (target_long)(int32_t)         \
2563
        ((acc & MIPSDSP_LHI) >> 32);                       \
2564
    env->active_tc.LO[ac] = (target_long)(int32_t)         \
2565
        (acc & MIPSDSP_LLO);                               \
2566
}
2567

    
2568
DP_HASFUNC_PH(dpaq_s_w_ph, 1, 16, 0, 16, 0);
2569
DP_HASFUNC_PH(dpaqx_s_w_ph, 1, 16, 0, 0, 16);
2570
DP_HASFUNC_PH(dpsq_s_w_ph, 0, 16, 0, 16, 0);
2571
DP_HASFUNC_PH(dpsqx_s_w_ph, 0, 16, 0, 0, 16);
2572

    
2573
#undef DP_HASFUNC_PH
2574

    
2575
#define DP_128OPERATION_PH(name, is_add) \
2576
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2577
                          CPUMIPSState *env)                             \
2578
{                                                                        \
2579
    int16_t rsh, rsl, rth, rtl;                                          \
2580
    int32_t tempB, tempA, tempC62_31, tempC63;                           \
2581
    int64_t acc, dotp, tempC;                                            \
2582
                                                                         \
2583
    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                                    \
2584
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                    \
2585
                                                                         \
2586
    tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl, env);                      \
2587
    tempA = mipsdsp_mul_q15_q15(ac, rsl, rth, env);                      \
2588
                                                                         \
2589
    dotp = (int64_t)tempB + (int64_t)tempA;                              \
2590
    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                      \
2591
          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);               \
2592
    if (is_add) {                                                        \
2593
        tempC = acc + dotp;                                              \
2594
    } else {                                                             \
2595
        tempC = acc - dotp;                                              \
2596
    }                                                                    \
2597
    tempC63 = (tempC >> 63) & 0x01;                                      \
2598
    tempC62_31 = (tempC >> 31) & 0xFFFFFFFF;                             \
2599
                                                                         \
2600
    if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) {                  \
2601
        tempC = 0x7FFFFFFF;                                              \
2602
        set_DSPControl_overflow_flag(1, 16 + ac, env);                   \
2603
    }                                                                    \
2604
                                                                         \
2605
    if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) {                  \
2606
        tempC = (int64_t)(int32_t)0x80000000;                            \
2607
        set_DSPControl_overflow_flag(1, 16 + ac, env);                   \
2608
    }                                                                    \
2609
                                                                         \
2610
    env->active_tc.HI[ac] = (target_long)(int32_t)                       \
2611
        ((tempC & MIPSDSP_LHI) >> 32);                                   \
2612
    env->active_tc.LO[ac] = (target_long)(int32_t)                       \
2613
        (tempC & MIPSDSP_LLO);                                           \
2614
}
2615

    
2616
DP_128OPERATION_PH(dpaqx_sa_w_ph, 1);
2617
DP_128OPERATION_PH(dpsqx_sa_w_ph, 0);
2618

    
2619
#undef DP_128OPERATION_HP
2620

    
2621
#if defined(TARGET_MIPS64)
2622
#define DP_QH(name, is_add, use_ac_env) \
2623
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,    \
2624
                   CPUMIPSState *env)                                \
2625
{                                                                    \
2626
    int32_t rs3, rs2, rs1, rs0;                                      \
2627
    int32_t rt3, rt2, rt1, rt0;                                      \
2628
    int32_t tempD, tempC, tempB, tempA;                              \
2629
    int64_t acc[2];                                                  \
2630
    int64_t temp[2];                                                 \
2631
    int64_t temp_sum;                                                \
2632
                                                                     \
2633
    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);                      \
2634
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                      \
2635
                                                                     \
2636
    if (use_ac_env) {                                                \
2637
        tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env);              \
2638
        tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env);              \
2639
        tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env);              \
2640
        tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env);              \
2641
    } else {                                                         \
2642
        tempD = mipsdsp_mul_u16_u16(rs3, rt3);                       \
2643
        tempC = mipsdsp_mul_u16_u16(rs2, rt2);                       \
2644
        tempB = mipsdsp_mul_u16_u16(rs1, rt1);                       \
2645
        tempA = mipsdsp_mul_u16_u16(rs0, rt0);                       \
2646
    }                                                                \
2647
                                                                     \
2648
    temp[0] = (int64_t)tempD + (int64_t)tempC +                      \
2649
              (int64_t)tempB + (int64_t)tempA;                       \
2650
                                                                     \
2651
    if (temp[0] >= 0) {                                              \
2652
        temp[1] = 0;                                                 \
2653
    } else {                                                         \
2654
        temp[1] = ~0ull;                                             \
2655
    }                                                                \
2656
                                                                     \
2657
    acc[1] = env->active_tc.HI[ac];                                  \
2658
    acc[0] = env->active_tc.LO[ac];                                  \
2659
                                                                     \
2660
    if (is_add) {                                                    \
2661
        temp_sum = acc[0] + temp[0];                                 \
2662
        if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&               \
2663
            ((uint64_t)temp_sum < (uint64_t)temp[0])) {              \
2664
            acc[1] = acc[1] + 1;                                     \
2665
        }                                                            \
2666
        temp[0] = temp_sum;                                          \
2667
        temp[1] = acc[1] + temp[1];                                  \
2668
    } else {                                                         \
2669
        temp_sum = acc[0] - temp[0];                                 \
2670
        if ((uint64_t)temp_sum > (uint64_t)acc[0]) {                 \
2671
            acc[1] = acc[1] - 1;                                     \
2672
        }                                                            \
2673
        temp[0] = temp_sum;                                          \
2674
        temp[1] = acc[1] - temp[1];                                  \
2675
    }                                                                \
2676
                                                                     \
2677
    env->active_tc.HI[ac] = temp[1];                                 \
2678
    env->active_tc.LO[ac] = temp[0];                                 \
2679
}
2680

    
2681
DP_QH(dpa_w_qh, 1, 0);
2682
DP_QH(dpaq_s_w_qh, 1, 1);
2683
DP_QH(dps_w_qh, 0, 0);
2684
DP_QH(dpsq_s_w_qh, 0, 1);
2685

    
2686
#undef DP_QH
2687

    
2688
#endif
2689

    
2690
#define DP_L_W(name, is_add) \
2691
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,     \
2692
                   CPUMIPSState *env)                                 \
2693
{                                                                     \
2694
    int32_t temp63;                                                   \
2695
    int64_t dotp, acc;                                                \
2696
    uint64_t temp;                                                    \
2697
                                                                      \
2698
    dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env);                      \
2699
    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                   \
2700
          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);            \
2701
    if (!is_add) {                                                    \
2702
        dotp = -dotp;                                                 \
2703
    }                                                                 \
2704
                                                                      \
2705
    temp = acc + dotp;                                                \
2706
    if (MIPSDSP_OVERFLOW((uint64_t)acc, (uint64_t)dotp, temp,         \
2707
                         (0x01ull << 63))) {                          \
2708
        temp63 = (temp >> 63) & 0x01;                                 \
2709
        if (temp63 == 1) {                                            \
2710
            temp = (0x01ull << 63) - 1;                               \
2711
        } else {                                                      \
2712
            temp = 0x01ull << 63;                                     \
2713
        }                                                             \
2714
                                                                      \
2715
        set_DSPControl_overflow_flag(1, 16 + ac, env);                \
2716
    }                                                                 \
2717
                                                                      \
2718
    env->active_tc.HI[ac] = (target_long)(int32_t)                    \
2719
        ((temp & MIPSDSP_LHI) >> 32);                                 \
2720
    env->active_tc.LO[ac] = (target_long)(int32_t)                    \
2721
        (temp & MIPSDSP_LLO);                                         \
2722
}
2723

    
2724
DP_L_W(dpaq_sa_l_w, 1);
2725
DP_L_W(dpsq_sa_l_w, 0);
2726

    
2727
#undef DP_L_W
2728

    
2729
#if defined(TARGET_MIPS64)
2730
#define DP_L_PW(name, func) \
2731
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2732
                   CPUMIPSState *env)                             \
2733
{                                                                 \
2734
    int32_t rs1, rs0;                                             \
2735
    int32_t rt1, rt0;                                             \
2736
    int64_t tempB[2], tempA[2];                                   \
2737
    int64_t temp[2];                                              \
2738
    int64_t acc[2];                                               \
2739
    int64_t temp_sum;                                             \
2740
                                                                  \
2741
    temp[0] = 0;                                                  \
2742
    temp[1] = 0;                                                  \
2743
                                                                  \
2744
    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                             \
2745
    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
2746
                                                                  \
2747
    tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env);            \
2748
    tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);            \
2749
                                                                  \
2750
    if (tempB[0] >= 0) {                                          \
2751
        tempB[1] = 0x00;                                          \
2752
    } else {                                                      \
2753
        tempB[1] = ~0ull;                                         \
2754
    }                                                             \
2755
                                                                  \
2756
    if (tempA[0] >= 0) {                                          \
2757
        tempA[1] = 0x00;                                          \
2758
    } else {                                                      \
2759
        tempA[1] = ~0ull;                                         \
2760
    }                                                             \
2761
                                                                  \
2762
    temp_sum = tempB[0] + tempA[0];                               \
2763
    if (((uint64_t)temp_sum < (uint64_t)tempB[0]) &&              \
2764
        ((uint64_t)temp_sum < (uint64_t)tempA[0])) {              \
2765
        temp[1] += 1;                                             \
2766
    }                                                             \
2767
    temp[0] = temp_sum;                                           \
2768
    temp[1] += tempB[1] + tempA[1];                               \
2769
                                                                  \
2770
    mipsdsp_##func(acc, ac, temp, env);                           \
2771
                                                                  \
2772
    env->active_tc.HI[ac] = acc[1];                               \
2773
    env->active_tc.LO[ac] = acc[0];                               \
2774
}
2775

    
2776
DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63);
2777
DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63);
2778

    
2779
#undef DP_L_PW
2780

    
2781
void helper_mulsaq_s_l_pw(target_ulong rs, target_ulong rt, uint32_t ac,
2782
                          CPUMIPSState *env)
2783
{
2784
    int32_t rs1, rs0;
2785
    int32_t rt1, rt0;
2786
    int64_t tempB[2], tempA[2];
2787
    int64_t temp[2];
2788
    int64_t acc[2];
2789
    int64_t temp_sum;
2790

    
2791
    rs1 = (rs >> 32) & MIPSDSP_LLO;
2792
    rs0 = rs & MIPSDSP_LLO;
2793
    rt1 = (rt >> 32) & MIPSDSP_LLO;
2794
    rt0 = rt & MIPSDSP_LLO;
2795

    
2796
    tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env);
2797
    tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);
2798

    
2799
    if (tempB[0] >= 0) {
2800
        tempB[1] = 0x00;
2801
    } else {
2802
        tempB[1] = ~0ull;
2803
    }
2804

    
2805
    if (tempA[0] >= 0) {
2806
        tempA[1] = 0x00;
2807
    } else {
2808
        tempA[1] = ~0ull;
2809
    }
2810

    
2811
    acc[0] = env->active_tc.LO[ac];
2812
    acc[1] = env->active_tc.HI[ac];
2813

    
2814
    temp_sum = tempB[0] - tempA[0];
2815
    if ((uint64_t)temp_sum > (uint64_t)tempB[0]) {
2816
        tempB[1] -= 1;
2817
    }
2818
    temp[0] = temp_sum;
2819
    temp[1] = tempB[1] - tempA[1];
2820

    
2821
    if ((temp[1] & 0x01) == 0) {
2822
        temp[1] = 0x00;
2823
    } else {
2824
        temp[1] = ~0ull;
2825
    }
2826

    
2827
    temp_sum = acc[0] + temp[0];
2828
    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
2829
       ((uint64_t)temp_sum < (uint64_t)temp[0])) {
2830
        acc[1] += 1;
2831
    }
2832
    acc[0] = temp_sum;
2833
    acc[1] += temp[1];
2834

    
2835
    env->active_tc.HI[ac] = acc[1];
2836
    env->active_tc.LO[ac] = acc[0];
2837
}
2838
#endif
2839

    
2840
#define MAQ_S_W(name, mov) \
2841
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2842
                   CPUMIPSState *env)                             \
2843
{                                                                 \
2844
    int16_t rsh, rth;                                             \
2845
    int32_t tempA;                                                \
2846
    int64_t tempL, acc;                                           \
2847
                                                                  \
2848
    rsh = (rs >> mov) & MIPSDSP_LO;                               \
2849
    rth = (rt >> mov) & MIPSDSP_LO;                               \
2850
    tempA  = mipsdsp_mul_q15_q15(ac, rsh, rth, env);              \
2851
    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |               \
2852
          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);        \
2853
    tempL  = (int64_t)tempA + acc;                                \
2854
    env->active_tc.HI[ac] = (target_long)(int32_t)                \
2855
        ((tempL & MIPSDSP_LHI) >> 32);                            \
2856
    env->active_tc.LO[ac] = (target_long)(int32_t)                \
2857
        (tempL & MIPSDSP_LLO);                                    \
2858
}
2859

    
2860
MAQ_S_W(maq_s_w_phl, 16);
2861
MAQ_S_W(maq_s_w_phr, 0);
2862

    
2863
#undef MAQ_S_W
2864

    
2865
#define MAQ_SA_W(name, mov) \
2866
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
2867
                   CPUMIPSState *env)                                    \
2868
{                                                                        \
2869
    int16_t rsh, rth;                                                    \
2870
    int32_t tempA;                                                       \
2871
                                                                         \
2872
    rsh = (rs >> mov) & MIPSDSP_LO;                                      \
2873
    rth = (rt >> mov) & MIPSDSP_LO;                                      \
2874
    tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env);                      \
2875
    tempA = mipsdsp_sat32_acc_q31(ac, tempA, env);                       \
2876
                                                                         \
2877
    env->active_tc.HI[ac] = (target_long)(int32_t)(((int64_t)tempA &     \
2878
                                                    MIPSDSP_LHI) >> 32); \
2879
    env->active_tc.LO[ac] = (target_long)(int32_t)((int64_t)tempA &      \
2880
                                                   MIPSDSP_LLO);         \
2881
}
2882

    
2883
MAQ_SA_W(maq_sa_w_phl, 16);
2884
MAQ_SA_W(maq_sa_w_phr, 0);
2885

    
2886
#undef MAQ_SA_W
2887

    
2888
#define MULQ_W(name, addvar) \
2889
target_ulong helper_##name(target_ulong rs, target_ulong rt,   \
2890
                           CPUMIPSState *env)                  \
2891
{                                                              \
2892
    uint32_t rs_t, rt_t;                                       \
2893
    int32_t tempI;                                             \
2894
    int64_t tempL;                                             \
2895
                                                               \
2896
    rs_t = rs & MIPSDSP_LLO;                                   \
2897
    rt_t = rt & MIPSDSP_LLO;                                   \
2898
                                                               \
2899
    if ((rs_t == 0x80000000) && (rt_t == 0x80000000)) {        \
2900
        tempL = 0x7FFFFFFF00000000ull;                         \
2901
        set_DSPControl_overflow_flag(1, 21, env);              \
2902
    } else {                                                   \
2903
        tempL  = ((int64_t)rs_t * (int64_t)rt_t) << 1;         \
2904
        tempL += addvar;                                       \
2905
    }                                                          \
2906
    tempI = (tempL & MIPSDSP_LHI) >> 32;                       \
2907
                                                               \
2908
    return (target_long)(int32_t)tempI;                        \
2909
}
2910

    
2911
MULQ_W(mulq_s_w, 0);
2912
MULQ_W(mulq_rs_w, 0x80000000ull);
2913

    
2914
#undef MULQ_W
2915

    
2916
#if defined(TARGET_MIPS64)
2917

    
2918
#define MAQ_S_W_QH(name, mov) \
2919
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2920
                   CPUMIPSState *env)                             \
2921
{                                                                 \
2922
    int16_t rs_t, rt_t;                                           \
2923
    int32_t temp_mul;                                             \
2924
    int64_t temp[2];                                              \
2925
    int64_t acc[2];                                               \
2926
    int64_t temp_sum;                                             \
2927
                                                                  \
2928
    temp[0] = 0;                                                  \
2929
    temp[1] = 0;                                                  \
2930
                                                                  \
2931
    rs_t = (rs >> mov) & MIPSDSP_LO;                              \
2932
    rt_t = (rt >> mov) & MIPSDSP_LO;                              \
2933
    temp_mul = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env);          \
2934
                                                                  \
2935
    temp[0] = (int64_t)temp_mul;                                  \
2936
    if (temp[0] >= 0) {                                           \
2937
        temp[1] = 0x00;                                           \
2938
    } else {                                                      \
2939
        temp[1] = ~0ull;                                          \
2940
    }                                                             \
2941
                                                                  \
2942
    acc[0] = env->active_tc.LO[ac];                               \
2943
    acc[1] = env->active_tc.HI[ac];                               \
2944
                                                                  \
2945
    temp_sum = acc[0] + temp[0];                                  \
2946
    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&                \
2947
        ((uint64_t)temp_sum < (uint64_t)temp[0])) {               \
2948
        acc[1] += 1;                                              \
2949
    }                                                             \
2950
    acc[0] = temp_sum;                                            \
2951
    acc[1] += temp[1];                                            \
2952
                                                                  \
2953
    env->active_tc.HI[ac] = acc[1];                               \
2954
    env->active_tc.LO[ac] = acc[0];                               \
2955
}
2956

    
2957
MAQ_S_W_QH(maq_s_w_qhll, 48);
2958
MAQ_S_W_QH(maq_s_w_qhlr, 32);
2959
MAQ_S_W_QH(maq_s_w_qhrl, 16);
2960
MAQ_S_W_QH(maq_s_w_qhrr, 0);
2961

    
2962
#undef MAQ_S_W_QH
2963

    
2964
#define MAQ_SA_W(name, mov) \
2965
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2966
                   CPUMIPSState *env)                             \
2967
{                                                                 \
2968
    int16_t rs_t, rt_t;                                           \
2969
    int32_t temp;                                                 \
2970
    int64_t acc[2];                                               \
2971
                                                                  \
2972
    rs_t = (rs >> mov) & MIPSDSP_LO;                              \
2973
    rt_t = (rt >> mov) & MIPSDSP_LO;                              \
2974
    temp = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env);              \
2975
    temp = mipsdsp_sat32_acc_q31(ac, temp, env);                  \
2976
                                                                  \
2977
    acc[0] = (int64_t)(int32_t)temp;                              \
2978
    if (acc[0] >= 0) {                                            \
2979
        acc[1] = 0x00;                                            \
2980
    } else {                                                      \
2981
        acc[1] = ~0ull;                                           \
2982
    }                                                             \
2983
                                                                  \
2984
    env->active_tc.HI[ac] = acc[1];                               \
2985
    env->active_tc.LO[ac] = acc[0];                               \
2986
}
2987

    
2988
MAQ_SA_W(maq_sa_w_qhll, 48);
2989
MAQ_SA_W(maq_sa_w_qhlr, 32);
2990
MAQ_SA_W(maq_sa_w_qhrl, 16);
2991
MAQ_SA_W(maq_sa_w_qhrr, 0);
2992

    
2993
#undef MAQ_SA_W
2994

    
2995
#define MAQ_S_L_PW(name, mov) \
2996
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2997
                   CPUMIPSState *env)                             \
2998
{                                                                 \
2999
    int32_t rs_t, rt_t;                                           \
3000
    int64_t temp[2];                                              \
3001
    int64_t acc[2];                                               \
3002
    int64_t temp_sum;                                             \
3003
                                                                  \
3004
    temp[0] = 0;                                                  \
3005
    temp[1] = 0;                                                  \
3006
                                                                  \
3007
    rs_t = (rs >> mov) & MIPSDSP_LLO;                             \
3008
    rt_t = (rt >> mov) & MIPSDSP_LLO;                             \
3009
                                                                  \
3010
    temp[0] = mipsdsp_mul_q31_q31(ac, rs_t, rt_t, env);           \
3011
    if (temp[0] >= 0) {                                           \
3012
        temp[1] = 0x00;                                           \
3013
    } else {                                                      \
3014
        temp[1] = ~0ull;                                          \
3015
    }                                                             \
3016
                                                                  \
3017
    acc[0] = env->active_tc.LO[ac];                               \
3018
    acc[1] = env->active_tc.HI[ac];                               \
3019
                                                                  \
3020
    temp_sum = acc[0] + temp[0];                                  \
3021
    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&                \
3022
        ((uint64_t)temp_sum < (uint64_t)temp[0])) {               \
3023
        acc[1] += 1;                                              \
3024
    }                                                             \
3025
    acc[0] = temp_sum;                                            \
3026
    acc[1] += temp[1];                                            \
3027
                                                                  \
3028
    env->active_tc.HI[ac] = acc[1];                               \
3029
    env->active_tc.LO[ac] = acc[0];                               \
3030
}
3031

    
3032
MAQ_S_L_PW(maq_s_l_pwl, 32);
3033
MAQ_S_L_PW(maq_s_l_pwr, 0);
3034

    
3035
#undef MAQ_S_L_PW
3036

    
3037
#define DM_OPERATE(name, func, is_add, sigext) \
3038
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,    \
3039
                  CPUMIPSState *env)                                 \
3040
{                                                                    \
3041
    int32_t rs1, rs0;                                                \
3042
    int32_t rt1, rt0;                                                \
3043
    int64_t tempBL[2], tempAL[2];                                    \
3044
    int64_t acc[2];                                                  \
3045
    int64_t temp[2];                                                 \
3046
    int64_t temp_sum;                                                \
3047
                                                                     \
3048
    temp[0] = 0x00;                                                  \
3049
    temp[1] = 0x00;                                                  \
3050
                                                                     \
3051
    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                                \
3052
    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                                \
3053
                                                                     \
3054
    if (sigext) {                                                    \
3055
        tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1);               \
3056
        tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0);               \
3057
                                                                     \
3058
        if (tempBL[0] >= 0) {                                        \
3059
            tempBL[1] = 0x0;                                         \
3060
        } else {                                                     \
3061
            tempBL[1] = ~0ull;                                       \
3062
        }                                                            \
3063
                                                                     \
3064
        if (tempAL[0] >= 0) {                                        \
3065
            tempAL[1] = 0x0;                                         \
3066
        } else {                                                     \
3067
            tempAL[1] = ~0ull;                                       \
3068
        }                                                            \
3069
    } else {                                                         \
3070
        tempBL[0] = mipsdsp_##func(rs1, rt1);                        \
3071
        tempAL[0] = mipsdsp_##func(rs0, rt0);                        \
3072
        tempBL[1] = 0;                                               \
3073
        tempAL[1] = 0;                                               \
3074
    }                                                                \
3075
                                                                     \
3076
    acc[1] = env->active_tc.HI[ac];                                  \
3077
    acc[0] = env->active_tc.LO[ac];                                  \
3078
                                                                     \
3079
    temp_sum = tempBL[0] + tempAL[0];                                \
3080
    if (((uint64_t)temp_sum < (uint64_t)tempBL[0]) &&                \
3081
        ((uint64_t)temp_sum < (uint64_t)tempAL[0])) {                \
3082
        temp[1] += 1;                                                \
3083
    }                                                                \
3084
    temp[0] = temp_sum;                                              \
3085
    temp[1] += tempBL[1] + tempAL[1];                                \
3086
                                                                     \
3087
    if (is_add) {                                                    \
3088
        temp_sum = acc[0] + temp[0];                                 \
3089
        if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&               \
3090
            ((uint64_t)temp_sum < (uint64_t)temp[0])) {              \
3091
            acc[1] += 1;                                             \
3092
        }                                                            \
3093
        temp[0] = temp_sum;                                          \
3094
        temp[1] = acc[1] + temp[1];                                  \
3095
    } else {                                                         \
3096
        temp_sum = acc[0] - temp[0];                                 \
3097
        if ((uint64_t)temp_sum > (uint64_t)acc[0]) {                 \
3098
            acc[1] -= 1;                                             \
3099
        }                                                            \
3100
        temp[0] = temp_sum;                                          \
3101
        temp[1] = acc[1] - temp[1];                                  \
3102
    }                                                                \
3103
                                                                     \
3104
    env->active_tc.HI[ac] = temp[1];                                 \
3105
    env->active_tc.LO[ac] = temp[0];                                 \
3106
}
3107

    
3108
DM_OPERATE(dmadd, mul_i32_i32, 1, 1);
3109
DM_OPERATE(dmaddu, mul_u32_u32, 1, 0);
3110
DM_OPERATE(dmsub, mul_i32_i32, 0, 1);
3111
DM_OPERATE(dmsubu, mul_u32_u32, 0, 0);
3112
#undef DM_OPERATE
3113
#endif
3114

    
3115
/** DSP Bit/Manipulation Sub-class insns **/
3116
target_ulong helper_bitrev(target_ulong rt)
3117
{
3118
    int32_t temp;
3119
    uint32_t rd;
3120
    int i;
3121

    
3122
    temp = rt & MIPSDSP_LO;
3123
    rd = 0;
3124
    for (i = 0; i < 16; i++) {
3125
        rd = (rd << 1) | (temp & 1);
3126
        temp = temp >> 1;
3127
    }
3128

    
3129
    return (target_ulong)rd;
3130
}
3131

    
3132
#define BIT_INSV(name, posfilter, sizefilter, ret_type)         \
3133
target_ulong helper_##name(CPUMIPSState *env, target_ulong rs,  \
3134
                           target_ulong rt)                     \
3135
{                                                               \
3136
    uint32_t pos, size, msb, lsb;                               \
3137
    target_ulong filter;                                        \
3138
    target_ulong temp, temprs, temprt;                          \
3139
    target_ulong dspc;                                          \
3140
                                                                \
3141
    dspc = env->active_tc.DSPControl;                           \
3142
                                                                \
3143
    pos  = dspc & posfilter;                                    \
3144
    size = (dspc >> 7) & sizefilter;                            \
3145
                                                                \
3146
    msb  = pos + size - 1;                                      \
3147
    lsb  = pos;                                                 \
3148
                                                                \
3149
    if (lsb > msb || (msb > TARGET_LONG_BITS)) {                \
3150
        return rt;                                              \
3151
    }                                                           \
3152
                                                                \
3153
    filter = ((int32_t)0x01 << size) - 1;                       \
3154
    filter = filter << pos;                                     \
3155
    temprs = rs & filter;                                       \
3156
    temprt = rt & ~filter;                                      \
3157
    temp = temprs | temprt;                                     \
3158
                                                                \
3159
    return (target_long)(ret_type)temp;                         \
3160
}
3161

    
3162
BIT_INSV(insv, 0x1F, 0x1F, int32_t);
3163
#ifdef TARGET_MIPS64
3164
BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
3165
#endif
3166

    
3167
#undef BIT_INSV
3168

    
3169

    
3170
/** DSP Compare-Pick Sub-class insns **/
3171
#define CMP_HAS_RET(name, func, split_num, filter, bit_size) \
3172
target_ulong helper_##name(target_ulong rs, target_ulong rt) \
3173
{                                                       \
3174
    uint32_t rs_t, rt_t;                                \
3175
    uint8_t cc;                                         \
3176
    uint32_t temp = 0;                                  \
3177
    int i;                                              \
3178
                                                        \
3179
    for (i = 0; i < split_num; i++) {                   \
3180
        rs_t = (rs >> (bit_size * i)) & filter;         \
3181
        rt_t = (rt >> (bit_size * i)) & filter;         \
3182
        cc = mipsdsp_##func(rs_t, rt_t);                \
3183
        temp |= cc << i;                                \
3184
    }                                                   \
3185
                                                        \
3186
    return (target_ulong)temp;                          \
3187
}
3188

    
3189
CMP_HAS_RET(cmpgu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8);
3190
CMP_HAS_RET(cmpgu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8);
3191
CMP_HAS_RET(cmpgu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8);
3192

    
3193
#ifdef TARGET_MIPS64
3194
CMP_HAS_RET(cmpgu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8);
3195
CMP_HAS_RET(cmpgu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8);
3196
CMP_HAS_RET(cmpgu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8);
3197
#endif
3198

    
3199
#undef CMP_HAS_RET
3200

    
3201

    
3202
#define CMP_NO_RET(name, func, split_num, filter, bit_size) \
3203
void helper_##name(target_ulong rs, target_ulong rt,        \
3204
                            CPUMIPSState *env)              \
3205
{                                                           \
3206
    int##bit_size##_t rs_t, rt_t;                           \
3207
    int##bit_size##_t flag = 0;                             \
3208
    int##bit_size##_t cc;                                   \
3209
    int i;                                                  \
3210
                                                            \
3211
    for (i = 0; i < split_num; i++) {                       \
3212
        rs_t = (rs >> (bit_size * i)) & filter;             \
3213
        rt_t = (rt >> (bit_size * i)) & filter;             \
3214
                                                            \
3215
        cc = mipsdsp_##func((int32_t)rs_t, (int32_t)rt_t);  \
3216
        flag |= cc << i;                                    \
3217
    }                                                       \
3218
                                                            \
3219
    set_DSPControl_24(flag, split_num, env);                \
3220
}
3221

    
3222
CMP_NO_RET(cmpu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8);
3223
CMP_NO_RET(cmpu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8);
3224
CMP_NO_RET(cmpu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8);
3225

    
3226
CMP_NO_RET(cmp_eq_ph, cmp_eq, 2, MIPSDSP_LO, 16);
3227
CMP_NO_RET(cmp_lt_ph, cmp_lt, 2, MIPSDSP_LO, 16);
3228
CMP_NO_RET(cmp_le_ph, cmp_le, 2, MIPSDSP_LO, 16);
3229

    
3230
#ifdef TARGET_MIPS64
3231
CMP_NO_RET(cmpu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8);
3232
CMP_NO_RET(cmpu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8);
3233
CMP_NO_RET(cmpu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8);
3234

    
3235
CMP_NO_RET(cmp_eq_qh, cmp_eq, 4, MIPSDSP_LO, 16);
3236
CMP_NO_RET(cmp_lt_qh, cmp_lt, 4, MIPSDSP_LO, 16);
3237
CMP_NO_RET(cmp_le_qh, cmp_le, 4, MIPSDSP_LO, 16);
3238

    
3239
CMP_NO_RET(cmp_eq_pw, cmp_eq, 2, MIPSDSP_LLO, 32);
3240
CMP_NO_RET(cmp_lt_pw, cmp_lt, 2, MIPSDSP_LLO, 32);
3241
CMP_NO_RET(cmp_le_pw, cmp_le, 2, MIPSDSP_LLO, 32);
3242
#endif
3243
#undef CMP_NO_RET
3244

    
3245
#if defined(TARGET_MIPS64)
3246

    
3247
#define CMPGDU_OB(name) \
3248
target_ulong helper_cmpgdu_##name##_ob(target_ulong rs, target_ulong rt, \
3249
                                       CPUMIPSState *env)  \
3250
{                                                     \
3251
    int i;                                            \
3252
    uint8_t rs_t, rt_t;                               \
3253
    uint32_t cond;                                    \
3254
                                                      \
3255
    cond = 0;                                         \
3256
                                                      \
3257
    for (i = 0; i < 8; i++) {                         \
3258
        rs_t = (rs >> (8 * i)) & MIPSDSP_Q0;          \
3259
        rt_t = (rt >> (8 * i)) & MIPSDSP_Q0;          \
3260
                                                      \
3261
        if (mipsdsp_cmpu_##name(rs_t, rt_t)) {        \
3262
            cond |= 0x01 << i;                        \
3263
        }                                             \
3264
    }                                                 \
3265
                                                      \
3266
    set_DSPControl_24(cond, 8, env);                  \
3267
                                                      \
3268
    return (uint64_t)cond;                            \
3269
}
3270

    
3271
CMPGDU_OB(eq)
3272
CMPGDU_OB(lt)
3273
CMPGDU_OB(le)
3274
#undef CMPGDU_OB
3275
#endif
3276

    
3277
#define PICK_INSN(name, split_num, filter, bit_size, ret32bit) \
3278
target_ulong helper_##name(target_ulong rs, target_ulong rt,   \
3279
                            CPUMIPSState *env)                 \
3280
{                                                              \
3281
    uint32_t rs_t, rt_t;                                       \
3282
    uint32_t cc;                                               \
3283
    target_ulong dsp;                                          \
3284
    int i;                                                     \
3285
    target_ulong result = 0;                                   \
3286
                                                               \
3287
    dsp = env->active_tc.DSPControl;                           \
3288
    for (i = 0; i < split_num; i++) {                          \
3289
        rs_t = (rs >> (bit_size * i)) & filter;                \
3290
        rt_t = (rt >> (bit_size * i)) & filter;                \
3291
        cc = (dsp >> (24 + i)) & 0x01;                         \
3292
        cc = cc == 1 ? rs_t : rt_t;                            \
3293
                                                               \
3294
        result |= (target_ulong)cc << (bit_size * i);          \
3295
    }                                                          \
3296
                                                               \
3297
    if (ret32bit) {                                            \
3298
        result = (target_long)(int32_t)(result & MIPSDSP_LLO); \
3299
    }                                                          \
3300
                                                               \
3301
    return result;                                             \
3302
}
3303

    
3304
PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1);
3305
PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1);
3306

    
3307
#ifdef TARGET_MIPS64
3308
PICK_INSN(pick_ob, 8, MIPSDSP_Q0, 8, 0);
3309
PICK_INSN(pick_qh, 4, MIPSDSP_LO, 16, 0);
3310
PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0);
3311
#endif
3312
#undef PICK_INSN
3313

    
3314
#define APPEND_INSN(name, ret_32) \
3315
target_ulong helper_##name(target_ulong rt, target_ulong rs, uint32_t sa) \
3316
{                                                                         \
3317
    target_ulong temp;                                                    \
3318
                                                                          \
3319
    if (ret_32) {                                                         \
3320
        temp = ((rt & MIPSDSP_LLO) << sa) |                               \
3321
               ((rs & MIPSDSP_LLO) & ((0x01 << sa) - 1));                 \
3322
        temp = (target_long)(int32_t)(temp & MIPSDSP_LLO);                \
3323
    } else {                                                              \
3324
        temp = (rt << sa) | (rs & ((0x01 << sa) - 1));                    \
3325
    }                                                                     \
3326
                                                                          \
3327
    return temp;                                                          \
3328
}
3329

    
3330
APPEND_INSN(append, 1);
3331
#ifdef TARGET_MIPS64
3332
APPEND_INSN(dappend, 0);
3333
#endif
3334
#undef APPEND_INSN
3335

    
3336
#define PREPEND_INSN(name, or_val, ret_32)                    \
3337
target_ulong helper_##name(target_ulong rs, target_ulong rt,  \
3338
                           uint32_t sa)                       \
3339
{                                                             \
3340
    sa |= or_val;                                             \
3341
                                                              \
3342
    if (1) {                                                  \
3343
        return (target_long)(int32_t)(uint32_t)               \
3344
            (((rs & MIPSDSP_LLO) << (32 - sa)) |              \
3345
             ((rt & MIPSDSP_LLO) >> sa));                     \
3346
    } else {                                                  \
3347
        return (rs << (64 - sa)) | (rt >> sa);                \
3348
    }                                                         \
3349
}
3350

    
3351
PREPEND_INSN(prepend, 0, 1);
3352
#ifdef TARGET_MIPS64
3353
PREPEND_INSN(prependw, 0, 0);
3354
PREPEND_INSN(prependd, 0x20, 0);
3355
#endif
3356
#undef PREPEND_INSN
3357

    
3358
#define BALIGN_INSN(name, filter, ret32) \
3359
target_ulong helper_##name(target_ulong rs, target_ulong rt, uint32_t bp) \
3360
{                                                                         \
3361
    bp = bp & 0x03;                                                       \
3362
                                                                          \
3363
    if ((bp & 1) == 0) {                                                  \
3364
        return rt;                                                        \
3365
    } else {                                                              \
3366
        if (ret32) {                                                      \
3367
            return (target_long)(int32_t)((rt << (8 * bp)) |              \
3368
                                          (rs >> (8 * (4 - bp))));        \
3369
        } else {                                                          \
3370
            return (rt << (8 * bp)) | (rs >> (8 * (8 - bp)));             \
3371
        }                                                                 \
3372
    }                                                                     \
3373
}
3374

    
3375
BALIGN_INSN(balign, 0x03, 1);
3376
#if defined(TARGET_MIPS64)
3377
BALIGN_INSN(dbalign, 0x07, 0);
3378
#endif
3379
#undef BALIGN_INSN
3380

    
3381
target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt)
3382
{
3383
    uint32_t rsl, rth;
3384

    
3385
    rsl =  rs & MIPSDSP_LO;
3386
    rth = (rt & MIPSDSP_HI) >> 16;
3387

    
3388
    return (target_long)(int32_t)((rsl << 16) | rth);
3389
}
3390

    
3391
#if defined(TARGET_MIPS64)
3392
target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt)
3393
{
3394
    uint32_t rs0, rt1;
3395

    
3396
    rs0 = rs & MIPSDSP_LLO;
3397
    rt1 = (rt >> 32) & MIPSDSP_LLO;
3398

    
3399
    return ((uint64_t)rs0 << 32) | (uint64_t)rt1;
3400
}
3401
#endif
3402

    
3403
/** DSP Accumulator and DSPControl Access Sub-class insns **/
3404
target_ulong helper_extr_w(target_ulong ac, target_ulong shift,
3405
                           CPUMIPSState *env)
3406
{
3407
    int32_t tempI;
3408
    int64_t tempDL[2];
3409

    
3410
    shift = shift & 0x0F;
3411

    
3412
    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
3413
    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3414
        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3415
        set_DSPControl_overflow_flag(1, 23, env);
3416
    }
3417

    
3418
    tempI = (tempDL[0] >> 1) & MIPSDSP_LLO;
3419

    
3420
    tempDL[0] += 1;
3421
    if (tempDL[0] == 0) {
3422
        tempDL[1] += 1;
3423
    }
3424

    
3425
    if ((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) &&
3426
        (!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI))) {
3427
        set_DSPControl_overflow_flag(1, 23, env);
3428
    }
3429

    
3430
    return (target_long)tempI;
3431
}
3432

    
3433
target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
3434
                             CPUMIPSState *env)
3435
{
3436
    int64_t tempDL[2];
3437

    
3438
    shift = shift & 0x0F;
3439

    
3440
    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
3441
    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3442
        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3443
        set_DSPControl_overflow_flag(1, 23, env);
3444
    }
3445

    
3446
    tempDL[0] += 1;
3447
    if (tempDL[0] == 0) {
3448
        tempDL[1] += 1;
3449
    }
3450

    
3451
    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3452
        (tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3453
        set_DSPControl_overflow_flag(1, 23, env);
3454
    }
3455

    
3456
    return (target_long)(int32_t)(tempDL[0] >> 1);
3457
}
3458

    
3459
target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
3460
                              CPUMIPSState *env)
3461
{
3462
    int32_t tempI, temp64;
3463
    int64_t tempDL[2];
3464

    
3465
    shift = shift & 0x0F;
3466

    
3467
    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
3468
    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3469
        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3470
        set_DSPControl_overflow_flag(1, 23, env);
3471
    }
3472
    tempDL[0] += 1;
3473
    if (tempDL[0] == 0) {
3474
        tempDL[1] += 1;
3475
    }
3476
    tempI = tempDL[0] >> 1;
3477

    
3478
    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3479
        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3480
        temp64 = tempDL[1];
3481
        if (temp64 == 0) {
3482
            tempI = 0x7FFFFFFF;
3483
        } else {
3484
            tempI = 0x80000000;
3485
        }
3486
        set_DSPControl_overflow_flag(1, 23, env);
3487
    }
3488

    
3489
    return (target_long)tempI;
3490
}
3491

    
3492
#if defined(TARGET_MIPS64)
3493
target_ulong helper_dextr_w(target_ulong ac, target_ulong shift,
3494
                            CPUMIPSState *env)
3495
{
3496
    uint64_t temp[3];
3497

    
3498
    shift = shift & 0x3F;
3499

    
3500
    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3501

    
3502
    return (int64_t)(int32_t)(temp[0] >> 1);
3503
}
3504

    
3505
target_ulong helper_dextr_r_w(target_ulong ac, target_ulong shift,
3506
                              CPUMIPSState *env)
3507
{
3508
    uint64_t temp[3];
3509
    uint32_t temp128;
3510

    
3511
    shift = shift & 0x3F;
3512
    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3513

    
3514
    temp[0] += 1;
3515
    if (temp[0] == 0) {
3516
        temp[1] += 1;
3517
        if (temp[1] == 0) {
3518
            temp[2] += 1;
3519
        }
3520
    }
3521

    
3522
    temp128 = temp[2] & 0x01;
3523

    
3524
    if ((temp128 != 0 || temp[1] != 0) &&
3525
       (temp128 != 1 || temp[1] != ~0ull)) {
3526
        set_DSPControl_overflow_flag(1, 23, env);
3527
    }
3528

    
3529
    return (int64_t)(int32_t)(temp[0] >> 1);
3530
}
3531

    
3532
target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift,
3533
                               CPUMIPSState *env)
3534
{
3535
    uint64_t temp[3];
3536
    uint32_t temp128;
3537

    
3538
    shift = shift & 0x3F;
3539
    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3540

    
3541
    temp[0] += 1;
3542
    if (temp[0] == 0) {
3543
        temp[1] += 1;
3544
        if (temp[1] == 0) {
3545
            temp[2] += 1;
3546
        }
3547
    }
3548

    
3549
    temp128 = temp[2] & 0x01;
3550

    
3551
    if ((temp128 != 0 || temp[1] != 0) &&
3552
       (temp128 != 1 || temp[1] != ~0ull)) {
3553
        if (temp128 == 0) {
3554
            temp[0] = 0x0FFFFFFFF;
3555
        } else {
3556
            temp[0] = 0x0100000000;
3557
        }
3558
        set_DSPControl_overflow_flag(1, 23, env);
3559
    }
3560

    
3561
    return (int64_t)(int32_t)(temp[0] >> 1);
3562
}
3563

    
3564
target_ulong helper_dextr_l(target_ulong ac, target_ulong shift,
3565
                            CPUMIPSState *env)
3566
{
3567
    uint64_t temp[3];
3568
    target_ulong result;
3569

    
3570
    shift = shift & 0x3F;
3571

    
3572
    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3573
    result = (temp[1] << 63) | (temp[0] >> 1);
3574

    
3575
    return result;
3576
}
3577

    
3578
target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift,
3579
                              CPUMIPSState *env)
3580
{
3581
    uint64_t temp[3];
3582
    uint32_t temp128;
3583
    target_ulong result;
3584

    
3585
    shift = shift & 0x3F;
3586
    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3587

    
3588
    temp[0] += 1;
3589
    if (temp[0] == 0) {
3590
        temp[1] += 1;
3591
        if (temp[1] == 0) {
3592
            temp[2] += 1;
3593
        }
3594
    }
3595

    
3596
    temp128 = temp[2] & 0x01;
3597

    
3598
    if ((temp128 != 0 || temp[1] != 0) &&
3599
       (temp128 != 1 || temp[1] != ~0ull)) {
3600
        set_DSPControl_overflow_flag(1, 23, env);
3601
    }
3602

    
3603
    result = (temp[1] << 63) | (temp[0] >> 1);
3604

    
3605
    return result;
3606
}
3607

    
3608
target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift,
3609
                               CPUMIPSState *env)
3610
{
3611
    uint64_t temp[3];
3612
    uint32_t temp128;
3613
    target_ulong result;
3614

    
3615
    shift = shift & 0x3F;
3616
    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3617

    
3618
    temp[0] += 1;
3619
    if (temp[0] == 0) {
3620
        temp[1] += 1;
3621
        if (temp[1] == 0) {
3622
            temp[2] += 1;
3623
        }
3624
    }
3625

    
3626
    temp128 = temp[2] & 0x01;
3627

    
3628
    if ((temp128 != 0 || temp[1] != 0) &&
3629
       (temp128 != 1 || temp[1] != ~0ull)) {
3630
        if (temp128 == 0) {
3631
            temp[1] &= ~0x00ull - 1;
3632
            temp[0] |= ~0x00ull - 1;
3633
        } else {
3634
            temp[1] |= 0x01;
3635
            temp[0] &= 0x01;
3636
        }
3637
        set_DSPControl_overflow_flag(1, 23, env);
3638
    }
3639
    result = (temp[1] << 63) | (temp[0] >> 1);
3640

    
3641
    return result;
3642
}
3643
#endif
3644

    
3645
target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift,
3646
                             CPUMIPSState *env)
3647
{
3648
    int64_t temp;
3649

    
3650
    shift = shift & 0x0F;
3651

    
3652
    temp = mipsdsp_rashift_short_acc(ac, shift, env);
3653
    if (temp > (int64_t)0x7FFF) {
3654
        temp = 0x00007FFF;
3655
        set_DSPControl_overflow_flag(1, 23, env);
3656
    } else if (temp < (int64_t)0xFFFFFFFFFFFF8000) {
3657
        temp = 0xFFFF8000;
3658
        set_DSPControl_overflow_flag(1, 23, env);
3659
    }
3660

    
3661
    return (target_long)(int32_t)(temp & 0xFFFFFFFF);
3662
}
3663

    
3664

    
3665
#if defined(TARGET_MIPS64)
3666
target_ulong helper_dextr_s_h(target_ulong ac, target_ulong shift,
3667
                              CPUMIPSState *env)
3668
{
3669
    int64_t temp[2];
3670
    uint32_t temp127;
3671

    
3672
    shift = shift & 0x1F;
3673

    
3674
    mipsdsp_rashift_acc((uint64_t *)temp, ac, shift, env);
3675

    
3676
    temp127 = (temp[1] >> 63) & 0x01;
3677

    
3678
    if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) {
3679
        temp[0] &= 0xFFFF0000;
3680
        temp[0] |= 0x00007FFF;
3681
        set_DSPControl_overflow_flag(1, 23, env);
3682
    } else if ((temp127 == 1) &&
3683
            (temp[1] < 0xFFFFFFFFFFFFFFFFll
3684
             || temp[0] < 0xFFFFFFFFFFFF1000ll)) {
3685
        temp[0] &= 0xFFFF0000;
3686
        temp[0] |= 0x00008000;
3687
        set_DSPControl_overflow_flag(1, 23, env);
3688
    }
3689

    
3690
    return (int64_t)(int16_t)(temp[0] & MIPSDSP_LO);
3691
}
3692

    
3693
#endif
3694

    
3695
target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState *env)
3696
{
3697
    int32_t start_pos;
3698
    int sub;
3699
    uint32_t temp;
3700
    uint64_t acc;
3701

    
3702
    size = size & 0x1F;
3703

    
3704
    temp = 0;
3705
    start_pos = get_DSPControl_pos(env);
3706
    sub = start_pos - (size + 1);
3707
    if (sub >= -1) {
3708
        acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
3709
              ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
3710
        temp = (acc >> (start_pos - size)) &
3711
               (((uint32_t)0x01 << (size + 1)) - 1);
3712
        set_DSPControl_efi(0, env);
3713
    } else {
3714
        set_DSPControl_efi(1, env);
3715
    }
3716

    
3717
    return (target_ulong)temp;
3718
}
3719

    
3720
target_ulong helper_extpdp(target_ulong ac, target_ulong size,
3721
                           CPUMIPSState *env)
3722
{
3723
    int32_t start_pos;
3724
    int sub;
3725
    uint32_t temp;
3726
    uint64_t acc;
3727

    
3728
    size = size & 0x1F;
3729
    temp = 0;
3730
    start_pos = get_DSPControl_pos(env);
3731
    sub = start_pos - (size + 1);
3732
    if (sub >= -1) {
3733
        acc  = ((uint64_t)env->active_tc.HI[ac] << 32) |
3734
               ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
3735
        temp = (acc >> (start_pos - size)) &
3736
               (((uint32_t)0x01 << (size + 1)) - 1);
3737

    
3738
        set_DSPControl_pos(start_pos - (size + 1), env);
3739
        set_DSPControl_efi(0, env);
3740
    } else {
3741
        set_DSPControl_efi(1, env);
3742
    }
3743

    
3744
    return (target_ulong)temp;
3745
}
3746

    
3747

    
3748
#if defined(TARGET_MIPS64)
3749
target_ulong helper_dextp(target_ulong ac, target_ulong size, CPUMIPSState *env)
3750
{
3751
    int start_pos;
3752
    int len;
3753
    int sub;
3754
    uint64_t tempB, tempA;
3755
    uint64_t temp;
3756

    
3757
    temp = 0;
3758

    
3759
    size = size & 0x3F;
3760
    start_pos = get_DSPControl_pos(env);
3761
    len = start_pos - size;
3762
    tempB = env->active_tc.HI[ac];
3763
    tempA = env->active_tc.LO[ac];
3764

    
3765
    sub = start_pos - (size + 1);
3766

    
3767
    if (sub >= -1) {
3768
        temp = (tempB << (64 - len)) | (tempA >> len);
3769
        temp = temp & ((0x01 << (size + 1)) - 1);
3770
        set_DSPControl_efi(0, env);
3771
    } else {
3772
        set_DSPControl_efi(1, env);
3773
    }
3774

    
3775
    return temp;
3776
}
3777

    
3778
target_ulong helper_dextpdp(target_ulong ac, target_ulong size,
3779
                            CPUMIPSState *env)
3780
{
3781
    int start_pos;
3782
    int len;
3783
    int sub;
3784
    uint64_t tempB, tempA;
3785
    uint64_t temp;
3786

    
3787
    temp = 0;
3788
    size = size & 0x3F;
3789
    start_pos = get_DSPControl_pos(env);
3790
    len = start_pos - size;
3791
    tempB = env->active_tc.HI[ac];
3792
    tempA = env->active_tc.LO[ac];
3793

    
3794
    sub = start_pos - (size + 1);
3795

    
3796
    if (sub >= -1) {
3797
        temp = (tempB << (64 - len)) | (tempA >> len);
3798
        temp = temp & ((0x01 << (size + 1)) - 1);
3799
        set_DSPControl_pos(sub, env);
3800
        set_DSPControl_efi(0, env);
3801
    } else {
3802
        set_DSPControl_efi(1, env);
3803
    }
3804

    
3805
    return temp;
3806
}
3807

    
3808
#endif
3809

    
3810
void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env)
3811
{
3812
    int8_t  rs5_0;
3813
    uint64_t temp, acc;
3814

    
3815
    rs5_0 = rs & 0x3F;
3816
    rs5_0 = (int8_t)(rs5_0 << 2) >> 2;
3817
    rs5_0 = MIPSDSP_ABS(rs5_0);
3818
    acc   = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) |
3819
            ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
3820
    if (rs5_0 == 0) {
3821
        temp = acc;
3822
    } else {
3823
        if (rs5_0 > 0) {
3824
            temp = acc >> rs5_0;
3825
        } else {
3826
            temp = acc << rs5_0;
3827
        }
3828
    }
3829

    
3830
    env->active_tc.HI[ac] = (target_ulong)(int32_t)((temp & MIPSDSP_LHI) >> 32);
3831
    env->active_tc.LO[ac] = (target_ulong)(int32_t)(temp & MIPSDSP_LLO);
3832
}
3833

    
3834
#if defined(TARGET_MIPS64)
3835
void helper_dshilo(target_ulong shift, target_ulong ac, CPUMIPSState *env)
3836
{
3837
    int8_t shift_t;
3838
    uint64_t tempB, tempA;
3839

    
3840
    shift_t = (int8_t)(shift << 1) >> 1;
3841

    
3842
    tempB = env->active_tc.HI[ac];
3843
    tempA = env->active_tc.LO[ac];
3844

    
3845
    if (shift_t != 0) {
3846
        if (shift_t >= 0) {
3847
            tempA = (tempB << (64 - shift_t)) | (tempA >> shift_t);
3848
            tempB = tempB >> shift_t;
3849
        } else {
3850
            shift_t = -shift_t;
3851
            tempB = (tempB << shift_t) | (tempA >> (64 - shift_t));
3852
            tempA = tempA << shift_t;
3853
        }
3854
    }
3855

    
3856
    env->active_tc.HI[ac] = tempB;
3857
    env->active_tc.LO[ac] = tempA;
3858
}
3859

    
3860
#endif
3861
void helper_mthlip(target_ulong ac, target_ulong rs, CPUMIPSState *env)
3862
{
3863
    int32_t tempA, tempB, pos;
3864

    
3865
    tempA = rs;
3866
    tempB = env->active_tc.LO[ac];
3867
    env->active_tc.HI[ac] = (target_long)tempB;
3868
    env->active_tc.LO[ac] = (target_long)tempA;
3869
    pos = get_DSPControl_pos(env);
3870

    
3871
    if (pos > 32) {
3872
        return;
3873
    } else {
3874
        set_DSPControl_pos(pos + 32, env);
3875
    }
3876
}
3877

    
3878
#if defined(TARGET_MIPS64)
3879
void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env)
3880
{
3881
    uint8_t ac_t;
3882
    uint8_t pos;
3883
    uint64_t tempB, tempA;
3884

    
3885
    ac_t = ac & 0x3;
3886

    
3887
    tempA = rs;
3888
    tempB = env->active_tc.LO[ac_t];
3889

    
3890
    env->active_tc.HI[ac_t] = tempB;
3891
    env->active_tc.LO[ac_t] = tempA;
3892

    
3893
    pos = get_DSPControl_pos(env);
3894

    
3895
    if (pos <= 64) {
3896
        pos = pos + 64;
3897
        set_DSPControl_pos(pos, env);
3898
    }
3899
}
3900
#endif
3901

    
3902
void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
3903
{
3904
    uint8_t  mask[6];
3905
    uint8_t  i;
3906
    uint32_t newbits, overwrite;
3907
    target_ulong dsp;
3908

    
3909
    newbits   = 0x00;
3910
    overwrite = 0xFFFFFFFF;
3911
    dsp = env->active_tc.DSPControl;
3912

    
3913
    for (i = 0; i < 6; i++) {
3914
        mask[i] = (mask_num >> i) & 0x01;
3915
    }
3916

    
3917
    if (mask[0] == 1) {
3918
#if defined(TARGET_MIPS64)
3919
        overwrite &= 0xFFFFFF80;
3920
        newbits   &= 0xFFFFFF80;
3921
        newbits   |= 0x0000007F & rs;
3922
#else
3923
        overwrite &= 0xFFFFFFC0;
3924
        newbits   &= 0xFFFFFFC0;
3925
        newbits   |= 0x0000003F & rs;
3926
#endif
3927
    }
3928

    
3929
    if (mask[1] == 1) {
3930
        overwrite &= 0xFFFFE07F;
3931
        newbits   &= 0xFFFFE07F;
3932
        newbits   |= 0x00001F80 & rs;
3933
    }
3934

    
3935
    if (mask[2] == 1) {
3936
        overwrite &= 0xFFFFDFFF;
3937
        newbits   &= 0xFFFFDFFF;
3938
        newbits   |= 0x00002000 & rs;
3939
    }
3940

    
3941
    if (mask[3] == 1) {
3942
        overwrite &= 0xFF00FFFF;
3943
        newbits   &= 0xFF00FFFF;
3944
        newbits   |= 0x00FF0000 & rs;
3945
    }
3946

    
3947
    if (mask[4] == 1) {
3948
        overwrite &= 0x00FFFFFF;
3949
        newbits   &= 0x00FFFFFF;
3950
        newbits   |= 0xFF000000 & rs;
3951
    }
3952

    
3953
    if (mask[5] == 1) {
3954
        overwrite &= 0xFFFFBFFF;
3955
        newbits   &= 0xFFFFBFFF;
3956
        newbits   |= 0x00004000 & rs;
3957
    }
3958

    
3959
    dsp = dsp & overwrite;
3960
    dsp = dsp | newbits;
3961
    env->active_tc.DSPControl = dsp;
3962
}
3963

    
3964
target_ulong helper_rddsp(target_ulong masknum, CPUMIPSState *env)
3965
{
3966
    uint8_t  mask[6];
3967
    uint32_t ruler, i;
3968
    target_ulong temp;
3969
    target_ulong dsp;
3970

    
3971
    ruler = 0x01;
3972
    for (i = 0; i < 6; i++) {
3973
        mask[i] = (masknum & ruler) >> i ;
3974
        ruler = ruler << 1;
3975
    }
3976

    
3977
    temp  = 0x00;
3978
    dsp = env->active_tc.DSPControl;
3979

    
3980
    if (mask[0] == 1) {
3981
#if defined(TARGET_MIPS64)
3982
        temp |= dsp & 0x7F;
3983
#else
3984
        temp |= dsp & 0x3F;
3985
#endif
3986
    }
3987

    
3988
    if (mask[1] == 1) {
3989
        temp |= dsp & 0x1F80;
3990
    }
3991

    
3992
    if (mask[2] == 1) {
3993
        temp |= dsp & 0x2000;
3994
    }
3995

    
3996
    if (mask[3] == 1) {
3997
        temp |= dsp & 0x00FF0000;
3998
    }
3999

    
4000
    if (mask[4] == 1) {
4001
        temp |= dsp & 0xFF000000;
4002
    }
4003

    
4004
    if (mask[5] == 1) {
4005
        temp |= dsp & 0x4000;
4006
    }
4007

    
4008
    return temp;
4009
}
4010

    
4011

    
4012
#undef MIPSDSP_LHI
4013
#undef MIPSDSP_LLO
4014
#undef MIPSDSP_HI
4015
#undef MIPSDSP_LO
4016
#undef MIPSDSP_Q3
4017
#undef MIPSDSP_Q2
4018
#undef MIPSDSP_Q1
4019
#undef MIPSDSP_Q0
4020

    
4021
#undef MIPSDSP_SPLIT32_8
4022
#undef MIPSDSP_SPLIT32_16
4023

    
4024
#undef MIPSDSP_RETURN32
4025
#undef MIPSDSP_RETURN32_8
4026
#undef MIPSDSP_RETURN32_16
4027

    
4028
#ifdef TARGET_MIPS64
4029
#undef MIPSDSP_SPLIT64_16
4030
#undef MIPSDSP_SPLIT64_32
4031
#undef MIPSDSP_RETURN64_16
4032
#undef MIPSDSP_RETURN64_32
4033
#endif