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