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