3 // Simulator definition for the MIPS DSP ASE.
4 // Copyright (C) 2005-2024 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 uint32_t v1 = GPR[rs];
31 uint32_t v2 = GPR[rt];
33 for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
35 h1 = (int16_t)(v1 & 0xffff);
36 h2 = (int16_t)(v2 & 0xffff);
38 h0 = (int32_t)h1 + (int32_t)h2;
39 else if (op == 1) // SUB
40 h0 = (int32_t)h1 - (int32_t)h2;
42 h0 = (int32_t)h1 * (int32_t)h2;
43 if (h0 > (int32_t)0x7fff || h0 < (int32_t)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 > (int32_t)0x7fff)
57 result |= ((uint32_t)((uint16_t)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 uint32_t v1 = GPR[rs];
68 uint32_t v2 = GPR[rt];
72 h0 = (int64_t)h1 + (int64_t)h2;
74 h0 = (int64_t)h1 - (int64_t)h2;
75 if (((h0 & 0x100000000LL) >> 1) != (h0 & 0x80000000))
77 DSPCR |= DSPCR_OUFLAG4;
78 if (h0 & 0x100000000LL)
83 GPR[rd] = EXTEND32 (h0);
86 // op: 0 = ADD, 1 = SUB
87 // sat: 0 = no saturation, 1 = saturation
88 :function:::void:do_qb_op:int rd, int rs, int rt, int op, int sat
93 uint32_t v1 = GPR[rs];
94 uint32_t v2 = GPR[rt];
96 for (i = 0; i < 32; i += 8, v1 >>= 8, v2 >>= 8)
98 h1 = (uint8_t)(v1 & 0xff);
99 h2 = (uint8_t)(v2 & 0xff);
101 h0 = (uint32_t)h1 + (uint32_t)h2;
103 h0 = (uint32_t)h1 - (uint32_t)h2;
106 DSPCR |= DSPCR_OUFLAG4;
115 result |= ((uint32_t)((uint8_t)h0) << i);
117 GPR[rd] = EXTEND32 (result);
120 // op: 0 = left, 1 = right
121 :function:::void:do_qb_shift:int rd, int rt, int shift, int op
125 uint32_t v1 = GPR[rt];
127 for (i = 0; i < 32; i += 8, v1 >>= 8)
129 h0 = (uint8_t)(v1 & 0xff);
132 for (j = 7; j >= 8 - shift; j--)
136 DSPCR |= DSPCR_OUFLAG6;
144 result |= ((uint32_t)h0 << i);
146 GPR[rd] = EXTEND32 (result);
149 // op: 0 = left, 1 = right
150 // sat: 0 = no saturation/rounding, 1 = saturation/rounding
151 :function:::void:do_ph_shift:int rd, int rt, int shift, int op, int sat
155 uint32_t v1 = GPR[rt];
158 for (i = 0; i < 32; i += 16, v1 >>= 16)
160 h0 = (int16_t)(v1 & 0xffff);
166 for (j = 14; j >= 15 - shift; j--)
168 if (!(h0 & (1 << j)))
170 DSPCR |= DSPCR_OUFLAG6;
178 for (j = 14; j >= 15 - shift; j--)
182 DSPCR |= DSPCR_OUFLAG6;
193 else if (setcond == 1)
199 if (sat == 1 && shift != 0 && (h0 & (1 << (shift-1))))
200 h0 = (h0 >> shift) + 1;
205 result |= ((uint32_t)((uint16_t)h0) << i);
207 GPR[rd] = EXTEND32 (result);
210 :function:::void:do_w_shll:int rd, int rt, int shift
213 uint32_t v1 = GPR[rt];
218 for (i = 30; i >= 31 - shift; i--)
220 if (!(v1 & (1 << i)))
222 DSPCR |= DSPCR_OUFLAG6;
230 for (i = 30; i >= 31 - shift; i--)
234 DSPCR |= DSPCR_OUFLAG6;
242 else if (setcond == 1)
245 result = v1 << shift;
246 GPR[rd] = EXTEND32 (result);
249 :function:::void:do_ph_s_absq:int rd, int rt
253 uint32_t v1 = GPR[rt];
255 for (i = 0; i < 32; i += 16, v1 >>= 16)
257 h0 = (int16_t)(v1 & 0xffff);
258 if (h0 == (int16_t)0x8000)
260 DSPCR |= DSPCR_OUFLAG4;
263 else if (h0 & 0x8000)
265 result |= ((uint32_t)((uint16_t)h0) << i);
267 GPR[rd] = EXTEND32 (result);
270 :function:::void:do_w_s_absq:int rd, int rt
272 uint32_t v1 = GPR[rt];
273 int32_t h0 = (int32_t)v1;
274 if (h0 == (int32_t)0x80000000)
276 DSPCR |= DSPCR_OUFLAG4;
279 else if (h0 & 0x80000000)
281 GPR[rd] = EXTEND32 (h0);
284 :function:::void:do_qb_s_absq:int rd, int rt
288 uint32_t v1 = GPR[rt];
290 for (i = 0; i < 32; i += 8, v1 >>= 8)
292 q0 = (int8_t)(v1 & 0xff);
293 if (q0 == (int8_t)0x80)
295 DSPCR |= DSPCR_OUFLAG4;
300 result |= ((uint32_t)((uint8_t)q0) << i);
302 GPR[rd] = EXTEND32 (result);
305 :function:::void:do_addsc:int rd, int rs, int rt
307 uint32_t v1 = GPR[rs];
308 uint32_t v2 = GPR[rt];
310 h0 = (uint64_t)v1 + (uint64_t)v2;
311 if (h0 & 0x100000000LL)
312 DSPCR |= DSPCR_CARRY;
313 GPR[rd] = EXTEND32 (h0);
316 :function:::void:do_addwc:int rd, int rs, int rt
318 uint32_t v1 = GPR[rs];
319 uint32_t v2 = GPR[rt];
321 int32_t h1 = (int32_t) v1;
322 int32_t h2 = (int32_t) v2;
323 h0 = (int64_t)h1 + (int64_t)h2
324 + (int64_t)((DSPCR >> DSPCR_CARRY_SHIFT) & DSPCR_CARRY_MASK);
325 if (((h0 & 0x100000000LL) >> 1) != (h0 & 0x80000000))
326 DSPCR |= DSPCR_OUFLAG4;
327 GPR[rd] = EXTEND32 (h0);
330 :function:::void:do_bitrev:int rd, int rt
333 uint32_t v1 = GPR[rt];
335 for (i = 0; i < 16; i++)
338 h1 |= (1 << (15 - i));
340 GPR[rd] = EXTEND32 (h1);
343 // op: 0 = EXTPV, 1 = EXTPDPV
344 :function:::void:do_extpv:int rt, int ac, int rs, int op
346 uint32_t size = GPR[rs] & 0x1f;
347 do_extp (SD_, rt, ac, size, op);
350 // op: 0 = EXTRV, 1 = EXTRV_R, 2 = EXTRV_RS
351 :function:::void:do_extrv:int rt, int ac, int rs, int op
353 uint32_t shift = GPR[rs] & 0x1f;
354 do_w_extr (SD_, rt, ac, shift, op);
357 :function:::void:do_extrv_s_h:int rt, int ac, int rs
359 uint32_t shift = GPR[rs] & 0x1f;
360 do_h_extr (SD_, rt, ac, shift);
363 :function:::void:do_insv:int rt, int rs
365 uint32_t v1 = GPR[rs];
366 uint32_t v2 = GPR[rt];
367 uint32_t pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
368 uint32_t size = (DSPCR >> DSPCR_SCOUNT_SHIFT) & DSPCR_SCOUNT_MASK;
369 uint32_t mask1, mask2, mask3, result;
371 mask1 = (1 << size) - 1;
374 mask2 = (1 << pos) - 1;
376 mask3 = ~((1 << (pos + size)) - 1);
379 result = (v2 & mask3) | ((v1 & mask1) << pos) | (v2 & mask2);
380 GPR[rt] = EXTEND32 (result);
383 // op: 0 = NORMAL, 1 = EXTEND16, 2 = EXTEND32
384 :function:::void:do_lxx:int rd, int base, int index, int op
387 GPR[rd] = do_load (SD_, AccessLength_BYTE, GPR[base], GPR[index]);
389 GPR[rd] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[base], GPR[index]));
391 GPR[rd] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[base], GPR[index]));
394 :function:::void:do_modsub:int rd, int rs, int rt
397 uint32_t v1 = GPR[rs];
398 uint32_t v2 = GPR[rt];
399 uint32_t decr = v2 & 0xff;
400 uint32_t lastindex = (v2 & 0xffff00) >> 8;
405 GPR[rd] = EXTEND32 (result);
408 :function:::void:do_mthlip:int rs, int ac
410 uint32_t pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
411 DSPHI(ac) = DSPLO(ac);
417 DSPCR &= (~DSPCR_POS_SMASK);
418 DSPCR |= (pos & DSPCR_POS_MASK) << DSPCR_POS_SHIFT;
421 :function:::void:do_mulsaq_s_w_ph:int ac, int rs, int rt
424 uint32_t v1 = GPR[rs];
425 uint32_t v2 = GPR[rt];
428 uint32_t lo = DSPLO(ac);
429 uint32_t hi = DSPHI(ac);
430 int64_t prod = (int64_t)((((uint64_t)hi) << 32) + (uint64_t)lo);
431 for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
433 h1 = (int16_t)(v1 & 0xffff);
434 h2 = (int16_t)(v2 & 0xffff);
435 if (h1 == (int16_t)0x8000 && h2 == (int16_t)0x8000)
437 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
438 result = (int32_t) 0x7fffffff;
441 result = ((int32_t)h1 * (int32_t)h2) << 1;
444 prod -= (int64_t) result;
446 prod += (int64_t) result;
448 DSPLO(ac) = EXTEND32 (prod);
449 DSPHI(ac) = EXTEND32 (prod >> 32);
452 :function:::void:do_ph_packrl:int rd, int rs, int rt
455 uint32_t v1 = GPR[rs];
456 uint32_t v2 = GPR[rt];
457 GPR[rd] = EXTEND32 ((v1 << 16) + (v2 >> 16));
460 :function:::void:do_qb_pick:int rd, int rs, int rt
463 uint32_t v1 = GPR[rs];
464 uint32_t v2 = GPR[rt];
467 for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
469 h1 = (uint8_t)(v1 & 0xff);
470 h2 = (uint8_t)(v2 & 0xff);
471 if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j)))
472 result |= (uint32_t)(h1 << i);
474 result |= (uint32_t)(h2 << i);
476 GPR[rd] = EXTEND32 (result);
479 :function:::void:do_ph_pick:int rd, int rs, int rt
482 uint32_t v1 = GPR[rs];
483 uint32_t v2 = GPR[rt];
486 for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16)
488 h1 = (uint16_t)(v1 & 0xffff);
489 h2 = (uint16_t)(v2 & 0xffff);
490 if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j)))
491 result |= (uint32_t)(h1 << i);
493 result |= (uint32_t)(h2 << i);
495 GPR[rd] = EXTEND32 (result);
498 // op: 0 = QBR, 1 = QBRA, 2 = QBL, 3 = QBLA
499 :function:::void:do_qb_ph_precequ:int rd, int rt, int op
501 uint32_t v1 = GPR[rt];
503 GPR[rd] = EXTEND32 ((v1 & 0xff00) << 15) | ((v1 & 0xff) << 7);
505 GPR[rd] = EXTEND32 ((v1 & 0xff0000) << 7) | ((v1 & 0xff) << 7);
507 GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff0000) >> 9);
509 GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff00) >> 1);
512 // op: 0 = QBR, 1 = QBRA, 2 = QBL, 3 = QBLA
513 :function:::void:do_qb_ph_preceu:int rd, int rt, int op
515 uint32_t v1 = GPR[rt];
517 GPR[rd] = EXTEND32 ((v1 & 0xff00) << 8) | (v1 & 0xff);
519 GPR[rd] = EXTEND32 ((v1 & 0xff0000) | (v1 & 0xff));
521 GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff0000) >> 16);
523 GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff00) >> 8);
526 // op: 0 = .PHL, 1 = PHR
527 :function:::void:do_w_preceq:int rd, int rt, int op
529 uint32_t v1 = GPR[rt];
531 GPR[rd] = EXTEND32 (v1 & 0xffff0000);
533 GPR[rd] = EXTEND32 ((v1 & 0xffff) << 16);
536 :function:::void:do_w_ph_precrq:int rd, int rs, int rt
538 uint32_t v1 = GPR[rs];
539 uint32_t v2 = GPR[rt];
540 uint32_t tempu = (v1 & 0xffff0000) >> 16;
541 uint32_t tempv = (v2 & 0xffff0000) >> 16;
542 GPR[rd] = EXTEND32 ((tempu << 16) | tempv);
545 // sat: 0 = PRECRQ.QB.PH, 1 = PRECRQU_S.QB.PH
546 :function:::void:do_ph_qb_precrq:int rd, int rs, int rt, int sat
548 uint32_t v1 = GPR[rs];
549 uint32_t v2 = GPR[rt];
550 uint32_t tempu = 0, tempv = 0, tempw = 0, tempx = 0;
553 tempu = (v1 & 0xff000000) >> 24;
554 tempv = (v1 & 0xff00) >> 8;
555 tempw = (v2 & 0xff000000) >> 24;
556 tempx = (v2 & 0xff00) >> 8;
562 DSPCR |= DSPCR_OUFLAG6;
565 else if (!(v1 & 0x80000000) && ((v1 >> 16) > (uint32_t)0x7f80))
567 DSPCR |= DSPCR_OUFLAG6;
571 tempu = (v1 & 0x7f800000) >> 23;
574 DSPCR |= DSPCR_OUFLAG6;
577 else if (!(v1 & 0x8000) && ((v1 & 0xffff) > (uint32_t)0x7f80))
579 DSPCR |= DSPCR_OUFLAG6;
583 tempv = (v1 & 0x7f80) >> 7;
586 DSPCR |= DSPCR_OUFLAG6;
589 else if (!(v2 & 0x80000000) && ((v2 >> 16) > (uint32_t)0x7f80))
591 DSPCR |= DSPCR_OUFLAG6;
595 tempw = (v2 & 0x7f800000) >> 23;
598 DSPCR |= DSPCR_OUFLAG6;
601 else if (!(v2 & 0x8000) && ((v2 & 0xffff) > (uint32_t)0x7f80))
603 DSPCR |= DSPCR_OUFLAG6;
607 tempx = (v2 & 0x7f80) >> 7;
609 GPR[rd] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx);
612 :function:::void:do_w_ph_rs_precrq:int rd, int rs, int rt
614 uint32_t v1 = GPR[rs];
615 uint32_t v2 = GPR[rt];
616 int32_t h1 = (int32_t)v1;
617 int32_t h2 = (int32_t)v2;
618 int64_t temp1 = (int64_t)h1 + (int64_t)0x8000;
620 int64_t temp3 = (int64_t)h2 + (int64_t)0x8000;
622 if (((temp1 & 0x100000000LL) >> 1) != (temp1 & 0x80000000))
624 DSPCR |= DSPCR_OUFLAG6;
628 temp2 = (int32_t)((temp1 & 0xffff0000) >> 16);
629 if (((temp3 & 0x100000000LL) >> 1) != (temp3 & 0x80000000))
631 DSPCR |= DSPCR_OUFLAG6;
635 temp4 = (int32_t)((temp3 & 0xffff0000) >> 16);
636 GPR[rd] = EXTEND32 ((temp2 << 16) | temp4);
639 :function:::void:do_qb_w_raddu:int rd, int rs
643 uint32_t v1 = GPR[rs];
645 for (i = 0; i < 32; i += 8, v1 >>= 8)
647 h0 = (uint8_t)(v1 & 0xff);
648 result += (uint32_t)h0;
650 GPR[rd] = EXTEND32 (result);
653 :function:::void:do_rddsp:int rd, int mask
658 result &= (~DSPCR_POS_SMASK);
659 result |= (DSPCR & DSPCR_POS_SMASK);
663 result &= (~DSPCR_SCOUNT_SMASK);
664 result |= (DSPCR & DSPCR_SCOUNT_SMASK);
668 result &= (~DSPCR_CARRY_SMASK);
669 result |= (DSPCR & DSPCR_CARRY_SMASK);
673 result &= (~DSPCR_OUFLAG_SMASK);
674 result |= (DSPCR & DSPCR_OUFLAG_SMASK);
678 result &= (~DSPCR_CCOND_SMASK);
679 result |= (DSPCR & DSPCR_CCOND_SMASK);
683 result &= (~DSPCR_EFI_SMASK);
684 result |= (DSPCR & DSPCR_EFI_SMASK);
686 GPR[rd] = EXTEND32 (result);
689 // op: 0 = REPL.QB, 1 = REPLV.QB, 2 = REPL.PH, 3 = REPLV.PH
690 :function:::void:do_repl:int rd, int p2, int op
693 GPR[rd] = EXTEND32 ((p2 << 24) | (p2 << 16) | (p2 << 8) | p2);
696 uint32_t v1 = GPR[p2] & 0xff;
697 GPR[rd] = EXTEND32 ((v1 << 24) | (v1 << 16) | (v1 << 8) | v1);
704 GPR[rd] = EXTEND32 ((v1 << 16) | (v1 & 0xffff));
708 uint32_t v1 = GPR[p2];
710 GPR[rd] = EXTEND32 ((v1 << 16) | v1);
714 :function:::void:do_shilov:int ac, int rs
716 int32_t shift = GPR[rs] & 0x3f;
717 do_shilo (SD_, ac, shift);
720 // op: 0 = SHLLV, 1 = SHRAV
721 // sat: 0 = normal, 1 = saturate/rounding
722 :function:::void:do_ph_shl:int rd, int rt, int rs, int op, int sat
724 uint32_t shift = GPR[rs] & 0xf;
725 do_ph_shift (SD_, rd, rt, shift, op, sat);
728 // op: 0 = SHLLV, 1 = SHRLV
729 :function:::void:do_qb_shl:int rd, int rt, int rs, int op
731 uint32_t shift = GPR[rs] & 0x7;
732 do_qb_shift (SD_, rd, rt, shift, op);
735 :function:::void:do_w_s_shllv:int rd, int rt, int rs
737 uint32_t shift = GPR[rs] & 0x1f;
738 do_w_shll (SD_, rd, rt, shift);
741 :function:::void:do_ph_shrlv:int rd, int rt, int rs
743 uint32_t shift = GPR[rs] & 0xf;
744 do_ph_shrl (SD_, rd, rt, shift);
747 :function:::void:do_w_r_shrav:int rd, int rt, int rs
749 uint32_t shift = GPR[rs] & 0x1f;
750 do_w_shra (SD_, rd, rt, shift);
753 :function:::void:do_wrdsp:int rs, int mask
755 uint32_t v1 = GPR[rs];
758 DSPCR &= (~DSPCR_POS_SMASK);
759 DSPCR |= (v1 & DSPCR_POS_SMASK);
763 DSPCR &= (~DSPCR_SCOUNT_SMASK);
764 DSPCR |= (v1 & DSPCR_SCOUNT_SMASK);
768 DSPCR &= (~DSPCR_CARRY_SMASK);
769 DSPCR |= (v1 & DSPCR_CARRY_SMASK);
773 DSPCR &= (~DSPCR_OUFLAG_SMASK);
774 DSPCR |= (v1 & DSPCR_OUFLAG_SMASK);
778 DSPCR &= (~DSPCR_CCOND_SMASK);
779 DSPCR |= (v1 & DSPCR_CCOND_SMASK);
783 DSPCR &= (~DSPCR_EFI_SMASK);
784 DSPCR |= (v1 & DSPCR_EFI_SMASK);
788 // round: 0 = no rounding, 1 = rounding
789 :function:::void:do_qb_shrav:int rd, int rt, int rs, int round
791 uint32_t shift = GPR[rs] & 0x7;
792 do_qb_shra (SD_, rd, rt, shift, round);
795 :function:::void:do_append:int rt, int rs, int sa
797 uint32_t v0 = GPR[rs];
798 uint32_t v1 = GPR[rt];
800 uint32_t mask = (1 << sa) - 1;
801 result = (v1 << sa) | (v0 & mask);
802 GPR[rt] = EXTEND32 (result);
805 :function:::void:do_balign:int rt, int rs, int bp
807 uint32_t v0 = GPR[rs];
808 uint32_t v1 = GPR[rt];
813 result = (v1 << 8 * bp) | (v0 >> 8 * (4 - bp));
814 GPR[rt] = EXTEND32 (result);
817 :function:::void:do_ph_w_mulsa:int ac, int rs, int rt
820 uint32_t v1 = GPR[rs];
821 uint32_t v2 = GPR[rt];
824 uint32_t lo = DSPLO(ac);
825 uint32_t hi = DSPHI(ac);
826 int64_t prod = (int64_t)((((uint64_t)hi) << 32) + (uint64_t)lo);
827 for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
829 h1 = (int16_t)(v1 & 0xffff);
830 h2 = (int16_t)(v2 & 0xffff);
831 result = (int32_t)h1 * (int32_t)h2;
834 prod -= (int64_t) result;
836 prod += (int64_t) result;
838 DSPLO(ac) = EXTEND32 (prod);
839 DSPHI(ac) = EXTEND32 (prod >> 32);
842 :function:::void:do_ph_qb_precr:int rd, int rs, int rt
844 uint32_t v1 = GPR[rs];
845 uint32_t v2 = GPR[rt];
846 uint32_t tempu = (v1 & 0xff0000) >> 16;
847 uint32_t tempv = (v1 & 0xff);
848 uint32_t tempw = (v2 & 0xff0000) >> 16;
849 uint32_t tempx = (v2 & 0xff);
850 GPR[rd] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx);
853 :function:::void:do_prepend:int rt, int rs, int sa
855 uint32_t v0 = GPR[rs];
856 uint32_t v1 = GPR[rt];
861 result = (v0 << (32 - sa)) | (v1 >> sa);
862 GPR[rt] = EXTEND32 (result);
865 :function:::void:do_w_shra:int rd, int rt, int shift
867 uint32_t result = GPR[rt];
868 int32_t h0 = (int32_t)result;
869 if (shift != 0 && (h0 & (1 << (shift-1))))
870 h0 = (h0 >> shift) + 1;
873 GPR[rd] = EXTEND32 (h0);
876 011111,5.RS,5.RT,5.RD,01010,010000:SPECIAL3:32::ADDQ.PH
877 "addq.ph r<RD>, r<RS>, r<RT>"
880 do_ph_op (SD_, RD, RS, RT, 0, 0);
883 011111,5.RS,5.RT,5.RD,01110,010000:SPECIAL3:32::ADDQ_S.PH
884 "addq_s.ph r<RD>, r<RS>, r<RT>"
887 do_ph_op (SD_, RD, RS, RT, 0, 1);
890 011111,5.RS,5.RT,5.RD,10110,010000:SPECIAL3:32::ADDQ_S.W
891 "addq_s.w r<RD>, r<RS>, r<RT>"
894 do_w_op (SD_, RD, RS, RT, 0);
897 011111,5.RS,5.RT,5.RD,00000,010000:SPECIAL3:32::ADDU.QB
898 "addu.qb r<RD>, r<RS>, r<RT>"
901 do_qb_op (SD_, RD, RS, RT, 0, 0);
904 011111,5.RS,5.RT,5.RD,00100,010000:SPECIAL3:32::ADDU_S.QB
905 "addu_s.qb r<RD>, r<RS>, r<RT>"
908 do_qb_op (SD_, RD, RS, RT, 0, 1);
911 011111,5.RS,5.RT,5.RD,01011,010000:SPECIAL3:32::SUBQ.PH
912 "subq.ph r<RD>, r<RS>, r<RT>"
915 do_ph_op (SD_, RD, RS, RT, 1, 0);
918 011111,5.RS,5.RT,5.RD,01111,010000:SPECIAL3:32::SUBQ_S.PH
919 "subq_s.ph r<RD>, r<RS>, r<RT>"
922 do_ph_op (SD_, RD, RS, RT, 1, 1);
925 011111,5.RS,5.RT,5.RD,10111,010000:SPECIAL3:32::SUBQ_S.W
926 "subq_s.w r<RD>, r<RS>, r<RT>"
929 do_w_op (SD_, RD, RS, RT, 1);
932 011111,5.RS,5.RT,5.RD,00001,010000:SPECIAL3:32::SUBU.QB
933 "subu.qb r<RD>, r<RS>, r<RT>"
936 do_qb_op (SD_, RD, RS, RT, 1, 0);
939 011111,5.RS,5.RT,5.RD,00101,010000:SPECIAL3:32::SUBU_S.QB
940 "subu_s.qb r<RD>, r<RS>, r<RT>"
943 do_qb_op (SD_, RD, RS, RT, 1, 1);
946 011111,5.RS,5.RT,5.RD,10000,010000:SPECIAL3:32::ADDSC
947 "addsc r<RD>, r<RS>, r<RT>"
950 do_addsc (SD_, RD, RS, RT);
953 011111,5.RS,5.RT,5.RD,10001,010000:SPECIAL3:32::ADDWC
954 "addwc r<RD>, r<RS>, r<RT>"
957 do_addwc (SD_, RD, RS, RT);
960 011111,5.RS,5.RT,5.RD,10010,010000:SPECIAL3:32::MODSUB
961 "modsub r<RD>, r<RS>, r<RT>"
964 do_modsub (SD_, RD, RS, RT);
967 011111,5.RS,00000,5.RD,10100,010000:SPECIAL3:32::RADDU.W.QB
968 "raddu.w.qb r<RD>, r<RS>"
971 do_qb_w_raddu (SD_, RD, RS);
974 011111,00000,5.RT,5.RD,01001,010010:SPECIAL3:32::ABSQ_S.PH
975 "absq_s.ph r<RD>, r<RT>"
978 do_ph_s_absq (SD_, RD, RT);
981 011111,00000,5.RT,5.RD,10001,010010:SPECIAL3:32::ABSQ_S.W
982 "absq_s.w r<RD>, r<RT>"
985 do_w_s_absq (SD_, RD, RT);
988 011111,5.RS,5.RT,5.RD,01100,010001:SPECIAL3:32::PRECRQ.QB.PH
989 "precrq.qb.ph r<RD>, r<RS>, r<RT>"
992 do_ph_qb_precrq (SD_, RD, RS, RT, 0);
995 011111,5.RS,5.RT,5.RD,10100,010001:SPECIAL3:32::PRECRQ.PH.W
996 "precrq.ph.w r<RD>, r<RS>, r<RT>"
999 do_w_ph_precrq (SD_, RD, RS, RT);
1002 011111,5.RS,5.RT,5.RD,10101,010001:SPECIAL3:32::PRECRQ_RS.PH.W
1003 "precrq_rs.ph.w r<RD>, r<RS>, r<RT>"
1006 do_w_ph_rs_precrq (SD_, RD, RS, RT);
1009 011111,5.RS,5.RT,5.RD,01111,010001:SPECIAL3:32::PRECRQU_S.QB.PH
1010 "precrqu_s.qb.ph r<RD>, r<RS>, r<RT>"
1013 do_ph_qb_precrq (SD_, RD, RS, RT, 1);
1016 011111,00000,5.RT,5.RD,01100,010010:SPECIAL3:32::PRECEQ.W.PHL
1017 "preceq.w.phl r<RD>, r<RT>"
1020 do_w_preceq (SD_, RD, RT, 0);
1023 011111,00000,5.RT,5.RD,01101,010010:SPECIAL3:32::PRECEQ.W.PHR
1024 "preceq.w.phr r<RD>, r<RT>"
1027 do_w_preceq (SD_, RD, RT, 1);
1030 011111,00000,5.RT,5.RD,00100,010010:SPECIAL3:32::PRECEQU.PH.QBL
1031 "precequ.ph.qbl r<RD>, r<RT>"
1034 do_qb_ph_precequ (SD_, RD, RT, 2);
1037 011111,00000,5.RT,5.RD,00101,010010:SPECIAL3:32::PRECEQU.PH.QBR
1038 "precequ.ph.qbr r<RD>, r<RT>"
1041 do_qb_ph_precequ (SD_, RD, RT, 0);
1044 011111,00000,5.RT,5.RD,00110,010010:SPECIAL3:32::PRECEQU.PH.QBLA
1045 "precequ.ph.qbla r<RD>, r<RT>"
1048 do_qb_ph_precequ (SD_, RD, RT, 3);
1051 011111,00000,5.RT,5.RD,00111,010010:SPECIAL3:32::PRECEQU.PH.QBRA
1052 "precequ.ph.qbra r<RD>, r<RT>"
1055 do_qb_ph_precequ (SD_, RD, RT, 1);
1058 011111,00000,5.RT,5.RD,11100,010010:SPECIAL3:32::PRECEU.PH.QBL
1059 "preceu.ph.qbl r<RD>, r<RT>"
1062 do_qb_ph_preceu (SD_, RD, RT, 2);
1065 011111,00000,5.RT,5.RD,11101,010010:SPECIAL3:32::PRECEU.PH.QBR
1066 "preceu.ph.qbr r<RD>, r<RT>"
1069 do_qb_ph_preceu (SD_, RD, RT, 0);
1072 011111,00000,5.RT,5.RD,11110,010010:SPECIAL3:32::PRECEU.PH.QBLA
1073 "preceu.ph.qbla r<RD>, r<RT>"
1076 do_qb_ph_preceu (SD_, RD, RT, 3);
1079 011111,00000,5.RT,5.RD,11111,010010:SPECIAL3:32::PRECEU.PH.QBRA
1080 "preceu.ph.qbra r<RD>, r<RT>"
1083 do_qb_ph_preceu (SD_, RD, RT, 1);
1086 011111,00,3.SHIFT3,5.RT,5.RD,00000,010011:SPECIAL3:32::SHLL.QB
1087 "shll.qb r<RD>, r<RT>, <SHIFT3>"
1090 do_qb_shift (SD_, RD, RT, SHIFT3, 0);
1093 011111,5.RS,5.RT,5.RD,00010,010011:SPECIAL3:32::SHLLV.QB
1094 "shllv.qb r<RD>, r<RT>, r<RS>"
1097 do_qb_shl (SD_, RD, RT, RS, 0);
1100 011111,0,4.SHIFT4,5.RT,5.RD,01000,010011:SPECIAL3:32::SHLL.PH
1101 "shll.ph r<RD>, r<RT>, <SHIFT4>"
1104 do_ph_shift (SD_, RD, RT, SHIFT4, 0, 0);
1107 011111,5.RS,5.RT,5.RD,01010,010011:SPECIAL3:32::SHLLV.PH
1108 "shllv.ph r<RD>, r<RT>, r<RS>"
1111 do_ph_shl (SD_, RD, RT, RS, 0, 0);
1114 011111,0,4.SHIFT4,5.RT,5.RD,01100,010011:SPECIAL3:32::SHLL_S.PH
1115 "shll_s.ph r<RD>, r<RT>, <SHIFT4>"
1118 do_ph_shift (SD_, RD, RT, SHIFT4, 0, 1);
1121 011111,5.RS,5.RT,5.RD,01110,010011:SPECIAL3:32::SHLLV_S.PH
1122 "shllv_s.ph r<RD>, r<RT>, r<RS>"
1125 do_ph_shl (SD_, RD, RT, RS, 0, 1);
1128 011111,5.SHIFT5,5.RT,5.RD,10100,010011:SPECIAL3:32::SHLL_S.W
1129 "shll_s.w r<RD>, r<RT>, <SHIFT5>"
1132 do_w_shll (SD_, RD, RT, SHIFT5);
1135 011111,5.RS,5.RT,5.RD,10110,010011:SPECIAL3:32::SHLLV_S.W
1136 "shllv_s.w r<RD>, r<RT>, r<RS>"
1139 do_w_s_shllv (SD_, RD, RT, RS);
1142 011111,00,3.SHIFT3,5.RT,5.RD,00001,010011:SPECIAL3:32::SHRL.QB
1143 "shrl.qb r<RD>, r<RT>, <SHIFT3>"
1146 do_qb_shift (SD_, RD, RT, SHIFT3, 1);
1149 011111,5.RS,5.RT,5.RD,00011,010011:SPECIAL3:32::SHRLV.QB
1150 "shrlv.qb r<RD>, r<RT>, r<RS>"
1153 do_qb_shl (SD_, RD, RT, RS, 1);
1156 011111,0,4.SHIFT4,5.RT,5.RD,01001,010011:SPECIAL3:32::SHRA.PH
1157 "shra.ph r<RD>, r<RT>, <SHIFT4>"
1160 do_ph_shift (SD_, RD, RT, SHIFT4, 1, 0);
1163 011111,5.RS,5.RT,5.RD,01011,010011:SPECIAL3:32::SHRAV.PH
1164 "shrav.ph r<RD>, r<RT>, r<RS>"
1167 do_ph_shl (SD_, RD, RT, RS, 1, 0);
1170 011111,0,4.SHIFT4,5.RT,5.RD,01101,010011:SPECIAL3:32::SHRA_R.PH
1171 "shra_r.ph r<RD>, r<RT>, <SHIFT4>"
1174 do_ph_shift (SD_, RD, RT, SHIFT4, 1, 1);
1177 011111,5.RS,5.RT,5.RD,01111,010011:SPECIAL3:32::SHRAV_R.PH
1178 "shrav_r.ph r<RD>, r<RT>, r<RS>"
1181 do_ph_shl (SD_, RD, RT, RS, 1, 1);
1184 011111,5.SHIFT5,5.RT,5.RD,10101,010011:SPECIAL3:32::SHRA_R.W
1185 "shra_r.w r<RD>, r<RT>, <SHIFT5>"
1188 do_w_shra (SD_, RD, RT, SHIFT5);
1191 011111,5.RS,5.RT,5.RD,10111,010011:SPECIAL3:32::SHRAV_R.W
1192 "shrav_r.w r<RD>, r<RT>, r<RS>"
1195 do_w_r_shrav (SD_, RD, RT, RS);
1198 // loc: 0 = qhl, 1 = qhr
1199 :function:::void:do_qb_muleu:int rd, int rs, int rt, int loc
1202 uint32_t result = 0;
1203 uint32_t v1 = GPR[rs];
1204 uint32_t v2 = GPR[rt];
1209 for (i = 0; i < 32; i += 16, v1 >>= 8, v2 >>= 16)
1211 h1 = (uint16_t)(v1 & 0xff);
1212 h2 = (uint16_t)(v2 & 0xffff);
1213 prod = (uint32_t)h1 * (uint32_t)h2;
1216 DSPCR |= DSPCR_OUFLAG5;
1219 result |= ((uint32_t)prod << i);
1221 GPR[rd] = EXTEND32 (result);
1224 011111,5.RS,5.RT,5.RD,00110,010000:SPECIAL3:32::MULEU_S.PH.QBL
1225 "muleu_s.ph.qbl r<RD>, r<RS>, r<RT>"
1228 do_qb_muleu (SD_, RD, RS, RT, 0);
1231 011111,5.RS,5.RT,5.RD,00111,010000:SPECIAL3:32::MULEU_S.PH.QBR
1232 "muleu_s.ph.qbr r<RD>, r<RS>, r<RT>"
1235 do_qb_muleu (SD_, RD, RS, RT, 1);
1238 // round: 0 = no rounding, 1 = rounding
1239 :function:::void:do_ph_mulq:int rd, int rs, int rt, int round
1242 uint32_t result = 0;
1243 uint32_t v1 = GPR[rs];
1244 uint32_t v2 = GPR[rt];
1247 for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
1249 h1 = (int16_t)(v1 & 0xffff);
1250 h2 = (int16_t)(v2 & 0xffff);
1251 if (h1 == (int16_t)0x8000 && h2 == (int16_t)0x8000)
1253 DSPCR |= DSPCR_OUFLAG5;
1258 prod = ((int32_t)h1 * (int32_t)h2) << 1;
1260 prod += (int32_t)0x8000;
1262 result |= (((uint32_t)prod >> 16) << i);
1264 GPR[rd] = EXTEND32 (result);
1267 011111,5.RS,5.RT,5.RD,11111,010000:SPECIAL3:32::MULQ_RS.PH
1268 "mulq_rs.ph r<RD>, r<RS>, r<RT>"
1271 do_ph_mulq (SD_, RD, RS, RT, 1);
1274 // loc: 0 = phl, 1 = phr
1275 :function:::void:do_ph_muleq:int rd, int rs, int rt, int loc
1277 uint32_t v1 = GPR[rs];
1278 uint32_t v2 = GPR[rt];
1283 h1 = (int16_t)(v1 >> 16);
1284 h2 = (int16_t)(v2 >> 16);
1288 h1 = (int16_t)(v1 & 0xffff);
1289 h2 = (int16_t)(v2 & 0xffff);
1291 if (h1 == (int16_t)0x8000 && h2 == (int16_t)0x8000)
1293 DSPCR |= DSPCR_OUFLAG5;
1297 prod = ((int32_t)h1 * (int32_t)h2) << 1;
1298 GPR[rd] = EXTEND32 (prod);
1301 011111,5.RS,5.RT,5.RD,11100,010000:SPECIAL3:32::MULEQ_S.W.PHL
1302 "muleq_s.w.phl r<RD>, r<RS>, r<RT>"
1305 do_ph_muleq (SD_, RD, RS, RT, 0);
1308 011111,5.RS,5.RT,5.RD,11101,010000:SPECIAL3:32::MULEQ_S.W.PHR
1309 "muleq_s.w.phr r<RD>, r<RS>, r<RT>"
1312 do_ph_muleq (SD_, RD, RS, RT, 1);
1315 // op: 0 = DPAU 1 = DPSU
1316 // loc: 0 = qbl, 1 = qbr
1317 :function:::void:do_qb_dot_product:int ac, int rs, int rt, int op, int loc
1320 uint32_t v1 = GPR[rs];
1321 uint32_t v2 = GPR[rt];
1323 uint32_t lo = DSPLO(ac);
1324 uint32_t hi = DSPHI(ac);
1325 uint64_t prod = (((uint64_t)hi) << 32) + (uint64_t)lo;
1331 for (i = 0; i < 16; i += 8, v1 >>= 8, v2 >>= 8)
1333 h1 = (uint8_t)(v1 & 0xff);
1334 h2 = (uint8_t)(v2 & 0xff);
1335 if (op == 0) // DPAU
1336 prod += (uint64_t)h1 * (uint64_t)h2;
1338 prod -= (uint64_t)h1 * (uint64_t)h2;
1340 DSPLO(ac) = EXTEND32 (prod);
1341 DSPHI(ac) = EXTEND32 (prod >> 32);
1344 011111,5.RS,5.RT,000,2.AC,00011,110000:SPECIAL3:32::DPAU.H.QBL
1345 "dpau.h.qbl ac<AC>, r<RS>, r<RT>"
1348 do_qb_dot_product (SD_, AC, RS, RT, 0, 0);
1351 011111,5.RS,5.RT,000,2.AC,00111,110000:SPECIAL3:32::DPAU.H.QBR
1352 "dpau.h.qbr ac<AC>, r<RS>, r<RT>"
1355 do_qb_dot_product (SD_, AC, RS, RT, 0, 1);
1358 011111,5.RS,5.RT,000,2.AC,01011,110000:SPECIAL3:32::DPSU.H.QBL
1359 "dpsu.h.qbl ac<AC>, r<RS>, r<RT>"
1362 do_qb_dot_product (SD_, AC, RS, RT, 1, 0);
1365 011111,5.RS,5.RT,000,2.AC,01111,110000:SPECIAL3:32::DPSU.H.QBR
1366 "dpsu.h.qbr ac<AC>, r<RS>, r<RT>"
1369 do_qb_dot_product (SD_, AC, RS, RT, 1, 1);
1372 // op: 0 = DPAQ 1 = DPSQ
1373 :function:::void:do_ph_dot_product:int ac, int rs, int rt, int op
1376 uint32_t v1 = GPR[rs];
1377 uint32_t v2 = GPR[rt];
1380 uint32_t lo = DSPLO(ac);
1381 uint32_t hi = DSPHI(ac);
1382 int64_t prod = (int64_t)((((uint64_t)hi) << 32) + (uint64_t)lo);
1383 for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
1385 h1 = (int16_t)(v1 & 0xffff);
1386 h2 = (int16_t)(v2 & 0xffff);
1387 if (h1 == (int16_t)0x8000 && h2 == (int16_t)0x8000)
1389 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1390 result = (int32_t)0x7fffffff;
1393 result = ((int32_t)h1 * (int32_t)h2) << 1;
1395 if (op == 0) // DPAQ
1396 prod += (int64_t)result;
1398 prod -= (int64_t)result;
1400 DSPLO(ac) = EXTEND32 (prod);
1401 DSPHI(ac) = EXTEND32 (prod >> 32);
1404 011111,5.RS,5.RT,000,2.AC,00100,110000:SPECIAL3:32::DPAQ_S.W.PH
1405 "dpaq_s.w.ph ac<AC>, r<RS>, r<RT>"
1408 do_ph_dot_product (SD_, AC, RS, RT, 0);
1411 011111,5.RS,5.RT,000,2.AC,00101,110000:SPECIAL3:32::DPSQ_S.W.PH
1412 "dpsq_s.w.ph ac<AC>, r<RS>, r<RT>"
1415 do_ph_dot_product (SD_, AC, RS, RT, 1);
1418 011111,5.RS,5.RT,000,2.AC,00110,110000:SPECIAL3:32::MULSAQ_S.W.PH
1419 "mulsaq_s.w.ph ac<AC>, r<RS>, r<RT>"
1422 do_mulsaq_s_w_ph (SD_, AC, RS, RT);
1425 // op: 0 = DPAQ 1 = DPSQ
1426 :function:::void:do_w_dot_product:int ac, int rs, int rt, int op
1428 uint32_t v1 = GPR[rs];
1429 uint32_t v2 = GPR[rt];
1432 uint32_t lo = DSPLO(ac);
1433 uint32_t hi = DSPHI(ac);
1441 if (h1 == 0x80000000 && h2 == 0x80000000)
1443 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1444 result = (int64_t) 0x7fffffffffffffffLL;
1447 result = ((int64_t)h1 * (int64_t)h2) << 1;
1448 resultlo = (uint32_t)(result);
1449 resulthi = (uint32_t)(result >> 32);
1452 temp1 = (uint64_t)lo + (uint64_t)resultlo;
1453 carry = (uint32_t)((temp1 >> 32) & 1);
1454 temp2 = (int64_t)((int32_t)hi) + (int64_t)((int32_t)resulthi) +
1455 (int64_t)((int32_t)carry);
1459 temp1 = (uint64_t)lo - (uint64_t)resultlo;
1460 carry = (uint32_t)((temp1 >> 32) & 1);
1461 temp2 = (int64_t)((int32_t)hi) - (int64_t)((int32_t)resulthi) -
1462 (int64_t)((int32_t)carry);
1464 if (((temp2 & 0x100000000LL) >> 1) != (temp2 & 0x80000000LL))
1466 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1467 if (temp2 & 0x100000000LL)
1469 DSPLO(ac) = EXTEND32 (0x00000000);
1470 DSPHI(ac) = EXTEND32 (0x80000000);
1474 DSPLO(ac) = EXTEND32 (0xffffffff);
1475 DSPHI(ac) = EXTEND32 (0x7fffffff);
1480 DSPLO(ac) = EXTEND32 (temp1);
1481 DSPHI(ac) = EXTEND32 (temp2);
1485 011111,5.RS,5.RT,000,2.AC,01100,110000:SPECIAL3:32::DPAQ_SA.L.W
1486 "dpaq_sa.l.w ac<AC>, r<RS>, r<RT>"
1489 do_w_dot_product (SD_, AC, RS, RT, 0);
1492 011111,5.RS,5.RT,000,2.AC,01101,110000:SPECIAL3:32::DPSQ_SA.L.W
1493 "dpsq_sa.l.w ac<AC>, r<RS>, r<RT>"
1496 do_w_dot_product (SD_, AC, RS, RT, 1);
1499 // op: 0 = MAQ_S 1 = MAQ_SA
1500 // loc: 0 = phl, 1 = phr
1501 :function:::void:do_ph_maq:int ac, int rs, int rt, int op, int loc
1504 uint32_t v1 = GPR[rs];
1505 uint32_t v2 = GPR[rt];
1508 uint32_t lo = DSPLO(ac);
1509 uint32_t hi = DSPHI(ac);
1510 int64_t prod = (int64_t)((((uint64_t)hi) << 32) + (uint64_t)lo);
1513 h1 = (int16_t)(v1 >> 16);
1514 h2 = (int16_t)(v2 >> 16);
1518 h1 = (int16_t)(v1 & 0xffff);
1519 h2 = (int16_t)(v2 & 0xffff);
1521 if (h1 == (int16_t)0x8000 && h2 == (int16_t)0x8000)
1523 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1524 result = (int32_t)0x7fffffff;
1527 result = ((int32_t)h1 * (int32_t)h2) << 1;
1528 prod += (int64_t)result;
1529 if (op == 1) // MAQ_SA
1531 if (prod & 0x8000000000000000LL)
1533 for (i = 62; i >= 31; i--)
1535 if (!(prod & ((int64_t)1 << i)))
1537 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1538 prod = 0xffffffff80000000LL;
1545 for (i = 62; i >= 31; i--)
1547 if (prod & ((int64_t)1 << i))
1549 DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1556 DSPLO(ac) = EXTEND32 (prod);
1557 DSPHI(ac) = EXTEND32 (prod >> 32);
1560 011111,5.RS,5.RT,000,2.AC,10100,110000:SPECIAL3:32::MAQ_S.W.PHL
1561 "maq_s.w.phl ac<AC>, r<RS>, r<RT>"
1564 do_ph_maq (SD_, AC, RS, RT, 0, 0);
1567 011111,5.RS,5.RT,000,2.AC,10110,110000:SPECIAL3:32::MAQ_S.W.PHR
1568 "maq_s.w.phr ac<AC>, r<RS>, r<RT>"
1571 do_ph_maq (SD_, AC, RS, RT, 0, 1);
1574 011111,5.RS,5.RT,000,2.AC,10000,110000:SPECIAL3:32::MAQ_SA.W.PHL
1575 "maq_sa.w.phl ac<AC>, r<RS>, r<RT>"
1578 do_ph_maq (SD_, AC, RS, RT, 1, 0);
1581 011111,5.RS,5.RT,000,2.AC,10010,110000:SPECIAL3:32::MAQ_SA.W.PHR
1582 "maq_sa.w.phr ac<AC>, r<RS>, r<RT>"
1585 do_ph_maq (SD_, AC, RS, RT, 1, 1);
1588 011111,00000,5.RT,5.RD,11011,010010:SPECIAL3:32::BITREV
1589 "bitrev r<RD>, r<RT>"
1592 do_bitrev (SD_, RD, RT);
1595 011111,5.RS,5.RT,00000,00000,001100:SPECIAL3:32::INSV
1599 do_insv (SD_, RT, RS);
1602 011111,00,8.IMM8,5.RD,00010,010010:SPECIAL3:32::REPL.QB
1603 "repl.qb r<RD>, <IMM8>"
1606 do_repl (SD_, RD, IMM8, 0);
1609 011111,00000,5.RT,5.RD,00011,010010:SPECIAL3:32::REPLV.QB
1610 "replv.qb r<RD>, r<RT>"
1613 do_repl (SD_, RD, RT, 1);
1616 011111,10.IMM10,5.RD,01010,010010:SPECIAL3:32::REPL.PH
1617 "repl.ph r<RD>, <IMM10>"
1620 do_repl (SD_, RD, IMM10, 2);
1623 011111,00000,5.RT,5.RD,01011,010010:SPECIAL3:32::REPLV.PH
1624 "replv.ph r<RD>, r<RT>"
1627 do_repl (SD_, RD, RT, 3);
1630 // op: 0 = EQ, 1 = LT, 2 = LE
1631 :function:::void:do_qb_cmpu:int rs, int rt, int op
1634 uint32_t v1 = GPR[rs];
1635 uint32_t v2 = GPR[rt];
1638 for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1640 h1 = (uint8_t)(v1 & 0xff);
1641 h2 = (uint8_t)(v2 & 0xff);
1642 mask = ~(1 << (DSPCR_CCOND_SHIFT + j));
1645 DSPCR |= ((h1 == h2) << (DSPCR_CCOND_SHIFT + j));
1646 else if (op == 1) // LT
1647 DSPCR |= ((h1 < h2) << (DSPCR_CCOND_SHIFT + j));
1649 DSPCR |= ((h1 <= h2) << (DSPCR_CCOND_SHIFT + j));
1653 011111,5.RS,5.RT,00000,00000,010001:SPECIAL3:32::CMPU.EQ.QB
1654 "cmpu.eq.qb r<RS>, r<RT>"
1657 do_qb_cmpu (SD_, RS, RT, 0);
1660 011111,5.RS,5.RT,00000,00001,010001:SPECIAL3:32::CMPU.LT.QB
1661 "cmpu.lt.qb r<RS>, r<RT>"
1664 do_qb_cmpu (SD_, RS, RT, 1);
1667 011111,5.RS,5.RT,00000,00010,010001:SPECIAL3:32::CMPU.LE.QB
1668 "cmpu.le.qb r<RS>, r<RT>"
1671 do_qb_cmpu (SD_, RS, RT, 2);
1674 // op: 0 = EQ, 1 = LT, 2 = LE
1675 :function:::void:do_qb_cmpgu:int rd, int rs, int rt, int op
1678 uint32_t v1 = GPR[rs];
1679 uint32_t v2 = GPR[rt];
1681 uint32_t result = 0;
1682 for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1684 h1 = (uint8_t)(v1 & 0xff);
1685 h2 = (uint8_t)(v2 & 0xff);
1687 result |= ((h1 == h2) << j);
1688 else if (op == 1) // LT
1689 result |= ((h1 < h2) << j);
1691 result |= ((h1 <= h2) << j);
1693 GPR[rd] = EXTEND32 (result);
1696 011111,5.RS,5.RT,5.RD,00100,010001:SPECIAL3:32::CMPGU.EQ.QB
1697 "cmpgu.eq.qb r<RD>, r<RS>, r<RT>"
1700 do_qb_cmpgu (SD_, RD, RS, RT, 0);
1703 011111,5.RS,5.RT,5.RD,00101,010001:SPECIAL3:32::CMPGU.LT.QB
1704 "cmpgu.lt.qb r<RD>, r<RS>, r<RT>"
1707 do_qb_cmpgu (SD_, RD, RS, RT, 1);
1710 011111,5.RS,5.RT,5.RD,00110,010001:SPECIAL3:32::CMPGU.LE.QB
1711 "cmpgu.le.qb r<RD>, r<RS>, r<RT>"
1714 do_qb_cmpgu (SD_, RD, RS, RT, 2);
1717 // op: 0 = EQ, 1 = LT, 2 = LE
1718 :function:::void:do_ph_cmpu:int rs, int rt, int op
1721 uint32_t v1 = GPR[rs];
1722 uint32_t v2 = GPR[rt];
1725 for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16)
1727 h1 = (int16_t)(v1 & 0xffff);
1728 h2 = (int16_t)(v2 & 0xffff);
1729 mask = ~(1 << (DSPCR_CCOND_SHIFT + j));
1732 DSPCR |= ((h1 == h2) << (DSPCR_CCOND_SHIFT + j));
1733 else if (op == 1) // LT
1734 DSPCR |= ((h1 < h2) << (DSPCR_CCOND_SHIFT + j));
1736 DSPCR |= ((h1 <= h2) << (DSPCR_CCOND_SHIFT + j));
1740 011111,5.RS,5.RT,00000,01000,010001:SPECIAL3:32::CMP.EQ.PH
1741 "cmp.eq.ph r<RS>, r<RT>"
1744 do_ph_cmpu (SD_, RS, RT, 0);
1747 011111,5.RS,5.RT,00000,01001,010001:SPECIAL3:32::CMP.LT.PH
1748 "cmp.lt.ph r<RS>, r<RT>"
1751 do_ph_cmpu (SD_, RS, RT, 1);
1754 011111,5.RS,5.RT,00000,01010,010001:SPECIAL3:32::CMP.LE.PH
1755 "cmp.le.ph r<RS>, r<RT>"
1758 do_ph_cmpu (SD_, RS, RT, 2);
1761 011111,5.RS,5.RT,5.RD,00011,010001:SPECIAL3:32::PICK.QB
1762 "pick.qb r<RD>, r<RS>, r<RT>"
1765 do_qb_pick (SD_, RD, RS, RT);
1768 011111,5.RS,5.RT,5.RD,01011,010001:SPECIAL3:32::PICK.PH
1769 "pick.ph r<RD>, r<RS>, r<RT>"
1772 do_ph_pick (SD_, RD, RS, RT);
1775 011111,5.RS,5.RT,5.RD,01110,010001:SPECIAL3:32::PACKRL.PH
1776 "packrl.ph r<RD>, r<RS>, r<RT>"
1779 do_ph_packrl (SD_, RD, RS, RT);
1782 // op: 0 = EXTR, 1 = EXTR_R, 2 = EXTR_RS
1783 :function:::void:do_w_extr:int rt, int ac, int shift, int op
1786 uint32_t lo = DSPLO(ac);
1787 uint32_t hi = DSPHI(ac);
1788 uint64_t prod = (((uint64_t)hi) << 32) + (uint64_t)lo;
1789 int64_t result = (int64_t)prod;
1791 if (!(prod & 0x8000000000000000LL))
1793 for (i = 62; i >= (shift + 31); i--)
1795 if (prod & ((uint64_t)1 << i))
1797 DSPCR |= DSPCR_OUFLAG7;
1802 if (((prod >> (shift - 1)) & 0xffffffffLL) == 0xffffffffLL)
1804 DSPCR |= DSPCR_OUFLAG7;
1810 for (i = 62; i >= (shift + 31); i--)
1812 if (!(prod & ((uint64_t)1 << i)))
1814 DSPCR |= DSPCR_OUFLAG7;
1820 if (op == 0) // EXTR
1821 result = result >> shift;
1822 else if (op == 1) // EXTR_R
1825 result = ((result >> (shift - 1)) + 1) >> 1;
1827 result = result >> shift;
1832 result = 0x7fffffff;
1833 else if (setcond == 2)
1834 result = 0x80000000;
1838 result = ((result >> (shift - 1)) + 1) >> 1;
1840 result = result >> shift;
1843 GPR[rt] = EXTEND32 (result);
1846 011111,5.SHIFT,5.RT,000,2.AC,00000,111000:SPECIAL3:32::EXTR.W
1847 "extr.w r<RT>, ac<AC>, <SHIFT>"
1850 do_w_extr (SD_, RT, AC, SHIFT, 0);
1853 011111,5.RS,5.RT,000,2.AC,00001,111000:SPECIAL3:32::EXTRV.W
1854 "extrv.w r<RT>, ac<AC>, r<RS>"
1857 do_extrv (SD_, RT, AC, RS, 0);
1860 011111,5.SHIFT,5.RT,000,2.AC,00100,111000:SPECIAL3:32::EXTR_R.W
1861 "extr_r.w r<RT>, ac<AC>, <SHIFT>"
1864 do_w_extr (SD_, RT, AC, SHIFT, 1);
1867 011111,5.RS,5.RT,000,2.AC,00101,111000:SPECIAL3:32::EXTRV_R.W
1868 "extrv_r.w r<RT>, ac<AC>, r<RS>"
1871 do_extrv (SD_, RT, AC, RS, 1);
1874 011111,5.SHIFT,5.RT,000,2.AC,00110,111000:SPECIAL3:32::EXTR_RS.W
1875 "extr_rs.w r<RT>, ac<AC>, <SHIFT>"
1878 do_w_extr (SD_, RT, AC, SHIFT, 2);
1881 011111,5.RS,5.RT,000,2.AC,00111,111000:SPECIAL3:32::EXTRV_RS.W
1882 "extrv_rs.w r<RT>, ac<AC>, r<RS>"
1885 do_extrv (SD_, RT, AC, RS, 2);
1888 :function:::void:do_h_extr:int rt, int ac, int shift
1890 uint32_t lo = DSPLO(ac);
1891 uint32_t hi = DSPHI(ac);
1892 uint64_t prod = (((uint64_t)hi) << 32) + (uint64_t)lo;
1893 int64_t result = (int64_t)prod;
1894 int64_t value = 0xffffffffffff8000LL;
1896 if (result > 0x7fff)
1899 DSPCR |= DSPCR_OUFLAG7;
1901 else if (result < value)
1904 DSPCR |= DSPCR_OUFLAG7;
1906 GPR[rt] = EXTEND32 (result);
1909 011111,5.SHIFT,5.RT,000,2.AC,01110,111000:SPECIAL3:32::EXTR_S.H
1910 "extr_s.h r<RT>, ac<AC>, <SHIFT>"
1913 do_h_extr (SD_, RT, AC, SHIFT);
1916 011111,5.RS,5.RT,000,2.AC,01111,111000:SPECIAL3:32::EXTRV_S.H
1917 "extrv_s.h r<RT>, ac<AC>, r<RS>"
1920 do_extrv_s_h (SD_, RT, AC, RS);
1923 // op: 0 = EXTP, 1 = EXTPDP
1924 :function:::void:do_extp:int rt, int ac, int size, int op
1926 int32_t pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
1927 uint32_t lo = DSPLO(ac);
1928 uint32_t hi = DSPHI(ac);
1929 uint64_t prod = (((uint64_t)hi) << 32) + (uint64_t)lo;
1930 uint64_t result = 0;
1931 if (pos - (size + 1) >= -1)
1933 prod >>= (pos - size);
1934 result = prod & (((uint64_t)1 << (size + 1)) - 1);
1935 DSPCR &= (~DSPCR_EFI_SMASK);
1936 if (op == 1) // EXTPDP
1938 if (pos - (size + 1) >= 0)
1940 DSPCR &= (~DSPCR_POS_SMASK);
1941 DSPCR |= ((pos - (size + 1)) & DSPCR_POS_MASK) << DSPCR_POS_SHIFT;
1943 else if (pos - (size + 1) == -1)
1945 DSPCR |= DSPCR_POS_SMASK;
1954 GPR[rt] = EXTEND32 (result);
1957 011111,5.SIZE,5.RT,000,2.AC,00010,111000:SPECIAL3:32::EXTP
1958 "extp r<RT>, ac<AC>, <SIZE>"
1961 do_extp (SD_, RT, AC, SIZE, 0);
1964 011111,5.RS,5.RT,000,2.AC,00011,111000:SPECIAL3:32::EXTPV
1965 "extpv r<RT>, ac<AC>, r<RS>"
1968 do_extpv (SD_, RT, AC, RS, 0);
1971 011111,5.SIZE,5.RT,000,2.AC,01010,111000:SPECIAL3:32::EXTPDP
1972 "extpdp r<RT>, ac<AC>, <SIZE>"
1975 do_extp (SD_, RT, AC, SIZE, 1);
1978 011111,5.RS,5.RT,000,2.AC,01011,111000:SPECIAL3:32::EXTPDPV
1979 "extpdpv r<RT>, ac<AC>, r<RS>"
1982 do_extpv (SD_, RT, AC, RS, 1);
1985 :function:::void:do_shilo:int ac, int shift
1987 uint32_t lo = DSPLO(ac);
1988 uint32_t hi = DSPHI(ac);
1989 uint64_t prod = (((uint64_t)hi) << 32) + (uint64_t)lo;
1996 DSPLO(ac) = EXTEND32 (prod);
1997 DSPHI(ac) = EXTEND32 (prod >> 32);
2000 011111,6.SHIFT6,0000,000,2.AC,11010,111000:SPECIAL3:32::SHILO
2001 "shilo ac<AC>, <SHIFT6>"
2004 do_shilo (SD_, AC, SHIFT6);
2007 011111,5.RS,00000,000,2.AC,11011,111000:SPECIAL3:32::SHILOV
2008 "shilov ac<AC>, r<RS>"
2011 do_shilov (SD_, AC, RS);
2014 011111,5.RS,00000,000,2.AC,11111,111000:SPECIAL3:32::MTHLIP
2015 "mthlip r<RS>, ac<AC>"
2018 do_mthlip (SD_, RS, AC);
2021 011111,5.RS,10.MASK10,10011,111000:SPECIAL3:32::WRDSP
2022 "wrdsp r<RS>":MASK10 == 1111111111
2023 "wrdsp r<RS>, <MASK10>"
2026 do_wrdsp (SD_, RS, MASK10);
2029 011111,10.MASK10,5.RD,10010,111000:SPECIAL3:32::RDDSP
2030 "rddsp r<RD>":MASK10 == 1111111111
2031 "rddsp r<RD>, <MASK10>"
2034 do_rddsp (SD_, RD, MASK10);
2037 011111,5.BASE,5.INDEX,5.RD,00110,001010:SPECIAL3:32::LBUX
2038 "lbux r<RD>, r<INDEX>(r<BASE>)"
2041 do_lxx (SD_, RD, BASE, INDEX, 0);
2044 011111,5.BASE,5.INDEX,5.RD,00100,001010:SPECIAL3:32::LHX
2045 "lhx r<RD>, r<INDEX>(r<BASE>)"
2048 do_lxx (SD_, RD, BASE, INDEX, 1);
2051 011111,5.BASE,5.INDEX,5.RD,00000,001010:SPECIAL3:32::LWX
2052 "lwx r<RD>, r<INDEX>(r<BASE>)"
2055 do_lxx (SD_, RD, BASE, INDEX, 2);
2058 000001,00000,11100,16.OFFSET:REGIMM:32::BPOSGE32
2062 uint32_t pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
2063 address_word offset = EXTEND16 (OFFSET) << 2;
2066 DELAY_SLOT (NIA + offset);