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