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