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