9ea5272f3ac175a3c576b310c34f5305d7edb0df
[external/binutils.git] / sim / mips / dsp.igen
1 // -*- C -*-
2
3 // Simulator definition for the MIPS DSP ASE.
4 // Copyright (C) 2005-2016 Free Software Foundation, Inc.
5 // Contributed by MIPS Technologies, Inc.  Written by Chao-ying Fu.
6 //
7 // This file is part of the MIPS sim
8 //
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.
13 //
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.
18 //
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/>.
21
22
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
26 {
27   int i;
28   signed32 h0 = 0;
29   signed16 h1, h2;
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)
34     {
35       h1 = (signed16)(v1 & 0xffff);
36       h2 = (signed16)(v2 & 0xffff);
37       if (op == 0) // ADD
38         h0 = (signed32)h1 + (signed32)h2;
39       else if (op == 1) // SUB
40         h0 = (signed32)h1 - (signed32)h2;
41       else // MUL
42         h0 = (signed32)h1 * (signed32)h2;
43       if (h0 > (signed32)0x7fff || h0 < (signed32)0xffff8000)
44         {
45           if (op == 0 || op == 1) // ADD, SUB
46             DSPCR |= DSPCR_OUFLAG4;
47           else if (op == 2) // MUL
48             DSPCR |= DSPCR_OUFLAG5;
49           if (sat == 1)
50             {
51               if (h0 > (signed32)0x7fff)
52                 h0 = 0x7fff;
53               else
54                 h0 = 0x8000;
55             }
56         }
57       result |= ((unsigned32)((unsigned16)h0) << i);
58     }
59   GPR[rd] = EXTEND32 (result);
60 }
61
62 // op: 0 = ADD, 1 = SUB
63 :function:::void:do_w_op:int rd, int rs, int rt, int op
64 {
65   signed64 h0;
66   signed32 h1, h2;
67   unsigned32 v1 = GPR[rs];
68   unsigned32 v2 = GPR[rt];
69   unsigned32 result = 0;
70   h1 = (signed32)v1;
71   h2 = (signed32)v2;
72   if (op == 0) // ADD
73     h0 = (signed64)h1 + (signed64)h2;
74   else // SUB
75     h0 = (signed64)h1 - (signed64)h2;
76   if (((h0 & 0x100000000LL) >> 1) != (h0 & 0x80000000))
77     {
78       DSPCR |= DSPCR_OUFLAG4;
79       if (h0 & 0x100000000LL)
80         h0 = 0x80000000;
81       else
82         h0 = 0x7fffffff;
83     }
84   GPR[rd] = EXTEND32 (h0);
85 }
86
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
90 {
91   int i;
92   unsigned32 h0;
93   unsigned8 h1, h2;
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)
98     {
99       h1 = (unsigned8)(v1 & 0xff);
100       h2 = (unsigned8)(v2 & 0xff);
101       if (op == 0) // ADD
102         h0 = (unsigned32)h1 + (unsigned32)h2;
103       else // SUB
104         h0 = (unsigned32)h1 - (unsigned32)h2;
105       if (h0 & 0x100)
106         {
107           DSPCR |= DSPCR_OUFLAG4;
108           if (sat == 1)
109             {
110               if (op == 0) // ADD
111                 h0 = 0xff;
112               else // SUB
113                 h0 = 0;
114             }
115         }
116       result |= ((unsigned32)((unsigned8)h0) << i);
117     }
118   GPR[rd] = EXTEND32 (result);
119 }
120
121 // op: 0 = left, 1 = right
122 :function:::void:do_qb_shift:int rd, int rt, int shift, int op
123 {
124   int i, j;
125   unsigned8 h0;
126   unsigned32 v1 = GPR[rt];
127   unsigned32 result = 0;
128   for (i = 0; i < 32; i += 8, v1 >>= 8)
129     {
130       h0 = (unsigned8)(v1 & 0xff);
131       if (op == 0) // left
132         {
133           for (j = 7; j >= 8 - shift; j--)
134             {
135               if (h0 & (1<<j))
136                 {
137                   DSPCR |= DSPCR_OUFLAG6;
138                   break;
139                 }
140             }
141           h0 = h0 << shift;
142         }
143       else // right
144         h0 = h0 >> shift;
145       result |= ((unsigned32)h0 << i);
146     }
147   GPR[rd] = EXTEND32 (result);
148 }
149
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
153 {
154   int i, j;
155   signed16 h0;
156   unsigned32 v1 = GPR[rt];
157   unsigned32 result = 0;
158   int setcond;
159   for (i = 0; i < 32; i += 16, v1 >>= 16)
160     {
161       h0 = (signed16)(v1 & 0xffff);
162       if (op == 0) // left
163         {
164           setcond = 0;
165           if (h0 & (1<<15))
166             {
167               for (j = 14; j >= 15 - shift; j--)
168                 {
169                   if (!(h0 & (1 << j)))
170                     {
171                       DSPCR |= DSPCR_OUFLAG6;
172                       setcond = 1;
173                       break;
174                     }
175                 }
176             }
177           else
178             {
179               for (j = 14; j >= 15 - shift; j--)
180                 {
181                   if (h0 & (1 << j))
182                     {
183                       DSPCR |= DSPCR_OUFLAG6;
184                       setcond = 2;
185                       break;
186                     }
187                 }
188             }
189           h0 = h0 << shift;
190           if (sat == 1)
191             {
192               if (setcond == 2)
193                 h0 = 0x7fff; 
194               else if (setcond == 1)
195                 h0 = 0x8000;
196             }
197         }
198       else // right
199         {
200           if (sat == 1 && shift != 0 && (h0 & (1 << (shift-1))))
201             h0 = (h0 >> shift) + 1;
202           else
203             h0 = h0 >> shift;
204         }
205
206       result |= ((unsigned32)((unsigned16)h0) << i);
207     }
208   GPR[rd] = EXTEND32 (result);
209 }
210
211 :function:::void:do_w_shll:int rd, int rt, int shift
212 {
213   int i;
214   unsigned32 v1 = GPR[rt];
215   unsigned32 result = 0;
216   int setcond = 0;
217   if (v1 & (1 << 31))
218     {
219       for (i = 30; i >= 31 - shift; i--)
220         {
221           if (!(v1 & (1 << i)))
222             {
223               DSPCR |= DSPCR_OUFLAG6;
224               setcond = 1;
225               break;
226             }
227         }
228     }
229   else
230     {
231       for (i = 30; i >= 31 - shift; i--)
232         {
233           if (v1 & (1 << i))
234             {
235               DSPCR |= DSPCR_OUFLAG6;
236               setcond = 2;
237               break;
238             }
239         }
240     }
241   if (setcond == 2)
242     result = 0x7fffffff; 
243   else if (setcond == 1)
244     result = 0x80000000;
245   else
246     result = v1 << shift; 
247   GPR[rd] = EXTEND32 (result);
248 }
249
250 :function:::void:do_ph_s_absq:int rd, int rt
251 {
252   int i;
253   signed16 h0;
254   unsigned32 v1 = GPR[rt];
255   unsigned32 result = 0;
256   for (i = 0; i < 32; i += 16, v1 >>= 16)
257     {
258       h0 = (signed16)(v1 & 0xffff);
259       if (h0 == (signed16)0x8000)
260         {
261           DSPCR |= DSPCR_OUFLAG4;
262           h0 = 0x7fff;
263         }
264       else if (h0 & 0x8000)
265         h0 = -h0;
266       result |= ((unsigned32)((unsigned16)h0) << i);
267     }
268   GPR[rd] = EXTEND32 (result);
269 }
270
271 :function:::void:do_w_s_absq:int rd, int rt
272 {
273   unsigned32 v1 = GPR[rt];
274   signed32 h0 = (signed32)v1;
275   if (h0 == (signed32)0x80000000)
276     {
277       DSPCR |= DSPCR_OUFLAG4;
278       h0 = 0x7fffffff;
279     }
280   else if (h0 & 0x80000000)
281     h0 = -h0;
282   GPR[rd] = EXTEND32 (h0);
283 }
284
285 :function:::void:do_qb_s_absq:int rd, int rt
286 {
287   int i;
288   signed8 q0;
289   unsigned32 v1 = GPR[rt];
290   unsigned32 result = 0;
291   for (i = 0; i < 32; i += 8, v1 >>= 8)
292     {
293       q0 = (signed8)(v1 & 0xff);
294       if (q0 == (signed8)0x80)
295         {
296           DSPCR |= DSPCR_OUFLAG4;
297           q0 = 0x7f;
298         }
299       else if (q0 & 0x80)
300         q0 = -q0;
301       result |= ((unsigned32)((unsigned8)q0) << i);
302     }
303   GPR[rd] = EXTEND32 (result);
304 }
305
306 :function:::void:do_addsc:int rd, int rs, int rt
307 {
308   unsigned32 v1 = GPR[rs];
309   unsigned32 v2 = GPR[rt];
310   unsigned64 h0;
311   h0 = (unsigned64)v1 + (unsigned64)v2;
312   if (h0 & 0x100000000LL)
313     DSPCR |= DSPCR_CARRY;
314   GPR[rd] = EXTEND32 (h0);
315 }
316
317 :function:::void:do_addwc:int rd, int rs, int rt
318 {
319   unsigned32 v1 = GPR[rs];
320   unsigned32 v2 = GPR[rt];
321   unsigned64 h0;
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);
329 }
330
331 :function:::void:do_bitrev:int rd, int rt
332 {
333   int i;
334   unsigned32 v1 = GPR[rt];
335   unsigned32 h1 = 0;
336   for (i = 0; i < 16; i++)
337     {
338       if (v1 & (1 << i))
339         h1 |= (1 << (15 - i));
340     }
341   GPR[rd] = EXTEND32 (h1);
342 }
343
344 // op: 0 = EXTPV, 1 = EXTPDPV
345 :function:::void:do_extpv:int rt, int ac, int rs, int op
346 {
347   unsigned32 size = GPR[rs] & 0x1f;
348   do_extp (SD_, rt, ac, size, op);
349 }
350
351 // op: 0 = EXTRV, 1 = EXTRV_R, 2 = EXTRV_RS
352 :function:::void:do_extrv:int rt, int ac, int rs, int op
353 {
354   unsigned32 shift = GPR[rs] & 0x1f;
355   do_w_extr (SD_, rt, ac, shift, op);
356 }
357
358 :function:::void:do_extrv_s_h:int rt, int ac, int rs
359 {
360   unsigned32 shift = GPR[rs] & 0x1f;
361   do_h_extr (SD_, rt, ac, shift);
362 }
363
364 :function:::void:do_insv:int rt, int rs
365 {
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;
371   if (size < 32)
372     mask1 = (1 << size) - 1;
373   else
374     mask1 = 0xffffffff;
375   mask2 = (1 << pos) - 1;
376   if (pos + size < 32)
377     mask3 = ~((1 << (pos + size)) - 1);
378   else
379     mask3 = 0;
380   result = (v2 & mask3) | ((v1 & mask1) << pos) | (v2 & mask2);
381   GPR[rt] = EXTEND32 (result);
382 }
383
384 // op: 0 = NORMAL,  1 = EXTEND16, 2 = EXTEND32
385 :function:::void:do_lxx:int rd, int base, int index, int op
386 {
387   if (op == 0)
388     GPR[rd] = do_load (SD_, AccessLength_BYTE, GPR[base], GPR[index]);
389   else if (op == 1)
390     GPR[rd] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[base], GPR[index]));
391   else if (op == 2)
392     GPR[rd] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[base], GPR[index]));
393 }
394
395 :function:::void:do_modsub:int rd, int rs, int rt
396 {
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;
402   if (v1 == 0)
403     result = lastindex;
404   else
405     result =  v1 - decr;
406   GPR[rd] = EXTEND32 (result);
407 }
408
409 :function:::void:do_mthlip:int rs, int ac
410 {
411   unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
412   DSPHI(ac) = DSPLO(ac);
413   DSPLO(ac) = GPR[rs];
414   if (pos >= 32)
415     Unpredictable ();
416   else
417     pos += 32;
418   DSPCR &= (~DSPCR_POS_SMASK);
419   DSPCR |= (pos & DSPCR_POS_MASK) << DSPCR_POS_SHIFT;
420 }
421
422 :function:::void:do_mulsaq_s_w_ph:int ac, int rs, int rt
423 {
424   int i;
425   unsigned32 v1 = GPR[rs];
426   unsigned32 v2 = GPR[rt];
427   signed16 h1, h2;
428   signed32 result;
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)
433     {
434       h1 = (signed16)(v1 & 0xffff);
435       h2 = (signed16)(v2 & 0xffff);
436       if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
437         {
438           DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
439           result = (signed32) 0x7fffffff;
440         }
441       else
442         result = ((signed32)h1 * (signed32)h2) << 1;
443
444       if (i == 0)
445         prod -= (signed64) result;
446       else
447         prod += (signed64) result;
448     }
449   DSPLO(ac) = EXTEND32 (prod);
450   DSPHI(ac) = EXTEND32 (prod >> 32);
451 }
452
453 :function:::void:do_ph_packrl:int rd, int rs, int rt
454 {
455
456   unsigned32 v1 = GPR[rs];
457   unsigned32 v2 = GPR[rt];
458   GPR[rd] = EXTEND32 ((v1 << 16) + (v2 >> 16));
459 }
460
461 :function:::void:do_qb_pick:int rd, int rs, int rt
462 {
463   int i, j;
464   unsigned32 v1 = GPR[rs];
465   unsigned32 v2 = GPR[rt];
466   unsigned8 h1, h2;
467   unsigned32 result = 0;
468   for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
469     {
470       h1 = (unsigned8)(v1 & 0xff);
471       h2 = (unsigned8)(v2 & 0xff);
472       if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j)))
473         result |= (unsigned32)(h1 << i);
474       else
475         result |= (unsigned32)(h2 << i);
476     }
477   GPR[rd] = EXTEND32 (result);
478 }
479
480 :function:::void:do_ph_pick:int rd, int rs, int rt
481 {
482   int i, j;
483   unsigned32 v1 = GPR[rs];
484   unsigned32 v2 = GPR[rt];
485   unsigned16 h1, h2;
486   unsigned32 result = 0;
487   for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16)
488     {
489       h1 = (unsigned16)(v1 & 0xffff);
490       h2 = (unsigned16)(v2 & 0xffff);
491       if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j)))
492         result |= (unsigned32)(h1 << i);
493       else
494         result |= (unsigned32)(h2 << i);
495     }
496   GPR[rd] = EXTEND32 (result);
497 }
498
499 // op: 0 = QBR, 1 = QBRA, 2 = QBL, 3 = QBLA
500 :function:::void:do_qb_ph_precequ:int rd, int rt, int op
501 {
502   unsigned32 v1 = GPR[rt];
503   if (op == 0)
504     GPR[rd] = EXTEND32 ((v1 & 0xff00) << 15) | ((v1 & 0xff) << 7);
505   else if (op == 1)
506     GPR[rd] = EXTEND32 ((v1 & 0xff0000) << 7) | ((v1 & 0xff) << 7);
507   else if (op == 2)
508     GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff0000) >> 9);
509   else if (op == 3)
510     GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff00) >> 1);
511 }
512
513 // op: 0 = QBR, 1 = QBRA, 2 = QBL, 3 = QBLA
514 :function:::void:do_qb_ph_preceu:int rd, int rt, int op
515 {
516   unsigned32 v1 = GPR[rt];
517   if (op == 0)
518     GPR[rd] = EXTEND32 ((v1 & 0xff00) << 8) | (v1 & 0xff);
519   else if (op == 1)
520     GPR[rd] = EXTEND32 ((v1 & 0xff0000) | (v1 & 0xff));
521   else if (op == 2)
522     GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff0000) >> 16);
523   else if (op == 3)
524     GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff00) >> 8);
525 }
526
527 // op: 0 = .PHL, 1 = PHR
528 :function:::void:do_w_preceq:int rd, int rt, int op
529 {
530   unsigned32 v1 = GPR[rt];
531   if (op == 0)
532     GPR[rd] = EXTEND32 (v1 & 0xffff0000);
533   else if (op == 1)
534     GPR[rd] = EXTEND32 ((v1 & 0xffff) << 16);
535 }
536
537 :function:::void:do_w_ph_precrq:int rd, int rs, int rt
538 {
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);
544 }
545
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
548 {
549   unsigned32 v1 = GPR[rs];
550   unsigned32 v2 = GPR[rt];
551   unsigned32 tempu = 0, tempv = 0, tempw = 0, tempx = 0;
552   if (sat == 0)
553     {
554       tempu = (v1 & 0xff000000) >> 24;
555       tempv = (v1 & 0xff00) >> 8;
556       tempw = (v2 & 0xff000000) >> 24;
557       tempx = (v2 & 0xff00) >> 8;
558     }
559   else if (sat == 1)
560     {
561       if (v1 & 0x80000000)
562         {
563           DSPCR |= DSPCR_OUFLAG6;
564           tempu = 0;
565         }
566       else if (!(v1 & 0x80000000) && ((v1 >> 16) > (unsigned32)0x7f80))
567         {
568           DSPCR |= DSPCR_OUFLAG6;
569           tempu = 0xff;
570         }
571       else
572         tempu = (v1 & 0x7f800000) >> 23;
573       if (v1 & 0x8000)
574         {
575           DSPCR |= DSPCR_OUFLAG6;
576           tempv = 0;
577         }
578       else if (!(v1 & 0x8000) && ((v1 & 0xffff) > (unsigned32)0x7f80))
579         {
580           DSPCR |= DSPCR_OUFLAG6;
581           tempv = 0xff;
582         }
583       else
584         tempv = (v1 & 0x7f80) >> 7;
585       if (v2 & 0x80000000)
586         {
587           DSPCR |= DSPCR_OUFLAG6;
588           tempw = 0;
589         }
590       else if (!(v2 & 0x80000000) && ((v2 >> 16) > (unsigned32)0x7f80))
591         {
592           DSPCR |= DSPCR_OUFLAG6;
593           tempw = 0xff;
594         }
595       else
596         tempw = (v2 & 0x7f800000) >> 23;
597       if (v2 & 0x8000)
598         {
599           DSPCR |= DSPCR_OUFLAG6;
600           tempx = 0;
601         }
602       else if (!(v2 & 0x8000) && ((v2 & 0xffff) > (unsigned32)0x7f80))
603         {
604           DSPCR |= DSPCR_OUFLAG6;
605           tempx = 0xff;
606         }
607       else
608         tempx = (v2 & 0x7f80) >> 7;
609     }
610   GPR[rd] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx);
611 }
612
613 :function:::void:do_w_ph_rs_precrq:int rd, int rs, int rt
614 {
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;
620   signed32 temp2;
621   signed64 temp3 = (signed64)h2 + (signed64)0x8000;
622   signed32 temp4;
623   if (((temp1 & 0x100000000LL) >> 1) != (temp1 & 0x80000000))
624     {
625       DSPCR |= DSPCR_OUFLAG6;
626       temp2 = 0x7fff;
627     }
628   else
629     temp2 = (signed32)((temp1 & 0xffff0000) >> 16);
630   if (((temp3 & 0x100000000LL) >> 1) != (temp3 & 0x80000000))
631     {
632       DSPCR |= DSPCR_OUFLAG6;
633       temp4 = 0x7fff;
634     }
635   else
636     temp4 = (signed32)((temp3 & 0xffff0000) >> 16);
637   GPR[rd] = EXTEND32 ((temp2 << 16) | temp4);
638 }
639
640 :function:::void:do_qb_w_raddu:int rd, int rs
641 {
642   int i;
643   unsigned8 h0;
644   unsigned32 v1 = GPR[rs];
645   unsigned32 result = 0;
646   for (i = 0; i < 32; i += 8, v1 >>= 8)
647     {
648       h0 = (unsigned8)(v1 & 0xff);
649       result += (unsigned32)h0;
650     }
651   GPR[rd] = EXTEND32 (result);
652 }
653
654 :function:::void:do_rddsp:int rd, int mask
655 {
656   unsigned32 result = 0;
657   if (mask & 0x1)
658     {
659       result &= (~DSPCR_POS_SMASK);
660       result |= (DSPCR & DSPCR_POS_SMASK);
661     }
662   if (mask & 0x2)
663     {
664       result &= (~DSPCR_SCOUNT_SMASK);
665       result |= (DSPCR & DSPCR_SCOUNT_SMASK);
666     }
667   if (mask & 0x4)
668     {
669       result &= (~DSPCR_CARRY_SMASK);
670       result |= (DSPCR & DSPCR_CARRY_SMASK);
671     }
672   if (mask & 0x8)
673     {
674       result &= (~DSPCR_OUFLAG_SMASK);
675       result |= (DSPCR & DSPCR_OUFLAG_SMASK);
676     }
677   if (mask & 0x10)
678     {
679       result &= (~DSPCR_CCOND_SMASK);
680       result |= (DSPCR & DSPCR_CCOND_SMASK);
681     }
682   if (mask & 0x20)
683     {
684       result &= (~DSPCR_EFI_SMASK);
685       result |= (DSPCR & DSPCR_EFI_SMASK);
686     }
687   GPR[rd] = EXTEND32 (result);
688 }
689
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
692 {
693   if (op == 0)
694     GPR[rd] = EXTEND32 ((p2 << 24) | (p2 << 16) | (p2 << 8) | p2);
695   else if (op == 1)
696     {
697       unsigned32 v1 = GPR[p2] & 0xff;
698       GPR[rd] = EXTEND32 ((v1 << 24) | (v1 << 16) | (v1 << 8) | v1);
699     }
700   else if (op == 2)
701     {
702       signed32 v1 = p2;
703       if (v1 & 0x200)
704         v1 |= 0xfffffc00;
705       GPR[rd] = EXTEND32 ((v1 << 16) | (v1 & 0xffff));
706     }
707   else if (op == 3)
708     {
709       unsigned32 v1 = GPR[p2];
710       v1 = v1 & 0xffff;
711       GPR[rd] = EXTEND32 ((v1 << 16) | v1);
712     }
713 }
714
715 :function:::void:do_shilov:int ac, int rs
716 {
717   signed32 shift = GPR[rs] & 0x3f;
718   do_shilo (SD_, ac, shift);
719 }
720
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
724 {
725   unsigned32 shift = GPR[rs] & 0xf;
726   do_ph_shift (SD_, rd, rt, shift, op, sat);
727 }
728
729 // op: 0 = SHLLV, 1 = SHRLV
730 :function:::void:do_qb_shl:int rd, int rt, int rs, int op
731 {
732   unsigned32 shift = GPR[rs] & 0x7;
733   do_qb_shift (SD_, rd, rt, shift, op);
734 }
735
736 :function:::void:do_w_s_shllv:int rd, int rt, int rs
737 {
738   unsigned32 shift = GPR[rs] & 0x1f;
739   do_w_shll (SD_, rd, rt, shift);
740 }
741
742 :function:::void:do_ph_shrlv:int rd, int rt, int rs
743 {
744   unsigned32 shift = GPR[rs] & 0xf;
745   do_ph_shrl (SD_, rd, rt, shift);
746 }
747
748 :function:::void:do_w_r_shrav:int rd, int rt, int rs
749 {
750   unsigned32 shift = GPR[rs] & 0x1f;
751   do_w_shra (SD_, rd, rt, shift);
752 }
753
754 :function:::void:do_wrdsp:int rs, int mask
755 {
756   unsigned32 v1 = GPR[rs];
757   if (mask & 0x1)
758     {
759       DSPCR &= (~DSPCR_POS_SMASK);
760       DSPCR |= (v1 & DSPCR_POS_SMASK);
761     }
762   if (mask & 0x2)
763     {
764       DSPCR &= (~DSPCR_SCOUNT_SMASK);
765       DSPCR |= (v1 & DSPCR_SCOUNT_SMASK);
766     }
767   if (mask & 0x4)
768     {
769       DSPCR &= (~DSPCR_CARRY_SMASK);
770       DSPCR |= (v1 & DSPCR_CARRY_SMASK);
771     }
772   if (mask & 0x8)
773     {
774       DSPCR &= (~DSPCR_OUFLAG_SMASK);
775       DSPCR |= (v1 & DSPCR_OUFLAG_SMASK);
776     }
777   if (mask & 0x10)
778     {
779       DSPCR &= (~DSPCR_CCOND_SMASK);
780       DSPCR |= (v1 & DSPCR_CCOND_SMASK);
781     }
782   if (mask & 0x20)
783     {
784       DSPCR &= (~DSPCR_EFI_SMASK);
785       DSPCR |= (v1 & DSPCR_EFI_SMASK);
786     }
787 }
788
789 // round: 0 = no rounding, 1 = rounding
790 :function:::void:do_qb_shrav:int rd, int rt, int rs, int round
791 {
792   unsigned32 shift = GPR[rs] & 0x7;
793   do_qb_shra (SD_, rd, rt, shift, round);
794 }
795
796 :function:::void:do_append:int rt, int rs, int sa
797 {
798   unsigned32 v0 = GPR[rs];
799   unsigned32 v1 = GPR[rt];
800   unsigned32 result;
801   unsigned32 mask = (1 << sa) - 1;
802   result = (v1 << sa) | (v0 & mask);
803   GPR[rt] = EXTEND32 (result);
804 }
805
806 :function:::void:do_balign:int rt, int rs, int bp
807 {
808   unsigned32 v0 = GPR[rs];
809   unsigned32 v1 = GPR[rt];
810   unsigned32 result;
811   if (bp == 0)
812     result = v1;
813   else
814     result = (v1 << 8 * bp) | (v0 >> 8 * (4 - bp));
815   GPR[rt] = EXTEND32 (result);
816 }
817
818 :function:::void:do_ph_w_mulsa:int ac, int rs, int rt
819 {
820   int i;
821   unsigned32 v1 = GPR[rs];
822   unsigned32 v2 = GPR[rt];
823   signed16 h1, h2;
824   signed32 result;
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)
829     {
830       h1 = (signed16)(v1 & 0xffff);
831       h2 = (signed16)(v2 & 0xffff);
832       result = (signed32)h1 * (signed32)h2;
833
834       if (i == 0)
835         prod -= (signed64) result;
836       else
837         prod += (signed64) result;
838     }
839   DSPLO(ac) = EXTEND32 (prod);
840   DSPHI(ac) = EXTEND32 (prod >> 32);
841 }
842
843 :function:::void:do_ph_qb_precr:int rd, int rs, int rt
844 {
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);
852 }
853
854 :function:::void:do_prepend:int rt, int rs, int sa
855 {
856   unsigned32 v0 = GPR[rs];
857   unsigned32 v1 = GPR[rt];
858   unsigned32 result;
859   if (sa == 0)
860     result = v1;
861   else
862     result = (v0 << (32 - sa)) | (v1 >> sa);
863   GPR[rt] = EXTEND32 (result);
864 }
865
866 :function:::void:do_w_shra:int rd, int rt, int shift
867 {
868   unsigned32 result = GPR[rt];
869   signed32 h0 = (signed32)result;
870   if (shift != 0 && (h0 & (1 << (shift-1))))
871     h0 = (h0 >> shift) + 1;
872   else
873     h0 = h0 >> shift;
874   GPR[rd] = EXTEND32 (h0);
875 }
876
877 011111,5.RS,5.RT,5.RD,01010,010000:SPECIAL3:32::ADDQ.PH
878 "addq.ph r<RD>, r<RS>, r<RT>"
879 *dsp:
880 {
881   do_ph_op (SD_, RD, RS, RT, 0, 0);
882 }
883
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>"
886 *dsp:
887 {
888   do_ph_op (SD_, RD, RS, RT, 0, 1);
889 }
890
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>"
893 *dsp:
894 {
895   do_w_op (SD_, RD, RS, RT, 0);
896 }
897
898 011111,5.RS,5.RT,5.RD,00000,010000:SPECIAL3:32::ADDU.QB
899 "addu.qb r<RD>, r<RS>, r<RT>"
900 *dsp:
901 {
902   do_qb_op (SD_, RD, RS, RT, 0, 0);
903 }
904
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>"
907 *dsp:
908 {
909   do_qb_op (SD_, RD, RS, RT, 0, 1);
910 }
911
912 011111,5.RS,5.RT,5.RD,01011,010000:SPECIAL3:32::SUBQ.PH
913 "subq.ph r<RD>, r<RS>, r<RT>"
914 *dsp:
915 {
916   do_ph_op (SD_, RD, RS, RT, 1, 0);
917 }
918
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>"
921 *dsp:
922 {
923   do_ph_op (SD_, RD, RS, RT, 1, 1);
924 }
925
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>"
928 *dsp:
929 {
930   do_w_op (SD_, RD, RS, RT, 1);
931 }
932
933 011111,5.RS,5.RT,5.RD,00001,010000:SPECIAL3:32::SUBU.QB
934 "subu.qb r<RD>, r<RS>, r<RT>"
935 *dsp:
936 {
937   do_qb_op (SD_, RD, RS, RT, 1, 0);
938 }
939
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>"
942 *dsp:
943 {
944   do_qb_op (SD_, RD, RS, RT, 1, 1);
945 }
946
947 011111,5.RS,5.RT,5.RD,10000,010000:SPECIAL3:32::ADDSC
948 "addsc r<RD>, r<RS>, r<RT>"
949 *dsp:
950 {
951   do_addsc (SD_, RD, RS, RT);
952 }
953
954 011111,5.RS,5.RT,5.RD,10001,010000:SPECIAL3:32::ADDWC
955 "addwc r<RD>, r<RS>, r<RT>"
956 *dsp:
957 {
958   do_addwc (SD_, RD, RS, RT);
959 }
960
961 011111,5.RS,5.RT,5.RD,10010,010000:SPECIAL3:32::MODSUB
962 "modsub r<RD>, r<RS>, r<RT>"
963 *dsp:
964 {
965   do_modsub (SD_, RD, RS, RT);
966 }
967
968 011111,5.RS,00000,5.RD,10100,010000:SPECIAL3:32::RADDU.W.QB
969 "raddu.w.qb r<RD>, r<RS>"
970 *dsp:
971 {
972   do_qb_w_raddu (SD_, RD, RS);
973 }
974
975 011111,00000,5.RT,5.RD,01001,010010:SPECIAL3:32::ABSQ_S.PH
976 "absq_s.ph r<RD>, r<RT>"
977 *dsp:
978 {
979   do_ph_s_absq (SD_, RD, RT);
980 }
981
982 011111,00000,5.RT,5.RD,10001,010010:SPECIAL3:32::ABSQ_S.W
983 "absq_s.w r<RD>, r<RT>"
984 *dsp:
985 {
986   do_w_s_absq (SD_, RD, RT);
987 }
988
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>"
991 *dsp:
992 {
993   do_ph_qb_precrq (SD_, RD, RS, RT, 0);
994 }
995
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>"
998 *dsp:
999 {
1000   do_w_ph_precrq (SD_, RD, RS, RT);
1001 }
1002
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>"
1005 *dsp:
1006 {
1007   do_w_ph_rs_precrq (SD_, RD, RS, RT);
1008 }
1009
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>"
1012 *dsp:
1013 {
1014   do_ph_qb_precrq (SD_, RD, RS, RT, 1);
1015 }
1016
1017 011111,00000,5.RT,5.RD,01100,010010:SPECIAL3:32::PRECEQ.W.PHL
1018 "preceq.w.phl r<RD>, r<RT>"
1019 *dsp:
1020 {
1021   do_w_preceq (SD_, RD, RT, 0);
1022 }
1023
1024 011111,00000,5.RT,5.RD,01101,010010:SPECIAL3:32::PRECEQ.W.PHR
1025 "preceq.w.phr r<RD>, r<RT>"
1026 *dsp:
1027 {
1028   do_w_preceq (SD_, RD, RT, 1);
1029 }
1030
1031 011111,00000,5.RT,5.RD,00100,010010:SPECIAL3:32::PRECEQU.PH.QBL
1032 "precequ.ph.qbl r<RD>, r<RT>"
1033 *dsp:
1034 {
1035   do_qb_ph_precequ (SD_, RD, RT, 2);
1036 }
1037
1038 011111,00000,5.RT,5.RD,00101,010010:SPECIAL3:32::PRECEQU.PH.QBR
1039 "precequ.ph.qbr r<RD>, r<RT>"
1040 *dsp:
1041 {
1042   do_qb_ph_precequ (SD_, RD, RT, 0);
1043 }
1044
1045 011111,00000,5.RT,5.RD,00110,010010:SPECIAL3:32::PRECEQU.PH.QBLA
1046 "precequ.ph.qbla r<RD>, r<RT>"
1047 *dsp:
1048 {
1049   do_qb_ph_precequ (SD_, RD, RT, 3);
1050 }
1051
1052 011111,00000,5.RT,5.RD,00111,010010:SPECIAL3:32::PRECEQU.PH.QBRA
1053 "precequ.ph.qbra r<RD>, r<RT>"
1054 *dsp:
1055 {
1056   do_qb_ph_precequ (SD_, RD, RT, 1);
1057 }
1058
1059 011111,00000,5.RT,5.RD,11100,010010:SPECIAL3:32::PRECEU.PH.QBL
1060 "preceu.ph.qbl r<RD>, r<RT>"
1061 *dsp:
1062 {
1063   do_qb_ph_preceu (SD_, RD, RT, 2);
1064 }
1065
1066 011111,00000,5.RT,5.RD,11101,010010:SPECIAL3:32::PRECEU.PH.QBR
1067 "preceu.ph.qbr r<RD>, r<RT>"
1068 *dsp:
1069 {
1070   do_qb_ph_preceu (SD_, RD, RT, 0);
1071 }
1072
1073 011111,00000,5.RT,5.RD,11110,010010:SPECIAL3:32::PRECEU.PH.QBLA
1074 "preceu.ph.qbla r<RD>, r<RT>"
1075 *dsp:
1076 {
1077   do_qb_ph_preceu (SD_, RD, RT, 3);
1078 }
1079
1080 011111,00000,5.RT,5.RD,11111,010010:SPECIAL3:32::PRECEU.PH.QBRA
1081 "preceu.ph.qbra r<RD>, r<RT>"
1082 *dsp:
1083 {
1084   do_qb_ph_preceu (SD_, RD, RT, 1);
1085 }
1086
1087 011111,00,3.SHIFT3,5.RT,5.RD,00000,010011:SPECIAL3:32::SHLL.QB
1088 "shll.qb r<RD>, r<RT>, <SHIFT3>"
1089 *dsp:
1090 {
1091   do_qb_shift (SD_, RD, RT, SHIFT3, 0);
1092 }
1093
1094 011111,5.RS,5.RT,5.RD,00010,010011:SPECIAL3:32::SHLLV.QB
1095 "shllv.qb r<RD>, r<RT>, r<RS>"
1096 *dsp:
1097 {
1098   do_qb_shl (SD_, RD, RT, RS, 0);
1099 }
1100
1101 011111,0,4.SHIFT4,5.RT,5.RD,01000,010011:SPECIAL3:32::SHLL.PH
1102 "shll.ph r<RD>, r<RT>, <SHIFT4>"
1103 *dsp:
1104 {
1105   do_ph_shift (SD_, RD, RT, SHIFT4, 0, 0);
1106 }
1107
1108 011111,5.RS,5.RT,5.RD,01010,010011:SPECIAL3:32::SHLLV.PH
1109 "shllv.ph r<RD>, r<RT>, r<RS>"
1110 *dsp:
1111 {
1112   do_ph_shl (SD_, RD, RT, RS, 0, 0);
1113 }
1114
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>"
1117 *dsp:
1118 {
1119   do_ph_shift (SD_, RD, RT, SHIFT4, 0, 1);
1120 }
1121
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>"
1124 *dsp:
1125 {
1126   do_ph_shl (SD_, RD, RT, RS, 0, 1);
1127 }
1128
1129 011111,5.SHIFT5,5.RT,5.RD,10100,010011:SPECIAL3:32::SHLL_S.W
1130 "shll_s.w r<RD>, r<RT>, <SHIFT5>"
1131 *dsp:
1132 {
1133   do_w_shll (SD_, RD, RT, SHIFT5);
1134 }
1135
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>"
1138 *dsp:
1139 {
1140   do_w_s_shllv (SD_, RD, RT, RS);
1141 }
1142
1143 011111,00,3.SHIFT3,5.RT,5.RD,00001,010011:SPECIAL3:32::SHRL.QB
1144 "shrl.qb r<RD>, r<RT>, <SHIFT3>"
1145 *dsp:
1146 {
1147   do_qb_shift (SD_, RD, RT, SHIFT3, 1);
1148 }
1149
1150 011111,5.RS,5.RT,5.RD,00011,010011:SPECIAL3:32::SHRLV.QB
1151 "shrlv.qb r<RD>, r<RT>, r<RS>"
1152 *dsp:
1153 {
1154   do_qb_shl (SD_, RD, RT, RS, 1);
1155 }
1156
1157 011111,0,4.SHIFT4,5.RT,5.RD,01001,010011:SPECIAL3:32::SHRA.PH
1158 "shra.ph r<RD>, r<RT>, <SHIFT4>"
1159 *dsp:
1160 {
1161   do_ph_shift (SD_, RD, RT, SHIFT4, 1, 0);
1162 }
1163
1164 011111,5.RS,5.RT,5.RD,01011,010011:SPECIAL3:32::SHRAV.PH
1165 "shrav.ph r<RD>, r<RT>, r<RS>"
1166 *dsp:
1167 {
1168   do_ph_shl (SD_, RD, RT, RS, 1, 0);
1169 }
1170
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>"
1173 *dsp:
1174 {
1175   do_ph_shift (SD_, RD, RT, SHIFT4, 1, 1);
1176 }
1177
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>"
1180 *dsp:
1181 {
1182   do_ph_shl (SD_, RD, RT, RS, 1, 1);
1183 }
1184
1185 011111,5.SHIFT5,5.RT,5.RD,10101,010011:SPECIAL3:32::SHRA_R.W
1186 "shra_r.w r<RD>, r<RT>, <SHIFT5>"
1187 *dsp:
1188 {
1189   do_w_shra (SD_, RD, RT, SHIFT5);
1190 }
1191
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>"
1194 *dsp:
1195 {
1196   do_w_r_shrav (SD_, RD, RT, RS);
1197 }
1198
1199 // loc: 0 = qhl, 1 = qhr
1200 :function:::void:do_qb_muleu:int rd, int rs, int rt, int loc
1201 {
1202   int i;
1203   unsigned32 result = 0;
1204   unsigned32 v1 = GPR[rs];
1205   unsigned32 v2 = GPR[rt];
1206   unsigned16 h1, h2;
1207   unsigned32 prod;
1208   if (loc == 0)
1209     v1 >>= 16;
1210   for (i = 0; i < 32; i += 16, v1 >>= 8, v2 >>= 16)
1211     {
1212       h1 = (unsigned16)(v1 & 0xff);
1213       h2 = (unsigned16)(v2 & 0xffff);
1214       prod = (unsigned32)h1 * (unsigned32)h2;
1215       if (prod > 0xffff)
1216         {
1217           DSPCR |= DSPCR_OUFLAG5;
1218           prod = 0xffff;
1219         }
1220       result |= ((unsigned32)prod << i);
1221     }
1222   GPR[rd] = EXTEND32 (result);
1223 }
1224
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>"
1227 *dsp:
1228 {
1229   do_qb_muleu (SD_, RD, RS, RT, 0);
1230 }
1231
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>"
1234 *dsp:
1235 {
1236   do_qb_muleu (SD_, RD, RS, RT, 1);
1237 }
1238
1239 // round: 0 = no rounding, 1 = rounding
1240 :function:::void:do_ph_mulq:int rd, int rs, int rt, int round
1241 {
1242   int i;
1243   unsigned32 result = 0;
1244   unsigned32 v1 = GPR[rs];
1245   unsigned32 v2 = GPR[rt];
1246   signed16 h1, h2;
1247   signed32 prod;
1248   for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
1249     {
1250       h1 = (signed16)(v1 & 0xffff);
1251       h2 = (signed16)(v2 & 0xffff);
1252       if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
1253         {
1254           DSPCR |= DSPCR_OUFLAG5;
1255           prod = 0x7fffffff;
1256         }
1257       else
1258         {
1259           prod = ((signed32)h1 * (signed32)h2) << 1;
1260           if (round == 1)
1261             prod += (signed32)0x8000;
1262         }
1263       result |= (((unsigned32)prod >> 16) << i);
1264     }
1265   GPR[rd] = EXTEND32 (result);
1266 }
1267
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>"
1270 *dsp:
1271 {
1272   do_ph_mulq (SD_, RD, RS, RT, 1);
1273 }
1274
1275 // loc: 0 = phl, 1 = phr
1276 :function:::void:do_ph_muleq:int rd, int rs, int rt, int loc
1277 {
1278   unsigned32 v1 = GPR[rs];
1279   unsigned32 v2 = GPR[rt];
1280   signed16 h1, h2;
1281   signed32 prod;
1282   if (loc == 0)
1283     {
1284       h1 = (signed16)(v1 >> 16);
1285       h2 = (signed16)(v2 >> 16);
1286     }
1287   else
1288     {
1289       h1 = (signed16)(v1 & 0xffff);
1290       h2 = (signed16)(v2 & 0xffff);
1291     }
1292   if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
1293     {
1294       DSPCR |= DSPCR_OUFLAG5;
1295       prod = 0x7fffffff;
1296     }
1297   else
1298     prod = ((signed32)h1 * (signed32)h2) << 1;
1299   GPR[rd] = EXTEND32 (prod);
1300 }
1301
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>"
1304 *dsp:
1305 {
1306   do_ph_muleq (SD_, RD, RS, RT, 0);
1307 }
1308
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>"
1311 *dsp:
1312 {
1313   do_ph_muleq (SD_, RD, RS, RT, 1);
1314 }
1315
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
1319 {
1320   int i;
1321   unsigned32 v1 = GPR[rs];
1322   unsigned32 v2 = GPR[rt];
1323   unsigned8 h1, h2;
1324   unsigned32 lo = DSPLO(ac);
1325   unsigned32 hi = DSPHI(ac);
1326   unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1327   if (loc == 0)
1328     {
1329       v1 >>= 16;
1330       v2 >>= 16;
1331     }
1332   for (i = 0; i < 16; i += 8, v1 >>= 8, v2 >>= 8)
1333     {
1334       h1 = (unsigned8)(v1 & 0xff);
1335       h2 = (unsigned8)(v2 & 0xff);
1336       if (op == 0) // DPAU
1337         prod += (unsigned64)h1 * (unsigned64)h2;
1338       else // DPSU
1339         prod -= (unsigned64)h1 * (unsigned64)h2;
1340     }
1341   DSPLO(ac) = EXTEND32 (prod);
1342   DSPHI(ac) = EXTEND32 (prod >> 32);
1343 }
1344
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>"
1347 *dsp:
1348 {
1349   do_qb_dot_product (SD_, AC, RS, RT, 0, 0);
1350 }
1351
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>"
1354 *dsp:
1355 {
1356   do_qb_dot_product (SD_, AC, RS, RT, 0, 1);
1357 }
1358
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>"
1361 *dsp:
1362 {
1363   do_qb_dot_product (SD_, AC, RS, RT, 1, 0);
1364 }
1365
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>"
1368 *dsp:
1369 {
1370   do_qb_dot_product (SD_, AC, RS, RT, 1, 1);
1371 }
1372
1373 // op: 0 = DPAQ 1 = DPSQ
1374 :function:::void:do_ph_dot_product:int ac, int rs, int rt, int op
1375 {
1376   int i;
1377   unsigned32 v1 = GPR[rs];
1378   unsigned32 v2 = GPR[rt];
1379   signed16 h1, h2;
1380   signed32 result;
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)
1385     {
1386       h1 = (signed16)(v1 & 0xffff);
1387       h2 = (signed16)(v2 & 0xffff);
1388       if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
1389         {
1390           DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1391           result = (signed32)0x7fffffff;
1392         }
1393       else
1394         result = ((signed32)h1 * (signed32)h2) << 1;
1395
1396       if (op == 0) // DPAQ
1397         prod += (signed64)result;
1398       else // DPSQ
1399         prod -= (signed64)result;
1400     }
1401   DSPLO(ac) = EXTEND32 (prod);
1402   DSPHI(ac) = EXTEND32 (prod >> 32);
1403 }
1404
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>"
1407 *dsp:
1408 {
1409   do_ph_dot_product (SD_, AC, RS, RT, 0);
1410 }
1411
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>"
1414 *dsp:
1415 {
1416   do_ph_dot_product (SD_, AC, RS, RT, 1);
1417 }
1418
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>"
1421 *dsp:
1422 {
1423   do_mulsaq_s_w_ph (SD_, AC, RS, RT);
1424 }
1425
1426 // op: 0 = DPAQ 1 = DPSQ
1427 :function:::void:do_w_dot_product:int ac, int rs, int rt, int op
1428 {
1429   unsigned32 v1 = GPR[rs];
1430   unsigned32 v2 = GPR[rt];
1431   signed32 h1, h2;
1432   signed64 result;
1433   unsigned32 lo = DSPLO(ac);
1434   unsigned32 hi = DSPHI(ac);
1435   unsigned32 resultlo;
1436   unsigned32 resulthi;
1437   unsigned32 carry;
1438   unsigned64 temp1;
1439   signed64 temp2;
1440   h1 = (signed32) v1;
1441   h2 = (signed32) v2;
1442   if (h1 == 0x80000000 && h2 == 0x80000000)
1443     {
1444       DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1445       result = (signed64) 0x7fffffffffffffffLL;
1446     }
1447   else
1448     result = ((signed64)h1 * (signed64)h2) << 1;
1449   resultlo = (unsigned32)(result);
1450   resulthi = (unsigned32)(result >> 32);
1451   if (op ==0) // DPAQ
1452     {
1453       temp1 = (unsigned64)lo + (unsigned64)resultlo;
1454       carry = (unsigned32)((temp1 >> 32) & 1);
1455       temp2 = (signed64)((signed32)hi) + (signed64)((signed32)resulthi) +
1456               (signed64)((signed32)carry);
1457     }
1458   else // DPSQ
1459     {
1460       temp1 = (unsigned64)lo - (unsigned64)resultlo;
1461       carry = (unsigned32)((temp1 >> 32) & 1);
1462       temp2 = (signed64)((signed32)hi) - (signed64)((signed32)resulthi) -
1463               (signed64)((signed32)carry);
1464     }
1465   if (((temp2 & 0x100000000LL) >> 1) != (temp2 & 0x80000000LL))
1466     {
1467       DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1468       if (temp2 & 0x100000000LL)
1469         {
1470           DSPLO(ac) = EXTEND32 (0x00000000);
1471           DSPHI(ac) = EXTEND32 (0x80000000);
1472         }
1473       else
1474         {
1475           DSPLO(ac) = EXTEND32 (0xffffffff);
1476           DSPHI(ac) = EXTEND32 (0x7fffffff);
1477         }
1478     }
1479   else
1480     {
1481       DSPLO(ac) = EXTEND32 (temp1);
1482       DSPHI(ac) = EXTEND32 (temp2);
1483     }
1484 }
1485
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>"
1488 *dsp:
1489 {
1490   do_w_dot_product (SD_, AC, RS, RT, 0);
1491 }
1492
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>"
1495 *dsp:
1496 {
1497   do_w_dot_product (SD_, AC, RS, RT, 1);
1498 }
1499
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
1503 {
1504   int i;
1505   unsigned32 v1 = GPR[rs];
1506   unsigned32 v2 = GPR[rt];
1507   signed16 h1, h2;
1508   signed32 result;
1509   unsigned32 lo = DSPLO(ac);
1510   unsigned32 hi = DSPHI(ac);
1511   signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo);
1512   if (loc == 0)
1513     {
1514       h1 = (signed16)(v1 >> 16);
1515       h2 = (signed16)(v2 >> 16);
1516     }
1517   else
1518     {
1519       h1 = (signed16)(v1 & 0xffff);
1520       h2 = (signed16)(v2 & 0xffff);
1521     }
1522   if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
1523     {
1524       DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1525       result = (signed32)0x7fffffff;
1526     }
1527   else
1528     result = ((signed32)h1 * (signed32)h2) << 1;
1529   prod += (signed64)result;
1530   if (op == 1) // MAQ_SA
1531     {
1532       if (prod & 0x8000000000000000LL)
1533         {
1534           for (i = 62; i >= 31; i--)
1535             {
1536               if (!(prod & ((signed64)1 << i)))
1537                 {
1538                   DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1539                   prod = 0xffffffff80000000LL;
1540                   break;
1541                 }
1542             }
1543         }
1544       else
1545         {
1546           for (i = 62; i >= 31; i--)
1547             {
1548               if (prod & ((signed64)1 << i))
1549                 {
1550                   DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1551                   prod = 0x7fffffff;
1552                   break;
1553                 }
1554             }
1555         }
1556     }
1557   DSPLO(ac) = EXTEND32 (prod);
1558   DSPHI(ac) = EXTEND32 (prod >> 32);
1559 }
1560
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>"
1563 *dsp:
1564 {
1565   do_ph_maq (SD_, AC, RS, RT, 0, 0);
1566 }
1567
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>"
1570 *dsp:
1571 {
1572   do_ph_maq (SD_, AC, RS, RT, 0, 1);
1573 }
1574
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>"
1577 *dsp:
1578 {
1579   do_ph_maq (SD_, AC, RS, RT, 1, 0);
1580 }
1581
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>"
1584 *dsp:
1585 {
1586   do_ph_maq (SD_, AC, RS, RT, 1, 1);
1587 }
1588
1589 011111,00000,5.RT,5.RD,11011,010010:SPECIAL3:32::BITREV
1590 "bitrev r<RD>, r<RT>"
1591 *dsp:
1592 {
1593   do_bitrev (SD_, RD, RT);
1594 }
1595
1596 011111,5.RS,5.RT,00000,00000,001100:SPECIAL3:32::INSV
1597 "insv r<RT>, r<RS>"
1598 *dsp:
1599 {
1600   do_insv (SD_, RT, RS);
1601 }
1602
1603 011111,00,8.IMM8,5.RD,00010,010010:SPECIAL3:32::REPL.QB
1604 "repl.qb r<RD>, <IMM8>"
1605 *dsp:
1606 {
1607   do_repl (SD_, RD, IMM8, 0);
1608 }
1609
1610 011111,00000,5.RT,5.RD,00011,010010:SPECIAL3:32::REPLV.QB
1611 "replv.qb r<RD>, r<RT>"
1612 *dsp:
1613 {
1614   do_repl (SD_, RD, RT, 1);
1615 }
1616
1617 011111,10.IMM10,5.RD,01010,010010:SPECIAL3:32::REPL.PH
1618 "repl.ph r<RD>, <IMM10>"
1619 *dsp:
1620 {
1621   do_repl (SD_, RD, IMM10, 2);
1622 }
1623
1624 011111,00000,5.RT,5.RD,01011,010010:SPECIAL3:32::REPLV.PH
1625 "replv.ph r<RD>, r<RT>"
1626 *dsp:
1627 {
1628   do_repl (SD_, RD, RT, 3);
1629 }
1630
1631 // op: 0 = EQ, 1 = LT, 2 = LE
1632 :function:::void:do_qb_cmpu:int rs, int rt, int op
1633 {
1634   int i, j;
1635   unsigned32 v1 = GPR[rs];
1636   unsigned32 v2 = GPR[rt];
1637   unsigned8 h1, h2;
1638   unsigned32 mask;
1639   for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1640     {
1641       h1 = (unsigned8)(v1 & 0xff);
1642       h2 = (unsigned8)(v2 & 0xff);
1643       mask = ~(1 << (DSPCR_CCOND_SHIFT + j));
1644       DSPCR &= mask;
1645       if (op == 0) // EQ
1646         DSPCR |= ((h1 == h2) << (DSPCR_CCOND_SHIFT + j));
1647       else if (op == 1) // LT
1648         DSPCR |= ((h1 < h2) << (DSPCR_CCOND_SHIFT + j));
1649       else // LE
1650         DSPCR |= ((h1 <= h2) << (DSPCR_CCOND_SHIFT + j));
1651     }
1652 }
1653
1654 011111,5.RS,5.RT,00000,00000,010001:SPECIAL3:32::CMPU.EQ.QB
1655 "cmpu.eq.qb r<RS>, r<RT>"
1656 *dsp:
1657 {
1658   do_qb_cmpu (SD_, RS, RT, 0);
1659 }
1660
1661 011111,5.RS,5.RT,00000,00001,010001:SPECIAL3:32::CMPU.LT.QB
1662 "cmpu.lt.qb r<RS>, r<RT>"
1663 *dsp:
1664 {
1665   do_qb_cmpu (SD_, RS, RT, 1);
1666 }
1667
1668 011111,5.RS,5.RT,00000,00010,010001:SPECIAL3:32::CMPU.LE.QB
1669 "cmpu.le.qb r<RS>, r<RT>"
1670 *dsp:
1671 {
1672   do_qb_cmpu (SD_, RS, RT, 2);
1673 }
1674
1675 // op: 0 = EQ, 1 = LT, 2 = LE
1676 :function:::void:do_qb_cmpgu:int rd, int rs, int rt, int op
1677 {
1678   int i, j;
1679   unsigned32 v1 = GPR[rs];
1680   unsigned32 v2 = GPR[rt];
1681   unsigned8 h1, h2;
1682   unsigned32 result = 0;
1683   for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1684     {
1685       h1 = (unsigned8)(v1 & 0xff);
1686       h2 = (unsigned8)(v2 & 0xff);
1687       if (op == 0) // EQ
1688         result |= ((h1 == h2) << j);
1689       else if (op == 1) // LT
1690         result |= ((h1 < h2) << j);
1691       else // LE
1692         result |= ((h1 <= h2) << j);
1693     }
1694   GPR[rd] = EXTEND32 (result);
1695 }
1696
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>"
1699 *dsp:
1700 {
1701   do_qb_cmpgu (SD_, RD, RS, RT, 0);
1702 }
1703
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>"
1706 *dsp:
1707 {
1708   do_qb_cmpgu (SD_, RD, RS, RT, 1);
1709 }
1710
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>"
1713 *dsp:
1714 {
1715   do_qb_cmpgu (SD_, RD, RS, RT, 2);
1716 }
1717
1718 // op: 0 = EQ, 1 = LT, 2 = LE
1719 :function:::void:do_ph_cmpu:int rs, int rt, int op
1720 {
1721   int i, j;
1722   unsigned32 v1 = GPR[rs];
1723   unsigned32 v2 = GPR[rt];
1724   signed16 h1, h2;
1725   unsigned32 mask;
1726   for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16)
1727     {
1728       h1 = (signed16)(v1 & 0xffff);
1729       h2 = (signed16)(v2 & 0xffff);
1730       mask = ~(1 << (DSPCR_CCOND_SHIFT + j));
1731       DSPCR &= mask;
1732       if (op == 0) // EQ
1733         DSPCR |= ((h1 == h2) << (DSPCR_CCOND_SHIFT + j));
1734       else if (op == 1) // LT
1735         DSPCR |= ((h1 < h2) << (DSPCR_CCOND_SHIFT + j));
1736       else // LE
1737         DSPCR |= ((h1 <= h2) << (DSPCR_CCOND_SHIFT + j));
1738     }
1739 }
1740
1741 011111,5.RS,5.RT,00000,01000,010001:SPECIAL3:32::CMP.EQ.PH
1742 "cmp.eq.ph r<RS>, r<RT>"
1743 *dsp:
1744 {
1745   do_ph_cmpu (SD_, RS, RT, 0);
1746 }
1747
1748 011111,5.RS,5.RT,00000,01001,010001:SPECIAL3:32::CMP.LT.PH
1749 "cmp.lt.ph r<RS>, r<RT>"
1750 *dsp:
1751 {
1752   do_ph_cmpu (SD_, RS, RT, 1);
1753 }
1754
1755 011111,5.RS,5.RT,00000,01010,010001:SPECIAL3:32::CMP.LE.PH
1756 "cmp.le.ph r<RS>, r<RT>"
1757 *dsp:
1758 {
1759   do_ph_cmpu (SD_, RS, RT, 2);
1760 }
1761
1762 011111,5.RS,5.RT,5.RD,00011,010001:SPECIAL3:32::PICK.QB
1763 "pick.qb r<RD>, r<RS>, r<RT>"
1764 *dsp:
1765 {
1766   do_qb_pick (SD_, RD, RS, RT);
1767 }
1768
1769 011111,5.RS,5.RT,5.RD,01011,010001:SPECIAL3:32::PICK.PH
1770 "pick.ph r<RD>, r<RS>, r<RT>"
1771 *dsp:
1772 {
1773   do_ph_pick (SD_, RD, RS, RT);
1774 }
1775
1776 011111,5.RS,5.RT,5.RD,01110,010001:SPECIAL3:32::PACKRL.PH
1777 "packrl.ph r<RD>, r<RS>, r<RT>"
1778 *dsp:
1779 {
1780   do_ph_packrl (SD_, RD, RS, RT);
1781 }
1782
1783 // op: 0 = EXTR, 1 = EXTR_R, 2 = EXTR_RS
1784 :function:::void:do_w_extr:int rt, int ac, int shift, int op
1785 {
1786   int i;
1787   unsigned32 lo = DSPLO(ac);
1788   unsigned32 hi = DSPHI(ac);
1789   unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1790   signed64 result = (signed64)prod;
1791   int setcond = 0;
1792   if (!(prod & 0x8000000000000000LL))
1793     {
1794       for (i = 62; i >= (shift + 31); i--)
1795         {
1796           if (prod & ((unsigned64)1 << i))
1797             {
1798               DSPCR |= DSPCR_OUFLAG7;
1799               setcond = 1;
1800               break;
1801             }
1802         }
1803       if (((prod >> (shift - 1)) & 0xffffffffLL) == 0xffffffffLL)
1804         {
1805           DSPCR |= DSPCR_OUFLAG7;
1806           setcond = 1;
1807         }
1808     }
1809   else
1810     {
1811       for (i = 62; i >= (shift + 31); i--)
1812         {
1813           if (!(prod & ((unsigned64)1 << i)))
1814             {
1815               DSPCR |= DSPCR_OUFLAG7;
1816               setcond = 2;
1817               break;
1818             }
1819         }
1820     }
1821   if (op == 0) // EXTR
1822     result = result >> shift;
1823   else if (op == 1) // EXTR_R
1824     {
1825       if (shift != 0)
1826         result = ((result >> (shift - 1)) + 1) >> 1;
1827       else
1828         result = result >> shift;
1829     }
1830   else // EXTR_RS
1831     {
1832       if (setcond == 1)
1833         result = 0x7fffffff;
1834       else if (setcond == 2)
1835         result = 0x80000000;
1836       else 
1837         {
1838           if (shift != 0)
1839             result = ((result >> (shift - 1)) + 1) >> 1;
1840           else
1841             result = result >> shift;
1842         }
1843     }
1844   GPR[rt] = EXTEND32 (result);
1845 }
1846
1847 011111,5.SHIFT,5.RT,000,2.AC,00000,111000:SPECIAL3:32::EXTR.W
1848 "extr.w r<RT>, ac<AC>, <SHIFT>"
1849 *dsp:
1850 {
1851   do_w_extr (SD_, RT, AC, SHIFT, 0);
1852 }
1853
1854 011111,5.RS,5.RT,000,2.AC,00001,111000:SPECIAL3:32::EXTRV.W
1855 "extrv.w r<RT>, ac<AC>, r<RS>"
1856 *dsp:
1857 {
1858   do_extrv (SD_, RT, AC, RS, 0);
1859 }
1860
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>"
1863 *dsp:
1864 {
1865   do_w_extr (SD_, RT, AC, SHIFT, 1);
1866 }
1867
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>"
1870 *dsp:
1871 {
1872   do_extrv (SD_, RT, AC, RS, 1);
1873 }
1874
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>"
1877 *dsp:
1878 {
1879   do_w_extr (SD_, RT, AC, SHIFT, 2);
1880 }
1881
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>"
1884 *dsp:
1885 {
1886   do_extrv (SD_, RT, AC, RS, 2);
1887 }
1888
1889 :function:::void:do_h_extr:int rt, int ac, int shift
1890 {
1891   int i;
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;
1897   result >>= shift;
1898   if (result > 0x7fff)
1899     {
1900       result = 0x7fff;
1901       DSPCR |= DSPCR_OUFLAG7;
1902     }
1903   else if (result < value)
1904     {
1905       result = value;
1906       DSPCR |= DSPCR_OUFLAG7;
1907     }
1908   GPR[rt] = EXTEND32 (result);
1909 }
1910
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>"
1913 *dsp:
1914 {
1915   do_h_extr (SD_, RT, AC, SHIFT);
1916 }
1917
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>"
1920 *dsp:
1921 {
1922   do_extrv_s_h (SD_, RT, AC, RS);
1923 }
1924
1925 // op: 0 = EXTP, 1 = EXTPDP
1926 :function:::void:do_extp:int rt, int ac, int size, int op
1927 {
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)
1934     {
1935       prod >>= (pos - size);
1936       result = prod & (((unsigned64)1 << (size + 1)) - 1);
1937       DSPCR &= (~DSPCR_EFI_SMASK);
1938       if (op == 1) // EXTPDP
1939         {
1940           if (pos - (size + 1) >= 0)
1941             {
1942               DSPCR &= (~DSPCR_POS_SMASK);
1943               DSPCR |= ((pos - (size + 1)) & DSPCR_POS_MASK) << DSPCR_POS_SHIFT;
1944             }
1945           else if (pos - (size + 1) == -1)
1946             {
1947               DSPCR |= DSPCR_POS_SMASK;
1948             }
1949         }
1950     }
1951   else
1952     {
1953       DSPCR |= DSPCR_EFI;
1954       Unpredictable ();
1955     }
1956   GPR[rt] = EXTEND32 (result);
1957 }
1958
1959 011111,5.SIZE,5.RT,000,2.AC,00010,111000:SPECIAL3:32::EXTP
1960 "extp r<RT>, ac<AC>, <SIZE>"
1961 *dsp:
1962 {
1963   do_extp (SD_, RT, AC, SIZE, 0);
1964 }
1965
1966 011111,5.RS,5.RT,000,2.AC,00011,111000:SPECIAL3:32::EXTPV
1967 "extpv r<RT>, ac<AC>, r<RS>"
1968 *dsp:
1969 {
1970   do_extpv (SD_, RT, AC, RS, 0);
1971 }
1972
1973 011111,5.SIZE,5.RT,000,2.AC,01010,111000:SPECIAL3:32::EXTPDP
1974 "extpdp r<RT>, ac<AC>, <SIZE>"
1975 *dsp:
1976 {
1977   do_extp (SD_, RT, AC, SIZE, 1);
1978 }
1979
1980 011111,5.RS,5.RT,000,2.AC,01011,111000:SPECIAL3:32::EXTPDPV
1981 "extpdpv r<RT>, ac<AC>, r<RS>"
1982 *dsp:
1983 {
1984   do_extpv (SD_, RT, AC, RS, 1);
1985 }
1986
1987 :function:::void:do_shilo:int ac, int shift
1988 {
1989   unsigned32 lo = DSPLO(ac);
1990   unsigned32 hi = DSPHI(ac);
1991   unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1992   if (shift > 31)
1993     shift = shift - 64;
1994   if (shift >= 0)
1995     prod >>= shift;
1996   else
1997     prod <<= (-shift);
1998   DSPLO(ac) = EXTEND32 (prod);
1999   DSPHI(ac) = EXTEND32 (prod >> 32);
2000 }
2001
2002 011111,6.SHIFT6,0000,000,2.AC,11010,111000:SPECIAL3:32::SHILO
2003 "shilo ac<AC>, <SHIFT6>"
2004 *dsp:
2005 {
2006   do_shilo (SD_, AC, SHIFT6);
2007 }
2008
2009 011111,5.RS,00000,000,2.AC,11011,111000:SPECIAL3:32::SHILOV
2010 "shilov ac<AC>, r<RS>"
2011 *dsp:
2012 {
2013   do_shilov (SD_, AC, RS);
2014 }
2015
2016 011111,5.RS,00000,000,2.AC,11111,111000:SPECIAL3:32::MTHLIP
2017 "mthlip r<RS>, ac<AC>"
2018 *dsp:
2019 {
2020   do_mthlip (SD_, RS, AC);
2021 }
2022
2023 011111,5.RS,10.MASK10,10011,111000:SPECIAL3:32::WRDSP
2024 "wrdsp r<RS>":MASK10 == 1111111111
2025 "wrdsp r<RS>, <MASK10>"
2026 *dsp:
2027 {
2028   do_wrdsp (SD_, RS, MASK10);
2029 }
2030
2031 011111,10.MASK10,5.RD,10010,111000:SPECIAL3:32::RDDSP
2032 "rddsp r<RD>":MASK10 == 1111111111
2033 "rddsp r<RD>, <MASK10>"
2034 *dsp:
2035 {
2036   do_rddsp (SD_, RD, MASK10);
2037 }
2038
2039 011111,5.BASE,5.INDEX,5.RD,00110,001010:SPECIAL3:32::LBUX
2040 "lbux r<RD>, r<INDEX>(r<BASE>)"
2041 *dsp:
2042 {
2043   do_lxx (SD_, RD, BASE, INDEX, 0);
2044 }
2045
2046 011111,5.BASE,5.INDEX,5.RD,00100,001010:SPECIAL3:32::LHX
2047 "lhx r<RD>, r<INDEX>(r<BASE>)"
2048 *dsp:
2049 {
2050   do_lxx (SD_, RD, BASE, INDEX, 1);
2051 }
2052
2053 011111,5.BASE,5.INDEX,5.RD,00000,001010:SPECIAL3:32::LWX
2054 "lwx r<RD>, r<INDEX>(r<BASE>)"
2055 *dsp:
2056 {
2057   do_lxx (SD_, RD, BASE, INDEX, 2);
2058 }
2059
2060 000001,00000,11100,16.OFFSET:REGIMM:32::BPOSGE32
2061 "bposge32 <OFFSET>"
2062 *dsp:
2063 {
2064   unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
2065   address_word offset = EXTEND16 (OFFSET) << 2;
2066   if (pos >= 32)
2067     {
2068       DELAY_SLOT (NIA + offset);
2069     }
2070 }