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