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