1// -*- C -*-
2
3// Simulator definition for the MIPS DSP ASE.
4// Copyright (C) 2005, 2007 Free Software Foundation, Inc.
5// Contributed by MIPS Technologies, Inc.  Written by Chao-ying Fu.
6//
7// This file is part of GDB, the GNU debugger.
8//
9// This program is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; either version 3 of the License, or
12// (at your option) any later version.
13//
14// This program is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License
20// along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22
23// op: 0 = ADD, 1 = SUB, 2 = MUL
24// sat: 0 = no saturation, 1 = saturation
25:function:::void:do_ph_op:int rd, int rs, int rt, int op, int sat
26{
27  int i;
28  signed32 h0 = 0;
29  signed16 h1, h2;
30  unsigned32 v1 = GPR[rs];
31  unsigned32 v2 = GPR[rt];
32  unsigned32 result = 0;
33  for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
34    {
35      h1 = (signed16)(v1 & 0xffff);
36      h2 = (signed16)(v2 & 0xffff);
37      if (op == 0) // ADD
38	h0 = (signed32)h1 + (signed32)h2;
39      else if (op == 1) // SUB
40        h0 = (signed32)h1 - (signed32)h2;
41      else // MUL
42        h0 = (signed32)h1 * (signed32)h2;
43      if (h0 > (signed32)0x7fff || h0 < (signed32)0xffff8000)
44	{
45	  if (op == 0 || op == 1) // ADD, SUB
46	    DSPCR |= DSPCR_OUFLAG4;
47	  else if (op == 2) // MUL
48	    DSPCR |= DSPCR_OUFLAG5;
49	  if (sat == 1)
50	    {
51	      if (h0 > (signed32)0x7fff)
52		h0 = 0x7fff;
53	      else
54		h0 = 0x8000;
55	    }
56	}
57      result |= ((unsigned32)((unsigned16)h0) << i);
58    }
59  GPR[rd] = EXTEND32 (result);
60}
61
62// op: 0 = ADD, 1 = SUB
63:function:::void:do_w_op:int rd, int rs, int rt, int op
64{
65  signed64 h0;
66  signed32 h1, h2;
67  unsigned32 v1 = GPR[rs];
68  unsigned32 v2 = GPR[rt];
69  unsigned32 result = 0;
70  h1 = (signed32)v1;
71  h2 = (signed32)v2;
72  if (op == 0) // ADD
73    h0 = (signed64)h1 + (signed64)h2;
74  else // SUB
75    h0 = (signed64)h1 - (signed64)h2;
76  if (((h0 & 0x100000000LL) >> 1) != (h0 & 0x80000000))
77    {
78      DSPCR |= DSPCR_OUFLAG4;
79      if (h0 & 0x100000000LL)
80	h0 = 0x80000000;
81      else
82	h0 = 0x7fffffff;
83    }
84  GPR[rd] = EXTEND32 (h0);
85}
86
87// op: 0 = ADD, 1 = SUB
88// sat: 0 = no saturation, 1 = saturation
89:function:::void:do_qb_op:int rd, int rs, int rt, int op, int sat
90{
91  int i;
92  unsigned32 h0;
93  unsigned8 h1, h2;
94  unsigned32 v1 = GPR[rs];
95  unsigned32 v2 = GPR[rt];
96  unsigned32 result = 0;
97  for (i = 0; i < 32; i += 8, v1 >>= 8, v2 >>= 8)
98    {
99      h1 = (unsigned8)(v1 & 0xff);
100      h2 = (unsigned8)(v2 & 0xff);
101      if (op == 0) // ADD
102	h0 = (unsigned32)h1 + (unsigned32)h2;
103      else // SUB
104	h0 = (unsigned32)h1 - (unsigned32)h2;
105      if (h0 & 0x100)
106	{
107	  DSPCR |= DSPCR_OUFLAG4;
108	  if (sat == 1)
109	    {
110	      if (op == 0) // ADD
111		h0 = 0xff;
112	      else // SUB
113		h0 = 0;
114	    }
115	}
116      result |= ((unsigned32)((unsigned8)h0) << i);
117    }
118  GPR[rd] = EXTEND32 (result);
119}
120
121// op: 0 = left, 1 = right
122:function:::void:do_qb_shift:int rd, int rt, int shift, int op
123{
124  int i, j;
125  unsigned8 h0;
126  unsigned32 v1 = GPR[rt];
127  unsigned32 result = 0;
128  for (i = 0; i < 32; i += 8, v1 >>= 8)
129    {
130      h0 = (unsigned8)(v1 & 0xff);
131      if (op == 0) // left
132	{
133	  for (j = 7; j >= 8 - shift; j--)
134	    {
135	      if (h0 & (1<<j))
136		{
137		  DSPCR |= DSPCR_OUFLAG6;
138		  break;
139		}
140	    }
141          h0 = h0 << shift;
142	}
143      else // right
144        h0 = h0 >> shift;
145      result |= ((unsigned32)h0 << i);
146    }
147  GPR[rd] = EXTEND32 (result);
148}
149
150// op: 0 = left, 1 = right
151// sat: 0 = no saturation/rounding, 1 = saturation/rounding
152:function:::void:do_ph_shift:int rd, int rt, int shift, int op, int sat
153{
154  int i, j;
155  signed16 h0;
156  unsigned32 v1 = GPR[rt];
157  unsigned32 result = 0;
158  int setcond;
159  for (i = 0; i < 32; i += 16, v1 >>= 16)
160    {
161      h0 = (signed16)(v1 & 0xffff);
162      if (op == 0) // left
163	{
164	  setcond = 0;
165	  if (h0 & (1<<15))
166	    {
167	      for (j = 14; j >= 15 - shift; j--)
168		{
169		  if (!(h0 & (1 << j)))
170		    {
171		      DSPCR |= DSPCR_OUFLAG6;
172		      setcond = 1;
173		      break;
174		    }
175		}
176	    }
177	  else
178	    {
179	      for (j = 14; j >= 15 - shift; j--)
180		{
181		  if (h0 & (1 << j))
182		    {
183		      DSPCR |= DSPCR_OUFLAG6;
184		      setcond = 2;
185		      break;
186		    }
187		}
188	    }
189	  h0 = h0 << shift;
190	  if (sat == 1)
191	    {
192	      if (setcond == 2)
193		h0 = 0x7fff; 
194	      else if (setcond == 1)
195		h0 = 0x8000;
196	    }
197	}
198      else // right
199	{
200	  if (sat == 1 && shift != 0 && (h0 & (1 << (shift-1))))
201	    h0 = (h0 >> shift) + 1;
202	  else
203	    h0 = h0 >> shift;
204	}
205
206      result |= ((unsigned32)((unsigned16)h0) << i);
207    }
208  GPR[rd] = EXTEND32 (result);
209}
210
211:function:::void:do_w_shll:int rd, int rt, int shift
212{
213  int i;
214  unsigned32 v1 = GPR[rt];
215  unsigned32 result = 0;
216  int setcond = 0;
217  if (v1 & (1 << 31))
218    {
219      for (i = 30; i >= 31 - shift; i--)
220	{
221	  if (!(v1 & (1 << i)))
222	    {
223	      DSPCR |= DSPCR_OUFLAG6;
224	      setcond = 1;
225	      break;
226	    }
227	}
228    }
229  else
230    {
231      for (i = 30; i >= 31 - shift; i--)
232	{
233	  if (v1 & (1 << i))
234	    {
235	      DSPCR |= DSPCR_OUFLAG6;
236	      setcond = 2;
237	      break;
238	    }
239	}
240    }
241  if (setcond == 2)
242    result = 0x7fffffff; 
243  else if (setcond == 1)
244    result = 0x80000000;
245  else
246    result = v1 << shift; 
247  GPR[rd] = EXTEND32 (result);
248}
249
250:function:::void:do_w_shra:int rd, int rt, int shift
251{
252  unsigned32 result = GPR[rt];
253  signed32 h0 = (signed32)result;
254  if (shift != 0 && (h0 & (1 << (shift-1))))
255    h0 = (h0 >> shift) + 1;
256  else
257    h0 = h0 >> shift;
258  GPR[rd] = EXTEND32 (h0);
259}
260
261011111,5.RS,5.RT,5.RD,01010,010000:SPECIAL3:32::ADDQ.PH
262"addq.ph r<RD>, r<RS>, r<RT>"
263*dsp:
264{
265  do_ph_op (SD_, RD, RS, RT, 0, 0);
266}
267
268011111,5.RS,5.RT,5.RD,01110,010000:SPECIAL3:32::ADDQ_S.PH
269"addq_s.ph r<RD>, r<RS>, r<RT>"
270*dsp:
271{
272  do_ph_op (SD_, RD, RS, RT, 0, 1);
273}
274
275011111,5.RS,5.RT,5.RD,10110,010000:SPECIAL3:32::ADDQ_S.W
276"addq_s.w r<RD>, r<RS>, r<RT>"
277*dsp:
278{
279  do_w_op (SD_, RD, RS, RT, 0);
280}
281
282011111,5.RS,5.RT,5.RD,00000,010000:SPECIAL3:32::ADDU.QB
283"addu.qb r<RD>, r<RS>, r<RT>"
284*dsp:
285{
286  do_qb_op (SD_, RD, RS, RT, 0, 0);
287}
288
289011111,5.RS,5.RT,5.RD,00100,010000:SPECIAL3:32::ADDU_S.QB
290"addu_s.qb r<RD>, r<RS>, r<RT>"
291*dsp:
292{
293  do_qb_op (SD_, RD, RS, RT, 0, 1);
294}
295
296011111,5.RS,5.RT,5.RD,01011,010000:SPECIAL3:32::SUBQ.PH
297"subq.ph r<RD>, r<RS>, r<RT>"
298*dsp:
299{
300  do_ph_op (SD_, RD, RS, RT, 1, 0);
301}
302
303011111,5.RS,5.RT,5.RD,01111,010000:SPECIAL3:32::SUBQ_S.PH
304"subq_s.ph r<RD>, r<RS>, r<RT>"
305*dsp:
306{
307  do_ph_op (SD_, RD, RS, RT, 1, 1);
308}
309
310011111,5.RS,5.RT,5.RD,10111,010000:SPECIAL3:32::SUBQ_S.W
311"subq_s.w r<RD>, r<RS>, r<RT>"
312*dsp:
313{
314  do_w_op (SD_, RD, RS, RT, 1);
315}
316
317011111,5.RS,5.RT,5.RD,00001,010000:SPECIAL3:32::SUBU.QB
318"subu.qb r<RD>, r<RS>, r<RT>"
319*dsp:
320{
321  do_qb_op (SD_, RD, RS, RT, 1, 0);
322}
323
324011111,5.RS,5.RT,5.RD,00101,010000:SPECIAL3:32::SUBU_S.QB
325"subu_s.qb r<RD>, r<RS>, r<RT>"
326*dsp:
327{
328  do_qb_op (SD_, RD, RS, RT, 1, 1);
329}
330
331011111,5.RS,5.RT,5.RD,10000,010000:SPECIAL3:32::ADDSC
332"addsc r<RD>, r<RS>, r<RT>"
333*dsp:
334{
335  unsigned32 v1 = GPR[RS];
336  unsigned32 v2 = GPR[RT];
337  unsigned64 h0;
338  h0 = (unsigned64)v1 + (unsigned64)v2;
339  if (h0 & 0x100000000LL)
340    DSPCR |= DSPCR_CARRY;
341  GPR[RD] = EXTEND32 (h0);
342}
343
344011111,5.RS,5.RT,5.RD,10001,010000:SPECIAL3:32::ADDWC
345"addwc r<RD>, r<RS>, r<RT>"
346*dsp:
347{
348  unsigned32 v1 = GPR[RS];
349  unsigned32 v2 = GPR[RT];
350  unsigned64 h0;
351  signed32 h1 = (signed32) v1;
352  signed32 h2 = (signed32) v2;
353  h0 = (signed64)h1 + (signed64)h2
354       + (signed64)((DSPCR >> DSPCR_CARRY_SHIFT) & DSPCR_CARRY_MASK);
355  if (((h0 & 0x100000000LL) >> 1) != (h0 & 0x80000000))
356    DSPCR |= DSPCR_OUFLAG4;
357  GPR[RD] = EXTEND32 (h0);
358}
359
360011111,5.RS,5.RT,5.RD,10010,010000:SPECIAL3:32::MODSUB
361"modsub r<RD>, r<RS>, r<RT>"
362*dsp:
363{
364  unsigned32 result = 0;
365  unsigned32 v1 = GPR[RS];
366  unsigned32 v2 = GPR[RT];
367  unsigned32 decr = v2 & 0xff;
368  unsigned32 lastindex = (v2 & 0xffff00) >> 8;
369  if (v1 == 0)
370    result = lastindex;
371  else
372    result =  v1 - decr;
373  GPR[RD] = EXTEND32 (result);
374}
375
376011111,5.RS,00000,5.RD,10100,010000:SPECIAL3:32::RADDU.W.QB
377"raddu.w.qb r<RD>, r<RS>"
378*dsp:
379{
380  int i;
381  unsigned8 h0;
382  unsigned32 v1 = GPR[RS];
383  unsigned32 result = 0;
384  for (i = 0; i < 32; i += 8, v1 >>= 8)
385    {
386      h0 = (unsigned8)(v1 & 0xff);
387      result += (unsigned32)h0;
388    }
389  GPR[RD] = EXTEND32 (result);
390}
391
392011111,00000,5.RT,5.RD,01001,010010:SPECIAL3:32::ABSQ_S.PH
393"absq_s.ph r<RD>, r<RT>"
394*dsp:
395{
396  int i;
397  signed16 h0;
398  unsigned32 v1 = GPR[RT];
399  unsigned32 result = 0;
400  for (i = 0; i < 32; i += 16, v1 >>= 16)
401    {
402      h0 = (signed16)(v1 & 0xffff);
403      if (h0 == (signed16)0x8000)
404	{
405	  DSPCR |= DSPCR_OUFLAG4;
406	  h0 = 0x7fff;
407	}
408      else if (h0 & 0x8000)
409	h0 = -h0; 
410      result |= ((unsigned32)((unsigned16)h0) << i);
411    }
412  GPR[RD] = EXTEND32 (result);
413}
414
415011111,00000,5.RT,5.RD,10001,010010:SPECIAL3:32::ABSQ_S.W
416"absq_s.w r<RD>, r<RT>"
417*dsp:
418{
419  unsigned32 v1 = GPR[RT];
420  signed32 h0 = (signed32)v1;
421  if (h0 == (signed32)0x80000000)
422    {
423      DSPCR |= DSPCR_OUFLAG4;
424      h0 = 0x7fffffff;
425    }
426  else if (h0 & 0x80000000)
427    h0 = -h0; 
428  GPR[RD] = EXTEND32 (h0);
429}
430
431011111,5.RS,5.RT,5.RD,01100,010001:SPECIAL3:32::PRECRQ.QB.PH
432"precrq.qb.ph r<RD>, r<RS>, r<RT>"
433*dsp:
434{
435  unsigned32 v1 = GPR[RS];
436  unsigned32 v2 = GPR[RT];
437  unsigned32 tempu = (v1 & 0xff000000) >> 24;
438  unsigned32 tempv = (v1 & 0xff00) >> 8;
439  unsigned32 tempw = (v2 & 0xff000000) >> 24;
440  unsigned32 tempx = (v2 & 0xff00) >> 8;
441  GPR[RD] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx);
442}
443
444011111,5.RS,5.RT,5.RD,10100,010001:SPECIAL3:32::PRECRQ.PH.W
445"precrq.ph.w r<RD>, r<RS>, r<RT>"
446*dsp:
447{
448  unsigned32 v1 = GPR[RS];
449  unsigned32 v2 = GPR[RT];
450  unsigned32 tempu = (v1 & 0xffff0000) >> 16;
451  unsigned32 tempv = (v2 & 0xffff0000) >> 16;
452  GPR[RD] = EXTEND32 ((tempu << 16) | tempv);
453}
454
455011111,5.RS,5.RT,5.RD,10101,010001:SPECIAL3:32::PRECRQ_RS.PH.W
456"precrq_rs.ph.w r<RD>, r<RS>, r<RT>"
457*dsp:
458{
459  unsigned32 v1 = GPR[RS];
460  unsigned32 v2 = GPR[RT];
461  signed32 h1 = (signed32)v1;
462  signed32 h2 = (signed32)v2;
463  signed64 temp1 = (signed64)h1 + (signed64)0x8000;
464  signed32 temp2;
465  signed64 temp3 = (signed64)h2 + (signed64)0x8000;
466  signed32 temp4;
467  if (((temp1 & 0x100000000LL) >> 1) != (temp1 & 0x80000000))
468    {
469      DSPCR |= DSPCR_OUFLAG6;
470      temp2 = 0x7fff;
471    }
472  else
473    temp2 = (signed32)((temp1 & 0xffff0000) >> 16);
474  if (((temp3 & 0x100000000LL) >> 1) != (temp3 & 0x80000000))
475    {
476      DSPCR |= DSPCR_OUFLAG6;
477      temp4 = 0x7fff;
478    }
479  else
480    temp4 = (signed32)((temp3 & 0xffff0000) >> 16);
481  GPR[RD] = EXTEND32 ((temp2 << 16) | temp4);
482}
483
484011111,5.RS,5.RT,5.RD,01111,010001:SPECIAL3:32::PRECRQU_S.QB.PH
485"precrqu_s.qb.ph r<RD>, r<RS>, r<RT>"
486*dsp:
487{
488  unsigned32 v1 = GPR[RS];
489  unsigned32 v2 = GPR[RT];
490  unsigned32 tempu, tempv, tempw, tempx;
491  if (v1 & 0x80000000)
492    {
493      DSPCR |= DSPCR_OUFLAG6;
494      tempu = 0;
495    }
496  else if (!(v1 & 0x80000000) && ((v1 >> 16) > (unsigned32)0x7f80))
497    {
498      DSPCR |= DSPCR_OUFLAG6;
499      tempu = 0xff;
500    }
501  else
502    tempu = (v1 & 0x7f800000) >> 23;
503  if (v1 & 0x8000)
504    {
505      DSPCR |= DSPCR_OUFLAG6;
506      tempv = 0;
507    }
508  else if (!(v1 & 0x8000) && ((v1 & 0xffff) > (unsigned32)0x7f80))
509    {
510      DSPCR |= DSPCR_OUFLAG6;
511      tempv = 0xff;
512    }
513  else
514    tempv = (v1 & 0x7f80) >> 7;
515  if (v2 & 0x80000000)
516    {
517      DSPCR |= DSPCR_OUFLAG6;
518      tempw = 0;
519    }
520  else if (!(v2 & 0x80000000) && ((v2 >> 16) > (unsigned32)0x7f80))
521    {
522      DSPCR |= DSPCR_OUFLAG6;
523      tempw = 0xff;
524    }
525  else
526    tempw = (v2 & 0x7f800000) >> 23;
527  if (v2 & 0x8000)
528    {
529      DSPCR |= DSPCR_OUFLAG6;
530      tempx = 0;
531    }
532  else if (!(v2 & 0x8000) && ((v2 & 0xffff) > (unsigned32)0x7f80))
533    {
534      DSPCR |= DSPCR_OUFLAG6;
535      tempx = 0xff;
536    }
537  else
538    tempx = (v2 & 0x7f80) >> 7;
539  GPR[RD] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx);
540}
541
542011111,00000,5.RT,5.RD,01100,010010:SPECIAL3:32::PRECEQ.W.PHL
543"preceq.w.phl r<RD>, r<RT>"
544*dsp:
545{
546  unsigned32 v1 = GPR[RT];
547  GPR[RD] = EXTEND32 (v1 & 0xffff0000);
548}
549
550011111,00000,5.RT,5.RD,01101,010010:SPECIAL3:32::PRECEQ.W.PHR
551"preceq.w.phr r<RD>, r<RT>"
552*dsp:
553{
554  unsigned32 v1 = GPR[RT];
555  GPR[RD] = EXTEND32 ((v1 & 0xffff) << 16);
556}
557
558011111,00000,5.RT,5.RD,00100,010010:SPECIAL3:32::PRECEQU.PH.QBL
559"precequ.ph.qbl r<RD>, r<RT>"
560*dsp:
561{
562  unsigned32 v1 = GPR[RT];
563  GPR[RD] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff0000) >> 9);
564}
565
566011111,00000,5.RT,5.RD,00101,010010:SPECIAL3:32::PRECEQU.PH.QBR
567"precequ.ph.qbr r<RD>, r<RT>"
568*dsp:
569{
570  unsigned32 v1 = GPR[RT];
571  GPR[RD] = EXTEND32 ((v1 & 0xff00) << 15) | ((v1 & 0xff) << 7);
572}
573
574011111,00000,5.RT,5.RD,00110,010010:SPECIAL3:32::PRECEQU.PH.QBLA
575"precequ.ph.qbla r<RD>, r<RT>"
576*dsp:
577{
578  unsigned32 v1 = GPR[RT];
579  GPR[RD] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff00) >> 1);
580}
581
582011111,00000,5.RT,5.RD,00111,010010:SPECIAL3:32::PRECEQU.PH.QBRA
583"precequ.ph.qbra r<RD>, r<RT>"
584*dsp:
585{
586  unsigned32 v1 = GPR[RT];
587  GPR[RD] = EXTEND32 ((v1 & 0xff0000) << 7) | ((v1 & 0xff) << 7);
588}
589
590011111,00000,5.RT,5.RD,11100,010010:SPECIAL3:32::PRECEU.PH.QBL
591"preceu.ph.qbl r<RD>, r<RT>"
592*dsp:
593{
594  unsigned32 v1 = GPR[RT];
595  GPR[RD] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff0000) >> 16);
596}
597
598011111,00000,5.RT,5.RD,11101,010010:SPECIAL3:32::PRECEU.PH.QBR
599"preceu.ph.qbr r<RD>, r<RT>"
600*dsp:
601{
602  unsigned32 v1 = GPR[RT];
603  GPR[RD] = EXTEND32 ((v1 & 0xff00) << 8) | (v1 & 0xff);
604}
605
606011111,00000,5.RT,5.RD,11110,010010:SPECIAL3:32::PRECEU.PH.QBLA
607"preceu.ph.qbla r<RD>, r<RT>"
608*dsp:
609{
610  unsigned32 v1 = GPR[RT];
611  GPR[RD] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff00) >> 8);
612}
613
614011111,00000,5.RT,5.RD,11111,010010:SPECIAL3:32::PRECEU.PH.QBRA
615"preceu.ph.qbra r<RD>, r<RT>"
616*dsp:
617{
618  unsigned32 v1 = GPR[RT];
619  GPR[RD] = EXTEND32 ((v1 & 0xff0000) | (v1 & 0xff));
620}
621
622011111,00,3.SHIFT3,5.RT,5.RD,00000,010011:SPECIAL3:32::SHLL.QB
623"shll.qb r<RD>, r<RT>, <SHIFT3>"
624*dsp:
625{
626  do_qb_shift (SD_, RD, RT, SHIFT3, 0);
627}
628
629011111,5.RS,5.RT,5.RD,00010,010011:SPECIAL3:32::SHLLV.QB
630"shllv.qb r<RD>, r<RT>, r<RS>"
631*dsp:
632{
633  unsigned32 shift = GPR[RS] & 0x7;
634  do_qb_shift (SD_, RD, RT, shift, 0);
635}
636
637011111,0,4.SHIFT4,5.RT,5.RD,01000,010011:SPECIAL3:32::SHLL.PH
638"shll.ph r<RD>, r<RT>, <SHIFT4>"
639*dsp:
640{
641  do_ph_shift (SD_, RD, RT, SHIFT4, 0, 0);
642}
643
644011111,5.RS,5.RT,5.RD,01010,010011:SPECIAL3:32::SHLLV.PH
645"shllv.ph r<RD>, r<RT>, r<RS>"
646*dsp:
647{
648  unsigned32 shift = GPR[RS] & 0xf;
649  do_ph_shift (SD_, RD, RT, shift, 0, 0);
650}
651
652011111,0,4.SHIFT4,5.RT,5.RD,01100,010011:SPECIAL3:32::SHLL_S.PH
653"shll_s.ph r<RD>, r<RT>, <SHIFT4>"
654*dsp:
655{
656  do_ph_shift (SD_, RD, RT, SHIFT4, 0, 1);
657}
658
659011111,5.RS,5.RT,5.RD,01110,010011:SPECIAL3:32::SHLLV_S.PH
660"shllv_s.ph r<RD>, r<RT>, r<RS>"
661*dsp:
662{
663  unsigned32 shift = GPR[RS] & 0xf;
664  do_ph_shift (SD_, RD, RT, shift, 0, 1);
665}
666
667011111,5.SHIFT5,5.RT,5.RD,10100,010011:SPECIAL3:32::SHLL_S.W
668"shll_s.w r<RD>, r<RT>, <SHIFT5>"
669*dsp:
670{
671  do_w_shll (SD_, RD, RT, SHIFT5);
672}
673
674011111,5.RS,5.RT,5.RD,10110,010011:SPECIAL3:32::SHLLV_S.W
675"shllv_s.w r<RD>, r<RT>, r<RS>"
676*dsp:
677{
678  unsigned32 shift = GPR[RS] & 0x1f;
679  do_w_shll (SD_, RD, RT, shift);
680}
681
682011111,00,3.SHIFT3,5.RT,5.RD,00001,010011:SPECIAL3:32::SHRL.QB
683"shrl.qb r<RD>, r<RT>, <SHIFT3>"
684*dsp:
685{
686  do_qb_shift (SD_, RD, RT, SHIFT3, 1);
687}
688
689011111,5.RS,5.RT,5.RD,00011,010011:SPECIAL3:32::SHRLV.QB
690"shrlv.qb r<RD>, r<RT>, r<RS>"
691*dsp:
692{
693  unsigned32 shift = GPR[RS] & 0x7;
694  do_qb_shift (SD_, RD, RT, shift, 1);
695}
696
697011111,0,4.SHIFT4,5.RT,5.RD,01001,010011:SPECIAL3:32::SHRA.PH
698"shra.ph r<RD>, r<RT>, <SHIFT4>"
699*dsp:
700{
701  do_ph_shift (SD_, RD, RT, SHIFT4, 1, 0);
702}
703
704011111,5.RS,5.RT,5.RD,01011,010011:SPECIAL3:32::SHRAV.PH
705"shrav.ph r<RD>, r<RT>, r<RS>"
706*dsp:
707{
708  unsigned32 shift = GPR[RS] & 0xf;
709  do_ph_shift (SD_, RD, RT, shift, 1, 0);
710}
711
712011111,0,4.SHIFT4,5.RT,5.RD,01101,010011:SPECIAL3:32::SHRA_R.PH
713"shra_r.ph r<RD>, r<RT>, <SHIFT4>"
714*dsp:
715{
716  do_ph_shift (SD_, RD, RT, SHIFT4, 1, 1);
717}
718
719011111,5.RS,5.RT,5.RD,01111,010011:SPECIAL3:32::SHRAV_R.PH
720"shrav_r.ph r<RD>, r<RT>, r<RS>"
721*dsp:
722{
723  unsigned32 shift = GPR[RS] & 0xf;
724  do_ph_shift (SD_, RD, RT, shift, 1, 1);
725}
726
727011111,5.SHIFT5,5.RT,5.RD,10101,010011:SPECIAL3:32::SHRA_R.W
728"shra_r.w r<RD>, r<RT>, <SHIFT5>"
729*dsp:
730{
731  do_w_shra (SD_, RD, RT, SHIFT5);
732}
733
734011111,5.RS,5.RT,5.RD,10111,010011:SPECIAL3:32::SHRAV_R.W
735"shrav_r.w r<RD>, r<RT>, r<RS>"
736*dsp:
737{
738  unsigned32 shift = GPR[RS] & 0x1f;
739  do_w_shra (SD_, RD, RT, shift);
740}
741
742// loc: 0 = qhl, 1 = qhr
743:function:::void:do_qb_muleu:int rd, int rs, int rt, int loc
744{
745  int i;
746  unsigned32 result = 0;
747  unsigned32 v1 = GPR[rs];
748  unsigned32 v2 = GPR[rt];
749  unsigned16 h1, h2;
750  unsigned32 prod;
751  if (loc == 0)
752    v1 >>= 16;
753  for (i = 0; i < 32; i += 16, v1 >>= 8, v2 >>= 16)
754    {
755      h1 = (unsigned16)(v1 & 0xff);
756      h2 = (unsigned16)(v2 & 0xffff);
757      prod = (unsigned32)h1 * (unsigned32)h2;
758      if (prod > 0xffff)
759	{
760	  DSPCR |= DSPCR_OUFLAG5;
761	  prod = 0xffff;
762	}
763      result |= ((unsigned32)prod << i);
764    }
765  GPR[rd] = EXTEND32 (result);
766}
767
768011111,5.RS,5.RT,5.RD,00110,010000:SPECIAL3:32::MULEU_S.PH.QBL
769"muleu_s.ph.qbl r<RD>, r<RS>, r<RT>"
770*dsp:
771{
772  do_qb_muleu (SD_, RD, RS, RT, 0);
773}
774
775011111,5.RS,5.RT,5.RD,00111,010000:SPECIAL3:32::MULEU_S.PH.QBR
776"muleu_s.ph.qbr r<RD>, r<RS>, r<RT>"
777*dsp:
778{
779  do_qb_muleu (SD_, RD, RS, RT, 1);
780}
781
782// round: 0 = no rounding, 1 = rounding
783:function:::void:do_ph_mulq:int rd, int rs, int rt, int round
784{
785  int i;
786  unsigned32 result = 0;
787  unsigned32 v1 = GPR[rs];
788  unsigned32 v2 = GPR[rt];
789  signed16 h1, h2;
790  signed32 prod;
791  for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
792    {
793      h1 = (signed16)(v1 & 0xffff);
794      h2 = (signed16)(v2 & 0xffff);
795      if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
796	{
797	  DSPCR |= DSPCR_OUFLAG5;
798	  prod = 0x7fffffff;
799	}
800      else
801	{
802	  prod = ((signed32)h1 * (signed32)h2) << 1;
803	  if (round == 1)
804	    prod += (signed32)0x8000;
805	}
806      result |= (((unsigned32)prod >> 16) << i);
807    }
808  GPR[rd] = EXTEND32 (result);
809}
810
811011111,5.RS,5.RT,5.RD,11111,010000:SPECIAL3:32::MULQ_RS.PH
812"mulq_rs.ph r<RD>, r<RS>, r<RT>"
813*dsp:
814{
815  do_ph_mulq (SD_, RD, RS, RT, 1);
816}
817
818// loc: 0 = phl, 1 = phr
819:function:::void:do_ph_muleq:int rd, int rs, int rt, int loc
820{
821  unsigned32 v1 = GPR[rs];
822  unsigned32 v2 = GPR[rt];
823  signed16 h1, h2;
824  signed32 prod;
825  if (loc == 0)
826    {
827      h1 = (signed16)(v1 >> 16);
828      h2 = (signed16)(v2 >> 16);
829    }
830  else
831    {
832      h1 = (signed16)(v1 & 0xffff);
833      h2 = (signed16)(v2 & 0xffff);
834    }
835  if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
836    {
837      DSPCR |= DSPCR_OUFLAG5;
838      prod = 0x7fffffff;
839    }
840  else
841    prod = ((signed32)h1 * (signed32)h2) << 1;
842  GPR[rd] = EXTEND32 (prod);
843}
844
845011111,5.RS,5.RT,5.RD,11100,010000:SPECIAL3:32::MULEQ_S.W.PHL
846"muleq_s.w.phl r<RD>, r<RS>, r<RT>"
847*dsp:
848{
849  do_ph_muleq (SD_, RD, RS, RT, 0);
850}
851
852011111,5.RS,5.RT,5.RD,11101,010000:SPECIAL3:32::MULEQ_S.W.PHR
853"muleq_s.w.phr r<RD>, r<RS>, r<RT>"
854*dsp:
855{
856  do_ph_muleq (SD_, RD, RS, RT, 1);
857}
858
859// op: 0 = DPAU 1 = DPSU
860// loc: 0 = qbl, 1 = qbr
861:function:::void:do_qb_dot_product:int ac, int rs, int rt, int op, int loc
862{
863  int i;
864  unsigned32 v1 = GPR[rs];
865  unsigned32 v2 = GPR[rt];
866  unsigned8 h1, h2;
867  unsigned32 lo = DSPLO(ac);
868  unsigned32 hi = DSPHI(ac);
869  unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
870  if (loc == 0)
871    {
872      v1 >>= 16;
873      v2 >>= 16;
874    }
875  for (i = 0; i < 16; i += 8, v1 >>= 8, v2 >>= 8)
876    {
877      h1 = (unsigned8)(v1 & 0xff);
878      h2 = (unsigned8)(v2 & 0xff);
879      if (op == 0) // DPAU
880	prod += (unsigned64)h1 * (unsigned64)h2;
881      else // DPSU
882	prod -= (unsigned64)h1 * (unsigned64)h2;
883    }
884  DSPLO(ac) = EXTEND32 (prod);
885  DSPHI(ac) = EXTEND32 (prod >> 32);
886}
887
888011111,5.RS,5.RT,000,2.AC,00011,110000:SPECIAL3:32::DPAU.H.QBL
889"dpau.h.qbl ac<AC>, r<RS>, r<RT>"
890*dsp:
891{
892  do_qb_dot_product (SD_, AC, RS, RT, 0, 0);
893}
894
895011111,5.RS,5.RT,000,2.AC,00111,110000:SPECIAL3:32::DPAU.H.QBR
896"dpau.h.qbr ac<AC>, r<RS>, r<RT>"
897*dsp:
898{
899  do_qb_dot_product (SD_, AC, RS, RT, 0, 1);
900}
901
902011111,5.RS,5.RT,000,2.AC,01011,110000:SPECIAL3:32::DPSU.H.QBL
903"dpsu.h.qbl ac<AC>, r<RS>, r<RT>"
904*dsp:
905{
906  do_qb_dot_product (SD_, AC, RS, RT, 1, 0);
907}
908
909011111,5.RS,5.RT,000,2.AC,01111,110000:SPECIAL3:32::DPSU.H.QBR
910"dpsu.h.qbr ac<AC>, r<RS>, r<RT>"
911*dsp:
912{
913  do_qb_dot_product (SD_, AC, RS, RT, 1, 1);
914}
915
916// op: 0 = DPAQ 1 = DPSQ
917:function:::void:do_ph_dot_product:int ac, int rs, int rt, int op
918{
919  int i;
920  unsigned32 v1 = GPR[rs];
921  unsigned32 v2 = GPR[rt];
922  signed16 h1, h2;
923  signed32 result;
924  unsigned32 lo = DSPLO(ac);
925  unsigned32 hi = DSPHI(ac);
926  signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo);
927  for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
928    {
929      h1 = (signed16)(v1 & 0xffff);
930      h2 = (signed16)(v2 & 0xffff);
931      if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
932	{
933	  DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
934	  result = (signed32)0x7fffffff;
935	}
936      else
937	result = ((signed32)h1 * (signed32)h2) << 1;
938
939      if (op == 0) // DPAQ
940	prod += (signed64)result;
941      else // DPSQ
942	prod -= (signed64)result;
943    }
944  DSPLO(ac) = EXTEND32 (prod);
945  DSPHI(ac) = EXTEND32 (prod >> 32);
946}
947
948011111,5.RS,5.RT,000,2.AC,00100,110000:SPECIAL3:32::DPAQ_S.W.PH
949"dpaq_s.w.ph ac<AC>, r<RS>, r<RT>"
950*dsp:
951{
952  do_ph_dot_product (SD_, AC, RS, RT, 0);
953}
954
955011111,5.RS,5.RT,000,2.AC,00101,110000:SPECIAL3:32::DPSQ_S.W.PH
956"dpsq_s.w.ph ac<AC>, r<RS>, r<RT>"
957*dsp:
958{
959  do_ph_dot_product (SD_, AC, RS, RT, 1);
960}
961
962011111,5.RS,5.RT,000,2.AC,00110,110000:SPECIAL3:32::MULSAQ_S.W.PH
963"mulsaq_s.w.ph ac<AC>, r<RS>, r<RT>"
964*dsp:
965{
966  int i;
967  unsigned32 v1 = GPR[RS];
968  unsigned32 v2 = GPR[RT];
969  signed16 h1, h2;
970  signed32 result;
971  unsigned32 lo = DSPLO(AC);
972  unsigned32 hi = DSPHI(AC);
973  signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo);
974  for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16)
975    {
976      h1 = (signed16)(v1 & 0xffff);
977      h2 = (signed16)(v2 & 0xffff);
978      if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
979	{
980	  DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + AC));
981	  result = (signed32) 0x7fffffff;
982	}
983      else
984	result = ((signed32)h1 * (signed32)h2) << 1;
985
986      if (i == 0)
987	prod -= (signed64) result;
988      else
989	prod += (signed64) result;
990    }
991  DSPLO(AC) = EXTEND32 (prod);
992  DSPHI(AC) = EXTEND32 (prod >> 32);
993}
994
995// op: 0 = DPAQ 1 = DPSQ
996:function:::void:do_w_dot_product:int ac, int rs, int rt, int op
997{
998  unsigned32 v1 = GPR[rs];
999  unsigned32 v2 = GPR[rt];
1000  signed32 h1, h2;
1001  signed64 result;
1002  unsigned32 lo = DSPLO(ac);
1003  unsigned32 hi = DSPHI(ac);
1004  unsigned32 resultlo;
1005  unsigned32 resulthi;
1006  unsigned32 carry;
1007  unsigned64 temp1;
1008  signed64 temp2;
1009  h1 = (signed32) v1;
1010  h2 = (signed32) v2;
1011  if (h1 == 0x80000000 && h2 == 0x80000000)
1012    {
1013      DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1014      result = (signed64) 0x7fffffffffffffffLL;
1015    }
1016  else
1017    result = ((signed64)h1 * (signed64)h2) << 1;
1018  resultlo = (unsigned32)(result);
1019  resulthi = (unsigned32)(result >> 32);
1020  if (op ==0) // DPAQ
1021    {
1022      temp1 = (unsigned64)lo + (unsigned64)resultlo;
1023      carry = (unsigned32)((temp1 >> 32) & 1);
1024      temp2 = (signed64)((signed32)hi) + (signed64)((signed32)resulthi) +
1025	      (signed64)((signed32)carry);
1026    }
1027  else // DPSQ
1028    {
1029      temp1 = (unsigned64)lo - (unsigned64)resultlo;
1030      carry = (unsigned32)((temp1 >> 32) & 1);
1031      temp2 = (signed64)((signed32)hi) - (signed64)((signed32)resulthi) -
1032	      (signed64)((signed32)carry);
1033    }
1034  if (((temp2 & 0x100000000LL) >> 1) != (temp2 & 0x80000000LL))
1035    {
1036      DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1037      if (temp2 & 0x100000000LL)
1038	{
1039	  DSPLO(ac) = EXTEND32 (0x00000000);
1040	  DSPHI(ac) = EXTEND32 (0x80000000);
1041	}
1042      else
1043	{
1044	  DSPLO(ac) = EXTEND32 (0xffffffff);
1045	  DSPHI(ac) = EXTEND32 (0x7fffffff);
1046	}
1047    }
1048  else
1049    {
1050      DSPLO(ac) = EXTEND32 (temp1);
1051      DSPHI(ac) = EXTEND32 (temp2);
1052    }
1053}
1054
1055011111,5.RS,5.RT,000,2.AC,01100,110000:SPECIAL3:32::DPAQ_SA.L.W
1056"dpaq_sa.l.w ac<AC>, r<RS>, r<RT>"
1057*dsp:
1058{
1059  do_w_dot_product (SD_, AC, RS, RT, 0);
1060}
1061
1062011111,5.RS,5.RT,000,2.AC,01101,110000:SPECIAL3:32::DPSQ_SA.L.W
1063"dpsq_sa.l.w ac<AC>, r<RS>, r<RT>"
1064*dsp:
1065{
1066  do_w_dot_product (SD_, AC, RS, RT, 1);
1067}
1068
1069// op: 0 = MAQ_S 1 = MAQ_SA
1070// loc: 0 = phl, 1 = phr
1071:function:::void:do_ph_maq:int ac, int rs, int rt, int op, int loc
1072{
1073  int i;
1074  unsigned32 v1 = GPR[rs];
1075  unsigned32 v2 = GPR[rt];
1076  signed16 h1, h2;
1077  signed32 result;
1078  unsigned32 lo = DSPLO(ac);
1079  unsigned32 hi = DSPHI(ac);
1080  signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo);
1081  if (loc == 0)
1082    {
1083      h1 = (signed16)(v1 >> 16);
1084      h2 = (signed16)(v2 >> 16);
1085    }
1086  else
1087    {
1088      h1 = (signed16)(v1 & 0xffff);
1089      h2 = (signed16)(v2 & 0xffff);
1090    }
1091  if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000)
1092    {
1093      DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1094      result = (signed32)0x7fffffff;
1095    }
1096  else
1097    result = ((signed32)h1 * (signed32)h2) << 1;
1098  prod += (signed64)result;
1099  if (op == 1) // MAQ_SA
1100    {
1101      if (prod & 0x8000000000000000LL)
1102	{
1103	  for (i = 62; i >= 31; i--)
1104	    {
1105	      if (!(prod & ((signed64)1 << i)))
1106		{
1107		  DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1108		  prod = 0xffffffff80000000LL;
1109		  break;
1110		}
1111	    }
1112	}
1113      else
1114	{
1115	  for (i = 62; i >= 31; i--)
1116	    {
1117	      if (prod & ((signed64)1 << i))
1118		{
1119		  DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac));
1120		  prod = 0x7fffffff;
1121		  break;
1122		}
1123	    }
1124	}
1125    }
1126  DSPLO(ac) = EXTEND32 (prod);
1127  DSPHI(ac) = EXTEND32 (prod >> 32);
1128}
1129
1130011111,5.RS,5.RT,000,2.AC,10100,110000:SPECIAL3:32::MAQ_S.W.PHL
1131"maq_s.w.phl ac<AC>, r<RS>, r<RT>"
1132*dsp:
1133{
1134  do_ph_maq (SD_, AC, RS, RT, 0, 0);
1135}
1136
1137011111,5.RS,5.RT,000,2.AC,10110,110000:SPECIAL3:32::MAQ_S.W.PHR
1138"maq_s.w.phr ac<AC>, r<RS>, r<RT>"
1139*dsp:
1140{
1141  do_ph_maq (SD_, AC, RS, RT, 0, 1);
1142}
1143
1144011111,5.RS,5.RT,000,2.AC,10000,110000:SPECIAL3:32::MAQ_SA.W.PHL
1145"maq_sa.w.phl ac<AC>, r<RS>, r<RT>"
1146*dsp:
1147{
1148  do_ph_maq (SD_, AC, RS, RT, 1, 0);
1149}
1150
1151011111,5.RS,5.RT,000,2.AC,10010,110000:SPECIAL3:32::MAQ_SA.W.PHR
1152"maq_sa.w.phr ac<AC>, r<RS>, r<RT>"
1153*dsp:
1154{
1155  do_ph_maq (SD_, AC, RS, RT, 1, 1);
1156}
1157
1158011111,00000,5.RT,5.RD,11011,010010:SPECIAL3:32::BITREV
1159"bitrev r<RD>, r<RT>"
1160*dsp:
1161{
1162  int i;
1163  unsigned32 v1 = GPR[RT];
1164  unsigned32 h1 = 0;
1165  for (i = 0; i < 16; i++)
1166    {
1167      if (v1 & (1 << i))
1168	h1 |= (1 << (15 - i));
1169    }
1170  GPR[RD] = EXTEND32 (h1);
1171}
1172
1173011111,5.RS,5.RT,00000,00000,001100:SPECIAL3:32::INSV
1174"insv r<RT>, r<RS>"
1175*dsp:
1176{
1177  unsigned32 v1 = GPR[RS];
1178  unsigned32 v2 = GPR[RT];
1179  unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
1180  unsigned32 size = (DSPCR >> DSPCR_SCOUNT_SHIFT) & DSPCR_SCOUNT_MASK;
1181  unsigned32 mask1, mask2, mask3, result;
1182  if (size < 32)
1183    mask1 = (1 << size) - 1;
1184  else
1185    mask1 = 0xffffffff;
1186  mask2 = (1 << pos) - 1;
1187  if (pos + size < 32)
1188    mask3 = ~((1 << (pos + size)) - 1);
1189  else
1190    mask3 = 0;
1191  result = (v2 & mask3) | ((v1 & mask1) << pos) | (v2 & mask2);
1192  GPR[RT] = EXTEND32 (result);
1193}
1194
1195011111,00,8.IMM8,5.RD,00010,010010:SPECIAL3:32::REPL.QB
1196"repl.qb r<RD>, <IMM8>"
1197*dsp:
1198{
1199  GPR[RD] = EXTEND32 ((IMM8 << 24) | (IMM8 << 16) | (IMM8 << 8) | IMM8);
1200}
1201
1202011111,00000,5.RT,5.RD,00011,010010:SPECIAL3:32::REPLV.QB
1203"replv.qb r<RD>, r<RT>"
1204*dsp:
1205{
1206  unsigned32 v1 = GPR[RT];
1207  v1 = v1 & 0xff;
1208  GPR[RD] = EXTEND32 ((v1 << 24) | (v1 << 16) | (v1 << 8) | v1);
1209}
1210
1211011111,10.IMM10,5.RD,01010,010010:SPECIAL3:32::REPL.PH
1212"repl.ph r<RD>, <IMM10>"
1213*dsp:
1214{
1215  signed32 v1 = IMM10;
1216  if (v1 & 0x200)
1217    v1 |= 0xfffffc00;
1218  GPR[RD] = EXTEND32 ((v1 << 16) | (v1 & 0xffff));
1219}
1220
1221011111,00000,5.RT,5.RD,01011,010010:SPECIAL3:32::REPLV.PH
1222"replv.ph r<RD>, r<RT>"
1223*dsp:
1224{
1225  unsigned32 v1 = GPR[RT];
1226  v1 = v1 & 0xffff;
1227  GPR[RD] = EXTEND32 ((v1 << 16) | v1);
1228}
1229
1230// op: 0 = EQ, 1 = LT, 2 = LE
1231:function:::void:do_qb_cmpu:int rs, int rt, int op
1232{
1233  int i, j;
1234  unsigned32 v1 = GPR[rs];
1235  unsigned32 v2 = GPR[rt];
1236  unsigned8 h1, h2;
1237  unsigned32 mask;
1238  for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1239    {
1240      h1 = (unsigned8)(v1 & 0xff);
1241      h2 = (unsigned8)(v2 & 0xff);
1242      mask = ~(1 << (DSPCR_CCOND_SHIFT + j));
1243      DSPCR &= mask;
1244      if (op == 0) // EQ
1245	DSPCR |= ((h1 == h2) << (DSPCR_CCOND_SHIFT + j));
1246      else if (op == 1) // LT
1247	DSPCR |= ((h1 < h2) << (DSPCR_CCOND_SHIFT + j));
1248      else // LE
1249	DSPCR |= ((h1 <= h2) << (DSPCR_CCOND_SHIFT + j));
1250    }
1251}
1252
1253011111,5.RS,5.RT,00000,00000,010001:SPECIAL3:32::CMPU.EQ.QB
1254"cmpu.eq.qb r<RS>, r<RT>"
1255*dsp:
1256{
1257  do_qb_cmpu (SD_, RS, RT, 0);
1258}
1259
1260011111,5.RS,5.RT,00000,00001,010001:SPECIAL3:32::CMPU.LT.QB
1261"cmpu.lt.qb r<RS>, r<RT>"
1262*dsp:
1263{
1264  do_qb_cmpu (SD_, RS, RT, 1);
1265}
1266
1267011111,5.RS,5.RT,00000,00010,010001:SPECIAL3:32::CMPU.LE.QB
1268"cmpu.le.qb r<RS>, r<RT>"
1269*dsp:
1270{
1271  do_qb_cmpu (SD_, RS, RT, 2);
1272}
1273
1274// op: 0 = EQ, 1 = LT, 2 = LE
1275:function:::void:do_qb_cmpgu:int rd, int rs, int rt, int op
1276{
1277  int i, j;
1278  unsigned32 v1 = GPR[rs];
1279  unsigned32 v2 = GPR[rt];
1280  unsigned8 h1, h2;
1281  unsigned32 result = 0;
1282  for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1283    {
1284      h1 = (unsigned8)(v1 & 0xff);
1285      h2 = (unsigned8)(v2 & 0xff);
1286      if (op == 0) // EQ
1287	result |= ((h1 == h2) << j);
1288      else if (op == 1) // LT
1289	result |= ((h1 < h2) << j);
1290      else // LE
1291	result |= ((h1 <= h2) << j);
1292    }
1293  GPR[rd] = EXTEND32 (result);
1294}
1295
1296011111,5.RS,5.RT,5.RD,00100,010001:SPECIAL3:32::CMPGU.EQ.QB
1297"cmpgu.eq.qb r<RD>, r<RS>, r<RT>"
1298*dsp:
1299{
1300  do_qb_cmpgu (SD_, RD, RS, RT, 0);
1301}
1302
1303011111,5.RS,5.RT,5.RD,00101,010001:SPECIAL3:32::CMPGU.LT.QB
1304"cmpgu.lt.qb r<RD>, r<RS>, r<RT>"
1305*dsp:
1306{
1307  do_qb_cmpgu (SD_, RD, RS, RT, 1);
1308}
1309
1310011111,5.RS,5.RT,5.RD,00110,010001:SPECIAL3:32::CMPGU.LE.QB
1311"cmpgu.le.qb r<RD>, r<RS>, r<RT>"
1312*dsp:
1313{
1314  do_qb_cmpgu (SD_, RD, RS, RT, 2);
1315}
1316
1317// op: 0 = EQ, 1 = LT, 2 = LE
1318:function:::void:do_ph_cmpu:int rs, int rt, int op
1319{
1320  int i, j;
1321  unsigned32 v1 = GPR[rs];
1322  unsigned32 v2 = GPR[rt];
1323  signed16 h1, h2;
1324  unsigned32 mask;
1325  for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16)
1326    {
1327      h1 = (signed16)(v1 & 0xffff);
1328      h2 = (signed16)(v2 & 0xffff);
1329      mask = ~(1 << (DSPCR_CCOND_SHIFT + j));
1330      DSPCR &= mask;
1331      if (op == 0) // EQ
1332	DSPCR |= ((h1 == h2) << (DSPCR_CCOND_SHIFT + j));
1333      else if (op == 1) // LT
1334	DSPCR |= ((h1 < h2) << (DSPCR_CCOND_SHIFT + j));
1335      else // LE
1336	DSPCR |= ((h1 <= h2) << (DSPCR_CCOND_SHIFT + j));
1337    }
1338}
1339
1340011111,5.RS,5.RT,00000,01000,010001:SPECIAL3:32::CMP.EQ.PH
1341"cmp.eq.ph r<RS>, r<RT>"
1342*dsp:
1343{
1344  do_ph_cmpu (SD_, RS, RT, 0);
1345}
1346
1347011111,5.RS,5.RT,00000,01001,010001:SPECIAL3:32::CMP.LT.PH
1348"cmp.lt.ph r<RS>, r<RT>"
1349*dsp:
1350{
1351  do_ph_cmpu (SD_, RS, RT, 1);
1352}
1353
1354011111,5.RS,5.RT,00000,01010,010001:SPECIAL3:32::CMP.LE.PH
1355"cmp.le.ph r<RS>, r<RT>"
1356*dsp:
1357{
1358  do_ph_cmpu (SD_, RS, RT, 2);
1359}
1360
1361011111,5.RS,5.RT,5.RD,00011,010001:SPECIAL3:32::PICK.QB
1362"pick.qb r<RD>, r<RS>, r<RT>"
1363*dsp:
1364{
1365  int i, j;
1366  unsigned32 v1 = GPR[RS];
1367  unsigned32 v2 = GPR[RT];
1368  unsigned8 h1, h2;
1369  unsigned32 result = 0;
1370  for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8)
1371    {
1372      h1 = (unsigned8)(v1 & 0xff);
1373      h2 = (unsigned8)(v2 & 0xff);
1374      if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j)))
1375	result |= (unsigned32)(h1 << i);
1376      else
1377	result |= (unsigned32)(h2 << i);
1378    }
1379  GPR[RD] = EXTEND32 (result);
1380}
1381
1382011111,5.RS,5.RT,5.RD,01011,010001:SPECIAL3:32::PICK.PH
1383"pick.ph r<RD>, r<RS>, r<RT>"
1384*dsp:
1385{
1386  int i, j;
1387  unsigned32 v1 = GPR[RS];
1388  unsigned32 v2 = GPR[RT];
1389  unsigned16 h1, h2;
1390  unsigned32 result = 0;
1391  for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16)
1392    {
1393      h1 = (unsigned16)(v1 & 0xffff);
1394      h2 = (unsigned16)(v2 & 0xffff);
1395      if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j)))
1396	result |= (unsigned32)(h1 << i);
1397      else
1398	result |= (unsigned32)(h2 << i);
1399    }
1400  GPR[RD] = EXTEND32 (result);
1401}
1402
1403011111,5.RS,5.RT,5.RD,01110,010001:SPECIAL3:32::PACKRL.PH
1404"packrl.ph r<RD>, r<RS>, r<RT>"
1405*dsp:
1406{
1407  unsigned32 v1 = GPR[RS];
1408  unsigned32 v2 = GPR[RT];
1409  GPR[RD] = EXTEND32 ((v1 << 16) + (v2 >> 16));
1410}
1411
1412// op: 0 = EXTR, 1 = EXTR_R, 2 = EXTR_RS
1413:function:::void:do_w_extr:int rt, int ac, int shift, int op
1414{
1415  int i;
1416  unsigned32 lo = DSPLO(ac);
1417  unsigned32 hi = DSPHI(ac);
1418  unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1419  signed64 result = (signed64)prod;
1420  int setcond = 0;
1421  if (!(prod & 0x8000000000000000LL))
1422    {
1423      for (i = 62; i >= (shift + 31); i--)
1424	{
1425	  if (prod & ((unsigned64)1 << i))
1426	    {
1427	      DSPCR |= DSPCR_OUFLAG7;
1428	      setcond = 1;
1429	      break;
1430	    }
1431	}
1432      if (((prod >> (shift - 1)) & 0xffffffffLL) == 0xffffffffLL)
1433	{
1434	  DSPCR |= DSPCR_OUFLAG7;
1435	  setcond = 1;
1436	}
1437    }
1438  else
1439    {
1440      for (i = 62; i >= (shift + 31); i--)
1441	{
1442	  if (!(prod & ((unsigned64)1 << i)))
1443	    {
1444	      DSPCR |= DSPCR_OUFLAG7;
1445	      setcond = 2;
1446	      break;
1447	    }
1448	}
1449    }
1450  if (op == 0) // EXTR
1451    result = result >> shift;
1452  else if (op == 1) // EXTR_R
1453    {
1454      if (shift != 0)
1455        result = ((result >> (shift - 1)) + 1) >> 1;
1456      else
1457	result = result >> shift;
1458    }
1459  else // EXTR_RS
1460    {
1461      if (setcond == 1)
1462	result = 0x7fffffff;
1463      else if (setcond == 2)
1464	result = 0x80000000;
1465      else 
1466	{
1467	  if (shift != 0)
1468	    result = ((result >> (shift - 1)) + 1) >> 1;
1469	  else
1470	    result = result >> shift;
1471	}
1472    }
1473  GPR[rt] = EXTEND32 (result);
1474}
1475
1476011111,5.SHIFT,5.RT,000,2.AC,00000,111000:SPECIAL3:32::EXTR.W
1477"extr.w r<RT>, ac<AC>, <SHIFT>"
1478*dsp:
1479{
1480  do_w_extr (SD_, RT, AC, SHIFT, 0);
1481}
1482
1483011111,5.RS,5.RT,000,2.AC,00001,111000:SPECIAL3:32::EXTRV.W
1484"extrv.w r<RT>, ac<AC>, r<RS>"
1485*dsp:
1486{
1487  unsigned32 shift = GPR[RS] & 0x1f;
1488  do_w_extr (SD_, RT, AC, shift, 0);
1489}
1490
1491011111,5.SHIFT,5.RT,000,2.AC,00100,111000:SPECIAL3:32::EXTR_R.W
1492"extr_r.w r<RT>, ac<AC>, <SHIFT>"
1493*dsp:
1494{
1495  do_w_extr (SD_, RT, AC, SHIFT, 1);
1496}
1497
1498011111,5.RS,5.RT,000,2.AC,00101,111000:SPECIAL3:32::EXTRV_R.W
1499"extrv_r.w r<RT>, ac<AC>, r<RS>"
1500*dsp:
1501{
1502  unsigned32 shift = GPR[RS] & 0x1f;
1503  do_w_extr (SD_, RT, AC, shift, 1);
1504}
1505
1506011111,5.SHIFT,5.RT,000,2.AC,00110,111000:SPECIAL3:32::EXTR_RS.W
1507"extr_rs.w r<RT>, ac<AC>, <SHIFT>"
1508*dsp:
1509{
1510  do_w_extr (SD_, RT, AC, SHIFT, 2);
1511}
1512
1513011111,5.RS,5.RT,000,2.AC,00111,111000:SPECIAL3:32::EXTRV_RS.W
1514"extrv_rs.w r<RT>, ac<AC>, r<RS>"
1515*dsp:
1516{
1517  unsigned32 shift = GPR[RS] & 0x1f;
1518  do_w_extr (SD_, RT, AC, shift, 2);
1519}
1520
1521:function:::void:do_h_extr:int rt, int ac, int shift
1522{
1523  int i;
1524  unsigned32 lo = DSPLO(ac);
1525  unsigned32 hi = DSPHI(ac);
1526  unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1527  signed64 result = (signed64)prod;
1528  signed64 value = 0xffffffffffff8000LL;
1529  result >>= shift;
1530  if (result > 0x7fff)
1531    {
1532      result = 0x7fff;
1533      DSPCR |= DSPCR_OUFLAG7;
1534    }
1535  else if (result < value)
1536    {
1537      result = value;
1538      DSPCR |= DSPCR_OUFLAG7;
1539    }
1540  GPR[rt] = EXTEND32 (result);
1541}
1542
1543011111,5.SHIFT,5.RT,000,2.AC,01110,111000:SPECIAL3:32::EXTR_S.H
1544"extr_s.h r<RT>, ac<AC>, <SHIFT>"
1545*dsp:
1546{
1547  do_h_extr (SD_, RT, AC, SHIFT);
1548}
1549
1550011111,5.RS,5.RT,000,2.AC,01111,111000:SPECIAL3:32::EXTRV_S.H
1551"extrv_s.h r<RT>, ac<AC>, r<RS>"
1552*dsp:
1553{
1554  unsigned32 shift = GPR[RS] & 0x1f;
1555  do_h_extr (SD_, RT, AC, shift);
1556}
1557
1558// op: 0 = EXTP, 1 = EXTPDP
1559:function:::void:do_extp:int rt, int ac, int size, int op
1560{
1561  signed32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
1562  unsigned32 lo = DSPLO(ac);
1563  unsigned32 hi = DSPHI(ac);
1564  unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1565  unsigned64 result = 0;
1566  if (pos - (size + 1) >= -1)
1567    {
1568      prod >>= (pos - size);
1569      result = prod & (((unsigned64)1 << (size + 1)) - 1);
1570      DSPCR &= (~DSPCR_EFI_SMASK);
1571      if (op == 1) // EXTPDP
1572	{
1573	  if (pos - (size + 1) >= 0)
1574	    {
1575	      DSPCR &= (~DSPCR_POS_SMASK);
1576	      DSPCR |= ((pos - (size + 1)) & DSPCR_POS_MASK) << DSPCR_POS_SHIFT;
1577	    }
1578	  else if (pos - (size + 1) == -1)
1579	    {
1580	      DSPCR |= DSPCR_POS_SMASK;
1581	    }
1582	}
1583    }
1584  else
1585    {
1586      DSPCR |= DSPCR_EFI;
1587      Unpredictable ();
1588    }
1589  GPR[rt] = EXTEND32 (result);
1590}
1591
1592011111,5.SIZE,5.RT,000,2.AC,00010,111000:SPECIAL3:32::EXTP
1593"extp r<RT>, ac<AC>, <SIZE>"
1594*dsp:
1595{
1596  do_extp (SD_, RT, AC, SIZE, 0);
1597}
1598
1599011111,5.RS,5.RT,000,2.AC,00011,111000:SPECIAL3:32::EXTPV
1600"extpv r<RT>, ac<AC>, r<RS>"
1601*dsp:
1602{
1603  unsigned32 size = GPR[RS] & 0x1f;
1604  do_extp (SD_, RT, AC, size, 0);
1605}
1606
1607011111,5.SIZE,5.RT,000,2.AC,01010,111000:SPECIAL3:32::EXTPDP
1608"extpdp r<RT>, ac<AC>, <SIZE>"
1609*dsp:
1610{
1611  do_extp (SD_, RT, AC, SIZE, 1);
1612}
1613
1614011111,5.RS,5.RT,000,2.AC,01011,111000:SPECIAL3:32::EXTPDPV
1615"extpdpv r<RT>, ac<AC>, r<RS>"
1616*dsp:
1617{
1618  unsigned32 size = GPR[RS] & 0x1f;
1619  do_extp (SD_, RT, AC, size, 1);
1620}
1621
1622:function:::void:do_shilo:int ac, int shift
1623{
1624  unsigned32 lo = DSPLO(ac);
1625  unsigned32 hi = DSPHI(ac);
1626  unsigned64 prod = (((unsigned64)hi) << 32) + (unsigned64)lo;
1627  if (shift > 31)
1628    shift = shift - 64;
1629  if (shift >= 0)
1630    prod >>= shift;
1631  else
1632    prod <<= (-shift);
1633  DSPLO(ac) = EXTEND32 (prod);
1634  DSPHI(ac) = EXTEND32 (prod >> 32);
1635}
1636
1637011111,6.SHIFT6,0000,000,2.AC,11010,111000:SPECIAL3:32::SHILO
1638"shilo ac<AC>, <SHIFT6>"
1639*dsp:
1640{
1641  do_shilo (SD_, AC, SHIFT6);
1642}
1643
1644011111,5.RS,00000,000,2.AC,11011,111000:SPECIAL3:32::SHILOV
1645"shilov ac<AC>, r<RS>"
1646*dsp:
1647{
1648  signed32 shift = GPR[RS] & 0x3f;
1649  do_shilo (SD_, AC, shift);
1650}
1651
1652011111,5.RS,00000,000,2.AC,11111,111000:SPECIAL3:32::MTHLIP
1653"mthlip r<RS>, ac<AC>"
1654*dsp:
1655{
1656  unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
1657  DSPHI(AC) = DSPLO(AC);
1658  DSPLO(AC) = GPR[RS];
1659  if (pos >= 32)
1660    Unpredictable ();
1661  else
1662    pos += 32;
1663  DSPCR &= (~DSPCR_POS_SMASK);
1664  DSPCR |= (pos & DSPCR_POS_MASK) << DSPCR_POS_SHIFT;
1665}
1666
1667011111,5.RS,10.MASK10,10011,111000:SPECIAL3:32::WRDSP
1668"wrdsp r<RS>":MASK10 == 1111111111
1669"wrdsp r<RS>, <MASK10>"
1670*dsp:
1671{
1672  unsigned32 v1 = GPR[RS];
1673  if (MASK10 & 0x1)
1674    {
1675      DSPCR &= (~DSPCR_POS_SMASK);
1676      DSPCR |= (v1 & DSPCR_POS_SMASK);
1677    }
1678  if (MASK10 & 0x2)
1679    {
1680      DSPCR &= (~DSPCR_SCOUNT_SMASK);
1681      DSPCR |= (v1 & DSPCR_SCOUNT_SMASK);
1682    }
1683  if (MASK10 & 0x4)
1684    {
1685      DSPCR &= (~DSPCR_CARRY_SMASK);
1686      DSPCR |= (v1 & DSPCR_CARRY_SMASK);
1687    }
1688  if (MASK10 & 0x8)
1689    {
1690      DSPCR &= (~DSPCR_OUFLAG_SMASK);
1691      DSPCR |= (v1 & DSPCR_OUFLAG_SMASK);
1692    }
1693  if (MASK10 & 0x10)
1694    {
1695      DSPCR &= (~DSPCR_CCOND_SMASK);
1696      DSPCR |= (v1 & DSPCR_CCOND_SMASK);
1697    }
1698  if (MASK10 & 0x20)
1699    {
1700      DSPCR &= (~DSPCR_EFI_SMASK);
1701      DSPCR |= (v1 & DSPCR_EFI_SMASK);
1702    }
1703}
1704
1705011111,10.MASK10,5.RD,10010,111000:SPECIAL3:32::RDDSP
1706"rddsp r<RD>":MASK10 == 1111111111
1707"rddsp r<RD>, <MASK10>"
1708*dsp:
1709{
1710  unsigned32 result = 0;
1711  if (MASK10 & 0x1)
1712    {
1713      result &= (~DSPCR_POS_SMASK);
1714      result |= (DSPCR & DSPCR_POS_SMASK);
1715    }
1716  if (MASK10 & 0x2)
1717    {
1718      result &= (~DSPCR_SCOUNT_SMASK);
1719      result |= (DSPCR & DSPCR_SCOUNT_SMASK);
1720    }
1721  if (MASK10 & 0x4)
1722    {
1723      result &= (~DSPCR_CARRY_SMASK);
1724      result |= (DSPCR & DSPCR_CARRY_SMASK);
1725    }
1726  if (MASK10 & 0x8)
1727    {
1728      result &= (~DSPCR_OUFLAG_SMASK);
1729      result |= (DSPCR & DSPCR_OUFLAG_SMASK);
1730    }
1731  if (MASK10 & 0x10)
1732    {
1733      result &= (~DSPCR_CCOND_SMASK);
1734      result |= (DSPCR & DSPCR_CCOND_SMASK);
1735    }
1736  if (MASK10 & 0x20)
1737    {
1738      result &= (~DSPCR_EFI_SMASK);
1739      result |= (DSPCR & DSPCR_EFI_SMASK);
1740    }
1741  GPR[RD] = EXTEND32 (result);
1742}
1743
1744011111,5.BASE,5.INDEX,5.RD,00110,001010:SPECIAL3:32::LBUX
1745"lbux r<RD>, r<INDEX>(r<BASE>)"
1746*dsp:
1747{
1748  GPR[RD] = do_load (SD_, AccessLength_BYTE, GPR[BASE], GPR[INDEX]);
1749}
1750
1751011111,5.BASE,5.INDEX,5.RD,00100,001010:SPECIAL3:32::LHX
1752"lhx r<RD>, r<INDEX>(r<BASE>)"
1753*dsp:
1754{
1755  GPR[RD] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[BASE], GPR[INDEX]));
1756}
1757
1758011111,5.BASE,5.INDEX,5.RD,00000,001010:SPECIAL3:32::LWX
1759"lwx r<RD>, r<INDEX>(r<BASE>)"
1760*dsp:
1761{
1762  GPR[RD] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[BASE], GPR[INDEX]));
1763}
1764
1765000001,00000,11100,16.OFFSET:REGIMM:32::BPOSGE32
1766"bposge32 <OFFSET>"
1767*dsp:
1768{
1769  unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
1770  address_word offset = EXTEND16 (OFFSET) << 2;
1771  if (pos >= 32)
1772    {
1773      DELAY_SLOT (NIA + offset);
1774    }
1775}
1776