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