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/>.
23 /* As the byte ordering doesn't matter, i.e. all columns are treated
24 identically, these unions can be used directly. */
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
,
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
)
70 filter
= ((0x01 << len
) - 1) << 24;
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
)
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
)
90 dspc
= env
->active_tc
.DSPControl
;
92 dspc
= dspc
& 0xFFFFFFC0;
95 dspc
= dspc
& 0xFFFFFF80;
98 env
->active_tc
.DSPControl
= dspc
;
101 static inline uint32_t get_DSPControl_pos(CPUMIPSState
*env
)
106 dspc
= env
->active_tc
.DSPControl
;
108 #ifndef TARGET_MIPS64
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, \
127 if (a == INT##size##_MIN) { \
128 set_DSPControl_overflow_flag(1, 20, env); \
129 return INT##size##_MAX; \
131 return MIPSDSP_ABS(a); \
137 #undef DO_MIPS_SAT_ABS
140 static inline int16_t mipsdsp_add_i16(int16_t a
, int16_t b
, CPUMIPSState
*env
)
146 if (MIPSDSP_OVERFLOW_ADD(a
, b
, tempI
, 0x8000)) {
147 set_DSPControl_overflow_flag(1, 20, env
);
153 static inline int16_t mipsdsp_sat_add_i16(int16_t a
, int16_t b
,
160 if (MIPSDSP_OVERFLOW_ADD(a
, b
, tempS
, 0x8000)) {
166 set_DSPControl_overflow_flag(1, 20, env
);
172 static inline int32_t mipsdsp_sat_add_i32(int32_t a
, int32_t b
,
179 if (MIPSDSP_OVERFLOW_ADD(a
, b
, tempI
, 0x80000000)) {
185 set_DSPControl_overflow_flag(1, 20, env
);
191 static inline uint8_t mipsdsp_add_u8(uint8_t a
, uint8_t b
, CPUMIPSState
*env
)
195 temp
= (uint16_t)a
+ (uint16_t)b
;
198 set_DSPControl_overflow_flag(1, 20, env
);
204 static inline uint16_t mipsdsp_add_u16(uint16_t a
, uint16_t b
,
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
,
224 temp
= (uint16_t)a
+ (uint16_t)b
;
225 result
= temp
& 0xFF;
229 set_DSPControl_overflow_flag(1, 20, env
);
235 static inline uint16_t mipsdsp_sat_add_u16(uint16_t a
, uint16_t b
,
241 temp
= (uint32_t)a
+ (uint32_t)b
;
242 result
= temp
& 0xFFFF;
244 if (0x00010000 & temp
) {
246 set_DSPControl_overflow_flag(1, 20, env
);
252 static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc
, int32_t a
,
256 int32_t temp32
, temp31
, result
;
259 #ifndef TARGET_MIPS64
260 temp
= ((uint64_t)env
->active_tc
.HI
[acc
] << 32) |
261 (uint64_t)env
->active_tc
.LO
[acc
];
263 temp
= (uint64_t)env
->active_tc
.LO
[acc
];
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
) {
278 set_DSPControl_overflow_flag(1, 16 + acc
, env
);
284 /* a[0] is LO, a[1] is HI. */
285 static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret
,
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])) {
300 if (temp64
!= ((ret
[0] >> 63) & 0x01)) {
302 ret
[0] = (0x01ull
<< 63);
305 ret
[0] = (0x01ull
<< 63) - 1;
308 set_DSPControl_overflow_flag(1, 16 + ac
, env
);
312 static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret
,
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
]) {
326 if (temp64
!= ((ret
[0] >> 63) & 0x01)) {
328 ret
[0] = (0x01ull
<< 63);
331 ret
[0] = (0x01ull
<< 63) - 1;
334 set_DSPControl_overflow_flag(1, 16 + ac
, env
);
338 static inline int32_t mipsdsp_mul_i16_i16(int16_t a
, int16_t b
,
343 temp
= (int32_t)a
* (int32_t)b
;
345 if ((temp
> (int)0x7FFF) || (temp
< (int)0xFFFF8000)) {
346 set_DSPControl_overflow_flag(1, 21, env
);
353 static inline int32_t mipsdsp_mul_u16_u16(int32_t a
, int32_t b
)
358 static inline int32_t mipsdsp_mul_i32_i32(int32_t a
, int32_t b
)
363 static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a
, int16_t b
,
368 temp
= (int32_t)a
* (int32_t)b
;
370 if (temp
> (int)0x7FFF) {
372 set_DSPControl_overflow_flag(1, 21, env
);
373 } else if (temp
< (int)0xffff8000) {
375 set_DSPControl_overflow_flag(1, 21, env
);
382 static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a
, uint16_t b
,
387 if ((a
== 0x8000) && (b
== 0x8000)) {
389 set_DSPControl_overflow_flag(1, 21, env
);
391 temp
= ((int32_t)(int16_t)a
* (int32_t)(int16_t)b
) << 1;
398 static inline uint8_t mipsdsp_rshift_u8(uint8_t a
, target_ulong mov
)
403 static inline uint16_t mipsdsp_rshift_u16(uint16_t a
, target_ulong mov
)
408 static inline int8_t mipsdsp_rashift8(int8_t a
, target_ulong mov
)
413 static inline int16_t mipsdsp_rashift16(int16_t a
, target_ulong mov
)
418 static inline int32_t mipsdsp_rashift32(int32_t a
, target_ulong mov
)
423 static inline int16_t mipsdsp_rshift1_add_q16(int16_t a
, int16_t b
)
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
)
437 temp
= (int32_t)a
+ (int32_t)b
;
440 return (temp
>> 1) & 0xFFFF;
443 static inline int32_t mipsdsp_rshift1_add_q32(int32_t a
, int32_t b
)
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
)
456 temp
= (int64_t)a
+ (int64_t)b
;
459 return (temp
>> 1) & 0xFFFFFFFF;
462 static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a
, uint8_t b
)
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
)
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
)
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
)
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
,
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
,
518 uint64_t tempB
, tempA
;
520 tempB
= env
->active_tc
.HI
[ac
];
521 tempA
= env
->active_tc
.LO
[ac
];
522 shift
= shift
& 0x1F;
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
,
539 int64_t tempB
, tempA
;
541 tempB
= env
->active_tc
.HI
[ac
];
542 tempA
= env
->active_tc
.LO
[ac
];
543 shift
= shift
& 0x3F;
547 p
[1] = (tempB
<< 1) | (tempA
>> 63);
550 p
[0] = (tempB
<< (65 - shift
)) | (tempA
>> (shift
- 1));
551 p
[1] = (int64_t)tempB
>> (shift
- 1);
560 static inline int32_t mipsdsp_mul_q15_q15(int32_t ac
, uint16_t a
, uint16_t b
,
565 if ((a
== 0x8000) && (b
== 0x8000)) {
567 set_DSPControl_overflow_flag(1, 16 + ac
, env
);
569 temp
= ((int16_t)a
* (int16_t)b
) << 1;
575 static inline int64_t mipsdsp_mul_q31_q31(int32_t ac
, uint32_t a
, uint32_t b
,
580 if ((a
== 0x80000000) && (b
== 0x80000000)) {
581 temp
= (0x01ull
<< 63) - 1;
582 set_DSPControl_overflow_flag(1, 16 + ac
, env
);
584 temp
= ((uint64_t)a
* (uint64_t)b
) << 1;
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
,
600 tempI
= (uint32_t)a
* (uint32_t)b
;
601 if (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
,
619 if ((a
== 0x8000) && (b
== 0x8000)) {
621 set_DSPControl_overflow_flag(1, 21, env
);
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
,
635 if ((a
== 0x8000) && (b
== 0x8000)) {
637 set_DSPControl_overflow_flag(1, 21, env
);
639 temp
= (int16_t)a
* (int16_t)b
;
643 return (temp
>> 16) & 0x0000FFFF;
646 static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a
,
651 temp
= (int32_t)a
+ 0x00008000;
653 if (a
> (int)0x7fff8000) {
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
,
667 sign
= (a
>> 15) & 0x01;
672 set_DSPControl_overflow_flag(1, 22, env
);
675 return (mag
>> 7) & 0xFFFF;
678 set_DSPControl_overflow_flag(1, 22, env
);
683 static inline uint8_t mipsdsp_lshift8(uint8_t a
, uint8_t s
, CPUMIPSState
*env
)
688 discard
= a
>> (8 - s
);
690 if (discard
!= 0x00) {
691 set_DSPControl_overflow_flag(1, 22, env
);
697 static inline uint16_t mipsdsp_lshift16(uint16_t a
, uint8_t s
,
703 discard
= (int16_t)a
>> (15 - s
);
705 if ((discard
!= 0x0000) && (discard
!= 0xFFFF)) {
706 set_DSPControl_overflow_flag(1, 22, env
);
713 static inline uint32_t mipsdsp_lshift32(uint32_t a
, uint8_t s
,
721 discard
= (int32_t)a
>> (31 - (s
- 1));
723 if ((discard
!= 0x00000000) && (discard
!= 0xFFFFFFFF)) {
724 set_DSPControl_overflow_flag(1, 22, env
);
730 static inline uint16_t mipsdsp_sat16_lshift(uint16_t a
, uint8_t s
,
739 sign
= (a
>> 15) & 0x01;
741 discard
= (((0x01 << (16 - s
)) - 1) << s
) |
742 ((a
>> (14 - (s
- 1))) & ((0x01 << s
) - 1));
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;
756 static inline uint32_t mipsdsp_sat32_lshift(uint32_t a
, uint8_t s
,
765 sign
= (a
>> 31) & 0x01;
767 discard
= (((0x01 << (32 - s
)) - 1) << s
) |
768 ((a
>> (30 - (s
- 1))) & ((0x01 << s
) - 1));
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;
782 static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a
, uint8_t s
)
787 temp
= (uint32_t)a
<< 1;
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
)
800 temp
= (uint32_t)a
<< 1;
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
)
813 temp
= (uint64_t)a
<< 1;
815 temp
= (int64_t)(int32_t)a
>> (s
- 1);
819 return (temp
>> 1) & 0xFFFFFFFFull
;
822 static inline uint16_t mipsdsp_sub_i16(int16_t a
, int16_t b
, CPUMIPSState
*env
)
827 if (MIPSDSP_OVERFLOW_SUB(a
, b
, temp
, 0x8000)) {
828 set_DSPControl_overflow_flag(1, 20, env
);
834 static inline uint16_t mipsdsp_sat16_sub(int16_t a
, int16_t b
,
840 if (MIPSDSP_OVERFLOW_SUB(a
, b
, temp
, 0x8000)) {
846 set_DSPControl_overflow_flag(1, 20, env
);
852 static inline uint32_t mipsdsp_sat32_sub(int32_t a
, int32_t b
,
858 if (MIPSDSP_OVERFLOW_SUB(a
, b
, 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
)
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
)
883 temp
= (int32_t)a
- (int32_t)b
;
886 return (temp
>> 1) & 0x0000FFFF;
889 static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a
, int32_t b
)
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
)
902 temp
= (int64_t)a
- (int64_t)b
;
905 return (temp
>> 1) & 0xFFFFFFFFull
;
908 static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a
, uint16_t b
,
914 temp
= (uint32_t)a
- (uint32_t)b
;
915 temp16
= (temp
>> 16) & 0x01;
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
,
928 temp
= (uint32_t)a
- (uint32_t)b
;
929 temp16
= (temp
>> 16) & 0x01;
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
)
944 temp
= (uint16_t)a
- (uint16_t)b
;
945 temp8
= (temp
>> 8) & 0x01;
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
)
958 temp
= (uint16_t)a
- (uint16_t)b
;
959 temp8
= (temp
>> 8) & 0x01;
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
)
973 if (MIPSDSP_OVERFLOW_SUB(a
, b
, temp
, 0x80000000)) {
974 set_DSPControl_overflow_flag(1, 20, env
);
980 static inline int32_t mipsdsp_add_i32(int32_t a
, int32_t b
, CPUMIPSState
*env
)
986 if (MIPSDSP_OVERFLOW_ADD(a
, b
, temp
, 0x80000000)) {
987 set_DSPControl_overflow_flag(1, 20, env
);
993 static inline int32_t mipsdsp_cmp_eq(int32_t a
, int32_t b
)
998 static inline int32_t mipsdsp_cmp_le(int32_t a
, int32_t b
)
1003 static inline int32_t mipsdsp_cmp_lt(int32_t a
, int32_t b
)
1008 static inline int32_t mipsdsp_cmpu_eq(uint32_t a
, uint32_t b
)
1013 static inline int32_t mipsdsp_cmpu_le(uint32_t a
, uint32_t b
)
1018 static inline int32_t mipsdsp_cmpu_lt(uint32_t a
, uint32_t 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) \
1035 a = (num >> 24) & MIPSDSP_Q0; \
1036 b = (num >> 16) & MIPSDSP_Q0; \
1037 c = (num >> 8) & MIPSDSP_Q0; \
1038 d = num & MIPSDSP_Q0; \
1041 #define MIPSDSP_SPLIT32_16(num, a, b) \
1043 a = (num >> 16) & MIPSDSP_LO; \
1044 b = num & MIPSDSP_LO; \
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) \
1059 a = (num >> 48) & MIPSDSP_LO; \
1060 b = (num >> 32) & MIPSDSP_LO; \
1061 c = (num >> 16) & MIPSDSP_LO; \
1062 d = num & MIPSDSP_LO; \
1065 #define MIPSDSP_SPLIT64_32(num, a, b) \
1067 a = (num >> 32) & MIPSDSP_LLO; \
1068 b = num & MIPSDSP_LLO; \
1071 #define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)a << 48) | \
1072 ((uint64_t)b << 32) | \
1073 ((uint64_t)c << 16) | \
1075 #define MIPSDSP_RETURN64_32(a, b) (((uint64_t)a << 32) | (uint64_t)b)
1078 /** DSP Arithmetic Sub-class insns **/
1079 #define MIPSDSP32_UNOP_ENV(name, func, element) \
1080 target_ulong helper_##name(target_ulong rt, CPUMIPSState *env) \
1083 unsigned int i, n; \
1085 n = sizeof(DSP32Value) / sizeof(dt.element[0]); \
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) \
1104 unsigned int i, n; \
1106 n = sizeof(DSP64Value) / sizeof(dt.element[0]); \
1109 for (i = 0; i < n; i++) { \
1110 dt.element[i] = mipsdsp_##func(dt.element[i], env); \
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
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]); \
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]); \
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]); \
1193 for (i = 0 ; i < n ; i++) { \
1194 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]); \
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]); \
1216 for (i = 0 ; i < n ; i++) { \
1217 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
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
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); \
1262 SUBUH_QB(subuh_r
, 1);
1266 target_ulong
helper_addsc(target_ulong rs
, target_ulong rt
, CPUMIPSState
*env
)
1268 uint64_t temp
, tempRs
, tempRt
;
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
)
1284 int32_t temp32
, temp31
;
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
)
1307 decr
= rt
& MIPSDSP_Q0
;
1308 lastindex
= (rt
>> 8) & MIPSDSP_LO
;
1310 if ((rs
& MIPSDSP_LLO
) == 0x00000000) {
1311 rd
= (target_ulong
)lastindex
;
1319 target_ulong
helper_raddu_w_qb(target_ulong rs
)
1321 target_ulong ret
= 0;
1326 for (i
= 0; i
< 4; i
++) {
1332 #if defined(TARGET_MIPS64)
1333 target_ulong
helper_raddu_l_ob(target_ulong rs
)
1335 target_ulong ret
= 0;
1340 for (i
= 0; i
< 8; i
++) {
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);
1365 target_ulong
helper_precr_sra_ph_w(uint32_t sa
, target_ulong rs
,
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. */
1383 tempB
= (rt
& MIPSDSP_LO
) << 1;
1384 tempA
= (rs
& MIPSDSP_LO
) << 1;
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
,
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
;
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
;
1439 #define PRECR_QH_PW(name, var) \
1440 target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \
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. */ \
1453 tempD = rt2 << var; \
1454 tempC = rt0 << var; \
1455 tempB = rs2 << var; \
1456 tempA = rs0 << var; \
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);
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
;
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
;
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
,
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
);
1538 target_ulong
helper_precrqu_s_qb_ph(target_ulong rs
, target_ulong rt
,
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
,
1562 uint16_t rs3
, rs2
, rs1
, rs0
;
1563 uint16_t rt3
, rt2
, rt1
, rt0
;
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
);
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);
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);
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);
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);
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);
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; \
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; \
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
);
1747 #if defined(TARGET_MIPS64)
1748 #define SHIFT_OB(name, func) \
1749 target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \
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); \
1767 #define SHIFT_OB_ENV(name, func) \
1768 target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \
1769 CPUMIPSState *env) \
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); \
1787 SHIFT_OB_ENV(shll
, lshift8
);
1788 SHIFT_OB(shrl
, rshift_u8
);
1790 SHIFT_OB(shra
, rashift8
);
1791 SHIFT_OB(shra_r
, rnd8_rashift
);
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; \
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
);
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; \
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; \
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
);
1867 #define SHIFT_W(name, func) \
1868 target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \
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) \
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
);
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; \
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; \
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
);
1937 #define SHIFT_PH(name, func) \
1938 target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \
1940 uint16_t rth, rtl; \
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
);
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
, \
1984 MUL_RETURN32_16_PH(muleu_s_ph_qbr
, mul_u8_u16
, \
1987 MUL_RETURN32_16_PH(mulq_rs_ph
, rndq15_mul_q15_q15
, \
1988 16, 0, MIPSDSP_LO
, \
1990 MUL_RETURN32_16_PH(mul_ph
, mul_i16_i16
, \
1991 16, 0, MIPSDSP_LO
, \
1993 MUL_RETURN32_16_PH(mul_s_ph
, sat16_mul_i16_i16
, \
1994 16, 0, MIPSDSP_LO
, \
1996 MUL_RETURN32_16_PH(mulq_s_ph
, sat16_mul_q15_q15
, \
1997 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) \
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); \
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);
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, \
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
,
2123 int16_t rs3
, rs2
, rs1
, rs0
;
2124 int16_t rt3
, rt2
, rt1
, rt0
;
2125 int32_t tempD
, tempC
, tempB
, tempA
;
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) {
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])) {
2158 env
->active_tc
.HI
[ac
] = acc
[1];
2159 env
->active_tc
.LO
[ac
] = acc
[0];
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) \
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; \
2180 tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \
2181 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \
2184 tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \
2185 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \
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);
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; \
2213 uint64_t temp_sum; \
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]; \
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])) { \
2244 temp[0] = temp_sum; \
2245 temp[1] = acc[1] + temp[1]; \
2247 temp_sum = acc[0] - temp[0]; \
2248 if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \
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);
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; \
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); \
2287 acc = acc + ((int64_t)tempB + (int64_t)tempA); \
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);
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); \
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); \
2359 tempC = acc + dotp; \
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; \
2399 MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \
2400 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
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); \
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) { \
2423 acc[1] = env->active_tc.HI[ac]; \
2424 acc[0] = env->active_tc.LO[ac]; \
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]; \
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);
2456 #define DP_L_W(name, is_add) \
2457 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2458 CPUMIPSState *env) \
2461 int64_t dotp, acc; \
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); \
2469 temp = acc + dotp; \
2470 overflow = MIPSDSP_OVERFLOW_ADD((uint64_t)acc, (uint64_t)dotp, \
2471 temp, (0x01ull << 63)); \
2473 temp = acc - dotp; \
2474 overflow = MIPSDSP_OVERFLOW_SUB((uint64_t)acc, (uint64_t)dotp, \
2475 temp, (0x01ull << 63)); \
2479 temp63 = (temp >> 63) & 0x01; \
2480 if (temp63 == 1) { \
2481 temp = (0x01ull << 63) - 1; \
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);
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) \
2507 int64_t tempB[2], tempA[2]; \
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) { \
2527 if (tempA[0] >= 0) { \
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])) { \
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
);
2552 void helper_mulsaq_s_l_pw(target_ulong rs
, target_ulong rt
, uint32_t ac
,
2557 int64_t tempB
[2], tempA
[2];
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) {
2576 if (tempA
[0] >= 0) {
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]) {
2590 temp
[1] = tempB
[1] - tempA
[1];
2592 if ((temp
[1] & 0x01) == 0) {
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])) {
2606 env
->active_tc
.HI
[ac
] = acc
[1];
2607 env
->active_tc
.LO
[ac
] = acc
[0];
2611 #define MAQ_S_W(name, mov) \
2612 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2613 CPUMIPSState *env) \
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);
2636 #define MAQ_SA_W(name, mov) \
2637 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2638 CPUMIPSState *env) \
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 & \
2654 MAQ_SA_W(maq_sa_w_phl
, 16);
2655 MAQ_SA_W(maq_sa_w_phr
, 0);
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; \
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); \
2674 tempL = ((int64_t)rs_t * (int64_t)rt_t) << 1; \
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
);
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; \
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) { \
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])) { \
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);
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; \
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) { \
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);
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; \
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) { \
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])) { \
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);
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) \
2814 int64_t tempBL[2], tempAL[2]; \
2822 MIPSDSP_SPLIT64_32(rs, rs1, rs0); \
2823 MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
2826 tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1); \
2827 tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0); \
2829 if (tempBL[0] >= 0) { \
2832 tempBL[1] = ~0ull; \
2835 if (tempAL[0] >= 0) { \
2838 tempAL[1] = ~0ull; \
2841 tempBL[0] = mipsdsp_##func(rs1, rt1); \
2842 tempAL[0] = mipsdsp_##func(rs0, rt0); \
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])) { \
2855 temp[0] = temp_sum; \
2856 temp[1] += tempBL[1] + tempAL[1]; \
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])) { \
2864 temp[0] = temp_sum; \
2865 temp[1] = acc[1] + temp[1]; \
2867 temp_sum = acc[0] - temp[0]; \
2868 if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \
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);
2886 /** DSP Bit/Manipulation Sub-class insns **/
2887 target_ulong
helper_bitrev(target_ulong rt
)
2893 temp
= rt
& MIPSDSP_LO
;
2895 for (i
= 0; i
< 16; i
++) {
2896 rd
= (rd
<< 1) | (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, \
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; \
2920 if (lsb > msb || (msb > TARGET_LONG_BITS)) { \
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
);
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; \
2947 uint32_t temp = 0; \
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); \
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);
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; \
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); \
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);
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) \
3023 uint8_t rs_t, rt_t; \
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; \
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; \
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); \
3069 result = (target_long)(int32_t)(result & MIPSDSP_LLO); \
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);
3085 target_ulong
helper_packrl_ph(target_ulong rs
, target_ulong rt
)
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
)
3100 rs0
= rs
& MIPSDSP_LLO
;
3101 rt1
= (rt
>> 32) & MIPSDSP_LLO
;
3103 return ((uint64_t)rs0
<< 32) | (uint64_t)rt1
;
3107 /** DSP Accumulator and DSPControl Access Sub-class insns **/
3108 target_ulong
helper_extr_w(target_ulong ac
, target_ulong shift
,
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
;
3125 if (tempDL
[0] == 0) {
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
,
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
);
3151 if (tempDL
[0] == 0) {
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
,
3166 int32_t tempI
, temp64
;
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
);
3177 if (tempDL
[0] == 0) {
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;
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
,
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
,
3215 shift
= shift
& 0x3F;
3216 mipsdsp_rndrashift_acc(temp
, ac
, shift
, env
);
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
,
3242 shift
= shift
& 0x3F;
3243 mipsdsp_rndrashift_acc(temp
, ac
, shift
, env
);
3253 temp128
= temp
[2] & 0x01;
3255 if ((temp128
!= 0 || temp
[1] != 0) &&
3256 (temp128
!= 1 || temp
[1] != ~0ull)) {
3258 temp
[0] = 0x0FFFFFFFF;
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
,
3272 target_ulong result
;
3274 shift
= shift
& 0x3F;
3276 mipsdsp_rndrashift_acc(temp
, ac
, shift
, env
);
3277 result
= (temp
[1] << 63) | (temp
[0] >> 1);
3282 target_ulong
helper_dextr_r_l(target_ulong ac
, target_ulong shift
,
3287 target_ulong result
;
3289 shift
= shift
& 0x3F;
3290 mipsdsp_rndrashift_acc(temp
, ac
, shift
, env
);
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);
3312 target_ulong
helper_dextr_rs_l(target_ulong ac
, target_ulong shift
,
3317 target_ulong result
;
3319 shift
= shift
& 0x3F;
3320 mipsdsp_rndrashift_acc(temp
, ac
, shift
, env
);
3330 temp128
= temp
[2] & 0x01;
3332 if ((temp128
!= 0 || temp
[1] != 0) &&
3333 (temp128
!= 1 || temp
[1] != ~0ull)) {
3335 temp
[1] &= ~0x00ull
- 1;
3336 temp
[0] |= ~0x00ull
- 1;
3341 set_DSPControl_overflow_flag(1, 23, env
);
3343 result
= (temp
[1] << 63) | (temp
[0] >> 1);
3349 target_ulong
helper_extr_s_h(target_ulong ac
, target_ulong shift
,
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) {
3363 set_DSPControl_overflow_flag(1, 23, env
);
3364 } else if (temp
< (int64_t)0xFFFFFFFFFFFF8000ULL
) {
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
,
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
);
3403 target_ulong
helper_extp(target_ulong ac
, target_ulong size
, CPUMIPSState
*env
)
3413 start_pos
= get_DSPControl_pos(env
);
3414 sub
= start_pos
- (size
+ 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
);
3422 set_DSPControl_efi(1, env
);
3425 return (target_ulong
)temp
;
3428 target_ulong
helper_extpdp(target_ulong ac
, target_ulong size
,
3438 start_pos
= get_DSPControl_pos(env
);
3439 sub
= start_pos
- (size
+ 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
);
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
)
3462 uint64_t tempB
, tempA
;
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);
3476 temp
= (tempB
<< (64 - len
)) | (tempA
>> len
);
3477 temp
= temp
& ((0x01 << (size
+ 1)) - 1);
3478 set_DSPControl_efi(0, env
);
3480 set_DSPControl_efi(1, env
);
3486 target_ulong
helper_dextpdp(target_ulong ac
, target_ulong size
,
3492 uint64_t tempB
, tempA
;
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);
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
);
3510 set_DSPControl_efi(1, env
);
3518 void helper_shilo(target_ulong ac
, target_ulong rs
, CPUMIPSState
*env
)
3524 rs5_0
= (int8_t)(rs5_0
<< 2) >> 2;
3526 if (unlikely(rs5_0
== 0)) {
3530 acc
= (((uint64_t)env
->active_tc
.HI
[ac
] << 32) & MIPSDSP_LHI
) |
3531 ((uint64_t)env
->active_tc
.LO
[ac
] & MIPSDSP_LLO
);
3534 temp
= acc
>> rs5_0
;
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
)
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
];
3556 tempA
= (tempB
<< (64 - shift_t
)) | (tempA
>> shift_t
);
3557 tempB
= tempB
>> 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
;
3570 void helper_mthlip(target_ulong ac
, target_ulong rs
, CPUMIPSState
*env
)
3572 int32_t tempA
, tempB
, pos
;
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
);
3583 set_DSPControl_pos(pos
+ 32, env
);
3587 #if defined(TARGET_MIPS64)
3588 void helper_dmthlip(target_ulong rs
, target_ulong ac
, CPUMIPSState
*env
)
3592 uint64_t tempB
, tempA
;
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
);
3606 set_DSPControl_pos(pos
, env
);
3611 void cpu_wrdsp(uint32_t rs
, uint32_t mask_num
, CPUMIPSState
*env
)
3615 uint32_t newbits
, overwrite
;
3619 overwrite
= 0xFFFFFFFF;
3620 dsp
= env
->active_tc
.DSPControl
;
3622 for (i
= 0; i
< 6; i
++) {
3623 mask
[i
] = (mask_num
>> i
) & 0x01;
3627 #if defined(TARGET_MIPS64)
3628 overwrite
&= 0xFFFFFF80;
3629 newbits
&= 0xFFFFFF80;
3630 newbits
|= 0x0000007F & rs
;
3632 overwrite
&= 0xFFFFFFC0;
3633 newbits
&= 0xFFFFFFC0;
3634 newbits
|= 0x0000003F & rs
;
3639 overwrite
&= 0xFFFFE07F;
3640 newbits
&= 0xFFFFE07F;
3641 newbits
|= 0x00001F80 & rs
;
3645 overwrite
&= 0xFFFFDFFF;
3646 newbits
&= 0xFFFFDFFF;
3647 newbits
|= 0x00002000 & rs
;
3651 overwrite
&= 0xFF00FFFF;
3652 newbits
&= 0xFF00FFFF;
3653 newbits
|= 0x00FF0000 & rs
;
3657 overwrite
&= 0x00FFFFFF;
3658 newbits
&= 0x00FFFFFF;
3659 #if defined(TARGET_MIPS64)
3660 newbits
|= 0xFF000000 & rs
;
3662 newbits
|= 0x0F000000 & rs
;
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
)
3690 for (i
= 0; i
< 6; i
++) {
3691 mask
[i
] = (mask_num
& ruler
) >> i
;
3696 dsp
= env
->active_tc
.DSPControl
;
3699 #if defined(TARGET_MIPS64)
3707 temp
|= dsp
& 0x1F80;
3711 temp
|= dsp
& 0x2000;
3715 temp
|= dsp
& 0x00FF0000;
3719 #if defined(TARGET_MIPS64)
3720 temp
|= dsp
& 0xFF000000;
3722 temp
|= dsp
& 0x0F000000;
3727 temp
|= dsp
& 0x4000;
3733 target_ulong
helper_rddsp(target_ulong mask_num
, CPUMIPSState
*env
)
3735 return cpu_rddsp(mask_num
, env
);
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