1// -*- C -*-
2
3// Simulator definition for the MIPS DSP ASE.
4// Copyright (C) 2005-2023 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  int32_t h0 = 0;
29  int16_t h1, h2;
30  uint32_t v1 = GPR[rs];
31  uint32_t v2 = GPR[rt];
32  uint32_t result = 0;
33  for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
34    {
35      h1 = (int16_t)(v1 & 0xffff);
36      h2 = (int16_t)(v2 & 0xffff);
37      if (op == 0) // ADD
38	h0 = (int32_t)h1 + (int32_t)h2;
39      else if (op == 1) // SUB
40        h0 = (int32_t)h1 - (int32_t)h2;
41      else // MUL
42        h0 = (int32_t)h1 * (int32_t)h2;
43      if (h0 > (int32_t)0x7fff || h0 < (int32_t)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 > (int32_t)0x7fff)
52		h0 = 0x7fff;
53	      else
54		h0 = 0x8000;
55	    }
56	}
57      result |= ((uint32_t)((uint16_t)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  int64_t h0;
66  int32_t h1, h2;
67  uint32_t v1 = GPR[rs];
68  uint32_t v2 = GPR[rt];
69  uint32_t result = 0;
70  h1 = (int32_t)v1;
71  h2 = (int32_t)v2;
72  if (op == 0) // ADD
73    h0 = (int64_t)h1 + (int64_t)h2;
74  else // SUB
75    h0 = (int64_t)h1 - (int64_t)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  uint32_t h0;
93  uint8_t h1, h2;
94  uint32_t v1 = GPR[rs];
95  uint32_t v2 = GPR[rt];
96  uint32_t result = 0;
97  for (i = 0; i < 32; i += 8, v1 >>= 8, v2 >>= 8)
98    {
99      h1 = (uint8_t)(v1 & 0xff);
100      h2 = (uint8_t)(v2 & 0xff);
101      if (op == 0) // ADD
102	h0 = (uint32_t)h1 + (uint32_t)h2;
103      else // SUB
104	h0 = (uint32_t)h1 - (uint32_t)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 |= ((uint32_t)((uint8_t)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  uint8_t h0;
126  uint32_t v1 = GPR[rt];
127  uint32_t result = 0;
128  for (i = 0; i < 32; i += 8, v1 >>= 8)
129    {
130      h0 = (uint8_t)(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 |= ((uint32_t)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  int16_t h0;
156  uint32_t v1 = GPR[rt];
157  uint32_t result = 0;
158  int setcond;
159  for (i = 0; i < 32; i += 16, v1 >>= 16)
160    {
161      h0 = (int16_t)(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 |= ((uint32_t)((uint16_t)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  uint32_t v1 = GPR[rt];
215  uint32_t 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  int16_t h0;
254  uint32_t v1 = GPR[rt];
255  uint32_t result = 0;
256  for (i = 0; i < 32; i += 16, v1 >>= 16)
257    {
258      h0 = (int16_t)(v1 & 0xffff);
259      if (h0 == (int16_t)0x8000)
260	{
261	  DSPCR |= DSPCR_OUFLAG4;
262	  h0 = 0x7fff;
263	}
264      else if (h0 & 0x8000)
265	h0 = -h0;
266      result |= ((uint32_t)((uint16_t)h0) << i);
267    }
268  GPR[rd] = EXTEND32 (result);
269}
270
271:function:::void:do_w_s_absq:int rd, int rt
272{
273  uint32_t v1 = GPR[rt];
274  int32_t h0 = (int32_t)v1;
275  if (h0 == (int32_t)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  int8_t q0;
289  uint32_t v1 = GPR[rt];
290  uint32_t result = 0;
291  for (i = 0; i < 32; i += 8, v1 >>= 8)
292    {
293      q0 = (int8_t)(v1 & 0xff);
294      if (q0 == (int8_t)0x80)
295	{
296	  DSPCR |= DSPCR_OUFLAG4;
297	  q0 = 0x7f;
298	}
299      else if (q0 & 0x80)
300	q0 = -q0;
301      result |= ((uint32_t)((uint8_t)q0) << i);
302    }
303  GPR[rd] = EXTEND32 (result);
304}
305
306:function:::void:do_addsc:int rd, int rs, int rt
307{
308  uint32_t v1 = GPR[rs];
309  uint32_t v2 = GPR[rt];
310  uint64_t h0;
311  h0 = (uint64_t)v1 + (uint64_t)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  uint32_t v1 = GPR[rs];
320  uint32_t v2 = GPR[rt];
321  uint64_t h0;
322  int32_t h1 = (int32_t) v1;
323  int32_t h2 = (int32_t) v2;
324  h0 = (int64_t)h1 + (int64_t)h2
325    + (int64_t)((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  uint32_t v1 = GPR[rt];
335  uint32_t 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  uint32_t 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  uint32_t 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  uint32_t 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  uint32_t v1 = GPR[rs];
367  uint32_t v2 = GPR[rt];
368  uint32_t pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
369  uint32_t size = (DSPCR >> DSPCR_SCOUNT_SHIFT) & DSPCR_SCOUNT_MASK;
370  uint32_t 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  uint32_t result = 0;
398  uint32_t v1 = GPR[rs];
399  uint32_t v2 = GPR[rt];
400  uint32_t decr = v2 & 0xff;
401  uint32_t 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  uint32_t 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  uint32_t v1 = GPR[rs];
426  uint32_t v2 = GPR[rt];
427  int16_t h1, h2;
428  int32_t result;
429  uint32_t lo = DSPLO(ac);
430  uint32_t hi = DSPHI(ac);
431  int64_t prod = (int64_t)((((uint64_t)hi) << 32) + (uint64_t)lo);
432  for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
433    {
434      h1 = (int16_t)(v1 & 0xffff);
435      h2 = (int16_t)(v2 & 0xffff);
436      if (h1 == (int16_t)0x8000 && h2 == (int16_t)0x8000)
437	{
438	  DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
439	  result = (int32_t) 0x7fffffff;
440	}
441      else
442	result = ((int32_t)h1 * (int32_t)h2) << 1;
443
444      if (i == 0)
445	prod -= (int64_t) result;
446      else
447	prod += (int64_t) 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  uint32_t v1 = GPR[rs];
457  uint32_t 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  uint32_t v1 = GPR[rs];
465  uint32_t v2 = GPR[rt];
466  uint8_t h1, h2;
467  uint32_t result = 0;
468  for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
469    {
470      h1 = (uint8_t)(v1 & 0xff);
471      h2 = (uint8_t)(v2 & 0xff);
472      if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j)))
473	result |= (uint32_t)(h1 << i);
474      else
475	result |= (uint32_t)(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  uint32_t v1 = GPR[rs];
484  uint32_t v2 = GPR[rt];
485  uint16_t h1, h2;
486  uint32_t result = 0;
487  for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16)
488    {
489      h1 = (uint16_t)(v1 & 0xffff);
490      h2 = (uint16_t)(v2 & 0xffff);
491      if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j)))
492	result |= (uint32_t)(h1 << i);
493      else
494	result |= (uint32_t)(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  uint32_t 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  uint32_t 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  uint32_t 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  uint32_t v1 = GPR[rs];
540  uint32_t v2 = GPR[rt];
541  uint32_t tempu = (v1 & 0xffff0000) >> 16;
542  uint32_t 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  uint32_t v1 = GPR[rs];
550  uint32_t v2 = GPR[rt];
551  uint32_t 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) > (uint32_t)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) > (uint32_t)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) > (uint32_t)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) > (uint32_t)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  uint32_t v1 = GPR[rs];
616  uint32_t v2 = GPR[rt];
617  int32_t h1 = (int32_t)v1;
618  int32_t h2 = (int32_t)v2;
619  int64_t temp1 = (int64_t)h1 + (int64_t)0x8000;
620  int32_t temp2;
621  int64_t temp3 = (int64_t)h2 + (int64_t)0x8000;
622  int32_t temp4;
623  if (((temp1 & 0x100000000LL) >> 1) != (temp1 & 0x80000000))
624    {
625      DSPCR |= DSPCR_OUFLAG6;
626      temp2 = 0x7fff;
627    }
628  else
629    temp2 = (int32_t)((temp1 & 0xffff0000) >> 16);
630  if (((temp3 & 0x100000000LL) >> 1) != (temp3 & 0x80000000))
631    {
632      DSPCR |= DSPCR_OUFLAG6;
633      temp4 = 0x7fff;
634    }
635  else
636    temp4 = (int32_t)((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  uint8_t h0;
644  uint32_t v1 = GPR[rs];
645  uint32_t result = 0;
646  for (i = 0; i < 32; i += 8, v1 >>= 8)
647    {
648      h0 = (uint8_t)(v1 & 0xff);
649      result += (uint32_t)h0;
650    }
651  GPR[rd] = EXTEND32 (result);
652}
653
654:function:::void:do_rddsp:int rd, int mask
655{
656  uint32_t 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      uint32_t v1 = GPR[p2] & 0xff;
698      GPR[rd] = EXTEND32 ((v1 << 24) | (v1 << 16) | (v1 << 8) | v1);
699    }
700  else if (op == 2)
701    {
702      int32_t 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      uint32_t 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  int32_t 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  uint32_t 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  uint32_t 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  uint32_t 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  uint32_t 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  uint32_t 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  uint32_t 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  uint32_t 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  uint32_t v0 = GPR[rs];
799  uint32_t v1 = GPR[rt];
800  uint32_t result;
801  uint32_t 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  uint32_t v0 = GPR[rs];
809  uint32_t v1 = GPR[rt];
810  uint32_t 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  uint32_t v1 = GPR[rs];
822  uint32_t v2 = GPR[rt];
823  int16_t h1, h2;
824  int32_t result;
825  uint32_t lo = DSPLO(ac);
826  uint32_t hi = DSPHI(ac);
827  int64_t prod = (int64_t)((((uint64_t)hi) << 32) + (uint64_t)lo);
828  for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
829    {
830      h1 = (int16_t)(v1 & 0xffff);
831      h2 = (int16_t)(v2 & 0xffff);
832      result = (int32_t)h1 * (int32_t)h2;
833
834      if (i == 0)
835	prod -= (int64_t) result;
836      else
837	prod += (int64_t) 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  uint32_t v1 = GPR[rs];
846  uint32_t v2 = GPR[rt];
847  uint32_t tempu = (v1 & 0xff0000) >> 16;
848  uint32_t tempv = (v1 & 0xff);
849  uint32_t tempw = (v2 & 0xff0000) >> 16;
850  uint32_t 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  uint32_t v0 = GPR[rs];
857  uint32_t v1 = GPR[rt];
858  uint32_t 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  uint32_t result = GPR[rt];
869  int32_t h0 = (int32_t)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
877011111,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
884011111,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
891011111,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
898011111,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
905011111,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
912011111,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
919011111,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
926011111,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
933011111,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
940011111,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
947011111,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
954011111,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
961011111,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
968011111,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
975011111,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
982011111,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
989011111,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
996011111,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
1003011111,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
1010011111,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
1017011111,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
1024011111,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
1031011111,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
1038011111,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
1045011111,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
1052011111,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
1059011111,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
1066011111,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
1073011111,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
1080011111,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
1087011111,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
1094011111,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
1101011111,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
1108011111,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
1115011111,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
1122011111,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
1129011111,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
1136011111,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
1143011111,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
1150011111,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
1157011111,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
1164011111,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
1171011111,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
1178011111,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
1185011111,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
1192011111,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  uint32_t result = 0;
1204  uint32_t v1 = GPR[rs];
1205  uint32_t v2 = GPR[rt];
1206  uint16_t h1, h2;
1207  uint32_t prod;
1208  if (loc == 0)
1209    v1 >>= 16;
1210  for (i = 0; i < 32; i += 16, v1 >>= 8, v2 >>= 16)
1211    {
1212      h1 = (uint16_t)(v1 & 0xff);
1213      h2 = (uint16_t)(v2 & 0xffff);
1214      prod = (uint32_t)h1 * (uint32_t)h2;
1215      if (prod > 0xffff)
1216	{
1217	  DSPCR |= DSPCR_OUFLAG5;
1218	  prod = 0xffff;
1219	}
1220      result |= ((uint32_t)prod << i);
1221    }
1222  GPR[rd] = EXTEND32 (result);
1223}
1224
1225011111,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
1232011111,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  uint32_t result = 0;
1244  uint32_t v1 = GPR[rs];
1245  uint32_t v2 = GPR[rt];
1246  int16_t h1, h2;
1247  int32_t prod;
1248  for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
1249    {
1250      h1 = (int16_t)(v1 & 0xffff);
1251      h2 = (int16_t)(v2 & 0xffff);
1252      if (h1 == (int16_t)0x8000 && h2 == (int16_t)0x8000)
1253	{
1254	  DSPCR |= DSPCR_OUFLAG5;
1255	  prod = 0x7fffffff;
1256	}
1257      else
1258	{
1259	  prod = ((int32_t)h1 * (int32_t)h2) << 1;
1260	  if (round == 1)
1261	    prod += (int32_t)0x8000;
1262	}
1263      result |= (((uint32_t)prod >> 16) << i);
1264    }
1265  GPR[rd] = EXTEND32 (result);
1266}
1267
1268011111,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  uint32_t v1 = GPR[rs];
1279  uint32_t v2 = GPR[rt];
1280  int16_t h1, h2;
1281  int32_t prod;
1282  if (loc == 0)
1283    {
1284      h1 = (int16_t)(v1 >> 16);
1285      h2 = (int16_t)(v2 >> 16);
1286    }
1287  else
1288    {
1289      h1 = (int16_t)(v1 & 0xffff);
1290      h2 = (int16_t)(v2 & 0xffff);
1291    }
1292  if (h1 == (int16_t)0x8000 && h2 == (int16_t)0x8000)
1293    {
1294      DSPCR |= DSPCR_OUFLAG5;
1295      prod = 0x7fffffff;
1296    }
1297  else
1298    prod = ((int32_t)h1 * (int32_t)h2) << 1;
1299  GPR[rd] = EXTEND32 (prod);
1300}
1301
1302011111,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
1309011111,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  uint32_t v1 = GPR[rs];
1322  uint32_t v2 = GPR[rt];
1323  uint8_t h1, h2;
1324  uint32_t lo = DSPLO(ac);
1325  uint32_t hi = DSPHI(ac);
1326  uint64_t prod = (((uint64_t)hi) << 32) + (uint64_t)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 = (uint8_t)(v1 & 0xff);
1335      h2 = (uint8_t)(v2 & 0xff);
1336      if (op == 0) // DPAU
1337	prod += (uint64_t)h1 * (uint64_t)h2;
1338      else // DPSU
1339	prod -= (uint64_t)h1 * (uint64_t)h2;
1340    }
1341  DSPLO(ac) = EXTEND32 (prod);
1342  DSPHI(ac) = EXTEND32 (prod >> 32);
1343}
1344
1345011111,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
1352011111,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
1359011111,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
1366011111,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  uint32_t v1 = GPR[rs];
1378  uint32_t v2 = GPR[rt];
1379  int16_t h1, h2;
1380  int32_t result;
1381  uint32_t lo = DSPLO(ac);
1382  uint32_t hi = DSPHI(ac);
1383  int64_t prod = (int64_t)((((uint64_t)hi) << 32) + (uint64_t)lo);
1384  for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
1385    {
1386      h1 = (int16_t)(v1 & 0xffff);
1387      h2 = (int16_t)(v2 & 0xffff);
1388      if (h1 == (int16_t)0x8000 && h2 == (int16_t)0x8000)
1389	{
1390	  DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1391	  result = (int32_t)0x7fffffff;
1392	}
1393      else
1394	result = ((int32_t)h1 * (int32_t)h2) << 1;
1395
1396      if (op == 0) // DPAQ
1397	prod += (int64_t)result;
1398      else // DPSQ
1399	prod -= (int64_t)result;
1400    }
1401  DSPLO(ac) = EXTEND32 (prod);
1402  DSPHI(ac) = EXTEND32 (prod >> 32);
1403}
1404
1405011111,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
1412011111,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
1419011111,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  uint32_t v1 = GPR[rs];
1430  uint32_t v2 = GPR[rt];
1431  int32_t h1, h2;
1432  int64_t result;
1433  uint32_t lo = DSPLO(ac);
1434  uint32_t hi = DSPHI(ac);
1435  uint32_t resultlo;
1436  uint32_t resulthi;
1437  uint32_t carry;
1438  uint64_t temp1;
1439  int64_t temp2;
1440  h1 = (int32_t) v1;
1441  h2 = (int32_t) v2;
1442  if (h1 == 0x80000000 && h2 == 0x80000000)
1443    {
1444      DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1445      result = (int64_t) 0x7fffffffffffffffLL;
1446    }
1447  else
1448    result = ((int64_t)h1 * (int64_t)h2) << 1;
1449  resultlo = (uint32_t)(result);
1450  resulthi = (uint32_t)(result >> 32);
1451  if (op ==0) // DPAQ
1452    {
1453      temp1 = (uint64_t)lo + (uint64_t)resultlo;
1454      carry = (uint32_t)((temp1 >> 32) & 1);
1455      temp2 = (int64_t)((int32_t)hi) + (int64_t)((int32_t)resulthi) +
1456	      (int64_t)((int32_t)carry);
1457    }
1458  else // DPSQ
1459    {
1460      temp1 = (uint64_t)lo - (uint64_t)resultlo;
1461      carry = (uint32_t)((temp1 >> 32) & 1);
1462      temp2 = (int64_t)((int32_t)hi) - (int64_t)((int32_t)resulthi) -
1463	      (int64_t)((int32_t)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
1486011111,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
1493011111,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  uint32_t v1 = GPR[rs];
1506  uint32_t v2 = GPR[rt];
1507  int16_t h1, h2;
1508  int32_t result;
1509  uint32_t lo = DSPLO(ac);
1510  uint32_t hi = DSPHI(ac);
1511  int64_t prod = (int64_t)((((uint64_t)hi) << 32) + (uint64_t)lo);
1512  if (loc == 0)
1513    {
1514      h1 = (int16_t)(v1 >> 16);
1515      h2 = (int16_t)(v2 >> 16);
1516    }
1517  else
1518    {
1519      h1 = (int16_t)(v1 & 0xffff);
1520      h2 = (int16_t)(v2 & 0xffff);
1521    }
1522  if (h1 == (int16_t)0x8000 && h2 == (int16_t)0x8000)
1523    {
1524      DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1525      result = (int32_t)0x7fffffff;
1526    }
1527  else
1528    result = ((int32_t)h1 * (int32_t)h2) << 1;
1529  prod += (int64_t)result;
1530  if (op == 1) // MAQ_SA
1531    {
1532      if (prod & 0x8000000000000000LL)
1533	{
1534	  for (i = 62; i >= 31; i--)
1535	    {
1536	      if (!(prod & ((int64_t)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 & ((int64_t)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
1561011111,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
1568011111,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
1575011111,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
1582011111,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
1589011111,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
1596011111,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
1603011111,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
1610011111,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
1617011111,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
1624011111,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  uint32_t v1 = GPR[rs];
1636  uint32_t v2 = GPR[rt];
1637  uint8_t h1, h2;
1638  uint32_t mask;
1639  for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1640    {
1641      h1 = (uint8_t)(v1 & 0xff);
1642      h2 = (uint8_t)(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
1654011111,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
1661011111,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
1668011111,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  uint32_t v1 = GPR[rs];
1680  uint32_t v2 = GPR[rt];
1681  uint8_t h1, h2;
1682  uint32_t result = 0;
1683  for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1684    {
1685      h1 = (uint8_t)(v1 & 0xff);
1686      h2 = (uint8_t)(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
1697011111,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
1704011111,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
1711011111,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  uint32_t v1 = GPR[rs];
1723  uint32_t v2 = GPR[rt];
1724  int16_t h1, h2;
1725  uint32_t mask;
1726  for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16)
1727    {
1728      h1 = (int16_t)(v1 & 0xffff);
1729      h2 = (int16_t)(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
1741011111,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
1748011111,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
1755011111,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
1762011111,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
1769011111,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
1776011111,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  uint32_t lo = DSPLO(ac);
1788  uint32_t hi = DSPHI(ac);
1789  uint64_t prod = (((uint64_t)hi) << 32) + (uint64_t)lo;
1790  int64_t result = (int64_t)prod;
1791  int setcond = 0;
1792  if (!(prod & 0x8000000000000000LL))
1793    {
1794      for (i = 62; i >= (shift + 31); i--)
1795	{
1796	  if (prod & ((uint64_t)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 & ((uint64_t)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
1847011111,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
1854011111,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
1861011111,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
1868011111,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
1875011111,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
1882011111,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  uint32_t lo = DSPLO(ac);
1893  uint32_t hi = DSPHI(ac);
1894  uint64_t prod = (((uint64_t)hi) << 32) + (uint64_t)lo;
1895  int64_t result = (int64_t)prod;
1896  int64_t 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
1911011111,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
1918011111,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  int32_t pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
1929  uint32_t lo = DSPLO(ac);
1930  uint32_t hi = DSPHI(ac);
1931  uint64_t prod = (((uint64_t)hi) << 32) + (uint64_t)lo;
1932  uint64_t result = 0;
1933  if (pos - (size + 1) >= -1)
1934    {
1935      prod >>= (pos - size);
1936      result = prod & (((uint64_t)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
1959011111,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
1966011111,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
1973011111,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
1980011111,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  uint32_t lo = DSPLO(ac);
1990  uint32_t hi = DSPHI(ac);
1991  uint64_t prod = (((uint64_t)hi) << 32) + (uint64_t)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
2002011111,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
2009011111,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
2016011111,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
2023011111,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
2031011111,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
2039011111,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
2046011111,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
2053011111,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
2060000001,00000,11100,16.OFFSET:REGIMM:32::BPOSGE32
2061"bposge32 <OFFSET>"
2062*dsp:
2063{
2064  uint32_t 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}
2071