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