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