1 /* maverick.c -- Cirrus/DSP co-processor interface.
2 Copyright (C) 2003-2019 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 DSPMRC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
102 unsigned type ATTRIBUTE_UNUSED
,
108 case 0: /* cfmvrdl */
109 /* Move lower half of a DF stored in a DSP reg into an Arm reg. */
110 printfdbg ("cfmvrdl\n");
111 printfdbg ("\tlower half=0x%x\n", DSPregs
[SRC1_REG
].lower
.i
);
112 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG
));
114 *value
= (ARMword
) DSPregs
[SRC1_REG
].lower
.i
;
117 case 1: /* cfmvrdh */
118 /* Move upper half of a DF stored in a DSP reg into an Arm reg. */
119 printfdbg ("cfmvrdh\n");
120 printfdbg ("\tupper half=0x%x\n", DSPregs
[SRC1_REG
].upper
.i
);
121 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG
));
123 *value
= (ARMword
) DSPregs
[SRC1_REG
].upper
.i
;
127 /* Move SF from upper half of a DSP register to an Arm register. */
128 *value
= (ARMword
) DSPregs
[SRC1_REG
].upper
.i
;
129 printfdbg ("cfmvrs = mvf%d <-- %f\n",
131 DSPregs
[SRC1_REG
].upper
.f
);
140 a
= DSPregs
[SRC1_REG
].upper
.f
;
141 b
= DSPregs
[SRC2_REG
].upper
.f
;
143 printfdbg ("cfcmps\n");
144 printfdbg ("\tcomparing %f and %f\n", a
, b
);
146 z
= a
== b
; /* zero */
147 n
= a
!= b
; /* negative */
148 v
= a
> b
; /* overflow */
150 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
159 a
= mv_getRegDouble (SRC1_REG
);
160 b
= mv_getRegDouble (SRC2_REG
);
162 printfdbg ("cfcmpd\n");
163 printfdbg ("\tcomparing %g and %g\n", a
, b
);
165 z
= a
== b
; /* zero */
166 n
= a
!= b
; /* negative */
167 v
= a
> b
; /* overflow */
169 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
178 a
= DSPregs
[SRC1_REG
].upper
.f
;
179 b
= DSPregs
[SRC2_REG
].upper
.f
;
181 printfdbg ("cfcmps\n");
182 printfdbg ("\tcomparing %f and %f\n", a
, b
);
184 z
= a
== b
; /* zero */
185 n
= a
< b
; /* negative */
186 c
= a
> b
; /* carry */
188 printfdbg ("\tz = %d, n = %d\n", z
, n
);
189 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
198 a
= mv_getRegDouble (SRC1_REG
);
199 b
= mv_getRegDouble (SRC2_REG
);
201 printfdbg ("cfcmpd\n");
202 printfdbg ("\tcomparing %g and %g\n", a
, b
);
204 z
= a
== b
; /* zero */
205 n
= a
< b
; /* negative */
206 c
= a
> b
; /* carry */
208 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
213 fprintf (stderr
, "unknown opcode in DSPMRC4 0x%x\n", instr
);
214 cirrus_not_implemented ("unknown");
222 DSPMRC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
223 unsigned type ATTRIBUTE_UNUSED
,
229 case 0: /* cfmvr64l */
230 /* Move lower half of 64bit int from Cirrus to Arm. */
231 *value
= (ARMword
) DSPregs
[SRC1_REG
].lower
.i
;
232 printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n",
237 case 1: /* cfmvr64h */
238 /* Move upper half of 64bit int from Cirrus to Arm. */
239 *value
= (ARMword
) DSPregs
[SRC1_REG
].upper
.i
;
240 printfdbg ("cfmvr64h <-- %d\n", (int) *value
);
243 case 4: /* cfcmp32 */
249 printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
253 /* FIXME: see comment for cfcmps. */
254 a
= DSPregs
[SRC1_REG
].lower
.i
;
255 b
= DSPregs
[SRC2_REG
].lower
.i
;
257 res
= DSPregs
[SRC1_REG
].lower
.i
- DSPregs
[SRC2_REG
].lower
.i
;
263 v
= SubOverflow (DSPregs
[SRC1_REG
].lower
.i
, DSPregs
[SRC2_REG
].lower
.i
,
266 c
= (NEG (a
) && POS (b
))
267 || (NEG (a
) && POS (res
))
268 || (POS (b
) && POS (res
));
270 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
274 case 5: /* cfcmp64 */
278 unsigned long long a
, b
;
280 printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
284 /* fixme: see comment for cfcmps. */
286 a
= mv_getReg64int (SRC1_REG
);
287 b
= mv_getReg64int (SRC2_REG
);
289 res
= mv_getReg64int (SRC1_REG
) - mv_getReg64int (SRC2_REG
);
295 v
= ((NEG64 (a
) && POS64 (b
) && POS64 (res
))
296 || (POS64 (a
) && NEG64 (b
) && NEG64 (res
)));
298 c
= (NEG64 (a
) && POS64 (b
))
299 || (NEG64 (a
) && POS64 (res
))
300 || (POS64 (b
) && POS64 (res
));
302 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
307 fprintf (stderr
, "unknown opcode in DSPMRC5 0x%x\n", instr
);
308 cirrus_not_implemented ("unknown");
316 DSPMRC6 (ARMul_State
* state ATTRIBUTE_UNUSED
,
317 unsigned type ATTRIBUTE_UNUSED
,
323 case 0: /* cfmval32 */
324 cirrus_not_implemented ("cfmval32");
327 case 1: /* cfmvam32 */
328 cirrus_not_implemented ("cfmvam32");
331 case 2: /* cfmvah32 */
332 cirrus_not_implemented ("cfmvah32");
335 case 3: /* cfmva32 */
336 cirrus_not_implemented ("cfmva32");
339 case 4: /* cfmva64 */
340 cirrus_not_implemented ("cfmva64");
343 case 5: /* cfmvsc32 */
344 cirrus_not_implemented ("cfmvsc32");
348 fprintf (stderr
, "unknown opcode in DSPMRC6 0x%x\n", instr
);
349 cirrus_not_implemented ("unknown");
357 DSPMCR4 (ARMul_State
* state
,
358 unsigned type ATTRIBUTE_UNUSED
,
364 case 0: /* cfmvdlr */
365 /* Move the lower half of a DF value from an Arm register into
366 the lower half of a Cirrus register. */
367 printfdbg ("cfmvdlr <-- 0x%x\n", (int) value
);
368 DSPregs
[SRC1_REG
].lower
.i
= (int) value
;
371 case 1: /* cfmvdhr */
372 /* Move the upper half of a DF value from an Arm register into
373 the upper half of a Cirrus register. */
374 printfdbg ("cfmvdhr <-- 0x%x\n", (int) value
);
375 DSPregs
[SRC1_REG
].upper
.i
= (int) value
;
379 /* Move SF from Arm register into upper half of Cirrus register. */
380 printfdbg ("cfmvsr <-- 0x%x\n", (int) value
);
381 DSPregs
[SRC1_REG
].upper
.i
= (int) value
;
385 fprintf (stderr
, "unknown opcode in DSPMCR4 0x%x\n", instr
);
386 cirrus_not_implemented ("unknown");
394 DSPMCR5 (ARMul_State
* state
,
395 unsigned type ATTRIBUTE_UNUSED
,
407 case 0: /* cfmv64lr */
408 /* Move lower half of a 64bit int from an ARM register into the
409 lower half of a DSP register and sign extend it. */
410 printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG
, (int) value
);
411 DSPregs
[SRC1_REG
].lower
.i
= (int) value
;
414 case 1: /* cfmv64hr */
415 /* Move upper half of a 64bit int from an ARM register into the
416 upper half of a DSP register. */
417 printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n",
420 DSPregs
[SRC1_REG
].upper
.i
= (int) value
;
423 case 2: /* cfrshl32 */
424 printfdbg ("cfrshl32\n");
427 DSPregs
[SRC2_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
<< value
;
429 DSPregs
[SRC2_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
>> -value
;
432 case 3: /* cfrshl64 */
433 printfdbg ("cfrshl64\n");
436 mv_setReg64int (SRC2_REG
, mv_getReg64int (SRC1_REG
) << value
);
438 mv_setReg64int (SRC2_REG
, mv_getReg64int (SRC1_REG
) >> -value
);
442 fprintf (stderr
, "unknown opcode in DSPMCR5 0x%x\n", instr
);
443 cirrus_not_implemented ("unknown");
451 DSPMCR6 (ARMul_State
* state
,
452 unsigned type ATTRIBUTE_UNUSED
,
458 case 0: /* cfmv32al */
459 cirrus_not_implemented ("cfmv32al");
462 case 1: /* cfmv32am */
463 cirrus_not_implemented ("cfmv32am");
466 case 2: /* cfmv32ah */
467 cirrus_not_implemented ("cfmv32ah");
470 case 3: /* cfmv32a */
471 cirrus_not_implemented ("cfmv32a");
474 case 4: /* cfmv64a */
475 cirrus_not_implemented ("cfmv64a");
478 case 5: /* cfmv32sc */
479 cirrus_not_implemented ("cfmv32sc");
483 fprintf (stderr
, "unknown opcode in DSPMCR6 0x%x\n", instr
);
484 cirrus_not_implemented ("unknown");
492 DSPLDC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
497 static unsigned words
;
499 if (type
!= ARMul_DATA
)
506 { /* it's a long access, get two words */
509 printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
510 data
, words
, state
->bigendSig
, DEST_REG
);
514 if (state
->bigendSig
)
515 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
517 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
521 if (state
->bigendSig
)
522 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
524 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
531 printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG
,
532 mv_getRegDouble (DEST_REG
));
541 /* Get just one word. */
544 printfdbg ("cfldrs\n");
546 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
548 printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG
,
549 DSPregs
[DEST_REG
].upper
.f
);
556 DSPLDC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
561 static unsigned words
;
563 if (type
!= ARMul_DATA
)
571 /* It's a long access, get two words. */
574 printfdbg ("cfldr64: %d\n", data
);
578 if (state
->bigendSig
)
579 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
581 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
585 if (state
->bigendSig
)
586 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
588 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
595 printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG
,
596 mv_getReg64int (DEST_REG
));
605 /* Get just one word. */
608 printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG
, (int) data
);
610 /* 32bit ints should be sign extended to 64bits when loaded. */
611 mv_setReg64int (DEST_REG
, (long long) data
);
618 DSPSTC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
623 static unsigned words
;
625 if (type
!= ARMul_DATA
)
633 /* It's a long access, get two words. */
635 printfdbg ("cfstrd\n");
639 if (state
->bigendSig
)
640 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
642 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
646 if (state
->bigendSig
)
647 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
649 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
656 printfdbg ("\tmem = mvd%d = %g\n", DEST_REG
,
657 mv_getRegDouble (DEST_REG
));
666 /* Get just one word. */
668 printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG
,
669 DSPregs
[DEST_REG
].upper
.f
);
671 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
678 DSPSTC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
683 static unsigned words
;
685 if (type
!= ARMul_DATA
)
693 /* It's a long access, store two words. */
695 printfdbg ("cfstr64\n");
699 if (state
->bigendSig
)
700 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
702 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
706 if (state
->bigendSig
)
707 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
709 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
716 printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG
,
717 mv_getReg64int (DEST_REG
));
726 /* Store just one word. */
728 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
730 printfdbg ("cfstr32 MEM = %d\n", (int) *data
);
737 DSPCDP4 (ARMul_State
* state
,
743 opcode2
= BITS (5,7);
745 switch (BITS (20,21))
751 printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
754 DSPregs
[SRC1_REG
].upper
.f
);
755 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
;
759 printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
762 mv_getRegDouble (SRC1_REG
));
763 mv_setRegDouble (DEST_REG
, mv_getRegDouble (SRC1_REG
));
766 case 2: /* cfcvtds */
767 printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
770 (float) mv_getRegDouble (SRC1_REG
));
771 DSPregs
[DEST_REG
].upper
.f
= (float) mv_getRegDouble (SRC1_REG
);
774 case 3: /* cfcvtsd */
775 printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
778 (double) DSPregs
[SRC1_REG
].upper
.f
);
779 mv_setRegDouble (DEST_REG
, (double) DSPregs
[SRC1_REG
].upper
.f
);
782 case 4: /* cfcvt32s */
783 printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
786 (float) DSPregs
[SRC1_REG
].lower
.i
);
787 DSPregs
[DEST_REG
].upper
.f
= (float) DSPregs
[SRC1_REG
].lower
.i
;
790 case 5: /* cfcvt32d */
791 printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
794 (double) DSPregs
[SRC1_REG
].lower
.i
);
795 mv_setRegDouble (DEST_REG
, (double) DSPregs
[SRC1_REG
].lower
.i
);
798 case 6: /* cfcvt64s */
799 printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
802 (float) mv_getReg64int (SRC1_REG
));
803 DSPregs
[DEST_REG
].upper
.f
= (float) mv_getReg64int (SRC1_REG
);
806 case 7: /* cfcvt64d */
807 printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
810 (double) mv_getReg64int (SRC1_REG
));
811 mv_setRegDouble (DEST_REG
, (double) mv_getReg64int (SRC1_REG
));
820 printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
823 DSPregs
[SRC1_REG
].upper
.f
* DSPregs
[SRC2_REG
].upper
.f
);
825 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
826 * DSPregs
[SRC2_REG
].upper
.f
;
830 printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
833 mv_getRegDouble (SRC1_REG
) * mv_getRegDouble (SRC2_REG
));
835 mv_setRegDouble (DEST_REG
,
836 mv_getRegDouble (SRC1_REG
)
837 * mv_getRegDouble (SRC2_REG
));
841 fprintf (stderr
, "unknown opcode in DSPCDP4 0x%x\n", instr
);
842 cirrus_not_implemented ("unknown");
851 DSPregs
[DEST_REG
].upper
.f
= (DSPregs
[SRC1_REG
].upper
.f
< 0.0F
?
852 -DSPregs
[SRC1_REG
].upper
.f
853 : DSPregs
[SRC1_REG
].upper
.f
);
854 printfdbg ("cfabss mvf%d = |mvf%d| = %f\n",
857 DSPregs
[DEST_REG
].upper
.f
);
861 mv_setRegDouble (DEST_REG
,
862 (mv_getRegDouble (SRC1_REG
) < 0.0 ?
863 -mv_getRegDouble (SRC1_REG
)
864 : mv_getRegDouble (SRC1_REG
)));
865 printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n",
868 mv_getRegDouble (DEST_REG
));
872 DSPregs
[DEST_REG
].upper
.f
= -DSPregs
[SRC1_REG
].upper
.f
;
873 printfdbg ("cfnegs mvf%d = -mvf%d = %f\n",
876 DSPregs
[DEST_REG
].upper
.f
);
880 mv_setRegDouble (DEST_REG
,
881 -mv_getRegDouble (SRC1_REG
));
882 printfdbg ("cfnegd mvd%d = -mvd%d = %g\n",
884 mv_getRegDouble (DEST_REG
));
888 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
889 + DSPregs
[SRC2_REG
].upper
.f
;
890 printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n",
894 DSPregs
[DEST_REG
].upper
.f
);
898 mv_setRegDouble (DEST_REG
,
899 mv_getRegDouble (SRC1_REG
)
900 + mv_getRegDouble (SRC2_REG
));
901 printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n",
905 mv_getRegDouble (DEST_REG
));
909 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
910 - DSPregs
[SRC2_REG
].upper
.f
;
911 printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n",
915 DSPregs
[DEST_REG
].upper
.f
);
919 mv_setRegDouble (DEST_REG
,
920 mv_getRegDouble (SRC1_REG
)
921 - mv_getRegDouble (SRC2_REG
));
922 printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n",
926 mv_getRegDouble (DEST_REG
));
932 fprintf (stderr
, "unknown opcode in DSPCDP4 0x%x\n", instr
);
933 cirrus_not_implemented ("unknown");
941 DSPCDP5 (ARMul_State
* state
,
948 opcode2
= BITS (5,7);
950 /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */
951 shift
= BITS (0, 3) | (BITS (5, 7)) << 4;
955 switch (BITS (20,21))
959 printfdbg ("cfsh32 %s amount=%d\n", shift
< 0 ? "right" : "left",
962 /* Negative shift is a right shift. */
963 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
>> -shift
;
965 /* Positive shift is a left shift. */
966 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
<< shift
;
972 case 0: /* cfmul32 */
973 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
974 * DSPregs
[SRC2_REG
].lower
.i
;
975 printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n",
979 DSPregs
[DEST_REG
].lower
.i
);
982 case 1: /* cfmul64 */
983 mv_setReg64int (DEST_REG
,
984 mv_getReg64int (SRC1_REG
)
985 * mv_getReg64int (SRC2_REG
));
986 printfdbg ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n",
990 mv_getReg64int (DEST_REG
));
993 case 2: /* cfmac32 */
994 DSPregs
[DEST_REG
].lower
.i
995 += DSPregs
[SRC1_REG
].lower
.i
* DSPregs
[SRC2_REG
].lower
.i
;
996 printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n",
1000 DSPregs
[DEST_REG
].lower
.i
);
1003 case 3: /* cfmsc32 */
1004 DSPregs
[DEST_REG
].lower
.i
1005 -= DSPregs
[SRC1_REG
].lower
.i
* DSPregs
[SRC2_REG
].lower
.i
;
1006 printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n",
1010 DSPregs
[DEST_REG
].lower
.i
);
1013 case 4: /* cfcvts32 */
1014 /* fixme: this should round */
1015 DSPregs
[DEST_REG
].lower
.i
= (int) DSPregs
[SRC1_REG
].upper
.f
;
1016 printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n",
1019 DSPregs
[DEST_REG
].lower
.i
);
1022 case 5: /* cfcvtd32 */
1023 /* fixme: this should round */
1024 DSPregs
[DEST_REG
].lower
.i
= (int) mv_getRegDouble (SRC1_REG
);
1025 printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n",
1028 DSPregs
[DEST_REG
].lower
.i
);
1031 case 6: /* cftruncs32 */
1032 DSPregs
[DEST_REG
].lower
.i
= (int) DSPregs
[SRC1_REG
].upper
.f
;
1033 printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n",
1036 DSPregs
[DEST_REG
].lower
.i
);
1039 case 7: /* cftruncd32 */
1040 DSPregs
[DEST_REG
].lower
.i
= (int) mv_getRegDouble (SRC1_REG
);
1041 printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
1044 DSPregs
[DEST_REG
].lower
.i
);
1051 printfdbg ("cfsh64\n");
1054 /* Negative shift is a right shift. */
1055 mv_setReg64int (DEST_REG
,
1056 mv_getReg64int (SRC1_REG
) >> -shift
);
1058 /* Positive shift is a left shift. */
1059 mv_setReg64int (DEST_REG
,
1060 mv_getReg64int (SRC1_REG
) << shift
);
1061 printfdbg ("\t%llx\n", mv_getReg64int(DEST_REG
));
1067 case 0: /* cfabs32 */
1068 DSPregs
[DEST_REG
].lower
.i
= (DSPregs
[SRC1_REG
].lower
.i
< 0
1069 ? -DSPregs
[SRC1_REG
].lower
.i
: DSPregs
[SRC1_REG
].lower
.i
);
1070 printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n",
1074 DSPregs
[DEST_REG
].lower
.i
);
1077 case 1: /* cfabs64 */
1078 mv_setReg64int (DEST_REG
,
1079 (mv_getReg64int (SRC1_REG
) < 0
1080 ? -mv_getReg64int (SRC1_REG
)
1081 : mv_getReg64int (SRC1_REG
)));
1082 printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n",
1086 mv_getReg64int (DEST_REG
));
1089 case 2: /* cfneg32 */
1090 DSPregs
[DEST_REG
].lower
.i
= -DSPregs
[SRC1_REG
].lower
.i
;
1091 printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
1095 DSPregs
[DEST_REG
].lower
.i
);
1098 case 3: /* cfneg64 */
1099 mv_setReg64int (DEST_REG
, -mv_getReg64int (SRC1_REG
));
1100 printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
1104 mv_getReg64int (DEST_REG
));
1107 case 4: /* cfadd32 */
1108 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
1109 + DSPregs
[SRC2_REG
].lower
.i
;
1110 printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n",
1114 DSPregs
[DEST_REG
].lower
.i
);
1117 case 5: /* cfadd64 */
1118 mv_setReg64int (DEST_REG
,
1119 mv_getReg64int (SRC1_REG
)
1120 + mv_getReg64int (SRC2_REG
));
1121 printfdbg ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n",
1125 mv_getReg64int (DEST_REG
));
1128 case 6: /* cfsub32 */
1129 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
1130 - DSPregs
[SRC2_REG
].lower
.i
;
1131 printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n",
1135 DSPregs
[DEST_REG
].lower
.i
);
1138 case 7: /* cfsub64 */
1139 mv_setReg64int (DEST_REG
,
1140 mv_getReg64int (SRC1_REG
)
1141 - mv_getReg64int (SRC2_REG
));
1142 printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n",
1146 mv_getReg64int (DEST_REG
));
1152 fprintf (stderr
, "unknown opcode in DSPCDP5 0x%x\n", instr
);
1153 cirrus_not_implemented ("unknown");
1161 DSPCDP6 (ARMul_State
* state
,
1165 switch (BITS (20,21))
1169 cirrus_not_implemented ("cfmadd32");
1174 cirrus_not_implemented ("cfmsub32");
1179 cirrus_not_implemented ("cfmadda32");
1184 cirrus_not_implemented ("cfmsuba32");
1188 fprintf (stderr
, "unknown opcode in DSPCDP6 0x%x\n", instr
);
1194 /* Conversion functions.
1196 32-bit integers are stored in the LOWER half of a 64-bit physical
1199 Single precision floats are stored in the UPPER half of a 64-bit
1200 physical register. */
1203 mv_getRegDouble (int regnum
)
1205 reg_conv
.ints
[lsw_float_index
] = DSPregs
[regnum
].upper
.i
;
1206 reg_conv
.ints
[msw_float_index
] = DSPregs
[regnum
].lower
.i
;
1211 mv_setRegDouble (int regnum
, double val
)
1214 DSPregs
[regnum
].upper
.i
= reg_conv
.ints
[lsw_float_index
];
1215 DSPregs
[regnum
].lower
.i
= reg_conv
.ints
[msw_float_index
];
1219 mv_getReg64int (int regnum
)
1221 reg_conv
.ints
[lsw_int_index
] = DSPregs
[regnum
].lower
.i
;
1222 reg_conv
.ints
[msw_int_index
] = DSPregs
[regnum
].upper
.i
;
1227 mv_setReg64int (int regnum
, long long val
)
1230 DSPregs
[regnum
].lower
.i
= reg_conv
.ints
[lsw_int_index
];
1231 DSPregs
[regnum
].upper
.i
= reg_conv
.ints
[msw_int_index
];