ld-x86-64/pr19609-2d.d: Move "#pass" to the end
[binutils-gdb.git] / sim / arm / maverick.c
blobda5b4ad7fd66a431abea07d2c216f73fa1c411fc
1 /* maverick.c -- Cirrus/DSP co-processor interface.
2 Copyright (C) 2003-2024 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez (aldyh@redhat.com).
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.
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.
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/>. */
18 /* This must come before any other includes. */
19 #include "defs.h"
21 #include <assert.h>
22 #include "armdefs.h"
23 #include "ansidecl.h"
24 #include "armemu.h"
25 #include "maverick.h"
27 /*#define CIRRUS_DEBUG 1 */
28 #if CIRRUS_DEBUG
29 # define printfdbg printf
30 #else
31 # define printfdbg printf_nothing
32 #endif
34 #define POS64(i) ( (~(i)) >> 63 )
35 #define NEG64(i) ( (i) >> 63 )
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;
45 #define DEST_REG (BITS (12, 15))
46 #define SRC1_REG (BITS (16, 19))
47 #define SRC2_REG (BITS (0, 3))
49 static int lsw_int_index, msw_int_index;
50 static int lsw_float_index, msw_float_index;
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);
57 static union
59 double d;
60 long long ll;
61 int ints[2];
62 } reg_conv;
64 static void
65 printf_nothing (void * foo, ...)
69 static void
70 cirrus_not_implemented (char * insn)
72 fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn);
73 fprintf (stderr, "aborting!\n");
75 exit (1);
78 unsigned
79 DSPMRC4 (ARMul_State * state ATTRIBUTE_UNUSED,
80 unsigned type ATTRIBUTE_UNUSED,
81 ARMword instr,
82 ARMword * value)
84 switch (BITS (5, 7))
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));
92 *value = (ARMword) DSPregs[SRC1_REG].lower.i;
93 break;
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));
101 *value = (ARMword) DSPregs[SRC1_REG].upper.i;
102 break;
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;
112 #ifdef doesnt_work
113 case 4: /* cfcmps */
115 float a, b;
116 int n, z, c, v;
118 a = DSPregs[SRC1_REG].upper.f;
119 b = DSPregs[SRC2_REG].upper.f;
121 printfdbg ("cfcmps\n");
122 printfdbg ("\tcomparing %f and %f\n", a, b);
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;
132 case 5: /* cfcmpd */
134 double a, b;
135 int n, z, c, v;
137 a = mv_getRegDouble (SRC1_REG);
138 b = mv_getRegDouble (SRC2_REG);
140 printfdbg ("cfcmpd\n");
141 printfdbg ("\tcomparing %g and %g\n", a, b);
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;
150 #else
151 case 4: /* cfcmps */
153 float a, b;
154 int n, z, c, v;
156 a = DSPregs[SRC1_REG].upper.f;
157 b = DSPregs[SRC2_REG].upper.f;
159 printfdbg ("cfcmps\n");
160 printfdbg ("\tcomparing %f and %f\n", a, b);
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;
171 case 5: /* cfcmpd */
173 double a, b;
174 int n, z, c, v;
176 a = mv_getRegDouble (SRC1_REG);
177 b = mv_getRegDouble (SRC2_REG);
179 printfdbg ("cfcmpd\n");
180 printfdbg ("\tcomparing %g and %g\n", a, b);
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;
189 #endif
190 default:
191 fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr);
192 cirrus_not_implemented ("unknown");
193 break;
196 return ARMul_DONE;
199 unsigned
200 DSPMRC5 (ARMul_State * state ATTRIBUTE_UNUSED,
201 unsigned type ATTRIBUTE_UNUSED,
202 ARMword instr,
203 ARMword * value)
205 switch (BITS (5, 7))
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;
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;
221 case 4: /* cfcmp32 */
223 int res;
224 int n, z, c, v;
225 unsigned int a, b;
227 printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
228 SRC1_REG,
229 SRC2_REG);
231 /* FIXME: see comment for cfcmps. */
232 a = DSPregs[SRC1_REG].lower.i;
233 b = DSPregs[SRC2_REG].lower.i;
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));
248 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
249 break;
252 case 5: /* cfcmp64 */
254 long long res;
255 int n, z, c, v;
256 unsigned long long a, b;
258 printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
259 SRC1_REG,
260 SRC2_REG);
262 /* fixme: see comment for cfcmps. */
264 a = mv_getReg64int (SRC1_REG);
265 b = mv_getReg64int (SRC2_REG);
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));
280 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
281 break;
284 default:
285 fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr);
286 cirrus_not_implemented ("unknown");
287 break;
290 return ARMul_DONE;
293 unsigned
294 DSPMRC6 (ARMul_State * state ATTRIBUTE_UNUSED,
295 unsigned type ATTRIBUTE_UNUSED,
296 ARMword instr,
297 ARMword * value)
299 switch (BITS (5, 7))
301 case 0: /* cfmval32 */
302 cirrus_not_implemented ("cfmval32");
303 break;
305 case 1: /* cfmvam32 */
306 cirrus_not_implemented ("cfmvam32");
307 break;
309 case 2: /* cfmvah32 */
310 cirrus_not_implemented ("cfmvah32");
311 break;
313 case 3: /* cfmva32 */
314 cirrus_not_implemented ("cfmva32");
315 break;
317 case 4: /* cfmva64 */
318 cirrus_not_implemented ("cfmva64");
319 break;
321 case 5: /* cfmvsc32 */
322 cirrus_not_implemented ("cfmvsc32");
323 break;
325 default:
326 fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr);
327 cirrus_not_implemented ("unknown");
328 break;
331 return ARMul_DONE;
334 unsigned
335 DSPMCR4 (ARMul_State * state,
336 unsigned type ATTRIBUTE_UNUSED,
337 ARMword instr,
338 ARMword value)
340 switch (BITS (5, 7))
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;
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;
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;
362 default:
363 fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr);
364 cirrus_not_implemented ("unknown");
365 break;
368 return ARMul_DONE;
371 unsigned
372 DSPMCR5 (ARMul_State * state,
373 unsigned type ATTRIBUTE_UNUSED,
374 ARMword instr,
375 ARMword value)
377 union
379 int s;
380 unsigned int us;
381 } val;
383 switch (BITS (5, 7))
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;
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;
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;
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;
419 default:
420 fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr);
421 cirrus_not_implemented ("unknown");
422 break;
425 return ARMul_DONE;
428 unsigned
429 DSPMCR6 (ARMul_State * state,
430 unsigned type ATTRIBUTE_UNUSED,
431 ARMword instr,
432 ARMword value)
434 switch (BITS (5, 7))
436 case 0: /* cfmv32al */
437 cirrus_not_implemented ("cfmv32al");
438 break;
440 case 1: /* cfmv32am */
441 cirrus_not_implemented ("cfmv32am");
442 break;
444 case 2: /* cfmv32ah */
445 cirrus_not_implemented ("cfmv32ah");
446 break;
448 case 3: /* cfmv32a */
449 cirrus_not_implemented ("cfmv32a");
450 break;
452 case 4: /* cfmv64a */
453 cirrus_not_implemented ("cfmv64a");
454 break;
456 case 5: /* cfmv32sc */
457 cirrus_not_implemented ("cfmv32sc");
458 break;
460 default:
461 fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr);
462 cirrus_not_implemented ("unknown");
463 break;
466 return ARMul_DONE;
469 unsigned
470 DSPLDC4 (ARMul_State * state ATTRIBUTE_UNUSED,
471 unsigned type,
472 ARMword instr,
473 ARMword data)
475 static unsigned words;
477 if (type != ARMul_DATA)
479 words = 0;
480 return ARMul_DONE;
483 if (BIT (22))
484 { /* it's a long access, get two words */
485 /* cfldrd */
487 printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
488 data, words, state->bigendSig, DEST_REG);
490 if (words == 0)
492 if (state->bigendSig)
493 DSPregs[DEST_REG].upper.i = (int) data;
494 else
495 DSPregs[DEST_REG].lower.i = (int) data;
497 else
499 if (state->bigendSig)
500 DSPregs[DEST_REG].lower.i = (int) data;
501 else
502 DSPregs[DEST_REG].upper.i = (int) data;
505 ++ words;
507 if (words == 2)
509 printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG,
510 mv_getRegDouble (DEST_REG));
512 return ARMul_DONE;
514 else
515 return ARMul_INC;
517 else
519 /* Get just one word. */
521 /* cfldrs */
522 printfdbg ("cfldrs\n");
524 DSPregs[DEST_REG].upper.i = (int) data;
526 printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG,
527 DSPregs[DEST_REG].upper.f);
529 return ARMul_DONE;
533 unsigned
534 DSPLDC5 (ARMul_State * state ATTRIBUTE_UNUSED,
535 unsigned type,
536 ARMword instr,
537 ARMword data)
539 static unsigned words;
541 if (type != ARMul_DATA)
543 words = 0;
544 return ARMul_DONE;
547 if (BIT (22))
549 /* It's a long access, get two words. */
551 /* cfldr64 */
552 printfdbg ("cfldr64: %d\n", data);
554 if (words == 0)
556 if (state->bigendSig)
557 DSPregs[DEST_REG].upper.i = (int) data;
558 else
559 DSPregs[DEST_REG].lower.i = (int) data;
561 else
563 if (state->bigendSig)
564 DSPregs[DEST_REG].lower.i = (int) data;
565 else
566 DSPregs[DEST_REG].upper.i = (int) data;
569 ++ words;
571 if (words == 2)
573 printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG,
574 mv_getReg64int (DEST_REG));
576 return ARMul_DONE;
578 else
579 return ARMul_INC;
581 else
583 /* Get just one word. */
585 /* cfldr32 */
586 printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data);
588 /* 32bit ints should be sign extended to 64bits when loaded. */
589 mv_setReg64int (DEST_REG, (long long) data);
591 return ARMul_DONE;
595 unsigned
596 DSPSTC4 (ARMul_State * state ATTRIBUTE_UNUSED,
597 unsigned type,
598 ARMword instr,
599 ARMword * data)
601 static unsigned words;
603 if (type != ARMul_DATA)
605 words = 0;
606 return ARMul_DONE;
609 if (BIT (22))
611 /* It's a long access, get two words. */
612 /* cfstrd */
613 printfdbg ("cfstrd\n");
615 if (words == 0)
617 if (state->bigendSig)
618 *data = (ARMword) DSPregs[DEST_REG].upper.i;
619 else
620 *data = (ARMword) DSPregs[DEST_REG].lower.i;
622 else
624 if (state->bigendSig)
625 *data = (ARMword) DSPregs[DEST_REG].lower.i;
626 else
627 *data = (ARMword) DSPregs[DEST_REG].upper.i;
630 ++ words;
632 if (words == 2)
634 printfdbg ("\tmem = mvd%d = %g\n", DEST_REG,
635 mv_getRegDouble (DEST_REG));
637 return ARMul_DONE;
639 else
640 return ARMul_INC;
642 else
644 /* Get just one word. */
645 /* cfstrs */
646 printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG,
647 DSPregs[DEST_REG].upper.f);
649 *data = (ARMword) DSPregs[DEST_REG].upper.i;
651 return ARMul_DONE;
655 unsigned
656 DSPSTC5 (ARMul_State * state ATTRIBUTE_UNUSED,
657 unsigned type,
658 ARMword instr,
659 ARMword * data)
661 static unsigned words;
663 if (type != ARMul_DATA)
665 words = 0;
666 return ARMul_DONE;
669 if (BIT (22))
671 /* It's a long access, store two words. */
672 /* cfstr64 */
673 printfdbg ("cfstr64\n");
675 if (words == 0)
677 if (state->bigendSig)
678 *data = (ARMword) DSPregs[DEST_REG].upper.i;
679 else
680 *data = (ARMword) DSPregs[DEST_REG].lower.i;
682 else
684 if (state->bigendSig)
685 *data = (ARMword) DSPregs[DEST_REG].lower.i;
686 else
687 *data = (ARMword) DSPregs[DEST_REG].upper.i;
690 ++ words;
692 if (words == 2)
694 printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG,
695 mv_getReg64int (DEST_REG));
697 return ARMul_DONE;
699 else
700 return ARMul_INC;
702 else
704 /* Store just one word. */
705 /* cfstr32 */
706 *data = (ARMword) DSPregs[DEST_REG].lower.i;
708 printfdbg ("cfstr32 MEM = %d\n", (int) *data);
710 return ARMul_DONE;
714 unsigned
715 DSPCDP4 (ARMul_State * state,
716 unsigned type,
717 ARMword instr)
719 int opcode2;
721 opcode2 = BITS (5,7);
723 switch (BITS (20,21))
725 case 0:
726 switch (opcode2)
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;
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;
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;
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;
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;
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;
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;
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;
792 break;
794 case 1:
795 switch (opcode2)
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);
803 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
804 * DSPregs[SRC2_REG].upper.f;
805 break;
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));
813 mv_setRegDouble (DEST_REG,
814 mv_getRegDouble (SRC1_REG)
815 * mv_getRegDouble (SRC2_REG));
816 break;
818 default:
819 fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
820 cirrus_not_implemented ("unknown");
821 break;
823 break;
825 case 3:
826 switch (opcode2)
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;
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;
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;
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;
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;
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;
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;
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;
907 break;
909 default:
910 fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
911 cirrus_not_implemented ("unknown");
912 break;
915 return ARMul_DONE;
918 unsigned
919 DSPCDP5 (ARMul_State * state,
920 unsigned type,
921 ARMword instr)
923 int opcode2;
924 char shift;
926 opcode2 = BITS (5,7);
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;
933 switch (BITS (20,21))
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;
947 case 1:
948 switch (opcode2)
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;
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;
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;
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;
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;
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;
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;
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;
1025 break;
1027 case 2:
1028 /* cfsh64 */
1029 printfdbg ("cfsh64\n");
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;
1042 case 3:
1043 switch (opcode2)
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;
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;
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;
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;
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;
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;
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;
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;
1127 break;
1129 default:
1130 fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr);
1131 cirrus_not_implemented ("unknown");
1132 break;
1135 return ARMul_DONE;
1138 unsigned
1139 DSPCDP6 (ARMul_State * state,
1140 unsigned type,
1141 ARMword instr)
1143 switch (BITS (20,21))
1145 case 0:
1146 /* cfmadd32 */
1147 cirrus_not_implemented ("cfmadd32");
1148 break;
1150 case 1:
1151 /* cfmsub32 */
1152 cirrus_not_implemented ("cfmsub32");
1153 break;
1155 case 2:
1156 /* cfmadda32 */
1157 cirrus_not_implemented ("cfmadda32");
1158 break;
1160 case 3:
1161 /* cfmsuba32 */
1162 cirrus_not_implemented ("cfmsuba32");
1163 break;
1165 default:
1166 fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr);
1169 return ARMul_DONE;
1172 /* Conversion functions.
1174 32-bit integers are stored in the LOWER half of a 64-bit physical
1175 register.
1177 Single precision floats are stored in the UPPER half of a 64-bit
1178 physical register. */
1180 static double
1181 mv_getRegDouble (int regnum)
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;
1188 static void
1189 mv_setRegDouble (int regnum, double val)
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];
1196 static long long
1197 mv_getReg64int (int regnum)
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;
1204 static void
1205 mv_setReg64int (int regnum, long long val)
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];