b910c9b8c676e284b10a3ae487f6f44ac6baf38b
1 /* maverick.c -- Cirrus/DSP co-processor interface.
2 Copyright (C) 2003, 2007 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez (aldyh@redhat.com).
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 /*#define CIRRUS_DEBUG 1 /**/
25 # define printfdbg printf
27 # define printfdbg printf_nothing
30 #define POS64(i) ( (~(i)) >> 63 )
31 #define NEG64(i) ( (i) >> 63 )
33 /* Define Co-Processor instruction handlers here. */
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. */
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
58 union maverick_acc_regs
60 long double ld
; /* Acc registers are 72-bits. */
63 struct maverick_regs DSPregs
[16];
64 union maverick_acc_regs DSPacc
[4];
67 #define DEST_REG (BITS (12, 15))
68 #define SRC1_REG (BITS (16, 19))
69 #define SRC2_REG (BITS (0, 3))
71 static int lsw_int_index
, msw_int_index
;
72 static int lsw_float_index
, msw_float_index
;
74 static double mv_getRegDouble (int);
75 static long long mv_getReg64int (int);
76 static void mv_setRegDouble (int, double val
);
77 static void mv_setReg64int (int, long long val
);
87 printf_nothing (void * foo
, ...)
92 cirrus_not_implemented (char * insn
)
94 fprintf (stderr
, "Cirrus instruction '%s' not implemented.\n", insn
);
95 fprintf (stderr
, "aborting!\n");
101 DSPInit (ARMul_State
* state
)
103 ARMul_ConsolePrint (state
, ", DSP present");
108 DSPMRC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
109 unsigned type ATTRIBUTE_UNUSED
,
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
));
121 *value
= (ARMword
) DSPregs
[SRC1_REG
].lower
.i
;
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
));
130 *value
= (ARMword
) DSPregs
[SRC1_REG
].upper
.i
;
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",
138 DSPregs
[SRC1_REG
].upper
.f
);
147 a
= DSPregs
[SRC1_REG
].upper
.f
;
148 b
= DSPregs
[SRC2_REG
].upper
.f
;
150 printfdbg ("cfcmps\n");
151 printfdbg ("\tcomparing %f and %f\n", a
, b
);
153 z
= a
== b
; /* zero */
154 n
= a
!= b
; /* negative */
155 v
= a
> b
; /* overflow */
157 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
166 a
= mv_getRegDouble (SRC1_REG
);
167 b
= mv_getRegDouble (SRC2_REG
);
169 printfdbg ("cfcmpd\n");
170 printfdbg ("\tcomparing %g and %g\n", a
, b
);
172 z
= a
== b
; /* zero */
173 n
= a
!= b
; /* negative */
174 v
= a
> b
; /* overflow */
176 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
185 a
= DSPregs
[SRC1_REG
].upper
.f
;
186 b
= DSPregs
[SRC2_REG
].upper
.f
;
188 printfdbg ("cfcmps\n");
189 printfdbg ("\tcomparing %f and %f\n", a
, b
);
191 z
= a
== b
; /* zero */
192 n
= a
< b
; /* negative */
193 c
= a
> b
; /* carry */
195 printfdbg ("\tz = %d, n = %d\n", z
, n
);
196 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
205 a
= mv_getRegDouble (SRC1_REG
);
206 b
= mv_getRegDouble (SRC2_REG
);
208 printfdbg ("cfcmpd\n");
209 printfdbg ("\tcomparing %g and %g\n", a
, b
);
211 z
= a
== b
; /* zero */
212 n
= a
< b
; /* negative */
213 c
= a
> b
; /* carry */
215 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
220 fprintf (stderr
, "unknown opcode in DSPMRC4 0x%x\n", instr
);
221 cirrus_not_implemented ("unknown");
229 DSPMRC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
230 unsigned type ATTRIBUTE_UNUSED
,
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",
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
);
250 case 4: /* cfcmp32 */
256 printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
260 /* FIXME: see comment for cfcmps. */
261 a
= DSPregs
[SRC1_REG
].lower
.i
;
262 b
= DSPregs
[SRC2_REG
].lower
.i
;
264 res
= DSPregs
[SRC1_REG
].lower
.i
- DSPregs
[SRC2_REG
].lower
.i
;
270 v
= SubOverflow (DSPregs
[SRC1_REG
].lower
.i
, DSPregs
[SRC2_REG
].lower
.i
,
273 c
= (NEG (a
) && POS (b
) ||
274 (NEG (a
) && POS (res
)) || (POS (b
) && POS (res
)));
276 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
280 case 5: /* cfcmp64 */
284 unsigned long long a
, b
;
286 printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
290 /* fixme: see comment for cfcmps. */
292 a
= mv_getReg64int (SRC1_REG
);
293 b
= mv_getReg64int (SRC2_REG
);
295 res
= mv_getReg64int (SRC1_REG
) - mv_getReg64int (SRC2_REG
);
301 v
= ((NEG64 (a
) && POS64 (b
) && POS64 (res
))
302 || (POS64 (a
) && NEG64 (b
) && NEG64 (res
)));
304 c
= (NEG64 (a
) && POS64 (b
) ||
305 (NEG64 (a
) && POS64 (res
)) || (POS64 (b
) && POS64 (res
)));
307 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
312 fprintf (stderr
, "unknown opcode in DSPMRC5 0x%x\n", instr
);
313 cirrus_not_implemented ("unknown");
321 DSPMRC6 (ARMul_State
* state ATTRIBUTE_UNUSED
,
322 unsigned type ATTRIBUTE_UNUSED
,
328 case 0: /* cfmval32 */
329 cirrus_not_implemented ("cfmval32");
332 case 1: /* cfmvam32 */
333 cirrus_not_implemented ("cfmvam32");
336 case 2: /* cfmvah32 */
337 cirrus_not_implemented ("cfmvah32");
340 case 3: /* cfmva32 */
341 cirrus_not_implemented ("cfmva32");
344 case 4: /* cfmva64 */
345 cirrus_not_implemented ("cfmva64");
348 case 5: /* cfmvsc32 */
349 cirrus_not_implemented ("cfmvsc32");
353 fprintf (stderr
, "unknown opcode in DSPMRC6 0x%x\n", instr
);
354 cirrus_not_implemented ("unknown");
362 DSPMCR4 (ARMul_State
* state
,
363 unsigned type ATTRIBUTE_UNUSED
,
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
;
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
;
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
;
390 fprintf (stderr
, "unknown opcode in DSPMCR4 0x%x\n", instr
);
391 cirrus_not_implemented ("unknown");
399 DSPMCR5 (ARMul_State
* state
,
400 unsigned type ATTRIBUTE_UNUSED
,
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
;
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",
425 DSPregs
[SRC1_REG
].upper
.i
= (int) value
;
428 case 2: /* cfrshl32 */
429 printfdbg ("cfrshl32\n");
432 DSPregs
[SRC2_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
<< value
;
434 DSPregs
[SRC2_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
>> -value
;
437 case 3: /* cfrshl64 */
438 printfdbg ("cfrshl64\n");
441 mv_setReg64int (SRC2_REG
, mv_getReg64int (SRC1_REG
) << value
);
443 mv_setReg64int (SRC2_REG
, mv_getReg64int (SRC1_REG
) >> -value
);
447 fprintf (stderr
, "unknown opcode in DSPMCR5 0x%x\n", instr
);
448 cirrus_not_implemented ("unknown");
456 DSPMCR6 (ARMul_State
* state
,
457 unsigned type ATTRIBUTE_UNUSED
,
463 case 0: /* cfmv32al */
464 cirrus_not_implemented ("cfmv32al");
467 case 1: /* cfmv32am */
468 cirrus_not_implemented ("cfmv32am");
471 case 2: /* cfmv32ah */
472 cirrus_not_implemented ("cfmv32ah");
475 case 3: /* cfmv32a */
476 cirrus_not_implemented ("cfmv32a");
479 case 4: /* cfmv64a */
480 cirrus_not_implemented ("cfmv64a");
483 case 5: /* cfmv32sc */
484 cirrus_not_implemented ("cfmv32sc");
488 fprintf (stderr
, "unknown opcode in DSPMCR6 0x%x\n", instr
);
489 cirrus_not_implemented ("unknown");
497 DSPLDC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
502 static unsigned words
;
504 if (type
!= ARMul_DATA
)
511 { /* it's a long access, get two words */
514 printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
515 data
, words
, state
->bigendSig
, DEST_REG
);
519 if (state
->bigendSig
)
520 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
522 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
526 if (state
->bigendSig
)
527 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
529 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
536 printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG
,
537 mv_getRegDouble (DEST_REG
));
546 /* Get just one word. */
549 printfdbg ("cfldrs\n");
551 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
553 printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG
,
554 DSPregs
[DEST_REG
].upper
.f
);
561 DSPLDC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
566 static unsigned words
;
568 if (type
!= ARMul_DATA
)
576 /* It's a long access, get two words. */
579 printfdbg ("cfldr64: %d\n", data
);
583 if (state
->bigendSig
)
584 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
586 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
590 if (state
->bigendSig
)
591 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
593 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
600 printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG
,
601 mv_getReg64int (DEST_REG
));
610 /* Get just one word. */
613 printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG
, (int) data
);
615 /* 32bit ints should be sign extended to 64bits when loaded. */
616 mv_setReg64int (DEST_REG
, (long long) data
);
623 DSPSTC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
628 static unsigned words
;
630 if (type
!= ARMul_DATA
)
638 /* It's a long access, get two words. */
640 printfdbg ("cfstrd\n");
644 if (state
->bigendSig
)
645 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
647 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
651 if (state
->bigendSig
)
652 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
654 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
661 printfdbg ("\tmem = mvd%d = %g\n", DEST_REG
,
662 mv_getRegDouble (DEST_REG
));
671 /* Get just one word. */
673 printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG
,
674 DSPregs
[DEST_REG
].upper
.f
);
676 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
683 DSPSTC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
688 static unsigned words
;
690 if (type
!= ARMul_DATA
)
698 /* It's a long access, store two words. */
700 printfdbg ("cfstr64\n");
704 if (state
->bigendSig
)
705 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
707 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
711 if (state
->bigendSig
)
712 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
714 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
721 printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG
,
722 mv_getReg64int (DEST_REG
));
731 /* Store just one word. */
733 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
735 printfdbg ("cfstr32 MEM = %d\n", (int) *data
);
742 DSPCDP4 (ARMul_State
* state
,
748 opcode2
= BITS (5,7);
750 switch (BITS (20,21))
756 printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
759 DSPregs
[SRC1_REG
].upper
.f
);
760 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
;
764 printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
767 mv_getRegDouble (SRC1_REG
));
768 mv_setRegDouble (DEST_REG
, mv_getRegDouble (SRC1_REG
));
771 case 2: /* cfcvtds */
772 printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
775 (float) mv_getRegDouble (SRC1_REG
));
776 DSPregs
[DEST_REG
].upper
.f
= (float) mv_getRegDouble (SRC1_REG
);
779 case 3: /* cfcvtsd */
780 printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
783 (double) DSPregs
[SRC1_REG
].upper
.f
);
784 mv_setRegDouble (DEST_REG
, (double) DSPregs
[SRC1_REG
].upper
.f
);
787 case 4: /* cfcvt32s */
788 printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
791 (float) DSPregs
[SRC1_REG
].lower
.i
);
792 DSPregs
[DEST_REG
].upper
.f
= (float) DSPregs
[SRC1_REG
].lower
.i
;
795 case 5: /* cfcvt32d */
796 printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
799 (double) DSPregs
[SRC1_REG
].lower
.i
);
800 mv_setRegDouble (DEST_REG
, (double) DSPregs
[SRC1_REG
].lower
.i
);
803 case 6: /* cfcvt64s */
804 printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
807 (float) mv_getReg64int (SRC1_REG
));
808 DSPregs
[DEST_REG
].upper
.f
= (float) mv_getReg64int (SRC1_REG
);
811 case 7: /* cfcvt64d */
812 printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
815 (double) mv_getReg64int (SRC1_REG
));
816 mv_setRegDouble (DEST_REG
, (double) mv_getReg64int (SRC1_REG
));
825 printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
828 DSPregs
[SRC1_REG
].upper
.f
* DSPregs
[SRC2_REG
].upper
.f
);
830 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
831 * DSPregs
[SRC2_REG
].upper
.f
;
835 printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
838 mv_getRegDouble (SRC1_REG
) * mv_getRegDouble (SRC2_REG
));
840 mv_setRegDouble (DEST_REG
,
841 mv_getRegDouble (SRC1_REG
)
842 * mv_getRegDouble (SRC2_REG
));
846 fprintf (stderr
, "unknown opcode in DSPCDP4 0x%x\n", instr
);
847 cirrus_not_implemented ("unknown");
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",
862 DSPregs
[DEST_REG
].upper
.f
);
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",
873 mv_getRegDouble (DEST_REG
));
877 DSPregs
[DEST_REG
].upper
.f
= -DSPregs
[SRC1_REG
].upper
.f
;
878 printfdbg ("cfnegs mvf%d = -mvf%d = %f\n",
881 DSPregs
[DEST_REG
].upper
.f
);
885 mv_setRegDouble (DEST_REG
,
886 -mv_getRegDouble (SRC1_REG
));
887 printfdbg ("cfnegd mvd%d = -mvd%d = %g\n",
889 mv_getRegDouble (DEST_REG
));
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",
899 DSPregs
[DEST_REG
].upper
.f
);
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",
910 mv_getRegDouble (DEST_REG
));
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",
920 DSPregs
[DEST_REG
].upper
.f
);
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",
931 mv_getRegDouble (DEST_REG
));
937 fprintf (stderr
, "unknown opcode in DSPCDP4 0x%x\n", instr
);
938 cirrus_not_implemented ("unknown");
946 DSPCDP5 (ARMul_State
* state
,
953 opcode2
= BITS (5,7);
955 /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */
956 shift
= BITS (0, 3) | (BITS (5, 7)) << 4;
960 switch (BITS (20,21))
964 printfdbg ("cfsh32 %s amount=%d\n", shift
< 0 ? "right" : "left",
967 /* Negative shift is a right shift. */
968 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
>> -shift
;
970 /* Positive shift is a left shift. */
971 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
<< shift
;
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",
984 DSPregs
[DEST_REG
].lower
.i
);
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",
995 mv_getReg64int (DEST_REG
));
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",
1005 DSPregs
[DEST_REG
].lower
.i
);
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",
1015 DSPregs
[DEST_REG
].lower
.i
);
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",
1024 DSPregs
[DEST_REG
].lower
.i
);
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",
1033 DSPregs
[DEST_REG
].lower
.i
);
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",
1041 DSPregs
[DEST_REG
].lower
.i
);
1044 case 7: /* cftruncd32 */
1045 DSPregs
[DEST_REG
].lower
.i
= (int) mv_getRegDouble (SRC1_REG
);
1046 printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
1049 DSPregs
[DEST_REG
].lower
.i
);
1056 printfdbg ("cfsh64\n");
1059 /* Negative shift is a right shift. */
1060 mv_setReg64int (DEST_REG
,
1061 mv_getReg64int (SRC1_REG
) >> -shift
);
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
));
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",
1079 DSPregs
[DEST_REG
].lower
.i
);
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",
1091 mv_getReg64int (DEST_REG
));
1094 case 2: /* cfneg32 */
1095 DSPregs
[DEST_REG
].lower
.i
= -DSPregs
[SRC1_REG
].lower
.i
;
1096 printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
1100 DSPregs
[DEST_REG
].lower
.i
);
1103 case 3: /* cfneg64 */
1104 mv_setReg64int (DEST_REG
, -mv_getReg64int (SRC1_REG
));
1105 printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
1109 mv_getReg64int (DEST_REG
));
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",
1119 DSPregs
[DEST_REG
].lower
.i
);
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",
1130 mv_getReg64int (DEST_REG
));
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",
1140 DSPregs
[DEST_REG
].lower
.i
);
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",
1151 mv_getReg64int (DEST_REG
));
1157 fprintf (stderr
, "unknown opcode in DSPCDP5 0x%x\n", instr
);
1158 cirrus_not_implemented ("unknown");
1166 DSPCDP6 (ARMul_State
* state
,
1172 opcode2
= BITS (5,7);
1174 switch (BITS (20,21))
1178 cirrus_not_implemented ("cfmadd32");
1183 cirrus_not_implemented ("cfmsub32");
1188 cirrus_not_implemented ("cfmadda32");
1193 cirrus_not_implemented ("cfmsuba32");
1197 fprintf (stderr
, "unknown opcode in DSPCDP6 0x%x\n", instr
);
1203 /* Conversion functions.
1205 32-bit integers are stored in the LOWER half of a 64-bit physical
1208 Single precision floats are stored in the UPPER half of a 64-bit
1209 physical register. */
1212 mv_getRegDouble (int regnum
)
1214 reg_conv
.ints
[lsw_float_index
] = DSPregs
[regnum
].upper
.i
;
1215 reg_conv
.ints
[msw_float_index
] = DSPregs
[regnum
].lower
.i
;
1220 mv_setRegDouble (int regnum
, double val
)
1223 DSPregs
[regnum
].upper
.i
= reg_conv
.ints
[lsw_float_index
];
1224 DSPregs
[regnum
].lower
.i
= reg_conv
.ints
[msw_float_index
];
1228 mv_getReg64int (int regnum
)
1230 reg_conv
.ints
[lsw_int_index
] = DSPregs
[regnum
].lower
.i
;
1231 reg_conv
.ints
[msw_int_index
] = DSPregs
[regnum
].upper
.i
;
1236 mv_setReg64int (int regnum
, long long val
)
1239 DSPregs
[regnum
].lower
.i
= reg_conv
.ints
[lsw_int_index
];
1240 DSPregs
[regnum
].upper
.i
= reg_conv
.ints
[msw_int_index
];
1243 /* Compute LSW in a double and a long long. */
1246 mv_compute_host_endianness (ARMul_State
* state
)
1258 /* Calculate where's the LSW in a 64bit int. */
1261 if (conv
.ints
[0] == 0)
1268 assert (conv
.ints
[1] == 0);
1273 /* Calculate where's the LSW in a double. */
1276 if (conv
.ints
[0] == 0)
1278 msw_float_index
= 0;
1279 lsw_float_index
= 1;
1283 assert (conv
.ints
[1] == 0);
1284 msw_float_index
= 1;
1285 lsw_float_index
= 0;
1288 printfdbg ("lsw_int_index %d\n", lsw_int_index
);
1289 printfdbg ("lsw_float_index %d\n", lsw_float_index
);