]> git.proxmox.com Git - qemu.git/blob - target-mips/dsp_helper.c
9212789b4e27fd2af6e8f99c3886f11b3667885b
[qemu.git] / target-mips / dsp_helper.c
1 /*
2 * MIPS ASE DSP Instruction emulation helpers for QEMU.
3 *
4 * Copyright (c) 2012 Jia Liu <proljc@gmail.com>
5 * Dongxue Zhang <elta.era@gmail.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "cpu.h"
21 #include "helper.h"
22
23 /* 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;
33
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;
44
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)
49
50 static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
51 CPUMIPSState *env)
52 {
53 env->active_tc.DSPControl |= (target_ulong)flag << position;
54 }
55
56 static inline void set_DSPControl_carryflag(uint32_t flag, CPUMIPSState *env)
57 {
58 env->active_tc.DSPControl |= (target_ulong)flag << 13;
59 }
60
61 static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
62 {
63 return (env->active_tc.DSPControl >> 13) & 0x01;
64 }
65
66 static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env)
67 {
68 uint32_t filter;
69
70 filter = ((0x01 << len) - 1) << 24;
71 filter = ~filter;
72
73 env->active_tc.DSPControl &= filter;
74 env->active_tc.DSPControl |= (target_ulong)flag << 24;
75 }
76
77 static inline uint32_t get_DSPControl_24(int len, CPUMIPSState *env)
78 {
79 uint32_t filter;
80
81 filter = (0x01 << len) - 1;
82
83 return (env->active_tc.DSPControl >> 24) & filter;
84 }
85
86 static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env)
87 {
88 target_ulong dspc;
89
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;
99 }
100
101 static inline uint32_t get_DSPControl_pos(CPUMIPSState *env)
102 {
103 target_ulong dspc;
104 uint32_t pos;
105
106 dspc = env->active_tc.DSPControl;
107
108 #ifndef TARGET_MIPS64
109 pos = dspc & 0x3F;
110 #else
111 pos = dspc & 0x7F;
112 #endif
113
114 return pos;
115 }
116
117 static inline void set_DSPControl_efi(uint32_t flag, CPUMIPSState *env)
118 {
119 env->active_tc.DSPControl &= 0xFFFFBFFF;
120 env->active_tc.DSPControl |= (target_ulong)flag << 14;
121 }
122
123 #define DO_MIPS_SAT_ABS(size) \
124 static inline int##size##_t mipsdsp_sat_abs##size(int##size##_t a, \
125 CPUMIPSState *env) \
126 { \
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); \
132 } \
133 }
134 DO_MIPS_SAT_ABS(8)
135 DO_MIPS_SAT_ABS(16)
136 DO_MIPS_SAT_ABS(32)
137 #undef DO_MIPS_SAT_ABS
138
139 /* get sum value */
140 static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env)
141 {
142 int16_t tempI;
143
144 tempI = a + b;
145
146 if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x8000)) {
147 set_DSPControl_overflow_flag(1, 20, env);
148 }
149
150 return tempI;
151 }
152
153 static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b,
154 CPUMIPSState *env)
155 {
156 int16_t tempS;
157
158 tempS = a + b;
159
160 if (MIPSDSP_OVERFLOW_ADD(a, b, tempS, 0x8000)) {
161 if (a > 0) {
162 tempS = 0x7FFF;
163 } else {
164 tempS = 0x8000;
165 }
166 set_DSPControl_overflow_flag(1, 20, env);
167 }
168
169 return tempS;
170 }
171
172 static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b,
173 CPUMIPSState *env)
174 {
175 int32_t tempI;
176
177 tempI = a + b;
178
179 if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x80000000)) {
180 if (a > 0) {
181 tempI = 0x7FFFFFFF;
182 } else {
183 tempI = 0x80000000;
184 }
185 set_DSPControl_overflow_flag(1, 20, env);
186 }
187
188 return tempI;
189 }
190
191 static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
192 {
193 uint16_t temp;
194
195 temp = (uint16_t)a + (uint16_t)b;
196
197 if (temp & 0x0100) {
198 set_DSPControl_overflow_flag(1, 20, env);
199 }
200
201 return temp & 0xFF;
202 }
203
204 static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b,
205 CPUMIPSState *env)
206 {
207 uint32_t temp;
208
209 temp = (uint32_t)a + (uint32_t)b;
210
211 if (temp & 0x00010000) {
212 set_DSPControl_overflow_flag(1, 20, env);
213 }
214
215 return temp & 0xFFFF;
216 }
217
218 static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b,
219 CPUMIPSState *env)
220 {
221 uint8_t result;
222 uint16_t temp;
223
224 temp = (uint16_t)a + (uint16_t)b;
225 result = temp & 0xFF;
226
227 if (0x0100 & temp) {
228 result = 0xFF;
229 set_DSPControl_overflow_flag(1, 20, env);
230 }
231
232 return result;
233 }
234
235 static inline uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b,
236 CPUMIPSState *env)
237 {
238 uint16_t result;
239 uint32_t temp;
240
241 temp = (uint32_t)a + (uint32_t)b;
242 result = temp & 0xFFFF;
243
244 if (0x00010000 & temp) {
245 result = 0xFFFF;
246 set_DSPControl_overflow_flag(1, 20, env);
247 }
248
249 return result;
250 }
251
252 static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a,
253 CPUMIPSState *env)
254 {
255 int64_t temp;
256 int32_t temp32, temp31, result;
257 int64_t temp_sum;
258
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
265
266 temp_sum = (int64_t)a + temp;
267
268 temp32 = (temp_sum >> 32) & 0x01;
269 temp31 = (temp_sum >> 31) & 0x01;
270 result = temp_sum & 0xFFFFFFFF;
271
272 if (temp32 != temp31) {
273 if (temp32 == 0) {
274 result = 0x7FFFFFFF;
275 } else {
276 result = 0x80000000;
277 }
278 set_DSPControl_overflow_flag(1, 16 + acc, env);
279 }
280
281 return result;
282 }
283
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)
289 {
290 bool temp64;
291
292 ret[0] = env->active_tc.LO[ac] + a[0];
293 ret[1] = env->active_tc.HI[ac] + a[1];
294
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;
298 }
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;
307 }
308 set_DSPControl_overflow_flag(1, 16 + ac, env);
309 }
310 }
311
312 static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
313 int32_t ac,
314 int64_t *a,
315 CPUMIPSState *env)
316 {
317 bool temp64;
318
319 ret[0] = env->active_tc.LO[ac] - a[0];
320 ret[1] = env->active_tc.HI[ac] - a[1];
321
322 if ((uint64_t)ret[0] > (uint64_t)env->active_tc.LO[ac]) {
323 ret[1] -= 1;
324 }
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;
333 }
334 set_DSPControl_overflow_flag(1, 16 + ac, env);
335 }
336 }
337
338 static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b,
339 CPUMIPSState *env)
340 {
341 int32_t temp;
342
343 temp = (int32_t)a * (int32_t)b;
344
345 if ((temp > (int)0x7FFF) || (temp < (int)0xFFFF8000)) {
346 set_DSPControl_overflow_flag(1, 21, env);
347 }
348 temp &= 0x0000FFFF;
349
350 return temp;
351 }
352
353 static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b)
354 {
355 return a * b;
356 }
357
358 static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b)
359 {
360 return a * b;
361 }
362
363 static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b,
364 CPUMIPSState *env)
365 {
366 int32_t temp;
367
368 temp = (int32_t)a * (int32_t)b;
369
370 if (temp > (int)0x7FFF) {
371 temp = 0x00007FFF;
372 set_DSPControl_overflow_flag(1, 21, env);
373 } else if (temp < (int)0xffff8000) {
374 temp = 0xFFFF8000;
375 set_DSPControl_overflow_flag(1, 21, env);
376 }
377 temp &= 0x0000FFFF;
378
379 return temp;
380 }
381
382 static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b,
383 CPUMIPSState *env)
384 {
385 int32_t temp;
386
387 if ((a == 0x8000) && (b == 0x8000)) {
388 temp = 0x7FFFFFFF;
389 set_DSPControl_overflow_flag(1, 21, env);
390 } else {
391 temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1;
392 }
393
394 return temp;
395 }
396
397 /* right shift */
398 static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov)
399 {
400 return a >> mov;
401 }
402
403 static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov)
404 {
405 return a >> mov;
406 }
407
408 static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov)
409 {
410 return a >> mov;
411 }
412
413 static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov)
414 {
415 return a >> mov;
416 }
417
418 static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov)
419 {
420 return a >> mov;
421 }
422
423 static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
424 {
425 int32_t temp;
426
427 temp = (int32_t)a + (int32_t)b;
428
429 return (temp >> 1) & 0xFFFF;
430 }
431
432 /* round right shift */
433 static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b)
434 {
435 int32_t temp;
436
437 temp = (int32_t)a + (int32_t)b;
438 temp += 1;
439
440 return (temp >> 1) & 0xFFFF;
441 }
442
443 static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b)
444 {
445 int64_t temp;
446
447 temp = (int64_t)a + (int64_t)b;
448
449 return (temp >> 1) & 0xFFFFFFFF;
450 }
451
452 static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b)
453 {
454 int64_t temp;
455
456 temp = (int64_t)a + (int64_t)b;
457 temp += 1;
458
459 return (temp >> 1) & 0xFFFFFFFF;
460 }
461
462 static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b)
463 {
464 uint16_t temp;
465
466 temp = (uint16_t)a + (uint16_t)b;
467
468 return (temp >> 1) & 0x00FF;
469 }
470
471 static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b)
472 {
473 uint16_t temp;
474
475 temp = (uint16_t)a + (uint16_t)b + 1;
476
477 return (temp >> 1) & 0x00FF;
478 }
479
480 static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b)
481 {
482 uint16_t temp;
483
484 temp = (uint16_t)a - (uint16_t)b;
485
486 return (temp >> 1) & 0x00FF;
487 }
488
489 static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b)
490 {
491 uint16_t temp;
492
493 temp = (uint16_t)a - (uint16_t)b + 1;
494
495 return (temp >> 1) & 0x00FF;
496 }
497
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)
503 {
504 int64_t acc;
505
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;
510 }
511
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)
517 {
518 uint64_t tempB, tempA;
519
520 tempB = env->active_tc.HI[ac];
521 tempA = env->active_tc.LO[ac];
522 shift = shift & 0x1F;
523
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;
530 }
531 }
532
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)
538 {
539 int64_t tempB, tempA;
540
541 tempB = env->active_tc.HI[ac];
542 tempA = env->active_tc.LO[ac];
543 shift = shift & 0x3F;
544
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;
556 }
557 }
558 }
559
560 static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b,
561 CPUMIPSState *env)
562 {
563 int32_t temp;
564
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;
570 }
571
572 return temp;
573 }
574
575 static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b,
576 CPUMIPSState *env)
577 {
578 uint64_t temp;
579
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;
585 }
586
587 return temp;
588 }
589
590 static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b)
591 {
592 return (uint16_t)a * (uint16_t)b;
593 }
594
595 static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b,
596 CPUMIPSState *env)
597 {
598 uint32_t tempI;
599
600 tempI = (uint32_t)a * (uint32_t)b;
601 if (tempI > 0x0000FFFF) {
602 tempI = 0x0000FFFF;
603 set_DSPControl_overflow_flag(1, 21, env);
604 }
605
606 return tempI & 0x0000FFFF;
607 }
608
609 static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b)
610 {
611 return (uint64_t)a * (uint64_t)b;
612 }
613
614 static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b,
615 CPUMIPSState *env)
616 {
617 uint32_t temp;
618
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;
625 }
626
627 return (temp & 0xFFFF0000) >> 16;
628 }
629
630 static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b,
631 CPUMIPSState *env)
632 {
633 int32_t temp;
634
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;
641 }
642
643 return (temp >> 16) & 0x0000FFFF;
644 }
645
646 static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a,
647 CPUMIPSState *env)
648 {
649 int64_t temp;
650
651 temp = (int32_t)a + 0x00008000;
652
653 if (a > (int)0x7fff8000) {
654 temp = 0x7FFFFFFF;
655 set_DSPControl_overflow_flag(1, 22, env);
656 }
657
658 return (temp >> 16) & 0xFFFF;
659 }
660
661 static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
662 CPUMIPSState *env)
663 {
664 uint16_t mag;
665 uint32_t sign;
666
667 sign = (a >> 15) & 0x01;
668 mag = a & 0x7FFF;
669
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;
676 }
677 } else {
678 set_DSPControl_overflow_flag(1, 22, env);
679 return 0x00;
680 }
681 }
682
683 static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env)
684 {
685 uint8_t discard;
686
687 if (s != 0) {
688 discard = a >> (8 - s);
689
690 if (discard != 0x00) {
691 set_DSPControl_overflow_flag(1, 22, env);
692 }
693 }
694 return a << s;
695 }
696
697 static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
698 CPUMIPSState *env)
699 {
700 uint16_t discard;
701
702 if (s != 0) {
703 discard = (int16_t)a >> (15 - s);
704
705 if ((discard != 0x0000) && (discard != 0xFFFF)) {
706 set_DSPControl_overflow_flag(1, 22, env);
707 }
708 }
709 return a << s;
710 }
711
712
713 static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s,
714 CPUMIPSState *env)
715 {
716 uint32_t discard;
717
718 if (s == 0) {
719 return a;
720 } else {
721 discard = (int32_t)a >> (31 - (s - 1));
722
723 if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
724 set_DSPControl_overflow_flag(1, 22, env);
725 }
726 return a << s;
727 }
728 }
729
730 static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s,
731 CPUMIPSState *env)
732 {
733 uint8_t sign;
734 uint16_t discard;
735
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));
745 }
746
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;
752 }
753 }
754 }
755
756 static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s,
757 CPUMIPSState *env)
758 {
759 uint8_t sign;
760 uint32_t discard;
761
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));
771 }
772
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;
778 }
779 }
780 }
781
782 static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a, uint8_t s)
783 {
784 uint32_t temp;
785
786 if (s == 0) {
787 temp = (uint32_t)a << 1;
788 } else {
789 temp = (int32_t)(int8_t)a >> (s - 1);
790 }
791
792 return (temp + 1) >> 1;
793 }
794
795 static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s)
796 {
797 uint32_t temp;
798
799 if (s == 0) {
800 temp = (uint32_t)a << 1;
801 } else {
802 temp = (int32_t)(int16_t)a >> (s - 1);
803 }
804
805 return (temp + 1) >> 1;
806 }
807
808 static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s)
809 {
810 int64_t temp;
811
812 if (s == 0) {
813 temp = (uint64_t)a << 1;
814 } else {
815 temp = (int64_t)(int32_t)a >> (s - 1);
816 }
817 temp += 1;
818
819 return (temp >> 1) & 0xFFFFFFFFull;
820 }
821
822 static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env)
823 {
824 int16_t temp;
825
826 temp = a - b;
827 if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) {
828 set_DSPControl_overflow_flag(1, 20, env);
829 }
830
831 return temp;
832 }
833
834 static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b,
835 CPUMIPSState *env)
836 {
837 int16_t temp;
838
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;
845 }
846 set_DSPControl_overflow_flag(1, 20, env);
847 }
848
849 return temp;
850 }
851
852 static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b,
853 CPUMIPSState *env)
854 {
855 int32_t temp;
856
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;
863 }
864 set_DSPControl_overflow_flag(1, 20, env);
865 }
866
867 return temp & 0xFFFFFFFFull;
868 }
869
870 static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b)
871 {
872 int32_t temp;
873
874 temp = (int32_t)a - (int32_t)b;
875
876 return (temp >> 1) & 0x0000FFFF;
877 }
878
879 static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b)
880 {
881 int32_t temp;
882
883 temp = (int32_t)a - (int32_t)b;
884 temp += 1;
885
886 return (temp >> 1) & 0x0000FFFF;
887 }
888
889 static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b)
890 {
891 int64_t temp;
892
893 temp = (int64_t)a - (int64_t)b;
894
895 return (temp >> 1) & 0xFFFFFFFFull;
896 }
897
898 static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b)
899 {
900 int64_t temp;
901
902 temp = (int64_t)a - (int64_t)b;
903 temp += 1;
904
905 return (temp >> 1) & 0xFFFFFFFFull;
906 }
907
908 static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b,
909 CPUMIPSState *env)
910 {
911 uint8_t temp16;
912 uint32_t temp;
913
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);
918 }
919 return temp & 0x0000FFFF;
920 }
921
922 static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b,
923 CPUMIPSState *env)
924 {
925 uint8_t temp16;
926 uint32_t temp;
927
928 temp = (uint32_t)a - (uint32_t)b;
929 temp16 = (temp >> 16) & 0x01;
930
931 if (temp16 == 1) {
932 temp = 0x0000;
933 set_DSPControl_overflow_flag(1, 20, env);
934 }
935
936 return temp & 0x0000FFFF;
937 }
938
939 static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
940 {
941 uint8_t temp8;
942 uint16_t temp;
943
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);
948 }
949
950 return temp & 0x00FF;
951 }
952
953 static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env)
954 {
955 uint8_t temp8;
956 uint16_t temp;
957
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);
963 }
964
965 return temp & 0x00FF;
966 }
967
968 static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
969 {
970 int32_t temp;
971
972 temp = a - b;
973 if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) {
974 set_DSPControl_overflow_flag(1, 20, env);
975 }
976
977 return temp;
978 }
979
980 static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env)
981 {
982 int32_t temp;
983
984 temp = a + b;
985
986 if (MIPSDSP_OVERFLOW_ADD(a, b, temp, 0x80000000)) {
987 set_DSPControl_overflow_flag(1, 20, env);
988 }
989
990 return temp;
991 }
992
993 static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b)
994 {
995 return a == b;
996 }
997
998 static inline int32_t mipsdsp_cmp_le(int32_t a, int32_t b)
999 {
1000 return a <= b;
1001 }
1002
1003 static inline int32_t mipsdsp_cmp_lt(int32_t a, int32_t b)
1004 {
1005 return a < b;
1006 }
1007
1008 static inline int32_t mipsdsp_cmpu_eq(uint32_t a, uint32_t b)
1009 {
1010 return a == b;
1011 }
1012
1013 static inline int32_t mipsdsp_cmpu_le(uint32_t a, uint32_t b)
1014 {
1015 return a <= b;
1016 }
1017
1018 static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b)
1019 {
1020 return a < b;
1021 }
1022 /*** MIPS DSP internal functions end ***/
1023
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
1032
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)
1040
1041 #define MIPSDSP_SPLIT32_16(num, a, b) \
1042 do { \
1043 a = (num >> 16) & MIPSDSP_LO; \
1044 b = num & MIPSDSP_LO; \
1045 } while (0)
1046
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)))
1055
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)
1064
1065 #define MIPSDSP_SPLIT64_32(num, a, b) \
1066 do { \
1067 a = (num >> 32) & MIPSDSP_LLO; \
1068 b = num & MIPSDSP_LLO; \
1069 } while (0)
1070
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
1077
1078 /** DSP Arithmetic Sub-class insns **/
1079 #define MIPSDSP32_UNOP_ENV(name, func, element) \
1080 target_ulong helper_##name(target_ulong rt, CPUMIPSState *env) \
1081 { \
1082 DSP32Value dt; \
1083 unsigned int i, n; \
1084 \
1085 n = sizeof(DSP32Value) / sizeof(dt.element[0]); \
1086 dt.sw[0] = rt; \
1087 \
1088 for (i = 0; i < n; i++) { \
1089 dt.element[i] = mipsdsp_##func(dt.element[i], env); \
1090 } \
1091 \
1092 return (target_long)dt.sw[0]; \
1093 }
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
1098
1099 #if defined(TARGET_MIPS64)
1100 #define MIPSDSP64_UNOP_ENV(name, func, element) \
1101 target_ulong helper_##name(target_ulong rt, CPUMIPSState *env) \
1102 { \
1103 DSP64Value dt; \
1104 unsigned int i, n; \
1105 \
1106 n = sizeof(DSP64Value) / sizeof(dt.element[0]); \
1107 dt.sl[0] = rt; \
1108 \
1109 for (i = 0; i < n; i++) { \
1110 dt.element[i] = mipsdsp_##func(dt.element[i], env); \
1111 } \
1112 \
1113 return dt.sl[0]; \
1114 }
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
1120
1121 #define MIPSDSP32_BINOP(name, func, element) \
1122 target_ulong helper_##name(target_ulong rs, target_ulong rt) \
1123 { \
1124 DSP32Value ds, dt; \
1125 unsigned int i, n; \
1126 \
1127 n = sizeof(DSP32Value) / sizeof(ds.element[0]); \
1128 ds.sw[0] = rs; \
1129 dt.sw[0] = rt; \
1130 \
1131 for (i = 0; i < n; i++) { \
1132 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]); \
1133 } \
1134 \
1135 return (target_long)ds.sw[0]; \
1136 }
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
1148
1149 #define MIPSDSP32_BINOP_ENV(name, func, element) \
1150 target_ulong helper_##name(target_ulong rs, target_ulong rt, \
1151 CPUMIPSState *env) \
1152 { \
1153 DSP32Value ds, dt; \
1154 unsigned int i, n; \
1155 \
1156 n = sizeof(DSP32Value) / sizeof(ds.element[0]); \
1157 ds.sw[0] = rs; \
1158 dt.sw[0] = rt; \
1159 \
1160 for (i = 0 ; i < n ; i++) { \
1161 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
1162 } \
1163 \
1164 return (target_long)ds.sw[0]; \
1165 }
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
1181
1182 #ifdef TARGET_MIPS64
1183 #define MIPSDSP64_BINOP(name, func, element) \
1184 target_ulong helper_##name(target_ulong rs, target_ulong rt) \
1185 { \
1186 DSP64Value ds, dt; \
1187 unsigned int i, n; \
1188 \
1189 n = sizeof(DSP64Value) / sizeof(ds.element[0]); \
1190 ds.sl[0] = rs; \
1191 dt.sl[0] = rt; \
1192 \
1193 for (i = 0 ; i < n ; i++) { \
1194 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]); \
1195 } \
1196 \
1197 return ds.sl[0]; \
1198 }
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
1204
1205 #define MIPSDSP64_BINOP_ENV(name, func, element) \
1206 target_ulong helper_##name(target_ulong rs, target_ulong rt, \
1207 CPUMIPSState *env) \
1208 { \
1209 DSP64Value ds, dt; \
1210 unsigned int i, n; \
1211 \
1212 n = sizeof(DSP64Value) / sizeof(ds.element[0]); \
1213 ds.sl[0] = rs; \
1214 dt.sl[0] = rt; \
1215 \
1216 for (i = 0 ; i < n ; i++) { \
1217 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
1218 } \
1219 \
1220 return ds.sl[0]; \
1221 }
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
1239
1240 #endif
1241
1242 #define SUBUH_QB(name, var) \
1243 target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \
1244 { \
1245 uint8_t rs3, rs2, rs1, rs0; \
1246 uint8_t rt3, rt2, rt1, rt0; \
1247 uint8_t tempD, tempC, tempB, tempA; \
1248 \
1249 MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); \
1250 MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \
1251 \
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; \
1256 \
1257 return ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
1258 ((uint32_t)tempB << 8) | ((uint32_t)tempA); \
1259 }
1260
1261 SUBUH_QB(subuh, 0);
1262 SUBUH_QB(subuh_r, 1);
1263
1264 #undef SUBUH_QB
1265
1266 target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
1267 {
1268 uint64_t temp, tempRs, tempRt;
1269 int32_t flag;
1270
1271 tempRs = (uint64_t)rs & MIPSDSP_LLO;
1272 tempRt = (uint64_t)rt & MIPSDSP_LLO;
1273
1274 temp = tempRs + tempRt;
1275 flag = (temp & 0x0100000000ull) >> 32;
1276 set_DSPControl_carryflag(flag, env);
1277
1278 return (target_long)(int32_t)(temp & MIPSDSP_LLO);
1279 }
1280
1281 target_ulong helper_addwc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
1282 {
1283 uint32_t rd;
1284 int32_t temp32, temp31;
1285 int64_t tempL;
1286
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;
1291
1292 if (temp31 != temp32) {
1293 set_DSPControl_overflow_flag(1, 20, env);
1294 }
1295
1296 rd = tempL & MIPSDSP_LLO;
1297
1298 return (target_long)(int32_t)rd;
1299 }
1300
1301 target_ulong helper_modsub(target_ulong rs, target_ulong rt)
1302 {
1303 int32_t decr;
1304 uint16_t lastindex;
1305 target_ulong rd;
1306
1307 decr = rt & MIPSDSP_Q0;
1308 lastindex = (rt >> 8) & MIPSDSP_LO;
1309
1310 if ((rs & MIPSDSP_LLO) == 0x00000000) {
1311 rd = (target_ulong)lastindex;
1312 } else {
1313 rd = rs - decr;
1314 }
1315
1316 return rd;
1317 }
1318
1319 target_ulong helper_raddu_w_qb(target_ulong rs)
1320 {
1321 target_ulong ret = 0;
1322 DSP32Value ds;
1323 unsigned int i;
1324
1325 ds.uw[0] = rs;
1326 for (i = 0; i < 4; i++) {
1327 ret += ds.ub[i];
1328 }
1329 return ret;
1330 }
1331
1332 #if defined(TARGET_MIPS64)
1333 target_ulong helper_raddu_l_ob(target_ulong rs)
1334 {
1335 target_ulong ret = 0;
1336 DSP64Value ds;
1337 unsigned int i;
1338
1339 ds.ul[0] = rs;
1340 for (i = 0; i < 8; i++) {
1341 ret += ds.ub[i];
1342 }
1343 return ret;
1344 }
1345 #endif
1346
1347 #define PRECR_QB_PH(name, a, b)\
1348 target_ulong helper_##name##_qb_ph(target_ulong rs, target_ulong rt) \
1349 { \
1350 uint8_t tempD, tempC, tempB, tempA; \
1351 \
1352 tempD = (rs >> a) & MIPSDSP_Q0; \
1353 tempC = (rs >> b) & MIPSDSP_Q0; \
1354 tempB = (rt >> a) & MIPSDSP_Q0; \
1355 tempA = (rt >> b) & MIPSDSP_Q0; \
1356 \
1357 return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); \
1358 }
1359
1360 PRECR_QB_PH(precr, 16, 0);
1361 PRECR_QB_PH(precrq, 24, 8);
1362
1363 #undef PRECR_QB_OH
1364
1365 target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs,
1366 target_ulong rt)
1367 {
1368 uint16_t tempB, tempA;
1369
1370 tempB = ((int32_t)rt >> sa) & MIPSDSP_LO;
1371 tempA = ((int32_t)rs >> sa) & MIPSDSP_LO;
1372
1373 return MIPSDSP_RETURN32_16(tempB, tempA);
1374 }
1375
1376 target_ulong helper_precr_sra_r_ph_w(uint32_t sa,
1377 target_ulong rs, target_ulong rt)
1378 {
1379 uint64_t tempB, tempA;
1380
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;
1388 }
1389 rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO);
1390
1391 return (target_long)(int32_t)rt;
1392 }
1393
1394 target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt)
1395 {
1396 uint16_t tempB, tempA;
1397
1398 tempB = (rs & MIPSDSP_HI) >> 16;
1399 tempA = (rt & MIPSDSP_HI) >> 16;
1400
1401 return MIPSDSP_RETURN32_16(tempB, tempA);
1402 }
1403
1404 target_ulong helper_precrq_rs_ph_w(target_ulong rs, target_ulong rt,
1405 CPUMIPSState *env)
1406 {
1407 uint16_t tempB, tempA;
1408
1409 tempB = mipsdsp_trunc16_sat16_round(rs, env);
1410 tempA = mipsdsp_trunc16_sat16_round(rt, env);
1411
1412 return MIPSDSP_RETURN32_16(tempB, tempA);
1413 }
1414
1415 #if defined(TARGET_MIPS64)
1416 target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt)
1417 {
1418 uint8_t rs6, rs4, rs2, rs0;
1419 uint8_t rt6, rt4, rt2, rt0;
1420 uint64_t temp;
1421
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;
1430
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;
1435
1436 return temp;
1437 }
1438
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) \
1442 { \
1443 uint16_t rs3, rs2, rs1, rs0; \
1444 uint16_t rt3, rt2, rt1, rt0; \
1445 uint16_t tempD, tempC, tempB, tempA; \
1446 \
1447 MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \
1448 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
1449 \
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; \
1462 } \
1463 \
1464 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \
1465 }
1466
1467 PRECR_QH_PW(sra, 0);
1468 PRECR_QH_PW(sra_r, 1);
1469
1470 #undef PRECR_QH_PW
1471
1472 target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt)
1473 {
1474 uint8_t rs6, rs4, rs2, rs0;
1475 uint8_t rt6, rt4, rt2, rt0;
1476 uint64_t temp;
1477
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;
1486
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;
1491
1492 return temp;
1493 }
1494
1495 target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt)
1496 {
1497 uint16_t tempD, tempC, tempB, tempA;
1498
1499 tempD = (rs >> 48) & MIPSDSP_LO;
1500 tempC = (rs >> 16) & MIPSDSP_LO;
1501 tempB = (rt >> 48) & MIPSDSP_LO;
1502 tempA = (rt >> 16) & MIPSDSP_LO;
1503
1504 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1505 }
1506
1507 target_ulong helper_precrq_rs_qh_pw(target_ulong rs, target_ulong rt,
1508 CPUMIPSState *env)
1509 {
1510 uint32_t rs2, rs0;
1511 uint32_t rt2, rt0;
1512 uint16_t tempD, tempC, tempB, tempA;
1513
1514 rs2 = (rs >> 32) & MIPSDSP_LLO;
1515 rs0 = rs & MIPSDSP_LLO;
1516 rt2 = (rt >> 32) & MIPSDSP_LLO;
1517 rt0 = rt & MIPSDSP_LLO;
1518
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);
1523
1524 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1525 }
1526
1527 target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt)
1528 {
1529 uint32_t tempB, tempA;
1530
1531 tempB = (rs >> 32) & MIPSDSP_LLO;
1532 tempA = (rt >> 32) & MIPSDSP_LLO;
1533
1534 return MIPSDSP_RETURN64_32(tempB, tempA);
1535 }
1536 #endif
1537
1538 target_ulong helper_precrqu_s_qb_ph(target_ulong rs, target_ulong rt,
1539 CPUMIPSState *env)
1540 {
1541 uint8_t tempD, tempC, tempB, tempA;
1542 uint16_t rsh, rsl, rth, rtl;
1543
1544 rsh = (rs & MIPSDSP_HI) >> 16;
1545 rsl = rs & MIPSDSP_LO;
1546 rth = (rt & MIPSDSP_HI) >> 16;
1547 rtl = rt & MIPSDSP_LO;
1548
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);
1553
1554 return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);
1555 }
1556
1557 #if defined(TARGET_MIPS64)
1558 target_ulong helper_precrqu_s_ob_qh(target_ulong rs, target_ulong rt,
1559 CPUMIPSState *env)
1560 {
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;
1566
1567 result = 0;
1568
1569 MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
1570 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
1571
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);
1580
1581 for (i = 0; i < 8; i++) {
1582 result |= (uint64_t)temp[i] << (8 * i);
1583 }
1584
1585 return result;
1586 }
1587
1588 #define PRECEQ_PW(name, a, b) \
1589 target_ulong helper_preceq_pw_##name(target_ulong rt) \
1590 { \
1591 uint16_t tempB, tempA; \
1592 uint32_t tempBI, tempAI; \
1593 \
1594 tempB = (rt >> a) & MIPSDSP_LO; \
1595 tempA = (rt >> b) & MIPSDSP_LO; \
1596 \
1597 tempBI = (uint32_t)tempB << 16; \
1598 tempAI = (uint32_t)tempA << 16; \
1599 \
1600 return MIPSDSP_RETURN64_32(tempBI, tempAI); \
1601 }
1602
1603 PRECEQ_PW(qhl, 48, 32);
1604 PRECEQ_PW(qhr, 16, 0);
1605 PRECEQ_PW(qhla, 48, 16);
1606 PRECEQ_PW(qhra, 32, 0);
1607
1608 #undef PRECEQ_PW
1609
1610 #endif
1611
1612 #define PRECEQU_PH(name, a, b) \
1613 target_ulong helper_precequ_ph_##name(target_ulong rt) \
1614 { \
1615 uint16_t tempB, tempA; \
1616 \
1617 tempB = (rt >> a) & MIPSDSP_Q0; \
1618 tempA = (rt >> b) & MIPSDSP_Q0; \
1619 \
1620 tempB = tempB << 7; \
1621 tempA = tempA << 7; \
1622 \
1623 return MIPSDSP_RETURN32_16(tempB, tempA); \
1624 }
1625
1626 PRECEQU_PH(qbl, 24, 16);
1627 PRECEQU_PH(qbr, 8, 0);
1628 PRECEQU_PH(qbla, 24, 8);
1629 PRECEQU_PH(qbra, 16, 0);
1630
1631 #undef PRECEQU_PH
1632
1633 #if defined(TARGET_MIPS64)
1634 #define PRECEQU_QH(name, a, b, c, d) \
1635 target_ulong helper_precequ_qh_##name(target_ulong rt) \
1636 { \
1637 uint16_t tempD, tempC, tempB, tempA; \
1638 \
1639 tempD = (rt >> a) & MIPSDSP_Q0; \
1640 tempC = (rt >> b) & MIPSDSP_Q0; \
1641 tempB = (rt >> c) & MIPSDSP_Q0; \
1642 tempA = (rt >> d) & MIPSDSP_Q0; \
1643 \
1644 tempD = tempD << 7; \
1645 tempC = tempC << 7; \
1646 tempB = tempB << 7; \
1647 tempA = tempA << 7; \
1648 \
1649 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \
1650 }
1651
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);
1656
1657 #undef PRECEQU_QH
1658
1659 #endif
1660
1661 #define PRECEU_PH(name, a, b) \
1662 target_ulong helper_preceu_ph_##name(target_ulong rt) \
1663 { \
1664 uint16_t tempB, tempA; \
1665 \
1666 tempB = (rt >> a) & MIPSDSP_Q0; \
1667 tempA = (rt >> b) & MIPSDSP_Q0; \
1668 \
1669 return MIPSDSP_RETURN32_16(tempB, tempA); \
1670 }
1671
1672 PRECEU_PH(qbl, 24, 16);
1673 PRECEU_PH(qbr, 8, 0);
1674 PRECEU_PH(qbla, 24, 8);
1675 PRECEU_PH(qbra, 16, 0);
1676
1677 #undef PRECEU_PH
1678
1679 #if defined(TARGET_MIPS64)
1680 #define PRECEU_QH(name, a, b, c, d) \
1681 target_ulong helper_preceu_qh_##name(target_ulong rt) \
1682 { \
1683 uint16_t tempD, tempC, tempB, tempA; \
1684 \
1685 tempD = (rt >> a) & MIPSDSP_Q0; \
1686 tempC = (rt >> b) & MIPSDSP_Q0; \
1687 tempB = (rt >> c) & MIPSDSP_Q0; \
1688 tempA = (rt >> d) & MIPSDSP_Q0; \
1689 \
1690 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \
1691 }
1692
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);
1697
1698 #undef PRECEU_QH
1699
1700 #endif
1701
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) \
1705 { \
1706 uint8_t rt3, rt2, rt1, rt0; \
1707 \
1708 sa = sa & 0x07; \
1709 \
1710 MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \
1711 \
1712 rt3 = mipsdsp_##func(rt3, sa); \
1713 rt2 = mipsdsp_##func(rt2, sa); \
1714 rt1 = mipsdsp_##func(rt1, sa); \
1715 rt0 = mipsdsp_##func(rt0, sa); \
1716 \
1717 return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \
1718 }
1719
1720 #define SHIFT_QB_ENV(name, func) \
1721 target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt,\
1722 CPUMIPSState *env) \
1723 { \
1724 uint8_t rt3, rt2, rt1, rt0; \
1725 \
1726 sa = sa & 0x07; \
1727 \
1728 MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \
1729 \
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); \
1734 \
1735 return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \
1736 }
1737
1738 SHIFT_QB_ENV(shll, lshift8);
1739 SHIFT_QB(shrl, rshift_u8);
1740
1741 SHIFT_QB(shra, rashift8);
1742 SHIFT_QB(shra_r, rnd8_rashift);
1743
1744 #undef SHIFT_QB
1745 #undef SHIFT_QB_ENV
1746
1747 #if defined(TARGET_MIPS64)
1748 #define SHIFT_OB(name, func) \
1749 target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \
1750 { \
1751 int i; \
1752 uint8_t rt_t[8]; \
1753 uint64_t temp; \
1754 \
1755 sa = sa & 0x07; \
1756 temp = 0; \
1757 \
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); \
1762 } \
1763 \
1764 return temp; \
1765 }
1766
1767 #define SHIFT_OB_ENV(name, func) \
1768 target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \
1769 CPUMIPSState *env) \
1770 { \
1771 int i; \
1772 uint8_t rt_t[8]; \
1773 uint64_t temp; \
1774 \
1775 sa = sa & 0x07; \
1776 temp = 0; \
1777 \
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); \
1782 } \
1783 \
1784 return temp; \
1785 }
1786
1787 SHIFT_OB_ENV(shll, lshift8);
1788 SHIFT_OB(shrl, rshift_u8);
1789
1790 SHIFT_OB(shra, rashift8);
1791 SHIFT_OB(shra_r, rnd8_rashift);
1792
1793 #undef SHIFT_OB
1794 #undef SHIFT_OB_ENV
1795
1796 #endif
1797
1798 #define SHIFT_PH(name, func) \
1799 target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt, \
1800 CPUMIPSState *env) \
1801 { \
1802 uint16_t rth, rtl; \
1803 \
1804 sa = sa & 0x0F; \
1805 \
1806 MIPSDSP_SPLIT32_16(rt, rth, rtl); \
1807 \
1808 rth = mipsdsp_##func(rth, sa, env); \
1809 rtl = mipsdsp_##func(rtl, sa, env); \
1810 \
1811 return MIPSDSP_RETURN32_16(rth, rtl); \
1812 }
1813
1814 SHIFT_PH(shll, lshift16);
1815 SHIFT_PH(shll_s, sat16_lshift);
1816
1817 #undef SHIFT_PH
1818
1819 #if defined(TARGET_MIPS64)
1820 #define SHIFT_QH(name, func) \
1821 target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa) \
1822 { \
1823 uint16_t rt3, rt2, rt1, rt0; \
1824 \
1825 sa = sa & 0x0F; \
1826 \
1827 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
1828 \
1829 rt3 = mipsdsp_##func(rt3, sa); \
1830 rt2 = mipsdsp_##func(rt2, sa); \
1831 rt1 = mipsdsp_##func(rt1, sa); \
1832 rt0 = mipsdsp_##func(rt0, sa); \
1833 \
1834 return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \
1835 }
1836
1837 #define SHIFT_QH_ENV(name, func) \
1838 target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa, \
1839 CPUMIPSState *env) \
1840 { \
1841 uint16_t rt3, rt2, rt1, rt0; \
1842 \
1843 sa = sa & 0x0F; \
1844 \
1845 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
1846 \
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); \
1851 \
1852 return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \
1853 }
1854
1855 SHIFT_QH_ENV(shll, lshift16);
1856 SHIFT_QH_ENV(shll_s, sat16_lshift);
1857
1858 SHIFT_QH(shrl, rshift_u16);
1859 SHIFT_QH(shra, rashift16);
1860 SHIFT_QH(shra_r, rnd16_rashift);
1861
1862 #undef SHIFT_QH
1863 #undef SHIFT_QH_ENV
1864
1865 #endif
1866
1867 #define SHIFT_W(name, func) \
1868 target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \
1869 { \
1870 uint32_t temp; \
1871 \
1872 sa = sa & 0x1F; \
1873 temp = mipsdsp_##func(rt, sa); \
1874 \
1875 return (target_long)(int32_t)temp; \
1876 }
1877
1878 #define SHIFT_W_ENV(name, func) \
1879 target_ulong helper_##name##_w(target_ulong sa, target_ulong rt, \
1880 CPUMIPSState *env) \
1881 { \
1882 uint32_t temp; \
1883 \
1884 sa = sa & 0x1F; \
1885 temp = mipsdsp_##func(rt, sa, env); \
1886 \
1887 return (target_long)(int32_t)temp; \
1888 }
1889
1890 SHIFT_W_ENV(shll_s, sat32_lshift);
1891 SHIFT_W(shra_r, rnd32_rashift);
1892
1893 #undef SHIFT_W
1894 #undef SHIFT_W_ENV
1895
1896 #if defined(TARGET_MIPS64)
1897 #define SHIFT_PW(name, func) \
1898 target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa) \
1899 { \
1900 uint32_t rt1, rt0; \
1901 \
1902 sa = sa & 0x1F; \
1903 MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
1904 \
1905 rt1 = mipsdsp_##func(rt1, sa); \
1906 rt0 = mipsdsp_##func(rt0, sa); \
1907 \
1908 return MIPSDSP_RETURN64_32(rt1, rt0); \
1909 }
1910
1911 #define SHIFT_PW_ENV(name, func) \
1912 target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa, \
1913 CPUMIPSState *env) \
1914 { \
1915 uint32_t rt1, rt0; \
1916 \
1917 sa = sa & 0x1F; \
1918 MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
1919 \
1920 rt1 = mipsdsp_##func(rt1, sa, env); \
1921 rt0 = mipsdsp_##func(rt0, sa, env); \
1922 \
1923 return MIPSDSP_RETURN64_32(rt1, rt0); \
1924 }
1925
1926 SHIFT_PW_ENV(shll, lshift32);
1927 SHIFT_PW_ENV(shll_s, sat32_lshift);
1928
1929 SHIFT_PW(shra, rashift32);
1930 SHIFT_PW(shra_r, rnd32_rashift);
1931
1932 #undef SHIFT_PW
1933 #undef SHIFT_PW_ENV
1934
1935 #endif
1936
1937 #define SHIFT_PH(name, func) \
1938 target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \
1939 { \
1940 uint16_t rth, rtl; \
1941 \
1942 sa = sa & 0x0F; \
1943 \
1944 MIPSDSP_SPLIT32_16(rt, rth, rtl); \
1945 \
1946 rth = mipsdsp_##func(rth, sa); \
1947 rtl = mipsdsp_##func(rtl, sa); \
1948 \
1949 return MIPSDSP_RETURN32_16(rth, rtl); \
1950 }
1951
1952 SHIFT_PH(shrl, rshift_u16);
1953 SHIFT_PH(shra, rashift16);
1954 SHIFT_PH(shra_r, rnd16_rashift);
1955
1956 #undef SHIFT_PH
1957
1958 /** DSP Multiply Sub-class insns **/
1959 /* Return value made up by two 16bits value.
1960 * FIXME give the macro a better name.
1961 */
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) \
1967 { \
1968 uint16_t rsB, rsA, rtB, rtA; \
1969 \
1970 rsB = (rs >> rsmov1) & rsfilter; \
1971 rsA = (rs >> rsmov2) & rsfilter; \
1972 rtB = (rt >> rtmov1) & rtfilter; \
1973 rtA = (rt >> rtmov2) & rtfilter; \
1974 \
1975 rsB = mipsdsp_##func(rsB, rtB, env); \
1976 rsA = mipsdsp_##func(rsA, rtA, env); \
1977 \
1978 return MIPSDSP_RETURN32_16(rsB, rsA); \
1979 }
1980
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);
1999
2000 #undef MUL_RETURN32_16_PH
2001
2002 #define MUL_RETURN32_32_ph(name, func, movbits) \
2003 target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2004 CPUMIPSState *env) \
2005 { \
2006 int16_t rsh, rth; \
2007 int32_t temp; \
2008 \
2009 rsh = (rs >> movbits) & MIPSDSP_LO; \
2010 rth = (rt >> movbits) & MIPSDSP_LO; \
2011 temp = mipsdsp_##func(rsh, rth, env); \
2012 \
2013 return (target_long)(int32_t)temp; \
2014 }
2015
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);
2018
2019 #undef MUL_RETURN32_32_ph
2020
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) \
2024 { \
2025 int16_t rsh, rsl, rth, rtl; \
2026 int32_t tempB, tempA; \
2027 int64_t acc, dotp; \
2028 \
2029 MIPSDSP_SPLIT32_16(rs, rsh, rsl); \
2030 MIPSDSP_SPLIT32_16(rt, rth, rtl); \
2031 \
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); \
2038 } \
2039 \
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); \
2047 }
2048
2049 MUL_VOID_PH(mulsaq_s_w_ph, 1);
2050 MUL_VOID_PH(mulsa_w_ph, 0);
2051
2052 #undef MUL_VOID_PH
2053
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) \
2060 { \
2061 uint16_t rs3, rs2, rs1, rs0; \
2062 uint16_t rt3, rt2, rt1, rt0; \
2063 uint16_t tempD, tempC, tempB, tempA; \
2064 \
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; \
2073 \
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); \
2078 \
2079 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \
2080 }
2081
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);
2091
2092 #undef MUL_RETURN64_16_QH
2093
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) \
2099 { \
2100 uint16_t rsB, rsA; \
2101 uint16_t rtB, rtA; \
2102 uint32_t tempB, tempA; \
2103 \
2104 rsB = (rs >> rsmov1) & MIPSDSP_LO; \
2105 rsA = (rs >> rsmov2) & MIPSDSP_LO; \
2106 rtB = (rt >> rtmov1) & MIPSDSP_LO; \
2107 rtA = (rt >> rtmov2) & MIPSDSP_LO; \
2108 \
2109 tempB = mipsdsp_mul_q15_q15(5, rsB, rtB, env); \
2110 tempA = mipsdsp_mul_q15_q15(5, rsA, rtA, env); \
2111 \
2112 return ((uint64_t)tempB << 32) | (uint64_t)tempA; \
2113 }
2114
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);
2117
2118 #undef MUL_RETURN64_32_QH
2119
2120 void helper_mulsaq_s_w_qh(target_ulong rs, target_ulong rt, uint32_t ac,
2121 CPUMIPSState *env)
2122 {
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;
2129
2130 MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
2131 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
2132
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);
2137
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;
2145 }
2146
2147 acc[0] = env->active_tc.LO[ac];
2148 acc[1] = env->active_tc.HI[ac];
2149
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;
2154 }
2155 acc[0] = temp_sum;
2156 acc[1] += temp[1];
2157
2158 env->active_tc.HI[ac] = acc[1];
2159 env->active_tc.LO[ac] = acc[0];
2160 }
2161 #endif
2162
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) \
2166 { \
2167 uint8_t rs3, rs2; \
2168 uint8_t rt3, rt2; \
2169 uint16_t tempB, tempA; \
2170 uint64_t tempC, dotp; \
2171 \
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; \
2187 } \
2188 \
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); \
2192 }
2193
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);
2198
2199 #undef DP_QB
2200
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) \
2207 { \
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; \
2214 \
2215 temp[0] = 0; \
2216 temp[1] = 0; \
2217 \
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; \
2226 \
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); \
2231 \
2232 temp[0] = (uint64_t)tempD + (uint64_t)tempC + \
2233 (uint64_t)tempB + (uint64_t)tempA; \
2234 \
2235 acc[0] = env->active_tc.LO[ac]; \
2236 acc[1] = env->active_tc.HI[ac]; \
2237 \
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; \
2243 } \
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; \
2250 } \
2251 temp[0] = temp_sum; \
2252 temp[1] = acc[1] - temp[1]; \
2253 } \
2254 \
2255 env->active_tc.HI[ac] = temp[1]; \
2256 env->active_tc.LO[ac] = temp[0]; \
2257 }
2258
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);
2263
2264 #undef DP_OB
2265 #endif
2266
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) \
2270 { \
2271 int16_t rsB, rsA, rtB, rtA; \
2272 int32_t tempA, tempB; \
2273 int64_t acc; \
2274 \
2275 rsB = (rs >> rsmov1) & MIPSDSP_LO; \
2276 rsA = (rs >> rsmov2) & MIPSDSP_LO; \
2277 rtB = (rt >> rtmov1) & MIPSDSP_LO; \
2278 rtA = (rt >> rtmov2) & MIPSDSP_LO; \
2279 \
2280 tempB = (int32_t)rsB * (int32_t)rtB; \
2281 tempA = (int32_t)rsA * (int32_t)rtA; \
2282 \
2283 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
2284 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
2285 \
2286 if (is_add) { \
2287 acc = acc + ((int64_t)tempB + (int64_t)tempA); \
2288 } else { \
2289 acc = acc - ((int64_t)tempB + (int64_t)tempA); \
2290 } \
2291 \
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); \
2294 }
2295
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
2301
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) \
2305 { \
2306 int16_t rsB, rsA, rtB, rtA; \
2307 int32_t tempB, tempA; \
2308 int64_t acc, dotp; \
2309 \
2310 rsB = (rs >> rsmov1) & MIPSDSP_LO; \
2311 rsA = (rs >> rsmov2) & MIPSDSP_LO; \
2312 rtB = (rt >> rtmov1) & MIPSDSP_LO; \
2313 rtA = (rt >> rtmov2) & MIPSDSP_LO; \
2314 \
2315 tempB = mipsdsp_mul_q15_q15(ac, rsB, rtB, env); \
2316 tempA = mipsdsp_mul_q15_q15(ac, rsA, rtA, env); \
2317 \
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); \
2321 \
2322 if (is_add) { \
2323 acc = acc + dotp; \
2324 } else { \
2325 acc = acc - dotp; \
2326 } \
2327 \
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); \
2332 }
2333
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);
2338
2339 #undef DP_HASFUNC_PH
2340
2341 #define DP_128OPERATION_PH(name, is_add) \
2342 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2343 CPUMIPSState *env) \
2344 { \
2345 int16_t rsh, rsl, rth, rtl; \
2346 int32_t tempB, tempA, tempC62_31, tempC63; \
2347 int64_t acc, dotp, tempC; \
2348 \
2349 MIPSDSP_SPLIT32_16(rs, rsh, rsl); \
2350 MIPSDSP_SPLIT32_16(rt, rth, rtl); \
2351 \
2352 tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl, env); \
2353 tempA = mipsdsp_mul_q15_q15(ac, rsl, rth, env); \
2354 \
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; \
2362 } \
2363 tempC63 = (tempC >> 63) & 0x01; \
2364 tempC62_31 = (tempC >> 31) & 0xFFFFFFFF; \
2365 \
2366 if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) { \
2367 tempC = 0x7FFFFFFF; \
2368 set_DSPControl_overflow_flag(1, 16 + ac, env); \
2369 } \
2370 \
2371 if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) { \
2372 tempC = (int64_t)(int32_t)0x80000000; \
2373 set_DSPControl_overflow_flag(1, 16 + ac, env); \
2374 } \
2375 \
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); \
2380 }
2381
2382 DP_128OPERATION_PH(dpaqx_sa_w_ph, 1);
2383 DP_128OPERATION_PH(dpsqx_sa_w_ph, 0);
2384
2385 #undef DP_128OPERATION_HP
2386
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) \
2391 { \
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; \
2398 \
2399 MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \
2400 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
2401 \
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); \
2412 } \
2413 \
2414 temp[0] = (int64_t)tempD + (int64_t)tempC + \
2415 (int64_t)tempB + (int64_t)tempA; \
2416 \
2417 if (temp[0] >= 0) { \
2418 temp[1] = 0; \
2419 } else { \
2420 temp[1] = ~0ull; \
2421 } \
2422 \
2423 acc[1] = env->active_tc.HI[ac]; \
2424 acc[0] = env->active_tc.LO[ac]; \
2425 \
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; \
2431 } \
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; \
2438 } \
2439 temp[0] = temp_sum; \
2440 temp[1] = acc[1] - temp[1]; \
2441 } \
2442 \
2443 env->active_tc.HI[ac] = temp[1]; \
2444 env->active_tc.LO[ac] = temp[0]; \
2445 }
2446
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);
2451
2452 #undef DP_QH
2453
2454 #endif
2455
2456 #define DP_L_W(name, is_add) \
2457 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2458 CPUMIPSState *env) \
2459 { \
2460 int32_t temp63; \
2461 int64_t dotp, acc; \
2462 uint64_t temp; \
2463 bool overflow; \
2464 \
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)); \
2476 } \
2477 \
2478 if (overflow) { \
2479 temp63 = (temp >> 63) & 0x01; \
2480 if (temp63 == 1) { \
2481 temp = (0x01ull << 63) - 1; \
2482 } else { \
2483 temp = 0x01ull << 63; \
2484 } \
2485 \
2486 set_DSPControl_overflow_flag(1, 16 + ac, env); \
2487 } \
2488 \
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); \
2493 }
2494
2495 DP_L_W(dpaq_sa_l_w, 1);
2496 DP_L_W(dpsq_sa_l_w, 0);
2497
2498 #undef DP_L_W
2499
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) \
2504 { \
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; \
2511 \
2512 temp[0] = 0; \
2513 temp[1] = 0; \
2514 \
2515 MIPSDSP_SPLIT64_32(rs, rs1, rs0); \
2516 MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
2517 \
2518 tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env); \
2519 tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env); \
2520 \
2521 if (tempB[0] >= 0) { \
2522 tempB[1] = 0x00; \
2523 } else { \
2524 tempB[1] = ~0ull; \
2525 } \
2526 \
2527 if (tempA[0] >= 0) { \
2528 tempA[1] = 0x00; \
2529 } else { \
2530 tempA[1] = ~0ull; \
2531 } \
2532 \
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; \
2537 } \
2538 temp[0] = temp_sum; \
2539 temp[1] += tempB[1] + tempA[1]; \
2540 \
2541 mipsdsp_##func(acc, ac, temp, env); \
2542 \
2543 env->active_tc.HI[ac] = acc[1]; \
2544 env->active_tc.LO[ac] = acc[0]; \
2545 }
2546
2547 DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63);
2548 DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63);
2549
2550 #undef DP_L_PW
2551
2552 void helper_mulsaq_s_l_pw(target_ulong rs, target_ulong rt, uint32_t ac,
2553 CPUMIPSState *env)
2554 {
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;
2561
2562 rs1 = (rs >> 32) & MIPSDSP_LLO;
2563 rs0 = rs & MIPSDSP_LLO;
2564 rt1 = (rt >> 32) & MIPSDSP_LLO;
2565 rt0 = rt & MIPSDSP_LLO;
2566
2567 tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env);
2568 tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);
2569
2570 if (tempB[0] >= 0) {
2571 tempB[1] = 0x00;
2572 } else {
2573 tempB[1] = ~0ull;
2574 }
2575
2576 if (tempA[0] >= 0) {
2577 tempA[1] = 0x00;
2578 } else {
2579 tempA[1] = ~0ull;
2580 }
2581
2582 acc[0] = env->active_tc.LO[ac];
2583 acc[1] = env->active_tc.HI[ac];
2584
2585 temp_sum = tempB[0] - tempA[0];
2586 if ((uint64_t)temp_sum > (uint64_t)tempB[0]) {
2587 tempB[1] -= 1;
2588 }
2589 temp[0] = temp_sum;
2590 temp[1] = tempB[1] - tempA[1];
2591
2592 if ((temp[1] & 0x01) == 0) {
2593 temp[1] = 0x00;
2594 } else {
2595 temp[1] = ~0ull;
2596 }
2597
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;
2602 }
2603 acc[0] = temp_sum;
2604 acc[1] += temp[1];
2605
2606 env->active_tc.HI[ac] = acc[1];
2607 env->active_tc.LO[ac] = acc[0];
2608 }
2609 #endif
2610
2611 #define MAQ_S_W(name, mov) \
2612 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2613 CPUMIPSState *env) \
2614 { \
2615 int16_t rsh, rth; \
2616 int32_t tempA; \
2617 int64_t tempL, acc; \
2618 \
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); \
2629 }
2630
2631 MAQ_S_W(maq_s_w_phl, 16);
2632 MAQ_S_W(maq_s_w_phr, 0);
2633
2634 #undef MAQ_S_W
2635
2636 #define MAQ_SA_W(name, mov) \
2637 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2638 CPUMIPSState *env) \
2639 { \
2640 int16_t rsh, rth; \
2641 int32_t tempA; \
2642 \
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); \
2647 \
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); \
2652 }
2653
2654 MAQ_SA_W(maq_sa_w_phl, 16);
2655 MAQ_SA_W(maq_sa_w_phr, 0);
2656
2657 #undef MAQ_SA_W
2658
2659 #define MULQ_W(name, addvar) \
2660 target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2661 CPUMIPSState *env) \
2662 { \
2663 int32_t rs_t, rt_t; \
2664 int32_t tempI; \
2665 int64_t tempL; \
2666 \
2667 rs_t = rs & MIPSDSP_LLO; \
2668 rt_t = rt & MIPSDSP_LLO; \
2669 \
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; \
2676 } \
2677 tempI = (tempL & MIPSDSP_LHI) >> 32; \
2678 \
2679 return (target_long)(int32_t)tempI; \
2680 }
2681
2682 MULQ_W(mulq_s_w, 0);
2683 MULQ_W(mulq_rs_w, 0x80000000ull);
2684
2685 #undef MULQ_W
2686
2687 #if defined(TARGET_MIPS64)
2688
2689 #define MAQ_S_W_QH(name, mov) \
2690 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2691 CPUMIPSState *env) \
2692 { \
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; \
2698 \
2699 temp[0] = 0; \
2700 temp[1] = 0; \
2701 \
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); \
2705 \
2706 temp[0] = (int64_t)temp_mul; \
2707 if (temp[0] >= 0) { \
2708 temp[1] = 0x00; \
2709 } else { \
2710 temp[1] = ~0ull; \
2711 } \
2712 \
2713 acc[0] = env->active_tc.LO[ac]; \
2714 acc[1] = env->active_tc.HI[ac]; \
2715 \
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; \
2720 } \
2721 acc[0] = temp_sum; \
2722 acc[1] += temp[1]; \
2723 \
2724 env->active_tc.HI[ac] = acc[1]; \
2725 env->active_tc.LO[ac] = acc[0]; \
2726 }
2727
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);
2732
2733 #undef MAQ_S_W_QH
2734
2735 #define MAQ_SA_W(name, mov) \
2736 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2737 CPUMIPSState *env) \
2738 { \
2739 int16_t rs_t, rt_t; \
2740 int32_t temp; \
2741 int64_t acc[2]; \
2742 \
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); \
2747 \
2748 acc[0] = (int64_t)(int32_t)temp; \
2749 if (acc[0] >= 0) { \
2750 acc[1] = 0x00; \
2751 } else { \
2752 acc[1] = ~0ull; \
2753 } \
2754 \
2755 env->active_tc.HI[ac] = acc[1]; \
2756 env->active_tc.LO[ac] = acc[0]; \
2757 }
2758
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);
2763
2764 #undef MAQ_SA_W
2765
2766 #define MAQ_S_L_PW(name, mov) \
2767 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2768 CPUMIPSState *env) \
2769 { \
2770 int32_t rs_t, rt_t; \
2771 int64_t temp[2]; \
2772 int64_t acc[2]; \
2773 int64_t temp_sum; \
2774 \
2775 temp[0] = 0; \
2776 temp[1] = 0; \
2777 \
2778 rs_t = (rs >> mov) & MIPSDSP_LLO; \
2779 rt_t = (rt >> mov) & MIPSDSP_LLO; \
2780 \
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; \
2786 } \
2787 \
2788 acc[0] = env->active_tc.LO[ac]; \
2789 acc[1] = env->active_tc.HI[ac]; \
2790 \
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; \
2795 } \
2796 acc[0] = temp_sum; \
2797 acc[1] += temp[1]; \
2798 \
2799 env->active_tc.HI[ac] = acc[1]; \
2800 env->active_tc.LO[ac] = acc[0]; \
2801 }
2802
2803 MAQ_S_L_PW(maq_s_l_pwl, 32);
2804 MAQ_S_L_PW(maq_s_l_pwr, 0);
2805
2806 #undef MAQ_S_L_PW
2807
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) \
2811 { \
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; \
2818 \
2819 temp[0] = 0x00; \
2820 temp[1] = 0x00; \
2821 \
2822 MIPSDSP_SPLIT64_32(rs, rs1, rs0); \
2823 MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
2824 \
2825 if (sigext) { \
2826 tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1); \
2827 tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0); \
2828 \
2829 if (tempBL[0] >= 0) { \
2830 tempBL[1] = 0x0; \
2831 } else { \
2832 tempBL[1] = ~0ull; \
2833 } \
2834 \
2835 if (tempAL[0] >= 0) { \
2836 tempAL[1] = 0x0; \
2837 } else { \
2838 tempAL[1] = ~0ull; \
2839 } \
2840 } else { \
2841 tempBL[0] = mipsdsp_##func(rs1, rt1); \
2842 tempAL[0] = mipsdsp_##func(rs0, rt0); \
2843 tempBL[1] = 0; \
2844 tempAL[1] = 0; \
2845 } \
2846 \
2847 acc[1] = env->active_tc.HI[ac]; \
2848 acc[0] = env->active_tc.LO[ac]; \
2849 \
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; \
2854 } \
2855 temp[0] = temp_sum; \
2856 temp[1] += tempBL[1] + tempAL[1]; \
2857 \
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; \
2863 } \
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; \
2870 } \
2871 temp[0] = temp_sum; \
2872 temp[1] = acc[1] - temp[1]; \
2873 } \
2874 \
2875 env->active_tc.HI[ac] = temp[1]; \
2876 env->active_tc.LO[ac] = temp[0]; \
2877 }
2878
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
2885
2886 /** DSP Bit/Manipulation Sub-class insns **/
2887 target_ulong helper_bitrev(target_ulong rt)
2888 {
2889 int32_t temp;
2890 uint32_t rd;
2891 int i;
2892
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;
2898 }
2899
2900 return (target_ulong)rd;
2901 }
2902
2903 #define BIT_INSV(name, posfilter, sizefilter, ret_type) \
2904 target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \
2905 target_ulong rt) \
2906 { \
2907 uint32_t pos, size, msb, lsb; \
2908 target_ulong filter; \
2909 target_ulong temp, temprs, temprt; \
2910 target_ulong dspc; \
2911 \
2912 dspc = env->active_tc.DSPControl; \
2913 \
2914 pos = dspc & posfilter; \
2915 size = (dspc >> 7) & sizefilter; \
2916 \
2917 msb = pos + size - 1; \
2918 lsb = pos; \
2919 \
2920 if (lsb > msb || (msb > TARGET_LONG_BITS)) { \
2921 return rt; \
2922 } \
2923 \
2924 filter = ((int64_t)0x01 << size) - 1; \
2925 filter = filter << pos; \
2926 temprs = (rs << pos) & filter; \
2927 temprt = rt & ~filter; \
2928 temp = temprs | temprt; \
2929 \
2930 return (target_long)(ret_type)temp; \
2931 }
2932
2933 BIT_INSV(insv, 0x1F, 0x3F, int32_t);
2934 #ifdef TARGET_MIPS64
2935 BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
2936 #endif
2937
2938 #undef BIT_INSV
2939
2940
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) \
2944 { \
2945 uint32_t rs_t, rt_t; \
2946 uint8_t cc; \
2947 uint32_t temp = 0; \
2948 int i; \
2949 \
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; \
2955 } \
2956 \
2957 return (target_ulong)temp; \
2958 }
2959
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);
2963
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
2969
2970 #undef CMP_HAS_RET
2971
2972
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) \
2976 { \
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; \
2981 \
2982 for (i = 0; i < split_num; i++) { \
2983 rs_t = (rs >> (bit_size * i)) & filter; \
2984 rt_t = (rt >> (bit_size * i)) & filter; \
2985 \
2986 cc = mipsdsp_##func((int32_t)rs_t, (int32_t)rt_t); \
2987 flag |= cc << i; \
2988 } \
2989 \
2990 set_DSPControl_24(flag, split_num, env); \
2991 }
2992
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);
2996
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);
3000
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);
3005
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);
3009
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
3015
3016 #if defined(TARGET_MIPS64)
3017
3018 #define CMPGDU_OB(name) \
3019 target_ulong helper_cmpgdu_##name##_ob(target_ulong rs, target_ulong rt, \
3020 CPUMIPSState *env) \
3021 { \
3022 int i; \
3023 uint8_t rs_t, rt_t; \
3024 uint32_t cond; \
3025 \
3026 cond = 0; \
3027 \
3028 for (i = 0; i < 8; i++) { \
3029 rs_t = (rs >> (8 * i)) & MIPSDSP_Q0; \
3030 rt_t = (rt >> (8 * i)) & MIPSDSP_Q0; \
3031 \
3032 if (mipsdsp_cmpu_##name(rs_t, rt_t)) { \
3033 cond |= 0x01 << i; \
3034 } \
3035 } \
3036 \
3037 set_DSPControl_24(cond, 8, env); \
3038 \
3039 return (uint64_t)cond; \
3040 }
3041
3042 CMPGDU_OB(eq)
3043 CMPGDU_OB(lt)
3044 CMPGDU_OB(le)
3045 #undef CMPGDU_OB
3046 #endif
3047
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) \
3051 { \
3052 uint32_t rs_t, rt_t; \
3053 uint32_t cc; \
3054 target_ulong dsp; \
3055 int i; \
3056 target_ulong result = 0; \
3057 \
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; \
3064 \
3065 result |= (target_ulong)cc << (bit_size * i); \
3066 } \
3067 \
3068 if (ret32bit) { \
3069 result = (target_long)(int32_t)(result & MIPSDSP_LLO); \
3070 } \
3071 \
3072 return result; \
3073 }
3074
3075 PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1);
3076 PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1);
3077
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
3084
3085 target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt)
3086 {
3087 uint32_t rsl, rth;
3088
3089 rsl = rs & MIPSDSP_LO;
3090 rth = (rt & MIPSDSP_HI) >> 16;
3091
3092 return (target_long)(int32_t)((rsl << 16) | rth);
3093 }
3094
3095 #if defined(TARGET_MIPS64)
3096 target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt)
3097 {
3098 uint32_t rs0, rt1;
3099
3100 rs0 = rs & MIPSDSP_LLO;
3101 rt1 = (rt >> 32) & MIPSDSP_LLO;
3102
3103 return ((uint64_t)rs0 << 32) | (uint64_t)rt1;
3104 }
3105 #endif
3106
3107 /** DSP Accumulator and DSPControl Access Sub-class insns **/
3108 target_ulong helper_extr_w(target_ulong ac, target_ulong shift,
3109 CPUMIPSState *env)
3110 {
3111 int32_t tempI;
3112 int64_t tempDL[2];
3113
3114 shift = shift & 0x1F;
3115
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);
3120 }
3121
3122 tempI = (tempDL[0] >> 1) & MIPSDSP_LLO;
3123
3124 tempDL[0] += 1;
3125 if (tempDL[0] == 0) {
3126 tempDL[1] += 1;
3127 }
3128
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);
3132 }
3133
3134 return (target_long)tempI;
3135 }
3136
3137 target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
3138 CPUMIPSState *env)
3139 {
3140 int64_t tempDL[2];
3141
3142 shift = shift & 0x1F;
3143
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);
3148 }
3149
3150 tempDL[0] += 1;
3151 if (tempDL[0] == 0) {
3152 tempDL[1] += 1;
3153 }
3154
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);
3158 }
3159
3160 return (target_long)(int32_t)(tempDL[0] >> 1);
3161 }
3162
3163 target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
3164 CPUMIPSState *env)
3165 {
3166 int32_t tempI, temp64;
3167 int64_t tempDL[2];
3168
3169 shift = shift & 0x1F;
3170
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);
3175 }
3176 tempDL[0] += 1;
3177 if (tempDL[0] == 0) {
3178 tempDL[1] += 1;
3179 }
3180 tempI = tempDL[0] >> 1;
3181
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;
3189 }
3190 set_DSPControl_overflow_flag(1, 23, env);
3191 }
3192
3193 return (target_long)tempI;
3194 }
3195
3196 #if defined(TARGET_MIPS64)
3197 target_ulong helper_dextr_w(target_ulong ac, target_ulong shift,
3198 CPUMIPSState *env)
3199 {
3200 uint64_t temp[3];
3201
3202 shift = shift & 0x3F;
3203
3204 mipsdsp_rndrashift_acc(temp, ac, shift, env);
3205
3206 return (int64_t)(int32_t)(temp[0] >> 1);
3207 }
3208
3209 target_ulong helper_dextr_r_w(target_ulong ac, target_ulong shift,
3210 CPUMIPSState *env)
3211 {
3212 uint64_t temp[3];
3213 uint32_t temp128;
3214
3215 shift = shift & 0x3F;
3216 mipsdsp_rndrashift_acc(temp, ac, shift, env);
3217
3218 temp[0] += 1;
3219 if (temp[0] == 0) {
3220 temp[1] += 1;
3221 if (temp[1] == 0) {
3222 temp[2] += 1;
3223 }
3224 }
3225
3226 temp128 = temp[2] & 0x01;
3227
3228 if ((temp128 != 0 || temp[1] != 0) &&
3229 (temp128 != 1 || temp[1] != ~0ull)) {
3230 set_DSPControl_overflow_flag(1, 23, env);
3231 }
3232
3233 return (int64_t)(int32_t)(temp[0] >> 1);
3234 }
3235
3236 target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift,
3237 CPUMIPSState *env)
3238 {
3239 uint64_t temp[3];
3240 uint32_t temp128;
3241
3242 shift = shift & 0x3F;
3243 mipsdsp_rndrashift_acc(temp, ac, shift, env);
3244
3245 temp[0] += 1;
3246 if (temp[0] == 0) {
3247 temp[1] += 1;
3248 if (temp[1] == 0) {
3249 temp[2] += 1;
3250 }
3251 }
3252
3253 temp128 = temp[2] & 0x01;
3254
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;
3261 }
3262 set_DSPControl_overflow_flag(1, 23, env);
3263 }
3264
3265 return (int64_t)(int32_t)(temp[0] >> 1);
3266 }
3267
3268 target_ulong helper_dextr_l(target_ulong ac, target_ulong shift,
3269 CPUMIPSState *env)
3270 {
3271 uint64_t temp[3];
3272 target_ulong result;
3273
3274 shift = shift & 0x3F;
3275
3276 mipsdsp_rndrashift_acc(temp, ac, shift, env);
3277 result = (temp[1] << 63) | (temp[0] >> 1);
3278
3279 return result;
3280 }
3281
3282 target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift,
3283 CPUMIPSState *env)
3284 {
3285 uint64_t temp[3];
3286 uint32_t temp128;
3287 target_ulong result;
3288
3289 shift = shift & 0x3F;
3290 mipsdsp_rndrashift_acc(temp, ac, shift, env);
3291
3292 temp[0] += 1;
3293 if (temp[0] == 0) {
3294 temp[1] += 1;
3295 if (temp[1] == 0) {
3296 temp[2] += 1;
3297 }
3298 }
3299
3300 temp128 = temp[2] & 0x01;
3301
3302 if ((temp128 != 0 || temp[1] != 0) &&
3303 (temp128 != 1 || temp[1] != ~0ull)) {
3304 set_DSPControl_overflow_flag(1, 23, env);
3305 }
3306
3307 result = (temp[1] << 63) | (temp[0] >> 1);
3308
3309 return result;
3310 }
3311
3312 target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift,
3313 CPUMIPSState *env)
3314 {
3315 uint64_t temp[3];
3316 uint32_t temp128;
3317 target_ulong result;
3318
3319 shift = shift & 0x3F;
3320 mipsdsp_rndrashift_acc(temp, ac, shift, env);
3321
3322 temp[0] += 1;
3323 if (temp[0] == 0) {
3324 temp[1] += 1;
3325 if (temp[1] == 0) {
3326 temp[2] += 1;
3327 }
3328 }
3329
3330 temp128 = temp[2] & 0x01;
3331
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;
3340 }
3341 set_DSPControl_overflow_flag(1, 23, env);
3342 }
3343 result = (temp[1] << 63) | (temp[0] >> 1);
3344
3345 return result;
3346 }
3347 #endif
3348
3349 target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift,
3350 CPUMIPSState *env)
3351 {
3352 int64_t temp, acc;
3353
3354 shift = shift & 0x1F;
3355
3356 acc = ((int64_t)env->active_tc.HI[ac] << 32) |
3357 ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
3358
3359 temp = acc >> shift;
3360
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);
3367 }
3368
3369 return (target_long)(int32_t)(temp & 0xFFFFFFFF);
3370 }
3371
3372
3373 #if defined(TARGET_MIPS64)
3374 target_ulong helper_dextr_s_h(target_ulong ac, target_ulong shift,
3375 CPUMIPSState *env)
3376 {
3377 int64_t temp[2];
3378 uint32_t temp127;
3379
3380 shift = shift & 0x1F;
3381
3382 mipsdsp_rashift_acc((uint64_t *)temp, ac, shift, env);
3383
3384 temp127 = (temp[1] >> 63) & 0x01;
3385
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);
3396 }
3397
3398 return (int64_t)(int16_t)(temp[0] & MIPSDSP_LO);
3399 }
3400
3401 #endif
3402
3403 target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState *env)
3404 {
3405 int32_t start_pos;
3406 int sub;
3407 uint32_t temp;
3408 uint64_t acc;
3409
3410 size = size & 0x1F;
3411
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);
3423 }
3424
3425 return (target_ulong)temp;
3426 }
3427
3428 target_ulong helper_extpdp(target_ulong ac, target_ulong size,
3429 CPUMIPSState *env)
3430 {
3431 int32_t start_pos;
3432 int sub;
3433 uint32_t temp;
3434 uint64_t acc;
3435
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);
3445
3446 set_DSPControl_pos(start_pos - (size + 1), env);
3447 set_DSPControl_efi(0, env);
3448 } else {
3449 set_DSPControl_efi(1, env);
3450 }
3451
3452 return (target_ulong)temp;
3453 }
3454
3455
3456 #if defined(TARGET_MIPS64)
3457 target_ulong helper_dextp(target_ulong ac, target_ulong size, CPUMIPSState *env)
3458 {
3459 int start_pos;
3460 int len;
3461 int sub;
3462 uint64_t tempB, tempA;
3463 uint64_t temp;
3464
3465 temp = 0;
3466
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];
3472
3473 sub = start_pos - (size + 1);
3474
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);
3481 }
3482
3483 return temp;
3484 }
3485
3486 target_ulong helper_dextpdp(target_ulong ac, target_ulong size,
3487 CPUMIPSState *env)
3488 {
3489 int start_pos;
3490 int len;
3491 int sub;
3492 uint64_t tempB, tempA;
3493 uint64_t temp;
3494
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];
3501
3502 sub = start_pos - (size + 1);
3503
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);
3511 }
3512
3513 return temp;
3514 }
3515
3516 #endif
3517
3518 void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env)
3519 {
3520 int8_t rs5_0;
3521 uint64_t temp, acc;
3522
3523 rs5_0 = rs & 0x3F;
3524 rs5_0 = (int8_t)(rs5_0 << 2) >> 2;
3525
3526 if (unlikely(rs5_0 == 0)) {
3527 return;
3528 }
3529
3530 acc = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) |
3531 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
3532
3533 if (rs5_0 > 0) {
3534 temp = acc >> rs5_0;
3535 } else {
3536 temp = acc << -rs5_0;
3537 }
3538
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);
3541 }
3542
3543 #if defined(TARGET_MIPS64)
3544 void helper_dshilo(target_ulong shift, target_ulong ac, CPUMIPSState *env)
3545 {
3546 int8_t shift_t;
3547 uint64_t tempB, tempA;
3548
3549 shift_t = (int8_t)(shift << 1) >> 1;
3550
3551 tempB = env->active_tc.HI[ac];
3552 tempA = env->active_tc.LO[ac];
3553
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;
3562 }
3563 }
3564
3565 env->active_tc.HI[ac] = tempB;
3566 env->active_tc.LO[ac] = tempA;
3567 }
3568
3569 #endif
3570 void helper_mthlip(target_ulong ac, target_ulong rs, CPUMIPSState *env)
3571 {
3572 int32_t tempA, tempB, pos;
3573
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);
3579
3580 if (pos > 32) {
3581 return;
3582 } else {
3583 set_DSPControl_pos(pos + 32, env);
3584 }
3585 }
3586
3587 #if defined(TARGET_MIPS64)
3588 void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env)
3589 {
3590 uint8_t ac_t;
3591 uint8_t pos;
3592 uint64_t tempB, tempA;
3593
3594 ac_t = ac & 0x3;
3595
3596 tempA = rs;
3597 tempB = env->active_tc.LO[ac_t];
3598
3599 env->active_tc.HI[ac_t] = tempB;
3600 env->active_tc.LO[ac_t] = tempA;
3601
3602 pos = get_DSPControl_pos(env);
3603
3604 if (pos <= 64) {
3605 pos = pos + 64;
3606 set_DSPControl_pos(pos, env);
3607 }
3608 }
3609 #endif
3610
3611 void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env)
3612 {
3613 uint8_t mask[6];
3614 uint8_t i;
3615 uint32_t newbits, overwrite;
3616 target_ulong dsp;
3617
3618 newbits = 0x00;
3619 overwrite = 0xFFFFFFFF;
3620 dsp = env->active_tc.DSPControl;
3621
3622 for (i = 0; i < 6; i++) {
3623 mask[i] = (mask_num >> i) & 0x01;
3624 }
3625
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
3636 }
3637
3638 if (mask[1] == 1) {
3639 overwrite &= 0xFFFFE07F;
3640 newbits &= 0xFFFFE07F;
3641 newbits |= 0x00001F80 & rs;
3642 }
3643
3644 if (mask[2] == 1) {
3645 overwrite &= 0xFFFFDFFF;
3646 newbits &= 0xFFFFDFFF;
3647 newbits |= 0x00002000 & rs;
3648 }
3649
3650 if (mask[3] == 1) {
3651 overwrite &= 0xFF00FFFF;
3652 newbits &= 0xFF00FFFF;
3653 newbits |= 0x00FF0000 & rs;
3654 }
3655
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
3664 }
3665
3666 if (mask[5] == 1) {
3667 overwrite &= 0xFFFFBFFF;
3668 newbits &= 0xFFFFBFFF;
3669 newbits |= 0x00004000 & rs;
3670 }
3671
3672 dsp = dsp & overwrite;
3673 dsp = dsp | newbits;
3674 env->active_tc.DSPControl = dsp;
3675 }
3676
3677 void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
3678 {
3679 return cpu_wrdsp(rs, mask_num, env);
3680 }
3681
3682 uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env)
3683 {
3684 uint8_t mask[6];
3685 uint32_t ruler, i;
3686 target_ulong temp;
3687 target_ulong dsp;
3688
3689 ruler = 0x01;
3690 for (i = 0; i < 6; i++) {
3691 mask[i] = (mask_num & ruler) >> i ;
3692 ruler = ruler << 1;
3693 }
3694
3695 temp = 0x00;
3696 dsp = env->active_tc.DSPControl;
3697
3698 if (mask[0] == 1) {
3699 #if defined(TARGET_MIPS64)
3700 temp |= dsp & 0x7F;
3701 #else
3702 temp |= dsp & 0x3F;
3703 #endif
3704 }
3705
3706 if (mask[1] == 1) {
3707 temp |= dsp & 0x1F80;
3708 }
3709
3710 if (mask[2] == 1) {
3711 temp |= dsp & 0x2000;
3712 }
3713
3714 if (mask[3] == 1) {
3715 temp |= dsp & 0x00FF0000;
3716 }
3717
3718 if (mask[4] == 1) {
3719 #if defined(TARGET_MIPS64)
3720 temp |= dsp & 0xFF000000;
3721 #else
3722 temp |= dsp & 0x0F000000;
3723 #endif
3724 }
3725
3726 if (mask[5] == 1) {
3727 temp |= dsp & 0x4000;
3728 }
3729
3730 return temp;
3731 }
3732
3733 target_ulong helper_rddsp(target_ulong mask_num, CPUMIPSState *env)
3734 {
3735 return cpu_rddsp(mask_num, env);
3736 }
3737
3738
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
3747
3748 #undef MIPSDSP_SPLIT32_8
3749 #undef MIPSDSP_SPLIT32_16
3750
3751 #undef MIPSDSP_RETURN32_8
3752 #undef MIPSDSP_RETURN32_16
3753
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