Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / sim / arm / maverick.c
CommitLineData
f603c8fe 1/* maverick.c -- Cirrus/DSP co-processor interface.
88b9d363 2 Copyright (C) 2003-2022 Free Software Foundation, Inc.
f603c8fe 3 Contributed by Aldy Hernandez (aldyh@redhat.com).
454de2ee 4
f603c8fe
NC
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
4744ac1b 7 the Free Software Foundation; either version 3 of the License, or
f603c8fe 8 (at your option) any later version.
4744ac1b 9
f603c8fe
NC
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.
4744ac1b 14
f603c8fe 15 You should have received a copy of the GNU General Public License
4744ac1b 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
f603c8fe 17
6df01ab8
MF
18/* This must come before any other includes. */
19#include "defs.h"
20
f603c8fe
NC
21#include <assert.h>
22#include "armdefs.h"
23#include "ansidecl.h"
24#include "armemu.h"
851c0536 25#include "maverick.h"
f603c8fe 26
8d052926 27/*#define CIRRUS_DEBUG 1 */
f603c8fe
NC
28#if CIRRUS_DEBUG
29# define printfdbg printf
30#else
31# define printfdbg printf_nothing
32#endif
33
34#define POS64(i) ( (~(i)) >> 63 )
35#define NEG64(i) ( (i) >> 63 )
36
851c0536
LM
37/* These variables are defined here and made extern in maverick.h for use
38 in wrapper.c for now.
39 Eventually the simulator should be made to handle any coprocessor at run
40 time. */
f603c8fe
NC
41struct maverick_regs DSPregs[16];
42union maverick_acc_regs DSPacc[4];
43ARMword DSPsc;
44
45#define DEST_REG (BITS (12, 15))
46#define SRC1_REG (BITS (16, 19))
47#define SRC2_REG (BITS (0, 3))
48
49static int lsw_int_index, msw_int_index;
50static int lsw_float_index, msw_float_index;
51
52static double mv_getRegDouble (int);
53static long long mv_getReg64int (int);
54static void mv_setRegDouble (int, double val);
55static void mv_setReg64int (int, long long val);
56
57static union
58{
59 double d;
60 long long ll;
61 int ints[2];
62} reg_conv;
63
64static void
65printf_nothing (void * foo, ...)
66{
67}
68
69static void
70cirrus_not_implemented (char * insn)
71{
72 fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn);
73 fprintf (stderr, "aborting!\n");
454de2ee 74
f603c8fe
NC
75 exit (1);
76}
77
f603c8fe
NC
78unsigned
79DSPMRC4 (ARMul_State * state ATTRIBUTE_UNUSED,
80 unsigned type ATTRIBUTE_UNUSED,
81 ARMword instr,
82 ARMword * value)
83{
84 switch (BITS (5, 7))
85 {
86 case 0: /* cfmvrdl */
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));
454de2ee 91
f603c8fe
NC
92 *value = (ARMword) DSPregs[SRC1_REG].lower.i;
93 break;
454de2ee 94
f603c8fe
NC
95 case 1: /* cfmvrdh */
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));
454de2ee 100
f603c8fe
NC
101 *value = (ARMword) DSPregs[SRC1_REG].upper.i;
102 break;
454de2ee 103
f603c8fe
NC
104 case 2: /* cfmvrs */
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",
108 SRC1_REG,
109 DSPregs[SRC1_REG].upper.f);
110 break;
454de2ee 111
f603c8fe
NC
112#ifdef doesnt_work
113 case 4: /* cfcmps */
114 {
115 float a, b;
116 int n, z, c, v;
117
118 a = DSPregs[SRC1_REG].upper.f;
119 b = DSPregs[SRC2_REG].upper.f;
120
121 printfdbg ("cfcmps\n");
122 printfdbg ("\tcomparing %f and %f\n", a, b);
123
124 z = a == b; /* zero */
125 n = a != b; /* negative */
126 v = a > b; /* overflow */
127 c = 0; /* carry */
128 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
129 break;
130 }
454de2ee 131
f603c8fe
NC
132 case 5: /* cfcmpd */
133 {
134 double a, b;
135 int n, z, c, v;
136
137 a = mv_getRegDouble (SRC1_REG);
138 b = mv_getRegDouble (SRC2_REG);
139
140 printfdbg ("cfcmpd\n");
141 printfdbg ("\tcomparing %g and %g\n", a, b);
142
143 z = a == b; /* zero */
144 n = a != b; /* negative */
145 v = a > b; /* overflow */
146 c = 0; /* carry */
147 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
148 break;
149 }
150#else
151 case 4: /* cfcmps */
152 {
153 float a, b;
154 int n, z, c, v;
155
156 a = DSPregs[SRC1_REG].upper.f;
157 b = DSPregs[SRC2_REG].upper.f;
454de2ee 158
f603c8fe
NC
159 printfdbg ("cfcmps\n");
160 printfdbg ("\tcomparing %f and %f\n", a, b);
161
162 z = a == b; /* zero */
163 n = a < b; /* negative */
164 c = a > b; /* carry */
165 v = 0; /* fixme */
166 printfdbg ("\tz = %d, n = %d\n", z, n);
167 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
168 break;
169 }
170
171 case 5: /* cfcmpd */
172 {
173 double a, b;
174 int n, z, c, v;
175
176 a = mv_getRegDouble (SRC1_REG);
177 b = mv_getRegDouble (SRC2_REG);
454de2ee 178
f603c8fe
NC
179 printfdbg ("cfcmpd\n");
180 printfdbg ("\tcomparing %g and %g\n", a, b);
454de2ee 181
f603c8fe
NC
182 z = a == b; /* zero */
183 n = a < b; /* negative */
184 c = a > b; /* carry */
185 v = 0; /* fixme */
186 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
187 break;
188 }
189#endif
190 default:
191 fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr);
192 cirrus_not_implemented ("unknown");
193 break;
194 }
195
196 return ARMul_DONE;
197}
198
199unsigned
200DSPMRC5 (ARMul_State * state ATTRIBUTE_UNUSED,
201 unsigned type ATTRIBUTE_UNUSED,
202 ARMword instr,
203 ARMword * value)
204{
205 switch (BITS (5, 7))
206 {
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",
211 DEST_REG,
212 (int) *value);
213 break;
454de2ee 214
f603c8fe
NC
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);
219 break;
454de2ee 220
f603c8fe
NC
221 case 4: /* cfcmp32 */
222 {
223 int res;
224 int n, z, c, v;
225 unsigned int a, b;
226
227 printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
228 SRC1_REG,
229 SRC2_REG);
230
231 /* FIXME: see comment for cfcmps. */
232 a = DSPregs[SRC1_REG].lower.i;
233 b = DSPregs[SRC2_REG].lower.i;
234
235 res = DSPregs[SRC1_REG].lower.i - DSPregs[SRC2_REG].lower.i;
236 /* zero */
237 z = res == 0;
238 /* negative */
239 n = res < 0;
240 /* overflow */
241 v = SubOverflow (DSPregs[SRC1_REG].lower.i, DSPregs[SRC2_REG].lower.i,
242 res);
243 /* carry */
8d052926
NC
244 c = (NEG (a) && POS (b))
245 || (NEG (a) && POS (res))
246 || (POS (b) && POS (res));
f603c8fe
NC
247
248 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
249 break;
250 }
454de2ee 251
f603c8fe
NC
252 case 5: /* cfcmp64 */
253 {
254 long long res;
255 int n, z, c, v;
256 unsigned long long a, b;
257
258 printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
259 SRC1_REG,
260 SRC2_REG);
261
262 /* fixme: see comment for cfcmps. */
263
264 a = mv_getReg64int (SRC1_REG);
265 b = mv_getReg64int (SRC2_REG);
266
267 res = mv_getReg64int (SRC1_REG) - mv_getReg64int (SRC2_REG);
268 /* zero */
269 z = res == 0;
270 /* negative */
271 n = res < 0;
272 /* overflow */
273 v = ((NEG64 (a) && POS64 (b) && POS64 (res))
274 || (POS64 (a) && NEG64 (b) && NEG64 (res)));
275 /* carry */
8d052926
NC
276 c = (NEG64 (a) && POS64 (b))
277 || (NEG64 (a) && POS64 (res))
278 || (POS64 (b) && POS64 (res));
f603c8fe
NC
279
280 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
281 break;
282 }
454de2ee 283
f603c8fe
NC
284 default:
285 fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr);
286 cirrus_not_implemented ("unknown");
287 break;
288 }
289
290 return ARMul_DONE;
291}
292
293unsigned
294DSPMRC6 (ARMul_State * state ATTRIBUTE_UNUSED,
295 unsigned type ATTRIBUTE_UNUSED,
296 ARMword instr,
297 ARMword * value)
298{
299 switch (BITS (5, 7))
300 {
301 case 0: /* cfmval32 */
302 cirrus_not_implemented ("cfmval32");
303 break;
454de2ee 304
f603c8fe
NC
305 case 1: /* cfmvam32 */
306 cirrus_not_implemented ("cfmvam32");
307 break;
454de2ee 308
f603c8fe
NC
309 case 2: /* cfmvah32 */
310 cirrus_not_implemented ("cfmvah32");
311 break;
454de2ee 312
f603c8fe
NC
313 case 3: /* cfmva32 */
314 cirrus_not_implemented ("cfmva32");
315 break;
454de2ee 316
f603c8fe
NC
317 case 4: /* cfmva64 */
318 cirrus_not_implemented ("cfmva64");
319 break;
454de2ee 320
f603c8fe
NC
321 case 5: /* cfmvsc32 */
322 cirrus_not_implemented ("cfmvsc32");
323 break;
454de2ee 324
f603c8fe
NC
325 default:
326 fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr);
327 cirrus_not_implemented ("unknown");
328 break;
329 }
330
331 return ARMul_DONE;
332}
333
334unsigned
335DSPMCR4 (ARMul_State * state,
336 unsigned type ATTRIBUTE_UNUSED,
337 ARMword instr,
338 ARMword value)
339{
340 switch (BITS (5, 7))
341 {
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;
347 break;
454de2ee 348
f603c8fe
NC
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;
354 break;
454de2ee 355
f603c8fe
NC
356 case 2: /* cfmvsr */
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;
360 break;
454de2ee 361
f603c8fe
NC
362 default:
363 fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr);
364 cirrus_not_implemented ("unknown");
365 break;
366 }
367
368 return ARMul_DONE;
369}
370
371unsigned
372DSPMCR5 (ARMul_State * state,
373 unsigned type ATTRIBUTE_UNUSED,
374 ARMword instr,
375 ARMword value)
376{
377 union
378 {
379 int s;
380 unsigned int us;
381 } val;
382
383 switch (BITS (5, 7))
384 {
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;
390 break;
454de2ee 391
f603c8fe
NC
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",
396 SRC1_REG,
397 (int) value);
398 DSPregs[SRC1_REG].upper.i = (int) value;
399 break;
454de2ee 400
f603c8fe
NC
401 case 2: /* cfrshl32 */
402 printfdbg ("cfrshl32\n");
403 val.us = value;
404 if (val.s > 0)
405 DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i << value;
406 else
407 DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -value;
408 break;
454de2ee 409
f603c8fe
NC
410 case 3: /* cfrshl64 */
411 printfdbg ("cfrshl64\n");
412 val.us = value;
413 if (val.s > 0)
414 mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) << value);
415 else
416 mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) >> -value);
417 break;
454de2ee 418
f603c8fe
NC
419 default:
420 fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr);
421 cirrus_not_implemented ("unknown");
422 break;
423 }
424
425 return ARMul_DONE;
426}
427
428unsigned
429DSPMCR6 (ARMul_State * state,
430 unsigned type ATTRIBUTE_UNUSED,
431 ARMword instr,
432 ARMword value)
433{
434 switch (BITS (5, 7))
435 {
436 case 0: /* cfmv32al */
437 cirrus_not_implemented ("cfmv32al");
438 break;
454de2ee 439
f603c8fe
NC
440 case 1: /* cfmv32am */
441 cirrus_not_implemented ("cfmv32am");
442 break;
454de2ee 443
f603c8fe
NC
444 case 2: /* cfmv32ah */
445 cirrus_not_implemented ("cfmv32ah");
446 break;
454de2ee 447
f603c8fe
NC
448 case 3: /* cfmv32a */
449 cirrus_not_implemented ("cfmv32a");
450 break;
454de2ee 451
f603c8fe
NC
452 case 4: /* cfmv64a */
453 cirrus_not_implemented ("cfmv64a");
454 break;
454de2ee 455
f603c8fe
NC
456 case 5: /* cfmv32sc */
457 cirrus_not_implemented ("cfmv32sc");
458 break;
454de2ee 459
f603c8fe
NC
460 default:
461 fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr);
462 cirrus_not_implemented ("unknown");
463 break;
464 }
465
466 return ARMul_DONE;
467}
468
469unsigned
470DSPLDC4 (ARMul_State * state ATTRIBUTE_UNUSED,
471 unsigned type,
472 ARMword instr,
473 ARMword data)
474{
475 static unsigned words;
476
477 if (type != ARMul_DATA)
478 {
479 words = 0;
480 return ARMul_DONE;
481 }
454de2ee 482
f603c8fe
NC
483 if (BIT (22))
484 { /* it's a long access, get two words */
485 /* cfldrd */
486
487 printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
488 data, words, state->bigendSig, DEST_REG);
454de2ee 489
f603c8fe
NC
490 if (words == 0)
491 {
492 if (state->bigendSig)
493 DSPregs[DEST_REG].upper.i = (int) data;
494 else
495 DSPregs[DEST_REG].lower.i = (int) data;
496 }
497 else
498 {
499 if (state->bigendSig)
500 DSPregs[DEST_REG].lower.i = (int) data;
501 else
502 DSPregs[DEST_REG].upper.i = (int) data;
503 }
454de2ee 504
f603c8fe 505 ++ words;
454de2ee 506
f603c8fe
NC
507 if (words == 2)
508 {
509 printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG,
510 mv_getRegDouble (DEST_REG));
454de2ee 511
f603c8fe
NC
512 return ARMul_DONE;
513 }
514 else
515 return ARMul_INC;
516 }
517 else
518 {
519 /* Get just one word. */
454de2ee 520
f603c8fe
NC
521 /* cfldrs */
522 printfdbg ("cfldrs\n");
523
524 DSPregs[DEST_REG].upper.i = (int) data;
525
526 printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG,
527 DSPregs[DEST_REG].upper.f);
528
529 return ARMul_DONE;
530 }
531}
532
533unsigned
534DSPLDC5 (ARMul_State * state ATTRIBUTE_UNUSED,
535 unsigned type,
536 ARMword instr,
537 ARMword data)
538{
539 static unsigned words;
540
541 if (type != ARMul_DATA)
542 {
543 words = 0;
544 return ARMul_DONE;
545 }
454de2ee 546
f603c8fe
NC
547 if (BIT (22))
548 {
549 /* It's a long access, get two words. */
454de2ee 550
f603c8fe
NC
551 /* cfldr64 */
552 printfdbg ("cfldr64: %d\n", data);
553
554 if (words == 0)
555 {
556 if (state->bigendSig)
557 DSPregs[DEST_REG].upper.i = (int) data;
558 else
559 DSPregs[DEST_REG].lower.i = (int) data;
560 }
561 else
562 {
563 if (state->bigendSig)
564 DSPregs[DEST_REG].lower.i = (int) data;
565 else
566 DSPregs[DEST_REG].upper.i = (int) data;
567 }
454de2ee 568
f603c8fe 569 ++ words;
454de2ee 570
f603c8fe
NC
571 if (words == 2)
572 {
573 printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG,
574 mv_getReg64int (DEST_REG));
454de2ee 575
f603c8fe
NC
576 return ARMul_DONE;
577 }
578 else
579 return ARMul_INC;
580 }
581 else
582 {
583 /* Get just one word. */
454de2ee 584
f603c8fe
NC
585 /* cfldr32 */
586 printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data);
454de2ee 587
f603c8fe
NC
588 /* 32bit ints should be sign extended to 64bits when loaded. */
589 mv_setReg64int (DEST_REG, (long long) data);
590
591 return ARMul_DONE;
592 }
593}
594
595unsigned
596DSPSTC4 (ARMul_State * state ATTRIBUTE_UNUSED,
597 unsigned type,
598 ARMword instr,
599 ARMword * data)
600{
601 static unsigned words;
602
603 if (type != ARMul_DATA)
604 {
605 words = 0;
606 return ARMul_DONE;
607 }
454de2ee 608
f603c8fe
NC
609 if (BIT (22))
610 {
611 /* It's a long access, get two words. */
612 /* cfstrd */
613 printfdbg ("cfstrd\n");
614
615 if (words == 0)
616 {
617 if (state->bigendSig)
618 *data = (ARMword) DSPregs[DEST_REG].upper.i;
619 else
620 *data = (ARMword) DSPregs[DEST_REG].lower.i;
621 }
622 else
623 {
624 if (state->bigendSig)
625 *data = (ARMword) DSPregs[DEST_REG].lower.i;
626 else
627 *data = (ARMword) DSPregs[DEST_REG].upper.i;
628 }
454de2ee 629
f603c8fe 630 ++ words;
454de2ee 631
f603c8fe
NC
632 if (words == 2)
633 {
634 printfdbg ("\tmem = mvd%d = %g\n", DEST_REG,
635 mv_getRegDouble (DEST_REG));
454de2ee 636
f603c8fe
NC
637 return ARMul_DONE;
638 }
639 else
640 return ARMul_INC;
641 }
642 else
643 {
644 /* Get just one word. */
645 /* cfstrs */
646 printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG,
647 DSPregs[DEST_REG].upper.f);
648
649 *data = (ARMword) DSPregs[DEST_REG].upper.i;
650
651 return ARMul_DONE;
652 }
653}
654
655unsigned
656DSPSTC5 (ARMul_State * state ATTRIBUTE_UNUSED,
657 unsigned type,
658 ARMword instr,
659 ARMword * data)
660{
661 static unsigned words;
662
663 if (type != ARMul_DATA)
664 {
665 words = 0;
666 return ARMul_DONE;
667 }
454de2ee 668
f603c8fe
NC
669 if (BIT (22))
670 {
671 /* It's a long access, store two words. */
672 /* cfstr64 */
673 printfdbg ("cfstr64\n");
674
675 if (words == 0)
676 {
677 if (state->bigendSig)
678 *data = (ARMword) DSPregs[DEST_REG].upper.i;
679 else
680 *data = (ARMword) DSPregs[DEST_REG].lower.i;
681 }
682 else
683 {
684 if (state->bigendSig)
685 *data = (ARMword) DSPregs[DEST_REG].lower.i;
686 else
687 *data = (ARMword) DSPregs[DEST_REG].upper.i;
688 }
454de2ee 689
f603c8fe 690 ++ words;
454de2ee 691
f603c8fe
NC
692 if (words == 2)
693 {
694 printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG,
695 mv_getReg64int (DEST_REG));
454de2ee 696
f603c8fe
NC
697 return ARMul_DONE;
698 }
699 else
700 return ARMul_INC;
701 }
702 else
703 {
704 /* Store just one word. */
705 /* cfstr32 */
706 *data = (ARMword) DSPregs[DEST_REG].lower.i;
454de2ee 707
f603c8fe
NC
708 printfdbg ("cfstr32 MEM = %d\n", (int) *data);
709
710 return ARMul_DONE;
711 }
712}
713
714unsigned
715DSPCDP4 (ARMul_State * state,
716 unsigned type,
717 ARMword instr)
718{
719 int opcode2;
720
721 opcode2 = BITS (5,7);
722
723 switch (BITS (20,21))
724 {
725 case 0:
726 switch (opcode2)
727 {
728 case 0: /* cfcpys */
729 printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
730 DEST_REG,
731 SRC1_REG,
732 DSPregs[SRC1_REG].upper.f);
733 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f;
734 break;
454de2ee 735
f603c8fe
NC
736 case 1: /* cfcpyd */
737 printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
738 DEST_REG,
739 SRC1_REG,
740 mv_getRegDouble (SRC1_REG));
741 mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG));
742 break;
454de2ee 743
f603c8fe
NC
744 case 2: /* cfcvtds */
745 printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
746 DEST_REG,
747 SRC1_REG,
748 (float) mv_getRegDouble (SRC1_REG));
749 DSPregs[DEST_REG].upper.f = (float) mv_getRegDouble (SRC1_REG);
750 break;
454de2ee 751
f603c8fe
NC
752 case 3: /* cfcvtsd */
753 printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
754 DEST_REG,
755 SRC1_REG,
756 (double) DSPregs[SRC1_REG].upper.f);
757 mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].upper.f);
758 break;
454de2ee 759
f603c8fe
NC
760 case 4: /* cfcvt32s */
761 printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
762 DEST_REG,
763 SRC1_REG,
764 (float) DSPregs[SRC1_REG].lower.i);
765 DSPregs[DEST_REG].upper.f = (float) DSPregs[SRC1_REG].lower.i;
766 break;
454de2ee 767
f603c8fe
NC
768 case 5: /* cfcvt32d */
769 printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
770 DEST_REG,
771 SRC1_REG,
772 (double) DSPregs[SRC1_REG].lower.i);
773 mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].lower.i);
774 break;
454de2ee 775
f603c8fe
NC
776 case 6: /* cfcvt64s */
777 printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
778 DEST_REG,
779 SRC1_REG,
780 (float) mv_getReg64int (SRC1_REG));
781 DSPregs[DEST_REG].upper.f = (float) mv_getReg64int (SRC1_REG);
782 break;
454de2ee 783
f603c8fe
NC
784 case 7: /* cfcvt64d */
785 printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
786 DEST_REG,
787 SRC1_REG,
788 (double) mv_getReg64int (SRC1_REG));
789 mv_setRegDouble (DEST_REG, (double) mv_getReg64int (SRC1_REG));
790 break;
791 }
792 break;
793
794 case 1:
795 switch (opcode2)
796 {
797 case 0: /* cfmuls */
798 printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
799 DEST_REG,
800 SRC1_REG,
801 DSPregs[SRC1_REG].upper.f * DSPregs[SRC2_REG].upper.f);
454de2ee 802
f603c8fe
NC
803 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
804 * DSPregs[SRC2_REG].upper.f;
805 break;
454de2ee 806
f603c8fe
NC
807 case 1: /* cfmuld */
808 printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
809 DEST_REG,
810 SRC1_REG,
811 mv_getRegDouble (SRC1_REG) * mv_getRegDouble (SRC2_REG));
812
813 mv_setRegDouble (DEST_REG,
814 mv_getRegDouble (SRC1_REG)
815 * mv_getRegDouble (SRC2_REG));
816 break;
454de2ee 817
f603c8fe
NC
818 default:
819 fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
820 cirrus_not_implemented ("unknown");
821 break;
822 }
823 break;
824
825 case 3:
826 switch (opcode2)
827 {
828 case 0: /* cfabss */
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",
833 DEST_REG,
834 SRC1_REG,
835 DSPregs[DEST_REG].upper.f);
836 break;
454de2ee 837
f603c8fe
NC
838 case 1: /* cfabsd */
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",
844 DEST_REG,
845 SRC1_REG,
846 mv_getRegDouble (DEST_REG));
847 break;
454de2ee 848
f603c8fe
NC
849 case 2: /* cfnegs */
850 DSPregs[DEST_REG].upper.f = -DSPregs[SRC1_REG].upper.f;
851 printfdbg ("cfnegs mvf%d = -mvf%d = %f\n",
852 DEST_REG,
853 SRC1_REG,
854 DSPregs[DEST_REG].upper.f);
855 break;
454de2ee 856
f603c8fe
NC
857 case 3: /* cfnegd */
858 mv_setRegDouble (DEST_REG,
859 -mv_getRegDouble (SRC1_REG));
860 printfdbg ("cfnegd mvd%d = -mvd%d = %g\n",
43724d16 861 DEST_REG, DEST_REG,
f603c8fe
NC
862 mv_getRegDouble (DEST_REG));
863 break;
454de2ee 864
f603c8fe
NC
865 case 4: /* cfadds */
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",
869 DEST_REG,
870 SRC1_REG,
871 SRC2_REG,
872 DSPregs[DEST_REG].upper.f);
873 break;
454de2ee 874
f603c8fe
NC
875 case 5: /* cfaddd */
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",
880 DEST_REG,
881 SRC1_REG,
882 SRC2_REG,
883 mv_getRegDouble (DEST_REG));
884 break;
454de2ee 885
f603c8fe
NC
886 case 6: /* cfsubs */
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",
890 DEST_REG,
891 SRC1_REG,
892 SRC2_REG,
893 DSPregs[DEST_REG].upper.f);
894 break;
454de2ee 895
f603c8fe
NC
896 case 7: /* cfsubd */
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",
901 DEST_REG,
902 SRC1_REG,
903 SRC2_REG,
904 mv_getRegDouble (DEST_REG));
905 break;
906 }
907 break;
908
909 default:
910 fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
911 cirrus_not_implemented ("unknown");
912 break;
913 }
914
915 return ARMul_DONE;
916}
917
918unsigned
919DSPCDP5 (ARMul_State * state,
920 unsigned type,
921 ARMword instr)
922{
923 int opcode2;
924 char shift;
925
926 opcode2 = BITS (5,7);
927
928 /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */
929 shift = BITS (0, 3) | (BITS (5, 7)) << 4;
930 if (shift & 0x40)
931 shift |= 0xc0;
932
933 switch (BITS (20,21))
934 {
935 case 0:
936 /* cfsh32 */
937 printfdbg ("cfsh32 %s amount=%d\n", shift < 0 ? "right" : "left",
938 shift);
939 if (shift < 0)
940 /* Negative shift is a right shift. */
941 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -shift;
942 else
943 /* Positive shift is a left shift. */
944 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i << shift;
945 break;
946
947 case 1:
948 switch (opcode2)
949 {
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",
954 DEST_REG,
955 SRC1_REG,
956 SRC2_REG,
957 DSPregs[DEST_REG].lower.i);
958 break;
454de2ee 959
f603c8fe
NC
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",
965 DEST_REG,
966 SRC1_REG,
967 SRC2_REG,
968 mv_getReg64int (DEST_REG));
969 break;
454de2ee 970
f603c8fe
NC
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",
975 DEST_REG,
976 SRC1_REG,
977 SRC2_REG,
978 DSPregs[DEST_REG].lower.i);
979 break;
454de2ee 980
f603c8fe
NC
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",
985 DEST_REG,
986 SRC1_REG,
987 SRC2_REG,
988 DSPregs[DEST_REG].lower.i);
989 break;
454de2ee 990
f603c8fe
NC
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",
995 DEST_REG,
996 SRC1_REG,
997 DSPregs[DEST_REG].lower.i);
998 break;
454de2ee 999
f603c8fe
NC
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",
1004 DEST_REG,
1005 SRC1_REG,
1006 DSPregs[DEST_REG].lower.i);
1007 break;
454de2ee 1008
f603c8fe
NC
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",
1012 DEST_REG,
1013 SRC1_REG,
1014 DSPregs[DEST_REG].lower.i);
1015 break;
454de2ee 1016
f603c8fe
NC
1017 case 7: /* cftruncd32 */
1018 DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
1019 printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
1020 DEST_REG,
1021 SRC1_REG,
1022 DSPregs[DEST_REG].lower.i);
1023 break;
1024 }
1025 break;
1026
1027 case 2:
1028 /* cfsh64 */
1029 printfdbg ("cfsh64\n");
454de2ee 1030
f603c8fe
NC
1031 if (shift < 0)
1032 /* Negative shift is a right shift. */
1033 mv_setReg64int (DEST_REG,
1034 mv_getReg64int (SRC1_REG) >> -shift);
1035 else
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));
1040 break;
1041
1042 case 3:
1043 switch (opcode2)
1044 {
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",
1049 DEST_REG,
1050 SRC1_REG,
1051 SRC2_REG,
1052 DSPregs[DEST_REG].lower.i);
1053 break;
454de2ee 1054
f603c8fe
NC
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",
1061 DEST_REG,
1062 SRC1_REG,
1063 SRC2_REG,
1064 mv_getReg64int (DEST_REG));
1065 break;
454de2ee 1066
f603c8fe
NC
1067 case 2: /* cfneg32 */
1068 DSPregs[DEST_REG].lower.i = -DSPregs[SRC1_REG].lower.i;
1069 printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
1070 DEST_REG,
1071 SRC1_REG,
1072 SRC2_REG,
1073 DSPregs[DEST_REG].lower.i);
1074 break;
454de2ee 1075
f603c8fe
NC
1076 case 3: /* cfneg64 */
1077 mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG));
1078 printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
1079 DEST_REG,
1080 SRC1_REG,
1081 SRC2_REG,
1082 mv_getReg64int (DEST_REG));
1083 break;
454de2ee 1084
f603c8fe
NC
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",
1089 DEST_REG,
1090 SRC1_REG,
1091 SRC2_REG,
1092 DSPregs[DEST_REG].lower.i);
1093 break;
454de2ee 1094
f603c8fe
NC
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",
1100 DEST_REG,
1101 SRC1_REG,
1102 SRC2_REG,
1103 mv_getReg64int (DEST_REG));
1104 break;
454de2ee 1105
f603c8fe
NC
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",
1110 DEST_REG,
1111 SRC1_REG,
1112 SRC2_REG,
1113 DSPregs[DEST_REG].lower.i);
1114 break;
454de2ee 1115
f603c8fe
NC
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",
1121 DEST_REG,
1122 SRC1_REG,
1123 SRC2_REG,
1124 mv_getReg64int (DEST_REG));
1125 break;
1126 }
1127 break;
1128
1129 default:
1130 fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr);
1131 cirrus_not_implemented ("unknown");
1132 break;
1133 }
1134
1135 return ARMul_DONE;
1136}
1137
1138unsigned
1139DSPCDP6 (ARMul_State * state,
1140 unsigned type,
1141 ARMword instr)
1142{
f603c8fe
NC
1143 switch (BITS (20,21))
1144 {
1145 case 0:
1146 /* cfmadd32 */
1147 cirrus_not_implemented ("cfmadd32");
1148 break;
454de2ee 1149
f603c8fe
NC
1150 case 1:
1151 /* cfmsub32 */
1152 cirrus_not_implemented ("cfmsub32");
1153 break;
454de2ee 1154
f603c8fe
NC
1155 case 2:
1156 /* cfmadda32 */
1157 cirrus_not_implemented ("cfmadda32");
1158 break;
454de2ee 1159
f603c8fe
NC
1160 case 3:
1161 /* cfmsuba32 */
1162 cirrus_not_implemented ("cfmsuba32");
1163 break;
1164
1165 default:
1166 fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr);
1167 }
1168
1169 return ARMul_DONE;
1170}
1171
1172/* Conversion functions.
1173
1174 32-bit integers are stored in the LOWER half of a 64-bit physical
1175 register.
1176
1177 Single precision floats are stored in the UPPER half of a 64-bit
1178 physical register. */
1179
1180static double
1181mv_getRegDouble (int regnum)
1182{
1183 reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i;
1184 reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i;
1185 return reg_conv.d;
1186}
1187
1188static void
1189mv_setRegDouble (int regnum, double val)
1190{
1191 reg_conv.d = val;
1192 DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index];
1193 DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index];
1194}
1195
1196static long long
1197mv_getReg64int (int regnum)
1198{
1199 reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i;
1200 reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i;
1201 return reg_conv.ll;
1202}
1203
1204static void
1205mv_setReg64int (int regnum, long long val)
1206{
1207 reg_conv.ll = val;
1208 DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index];
1209 DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index];
1210}
This page took 0.902162 seconds and 4 git commands to generate.