3 // Simulator definition for the MIPS DSP ASE.
4 // Copyright (C) 2005-2019 Free Software Foundation, Inc.
5 // Contributed by MIPS Technologies, Inc. Written by Chao-ying Fu.
7 // This file is part of the MIPS sim
9 // This program is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 3 of the License, or
12 // (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
19 // You should have received a copy of the GNU General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 // op: 0 = ADD, 1 = SUB, 2 = MUL
24 // sat: 0 = no saturation, 1 = saturation
25 :function:::void:do_ph_op:int rd, int rs, int rt, int op, int sat
30 unsigned32 v1 = GPR[rs];
31 unsigned32 v2 = GPR[rt];
32 unsigned32 result = 0;
33 for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
35 h1 = (signed16)(v1 & 0xffff);
36 h2 = (signed16)(v2 & 0xffff);
38 h0 = (signed32)h1 + (signed32)h2;
39 else if (op == 1) // SUB
40 h0 = (signed32)h1 - (signed32)h2;
42 h0 = (signed32)h1 * (signed32)h2;
43 if (h0 > (signed32)0x7fff || h0 < (signed32)0xffff8000)
45 if (op == 0 || op == 1) // ADD, SUB
46 DSPCR |= DSPCR_OUFLAG4;
47 else if (op == 2) // MUL
48 DSPCR |= DSPCR_OUFLAG5;
51 if (h0 > (signed32)0x7fff)
57 result |= ((unsigned32)((unsigned16)h0) << i);
59 GPR[rd] = EXTEND32 (result);
62 // op: 0 = ADD, 1 = SUB
63 :function:::void:do_w_op:int rd, int rs, int rt, int op
67 unsigned32 v1 = GPR[rs];
68 unsigned32 v2 = GPR[rt];
69 unsigned32 result = 0;
73 h0 = (signed64)h1 + (signed64)h2;
75 h0 = (signed64)h1 - (signed64)h2;
76 if (((h0 & 0x100000000LL) >> 1) != (h0 & 0x80000000))
78 DSPCR |= DSPCR_OUFLAG4;
79 if (h0 & 0x100000000LL)
84 GPR[rd] = EXTEND32 (h0);
87 // op: 0 = ADD, 1 = SUB
88 // sat: 0 = no saturation, 1 = saturation
89 :function:::void:do_qb_op:int rd, int rs, int rt, int op, int sat
94 unsigned32 v1 = GPR[rs];
95 unsigned32 v2 = GPR[rt];
96 unsigned32 result = 0;
97 for (i = 0; i < 32; i += 8, v1 >>= 8, v2 >>= 8)
99 h1 = (unsigned8)(v1 & 0xff);
100 h2 = (unsigned8)(v2 & 0xff);
102 h0 = (unsigned32)h1 + (unsigned32)h2;
104 h0 = (unsigned32)h1 - (unsigned32)h2;
107 DSPCR |= DSPCR_OUFLAG4;
116 result |= ((unsigned32)((unsigned8)h0) << i);
118 GPR[rd] = EXTEND32 (result);
121 // op: 0 = left, 1 = right
122 :function:::void:do_qb_shift:int rd, int rt, int shift, int op
126 unsigned32 v1 = GPR[rt];
127 unsigned32 result = 0;
128 for (i = 0; i < 32; i += 8, v1 >>= 8)
130 h0 = (unsigned8)(v1 & 0xff);
133 for (j = 7; j >= 8 - shift; j--)
137 DSPCR |= DSPCR_OUFLAG6;
145 result |= ((unsigned32)h0 << i);
147 GPR[rd] = EXTEND32 (result);
150 // op: 0 = left, 1 = right
151 // sat: 0 = no saturation/rounding, 1 = saturation/rounding
152 :function:::void:do_ph_shift:int rd, int rt, int shift, int op, int sat
156 unsigned32 v1 = GPR[rt];
157 unsigned32 result = 0;
159 for (i = 0; i < 32; i += 16, v1 >>= 16)
161 h0 = (signed16)(v1 & 0xffff);
167 for (j = 14; j >= 15 - shift; j--)
169 if (!(h0 & (1 << j)))
171 DSPCR |= DSPCR_OUFLAG6;
179 for (j = 14; j >= 15 - shift; j--)
183 DSPCR |= DSPCR_OUFLAG6;
194 else if (setcond == 1)
200 if (sat == 1 && shift != 0 && (h0 & (1 << (shift-1))))
201 h0 = (h0 >> shift) + 1;
206 result |= ((unsigned32)((unsigned16)h0) << i);
208 GPR[rd] = EXTEND32 (result);
211 :function:::void:do_w_shll:int rd, int rt, int shift
214 unsigned32 v1 = GPR[rt];
215 unsigned32 result = 0;
219 for (i = 30; i >= 31 - shift; i--)
221 if (!(v1 & (1 << i)))
223 DSPCR |= DSPCR_OUFLAG6;
231 for (i = 30; i >= 31 - shift; i--)
235 DSPCR |= DSPCR_OUFLAG6;
243 else if (setcond == 1)
246 result = v1 << shift;
247 GPR[rd] = EXTEND32 (result);
250 :function:::void:do_ph_s_absq:int rd, int rt
254 unsigned32 v1 = GPR[rt];
255 unsigned32 result = 0;
256 for (i = 0; i < 32; i += 16, v1 >>= 16)
258 h0 = (signed16)(v1 & 0xffff);
259 if (h0 == (signed16)0x8000)
261 DSPCR |= DSPCR_OUFLAG4;
264 else if (h0 & 0x8000)
266 result |= ((unsigned32)((unsigned16)h0) << i);
268 GPR[rd] = EXTEND32 (result);
271 :function:::void:do_w_s_absq:int rd, int rt
273 unsigned32 v1 = GPR[rt];
274 signed32 h0 = (signed32)v1;
275 if (h0 == (signed32)0x80000000)
277 DSPCR |= DSPCR_OUFLAG4;
280 else if (h0 & 0x80000000)
282 GPR[rd] = EXTEND32 (h0);
285 :function:::void:do_qb_s_absq:int rd, int rt
289 unsigned32 v1 = GPR[rt];
290 unsigned32 result = 0;
291 for (i = 0; i < 32; i += 8, v1 >>= 8)
293 q0 = (signed8)(v1 & 0xff);
294 if (q0 == (signed8)0x80)
296 DSPCR |= DSPCR_OUFLAG4;
301 result |= ((unsigned32)((unsigned8)q0) << i);
303 GPR[rd] = EXTEND32 (result);
306 :function:::void:do_addsc:int rd, int rs, int rt
308 unsigned32 v1 = GPR[rs];
309 unsigned32 v2 = GPR[rt];
311 h0 = (unsigned64)v1 + (unsigned64)v2;
312 if (h0 & 0x100000000LL)
313 DSPCR |= DSPCR_CARRY;
314 GPR[rd] = EXTEND32 (h0);
317 :function:::void:do_addwc:int rd, int rs, int rt
319 unsigned32 v1 = GPR[rs];
320 unsigned32 v2 = GPR[rt];
322 signed32 h1 = (signed32) v1;
323 signed32 h2 = (signed32) v2;
324 h0 = (signed64)h1 + (signed64)h2
325 + (signed64)((DSPCR >> DSPCR_CARRY_SHIFT) & DSPCR_CARRY_MASK);
326 if (((h0 & 0x100000000LL) >> 1) != (h0 & 0x80000000))
327 DSPCR |= DSPCR_OUFLAG4;
328 GPR[rd] = EXTEND32 (h0);
331 :function:::void:do_bitrev:int rd, int rt
334 unsigned32 v1 = GPR[rt];
336 for (i = 0; i < 16; i++)
339 h1 |= (1 << (15 - i));
341 GPR[rd] = EXTEND32 (h1);
344 // op: 0 = EXTPV, 1 = EXTPDPV
345 :function:::void:do_extpv:int rt, int ac, int rs, int op
347 unsigned32 size = GPR[rs] & 0x1f;
348 do_extp (SD_, rt, ac, size, op);
351 // op: 0 = EXTRV, 1 = EXTRV_R, 2 = EXTRV_RS
352 :function:::void:do_extrv:int rt, int ac, int rs, int op
354 unsigned32 shift = GPR[rs] & 0x1f;
355 do_w_extr (SD_, rt, ac, shift, op);
358 :function:::void:do_extrv_s_h:int rt, int ac, int rs
360 unsigned32 shift = GPR[rs] & 0x1f;
361 do_h_extr (SD_, rt, ac, shift);
364 :function:::void:do_insv:int rt, int rs
366 unsigned32 v1 = GPR[rs];
367 unsigned32 v2 = GPR[rt];
368 unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
369 unsigned32 size = (DSPCR >> DSPCR_SCOUNT_SHIFT) & DSPCR_SCOUNT_MASK;
370 unsigned32 mask1, mask2, mask3, result;
372 mask1 = (1 << size) - 1;
375 mask2 = (1 << pos) - 1;
377 mask3 = ~((1 << (pos + size)) - 1);
380 result = (v2 & mask3) | ((v1 & mask1) << pos) | (v2 & mask2);
381 GPR[rt] = EXTEND32 (result);
384 // op: 0 = NORMAL, 1 = EXTEND16, 2 = EXTEND32
385 :function:::void:do_lxx:int rd, int base, int index, int op
388 GPR[rd] = do_load (SD_, AccessLength_BYTE, GPR[base], GPR[index]);
390 GPR[rd] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[base], GPR[index]));
392 GPR[rd] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[base], GPR[index]));
395 :function:::void:do_modsub:int rd, int rs, int rt
397 unsigned32 result = 0;
398 unsigned32 v1 = GPR[rs];
399 unsigned32 v2 = GPR[rt];
400 unsigned32 decr = v2 & 0xff;
401 unsigned32 lastindex = (v2 & 0xffff00) >> 8;
406 GPR[rd] = EXTEND32 (result);
409 :function:::void:do_mthlip:int rs, int ac
411 unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
412 DSPHI(ac) = DSPLO(ac);
418 DSPCR &= (~DSPCR_POS_SMASK);
419 DSPCR |= (pos & DSPCR_POS_MASK) << DSPCR_POS_SHIFT;
422 :function:::void:do_mulsaq_s_w_ph:int ac, int rs, int rt
425 unsigned32 v1 = GPR[rs];
426 unsigned32 v2 = GPR[rt];
429 unsigned32 lo = DSPLO(ac);
430 unsigned32 hi = DSPHI(ac);
431 signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo);
432 for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
434 h1 = (signed16)(v1 & 0xffff);
435 h2 = (signed16)(v2 & 0xffff);
436 if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
438 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
439 result = (signed32) 0x7fffffff;
442 result = ((signed32)h1 * (signed32)h2) << 1;
445 prod -= (signed64) result;
447 prod += (signed64) result;
449 DSPLO(ac) = EXTEND32 (prod);
450 DSPHI(ac) = EXTEND32 (prod >> 32);
453 :function:::void:do_ph_packrl:int rd, int rs, int rt
456 unsigned32 v1 = GPR[rs];
457 unsigned32 v2 = GPR[rt];
458 GPR[rd] = EXTEND32 ((v1 << 16) + (v2 >> 16));
461 :function:::void:do_qb_pick:int rd, int rs, int rt
464 unsigned32 v1 = GPR[rs];
465 unsigned32 v2 = GPR[rt];
467 unsigned32 result = 0;
468 for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
470 h1 = (unsigned8)(v1 & 0xff);
471 h2 = (unsigned8)(v2 & 0xff);
472 if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j)))
473 result |= (unsigned32)(h1 << i);
475 result |= (unsigned32)(h2 << i);
477 GPR[rd] = EXTEND32 (result);
480 :function:::void:do_ph_pick:int rd, int rs, int rt
483 unsigned32 v1 = GPR[rs];
484 unsigned32 v2 = GPR[rt];
486 unsigned32 result = 0;
487 for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16)
489 h1 = (unsigned16)(v1 & 0xffff);
490 h2 = (unsigned16)(v2 & 0xffff);
491 if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j)))
492 result |= (unsigned32)(h1 << i);
494 result |= (unsigned32)(h2 << i);
496 GPR[rd] = EXTEND32 (result);
499 // op: 0 = QBR, 1 = QBRA, 2 = QBL, 3 = QBLA
500 :function:::void:do_qb_ph_precequ:int rd, int rt, int op
502 unsigned32 v1 = GPR[rt];
504 GPR[rd] = EXTEND32 ((v1 & 0xff00) << 15) | ((v1 & 0xff) << 7);
506 GPR[rd] = EXTEND32 ((v1 & 0xff0000) << 7) | ((v1 & 0xff) << 7);
508 GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff0000) >> 9);
510 GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff00) >> 1);
513 // op: 0 = QBR, 1 = QBRA, 2 = QBL, 3 = QBLA
514 :function:::void:do_qb_ph_preceu:int rd, int rt, int op
516 unsigned32 v1 = GPR[rt];
518 GPR[rd] = EXTEND32 ((v1 & 0xff00) << 8) | (v1 & 0xff);
520 GPR[rd] = EXTEND32 ((v1 & 0xff0000) | (v1 & 0xff));
522 GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff0000) >> 16);
524 GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff00) >> 8);
527 // op: 0 = .PHL, 1 = PHR
528 :function:::void:do_w_preceq:int rd, int rt, int op
530 unsigned32 v1 = GPR[rt];
532 GPR[rd] = EXTEND32 (v1 & 0xffff0000);
534 GPR[rd] = EXTEND32 ((v1 & 0xffff) << 16);
537 :function:::void:do_w_ph_precrq:int rd, int rs, int rt
539 unsigned32 v1 = GPR[rs];
540 unsigned32 v2 = GPR[rt];
541 unsigned32 tempu = (v1 & 0xffff0000) >> 16;
542 unsigned32 tempv = (v2 & 0xffff0000) >> 16;
543 GPR[rd] = EXTEND32 ((tempu << 16) | tempv);
546 // sat: 0 = PRECRQ.QB.PH, 1 = PRECRQU_S.QB.PH
547 :function:::void:do_ph_qb_precrq:int rd, int rs, int rt, int sat
549 unsigned32 v1 = GPR[rs];
550 unsigned32 v2 = GPR[rt];
551 unsigned32 tempu = 0, tempv = 0, tempw = 0, tempx = 0;
554 tempu = (v1 & 0xff000000) >> 24;
555 tempv = (v1 & 0xff00) >> 8;
556 tempw = (v2 & 0xff000000) >> 24;
557 tempx = (v2 & 0xff00) >> 8;
563 DSPCR |= DSPCR_OUFLAG6;
566 else if (!(v1 & 0x80000000) && ((v1 >> 16) > (unsigned32)0x7f80))
568 DSPCR |= DSPCR_OUFLAG6;
572 tempu = (v1 & 0x7f800000) >> 23;
575 DSPCR |= DSPCR_OUFLAG6;
578 else if (!(v1 & 0x8000) && ((v1 & 0xffff) > (unsigned32)0x7f80))
580 DSPCR |= DSPCR_OUFLAG6;
584 tempv = (v1 & 0x7f80) >> 7;
587 DSPCR |= DSPCR_OUFLAG6;
590 else if (!(v2 & 0x80000000) && ((v2 >> 16) > (unsigned32)0x7f80))
592 DSPCR |= DSPCR_OUFLAG6;
596 tempw = (v2 & 0x7f800000) >> 23;
599 DSPCR |= DSPCR_OUFLAG6;
602 else if (!(v2 & 0x8000) && ((v2 & 0xffff) > (unsigned32)0x7f80))
604 DSPCR |= DSPCR_OUFLAG6;
608 tempx = (v2 & 0x7f80) >> 7;
610 GPR[rd] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx);
613 :function:::void:do_w_ph_rs_precrq:int rd, int rs, int rt
615 unsigned32 v1 = GPR[rs];
616 unsigned32 v2 = GPR[rt];
617 signed32 h1 = (signed32)v1;
618 signed32 h2 = (signed32)v2;
619 signed64 temp1 = (signed64)h1 + (signed64)0x8000;
621 signed64 temp3 = (signed64)h2 + (signed64)0x8000;
623 if (((temp1 & 0x100000000LL) >> 1) != (temp1 & 0x80000000))
625 DSPCR |= DSPCR_OUFLAG6;
629 temp2 = (signed32)((temp1 & 0xffff0000) >> 16);
630 if (((temp3 & 0x100000000LL) >> 1) != (temp3 & 0x80000000))
632 DSPCR |= DSPCR_OUFLAG6;
636 temp4 = (signed32)((temp3 & 0xffff0000) >> 16);
637 GPR[rd] = EXTEND32 ((temp2 << 16) | temp4);
640 :function:::void:do_qb_w_raddu:int rd, int rs
644 unsigned32 v1 = GPR[rs];
645 unsigned32 result = 0;
646 for (i = 0; i < 32; i += 8, v1 >>= 8)
648 h0 = (unsigned8)(v1 & 0xff);
649 result += (unsigned32)h0;
651 GPR[rd] = EXTEND32 (result);
654 :function:::void:do_rddsp:int rd, int mask
656 unsigned32 result = 0;
659 result &= (~DSPCR_POS_SMASK);
660 result |= (DSPCR & DSPCR_POS_SMASK);
664 result &= (~DSPCR_SCOUNT_SMASK);
665 result |= (DSPCR & DSPCR_SCOUNT_SMASK);
669 result &= (~DSPCR_CARRY_SMASK);
670 result |= (DSPCR & DSPCR_CARRY_SMASK);
674 result &= (~DSPCR_OUFLAG_SMASK);
675 result |= (DSPCR & DSPCR_OUFLAG_SMASK);
679 result &= (~DSPCR_CCOND_SMASK);
680 result |= (DSPCR & DSPCR_CCOND_SMASK);
684 result &= (~DSPCR_EFI_SMASK);
685 result |= (DSPCR & DSPCR_EFI_SMASK);
687 GPR[rd] = EXTEND32 (result);
690 // op: 0 = REPL.QB, 1 = REPLV.QB, 2 = REPL.PH, 3 = REPLV.PH
691 :function:::void:do_repl:int rd, int p2, int op
694 GPR[rd] = EXTEND32 ((p2 << 24) | (p2 << 16) | (p2 << 8) | p2);
697 unsigned32 v1 = GPR[p2] & 0xff;
698 GPR[rd] = EXTEND32 ((v1 << 24) | (v1 << 16) | (v1 << 8) | v1);
705 GPR[rd] = EXTEND32 ((v1 << 16) | (v1 & 0xffff));
709 unsigned32 v1 = GPR[p2];
711 GPR[rd] = EXTEND32 ((v1 << 16) | v1);
715 :function:::void:do_shilov:int ac, int rs
717 signed32 shift = GPR[rs] & 0x3f;
718 do_shilo (SD_, ac, shift);
721 // op: 0 = SHLLV, 1 = SHRAV
722 // sat: 0 = normal, 1 = saturate/rounding
723 :function:::void:do_ph_shl:int rd, int rt, int rs, int op, int sat
725 unsigned32 shift = GPR[rs] & 0xf;
726 do_ph_shift (SD_, rd, rt, shift, op, sat);
729 // op: 0 = SHLLV, 1 = SHRLV
730 :function:::void:do_qb_shl:int rd, int rt, int rs, int op
732 unsigned32 shift = GPR[rs] & 0x7;
733 do_qb_shift (SD_, rd, rt, shift, op);
736 :function:::void:do_w_s_shllv:int rd, int rt, int rs
738 unsigned32 shift = GPR[rs] & 0x1f;
739 do_w_shll (SD_, rd, rt, shift);
742 :function:::void:do_ph_shrlv:int rd, int rt, int rs
744 unsigned32 shift = GPR[rs] & 0xf;
745 do_ph_shrl (SD_, rd, rt, shift);
748 :function:::void:do_w_r_shrav:int rd, int rt, int rs
750 unsigned32 shift = GPR[rs] & 0x1f;
751 do_w_shra (SD_, rd, rt, shift);
754 :function:::void:do_wrdsp:int rs, int mask
756 unsigned32 v1 = GPR[rs];
759 DSPCR &= (~DSPCR_POS_SMASK);
760 DSPCR |= (v1 & DSPCR_POS_SMASK);
764 DSPCR &= (~DSPCR_SCOUNT_SMASK);
765 DSPCR |= (v1 & DSPCR_SCOUNT_SMASK);
769 DSPCR &= (~DSPCR_CARRY_SMASK);
770 DSPCR |= (v1 & DSPCR_CARRY_SMASK);
774 DSPCR &= (~DSPCR_OUFLAG_SMASK);
775 DSPCR |= (v1 & DSPCR_OUFLAG_SMASK);
779 DSPCR &= (~DSPCR_CCOND_SMASK);
780 DSPCR |= (v1 & DSPCR_CCOND_SMASK);
784 DSPCR &= (~DSPCR_EFI_SMASK);
785 DSPCR |= (v1 & DSPCR_EFI_SMASK);
789 // round: 0 = no rounding, 1 = rounding
790 :function:::void:do_qb_shrav:int rd, int rt, int rs, int round
792 unsigned32 shift = GPR[rs] & 0x7;
793 do_qb_shra (SD_, rd, rt, shift, round);
796 :function:::void:do_append:int rt, int rs, int sa
798 unsigned32 v0 = GPR[rs];
799 unsigned32 v1 = GPR[rt];
801 unsigned32 mask = (1 << sa) - 1;
802 result = (v1 << sa) | (v0 & mask);
803 GPR[rt] = EXTEND32 (result);
806 :function:::void:do_balign:int rt, int rs, int bp
808 unsigned32 v0 = GPR[rs];
809 unsigned32 v1 = GPR[rt];
814 result = (v1 << 8 * bp) | (v0 >> 8 * (4 - bp));
815 GPR[rt] = EXTEND32 (result);
818 :function:::void:do_ph_w_mulsa:int ac, int rs, int rt
821 unsigned32 v1 = GPR[rs];
822 unsigned32 v2 = GPR[rt];
825 unsigned32 lo = DSPLO(ac);
826 unsigned32 hi = DSPHI(ac);
827 signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo);
828 for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
830 h1 = (signed16)(v1 & 0xffff);
831 h2 = (signed16)(v2 & 0xffff);
832 result = (signed32)h1 * (signed32)h2;
835 prod -= (signed64) result;
837 prod += (signed64) result;
839 DSPLO(ac) = EXTEND32 (prod);
840 DSPHI(ac) = EXTEND32 (prod >> 32);
843 :function:::void:do_ph_qb_precr:int rd, int rs, int rt
845 unsigned32 v1 = GPR[rs];
846 unsigned32 v2 = GPR[rt];
847 unsigned32 tempu = (v1 & 0xff0000) >> 16;
848 unsigned32 tempv = (v1 & 0xff);
849 unsigned32 tempw = (v2 & 0xff0000) >> 16;
850 unsigned32 tempx = (v2 & 0xff);
851 GPR[rd] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx);
854 :function:::void:do_prepend:int rt, int rs, int sa
856 unsigned32 v0 = GPR[rs];
857 unsigned32 v1 = GPR[rt];
862 result = (v0 << (32 - sa)) | (v1 >> sa);
863 GPR[rt] = EXTEND32 (result);
866 :function:::void:do_w_shra:int rd, int rt, int shift
868 unsigned32 result = GPR[rt];
869 signed32 h0 = (signed32)result;
870 if (shift != 0 && (h0 & (1 << (shift-1))))
871 h0 = (h0 >> shift) + 1;
874 GPR[rd] = EXTEND32 (h0);
877 011111,5.RS,5.RT,5.RD,01010,010000:SPECIAL3:32::ADDQ.PH
878 "addq.ph r<RD>, r<RS>, r<RT>"
881 do_ph_op (SD_, RD, RS, RT, 0, 0);
884 011111,5.RS,5.RT,5.RD,01110,010000:SPECIAL3:32::ADDQ_S.PH
885 "addq_s.ph r<RD>, r<RS>, r<RT>"
888 do_ph_op (SD_, RD, RS, RT, 0, 1);
891 011111,5.RS,5.RT,5.RD,10110,010000:SPECIAL3:32::ADDQ_S.W
892 "addq_s.w r<RD>, r<RS>, r<RT>"
895 do_w_op (SD_, RD, RS, RT, 0);
898 011111,5.RS,5.RT,5.RD,00000,010000:SPECIAL3:32::ADDU.QB
899 "addu.qb r<RD>, r<RS>, r<RT>"
902 do_qb_op (SD_, RD, RS, RT, 0, 0);
905 011111,5.RS,5.RT,5.RD,00100,010000:SPECIAL3:32::ADDU_S.QB
906 "addu_s.qb r<RD>, r<RS>, r<RT>"
909 do_qb_op (SD_, RD, RS, RT, 0, 1);
912 011111,5.RS,5.RT,5.RD,01011,010000:SPECIAL3:32::SUBQ.PH
913 "subq.ph r<RD>, r<RS>, r<RT>"
916 do_ph_op (SD_, RD, RS, RT, 1, 0);
919 011111,5.RS,5.RT,5.RD,01111,010000:SPECIAL3:32::SUBQ_S.PH
920 "subq_s.ph r<RD>, r<RS>, r<RT>"
923 do_ph_op (SD_, RD, RS, RT, 1, 1);
926 011111,5.RS,5.RT,5.RD,10111,010000:SPECIAL3:32::SUBQ_S.W
927 "subq_s.w r<RD>, r<RS>, r<RT>"
930 do_w_op (SD_, RD, RS, RT, 1);
933 011111,5.RS,5.RT,5.RD,00001,010000:SPECIAL3:32::SUBU.QB
934 "subu.qb r<RD>, r<RS>, r<RT>"
937 do_qb_op (SD_, RD, RS, RT, 1, 0);
940 011111,5.RS,5.RT,5.RD,00101,010000:SPECIAL3:32::SUBU_S.QB
941 "subu_s.qb r<RD>, r<RS>, r<RT>"
944 do_qb_op (SD_, RD, RS, RT, 1, 1);
947 011111,5.RS,5.RT,5.RD,10000,010000:SPECIAL3:32::ADDSC
948 "addsc r<RD>, r<RS>, r<RT>"
951 do_addsc (SD_, RD, RS, RT);
954 011111,5.RS,5.RT,5.RD,10001,010000:SPECIAL3:32::ADDWC
955 "addwc r<RD>, r<RS>, r<RT>"
958 do_addwc (SD_, RD, RS, RT);
961 011111,5.RS,5.RT,5.RD,10010,010000:SPECIAL3:32::MODSUB
962 "modsub r<RD>, r<RS>, r<RT>"
965 do_modsub (SD_, RD, RS, RT);
968 011111,5.RS,00000,5.RD,10100,010000:SPECIAL3:32::RADDU.W.QB
969 "raddu.w.qb r<RD>, r<RS>"
972 do_qb_w_raddu (SD_, RD, RS);
975 011111,00000,5.RT,5.RD,01001,010010:SPECIAL3:32::ABSQ_S.PH
976 "absq_s.ph r<RD>, r<RT>"
979 do_ph_s_absq (SD_, RD, RT);
982 011111,00000,5.RT,5.RD,10001,010010:SPECIAL3:32::ABSQ_S.W
983 "absq_s.w r<RD>, r<RT>"
986 do_w_s_absq (SD_, RD, RT);
989 011111,5.RS,5.RT,5.RD,01100,010001:SPECIAL3:32::PRECRQ.QB.PH
990 "precrq.qb.ph r<RD>, r<RS>, r<RT>"
993 do_ph_qb_precrq (SD_, RD, RS, RT, 0);
996 011111,5.RS,5.RT,5.RD,10100,010001:SPECIAL3:32::PRECRQ.PH.W
997 "precrq.ph.w r<RD>, r<RS>, r<RT>"
1000 do_w_ph_precrq (SD_, RD, RS, RT);
1003 011111,5.RS,5.RT,5.RD,10101,010001:SPECIAL3:32::PRECRQ_RS.PH.W
1004 "precrq_rs.ph.w r<RD>, r<RS>, r<RT>"
1007 do_w_ph_rs_precrq (SD_, RD, RS, RT);
1010 011111,5.RS,5.RT,5.RD,01111,010001:SPECIAL3:32::PRECRQU_S.QB.PH
1011 "precrqu_s.qb.ph r<RD>, r<RS>, r<RT>"
1014 do_ph_qb_precrq (SD_, RD, RS, RT, 1);
1017 011111,00000,5.RT,5.RD,01100,010010:SPECIAL3:32::PRECEQ.W.PHL
1018 "preceq.w.phl r<RD>, r<RT>"
1021 do_w_preceq (SD_, RD, RT, 0);
1024 011111,00000,5.RT,5.RD,01101,010010:SPECIAL3:32::PRECEQ.W.PHR
1025 "preceq.w.phr r<RD>, r<RT>"
1028 do_w_preceq (SD_, RD, RT, 1);
1031 011111,00000,5.RT,5.RD,00100,010010:SPECIAL3:32::PRECEQU.PH.QBL
1032 "precequ.ph.qbl r<RD>, r<RT>"
1035 do_qb_ph_precequ (SD_, RD, RT, 2);
1038 011111,00000,5.RT,5.RD,00101,010010:SPECIAL3:32::PRECEQU.PH.QBR
1039 "precequ.ph.qbr r<RD>, r<RT>"
1042 do_qb_ph_precequ (SD_, RD, RT, 0);
1045 011111,00000,5.RT,5.RD,00110,010010:SPECIAL3:32::PRECEQU.PH.QBLA
1046 "precequ.ph.qbla r<RD>, r<RT>"
1049 do_qb_ph_precequ (SD_, RD, RT, 3);
1052 011111,00000,5.RT,5.RD,00111,010010:SPECIAL3:32::PRECEQU.PH.QBRA
1053 "precequ.ph.qbra r<RD>, r<RT>"
1056 do_qb_ph_precequ (SD_, RD, RT, 1);
1059 011111,00000,5.RT,5.RD,11100,010010:SPECIAL3:32::PRECEU.PH.QBL
1060 "preceu.ph.qbl r<RD>, r<RT>"
1063 do_qb_ph_preceu (SD_, RD, RT, 2);
1066 011111,00000,5.RT,5.RD,11101,010010:SPECIAL3:32::PRECEU.PH.QBR
1067 "preceu.ph.qbr r<RD>, r<RT>"
1070 do_qb_ph_preceu (SD_, RD, RT, 0);
1073 011111,00000,5.RT,5.RD,11110,010010:SPECIAL3:32::PRECEU.PH.QBLA
1074 "preceu.ph.qbla r<RD>, r<RT>"
1077 do_qb_ph_preceu (SD_, RD, RT, 3);
1080 011111,00000,5.RT,5.RD,11111,010010:SPECIAL3:32::PRECEU.PH.QBRA
1081 "preceu.ph.qbra r<RD>, r<RT>"
1084 do_qb_ph_preceu (SD_, RD, RT, 1);
1087 011111,00,3.SHIFT3,5.RT,5.RD,00000,010011:SPECIAL3:32::SHLL.QB
1088 "shll.qb r<RD>, r<RT>, <SHIFT3>"
1091 do_qb_shift (SD_, RD, RT, SHIFT3, 0);
1094 011111,5.RS,5.RT,5.RD,00010,010011:SPECIAL3:32::SHLLV.QB
1095 "shllv.qb r<RD>, r<RT>, r<RS>"
1098 do_qb_shl (SD_, RD, RT, RS, 0);
1101 011111,0,4.SHIFT4,5.RT,5.RD,01000,010011:SPECIAL3:32::SHLL.PH
1102 "shll.ph r<RD>, r<RT>, <SHIFT4>"
1105 do_ph_shift (SD_, RD, RT, SHIFT4, 0, 0);
1108 011111,5.RS,5.RT,5.RD,01010,010011:SPECIAL3:32::SHLLV.PH
1109 "shllv.ph r<RD>, r<RT>, r<RS>"
1112 do_ph_shl (SD_, RD, RT, RS, 0, 0);
1115 011111,0,4.SHIFT4,5.RT,5.RD,01100,010011:SPECIAL3:32::SHLL_S.PH
1116 "shll_s.ph r<RD>, r<RT>, <SHIFT4>"
1119 do_ph_shift (SD_, RD, RT, SHIFT4, 0, 1);
1122 011111,5.RS,5.RT,5.RD,01110,010011:SPECIAL3:32::SHLLV_S.PH
1123 "shllv_s.ph r<RD>, r<RT>, r<RS>"
1126 do_ph_shl (SD_, RD, RT, RS, 0, 1);
1129 011111,5.SHIFT5,5.RT,5.RD,10100,010011:SPECIAL3:32::SHLL_S.W
1130 "shll_s.w r<RD>, r<RT>, <SHIFT5>"
1133 do_w_shll (SD_, RD, RT, SHIFT5);
1136 011111,5.RS,5.RT,5.RD,10110,010011:SPECIAL3:32::SHLLV_S.W
1137 "shllv_s.w r<RD>, r<RT>, r<RS>"
1140 do_w_s_shllv (SD_, RD, RT, RS);
1143 011111,00,3.SHIFT3,5.RT,5.RD,00001,010011:SPECIAL3:32::SHRL.QB
1144 "shrl.qb r<RD>, r<RT>, <SHIFT3>"
1147 do_qb_shift (SD_, RD, RT, SHIFT3, 1);
1150 011111,5.RS,5.RT,5.RD,00011,010011:SPECIAL3:32::SHRLV.QB
1151 "shrlv.qb r<RD>, r<RT>, r<RS>"
1154 do_qb_shl (SD_, RD, RT, RS, 1);
1157 011111,0,4.SHIFT4,5.RT,5.RD,01001,010011:SPECIAL3:32::SHRA.PH
1158 "shra.ph r<RD>, r<RT>, <SHIFT4>"
1161 do_ph_shift (SD_, RD, RT, SHIFT4, 1, 0);
1164 011111,5.RS,5.RT,5.RD,01011,010011:SPECIAL3:32::SHRAV.PH
1165 "shrav.ph r<RD>, r<RT>, r<RS>"
1168 do_ph_shl (SD_, RD, RT, RS, 1, 0);
1171 011111,0,4.SHIFT4,5.RT,5.RD,01101,010011:SPECIAL3:32::SHRA_R.PH
1172 "shra_r.ph r<RD>, r<RT>, <SHIFT4>"
1175 do_ph_shift (SD_, RD, RT, SHIFT4, 1, 1);
1178 011111,5.RS,5.RT,5.RD,01111,010011:SPECIAL3:32::SHRAV_R.PH
1179 "shrav_r.ph r<RD>, r<RT>, r<RS>"
1182 do_ph_shl (SD_, RD, RT, RS, 1, 1);
1185 011111,5.SHIFT5,5.RT,5.RD,10101,010011:SPECIAL3:32::SHRA_R.W
1186 "shra_r.w r<RD>, r<RT>, <SHIFT5>"
1189 do_w_shra (SD_, RD, RT, SHIFT5);
1192 011111,5.RS,5.RT,5.RD,10111,010011:SPECIAL3:32::SHRAV_R.W
1193 "shrav_r.w r<RD>, r<RT>, r<RS>"
1196 do_w_r_shrav (SD_, RD, RT, RS);
1199 // loc: 0 = qhl, 1 = qhr
1200 :function:::void:do_qb_muleu:int rd, int rs, int rt, int loc
1203 unsigned32 result = 0;
1204 unsigned32 v1 = GPR[rs];
1205 unsigned32 v2 = GPR[rt];
1210 for (i = 0; i < 32; i += 16, v1 >>= 8, v2 >>= 16)
1212 h1 = (unsigned16)(v1 & 0xff);
1213 h2 = (unsigned16)(v2 & 0xffff);
1214 prod = (unsigned32)h1 * (unsigned32)h2;
1217 DSPCR |= DSPCR_OUFLAG5;
1220 result |= ((unsigned32)prod << i);
1222 GPR[rd] = EXTEND32 (result);
1225 011111,5.RS,5.RT,5.RD,00110,010000:SPECIAL3:32::MULEU_S.PH.QBL
1226 "muleu_s.ph.qbl r<RD>, r<RS>, r<RT>"
1229 do_qb_muleu (SD_, RD, RS, RT, 0);
1232 011111,5.RS,5.RT,5.RD,00111,010000:SPECIAL3:32::MULEU_S.PH.QBR
1233 "muleu_s.ph.qbr r<RD>, r<RS>, r<RT>"
1236 do_qb_muleu (SD_, RD, RS, RT, 1);
1239 // round: 0 = no rounding, 1 = rounding
1240 :function:::void:do_ph_mulq:int rd, int rs, int rt, int round
1243 unsigned32 result = 0;
1244 unsigned32 v1 = GPR[rs];
1245 unsigned32 v2 = GPR[rt];
1248 for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
1250 h1 = (signed16)(v1 & 0xffff);
1251 h2 = (signed16)(v2 & 0xffff);
1252 if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
1254 DSPCR |= DSPCR_OUFLAG5;
1259 prod = ((signed32)h1 * (signed32)h2) << 1;
1261 prod += (signed32)0x8000;
1263 result |= (((unsigned32)prod >> 16) << i);
1265 GPR[rd] = EXTEND32 (result);
1268 011111,5.RS,5.RT,5.RD,11111,010000:SPECIAL3:32::MULQ_RS.PH
1269 "mulq_rs.ph r<RD>, r<RS>, r<RT>"
1272 do_ph_mulq (SD_, RD, RS, RT, 1);
1275 // loc: 0 = phl, 1 = phr
1276 :function:::void:do_ph_muleq:int rd, int rs, int rt, int loc
1278 unsigned32 v1 = GPR[rs];
1279 unsigned32 v2 = GPR[rt];
1284 h1 = (signed16)(v1 >> 16);
1285 h2 = (signed16)(v2 >> 16);
1289 h1 = (signed16)(v1 & 0xffff);
1290 h2 = (signed16)(v2 & 0xffff);
1292 if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
1294 DSPCR |= DSPCR_OUFLAG5;
1298 prod = ((signed32)h1 * (signed32)h2) << 1;
1299 GPR[rd] = EXTEND32 (prod);
1302 011111,5.RS,5.RT,5.RD,11100,010000:SPECIAL3:32::MULEQ_S.W.PHL
1303 "muleq_s.w.phl r<RD>, r<RS>, r<RT>"
1306 do_ph_muleq (SD_, RD, RS, RT, 0);
1309 011111,5.RS,5.RT,5.RD,11101,010000:SPECIAL3:32::MULEQ_S.W.PHR
1310 "muleq_s.w.phr r<RD>, r<RS>, r<RT>"
1313 do_ph_muleq (SD_, RD, RS, RT, 1);
1316 // op: 0 = DPAU 1 = DPSU
1317 // loc: 0 = qbl, 1 = qbr
1318 :function:::void:do_qb_dot_product:int ac, int rs, int rt, int op, int loc
1321 unsigned32 v1 = GPR[rs];
1322 unsigned32 v2 = GPR[rt];
1324 unsigned32 lo = DSPLO(ac);
1325 unsigned32 hi = DSPHI(ac);
1326 unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1332 for (i = 0; i < 16; i += 8, v1 >>= 8, v2 >>= 8)
1334 h1 = (unsigned8)(v1 & 0xff);
1335 h2 = (unsigned8)(v2 & 0xff);
1336 if (op == 0) // DPAU
1337 prod += (unsigned64)h1 * (unsigned64)h2;
1339 prod -= (unsigned64)h1 * (unsigned64)h2;
1341 DSPLO(ac) = EXTEND32 (prod);
1342 DSPHI(ac) = EXTEND32 (prod >> 32);
1345 011111,5.RS,5.RT,000,2.AC,00011,110000:SPECIAL3:32::DPAU.H.QBL
1346 "dpau.h.qbl ac<AC>, r<RS>, r<RT>"
1349 do_qb_dot_product (SD_, AC, RS, RT, 0, 0);
1352 011111,5.RS,5.RT,000,2.AC,00111,110000:SPECIAL3:32::DPAU.H.QBR
1353 "dpau.h.qbr ac<AC>, r<RS>, r<RT>"
1356 do_qb_dot_product (SD_, AC, RS, RT, 0, 1);
1359 011111,5.RS,5.RT,000,2.AC,01011,110000:SPECIAL3:32::DPSU.H.QBL
1360 "dpsu.h.qbl ac<AC>, r<RS>, r<RT>"
1363 do_qb_dot_product (SD_, AC, RS, RT, 1, 0);
1366 011111,5.RS,5.RT,000,2.AC,01111,110000:SPECIAL3:32::DPSU.H.QBR
1367 "dpsu.h.qbr ac<AC>, r<RS>, r<RT>"
1370 do_qb_dot_product (SD_, AC, RS, RT, 1, 1);
1373 // op: 0 = DPAQ 1 = DPSQ
1374 :function:::void:do_ph_dot_product:int ac, int rs, int rt, int op
1377 unsigned32 v1 = GPR[rs];
1378 unsigned32 v2 = GPR[rt];
1381 unsigned32 lo = DSPLO(ac);
1382 unsigned32 hi = DSPHI(ac);
1383 signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo);
1384 for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
1386 h1 = (signed16)(v1 & 0xffff);
1387 h2 = (signed16)(v2 & 0xffff);
1388 if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
1390 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1391 result = (signed32)0x7fffffff;
1394 result = ((signed32)h1 * (signed32)h2) << 1;
1396 if (op == 0) // DPAQ
1397 prod += (signed64)result;
1399 prod -= (signed64)result;
1401 DSPLO(ac) = EXTEND32 (prod);
1402 DSPHI(ac) = EXTEND32 (prod >> 32);
1405 011111,5.RS,5.RT,000,2.AC,00100,110000:SPECIAL3:32::DPAQ_S.W.PH
1406 "dpaq_s.w.ph ac<AC>, r<RS>, r<RT>"
1409 do_ph_dot_product (SD_, AC, RS, RT, 0);
1412 011111,5.RS,5.RT,000,2.AC,00101,110000:SPECIAL3:32::DPSQ_S.W.PH
1413 "dpsq_s.w.ph ac<AC>, r<RS>, r<RT>"
1416 do_ph_dot_product (SD_, AC, RS, RT, 1);
1419 011111,5.RS,5.RT,000,2.AC,00110,110000:SPECIAL3:32::MULSAQ_S.W.PH
1420 "mulsaq_s.w.ph ac<AC>, r<RS>, r<RT>"
1423 do_mulsaq_s_w_ph (SD_, AC, RS, RT);
1426 // op: 0 = DPAQ 1 = DPSQ
1427 :function:::void:do_w_dot_product:int ac, int rs, int rt, int op
1429 unsigned32 v1 = GPR[rs];
1430 unsigned32 v2 = GPR[rt];
1433 unsigned32 lo = DSPLO(ac);
1434 unsigned32 hi = DSPHI(ac);
1435 unsigned32 resultlo;
1436 unsigned32 resulthi;
1442 if (h1 == 0x80000000 && h2 == 0x80000000)
1444 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1445 result = (signed64) 0x7fffffffffffffffLL;
1448 result = ((signed64)h1 * (signed64)h2) << 1;
1449 resultlo = (unsigned32)(result);
1450 resulthi = (unsigned32)(result >> 32);
1453 temp1 = (unsigned64)lo + (unsigned64)resultlo;
1454 carry = (unsigned32)((temp1 >> 32) & 1);
1455 temp2 = (signed64)((signed32)hi) + (signed64)((signed32)resulthi) +
1456 (signed64)((signed32)carry);
1460 temp1 = (unsigned64)lo - (unsigned64)resultlo;
1461 carry = (unsigned32)((temp1 >> 32) & 1);
1462 temp2 = (signed64)((signed32)hi) - (signed64)((signed32)resulthi) -
1463 (signed64)((signed32)carry);
1465 if (((temp2 & 0x100000000LL) >> 1) != (temp2 & 0x80000000LL))
1467 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1468 if (temp2 & 0x100000000LL)
1470 DSPLO(ac) = EXTEND32 (0x00000000);
1471 DSPHI(ac) = EXTEND32 (0x80000000);
1475 DSPLO(ac) = EXTEND32 (0xffffffff);
1476 DSPHI(ac) = EXTEND32 (0x7fffffff);
1481 DSPLO(ac) = EXTEND32 (temp1);
1482 DSPHI(ac) = EXTEND32 (temp2);
1486 011111,5.RS,5.RT,000,2.AC,01100,110000:SPECIAL3:32::DPAQ_SA.L.W
1487 "dpaq_sa.l.w ac<AC>, r<RS>, r<RT>"
1490 do_w_dot_product (SD_, AC, RS, RT, 0);
1493 011111,5.RS,5.RT,000,2.AC,01101,110000:SPECIAL3:32::DPSQ_SA.L.W
1494 "dpsq_sa.l.w ac<AC>, r<RS>, r<RT>"
1497 do_w_dot_product (SD_, AC, RS, RT, 1);
1500 // op: 0 = MAQ_S 1 = MAQ_SA
1501 // loc: 0 = phl, 1 = phr
1502 :function:::void:do_ph_maq:int ac, int rs, int rt, int op, int loc
1505 unsigned32 v1 = GPR[rs];
1506 unsigned32 v2 = GPR[rt];
1509 unsigned32 lo = DSPLO(ac);
1510 unsigned32 hi = DSPHI(ac);
1511 signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo);
1514 h1 = (signed16)(v1 >> 16);
1515 h2 = (signed16)(v2 >> 16);
1519 h1 = (signed16)(v1 & 0xffff);
1520 h2 = (signed16)(v2 & 0xffff);
1522 if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
1524 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1525 result = (signed32)0x7fffffff;
1528 result = ((signed32)h1 * (signed32)h2) << 1;
1529 prod += (signed64)result;
1530 if (op == 1) // MAQ_SA
1532 if (prod & 0x8000000000000000LL)
1534 for (i = 62; i >= 31; i--)
1536 if (!(prod & ((signed64)1 << i)))
1538 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1539 prod = 0xffffffff80000000LL;
1546 for (i = 62; i >= 31; i--)
1548 if (prod & ((signed64)1 << i))
1550 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1557 DSPLO(ac) = EXTEND32 (prod);
1558 DSPHI(ac) = EXTEND32 (prod >> 32);
1561 011111,5.RS,5.RT,000,2.AC,10100,110000:SPECIAL3:32::MAQ_S.W.PHL
1562 "maq_s.w.phl ac<AC>, r<RS>, r<RT>"
1565 do_ph_maq (SD_, AC, RS, RT, 0, 0);
1568 011111,5.RS,5.RT,000,2.AC,10110,110000:SPECIAL3:32::MAQ_S.W.PHR
1569 "maq_s.w.phr ac<AC>, r<RS>, r<RT>"
1572 do_ph_maq (SD_, AC, RS, RT, 0, 1);
1575 011111,5.RS,5.RT,000,2.AC,10000,110000:SPECIAL3:32::MAQ_SA.W.PHL
1576 "maq_sa.w.phl ac<AC>, r<RS>, r<RT>"
1579 do_ph_maq (SD_, AC, RS, RT, 1, 0);
1582 011111,5.RS,5.RT,000,2.AC,10010,110000:SPECIAL3:32::MAQ_SA.W.PHR
1583 "maq_sa.w.phr ac<AC>, r<RS>, r<RT>"
1586 do_ph_maq (SD_, AC, RS, RT, 1, 1);
1589 011111,00000,5.RT,5.RD,11011,010010:SPECIAL3:32::BITREV
1590 "bitrev r<RD>, r<RT>"
1593 do_bitrev (SD_, RD, RT);
1596 011111,5.RS,5.RT,00000,00000,001100:SPECIAL3:32::INSV
1600 do_insv (SD_, RT, RS);
1603 011111,00,8.IMM8,5.RD,00010,010010:SPECIAL3:32::REPL.QB
1604 "repl.qb r<RD>, <IMM8>"
1607 do_repl (SD_, RD, IMM8, 0);
1610 011111,00000,5.RT,5.RD,00011,010010:SPECIAL3:32::REPLV.QB
1611 "replv.qb r<RD>, r<RT>"
1614 do_repl (SD_, RD, RT, 1);
1617 011111,10.IMM10,5.RD,01010,010010:SPECIAL3:32::REPL.PH
1618 "repl.ph r<RD>, <IMM10>"
1621 do_repl (SD_, RD, IMM10, 2);
1624 011111,00000,5.RT,5.RD,01011,010010:SPECIAL3:32::REPLV.PH
1625 "replv.ph r<RD>, r<RT>"
1628 do_repl (SD_, RD, RT, 3);
1631 // op: 0 = EQ, 1 = LT, 2 = LE
1632 :function:::void:do_qb_cmpu:int rs, int rt, int op
1635 unsigned32 v1 = GPR[rs];
1636 unsigned32 v2 = GPR[rt];
1639 for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1641 h1 = (unsigned8)(v1 & 0xff);
1642 h2 = (unsigned8)(v2 & 0xff);
1643 mask = ~(1 << (DSPCR_CCOND_SHIFT + j));
1646 DSPCR |= ((h1 == h2) << (DSPCR_CCOND_SHIFT + j));
1647 else if (op == 1) // LT
1648 DSPCR |= ((h1 < h2) << (DSPCR_CCOND_SHIFT + j));
1650 DSPCR |= ((h1 <= h2) << (DSPCR_CCOND_SHIFT + j));
1654 011111,5.RS,5.RT,00000,00000,010001:SPECIAL3:32::CMPU.EQ.QB
1655 "cmpu.eq.qb r<RS>, r<RT>"
1658 do_qb_cmpu (SD_, RS, RT, 0);
1661 011111,5.RS,5.RT,00000,00001,010001:SPECIAL3:32::CMPU.LT.QB
1662 "cmpu.lt.qb r<RS>, r<RT>"
1665 do_qb_cmpu (SD_, RS, RT, 1);
1668 011111,5.RS,5.RT,00000,00010,010001:SPECIAL3:32::CMPU.LE.QB
1669 "cmpu.le.qb r<RS>, r<RT>"
1672 do_qb_cmpu (SD_, RS, RT, 2);
1675 // op: 0 = EQ, 1 = LT, 2 = LE
1676 :function:::void:do_qb_cmpgu:int rd, int rs, int rt, int op
1679 unsigned32 v1 = GPR[rs];
1680 unsigned32 v2 = GPR[rt];
1682 unsigned32 result = 0;
1683 for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1685 h1 = (unsigned8)(v1 & 0xff);
1686 h2 = (unsigned8)(v2 & 0xff);
1688 result |= ((h1 == h2) << j);
1689 else if (op == 1) // LT
1690 result |= ((h1 < h2) << j);
1692 result |= ((h1 <= h2) << j);
1694 GPR[rd] = EXTEND32 (result);
1697 011111,5.RS,5.RT,5.RD,00100,010001:SPECIAL3:32::CMPGU.EQ.QB
1698 "cmpgu.eq.qb r<RD>, r<RS>, r<RT>"
1701 do_qb_cmpgu (SD_, RD, RS, RT, 0);
1704 011111,5.RS,5.RT,5.RD,00101,010001:SPECIAL3:32::CMPGU.LT.QB
1705 "cmpgu.lt.qb r<RD>, r<RS>, r<RT>"
1708 do_qb_cmpgu (SD_, RD, RS, RT, 1);
1711 011111,5.RS,5.RT,5.RD,00110,010001:SPECIAL3:32::CMPGU.LE.QB
1712 "cmpgu.le.qb r<RD>, r<RS>, r<RT>"
1715 do_qb_cmpgu (SD_, RD, RS, RT, 2);
1718 // op: 0 = EQ, 1 = LT, 2 = LE
1719 :function:::void:do_ph_cmpu:int rs, int rt, int op
1722 unsigned32 v1 = GPR[rs];
1723 unsigned32 v2 = GPR[rt];
1726 for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16)
1728 h1 = (signed16)(v1 & 0xffff);
1729 h2 = (signed16)(v2 & 0xffff);
1730 mask = ~(1 << (DSPCR_CCOND_SHIFT + j));
1733 DSPCR |= ((h1 == h2) << (DSPCR_CCOND_SHIFT + j));
1734 else if (op == 1) // LT
1735 DSPCR |= ((h1 < h2) << (DSPCR_CCOND_SHIFT + j));
1737 DSPCR |= ((h1 <= h2) << (DSPCR_CCOND_SHIFT + j));
1741 011111,5.RS,5.RT,00000,01000,010001:SPECIAL3:32::CMP.EQ.PH
1742 "cmp.eq.ph r<RS>, r<RT>"
1745 do_ph_cmpu (SD_, RS, RT, 0);
1748 011111,5.RS,5.RT,00000,01001,010001:SPECIAL3:32::CMP.LT.PH
1749 "cmp.lt.ph r<RS>, r<RT>"
1752 do_ph_cmpu (SD_, RS, RT, 1);
1755 011111,5.RS,5.RT,00000,01010,010001:SPECIAL3:32::CMP.LE.PH
1756 "cmp.le.ph r<RS>, r<RT>"
1759 do_ph_cmpu (SD_, RS, RT, 2);
1762 011111,5.RS,5.RT,5.RD,00011,010001:SPECIAL3:32::PICK.QB
1763 "pick.qb r<RD>, r<RS>, r<RT>"
1766 do_qb_pick (SD_, RD, RS, RT);
1769 011111,5.RS,5.RT,5.RD,01011,010001:SPECIAL3:32::PICK.PH
1770 "pick.ph r<RD>, r<RS>, r<RT>"
1773 do_ph_pick (SD_, RD, RS, RT);
1776 011111,5.RS,5.RT,5.RD,01110,010001:SPECIAL3:32::PACKRL.PH
1777 "packrl.ph r<RD>, r<RS>, r<RT>"
1780 do_ph_packrl (SD_, RD, RS, RT);
1783 // op: 0 = EXTR, 1 = EXTR_R, 2 = EXTR_RS
1784 :function:::void:do_w_extr:int rt, int ac, int shift, int op
1787 unsigned32 lo = DSPLO(ac);
1788 unsigned32 hi = DSPHI(ac);
1789 unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1790 signed64 result = (signed64)prod;
1792 if (!(prod & 0x8000000000000000LL))
1794 for (i = 62; i >= (shift + 31); i--)
1796 if (prod & ((unsigned64)1 << i))
1798 DSPCR |= DSPCR_OUFLAG7;
1803 if (((prod >> (shift - 1)) & 0xffffffffLL) == 0xffffffffLL)
1805 DSPCR |= DSPCR_OUFLAG7;
1811 for (i = 62; i >= (shift + 31); i--)
1813 if (!(prod & ((unsigned64)1 << i)))
1815 DSPCR |= DSPCR_OUFLAG7;
1821 if (op == 0) // EXTR
1822 result = result >> shift;
1823 else if (op == 1) // EXTR_R
1826 result = ((result >> (shift - 1)) + 1) >> 1;
1828 result = result >> shift;
1833 result = 0x7fffffff;
1834 else if (setcond == 2)
1835 result = 0x80000000;
1839 result = ((result >> (shift - 1)) + 1) >> 1;
1841 result = result >> shift;
1844 GPR[rt] = EXTEND32 (result);
1847 011111,5.SHIFT,5.RT,000,2.AC,00000,111000:SPECIAL3:32::EXTR.W
1848 "extr.w r<RT>, ac<AC>, <SHIFT>"
1851 do_w_extr (SD_, RT, AC, SHIFT, 0);
1854 011111,5.RS,5.RT,000,2.AC,00001,111000:SPECIAL3:32::EXTRV.W
1855 "extrv.w r<RT>, ac<AC>, r<RS>"
1858 do_extrv (SD_, RT, AC, RS, 0);
1861 011111,5.SHIFT,5.RT,000,2.AC,00100,111000:SPECIAL3:32::EXTR_R.W
1862 "extr_r.w r<RT>, ac<AC>, <SHIFT>"
1865 do_w_extr (SD_, RT, AC, SHIFT, 1);
1868 011111,5.RS,5.RT,000,2.AC,00101,111000:SPECIAL3:32::EXTRV_R.W
1869 "extrv_r.w r<RT>, ac<AC>, r<RS>"
1872 do_extrv (SD_, RT, AC, RS, 1);
1875 011111,5.SHIFT,5.RT,000,2.AC,00110,111000:SPECIAL3:32::EXTR_RS.W
1876 "extr_rs.w r<RT>, ac<AC>, <SHIFT>"
1879 do_w_extr (SD_, RT, AC, SHIFT, 2);
1882 011111,5.RS,5.RT,000,2.AC,00111,111000:SPECIAL3:32::EXTRV_RS.W
1883 "extrv_rs.w r<RT>, ac<AC>, r<RS>"
1886 do_extrv (SD_, RT, AC, RS, 2);
1889 :function:::void:do_h_extr:int rt, int ac, int shift
1892 unsigned32 lo = DSPLO(ac);
1893 unsigned32 hi = DSPHI(ac);
1894 unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1895 signed64 result = (signed64)prod;
1896 signed64 value = 0xffffffffffff8000LL;
1898 if (result > 0x7fff)
1901 DSPCR |= DSPCR_OUFLAG7;
1903 else if (result < value)
1906 DSPCR |= DSPCR_OUFLAG7;
1908 GPR[rt] = EXTEND32 (result);
1911 011111,5.SHIFT,5.RT,000,2.AC,01110,111000:SPECIAL3:32::EXTR_S.H
1912 "extr_s.h r<RT>, ac<AC>, <SHIFT>"
1915 do_h_extr (SD_, RT, AC, SHIFT);
1918 011111,5.RS,5.RT,000,2.AC,01111,111000:SPECIAL3:32::EXTRV_S.H
1919 "extrv_s.h r<RT>, ac<AC>, r<RS>"
1922 do_extrv_s_h (SD_, RT, AC, RS);
1925 // op: 0 = EXTP, 1 = EXTPDP
1926 :function:::void:do_extp:int rt, int ac, int size, int op
1928 signed32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
1929 unsigned32 lo = DSPLO(ac);
1930 unsigned32 hi = DSPHI(ac);
1931 unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1932 unsigned64 result = 0;
1933 if (pos - (size + 1) >= -1)
1935 prod >>= (pos - size);
1936 result = prod & (((unsigned64)1 << (size + 1)) - 1);
1937 DSPCR &= (~DSPCR_EFI_SMASK);
1938 if (op == 1) // EXTPDP
1940 if (pos - (size + 1) >= 0)
1942 DSPCR &= (~DSPCR_POS_SMASK);
1943 DSPCR |= ((pos - (size + 1)) & DSPCR_POS_MASK) << DSPCR_POS_SHIFT;
1945 else if (pos - (size + 1) == -1)
1947 DSPCR |= DSPCR_POS_SMASK;
1956 GPR[rt] = EXTEND32 (result);
1959 011111,5.SIZE,5.RT,000,2.AC,00010,111000:SPECIAL3:32::EXTP
1960 "extp r<RT>, ac<AC>, <SIZE>"
1963 do_extp (SD_, RT, AC, SIZE, 0);
1966 011111,5.RS,5.RT,000,2.AC,00011,111000:SPECIAL3:32::EXTPV
1967 "extpv r<RT>, ac<AC>, r<RS>"
1970 do_extpv (SD_, RT, AC, RS, 0);
1973 011111,5.SIZE,5.RT,000,2.AC,01010,111000:SPECIAL3:32::EXTPDP
1974 "extpdp r<RT>, ac<AC>, <SIZE>"
1977 do_extp (SD_, RT, AC, SIZE, 1);
1980 011111,5.RS,5.RT,000,2.AC,01011,111000:SPECIAL3:32::EXTPDPV
1981 "extpdpv r<RT>, ac<AC>, r<RS>"
1984 do_extpv (SD_, RT, AC, RS, 1);
1987 :function:::void:do_shilo:int ac, int shift
1989 unsigned32 lo = DSPLO(ac);
1990 unsigned32 hi = DSPHI(ac);
1991 unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1998 DSPLO(ac) = EXTEND32 (prod);
1999 DSPHI(ac) = EXTEND32 (prod >> 32);
2002 011111,6.SHIFT6,0000,000,2.AC,11010,111000:SPECIAL3:32::SHILO
2003 "shilo ac<AC>, <SHIFT6>"
2006 do_shilo (SD_, AC, SHIFT6);
2009 011111,5.RS,00000,000,2.AC,11011,111000:SPECIAL3:32::SHILOV
2010 "shilov ac<AC>, r<RS>"
2013 do_shilov (SD_, AC, RS);
2016 011111,5.RS,00000,000,2.AC,11111,111000:SPECIAL3:32::MTHLIP
2017 "mthlip r<RS>, ac<AC>"
2020 do_mthlip (SD_, RS, AC);
2023 011111,5.RS,10.MASK10,10011,111000:SPECIAL3:32::WRDSP
2024 "wrdsp r<RS>":MASK10 == 1111111111
2025 "wrdsp r<RS>, <MASK10>"
2028 do_wrdsp (SD_, RS, MASK10);
2031 011111,10.MASK10,5.RD,10010,111000:SPECIAL3:32::RDDSP
2032 "rddsp r<RD>":MASK10 == 1111111111
2033 "rddsp r<RD>, <MASK10>"
2036 do_rddsp (SD_, RD, MASK10);
2039 011111,5.BASE,5.INDEX,5.RD,00110,001010:SPECIAL3:32::LBUX
2040 "lbux r<RD>, r<INDEX>(r<BASE>)"
2043 do_lxx (SD_, RD, BASE, INDEX, 0);
2046 011111,5.BASE,5.INDEX,5.RD,00100,001010:SPECIAL3:32::LHX
2047 "lhx r<RD>, r<INDEX>(r<BASE>)"
2050 do_lxx (SD_, RD, BASE, INDEX, 1);
2053 011111,5.BASE,5.INDEX,5.RD,00000,001010:SPECIAL3:32::LWX
2054 "lwx r<RD>, r<INDEX>(r<BASE>)"
2057 do_lxx (SD_, RD, BASE, INDEX, 2);
2060 000001,00000,11100,16.OFFSET:REGIMM:32::BPOSGE32
2064 unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
2065 address_word offset = EXTEND16 (OFFSET) << 2;
2068 DELAY_SLOT (NIA + offset);