]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/mips/dsp.igen
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / sim / mips / dsp.igen
1 // -*- C -*-
2
3 // Simulator definition for the MIPS DSP ASE.
4 // Copyright (C) 2005-2013 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 }