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