xref: /netbsd-src/external/gpl3/gdb/dist/sim/arm/maverick.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
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).
5 
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.
10 
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.
15 
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/>. */
18 
19 #include <assert.h>
20 #include "armdefs.h"
21 #include "ansidecl.h"
22 #include "armemu.h"
23 
24 /*#define CIRRUS_DEBUG 1	/**/
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 
34 /* Define Co-Processor instruction handlers here.  */
35 
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.  */
39 
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
43    at run time.  */
44 struct maverick_regs
45 {
46   union
47   {
48     int i;
49     float f;
50   } upper;
51 
52   union
53   {
54     int i;
55     float f;
56   } lower;
57 };
58 
59 union maverick_acc_regs
60 {
61   long double ld;		/* Acc registers are 72-bits.  */
62 };
63 
64 struct maverick_regs DSPregs[16];
65 union maverick_acc_regs DSPacc[4];
66 ARMword DSPsc;
67 
68 #define DEST_REG	(BITS (12, 15))
69 #define SRC1_REG	(BITS (16, 19))
70 #define SRC2_REG	(BITS (0, 3))
71 
72 static int lsw_int_index, msw_int_index;
73 static int lsw_float_index, msw_float_index;
74 
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);
79 
80 static union
81 {
82   double d;
83   long long ll;
84   int ints[2];
85 } reg_conv;
86 
87 static void
88 printf_nothing (void * foo, ...)
89 {
90 }
91 
92 static void
93 cirrus_not_implemented (char * insn)
94 {
95   fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn);
96   fprintf (stderr, "aborting!\n");
97 
98   exit (1);
99 }
100 
101 static unsigned
102 DSPInit (ARMul_State * state)
103 {
104   ARMul_ConsolePrint (state, ", DSP present");
105   return TRUE;
106 }
107 
108 unsigned
109 DSPMRC4 (ARMul_State * state ATTRIBUTE_UNUSED,
110 	 unsigned      type  ATTRIBUTE_UNUSED,
111 	 ARMword       instr,
112 	 ARMword *     value)
113 {
114   switch (BITS (5, 7))
115     {
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));
121 
122       *value = (ARMword) DSPregs[SRC1_REG].lower.i;
123       break;
124 
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));
130 
131       *value = (ARMword) DSPregs[SRC1_REG].upper.i;
132       break;
133 
134     case 2: /* cfmvrs */
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",
138 		 SRC1_REG,
139 		 DSPregs[SRC1_REG].upper.f);
140       break;
141 
142 #ifdef doesnt_work
143     case 4: /* cfcmps */
144       {
145 	float a, b;
146 	int n, z, c, v;
147 
148 	a = DSPregs[SRC1_REG].upper.f;
149 	b = DSPregs[SRC2_REG].upper.f;
150 
151 	printfdbg ("cfcmps\n");
152 	printfdbg ("\tcomparing %f and %f\n", a, b);
153 
154 	z = a == b;		/* zero */
155 	n = a != b;		/* negative */
156 	v = a > b;		/* overflow */
157 	c = 0;			/* carry */
158 	*value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
159 	break;
160       }
161 
162     case 5: /* cfcmpd */
163       {
164 	double a, b;
165 	int n, z, c, v;
166 
167 	a = mv_getRegDouble (SRC1_REG);
168 	b = mv_getRegDouble (SRC2_REG);
169 
170 	printfdbg ("cfcmpd\n");
171 	printfdbg ("\tcomparing %g and %g\n", a, b);
172 
173 	z = a == b;		/* zero */
174 	n = a != b;		/* negative */
175 	v = a > b;		/* overflow */
176 	c = 0;			/* carry */
177 	*value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
178 	break;
179       }
180 #else
181       case 4: /* cfcmps */
182         {
183 	  float a, b;
184 	  int n, z, c, v;
185 
186 	  a = DSPregs[SRC1_REG].upper.f;
187 	  b = DSPregs[SRC2_REG].upper.f;
188 
189 	  printfdbg ("cfcmps\n");
190 	  printfdbg ("\tcomparing %f and %f\n", a, b);
191 
192 	  z = a == b;		/* zero */
193 	  n = a < b;		/* negative */
194 	  c = a > b;		/* carry */
195 	  v = 0;		/* fixme */
196 	  printfdbg ("\tz = %d, n = %d\n", z, n);
197 	  *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
198 	  break;
199         }
200 
201       case 5: /* cfcmpd */
202         {
203 	  double a, b;
204 	  int n, z, c, v;
205 
206 	  a = mv_getRegDouble (SRC1_REG);
207 	  b = mv_getRegDouble (SRC2_REG);
208 
209 	  printfdbg ("cfcmpd\n");
210 	  printfdbg ("\tcomparing %g and %g\n", a, b);
211 
212 	  z = a == b;		/* zero */
213 	  n = a < b;		/* negative */
214 	  c = a > b;		/* carry */
215 	  v = 0;		/* fixme */
216 	  *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
217 	  break;
218         }
219 #endif
220     default:
221       fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr);
222       cirrus_not_implemented ("unknown");
223       break;
224     }
225 
226   return ARMul_DONE;
227 }
228 
229 unsigned
230 DSPMRC5 (ARMul_State * state ATTRIBUTE_UNUSED,
231 	 unsigned      type  ATTRIBUTE_UNUSED,
232 	 ARMword       instr,
233 	 ARMword *     value)
234 {
235   switch (BITS (5, 7))
236     {
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",
241 		 DEST_REG,
242 		 (int) *value);
243       break;
244 
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);
249       break;
250 
251     case 4: /* cfcmp32 */
252       {
253 	int res;
254 	int n, z, c, v;
255 	unsigned int a, b;
256 
257 	printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
258 		   SRC1_REG,
259 		   SRC2_REG);
260 
261 	/* FIXME: see comment for cfcmps.  */
262 	a = DSPregs[SRC1_REG].lower.i;
263 	b = DSPregs[SRC2_REG].lower.i;
264 
265 	res = DSPregs[SRC1_REG].lower.i - DSPregs[SRC2_REG].lower.i;
266 	/* zero */
267 	z = res == 0;
268 	/* negative */
269 	n = res < 0;
270 	/* overflow */
271 	v = SubOverflow (DSPregs[SRC1_REG].lower.i, DSPregs[SRC2_REG].lower.i,
272 			 res);
273 	/* carry */
274 	c = (NEG (a) && POS (b) ||
275 	     (NEG (a) && POS (res)) || (POS (b) && POS (res)));
276 
277 	*value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
278 	break;
279       }
280 
281     case 5: /* cfcmp64 */
282       {
283 	long long res;
284 	int n, z, c, v;
285 	unsigned long long a, b;
286 
287 	printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
288 		   SRC1_REG,
289 		   SRC2_REG);
290 
291 	/* fixme: see comment for cfcmps.  */
292 
293 	a = mv_getReg64int (SRC1_REG);
294 	b = mv_getReg64int (SRC2_REG);
295 
296 	res = mv_getReg64int (SRC1_REG) - mv_getReg64int (SRC2_REG);
297 	/* zero */
298 	z = res == 0;
299 	/* negative */
300 	n = res < 0;
301 	/* overflow */
302 	v = ((NEG64 (a) && POS64 (b) && POS64 (res))
303 	     || (POS64 (a) && NEG64 (b) && NEG64 (res)));
304 	/* carry */
305 	c = (NEG64 (a) && POS64 (b) ||
306 	     (NEG64 (a) && POS64 (res)) || (POS64 (b) && POS64 (res)));
307 
308 	*value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
309 	break;
310       }
311 
312     default:
313       fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr);
314       cirrus_not_implemented ("unknown");
315       break;
316     }
317 
318   return ARMul_DONE;
319 }
320 
321 unsigned
322 DSPMRC6 (ARMul_State * state ATTRIBUTE_UNUSED,
323 	 unsigned      type  ATTRIBUTE_UNUSED,
324 	 ARMword       instr,
325 	 ARMword *     value)
326 {
327   switch (BITS (5, 7))
328     {
329     case 0: /* cfmval32 */
330       cirrus_not_implemented ("cfmval32");
331       break;
332 
333     case 1: /* cfmvam32 */
334       cirrus_not_implemented ("cfmvam32");
335       break;
336 
337     case 2: /* cfmvah32 */
338       cirrus_not_implemented ("cfmvah32");
339       break;
340 
341     case 3: /* cfmva32 */
342       cirrus_not_implemented ("cfmva32");
343       break;
344 
345     case 4: /* cfmva64 */
346       cirrus_not_implemented ("cfmva64");
347       break;
348 
349     case 5: /* cfmvsc32 */
350       cirrus_not_implemented ("cfmvsc32");
351       break;
352 
353     default:
354       fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr);
355       cirrus_not_implemented ("unknown");
356       break;
357     }
358 
359   return ARMul_DONE;
360 }
361 
362 unsigned
363 DSPMCR4 (ARMul_State * state,
364 	 unsigned      type ATTRIBUTE_UNUSED,
365 	 ARMword       instr,
366 	 ARMword       value)
367 {
368   switch (BITS (5, 7))
369     {
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;
375       break;
376 
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;
382       break;
383 
384     case 2: /* cfmvsr */
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;
388       break;
389 
390     default:
391       fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr);
392       cirrus_not_implemented ("unknown");
393       break;
394     }
395 
396   return ARMul_DONE;
397 }
398 
399 unsigned
400 DSPMCR5 (ARMul_State * state,
401 	 unsigned      type   ATTRIBUTE_UNUSED,
402 	 ARMword       instr,
403 	 ARMword       value)
404 {
405   union
406   {
407     int s;
408     unsigned int us;
409   } val;
410 
411   switch (BITS (5, 7))
412     {
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;
418       break;
419 
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",
424 		 SRC1_REG,
425 		 (int) value);
426       DSPregs[SRC1_REG].upper.i = (int) value;
427       break;
428 
429     case 2: /* cfrshl32 */
430       printfdbg ("cfrshl32\n");
431       val.us = value;
432       if (val.s > 0)
433 	DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i << value;
434       else
435 	DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -value;
436       break;
437 
438     case 3: /* cfrshl64 */
439       printfdbg ("cfrshl64\n");
440       val.us = value;
441       if (val.s > 0)
442 	mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) << value);
443       else
444 	mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) >> -value);
445       break;
446 
447     default:
448       fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr);
449       cirrus_not_implemented ("unknown");
450       break;
451     }
452 
453   return ARMul_DONE;
454 }
455 
456 unsigned
457 DSPMCR6 (ARMul_State * state,
458 	 unsigned      type   ATTRIBUTE_UNUSED,
459 	 ARMword       instr,
460 	 ARMword       value)
461 {
462   switch (BITS (5, 7))
463     {
464     case 0: /* cfmv32al */
465       cirrus_not_implemented ("cfmv32al");
466       break;
467 
468     case 1: /* cfmv32am */
469       cirrus_not_implemented ("cfmv32am");
470       break;
471 
472     case 2: /* cfmv32ah */
473       cirrus_not_implemented ("cfmv32ah");
474       break;
475 
476     case 3: /* cfmv32a */
477       cirrus_not_implemented ("cfmv32a");
478       break;
479 
480     case 4: /* cfmv64a */
481       cirrus_not_implemented ("cfmv64a");
482       break;
483 
484     case 5: /* cfmv32sc */
485       cirrus_not_implemented ("cfmv32sc");
486       break;
487 
488     default:
489       fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr);
490       cirrus_not_implemented ("unknown");
491       break;
492     }
493 
494   return ARMul_DONE;
495 }
496 
497 unsigned
498 DSPLDC4 (ARMul_State * state ATTRIBUTE_UNUSED,
499 	 unsigned      type,
500 	 ARMword       instr,
501 	 ARMword       data)
502 {
503   static unsigned words;
504 
505   if (type != ARMul_DATA)
506     {
507       words = 0;
508       return ARMul_DONE;
509     }
510 
511   if (BIT (22))
512     {				/* it's a long access, get two words */
513       /* cfldrd */
514 
515       printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
516 		 data, words, state->bigendSig, DEST_REG);
517 
518       if (words == 0)
519 	{
520 	  if (state->bigendSig)
521 	    DSPregs[DEST_REG].upper.i = (int) data;
522 	  else
523 	    DSPregs[DEST_REG].lower.i = (int) data;
524 	}
525       else
526 	{
527 	  if (state->bigendSig)
528 	    DSPregs[DEST_REG].lower.i = (int) data;
529 	  else
530 	    DSPregs[DEST_REG].upper.i = (int) data;
531 	}
532 
533       ++ words;
534 
535       if (words == 2)
536 	{
537 	  printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG,
538 		     mv_getRegDouble (DEST_REG));
539 
540 	  return ARMul_DONE;
541 	}
542       else
543 	return ARMul_INC;
544     }
545   else
546     {
547       /* Get just one word.  */
548 
549       /* cfldrs */
550       printfdbg ("cfldrs\n");
551 
552       DSPregs[DEST_REG].upper.i = (int) data;
553 
554       printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG,
555 		 DSPregs[DEST_REG].upper.f);
556 
557       return ARMul_DONE;
558     }
559 }
560 
561 unsigned
562 DSPLDC5 (ARMul_State * state ATTRIBUTE_UNUSED,
563 	 unsigned      type,
564 	 ARMword       instr,
565 	 ARMword       data)
566 {
567   static unsigned words;
568 
569   if (type != ARMul_DATA)
570     {
571       words = 0;
572       return ARMul_DONE;
573     }
574 
575   if (BIT (22))
576     {
577       /* It's a long access, get two words.  */
578 
579       /* cfldr64 */
580       printfdbg ("cfldr64: %d\n", data);
581 
582       if (words == 0)
583 	{
584 	  if (state->bigendSig)
585 	    DSPregs[DEST_REG].upper.i = (int) data;
586 	  else
587 	    DSPregs[DEST_REG].lower.i = (int) data;
588 	}
589       else
590 	{
591 	  if (state->bigendSig)
592 	    DSPregs[DEST_REG].lower.i = (int) data;
593 	  else
594 	    DSPregs[DEST_REG].upper.i = (int) data;
595 	}
596 
597       ++ words;
598 
599       if (words == 2)
600 	{
601 	  printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG,
602 		     mv_getReg64int (DEST_REG));
603 
604 	  return ARMul_DONE;
605 	}
606       else
607 	return ARMul_INC;
608     }
609   else
610     {
611       /* Get just one word.  */
612 
613       /* cfldr32 */
614       printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data);
615 
616       /* 32bit ints should be sign extended to 64bits when loaded.  */
617       mv_setReg64int (DEST_REG, (long long) data);
618 
619       return ARMul_DONE;
620     }
621 }
622 
623 unsigned
624 DSPSTC4 (ARMul_State * state ATTRIBUTE_UNUSED,
625 	 unsigned      type,
626 	 ARMword       instr,
627 	 ARMword *     data)
628 {
629   static unsigned words;
630 
631   if (type != ARMul_DATA)
632     {
633       words = 0;
634       return ARMul_DONE;
635     }
636 
637   if (BIT (22))
638     {
639       /* It's a long access, get two words.  */
640       /* cfstrd */
641       printfdbg ("cfstrd\n");
642 
643       if (words == 0)
644 	{
645 	  if (state->bigendSig)
646 	    *data = (ARMword) DSPregs[DEST_REG].upper.i;
647 	  else
648 	    *data = (ARMword) DSPregs[DEST_REG].lower.i;
649 	}
650       else
651 	{
652 	  if (state->bigendSig)
653 	    *data = (ARMword) DSPregs[DEST_REG].lower.i;
654 	  else
655 	    *data = (ARMword) DSPregs[DEST_REG].upper.i;
656 	}
657 
658       ++ words;
659 
660       if (words == 2)
661 	{
662 	  printfdbg ("\tmem = mvd%d = %g\n", DEST_REG,
663 		     mv_getRegDouble (DEST_REG));
664 
665 	  return ARMul_DONE;
666 	}
667       else
668 	return ARMul_INC;
669     }
670   else
671     {
672       /* Get just one word.  */
673       /* cfstrs */
674       printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG,
675 		 DSPregs[DEST_REG].upper.f);
676 
677       *data = (ARMword) DSPregs[DEST_REG].upper.i;
678 
679       return ARMul_DONE;
680     }
681 }
682 
683 unsigned
684 DSPSTC5 (ARMul_State * state ATTRIBUTE_UNUSED,
685 	 unsigned      type,
686 	 ARMword       instr,
687 	 ARMword *     data)
688 {
689   static unsigned words;
690 
691   if (type != ARMul_DATA)
692     {
693       words = 0;
694       return ARMul_DONE;
695     }
696 
697   if (BIT (22))
698     {
699       /* It's a long access, store two words.  */
700       /* cfstr64 */
701       printfdbg ("cfstr64\n");
702 
703       if (words == 0)
704 	{
705 	  if (state->bigendSig)
706 	    *data = (ARMword) DSPregs[DEST_REG].upper.i;
707 	  else
708 	    *data = (ARMword) DSPregs[DEST_REG].lower.i;
709 	}
710       else
711 	{
712 	  if (state->bigendSig)
713 	    *data = (ARMword) DSPregs[DEST_REG].lower.i;
714 	  else
715 	    *data = (ARMword) DSPregs[DEST_REG].upper.i;
716 	}
717 
718       ++ words;
719 
720       if (words == 2)
721 	{
722 	  printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG,
723 		     mv_getReg64int (DEST_REG));
724 
725 	  return ARMul_DONE;
726 	}
727       else
728 	return ARMul_INC;
729     }
730   else
731     {
732       /* Store just one word.  */
733       /* cfstr32 */
734       *data = (ARMword) DSPregs[DEST_REG].lower.i;
735 
736       printfdbg ("cfstr32 MEM = %d\n", (int) *data);
737 
738       return ARMul_DONE;
739     }
740 }
741 
742 unsigned
743 DSPCDP4 (ARMul_State * state,
744 	 unsigned      type,
745 	 ARMword       instr)
746 {
747   int opcode2;
748 
749   opcode2 = BITS (5,7);
750 
751   switch (BITS (20,21))
752     {
753     case 0:
754       switch (opcode2)
755 	{
756 	case 0: /* cfcpys */
757 	  printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
758 		     DEST_REG,
759 		     SRC1_REG,
760 		     DSPregs[SRC1_REG].upper.f);
761 	  DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f;
762 	  break;
763 
764 	case 1: /* cfcpyd */
765 	  printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
766 		     DEST_REG,
767 		     SRC1_REG,
768 		     mv_getRegDouble (SRC1_REG));
769 	  mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG));
770 	  break;
771 
772 	case 2: /* cfcvtds */
773 	  printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
774 		     DEST_REG,
775 		     SRC1_REG,
776 		     (float) mv_getRegDouble (SRC1_REG));
777 	  DSPregs[DEST_REG].upper.f = (float) mv_getRegDouble (SRC1_REG);
778 	  break;
779 
780 	case 3: /* cfcvtsd */
781 	  printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
782 		     DEST_REG,
783 		     SRC1_REG,
784 		     (double) DSPregs[SRC1_REG].upper.f);
785 	  mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].upper.f);
786 	  break;
787 
788 	case 4: /* cfcvt32s */
789 	  printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
790 		     DEST_REG,
791 		     SRC1_REG,
792 		     (float) DSPregs[SRC1_REG].lower.i);
793 	  DSPregs[DEST_REG].upper.f = (float) DSPregs[SRC1_REG].lower.i;
794 	  break;
795 
796 	case 5: /* cfcvt32d */
797 	  printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
798 		     DEST_REG,
799 		     SRC1_REG,
800 		     (double) DSPregs[SRC1_REG].lower.i);
801 	  mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].lower.i);
802 	  break;
803 
804 	case 6: /* cfcvt64s */
805 	  printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
806 		     DEST_REG,
807 		     SRC1_REG,
808 		     (float) mv_getReg64int (SRC1_REG));
809 	  DSPregs[DEST_REG].upper.f = (float) mv_getReg64int (SRC1_REG);
810 	  break;
811 
812 	case 7: /* cfcvt64d */
813 	  printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
814 		     DEST_REG,
815 		     SRC1_REG,
816 		     (double) mv_getReg64int (SRC1_REG));
817 	  mv_setRegDouble (DEST_REG, (double) mv_getReg64int (SRC1_REG));
818 	  break;
819 	}
820       break;
821 
822     case 1:
823       switch (opcode2)
824 	{
825 	case 0: /* cfmuls */
826 	  printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
827 		     DEST_REG,
828 		     SRC1_REG,
829 		     DSPregs[SRC1_REG].upper.f * DSPregs[SRC2_REG].upper.f);
830 
831 	  DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
832 	    * DSPregs[SRC2_REG].upper.f;
833 	  break;
834 
835 	case 1: /* cfmuld */
836 	  printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
837 		     DEST_REG,
838 		     SRC1_REG,
839 		     mv_getRegDouble (SRC1_REG) * mv_getRegDouble (SRC2_REG));
840 
841 	  mv_setRegDouble (DEST_REG,
842 			   mv_getRegDouble (SRC1_REG)
843 			   * mv_getRegDouble (SRC2_REG));
844 	  break;
845 
846 	default:
847 	  fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
848 	  cirrus_not_implemented ("unknown");
849 	  break;
850 	}
851       break;
852 
853     case 3:
854       switch (opcode2)
855 	{
856 	case 0: /* cfabss */
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",
861 		     DEST_REG,
862 		     SRC1_REG,
863 		     DSPregs[DEST_REG].upper.f);
864 	  break;
865 
866 	case 1: /* cfabsd */
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",
872 		     DEST_REG,
873 		     SRC1_REG,
874 		     mv_getRegDouble (DEST_REG));
875 	  break;
876 
877 	case 2: /* cfnegs */
878 	  DSPregs[DEST_REG].upper.f = -DSPregs[SRC1_REG].upper.f;
879 	  printfdbg ("cfnegs mvf%d = -mvf%d = %f\n",
880 		     DEST_REG,
881 		     SRC1_REG,
882 		     DSPregs[DEST_REG].upper.f);
883 	  break;
884 
885 	case 3: /* cfnegd */
886 	  mv_setRegDouble (DEST_REG,
887 			   -mv_getRegDouble (SRC1_REG));
888 	  printfdbg ("cfnegd mvd%d = -mvd%d = %g\n",
889 		     DEST_REG,
890 		     mv_getRegDouble (DEST_REG));
891 	  break;
892 
893 	case 4: /* cfadds */
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",
897 		     DEST_REG,
898 		     SRC1_REG,
899 		     SRC2_REG,
900 		     DSPregs[DEST_REG].upper.f);
901 	  break;
902 
903 	case 5: /* cfaddd */
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",
908 		     DEST_REG,
909 		     SRC1_REG,
910 		     SRC2_REG,
911 		     mv_getRegDouble (DEST_REG));
912 	  break;
913 
914 	case 6: /* cfsubs */
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",
918 		     DEST_REG,
919 		     SRC1_REG,
920 		     SRC2_REG,
921 		     DSPregs[DEST_REG].upper.f);
922 	  break;
923 
924 	case 7: /* cfsubd */
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",
929 		     DEST_REG,
930 		     SRC1_REG,
931 		     SRC2_REG,
932 		     mv_getRegDouble (DEST_REG));
933 	  break;
934 	}
935       break;
936 
937     default:
938       fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
939       cirrus_not_implemented ("unknown");
940       break;
941     }
942 
943   return ARMul_DONE;
944 }
945 
946 unsigned
947 DSPCDP5 (ARMul_State * state,
948 	 unsigned      type,
949 	 ARMword       instr)
950 {
951    int opcode2;
952    char shift;
953 
954    opcode2 = BITS (5,7);
955 
956    /* Shift constants are 7bit signed numbers in bits 0..3|5..7.  */
957    shift = BITS (0, 3) | (BITS (5, 7)) << 4;
958    if (shift & 0x40)
959      shift |= 0xc0;
960 
961    switch (BITS (20,21))
962      {
963      case 0:
964        /* cfsh32 */
965        printfdbg ("cfsh32 %s amount=%d\n", shift < 0 ? "right" : "left",
966 		  shift);
967        if (shift < 0)
968 	 /* Negative shift is a right shift.  */
969 	 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -shift;
970        else
971 	 /* Positive shift is a left shift.  */
972 	 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i << shift;
973        break;
974 
975      case 1:
976        switch (opcode2)
977          {
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",
982 		      DEST_REG,
983 		      SRC1_REG,
984 		      SRC2_REG,
985 		      DSPregs[DEST_REG].lower.i);
986            break;
987 
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",
993 		      DEST_REG,
994 		      SRC1_REG,
995 		      SRC2_REG,
996 		      mv_getReg64int (DEST_REG));
997            break;
998 
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",
1003 		      DEST_REG,
1004 		      SRC1_REG,
1005 		      SRC2_REG,
1006 		      DSPregs[DEST_REG].lower.i);
1007            break;
1008 
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",
1013 		      DEST_REG,
1014 		      SRC1_REG,
1015 		      SRC2_REG,
1016 		      DSPregs[DEST_REG].lower.i);
1017            break;
1018 
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",
1023 		      DEST_REG,
1024 		      SRC1_REG,
1025 		      DSPregs[DEST_REG].lower.i);
1026            break;
1027 
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",
1032 		      DEST_REG,
1033 		      SRC1_REG,
1034 		      DSPregs[DEST_REG].lower.i);
1035            break;
1036 
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",
1040 		      DEST_REG,
1041 		      SRC1_REG,
1042 		      DSPregs[DEST_REG].lower.i);
1043            break;
1044 
1045          case 7: /* cftruncd32 */
1046 	   DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
1047 	   printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
1048 		      DEST_REG,
1049 		      SRC1_REG,
1050 		      DSPregs[DEST_REG].lower.i);
1051            break;
1052          }
1053        break;
1054 
1055      case 2:
1056        /* cfsh64 */
1057        printfdbg ("cfsh64\n");
1058 
1059        if (shift < 0)
1060 	 /* Negative shift is a right shift.  */
1061 	 mv_setReg64int (DEST_REG,
1062 			 mv_getReg64int (SRC1_REG) >> -shift);
1063        else
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));
1068        break;
1069 
1070      case 3:
1071        switch (opcode2)
1072          {
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",
1077 		      DEST_REG,
1078 		      SRC1_REG,
1079 		      SRC2_REG,
1080 		      DSPregs[DEST_REG].lower.i);
1081            break;
1082 
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",
1089 		      DEST_REG,
1090 		      SRC1_REG,
1091 		      SRC2_REG,
1092 		      mv_getReg64int (DEST_REG));
1093            break;
1094 
1095          case 2: /* cfneg32 */
1096 	   DSPregs[DEST_REG].lower.i = -DSPregs[SRC1_REG].lower.i;
1097 	   printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
1098 		      DEST_REG,
1099 		      SRC1_REG,
1100 		      SRC2_REG,
1101 		      DSPregs[DEST_REG].lower.i);
1102            break;
1103 
1104          case 3: /* cfneg64 */
1105 	   mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG));
1106 	   printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
1107 		      DEST_REG,
1108 		      SRC1_REG,
1109 		      SRC2_REG,
1110 		      mv_getReg64int (DEST_REG));
1111            break;
1112 
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",
1117 		      DEST_REG,
1118 		      SRC1_REG,
1119 		      SRC2_REG,
1120 		      DSPregs[DEST_REG].lower.i);
1121            break;
1122 
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",
1128 		      DEST_REG,
1129 		      SRC1_REG,
1130 		      SRC2_REG,
1131 		      mv_getReg64int (DEST_REG));
1132            break;
1133 
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",
1138 		      DEST_REG,
1139 		      SRC1_REG,
1140 		      SRC2_REG,
1141 		      DSPregs[DEST_REG].lower.i);
1142            break;
1143 
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",
1149 		      DEST_REG,
1150 		      SRC1_REG,
1151 		      SRC2_REG,
1152 		      mv_getReg64int (DEST_REG));
1153            break;
1154          }
1155        break;
1156 
1157      default:
1158        fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr);
1159        cirrus_not_implemented ("unknown");
1160        break;
1161      }
1162 
1163   return ARMul_DONE;
1164 }
1165 
1166 unsigned
1167 DSPCDP6 (ARMul_State * state,
1168 	 unsigned      type,
1169 	 ARMword       instr)
1170 {
1171    int opcode2;
1172 
1173    opcode2 = BITS (5,7);
1174 
1175    switch (BITS (20,21))
1176      {
1177      case 0:
1178        /* cfmadd32 */
1179        cirrus_not_implemented ("cfmadd32");
1180        break;
1181 
1182      case 1:
1183        /* cfmsub32 */
1184        cirrus_not_implemented ("cfmsub32");
1185        break;
1186 
1187      case 2:
1188        /* cfmadda32 */
1189        cirrus_not_implemented ("cfmadda32");
1190        break;
1191 
1192      case 3:
1193        /* cfmsuba32 */
1194        cirrus_not_implemented ("cfmsuba32");
1195        break;
1196 
1197      default:
1198        fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr);
1199      }
1200 
1201    return ARMul_DONE;
1202 }
1203 
1204 /* Conversion functions.
1205 
1206    32-bit integers are stored in the LOWER half of a 64-bit physical
1207    register.
1208 
1209    Single precision floats are stored in the UPPER half of a 64-bit
1210    physical register.  */
1211 
1212 static double
1213 mv_getRegDouble (int regnum)
1214 {
1215   reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i;
1216   reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i;
1217   return reg_conv.d;
1218 }
1219 
1220 static void
1221 mv_setRegDouble (int regnum, double val)
1222 {
1223   reg_conv.d = val;
1224   DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index];
1225   DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index];
1226 }
1227 
1228 static long long
1229 mv_getReg64int (int regnum)
1230 {
1231   reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i;
1232   reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i;
1233   return reg_conv.ll;
1234 }
1235 
1236 static void
1237 mv_setReg64int (int regnum, long long val)
1238 {
1239   reg_conv.ll = val;
1240   DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index];
1241   DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index];
1242 }
1243 
1244 /* Compute LSW in a double and a long long.  */
1245 
1246 void
1247 mv_compute_host_endianness (ARMul_State * state)
1248 {
1249   static union
1250   {
1251     long long ll;
1252     long ints[2];
1253     long i;
1254     double d;
1255     float floats[2];
1256     float f;
1257   } conv;
1258 
1259   /* Calculate where's the LSW in a 64bit int.  */
1260   conv.ll = 45;
1261 
1262   if (conv.ints[0] == 0)
1263     {
1264       msw_int_index = 0;
1265       lsw_int_index = 1;
1266     }
1267   else
1268     {
1269       assert (conv.ints[1] == 0);
1270       msw_int_index = 1;
1271       lsw_int_index = 0;
1272     }
1273 
1274   /* Calculate where's the LSW in a double.  */
1275   conv.d = 3.0;
1276 
1277   if (conv.ints[0] == 0)
1278     {
1279       msw_float_index = 0;
1280       lsw_float_index = 1;
1281     }
1282   else
1283     {
1284       assert (conv.ints[1] == 0);
1285       msw_float_index = 1;
1286       lsw_float_index = 0;
1287     }
1288 
1289   printfdbg ("lsw_int_index   %d\n", lsw_int_index);
1290   printfdbg ("lsw_float_index %d\n", lsw_float_index);
1291 }
1292