PPC: Fix rldcl
[qemu/agraf.git] / target-mips / dsp_helper.c
blob805247d2529c0645dee58e648f9303c92ca26c77
1 /*
2 * MIPS ASE DSP Instruction emulation helpers for QEMU.
4 * Copyright (c) 2012 Jia Liu <proljc@gmail.com>
5 * Dongxue Zhang <elta.era@gmail.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
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.
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/>.
20 #include "cpu.h"
21 #include "helper.h"
23 /* As the byte ordering doesn't matter, i.e. all columns are treated
24 identically, these unions can be used directly. */
25 typedef union {
26 uint8_t ub[4];
27 int8_t sb[4];
28 uint16_t uh[2];
29 int16_t sh[2];
30 uint32_t uw[1];
31 int32_t sw[1];
32 } DSP32Value;
34 typedef union {
35 uint8_t ub[8];
36 int8_t sb[8];
37 uint16_t uh[4];
38 int16_t sh[4];
39 uint32_t uw[2];
40 int32_t sw[2];
41 uint64_t ul[1];
42 int64_t sl[1];
43 } DSP64Value;
45 /*** MIPS DSP internal functions begin ***/
46 #define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x)
47 #define MIPSDSP_OVERFLOW_ADD(a, b, c, d) (~(a ^ b) & (a ^ c) & d)
48 #define MIPSDSP_OVERFLOW_SUB(a, b, c, d) ((a ^ b) & (a ^ c) & d)
50 static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
51 CPUMIPSState *env)
53 env->active_tc.DSPControl |= (target_ulong)flag << position;
56 static inline void set_DSPControl_carryflag(uint32_t flag, CPUMIPSState *env)
58 env->active_tc.DSPControl |= (target_ulong)flag << 13;
61 static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
63 return (env->active_tc.DSPControl >> 13) & 0x01;
66 static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env)
68 uint32_t filter;
70 filter = ((0x01 << len) - 1) << 24;
71 filter = ~filter;
73 env->active_tc.DSPControl &= filter;
74 env->active_tc.DSPControl |= (target_ulong)flag << 24;
77 static inline uint32_t get_DSPControl_24(int len, CPUMIPSState *env)
79 uint32_t filter;
81 filter = (0x01 << len) - 1;
83 return (env->active_tc.DSPControl >> 24) & filter;
86 static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env)
88 target_ulong dspc;
90 dspc = env->active_tc.DSPControl;
91 #ifndef TARGET_MIPS64
92 dspc = dspc & 0xFFFFFFC0;
93 dspc |= pos;
94 #else
95 dspc = dspc & 0xFFFFFF80;
96 dspc |= pos;
97 #endif
98 env->active_tc.DSPControl = dspc;
101 static inline uint32_t get_DSPControl_pos(CPUMIPSState *env)
103 target_ulong dspc;
104 uint32_t pos;
106 dspc = env->active_tc.DSPControl;
108 #ifndef TARGET_MIPS64
109 pos = dspc & 0x3F;
110 #else
111 pos = dspc & 0x7F;
112 #endif
114 return pos;
117 static inline void set_DSPControl_efi(uint32_t flag, CPUMIPSState *env)
119 env->active_tc.DSPControl &= 0xFFFFBFFF;
120 env->active_tc.DSPControl |= (target_ulong)flag << 14;
123 #define DO_MIPS_SAT_ABS(size) \
124 static inline int##size##_t mipsdsp_sat_abs##size(int##size##_t a, \
125 CPUMIPSState *env) \
127 if (a == INT##size##_MIN) { \
128 set_DSPControl_overflow_flag(1, 20, env); \
129 return INT##size##_MAX; \
130 } else { \
131 return MIPSDSP_ABS(a); \
134 DO_MIPS_SAT_ABS(8)
135 DO_MIPS_SAT_ABS(16)
136 DO_MIPS_SAT_ABS(32)
137 #undef DO_MIPS_SAT_ABS
139 /* get sum value */
140 static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env)
142 int16_t tempI;
144 tempI = a + b;
146 if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x8000)) {
147 set_DSPControl_overflow_flag(1, 20, env);
150 return tempI;
153 static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b,
154 CPUMIPSState *env)
156 int16_t tempS;
158 tempS = a + b;
160 if (MIPSDSP_OVERFLOW_ADD(a, b, tempS, 0x8000)) {
161 if (a > 0) {
162 tempS = 0x7FFF;
163 } else {
164 tempS = 0x8000;
166 set_DSPControl_overflow_flag(1, 20, env);
169 return tempS;
172 static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b,
173 CPUMIPSState *env)
175 int32_t tempI;
177 tempI = a + b;
179 if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x80000000)) {
180 if (a > 0) {
181 tempI = 0x7FFFFFFF;
182 } else {
183 tempI = 0x80000000;
185 set_DSPControl_overflow_flag(1, 20, env);
188 return tempI;
191 static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
193 uint16_t temp;
195 temp = (uint16_t)a + (uint16_t)b;
197 if (temp & 0x0100) {
198 set_DSPControl_overflow_flag(1, 20, env);
201 return temp & 0xFF;
204 static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b,
205 CPUMIPSState *env)
207 uint32_t temp;
209 temp = (uint32_t)a + (uint32_t)b;
211 if (temp & 0x00010000) {
212 set_DSPControl_overflow_flag(1, 20, env);
215 return temp & 0xFFFF;
218 static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b,
219 CPUMIPSState *env)
221 uint8_t result;
222 uint16_t temp;
224 temp = (uint16_t)a + (uint16_t)b;
225 result = temp & 0xFF;
227 if (0x0100 & temp) {
228 result = 0xFF;
229 set_DSPControl_overflow_flag(1, 20, env);
232 return result;
235 static inline uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b,
236 CPUMIPSState *env)
238 uint16_t result;
239 uint32_t temp;
241 temp = (uint32_t)a + (uint32_t)b;
242 result = temp & 0xFFFF;
244 if (0x00010000 & temp) {
245 result = 0xFFFF;
246 set_DSPControl_overflow_flag(1, 20, env);
249 return result;
252 static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a,
253 CPUMIPSState *env)
255 int64_t temp;
256 int32_t temp32, temp31, result;
257 int64_t temp_sum;
259 #ifndef TARGET_MIPS64
260 temp = ((uint64_t)env->active_tc.HI[acc] << 32) |
261 (uint64_t)env->active_tc.LO[acc];
262 #else
263 temp = (uint64_t)env->active_tc.LO[acc];
264 #endif
266 temp_sum = (int64_t)a + temp;
268 temp32 = (temp_sum >> 32) & 0x01;
269 temp31 = (temp_sum >> 31) & 0x01;
270 result = temp_sum & 0xFFFFFFFF;
272 if (temp32 != temp31) {
273 if (temp32 == 0) {
274 result = 0x7FFFFFFF;
275 } else {
276 result = 0x80000000;
278 set_DSPControl_overflow_flag(1, 16 + acc, env);
281 return result;
284 /* a[0] is LO, a[1] is HI. */
285 static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret,
286 int32_t ac,
287 int64_t *a,
288 CPUMIPSState *env)
290 bool temp64;
292 ret[0] = env->active_tc.LO[ac] + a[0];
293 ret[1] = env->active_tc.HI[ac] + a[1];
295 if (((uint64_t)ret[0] < (uint64_t)env->active_tc.LO[ac]) &&
296 ((uint64_t)ret[0] < (uint64_t)a[0])) {
297 ret[1] += 1;
299 temp64 = ret[1] & 1;
300 if (temp64 != ((ret[0] >> 63) & 0x01)) {
301 if (temp64) {
302 ret[0] = (0x01ull << 63);
303 ret[1] = ~0ull;
304 } else {
305 ret[0] = (0x01ull << 63) - 1;
306 ret[1] = 0x00;
308 set_DSPControl_overflow_flag(1, 16 + ac, env);
312 static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
313 int32_t ac,
314 int64_t *a,
315 CPUMIPSState *env)
317 bool temp64;
319 ret[0] = env->active_tc.LO[ac] - a[0];
320 ret[1] = env->active_tc.HI[ac] - a[1];
322 if ((uint64_t)ret[0] > (uint64_t)env->active_tc.LO[ac]) {
323 ret[1] -= 1;
325 temp64 = ret[1] & 1;
326 if (temp64 != ((ret[0] >> 63) & 0x01)) {
327 if (temp64) {
328 ret[0] = (0x01ull << 63);
329 ret[1] = ~0ull;
330 } else {
331 ret[0] = (0x01ull << 63) - 1;
332 ret[1] = 0x00;
334 set_DSPControl_overflow_flag(1, 16 + ac, env);
338 static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b,
339 CPUMIPSState *env)
341 int32_t temp;
343 temp = (int32_t)a * (int32_t)b;
345 if ((temp > (int)0x7FFF) || (temp < (int)0xFFFF8000)) {
346 set_DSPControl_overflow_flag(1, 21, env);
348 temp &= 0x0000FFFF;
350 return temp;
353 static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b)
355 return a * b;
358 static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b)
360 return a * b;
363 static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b,
364 CPUMIPSState *env)
366 int32_t temp;
368 temp = (int32_t)a * (int32_t)b;
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);
377 temp &= 0x0000FFFF;
379 return temp;
382 static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b,
383 CPUMIPSState *env)
385 int32_t temp;
387 if ((a == 0x8000) && (b == 0x8000)) {
388 temp = 0x7FFFFFFF;
389 set_DSPControl_overflow_flag(1, 21, env);
390 } else {
391 temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1;
394 return temp;
397 /* right shift */
398 static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov)
400 return a >> mov;
403 static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov)
405 return a >> mov;
408 static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov)
410 return a >> mov;
413 static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov)
415 return a >> mov;
418 static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov)
420 return a >> mov;
423 static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
425 int32_t temp;
427 temp = (int32_t)a + (int32_t)b;
429 return (temp >> 1) & 0xFFFF;
432 /* round right shift */
433 static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b)
435 int32_t temp;
437 temp = (int32_t)a + (int32_t)b;
438 temp += 1;
440 return (temp >> 1) & 0xFFFF;
443 static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b)
445 int64_t temp;
447 temp = (int64_t)a + (int64_t)b;
449 return (temp >> 1) & 0xFFFFFFFF;
452 static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b)
454 int64_t temp;
456 temp = (int64_t)a + (int64_t)b;
457 temp += 1;
459 return (temp >> 1) & 0xFFFFFFFF;
462 static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b)
464 uint16_t temp;
466 temp = (uint16_t)a + (uint16_t)b;
468 return (temp >> 1) & 0x00FF;
471 static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b)
473 uint16_t temp;
475 temp = (uint16_t)a + (uint16_t)b + 1;
477 return (temp >> 1) & 0x00FF;
480 static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b)
482 uint16_t temp;
484 temp = (uint16_t)a - (uint16_t)b;
486 return (temp >> 1) & 0x00FF;
489 static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b)
491 uint16_t temp;
493 temp = (uint16_t)a - (uint16_t)b + 1;
495 return (temp >> 1) & 0x00FF;
498 /* 128 bits long. p[0] is LO, p[1] is HI. */
499 static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
500 int32_t ac,
501 int32_t shift,
502 CPUMIPSState *env)
504 int64_t acc;
506 acc = ((int64_t)env->active_tc.HI[ac] << 32) |
507 ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
508 p[0] = (shift == 0) ? (acc << 1) : (acc >> (shift - 1));
509 p[1] = (acc >> 63) & 0x01;
512 /* 128 bits long. p[0] is LO, p[1] is HI */
513 static inline void mipsdsp_rashift_acc(uint64_t *p,
514 uint32_t ac,
515 uint32_t shift,
516 CPUMIPSState *env)
518 uint64_t tempB, tempA;
520 tempB = env->active_tc.HI[ac];
521 tempA = env->active_tc.LO[ac];
522 shift = shift & 0x1F;
524 if (shift == 0) {
525 p[1] = tempB;
526 p[0] = tempA;
527 } else {
528 p[0] = (tempB << (64 - shift)) | (tempA >> shift);
529 p[1] = (int64_t)tempB >> shift;
533 /* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/
534 static inline void mipsdsp_rndrashift_acc(uint64_t *p,
535 uint32_t ac,
536 uint32_t shift,
537 CPUMIPSState *env)
539 int64_t tempB, tempA;
541 tempB = env->active_tc.HI[ac];
542 tempA = env->active_tc.LO[ac];
543 shift = shift & 0x3F;
545 if (shift == 0) {
546 p[2] = tempB >> 63;
547 p[1] = (tempB << 1) | (tempA >> 63);
548 p[0] = tempA << 1;
549 } else {
550 p[0] = (tempB << (65 - shift)) | (tempA >> (shift - 1));
551 p[1] = (int64_t)tempB >> (shift - 1);
552 if (tempB >= 0) {
553 p[2] = 0x0;
554 } else {
555 p[2] = ~0ull;
560 static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b,
561 CPUMIPSState *env)
563 int32_t temp;
565 if ((a == 0x8000) && (b == 0x8000)) {
566 temp = 0x7FFFFFFF;
567 set_DSPControl_overflow_flag(1, 16 + ac, env);
568 } else {
569 temp = ((int16_t)a * (int16_t)b) << 1;
572 return temp;
575 static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b,
576 CPUMIPSState *env)
578 uint64_t temp;
580 if ((a == 0x80000000) && (b == 0x80000000)) {
581 temp = (0x01ull << 63) - 1;
582 set_DSPControl_overflow_flag(1, 16 + ac, env);
583 } else {
584 temp = ((uint64_t)a * (uint64_t)b) << 1;
587 return temp;
590 static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b)
592 return (uint16_t)a * (uint16_t)b;
595 static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b,
596 CPUMIPSState *env)
598 uint32_t tempI;
600 tempI = (uint32_t)a * (uint32_t)b;
601 if (tempI > 0x0000FFFF) {
602 tempI = 0x0000FFFF;
603 set_DSPControl_overflow_flag(1, 21, env);
606 return tempI & 0x0000FFFF;
609 static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b)
611 return (uint64_t)a * (uint64_t)b;
614 static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b,
615 CPUMIPSState *env)
617 uint32_t temp;
619 if ((a == 0x8000) && (b == 0x8000)) {
620 temp = 0x7FFF0000;
621 set_DSPControl_overflow_flag(1, 21, env);
622 } else {
623 temp = (a * b) << 1;
624 temp = temp + 0x00008000;
627 return (temp & 0xFFFF0000) >> 16;
630 static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b,
631 CPUMIPSState *env)
633 int32_t temp;
635 if ((a == 0x8000) && (b == 0x8000)) {
636 temp = 0x7FFF0000;
637 set_DSPControl_overflow_flag(1, 21, env);
638 } else {
639 temp = (int16_t)a * (int16_t)b;
640 temp = temp << 1;
643 return (temp >> 16) & 0x0000FFFF;
646 static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a,
647 CPUMIPSState *env)
649 int64_t temp;
651 temp = (int32_t)a + 0x00008000;
653 if (a > (int)0x7fff8000) {
654 temp = 0x7FFFFFFF;
655 set_DSPControl_overflow_flag(1, 22, env);
658 return (temp >> 16) & 0xFFFF;
661 static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
662 CPUMIPSState *env)
664 uint16_t mag;
665 uint32_t sign;
667 sign = (a >> 15) & 0x01;
668 mag = a & 0x7FFF;
670 if (sign == 0) {
671 if (mag > 0x7F80) {
672 set_DSPControl_overflow_flag(1, 22, env);
673 return 0xFF;
674 } else {
675 return (mag >> 7) & 0xFFFF;
677 } else {
678 set_DSPControl_overflow_flag(1, 22, env);
679 return 0x00;
683 static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env)
685 uint8_t discard;
687 if (s != 0) {
688 discard = a >> (8 - s);
690 if (discard != 0x00) {
691 set_DSPControl_overflow_flag(1, 22, env);
694 return a << s;
697 static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
698 CPUMIPSState *env)
700 uint16_t discard;
702 if (s != 0) {
703 discard = (int16_t)a >> (15 - s);
705 if ((discard != 0x0000) && (discard != 0xFFFF)) {
706 set_DSPControl_overflow_flag(1, 22, env);
709 return a << s;
713 static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s,
714 CPUMIPSState *env)
716 uint32_t discard;
718 if (s == 0) {
719 return a;
720 } else {
721 discard = (int32_t)a >> (31 - (s - 1));
723 if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
724 set_DSPControl_overflow_flag(1, 22, env);
726 return a << s;
730 static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s,
731 CPUMIPSState *env)
733 uint8_t sign;
734 uint16_t discard;
736 if (s == 0) {
737 return a;
738 } else {
739 sign = (a >> 15) & 0x01;
740 if (sign != 0) {
741 discard = (((0x01 << (16 - s)) - 1) << s) |
742 ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
743 } else {
744 discard = a >> (14 - (s - 1));
747 if ((discard != 0x0000) && (discard != 0xFFFF)) {
748 set_DSPControl_overflow_flag(1, 22, env);
749 return (sign == 0) ? 0x7FFF : 0x8000;
750 } else {
751 return a << s;
756 static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s,
757 CPUMIPSState *env)
759 uint8_t sign;
760 uint32_t discard;
762 if (s == 0) {
763 return a;
764 } else {
765 sign = (a >> 31) & 0x01;
766 if (sign != 0) {
767 discard = (((0x01 << (32 - s)) - 1) << s) |
768 ((a >> (30 - (s - 1))) & ((0x01 << s) - 1));
769 } else {
770 discard = a >> (30 - (s - 1));
773 if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
774 set_DSPControl_overflow_flag(1, 22, env);
775 return (sign == 0) ? 0x7FFFFFFF : 0x80000000;
776 } else {
777 return a << s;
782 static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a, uint8_t s)
784 uint32_t temp;
786 if (s == 0) {
787 temp = (uint32_t)a << 1;
788 } else {
789 temp = (int32_t)(int8_t)a >> (s - 1);
792 return (temp + 1) >> 1;
795 static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s)
797 uint32_t temp;
799 if (s == 0) {
800 temp = (uint32_t)a << 1;
801 } else {
802 temp = (int32_t)(int16_t)a >> (s - 1);
805 return (temp + 1) >> 1;
808 static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s)
810 int64_t temp;
812 if (s == 0) {
813 temp = (uint64_t)a << 1;
814 } else {
815 temp = (int64_t)(int32_t)a >> (s - 1);
817 temp += 1;
819 return (temp >> 1) & 0xFFFFFFFFull;
822 static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env)
824 int16_t temp;
826 temp = a - b;
827 if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) {
828 set_DSPControl_overflow_flag(1, 20, env);
831 return temp;
834 static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b,
835 CPUMIPSState *env)
837 int16_t temp;
839 temp = a - b;
840 if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) {
841 if (a >= 0) {
842 temp = 0x7FFF;
843 } else {
844 temp = 0x8000;
846 set_DSPControl_overflow_flag(1, 20, env);
849 return temp;
852 static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b,
853 CPUMIPSState *env)
855 int32_t temp;
857 temp = a - b;
858 if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) {
859 if (a >= 0) {
860 temp = 0x7FFFFFFF;
861 } else {
862 temp = 0x80000000;
864 set_DSPControl_overflow_flag(1, 20, env);
867 return temp & 0xFFFFFFFFull;
870 static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b)
872 int32_t temp;
874 temp = (int32_t)a - (int32_t)b;
876 return (temp >> 1) & 0x0000FFFF;
879 static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b)
881 int32_t temp;
883 temp = (int32_t)a - (int32_t)b;
884 temp += 1;
886 return (temp >> 1) & 0x0000FFFF;
889 static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b)
891 int64_t temp;
893 temp = (int64_t)a - (int64_t)b;
895 return (temp >> 1) & 0xFFFFFFFFull;
898 static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b)
900 int64_t temp;
902 temp = (int64_t)a - (int64_t)b;
903 temp += 1;
905 return (temp >> 1) & 0xFFFFFFFFull;
908 static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b,
909 CPUMIPSState *env)
911 uint8_t temp16;
912 uint32_t temp;
914 temp = (uint32_t)a - (uint32_t)b;
915 temp16 = (temp >> 16) & 0x01;
916 if (temp16 == 1) {
917 set_DSPControl_overflow_flag(1, 20, env);
919 return temp & 0x0000FFFF;
922 static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b,
923 CPUMIPSState *env)
925 uint8_t temp16;
926 uint32_t temp;
928 temp = (uint32_t)a - (uint32_t)b;
929 temp16 = (temp >> 16) & 0x01;
931 if (temp16 == 1) {
932 temp = 0x0000;
933 set_DSPControl_overflow_flag(1, 20, env);
936 return temp & 0x0000FFFF;
939 static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
941 uint8_t temp8;
942 uint16_t temp;
944 temp = (uint16_t)a - (uint16_t)b;
945 temp8 = (temp >> 8) & 0x01;
946 if (temp8 == 1) {
947 set_DSPControl_overflow_flag(1, 20, env);
950 return temp & 0x00FF;
953 static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env)
955 uint8_t temp8;
956 uint16_t temp;
958 temp = (uint16_t)a - (uint16_t)b;
959 temp8 = (temp >> 8) & 0x01;
960 if (temp8 == 1) {
961 temp = 0x00;
962 set_DSPControl_overflow_flag(1, 20, env);
965 return temp & 0x00FF;
968 static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
970 int32_t temp;
972 temp = a - b;
973 if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) {
974 set_DSPControl_overflow_flag(1, 20, env);
977 return temp;
980 static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env)
982 int32_t temp;
984 temp = a + b;
986 if (MIPSDSP_OVERFLOW_ADD(a, b, temp, 0x80000000)) {
987 set_DSPControl_overflow_flag(1, 20, env);
990 return temp;
993 static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b)
995 return a == b;
998 static inline int32_t mipsdsp_cmp_le(int32_t a, int32_t b)
1000 return a <= b;
1003 static inline int32_t mipsdsp_cmp_lt(int32_t a, int32_t b)
1005 return a < b;
1008 static inline int32_t mipsdsp_cmpu_eq(uint32_t a, uint32_t b)
1010 return a == b;
1013 static inline int32_t mipsdsp_cmpu_le(uint32_t a, uint32_t b)
1015 return a <= b;
1018 static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b)
1020 return a < b;
1022 /*** MIPS DSP internal functions end ***/
1024 #define MIPSDSP_LHI 0xFFFFFFFF00000000ull
1025 #define MIPSDSP_LLO 0x00000000FFFFFFFFull
1026 #define MIPSDSP_HI 0xFFFF0000
1027 #define MIPSDSP_LO 0x0000FFFF
1028 #define MIPSDSP_Q3 0xFF000000
1029 #define MIPSDSP_Q2 0x00FF0000
1030 #define MIPSDSP_Q1 0x0000FF00
1031 #define MIPSDSP_Q0 0x000000FF
1033 #define MIPSDSP_SPLIT32_8(num, a, b, c, d) \
1034 do { \
1035 a = (num >> 24) & MIPSDSP_Q0; \
1036 b = (num >> 16) & MIPSDSP_Q0; \
1037 c = (num >> 8) & MIPSDSP_Q0; \
1038 d = num & MIPSDSP_Q0; \
1039 } while (0)
1041 #define MIPSDSP_SPLIT32_16(num, a, b) \
1042 do { \
1043 a = (num >> 16) & MIPSDSP_LO; \
1044 b = num & MIPSDSP_LO; \
1045 } while (0)
1047 #define MIPSDSP_RETURN32_8(a, b, c, d) ((target_long)(int32_t) \
1048 (((uint32_t)a << 24) | \
1049 (((uint32_t)b << 16) | \
1050 (((uint32_t)c << 8) | \
1051 ((uint32_t)d & 0xFF)))))
1052 #define MIPSDSP_RETURN32_16(a, b) ((target_long)(int32_t) \
1053 (((uint32_t)a << 16) | \
1054 ((uint32_t)b & 0xFFFF)))
1056 #ifdef TARGET_MIPS64
1057 #define MIPSDSP_SPLIT64_16(num, a, b, c, d) \
1058 do { \
1059 a = (num >> 48) & MIPSDSP_LO; \
1060 b = (num >> 32) & MIPSDSP_LO; \
1061 c = (num >> 16) & MIPSDSP_LO; \
1062 d = num & MIPSDSP_LO; \
1063 } while (0)
1065 #define MIPSDSP_SPLIT64_32(num, a, b) \
1066 do { \
1067 a = (num >> 32) & MIPSDSP_LLO; \
1068 b = num & MIPSDSP_LLO; \
1069 } while (0)
1071 #define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)a << 48) | \
1072 ((uint64_t)b << 32) | \
1073 ((uint64_t)c << 16) | \
1074 (uint64_t)d)
1075 #define MIPSDSP_RETURN64_32(a, b) (((uint64_t)a << 32) | (uint64_t)b)
1076 #endif
1078 /** DSP Arithmetic Sub-class insns **/
1079 #define MIPSDSP32_UNOP_ENV(name, func, element) \
1080 target_ulong helper_##name(target_ulong rt, CPUMIPSState *env) \
1082 DSP32Value dt; \
1083 unsigned int i, n; \
1085 n = sizeof(DSP32Value) / sizeof(dt.element[0]); \
1086 dt.sw[0] = rt; \
1088 for (i = 0; i < n; i++) { \
1089 dt.element[i] = mipsdsp_##func(dt.element[i], env); \
1092 return (target_long)dt.sw[0]; \
1094 MIPSDSP32_UNOP_ENV(absq_s_ph, sat_abs16, sh)
1095 MIPSDSP32_UNOP_ENV(absq_s_qb, sat_abs8, sb)
1096 MIPSDSP32_UNOP_ENV(absq_s_w, sat_abs32, sw)
1097 #undef MIPSDSP32_UNOP_ENV
1099 #if defined(TARGET_MIPS64)
1100 #define MIPSDSP64_UNOP_ENV(name, func, element) \
1101 target_ulong helper_##name(target_ulong rt, CPUMIPSState *env) \
1103 DSP64Value dt; \
1104 unsigned int i, n; \
1106 n = sizeof(DSP64Value) / sizeof(dt.element[0]); \
1107 dt.sl[0] = rt; \
1109 for (i = 0; i < n; i++) { \
1110 dt.element[i] = mipsdsp_##func(dt.element[i], env); \
1113 return dt.sl[0]; \
1115 MIPSDSP64_UNOP_ENV(absq_s_ob, sat_abs8, sb)
1116 MIPSDSP64_UNOP_ENV(absq_s_qh, sat_abs16, sh)
1117 MIPSDSP64_UNOP_ENV(absq_s_pw, sat_abs32, sw)
1118 #undef MIPSDSP64_UNOP_ENV
1119 #endif
1121 #define MIPSDSP32_BINOP(name, func, element) \
1122 target_ulong helper_##name(target_ulong rs, target_ulong rt) \
1124 DSP32Value ds, dt; \
1125 unsigned int i, n; \
1127 n = sizeof(DSP32Value) / sizeof(ds.element[0]); \
1128 ds.sw[0] = rs; \
1129 dt.sw[0] = rt; \
1131 for (i = 0; i < n; i++) { \
1132 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]); \
1135 return (target_long)ds.sw[0]; \
1137 MIPSDSP32_BINOP(addqh_ph, rshift1_add_q16, sh);
1138 MIPSDSP32_BINOP(addqh_r_ph, rrshift1_add_q16, sh);
1139 MIPSDSP32_BINOP(addqh_r_w, rrshift1_add_q32, sw);
1140 MIPSDSP32_BINOP(addqh_w, rshift1_add_q32, sw);
1141 MIPSDSP32_BINOP(adduh_qb, rshift1_add_u8, ub);
1142 MIPSDSP32_BINOP(adduh_r_qb, rrshift1_add_u8, ub);
1143 MIPSDSP32_BINOP(subqh_ph, rshift1_sub_q16, sh);
1144 MIPSDSP32_BINOP(subqh_r_ph, rrshift1_sub_q16, sh);
1145 MIPSDSP32_BINOP(subqh_r_w, rrshift1_sub_q32, sw);
1146 MIPSDSP32_BINOP(subqh_w, rshift1_sub_q32, sw);
1147 #undef MIPSDSP32_BINOP
1149 #define MIPSDSP32_BINOP_ENV(name, func, element) \
1150 target_ulong helper_##name(target_ulong rs, target_ulong rt, \
1151 CPUMIPSState *env) \
1153 DSP32Value ds, dt; \
1154 unsigned int i, n; \
1156 n = sizeof(DSP32Value) / sizeof(ds.element[0]); \
1157 ds.sw[0] = rs; \
1158 dt.sw[0] = rt; \
1160 for (i = 0 ; i < n ; i++) { \
1161 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
1164 return (target_long)ds.sw[0]; \
1166 MIPSDSP32_BINOP_ENV(addq_ph, add_i16, sh)
1167 MIPSDSP32_BINOP_ENV(addq_s_ph, sat_add_i16, sh)
1168 MIPSDSP32_BINOP_ENV(addq_s_w, sat_add_i32, sw);
1169 MIPSDSP32_BINOP_ENV(addu_ph, add_u16, sh)
1170 MIPSDSP32_BINOP_ENV(addu_qb, add_u8, ub);
1171 MIPSDSP32_BINOP_ENV(addu_s_ph, sat_add_u16, sh)
1172 MIPSDSP32_BINOP_ENV(addu_s_qb, sat_add_u8, ub);
1173 MIPSDSP32_BINOP_ENV(subq_ph, sub_i16, sh);
1174 MIPSDSP32_BINOP_ENV(subq_s_ph, sat16_sub, sh);
1175 MIPSDSP32_BINOP_ENV(subq_s_w, sat32_sub, sw);
1176 MIPSDSP32_BINOP_ENV(subu_ph, sub_u16_u16, sh);
1177 MIPSDSP32_BINOP_ENV(subu_qb, sub_u8, ub);
1178 MIPSDSP32_BINOP_ENV(subu_s_ph, satu16_sub_u16_u16, sh);
1179 MIPSDSP32_BINOP_ENV(subu_s_qb, satu8_sub, ub);
1180 #undef MIPSDSP32_BINOP_ENV
1182 #ifdef TARGET_MIPS64
1183 #define MIPSDSP64_BINOP(name, func, element) \
1184 target_ulong helper_##name(target_ulong rs, target_ulong rt) \
1186 DSP64Value ds, dt; \
1187 unsigned int i, n; \
1189 n = sizeof(DSP64Value) / sizeof(ds.element[0]); \
1190 ds.sl[0] = rs; \
1191 dt.sl[0] = rt; \
1193 for (i = 0 ; i < n ; i++) { \
1194 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]); \
1197 return ds.sl[0]; \
1199 MIPSDSP64_BINOP(adduh_ob, rshift1_add_u8, ub);
1200 MIPSDSP64_BINOP(adduh_r_ob, rrshift1_add_u8, ub);
1201 MIPSDSP64_BINOP(subuh_ob, rshift1_sub_u8, ub);
1202 MIPSDSP64_BINOP(subuh_r_ob, rrshift1_sub_u8, ub);
1203 #undef MIPSDSP64_BINOP
1205 #define MIPSDSP64_BINOP_ENV(name, func, element) \
1206 target_ulong helper_##name(target_ulong rs, target_ulong rt, \
1207 CPUMIPSState *env) \
1209 DSP64Value ds, dt; \
1210 unsigned int i, n; \
1212 n = sizeof(DSP64Value) / sizeof(ds.element[0]); \
1213 ds.sl[0] = rs; \
1214 dt.sl[0] = rt; \
1216 for (i = 0 ; i < n ; i++) { \
1217 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
1220 return ds.sl[0]; \
1222 MIPSDSP64_BINOP_ENV(addq_pw, add_i32, sw);
1223 MIPSDSP64_BINOP_ENV(addq_qh, add_i16, sh);
1224 MIPSDSP64_BINOP_ENV(addq_s_pw, sat_add_i32, sw);
1225 MIPSDSP64_BINOP_ENV(addq_s_qh, sat_add_i16, sh);
1226 MIPSDSP64_BINOP_ENV(addu_ob, add_u8, uh);
1227 MIPSDSP64_BINOP_ENV(addu_qh, add_u16, uh);
1228 MIPSDSP64_BINOP_ENV(addu_s_ob, sat_add_u8, uh);
1229 MIPSDSP64_BINOP_ENV(addu_s_qh, sat_add_u16, uh);
1230 MIPSDSP64_BINOP_ENV(subq_pw, sub32, sw);
1231 MIPSDSP64_BINOP_ENV(subq_qh, sub_i16, sh);
1232 MIPSDSP64_BINOP_ENV(subq_s_pw, sat32_sub, sw);
1233 MIPSDSP64_BINOP_ENV(subq_s_qh, sat16_sub, sh);
1234 MIPSDSP64_BINOP_ENV(subu_ob, sub_u8, uh);
1235 MIPSDSP64_BINOP_ENV(subu_qh, sub_u16_u16, uh);
1236 MIPSDSP64_BINOP_ENV(subu_s_ob, satu8_sub, uh);
1237 MIPSDSP64_BINOP_ENV(subu_s_qh, satu16_sub_u16_u16, uh);
1238 #undef MIPSDSP64_BINOP_ENV
1240 #endif
1242 #define SUBUH_QB(name, var) \
1243 target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \
1245 uint8_t rs3, rs2, rs1, rs0; \
1246 uint8_t rt3, rt2, rt1, rt0; \
1247 uint8_t tempD, tempC, tempB, tempA; \
1249 MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); \
1250 MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \
1252 tempD = ((uint16_t)rs3 - (uint16_t)rt3 + var) >> 1; \
1253 tempC = ((uint16_t)rs2 - (uint16_t)rt2 + var) >> 1; \
1254 tempB = ((uint16_t)rs1 - (uint16_t)rt1 + var) >> 1; \
1255 tempA = ((uint16_t)rs0 - (uint16_t)rt0 + var) >> 1; \
1257 return ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
1258 ((uint32_t)tempB << 8) | ((uint32_t)tempA); \
1261 SUBUH_QB(subuh, 0);
1262 SUBUH_QB(subuh_r, 1);
1264 #undef SUBUH_QB
1266 target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
1268 uint64_t temp, tempRs, tempRt;
1269 int32_t flag;
1271 tempRs = (uint64_t)rs & MIPSDSP_LLO;
1272 tempRt = (uint64_t)rt & MIPSDSP_LLO;
1274 temp = tempRs + tempRt;
1275 flag = (temp & 0x0100000000ull) >> 32;
1276 set_DSPControl_carryflag(flag, env);
1278 return (target_long)(int32_t)(temp & MIPSDSP_LLO);
1281 target_ulong helper_addwc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
1283 uint32_t rd;
1284 int32_t temp32, temp31;
1285 int64_t tempL;
1287 tempL = (int64_t)(int32_t)rs + (int64_t)(int32_t)rt +
1288 get_DSPControl_carryflag(env);
1289 temp31 = (tempL >> 31) & 0x01;
1290 temp32 = (tempL >> 32) & 0x01;
1292 if (temp31 != temp32) {
1293 set_DSPControl_overflow_flag(1, 20, env);
1296 rd = tempL & MIPSDSP_LLO;
1298 return (target_long)(int32_t)rd;
1301 target_ulong helper_modsub(target_ulong rs, target_ulong rt)
1303 int32_t decr;
1304 uint16_t lastindex;
1305 target_ulong rd;
1307 decr = rt & MIPSDSP_Q0;
1308 lastindex = (rt >> 8) & MIPSDSP_LO;
1310 if ((rs & MIPSDSP_LLO) == 0x00000000) {
1311 rd = (target_ulong)lastindex;
1312 } else {
1313 rd = rs - decr;
1316 return rd;
1319 target_ulong helper_raddu_w_qb(target_ulong rs)
1321 target_ulong ret = 0;
1322 DSP32Value ds;
1323 unsigned int i;
1325 ds.uw[0] = rs;
1326 for (i = 0; i < 4; i++) {
1327 ret += ds.ub[i];
1329 return ret;
1332 #if defined(TARGET_MIPS64)
1333 target_ulong helper_raddu_l_ob(target_ulong rs)
1335 target_ulong ret = 0;
1336 DSP64Value ds;
1337 unsigned int i;
1339 ds.ul[0] = rs;
1340 for (i = 0; i < 8; i++) {
1341 ret += ds.ub[i];
1343 return ret;
1345 #endif
1347 #define PRECR_QB_PH(name, a, b)\
1348 target_ulong helper_##name##_qb_ph(target_ulong rs, target_ulong rt) \
1350 uint8_t tempD, tempC, tempB, tempA; \
1352 tempD = (rs >> a) & MIPSDSP_Q0; \
1353 tempC = (rs >> b) & MIPSDSP_Q0; \
1354 tempB = (rt >> a) & MIPSDSP_Q0; \
1355 tempA = (rt >> b) & MIPSDSP_Q0; \
1357 return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); \
1360 PRECR_QB_PH(precr, 16, 0);
1361 PRECR_QB_PH(precrq, 24, 8);
1363 #undef PRECR_QB_OH
1365 target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs,
1366 target_ulong rt)
1368 uint16_t tempB, tempA;
1370 tempB = ((int32_t)rt >> sa) & MIPSDSP_LO;
1371 tempA = ((int32_t)rs >> sa) & MIPSDSP_LO;
1373 return MIPSDSP_RETURN32_16(tempB, tempA);
1376 target_ulong helper_precr_sra_r_ph_w(uint32_t sa,
1377 target_ulong rs, target_ulong rt)
1379 uint64_t tempB, tempA;
1381 /* If sa = 0, then (sa - 1) = -1 will case shift error, so we need else. */
1382 if (sa == 0) {
1383 tempB = (rt & MIPSDSP_LO) << 1;
1384 tempA = (rs & MIPSDSP_LO) << 1;
1385 } else {
1386 tempB = ((int32_t)rt >> (sa - 1)) + 1;
1387 tempA = ((int32_t)rs >> (sa - 1)) + 1;
1389 rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO);
1391 return (target_long)(int32_t)rt;
1394 target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt)
1396 uint16_t tempB, tempA;
1398 tempB = (rs & MIPSDSP_HI) >> 16;
1399 tempA = (rt & MIPSDSP_HI) >> 16;
1401 return MIPSDSP_RETURN32_16(tempB, tempA);
1404 target_ulong helper_precrq_rs_ph_w(target_ulong rs, target_ulong rt,
1405 CPUMIPSState *env)
1407 uint16_t tempB, tempA;
1409 tempB = mipsdsp_trunc16_sat16_round(rs, env);
1410 tempA = mipsdsp_trunc16_sat16_round(rt, env);
1412 return MIPSDSP_RETURN32_16(tempB, tempA);
1415 #if defined(TARGET_MIPS64)
1416 target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt)
1418 uint8_t rs6, rs4, rs2, rs0;
1419 uint8_t rt6, rt4, rt2, rt0;
1420 uint64_t temp;
1422 rs6 = (rs >> 48) & MIPSDSP_Q0;
1423 rs4 = (rs >> 32) & MIPSDSP_Q0;
1424 rs2 = (rs >> 16) & MIPSDSP_Q0;
1425 rs0 = rs & MIPSDSP_Q0;
1426 rt6 = (rt >> 48) & MIPSDSP_Q0;
1427 rt4 = (rt >> 32) & MIPSDSP_Q0;
1428 rt2 = (rt >> 16) & MIPSDSP_Q0;
1429 rt0 = rt & MIPSDSP_Q0;
1431 temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
1432 ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
1433 ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
1434 ((uint64_t)rt2 << 8) | (uint64_t)rt0;
1436 return temp;
1439 #define PRECR_QH_PW(name, var) \
1440 target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \
1441 uint32_t sa) \
1443 uint16_t rs3, rs2, rs1, rs0; \
1444 uint16_t rt3, rt2, rt1, rt0; \
1445 uint16_t tempD, tempC, tempB, tempA; \
1447 MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \
1448 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
1450 /* When sa = 0, we use rt2, rt0, rs2, rs0; \
1451 * when sa != 0, we use rt3, rt1, rs3, rs1. */ \
1452 if (sa == 0) { \
1453 tempD = rt2 << var; \
1454 tempC = rt0 << var; \
1455 tempB = rs2 << var; \
1456 tempA = rs0 << var; \
1457 } else { \
1458 tempD = (((int16_t)rt3 >> sa) + var) >> var; \
1459 tempC = (((int16_t)rt1 >> sa) + var) >> var; \
1460 tempB = (((int16_t)rs3 >> sa) + var) >> var; \
1461 tempA = (((int16_t)rs1 >> sa) + var) >> var; \
1464 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \
1467 PRECR_QH_PW(sra, 0);
1468 PRECR_QH_PW(sra_r, 1);
1470 #undef PRECR_QH_PW
1472 target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt)
1474 uint8_t rs6, rs4, rs2, rs0;
1475 uint8_t rt6, rt4, rt2, rt0;
1476 uint64_t temp;
1478 rs6 = (rs >> 56) & MIPSDSP_Q0;
1479 rs4 = (rs >> 40) & MIPSDSP_Q0;
1480 rs2 = (rs >> 24) & MIPSDSP_Q0;
1481 rs0 = (rs >> 8) & MIPSDSP_Q0;
1482 rt6 = (rt >> 56) & MIPSDSP_Q0;
1483 rt4 = (rt >> 40) & MIPSDSP_Q0;
1484 rt2 = (rt >> 24) & MIPSDSP_Q0;
1485 rt0 = (rt >> 8) & MIPSDSP_Q0;
1487 temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
1488 ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
1489 ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
1490 ((uint64_t)rt2 << 8) | (uint64_t)rt0;
1492 return temp;
1495 target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt)
1497 uint16_t tempD, tempC, tempB, tempA;
1499 tempD = (rs >> 48) & MIPSDSP_LO;
1500 tempC = (rs >> 16) & MIPSDSP_LO;
1501 tempB = (rt >> 48) & MIPSDSP_LO;
1502 tempA = (rt >> 16) & MIPSDSP_LO;
1504 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1507 target_ulong helper_precrq_rs_qh_pw(target_ulong rs, target_ulong rt,
1508 CPUMIPSState *env)
1510 uint32_t rs2, rs0;
1511 uint32_t rt2, rt0;
1512 uint16_t tempD, tempC, tempB, tempA;
1514 rs2 = (rs >> 32) & MIPSDSP_LLO;
1515 rs0 = rs & MIPSDSP_LLO;
1516 rt2 = (rt >> 32) & MIPSDSP_LLO;
1517 rt0 = rt & MIPSDSP_LLO;
1519 tempD = mipsdsp_trunc16_sat16_round(rs2, env);
1520 tempC = mipsdsp_trunc16_sat16_round(rs0, env);
1521 tempB = mipsdsp_trunc16_sat16_round(rt2, env);
1522 tempA = mipsdsp_trunc16_sat16_round(rt0, env);
1524 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1527 target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt)
1529 uint32_t tempB, tempA;
1531 tempB = (rs >> 32) & MIPSDSP_LLO;
1532 tempA = (rt >> 32) & MIPSDSP_LLO;
1534 return MIPSDSP_RETURN64_32(tempB, tempA);
1536 #endif
1538 target_ulong helper_precrqu_s_qb_ph(target_ulong rs, target_ulong rt,
1539 CPUMIPSState *env)
1541 uint8_t tempD, tempC, tempB, tempA;
1542 uint16_t rsh, rsl, rth, rtl;
1544 rsh = (rs & MIPSDSP_HI) >> 16;
1545 rsl = rs & MIPSDSP_LO;
1546 rth = (rt & MIPSDSP_HI) >> 16;
1547 rtl = rt & MIPSDSP_LO;
1549 tempD = mipsdsp_sat8_reduce_precision(rsh, env);
1550 tempC = mipsdsp_sat8_reduce_precision(rsl, env);
1551 tempB = mipsdsp_sat8_reduce_precision(rth, env);
1552 tempA = mipsdsp_sat8_reduce_precision(rtl, env);
1554 return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);
1557 #if defined(TARGET_MIPS64)
1558 target_ulong helper_precrqu_s_ob_qh(target_ulong rs, target_ulong rt,
1559 CPUMIPSState *env)
1561 int i;
1562 uint16_t rs3, rs2, rs1, rs0;
1563 uint16_t rt3, rt2, rt1, rt0;
1564 uint8_t temp[8];
1565 uint64_t result;
1567 result = 0;
1569 MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
1570 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
1572 temp[7] = mipsdsp_sat8_reduce_precision(rs3, env);
1573 temp[6] = mipsdsp_sat8_reduce_precision(rs2, env);
1574 temp[5] = mipsdsp_sat8_reduce_precision(rs1, env);
1575 temp[4] = mipsdsp_sat8_reduce_precision(rs0, env);
1576 temp[3] = mipsdsp_sat8_reduce_precision(rt3, env);
1577 temp[2] = mipsdsp_sat8_reduce_precision(rt2, env);
1578 temp[1] = mipsdsp_sat8_reduce_precision(rt1, env);
1579 temp[0] = mipsdsp_sat8_reduce_precision(rt0, env);
1581 for (i = 0; i < 8; i++) {
1582 result |= (uint64_t)temp[i] << (8 * i);
1585 return result;
1588 #define PRECEQ_PW(name, a, b) \
1589 target_ulong helper_preceq_pw_##name(target_ulong rt) \
1591 uint16_t tempB, tempA; \
1592 uint32_t tempBI, tempAI; \
1594 tempB = (rt >> a) & MIPSDSP_LO; \
1595 tempA = (rt >> b) & MIPSDSP_LO; \
1597 tempBI = (uint32_t)tempB << 16; \
1598 tempAI = (uint32_t)tempA << 16; \
1600 return MIPSDSP_RETURN64_32(tempBI, tempAI); \
1603 PRECEQ_PW(qhl, 48, 32);
1604 PRECEQ_PW(qhr, 16, 0);
1605 PRECEQ_PW(qhla, 48, 16);
1606 PRECEQ_PW(qhra, 32, 0);
1608 #undef PRECEQ_PW
1610 #endif
1612 #define PRECEQU_PH(name, a, b) \
1613 target_ulong helper_precequ_ph_##name(target_ulong rt) \
1615 uint16_t tempB, tempA; \
1617 tempB = (rt >> a) & MIPSDSP_Q0; \
1618 tempA = (rt >> b) & MIPSDSP_Q0; \
1620 tempB = tempB << 7; \
1621 tempA = tempA << 7; \
1623 return MIPSDSP_RETURN32_16(tempB, tempA); \
1626 PRECEQU_PH(qbl, 24, 16);
1627 PRECEQU_PH(qbr, 8, 0);
1628 PRECEQU_PH(qbla, 24, 8);
1629 PRECEQU_PH(qbra, 16, 0);
1631 #undef PRECEQU_PH
1633 #if defined(TARGET_MIPS64)
1634 #define PRECEQU_QH(name, a, b, c, d) \
1635 target_ulong helper_precequ_qh_##name(target_ulong rt) \
1637 uint16_t tempD, tempC, tempB, tempA; \
1639 tempD = (rt >> a) & MIPSDSP_Q0; \
1640 tempC = (rt >> b) & MIPSDSP_Q0; \
1641 tempB = (rt >> c) & MIPSDSP_Q0; \
1642 tempA = (rt >> d) & MIPSDSP_Q0; \
1644 tempD = tempD << 7; \
1645 tempC = tempC << 7; \
1646 tempB = tempB << 7; \
1647 tempA = tempA << 7; \
1649 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \
1652 PRECEQU_QH(obl, 56, 48, 40, 32);
1653 PRECEQU_QH(obr, 24, 16, 8, 0);
1654 PRECEQU_QH(obla, 56, 40, 24, 8);
1655 PRECEQU_QH(obra, 48, 32, 16, 0);
1657 #undef PRECEQU_QH
1659 #endif
1661 #define PRECEU_PH(name, a, b) \
1662 target_ulong helper_preceu_ph_##name(target_ulong rt) \
1664 uint16_t tempB, tempA; \
1666 tempB = (rt >> a) & MIPSDSP_Q0; \
1667 tempA = (rt >> b) & MIPSDSP_Q0; \
1669 return MIPSDSP_RETURN32_16(tempB, tempA); \
1672 PRECEU_PH(qbl, 24, 16);
1673 PRECEU_PH(qbr, 8, 0);
1674 PRECEU_PH(qbla, 24, 8);
1675 PRECEU_PH(qbra, 16, 0);
1677 #undef PRECEU_PH
1679 #if defined(TARGET_MIPS64)
1680 #define PRECEU_QH(name, a, b, c, d) \
1681 target_ulong helper_preceu_qh_##name(target_ulong rt) \
1683 uint16_t tempD, tempC, tempB, tempA; \
1685 tempD = (rt >> a) & MIPSDSP_Q0; \
1686 tempC = (rt >> b) & MIPSDSP_Q0; \
1687 tempB = (rt >> c) & MIPSDSP_Q0; \
1688 tempA = (rt >> d) & MIPSDSP_Q0; \
1690 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \
1693 PRECEU_QH(obl, 56, 48, 40, 32);
1694 PRECEU_QH(obr, 24, 16, 8, 0);
1695 PRECEU_QH(obla, 56, 40, 24, 8);
1696 PRECEU_QH(obra, 48, 32, 16, 0);
1698 #undef PRECEU_QH
1700 #endif
1702 /** DSP GPR-Based Shift Sub-class insns **/
1703 #define SHIFT_QB(name, func) \
1704 target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt) \
1706 uint8_t rt3, rt2, rt1, rt0; \
1708 sa = sa & 0x07; \
1710 MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \
1712 rt3 = mipsdsp_##func(rt3, sa); \
1713 rt2 = mipsdsp_##func(rt2, sa); \
1714 rt1 = mipsdsp_##func(rt1, sa); \
1715 rt0 = mipsdsp_##func(rt0, sa); \
1717 return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \
1720 #define SHIFT_QB_ENV(name, func) \
1721 target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt,\
1722 CPUMIPSState *env) \
1724 uint8_t rt3, rt2, rt1, rt0; \
1726 sa = sa & 0x07; \
1728 MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \
1730 rt3 = mipsdsp_##func(rt3, sa, env); \
1731 rt2 = mipsdsp_##func(rt2, sa, env); \
1732 rt1 = mipsdsp_##func(rt1, sa, env); \
1733 rt0 = mipsdsp_##func(rt0, sa, env); \
1735 return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \
1738 SHIFT_QB_ENV(shll, lshift8);
1739 SHIFT_QB(shrl, rshift_u8);
1741 SHIFT_QB(shra, rashift8);
1742 SHIFT_QB(shra_r, rnd8_rashift);
1744 #undef SHIFT_QB
1745 #undef SHIFT_QB_ENV
1747 #if defined(TARGET_MIPS64)
1748 #define SHIFT_OB(name, func) \
1749 target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \
1751 int i; \
1752 uint8_t rt_t[8]; \
1753 uint64_t temp; \
1755 sa = sa & 0x07; \
1756 temp = 0; \
1758 for (i = 0; i < 8; i++) { \
1759 rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \
1760 rt_t[i] = mipsdsp_##func(rt_t[i], sa); \
1761 temp |= (uint64_t)rt_t[i] << (8 * i); \
1764 return temp; \
1767 #define SHIFT_OB_ENV(name, func) \
1768 target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \
1769 CPUMIPSState *env) \
1771 int i; \
1772 uint8_t rt_t[8]; \
1773 uint64_t temp; \
1775 sa = sa & 0x07; \
1776 temp = 0; \
1778 for (i = 0; i < 8; i++) { \
1779 rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \
1780 rt_t[i] = mipsdsp_##func(rt_t[i], sa, env); \
1781 temp |= (uint64_t)rt_t[i] << (8 * i); \
1784 return temp; \
1787 SHIFT_OB_ENV(shll, lshift8);
1788 SHIFT_OB(shrl, rshift_u8);
1790 SHIFT_OB(shra, rashift8);
1791 SHIFT_OB(shra_r, rnd8_rashift);
1793 #undef SHIFT_OB
1794 #undef SHIFT_OB_ENV
1796 #endif
1798 #define SHIFT_PH(name, func) \
1799 target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt, \
1800 CPUMIPSState *env) \
1802 uint16_t rth, rtl; \
1804 sa = sa & 0x0F; \
1806 MIPSDSP_SPLIT32_16(rt, rth, rtl); \
1808 rth = mipsdsp_##func(rth, sa, env); \
1809 rtl = mipsdsp_##func(rtl, sa, env); \
1811 return MIPSDSP_RETURN32_16(rth, rtl); \
1814 SHIFT_PH(shll, lshift16);
1815 SHIFT_PH(shll_s, sat16_lshift);
1817 #undef SHIFT_PH
1819 #if defined(TARGET_MIPS64)
1820 #define SHIFT_QH(name, func) \
1821 target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa) \
1823 uint16_t rt3, rt2, rt1, rt0; \
1825 sa = sa & 0x0F; \
1827 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
1829 rt3 = mipsdsp_##func(rt3, sa); \
1830 rt2 = mipsdsp_##func(rt2, sa); \
1831 rt1 = mipsdsp_##func(rt1, sa); \
1832 rt0 = mipsdsp_##func(rt0, sa); \
1834 return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \
1837 #define SHIFT_QH_ENV(name, func) \
1838 target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa, \
1839 CPUMIPSState *env) \
1841 uint16_t rt3, rt2, rt1, rt0; \
1843 sa = sa & 0x0F; \
1845 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
1847 rt3 = mipsdsp_##func(rt3, sa, env); \
1848 rt2 = mipsdsp_##func(rt2, sa, env); \
1849 rt1 = mipsdsp_##func(rt1, sa, env); \
1850 rt0 = mipsdsp_##func(rt0, sa, env); \
1852 return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \
1855 SHIFT_QH_ENV(shll, lshift16);
1856 SHIFT_QH_ENV(shll_s, sat16_lshift);
1858 SHIFT_QH(shrl, rshift_u16);
1859 SHIFT_QH(shra, rashift16);
1860 SHIFT_QH(shra_r, rnd16_rashift);
1862 #undef SHIFT_QH
1863 #undef SHIFT_QH_ENV
1865 #endif
1867 #define SHIFT_W(name, func) \
1868 target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \
1870 uint32_t temp; \
1872 sa = sa & 0x1F; \
1873 temp = mipsdsp_##func(rt, sa); \
1875 return (target_long)(int32_t)temp; \
1878 #define SHIFT_W_ENV(name, func) \
1879 target_ulong helper_##name##_w(target_ulong sa, target_ulong rt, \
1880 CPUMIPSState *env) \
1882 uint32_t temp; \
1884 sa = sa & 0x1F; \
1885 temp = mipsdsp_##func(rt, sa, env); \
1887 return (target_long)(int32_t)temp; \
1890 SHIFT_W_ENV(shll_s, sat32_lshift);
1891 SHIFT_W(shra_r, rnd32_rashift);
1893 #undef SHIFT_W
1894 #undef SHIFT_W_ENV
1896 #if defined(TARGET_MIPS64)
1897 #define SHIFT_PW(name, func) \
1898 target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa) \
1900 uint32_t rt1, rt0; \
1902 sa = sa & 0x1F; \
1903 MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
1905 rt1 = mipsdsp_##func(rt1, sa); \
1906 rt0 = mipsdsp_##func(rt0, sa); \
1908 return MIPSDSP_RETURN64_32(rt1, rt0); \
1911 #define SHIFT_PW_ENV(name, func) \
1912 target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa, \
1913 CPUMIPSState *env) \
1915 uint32_t rt1, rt0; \
1917 sa = sa & 0x1F; \
1918 MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
1920 rt1 = mipsdsp_##func(rt1, sa, env); \
1921 rt0 = mipsdsp_##func(rt0, sa, env); \
1923 return MIPSDSP_RETURN64_32(rt1, rt0); \
1926 SHIFT_PW_ENV(shll, lshift32);
1927 SHIFT_PW_ENV(shll_s, sat32_lshift);
1929 SHIFT_PW(shra, rashift32);
1930 SHIFT_PW(shra_r, rnd32_rashift);
1932 #undef SHIFT_PW
1933 #undef SHIFT_PW_ENV
1935 #endif
1937 #define SHIFT_PH(name, func) \
1938 target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \
1940 uint16_t rth, rtl; \
1942 sa = sa & 0x0F; \
1944 MIPSDSP_SPLIT32_16(rt, rth, rtl); \
1946 rth = mipsdsp_##func(rth, sa); \
1947 rtl = mipsdsp_##func(rtl, sa); \
1949 return MIPSDSP_RETURN32_16(rth, rtl); \
1952 SHIFT_PH(shrl, rshift_u16);
1953 SHIFT_PH(shra, rashift16);
1954 SHIFT_PH(shra_r, rnd16_rashift);
1956 #undef SHIFT_PH
1958 /** DSP Multiply Sub-class insns **/
1959 /* Return value made up by two 16bits value.
1960 * FIXME give the macro a better name.
1962 #define MUL_RETURN32_16_PH(name, func, \
1963 rsmov1, rsmov2, rsfilter, \
1964 rtmov1, rtmov2, rtfilter) \
1965 target_ulong helper_##name(target_ulong rs, target_ulong rt, \
1966 CPUMIPSState *env) \
1968 uint16_t rsB, rsA, rtB, rtA; \
1970 rsB = (rs >> rsmov1) & rsfilter; \
1971 rsA = (rs >> rsmov2) & rsfilter; \
1972 rtB = (rt >> rtmov1) & rtfilter; \
1973 rtA = (rt >> rtmov2) & rtfilter; \
1975 rsB = mipsdsp_##func(rsB, rtB, env); \
1976 rsA = mipsdsp_##func(rsA, rtA, env); \
1978 return MIPSDSP_RETURN32_16(rsB, rsA); \
1981 MUL_RETURN32_16_PH(muleu_s_ph_qbl, mul_u8_u16, \
1982 24, 16, MIPSDSP_Q0, \
1983 16, 0, MIPSDSP_LO);
1984 MUL_RETURN32_16_PH(muleu_s_ph_qbr, mul_u8_u16, \
1985 8, 0, MIPSDSP_Q0, \
1986 16, 0, MIPSDSP_LO);
1987 MUL_RETURN32_16_PH(mulq_rs_ph, rndq15_mul_q15_q15, \
1988 16, 0, MIPSDSP_LO, \
1989 16, 0, MIPSDSP_LO);
1990 MUL_RETURN32_16_PH(mul_ph, mul_i16_i16, \
1991 16, 0, MIPSDSP_LO, \
1992 16, 0, MIPSDSP_LO);
1993 MUL_RETURN32_16_PH(mul_s_ph, sat16_mul_i16_i16, \
1994 16, 0, MIPSDSP_LO, \
1995 16, 0, MIPSDSP_LO);
1996 MUL_RETURN32_16_PH(mulq_s_ph, sat16_mul_q15_q15, \
1997 16, 0, MIPSDSP_LO, \
1998 16, 0, MIPSDSP_LO);
2000 #undef MUL_RETURN32_16_PH
2002 #define MUL_RETURN32_32_ph(name, func, movbits) \
2003 target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2004 CPUMIPSState *env) \
2006 int16_t rsh, rth; \
2007 int32_t temp; \
2009 rsh = (rs >> movbits) & MIPSDSP_LO; \
2010 rth = (rt >> movbits) & MIPSDSP_LO; \
2011 temp = mipsdsp_##func(rsh, rth, env); \
2013 return (target_long)(int32_t)temp; \
2016 MUL_RETURN32_32_ph(muleq_s_w_phl, mul_q15_q15_overflowflag21, 16);
2017 MUL_RETURN32_32_ph(muleq_s_w_phr, mul_q15_q15_overflowflag21, 0);
2019 #undef MUL_RETURN32_32_ph
2021 #define MUL_VOID_PH(name, use_ac_env) \
2022 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2023 CPUMIPSState *env) \
2025 int16_t rsh, rsl, rth, rtl; \
2026 int32_t tempB, tempA; \
2027 int64_t acc, dotp; \
2029 MIPSDSP_SPLIT32_16(rs, rsh, rsl); \
2030 MIPSDSP_SPLIT32_16(rt, rth, rtl); \
2032 if (use_ac_env == 1) { \
2033 tempB = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \
2034 tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl, env); \
2035 } else { \
2036 tempB = mipsdsp_mul_u16_u16(rsh, rth); \
2037 tempA = mipsdsp_mul_u16_u16(rsl, rtl); \
2040 dotp = (int64_t)tempB - (int64_t)tempA; \
2041 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
2042 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
2043 dotp = dotp + acc; \
2044 env->active_tc.HI[ac] = (target_long)(int32_t) \
2045 ((dotp & MIPSDSP_LHI) >> 32); \
2046 env->active_tc.LO[ac] = (target_long)(int32_t)(dotp & MIPSDSP_LLO); \
2049 MUL_VOID_PH(mulsaq_s_w_ph, 1);
2050 MUL_VOID_PH(mulsa_w_ph, 0);
2052 #undef MUL_VOID_PH
2054 #if defined(TARGET_MIPS64)
2055 #define MUL_RETURN64_16_QH(name, func, \
2056 rsmov1, rsmov2, rsmov3, rsmov4, rsfilter, \
2057 rtmov1, rtmov2, rtmov3, rtmov4, rtfilter) \
2058 target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2059 CPUMIPSState *env) \
2061 uint16_t rs3, rs2, rs1, rs0; \
2062 uint16_t rt3, rt2, rt1, rt0; \
2063 uint16_t tempD, tempC, tempB, tempA; \
2065 rs3 = (rs >> rsmov1) & rsfilter; \
2066 rs2 = (rs >> rsmov2) & rsfilter; \
2067 rs1 = (rs >> rsmov3) & rsfilter; \
2068 rs0 = (rs >> rsmov4) & rsfilter; \
2069 rt3 = (rt >> rtmov1) & rtfilter; \
2070 rt2 = (rt >> rtmov2) & rtfilter; \
2071 rt1 = (rt >> rtmov3) & rtfilter; \
2072 rt0 = (rt >> rtmov4) & rtfilter; \
2074 tempD = mipsdsp_##func(rs3, rt3, env); \
2075 tempC = mipsdsp_##func(rs2, rt2, env); \
2076 tempB = mipsdsp_##func(rs1, rt1, env); \
2077 tempA = mipsdsp_##func(rs0, rt0, env); \
2079 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \
2082 MUL_RETURN64_16_QH(muleu_s_qh_obl, mul_u8_u16, \
2083 56, 48, 40, 32, MIPSDSP_Q0, \
2084 48, 32, 16, 0, MIPSDSP_LO);
2085 MUL_RETURN64_16_QH(muleu_s_qh_obr, mul_u8_u16, \
2086 24, 16, 8, 0, MIPSDSP_Q0, \
2087 48, 32, 16, 0, MIPSDSP_LO);
2088 MUL_RETURN64_16_QH(mulq_rs_qh, rndq15_mul_q15_q15, \
2089 48, 32, 16, 0, MIPSDSP_LO, \
2090 48, 32, 16, 0, MIPSDSP_LO);
2092 #undef MUL_RETURN64_16_QH
2094 #define MUL_RETURN64_32_QH(name, \
2095 rsmov1, rsmov2, \
2096 rtmov1, rtmov2) \
2097 target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2098 CPUMIPSState *env) \
2100 uint16_t rsB, rsA; \
2101 uint16_t rtB, rtA; \
2102 uint32_t tempB, tempA; \
2104 rsB = (rs >> rsmov1) & MIPSDSP_LO; \
2105 rsA = (rs >> rsmov2) & MIPSDSP_LO; \
2106 rtB = (rt >> rtmov1) & MIPSDSP_LO; \
2107 rtA = (rt >> rtmov2) & MIPSDSP_LO; \
2109 tempB = mipsdsp_mul_q15_q15(5, rsB, rtB, env); \
2110 tempA = mipsdsp_mul_q15_q15(5, rsA, rtA, env); \
2112 return ((uint64_t)tempB << 32) | (uint64_t)tempA; \
2115 MUL_RETURN64_32_QH(muleq_s_pw_qhl, 48, 32, 48, 32);
2116 MUL_RETURN64_32_QH(muleq_s_pw_qhr, 16, 0, 16, 0);
2118 #undef MUL_RETURN64_32_QH
2120 void helper_mulsaq_s_w_qh(target_ulong rs, target_ulong rt, uint32_t ac,
2121 CPUMIPSState *env)
2123 int16_t rs3, rs2, rs1, rs0;
2124 int16_t rt3, rt2, rt1, rt0;
2125 int32_t tempD, tempC, tempB, tempA;
2126 int64_t acc[2];
2127 int64_t temp[2];
2128 int64_t temp_sum;
2130 MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
2131 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
2133 tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env);
2134 tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env);
2135 tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env);
2136 tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env);
2138 temp[0] = ((int32_t)tempD - (int32_t)tempC) +
2139 ((int32_t)tempB - (int32_t)tempA);
2140 temp[0] = (int64_t)(temp[0] << 30) >> 30;
2141 if (((temp[0] >> 33) & 0x01) == 0) {
2142 temp[1] = 0x00;
2143 } else {
2144 temp[1] = ~0ull;
2147 acc[0] = env->active_tc.LO[ac];
2148 acc[1] = env->active_tc.HI[ac];
2150 temp_sum = acc[0] + temp[0];
2151 if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
2152 ((uint64_t)temp_sum < (uint64_t)temp[0])) {
2153 acc[1] += 1;
2155 acc[0] = temp_sum;
2156 acc[1] += temp[1];
2158 env->active_tc.HI[ac] = acc[1];
2159 env->active_tc.LO[ac] = acc[0];
2161 #endif
2163 #define DP_QB(name, func, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
2164 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2165 CPUMIPSState *env) \
2167 uint8_t rs3, rs2; \
2168 uint8_t rt3, rt2; \
2169 uint16_t tempB, tempA; \
2170 uint64_t tempC, dotp; \
2172 rs3 = (rs >> rsmov1) & MIPSDSP_Q0; \
2173 rs2 = (rs >> rsmov2) & MIPSDSP_Q0; \
2174 rt3 = (rt >> rtmov1) & MIPSDSP_Q0; \
2175 rt2 = (rt >> rtmov2) & MIPSDSP_Q0; \
2176 tempB = mipsdsp_##func(rs3, rt3); \
2177 tempA = mipsdsp_##func(rs2, rt2); \
2178 dotp = (int64_t)tempB + (int64_t)tempA; \
2179 if (is_add) { \
2180 tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \
2181 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \
2182 + dotp; \
2183 } else { \
2184 tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \
2185 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \
2186 - dotp; \
2189 env->active_tc.HI[ac] = (target_long)(int32_t) \
2190 ((tempC & MIPSDSP_LHI) >> 32); \
2191 env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO); \
2194 DP_QB(dpau_h_qbl, mul_u8_u8, 1, 24, 16, 24, 16);
2195 DP_QB(dpau_h_qbr, mul_u8_u8, 1, 8, 0, 8, 0);
2196 DP_QB(dpsu_h_qbl, mul_u8_u8, 0, 24, 16, 24, 16);
2197 DP_QB(dpsu_h_qbr, mul_u8_u8, 0, 8, 0, 8, 0);
2199 #undef DP_QB
2201 #if defined(TARGET_MIPS64)
2202 #define DP_OB(name, add_sub, \
2203 rsmov1, rsmov2, rsmov3, rsmov4, \
2204 rtmov1, rtmov2, rtmov3, rtmov4) \
2205 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2206 CPUMIPSState *env) \
2208 uint8_t rsD, rsC, rsB, rsA; \
2209 uint8_t rtD, rtC, rtB, rtA; \
2210 uint16_t tempD, tempC, tempB, tempA; \
2211 uint64_t temp[2]; \
2212 uint64_t acc[2]; \
2213 uint64_t temp_sum; \
2215 temp[0] = 0; \
2216 temp[1] = 0; \
2218 rsD = (rs >> rsmov1) & MIPSDSP_Q0; \
2219 rsC = (rs >> rsmov2) & MIPSDSP_Q0; \
2220 rsB = (rs >> rsmov3) & MIPSDSP_Q0; \
2221 rsA = (rs >> rsmov4) & MIPSDSP_Q0; \
2222 rtD = (rt >> rtmov1) & MIPSDSP_Q0; \
2223 rtC = (rt >> rtmov2) & MIPSDSP_Q0; \
2224 rtB = (rt >> rtmov3) & MIPSDSP_Q0; \
2225 rtA = (rt >> rtmov4) & MIPSDSP_Q0; \
2227 tempD = mipsdsp_mul_u8_u8(rsD, rtD); \
2228 tempC = mipsdsp_mul_u8_u8(rsC, rtC); \
2229 tempB = mipsdsp_mul_u8_u8(rsB, rtB); \
2230 tempA = mipsdsp_mul_u8_u8(rsA, rtA); \
2232 temp[0] = (uint64_t)tempD + (uint64_t)tempC + \
2233 (uint64_t)tempB + (uint64_t)tempA; \
2235 acc[0] = env->active_tc.LO[ac]; \
2236 acc[1] = env->active_tc.HI[ac]; \
2238 if (add_sub) { \
2239 temp_sum = acc[0] + temp[0]; \
2240 if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
2241 ((uint64_t)temp_sum < (uint64_t)temp[0])) { \
2242 acc[1] += 1; \
2244 temp[0] = temp_sum; \
2245 temp[1] = acc[1] + temp[1]; \
2246 } else { \
2247 temp_sum = acc[0] - temp[0]; \
2248 if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \
2249 acc[1] -= 1; \
2251 temp[0] = temp_sum; \
2252 temp[1] = acc[1] - temp[1]; \
2255 env->active_tc.HI[ac] = temp[1]; \
2256 env->active_tc.LO[ac] = temp[0]; \
2259 DP_OB(dpau_h_obl, 1, 56, 48, 40, 32, 56, 48, 40, 32);
2260 DP_OB(dpau_h_obr, 1, 24, 16, 8, 0, 24, 16, 8, 0);
2261 DP_OB(dpsu_h_obl, 0, 56, 48, 40, 32, 56, 48, 40, 32);
2262 DP_OB(dpsu_h_obr, 0, 24, 16, 8, 0, 24, 16, 8, 0);
2264 #undef DP_OB
2265 #endif
2267 #define DP_NOFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
2268 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2269 CPUMIPSState *env) \
2271 int16_t rsB, rsA, rtB, rtA; \
2272 int32_t tempA, tempB; \
2273 int64_t acc; \
2275 rsB = (rs >> rsmov1) & MIPSDSP_LO; \
2276 rsA = (rs >> rsmov2) & MIPSDSP_LO; \
2277 rtB = (rt >> rtmov1) & MIPSDSP_LO; \
2278 rtA = (rt >> rtmov2) & MIPSDSP_LO; \
2280 tempB = (int32_t)rsB * (int32_t)rtB; \
2281 tempA = (int32_t)rsA * (int32_t)rtA; \
2283 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
2284 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
2286 if (is_add) { \
2287 acc = acc + ((int64_t)tempB + (int64_t)tempA); \
2288 } else { \
2289 acc = acc - ((int64_t)tempB + (int64_t)tempA); \
2292 env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32); \
2293 env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO); \
2296 DP_NOFUNC_PH(dpa_w_ph, 1, 16, 0, 16, 0);
2297 DP_NOFUNC_PH(dpax_w_ph, 1, 16, 0, 0, 16);
2298 DP_NOFUNC_PH(dps_w_ph, 0, 16, 0, 16, 0);
2299 DP_NOFUNC_PH(dpsx_w_ph, 0, 16, 0, 0, 16);
2300 #undef DP_NOFUNC_PH
2302 #define DP_HASFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
2303 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2304 CPUMIPSState *env) \
2306 int16_t rsB, rsA, rtB, rtA; \
2307 int32_t tempB, tempA; \
2308 int64_t acc, dotp; \
2310 rsB = (rs >> rsmov1) & MIPSDSP_LO; \
2311 rsA = (rs >> rsmov2) & MIPSDSP_LO; \
2312 rtB = (rt >> rtmov1) & MIPSDSP_LO; \
2313 rtA = (rt >> rtmov2) & MIPSDSP_LO; \
2315 tempB = mipsdsp_mul_q15_q15(ac, rsB, rtB, env); \
2316 tempA = mipsdsp_mul_q15_q15(ac, rsA, rtA, env); \
2318 dotp = (int64_t)tempB + (int64_t)tempA; \
2319 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
2320 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
2322 if (is_add) { \
2323 acc = acc + dotp; \
2324 } else { \
2325 acc = acc - dotp; \
2328 env->active_tc.HI[ac] = (target_long)(int32_t) \
2329 ((acc & MIPSDSP_LHI) >> 32); \
2330 env->active_tc.LO[ac] = (target_long)(int32_t) \
2331 (acc & MIPSDSP_LLO); \
2334 DP_HASFUNC_PH(dpaq_s_w_ph, 1, 16, 0, 16, 0);
2335 DP_HASFUNC_PH(dpaqx_s_w_ph, 1, 16, 0, 0, 16);
2336 DP_HASFUNC_PH(dpsq_s_w_ph, 0, 16, 0, 16, 0);
2337 DP_HASFUNC_PH(dpsqx_s_w_ph, 0, 16, 0, 0, 16);
2339 #undef DP_HASFUNC_PH
2341 #define DP_128OPERATION_PH(name, is_add) \
2342 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2343 CPUMIPSState *env) \
2345 int16_t rsh, rsl, rth, rtl; \
2346 int32_t tempB, tempA, tempC62_31, tempC63; \
2347 int64_t acc, dotp, tempC; \
2349 MIPSDSP_SPLIT32_16(rs, rsh, rsl); \
2350 MIPSDSP_SPLIT32_16(rt, rth, rtl); \
2352 tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl, env); \
2353 tempA = mipsdsp_mul_q15_q15(ac, rsl, rth, env); \
2355 dotp = (int64_t)tempB + (int64_t)tempA; \
2356 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
2357 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
2358 if (is_add) { \
2359 tempC = acc + dotp; \
2360 } else { \
2361 tempC = acc - dotp; \
2363 tempC63 = (tempC >> 63) & 0x01; \
2364 tempC62_31 = (tempC >> 31) & 0xFFFFFFFF; \
2366 if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) { \
2367 tempC = 0x7FFFFFFF; \
2368 set_DSPControl_overflow_flag(1, 16 + ac, env); \
2371 if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) { \
2372 tempC = (int64_t)(int32_t)0x80000000; \
2373 set_DSPControl_overflow_flag(1, 16 + ac, env); \
2376 env->active_tc.HI[ac] = (target_long)(int32_t) \
2377 ((tempC & MIPSDSP_LHI) >> 32); \
2378 env->active_tc.LO[ac] = (target_long)(int32_t) \
2379 (tempC & MIPSDSP_LLO); \
2382 DP_128OPERATION_PH(dpaqx_sa_w_ph, 1);
2383 DP_128OPERATION_PH(dpsqx_sa_w_ph, 0);
2385 #undef DP_128OPERATION_HP
2387 #if defined(TARGET_MIPS64)
2388 #define DP_QH(name, is_add, use_ac_env) \
2389 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2390 CPUMIPSState *env) \
2392 int32_t rs3, rs2, rs1, rs0; \
2393 int32_t rt3, rt2, rt1, rt0; \
2394 int32_t tempD, tempC, tempB, tempA; \
2395 int64_t acc[2]; \
2396 int64_t temp[2]; \
2397 int64_t temp_sum; \
2399 MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \
2400 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
2402 if (use_ac_env) { \
2403 tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env); \
2404 tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env); \
2405 tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env); \
2406 tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env); \
2407 } else { \
2408 tempD = mipsdsp_mul_u16_u16(rs3, rt3); \
2409 tempC = mipsdsp_mul_u16_u16(rs2, rt2); \
2410 tempB = mipsdsp_mul_u16_u16(rs1, rt1); \
2411 tempA = mipsdsp_mul_u16_u16(rs0, rt0); \
2414 temp[0] = (int64_t)tempD + (int64_t)tempC + \
2415 (int64_t)tempB + (int64_t)tempA; \
2417 if (temp[0] >= 0) { \
2418 temp[1] = 0; \
2419 } else { \
2420 temp[1] = ~0ull; \
2423 acc[1] = env->active_tc.HI[ac]; \
2424 acc[0] = env->active_tc.LO[ac]; \
2426 if (is_add) { \
2427 temp_sum = acc[0] + temp[0]; \
2428 if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
2429 ((uint64_t)temp_sum < (uint64_t)temp[0])) { \
2430 acc[1] = acc[1] + 1; \
2432 temp[0] = temp_sum; \
2433 temp[1] = acc[1] + temp[1]; \
2434 } else { \
2435 temp_sum = acc[0] - temp[0]; \
2436 if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \
2437 acc[1] = acc[1] - 1; \
2439 temp[0] = temp_sum; \
2440 temp[1] = acc[1] - temp[1]; \
2443 env->active_tc.HI[ac] = temp[1]; \
2444 env->active_tc.LO[ac] = temp[0]; \
2447 DP_QH(dpa_w_qh, 1, 0);
2448 DP_QH(dpaq_s_w_qh, 1, 1);
2449 DP_QH(dps_w_qh, 0, 0);
2450 DP_QH(dpsq_s_w_qh, 0, 1);
2452 #undef DP_QH
2454 #endif
2456 #define DP_L_W(name, is_add) \
2457 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2458 CPUMIPSState *env) \
2460 int32_t temp63; \
2461 int64_t dotp, acc; \
2462 uint64_t temp; \
2463 bool overflow; \
2465 dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env); \
2466 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
2467 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
2468 if (is_add) { \
2469 temp = acc + dotp; \
2470 overflow = MIPSDSP_OVERFLOW_ADD((uint64_t)acc, (uint64_t)dotp, \
2471 temp, (0x01ull << 63)); \
2472 } else { \
2473 temp = acc - dotp; \
2474 overflow = MIPSDSP_OVERFLOW_SUB((uint64_t)acc, (uint64_t)dotp, \
2475 temp, (0x01ull << 63)); \
2478 if (overflow) { \
2479 temp63 = (temp >> 63) & 0x01; \
2480 if (temp63 == 1) { \
2481 temp = (0x01ull << 63) - 1; \
2482 } else { \
2483 temp = 0x01ull << 63; \
2486 set_DSPControl_overflow_flag(1, 16 + ac, env); \
2489 env->active_tc.HI[ac] = (target_long)(int32_t) \
2490 ((temp & MIPSDSP_LHI) >> 32); \
2491 env->active_tc.LO[ac] = (target_long)(int32_t) \
2492 (temp & MIPSDSP_LLO); \
2495 DP_L_W(dpaq_sa_l_w, 1);
2496 DP_L_W(dpsq_sa_l_w, 0);
2498 #undef DP_L_W
2500 #if defined(TARGET_MIPS64)
2501 #define DP_L_PW(name, func) \
2502 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2503 CPUMIPSState *env) \
2505 int32_t rs1, rs0; \
2506 int32_t rt1, rt0; \
2507 int64_t tempB[2], tempA[2]; \
2508 int64_t temp[2]; \
2509 int64_t acc[2]; \
2510 int64_t temp_sum; \
2512 temp[0] = 0; \
2513 temp[1] = 0; \
2515 MIPSDSP_SPLIT64_32(rs, rs1, rs0); \
2516 MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
2518 tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env); \
2519 tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env); \
2521 if (tempB[0] >= 0) { \
2522 tempB[1] = 0x00; \
2523 } else { \
2524 tempB[1] = ~0ull; \
2527 if (tempA[0] >= 0) { \
2528 tempA[1] = 0x00; \
2529 } else { \
2530 tempA[1] = ~0ull; \
2533 temp_sum = tempB[0] + tempA[0]; \
2534 if (((uint64_t)temp_sum < (uint64_t)tempB[0]) && \
2535 ((uint64_t)temp_sum < (uint64_t)tempA[0])) { \
2536 temp[1] += 1; \
2538 temp[0] = temp_sum; \
2539 temp[1] += tempB[1] + tempA[1]; \
2541 mipsdsp_##func(acc, ac, temp, env); \
2543 env->active_tc.HI[ac] = acc[1]; \
2544 env->active_tc.LO[ac] = acc[0]; \
2547 DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63);
2548 DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63);
2550 #undef DP_L_PW
2552 void helper_mulsaq_s_l_pw(target_ulong rs, target_ulong rt, uint32_t ac,
2553 CPUMIPSState *env)
2555 int32_t rs1, rs0;
2556 int32_t rt1, rt0;
2557 int64_t tempB[2], tempA[2];
2558 int64_t temp[2];
2559 int64_t acc[2];
2560 int64_t temp_sum;
2562 rs1 = (rs >> 32) & MIPSDSP_LLO;
2563 rs0 = rs & MIPSDSP_LLO;
2564 rt1 = (rt >> 32) & MIPSDSP_LLO;
2565 rt0 = rt & MIPSDSP_LLO;
2567 tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env);
2568 tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);
2570 if (tempB[0] >= 0) {
2571 tempB[1] = 0x00;
2572 } else {
2573 tempB[1] = ~0ull;
2576 if (tempA[0] >= 0) {
2577 tempA[1] = 0x00;
2578 } else {
2579 tempA[1] = ~0ull;
2582 acc[0] = env->active_tc.LO[ac];
2583 acc[1] = env->active_tc.HI[ac];
2585 temp_sum = tempB[0] - tempA[0];
2586 if ((uint64_t)temp_sum > (uint64_t)tempB[0]) {
2587 tempB[1] -= 1;
2589 temp[0] = temp_sum;
2590 temp[1] = tempB[1] - tempA[1];
2592 if ((temp[1] & 0x01) == 0) {
2593 temp[1] = 0x00;
2594 } else {
2595 temp[1] = ~0ull;
2598 temp_sum = acc[0] + temp[0];
2599 if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
2600 ((uint64_t)temp_sum < (uint64_t)temp[0])) {
2601 acc[1] += 1;
2603 acc[0] = temp_sum;
2604 acc[1] += temp[1];
2606 env->active_tc.HI[ac] = acc[1];
2607 env->active_tc.LO[ac] = acc[0];
2609 #endif
2611 #define MAQ_S_W(name, mov) \
2612 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2613 CPUMIPSState *env) \
2615 int16_t rsh, rth; \
2616 int32_t tempA; \
2617 int64_t tempL, acc; \
2619 rsh = (rs >> mov) & MIPSDSP_LO; \
2620 rth = (rt >> mov) & MIPSDSP_LO; \
2621 tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \
2622 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
2623 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
2624 tempL = (int64_t)tempA + acc; \
2625 env->active_tc.HI[ac] = (target_long)(int32_t) \
2626 ((tempL & MIPSDSP_LHI) >> 32); \
2627 env->active_tc.LO[ac] = (target_long)(int32_t) \
2628 (tempL & MIPSDSP_LLO); \
2631 MAQ_S_W(maq_s_w_phl, 16);
2632 MAQ_S_W(maq_s_w_phr, 0);
2634 #undef MAQ_S_W
2636 #define MAQ_SA_W(name, mov) \
2637 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2638 CPUMIPSState *env) \
2640 int16_t rsh, rth; \
2641 int32_t tempA; \
2643 rsh = (rs >> mov) & MIPSDSP_LO; \
2644 rth = (rt >> mov) & MIPSDSP_LO; \
2645 tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \
2646 tempA = mipsdsp_sat32_acc_q31(ac, tempA, env); \
2648 env->active_tc.HI[ac] = (target_long)(int32_t)(((int64_t)tempA & \
2649 MIPSDSP_LHI) >> 32); \
2650 env->active_tc.LO[ac] = (target_long)(int32_t)((int64_t)tempA & \
2651 MIPSDSP_LLO); \
2654 MAQ_SA_W(maq_sa_w_phl, 16);
2655 MAQ_SA_W(maq_sa_w_phr, 0);
2657 #undef MAQ_SA_W
2659 #define MULQ_W(name, addvar) \
2660 target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2661 CPUMIPSState *env) \
2663 int32_t rs_t, rt_t; \
2664 int32_t tempI; \
2665 int64_t tempL; \
2667 rs_t = rs & MIPSDSP_LLO; \
2668 rt_t = rt & MIPSDSP_LLO; \
2670 if ((rs_t == 0x80000000) && (rt_t == 0x80000000)) { \
2671 tempL = 0x7FFFFFFF00000000ull; \
2672 set_DSPControl_overflow_flag(1, 21, env); \
2673 } else { \
2674 tempL = ((int64_t)rs_t * (int64_t)rt_t) << 1; \
2675 tempL += addvar; \
2677 tempI = (tempL & MIPSDSP_LHI) >> 32; \
2679 return (target_long)(int32_t)tempI; \
2682 MULQ_W(mulq_s_w, 0);
2683 MULQ_W(mulq_rs_w, 0x80000000ull);
2685 #undef MULQ_W
2687 #if defined(TARGET_MIPS64)
2689 #define MAQ_S_W_QH(name, mov) \
2690 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2691 CPUMIPSState *env) \
2693 int16_t rs_t, rt_t; \
2694 int32_t temp_mul; \
2695 int64_t temp[2]; \
2696 int64_t acc[2]; \
2697 int64_t temp_sum; \
2699 temp[0] = 0; \
2700 temp[1] = 0; \
2702 rs_t = (rs >> mov) & MIPSDSP_LO; \
2703 rt_t = (rt >> mov) & MIPSDSP_LO; \
2704 temp_mul = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \
2706 temp[0] = (int64_t)temp_mul; \
2707 if (temp[0] >= 0) { \
2708 temp[1] = 0x00; \
2709 } else { \
2710 temp[1] = ~0ull; \
2713 acc[0] = env->active_tc.LO[ac]; \
2714 acc[1] = env->active_tc.HI[ac]; \
2716 temp_sum = acc[0] + temp[0]; \
2717 if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
2718 ((uint64_t)temp_sum < (uint64_t)temp[0])) { \
2719 acc[1] += 1; \
2721 acc[0] = temp_sum; \
2722 acc[1] += temp[1]; \
2724 env->active_tc.HI[ac] = acc[1]; \
2725 env->active_tc.LO[ac] = acc[0]; \
2728 MAQ_S_W_QH(maq_s_w_qhll, 48);
2729 MAQ_S_W_QH(maq_s_w_qhlr, 32);
2730 MAQ_S_W_QH(maq_s_w_qhrl, 16);
2731 MAQ_S_W_QH(maq_s_w_qhrr, 0);
2733 #undef MAQ_S_W_QH
2735 #define MAQ_SA_W(name, mov) \
2736 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2737 CPUMIPSState *env) \
2739 int16_t rs_t, rt_t; \
2740 int32_t temp; \
2741 int64_t acc[2]; \
2743 rs_t = (rs >> mov) & MIPSDSP_LO; \
2744 rt_t = (rt >> mov) & MIPSDSP_LO; \
2745 temp = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \
2746 temp = mipsdsp_sat32_acc_q31(ac, temp, env); \
2748 acc[0] = (int64_t)(int32_t)temp; \
2749 if (acc[0] >= 0) { \
2750 acc[1] = 0x00; \
2751 } else { \
2752 acc[1] = ~0ull; \
2755 env->active_tc.HI[ac] = acc[1]; \
2756 env->active_tc.LO[ac] = acc[0]; \
2759 MAQ_SA_W(maq_sa_w_qhll, 48);
2760 MAQ_SA_W(maq_sa_w_qhlr, 32);
2761 MAQ_SA_W(maq_sa_w_qhrl, 16);
2762 MAQ_SA_W(maq_sa_w_qhrr, 0);
2764 #undef MAQ_SA_W
2766 #define MAQ_S_L_PW(name, mov) \
2767 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2768 CPUMIPSState *env) \
2770 int32_t rs_t, rt_t; \
2771 int64_t temp[2]; \
2772 int64_t acc[2]; \
2773 int64_t temp_sum; \
2775 temp[0] = 0; \
2776 temp[1] = 0; \
2778 rs_t = (rs >> mov) & MIPSDSP_LLO; \
2779 rt_t = (rt >> mov) & MIPSDSP_LLO; \
2781 temp[0] = mipsdsp_mul_q31_q31(ac, rs_t, rt_t, env); \
2782 if (temp[0] >= 0) { \
2783 temp[1] = 0x00; \
2784 } else { \
2785 temp[1] = ~0ull; \
2788 acc[0] = env->active_tc.LO[ac]; \
2789 acc[1] = env->active_tc.HI[ac]; \
2791 temp_sum = acc[0] + temp[0]; \
2792 if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
2793 ((uint64_t)temp_sum < (uint64_t)temp[0])) { \
2794 acc[1] += 1; \
2796 acc[0] = temp_sum; \
2797 acc[1] += temp[1]; \
2799 env->active_tc.HI[ac] = acc[1]; \
2800 env->active_tc.LO[ac] = acc[0]; \
2803 MAQ_S_L_PW(maq_s_l_pwl, 32);
2804 MAQ_S_L_PW(maq_s_l_pwr, 0);
2806 #undef MAQ_S_L_PW
2808 #define DM_OPERATE(name, func, is_add, sigext) \
2809 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2810 CPUMIPSState *env) \
2812 int32_t rs1, rs0; \
2813 int32_t rt1, rt0; \
2814 int64_t tempBL[2], tempAL[2]; \
2815 int64_t acc[2]; \
2816 int64_t temp[2]; \
2817 int64_t temp_sum; \
2819 temp[0] = 0x00; \
2820 temp[1] = 0x00; \
2822 MIPSDSP_SPLIT64_32(rs, rs1, rs0); \
2823 MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
2825 if (sigext) { \
2826 tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1); \
2827 tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0); \
2829 if (tempBL[0] >= 0) { \
2830 tempBL[1] = 0x0; \
2831 } else { \
2832 tempBL[1] = ~0ull; \
2835 if (tempAL[0] >= 0) { \
2836 tempAL[1] = 0x0; \
2837 } else { \
2838 tempAL[1] = ~0ull; \
2840 } else { \
2841 tempBL[0] = mipsdsp_##func(rs1, rt1); \
2842 tempAL[0] = mipsdsp_##func(rs0, rt0); \
2843 tempBL[1] = 0; \
2844 tempAL[1] = 0; \
2847 acc[1] = env->active_tc.HI[ac]; \
2848 acc[0] = env->active_tc.LO[ac]; \
2850 temp_sum = tempBL[0] + tempAL[0]; \
2851 if (((uint64_t)temp_sum < (uint64_t)tempBL[0]) && \
2852 ((uint64_t)temp_sum < (uint64_t)tempAL[0])) { \
2853 temp[1] += 1; \
2855 temp[0] = temp_sum; \
2856 temp[1] += tempBL[1] + tempAL[1]; \
2858 if (is_add) { \
2859 temp_sum = acc[0] + temp[0]; \
2860 if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
2861 ((uint64_t)temp_sum < (uint64_t)temp[0])) { \
2862 acc[1] += 1; \
2864 temp[0] = temp_sum; \
2865 temp[1] = acc[1] + temp[1]; \
2866 } else { \
2867 temp_sum = acc[0] - temp[0]; \
2868 if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \
2869 acc[1] -= 1; \
2871 temp[0] = temp_sum; \
2872 temp[1] = acc[1] - temp[1]; \
2875 env->active_tc.HI[ac] = temp[1]; \
2876 env->active_tc.LO[ac] = temp[0]; \
2879 DM_OPERATE(dmadd, mul_i32_i32, 1, 1);
2880 DM_OPERATE(dmaddu, mul_u32_u32, 1, 0);
2881 DM_OPERATE(dmsub, mul_i32_i32, 0, 1);
2882 DM_OPERATE(dmsubu, mul_u32_u32, 0, 0);
2883 #undef DM_OPERATE
2884 #endif
2886 /** DSP Bit/Manipulation Sub-class insns **/
2887 target_ulong helper_bitrev(target_ulong rt)
2889 int32_t temp;
2890 uint32_t rd;
2891 int i;
2893 temp = rt & MIPSDSP_LO;
2894 rd = 0;
2895 for (i = 0; i < 16; i++) {
2896 rd = (rd << 1) | (temp & 1);
2897 temp = temp >> 1;
2900 return (target_ulong)rd;
2903 #define BIT_INSV(name, posfilter, sizefilter, ret_type) \
2904 target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \
2905 target_ulong rt) \
2907 uint32_t pos, size, msb, lsb; \
2908 target_ulong filter; \
2909 target_ulong temp, temprs, temprt; \
2910 target_ulong dspc; \
2912 dspc = env->active_tc.DSPControl; \
2914 pos = dspc & posfilter; \
2915 size = (dspc >> 7) & sizefilter; \
2917 msb = pos + size - 1; \
2918 lsb = pos; \
2920 if (lsb > msb || (msb > TARGET_LONG_BITS)) { \
2921 return rt; \
2924 filter = ((int32_t)0x01 << size) - 1; \
2925 filter = filter << pos; \
2926 temprs = (rs << pos) & filter; \
2927 temprt = rt & ~filter; \
2928 temp = temprs | temprt; \
2930 return (target_long)(ret_type)temp; \
2933 BIT_INSV(insv, 0x1F, 0x1F, int32_t);
2934 #ifdef TARGET_MIPS64
2935 BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
2936 #endif
2938 #undef BIT_INSV
2941 /** DSP Compare-Pick Sub-class insns **/
2942 #define CMP_HAS_RET(name, func, split_num, filter, bit_size) \
2943 target_ulong helper_##name(target_ulong rs, target_ulong rt) \
2945 uint32_t rs_t, rt_t; \
2946 uint8_t cc; \
2947 uint32_t temp = 0; \
2948 int i; \
2950 for (i = 0; i < split_num; i++) { \
2951 rs_t = (rs >> (bit_size * i)) & filter; \
2952 rt_t = (rt >> (bit_size * i)) & filter; \
2953 cc = mipsdsp_##func(rs_t, rt_t); \
2954 temp |= cc << i; \
2957 return (target_ulong)temp; \
2960 CMP_HAS_RET(cmpgu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8);
2961 CMP_HAS_RET(cmpgu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8);
2962 CMP_HAS_RET(cmpgu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8);
2964 #ifdef TARGET_MIPS64
2965 CMP_HAS_RET(cmpgu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8);
2966 CMP_HAS_RET(cmpgu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8);
2967 CMP_HAS_RET(cmpgu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8);
2968 #endif
2970 #undef CMP_HAS_RET
2973 #define CMP_NO_RET(name, func, split_num, filter, bit_size) \
2974 void helper_##name(target_ulong rs, target_ulong rt, \
2975 CPUMIPSState *env) \
2977 int##bit_size##_t rs_t, rt_t; \
2978 int##bit_size##_t flag = 0; \
2979 int##bit_size##_t cc; \
2980 int i; \
2982 for (i = 0; i < split_num; i++) { \
2983 rs_t = (rs >> (bit_size * i)) & filter; \
2984 rt_t = (rt >> (bit_size * i)) & filter; \
2986 cc = mipsdsp_##func((int32_t)rs_t, (int32_t)rt_t); \
2987 flag |= cc << i; \
2990 set_DSPControl_24(flag, split_num, env); \
2993 CMP_NO_RET(cmpu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8);
2994 CMP_NO_RET(cmpu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8);
2995 CMP_NO_RET(cmpu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8);
2997 CMP_NO_RET(cmp_eq_ph, cmp_eq, 2, MIPSDSP_LO, 16);
2998 CMP_NO_RET(cmp_lt_ph, cmp_lt, 2, MIPSDSP_LO, 16);
2999 CMP_NO_RET(cmp_le_ph, cmp_le, 2, MIPSDSP_LO, 16);
3001 #ifdef TARGET_MIPS64
3002 CMP_NO_RET(cmpu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8);
3003 CMP_NO_RET(cmpu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8);
3004 CMP_NO_RET(cmpu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8);
3006 CMP_NO_RET(cmp_eq_qh, cmp_eq, 4, MIPSDSP_LO, 16);
3007 CMP_NO_RET(cmp_lt_qh, cmp_lt, 4, MIPSDSP_LO, 16);
3008 CMP_NO_RET(cmp_le_qh, cmp_le, 4, MIPSDSP_LO, 16);
3010 CMP_NO_RET(cmp_eq_pw, cmp_eq, 2, MIPSDSP_LLO, 32);
3011 CMP_NO_RET(cmp_lt_pw, cmp_lt, 2, MIPSDSP_LLO, 32);
3012 CMP_NO_RET(cmp_le_pw, cmp_le, 2, MIPSDSP_LLO, 32);
3013 #endif
3014 #undef CMP_NO_RET
3016 #if defined(TARGET_MIPS64)
3018 #define CMPGDU_OB(name) \
3019 target_ulong helper_cmpgdu_##name##_ob(target_ulong rs, target_ulong rt, \
3020 CPUMIPSState *env) \
3022 int i; \
3023 uint8_t rs_t, rt_t; \
3024 uint32_t cond; \
3026 cond = 0; \
3028 for (i = 0; i < 8; i++) { \
3029 rs_t = (rs >> (8 * i)) & MIPSDSP_Q0; \
3030 rt_t = (rt >> (8 * i)) & MIPSDSP_Q0; \
3032 if (mipsdsp_cmpu_##name(rs_t, rt_t)) { \
3033 cond |= 0x01 << i; \
3037 set_DSPControl_24(cond, 8, env); \
3039 return (uint64_t)cond; \
3042 CMPGDU_OB(eq)
3043 CMPGDU_OB(lt)
3044 CMPGDU_OB(le)
3045 #undef CMPGDU_OB
3046 #endif
3048 #define PICK_INSN(name, split_num, filter, bit_size, ret32bit) \
3049 target_ulong helper_##name(target_ulong rs, target_ulong rt, \
3050 CPUMIPSState *env) \
3052 uint32_t rs_t, rt_t; \
3053 uint32_t cc; \
3054 target_ulong dsp; \
3055 int i; \
3056 target_ulong result = 0; \
3058 dsp = env->active_tc.DSPControl; \
3059 for (i = 0; i < split_num; i++) { \
3060 rs_t = (rs >> (bit_size * i)) & filter; \
3061 rt_t = (rt >> (bit_size * i)) & filter; \
3062 cc = (dsp >> (24 + i)) & 0x01; \
3063 cc = cc == 1 ? rs_t : rt_t; \
3065 result |= (target_ulong)cc << (bit_size * i); \
3068 if (ret32bit) { \
3069 result = (target_long)(int32_t)(result & MIPSDSP_LLO); \
3072 return result; \
3075 PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1);
3076 PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1);
3078 #ifdef TARGET_MIPS64
3079 PICK_INSN(pick_ob, 8, MIPSDSP_Q0, 8, 0);
3080 PICK_INSN(pick_qh, 4, MIPSDSP_LO, 16, 0);
3081 PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0);
3082 #endif
3083 #undef PICK_INSN
3085 target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt)
3087 uint32_t rsl, rth;
3089 rsl = rs & MIPSDSP_LO;
3090 rth = (rt & MIPSDSP_HI) >> 16;
3092 return (target_long)(int32_t)((rsl << 16) | rth);
3095 #if defined(TARGET_MIPS64)
3096 target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt)
3098 uint32_t rs0, rt1;
3100 rs0 = rs & MIPSDSP_LLO;
3101 rt1 = (rt >> 32) & MIPSDSP_LLO;
3103 return ((uint64_t)rs0 << 32) | (uint64_t)rt1;
3105 #endif
3107 /** DSP Accumulator and DSPControl Access Sub-class insns **/
3108 target_ulong helper_extr_w(target_ulong ac, target_ulong shift,
3109 CPUMIPSState *env)
3111 int32_t tempI;
3112 int64_t tempDL[2];
3114 shift = shift & 0x1F;
3116 mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
3117 if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3118 (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3119 set_DSPControl_overflow_flag(1, 23, env);
3122 tempI = (tempDL[0] >> 1) & MIPSDSP_LLO;
3124 tempDL[0] += 1;
3125 if (tempDL[0] == 0) {
3126 tempDL[1] += 1;
3129 if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3130 ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3131 set_DSPControl_overflow_flag(1, 23, env);
3134 return (target_long)tempI;
3137 target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
3138 CPUMIPSState *env)
3140 int64_t tempDL[2];
3142 shift = shift & 0x1F;
3144 mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
3145 if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3146 (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3147 set_DSPControl_overflow_flag(1, 23, env);
3150 tempDL[0] += 1;
3151 if (tempDL[0] == 0) {
3152 tempDL[1] += 1;
3155 if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3156 ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3157 set_DSPControl_overflow_flag(1, 23, env);
3160 return (target_long)(int32_t)(tempDL[0] >> 1);
3163 target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
3164 CPUMIPSState *env)
3166 int32_t tempI, temp64;
3167 int64_t tempDL[2];
3169 shift = shift & 0x1F;
3171 mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
3172 if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3173 (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3174 set_DSPControl_overflow_flag(1, 23, env);
3176 tempDL[0] += 1;
3177 if (tempDL[0] == 0) {
3178 tempDL[1] += 1;
3180 tempI = tempDL[0] >> 1;
3182 if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3183 ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3184 temp64 = tempDL[1] & 0x01;
3185 if (temp64 == 0) {
3186 tempI = 0x7FFFFFFF;
3187 } else {
3188 tempI = 0x80000000;
3190 set_DSPControl_overflow_flag(1, 23, env);
3193 return (target_long)tempI;
3196 #if defined(TARGET_MIPS64)
3197 target_ulong helper_dextr_w(target_ulong ac, target_ulong shift,
3198 CPUMIPSState *env)
3200 uint64_t temp[3];
3202 shift = shift & 0x3F;
3204 mipsdsp_rndrashift_acc(temp, ac, shift, env);
3206 return (int64_t)(int32_t)(temp[0] >> 1);
3209 target_ulong helper_dextr_r_w(target_ulong ac, target_ulong shift,
3210 CPUMIPSState *env)
3212 uint64_t temp[3];
3213 uint32_t temp128;
3215 shift = shift & 0x3F;
3216 mipsdsp_rndrashift_acc(temp, ac, shift, env);
3218 temp[0] += 1;
3219 if (temp[0] == 0) {
3220 temp[1] += 1;
3221 if (temp[1] == 0) {
3222 temp[2] += 1;
3226 temp128 = temp[2] & 0x01;
3228 if ((temp128 != 0 || temp[1] != 0) &&
3229 (temp128 != 1 || temp[1] != ~0ull)) {
3230 set_DSPControl_overflow_flag(1, 23, env);
3233 return (int64_t)(int32_t)(temp[0] >> 1);
3236 target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift,
3237 CPUMIPSState *env)
3239 uint64_t temp[3];
3240 uint32_t temp128;
3242 shift = shift & 0x3F;
3243 mipsdsp_rndrashift_acc(temp, ac, shift, env);
3245 temp[0] += 1;
3246 if (temp[0] == 0) {
3247 temp[1] += 1;
3248 if (temp[1] == 0) {
3249 temp[2] += 1;
3253 temp128 = temp[2] & 0x01;
3255 if ((temp128 != 0 || temp[1] != 0) &&
3256 (temp128 != 1 || temp[1] != ~0ull)) {
3257 if (temp128 == 0) {
3258 temp[0] = 0x0FFFFFFFF;
3259 } else {
3260 temp[0] = 0x0100000000ULL;
3262 set_DSPControl_overflow_flag(1, 23, env);
3265 return (int64_t)(int32_t)(temp[0] >> 1);
3268 target_ulong helper_dextr_l(target_ulong ac, target_ulong shift,
3269 CPUMIPSState *env)
3271 uint64_t temp[3];
3272 target_ulong result;
3274 shift = shift & 0x3F;
3276 mipsdsp_rndrashift_acc(temp, ac, shift, env);
3277 result = (temp[1] << 63) | (temp[0] >> 1);
3279 return result;
3282 target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift,
3283 CPUMIPSState *env)
3285 uint64_t temp[3];
3286 uint32_t temp128;
3287 target_ulong result;
3289 shift = shift & 0x3F;
3290 mipsdsp_rndrashift_acc(temp, ac, shift, env);
3292 temp[0] += 1;
3293 if (temp[0] == 0) {
3294 temp[1] += 1;
3295 if (temp[1] == 0) {
3296 temp[2] += 1;
3300 temp128 = temp[2] & 0x01;
3302 if ((temp128 != 0 || temp[1] != 0) &&
3303 (temp128 != 1 || temp[1] != ~0ull)) {
3304 set_DSPControl_overflow_flag(1, 23, env);
3307 result = (temp[1] << 63) | (temp[0] >> 1);
3309 return result;
3312 target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift,
3313 CPUMIPSState *env)
3315 uint64_t temp[3];
3316 uint32_t temp128;
3317 target_ulong result;
3319 shift = shift & 0x3F;
3320 mipsdsp_rndrashift_acc(temp, ac, shift, env);
3322 temp[0] += 1;
3323 if (temp[0] == 0) {
3324 temp[1] += 1;
3325 if (temp[1] == 0) {
3326 temp[2] += 1;
3330 temp128 = temp[2] & 0x01;
3332 if ((temp128 != 0 || temp[1] != 0) &&
3333 (temp128 != 1 || temp[1] != ~0ull)) {
3334 if (temp128 == 0) {
3335 temp[1] &= ~0x00ull - 1;
3336 temp[0] |= ~0x00ull - 1;
3337 } else {
3338 temp[1] |= 0x01;
3339 temp[0] &= 0x01;
3341 set_DSPControl_overflow_flag(1, 23, env);
3343 result = (temp[1] << 63) | (temp[0] >> 1);
3345 return result;
3347 #endif
3349 target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift,
3350 CPUMIPSState *env)
3352 int64_t temp, acc;
3354 shift = shift & 0x1F;
3356 acc = ((int64_t)env->active_tc.HI[ac] << 32) |
3357 ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
3359 temp = acc >> shift;
3361 if (temp > (int64_t)0x7FFF) {
3362 temp = 0x00007FFF;
3363 set_DSPControl_overflow_flag(1, 23, env);
3364 } else if (temp < (int64_t)0xFFFFFFFFFFFF8000ULL) {
3365 temp = 0xFFFF8000;
3366 set_DSPControl_overflow_flag(1, 23, env);
3369 return (target_long)(int32_t)(temp & 0xFFFFFFFF);
3373 #if defined(TARGET_MIPS64)
3374 target_ulong helper_dextr_s_h(target_ulong ac, target_ulong shift,
3375 CPUMIPSState *env)
3377 int64_t temp[2];
3378 uint32_t temp127;
3380 shift = shift & 0x1F;
3382 mipsdsp_rashift_acc((uint64_t *)temp, ac, shift, env);
3384 temp127 = (temp[1] >> 63) & 0x01;
3386 if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) {
3387 temp[0] &= 0xFFFF0000;
3388 temp[0] |= 0x00007FFF;
3389 set_DSPControl_overflow_flag(1, 23, env);
3390 } else if ((temp127 == 1) &&
3391 (temp[1] < 0xFFFFFFFFFFFFFFFFll
3392 || temp[0] < 0xFFFFFFFFFFFF1000ll)) {
3393 temp[0] &= 0xFFFF0000;
3394 temp[0] |= 0x00008000;
3395 set_DSPControl_overflow_flag(1, 23, env);
3398 return (int64_t)(int16_t)(temp[0] & MIPSDSP_LO);
3401 #endif
3403 target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState *env)
3405 int32_t start_pos;
3406 int sub;
3407 uint32_t temp;
3408 uint64_t acc;
3410 size = size & 0x1F;
3412 temp = 0;
3413 start_pos = get_DSPControl_pos(env);
3414 sub = start_pos - (size + 1);
3415 if (sub >= -1) {
3416 acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
3417 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
3418 temp = (acc >> (start_pos - size)) &
3419 (((uint32_t)0x01 << (size + 1)) - 1);
3420 set_DSPControl_efi(0, env);
3421 } else {
3422 set_DSPControl_efi(1, env);
3425 return (target_ulong)temp;
3428 target_ulong helper_extpdp(target_ulong ac, target_ulong size,
3429 CPUMIPSState *env)
3431 int32_t start_pos;
3432 int sub;
3433 uint32_t temp;
3434 uint64_t acc;
3436 size = size & 0x1F;
3437 temp = 0;
3438 start_pos = get_DSPControl_pos(env);
3439 sub = start_pos - (size + 1);
3440 if (sub >= -1) {
3441 acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
3442 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
3443 temp = (acc >> (start_pos - size)) &
3444 (((uint32_t)0x01 << (size + 1)) - 1);
3446 set_DSPControl_pos(start_pos - (size + 1), env);
3447 set_DSPControl_efi(0, env);
3448 } else {
3449 set_DSPControl_efi(1, env);
3452 return (target_ulong)temp;
3456 #if defined(TARGET_MIPS64)
3457 target_ulong helper_dextp(target_ulong ac, target_ulong size, CPUMIPSState *env)
3459 int start_pos;
3460 int len;
3461 int sub;
3462 uint64_t tempB, tempA;
3463 uint64_t temp;
3465 temp = 0;
3467 size = size & 0x3F;
3468 start_pos = get_DSPControl_pos(env);
3469 len = start_pos - size;
3470 tempB = env->active_tc.HI[ac];
3471 tempA = env->active_tc.LO[ac];
3473 sub = start_pos - (size + 1);
3475 if (sub >= -1) {
3476 temp = (tempB << (64 - len)) | (tempA >> len);
3477 temp = temp & ((0x01 << (size + 1)) - 1);
3478 set_DSPControl_efi(0, env);
3479 } else {
3480 set_DSPControl_efi(1, env);
3483 return temp;
3486 target_ulong helper_dextpdp(target_ulong ac, target_ulong size,
3487 CPUMIPSState *env)
3489 int start_pos;
3490 int len;
3491 int sub;
3492 uint64_t tempB, tempA;
3493 uint64_t temp;
3495 temp = 0;
3496 size = size & 0x3F;
3497 start_pos = get_DSPControl_pos(env);
3498 len = start_pos - size;
3499 tempB = env->active_tc.HI[ac];
3500 tempA = env->active_tc.LO[ac];
3502 sub = start_pos - (size + 1);
3504 if (sub >= -1) {
3505 temp = (tempB << (64 - len)) | (tempA >> len);
3506 temp = temp & ((0x01 << (size + 1)) - 1);
3507 set_DSPControl_pos(sub, env);
3508 set_DSPControl_efi(0, env);
3509 } else {
3510 set_DSPControl_efi(1, env);
3513 return temp;
3516 #endif
3518 void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env)
3520 int8_t rs5_0;
3521 uint64_t temp, acc;
3523 rs5_0 = rs & 0x3F;
3524 rs5_0 = (int8_t)(rs5_0 << 2) >> 2;
3526 if (unlikely(rs5_0 == 0)) {
3527 return;
3530 acc = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) |
3531 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
3533 if (rs5_0 > 0) {
3534 temp = acc >> rs5_0;
3535 } else {
3536 temp = acc << -rs5_0;
3539 env->active_tc.HI[ac] = (target_ulong)(int32_t)((temp & MIPSDSP_LHI) >> 32);
3540 env->active_tc.LO[ac] = (target_ulong)(int32_t)(temp & MIPSDSP_LLO);
3543 #if defined(TARGET_MIPS64)
3544 void helper_dshilo(target_ulong shift, target_ulong ac, CPUMIPSState *env)
3546 int8_t shift_t;
3547 uint64_t tempB, tempA;
3549 shift_t = (int8_t)(shift << 1) >> 1;
3551 tempB = env->active_tc.HI[ac];
3552 tempA = env->active_tc.LO[ac];
3554 if (shift_t != 0) {
3555 if (shift_t >= 0) {
3556 tempA = (tempB << (64 - shift_t)) | (tempA >> shift_t);
3557 tempB = tempB >> shift_t;
3558 } else {
3559 shift_t = -shift_t;
3560 tempB = (tempB << shift_t) | (tempA >> (64 - shift_t));
3561 tempA = tempA << shift_t;
3565 env->active_tc.HI[ac] = tempB;
3566 env->active_tc.LO[ac] = tempA;
3569 #endif
3570 void helper_mthlip(target_ulong ac, target_ulong rs, CPUMIPSState *env)
3572 int32_t tempA, tempB, pos;
3574 tempA = rs;
3575 tempB = env->active_tc.LO[ac];
3576 env->active_tc.HI[ac] = (target_long)tempB;
3577 env->active_tc.LO[ac] = (target_long)tempA;
3578 pos = get_DSPControl_pos(env);
3580 if (pos > 32) {
3581 return;
3582 } else {
3583 set_DSPControl_pos(pos + 32, env);
3587 #if defined(TARGET_MIPS64)
3588 void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env)
3590 uint8_t ac_t;
3591 uint8_t pos;
3592 uint64_t tempB, tempA;
3594 ac_t = ac & 0x3;
3596 tempA = rs;
3597 tempB = env->active_tc.LO[ac_t];
3599 env->active_tc.HI[ac_t] = tempB;
3600 env->active_tc.LO[ac_t] = tempA;
3602 pos = get_DSPControl_pos(env);
3604 if (pos <= 64) {
3605 pos = pos + 64;
3606 set_DSPControl_pos(pos, env);
3609 #endif
3611 void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env)
3613 uint8_t mask[6];
3614 uint8_t i;
3615 uint32_t newbits, overwrite;
3616 target_ulong dsp;
3618 newbits = 0x00;
3619 overwrite = 0xFFFFFFFF;
3620 dsp = env->active_tc.DSPControl;
3622 for (i = 0; i < 6; i++) {
3623 mask[i] = (mask_num >> i) & 0x01;
3626 if (mask[0] == 1) {
3627 #if defined(TARGET_MIPS64)
3628 overwrite &= 0xFFFFFF80;
3629 newbits &= 0xFFFFFF80;
3630 newbits |= 0x0000007F & rs;
3631 #else
3632 overwrite &= 0xFFFFFFC0;
3633 newbits &= 0xFFFFFFC0;
3634 newbits |= 0x0000003F & rs;
3635 #endif
3638 if (mask[1] == 1) {
3639 overwrite &= 0xFFFFE07F;
3640 newbits &= 0xFFFFE07F;
3641 newbits |= 0x00001F80 & rs;
3644 if (mask[2] == 1) {
3645 overwrite &= 0xFFFFDFFF;
3646 newbits &= 0xFFFFDFFF;
3647 newbits |= 0x00002000 & rs;
3650 if (mask[3] == 1) {
3651 overwrite &= 0xFF00FFFF;
3652 newbits &= 0xFF00FFFF;
3653 newbits |= 0x00FF0000 & rs;
3656 if (mask[4] == 1) {
3657 overwrite &= 0x00FFFFFF;
3658 newbits &= 0x00FFFFFF;
3659 #if defined(TARGET_MIPS64)
3660 newbits |= 0xFF000000 & rs;
3661 #else
3662 newbits |= 0x0F000000 & rs;
3663 #endif
3666 if (mask[5] == 1) {
3667 overwrite &= 0xFFFFBFFF;
3668 newbits &= 0xFFFFBFFF;
3669 newbits |= 0x00004000 & rs;
3672 dsp = dsp & overwrite;
3673 dsp = dsp | newbits;
3674 env->active_tc.DSPControl = dsp;
3677 void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
3679 return cpu_wrdsp(rs, mask_num, env);
3682 uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env)
3684 uint8_t mask[6];
3685 uint32_t ruler, i;
3686 target_ulong temp;
3687 target_ulong dsp;
3689 ruler = 0x01;
3690 for (i = 0; i < 6; i++) {
3691 mask[i] = (mask_num & ruler) >> i ;
3692 ruler = ruler << 1;
3695 temp = 0x00;
3696 dsp = env->active_tc.DSPControl;
3698 if (mask[0] == 1) {
3699 #if defined(TARGET_MIPS64)
3700 temp |= dsp & 0x7F;
3701 #else
3702 temp |= dsp & 0x3F;
3703 #endif
3706 if (mask[1] == 1) {
3707 temp |= dsp & 0x1F80;
3710 if (mask[2] == 1) {
3711 temp |= dsp & 0x2000;
3714 if (mask[3] == 1) {
3715 temp |= dsp & 0x00FF0000;
3718 if (mask[4] == 1) {
3719 #if defined(TARGET_MIPS64)
3720 temp |= dsp & 0xFF000000;
3721 #else
3722 temp |= dsp & 0x0F000000;
3723 #endif
3726 if (mask[5] == 1) {
3727 temp |= dsp & 0x4000;
3730 return temp;
3733 target_ulong helper_rddsp(target_ulong mask_num, CPUMIPSState *env)
3735 return cpu_rddsp(mask_num, env);
3739 #undef MIPSDSP_LHI
3740 #undef MIPSDSP_LLO
3741 #undef MIPSDSP_HI
3742 #undef MIPSDSP_LO
3743 #undef MIPSDSP_Q3
3744 #undef MIPSDSP_Q2
3745 #undef MIPSDSP_Q1
3746 #undef MIPSDSP_Q0
3748 #undef MIPSDSP_SPLIT32_8
3749 #undef MIPSDSP_SPLIT32_16
3751 #undef MIPSDSP_RETURN32_8
3752 #undef MIPSDSP_RETURN32_16
3754 #ifdef TARGET_MIPS64
3755 #undef MIPSDSP_SPLIT64_16
3756 #undef MIPSDSP_SPLIT64_32
3757 #undef MIPSDSP_RETURN64_16
3758 #undef MIPSDSP_RETURN64_32
3759 #endif