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