This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Add support for Analog Devices Blackfin processor (part 4/6: simulator)


This is the fourth part for Analog Devices Blackfin processor, which adds the Blackfin simulator. It was written by Bernd Schmidt <bernd.schmidt@analog.com>. I cleaned up the source code for submitting.

It's mainly used for GCC testing. Not all Blackfin instructions have been implemented. More instructions will be added in future if required.

The sim/bfin/configure is not included in this patch. I'll generate it
from sim/bfin/configure.ac when committing.

Any comments?

Thanks,
Jie

sim/

	* bfin: New target subdirectory.
	* configure.ac: Add bfin target.
	* configure: Regenerate.

sim/bfin/

	* acconfig.h: New file.
	* bfin-dis.c: New file.
	* bfin-sim.h: New file.
	* config.in: New file.
	* configure.ac: New file.
	* interp.c: New file.
	* Makefile.in: New file.
	* syscall.h: New file.

diff -r -u -N -x CVS src.orig/sim/bfin/acconfig.h src/sim/bfin/acconfig.h
--- src.orig/sim/bfin/acconfig.h	1970-01-01 08:00:00.000000000 +0800
+++ src/sim/bfin/acconfig.h	2004-10-06 00:58:39.000000000 +0800
@@ -0,0 +1,15 @@
+
+/* Define to 1 if NLS is requested.  */
+#undef ENABLE_NLS
+
+/* Define as 1 if you have catgets and don't want to use GNU gettext.  */
+#undef HAVE_CATGETS
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext.  */
+#undef HAVE_GETTEXT
+
+/* Define as 1 if you have the stpcpy function.  */
+#undef HAVE_STPCPY
+
+/* Define if your locale.h file contains LC_MESSAGES.  */
+#undef HAVE_LC_MESSAGES
diff -r -u -N -x CVS src.orig/sim/bfin/bfin-dis.c src/sim/bfin/bfin-dis.c
--- src.orig/sim/bfin/bfin-dis.c	1970-01-01 08:00:00.000000000 +0800
+++ src/sim/bfin/bfin-dis.c	2005-12-27 11:12:59.000000000 +0800
@@ -0,0 +1,2690 @@
+/* Simulator for Analog Devices Blackfin processer.
+
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   Contributed by Analog Devices.
+
+   This file is part of simulators.
+
+   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
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+#include "opcode/bfin.h"
+#include "bfin-sim.h"
+
+#define M_S2RND 1
+#define M_T     2
+#define M_W32   3
+#define M_FU    4
+#define M_TFU   6
+#define M_IS    8
+#define M_ISS2  9
+#define M_IH    11
+#define M_IU    12
+
+#define HOST_LONG_WORD_SIZE (sizeof(long)*8)
+
+#define SIGNEXTEND(v, n) (((bs32)v << (HOST_LONG_WORD_SIZE - (n))) >> (HOST_LONG_WORD_SIZE - (n)))
+
+/* For dealing with parallel instructions, we must avoid changing our register
+   file until all parallel insns have been simulated.  This queue of stores
+   can be used to delay a modification.
+   @@@ Should go and convert all 32 bit insns to use this.  */
+struct store {
+  bu32 *addr;
+  bu32 val;
+};
+
+struct store stores[10];
+int n_stores;
+
+#define STORE(X,Y) do { \
+    stores[n_stores].addr = &(X); \
+    stores[n_stores++].val = (Y); \
+  } while (0)
+
+static __attribute__ ((noreturn)) void
+unhandled_instruction (char *insn)
+{
+  fprintf(stderr, "Unhandled instruction \"%s\" ... aborting\n", insn);
+  raise (SIGILL);
+  abort ();
+}
+
+static __attribute__ ((noreturn)) void
+illegal_instruction ()
+{
+  fprintf(stderr, "Illegal instruction ... aborting\n");
+  raise (SIGILL);
+  abort ();
+}
+
+static void
+setflags_nz (bu32 val)
+{
+  saved_state.az = val == 0;
+  saved_state.an = val >> 31;
+}
+
+static void
+setflags_logical (bu32 val)
+{
+  setflags_nz (val);
+  saved_state.ac0 = 0;
+  saved_state.v = 0;
+}
+
+static bu32
+ashiftrt (bu32 val, int cnt)
+{
+  int real_cnt = cnt > 32 ? 32 : cnt;
+  bu32 sgn = ~((val >> 31) - 1);
+  int sgncnt = 32 - real_cnt;
+  if (sgncnt > 16)
+    sgn <<= 16, sgncnt -= 16;
+  sgn <<= sgncnt;
+  if (real_cnt > 16)
+    val >>= 16, real_cnt -= 16;
+  val >>= real_cnt;
+  val |= sgn;
+  saved_state.an = val >> 31;
+  saved_state.az = val == 0;
+  /* @@@ */
+  saved_state.v = 0;
+  return val;
+}
+
+static bu32
+lshiftrt (bu32 val, int cnt)
+{
+  int real_cnt = cnt > 32 ? 32 : cnt;
+  if (real_cnt > 16)
+    val >>= 16, real_cnt -= 16;
+  val >>= real_cnt;
+  saved_state.an = val >> 31;
+  saved_state.az = val == 0;
+  saved_state.v = 0;
+  return val;
+}
+
+static bu32
+lshift (bu32 val, int cnt)
+{
+  int real_cnt = cnt > 32 ? 32 : cnt;
+  if (real_cnt > 16)
+    val <<= 16, real_cnt -= 16;
+  val <<= real_cnt;
+  saved_state.an = val >> 31;
+  saved_state.az = val == 0;
+  saved_state.v = 0;
+  return val;
+}
+
+static bu32
+add32 (bu32 a, bu32 b, int carry)
+{
+  int flgs = a >> 31;
+  int flgo = b >> 31;
+  bu32 v = a + b;
+  int flgn = v >> 31;
+  int overflow = (flgs ^ flgn) & (flgo ^ flgn);
+  saved_state.an = flgn;
+  saved_state.vs |= overflow;
+  saved_state.v = overflow;
+  saved_state.v_internal |= overflow;
+  saved_state.az = v == 0;
+  if (carry)
+    saved_state.ac0 = ~a < b;
+  return v;
+}
+
+static bu32
+sub32 (bu32 a, bu32 b, int carry)
+{
+  int flgs = a >> 31;
+  int flgo = b >> 31;
+  bu32 v = a - b;
+  int flgn = v >> 31;
+  int overflow = (flgs ^ flgo) & (flgn ^ flgs);
+  saved_state.an = flgn;
+  saved_state.vs |= overflow;
+  saved_state.v = overflow;
+  saved_state.v_internal |= overflow;
+  saved_state.az = v == 0;
+  if (carry)
+    saved_state.ac0 = b <= a;
+  return v;
+}
+
+static bu32
+min32 (bu32 a, bu32 b)
+{
+  int val = a;
+  if ((bs32)a > (bs32)b)
+    val = b;
+  setflags_nz (val);
+  saved_state.v = 0;
+  return val;
+}
+
+static bu32
+max32 (bu32 a, bu32 b)
+{
+  int val = a;
+  if ((bs32)a < (bs32)b)
+    val = b;
+  setflags_nz (val);
+  saved_state.v = 0;
+  return val;
+}
+
+static bu32
+add_and_shift (bu32 a, bu32 b, int shift)
+{
+  int v;
+  saved_state.v_internal = 0;
+  v = add32 (a, b, 0);
+  while (shift-- > 0)
+    {
+      int x = v >> 30;
+      if (x == 1 || x == 2)
+	saved_state.v_internal = 1;
+      v <<= 1;
+    }
+  saved_state.v = saved_state.v_internal;
+  saved_state.vs |= saved_state.v;
+  return v;
+}
+
+typedef enum
+{
+  c_0, c_1, c_4, c_2, c_uimm2, c_uimm3, c_imm3, c_pcrel4,
+  c_imm4, c_uimm4s4, c_uimm4, c_uimm4s2, c_negimm5s4, c_imm5, c_uimm5, c_imm6,
+  c_imm7, c_imm8, c_uimm8, c_pcrel8, c_uimm8s4, c_pcrel8s4, c_lppcrel10,
+    c_pcrel10,
+  c_pcrel12, c_imm16s4, c_luimm16, c_imm16, c_huimm16, c_rimm16, c_imm16s2,
+    c_uimm16s4,
+  c_uimm16, c_pcrel24,
+} const_forms_t;
+
+static struct
+{
+  char *name;
+  int nbits;
+  char reloc;
+  char issigned;
+  char pcrel;
+  char scale;
+  char offset;
+  char negative;
+  char positive;
+} constant_formats[] =
+{
+  { "0", 0, 0, 1, 0, 0, 0, 0, 0},
+  { "1", 0, 0, 1, 0, 0, 0, 0, 0},
+  { "4", 0, 0, 1, 0, 0, 0, 0, 0},
+  { "2", 0, 0, 1, 0, 0, 0, 0, 0},
+  { "uimm2", 2, 0, 0, 0, 0, 0, 0, 0},
+  { "uimm3", 3, 0, 0, 0, 0, 0, 0, 0},
+  { "imm3", 3, 0, 1, 0, 0, 0, 0, 0},
+  { "pcrel4", 4, 1, 0, 1, 1, 0, 0, 0},
+  { "imm4", 4, 0, 1, 0, 0, 0, 0, 0},
+  { "uimm4s4", 4, 0, 0, 0, 2, 0, 0, 1},
+  { "uimm4", 4, 0, 0, 0, 0, 0, 0, 0},
+  { "uimm4s2", 4, 0, 0, 0, 1, 0, 0, 1},
+  { "negimm5s4", 5, 0, 1, 0, 2, 0, 1, 0},
+  { "imm5", 5, 0, 1, 0, 0, 0, 0, 0},
+  { "uimm5", 5, 0, 0, 0, 0, 0, 0, 0},
+  { "imm6", 6, 0, 1, 0, 0, 0, 0, 0},
+  { "imm7", 7, 0, 1, 0, 0, 0, 0, 0},
+  { "imm8", 8, 0, 1, 0, 0, 0, 0, 0},
+  { "uimm8", 8, 0, 0, 0, 0, 0, 0, 0},
+  { "pcrel8", 8, 1, 0, 1, 1, 0, 0, 0},
+  { "uimm8s4", 8, 0, 0, 0, 2, 0, 0, 0},
+  { "pcrel8s4", 8, 1, 1, 1, 2, 0, 0, 0},
+  { "lppcrel10", 10, 1, 0, 1, 1, 0, 0, 0},
+  { "pcrel10", 10, 1, 1, 1, 1, 0, 0, 0},
+  { "pcrel12", 12, 1, 1, 1, 1, 0, 0, 0},
+  { "imm16s4", 16, 0, 1, 0, 2, 0, 0, 0},
+  { "luimm16", 16, 1, 0, 0, 0, 0, 0, 0},
+  { "imm16", 16, 0, 1, 0, 0, 0, 0, 0},
+  { "huimm16", 16, 1, 0, 0, 0, 0, 0, 0},
+  { "rimm16", 16, 1, 1, 0, 0, 0, 0, 0},
+  { "imm16s2", 16, 0, 1, 0, 1, 0, 0, 0},
+  { "uimm16s4", 16, 0, 0, 0, 2, 0, 0, 0},
+  { "uimm16", 16, 0, 0, 0, 0, 0, 0, 0},
+  { "pcrel24", 24, 1, 1, 1, 1, 0, 0, 0},};
+
+static bu32
+fmtconst (const_forms_t cf, bu32 x, bu32 pc)
+{
+  if (0 && constant_formats[cf].reloc)
+    {
+      bu32 ea = (((constant_formats[cf].pcrel
+		   ? SIGNEXTEND (x, constant_formats[cf].nbits)
+		   : x) + constant_formats[cf].offset)
+		 << constant_formats[cf].scale);
+      if (constant_formats[cf].pcrel)
+	ea += pc;
+
+      return ea;
+    }
+
+  /* Negative constants have an implied sign bit.  */
+  if (constant_formats[cf].negative)
+    {
+      int nb = constant_formats[cf].nbits + 1;
+      x = x | (1 << constant_formats[cf].nbits);
+      x = SIGNEXTEND (x, nb);
+    }
+  else if (constant_formats[cf].issigned)
+    x = SIGNEXTEND (x, constant_formats[cf].nbits);
+
+  x += constant_formats[cf].offset;
+  x <<= constant_formats[cf].scale;
+
+  return x;
+}
+
+#define uimm16s4(x) fmtconst(c_uimm16s4, x, 0)
+#define pcrel4(x) fmtconst(c_pcrel4, x, pc)
+#define pcrel8(x) fmtconst(c_pcrel8, x, pc)
+#define pcrel8s4(x) fmtconst(c_pcrel8s4, x, pc)
+#define pcrel10(x) fmtconst(c_pcrel10, x, pc)
+#define pcrel12(x) fmtconst(c_pcrel12, x, pc)
+#define negimm5s4(x) fmtconst(c_negimm5s4, x, 0)
+#define rimm16(x) fmtconst(c_rimm16, x, 0)
+#define huimm16(x) fmtconst(c_huimm16, x, 0)
+#define imm16(x) fmtconst(c_imm16, x, 0)
+#define uimm2(x) fmtconst(c_uimm2, x, 0)
+#define uimm3(x) fmtconst(c_uimm3, x, 0)
+#define luimm16(x) fmtconst(c_luimm16, x, 0)
+#define uimm4(x) fmtconst(c_uimm4, x, 0)
+#define uimm5(x) fmtconst(c_uimm5, x, 0)
+#define imm16s2(x) fmtconst(c_imm16s2, x, 0)
+#define uimm8(x) fmtconst(c_uimm8, x, 0)
+#define imm16s4(x) fmtconst(c_imm16s4, x, 0)
+#define uimm4s2(x) fmtconst(c_uimm4s2, x, 0)
+#define uimm4s4(x) fmtconst(c_uimm4s4, x, 0)
+#define lppcrel10(x) fmtconst(c_lppcrel10, x, pc)
+#define imm3(x) fmtconst(c_imm3, x, 0)
+#define imm4(x) fmtconst(c_imm4, x, 0)
+#define uimm8s4(x) fmtconst(c_uimm8s4, x, 0)
+#define imm5(x) fmtconst(c_imm5, x, 0)
+#define imm6(x) fmtconst(c_imm6, x, 0)
+#define imm7(x) fmtconst(c_imm7, x, 0)
+#define imm8(x) fmtconst(c_imm8, x, 0)
+#define pcrel24(x) fmtconst(c_pcrel24, x, pc)
+#define uimm16(x) fmtconst(c_uimm16, x, 0)
+
+static bu32 *
+get_allreg (int grp, int reg)
+{
+  int fullreg = (grp << 3) | reg;
+  /* REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
+     REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
+     REG_I0, REG_I1, REG_I2, REG_I3, REG_M0, REG_M1, REG_M2, REG_M3,
+     REG_B0, REG_B1, REG_B2, REG_B3, REG_L0, REG_L1, REG_L2, REG_L3,
+     REG_A0x, REG_A0w, REG_A1x, REG_A1w, , , REG_ASTAT, REG_RETS,
+     , , , , , , , ,
+     REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES,
+     REG_CYCLES2,
+     REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE,
+     REG_LASTREG */
+  switch (fullreg >> 2)
+    {
+    case 0: case 1: return &DREG (reg); break;
+    case 2: case 3: return &PREG (reg); break;
+    case 4: return &IREG (reg & 3); break;
+    case 5: return &MREG (reg & 3); break;
+    case 6: return &BREG (reg & 3); break;
+    case 7: return &LREG (reg & 3); break;
+    default:
+      switch (fullreg)
+	{
+	case 39: return &saved_state.rets;
+	}
+      return 0;
+    }
+}
+
+/* Perform a multiplication, sign- or zero-extending the result to 64 bit.  */
+static bu64
+decode_multfunc (int h0, int h1, int src0, int src1, int mmod, int MM)
+{
+  bu32 s0 = DREG (src0), s1 = DREG (src1);
+  bu32 sgn0, sgn1;
+  bu32 val;
+  bu64 val1;
+
+  if (h0)
+    s0 >>= 16;
+
+  if (h1)
+    s1 >>= 16;
+
+  s0 &= 0xffff;
+  s1 &= 0xffff;
+
+  sgn0 = -(s0 & 0x8000);
+  sgn1 = -(s1 & 0x8000);
+
+  if (MM)
+    s0 |= sgn0;
+  else switch (mmod)
+    {
+    case 0:
+    case M_S2RND:
+    case M_T:
+    case M_IS:
+    case M_ISS2:
+    case M_IH:
+      s0 |= sgn0;
+      s1 |= sgn1;
+      break;
+    case M_FU:
+    case M_IU:
+    case M_TFU:
+      break;
+    default:
+      abort ();
+    }
+
+  val = s0 * s1;
+  /* Perform shift correction if appropriate for the mode.  */
+  if (mmod == 0 || mmod == M_T || mmod == M_S2RND)
+    {
+      if (val == 0x40000000)
+	val = 0x7fffffff;
+      else
+	val <<= 1;
+    }
+
+  val1 = val;
+  if (mmod == 0 || mmod == M_IS || mmod == M_T || mmod == M_S2RND
+      || mmod == M_ISS2 || mmod == M_IH)
+    val1 |= -(val1 & 0x80000000);
+
+  return val1;
+}
+
+static bu32
+saturate_s32 (bu64 val)
+{
+  if ((bs64)val < -0x80000000ll)
+    return 0x80000000;
+  if ((bs64)val > 0x7fffffff)
+    return 0x7fffffff;
+  return val;
+}
+
+static bu32
+saturate_s16 (bu64 val)
+{
+  if ((bs64)val < -0x8000ll)
+    return 0x8000;
+  if ((bs64)val > 0x7fff)
+    return 0x7fff;
+  return val;
+}
+
+static bu32
+saturate_u32 (bu64 val)
+{
+  if (val > 0xffffffff)
+    return 0xffffffff;
+  return val;
+}
+
+static bu32
+saturate_u16 (bu64 val)
+{
+  if (val > 0xffff)
+    return 0xffff;
+  return val;
+}
+
+static bu64
+rnd16 (bu64 val)
+{
+  bu64 sgnbits = val & 0xff00000000000000ull;
+  /* @@@ Should honour rounding mode.  Can this overflow?  */
+  val += 0x8000;
+  val >>= 16;
+  return val | sgnbits;
+}
+
+static bu64
+trunc16 (bu64 val)
+{
+  bu64 sgnbits = val & 0xff00000000000000ull;
+  val >>= 16;
+  return val | sgnbits;
+}
+
+/* Extract a 16 or 32 bit value from a 64 bit multiplication result.
+   These 64 bits must be sign- or zero-extended properly from the source
+   we want to extract, either a 32 bit multiply or a 40 bit accumulator.  */
+
+static bu32
+extract_mult (bu64 res, int mmod, int fullword)
+{
+  if (fullword)
+    switch (mmod)
+      {
+      case 0:
+      case M_IS:
+	return saturate_s32 (res);
+      case M_FU:
+	return saturate_u32 (res);
+      case M_S2RND:
+      case M_ISS2:
+	return saturate_s32 (res << 1);
+      default:
+	abort ();
+      }
+  else
+    switch (mmod)
+      {
+      case 0:
+      case M_IH:
+	return saturate_s16 (rnd16 (res));
+      case M_IS:
+	return saturate_s16 (res);
+      case M_FU:
+	return saturate_u16 (rnd16 (res));
+      case M_IU:
+	return saturate_u16 (res);
+
+      case M_T:
+	return saturate_s16 (trunc16 (res));
+      case M_TFU:
+	return saturate_u16 (trunc16 (res));
+
+      case M_S2RND:
+	return saturate_s16 (rnd16 (res << 1));
+      case M_ISS2:
+	return saturate_s16 (res << 1);
+      default:
+	abort ();
+      }
+}
+
+static bu32
+decode_macfunc (int which, int op, int h0, int h1, int src0, int src1,
+		int mmod, int MM, int fullword)
+{
+  bu64 *accum = which ? &A1REG : &A0REG;
+  bu64 acc = *accum & 0xFFFFFFFFFFull;
+
+  /* Sign extend accumulator if necessary.  */
+  if (mmod == 0 || mmod == M_T || mmod == M_IS || mmod == M_ISS2
+      || mmod == M_S2RND)
+    acc |= -(acc & 0x80000000);
+
+  if (op != 3)
+    {
+      bu64 res = decode_multfunc (h0, h1, src0, src1, mmod, MM);
+
+      /* Perform accumulation.  */
+      switch (op)
+	{
+	case 0:
+	  *accum = res;
+	  break;
+	case 1:
+	  *accum = acc + res;
+	  break;
+	case 2:
+	  *accum = acc - res;
+	  break;
+	}
+
+      /* Saturate.  */
+      switch (mmod)
+	{
+	case 0:
+	case M_T:
+	case M_IS:
+	case M_ISS2:
+	case M_S2RND:
+	  if ((bs64)*accum < -0x8000000000ll)
+	    *accum = -0x8000000000ull;
+	  else if ((bs64)*accum >= 0x7fffffffffll)
+	    *accum = 0x7fffffffffull;
+	  break;
+	case M_TFU:
+	case M_FU:
+	case M_IU:
+	  if (*accum > 0xFFFFFFFFFFull)
+	    *accum = 0xFFFFFFFFFFull;
+	  break;
+	default:
+	  abort ();
+	}
+      acc = *accum;
+    }
+
+  return extract_mult (acc, mmod, fullword);
+}
+
+static void
+decode_ProgCtrl_0 (bu16 iw0)
+{
+  /* ProgCtrl
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int poprnd = ((iw0 >> 0) & 0xf);
+  int prgfunc = ((iw0 >> 4) & 0xf);
+
+  if (prgfunc == 0 && poprnd == 0)
+    /* NOP */
+    PCREG += 2;
+  else if (prgfunc == 1 && poprnd == 0)
+    /* RTS */
+    PCREG = saved_state.rets;
+  else if (prgfunc == 1 && poprnd == 1)
+    unhandled_instruction ("RTI");
+  else if (prgfunc == 1 && poprnd == 2)
+    unhandled_instruction ("RTX");
+  else if (prgfunc == 1 && poprnd == 3)
+    unhandled_instruction ("RTN");
+  else if (prgfunc == 1 && poprnd == 4)
+    unhandled_instruction ("RTE");
+  else if (prgfunc == 2 && poprnd == 0)
+    unhandled_instruction ("IDLE");
+  else if (prgfunc == 2 && poprnd == 3)
+    unhandled_instruction ("CSYNC");
+  else if (prgfunc == 2 && poprnd == 4)
+    unhandled_instruction ("SSYNC");
+  else if (prgfunc == 2 && poprnd == 5)
+    unhandled_instruction ("EMUEXCPT");
+  else if (prgfunc == 3)
+    unhandled_instruction ("CLI dregs");
+  else if (prgfunc == 4)
+    unhandled_instruction ("STI dregs");
+  else if (prgfunc == 5)
+    {
+      /* JUMP (pregs) */
+      PCREG = PREG (poprnd);
+      did_jump = 1;
+    }
+  else if (prgfunc == 6)
+    {
+      /* CALL (pregs) */
+      saved_state.rets = PCREG + 2;
+      PCREG = PREG (poprnd);
+      did_jump = 1;
+    }
+  else if (prgfunc == 7)
+    {
+      /* CALL (PC + pregs) */
+      saved_state.rets = PCREG + 2;
+      PCREG = PCREG + PREG (poprnd);
+      did_jump = 1;
+    }
+  else if (prgfunc == 8)
+    {
+      /* JUMP (PC + pregs) */
+      PCREG = PCREG + PREG (poprnd);
+      did_jump = 1;
+    }
+  else if (prgfunc == 9)
+    {
+      /* RAISE uimm4 */
+      bfin_trap ();
+      PCREG += 2;
+    }
+  else if (prgfunc == 10)
+    {
+      /* EXCPT uimm4 */
+      if(uimm4 (poprnd) == 1)
+        raise_exception(SIGTRAP);
+      else
+	unhandled_instruction ("unhandled exception");
+    }
+  else if (prgfunc == 11)
+    unhandled_instruction ("TESTSET");
+  else
+    illegal_instruction ();
+}
+
+static void
+decode_CaCTRL_0 (bu16 iw0)
+{
+  /* CaCTRL
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int a = ((iw0 >> 5) & 0x1);
+  int reg = ((iw0 >> 0) & 0x7);
+  int op = ((iw0 >> 3) & 0x3);
+
+  if (a == 0 && op == 0)
+    unhandled_instruction ("PREFETCH [pregs]");
+  else if (a == 0 && op == 1)
+    unhandled_instruction ("FLUSHINV [pregs]");
+  else if (a == 0 && op == 2)
+    unhandled_instruction ("FLUSH [pregs]");
+  else if (a == 0 && op == 3)
+    unhandled_instruction ("IFLUSH [pregs]");
+  else if (a == 1 && op == 0)
+    unhandled_instruction ("PREFETCH [pregs++]");
+  else if (a == 1 && op == 1)
+    unhandled_instruction ("FLUSHINV [pregs++]");
+  else if (a == 1 && op == 2)
+    unhandled_instruction ("FLUSH [pregs++]");
+  else if (a == 1 && op == 3)
+    unhandled_instruction ("IFLUSH [pregs++]");
+  else
+    illegal_instruction ();
+
+  PCREG += 2;
+}
+
+static void
+decode_PushPopReg_0 (bu16 iw0)
+{
+  /* PushPopReg
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int grp = ((iw0 >> 3) & 0x7);
+  int reg = ((iw0 >> 0) & 0x7);
+  int W = ((iw0 >> 6) & 0x1);
+  bu32 *whichreg = get_allreg (grp, reg);
+
+  if (whichreg == 0)
+    unhandled_instruction ("push/pop");
+
+  if (W == 0)
+    {
+      /* allregs = [SP++] */
+      *whichreg = get_long (saved_state.memory, PREG (6));
+      PREG (6) += 4;
+    }
+  else
+    {
+      /* [--SP] = allregs */
+      PREG (6) -= 4;
+      put_long (saved_state.memory, PREG (6), *whichreg);
+    }
+  PCREG += 2;
+}
+
+static void
+decode_PushPopMultiple_0 (bu16 iw0)
+{
+  /* PushPopMultiple
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int p = ((iw0 >> 7) & 0x1);
+  int pr = ((iw0 >> 0) & 0x7);
+  int d = ((iw0 >> 8) & 0x1);
+  int dr = ((iw0 >> 3) & 0x7);
+  int W = ((iw0 >> 6) & 0x1);
+  int i;
+  bu32 sp = PREG (6);
+
+  if ((d == 0 && p == 0)
+      || (p && imm5 (pr) > 5))
+    illegal_instruction ();
+
+  if (W == 1)
+    {
+      if (d)
+	for (i = dr; i < 8; i++)
+	  {
+	    sp -= 4;
+	    put_long (saved_state.memory, sp, DREG (i));
+	  }
+      if (p)
+	for (i = pr; i < 6; i++)
+	  {
+	    sp -= 4;
+	    put_long (saved_state.memory, sp, PREG (i));
+	  }
+    }
+  else
+    {
+      if (p)
+	for (i = 5; i >= pr; i--)
+	  {
+	    PREG (i) = get_long (saved_state.memory, sp);
+	    sp += 4;
+	  }
+      if (d)
+	for (i = 7; i >= dr; i--)
+	  {
+	    DREG (i) = get_long (saved_state.memory, sp);
+	    sp += 4;
+	  }
+    }      
+  PREG (6) = sp;
+  PCREG += 2;
+}
+
+static void
+decode_ccMV_0 (bu16 iw0)
+{
+  /* ccMV
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int src = ((iw0 >> 0) & 0x7);
+  int dst = ((iw0 >> 3) & 0x7);
+  int s = ((iw0 >> 6) & 0x1);
+  int d = ((iw0 >> 7) & 0x1);
+  int T = ((iw0 >> 8) & 0x1);
+  int cond = T ? CCREG : ! CCREG;
+  if (cond)
+    GREG (dst, d) = GREG (src, s);
+  PCREG += 2;
+}
+
+static void
+decode_CCflag_0 (bu16 iw0)
+{
+  /* CCflag
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int x = ((iw0 >> 0) & 0x7);
+  int y = ((iw0 >> 3) & 0x7);
+  int I = ((iw0 >> 10) & 0x1);
+  int opc = ((iw0 >> 7) & 0x7);
+  int G = ((iw0 >> 6) & 0x1);
+
+  if (opc > 4)
+    {
+      if (opc == 5 && I == 0 && G == 0)
+	unhandled_instruction ("CC = A0 == A1");
+      else if (opc == 6 && I == 0 && G == 0)
+	unhandled_instruction ("CC = A0 < A1");
+      else if (opc == 7 && I == 0 && G == 0)
+	unhandled_instruction ("CC = A0 <= A1");
+    }
+  else
+    {
+      int issigned = opc < 3;
+      bu32 srcop = G ? PREG (x) : DREG (x);
+      bu32 dstop = I ? (issigned ? imm3 (y) : uimm3 (y)) : G ? PREG (y) : DREG (y);
+      int flgs = srcop >> 31;
+      int flgo = dstop >> 31;
+
+      bu32 result = srcop - dstop;
+      int flgn = result >> 31;
+      int overflow = (flgs ^ flgo) & (flgn ^ flgs);
+
+      saved_state.az = result == 0;
+      saved_state.an = flgn;
+      saved_state.ac0 = srcop < dstop;
+      switch (opc)
+	{
+	case 0: /* == */
+	  CCREG = saved_state.az;
+	  break;
+	case 1: /* <, signed */
+	  CCREG = (flgn && !overflow) || (!flgn && overflow);
+	  break;
+	case 2: /* <=, signed */
+	  CCREG = (flgn && !overflow) || (!flgn && overflow) || saved_state.az;
+	  break;
+	case 3: /* <, unsigned */
+	  CCREG = saved_state.ac0;
+	  break;
+	case 4: /* <=, unsigned */
+	  CCREG = saved_state.ac0 | saved_state.az;
+	  break;
+	}
+    }
+  PCREG += 2;
+}
+
+static void
+decode_CC2dreg_0 (bu16 iw0)
+{
+  /* CC2dreg
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int reg = ((iw0 >> 0) & 0x7);
+  int op = ((iw0 >> 3) & 0x3);
+
+  if (op == 0)
+    /* dregs = CC */
+    DREG (reg) = CCREG;
+  else if (op == 1)
+    /* CC = dregs */
+    CCREG = DREG (reg) != 0;
+  else if (op == 3)
+    /* CC = !CC */
+    CCREG = !CCREG;
+  else
+    illegal_instruction ();
+  PCREG += 2;
+}
+
+static void
+decode_CC2stat_0 (bu16 iw0)
+{
+  /* CC2stat
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int cbit = ((iw0 >> 0) & 0x1f);
+  int D = ((iw0 >> 7) & 0x1);
+  int op = ((iw0 >> 5) & 0x3);
+  int *pval;
+
+  switch (cbit)
+    {
+    case 0: pval = &saved_state.az; break;
+    case 1: pval = &saved_state.an; break;
+    case 6: pval = &saved_state.aq; break;
+    case 12: pval = &saved_state.ac0; break;
+    case 13: pval = &saved_state.ac1; break;
+    case 16: pval = &saved_state.av0; break;
+    case 17: pval = &saved_state.av0s; break;
+    case 18: pval = &saved_state.av1; break;
+    case 19: pval = &saved_state.av1s; break;
+    case 24: pval = &saved_state.v; break;
+    case 25: pval = &saved_state.vs; break;
+    default:
+      illegal_instruction ();
+    }
+
+  if (D == 0)
+    switch (op)
+      {
+      case 0: CCREG = *pval; break;
+      case 1: CCREG |= *pval; break;
+      case 2: CCREG &= *pval; break;
+      case 3: CCREG ^= *pval; break;
+      }
+  else
+    switch (op)
+      {
+      case 0: *pval = CCREG; break;
+      case 1: *pval |= CCREG; break;
+      case 2: *pval &= CCREG; break;
+      case 3: *pval ^= CCREG; break;
+      }
+  PCREG += 2;
+}
+
+static void
+decode_BRCC_0 (bu16 iw0, bu32 pc)
+{
+  /* BRCC
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int B = ((iw0 >> 10) & 0x1);
+  int T = ((iw0 >> 11) & 0x1);
+  int offset = ((iw0 >> 0) & 0x3ff);
+
+  /* B is just the branch predictor hint - we can ignore it.  */
+
+  /* IF CC JUMP pcrel10 */
+  if (CCREG == T)
+    {
+      PCREG += pcrel10 (offset);
+      did_jump = 1;
+    }
+  else
+    PCREG += 2;
+}
+
+static void
+decode_UJUMP_0 (bu16 iw0, bu32 pc)
+{
+  /* UJUMP
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 1 | 0 |.offset........................................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int offset = ((iw0 >> 0) & 0xfff);
+
+  /* JUMP.S pcrel12 */
+  PCREG += pcrel12 (offset);
+  did_jump = 1;
+}
+
+static void
+decode_REGMV_0 (bu16 iw0)
+{
+  /* REGMV
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int src = ((iw0 >> 0) & 0x7);
+  int gs = ((iw0 >> 6) & 0x7);
+  int dst = ((iw0 >> 3) & 0x7);
+  int gd = ((iw0 >> 9) & 0x7);
+  bu32 *srcreg = get_allreg (gs, src);
+  bu32 *dstreg = get_allreg (gd, dst);
+  
+  if (srcreg == 0 || dstreg == 0)
+    unhandled_instruction ("reg move");
+
+  *dstreg = *srcreg;
+  PCREG += 2;
+}
+
+static void
+decode_ALU2op_0 (bu16 iw0)
+{
+  /* ALU2op
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int src = ((iw0 >> 3) & 0x7);
+  int opc = ((iw0 >> 6) & 0xf);
+  int dst = ((iw0 >> 0) & 0x7);
+
+  if (opc == 0)
+    /* dregs >>>= dregs */
+    DREG (dst) = ashiftrt (DREG (dst), DREG (src));
+  else if (opc == 1)
+    /* dregs >>= dregs */
+    DREG (dst) = lshiftrt (DREG (dst), DREG (src));
+  else if (opc == 2)
+    /* dregs <<= dregs */
+    DREG (dst) = lshift (DREG (dst), DREG (src));
+  else if (opc == 3)
+    /* dregs *= dregs */
+    DREG (dst) *= DREG (src);
+  else if (opc == 4)
+    /* dregs = (dregs + dregs) << 1 */
+    DREG (dst) = add_and_shift (DREG (dst), DREG (src), 1);
+  else if (opc == 5)
+    /* dregs = (dregs + dregs) << 2 */
+    DREG (dst) = add_and_shift (DREG (dst), DREG (src), 2);
+  else if (opc == 8)
+    unhandled_instruction ("DIVQ (dregs , dregs)");
+  else if (opc == 9)
+    unhandled_instruction ("DIVS (dregs , dregs)");
+  else if (opc == 10)
+    {
+      /* dregs = dregs_lo (X) */
+      DREG (dst) = (bs32) (bs16) DREG (src);
+      setflags_logical (DREG (dst));
+    }
+  else if (opc == 11)
+    {
+      /* dregs = dregs_lo (Z) */
+      DREG (dst) = (bu32) (bu16) DREG (src);
+      setflags_logical (DREG (dst));
+    }
+  else if (opc == 12)
+    {
+      /* dregs = dregs_byte (X) */
+      DREG (dst) = (bs32) (bs8) DREG (src);
+      setflags_logical (DREG (dst));
+    }
+  else if (opc == 13)
+    {
+      /* dregs = dregs_byte (Z) */
+      DREG (dst) = (bu32) (bu8) DREG (src);
+      setflags_logical (DREG (dst));
+    }
+  else if (opc == 14)
+    {
+      /* dregs = - dregs */
+      bu32 val = DREG (src);
+      DREG (dst) = -val;
+      setflags_nz (DREG (dst));
+      if (val == 0x80000000)
+	saved_state.v = saved_state.vs = 1;
+      /* @@@ Documentation isn't entirely clear about av0 and av1.  */
+    }
+  else if (opc == 15)
+    {
+      /* dregs = ~ dregs */
+      DREG (dst) = ~DREG (src);
+      setflags_logical (DREG (dst));
+    }
+  else
+    illegal_instruction ();
+  PCREG += 2;
+}
+
+static void
+decode_PTR2op_0 (bu16 iw0)
+{
+  /* PTR2op
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int src = ((iw0 >> 3) & 0x7);
+  int opc = ((iw0 >> 6) & 0x7);
+  int dst = ((iw0 >> 0) & 0x7);
+
+  if (opc == 0)
+    PREG (dst) -= PREG (src);
+  else if (opc == 1)
+    PREG (dst) = PREG (src) << 2;
+  else if (opc == 3)
+    PREG (dst) = PREG (src) >> 2;
+  else if (opc == 4)
+    PREG (dst) = PREG (src) >> 1;
+  else if (opc == 5)
+    unhandled_instruction ("pregs += pregs ( BREV )");
+  else if (opc == 6)
+    PREG (dst) = (PREG (dst) + PREG (src)) << 1;
+  else if (opc == 7)
+    PREG (dst) = (PREG (dst) + PREG (src)) << 2;
+  else
+    illegal_instruction ();
+
+  PCREG += 2;
+}
+
+static void
+decode_LOGI2op_0 (bu16 iw0)
+{
+  /* LOGI2op
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int src = ((iw0 >> 3) & 0x1f);
+  int opc = ((iw0 >> 8) & 0x7);
+  int dst = ((iw0 >> 0) & 0x7);
+
+  if (opc == 0)
+    /* CC = ! BITTST (dregs, uimm5) */
+    CCREG = (~DREG (dst) >> uimm5 (src)) & 1;
+  else if (opc == 1)
+    /* CC = BITTST (dregs, uimm5) */
+    CCREG = (DREG (dst) >> uimm5 (src)) & 1;
+  else if (opc == 2)
+    {
+      /* BITSET (dregs, uimm5) */
+      DREG (dst) |= 1 << uimm5 (src);
+      setflags_logical (DREG (dst));
+    }
+  else if (opc == 3)
+    {
+      /* BITTGL (dregs, uimm5) */
+      DREG (dst) ^= 1 << uimm5 (src);
+      setflags_logical (DREG (dst));
+    }
+  else if (opc == 4)
+    {
+      /* BITCLR (dregs, uimm5) */
+      DREG (dst) &= ~(1 << uimm5 (src));
+      setflags_logical (DREG (dst));
+    }
+  else if (opc == 5)
+    /* dregs >>>= uimm5 */
+    DREG (dst) = ashiftrt (DREG (dst), uimm5 (src));
+  else if (opc == 6)
+    /* dregs >>= uimm5 */
+    DREG (dst) = lshiftrt (DREG (dst), uimm5 (src));
+  else if (opc == 7)
+    /* dregs <<= uimm5 */
+    DREG (dst) = lshift (DREG (dst), uimm5 (src));
+
+  PCREG += 2;
+}
+
+static void
+decode_COMP3op_0 (bu16 iw0)
+{
+  /* COMP3op
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int src0 = ((iw0 >> 0) & 0x7);
+  int src1 = ((iw0 >> 3) & 0x7);
+  int opc = ((iw0 >> 9) & 0x7);
+  int dst = ((iw0 >> 6) & 0x7);
+
+  if (opc == 0)
+    /* dregs = dregs + dregs */
+    DREG (dst) = add32 (DREG (src0), DREG (src1), 1);
+  else if (opc == 1)
+    /* dregs = dregs - dregs */
+    DREG (dst) = sub32 (DREG (src0), DREG (src1), 1);
+  else if (opc == 2)
+    {
+      /* dregs = dregs & dregs */
+      DREG (dst) = DREG (src0) & DREG (src1);
+      setflags_logical (DREG (dst));
+    }
+  else if (opc == 3)
+    {
+      /* dregs = dregs | dregs */
+      DREG (dst) = DREG (src0) | DREG (src1);
+      setflags_logical (DREG (dst));
+    }
+  else if (opc == 4)
+    {
+      /* dregs = dregs ^ dregs */
+      DREG (dst) = DREG (src0) ^ DREG (src1);
+      setflags_logical (DREG (dst));
+    }
+  else if (opc == 5)
+    /* If src0 == src1 this is disassembled as a shift by 1, but this
+       distinction doesn't matter for our purposes.  */
+    PREG (dst) = PREG (src0) + PREG (src1);
+  else if (opc == 6)
+    PREG (dst) = PREG (src0) + (PREG (src1) << 1);
+  else if (opc == 7)
+    PREG (dst) = PREG (src0) + (PREG (src1) << 2);
+
+  PCREG += 2;
+}
+
+static void
+decode_COMPI2opD_0 (bu16 iw0)
+{
+  /* COMPI2opD
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 1 | 1 | 0 | 0 |.op|.isrc......................|.dst.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int isrc = ((iw0 >> 3) & 0x7f);
+  int dst = ((iw0 >> 0) & 0x7);
+  int op = ((iw0 >> 10) & 0x1);
+
+  if (op == 0)
+    DREG (dst) = imm7 (isrc);
+  else if (op == 1)
+    DREG (dst) = add32 (DREG (dst), imm7 (isrc), 1);
+  PCREG += 2;
+}
+
+static void
+decode_COMPI2opP_0 (bu16 iw0)
+{
+  /* COMPI2opP
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int src = ((iw0 >> 3) & 0x7f);
+  int dst = ((iw0 >> 0) & 0x7);
+  int op = ((iw0 >> 10) & 0x1);
+
+  if (op == 0)
+    PREG (dst) = imm7 (src);
+  else if (op == 1)
+    PREG (dst) += imm7 (src);
+  PCREG += 2;
+}
+
+static void
+decode_LDSTpmod_0 (bu16 iw0)
+{
+  /* LDSTpmod
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int aop = ((iw0 >> 9) & 0x3);
+  int idx = ((iw0 >> 3) & 0x7);
+  int ptr = ((iw0 >> 0) & 0x7);
+  int reg = ((iw0 >> 6) & 0x7);
+  int W = ((iw0 >> 11) & 0x1);
+  bu32 addr, val;
+
+  if (aop == 1 && W == 0 && idx == ptr)
+    {
+      /* dregs_lo = W[pregs] */
+      addr = PREG (ptr);
+      val = get_word (saved_state.memory, addr);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val);
+    }
+  else if (aop == 2 && W == 0 && idx == ptr)
+    {
+      /* dregs_hi = W[pregs] */
+      addr = PREG (ptr);
+      val = get_word (saved_state.memory, addr);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16));
+    }
+  else if (aop == 1 && W == 1 && idx == ptr)
+    {
+      /* W[pregs] = dregs_lo */
+      addr = PREG (ptr);
+      put_word (saved_state.memory, addr, DREG (reg));
+    }
+  else if (aop == 2 && W == 1 && idx == ptr)
+    {
+      /* W[pregs] = dregs_hi */
+      addr = PREG (ptr);
+      put_word (saved_state.memory, addr, DREG (reg) >> 16);
+    }
+  else if (aop == 0 && W == 0)
+    {
+      /* dregs = [pregs ++ pregs] */
+      addr = PREG (ptr);
+      val = get_long (saved_state.memory, addr);
+      STORE (DREG (reg), val);
+      STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 1 && W == 0)
+    {
+      /* dregs_lo = W[pregs ++ pregs] */
+      addr = PREG (ptr);
+      val = get_word (saved_state.memory, addr);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val);
+      STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 2 && W == 0)
+    {
+      /* dregs_hi = W[pregs ++ pregs] */
+      addr = PREG (ptr);
+      val = get_word (saved_state.memory, addr);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16));
+      STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 3 && W == 0)
+    {
+      /* dregs = W[pregs ++ pregs] (Z) */
+      addr = PREG (ptr);
+      val = get_word (saved_state.memory, addr);
+      STORE (DREG (reg), val);
+      STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 3 && W == 1)
+    {
+      /* dregs = W [ pregs ++ pregs ] (X) */
+      addr = PREG (ptr);
+      val = get_word (saved_state.memory, addr);
+      STORE (DREG (reg), (bs32) (bs16) val);
+      STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 0 && W == 1)
+    {
+      /* [pregs ++ pregs] = dregs */
+      addr = PREG (ptr);
+      put_long (saved_state.memory, addr, DREG (reg));
+      STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 1 && W == 1)
+    {
+      /* W[pregs ++ pregs] = dregs_lo */
+      addr = PREG (ptr);
+      put_word (saved_state.memory, addr, DREG (reg));
+      STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 2 && W == 1)
+    {
+      /* W[pregs ++ pregs] = dregs_hi */
+      addr = PREG (ptr);
+      put_word (saved_state.memory, addr, DREG (reg) >> 16);
+      STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else
+    illegal_instruction ();
+
+  PCREG += 2;
+}
+
+static void
+decode_dagMODim_0 (bu16 iw0)
+{
+  /* dagMODim
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int i = ((iw0 >> 0) & 0x3);
+  int br = ((iw0 >> 7) & 0x1);
+  int m = ((iw0 >> 2) & 0x3);
+  int op = ((iw0 >> 4) & 0x1);
+
+  if (op == 0 && br == 1)
+    unhandled_instruction ("iregs += mregs (BREV)");
+  else if (op == 0)
+    unhandled_instruction ("iregs += mregs");
+  else if (op == 1)
+    unhandled_instruction ("iregs -= mregs");
+  else
+    illegal_instruction ();
+  PCREG += 2;
+}
+
+static void
+decode_dagMODik_0 (bu16 iw0)
+{
+  /* dagMODik
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int i = ((iw0 >> 0) & 0x3);
+  int op = ((iw0 >> 2) & 0x3);
+
+  if (op == 0)
+    unhandled_instruction ("iregs += 2");
+  else if (op == 1)
+    unhandled_instruction ("iregs -= 2");
+  else if (op == 2)
+    unhandled_instruction ("iregs += 4");
+  else if (op == 3)
+    unhandled_instruction ("iregs -= 4");
+  else
+    illegal_instruction ();
+  PCREG += 2;
+}
+
+static void
+decode_dspLDST_0 (bu16 iw0)
+{
+  /* dspLDST
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int aop = ((iw0 >> 7) & 0x3);
+  int i = ((iw0 >> 3) & 0x3);
+  int m = ((iw0 >> 5) & 0x3);
+  int reg = ((iw0 >> 0) & 0x7);
+  int W = ((iw0 >> 9) & 0x1);
+  bu32 addr;
+
+  if (aop == 0 && W == 0 && m == 0)
+    {
+      /* dregs = [iregs++] */
+      addr = IREG (i);
+      STORE (IREG (i), addr + 4);
+      STORE (DREG (reg), get_long (saved_state.memory, addr));
+    }
+  else if (aop == 0 && W == 0 && m == 1)
+    {
+      /* dregs_lo = W[iregs++] */
+      addr = IREG (i);
+      STORE (IREG (i), addr + 2);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | get_word (saved_state.memory, addr));
+    }
+  else if (aop == 0 && W == 0 && m == 2)
+    {
+      /* dregs_hi = W[iregs++] */
+      addr = IREG (i);
+      STORE (IREG (i), addr + 2);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (get_word (saved_state.memory, addr) << 16));
+    }
+  else if (aop == 1 && W == 0 && m == 0)
+    {
+      /* dregs = [iregs--] */
+      addr = IREG (i);
+      STORE (IREG (i), addr - 4);
+      STORE (DREG (reg), get_long (saved_state.memory, addr));
+    }
+  else if (aop == 1 && W == 0 && m == 1)
+    {
+      /* dregs_lo = W[iregs--] */
+      addr = IREG (i);
+      STORE (IREG (i), addr - 2);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | get_word (saved_state.memory, addr));
+    }
+  else if (aop == 1 && W == 0 && m == 2)
+    {
+      /* dregs_hi = W[iregs--] */
+      addr = IREG (i);
+      STORE (IREG (i), addr - 2);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (get_word (saved_state.memory, addr) << 16));
+    }
+  else if (aop == 2 && W == 0 && m == 0)
+    {
+      /* dregs = [iregs] */
+      addr = IREG (i);
+      STORE (DREG (reg), get_long (saved_state.memory, addr));
+    }
+  else if (aop == 2 && W == 0 && m == 1)
+    {
+      /* dregs_lo = W[iregs] */
+      addr = IREG (i);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | get_word (saved_state.memory, addr));
+    }
+  else if (aop == 2 && W == 0 && m == 2)
+    {
+      /* dregs_hi = W[iregs] */
+      addr = IREG (i);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (get_word (saved_state.memory, addr) << 16));
+    }
+  else if (aop == 0 && W == 1 && m == 0)
+    {
+      /* [iregs++] = dregs */
+      addr = IREG (i);
+      STORE (IREG (i), addr + 4);
+      put_long (saved_state.memory, addr, DREG (reg));
+    }
+  else if (aop == 0 && W == 1 && m == 1)
+    {
+      /* W[iregs++] = dregs_lo */
+      addr = IREG (i);
+      STORE (IREG (i), addr + 2);
+      put_word (saved_state.memory, addr, DREG (reg));
+    }
+  else if (aop == 0 && W == 1 && m == 2)
+    {
+      /* W[iregs++] = dregs_hi */
+      addr = IREG (i);
+      STORE (IREG (i), addr + 2);
+      put_word (saved_state.memory, addr, DREG (reg) >> 16);
+    }
+  else if (aop == 1 && W == 1 && m == 0)
+    {
+      /* [iregs--] = dregs */
+      addr = IREG (i);
+      STORE (IREG (i), addr - 4);
+      put_long (saved_state.memory, addr, DREG (reg));
+    }
+  else if (aop == 1 && W == 1 && m == 1)
+    {
+      /* W[iregs--] = dregs_lo */
+      addr = IREG (i);
+      STORE (IREG (i), addr - 2);
+      put_word (saved_state.memory, addr, DREG (reg));
+    }
+  else if (aop == 1 && W == 1 && m == 2)
+    {
+      /* W[iregs--] = dregs_hi */
+      addr = IREG (i);
+      STORE (IREG (i), addr - 2);
+      put_word (saved_state.memory, addr, DREG (reg) >> 16);
+    }
+  else if (aop == 2 && W == 1 && m == 0)
+    {
+      /* [iregs] = dregs */
+      addr = IREG (i);
+      put_long (saved_state.memory, addr, DREG (reg));
+    }
+  else if (aop == 2 && W == 1 && m == 1)
+    {
+      /*  W[iregs] = dregs_lo */
+      addr = IREG (i);
+      put_word (saved_state.memory, addr, DREG (reg));
+    }
+  else if (aop == 2 && W == 1 && m == 2)
+    {
+      /*  W[iregs] = dregs_hi */
+      addr = IREG (i);
+      put_word (saved_state.memory, addr, DREG (reg) >> 16);
+    }
+  else if (aop == 3 && W == 0)
+    {
+      /* dregs = [iregs ++ mregs] */
+      addr = IREG (i);
+      STORE (IREG (i), addr + MREG (m));
+      STORE (DREG (reg), get_long (saved_state.memory, addr));
+    }
+  else if (aop == 3 && W == 1)
+    {
+      /* [iregs ++ mregs] = dregs */
+      addr = IREG (i);
+      STORE (IREG (i), addr + MREG (m));
+      put_long (saved_state.memory, addr, DREG (reg));
+    }
+  else
+    illegal_instruction ();
+
+  PCREG += 2;
+}
+
+static void
+decode_LDST_0 (bu16 iw0)
+{
+  /* LDST
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int aop = ((iw0 >> 7) & 0x3);
+  int Z = ((iw0 >> 6) & 0x1);
+  int sz = ((iw0 >> 10) & 0x3);
+  int reg = ((iw0 >> 0) & 0x7);
+  int ptr = ((iw0 >> 3) & 0x7);
+  int W = ((iw0 >> 9) & 0x1);
+
+  if (aop == 3)
+    illegal_instruction ();
+
+  if (W == 0)
+    {
+      if (aop != 2 && sz == 0 && Z == 1
+	  && ptr == reg)
+	illegal_instruction ();
+
+      if (sz == 0 && Z == 0)
+	/* dregs = [pregs] */
+	DREG (reg) = get_long (saved_state.memory, PREG (ptr));
+      else if (sz == 0 && Z == 1)
+	/* pregs = [pregs] */
+	PREG (reg) = get_long (saved_state.memory, PREG (ptr));
+      else if (sz == 1 && Z == 0)
+	/* dregs = W[pregs] (z) */
+	DREG (reg) = get_word (saved_state.memory, PREG (ptr));
+      else if (sz == 1 && Z == 1)
+	/* dregs = W[pregs] (X) */
+	DREG (reg) = (bs32) (bs16) get_word (saved_state.memory, PREG (ptr));
+      else if (sz == 2 && Z == 0)
+	/* dregs = B[pregs] (Z) */
+	DREG (reg) = get_byte (saved_state.memory, PREG (ptr));
+      else if (sz == 2 && Z == 1)
+	/* dregs = B[pregs] (X) */
+	DREG (reg) = (bs32) (bs8) get_byte (saved_state.memory, PREG (ptr));
+
+      if (aop == 0)
+	PREG (ptr) += sz == 0 ? 4 : sz == 1 ? 2 : 1;
+      if (aop == 1)
+	PREG (ptr) -= sz == 0 ? 4 : sz == 1 ? 2 : 1;
+    }
+  else
+    {
+      if (sz != 0 && Z == 1)
+	illegal_instruction ();
+
+      if (sz == 0 && Z == 0)
+	/* [pregs] = dregs */
+	put_long (saved_state.memory, PREG (ptr), DREG (reg));
+      else if (sz == 0 && Z == 1)
+	/* [pregs] = pregs */
+	put_long (saved_state.memory, PREG (ptr), PREG (reg));
+      else if (sz == 1 && Z == 0)
+	/* W[pregs] = dregs */
+	put_word (saved_state.memory, PREG (ptr), DREG (reg));
+      else if (sz == 2 && Z == 0)
+	/* B[pregs] = dregs */
+	put_byte (saved_state.memory, PREG (ptr), DREG (reg));
+
+      if (aop == 0)
+	PREG (ptr) += sz == 0 ? 4 : sz == 1 ? 2 : 1;
+      if (aop == 1)
+	PREG (ptr) -= sz == 0 ? 4 : sz == 1 ? 2 : 1;
+    }      
+
+  PCREG += 2;
+}
+
+static void
+decode_LDSTiiFP_0 (bu16 iw0)
+{
+  /* LDSTiiFP
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int reg = ((iw0 >> 0) & 0xf);
+  int offset = ((iw0 >> 4) & 0x1f);
+  int W = ((iw0 >> 9) & 0x1);
+  bu32 ea = PREG (7) + negimm5s4 (offset);
+
+  if (W == 0)
+    DPREG (reg) = get_long (saved_state.memory, ea);
+  else
+    put_long (saved_state.memory, ea, DPREG (reg));
+  PCREG += 2;
+}
+
+static void
+decode_LDSTii_0 (bu16 iw0)
+{
+  /* LDSTii
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int reg = ((iw0 >> 0) & 0x7);
+  int ptr = ((iw0 >> 3) & 0x7);
+  int offset = ((iw0 >> 6) & 0xf);
+  int op = ((iw0 >> 10) & 0x3);
+  int W = ((iw0 >> 12) & 0x1);
+  bu32 ea = PREG (ptr) + (op == 0 || op == 3 ? uimm4s4 (offset) 
+			  : uimm4s2 (offset));
+
+  if (W == 1 && op == 2)
+    illegal_instruction ();
+
+  if (W == 0)
+    { 
+      if (op == 0)
+	/* dregs = [pregs + uimm4s4] */
+	DREG (reg) = get_long (saved_state.memory, ea);
+      else if (op == 1)
+	/* dregs = W[pregs + uimm4s2] (Z) */
+	DREG (reg) = get_word (saved_state.memory, ea);
+      else if (op == 2)
+	/* dregs = W[pregs + uimm4s2] (X) */
+	DREG (reg) = (bs32) (bs16) get_word (saved_state.memory, ea);
+      else if (op == 3)
+	/* pregs = [pregs + uimm4s4] */
+	PREG (reg) = get_long (saved_state.memory, ea);
+    }
+  else
+    {
+      if (op == 0)
+	/* [pregs + uimm4s4] = dregs */
+	put_long (saved_state.memory, ea, DREG (reg));
+      else if (op == 1)
+	/* W[pregs + uimm4s2] = dregs */
+	put_word (saved_state.memory, ea, DREG (reg));
+      else if (op == 3)
+	/* [pregs + uimm4s4] = pregs */
+	put_long (saved_state.memory, ea, PREG (reg));
+    }
+  PCREG += 2;
+}
+
+static void
+decode_LoopSetup_0 (bu16 iw0, bu16 iw1, bu32 pc)
+{
+  /* LoopSetup
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
+     |.reg...........| - | - |.eoffset...............................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int rop = ((iw0 >> 5) & 0x3);
+  int soffset = ((iw0 >> 0) & 0xf);
+  int c = ((iw0 >> 4) & 0x1);
+  int eoffset = ((iw1 >> 0) & 0x3ff);
+  int reg = ((iw1 >> 12) & 0xf);
+
+  if (rop == 0)
+    {
+      /* LSETUP (pcrel4, lppcrel10) counters */
+      saved_state.lt[c] = PCREG + pcrel4 (soffset);
+      saved_state.lb[c] = PCREG + lppcrel10 (eoffset);
+    }
+  else if (rop == 1)
+    {
+      /* LSETUP (pcrel4, lppcrel10) counters = pregs */
+      saved_state.lt[c] = PCREG + pcrel4 (soffset);
+      saved_state.lb[c] = PCREG + lppcrel10 (eoffset);
+      saved_state.lc[c] = PREG (reg);
+    }
+  else if (rop == 3)
+    {
+      /* LSETUP (pcrel4, lppcrel10) counters = pregs >> 1 */
+      saved_state.lt[c] = PCREG + pcrel4 (soffset);
+      saved_state.lb[c] = PCREG + lppcrel10 (eoffset);
+      saved_state.lc[c] = PREG (reg) >> 1;
+    }
+  else
+    illegal_instruction ();
+
+  PCREG += 4;
+}
+
+static void
+decode_LDIMMhalf_0 (bu16 iw0, bu16 iw1, bu32 pc)
+{
+  /* LDIMMhalf
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
+     |.hword.........................................................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int H = ((iw0 >> 6) & 0x1);
+  int grp = ((iw0 >> 3) & 0x3);
+  int Z = ((iw0 >> 7) & 0x1);
+  int S = ((iw0 >> 5) & 0x1);
+  int hword = ((iw1 >> 0) & 0xffff);
+  int reg = ((iw0 >> 0) & 0x7);
+
+  if (H == 0 && S == 1 && Z == 0)
+    {
+      bu32 *pval = get_allreg (grp, reg);
+      /* regs = imm16 (x) */
+      *pval = imm16 (hword);
+    }
+  else if (H == 0 && S == 0 && Z == 1)
+    {
+      bu32 *pval = get_allreg (grp, reg);
+      /* regs = luimm16 (Z) */
+      *pval = luimm16 (hword);
+    }
+  else if (H == 0 && S == 0 && Z == 0)
+    {
+      bu32 *pval = get_allreg (grp, reg);
+      /* regs_lo = luimm16 */
+      *pval &= 0xFFFF0000;
+      *pval |= luimm16 (hword);
+    }
+  else if (H == 1 && S == 0 && Z == 0)
+    {
+      bu32 *pval = get_allreg (grp, reg);
+      /* regs_hi = huimm16 */
+      *pval &= 0xFFFF;
+      *pval |= luimm16 (hword) << 16;
+    }
+  else
+    illegal_instruction ();
+  PCREG += 4;
+}
+
+static void
+decode_CALLa_0 (bu16 iw0, bu16 iw1, bu32 pc)
+{
+  /* CALLa
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
+     |.lsw...........................................................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+   */
+  int S = ((iw0 >> 8) & 0x1);
+  int lsw = ((iw1 >> 0) & 0xffff);
+  int msw = ((iw0 >> 0) & 0xff);
+
+  if (S == 1)
+    /* CALL  pcrel24 */
+    saved_state.rets = PCREG + 4;
+  /* JUMP.L  pcrel24 */
+  PCREG += pcrel24 (((msw) << 16) | (lsw));
+}
+
+static void
+decode_LDSTidxI_0 (bu16 iw0, bu16 iw1, bu32 pc)
+{
+  /* LDSTidxI
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
+     |.offset........................................................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int Z = ((iw0 >> 8) & 0x1);
+  int sz = ((iw0 >> 6) & 0x3);
+  int reg = ((iw0 >> 0) & 0x7);
+  int ptr = ((iw0 >> 3) & 0x7);
+  int offset = ((iw1 >> 0) & 0xffff);
+  int W = ((iw0 >> 9) & 0x1);
+
+  if (sz == 3)
+    illegal_instruction ();
+
+  if (W == 0)
+    {
+      if (sz == 0 && Z == 0)
+	/* dregs = [pregs + imm16s4] */
+	DREG (reg) = get_long (saved_state.memory, PREG (ptr) + imm16s4 (offset));
+      else if (sz == 0 && Z == 1)
+	/* pregs = [pregs + imm16s4] */
+	PREG (reg) = get_long (saved_state.memory, PREG (ptr) + imm16s4 (offset));
+      else if (sz == 1 && Z == 0)
+	/* dregs = W[pregs + imm16s2] (Z) */
+	DREG (reg) = get_word (saved_state.memory, PREG (ptr) + imm16s2 (offset));
+      else if (sz == 1 && Z == 1)
+	/* dregs = W[pregs + imm16s2] (X) */
+	DREG (reg) = (bs32) (bs16) get_word (saved_state.memory, PREG (ptr) + imm16s2 (offset));
+      else if (sz == 2 && Z == 0)
+	/* dregs = B[pregs + imm16] (Z) */
+	DREG (reg) = get_byte (saved_state.memory, PREG (ptr) + imm16 (offset));
+      else if (sz == 2 && Z == 1)
+	/* dregs = B[pregs + imm16] (X) */
+	DREG (reg) = (bs32) (bs8) get_byte (saved_state.memory, PREG (ptr) + imm16 (offset));
+    }
+  else
+    {
+      if (sz != 0 && Z != 0)
+	illegal_instruction ();
+
+      if (sz == 0 && Z == 0)
+	/* [pregs + imm16s4] = dregs */
+	put_long (saved_state.memory, PREG (ptr) + imm16s4 (offset), DREG (reg));
+      else if (sz == 0 && Z == 1)
+	/* [pregs + imm16s4] = pregs */
+	put_long (saved_state.memory, PREG (ptr) + imm16s4 (offset), PREG (reg));
+      else if (sz == 1 && Z == 0)
+	/* W[pregs + imm16s2] = dregs */
+	put_word (saved_state.memory, PREG (ptr) + imm16s2 (offset), DREG (reg));
+      else if (sz == 2 && Z == 0)
+	/* B[pregs + imm16] = dregs */
+	put_byte (saved_state.memory, PREG (ptr) + imm16 (offset), DREG (reg));
+    }
+  PCREG += 4;
+}
+
+static void
+decode_linkage_0 (bu16 iw0, bu16 iw1)
+{
+  /* linkage
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
+     |.framesize.....................................................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int R = ((iw0 >> 0) & 0x1);
+  int framesize = ((iw1 >> 0) & 0xffff);
+
+  if (R == 0)
+    {
+      bu32 sp = PREG (6);
+      /* LINK uimm16s4 */
+      sp -= 4;
+      put_long (saved_state.memory, sp, saved_state.rets);
+      sp -= 4;
+      put_long (saved_state.memory, sp, PREG (7));
+      PREG (7) = sp;
+      sp -= uimm16s4 (framesize);
+      PREG (6) = sp;
+    }
+  else
+    {
+      /* Restore SP from FP.  */
+      bu32 sp = PREG (7);
+      /* UNLINK */
+      PREG (7) = get_long (saved_state.memory, sp);
+      sp += 4;
+      saved_state.rets = get_long (saved_state.memory, sp);
+      sp += 4;
+      PREG (6) = sp;
+    }
+  PCREG += 4;
+}
+
+static void
+decode_dsp32mac_0 (bu16 iw0, bu16 iw1, bu32 pc)
+{
+  /* dsp32mac
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
+     |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int op1 = ((iw0 >> 0) & 0x3);
+  int w1 = ((iw0 >> 2) & 0x1);
+  int P = ((iw0 >> 3) & 0x1);
+  int MM = ((iw0 >> 4) & 0x1);
+  int mmod = ((iw0 >> 5) & 0xf);
+  int M = ((iw0 >> 11) & 0x1);
+
+  int w0 = ((iw1 >> 13) & 0x1);
+  int src1 = ((iw1 >> 0) & 0x7);
+  int src0 = ((iw1 >> 3) & 0x7);
+  int dst = ((iw1 >> 6) & 0x7);
+  int h10 = ((iw1 >> 9) & 0x1);
+  int h00 = ((iw1 >> 10) & 0x1);
+  int op0 = ((iw1 >> 11) & 0x3);
+  int h11 = ((iw1 >> 14) & 0x1);
+  int h01 = ((iw1 >> 15) & 0x1);
+
+  bu32 res0, res1;
+
+  if (w0 == 0 && w1 == 0 && op1 == 3 && op0 == 3)
+    illegal_instruction ();
+
+  if (op1 == 3 && MM)
+    illegal_instruction ();
+
+  if (((1 << mmod) & (P ? 0x313 : 0x1b57)) == 0)
+    illegal_instruction ();
+
+  if (w1 == 1 || op1 != 3)
+    res1 = decode_macfunc (1, op1, h01, h11, src0, src1, mmod, MM, P);
+
+  if (w0 == 1 || op0 != 3)
+    res0 = decode_macfunc (0, op0, h00, h10, src0, src1, mmod, 0, P);
+
+  if (w0)
+    {
+      if (P)
+	DREG (dst) = res0;
+      else
+	{
+	  if (res0 & 0xffff0000)
+	    abort ();
+	  DREG (dst) = (DREG (dst) & 0xFFFF0000) | res0;
+	}
+    }
+
+  if (w1)
+    {
+      if (P)
+	DREG (dst + 1) = res1;
+      else
+	{
+	  if (res1 & 0xffff0000)
+	    abort ();
+	  DREG (dst) = (DREG (dst) & 0xFFFF) | (res1 << 16);
+	}
+    }
+
+  PCREG += 4;
+}
+
+static void
+decode_dsp32mult_0 (bu16 iw0, bu16 iw1, bu32 pc)
+{
+  /* dsp32mult
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
+     |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int op1 = ((iw0 >> 0) & 0x3);
+  int w1 = ((iw0 >> 2) & 0x1);
+  int P = ((iw0 >> 3) & 0x1);
+  int MM = ((iw0 >> 4) & 0x1);
+  int mmod = ((iw0 >> 5) & 0xf);
+  int M = ((iw0 >> 11) & 0x1);
+
+  int src1 = ((iw1 >> 0) & 0x7);
+  int src0 = ((iw1 >> 3) & 0x7);
+  int dst = ((iw1 >> 6) & 0x7);
+  int h10 = ((iw1 >> 9) & 0x1);
+  int h00 = ((iw1 >> 10) & 0x1);
+  int op0 = ((iw1 >> 11) & 0x3);
+  int w0 = ((iw1 >> 13) & 0x1);
+  int h01 = ((iw1 >> 15) & 0x1);
+  int h11 = ((iw1 >> 14) & 0x1);
+
+  bu32 res0, res1;
+
+  if (w1 == 0 && w0 == 0)
+    illegal_instruction ();
+  if (((1 << mmod) & (P ? 0x313 : 0x1b57)) == 0)
+    illegal_instruction ();
+
+  if (w1)
+    {
+      bu64 r = decode_multfunc (h01, h11, src0, src1, mmod, MM);
+      res1 = extract_mult (r, mmod, P);
+    }
+
+  if (w0)
+    {
+      bu64 r = decode_multfunc (h00, h10, src0, src1, mmod, 0);
+      res0 = extract_mult (r, mmod, P);
+    }
+
+  if (w0)
+    {
+      if (P)
+	DREG (dst) = res0;
+      else
+	{
+	  if (res0 & 0xFFFF0000)
+	    abort ();
+	  DREG (dst) = (DREG (dst) & 0xFFFF0000) | res0;
+	}
+    }
+
+  if (w1)
+    {
+      if (P)
+	DREG (dst + 1) = res1;
+      else
+	{
+	  if (res1 & 0xFFFF0000)
+	    abort ();
+	  DREG (dst) = (DREG (dst) & 0xFFFF) | (res1 << 16);
+	}
+    }
+
+  PCREG += 4;
+}
+
+static void
+decode_dsp32alu_0 (bu16 iw0, bu16 iw1, bu32 pc)
+{
+  /* dsp32alu
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
+     |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int aop = ((iw1 >> 14) & 0x3);
+  int s = ((iw1 >> 13) & 0x1);
+  int HL = ((iw0 >> 5) & 0x1);
+  int x = ((iw1 >> 12) & 0x1);
+  int src0 = ((iw1 >> 3) & 0x7);
+  int src1 = ((iw1 >> 0) & 0x7);
+  int dst0 = ((iw1 >> 9) & 0x7);
+  int aopcde = ((iw0 >> 0) & 0x1f);
+  int dst1 = ((iw1 >> 6) & 0x7);
+  int M = ((iw0 >> 11) & 0x1);
+
+  if (aop == 0 && aopcde == 9 && HL == 0 && s == 0)
+    unhandled_instruction ("A0.L = dregs_lo");
+  else if (aop == 2 && aopcde == 9 && HL == 1 && s == 0)
+    unhandled_instruction ("A1.H = dregs_hi");
+  else if (aop == 2 && aopcde == 9 && HL == 0 && s == 0)
+    unhandled_instruction ("A1.L = dregs_lo");
+  else if (aop == 0 && aopcde == 9 && HL == 1 && s == 0)
+    unhandled_instruction ("A0.H = dregs_hi");
+  else if (x == 1 && HL == 1 && aop == 3 && aopcde == 5)
+    unhandled_instruction ("dregs_hi = dregs - dregs (RND20)");
+  else if (x == 1 && HL == 1 && aop == 2 && aopcde == 5)
+    unhandled_instruction ("dregs_hi = dregs + dregs (RND20)");
+  else if (x == 0 && HL == 0 && aop == 1 && aopcde == 5)
+    unhandled_instruction ("dregs_lo = dregs - dregs (RND12)");
+  else if (x == 0 && HL == 0 && aop == 0 && aopcde == 5)
+    unhandled_instruction ("dregs_lo = dregs + dregs (RND12)");
+  else if (x == 1 && HL == 0 && aop == 3 && aopcde == 5)
+    unhandled_instruction ("dregs_lo = dregs - dregs (RND20)");
+  else if (x == 0 && HL == 1 && aop == 0 && aopcde == 5)
+    unhandled_instruction ("dregs_hi = dregs + dregs (RND12)");
+  else if (x == 1 && HL == 0 && aop == 2 && aopcde == 5)
+    unhandled_instruction ("dregs_lo = dregs + dregs (RND20)");
+  else if (x == 0 && HL == 1 && aop == 1 && aopcde == 5)
+    unhandled_instruction ("dregs_hi = dregs - dregs (RND12)");
+  else if (HL == 1 && aop == 0 && aopcde == 2)
+    unhandled_instruction ("dregs_hi = dregs_lo + dregs_lo amod1");
+  else if (HL == 1 && aop == 1 && aopcde == 2)
+    unhandled_instruction ("dregs_hi = dregs_lo + dregs_hi amod1");
+  else if (HL == 1 && aop == 2 && aopcde == 2)
+    unhandled_instruction ("dregs_hi = dregs_hi + dregs_lo amod1");
+  else if (HL == 1 && aop == 3 && aopcde == 2)
+    unhandled_instruction ("dregs_hi = dregs_hi + dregs_hi amod1");
+  else if (HL == 0 && aop == 0 && aopcde == 3)
+    unhandled_instruction ("dregs_lo = dregs_lo - dregs_lo amod1");
+  else if (HL == 0 && aop == 1 && aopcde == 3)
+    unhandled_instruction ("dregs_lo = dregs_lo - dregs_hi amod1");
+  else if (HL == 0 && aop == 3 && aopcde == 2)
+    unhandled_instruction ("dregs_lo = dregs_hi + dregs_hi amod1");
+  else if (HL == 1 && aop == 0 && aopcde == 3)
+    unhandled_instruction ("dregs_hi = dregs_lo - dregs_lo amod1");
+  else if (HL == 1 && aop == 1 && aopcde == 3)
+    unhandled_instruction ("dregs_hi = dregs_lo - dregs_hi amod1");
+  else if (HL == 1 && aop == 2 && aopcde == 3)
+    unhandled_instruction ("dregs_hi = dregs_hi - dregs_lo amod1");
+  else if (HL == 1 && aop == 3 && aopcde == 3)
+    unhandled_instruction ("dregs_hi = dregs_hi - dregs_hi amod1");
+  else if (HL == 0 && aop == 2 && aopcde == 2)
+    unhandled_instruction ("dregs_lo = dregs_hi + dregs_lo amod1");
+  else if (HL == 0 && aop == 1 && aopcde == 2)
+    unhandled_instruction ("dregs_lo = dregs_lo + dregs_hi amod1");
+  else if (HL == 0 && aop == 2 && aopcde == 3)
+    unhandled_instruction ("dregs_lo = dregs_hi - dregs_lo amod1");
+  else if (HL == 0 && aop == 3 && aopcde == 3)
+    unhandled_instruction ("dregs_lo = dregs_hi - dregs_hi amod1");
+  else if (HL == 0 && aop == 0 && aopcde == 2)
+    unhandled_instruction ("dregs_lo = dregs_lo + dregs_lo amod1");
+  else if (aop == 0 && aopcde == 9 && s == 1)
+    unhandled_instruction ("A0 = dregs");
+  else if (aop == 3 && aopcde == 11 && s == 0)
+    unhandled_instruction ("A0 -= A1");
+  else if (aop == 3 && aopcde == 11 && s == 1)
+    unhandled_instruction ("A0 -= A1 (W32)");
+  else if (aop == 3 && aopcde == 22 && HL == 1)
+    unhandled_instruction ("dregs = BYTEOP2M (dregs_pair, dregs_pair) (TH,R)");
+  else if (aop == 3 && aopcde == 22 && HL == 0)
+    unhandled_instruction ("dregs = BYTEOP2M (dregs_pair, dregs_pair) (TL,R)");
+  else if (aop == 2 && aopcde == 22 && HL == 1)
+    unhandled_instruction ("dregs = BYTEOP2M (dregs_pair, dregs_pair) (RNDH,R)");
+  else if (aop == 2 && aopcde == 22 && HL == 0)
+    unhandled_instruction ("dregs = BYTEOP2M (dregs_pair, dregs_pair) (RNDL,R)");
+  else if (aop == 1 && aopcde == 22 && HL == 1)
+    unhandled_instruction ("dregs = BYTEOP2P (dregs_pair, dregs_pair) (TH ,R)");
+  else if (aop == 1 && aopcde == 22 && HL == 0)
+    unhandled_instruction ("dregs = BYTEOP2P (dregs_pair, dregs_pair) (TL ,R)");
+  else if (aop == 0 && aopcde == 22 && HL == 1)
+    unhandled_instruction ("dregs = BYTEOP2P (dregs_pair, dregs_pair) (RNDH,R)");
+  else if (aop == 0 && aopcde == 22 && HL == 0)
+    unhandled_instruction ("dregs = BYTEOP2P (dregs_pair, dregs_pair) (RNDL,aligndir)");
+  else if (aop == 0 && s == 0 && aopcde == 8)
+    /* A0 = 0 */
+    saved_state.a0 = 0;
+  else if (aop == 0 && s == 1 && aopcde == 8)
+    unhandled_instruction ("A0 = A0 (S)");
+  else if (aop == 1 && s == 0 && aopcde == 8)
+    /* A1 = 0 */
+    saved_state.a1 = 0;
+  else if (aop == 1 && s == 1 && aopcde == 8)
+    unhandled_instruction ("A1 = A1 (S)");
+  else if (aop == 2 && s == 0 && aopcde == 8)
+    /* A1 = A0 = 0 */
+    saved_state.a1 = saved_state.a0 = 0;
+  else if (aop == 2 && s == 1 && aopcde == 8)
+    unhandled_instruction ("A1 = A1 (S) , A0 = A0 (S)");
+  else if (aop == 3 && s == 0 && aopcde == 8)
+    unhandled_instruction ("A0 = A1");
+  else if (aop == 3 && s == 1 && aopcde == 8)
+    unhandled_instruction ("A1 = A0");
+  else if (aop == 1 && aopcde == 9 && s == 0)
+    unhandled_instruction ("A0.x = dregs_lo");
+  else if (aop == 1 && HL == 0 && aopcde == 11)
+    unhandled_instruction ("dregs_lo = (A0 += A1)");
+  else if (aop == 3 && HL == 0 && aopcde == 16)
+    unhandled_instruction ("A1 = ABS A1, A0 = ABS A0");
+  else if (aop == 0 && aopcde == 23 && HL == 1)
+    unhandled_instruction ("dregs = BYTEOP3P (dregs_pair, dregs_pair) (HI,R)");
+  else if (aop == 3 && aopcde == 9 && s == 0)
+    unhandled_instruction ("A1.x = dregs_lo");
+  else if (aop == 1 && HL == 1 && aopcde == 16)
+    unhandled_instruction ("A1 = ABS A1");
+  else if (aop == 0 && HL == 1 && aopcde == 16)
+    unhandled_instruction ("A1 = ABS A0");
+  else if (aop == 2 && aopcde == 9 && s == 1)
+    unhandled_instruction ("A1 = dregs");
+  else if (HL == 0 && aop == 3 && aopcde == 12)
+    unhandled_instruction ("dregs_lo = dregs (RND)");
+  else if (aop == 1 && HL == 0 && aopcde == 16)
+    unhandled_instruction ("A0 = ABS A1");
+  else if (aop == 0 && HL == 0 && aopcde == 16)
+    unhandled_instruction ("A0 = ABS A0");
+  else if (aop == 3 && HL == 0 && aopcde == 15)
+    unhandled_instruction ("dregs = - dregs (V)");
+  else if (aop == 1 && HL == 1 && aopcde == 11)
+    unhandled_instruction ("dregs_hi = (A0 += A1)");
+  else if (aop == 2 && aopcde == 11 && s == 0)
+    unhandled_instruction ("A0 += A1");
+  else if (aop == 2 && aopcde == 11 && s == 1)
+    unhandled_instruction ("A0 += A1 (W32)");
+  else if (aop == 3 && HL == 0 && aopcde == 14)
+    unhandled_instruction ("A1 = - A1 , A0 = - A0");
+  else if (HL == 1 && aop == 3 && aopcde == 12)
+    unhandled_instruction ("dregs_hi = dregs (RND)");
+  else if (aop == 0 && aopcde == 23 && HL == 0)
+    unhandled_instruction ("dregs = BYTEOP3P (dregs_pair, dregs_pair) (LO,R)");
+  else if (aop == 0 && HL == 0 && aopcde == 14)
+    unhandled_instruction ("A0 = - A0");
+  else if (aop == 1 && HL == 0 && aopcde == 14)
+    unhandled_instruction ("A0 = - A1");
+  else if (aop == 0 && HL == 1 && aopcde == 14)
+    unhandled_instruction ("A1 = - A0");
+  else if (aop == 1 && HL == 1 && aopcde == 14)
+    unhandled_instruction ("A1 = - A1");
+  else if (aop == 0 && aopcde == 12)
+    unhandled_instruction ("dregs_hi=dregs_lo=SIGN(dregs_hi)*dregs_hi + SIGN(dregs_lo)*dregs_lo)");
+  else if (aop == 2 && aopcde == 0)
+    unhandled_instruction ("dregs = dregs -|+ dregs amod0");
+  else if (aop == 1 && aopcde == 12)
+    unhandled_instruction ("dregs = A1.L + A1.H , dregs = A0.L + A0.H");
+  else if (aop == 2 && aopcde == 4)
+    unhandled_instruction ("dregs = dregs + dregs , dregs = dregs - dregs amod1");
+  else if (HL == 0 && aopcde == 1)
+    unhandled_instruction ("dregs = dregs +|+ dregs , dregs = dregs -|- dregs (amod0, amod2)");
+  else if (aop == 0 && aopcde == 11)
+    unhandled_instruction ("dregs = (A0 += A1)");
+  else if (aop == 0 && aopcde == 10)
+    unhandled_instruction ("dregs_lo = A0.x");
+  else if (aop == 1 && aopcde == 10)
+    unhandled_instruction ("dregs_lo = A1.x");
+  else if (aop == 1 && aopcde == 0)
+    unhandled_instruction ("dregs = dregs +|- dregs amod0");
+  else if (aop == 3 && aopcde == 0)
+    unhandled_instruction ("dregs = dregs -|- dregs amod0");
+  else if (aop == 1 && aopcde == 4)
+    unhandled_instruction ("dregs = dregs - dregs amod1");
+  else if (aop == 0 && aopcde == 17)
+    unhandled_instruction ("dregs = A1 + A0, dregs = A1 - A0 amod1");
+  else if (aop == 1 && aopcde == 17)
+    unhandled_instruction ("dregs = A0 + A1, dregs = A0 - A1 amod1");
+  else if (aop == 0 && aopcde == 18)
+    unhandled_instruction ("SAA (dregs_pair, dregs_pair) aligndir");
+  else if (aop == 3 && aopcde == 18)
+    unhandled_instruction ("DISALGNEXCPT");
+  else if (aop == 0 && aopcde == 20)
+    unhandled_instruction ("dregs = BYTEOP1P (dregs_pair, dregs_pair) aligndir");
+  else if (aop == 1 && aopcde == 20)
+    unhandled_instruction ("dregs = BYTEOP1P (dregs_pair, dregs_pair) (T, R)");
+  else if (aop == 0 && aopcde == 21)
+    unhandled_instruction ("(dregs, dregs) = BYTEOP16P (dregs_pair, dregs_pair) aligndir");
+  else if (aop == 1 && aopcde == 21)
+    unhandled_instruction ("(dregs, dregs) = BYTEOP16M (dregs_pair, dregs_pair) aligndir");
+  else if (aop == 2 && aopcde == 7)
+    {
+      bu32 val = DREG (src0);
+      /* dregs = ABS dregs */
+      if (val >> 31)
+	val = -val;
+      /* @@@ The manual is talking about saturation.  Check what the hardware
+	 does when it gets 0x80000000.  */
+      setflags_logical (val);
+      DREG (dst0) = val;
+    }
+  else if (aop == 1 && aopcde == 7)
+    /* dregs = MIN (dregs, dregs) */
+    DREG (dst0) = min32 (DREG (src0), DREG (src1));
+  else if (aop == 0 && aopcde == 7)
+    /* dregs = MAX (dregs, dregs) */
+    DREG (dst0) = max32 (DREG (src0), DREG (src1));
+  else if (aop == 2 && aopcde == 6)
+    unhandled_instruction ("dregs = ABS dregs (V)");
+  else if (aop == 1 && aopcde == 6)
+    unhandled_instruction ("dregs = MIN (dregs, dregs) (V)");
+  else if (aop == 0 && aopcde == 6)
+    unhandled_instruction ("dregs = MAX (dregs, dregs) (V)");
+  else if (HL == 1 && aopcde == 1)
+    unhandled_instruction ("dregs = dregs +|- dregs, dregs = dregs -|+ dregs (amod0, amod2)");
+  else if (aop == 0 && aopcde == 4)
+    unhandled_instruction ("dregs = dregs + dregs amod1");
+  else if (aop == 0 && aopcde == 0)
+    unhandled_instruction ("dregs = dregs +|+ dregs amod0");
+  else if (aop == 0 && aopcde == 24)
+    unhandled_instruction ("dregs = BYTEPACK (dregs, dregs)");
+  else if (aop == 1 && aopcde == 24)
+    unhandled_instruction ("(dregs, dregs) = BYTEUNPACK dregs_pair aligndir");
+  else if (aopcde == 13)
+    unhandled_instruction ("(dregs, dregs) = SEARCH dregs (searchmod)");
+  else
+    illegal_instruction ();
+  PCREG += 4;
+}
+
+static void
+decode_dsp32shift_0 (bu16 iw0, bu16 iw1, bu32 pc)
+{
+  /* dsp32shift
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
+     |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int src0 = ((iw1 >> 3) & 0x7);
+  int src1 = ((iw1 >> 0) & 0x7);
+  int sop = ((iw1 >> 14) & 0x3);
+  int dst0 = ((iw1 >> 9) & 0x7);
+  int M = ((iw0 >> 11) & 0x1);
+  int sopcde = ((iw0 >> 0) & 0x1f);
+  int HLs = ((iw1 >> 12) & 0x3);
+
+  if (HLs == 0 && sop == 0 && sopcde == 0)
+    unhandled_instruction ("dregs_lo = ASHIFT dregs_lo BY dregs_lo");
+  else if (HLs == 1 && sop == 0 && sopcde == 0)
+    unhandled_instruction ("dregs_lo = ASHIFT dregs_hi BY dregs_lo");
+  else if (HLs == 2 && sop == 0 && sopcde == 0)
+    unhandled_instruction ("dregs_hi = ASHIFT dregs_lo BY dregs_lo");
+  else if (HLs == 3 && sop == 0 && sopcde == 0)
+    unhandled_instruction ("dregs_hi = ASHIFT dregs_hi BY dregs_lo");
+  else if (HLs == 0 && sop == 1 && sopcde == 0)
+    unhandled_instruction ("dregs_lo = ASHIFT dregs_lo BY dregs_lo (S)");
+  else if (HLs == 1 && sop == 1 && sopcde == 0)
+    unhandled_instruction ("dregs_lo = ASHIFT dregs_hi BY dregs_lo (S)");
+  else if (HLs == 2 && sop == 1 && sopcde == 0)
+    unhandled_instruction ("dregs_hi = ASHIFT dregs_lo BY dregs_lo (S)");
+  else if (HLs == 3 && sop == 1 && sopcde == 0)
+    unhandled_instruction ("dregs_hi = ASHIFT dregs_hi BY dregs_lo (S)");
+  else if (HLs == 0 && sop == 2 && sopcde == 0)
+    unhandled_instruction ("dregs_lo = LSHIFT dregs_lo BY dregs_lo");
+  else if (HLs == 1 && sop == 2 && sopcde == 0)
+    unhandled_instruction ("dregs_lo = LSHIFT dregs_hi BY dregs_lo");
+  else if (HLs == 2 && sop == 2 && sopcde == 0)
+    unhandled_instruction ("dregs_hi = LSHIFT dregs_lo BY dregs_lo");
+  else if (HLs == 3 && sop == 2 && sopcde == 0)
+    unhandled_instruction ("dregs_hi = LSHIFT dregs_hi BY dregs_lo");
+  else if (sop == 2 && sopcde == 3 && HLs == 1)
+    unhandled_instruction ("A1 = ROT A1 BY dregs_lo");
+  else if (sop == 0 && sopcde == 3 && HLs == 0)
+    unhandled_instruction ("A0 = ASHIFT A0 BY dregs_lo");
+  else if (sop == 0 && sopcde == 3 && HLs == 1)
+    unhandled_instruction ("A1 = ASHIFT A1 BY dregs_lo");
+  else if (sop == 1 && sopcde == 3 && HLs == 0)
+    unhandled_instruction ("A0 = LSHIFT A0 BY dregs_lo");
+  else if (sop == 1 && sopcde == 3 && HLs == 1)
+    unhandled_instruction ("A1 = LSHIFT A1 BY dregs_lo");
+  else if (sop == 2 && sopcde == 3 && HLs == 0)
+    unhandled_instruction ("A0 = ROT A0 BY dregs_lo");
+  else if (sop == 1 && sopcde == 1)
+    unhandled_instruction ("dregs = ASHIFT dregs BY dregs_lo (V,S)");
+  else if (sop == 0 && sopcde == 1)
+    unhandled_instruction ("dregs = ASHIFT dregs BY dregs_lo (V)");
+  else if (sop == 0 && sopcde == 2)
+    unhandled_instruction ("dregs = ASHIFT dregs BY dregs_lo");
+  else if (sop == 1 && sopcde == 2)
+    unhandled_instruction ("dregs = ASHIFT dregs BY dregs_lo (S)");
+  else if (sop == 2 && sopcde == 2)
+    unhandled_instruction ("dregs = SHIFT dregs BY dregs_lo");
+  else if (sop == 3 && sopcde == 2)
+    unhandled_instruction ("dregs = ROT dregs BY dregs_lo");
+  else if (sop == 2 && sopcde == 1)
+    unhandled_instruction ("dregs = SHIFT dregs BY dregs_lo (V)");
+  else if (sop == 0 && sopcde == 4)
+    unhandled_instruction ("dregs = PACK (dregs_lo, dregs_lo)");
+  else if (sop == 1 && sopcde == 4)
+    unhandled_instruction ("dregs = PACK (dregs_lo, dregs_hi)");
+  else if (sop == 2 && sopcde == 4)
+    unhandled_instruction ("dregs = PACK (dregs_hi, dregs_lo)");
+  else if (sop == 3 && sopcde == 4)
+    unhandled_instruction ("dregs = PACK (dregs_hi, dregs_hi)");
+  else if (sop == 0 && sopcde == 5)
+    unhandled_instruction ("dregs_lo = SIGNBITS dregs");
+  else if (sop == 1 && sopcde == 5)
+    unhandled_instruction ("dregs_lo = SIGNBITS dregs_lo");
+  else if (sop == 2 && sopcde == 5)
+    unhandled_instruction ("dregs_lo = SIGNBITS dregs_hi");
+  else if (sop == 0 && sopcde == 6)
+    unhandled_instruction ("dregs_lo = SIGNBITS A0");
+  else if (sop == 1 && sopcde == 6)
+    unhandled_instruction ("dregs_lo = SIGNBITS A1");
+  else if (sop == 3 && sopcde == 6)
+    unhandled_instruction ("dregs_lo = ONES dregs");
+  else if (sop == 0 && sopcde == 7)
+    unhandled_instruction ("dregs_lo = EXPADJ (dregs, dregs_lo)");
+  else if (sop == 1 && sopcde == 7)
+    unhandled_instruction ("dregs_lo = EXPADJ (dregs, dregs_lo) (V)");
+  else if (sop == 2 && sopcde == 7)
+    unhandled_instruction ("dregs_lo = EXPADJ (dregs_lo, dregs_lo)");
+  else if (sop == 3 && sopcde == 7)
+    unhandled_instruction ("dregs_lo = EXPADJ (dregs_hi, dregs_lo)");
+  else if (sop == 0 && sopcde == 8)
+    unhandled_instruction ("BITMUX (dregs, dregs, A0) (ASR)");
+  else if (sop == 1 && sopcde == 8)
+    unhandled_instruction ("BITMUX (dregs, dregs, A0) (ASL)");
+  else if (sop == 0 && sopcde == 9)
+    unhandled_instruction ("dregs_lo = VIT_MAX (dregs) (ASL)");
+  else if (sop == 1 && sopcde == 9)
+    unhandled_instruction ("dregs_lo = VIT_MAX (dregs) (ASR)");
+  else if (sop == 2 && sopcde == 9)
+    unhandled_instruction ("dregs = VIT_MAX (dregs, dregs) (ASL)");
+  else if (sop == 3 && sopcde == 9)
+    unhandled_instruction ("dregs = VIT_MAX (dregs, dregs) (ASR)");
+  else if (sop == 0 && sopcde == 10)
+    unhandled_instruction ("dregs = EXTRACT (dregs, dregs_lo) (Z)");
+  else if (sop == 1 && sopcde == 10)
+    unhandled_instruction ("dregs = EXTRACT (dregs, dregs_lo) (X)");
+  else if (sop == 2 && sopcde == 10)
+    unhandled_instruction ("dregs = DEPOSIT (dregs, dregs)");
+  else if (sop == 3 && sopcde == 10)
+    unhandled_instruction ("dregs = DEPOSIT (dregs, dregs) (X)");
+  else if (sop == 0 && sopcde == 11)
+    unhandled_instruction ("dregs_lo = CC = BXORSHIFT (A0, dregs)");
+  else if (sop == 1 && sopcde == 11)
+    unhandled_instruction ("dregs_lo = CC = BXOR (A0, dregs)");
+  else if (sop == 0 && sopcde == 12)
+    unhandled_instruction ("A0 = BXORSHIFT (A0, A1, CC)");
+  else if (sop == 1 && sopcde == 12)
+    unhandled_instruction ("dregs_lo = CC = BXOR (A0, A1, CC)");
+  else if (sop == 0 && sopcde == 13)
+    /* dregs = ALIGN8 (dregs, dregs) */
+    DREG (dst0) = (DREG (src1) << 24) | (DREG (src0) >> 8);
+  else if (sop == 1 && sopcde == 13)
+    /* dregs = ALIGN16 (dregs, dregs) */
+    DREG (dst0) = (DREG (src1) << 16) | (DREG (src0) >> 16);
+  else if (sop == 2 && sopcde == 13)
+    /* dregs = ALIGN24 (dregs , dregs) */
+    DREG (dst0) = (DREG (src1) << 8) | (DREG (src0) >> 24);
+  else
+    illegal_instruction ();
+  PCREG += 4;
+}
+
+static void
+decode_dsp32shiftimm_0 (bu16 iw0, bu16 iw1, bu32 pc)
+{
+  /* dsp32shiftimm
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
+     |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int src1 = ((iw1 >> 0) & 0x7);
+  int sop = ((iw1 >> 14) & 0x3);
+  int immag = ((iw1 >> 3) & 0x3f);
+  int newimmag = (-(iw1 >> 3) & 0x3f);
+  int dst0 = ((iw1 >> 9) & 0x7);
+  int M = ((iw0 >> 11) & 0x1);
+  int sopcde = ((iw0 >> 0) & 0x1f);
+  int HLs = ((iw1 >> 12) & 0x3);
+
+  if (HLs == 0 && sop == 0 && sopcde == 0)
+    unhandled_instruction ("dregs_lo = dregs_lo << uimm5");
+  else if (HLs == 1 && sop == 0 && sopcde == 0)
+    unhandled_instruction ("dregs_lo = dregs_hi << uimm5");
+  else if (HLs == 2 && sop == 0 && sopcde == 0)
+    unhandled_instruction ("dregs_hi = dregs_lo << uimm5");
+  else if (HLs == 3 && sop == 0 && sopcde == 0)
+    unhandled_instruction ("dregs_hi = dregs_hi << uimm5");
+  else if (HLs == 0 && sop == 1 && sopcde == 0)
+    unhandled_instruction ("dregs_lo = dregs_lo << imm5 (S)");
+  else if (HLs == 1 && sop == 1 && sopcde == 0)
+    unhandled_instruction ("dregs_lo = dregs_hi << imm5 (S)");
+  else if (HLs == 2 && sop == 1 && sopcde == 0)
+    unhandled_instruction ("dregs_hi = dregs_lo << imm5 (S)");
+  else if (HLs == 3 && sop == 1 && sopcde == 0)
+    unhandled_instruction ("dregs_hi = dregs_hi << imm5 (S)");
+  else if (HLs == 0 && sop == 2 && sopcde == 0)
+    unhandled_instruction ("dregs_lo = dregs_lo >> uimm5");
+  else if (HLs == 1 && sop == 2 && sopcde == 0)
+    unhandled_instruction ("dregs_lo = dregs_hi >> uimm5");
+  else if (HLs == 2 && sop == 2 && sopcde == 0)
+    unhandled_instruction ("dregs_hi = dregs_lo >> uimm5");
+  else if (HLs == 3 && sop == 2 && sopcde == 0)
+    unhandled_instruction ("dregs_hi = dregs_hi >> uimm5");
+  else if (sop == 2 && sopcde == 3 && HLs == 1)
+    unhandled_instruction ("A1 = ROT A1 BY imm6");
+  else if (sop == 0 && sopcde == 3 && HLs == 0)
+    unhandled_instruction ("A0 = A0 << imm6");
+  else if (sop == 0 && sopcde == 3 && HLs == 1)
+    unhandled_instruction ("A1 = A1 << imm6");
+  else if (sop == 1 && sopcde == 3 && HLs == 0)
+    unhandled_instruction ("A0 = A0 >> imm6");
+  else if (sop == 1 && sopcde == 3 && HLs == 1)
+    unhandled_instruction ("A1 = A1 >> imm6");
+  else if (sop == 2 && sopcde == 3 && HLs == 0)
+    unhandled_instruction ("A0 = ROT A0 BY imm6");
+  else if (sop == 1 && sopcde == 1)
+    unhandled_instruction ("dregs = dregs >>> uimm5 (V,S)");
+  else if (sop == 2 && sopcde == 1)
+    unhandled_instruction ("dregs = dregs >> uimm5 (V)");
+  else if (sop == 0 && sopcde == 1)
+    unhandled_instruction ("dregs = dregs << imm5 (V)");
+  else if (sop == 1 && sopcde == 2)
+    unhandled_instruction ("dregs = dregs << imm6 (S)");
+  else if (sop == 2 && sopcde == 2)
+    {
+      int count = imm6 (newimmag);
+      /* dregs = dregs >> imm6 */
+      if (count < 0)
+	DREG (dst0) = lshift (DREG (src1), -count);
+      else
+	DREG (dst0) = lshiftrt (DREG (src1), count);
+    }
+  else if (sop == 3 && sopcde == 2)
+    {
+      int t = imm6 (immag);
+      /* dregs = ROT dregs BY imm6 */
+
+      /* Reduce everything to rotate left.  */
+      if (t < 0)
+	t += 33;
+
+      if (t > 0)
+	{
+	  int oldcc = CCREG;
+	  bu32 srcval = DREG (src1);
+	  bu32 result;
+	  result = t == 32 ? 0 : srcval << t;
+	  result |= t == 1 ? 0 : srcval >> (33 - t);
+	  result |= oldcc << (t - 1);
+	  DREG (dst0) = result;
+	  CCREG = (srcval >> (32 - t)) & 1;
+	}
+    }
+  else if (sop == 0 && sopcde == 2)
+    {
+      int count = imm6 (newimmag);
+      /* dregs = dregs >>> imm6 */
+      if (count < 0)
+	DREG (dst0) = lshift (DREG (src1), -count);
+      else
+	DREG (dst0) = ashiftrt (DREG (src1), count);
+    }
+  else
+    illegal_instruction ();
+
+  PCREG += 4;
+}
+
+static void
+decode_psedoDEBUG_0 (bu16 iw0)
+{
+  /* psedoDEBUG
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int grp = ((iw0 >> 3) & 0x7);
+  int fn = ((iw0 >> 6) & 0x3);
+  int reg = ((iw0 >> 0) & 0x7);
+
+  if (reg == 0 && fn == 3)
+    unhandled_instruction ("DBG A0");
+  else if (reg == 1 && fn == 3)
+    unhandled_instruction ("DBG A1");
+  else if (reg == 3 && fn == 3)
+    unhandled_instruction ("ABORT");
+  else if (reg == 4 && fn == 3)
+    unhandled_instruction ("HLT");
+  else if (reg == 5 && fn == 3)
+    unhandled_instruction ("DBGHALT");
+  else if (reg == 6 && fn == 3)
+    unhandled_instruction ("DBGCMPLX (dregs)");
+  else if (reg == 7 && fn == 3)
+    unhandled_instruction ("DBG");
+  else if (grp == 0 && fn == 2)
+    unhandled_instruction ("OUTC dregs");
+  else if (fn == 0)
+    unhandled_instruction ("DBG allregs");
+  else if (fn == 1)
+    unhandled_instruction ("PRNT allregs");
+  else
+    illegal_instruction ();
+
+  PCREG += 2;
+}
+
+static void
+decode_psedoOChar_0 (bu16 iw0)
+{
+  /* psedoOChar
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int ch = ((iw0 >> 0) & 0xff);
+
+  unhandled_instruction ("OUTC uimm8");
+  PCREG += 2;
+}
+
+static void
+decode_psedodbg_assert_0 (bu16 iw0, bu16 iw1)
+{
+  /* psedodbg_assert
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 1 | 0 | - | - | - | - | - |.dbgop.....|.regtest...|
+     |.expected......................................................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int expected = ((iw1 >> 0) & 0xffff);
+  int dbgop = ((iw0 >> 3) & 0x7);
+  int regtest = ((iw0 >> 0) & 0x7);
+
+  if (dbgop == 0)
+    unhandled_instruction ("DBGA ( dregs_lo , uimm16 )");
+  else if (dbgop == 1)
+    unhandled_instruction ("DBGA ( dregs_hi , uimm16 )");
+  else if (dbgop == 2)
+    unhandled_instruction ("DBGAL ( dregs , uimm16 )");
+  else if (dbgop == 3)
+    unhandled_instruction ("DBGAH ( dregs , uimm16 )");
+  else
+    illegal_instruction ();
+  PCREG += 4;
+}
+
+static void
+_interp_insn_bfin (bu32 pc)
+{
+  bu8 buf[4];
+  bu16 iw0 = get_word (saved_state.memory, pc);
+  bu16 iw1 = get_word (saved_state.memory, pc + 2);
+
+  if ((iw0 & 0xf7ff) == 0xc003 && iw1 == 0x1800)
+    {
+      /* MNOP.  */
+      PCREG += 4;
+      return;
+    }
+  if ((iw0 & 0xFF00) == 0x0000)
+    decode_ProgCtrl_0 (iw0);
+  else if ((iw0 & 0xFFC0) == 0x0240)
+    decode_CaCTRL_0 (iw0);
+  else if ((iw0 & 0xFF80) == 0x0100)
+    decode_PushPopReg_0 (iw0);
+  else if ((iw0 & 0xFE00) == 0x0400)
+    decode_PushPopMultiple_0 (iw0);
+  else if ((iw0 & 0xFE00) == 0x0600)
+    decode_ccMV_0 (iw0);
+  else if ((iw0 & 0xF800) == 0x0800)
+    decode_CCflag_0 (iw0);
+  else if ((iw0 & 0xFFE0) == 0x0200)
+    decode_CC2dreg_0 (iw0);
+  else if ((iw0 & 0xFF00) == 0x0300)
+    decode_CC2stat_0 (iw0);
+  else if ((iw0 & 0xF000) == 0x1000)
+    decode_BRCC_0 (iw0, pc);
+  else if ((iw0 & 0xF000) == 0x2000)
+    decode_UJUMP_0 (iw0, pc);
+  else if ((iw0 & 0xF000) == 0x3000)
+    decode_REGMV_0 (iw0);
+  else if ((iw0 & 0xFC00) == 0x4000)
+    decode_ALU2op_0 (iw0);
+  else if ((iw0 & 0xFE00) == 0x4400)
+    decode_PTR2op_0 (iw0);
+  else if (((iw0 & 0xF800) == 0x4800))
+    decode_LOGI2op_0 (iw0);
+  else if (((iw0 & 0xF000) == 0x5000))
+    decode_COMP3op_0 (iw0);
+  else if (((iw0 & 0xF800) == 0x6000))
+    decode_COMPI2opD_0 (iw0);
+  else if (((iw0 & 0xF800) == 0x6800))
+    decode_COMPI2opP_0 (iw0);
+  else if (((iw0 & 0xF000) == 0x8000))
+    decode_LDSTpmod_0 (iw0);
+  else if (((iw0 & 0xFF60) == 0x9E60))
+    decode_dagMODim_0 (iw0);
+  else if (((iw0 & 0xFFF0) == 0x9F60))
+    decode_dagMODik_0 (iw0);
+  else if (((iw0 & 0xFC00) == 0x9C00))
+    decode_dspLDST_0 (iw0);
+  else if (((iw0 & 0xF000) == 0x9000))
+    decode_LDST_0 (iw0);
+  else if (((iw0 & 0xFC00) == 0xB800))
+    decode_LDSTiiFP_0 (iw0);
+  else if (((iw0 & 0xE000) == 0xA000))
+    decode_LDSTii_0 (iw0);
+  else if (((iw0 & 0xFF80) == 0xE080) && ((iw1 & 0x0C00) == 0x0000))
+    decode_LoopSetup_0 (iw0, iw1, pc);
+  else if (((iw0 & 0xFF00) == 0xE100) && ((iw1 & 0x0000) == 0x0000))
+    decode_LDIMMhalf_0 (iw0, iw1, pc);
+  else if (((iw0 & 0xFE00) == 0xE200) && ((iw1 & 0x0000) == 0x0000))
+    decode_CALLa_0 (iw0, iw1, pc);
+  else if (((iw0 & 0xFC00) == 0xE400) && ((iw1 & 0x0000) == 0x0000))
+    decode_LDSTidxI_0 (iw0, iw1, pc);
+  else if (((iw0 & 0xFFFE) == 0xE800) && ((iw1 & 0x0000) == 0x0000))
+    decode_linkage_0 (iw0, iw1);
+  else if (((iw0 & 0xF600) == 0xC000) && ((iw1 & 0x0000) == 0x0000))
+    decode_dsp32mac_0 (iw0, iw1, pc);
+  else if (((iw0 & 0xF600) == 0xC200) && ((iw1 & 0x0000) == 0x0000))
+    decode_dsp32mult_0 (iw0, iw1, pc);
+  else if (((iw0 & 0xF7C0) == 0xC400) && ((iw1 & 0x0000) == 0x0000))
+    decode_dsp32alu_0 (iw0, iw1, pc);
+  else if (((iw0 & 0xF7E0) == 0xC600) && ((iw1 & 0x01C0) == 0x0000))
+    decode_dsp32shift_0 (iw0, iw1, pc);
+  else if (((iw0 & 0xF7E0) == 0xC680) && ((iw1 & 0x0000) == 0x0000))
+    decode_dsp32shiftimm_0 (iw0, iw1, pc);
+  else if (((iw0 & 0xFF00) == 0xF800))
+    decode_psedoDEBUG_0 (iw0);
+  else if (((iw0 & 0xFF00) == 0xF900))
+    decode_psedoOChar_0 (iw0);
+  else if (((iw0 & 0xFFC0) == 0xF000) && ((iw1 & 0x0000) == 0x0000))
+    decode_psedodbg_assert_0 (iw0, iw1);
+  else
+    illegal_instruction ();
+}
+
+void
+interp_insn_bfin (bu32 pc)
+{
+  int i;
+  bu16 iw0 = get_word (saved_state.memory, pc);
+  
+  int is_multiinsn = ((iw0 & 0xc000) == 0xc000 && (iw0 & BIT_MULTI_INS)
+		      && ((iw0 & 0xe800) != 0xe800 /* not linkage */));
+
+  n_stores = 0;
+
+  _interp_insn_bfin (pc);
+  
+  /* Proper display of multiple issue instructions.  */
+  if (is_multiinsn)
+    {
+      _interp_insn_bfin (pc + 4);
+      _interp_insn_bfin (pc + 6);
+    }
+  for (i = 0; i < n_stores; i++)
+    *stores[i].addr = stores[i].val;
+}
diff -r -u -N -x CVS src.orig/sim/bfin/bfin-sim.h src/sim/bfin/bfin-sim.h
--- src.orig/sim/bfin/bfin-sim.h	1970-01-01 08:00:00.000000000 +0800
+++ src/sim/bfin/bfin-sim.h	2005-12-27 11:13:15.000000000 +0800
@@ -0,0 +1,122 @@
+/* Simulator for Analog Devices Blackfin processer.
+
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   Contributed by Analog Devices.
+
+   This file is part of simulators.
+
+   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
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include "sysdep.h"
+#include "gdb/callback.h"
+#include "gdb/remote-sim.h"
+#include "sim-config.h"
+#include "sim-types.h"
+
+typedef unsigned8 bu8;
+typedef unsigned16 bu16;
+typedef unsigned32 bu32;
+typedef unsigned64 bu64;
+typedef signed8 bs8;
+typedef signed16 bs16;
+typedef signed32 bs32;
+typedef signed64 bs64;
+
+typedef struct
+{
+  bu32 dpregs[16], iregs[4], mregs[4], bregs[4], lregs[4];
+  bu64 a0, a1;
+  bu32 lt[2], lc[2], lb[2];
+  int ac0, ac0_copy, ac1, an, aq;
+  int av0, av0s, av1, av1s, az, cc, v, v_copy, vs;
+  int v_internal;
+  bu32 pc, rets;
+
+  int ticks;
+  int insts;
+
+  int exception;
+
+  int end_of_registers;
+
+  int msize;
+  unsigned char *memory;
+  unsigned long bfd_mach;
+} saved_state_type;
+
+extern saved_state_type saved_state;
+
+#define GREG(x,i)	DPREG ((x) | (i << 3))
+#define DPREG(x)	(saved_state.dpregs[x])
+#define DREG(x)		(saved_state.dpregs[x])
+#define PREG(x)		(saved_state.dpregs[x + 8])
+#define SPREG		PREG (6)
+#define FPREG		PREG (7)
+#define IREG(x)		(saved_state.iregs[x])
+#define MREG(x)		(saved_state.mregs[x])
+#define BREG(x)		(saved_state.bregs[x])
+#define LREG(x)		(saved_state.lregs[x])
+#define A0REG		(saved_state.a0)
+#define A1REG		(saved_state.a1)
+#define CCREG		(saved_state.cc)
+#define LC0REG		(saved_state.lc[0])
+#define LT0REG		(saved_state.lt[0])
+#define LB0REG		(saved_state.lb[0])
+#define LC1REG		(saved_state.lc[1])
+#define LT1REG		(saved_state.lt[1])
+#define LB1REG		(saved_state.lb[1])
+#define RETSREG		(saved_state.rets)
+#define PCREG		(saved_state.pc)
+
+extern int did_jump;
+
+static inline void put_byte (unsigned char *memory, bu32 addr, bu8 v)
+{
+  memory[addr] = v;
+}
+
+static inline void put_word (unsigned char *memory, bu32 addr, bu16 v)
+{
+  memory[addr] = v;
+  memory[addr + 1] = v >> 8;
+}
+
+static inline void put_long (unsigned char *memory, bu32 addr, bu32 v)
+{
+  memory[addr] = v;
+  memory[addr + 1] = v >> 8;
+  memory[addr + 2] = v >> 16;
+  memory[addr + 3] = v >> 24;
+}
+
+static inline bu8 get_byte (unsigned char *memory, bu32 addr)
+{
+  return memory[addr];
+}
+
+static inline bu16 get_word (unsigned char *memory, bu32 addr)
+{
+  return (memory[addr] | (memory[addr + 1] << 8));
+}
+
+static inline bu32 get_long (unsigned char *memory, bu32 addr)
+{
+  return (memory[addr] | (memory[addr + 1] << 8)
+	  | (memory[addr + 2] << 16) | (memory[addr + 3] << 24));
+}
+
+extern void interp_insn_bfin (bu32);
+
diff -r -u -N -x CVS src.orig/sim/bfin/config.in src/sim/bfin/config.in
--- src.orig/sim/bfin/config.in	1970-01-01 08:00:00.000000000 +0800
+++ src/sim/bfin/config.in	2004-10-06 00:58:39.000000000 +0800
@@ -0,0 +1,158 @@
+/* config.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if using alloca.c.  */
+#undef C_ALLOCA
+
+/* Define to empty if the keyword does not work.  */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro.  */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+#undef HAVE_ALLOCA_H
+
+/* Define if you have a working `mmap' system call.  */
+#undef HAVE_MMAP
+
+/* Define as __inline if that's what the C compiler calls it.  */
+#undef inline
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+#undef off_t
+
+/* Define if you need to in order for stat and other things to work.  */
+#undef _POSIX_SOURCE
+
+/* Define as the return type of signal handlers (int or void).  */
+#undef RETSIGTYPE
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define to 1 if NLS is requested.  */
+#undef ENABLE_NLS
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext.  */
+#undef HAVE_GETTEXT
+
+/* Define as 1 if you have the stpcpy function.  */
+#undef HAVE_STPCPY
+
+/* Define if your locale.h file contains LC_MESSAGES.  */
+#undef HAVE_LC_MESSAGES
+
+/* Define if you have the __argz_count function.  */
+#undef HAVE___ARGZ_COUNT
+
+/* Define if you have the __argz_next function.  */
+#undef HAVE___ARGZ_NEXT
+
+/* Define if you have the __argz_stringify function.  */
+#undef HAVE___ARGZ_STRINGIFY
+
+/* Define if you have the __setfpucw function.  */
+#undef HAVE___SETFPUCW
+
+/* Define if you have the dcgettext function.  */
+#undef HAVE_DCGETTEXT
+
+/* Define if you have the getcwd function.  */
+#undef HAVE_GETCWD
+
+/* Define if you have the getpagesize function.  */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the getrusage function.  */
+#undef HAVE_GETRUSAGE
+
+/* Define if you have the munmap function.  */
+#undef HAVE_MUNMAP
+
+/* Define if you have the putenv function.  */
+#undef HAVE_PUTENV
+
+/* Define if you have the setenv function.  */
+#undef HAVE_SETENV
+
+/* Define if you have the setlocale function.  */
+#undef HAVE_SETLOCALE
+
+/* Define if you have the sigaction function.  */
+#undef HAVE_SIGACTION
+
+/* Define if you have the stpcpy function.  */
+#undef HAVE_STPCPY
+
+/* Define if you have the strcasecmp function.  */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the strchr function.  */
+#undef HAVE_STRCHR
+
+/* Define if you have the time function.  */
+#undef HAVE_TIME
+
+/* Define if you have the <argz.h> header file.  */
+#undef HAVE_ARGZ_H
+
+/* Define if you have the <fcntl.h> header file.  */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <fpu_control.h> header file.  */
+#undef HAVE_FPU_CONTROL_H
+
+/* Define if you have the <limits.h> header file.  */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <locale.h> header file.  */
+#undef HAVE_LOCALE_H
+
+/* Define if you have the <malloc.h> header file.  */
+#undef HAVE_MALLOC_H
+
+/* Define if you have the <nl_types.h> header file.  */
+#undef HAVE_NL_TYPES_H
+
+/* Define if you have the <stdlib.h> header file.  */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file.  */
+#undef HAVE_STRING_H
+
+/* Define if you have the <strings.h> header file.  */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/param.h> header file.  */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/resource.h> header file.  */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define if you have the <sys/time.h> header file.  */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <time.h> header file.  */
+#undef HAVE_TIME_H
+
+/* Define if you have the <unistd.h> header file.  */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the <values.h> header file.  */
+#undef HAVE_VALUES_H
diff -r -u -N -x CVS src.orig/sim/bfin/configure.ac src/sim/bfin/configure.ac
--- src.orig/sim/bfin/configure.ac	1970-01-01 08:00:00.000000000 +0800
+++ src/sim/bfin/configure.ac	2005-12-15 02:00:10.000000000 +0800
@@ -0,0 +1,12 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.59)dnl
+AC_INIT(Makefile.in)
+AC_CONFIG_HEADER(config.h:config.in)
+
+sinclude(../common/aclocal.m4)
+
+sinclude(../common/common.m4)
+
+AC_CHECK_HEADERS(unistd.h)
+
+SIM_AC_OUTPUT
diff -r -u -N -x CVS src.orig/sim/bfin/interp.c src/sim/bfin/interp.c
--- src.orig/sim/bfin/interp.c	1970-01-01 08:00:00.000000000 +0800
+++ src/sim/bfin/interp.c	2005-12-27 16:24:04.000000000 +0800
@@ -0,0 +1,618 @@
+/* Simulator for Analog Devices Blackfin processer.
+
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   Contributed by Analog Devices.
+
+   This file is part of simulators.
+
+   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
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+
+#include <signal.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "gdb/callback.h"
+#include "bfin-sim.h"
+#include "gdb/sim-bfin.h"
+
+/* This file is local - if newlib changes, then so should this.  */
+#include "syscall.h"
+
+#include <math.h>
+
+#ifdef _WIN32
+#include <float.h>		/* Needed for _isnan().  */
+#define isnan _isnan
+#endif
+
+#ifndef SIGBUS
+#define SIGBUS SIGSEGV
+#endif
+
+#ifndef SIGQUIT
+#define SIGQUIT SIGTERM
+#endif
+
+#ifndef SIGTRAP
+#define SIGTRAP 5
+#endif
+
+/* Define the rate at which the simulator should poll the host
+   for a quit. */
+#define POLL_QUIT_INTERVAL 0x60000
+
+saved_state_type saved_state;
+
+static char **prog_argv;
+static SIM_OPEN_KIND sim_kind;
+static char *myname;
+static int tracing = 0;
+static host_callback *callback;
+
+#if defined(__GO32__) || defined(_WIN32)
+int sim_memory_size = 19;
+#else
+int sim_memory_size = 24;
+#endif
+
+
+/* Count the number of arguments in an argv.  */
+static int
+count_argc (char **argv)
+{
+  int i;
+
+  if (! argv)
+    return -1;
+
+  for (i = 0; argv[i] != NULL; ++i)
+    continue;
+  return i;
+}
+
+/* This function exists mainly for the purpose of setting a breakpoint to
+   catch simulated bus errors when running the simulator under GDB.  */
+
+void
+raise_exception (int x)
+{
+  saved_state.exception = x;
+}
+
+void
+raise_buserror ()
+{
+  raise_exception (SIGBUS);
+}
+
+static int
+get_now ()
+{
+  return time ((long *) 0);
+}
+
+static int
+now_persec ()
+{
+  return 1;
+}
+
+/* Simulate a monitor trap, put the result into r0 and errno into r1
+   return offset by which to adjust pc.  */
+
+void
+bfin_trap ()
+{
+  int reason = DREG (2);
+  int sys = DREG (0);
+  bu32 args = DREG (1);
+
+  switch (sys)
+    {
+    case SYS_exit:
+      saved_state.exception = SIGQUIT;
+      DREG (0) = get_long (saved_state.memory, args);
+      return;
+    case SYS_open:
+      {
+	char *arg0 = (char *)(saved_state.memory + get_long (saved_state.memory, args));
+	bu32 arg1 = get_long (saved_state.memory, args + 4);
+	bu32 arg2 = get_long (saved_state.memory, args + 8);
+	if (strcmp (arg0, ":tt") == 0)
+	  DREG (0) = arg2 == 4 ? 0 : 1;
+	else
+	  DREG (0) = callback->open (callback, arg0, arg1);
+      }
+      return;
+
+    case SYS_write:
+      {
+	bu32 arg0 = get_long (saved_state.memory, args);
+	char *arg1 = (char *)(saved_state.memory + get_long (saved_state.memory, args + 4));
+	bu32 arg2 = get_long (saved_state.memory, args + 8);
+	DREG (0) = callback->write (callback, arg0, arg1, arg2);
+      }
+      return;
+
+    case SYS_read:
+      {
+	bu32 arg0 = get_long (saved_state.memory, args);
+	char *arg1 = (char *)(saved_state.memory + get_long (saved_state.memory, args + 4));
+	bu32 arg2 = get_long (saved_state.memory, args + 8);
+	DREG (0) = callback->read (callback, arg0, arg1, arg2);
+      }
+      return;
+      
+    case SYS_kill:
+      printf ("Killing with signal %d\n", get_long (saved_state.memory, args + 4));
+      raise (SIGABRT);
+
+    case SYS_close:
+      DREG (0) = callback->close (callback, get_long (saved_state.memory, args));
+      return;
+    case SYS_argc:
+      DREG (0) = count_argc (prog_argv);
+      break;
+    case SYS_argnlen:
+      {
+	bu32 arg0 = get_long (saved_state.memory, args);
+	if (arg0 < count_argc (prog_argv))
+	  DREG (0) = strlen (prog_argv[arg0]);
+	else
+	  DREG (0) = -1;
+      }
+      return;
+    case SYS_argn:
+      {
+	bu32 arg0 = get_long (saved_state.memory, args);
+	char *arg1 = (char *)(saved_state.memory + get_long (saved_state.memory, args + 4));
+	if (arg0 < count_argc (prog_argv))
+	  {
+	    /* Include the termination byte.  */
+	    int i = strlen (prog_argv[arg0]) + 1;
+	    DREG (0) = get_long (saved_state.memory, args + 4);
+	    memcpy (arg1, prog_argv[arg0], i);
+	  }
+	else
+	  DREG (0) = -1;
+      }
+      return;
+    case SYS_time:
+      DREG (0) = get_now ();
+      return;
+    default:
+      abort ();
+    }
+}
+
+void
+control_c (int sig)
+{
+  raise_exception (SIGINT);
+}
+
+/* Set the memory size to the power of two provided. */
+
+void
+sim_size (int power)
+{
+  saved_state.msize = 1 << power;
+
+  sim_memory_size = power;
+
+  if (saved_state.memory)
+    free (saved_state.memory);
+
+  saved_state.memory =
+    (unsigned char *) calloc (64, saved_state.msize / 64);
+
+  if (!saved_state.memory)
+    {
+      fprintf (stderr,
+	       "Not enough VM for simulation of %d bytes of RAM\n",
+	       saved_state.msize);
+
+      saved_state.msize = 1;
+      saved_state.memory = (unsigned char *) calloc (1, 1);
+    }
+}
+
+static void
+init_pointers ()
+{
+  if (saved_state.msize != 1 << sim_memory_size)
+    sim_size (sim_memory_size);
+}
+
+#define MMASKB ((saved_state.msize -1) & ~0)
+
+int
+sim_stop (SIM_DESC sd)
+{
+  raise_exception (SIGINT);
+  return 1;
+}
+
+/* Set by an instruction emulation function if we performed a jump.  */
+int did_jump;
+
+/* Execute a single instruction.  */
+
+static void
+step_once (SIM_DESC sd)
+{
+  bu32 oldpc = PCREG;
+
+  if (tracing)
+    fprintf (stderr, "PC: %08x, insn: %04x\n", PCREG,
+	     get_word (saved_state.memory, PCREG));
+
+  did_jump = 0;
+  interp_insn_bfin (PCREG);
+
+  /* @@@ Not sure how the hardware really behaves when the last insn
+     of a loop is a jump.  */
+  if (!did_jump)
+    {
+      if (LC1REG && oldpc == LB1REG && --LC1REG)
+	PCREG = LT1REG;
+      else if (LC0REG && oldpc == LB0REG && --LC0REG)
+	PCREG = LT0REG;
+    }
+}
+
+void
+sim_resume (SIM_DESC sd, int step, int siggnal)
+{
+  register int insts = 0;
+
+  int tick_start = get_now ();
+  void (*prev) () = signal (SIGINT, control_c);
+  void (*prev_fpe) () = signal (SIGFPE, SIG_IGN);
+
+  init_pointers ();
+
+  /* clear exceptions else it will stop */
+  saved_state.exception = 0;
+
+  if(step)
+    {
+      while(step && saved_state.exception == 0)
+	{
+	  /* not clear if this will be > 1. Potential problem area */
+	  step_once(sd);
+	  step--;
+	}
+      /* Emulate a hardware single step ... raise an exception */
+      saved_state.exception = SIGTRAP;
+    }
+  else
+    while (saved_state.exception == 0)
+      step_once(sd);
+
+  saved_state.ticks += get_now () - tick_start;
+  saved_state.insts += insts;
+
+  signal (SIGFPE, prev_fpe);
+  signal (SIGINT, prev);
+}
+
+int
+sim_write (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
+{
+  int i;
+
+  init_pointers ();
+
+  for (i = 0; i < size; i++)
+    saved_state.memory[(MMASKB & (addr + i))] = buffer[i];
+
+  return size;
+}
+
+int
+sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
+{
+  int i;
+
+  init_pointers ();
+
+  for (i = 0; i < size; i++)
+    buffer[i] = saved_state.memory[(MMASKB & (addr + i))];
+
+  return size;
+}
+
+int
+sim_trace (SIM_DESC sd)
+{
+  tracing = 1;
+  sim_resume (sd, 0, 0);
+  tracing = 0;
+  return 1;
+}
+
+void
+sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
+{
+  if (saved_state.exception == SIGQUIT)
+    {
+      *reason = sim_exited;
+      *sigrc = DREG (0);
+    }
+  else
+    {
+      *reason = sim_stopped;
+      *sigrc = saved_state.exception;
+    }
+}
+
+void
+sim_info (SIM_DESC sd, int verbose)
+{
+  double timetaken = 
+    (double) saved_state.ticks / (double) now_persec ();
+
+  callback->printf_filtered (callback, "\n\n# instructions executed  %10d\n", 
+			     saved_state.insts);
+  callback->printf_filtered (callback, "# real time taken        %10.4f\n",
+			     timetaken);
+}
+
+static void
+parse_and_set_memory_size (char *str)
+{
+  int n;
+
+  n = strtol (str, NULL, 10);
+  if (n > 0 && n <= 24)
+    sim_memory_size = n;
+  else
+    callback->printf_filtered (callback,
+			"Bad memory size %d; must be 1 to 24, inclusive\n", n);
+}
+
+SIM_DESC
+sim_open (SIM_OPEN_KIND kind, host_callback *cb,
+	  struct bfd *abfd, char **argv)
+{
+  char **p;
+
+  sim_kind = kind;
+  myname = argv[0];
+  callback = cb;
+
+  for (p = argv + 1; *p != NULL; ++p)
+    if (isdigit (**p))
+      parse_and_set_memory_size (*p);
+
+  /* fudge our descriptor for now */
+  return (SIM_DESC) 1;
+}
+
+void
+sim_close (SIM_DESC sd, int quitting)
+{
+  /* Nothing to do.  */
+}
+
+SIM_RC
+sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty)
+{
+  extern bfd *sim_load_file (); /* ??? Don't know where this should live.  */
+  bfd *prog_bfd;
+
+  prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
+			    sim_kind == SIM_OPEN_DEBUG,
+			    0, sim_write);
+
+  /* Set the bfd machine type.  */
+  if (prog_bfd)
+    saved_state.bfd_mach = bfd_get_mach (prog_bfd);
+  else if (abfd)
+    saved_state.bfd_mach = bfd_get_mach (abfd);
+  else
+    saved_state.bfd_mach = 0;
+
+  if (prog_bfd == NULL)
+    return SIM_RC_FAIL;
+  if (abfd == NULL)
+    bfd_close (prog_bfd);
+  return SIM_RC_OK;
+}
+
+SIM_RC
+sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
+		     char **argv, char **env)
+{
+  /* Clear the registers.  */
+  memset (&saved_state, 0,
+	  (char*) &saved_state.end_of_registers - (char*) &saved_state);
+
+  /* Set the PC.  */
+  if (prog_bfd != NULL)
+    saved_state.pc = bfd_get_start_address (prog_bfd);
+
+  SPREG = saved_state.msize;
+  /* Set the bfd machine type.  */
+  if (prog_bfd != NULL)
+    saved_state.bfd_mach = bfd_get_mach (prog_bfd);
+
+  /* Record the program's arguments.  */
+  prog_argv = argv;
+
+  return SIM_RC_OK;
+}
+
+void
+sim_do_command (SIM_DESC sd, char *cmd)
+{
+  char *sms_cmd = "set-memory-size";
+  int cmdsize;
+
+  if (cmd == NULL || *cmd == '\0')
+    cmd = "help";
+
+  cmdsize = strlen (sms_cmd);
+  if (strncmp (cmd, sms_cmd, cmdsize) == 0 
+      && strchr (" \t", cmd[cmdsize]) != NULL)
+    parse_and_set_memory_size (cmd + cmdsize + 1);
+  else if (strcmp (cmd, "help") == 0)
+    {
+      (callback->printf_filtered) (callback, 
+				   "List of Blackfin simulator commands:\n\n");
+      (callback->printf_filtered) (callback, "help <n> -- Display this information\n");
+      (callback->printf_filtered) (callback, "set-memory-size <n> -- Set the number of address bits to use\n");
+      (callback->printf_filtered) (callback, "\n");
+    }
+  else
+    (callback->printf_filtered) (callback, "Error: \"%s\" is not a valid Blackfin simulator command.\n", cmd);
+}
+
+void
+sim_set_callbacks (host_callback *p)
+{
+  callback = p;
+}
+
+int
+sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
+{
+  int value;
+
+  init_pointers ();
+  switch (rn)
+    {
+    case SIM_BFIN_R0_REGNUM : value = DREG(0); break;
+    case SIM_BFIN_R1_REGNUM : value = DREG(1); break;
+    case SIM_BFIN_R2_REGNUM : value = DREG(2); break;
+    case SIM_BFIN_R3_REGNUM : value = DREG(3); break;
+    case SIM_BFIN_R4_REGNUM : value = DREG(4); break;
+    case SIM_BFIN_R5_REGNUM : value = DREG(5); break;
+    case SIM_BFIN_R6_REGNUM : value = DREG(6); break;
+    case SIM_BFIN_R7_REGNUM : value = DREG(7); break;
+    case SIM_BFIN_P0_REGNUM : value = PREG(0); break;
+    case SIM_BFIN_P1_REGNUM : value = PREG(1); break;
+    case SIM_BFIN_P2_REGNUM : value = PREG(2); break;
+    case SIM_BFIN_P3_REGNUM : value = PREG(3); break;
+    case SIM_BFIN_P4_REGNUM : value = PREG(4); break;
+    case SIM_BFIN_P5_REGNUM : value = PREG(5); break;
+    case SIM_BFIN_SP_REGNUM : value = SPREG; break;
+    case SIM_BFIN_FP_REGNUM : value = FPREG; break;
+    case SIM_BFIN_I0_REGNUM : value = IREG(0); break;
+    case SIM_BFIN_I1_REGNUM : value = IREG(1); break;
+    case SIM_BFIN_I2_REGNUM : value = IREG(2); break;
+    case SIM_BFIN_I3_REGNUM : value = IREG(3); break;
+    case SIM_BFIN_M0_REGNUM : value = MREG(0); break;
+    case SIM_BFIN_M1_REGNUM : value = MREG(1); break;
+    case SIM_BFIN_M2_REGNUM : value = MREG(2); break;
+    case SIM_BFIN_M3_REGNUM : value = MREG(3); break;
+    case SIM_BFIN_B0_REGNUM : value = BREG(0); break;
+    case SIM_BFIN_B1_REGNUM : value = BREG(1); break;
+    case SIM_BFIN_B2_REGNUM : value = BREG(2); break;
+    case SIM_BFIN_B3_REGNUM : value = BREG(3); break;
+    case SIM_BFIN_L0_REGNUM : value = LREG(0); break;
+    case SIM_BFIN_L1_REGNUM : value = LREG(1); break;
+    case SIM_BFIN_L2_REGNUM : value = LREG(2); break;
+    case SIM_BFIN_L3_REGNUM : value = LREG(3); break;
+    case SIM_BFIN_RETS_REGNUM : value = RETSREG; break;
+    case SIM_BFIN_A0_DOT_X_REGNUM : value = A0REG; break;
+    case SIM_BFIN_AO_DOT_W_REGNUM : value = A0REG; break;
+    case SIM_BFIN_A1_DOT_X_REGNUM : value = A1REG; break;
+    case SIM_BFIN_A1_DOT_W_REGNUM : value = A1REG; break;
+    case SIM_BFIN_LC0_REGNUM : value = LC0REG; break;
+    case SIM_BFIN_LT0_REGNUM : value = LT0REG; break;
+    case SIM_BFIN_LB0_REGNUM : value = LB0REG; break;
+    case SIM_BFIN_LC1_REGNUM : value = LC1REG; break;
+    case SIM_BFIN_LT1_REGNUM : value = LT1REG; break;
+    case SIM_BFIN_LB1_REGNUM : value = LB1REG; break;
+    case SIM_BFIN_PC_REGNUM : value = PCREG; break;
+    case SIM_BFIN_CC_REGNUM : value = CCREG; break;
+    default :
+      return 0; // will be an error in gdb
+      break;
+  }
+
+  *(int *)memory = value;
+  return -1; // disables size checking in gdb
+}
+
+int
+sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
+{
+  int value = *(int *)memory;
+
+  init_pointers ();
+  switch (rn)
+    {
+    case SIM_BFIN_R0_REGNUM : DREG(0) = value; break;
+    case SIM_BFIN_R1_REGNUM : DREG(1) = value; break;
+    case SIM_BFIN_R2_REGNUM : DREG(2) = value; break;
+    case SIM_BFIN_R3_REGNUM : DREG(3) = value; break;
+    case SIM_BFIN_R4_REGNUM : DREG(4) = value; break;
+    case SIM_BFIN_R5_REGNUM : DREG(5) = value; break;
+    case SIM_BFIN_R6_REGNUM : DREG(6) = value; break;
+    case SIM_BFIN_R7_REGNUM : DREG(7) = value; break;
+    case SIM_BFIN_P0_REGNUM : PREG(0) = value; break;
+    case SIM_BFIN_P1_REGNUM : PREG(1) = value; break;
+    case SIM_BFIN_P2_REGNUM : PREG(2) = value; break;
+    case SIM_BFIN_P3_REGNUM : PREG(3) = value; break;
+    case SIM_BFIN_P4_REGNUM : PREG(4) = value; break;
+    case SIM_BFIN_P5_REGNUM : PREG(5) = value; break;
+    case SIM_BFIN_SP_REGNUM : SPREG = value; break;
+    case SIM_BFIN_FP_REGNUM : FPREG = value; break;
+    case SIM_BFIN_I0_REGNUM : IREG(0) = value; break;
+    case SIM_BFIN_I1_REGNUM : IREG(1) = value; break;
+    case SIM_BFIN_I2_REGNUM : IREG(2) = value; break;
+    case SIM_BFIN_I3_REGNUM : IREG(3) = value; break;
+    case SIM_BFIN_M0_REGNUM : MREG(0) = value; break;
+    case SIM_BFIN_M1_REGNUM : MREG(1) = value; break;
+    case SIM_BFIN_M2_REGNUM : MREG(2) = value; break;
+    case SIM_BFIN_M3_REGNUM : MREG(3) = value; break;
+    case SIM_BFIN_B0_REGNUM : BREG(0) = value; break;
+    case SIM_BFIN_B1_REGNUM : BREG(1) = value; break;
+    case SIM_BFIN_B2_REGNUM : BREG(2) = value; break;
+    case SIM_BFIN_B3_REGNUM : BREG(3) = value; break;
+    case SIM_BFIN_L0_REGNUM : LREG(0) = value; break;
+    case SIM_BFIN_L1_REGNUM : LREG(1) = value; break;
+    case SIM_BFIN_L2_REGNUM : LREG(2) = value; break;
+    case SIM_BFIN_L3_REGNUM : LREG(3) = value; break;
+    case SIM_BFIN_RETS_REGNUM : RETSREG = value; break;
+    case SIM_BFIN_A0_DOT_X_REGNUM : A0REG = value; break;
+    case SIM_BFIN_AO_DOT_W_REGNUM : A0REG = value; break;
+    case SIM_BFIN_A1_DOT_X_REGNUM : A1REG = value; break;
+    case SIM_BFIN_A1_DOT_W_REGNUM : A1REG = value; break;
+    case SIM_BFIN_LC0_REGNUM : LC0REG = value; break;
+    case SIM_BFIN_LT0_REGNUM : LT0REG = value; break;
+    case SIM_BFIN_LB0_REGNUM : LB0REG = value; break;
+    case SIM_BFIN_LC1_REGNUM : LC1REG = value; break;
+    case SIM_BFIN_LT1_REGNUM : LT1REG = value; break;
+    case SIM_BFIN_LB1_REGNUM : LB1REG = value; break;
+    case SIM_BFIN_PC_REGNUM : PCREG = value; break;
+    case SIM_BFIN_CC_REGNUM : CCREG = value; break;
+    default :
+      return 0; // will be an error in gdb
+      break;
+  }
+
+  return -1; // disables size checking in gdb
+}
+
diff -r -u -N -x CVS src.orig/sim/bfin/Makefile.in src/sim/bfin/Makefile.in
--- src.orig/sim/bfin/Makefile.in	1970-01-01 08:00:00.000000000 +0800
+++ src/sim/bfin/Makefile.in	2005-12-27 10:53:25.000000000 +0800
@@ -0,0 +1,29 @@
+#    Makefile template for Configure for the Blackfin simulator.
+#    Copyright (C) 2005 Free Software Foundation, Inc.
+#    Written by Analog Devices, Inc.
+# 
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+## COMMON_PRE_CONFIG_FRAG
+
+SIM_OBJS = interp.o bfin-dis.o sim-load.o
+
+INCLUDE = bfin-sim.h
+
+## COMMON_POST_CONFIG_FRAG
+
+interp.o: interp.c $(INCLUDE)
+bfin-dis.o: bfin-dis.c $(INCLUDE)
diff -r -u -N -x CVS src.orig/sim/bfin/syscall.h src/sim/bfin/syscall.h
--- src.orig/sim/bfin/syscall.h	1970-01-01 08:00:00.000000000 +0800
+++ src/sim/bfin/syscall.h	2005-12-27 16:04:50.000000000 +0800
@@ -0,0 +1,41 @@
+/* This file is copied from newlib.  Do not edit this alone.  */
+
+#define SYS_exit	1
+#define SYS_fork	2
+#define SYS_read	3
+#define SYS_write	4
+#define SYS_open	5
+#define SYS_close	6
+#define SYS_wait4	7
+#define SYS_creat	8
+#define SYS_link	9
+#define SYS_unlink	10
+#define SYS_execv	11
+#define SYS_chdir	12
+
+#define SYS_mknod	14
+#define SYS_chmod	15
+#define SYS_chown	16
+
+#define SYS_lseek	19
+#define SYS_getpid	20
+#define SYS_isatty	21
+#define SYS_fstat	22
+#define SYS_time	23
+#define SYS_kill	24
+
+#define SYS_stat	38
+
+#define SYS_pipe	42
+
+#define SYS_execve	59
+
+#define SYS_truncate	129
+#define SYS_ftruncate	130
+
+#define SYS_argc	172
+#define SYS_argnlen	173
+#define SYS_argn	174
+
+#define SYS_utime	201
+#define SYS_wait	202
diff -r -u -N -x CVS src.orig/sim/configure src/sim/configure
--- src.orig/sim/configure	2005-05-17 22:11:24.000000000 +0800
+++ src/sim/configure	2005-12-27 16:21:31.000000000 +0800
@@ -273,6 +273,7 @@
 
 ac_unique_file="Makefile.in"
 ac_subdirs_all="$ac_subdirs_all arm"
+ac_subdirs_all="$ac_subdirs_all bfin"
 ac_subdirs_all="$ac_subdirs_all cris"
 ac_subdirs_all="$ac_subdirs_all d10v"
 ac_subdirs_all="$ac_subdirs_all frv"
@@ -3420,6 +3421,13 @@
 	   testsuite=yes
 	   common=yes
 	   ;;
+       bfin-*-*)
+
+
+subdirs="$subdirs bfin"
+
+	   common=yes
+	   ;;
        cris-*-* | crisv32-*-*)
 
 
diff -r -u -N -x CVS src.orig/sim/configure.ac src/sim/configure.ac
--- src.orig/sim/configure.ac	2005-05-17 22:11:24.000000000 +0800
+++ src/sim/configure.ac	2005-12-12 18:01:29.000000000 +0800
@@ -50,6 +50,10 @@
 	   testsuite=yes
 	   common=yes
 	   ;;
+	bfin-*-*)
+           AC_CONFIG_SUBDIRS(bfin)
+	   common=yes
+	   ;;
        cris-*-* | crisv32-*-*)
 	   AC_CONFIG_SUBDIRS(cris)
 	   testsuite=yes



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]