]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/arm/maverick.c
sim: switch config.h usage to defs.h
[thirdparty/binutils-gdb.git] / sim / arm / maverick.c
1 /* maverick.c -- Cirrus/DSP co-processor interface.
2 Copyright (C) 2003-2021 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez (aldyh@redhat.com).
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18 /* This must come before any other includes. */
19 #include "defs.h"
20
21 #include <assert.h>
22 #include "armdefs.h"
23 #include "ansidecl.h"
24 #include "armemu.h"
25 #include "maverick.h"
26
27 /*#define CIRRUS_DEBUG 1 */
28 #if CIRRUS_DEBUG
29 # define printfdbg printf
30 #else
31 # define printfdbg printf_nothing
32 #endif
33
34 #define POS64(i) ( (~(i)) >> 63 )
35 #define NEG64(i) ( (i) >> 63 )
36
37 /* These variables are defined here and made extern in maverick.h for use
38 in wrapper.c for now.
39 Eventually the simulator should be made to handle any coprocessor at run
40 time. */
41 struct maverick_regs DSPregs[16];
42 union maverick_acc_regs DSPacc[4];
43 ARMword DSPsc;
44
45 #define DEST_REG (BITS (12, 15))
46 #define SRC1_REG (BITS (16, 19))
47 #define SRC2_REG (BITS (0, 3))
48
49 static int lsw_int_index, msw_int_index;
50 static int lsw_float_index, msw_float_index;
51
52 static double mv_getRegDouble (int);
53 static long long mv_getReg64int (int);
54 static void mv_setRegDouble (int, double val);
55 static void mv_setReg64int (int, long long val);
56
57 static union
58 {
59 double d;
60 long long ll;
61 int ints[2];
62 } reg_conv;
63
64 static void
65 printf_nothing (void * foo, ...)
66 {
67 }
68
69 static void
70 cirrus_not_implemented (char * insn)
71 {
72 fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn);
73 fprintf (stderr, "aborting!\n");
74
75 exit (1);
76 }
77
78 unsigned
79 DSPMRC4 (ARMul_State * state ATTRIBUTE_UNUSED,
80 unsigned type ATTRIBUTE_UNUSED,
81 ARMword instr,
82 ARMword * value)
83 {
84 switch (BITS (5, 7))
85 {
86 case 0: /* cfmvrdl */
87 /* Move lower half of a DF stored in a DSP reg into an Arm reg. */
88 printfdbg ("cfmvrdl\n");
89 printfdbg ("\tlower half=0x%x\n", DSPregs[SRC1_REG].lower.i);
90 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
91
92 *value = (ARMword) DSPregs[SRC1_REG].lower.i;
93 break;
94
95 case 1: /* cfmvrdh */
96 /* Move upper half of a DF stored in a DSP reg into an Arm reg. */
97 printfdbg ("cfmvrdh\n");
98 printfdbg ("\tupper half=0x%x\n", DSPregs[SRC1_REG].upper.i);
99 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
100
101 *value = (ARMword) DSPregs[SRC1_REG].upper.i;
102 break;
103
104 case 2: /* cfmvrs */
105 /* Move SF from upper half of a DSP register to an Arm register. */
106 *value = (ARMword) DSPregs[SRC1_REG].upper.i;
107 printfdbg ("cfmvrs = mvf%d <-- %f\n",
108 SRC1_REG,
109 DSPregs[SRC1_REG].upper.f);
110 break;
111
112 #ifdef doesnt_work
113 case 4: /* cfcmps */
114 {
115 float a, b;
116 int n, z, c, v;
117
118 a = DSPregs[SRC1_REG].upper.f;
119 b = DSPregs[SRC2_REG].upper.f;
120
121 printfdbg ("cfcmps\n");
122 printfdbg ("\tcomparing %f and %f\n", a, b);
123
124 z = a == b; /* zero */
125 n = a != b; /* negative */
126 v = a > b; /* overflow */
127 c = 0; /* carry */
128 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
129 break;
130 }
131
132 case 5: /* cfcmpd */
133 {
134 double a, b;
135 int n, z, c, v;
136
137 a = mv_getRegDouble (SRC1_REG);
138 b = mv_getRegDouble (SRC2_REG);
139
140 printfdbg ("cfcmpd\n");
141 printfdbg ("\tcomparing %g and %g\n", a, b);
142
143 z = a == b; /* zero */
144 n = a != b; /* negative */
145 v = a > b; /* overflow */
146 c = 0; /* carry */
147 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
148 break;
149 }
150 #else
151 case 4: /* cfcmps */
152 {
153 float a, b;
154 int n, z, c, v;
155
156 a = DSPregs[SRC1_REG].upper.f;
157 b = DSPregs[SRC2_REG].upper.f;
158
159 printfdbg ("cfcmps\n");
160 printfdbg ("\tcomparing %f and %f\n", a, b);
161
162 z = a == b; /* zero */
163 n = a < b; /* negative */
164 c = a > b; /* carry */
165 v = 0; /* fixme */
166 printfdbg ("\tz = %d, n = %d\n", z, n);
167 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
168 break;
169 }
170
171 case 5: /* cfcmpd */
172 {
173 double a, b;
174 int n, z, c, v;
175
176 a = mv_getRegDouble (SRC1_REG);
177 b = mv_getRegDouble (SRC2_REG);
178
179 printfdbg ("cfcmpd\n");
180 printfdbg ("\tcomparing %g and %g\n", a, b);
181
182 z = a == b; /* zero */
183 n = a < b; /* negative */
184 c = a > b; /* carry */
185 v = 0; /* fixme */
186 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
187 break;
188 }
189 #endif
190 default:
191 fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr);
192 cirrus_not_implemented ("unknown");
193 break;
194 }
195
196 return ARMul_DONE;
197 }
198
199 unsigned
200 DSPMRC5 (ARMul_State * state ATTRIBUTE_UNUSED,
201 unsigned type ATTRIBUTE_UNUSED,
202 ARMword instr,
203 ARMword * value)
204 {
205 switch (BITS (5, 7))
206 {
207 case 0: /* cfmvr64l */
208 /* Move lower half of 64bit int from Cirrus to Arm. */
209 *value = (ARMword) DSPregs[SRC1_REG].lower.i;
210 printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n",
211 DEST_REG,
212 (int) *value);
213 break;
214
215 case 1: /* cfmvr64h */
216 /* Move upper half of 64bit int from Cirrus to Arm. */
217 *value = (ARMword) DSPregs[SRC1_REG].upper.i;
218 printfdbg ("cfmvr64h <-- %d\n", (int) *value);
219 break;
220
221 case 4: /* cfcmp32 */
222 {
223 int res;
224 int n, z, c, v;
225 unsigned int a, b;
226
227 printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
228 SRC1_REG,
229 SRC2_REG);
230
231 /* FIXME: see comment for cfcmps. */
232 a = DSPregs[SRC1_REG].lower.i;
233 b = DSPregs[SRC2_REG].lower.i;
234
235 res = DSPregs[SRC1_REG].lower.i - DSPregs[SRC2_REG].lower.i;
236 /* zero */
237 z = res == 0;
238 /* negative */
239 n = res < 0;
240 /* overflow */
241 v = SubOverflow (DSPregs[SRC1_REG].lower.i, DSPregs[SRC2_REG].lower.i,
242 res);
243 /* carry */
244 c = (NEG (a) && POS (b))
245 || (NEG (a) && POS (res))
246 || (POS (b) && POS (res));
247
248 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
249 break;
250 }
251
252 case 5: /* cfcmp64 */
253 {
254 long long res;
255 int n, z, c, v;
256 unsigned long long a, b;
257
258 printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
259 SRC1_REG,
260 SRC2_REG);
261
262 /* fixme: see comment for cfcmps. */
263
264 a = mv_getReg64int (SRC1_REG);
265 b = mv_getReg64int (SRC2_REG);
266
267 res = mv_getReg64int (SRC1_REG) - mv_getReg64int (SRC2_REG);
268 /* zero */
269 z = res == 0;
270 /* negative */
271 n = res < 0;
272 /* overflow */
273 v = ((NEG64 (a) && POS64 (b) && POS64 (res))
274 || (POS64 (a) && NEG64 (b) && NEG64 (res)));
275 /* carry */
276 c = (NEG64 (a) && POS64 (b))
277 || (NEG64 (a) && POS64 (res))
278 || (POS64 (b) && POS64 (res));
279
280 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
281 break;
282 }
283
284 default:
285 fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr);
286 cirrus_not_implemented ("unknown");
287 break;
288 }
289
290 return ARMul_DONE;
291 }
292
293 unsigned
294 DSPMRC6 (ARMul_State * state ATTRIBUTE_UNUSED,
295 unsigned type ATTRIBUTE_UNUSED,
296 ARMword instr,
297 ARMword * value)
298 {
299 switch (BITS (5, 7))
300 {
301 case 0: /* cfmval32 */
302 cirrus_not_implemented ("cfmval32");
303 break;
304
305 case 1: /* cfmvam32 */
306 cirrus_not_implemented ("cfmvam32");
307 break;
308
309 case 2: /* cfmvah32 */
310 cirrus_not_implemented ("cfmvah32");
311 break;
312
313 case 3: /* cfmva32 */
314 cirrus_not_implemented ("cfmva32");
315 break;
316
317 case 4: /* cfmva64 */
318 cirrus_not_implemented ("cfmva64");
319 break;
320
321 case 5: /* cfmvsc32 */
322 cirrus_not_implemented ("cfmvsc32");
323 break;
324
325 default:
326 fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr);
327 cirrus_not_implemented ("unknown");
328 break;
329 }
330
331 return ARMul_DONE;
332 }
333
334 unsigned
335 DSPMCR4 (ARMul_State * state,
336 unsigned type ATTRIBUTE_UNUSED,
337 ARMword instr,
338 ARMword value)
339 {
340 switch (BITS (5, 7))
341 {
342 case 0: /* cfmvdlr */
343 /* Move the lower half of a DF value from an Arm register into
344 the lower half of a Cirrus register. */
345 printfdbg ("cfmvdlr <-- 0x%x\n", (int) value);
346 DSPregs[SRC1_REG].lower.i = (int) value;
347 break;
348
349 case 1: /* cfmvdhr */
350 /* Move the upper half of a DF value from an Arm register into
351 the upper half of a Cirrus register. */
352 printfdbg ("cfmvdhr <-- 0x%x\n", (int) value);
353 DSPregs[SRC1_REG].upper.i = (int) value;
354 break;
355
356 case 2: /* cfmvsr */
357 /* Move SF from Arm register into upper half of Cirrus register. */
358 printfdbg ("cfmvsr <-- 0x%x\n", (int) value);
359 DSPregs[SRC1_REG].upper.i = (int) value;
360 break;
361
362 default:
363 fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr);
364 cirrus_not_implemented ("unknown");
365 break;
366 }
367
368 return ARMul_DONE;
369 }
370
371 unsigned
372 DSPMCR5 (ARMul_State * state,
373 unsigned type ATTRIBUTE_UNUSED,
374 ARMword instr,
375 ARMword value)
376 {
377 union
378 {
379 int s;
380 unsigned int us;
381 } val;
382
383 switch (BITS (5, 7))
384 {
385 case 0: /* cfmv64lr */
386 /* Move lower half of a 64bit int from an ARM register into the
387 lower half of a DSP register and sign extend it. */
388 printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG, (int) value);
389 DSPregs[SRC1_REG].lower.i = (int) value;
390 break;
391
392 case 1: /* cfmv64hr */
393 /* Move upper half of a 64bit int from an ARM register into the
394 upper half of a DSP register. */
395 printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n",
396 SRC1_REG,
397 (int) value);
398 DSPregs[SRC1_REG].upper.i = (int) value;
399 break;
400
401 case 2: /* cfrshl32 */
402 printfdbg ("cfrshl32\n");
403 val.us = value;
404 if (val.s > 0)
405 DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i << value;
406 else
407 DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -value;
408 break;
409
410 case 3: /* cfrshl64 */
411 printfdbg ("cfrshl64\n");
412 val.us = value;
413 if (val.s > 0)
414 mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) << value);
415 else
416 mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) >> -value);
417 break;
418
419 default:
420 fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr);
421 cirrus_not_implemented ("unknown");
422 break;
423 }
424
425 return ARMul_DONE;
426 }
427
428 unsigned
429 DSPMCR6 (ARMul_State * state,
430 unsigned type ATTRIBUTE_UNUSED,
431 ARMword instr,
432 ARMword value)
433 {
434 switch (BITS (5, 7))
435 {
436 case 0: /* cfmv32al */
437 cirrus_not_implemented ("cfmv32al");
438 break;
439
440 case 1: /* cfmv32am */
441 cirrus_not_implemented ("cfmv32am");
442 break;
443
444 case 2: /* cfmv32ah */
445 cirrus_not_implemented ("cfmv32ah");
446 break;
447
448 case 3: /* cfmv32a */
449 cirrus_not_implemented ("cfmv32a");
450 break;
451
452 case 4: /* cfmv64a */
453 cirrus_not_implemented ("cfmv64a");
454 break;
455
456 case 5: /* cfmv32sc */
457 cirrus_not_implemented ("cfmv32sc");
458 break;
459
460 default:
461 fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr);
462 cirrus_not_implemented ("unknown");
463 break;
464 }
465
466 return ARMul_DONE;
467 }
468
469 unsigned
470 DSPLDC4 (ARMul_State * state ATTRIBUTE_UNUSED,
471 unsigned type,
472 ARMword instr,
473 ARMword data)
474 {
475 static unsigned words;
476
477 if (type != ARMul_DATA)
478 {
479 words = 0;
480 return ARMul_DONE;
481 }
482
483 if (BIT (22))
484 { /* it's a long access, get two words */
485 /* cfldrd */
486
487 printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
488 data, words, state->bigendSig, DEST_REG);
489
490 if (words == 0)
491 {
492 if (state->bigendSig)
493 DSPregs[DEST_REG].upper.i = (int) data;
494 else
495 DSPregs[DEST_REG].lower.i = (int) data;
496 }
497 else
498 {
499 if (state->bigendSig)
500 DSPregs[DEST_REG].lower.i = (int) data;
501 else
502 DSPregs[DEST_REG].upper.i = (int) data;
503 }
504
505 ++ words;
506
507 if (words == 2)
508 {
509 printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG,
510 mv_getRegDouble (DEST_REG));
511
512 return ARMul_DONE;
513 }
514 else
515 return ARMul_INC;
516 }
517 else
518 {
519 /* Get just one word. */
520
521 /* cfldrs */
522 printfdbg ("cfldrs\n");
523
524 DSPregs[DEST_REG].upper.i = (int) data;
525
526 printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG,
527 DSPregs[DEST_REG].upper.f);
528
529 return ARMul_DONE;
530 }
531 }
532
533 unsigned
534 DSPLDC5 (ARMul_State * state ATTRIBUTE_UNUSED,
535 unsigned type,
536 ARMword instr,
537 ARMword data)
538 {
539 static unsigned words;
540
541 if (type != ARMul_DATA)
542 {
543 words = 0;
544 return ARMul_DONE;
545 }
546
547 if (BIT (22))
548 {
549 /* It's a long access, get two words. */
550
551 /* cfldr64 */
552 printfdbg ("cfldr64: %d\n", data);
553
554 if (words == 0)
555 {
556 if (state->bigendSig)
557 DSPregs[DEST_REG].upper.i = (int) data;
558 else
559 DSPregs[DEST_REG].lower.i = (int) data;
560 }
561 else
562 {
563 if (state->bigendSig)
564 DSPregs[DEST_REG].lower.i = (int) data;
565 else
566 DSPregs[DEST_REG].upper.i = (int) data;
567 }
568
569 ++ words;
570
571 if (words == 2)
572 {
573 printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG,
574 mv_getReg64int (DEST_REG));
575
576 return ARMul_DONE;
577 }
578 else
579 return ARMul_INC;
580 }
581 else
582 {
583 /* Get just one word. */
584
585 /* cfldr32 */
586 printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data);
587
588 /* 32bit ints should be sign extended to 64bits when loaded. */
589 mv_setReg64int (DEST_REG, (long long) data);
590
591 return ARMul_DONE;
592 }
593 }
594
595 unsigned
596 DSPSTC4 (ARMul_State * state ATTRIBUTE_UNUSED,
597 unsigned type,
598 ARMword instr,
599 ARMword * data)
600 {
601 static unsigned words;
602
603 if (type != ARMul_DATA)
604 {
605 words = 0;
606 return ARMul_DONE;
607 }
608
609 if (BIT (22))
610 {
611 /* It's a long access, get two words. */
612 /* cfstrd */
613 printfdbg ("cfstrd\n");
614
615 if (words == 0)
616 {
617 if (state->bigendSig)
618 *data = (ARMword) DSPregs[DEST_REG].upper.i;
619 else
620 *data = (ARMword) DSPregs[DEST_REG].lower.i;
621 }
622 else
623 {
624 if (state->bigendSig)
625 *data = (ARMword) DSPregs[DEST_REG].lower.i;
626 else
627 *data = (ARMword) DSPregs[DEST_REG].upper.i;
628 }
629
630 ++ words;
631
632 if (words == 2)
633 {
634 printfdbg ("\tmem = mvd%d = %g\n", DEST_REG,
635 mv_getRegDouble (DEST_REG));
636
637 return ARMul_DONE;
638 }
639 else
640 return ARMul_INC;
641 }
642 else
643 {
644 /* Get just one word. */
645 /* cfstrs */
646 printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG,
647 DSPregs[DEST_REG].upper.f);
648
649 *data = (ARMword) DSPregs[DEST_REG].upper.i;
650
651 return ARMul_DONE;
652 }
653 }
654
655 unsigned
656 DSPSTC5 (ARMul_State * state ATTRIBUTE_UNUSED,
657 unsigned type,
658 ARMword instr,
659 ARMword * data)
660 {
661 static unsigned words;
662
663 if (type != ARMul_DATA)
664 {
665 words = 0;
666 return ARMul_DONE;
667 }
668
669 if (BIT (22))
670 {
671 /* It's a long access, store two words. */
672 /* cfstr64 */
673 printfdbg ("cfstr64\n");
674
675 if (words == 0)
676 {
677 if (state->bigendSig)
678 *data = (ARMword) DSPregs[DEST_REG].upper.i;
679 else
680 *data = (ARMword) DSPregs[DEST_REG].lower.i;
681 }
682 else
683 {
684 if (state->bigendSig)
685 *data = (ARMword) DSPregs[DEST_REG].lower.i;
686 else
687 *data = (ARMword) DSPregs[DEST_REG].upper.i;
688 }
689
690 ++ words;
691
692 if (words == 2)
693 {
694 printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG,
695 mv_getReg64int (DEST_REG));
696
697 return ARMul_DONE;
698 }
699 else
700 return ARMul_INC;
701 }
702 else
703 {
704 /* Store just one word. */
705 /* cfstr32 */
706 *data = (ARMword) DSPregs[DEST_REG].lower.i;
707
708 printfdbg ("cfstr32 MEM = %d\n", (int) *data);
709
710 return ARMul_DONE;
711 }
712 }
713
714 unsigned
715 DSPCDP4 (ARMul_State * state,
716 unsigned type,
717 ARMword instr)
718 {
719 int opcode2;
720
721 opcode2 = BITS (5,7);
722
723 switch (BITS (20,21))
724 {
725 case 0:
726 switch (opcode2)
727 {
728 case 0: /* cfcpys */
729 printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
730 DEST_REG,
731 SRC1_REG,
732 DSPregs[SRC1_REG].upper.f);
733 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f;
734 break;
735
736 case 1: /* cfcpyd */
737 printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
738 DEST_REG,
739 SRC1_REG,
740 mv_getRegDouble (SRC1_REG));
741 mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG));
742 break;
743
744 case 2: /* cfcvtds */
745 printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
746 DEST_REG,
747 SRC1_REG,
748 (float) mv_getRegDouble (SRC1_REG));
749 DSPregs[DEST_REG].upper.f = (float) mv_getRegDouble (SRC1_REG);
750 break;
751
752 case 3: /* cfcvtsd */
753 printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
754 DEST_REG,
755 SRC1_REG,
756 (double) DSPregs[SRC1_REG].upper.f);
757 mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].upper.f);
758 break;
759
760 case 4: /* cfcvt32s */
761 printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
762 DEST_REG,
763 SRC1_REG,
764 (float) DSPregs[SRC1_REG].lower.i);
765 DSPregs[DEST_REG].upper.f = (float) DSPregs[SRC1_REG].lower.i;
766 break;
767
768 case 5: /* cfcvt32d */
769 printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
770 DEST_REG,
771 SRC1_REG,
772 (double) DSPregs[SRC1_REG].lower.i);
773 mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].lower.i);
774 break;
775
776 case 6: /* cfcvt64s */
777 printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
778 DEST_REG,
779 SRC1_REG,
780 (float) mv_getReg64int (SRC1_REG));
781 DSPregs[DEST_REG].upper.f = (float) mv_getReg64int (SRC1_REG);
782 break;
783
784 case 7: /* cfcvt64d */
785 printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
786 DEST_REG,
787 SRC1_REG,
788 (double) mv_getReg64int (SRC1_REG));
789 mv_setRegDouble (DEST_REG, (double) mv_getReg64int (SRC1_REG));
790 break;
791 }
792 break;
793
794 case 1:
795 switch (opcode2)
796 {
797 case 0: /* cfmuls */
798 printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
799 DEST_REG,
800 SRC1_REG,
801 DSPregs[SRC1_REG].upper.f * DSPregs[SRC2_REG].upper.f);
802
803 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
804 * DSPregs[SRC2_REG].upper.f;
805 break;
806
807 case 1: /* cfmuld */
808 printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
809 DEST_REG,
810 SRC1_REG,
811 mv_getRegDouble (SRC1_REG) * mv_getRegDouble (SRC2_REG));
812
813 mv_setRegDouble (DEST_REG,
814 mv_getRegDouble (SRC1_REG)
815 * mv_getRegDouble (SRC2_REG));
816 break;
817
818 default:
819 fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
820 cirrus_not_implemented ("unknown");
821 break;
822 }
823 break;
824
825 case 3:
826 switch (opcode2)
827 {
828 case 0: /* cfabss */
829 DSPregs[DEST_REG].upper.f = (DSPregs[SRC1_REG].upper.f < 0.0F ?
830 -DSPregs[SRC1_REG].upper.f
831 : DSPregs[SRC1_REG].upper.f);
832 printfdbg ("cfabss mvf%d = |mvf%d| = %f\n",
833 DEST_REG,
834 SRC1_REG,
835 DSPregs[DEST_REG].upper.f);
836 break;
837
838 case 1: /* cfabsd */
839 mv_setRegDouble (DEST_REG,
840 (mv_getRegDouble (SRC1_REG) < 0.0 ?
841 -mv_getRegDouble (SRC1_REG)
842 : mv_getRegDouble (SRC1_REG)));
843 printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n",
844 DEST_REG,
845 SRC1_REG,
846 mv_getRegDouble (DEST_REG));
847 break;
848
849 case 2: /* cfnegs */
850 DSPregs[DEST_REG].upper.f = -DSPregs[SRC1_REG].upper.f;
851 printfdbg ("cfnegs mvf%d = -mvf%d = %f\n",
852 DEST_REG,
853 SRC1_REG,
854 DSPregs[DEST_REG].upper.f);
855 break;
856
857 case 3: /* cfnegd */
858 mv_setRegDouble (DEST_REG,
859 -mv_getRegDouble (SRC1_REG));
860 printfdbg ("cfnegd mvd%d = -mvd%d = %g\n",
861 DEST_REG, DEST_REG,
862 mv_getRegDouble (DEST_REG));
863 break;
864
865 case 4: /* cfadds */
866 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
867 + DSPregs[SRC2_REG].upper.f;
868 printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n",
869 DEST_REG,
870 SRC1_REG,
871 SRC2_REG,
872 DSPregs[DEST_REG].upper.f);
873 break;
874
875 case 5: /* cfaddd */
876 mv_setRegDouble (DEST_REG,
877 mv_getRegDouble (SRC1_REG)
878 + mv_getRegDouble (SRC2_REG));
879 printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n",
880 DEST_REG,
881 SRC1_REG,
882 SRC2_REG,
883 mv_getRegDouble (DEST_REG));
884 break;
885
886 case 6: /* cfsubs */
887 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
888 - DSPregs[SRC2_REG].upper.f;
889 printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n",
890 DEST_REG,
891 SRC1_REG,
892 SRC2_REG,
893 DSPregs[DEST_REG].upper.f);
894 break;
895
896 case 7: /* cfsubd */
897 mv_setRegDouble (DEST_REG,
898 mv_getRegDouble (SRC1_REG)
899 - mv_getRegDouble (SRC2_REG));
900 printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n",
901 DEST_REG,
902 SRC1_REG,
903 SRC2_REG,
904 mv_getRegDouble (DEST_REG));
905 break;
906 }
907 break;
908
909 default:
910 fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
911 cirrus_not_implemented ("unknown");
912 break;
913 }
914
915 return ARMul_DONE;
916 }
917
918 unsigned
919 DSPCDP5 (ARMul_State * state,
920 unsigned type,
921 ARMword instr)
922 {
923 int opcode2;
924 char shift;
925
926 opcode2 = BITS (5,7);
927
928 /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */
929 shift = BITS (0, 3) | (BITS (5, 7)) << 4;
930 if (shift & 0x40)
931 shift |= 0xc0;
932
933 switch (BITS (20,21))
934 {
935 case 0:
936 /* cfsh32 */
937 printfdbg ("cfsh32 %s amount=%d\n", shift < 0 ? "right" : "left",
938 shift);
939 if (shift < 0)
940 /* Negative shift is a right shift. */
941 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -shift;
942 else
943 /* Positive shift is a left shift. */
944 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i << shift;
945 break;
946
947 case 1:
948 switch (opcode2)
949 {
950 case 0: /* cfmul32 */
951 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
952 * DSPregs[SRC2_REG].lower.i;
953 printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n",
954 DEST_REG,
955 SRC1_REG,
956 SRC2_REG,
957 DSPregs[DEST_REG].lower.i);
958 break;
959
960 case 1: /* cfmul64 */
961 mv_setReg64int (DEST_REG,
962 mv_getReg64int (SRC1_REG)
963 * mv_getReg64int (SRC2_REG));
964 printfdbg ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n",
965 DEST_REG,
966 SRC1_REG,
967 SRC2_REG,
968 mv_getReg64int (DEST_REG));
969 break;
970
971 case 2: /* cfmac32 */
972 DSPregs[DEST_REG].lower.i
973 += DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i;
974 printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n",
975 DEST_REG,
976 SRC1_REG,
977 SRC2_REG,
978 DSPregs[DEST_REG].lower.i);
979 break;
980
981 case 3: /* cfmsc32 */
982 DSPregs[DEST_REG].lower.i
983 -= DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i;
984 printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n",
985 DEST_REG,
986 SRC1_REG,
987 SRC2_REG,
988 DSPregs[DEST_REG].lower.i);
989 break;
990
991 case 4: /* cfcvts32 */
992 /* fixme: this should round */
993 DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f;
994 printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n",
995 DEST_REG,
996 SRC1_REG,
997 DSPregs[DEST_REG].lower.i);
998 break;
999
1000 case 5: /* cfcvtd32 */
1001 /* fixme: this should round */
1002 DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
1003 printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n",
1004 DEST_REG,
1005 SRC1_REG,
1006 DSPregs[DEST_REG].lower.i);
1007 break;
1008
1009 case 6: /* cftruncs32 */
1010 DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f;
1011 printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n",
1012 DEST_REG,
1013 SRC1_REG,
1014 DSPregs[DEST_REG].lower.i);
1015 break;
1016
1017 case 7: /* cftruncd32 */
1018 DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
1019 printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
1020 DEST_REG,
1021 SRC1_REG,
1022 DSPregs[DEST_REG].lower.i);
1023 break;
1024 }
1025 break;
1026
1027 case 2:
1028 /* cfsh64 */
1029 printfdbg ("cfsh64\n");
1030
1031 if (shift < 0)
1032 /* Negative shift is a right shift. */
1033 mv_setReg64int (DEST_REG,
1034 mv_getReg64int (SRC1_REG) >> -shift);
1035 else
1036 /* Positive shift is a left shift. */
1037 mv_setReg64int (DEST_REG,
1038 mv_getReg64int (SRC1_REG) << shift);
1039 printfdbg ("\t%llx\n", mv_getReg64int(DEST_REG));
1040 break;
1041
1042 case 3:
1043 switch (opcode2)
1044 {
1045 case 0: /* cfabs32 */
1046 DSPregs[DEST_REG].lower.i = (DSPregs[SRC1_REG].lower.i < 0
1047 ? -DSPregs[SRC1_REG].lower.i : DSPregs[SRC1_REG].lower.i);
1048 printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n",
1049 DEST_REG,
1050 SRC1_REG,
1051 SRC2_REG,
1052 DSPregs[DEST_REG].lower.i);
1053 break;
1054
1055 case 1: /* cfabs64 */
1056 mv_setReg64int (DEST_REG,
1057 (mv_getReg64int (SRC1_REG) < 0
1058 ? -mv_getReg64int (SRC1_REG)
1059 : mv_getReg64int (SRC1_REG)));
1060 printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n",
1061 DEST_REG,
1062 SRC1_REG,
1063 SRC2_REG,
1064 mv_getReg64int (DEST_REG));
1065 break;
1066
1067 case 2: /* cfneg32 */
1068 DSPregs[DEST_REG].lower.i = -DSPregs[SRC1_REG].lower.i;
1069 printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
1070 DEST_REG,
1071 SRC1_REG,
1072 SRC2_REG,
1073 DSPregs[DEST_REG].lower.i);
1074 break;
1075
1076 case 3: /* cfneg64 */
1077 mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG));
1078 printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
1079 DEST_REG,
1080 SRC1_REG,
1081 SRC2_REG,
1082 mv_getReg64int (DEST_REG));
1083 break;
1084
1085 case 4: /* cfadd32 */
1086 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
1087 + DSPregs[SRC2_REG].lower.i;
1088 printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n",
1089 DEST_REG,
1090 SRC1_REG,
1091 SRC2_REG,
1092 DSPregs[DEST_REG].lower.i);
1093 break;
1094
1095 case 5: /* cfadd64 */
1096 mv_setReg64int (DEST_REG,
1097 mv_getReg64int (SRC1_REG)
1098 + mv_getReg64int (SRC2_REG));
1099 printfdbg ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n",
1100 DEST_REG,
1101 SRC1_REG,
1102 SRC2_REG,
1103 mv_getReg64int (DEST_REG));
1104 break;
1105
1106 case 6: /* cfsub32 */
1107 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
1108 - DSPregs[SRC2_REG].lower.i;
1109 printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n",
1110 DEST_REG,
1111 SRC1_REG,
1112 SRC2_REG,
1113 DSPregs[DEST_REG].lower.i);
1114 break;
1115
1116 case 7: /* cfsub64 */
1117 mv_setReg64int (DEST_REG,
1118 mv_getReg64int (SRC1_REG)
1119 - mv_getReg64int (SRC2_REG));
1120 printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n",
1121 DEST_REG,
1122 SRC1_REG,
1123 SRC2_REG,
1124 mv_getReg64int (DEST_REG));
1125 break;
1126 }
1127 break;
1128
1129 default:
1130 fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr);
1131 cirrus_not_implemented ("unknown");
1132 break;
1133 }
1134
1135 return ARMul_DONE;
1136 }
1137
1138 unsigned
1139 DSPCDP6 (ARMul_State * state,
1140 unsigned type,
1141 ARMword instr)
1142 {
1143 switch (BITS (20,21))
1144 {
1145 case 0:
1146 /* cfmadd32 */
1147 cirrus_not_implemented ("cfmadd32");
1148 break;
1149
1150 case 1:
1151 /* cfmsub32 */
1152 cirrus_not_implemented ("cfmsub32");
1153 break;
1154
1155 case 2:
1156 /* cfmadda32 */
1157 cirrus_not_implemented ("cfmadda32");
1158 break;
1159
1160 case 3:
1161 /* cfmsuba32 */
1162 cirrus_not_implemented ("cfmsuba32");
1163 break;
1164
1165 default:
1166 fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr);
1167 }
1168
1169 return ARMul_DONE;
1170 }
1171
1172 /* Conversion functions.
1173
1174 32-bit integers are stored in the LOWER half of a 64-bit physical
1175 register.
1176
1177 Single precision floats are stored in the UPPER half of a 64-bit
1178 physical register. */
1179
1180 static double
1181 mv_getRegDouble (int regnum)
1182 {
1183 reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i;
1184 reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i;
1185 return reg_conv.d;
1186 }
1187
1188 static void
1189 mv_setRegDouble (int regnum, double val)
1190 {
1191 reg_conv.d = val;
1192 DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index];
1193 DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index];
1194 }
1195
1196 static long long
1197 mv_getReg64int (int regnum)
1198 {
1199 reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i;
1200 reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i;
1201 return reg_conv.ll;
1202 }
1203
1204 static void
1205 mv_setReg64int (int regnum, long long val)
1206 {
1207 reg_conv.ll = val;
1208 DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index];
1209 DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index];
1210 }