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