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