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