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