1 /* maverick.c -- Cirrus/DSP co-processor interface.
2 Copyright (C) 2003-2021 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/>. */
24 /*#define CIRRUS_DEBUG 1 */
26 # define printfdbg printf
28 # define printfdbg printf_nothing
31 #define POS64(i) ( (~(i)) >> 63 )
32 #define NEG64(i) ( (i) >> 63 )
34 /* These variables are defined here and made extern in maverick.h for use
36 Eventually the simulator should be made to handle any coprocessor at run
38 struct maverick_regs DSPregs
[16];
39 union maverick_acc_regs DSPacc
[4];
42 #define DEST_REG (BITS (12, 15))
43 #define SRC1_REG (BITS (16, 19))
44 #define SRC2_REG (BITS (0, 3))
46 static int lsw_int_index
, msw_int_index
;
47 static int lsw_float_index
, msw_float_index
;
49 static double mv_getRegDouble (int);
50 static long long mv_getReg64int (int);
51 static void mv_setRegDouble (int, double val
);
52 static void mv_setReg64int (int, long long val
);
62 printf_nothing (void * foo
, ...)
67 cirrus_not_implemented (char * insn
)
69 fprintf (stderr
, "Cirrus instruction '%s' not implemented.\n", insn
);
70 fprintf (stderr
, "aborting!\n");
76 DSPMRC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
77 unsigned type ATTRIBUTE_UNUSED
,
84 /* Move lower half of a DF stored in a DSP reg into an Arm reg. */
85 printfdbg ("cfmvrdl\n");
86 printfdbg ("\tlower half=0x%x\n", DSPregs
[SRC1_REG
].lower
.i
);
87 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG
));
89 *value
= (ARMword
) DSPregs
[SRC1_REG
].lower
.i
;
93 /* Move upper half of a DF stored in a DSP reg into an Arm reg. */
94 printfdbg ("cfmvrdh\n");
95 printfdbg ("\tupper half=0x%x\n", DSPregs
[SRC1_REG
].upper
.i
);
96 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG
));
98 *value
= (ARMword
) DSPregs
[SRC1_REG
].upper
.i
;
102 /* Move SF from upper half of a DSP register to an Arm register. */
103 *value
= (ARMword
) DSPregs
[SRC1_REG
].upper
.i
;
104 printfdbg ("cfmvrs = mvf%d <-- %f\n",
106 DSPregs
[SRC1_REG
].upper
.f
);
115 a
= DSPregs
[SRC1_REG
].upper
.f
;
116 b
= DSPregs
[SRC2_REG
].upper
.f
;
118 printfdbg ("cfcmps\n");
119 printfdbg ("\tcomparing %f and %f\n", a
, b
);
121 z
= a
== b
; /* zero */
122 n
= a
!= b
; /* negative */
123 v
= a
> b
; /* overflow */
125 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
134 a
= mv_getRegDouble (SRC1_REG
);
135 b
= mv_getRegDouble (SRC2_REG
);
137 printfdbg ("cfcmpd\n");
138 printfdbg ("\tcomparing %g and %g\n", a
, b
);
140 z
= a
== b
; /* zero */
141 n
= a
!= b
; /* negative */
142 v
= a
> b
; /* overflow */
144 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
153 a
= DSPregs
[SRC1_REG
].upper
.f
;
154 b
= DSPregs
[SRC2_REG
].upper
.f
;
156 printfdbg ("cfcmps\n");
157 printfdbg ("\tcomparing %f and %f\n", a
, b
);
159 z
= a
== b
; /* zero */
160 n
= a
< b
; /* negative */
161 c
= a
> b
; /* carry */
163 printfdbg ("\tz = %d, n = %d\n", z
, n
);
164 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
173 a
= mv_getRegDouble (SRC1_REG
);
174 b
= mv_getRegDouble (SRC2_REG
);
176 printfdbg ("cfcmpd\n");
177 printfdbg ("\tcomparing %g and %g\n", a
, b
);
179 z
= a
== b
; /* zero */
180 n
= a
< b
; /* negative */
181 c
= a
> b
; /* carry */
183 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
188 fprintf (stderr
, "unknown opcode in DSPMRC4 0x%x\n", instr
);
189 cirrus_not_implemented ("unknown");
197 DSPMRC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
198 unsigned type ATTRIBUTE_UNUSED
,
204 case 0: /* cfmvr64l */
205 /* Move lower half of 64bit int from Cirrus to Arm. */
206 *value
= (ARMword
) DSPregs
[SRC1_REG
].lower
.i
;
207 printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n",
212 case 1: /* cfmvr64h */
213 /* Move upper half of 64bit int from Cirrus to Arm. */
214 *value
= (ARMword
) DSPregs
[SRC1_REG
].upper
.i
;
215 printfdbg ("cfmvr64h <-- %d\n", (int) *value
);
218 case 4: /* cfcmp32 */
224 printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
228 /* FIXME: see comment for cfcmps. */
229 a
= DSPregs
[SRC1_REG
].lower
.i
;
230 b
= DSPregs
[SRC2_REG
].lower
.i
;
232 res
= DSPregs
[SRC1_REG
].lower
.i
- DSPregs
[SRC2_REG
].lower
.i
;
238 v
= SubOverflow (DSPregs
[SRC1_REG
].lower
.i
, DSPregs
[SRC2_REG
].lower
.i
,
241 c
= (NEG (a
) && POS (b
))
242 || (NEG (a
) && POS (res
))
243 || (POS (b
) && POS (res
));
245 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
249 case 5: /* cfcmp64 */
253 unsigned long long a
, b
;
255 printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
259 /* fixme: see comment for cfcmps. */
261 a
= mv_getReg64int (SRC1_REG
);
262 b
= mv_getReg64int (SRC2_REG
);
264 res
= mv_getReg64int (SRC1_REG
) - mv_getReg64int (SRC2_REG
);
270 v
= ((NEG64 (a
) && POS64 (b
) && POS64 (res
))
271 || (POS64 (a
) && NEG64 (b
) && NEG64 (res
)));
273 c
= (NEG64 (a
) && POS64 (b
))
274 || (NEG64 (a
) && POS64 (res
))
275 || (POS64 (b
) && POS64 (res
));
277 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
282 fprintf (stderr
, "unknown opcode in DSPMRC5 0x%x\n", instr
);
283 cirrus_not_implemented ("unknown");
291 DSPMRC6 (ARMul_State
* state ATTRIBUTE_UNUSED
,
292 unsigned type ATTRIBUTE_UNUSED
,
298 case 0: /* cfmval32 */
299 cirrus_not_implemented ("cfmval32");
302 case 1: /* cfmvam32 */
303 cirrus_not_implemented ("cfmvam32");
306 case 2: /* cfmvah32 */
307 cirrus_not_implemented ("cfmvah32");
310 case 3: /* cfmva32 */
311 cirrus_not_implemented ("cfmva32");
314 case 4: /* cfmva64 */
315 cirrus_not_implemented ("cfmva64");
318 case 5: /* cfmvsc32 */
319 cirrus_not_implemented ("cfmvsc32");
323 fprintf (stderr
, "unknown opcode in DSPMRC6 0x%x\n", instr
);
324 cirrus_not_implemented ("unknown");
332 DSPMCR4 (ARMul_State
* state
,
333 unsigned type ATTRIBUTE_UNUSED
,
339 case 0: /* cfmvdlr */
340 /* Move the lower half of a DF value from an Arm register into
341 the lower half of a Cirrus register. */
342 printfdbg ("cfmvdlr <-- 0x%x\n", (int) value
);
343 DSPregs
[SRC1_REG
].lower
.i
= (int) value
;
346 case 1: /* cfmvdhr */
347 /* Move the upper half of a DF value from an Arm register into
348 the upper half of a Cirrus register. */
349 printfdbg ("cfmvdhr <-- 0x%x\n", (int) value
);
350 DSPregs
[SRC1_REG
].upper
.i
= (int) value
;
354 /* Move SF from Arm register into upper half of Cirrus register. */
355 printfdbg ("cfmvsr <-- 0x%x\n", (int) value
);
356 DSPregs
[SRC1_REG
].upper
.i
= (int) value
;
360 fprintf (stderr
, "unknown opcode in DSPMCR4 0x%x\n", instr
);
361 cirrus_not_implemented ("unknown");
369 DSPMCR5 (ARMul_State
* state
,
370 unsigned type ATTRIBUTE_UNUSED
,
382 case 0: /* cfmv64lr */
383 /* Move lower half of a 64bit int from an ARM register into the
384 lower half of a DSP register and sign extend it. */
385 printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG
, (int) value
);
386 DSPregs
[SRC1_REG
].lower
.i
= (int) value
;
389 case 1: /* cfmv64hr */
390 /* Move upper half of a 64bit int from an ARM register into the
391 upper half of a DSP register. */
392 printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n",
395 DSPregs
[SRC1_REG
].upper
.i
= (int) value
;
398 case 2: /* cfrshl32 */
399 printfdbg ("cfrshl32\n");
402 DSPregs
[SRC2_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
<< value
;
404 DSPregs
[SRC2_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
>> -value
;
407 case 3: /* cfrshl64 */
408 printfdbg ("cfrshl64\n");
411 mv_setReg64int (SRC2_REG
, mv_getReg64int (SRC1_REG
) << value
);
413 mv_setReg64int (SRC2_REG
, mv_getReg64int (SRC1_REG
) >> -value
);
417 fprintf (stderr
, "unknown opcode in DSPMCR5 0x%x\n", instr
);
418 cirrus_not_implemented ("unknown");
426 DSPMCR6 (ARMul_State
* state
,
427 unsigned type ATTRIBUTE_UNUSED
,
433 case 0: /* cfmv32al */
434 cirrus_not_implemented ("cfmv32al");
437 case 1: /* cfmv32am */
438 cirrus_not_implemented ("cfmv32am");
441 case 2: /* cfmv32ah */
442 cirrus_not_implemented ("cfmv32ah");
445 case 3: /* cfmv32a */
446 cirrus_not_implemented ("cfmv32a");
449 case 4: /* cfmv64a */
450 cirrus_not_implemented ("cfmv64a");
453 case 5: /* cfmv32sc */
454 cirrus_not_implemented ("cfmv32sc");
458 fprintf (stderr
, "unknown opcode in DSPMCR6 0x%x\n", instr
);
459 cirrus_not_implemented ("unknown");
467 DSPLDC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
472 static unsigned words
;
474 if (type
!= ARMul_DATA
)
481 { /* it's a long access, get two words */
484 printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
485 data
, words
, state
->bigendSig
, DEST_REG
);
489 if (state
->bigendSig
)
490 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
492 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
496 if (state
->bigendSig
)
497 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
499 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
506 printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG
,
507 mv_getRegDouble (DEST_REG
));
516 /* Get just one word. */
519 printfdbg ("cfldrs\n");
521 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
523 printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG
,
524 DSPregs
[DEST_REG
].upper
.f
);
531 DSPLDC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
536 static unsigned words
;
538 if (type
!= ARMul_DATA
)
546 /* It's a long access, get two words. */
549 printfdbg ("cfldr64: %d\n", data
);
553 if (state
->bigendSig
)
554 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
556 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
560 if (state
->bigendSig
)
561 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
563 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
570 printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG
,
571 mv_getReg64int (DEST_REG
));
580 /* Get just one word. */
583 printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG
, (int) data
);
585 /* 32bit ints should be sign extended to 64bits when loaded. */
586 mv_setReg64int (DEST_REG
, (long long) data
);
593 DSPSTC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
598 static unsigned words
;
600 if (type
!= ARMul_DATA
)
608 /* It's a long access, get two words. */
610 printfdbg ("cfstrd\n");
614 if (state
->bigendSig
)
615 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
617 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
621 if (state
->bigendSig
)
622 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
624 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
631 printfdbg ("\tmem = mvd%d = %g\n", DEST_REG
,
632 mv_getRegDouble (DEST_REG
));
641 /* Get just one word. */
643 printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG
,
644 DSPregs
[DEST_REG
].upper
.f
);
646 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
653 DSPSTC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
658 static unsigned words
;
660 if (type
!= ARMul_DATA
)
668 /* It's a long access, store two words. */
670 printfdbg ("cfstr64\n");
674 if (state
->bigendSig
)
675 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
677 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
681 if (state
->bigendSig
)
682 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
684 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
691 printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG
,
692 mv_getReg64int (DEST_REG
));
701 /* Store just one word. */
703 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
705 printfdbg ("cfstr32 MEM = %d\n", (int) *data
);
712 DSPCDP4 (ARMul_State
* state
,
718 opcode2
= BITS (5,7);
720 switch (BITS (20,21))
726 printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
729 DSPregs
[SRC1_REG
].upper
.f
);
730 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
;
734 printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
737 mv_getRegDouble (SRC1_REG
));
738 mv_setRegDouble (DEST_REG
, mv_getRegDouble (SRC1_REG
));
741 case 2: /* cfcvtds */
742 printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
745 (float) mv_getRegDouble (SRC1_REG
));
746 DSPregs
[DEST_REG
].upper
.f
= (float) mv_getRegDouble (SRC1_REG
);
749 case 3: /* cfcvtsd */
750 printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
753 (double) DSPregs
[SRC1_REG
].upper
.f
);
754 mv_setRegDouble (DEST_REG
, (double) DSPregs
[SRC1_REG
].upper
.f
);
757 case 4: /* cfcvt32s */
758 printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
761 (float) DSPregs
[SRC1_REG
].lower
.i
);
762 DSPregs
[DEST_REG
].upper
.f
= (float) DSPregs
[SRC1_REG
].lower
.i
;
765 case 5: /* cfcvt32d */
766 printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
769 (double) DSPregs
[SRC1_REG
].lower
.i
);
770 mv_setRegDouble (DEST_REG
, (double) DSPregs
[SRC1_REG
].lower
.i
);
773 case 6: /* cfcvt64s */
774 printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
777 (float) mv_getReg64int (SRC1_REG
));
778 DSPregs
[DEST_REG
].upper
.f
= (float) mv_getReg64int (SRC1_REG
);
781 case 7: /* cfcvt64d */
782 printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
785 (double) mv_getReg64int (SRC1_REG
));
786 mv_setRegDouble (DEST_REG
, (double) mv_getReg64int (SRC1_REG
));
795 printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
798 DSPregs
[SRC1_REG
].upper
.f
* DSPregs
[SRC2_REG
].upper
.f
);
800 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
801 * DSPregs
[SRC2_REG
].upper
.f
;
805 printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
808 mv_getRegDouble (SRC1_REG
) * mv_getRegDouble (SRC2_REG
));
810 mv_setRegDouble (DEST_REG
,
811 mv_getRegDouble (SRC1_REG
)
812 * mv_getRegDouble (SRC2_REG
));
816 fprintf (stderr
, "unknown opcode in DSPCDP4 0x%x\n", instr
);
817 cirrus_not_implemented ("unknown");
826 DSPregs
[DEST_REG
].upper
.f
= (DSPregs
[SRC1_REG
].upper
.f
< 0.0F
?
827 -DSPregs
[SRC1_REG
].upper
.f
828 : DSPregs
[SRC1_REG
].upper
.f
);
829 printfdbg ("cfabss mvf%d = |mvf%d| = %f\n",
832 DSPregs
[DEST_REG
].upper
.f
);
836 mv_setRegDouble (DEST_REG
,
837 (mv_getRegDouble (SRC1_REG
) < 0.0 ?
838 -mv_getRegDouble (SRC1_REG
)
839 : mv_getRegDouble (SRC1_REG
)));
840 printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n",
843 mv_getRegDouble (DEST_REG
));
847 DSPregs
[DEST_REG
].upper
.f
= -DSPregs
[SRC1_REG
].upper
.f
;
848 printfdbg ("cfnegs mvf%d = -mvf%d = %f\n",
851 DSPregs
[DEST_REG
].upper
.f
);
855 mv_setRegDouble (DEST_REG
,
856 -mv_getRegDouble (SRC1_REG
));
857 printfdbg ("cfnegd mvd%d = -mvd%d = %g\n",
859 mv_getRegDouble (DEST_REG
));
863 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
864 + DSPregs
[SRC2_REG
].upper
.f
;
865 printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n",
869 DSPregs
[DEST_REG
].upper
.f
);
873 mv_setRegDouble (DEST_REG
,
874 mv_getRegDouble (SRC1_REG
)
875 + mv_getRegDouble (SRC2_REG
));
876 printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n",
880 mv_getRegDouble (DEST_REG
));
884 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
885 - DSPregs
[SRC2_REG
].upper
.f
;
886 printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n",
890 DSPregs
[DEST_REG
].upper
.f
);
894 mv_setRegDouble (DEST_REG
,
895 mv_getRegDouble (SRC1_REG
)
896 - mv_getRegDouble (SRC2_REG
));
897 printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n",
901 mv_getRegDouble (DEST_REG
));
907 fprintf (stderr
, "unknown opcode in DSPCDP4 0x%x\n", instr
);
908 cirrus_not_implemented ("unknown");
916 DSPCDP5 (ARMul_State
* state
,
923 opcode2
= BITS (5,7);
925 /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */
926 shift
= BITS (0, 3) | (BITS (5, 7)) << 4;
930 switch (BITS (20,21))
934 printfdbg ("cfsh32 %s amount=%d\n", shift
< 0 ? "right" : "left",
937 /* Negative shift is a right shift. */
938 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
>> -shift
;
940 /* Positive shift is a left shift. */
941 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
<< shift
;
947 case 0: /* cfmul32 */
948 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
949 * DSPregs
[SRC2_REG
].lower
.i
;
950 printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n",
954 DSPregs
[DEST_REG
].lower
.i
);
957 case 1: /* cfmul64 */
958 mv_setReg64int (DEST_REG
,
959 mv_getReg64int (SRC1_REG
)
960 * mv_getReg64int (SRC2_REG
));
961 printfdbg ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n",
965 mv_getReg64int (DEST_REG
));
968 case 2: /* cfmac32 */
969 DSPregs
[DEST_REG
].lower
.i
970 += DSPregs
[SRC1_REG
].lower
.i
* DSPregs
[SRC2_REG
].lower
.i
;
971 printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n",
975 DSPregs
[DEST_REG
].lower
.i
);
978 case 3: /* cfmsc32 */
979 DSPregs
[DEST_REG
].lower
.i
980 -= DSPregs
[SRC1_REG
].lower
.i
* DSPregs
[SRC2_REG
].lower
.i
;
981 printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n",
985 DSPregs
[DEST_REG
].lower
.i
);
988 case 4: /* cfcvts32 */
989 /* fixme: this should round */
990 DSPregs
[DEST_REG
].lower
.i
= (int) DSPregs
[SRC1_REG
].upper
.f
;
991 printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n",
994 DSPregs
[DEST_REG
].lower
.i
);
997 case 5: /* cfcvtd32 */
998 /* fixme: this should round */
999 DSPregs
[DEST_REG
].lower
.i
= (int) mv_getRegDouble (SRC1_REG
);
1000 printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n",
1003 DSPregs
[DEST_REG
].lower
.i
);
1006 case 6: /* cftruncs32 */
1007 DSPregs
[DEST_REG
].lower
.i
= (int) DSPregs
[SRC1_REG
].upper
.f
;
1008 printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n",
1011 DSPregs
[DEST_REG
].lower
.i
);
1014 case 7: /* cftruncd32 */
1015 DSPregs
[DEST_REG
].lower
.i
= (int) mv_getRegDouble (SRC1_REG
);
1016 printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
1019 DSPregs
[DEST_REG
].lower
.i
);
1026 printfdbg ("cfsh64\n");
1029 /* Negative shift is a right shift. */
1030 mv_setReg64int (DEST_REG
,
1031 mv_getReg64int (SRC1_REG
) >> -shift
);
1033 /* Positive shift is a left shift. */
1034 mv_setReg64int (DEST_REG
,
1035 mv_getReg64int (SRC1_REG
) << shift
);
1036 printfdbg ("\t%llx\n", mv_getReg64int(DEST_REG
));
1042 case 0: /* cfabs32 */
1043 DSPregs
[DEST_REG
].lower
.i
= (DSPregs
[SRC1_REG
].lower
.i
< 0
1044 ? -DSPregs
[SRC1_REG
].lower
.i
: DSPregs
[SRC1_REG
].lower
.i
);
1045 printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n",
1049 DSPregs
[DEST_REG
].lower
.i
);
1052 case 1: /* cfabs64 */
1053 mv_setReg64int (DEST_REG
,
1054 (mv_getReg64int (SRC1_REG
) < 0
1055 ? -mv_getReg64int (SRC1_REG
)
1056 : mv_getReg64int (SRC1_REG
)));
1057 printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n",
1061 mv_getReg64int (DEST_REG
));
1064 case 2: /* cfneg32 */
1065 DSPregs
[DEST_REG
].lower
.i
= -DSPregs
[SRC1_REG
].lower
.i
;
1066 printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
1070 DSPregs
[DEST_REG
].lower
.i
);
1073 case 3: /* cfneg64 */
1074 mv_setReg64int (DEST_REG
, -mv_getReg64int (SRC1_REG
));
1075 printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
1079 mv_getReg64int (DEST_REG
));
1082 case 4: /* cfadd32 */
1083 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
1084 + DSPregs
[SRC2_REG
].lower
.i
;
1085 printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n",
1089 DSPregs
[DEST_REG
].lower
.i
);
1092 case 5: /* cfadd64 */
1093 mv_setReg64int (DEST_REG
,
1094 mv_getReg64int (SRC1_REG
)
1095 + mv_getReg64int (SRC2_REG
));
1096 printfdbg ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n",
1100 mv_getReg64int (DEST_REG
));
1103 case 6: /* cfsub32 */
1104 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
1105 - DSPregs
[SRC2_REG
].lower
.i
;
1106 printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n",
1110 DSPregs
[DEST_REG
].lower
.i
);
1113 case 7: /* cfsub64 */
1114 mv_setReg64int (DEST_REG
,
1115 mv_getReg64int (SRC1_REG
)
1116 - mv_getReg64int (SRC2_REG
));
1117 printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n",
1121 mv_getReg64int (DEST_REG
));
1127 fprintf (stderr
, "unknown opcode in DSPCDP5 0x%x\n", instr
);
1128 cirrus_not_implemented ("unknown");
1136 DSPCDP6 (ARMul_State
* state
,
1140 switch (BITS (20,21))
1144 cirrus_not_implemented ("cfmadd32");
1149 cirrus_not_implemented ("cfmsub32");
1154 cirrus_not_implemented ("cfmadda32");
1159 cirrus_not_implemented ("cfmsuba32");
1163 fprintf (stderr
, "unknown opcode in DSPCDP6 0x%x\n", instr
);
1169 /* Conversion functions.
1171 32-bit integers are stored in the LOWER half of a 64-bit physical
1174 Single precision floats are stored in the UPPER half of a 64-bit
1175 physical register. */
1178 mv_getRegDouble (int regnum
)
1180 reg_conv
.ints
[lsw_float_index
] = DSPregs
[regnum
].upper
.i
;
1181 reg_conv
.ints
[msw_float_index
] = DSPregs
[regnum
].lower
.i
;
1186 mv_setRegDouble (int regnum
, double val
)
1189 DSPregs
[regnum
].upper
.i
= reg_conv
.ints
[lsw_float_index
];
1190 DSPregs
[regnum
].lower
.i
= reg_conv
.ints
[msw_float_index
];
1194 mv_getReg64int (int regnum
)
1196 reg_conv
.ints
[lsw_int_index
] = DSPregs
[regnum
].lower
.i
;
1197 reg_conv
.ints
[msw_int_index
] = DSPregs
[regnum
].upper
.i
;
1202 mv_setReg64int (int regnum
, long long val
)
1205 DSPregs
[regnum
].lower
.i
= reg_conv
.ints
[lsw_int_index
];
1206 DSPregs
[regnum
].upper
.i
= reg_conv
.ints
[msw_int_index
];