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