OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [sim/] [arm/] [maverick.c] - Diff between revs 24 and 157

Only display areas with differences | Details | Blame | View Log

Rev 24 Rev 157
/*  maverick.c -- Cirrus/DSP co-processor interface.
/*  maverick.c -- Cirrus/DSP co-processor interface.
    Copyright (C) 2003, 2007, 2008 Free Software Foundation, Inc.
    Copyright (C) 2003, 2007, 2008 Free Software Foundation, Inc.
    Contributed by Aldy Hernandez (aldyh@redhat.com).
    Contributed by Aldy Hernandez (aldyh@redhat.com).
 
 
    This program is free software; you can redistribute it and/or modify
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    (at your option) any later version.
 
 
    This program is distributed in the hope that it will be useful,
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    GNU General Public License for more details.
 
 
    You should have received a copy of the GNU General Public License
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 
#include <assert.h>
#include <assert.h>
#include "armdefs.h"
#include "armdefs.h"
#include "ansidecl.h"
#include "ansidecl.h"
#include "armemu.h"
#include "armemu.h"
 
 
/*#define CIRRUS_DEBUG 1        /**/
/*#define CIRRUS_DEBUG 1        /**/
#if CIRRUS_DEBUG
#if CIRRUS_DEBUG
#  define printfdbg printf
#  define printfdbg printf
#else
#else
#  define printfdbg printf_nothing
#  define printfdbg printf_nothing
#endif
#endif
 
 
#define POS64(i) ( (~(i)) >> 63 )
#define POS64(i) ( (~(i)) >> 63 )
#define NEG64(i) ( (i) >> 63 )
#define NEG64(i) ( (i) >> 63 )
 
 
/* Define Co-Processor instruction handlers here.  */
/* Define Co-Processor instruction handlers here.  */
 
 
/* Here's ARMulator's DSP definition.  A few things to note:
/* Here's ARMulator's DSP definition.  A few things to note:
   1) it has 16 64-bit registers and 4 72-bit accumulators
   1) it has 16 64-bit registers and 4 72-bit accumulators
   2) you can only access its registers with MCR and MRC.  */
   2) you can only access its registers with MCR and MRC.  */
 
 
/* We can't define these in here because this file might not be linked
/* We can't define these in here because this file might not be linked
   unless the target is arm9e-*.  They are defined in wrapper.c.
   unless the target is arm9e-*.  They are defined in wrapper.c.
   Eventually the simulator should be made to handle any coprocessor
   Eventually the simulator should be made to handle any coprocessor
   at run time.  */
   at run time.  */
struct maverick_regs
struct maverick_regs
{
{
  union
  union
  {
  {
    int i;
    int i;
    float f;
    float f;
  } upper;
  } upper;
 
 
  union
  union
  {
  {
    int i;
    int i;
    float f;
    float f;
  } lower;
  } lower;
};
};
 
 
union maverick_acc_regs
union maverick_acc_regs
{
{
  long double ld;               /* Acc registers are 72-bits.  */
  long double ld;               /* Acc registers are 72-bits.  */
};
};
 
 
struct maverick_regs DSPregs[16];
struct maverick_regs DSPregs[16];
union maverick_acc_regs DSPacc[4];
union maverick_acc_regs DSPacc[4];
ARMword DSPsc;
ARMword DSPsc;
 
 
#define DEST_REG        (BITS (12, 15))
#define DEST_REG        (BITS (12, 15))
#define SRC1_REG        (BITS (16, 19))
#define SRC1_REG        (BITS (16, 19))
#define SRC2_REG        (BITS (0, 3))
#define SRC2_REG        (BITS (0, 3))
 
 
static int lsw_int_index, msw_int_index;
static int lsw_int_index, msw_int_index;
static int lsw_float_index, msw_float_index;
static int lsw_float_index, msw_float_index;
 
 
static double mv_getRegDouble (int);
static double mv_getRegDouble (int);
static long long mv_getReg64int (int);
static long long mv_getReg64int (int);
static void mv_setRegDouble (int, double val);
static void mv_setRegDouble (int, double val);
static void mv_setReg64int (int, long long val);
static void mv_setReg64int (int, long long val);
 
 
static union
static union
{
{
  double d;
  double d;
  long long ll;
  long long ll;
  int ints[2];
  int ints[2];
} reg_conv;
} reg_conv;
 
 
static void
static void
printf_nothing (void * foo, ...)
printf_nothing (void * foo, ...)
{
{
}
}
 
 
static void
static void
cirrus_not_implemented (char * insn)
cirrus_not_implemented (char * insn)
{
{
  fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn);
  fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn);
  fprintf (stderr, "aborting!\n");
  fprintf (stderr, "aborting!\n");
 
 
  exit (1);
  exit (1);
}
}
 
 
static unsigned
static unsigned
DSPInit (ARMul_State * state)
DSPInit (ARMul_State * state)
{
{
  ARMul_ConsolePrint (state, ", DSP present");
  ARMul_ConsolePrint (state, ", DSP present");
  return TRUE;
  return TRUE;
}
}
 
 
unsigned
unsigned
DSPMRC4 (ARMul_State * state ATTRIBUTE_UNUSED,
DSPMRC4 (ARMul_State * state ATTRIBUTE_UNUSED,
         unsigned      type  ATTRIBUTE_UNUSED,
         unsigned      type  ATTRIBUTE_UNUSED,
         ARMword       instr,
         ARMword       instr,
         ARMword *     value)
         ARMword *     value)
{
{
  switch (BITS (5, 7))
  switch (BITS (5, 7))
    {
    {
    case 0: /* cfmvrdl */
    case 0: /* cfmvrdl */
      /* Move lower half of a DF stored in a DSP reg into an Arm reg.  */
      /* Move lower half of a DF stored in a DSP reg into an Arm reg.  */
      printfdbg ("cfmvrdl\n");
      printfdbg ("cfmvrdl\n");
      printfdbg ("\tlower half=0x%x\n", DSPregs[SRC1_REG].lower.i);
      printfdbg ("\tlower half=0x%x\n", DSPregs[SRC1_REG].lower.i);
      printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
      printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
 
 
      *value = (ARMword) DSPregs[SRC1_REG].lower.i;
      *value = (ARMword) DSPregs[SRC1_REG].lower.i;
      break;
      break;
 
 
    case 1: /* cfmvrdh */
    case 1: /* cfmvrdh */
      /* Move upper half of a DF stored in a DSP reg into an Arm reg.  */
      /* Move upper half of a DF stored in a DSP reg into an Arm reg.  */
      printfdbg ("cfmvrdh\n");
      printfdbg ("cfmvrdh\n");
      printfdbg ("\tupper half=0x%x\n", DSPregs[SRC1_REG].upper.i);
      printfdbg ("\tupper half=0x%x\n", DSPregs[SRC1_REG].upper.i);
      printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
      printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
 
 
      *value = (ARMword) DSPregs[SRC1_REG].upper.i;
      *value = (ARMword) DSPregs[SRC1_REG].upper.i;
      break;
      break;
 
 
    case 2: /* cfmvrs */
    case 2: /* cfmvrs */
      /* Move SF from upper half of a DSP register to an Arm register.  */
      /* Move SF from upper half of a DSP register to an Arm register.  */
      *value = (ARMword) DSPregs[SRC1_REG].upper.i;
      *value = (ARMword) DSPregs[SRC1_REG].upper.i;
      printfdbg ("cfmvrs = mvf%d <-- %f\n",
      printfdbg ("cfmvrs = mvf%d <-- %f\n",
                 SRC1_REG,
                 SRC1_REG,
                 DSPregs[SRC1_REG].upper.f);
                 DSPregs[SRC1_REG].upper.f);
      break;
      break;
 
 
#ifdef doesnt_work
#ifdef doesnt_work
    case 4: /* cfcmps */
    case 4: /* cfcmps */
      {
      {
        float a, b;
        float a, b;
        int n, z, c, v;
        int n, z, c, v;
 
 
        a = DSPregs[SRC1_REG].upper.f;
        a = DSPregs[SRC1_REG].upper.f;
        b = DSPregs[SRC2_REG].upper.f;
        b = DSPregs[SRC2_REG].upper.f;
 
 
        printfdbg ("cfcmps\n");
        printfdbg ("cfcmps\n");
        printfdbg ("\tcomparing %f and %f\n", a, b);
        printfdbg ("\tcomparing %f and %f\n", a, b);
 
 
        z = a == b;             /* zero */
        z = a == b;             /* zero */
        n = a != b;             /* negative */
        n = a != b;             /* negative */
        v = a > b;              /* overflow */
        v = a > b;              /* overflow */
        c = 0;                   /* carry */
        c = 0;                   /* carry */
        *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
        *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
        break;
        break;
      }
      }
 
 
    case 5: /* cfcmpd */
    case 5: /* cfcmpd */
      {
      {
        double a, b;
        double a, b;
        int n, z, c, v;
        int n, z, c, v;
 
 
        a = mv_getRegDouble (SRC1_REG);
        a = mv_getRegDouble (SRC1_REG);
        b = mv_getRegDouble (SRC2_REG);
        b = mv_getRegDouble (SRC2_REG);
 
 
        printfdbg ("cfcmpd\n");
        printfdbg ("cfcmpd\n");
        printfdbg ("\tcomparing %g and %g\n", a, b);
        printfdbg ("\tcomparing %g and %g\n", a, b);
 
 
        z = a == b;             /* zero */
        z = a == b;             /* zero */
        n = a != b;             /* negative */
        n = a != b;             /* negative */
        v = a > b;              /* overflow */
        v = a > b;              /* overflow */
        c = 0;                   /* carry */
        c = 0;                   /* carry */
        *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
        *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
        break;
        break;
      }
      }
#else
#else
      case 4: /* cfcmps */
      case 4: /* cfcmps */
        {
        {
          float a, b;
          float a, b;
          int n, z, c, v;
          int n, z, c, v;
 
 
          a = DSPregs[SRC1_REG].upper.f;
          a = DSPregs[SRC1_REG].upper.f;
          b = DSPregs[SRC2_REG].upper.f;
          b = DSPregs[SRC2_REG].upper.f;
 
 
          printfdbg ("cfcmps\n");
          printfdbg ("cfcmps\n");
          printfdbg ("\tcomparing %f and %f\n", a, b);
          printfdbg ("\tcomparing %f and %f\n", a, b);
 
 
          z = a == b;           /* zero */
          z = a == b;           /* zero */
          n = a < b;            /* negative */
          n = a < b;            /* negative */
          c = a > b;            /* carry */
          c = a > b;            /* carry */
          v = 0;         /* fixme */
          v = 0;         /* fixme */
          printfdbg ("\tz = %d, n = %d\n", z, n);
          printfdbg ("\tz = %d, n = %d\n", z, n);
          *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
          *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
          break;
          break;
        }
        }
 
 
      case 5: /* cfcmpd */
      case 5: /* cfcmpd */
        {
        {
          double a, b;
          double a, b;
          int n, z, c, v;
          int n, z, c, v;
 
 
          a = mv_getRegDouble (SRC1_REG);
          a = mv_getRegDouble (SRC1_REG);
          b = mv_getRegDouble (SRC2_REG);
          b = mv_getRegDouble (SRC2_REG);
 
 
          printfdbg ("cfcmpd\n");
          printfdbg ("cfcmpd\n");
          printfdbg ("\tcomparing %g and %g\n", a, b);
          printfdbg ("\tcomparing %g and %g\n", a, b);
 
 
          z = a == b;           /* zero */
          z = a == b;           /* zero */
          n = a < b;            /* negative */
          n = a < b;            /* negative */
          c = a > b;            /* carry */
          c = a > b;            /* carry */
          v = 0;         /* fixme */
          v = 0;         /* fixme */
          *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
          *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
          break;
          break;
        }
        }
#endif
#endif
    default:
    default:
      fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr);
      fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr);
      cirrus_not_implemented ("unknown");
      cirrus_not_implemented ("unknown");
      break;
      break;
    }
    }
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
unsigned
unsigned
DSPMRC5 (ARMul_State * state ATTRIBUTE_UNUSED,
DSPMRC5 (ARMul_State * state ATTRIBUTE_UNUSED,
         unsigned      type  ATTRIBUTE_UNUSED,
         unsigned      type  ATTRIBUTE_UNUSED,
         ARMword       instr,
         ARMword       instr,
         ARMword *     value)
         ARMword *     value)
{
{
  switch (BITS (5, 7))
  switch (BITS (5, 7))
    {
    {
    case 0: /* cfmvr64l */
    case 0: /* cfmvr64l */
      /* Move lower half of 64bit int from Cirrus to Arm.  */
      /* Move lower half of 64bit int from Cirrus to Arm.  */
      *value = (ARMword) DSPregs[SRC1_REG].lower.i;
      *value = (ARMword) DSPregs[SRC1_REG].lower.i;
      printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n",
      printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n",
                 DEST_REG,
                 DEST_REG,
                 (int) *value);
                 (int) *value);
      break;
      break;
 
 
    case 1: /* cfmvr64h */
    case 1: /* cfmvr64h */
      /* Move upper half of 64bit int from Cirrus to Arm.  */
      /* Move upper half of 64bit int from Cirrus to Arm.  */
      *value = (ARMword) DSPregs[SRC1_REG].upper.i;
      *value = (ARMword) DSPregs[SRC1_REG].upper.i;
      printfdbg ("cfmvr64h <-- %d\n", (int) *value);
      printfdbg ("cfmvr64h <-- %d\n", (int) *value);
      break;
      break;
 
 
    case 4: /* cfcmp32 */
    case 4: /* cfcmp32 */
      {
      {
        int res;
        int res;
        int n, z, c, v;
        int n, z, c, v;
        unsigned int a, b;
        unsigned int a, b;
 
 
        printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
        printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
                   SRC1_REG,
                   SRC1_REG,
                   SRC2_REG);
                   SRC2_REG);
 
 
        /* FIXME: see comment for cfcmps.  */
        /* FIXME: see comment for cfcmps.  */
        a = DSPregs[SRC1_REG].lower.i;
        a = DSPregs[SRC1_REG].lower.i;
        b = DSPregs[SRC2_REG].lower.i;
        b = DSPregs[SRC2_REG].lower.i;
 
 
        res = DSPregs[SRC1_REG].lower.i - DSPregs[SRC2_REG].lower.i;
        res = DSPregs[SRC1_REG].lower.i - DSPregs[SRC2_REG].lower.i;
        /* zero */
        /* zero */
        z = res == 0;
        z = res == 0;
        /* negative */
        /* negative */
        n = res < 0;
        n = res < 0;
        /* overflow */
        /* overflow */
        v = SubOverflow (DSPregs[SRC1_REG].lower.i, DSPregs[SRC2_REG].lower.i,
        v = SubOverflow (DSPregs[SRC1_REG].lower.i, DSPregs[SRC2_REG].lower.i,
                         res);
                         res);
        /* carry */
        /* carry */
        c = (NEG (a) && POS (b) ||
        c = (NEG (a) && POS (b) ||
             (NEG (a) && POS (res)) || (POS (b) && POS (res)));
             (NEG (a) && POS (res)) || (POS (b) && POS (res)));
 
 
        *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
        *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
        break;
        break;
      }
      }
 
 
    case 5: /* cfcmp64 */
    case 5: /* cfcmp64 */
      {
      {
        long long res;
        long long res;
        int n, z, c, v;
        int n, z, c, v;
        unsigned long long a, b;
        unsigned long long a, b;
 
 
        printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
        printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
                   SRC1_REG,
                   SRC1_REG,
                   SRC2_REG);
                   SRC2_REG);
 
 
        /* fixme: see comment for cfcmps.  */
        /* fixme: see comment for cfcmps.  */
 
 
        a = mv_getReg64int (SRC1_REG);
        a = mv_getReg64int (SRC1_REG);
        b = mv_getReg64int (SRC2_REG);
        b = mv_getReg64int (SRC2_REG);
 
 
        res = mv_getReg64int (SRC1_REG) - mv_getReg64int (SRC2_REG);
        res = mv_getReg64int (SRC1_REG) - mv_getReg64int (SRC2_REG);
        /* zero */
        /* zero */
        z = res == 0;
        z = res == 0;
        /* negative */
        /* negative */
        n = res < 0;
        n = res < 0;
        /* overflow */
        /* overflow */
        v = ((NEG64 (a) && POS64 (b) && POS64 (res))
        v = ((NEG64 (a) && POS64 (b) && POS64 (res))
             || (POS64 (a) && NEG64 (b) && NEG64 (res)));
             || (POS64 (a) && NEG64 (b) && NEG64 (res)));
        /* carry */
        /* carry */
        c = (NEG64 (a) && POS64 (b) ||
        c = (NEG64 (a) && POS64 (b) ||
             (NEG64 (a) && POS64 (res)) || (POS64 (b) && POS64 (res)));
             (NEG64 (a) && POS64 (res)) || (POS64 (b) && POS64 (res)));
 
 
        *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
        *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
        break;
        break;
      }
      }
 
 
    default:
    default:
      fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr);
      fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr);
      cirrus_not_implemented ("unknown");
      cirrus_not_implemented ("unknown");
      break;
      break;
    }
    }
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
unsigned
unsigned
DSPMRC6 (ARMul_State * state ATTRIBUTE_UNUSED,
DSPMRC6 (ARMul_State * state ATTRIBUTE_UNUSED,
         unsigned      type  ATTRIBUTE_UNUSED,
         unsigned      type  ATTRIBUTE_UNUSED,
         ARMword       instr,
         ARMword       instr,
         ARMword *     value)
         ARMword *     value)
{
{
  switch (BITS (5, 7))
  switch (BITS (5, 7))
    {
    {
    case 0: /* cfmval32 */
    case 0: /* cfmval32 */
      cirrus_not_implemented ("cfmval32");
      cirrus_not_implemented ("cfmval32");
      break;
      break;
 
 
    case 1: /* cfmvam32 */
    case 1: /* cfmvam32 */
      cirrus_not_implemented ("cfmvam32");
      cirrus_not_implemented ("cfmvam32");
      break;
      break;
 
 
    case 2: /* cfmvah32 */
    case 2: /* cfmvah32 */
      cirrus_not_implemented ("cfmvah32");
      cirrus_not_implemented ("cfmvah32");
      break;
      break;
 
 
    case 3: /* cfmva32 */
    case 3: /* cfmva32 */
      cirrus_not_implemented ("cfmva32");
      cirrus_not_implemented ("cfmva32");
      break;
      break;
 
 
    case 4: /* cfmva64 */
    case 4: /* cfmva64 */
      cirrus_not_implemented ("cfmva64");
      cirrus_not_implemented ("cfmva64");
      break;
      break;
 
 
    case 5: /* cfmvsc32 */
    case 5: /* cfmvsc32 */
      cirrus_not_implemented ("cfmvsc32");
      cirrus_not_implemented ("cfmvsc32");
      break;
      break;
 
 
    default:
    default:
      fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr);
      fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr);
      cirrus_not_implemented ("unknown");
      cirrus_not_implemented ("unknown");
      break;
      break;
    }
    }
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
unsigned
unsigned
DSPMCR4 (ARMul_State * state,
DSPMCR4 (ARMul_State * state,
         unsigned      type ATTRIBUTE_UNUSED,
         unsigned      type ATTRIBUTE_UNUSED,
         ARMword       instr,
         ARMword       instr,
         ARMword       value)
         ARMword       value)
{
{
  switch (BITS (5, 7))
  switch (BITS (5, 7))
    {
    {
    case 0: /* cfmvdlr */
    case 0: /* cfmvdlr */
      /* Move the lower half of a DF value from an Arm register into
      /* Move the lower half of a DF value from an Arm register into
         the lower half of a Cirrus register.  */
         the lower half of a Cirrus register.  */
      printfdbg ("cfmvdlr <-- 0x%x\n", (int) value);
      printfdbg ("cfmvdlr <-- 0x%x\n", (int) value);
      DSPregs[SRC1_REG].lower.i = (int) value;
      DSPregs[SRC1_REG].lower.i = (int) value;
      break;
      break;
 
 
    case 1: /* cfmvdhr */
    case 1: /* cfmvdhr */
      /* Move the upper half of a DF value from an Arm register into
      /* Move the upper half of a DF value from an Arm register into
         the upper half of a Cirrus register.  */
         the upper half of a Cirrus register.  */
      printfdbg ("cfmvdhr <-- 0x%x\n", (int) value);
      printfdbg ("cfmvdhr <-- 0x%x\n", (int) value);
      DSPregs[SRC1_REG].upper.i = (int) value;
      DSPregs[SRC1_REG].upper.i = (int) value;
      break;
      break;
 
 
    case 2: /* cfmvsr */
    case 2: /* cfmvsr */
      /* Move SF from Arm register into upper half of Cirrus register.  */
      /* Move SF from Arm register into upper half of Cirrus register.  */
      printfdbg ("cfmvsr <-- 0x%x\n", (int) value);
      printfdbg ("cfmvsr <-- 0x%x\n", (int) value);
      DSPregs[SRC1_REG].upper.i = (int) value;
      DSPregs[SRC1_REG].upper.i = (int) value;
      break;
      break;
 
 
    default:
    default:
      fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr);
      fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr);
      cirrus_not_implemented ("unknown");
      cirrus_not_implemented ("unknown");
      break;
      break;
    }
    }
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
unsigned
unsigned
DSPMCR5 (ARMul_State * state,
DSPMCR5 (ARMul_State * state,
         unsigned      type   ATTRIBUTE_UNUSED,
         unsigned      type   ATTRIBUTE_UNUSED,
         ARMword       instr,
         ARMword       instr,
         ARMword       value)
         ARMword       value)
{
{
  union
  union
  {
  {
    int s;
    int s;
    unsigned int us;
    unsigned int us;
  } val;
  } val;
 
 
  switch (BITS (5, 7))
  switch (BITS (5, 7))
    {
    {
    case 0: /* cfmv64lr */
    case 0: /* cfmv64lr */
      /* Move lower half of a 64bit int from an ARM register into the
      /* Move lower half of a 64bit int from an ARM register into the
         lower half of a DSP register and sign extend it.  */
         lower half of a DSP register and sign extend it.  */
      printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG, (int) value);
      printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG, (int) value);
      DSPregs[SRC1_REG].lower.i = (int) value;
      DSPregs[SRC1_REG].lower.i = (int) value;
      break;
      break;
 
 
    case 1: /* cfmv64hr */
    case 1: /* cfmv64hr */
      /* Move upper half of a 64bit int from an ARM register into the
      /* Move upper half of a 64bit int from an ARM register into the
         upper half of a DSP register.  */
         upper half of a DSP register.  */
      printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n",
      printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n",
                 SRC1_REG,
                 SRC1_REG,
                 (int) value);
                 (int) value);
      DSPregs[SRC1_REG].upper.i = (int) value;
      DSPregs[SRC1_REG].upper.i = (int) value;
      break;
      break;
 
 
    case 2: /* cfrshl32 */
    case 2: /* cfrshl32 */
      printfdbg ("cfrshl32\n");
      printfdbg ("cfrshl32\n");
      val.us = value;
      val.us = value;
      if (val.s > 0)
      if (val.s > 0)
        DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i << value;
        DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i << value;
      else
      else
        DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -value;
        DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -value;
      break;
      break;
 
 
    case 3: /* cfrshl64 */
    case 3: /* cfrshl64 */
      printfdbg ("cfrshl64\n");
      printfdbg ("cfrshl64\n");
      val.us = value;
      val.us = value;
      if (val.s > 0)
      if (val.s > 0)
        mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) << value);
        mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) << value);
      else
      else
        mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) >> -value);
        mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) >> -value);
      break;
      break;
 
 
    default:
    default:
      fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr);
      fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr);
      cirrus_not_implemented ("unknown");
      cirrus_not_implemented ("unknown");
      break;
      break;
    }
    }
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
unsigned
unsigned
DSPMCR6 (ARMul_State * state,
DSPMCR6 (ARMul_State * state,
         unsigned      type   ATTRIBUTE_UNUSED,
         unsigned      type   ATTRIBUTE_UNUSED,
         ARMword       instr,
         ARMword       instr,
         ARMword       value)
         ARMword       value)
{
{
  switch (BITS (5, 7))
  switch (BITS (5, 7))
    {
    {
    case 0: /* cfmv32al */
    case 0: /* cfmv32al */
      cirrus_not_implemented ("cfmv32al");
      cirrus_not_implemented ("cfmv32al");
      break;
      break;
 
 
    case 1: /* cfmv32am */
    case 1: /* cfmv32am */
      cirrus_not_implemented ("cfmv32am");
      cirrus_not_implemented ("cfmv32am");
      break;
      break;
 
 
    case 2: /* cfmv32ah */
    case 2: /* cfmv32ah */
      cirrus_not_implemented ("cfmv32ah");
      cirrus_not_implemented ("cfmv32ah");
      break;
      break;
 
 
    case 3: /* cfmv32a */
    case 3: /* cfmv32a */
      cirrus_not_implemented ("cfmv32a");
      cirrus_not_implemented ("cfmv32a");
      break;
      break;
 
 
    case 4: /* cfmv64a */
    case 4: /* cfmv64a */
      cirrus_not_implemented ("cfmv64a");
      cirrus_not_implemented ("cfmv64a");
      break;
      break;
 
 
    case 5: /* cfmv32sc */
    case 5: /* cfmv32sc */
      cirrus_not_implemented ("cfmv32sc");
      cirrus_not_implemented ("cfmv32sc");
      break;
      break;
 
 
    default:
    default:
      fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr);
      fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr);
      cirrus_not_implemented ("unknown");
      cirrus_not_implemented ("unknown");
      break;
      break;
    }
    }
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
unsigned
unsigned
DSPLDC4 (ARMul_State * state ATTRIBUTE_UNUSED,
DSPLDC4 (ARMul_State * state ATTRIBUTE_UNUSED,
         unsigned      type,
         unsigned      type,
         ARMword       instr,
         ARMword       instr,
         ARMword       data)
         ARMword       data)
{
{
  static unsigned words;
  static unsigned words;
 
 
  if (type != ARMul_DATA)
  if (type != ARMul_DATA)
    {
    {
      words = 0;
      words = 0;
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  if (BIT (22))
  if (BIT (22))
    {                           /* it's a long access, get two words */
    {                           /* it's a long access, get two words */
      /* cfldrd */
      /* cfldrd */
 
 
      printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
      printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
                 data, words, state->bigendSig, DEST_REG);
                 data, words, state->bigendSig, DEST_REG);
 
 
      if (words == 0)
      if (words == 0)
        {
        {
          if (state->bigendSig)
          if (state->bigendSig)
            DSPregs[DEST_REG].upper.i = (int) data;
            DSPregs[DEST_REG].upper.i = (int) data;
          else
          else
            DSPregs[DEST_REG].lower.i = (int) data;
            DSPregs[DEST_REG].lower.i = (int) data;
        }
        }
      else
      else
        {
        {
          if (state->bigendSig)
          if (state->bigendSig)
            DSPregs[DEST_REG].lower.i = (int) data;
            DSPregs[DEST_REG].lower.i = (int) data;
          else
          else
            DSPregs[DEST_REG].upper.i = (int) data;
            DSPregs[DEST_REG].upper.i = (int) data;
        }
        }
 
 
      ++ words;
      ++ words;
 
 
      if (words == 2)
      if (words == 2)
        {
        {
          printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG,
          printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG,
                     mv_getRegDouble (DEST_REG));
                     mv_getRegDouble (DEST_REG));
 
 
          return ARMul_DONE;
          return ARMul_DONE;
        }
        }
      else
      else
        return ARMul_INC;
        return ARMul_INC;
    }
    }
  else
  else
    {
    {
      /* Get just one word.  */
      /* Get just one word.  */
 
 
      /* cfldrs */
      /* cfldrs */
      printfdbg ("cfldrs\n");
      printfdbg ("cfldrs\n");
 
 
      DSPregs[DEST_REG].upper.i = (int) data;
      DSPregs[DEST_REG].upper.i = (int) data;
 
 
      printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG,
      printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG,
                 DSPregs[DEST_REG].upper.f);
                 DSPregs[DEST_REG].upper.f);
 
 
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
}
}
 
 
unsigned
unsigned
DSPLDC5 (ARMul_State * state ATTRIBUTE_UNUSED,
DSPLDC5 (ARMul_State * state ATTRIBUTE_UNUSED,
         unsigned      type,
         unsigned      type,
         ARMword       instr,
         ARMword       instr,
         ARMword       data)
         ARMword       data)
{
{
  static unsigned words;
  static unsigned words;
 
 
  if (type != ARMul_DATA)
  if (type != ARMul_DATA)
    {
    {
      words = 0;
      words = 0;
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  if (BIT (22))
  if (BIT (22))
    {
    {
      /* It's a long access, get two words.  */
      /* It's a long access, get two words.  */
 
 
      /* cfldr64 */
      /* cfldr64 */
      printfdbg ("cfldr64: %d\n", data);
      printfdbg ("cfldr64: %d\n", data);
 
 
      if (words == 0)
      if (words == 0)
        {
        {
          if (state->bigendSig)
          if (state->bigendSig)
            DSPregs[DEST_REG].upper.i = (int) data;
            DSPregs[DEST_REG].upper.i = (int) data;
          else
          else
            DSPregs[DEST_REG].lower.i = (int) data;
            DSPregs[DEST_REG].lower.i = (int) data;
        }
        }
      else
      else
        {
        {
          if (state->bigendSig)
          if (state->bigendSig)
            DSPregs[DEST_REG].lower.i = (int) data;
            DSPregs[DEST_REG].lower.i = (int) data;
          else
          else
            DSPregs[DEST_REG].upper.i = (int) data;
            DSPregs[DEST_REG].upper.i = (int) data;
        }
        }
 
 
      ++ words;
      ++ words;
 
 
      if (words == 2)
      if (words == 2)
        {
        {
          printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG,
          printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG,
                     mv_getReg64int (DEST_REG));
                     mv_getReg64int (DEST_REG));
 
 
          return ARMul_DONE;
          return ARMul_DONE;
        }
        }
      else
      else
        return ARMul_INC;
        return ARMul_INC;
    }
    }
  else
  else
    {
    {
      /* Get just one word.  */
      /* Get just one word.  */
 
 
      /* cfldr32 */
      /* cfldr32 */
      printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data);
      printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data);
 
 
      /* 32bit ints should be sign extended to 64bits when loaded.  */
      /* 32bit ints should be sign extended to 64bits when loaded.  */
      mv_setReg64int (DEST_REG, (long long) data);
      mv_setReg64int (DEST_REG, (long long) data);
 
 
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
}
}
 
 
unsigned
unsigned
DSPSTC4 (ARMul_State * state ATTRIBUTE_UNUSED,
DSPSTC4 (ARMul_State * state ATTRIBUTE_UNUSED,
         unsigned      type,
         unsigned      type,
         ARMword       instr,
         ARMword       instr,
         ARMword *     data)
         ARMword *     data)
{
{
  static unsigned words;
  static unsigned words;
 
 
  if (type != ARMul_DATA)
  if (type != ARMul_DATA)
    {
    {
      words = 0;
      words = 0;
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  if (BIT (22))
  if (BIT (22))
    {
    {
      /* It's a long access, get two words.  */
      /* It's a long access, get two words.  */
      /* cfstrd */
      /* cfstrd */
      printfdbg ("cfstrd\n");
      printfdbg ("cfstrd\n");
 
 
      if (words == 0)
      if (words == 0)
        {
        {
          if (state->bigendSig)
          if (state->bigendSig)
            *data = (ARMword) DSPregs[DEST_REG].upper.i;
            *data = (ARMword) DSPregs[DEST_REG].upper.i;
          else
          else
            *data = (ARMword) DSPregs[DEST_REG].lower.i;
            *data = (ARMword) DSPregs[DEST_REG].lower.i;
        }
        }
      else
      else
        {
        {
          if (state->bigendSig)
          if (state->bigendSig)
            *data = (ARMword) DSPregs[DEST_REG].lower.i;
            *data = (ARMword) DSPregs[DEST_REG].lower.i;
          else
          else
            *data = (ARMword) DSPregs[DEST_REG].upper.i;
            *data = (ARMword) DSPregs[DEST_REG].upper.i;
        }
        }
 
 
      ++ words;
      ++ words;
 
 
      if (words == 2)
      if (words == 2)
        {
        {
          printfdbg ("\tmem = mvd%d = %g\n", DEST_REG,
          printfdbg ("\tmem = mvd%d = %g\n", DEST_REG,
                     mv_getRegDouble (DEST_REG));
                     mv_getRegDouble (DEST_REG));
 
 
          return ARMul_DONE;
          return ARMul_DONE;
        }
        }
      else
      else
        return ARMul_INC;
        return ARMul_INC;
    }
    }
  else
  else
    {
    {
      /* Get just one word.  */
      /* Get just one word.  */
      /* cfstrs */
      /* cfstrs */
      printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG,
      printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG,
                 DSPregs[DEST_REG].upper.f);
                 DSPregs[DEST_REG].upper.f);
 
 
      *data = (ARMword) DSPregs[DEST_REG].upper.i;
      *data = (ARMword) DSPregs[DEST_REG].upper.i;
 
 
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
}
}
 
 
unsigned
unsigned
DSPSTC5 (ARMul_State * state ATTRIBUTE_UNUSED,
DSPSTC5 (ARMul_State * state ATTRIBUTE_UNUSED,
         unsigned      type,
         unsigned      type,
         ARMword       instr,
         ARMword       instr,
         ARMword *     data)
         ARMword *     data)
{
{
  static unsigned words;
  static unsigned words;
 
 
  if (type != ARMul_DATA)
  if (type != ARMul_DATA)
    {
    {
      words = 0;
      words = 0;
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  if (BIT (22))
  if (BIT (22))
    {
    {
      /* It's a long access, store two words.  */
      /* It's a long access, store two words.  */
      /* cfstr64 */
      /* cfstr64 */
      printfdbg ("cfstr64\n");
      printfdbg ("cfstr64\n");
 
 
      if (words == 0)
      if (words == 0)
        {
        {
          if (state->bigendSig)
          if (state->bigendSig)
            *data = (ARMword) DSPregs[DEST_REG].upper.i;
            *data = (ARMword) DSPregs[DEST_REG].upper.i;
          else
          else
            *data = (ARMword) DSPregs[DEST_REG].lower.i;
            *data = (ARMword) DSPregs[DEST_REG].lower.i;
        }
        }
      else
      else
        {
        {
          if (state->bigendSig)
          if (state->bigendSig)
            *data = (ARMword) DSPregs[DEST_REG].lower.i;
            *data = (ARMword) DSPregs[DEST_REG].lower.i;
          else
          else
            *data = (ARMword) DSPregs[DEST_REG].upper.i;
            *data = (ARMword) DSPregs[DEST_REG].upper.i;
        }
        }
 
 
      ++ words;
      ++ words;
 
 
      if (words == 2)
      if (words == 2)
        {
        {
          printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG,
          printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG,
                     mv_getReg64int (DEST_REG));
                     mv_getReg64int (DEST_REG));
 
 
          return ARMul_DONE;
          return ARMul_DONE;
        }
        }
      else
      else
        return ARMul_INC;
        return ARMul_INC;
    }
    }
  else
  else
    {
    {
      /* Store just one word.  */
      /* Store just one word.  */
      /* cfstr32 */
      /* cfstr32 */
      *data = (ARMword) DSPregs[DEST_REG].lower.i;
      *data = (ARMword) DSPregs[DEST_REG].lower.i;
 
 
      printfdbg ("cfstr32 MEM = %d\n", (int) *data);
      printfdbg ("cfstr32 MEM = %d\n", (int) *data);
 
 
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
}
}
 
 
unsigned
unsigned
DSPCDP4 (ARMul_State * state,
DSPCDP4 (ARMul_State * state,
         unsigned      type,
         unsigned      type,
         ARMword       instr)
         ARMword       instr)
{
{
  int opcode2;
  int opcode2;
 
 
  opcode2 = BITS (5,7);
  opcode2 = BITS (5,7);
 
 
  switch (BITS (20,21))
  switch (BITS (20,21))
    {
    {
    case 0:
    case 0:
      switch (opcode2)
      switch (opcode2)
        {
        {
        case 0: /* cfcpys */
        case 0: /* cfcpys */
          printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
          printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     DSPregs[SRC1_REG].upper.f);
                     DSPregs[SRC1_REG].upper.f);
          DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f;
          DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f;
          break;
          break;
 
 
        case 1: /* cfcpyd */
        case 1: /* cfcpyd */
          printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
          printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     mv_getRegDouble (SRC1_REG));
                     mv_getRegDouble (SRC1_REG));
          mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG));
          mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG));
          break;
          break;
 
 
        case 2: /* cfcvtds */
        case 2: /* cfcvtds */
          printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
          printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     (float) mv_getRegDouble (SRC1_REG));
                     (float) mv_getRegDouble (SRC1_REG));
          DSPregs[DEST_REG].upper.f = (float) mv_getRegDouble (SRC1_REG);
          DSPregs[DEST_REG].upper.f = (float) mv_getRegDouble (SRC1_REG);
          break;
          break;
 
 
        case 3: /* cfcvtsd */
        case 3: /* cfcvtsd */
          printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
          printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     (double) DSPregs[SRC1_REG].upper.f);
                     (double) DSPregs[SRC1_REG].upper.f);
          mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].upper.f);
          mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].upper.f);
          break;
          break;
 
 
        case 4: /* cfcvt32s */
        case 4: /* cfcvt32s */
          printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
          printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     (float) DSPregs[SRC1_REG].lower.i);
                     (float) DSPregs[SRC1_REG].lower.i);
          DSPregs[DEST_REG].upper.f = (float) DSPregs[SRC1_REG].lower.i;
          DSPregs[DEST_REG].upper.f = (float) DSPregs[SRC1_REG].lower.i;
          break;
          break;
 
 
        case 5: /* cfcvt32d */
        case 5: /* cfcvt32d */
          printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
          printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     (double) DSPregs[SRC1_REG].lower.i);
                     (double) DSPregs[SRC1_REG].lower.i);
          mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].lower.i);
          mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].lower.i);
          break;
          break;
 
 
        case 6: /* cfcvt64s */
        case 6: /* cfcvt64s */
          printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
          printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     (float) mv_getReg64int (SRC1_REG));
                     (float) mv_getReg64int (SRC1_REG));
          DSPregs[DEST_REG].upper.f = (float) mv_getReg64int (SRC1_REG);
          DSPregs[DEST_REG].upper.f = (float) mv_getReg64int (SRC1_REG);
          break;
          break;
 
 
        case 7: /* cfcvt64d */
        case 7: /* cfcvt64d */
          printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
          printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     (double) mv_getReg64int (SRC1_REG));
                     (double) mv_getReg64int (SRC1_REG));
          mv_setRegDouble (DEST_REG, (double) mv_getReg64int (SRC1_REG));
          mv_setRegDouble (DEST_REG, (double) mv_getReg64int (SRC1_REG));
          break;
          break;
        }
        }
      break;
      break;
 
 
    case 1:
    case 1:
      switch (opcode2)
      switch (opcode2)
        {
        {
        case 0: /* cfmuls */
        case 0: /* cfmuls */
          printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
          printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     DSPregs[SRC1_REG].upper.f * DSPregs[SRC2_REG].upper.f);
                     DSPregs[SRC1_REG].upper.f * DSPregs[SRC2_REG].upper.f);
 
 
          DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
          DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
            * DSPregs[SRC2_REG].upper.f;
            * DSPregs[SRC2_REG].upper.f;
          break;
          break;
 
 
        case 1: /* cfmuld */
        case 1: /* cfmuld */
          printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
          printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     mv_getRegDouble (SRC1_REG) * mv_getRegDouble (SRC2_REG));
                     mv_getRegDouble (SRC1_REG) * mv_getRegDouble (SRC2_REG));
 
 
          mv_setRegDouble (DEST_REG,
          mv_setRegDouble (DEST_REG,
                           mv_getRegDouble (SRC1_REG)
                           mv_getRegDouble (SRC1_REG)
                           * mv_getRegDouble (SRC2_REG));
                           * mv_getRegDouble (SRC2_REG));
          break;
          break;
 
 
        default:
        default:
          fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
          fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
          cirrus_not_implemented ("unknown");
          cirrus_not_implemented ("unknown");
          break;
          break;
        }
        }
      break;
      break;
 
 
    case 3:
    case 3:
      switch (opcode2)
      switch (opcode2)
        {
        {
        case 0: /* cfabss */
        case 0: /* cfabss */
          DSPregs[DEST_REG].upper.f = (DSPregs[SRC1_REG].upper.f < 0.0F ?
          DSPregs[DEST_REG].upper.f = (DSPregs[SRC1_REG].upper.f < 0.0F ?
                                       -DSPregs[SRC1_REG].upper.f
                                       -DSPregs[SRC1_REG].upper.f
                                       : DSPregs[SRC1_REG].upper.f);
                                       : DSPregs[SRC1_REG].upper.f);
          printfdbg ("cfabss mvf%d = |mvf%d| = %f\n",
          printfdbg ("cfabss mvf%d = |mvf%d| = %f\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     DSPregs[DEST_REG].upper.f);
                     DSPregs[DEST_REG].upper.f);
          break;
          break;
 
 
        case 1: /* cfabsd */
        case 1: /* cfabsd */
          mv_setRegDouble (DEST_REG,
          mv_setRegDouble (DEST_REG,
                           (mv_getRegDouble (SRC1_REG) < 0.0 ?
                           (mv_getRegDouble (SRC1_REG) < 0.0 ?
                            -mv_getRegDouble (SRC1_REG)
                            -mv_getRegDouble (SRC1_REG)
                            : mv_getRegDouble (SRC1_REG)));
                            : mv_getRegDouble (SRC1_REG)));
          printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n",
          printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     mv_getRegDouble (DEST_REG));
                     mv_getRegDouble (DEST_REG));
          break;
          break;
 
 
        case 2: /* cfnegs */
        case 2: /* cfnegs */
          DSPregs[DEST_REG].upper.f = -DSPregs[SRC1_REG].upper.f;
          DSPregs[DEST_REG].upper.f = -DSPregs[SRC1_REG].upper.f;
          printfdbg ("cfnegs mvf%d = -mvf%d = %f\n",
          printfdbg ("cfnegs mvf%d = -mvf%d = %f\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     DSPregs[DEST_REG].upper.f);
                     DSPregs[DEST_REG].upper.f);
          break;
          break;
 
 
        case 3: /* cfnegd */
        case 3: /* cfnegd */
          mv_setRegDouble (DEST_REG,
          mv_setRegDouble (DEST_REG,
                           -mv_getRegDouble (SRC1_REG));
                           -mv_getRegDouble (SRC1_REG));
          printfdbg ("cfnegd mvd%d = -mvd%d = %g\n",
          printfdbg ("cfnegd mvd%d = -mvd%d = %g\n",
                     DEST_REG,
                     DEST_REG,
                     mv_getRegDouble (DEST_REG));
                     mv_getRegDouble (DEST_REG));
          break;
          break;
 
 
        case 4: /* cfadds */
        case 4: /* cfadds */
          DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
          DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
            + DSPregs[SRC2_REG].upper.f;
            + DSPregs[SRC2_REG].upper.f;
          printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n",
          printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     SRC2_REG,
                     SRC2_REG,
                     DSPregs[DEST_REG].upper.f);
                     DSPregs[DEST_REG].upper.f);
          break;
          break;
 
 
        case 5: /* cfaddd */
        case 5: /* cfaddd */
          mv_setRegDouble (DEST_REG,
          mv_setRegDouble (DEST_REG,
                           mv_getRegDouble (SRC1_REG)
                           mv_getRegDouble (SRC1_REG)
                           + mv_getRegDouble (SRC2_REG));
                           + mv_getRegDouble (SRC2_REG));
          printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n",
          printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     SRC2_REG,
                     SRC2_REG,
                     mv_getRegDouble (DEST_REG));
                     mv_getRegDouble (DEST_REG));
          break;
          break;
 
 
        case 6: /* cfsubs */
        case 6: /* cfsubs */
          DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
          DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
            - DSPregs[SRC2_REG].upper.f;
            - DSPregs[SRC2_REG].upper.f;
          printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n",
          printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     SRC2_REG,
                     SRC2_REG,
                     DSPregs[DEST_REG].upper.f);
                     DSPregs[DEST_REG].upper.f);
          break;
          break;
 
 
        case 7: /* cfsubd */
        case 7: /* cfsubd */
          mv_setRegDouble (DEST_REG,
          mv_setRegDouble (DEST_REG,
                           mv_getRegDouble (SRC1_REG)
                           mv_getRegDouble (SRC1_REG)
                           - mv_getRegDouble (SRC2_REG));
                           - mv_getRegDouble (SRC2_REG));
          printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n",
          printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n",
                     DEST_REG,
                     DEST_REG,
                     SRC1_REG,
                     SRC1_REG,
                     SRC2_REG,
                     SRC2_REG,
                     mv_getRegDouble (DEST_REG));
                     mv_getRegDouble (DEST_REG));
          break;
          break;
        }
        }
      break;
      break;
 
 
    default:
    default:
      fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
      fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
      cirrus_not_implemented ("unknown");
      cirrus_not_implemented ("unknown");
      break;
      break;
    }
    }
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
unsigned
unsigned
DSPCDP5 (ARMul_State * state,
DSPCDP5 (ARMul_State * state,
         unsigned      type,
         unsigned      type,
         ARMword       instr)
         ARMword       instr)
{
{
   int opcode2;
   int opcode2;
   char shift;
   char shift;
 
 
   opcode2 = BITS (5,7);
   opcode2 = BITS (5,7);
 
 
   /* Shift constants are 7bit signed numbers in bits 0..3|5..7.  */
   /* Shift constants are 7bit signed numbers in bits 0..3|5..7.  */
   shift = BITS (0, 3) | (BITS (5, 7)) << 4;
   shift = BITS (0, 3) | (BITS (5, 7)) << 4;
   if (shift & 0x40)
   if (shift & 0x40)
     shift |= 0xc0;
     shift |= 0xc0;
 
 
   switch (BITS (20,21))
   switch (BITS (20,21))
     {
     {
     case 0:
     case 0:
       /* cfsh32 */
       /* cfsh32 */
       printfdbg ("cfsh32 %s amount=%d\n", shift < 0 ? "right" : "left",
       printfdbg ("cfsh32 %s amount=%d\n", shift < 0 ? "right" : "left",
                  shift);
                  shift);
       if (shift < 0)
       if (shift < 0)
         /* Negative shift is a right shift.  */
         /* Negative shift is a right shift.  */
         DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -shift;
         DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -shift;
       else
       else
         /* Positive shift is a left shift.  */
         /* Positive shift is a left shift.  */
         DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i << shift;
         DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i << shift;
       break;
       break;
 
 
     case 1:
     case 1:
       switch (opcode2)
       switch (opcode2)
         {
         {
         case 0: /* cfmul32 */
         case 0: /* cfmul32 */
           DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
           DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
             * DSPregs[SRC2_REG].lower.i;
             * DSPregs[SRC2_REG].lower.i;
           printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n",
           printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      SRC2_REG,
                      SRC2_REG,
                      DSPregs[DEST_REG].lower.i);
                      DSPregs[DEST_REG].lower.i);
           break;
           break;
 
 
         case 1: /* cfmul64 */
         case 1: /* cfmul64 */
           mv_setReg64int (DEST_REG,
           mv_setReg64int (DEST_REG,
                           mv_getReg64int (SRC1_REG)
                           mv_getReg64int (SRC1_REG)
                           * mv_getReg64int (SRC2_REG));
                           * mv_getReg64int (SRC2_REG));
           printfdbg ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n",
           printfdbg ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      SRC2_REG,
                      SRC2_REG,
                      mv_getReg64int (DEST_REG));
                      mv_getReg64int (DEST_REG));
           break;
           break;
 
 
         case 2: /* cfmac32 */
         case 2: /* cfmac32 */
           DSPregs[DEST_REG].lower.i
           DSPregs[DEST_REG].lower.i
             += DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i;
             += DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i;
           printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n",
           printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      SRC2_REG,
                      SRC2_REG,
                      DSPregs[DEST_REG].lower.i);
                      DSPregs[DEST_REG].lower.i);
           break;
           break;
 
 
         case 3: /* cfmsc32 */
         case 3: /* cfmsc32 */
           DSPregs[DEST_REG].lower.i
           DSPregs[DEST_REG].lower.i
             -= DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i;
             -= DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i;
           printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n",
           printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      SRC2_REG,
                      SRC2_REG,
                      DSPregs[DEST_REG].lower.i);
                      DSPregs[DEST_REG].lower.i);
           break;
           break;
 
 
         case 4: /* cfcvts32 */
         case 4: /* cfcvts32 */
           /* fixme: this should round */
           /* fixme: this should round */
           DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f;
           DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f;
           printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n",
           printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      DSPregs[DEST_REG].lower.i);
                      DSPregs[DEST_REG].lower.i);
           break;
           break;
 
 
         case 5: /* cfcvtd32 */
         case 5: /* cfcvtd32 */
           /* fixme: this should round */
           /* fixme: this should round */
           DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
           DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
           printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n",
           printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      DSPregs[DEST_REG].lower.i);
                      DSPregs[DEST_REG].lower.i);
           break;
           break;
 
 
         case 6: /* cftruncs32 */
         case 6: /* cftruncs32 */
           DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f;
           DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f;
           printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n",
           printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      DSPregs[DEST_REG].lower.i);
                      DSPregs[DEST_REG].lower.i);
           break;
           break;
 
 
         case 7: /* cftruncd32 */
         case 7: /* cftruncd32 */
           DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
           DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
           printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
           printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      DSPregs[DEST_REG].lower.i);
                      DSPregs[DEST_REG].lower.i);
           break;
           break;
         }
         }
       break;
       break;
 
 
     case 2:
     case 2:
       /* cfsh64 */
       /* cfsh64 */
       printfdbg ("cfsh64\n");
       printfdbg ("cfsh64\n");
 
 
       if (shift < 0)
       if (shift < 0)
         /* Negative shift is a right shift.  */
         /* Negative shift is a right shift.  */
         mv_setReg64int (DEST_REG,
         mv_setReg64int (DEST_REG,
                         mv_getReg64int (SRC1_REG) >> -shift);
                         mv_getReg64int (SRC1_REG) >> -shift);
       else
       else
         /* Positive shift is a left shift.  */
         /* Positive shift is a left shift.  */
         mv_setReg64int (DEST_REG,
         mv_setReg64int (DEST_REG,
                         mv_getReg64int (SRC1_REG) << shift);
                         mv_getReg64int (SRC1_REG) << shift);
       printfdbg ("\t%llx\n", mv_getReg64int(DEST_REG));
       printfdbg ("\t%llx\n", mv_getReg64int(DEST_REG));
       break;
       break;
 
 
     case 3:
     case 3:
       switch (opcode2)
       switch (opcode2)
         {
         {
         case 0: /* cfabs32 */
         case 0: /* cfabs32 */
           DSPregs[DEST_REG].lower.i = (DSPregs[SRC1_REG].lower.i < 0
           DSPregs[DEST_REG].lower.i = (DSPregs[SRC1_REG].lower.i < 0
             ? -DSPregs[SRC1_REG].lower.i : DSPregs[SRC1_REG].lower.i);
             ? -DSPregs[SRC1_REG].lower.i : DSPregs[SRC1_REG].lower.i);
           printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n",
           printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      SRC2_REG,
                      SRC2_REG,
                      DSPregs[DEST_REG].lower.i);
                      DSPregs[DEST_REG].lower.i);
           break;
           break;
 
 
         case 1: /* cfabs64 */
         case 1: /* cfabs64 */
           mv_setReg64int (DEST_REG,
           mv_setReg64int (DEST_REG,
                           (mv_getReg64int (SRC1_REG) < 0
                           (mv_getReg64int (SRC1_REG) < 0
                            ? -mv_getReg64int (SRC1_REG)
                            ? -mv_getReg64int (SRC1_REG)
                            : mv_getReg64int (SRC1_REG)));
                            : mv_getReg64int (SRC1_REG)));
           printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n",
           printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      SRC2_REG,
                      SRC2_REG,
                      mv_getReg64int (DEST_REG));
                      mv_getReg64int (DEST_REG));
           break;
           break;
 
 
         case 2: /* cfneg32 */
         case 2: /* cfneg32 */
           DSPregs[DEST_REG].lower.i = -DSPregs[SRC1_REG].lower.i;
           DSPregs[DEST_REG].lower.i = -DSPregs[SRC1_REG].lower.i;
           printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
           printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      SRC2_REG,
                      SRC2_REG,
                      DSPregs[DEST_REG].lower.i);
                      DSPregs[DEST_REG].lower.i);
           break;
           break;
 
 
         case 3: /* cfneg64 */
         case 3: /* cfneg64 */
           mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG));
           mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG));
           printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
           printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      SRC2_REG,
                      SRC2_REG,
                      mv_getReg64int (DEST_REG));
                      mv_getReg64int (DEST_REG));
           break;
           break;
 
 
         case 4: /* cfadd32 */
         case 4: /* cfadd32 */
           DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
           DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
             + DSPregs[SRC2_REG].lower.i;
             + DSPregs[SRC2_REG].lower.i;
           printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n",
           printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      SRC2_REG,
                      SRC2_REG,
                      DSPregs[DEST_REG].lower.i);
                      DSPregs[DEST_REG].lower.i);
           break;
           break;
 
 
         case 5: /* cfadd64 */
         case 5: /* cfadd64 */
           mv_setReg64int (DEST_REG,
           mv_setReg64int (DEST_REG,
                           mv_getReg64int (SRC1_REG)
                           mv_getReg64int (SRC1_REG)
                           + mv_getReg64int (SRC2_REG));
                           + mv_getReg64int (SRC2_REG));
           printfdbg ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n",
           printfdbg ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      SRC2_REG,
                      SRC2_REG,
                      mv_getReg64int (DEST_REG));
                      mv_getReg64int (DEST_REG));
           break;
           break;
 
 
         case 6: /* cfsub32 */
         case 6: /* cfsub32 */
           DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
           DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
             - DSPregs[SRC2_REG].lower.i;
             - DSPregs[SRC2_REG].lower.i;
           printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n",
           printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      SRC2_REG,
                      SRC2_REG,
                      DSPregs[DEST_REG].lower.i);
                      DSPregs[DEST_REG].lower.i);
           break;
           break;
 
 
         case 7: /* cfsub64 */
         case 7: /* cfsub64 */
           mv_setReg64int (DEST_REG,
           mv_setReg64int (DEST_REG,
                           mv_getReg64int (SRC1_REG)
                           mv_getReg64int (SRC1_REG)
                           - mv_getReg64int (SRC2_REG));
                           - mv_getReg64int (SRC2_REG));
           printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n",
           printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n",
                      DEST_REG,
                      DEST_REG,
                      SRC1_REG,
                      SRC1_REG,
                      SRC2_REG,
                      SRC2_REG,
                      mv_getReg64int (DEST_REG));
                      mv_getReg64int (DEST_REG));
           break;
           break;
         }
         }
       break;
       break;
 
 
     default:
     default:
       fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr);
       fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr);
       cirrus_not_implemented ("unknown");
       cirrus_not_implemented ("unknown");
       break;
       break;
     }
     }
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
unsigned
unsigned
DSPCDP6 (ARMul_State * state,
DSPCDP6 (ARMul_State * state,
         unsigned      type,
         unsigned      type,
         ARMword       instr)
         ARMword       instr)
{
{
   int opcode2;
   int opcode2;
 
 
   opcode2 = BITS (5,7);
   opcode2 = BITS (5,7);
 
 
   switch (BITS (20,21))
   switch (BITS (20,21))
     {
     {
     case 0:
     case 0:
       /* cfmadd32 */
       /* cfmadd32 */
       cirrus_not_implemented ("cfmadd32");
       cirrus_not_implemented ("cfmadd32");
       break;
       break;
 
 
     case 1:
     case 1:
       /* cfmsub32 */
       /* cfmsub32 */
       cirrus_not_implemented ("cfmsub32");
       cirrus_not_implemented ("cfmsub32");
       break;
       break;
 
 
     case 2:
     case 2:
       /* cfmadda32 */
       /* cfmadda32 */
       cirrus_not_implemented ("cfmadda32");
       cirrus_not_implemented ("cfmadda32");
       break;
       break;
 
 
     case 3:
     case 3:
       /* cfmsuba32 */
       /* cfmsuba32 */
       cirrus_not_implemented ("cfmsuba32");
       cirrus_not_implemented ("cfmsuba32");
       break;
       break;
 
 
     default:
     default:
       fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr);
       fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr);
     }
     }
 
 
   return ARMul_DONE;
   return ARMul_DONE;
}
}
 
 
/* Conversion functions.
/* Conversion functions.
 
 
   32-bit integers are stored in the LOWER half of a 64-bit physical
   32-bit integers are stored in the LOWER half of a 64-bit physical
   register.
   register.
 
 
   Single precision floats are stored in the UPPER half of a 64-bit
   Single precision floats are stored in the UPPER half of a 64-bit
   physical register.  */
   physical register.  */
 
 
static double
static double
mv_getRegDouble (int regnum)
mv_getRegDouble (int regnum)
{
{
  reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i;
  reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i;
  reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i;
  reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i;
  return reg_conv.d;
  return reg_conv.d;
}
}
 
 
static void
static void
mv_setRegDouble (int regnum, double val)
mv_setRegDouble (int regnum, double val)
{
{
  reg_conv.d = val;
  reg_conv.d = val;
  DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index];
  DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index];
  DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index];
  DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index];
}
}
 
 
static long long
static long long
mv_getReg64int (int regnum)
mv_getReg64int (int regnum)
{
{
  reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i;
  reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i;
  reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i;
  reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i;
  return reg_conv.ll;
  return reg_conv.ll;
}
}
 
 
static void
static void
mv_setReg64int (int regnum, long long val)
mv_setReg64int (int regnum, long long val)
{
{
  reg_conv.ll = val;
  reg_conv.ll = val;
  DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index];
  DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index];
  DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index];
  DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index];
}
}
 
 
/* Compute LSW in a double and a long long.  */
/* Compute LSW in a double and a long long.  */
 
 
void
void
mv_compute_host_endianness (ARMul_State * state)
mv_compute_host_endianness (ARMul_State * state)
{
{
  static union
  static union
  {
  {
    long long ll;
    long long ll;
    long ints[2];
    long ints[2];
    long i;
    long i;
    double d;
    double d;
    float floats[2];
    float floats[2];
    float f;
    float f;
  } conv;
  } conv;
 
 
  /* Calculate where's the LSW in a 64bit int.  */
  /* Calculate where's the LSW in a 64bit int.  */
  conv.ll = 45;
  conv.ll = 45;
 
 
  if (conv.ints[0] == 0)
  if (conv.ints[0] == 0)
    {
    {
      msw_int_index = 0;
      msw_int_index = 0;
      lsw_int_index = 1;
      lsw_int_index = 1;
    }
    }
  else
  else
    {
    {
      assert (conv.ints[1] == 0);
      assert (conv.ints[1] == 0);
      msw_int_index = 1;
      msw_int_index = 1;
      lsw_int_index = 0;
      lsw_int_index = 0;
    }
    }
 
 
  /* Calculate where's the LSW in a double.  */
  /* Calculate where's the LSW in a double.  */
  conv.d = 3.0;
  conv.d = 3.0;
 
 
  if (conv.ints[0] == 0)
  if (conv.ints[0] == 0)
    {
    {
      msw_float_index = 0;
      msw_float_index = 0;
      lsw_float_index = 1;
      lsw_float_index = 1;
    }
    }
  else
  else
    {
    {
      assert (conv.ints[1] == 0);
      assert (conv.ints[1] == 0);
      msw_float_index = 1;
      msw_float_index = 1;
      lsw_float_index = 0;
      lsw_float_index = 0;
    }
    }
 
 
  printfdbg ("lsw_int_index   %d\n", lsw_int_index);
  printfdbg ("lsw_int_index   %d\n", lsw_int_index);
  printfdbg ("lsw_float_index %d\n", lsw_float_index);
  printfdbg ("lsw_float_index %d\n", lsw_float_index);
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.