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