1 /* maverick.c -- Cirrus/DSP co-processor interface.
2 Copyright (C) 2003-2024 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/>. */
18 /* This must come before any other includes. */
27 /*#define CIRRUS_DEBUG 1 */
29 # define printfdbg printf
31 # define printfdbg printf_nothing
34 #define POS64(i) ( (~(i)) >> 63 )
35 #define NEG64(i) ( (i) >> 63 )
37 /* These variables are defined here and made extern in maverick.h for use
39 Eventually the simulator should be made to handle any coprocessor at run
41 struct maverick_regs DSPregs
[16];
42 union maverick_acc_regs DSPacc
[4];
45 #define DEST_REG (BITS (12, 15))
46 #define SRC1_REG (BITS (16, 19))
47 #define SRC2_REG (BITS (0, 3))
49 static int lsw_int_index
, msw_int_index
;
50 static int lsw_float_index
, msw_float_index
;
52 static double mv_getRegDouble (int);
53 static long long mv_getReg64int (int);
54 static void mv_setRegDouble (int, double val
);
55 static void mv_setReg64int (int, long long val
);
65 printf_nothing (void * foo
, ...)
70 cirrus_not_implemented (char * insn
)
72 fprintf (stderr
, "Cirrus instruction '%s' not implemented.\n", insn
);
73 fprintf (stderr
, "aborting!\n");
79 DSPMRC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
80 unsigned type ATTRIBUTE_UNUSED
,
87 /* Move lower half of a DF stored in a DSP reg into an Arm reg. */
88 printfdbg ("cfmvrdl\n");
89 printfdbg ("\tlower half=0x%x\n", DSPregs
[SRC1_REG
].lower
.i
);
90 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG
));
92 *value
= (ARMword
) DSPregs
[SRC1_REG
].lower
.i
;
96 /* Move upper half of a DF stored in a DSP reg into an Arm reg. */
97 printfdbg ("cfmvrdh\n");
98 printfdbg ("\tupper half=0x%x\n", DSPregs
[SRC1_REG
].upper
.i
);
99 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG
));
101 *value
= (ARMword
) DSPregs
[SRC1_REG
].upper
.i
;
105 /* Move SF from upper half of a DSP register to an Arm register. */
106 *value
= (ARMword
) DSPregs
[SRC1_REG
].upper
.i
;
107 printfdbg ("cfmvrs = mvf%d <-- %f\n",
109 DSPregs
[SRC1_REG
].upper
.f
);
118 a
= DSPregs
[SRC1_REG
].upper
.f
;
119 b
= DSPregs
[SRC2_REG
].upper
.f
;
121 printfdbg ("cfcmps\n");
122 printfdbg ("\tcomparing %f and %f\n", a
, b
);
124 z
= a
== b
; /* zero */
125 n
= a
!= b
; /* negative */
126 v
= a
> b
; /* overflow */
128 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
137 a
= mv_getRegDouble (SRC1_REG
);
138 b
= mv_getRegDouble (SRC2_REG
);
140 printfdbg ("cfcmpd\n");
141 printfdbg ("\tcomparing %g and %g\n", a
, b
);
143 z
= a
== b
; /* zero */
144 n
= a
!= b
; /* negative */
145 v
= a
> b
; /* overflow */
147 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
156 a
= DSPregs
[SRC1_REG
].upper
.f
;
157 b
= DSPregs
[SRC2_REG
].upper
.f
;
159 printfdbg ("cfcmps\n");
160 printfdbg ("\tcomparing %f and %f\n", a
, b
);
162 z
= a
== b
; /* zero */
163 n
= a
< b
; /* negative */
164 c
= a
> b
; /* carry */
166 printfdbg ("\tz = %d, n = %d\n", z
, n
);
167 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
176 a
= mv_getRegDouble (SRC1_REG
);
177 b
= mv_getRegDouble (SRC2_REG
);
179 printfdbg ("cfcmpd\n");
180 printfdbg ("\tcomparing %g and %g\n", a
, b
);
182 z
= a
== b
; /* zero */
183 n
= a
< b
; /* negative */
184 c
= a
> b
; /* carry */
186 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
191 fprintf (stderr
, "unknown opcode in DSPMRC4 0x%x\n", instr
);
192 cirrus_not_implemented ("unknown");
200 DSPMRC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
201 unsigned type ATTRIBUTE_UNUSED
,
207 case 0: /* cfmvr64l */
208 /* Move lower half of 64bit int from Cirrus to Arm. */
209 *value
= (ARMword
) DSPregs
[SRC1_REG
].lower
.i
;
210 printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n",
215 case 1: /* cfmvr64h */
216 /* Move upper half of 64bit int from Cirrus to Arm. */
217 *value
= (ARMword
) DSPregs
[SRC1_REG
].upper
.i
;
218 printfdbg ("cfmvr64h <-- %d\n", (int) *value
);
221 case 4: /* cfcmp32 */
227 printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
231 /* FIXME: see comment for cfcmps. */
232 a
= DSPregs
[SRC1_REG
].lower
.i
;
233 b
= DSPregs
[SRC2_REG
].lower
.i
;
235 res
= DSPregs
[SRC1_REG
].lower
.i
- DSPregs
[SRC2_REG
].lower
.i
;
241 v
= SubOverflow (DSPregs
[SRC1_REG
].lower
.i
, DSPregs
[SRC2_REG
].lower
.i
,
244 c
= (NEG (a
) && POS (b
))
245 || (NEG (a
) && POS (res
))
246 || (POS (b
) && POS (res
));
248 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
252 case 5: /* cfcmp64 */
256 unsigned long long a
, b
;
258 printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
262 /* fixme: see comment for cfcmps. */
264 a
= mv_getReg64int (SRC1_REG
);
265 b
= mv_getReg64int (SRC2_REG
);
267 res
= mv_getReg64int (SRC1_REG
) - mv_getReg64int (SRC2_REG
);
273 v
= ((NEG64 (a
) && POS64 (b
) && POS64 (res
))
274 || (POS64 (a
) && NEG64 (b
) && NEG64 (res
)));
276 c
= (NEG64 (a
) && POS64 (b
))
277 || (NEG64 (a
) && POS64 (res
))
278 || (POS64 (b
) && POS64 (res
));
280 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
285 fprintf (stderr
, "unknown opcode in DSPMRC5 0x%x\n", instr
);
286 cirrus_not_implemented ("unknown");
294 DSPMRC6 (ARMul_State
* state ATTRIBUTE_UNUSED
,
295 unsigned type ATTRIBUTE_UNUSED
,
301 case 0: /* cfmval32 */
302 cirrus_not_implemented ("cfmval32");
305 case 1: /* cfmvam32 */
306 cirrus_not_implemented ("cfmvam32");
309 case 2: /* cfmvah32 */
310 cirrus_not_implemented ("cfmvah32");
313 case 3: /* cfmva32 */
314 cirrus_not_implemented ("cfmva32");
317 case 4: /* cfmva64 */
318 cirrus_not_implemented ("cfmva64");
321 case 5: /* cfmvsc32 */
322 cirrus_not_implemented ("cfmvsc32");
326 fprintf (stderr
, "unknown opcode in DSPMRC6 0x%x\n", instr
);
327 cirrus_not_implemented ("unknown");
335 DSPMCR4 (ARMul_State
* state
,
336 unsigned type ATTRIBUTE_UNUSED
,
342 case 0: /* cfmvdlr */
343 /* Move the lower half of a DF value from an Arm register into
344 the lower half of a Cirrus register. */
345 printfdbg ("cfmvdlr <-- 0x%x\n", (int) value
);
346 DSPregs
[SRC1_REG
].lower
.i
= (int) value
;
349 case 1: /* cfmvdhr */
350 /* Move the upper half of a DF value from an Arm register into
351 the upper half of a Cirrus register. */
352 printfdbg ("cfmvdhr <-- 0x%x\n", (int) value
);
353 DSPregs
[SRC1_REG
].upper
.i
= (int) value
;
357 /* Move SF from Arm register into upper half of Cirrus register. */
358 printfdbg ("cfmvsr <-- 0x%x\n", (int) value
);
359 DSPregs
[SRC1_REG
].upper
.i
= (int) value
;
363 fprintf (stderr
, "unknown opcode in DSPMCR4 0x%x\n", instr
);
364 cirrus_not_implemented ("unknown");
372 DSPMCR5 (ARMul_State
* state
,
373 unsigned type ATTRIBUTE_UNUSED
,
385 case 0: /* cfmv64lr */
386 /* Move lower half of a 64bit int from an ARM register into the
387 lower half of a DSP register and sign extend it. */
388 printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG
, (int) value
);
389 DSPregs
[SRC1_REG
].lower
.i
= (int) value
;
392 case 1: /* cfmv64hr */
393 /* Move upper half of a 64bit int from an ARM register into the
394 upper half of a DSP register. */
395 printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n",
398 DSPregs
[SRC1_REG
].upper
.i
= (int) value
;
401 case 2: /* cfrshl32 */
402 printfdbg ("cfrshl32\n");
405 DSPregs
[SRC2_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
<< value
;
407 DSPregs
[SRC2_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
>> -value
;
410 case 3: /* cfrshl64 */
411 printfdbg ("cfrshl64\n");
414 mv_setReg64int (SRC2_REG
, mv_getReg64int (SRC1_REG
) << value
);
416 mv_setReg64int (SRC2_REG
, mv_getReg64int (SRC1_REG
) >> -value
);
420 fprintf (stderr
, "unknown opcode in DSPMCR5 0x%x\n", instr
);
421 cirrus_not_implemented ("unknown");
429 DSPMCR6 (ARMul_State
* state
,
430 unsigned type ATTRIBUTE_UNUSED
,
436 case 0: /* cfmv32al */
437 cirrus_not_implemented ("cfmv32al");
440 case 1: /* cfmv32am */
441 cirrus_not_implemented ("cfmv32am");
444 case 2: /* cfmv32ah */
445 cirrus_not_implemented ("cfmv32ah");
448 case 3: /* cfmv32a */
449 cirrus_not_implemented ("cfmv32a");
452 case 4: /* cfmv64a */
453 cirrus_not_implemented ("cfmv64a");
456 case 5: /* cfmv32sc */
457 cirrus_not_implemented ("cfmv32sc");
461 fprintf (stderr
, "unknown opcode in DSPMCR6 0x%x\n", instr
);
462 cirrus_not_implemented ("unknown");
470 DSPLDC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
475 static unsigned words
;
477 if (type
!= ARMul_DATA
)
484 { /* it's a long access, get two words */
487 printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
488 data
, words
, state
->bigendSig
, DEST_REG
);
492 if (state
->bigendSig
)
493 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
495 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
499 if (state
->bigendSig
)
500 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
502 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
509 printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG
,
510 mv_getRegDouble (DEST_REG
));
519 /* Get just one word. */
522 printfdbg ("cfldrs\n");
524 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
526 printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG
,
527 DSPregs
[DEST_REG
].upper
.f
);
534 DSPLDC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
539 static unsigned words
;
541 if (type
!= ARMul_DATA
)
549 /* It's a long access, get two words. */
552 printfdbg ("cfldr64: %d\n", data
);
556 if (state
->bigendSig
)
557 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
559 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
563 if (state
->bigendSig
)
564 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
566 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
573 printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG
,
574 mv_getReg64int (DEST_REG
));
583 /* Get just one word. */
586 printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG
, (int) data
);
588 /* 32bit ints should be sign extended to 64bits when loaded. */
589 mv_setReg64int (DEST_REG
, (long long) data
);
596 DSPSTC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
601 static unsigned words
;
603 if (type
!= ARMul_DATA
)
611 /* It's a long access, get two words. */
613 printfdbg ("cfstrd\n");
617 if (state
->bigendSig
)
618 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
620 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
624 if (state
->bigendSig
)
625 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
627 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
634 printfdbg ("\tmem = mvd%d = %g\n", DEST_REG
,
635 mv_getRegDouble (DEST_REG
));
644 /* Get just one word. */
646 printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG
,
647 DSPregs
[DEST_REG
].upper
.f
);
649 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
656 DSPSTC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
661 static unsigned words
;
663 if (type
!= ARMul_DATA
)
671 /* It's a long access, store two words. */
673 printfdbg ("cfstr64\n");
677 if (state
->bigendSig
)
678 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
680 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
684 if (state
->bigendSig
)
685 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
687 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
694 printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG
,
695 mv_getReg64int (DEST_REG
));
704 /* Store just one word. */
706 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
708 printfdbg ("cfstr32 MEM = %d\n", (int) *data
);
715 DSPCDP4 (ARMul_State
* state
,
721 opcode2
= BITS (5,7);
723 switch (BITS (20,21))
729 printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
732 DSPregs
[SRC1_REG
].upper
.f
);
733 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
;
737 printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
740 mv_getRegDouble (SRC1_REG
));
741 mv_setRegDouble (DEST_REG
, mv_getRegDouble (SRC1_REG
));
744 case 2: /* cfcvtds */
745 printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
748 (float) mv_getRegDouble (SRC1_REG
));
749 DSPregs
[DEST_REG
].upper
.f
= (float) mv_getRegDouble (SRC1_REG
);
752 case 3: /* cfcvtsd */
753 printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
756 (double) DSPregs
[SRC1_REG
].upper
.f
);
757 mv_setRegDouble (DEST_REG
, (double) DSPregs
[SRC1_REG
].upper
.f
);
760 case 4: /* cfcvt32s */
761 printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
764 (float) DSPregs
[SRC1_REG
].lower
.i
);
765 DSPregs
[DEST_REG
].upper
.f
= (float) DSPregs
[SRC1_REG
].lower
.i
;
768 case 5: /* cfcvt32d */
769 printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
772 (double) DSPregs
[SRC1_REG
].lower
.i
);
773 mv_setRegDouble (DEST_REG
, (double) DSPregs
[SRC1_REG
].lower
.i
);
776 case 6: /* cfcvt64s */
777 printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
780 (float) mv_getReg64int (SRC1_REG
));
781 DSPregs
[DEST_REG
].upper
.f
= (float) mv_getReg64int (SRC1_REG
);
784 case 7: /* cfcvt64d */
785 printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
788 (double) mv_getReg64int (SRC1_REG
));
789 mv_setRegDouble (DEST_REG
, (double) mv_getReg64int (SRC1_REG
));
798 printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
801 DSPregs
[SRC1_REG
].upper
.f
* DSPregs
[SRC2_REG
].upper
.f
);
803 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
804 * DSPregs
[SRC2_REG
].upper
.f
;
808 printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
811 mv_getRegDouble (SRC1_REG
) * mv_getRegDouble (SRC2_REG
));
813 mv_setRegDouble (DEST_REG
,
814 mv_getRegDouble (SRC1_REG
)
815 * mv_getRegDouble (SRC2_REG
));
819 fprintf (stderr
, "unknown opcode in DSPCDP4 0x%x\n", instr
);
820 cirrus_not_implemented ("unknown");
829 DSPregs
[DEST_REG
].upper
.f
= (DSPregs
[SRC1_REG
].upper
.f
< 0.0F
?
830 -DSPregs
[SRC1_REG
].upper
.f
831 : DSPregs
[SRC1_REG
].upper
.f
);
832 printfdbg ("cfabss mvf%d = |mvf%d| = %f\n",
835 DSPregs
[DEST_REG
].upper
.f
);
839 mv_setRegDouble (DEST_REG
,
840 (mv_getRegDouble (SRC1_REG
) < 0.0 ?
841 -mv_getRegDouble (SRC1_REG
)
842 : mv_getRegDouble (SRC1_REG
)));
843 printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n",
846 mv_getRegDouble (DEST_REG
));
850 DSPregs
[DEST_REG
].upper
.f
= -DSPregs
[SRC1_REG
].upper
.f
;
851 printfdbg ("cfnegs mvf%d = -mvf%d = %f\n",
854 DSPregs
[DEST_REG
].upper
.f
);
858 mv_setRegDouble (DEST_REG
,
859 -mv_getRegDouble (SRC1_REG
));
860 printfdbg ("cfnegd mvd%d = -mvd%d = %g\n",
862 mv_getRegDouble (DEST_REG
));
866 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
867 + DSPregs
[SRC2_REG
].upper
.f
;
868 printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n",
872 DSPregs
[DEST_REG
].upper
.f
);
876 mv_setRegDouble (DEST_REG
,
877 mv_getRegDouble (SRC1_REG
)
878 + mv_getRegDouble (SRC2_REG
));
879 printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n",
883 mv_getRegDouble (DEST_REG
));
887 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
888 - DSPregs
[SRC2_REG
].upper
.f
;
889 printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n",
893 DSPregs
[DEST_REG
].upper
.f
);
897 mv_setRegDouble (DEST_REG
,
898 mv_getRegDouble (SRC1_REG
)
899 - mv_getRegDouble (SRC2_REG
));
900 printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n",
904 mv_getRegDouble (DEST_REG
));
910 fprintf (stderr
, "unknown opcode in DSPCDP4 0x%x\n", instr
);
911 cirrus_not_implemented ("unknown");
919 DSPCDP5 (ARMul_State
* state
,
926 opcode2
= BITS (5,7);
928 /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */
929 shift
= BITS (0, 3) | (BITS (5, 7)) << 4;
933 switch (BITS (20,21))
937 printfdbg ("cfsh32 %s amount=%d\n", shift
< 0 ? "right" : "left",
940 /* Negative shift is a right shift. */
941 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
>> -shift
;
943 /* Positive shift is a left shift. */
944 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
<< shift
;
950 case 0: /* cfmul32 */
951 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
952 * DSPregs
[SRC2_REG
].lower
.i
;
953 printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n",
957 DSPregs
[DEST_REG
].lower
.i
);
960 case 1: /* cfmul64 */
961 mv_setReg64int (DEST_REG
,
962 mv_getReg64int (SRC1_REG
)
963 * mv_getReg64int (SRC2_REG
));
964 printfdbg ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n",
968 mv_getReg64int (DEST_REG
));
971 case 2: /* cfmac32 */
972 DSPregs
[DEST_REG
].lower
.i
973 += DSPregs
[SRC1_REG
].lower
.i
* DSPregs
[SRC2_REG
].lower
.i
;
974 printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n",
978 DSPregs
[DEST_REG
].lower
.i
);
981 case 3: /* cfmsc32 */
982 DSPregs
[DEST_REG
].lower
.i
983 -= DSPregs
[SRC1_REG
].lower
.i
* DSPregs
[SRC2_REG
].lower
.i
;
984 printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n",
988 DSPregs
[DEST_REG
].lower
.i
);
991 case 4: /* cfcvts32 */
992 /* fixme: this should round */
993 DSPregs
[DEST_REG
].lower
.i
= (int) DSPregs
[SRC1_REG
].upper
.f
;
994 printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n",
997 DSPregs
[DEST_REG
].lower
.i
);
1000 case 5: /* cfcvtd32 */
1001 /* fixme: this should round */
1002 DSPregs
[DEST_REG
].lower
.i
= (int) mv_getRegDouble (SRC1_REG
);
1003 printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n",
1006 DSPregs
[DEST_REG
].lower
.i
);
1009 case 6: /* cftruncs32 */
1010 DSPregs
[DEST_REG
].lower
.i
= (int) DSPregs
[SRC1_REG
].upper
.f
;
1011 printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n",
1014 DSPregs
[DEST_REG
].lower
.i
);
1017 case 7: /* cftruncd32 */
1018 DSPregs
[DEST_REG
].lower
.i
= (int) mv_getRegDouble (SRC1_REG
);
1019 printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
1022 DSPregs
[DEST_REG
].lower
.i
);
1029 printfdbg ("cfsh64\n");
1032 /* Negative shift is a right shift. */
1033 mv_setReg64int (DEST_REG
,
1034 mv_getReg64int (SRC1_REG
) >> -shift
);
1036 /* Positive shift is a left shift. */
1037 mv_setReg64int (DEST_REG
,
1038 mv_getReg64int (SRC1_REG
) << shift
);
1039 printfdbg ("\t%llx\n", mv_getReg64int(DEST_REG
));
1045 case 0: /* cfabs32 */
1046 DSPregs
[DEST_REG
].lower
.i
= (DSPregs
[SRC1_REG
].lower
.i
< 0
1047 ? -DSPregs
[SRC1_REG
].lower
.i
: DSPregs
[SRC1_REG
].lower
.i
);
1048 printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n",
1052 DSPregs
[DEST_REG
].lower
.i
);
1055 case 1: /* cfabs64 */
1056 mv_setReg64int (DEST_REG
,
1057 (mv_getReg64int (SRC1_REG
) < 0
1058 ? -mv_getReg64int (SRC1_REG
)
1059 : mv_getReg64int (SRC1_REG
)));
1060 printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n",
1064 mv_getReg64int (DEST_REG
));
1067 case 2: /* cfneg32 */
1068 DSPregs
[DEST_REG
].lower
.i
= -DSPregs
[SRC1_REG
].lower
.i
;
1069 printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
1073 DSPregs
[DEST_REG
].lower
.i
);
1076 case 3: /* cfneg64 */
1077 mv_setReg64int (DEST_REG
, -mv_getReg64int (SRC1_REG
));
1078 printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
1082 mv_getReg64int (DEST_REG
));
1085 case 4: /* cfadd32 */
1086 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
1087 + DSPregs
[SRC2_REG
].lower
.i
;
1088 printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n",
1092 DSPregs
[DEST_REG
].lower
.i
);
1095 case 5: /* cfadd64 */
1096 mv_setReg64int (DEST_REG
,
1097 mv_getReg64int (SRC1_REG
)
1098 + mv_getReg64int (SRC2_REG
));
1099 printfdbg ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n",
1103 mv_getReg64int (DEST_REG
));
1106 case 6: /* cfsub32 */
1107 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
1108 - DSPregs
[SRC2_REG
].lower
.i
;
1109 printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n",
1113 DSPregs
[DEST_REG
].lower
.i
);
1116 case 7: /* cfsub64 */
1117 mv_setReg64int (DEST_REG
,
1118 mv_getReg64int (SRC1_REG
)
1119 - mv_getReg64int (SRC2_REG
));
1120 printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n",
1124 mv_getReg64int (DEST_REG
));
1130 fprintf (stderr
, "unknown opcode in DSPCDP5 0x%x\n", instr
);
1131 cirrus_not_implemented ("unknown");
1139 DSPCDP6 (ARMul_State
* state
,
1143 switch (BITS (20,21))
1147 cirrus_not_implemented ("cfmadd32");
1152 cirrus_not_implemented ("cfmsub32");
1157 cirrus_not_implemented ("cfmadda32");
1162 cirrus_not_implemented ("cfmsuba32");
1166 fprintf (stderr
, "unknown opcode in DSPCDP6 0x%x\n", instr
);
1172 /* Conversion functions.
1174 32-bit integers are stored in the LOWER half of a 64-bit physical
1177 Single precision floats are stored in the UPPER half of a 64-bit
1178 physical register. */
1181 mv_getRegDouble (int regnum
)
1183 reg_conv
.ints
[lsw_float_index
] = DSPregs
[regnum
].upper
.i
;
1184 reg_conv
.ints
[msw_float_index
] = DSPregs
[regnum
].lower
.i
;
1189 mv_setRegDouble (int regnum
, double val
)
1192 DSPregs
[regnum
].upper
.i
= reg_conv
.ints
[lsw_float_index
];
1193 DSPregs
[regnum
].lower
.i
= reg_conv
.ints
[msw_float_index
];
1197 mv_getReg64int (int regnum
)
1199 reg_conv
.ints
[lsw_int_index
] = DSPregs
[regnum
].lower
.i
;
1200 reg_conv
.ints
[msw_int_index
] = DSPregs
[regnum
].upper
.i
;
1205 mv_setReg64int (int regnum
, long long val
)
1208 DSPregs
[regnum
].lower
.i
= reg_conv
.ints
[lsw_int_index
];
1209 DSPregs
[regnum
].upper
.i
= reg_conv
.ints
[msw_int_index
];