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