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).
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.
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.
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/>. */
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 /* Define Co-Processor instruction handlers here. */
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. */
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
59 union maverick_acc_regs
61 long double ld
; /* Acc registers are 72-bits. */
64 struct maverick_regs DSPregs
[16];
65 union maverick_acc_regs DSPacc
[4];
68 #define DEST_REG (BITS (12, 15))
69 #define SRC1_REG (BITS (16, 19))
70 #define SRC2_REG (BITS (0, 3))
72 static int lsw_int_index
, msw_int_index
;
73 static int lsw_float_index
, msw_float_index
;
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
);
88 printf_nothing (void * foo
, ...)
93 cirrus_not_implemented (char * insn
)
95 fprintf (stderr
, "Cirrus instruction '%s' not implemented.\n", insn
);
96 fprintf (stderr
, "aborting!\n");
102 DSPInit (ARMul_State
* state
)
104 ARMul_ConsolePrint (state
, ", DSP present");
109 DSPMRC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
110 unsigned type ATTRIBUTE_UNUSED
,
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
));
122 *value
= (ARMword
) DSPregs
[SRC1_REG
].lower
.i
;
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
));
131 *value
= (ARMword
) DSPregs
[SRC1_REG
].upper
.i
;
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",
139 DSPregs
[SRC1_REG
].upper
.f
);
148 a
= DSPregs
[SRC1_REG
].upper
.f
;
149 b
= DSPregs
[SRC2_REG
].upper
.f
;
151 printfdbg ("cfcmps\n");
152 printfdbg ("\tcomparing %f and %f\n", a
, b
);
154 z
= a
== b
; /* zero */
155 n
= a
!= b
; /* negative */
156 v
= a
> b
; /* overflow */
158 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
167 a
= mv_getRegDouble (SRC1_REG
);
168 b
= mv_getRegDouble (SRC2_REG
);
170 printfdbg ("cfcmpd\n");
171 printfdbg ("\tcomparing %g and %g\n", a
, b
);
173 z
= a
== b
; /* zero */
174 n
= a
!= b
; /* negative */
175 v
= a
> b
; /* overflow */
177 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
186 a
= DSPregs
[SRC1_REG
].upper
.f
;
187 b
= DSPregs
[SRC2_REG
].upper
.f
;
189 printfdbg ("cfcmps\n");
190 printfdbg ("\tcomparing %f and %f\n", a
, b
);
192 z
= a
== b
; /* zero */
193 n
= a
< b
; /* negative */
194 c
= a
> b
; /* carry */
196 printfdbg ("\tz = %d, n = %d\n", z
, n
);
197 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
206 a
= mv_getRegDouble (SRC1_REG
);
207 b
= mv_getRegDouble (SRC2_REG
);
209 printfdbg ("cfcmpd\n");
210 printfdbg ("\tcomparing %g and %g\n", a
, b
);
212 z
= a
== b
; /* zero */
213 n
= a
< b
; /* negative */
214 c
= a
> b
; /* carry */
216 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
221 fprintf (stderr
, "unknown opcode in DSPMRC4 0x%x\n", instr
);
222 cirrus_not_implemented ("unknown");
230 DSPMRC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
231 unsigned type ATTRIBUTE_UNUSED
,
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",
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
);
251 case 4: /* cfcmp32 */
257 printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
261 /* FIXME: see comment for cfcmps. */
262 a
= DSPregs
[SRC1_REG
].lower
.i
;
263 b
= DSPregs
[SRC2_REG
].lower
.i
;
265 res
= DSPregs
[SRC1_REG
].lower
.i
- DSPregs
[SRC2_REG
].lower
.i
;
271 v
= SubOverflow (DSPregs
[SRC1_REG
].lower
.i
, DSPregs
[SRC2_REG
].lower
.i
,
274 c
= (NEG (a
) && POS (b
) ||
275 (NEG (a
) && POS (res
)) || (POS (b
) && POS (res
)));
277 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
281 case 5: /* cfcmp64 */
285 unsigned long long a
, b
;
287 printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
291 /* fixme: see comment for cfcmps. */
293 a
= mv_getReg64int (SRC1_REG
);
294 b
= mv_getReg64int (SRC2_REG
);
296 res
= mv_getReg64int (SRC1_REG
) - mv_getReg64int (SRC2_REG
);
302 v
= ((NEG64 (a
) && POS64 (b
) && POS64 (res
))
303 || (POS64 (a
) && NEG64 (b
) && NEG64 (res
)));
305 c
= (NEG64 (a
) && POS64 (b
) ||
306 (NEG64 (a
) && POS64 (res
)) || (POS64 (b
) && POS64 (res
)));
308 *value
= (n
<< 31) | (z
<< 30) | (c
<< 29) | (v
<< 28);
313 fprintf (stderr
, "unknown opcode in DSPMRC5 0x%x\n", instr
);
314 cirrus_not_implemented ("unknown");
322 DSPMRC6 (ARMul_State
* state ATTRIBUTE_UNUSED
,
323 unsigned type ATTRIBUTE_UNUSED
,
329 case 0: /* cfmval32 */
330 cirrus_not_implemented ("cfmval32");
333 case 1: /* cfmvam32 */
334 cirrus_not_implemented ("cfmvam32");
337 case 2: /* cfmvah32 */
338 cirrus_not_implemented ("cfmvah32");
341 case 3: /* cfmva32 */
342 cirrus_not_implemented ("cfmva32");
345 case 4: /* cfmva64 */
346 cirrus_not_implemented ("cfmva64");
349 case 5: /* cfmvsc32 */
350 cirrus_not_implemented ("cfmvsc32");
354 fprintf (stderr
, "unknown opcode in DSPMRC6 0x%x\n", instr
);
355 cirrus_not_implemented ("unknown");
363 DSPMCR4 (ARMul_State
* state
,
364 unsigned type ATTRIBUTE_UNUSED
,
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
;
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
;
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
;
391 fprintf (stderr
, "unknown opcode in DSPMCR4 0x%x\n", instr
);
392 cirrus_not_implemented ("unknown");
400 DSPMCR5 (ARMul_State
* state
,
401 unsigned type ATTRIBUTE_UNUSED
,
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
;
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",
426 DSPregs
[SRC1_REG
].upper
.i
= (int) value
;
429 case 2: /* cfrshl32 */
430 printfdbg ("cfrshl32\n");
433 DSPregs
[SRC2_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
<< value
;
435 DSPregs
[SRC2_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
>> -value
;
438 case 3: /* cfrshl64 */
439 printfdbg ("cfrshl64\n");
442 mv_setReg64int (SRC2_REG
, mv_getReg64int (SRC1_REG
) << value
);
444 mv_setReg64int (SRC2_REG
, mv_getReg64int (SRC1_REG
) >> -value
);
448 fprintf (stderr
, "unknown opcode in DSPMCR5 0x%x\n", instr
);
449 cirrus_not_implemented ("unknown");
457 DSPMCR6 (ARMul_State
* state
,
458 unsigned type ATTRIBUTE_UNUSED
,
464 case 0: /* cfmv32al */
465 cirrus_not_implemented ("cfmv32al");
468 case 1: /* cfmv32am */
469 cirrus_not_implemented ("cfmv32am");
472 case 2: /* cfmv32ah */
473 cirrus_not_implemented ("cfmv32ah");
476 case 3: /* cfmv32a */
477 cirrus_not_implemented ("cfmv32a");
480 case 4: /* cfmv64a */
481 cirrus_not_implemented ("cfmv64a");
484 case 5: /* cfmv32sc */
485 cirrus_not_implemented ("cfmv32sc");
489 fprintf (stderr
, "unknown opcode in DSPMCR6 0x%x\n", instr
);
490 cirrus_not_implemented ("unknown");
498 DSPLDC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
503 static unsigned words
;
505 if (type
!= ARMul_DATA
)
512 { /* it's a long access, get two words */
515 printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
516 data
, words
, state
->bigendSig
, DEST_REG
);
520 if (state
->bigendSig
)
521 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
523 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
527 if (state
->bigendSig
)
528 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
530 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
537 printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG
,
538 mv_getRegDouble (DEST_REG
));
547 /* Get just one word. */
550 printfdbg ("cfldrs\n");
552 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
554 printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG
,
555 DSPregs
[DEST_REG
].upper
.f
);
562 DSPLDC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
567 static unsigned words
;
569 if (type
!= ARMul_DATA
)
577 /* It's a long access, get two words. */
580 printfdbg ("cfldr64: %d\n", data
);
584 if (state
->bigendSig
)
585 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
587 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
591 if (state
->bigendSig
)
592 DSPregs
[DEST_REG
].lower
.i
= (int) data
;
594 DSPregs
[DEST_REG
].upper
.i
= (int) data
;
601 printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG
,
602 mv_getReg64int (DEST_REG
));
611 /* Get just one word. */
614 printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG
, (int) data
);
616 /* 32bit ints should be sign extended to 64bits when loaded. */
617 mv_setReg64int (DEST_REG
, (long long) data
);
624 DSPSTC4 (ARMul_State
* state ATTRIBUTE_UNUSED
,
629 static unsigned words
;
631 if (type
!= ARMul_DATA
)
639 /* It's a long access, get two words. */
641 printfdbg ("cfstrd\n");
645 if (state
->bigendSig
)
646 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
648 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
652 if (state
->bigendSig
)
653 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
655 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
662 printfdbg ("\tmem = mvd%d = %g\n", DEST_REG
,
663 mv_getRegDouble (DEST_REG
));
672 /* Get just one word. */
674 printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG
,
675 DSPregs
[DEST_REG
].upper
.f
);
677 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
684 DSPSTC5 (ARMul_State
* state ATTRIBUTE_UNUSED
,
689 static unsigned words
;
691 if (type
!= ARMul_DATA
)
699 /* It's a long access, store two words. */
701 printfdbg ("cfstr64\n");
705 if (state
->bigendSig
)
706 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
708 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
712 if (state
->bigendSig
)
713 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
715 *data
= (ARMword
) DSPregs
[DEST_REG
].upper
.i
;
722 printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG
,
723 mv_getReg64int (DEST_REG
));
732 /* Store just one word. */
734 *data
= (ARMword
) DSPregs
[DEST_REG
].lower
.i
;
736 printfdbg ("cfstr32 MEM = %d\n", (int) *data
);
743 DSPCDP4 (ARMul_State
* state
,
749 opcode2
= BITS (5,7);
751 switch (BITS (20,21))
757 printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
760 DSPregs
[SRC1_REG
].upper
.f
);
761 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
;
765 printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
768 mv_getRegDouble (SRC1_REG
));
769 mv_setRegDouble (DEST_REG
, mv_getRegDouble (SRC1_REG
));
772 case 2: /* cfcvtds */
773 printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
776 (float) mv_getRegDouble (SRC1_REG
));
777 DSPregs
[DEST_REG
].upper
.f
= (float) mv_getRegDouble (SRC1_REG
);
780 case 3: /* cfcvtsd */
781 printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
784 (double) DSPregs
[SRC1_REG
].upper
.f
);
785 mv_setRegDouble (DEST_REG
, (double) DSPregs
[SRC1_REG
].upper
.f
);
788 case 4: /* cfcvt32s */
789 printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
792 (float) DSPregs
[SRC1_REG
].lower
.i
);
793 DSPregs
[DEST_REG
].upper
.f
= (float) DSPregs
[SRC1_REG
].lower
.i
;
796 case 5: /* cfcvt32d */
797 printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
800 (double) DSPregs
[SRC1_REG
].lower
.i
);
801 mv_setRegDouble (DEST_REG
, (double) DSPregs
[SRC1_REG
].lower
.i
);
804 case 6: /* cfcvt64s */
805 printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
808 (float) mv_getReg64int (SRC1_REG
));
809 DSPregs
[DEST_REG
].upper
.f
= (float) mv_getReg64int (SRC1_REG
);
812 case 7: /* cfcvt64d */
813 printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
816 (double) mv_getReg64int (SRC1_REG
));
817 mv_setRegDouble (DEST_REG
, (double) mv_getReg64int (SRC1_REG
));
826 printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
829 DSPregs
[SRC1_REG
].upper
.f
* DSPregs
[SRC2_REG
].upper
.f
);
831 DSPregs
[DEST_REG
].upper
.f
= DSPregs
[SRC1_REG
].upper
.f
832 * DSPregs
[SRC2_REG
].upper
.f
;
836 printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
839 mv_getRegDouble (SRC1_REG
) * mv_getRegDouble (SRC2_REG
));
841 mv_setRegDouble (DEST_REG
,
842 mv_getRegDouble (SRC1_REG
)
843 * mv_getRegDouble (SRC2_REG
));
847 fprintf (stderr
, "unknown opcode in DSPCDP4 0x%x\n", instr
);
848 cirrus_not_implemented ("unknown");
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",
863 DSPregs
[DEST_REG
].upper
.f
);
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",
874 mv_getRegDouble (DEST_REG
));
878 DSPregs
[DEST_REG
].upper
.f
= -DSPregs
[SRC1_REG
].upper
.f
;
879 printfdbg ("cfnegs mvf%d = -mvf%d = %f\n",
882 DSPregs
[DEST_REG
].upper
.f
);
886 mv_setRegDouble (DEST_REG
,
887 -mv_getRegDouble (SRC1_REG
));
888 printfdbg ("cfnegd mvd%d = -mvd%d = %g\n",
890 mv_getRegDouble (DEST_REG
));
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",
900 DSPregs
[DEST_REG
].upper
.f
);
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",
911 mv_getRegDouble (DEST_REG
));
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",
921 DSPregs
[DEST_REG
].upper
.f
);
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",
932 mv_getRegDouble (DEST_REG
));
938 fprintf (stderr
, "unknown opcode in DSPCDP4 0x%x\n", instr
);
939 cirrus_not_implemented ("unknown");
947 DSPCDP5 (ARMul_State
* state
,
954 opcode2
= BITS (5,7);
956 /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */
957 shift
= BITS (0, 3) | (BITS (5, 7)) << 4;
961 switch (BITS (20,21))
965 printfdbg ("cfsh32 %s amount=%d\n", shift
< 0 ? "right" : "left",
968 /* Negative shift is a right shift. */
969 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
>> -shift
;
971 /* Positive shift is a left shift. */
972 DSPregs
[DEST_REG
].lower
.i
= DSPregs
[SRC1_REG
].lower
.i
<< shift
;
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",
985 DSPregs
[DEST_REG
].lower
.i
);
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",
996 mv_getReg64int (DEST_REG
));
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",
1006 DSPregs
[DEST_REG
].lower
.i
);
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",
1016 DSPregs
[DEST_REG
].lower
.i
);
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",
1025 DSPregs
[DEST_REG
].lower
.i
);
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",
1034 DSPregs
[DEST_REG
].lower
.i
);
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",
1042 DSPregs
[DEST_REG
].lower
.i
);
1045 case 7: /* cftruncd32 */
1046 DSPregs
[DEST_REG
].lower
.i
= (int) mv_getRegDouble (SRC1_REG
);
1047 printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
1050 DSPregs
[DEST_REG
].lower
.i
);
1057 printfdbg ("cfsh64\n");
1060 /* Negative shift is a right shift. */
1061 mv_setReg64int (DEST_REG
,
1062 mv_getReg64int (SRC1_REG
) >> -shift
);
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
));
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",
1080 DSPregs
[DEST_REG
].lower
.i
);
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",
1092 mv_getReg64int (DEST_REG
));
1095 case 2: /* cfneg32 */
1096 DSPregs
[DEST_REG
].lower
.i
= -DSPregs
[SRC1_REG
].lower
.i
;
1097 printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
1101 DSPregs
[DEST_REG
].lower
.i
);
1104 case 3: /* cfneg64 */
1105 mv_setReg64int (DEST_REG
, -mv_getReg64int (SRC1_REG
));
1106 printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
1110 mv_getReg64int (DEST_REG
));
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",
1120 DSPregs
[DEST_REG
].lower
.i
);
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",
1131 mv_getReg64int (DEST_REG
));
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",
1141 DSPregs
[DEST_REG
].lower
.i
);
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",
1152 mv_getReg64int (DEST_REG
));
1158 fprintf (stderr
, "unknown opcode in DSPCDP5 0x%x\n", instr
);
1159 cirrus_not_implemented ("unknown");
1167 DSPCDP6 (ARMul_State
* state
,
1173 opcode2
= BITS (5,7);
1175 switch (BITS (20,21))
1179 cirrus_not_implemented ("cfmadd32");
1184 cirrus_not_implemented ("cfmsub32");
1189 cirrus_not_implemented ("cfmadda32");
1194 cirrus_not_implemented ("cfmsuba32");
1198 fprintf (stderr
, "unknown opcode in DSPCDP6 0x%x\n", instr
);
1204 /* Conversion functions.
1206 32-bit integers are stored in the LOWER half of a 64-bit physical
1209 Single precision floats are stored in the UPPER half of a 64-bit
1210 physical register. */
1213 mv_getRegDouble (int regnum
)
1215 reg_conv
.ints
[lsw_float_index
] = DSPregs
[regnum
].upper
.i
;
1216 reg_conv
.ints
[msw_float_index
] = DSPregs
[regnum
].lower
.i
;
1221 mv_setRegDouble (int regnum
, double val
)
1224 DSPregs
[regnum
].upper
.i
= reg_conv
.ints
[lsw_float_index
];
1225 DSPregs
[regnum
].lower
.i
= reg_conv
.ints
[msw_float_index
];
1229 mv_getReg64int (int regnum
)
1231 reg_conv
.ints
[lsw_int_index
] = DSPregs
[regnum
].lower
.i
;
1232 reg_conv
.ints
[msw_int_index
] = DSPregs
[regnum
].upper
.i
;
1237 mv_setReg64int (int regnum
, long long val
)
1240 DSPregs
[regnum
].lower
.i
= reg_conv
.ints
[lsw_int_index
];
1241 DSPregs
[regnum
].upper
.i
= reg_conv
.ints
[msw_int_index
];
1244 /* Compute LSW in a double and a long long. */
1247 mv_compute_host_endianness (ARMul_State
* state
)
1259 /* Calculate where's the LSW in a 64bit int. */
1262 if (conv
.ints
[0] == 0)
1269 assert (conv
.ints
[1] == 0);
1274 /* Calculate where's the LSW in a double. */
1277 if (conv
.ints
[0] == 0)
1279 msw_float_index
= 0;
1280 lsw_float_index
= 1;
1284 assert (conv
.ints
[1] == 0);
1285 msw_float_index
= 1;
1286 lsw_float_index
= 0;
1289 printfdbg ("lsw_int_index %d\n", lsw_int_index
);
1290 printfdbg ("lsw_float_index %d\n", lsw_float_index
);
This page took 0.058012 seconds and 4 git commands to generate.