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