sim: bfin: new port
authorMike Frysinger <vapier@gentoo.org>
Sun, 6 Mar 2011 00:20:21 +0000 (00:20 +0000)
committerMike Frysinger <vapier@gentoo.org>
Sun, 6 Mar 2011 00:20:21 +0000 (00:20 +0000)
This can boot Das U-Boot and a Linux kernel.  It also supports Linux
userspace FLAT and FDPIC (dynamic and static) ELFs.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
110 files changed:
include/gdb/ChangeLog
include/gdb/sim-bfin.h [new file with mode: 0644]
sim/ChangeLog
sim/MAINTAINERS
sim/bfin/Makefile.in [new file with mode: 0644]
sim/bfin/TODO [new file with mode: 0644]
sim/bfin/aclocal.m4 [new file with mode: 0644]
sim/bfin/bfin-sim.c [new file with mode: 0644]
sim/bfin/bfin-sim.h [new file with mode: 0644]
sim/bfin/bfroms/all.h [new file with mode: 0644]
sim/bfin/bfroms/bf50x-0.0.h [new file with mode: 0644]
sim/bfin/bfroms/bf51x-0.0.h [new file with mode: 0644]
sim/bfin/bfroms/bf51x-0.1.h [new file with mode: 0644]
sim/bfin/bfroms/bf51x-0.2.h [new file with mode: 0644]
sim/bfin/bfroms/bf526-0.0.h [new file with mode: 0644]
sim/bfin/bfroms/bf526-0.1.h [new file with mode: 0644]
sim/bfin/bfroms/bf527-0.0.h [new file with mode: 0644]
sim/bfin/bfroms/bf527-0.1.h [new file with mode: 0644]
sim/bfin/bfroms/bf527-0.2.h [new file with mode: 0644]
sim/bfin/bfroms/bf533-0.1.h [new file with mode: 0644]
sim/bfin/bfroms/bf533-0.2.h [new file with mode: 0644]
sim/bfin/bfroms/bf533-0.3.h [new file with mode: 0644]
sim/bfin/bfroms/bf537-0.0.h [new file with mode: 0644]
sim/bfin/bfroms/bf537-0.1.h [new file with mode: 0644]
sim/bfin/bfroms/bf537-0.3.h [new file with mode: 0644]
sim/bfin/bfroms/bf538-0.0.h [new file with mode: 0644]
sim/bfin/bfroms/bf54x-0.0.h [new file with mode: 0644]
sim/bfin/bfroms/bf54x-0.1.h [new file with mode: 0644]
sim/bfin/bfroms/bf54x-0.2.h [new file with mode: 0644]
sim/bfin/bfroms/bf54x_l1-0.0.h [new file with mode: 0644]
sim/bfin/bfroms/bf54x_l1-0.1.h [new file with mode: 0644]
sim/bfin/bfroms/bf54x_l1-0.2.h [new file with mode: 0644]
sim/bfin/bfroms/bf561-0.5.h [new file with mode: 0644]
sim/bfin/bfroms/bf59x-0.0.h [new file with mode: 0644]
sim/bfin/bfroms/bf59x_l1-0.1.h [new file with mode: 0644]
sim/bfin/config.in [new file with mode: 0644]
sim/bfin/configure [new file with mode: 0755]
sim/bfin/configure.ac [new file with mode: 0644]
sim/bfin/devices.c [new file with mode: 0644]
sim/bfin/devices.h [new file with mode: 0644]
sim/bfin/dv-bfin_cec.c [new file with mode: 0644]
sim/bfin/dv-bfin_cec.h [new file with mode: 0644]
sim/bfin/dv-bfin_ctimer.c [new file with mode: 0644]
sim/bfin/dv-bfin_ctimer.h [new file with mode: 0644]
sim/bfin/dv-bfin_dma.c [new file with mode: 0644]
sim/bfin/dv-bfin_dma.h [new file with mode: 0644]
sim/bfin/dv-bfin_dmac.c [new file with mode: 0644]
sim/bfin/dv-bfin_dmac.h [new file with mode: 0644]
sim/bfin/dv-bfin_ebiu_amc.c [new file with mode: 0644]
sim/bfin/dv-bfin_ebiu_amc.h [new file with mode: 0644]
sim/bfin/dv-bfin_ebiu_ddrc.c [new file with mode: 0644]
sim/bfin/dv-bfin_ebiu_ddrc.h [new file with mode: 0644]
sim/bfin/dv-bfin_ebiu_sdc.c [new file with mode: 0644]
sim/bfin/dv-bfin_ebiu_sdc.h [new file with mode: 0644]
sim/bfin/dv-bfin_emac.c [new file with mode: 0644]
sim/bfin/dv-bfin_emac.h [new file with mode: 0644]
sim/bfin/dv-bfin_eppi.c [new file with mode: 0644]
sim/bfin/dv-bfin_eppi.h [new file with mode: 0644]
sim/bfin/dv-bfin_evt.c [new file with mode: 0644]
sim/bfin/dv-bfin_evt.h [new file with mode: 0644]
sim/bfin/dv-bfin_gptimer.c [new file with mode: 0644]
sim/bfin/dv-bfin_gptimer.h [new file with mode: 0644]
sim/bfin/dv-bfin_jtag.c [new file with mode: 0644]
sim/bfin/dv-bfin_jtag.h [new file with mode: 0644]
sim/bfin/dv-bfin_mmu.c [new file with mode: 0644]
sim/bfin/dv-bfin_mmu.h [new file with mode: 0644]
sim/bfin/dv-bfin_nfc.c [new file with mode: 0644]
sim/bfin/dv-bfin_nfc.h [new file with mode: 0644]
sim/bfin/dv-bfin_otp.c [new file with mode: 0644]
sim/bfin/dv-bfin_otp.h [new file with mode: 0644]
sim/bfin/dv-bfin_pll.c [new file with mode: 0644]
sim/bfin/dv-bfin_pll.h [new file with mode: 0644]
sim/bfin/dv-bfin_ppi.c [new file with mode: 0644]
sim/bfin/dv-bfin_ppi.h [new file with mode: 0644]
sim/bfin/dv-bfin_rtc.c [new file with mode: 0644]
sim/bfin/dv-bfin_rtc.h [new file with mode: 0644]
sim/bfin/dv-bfin_sic.c [new file with mode: 0644]
sim/bfin/dv-bfin_sic.h [new file with mode: 0644]
sim/bfin/dv-bfin_spi.c [new file with mode: 0644]
sim/bfin/dv-bfin_spi.h [new file with mode: 0644]
sim/bfin/dv-bfin_trace.c [new file with mode: 0644]
sim/bfin/dv-bfin_trace.h [new file with mode: 0644]
sim/bfin/dv-bfin_twi.c [new file with mode: 0644]
sim/bfin/dv-bfin_twi.h [new file with mode: 0644]
sim/bfin/dv-bfin_uart.c [new file with mode: 0644]
sim/bfin/dv-bfin_uart.h [new file with mode: 0644]
sim/bfin/dv-bfin_uart2.c [new file with mode: 0644]
sim/bfin/dv-bfin_uart2.h [new file with mode: 0644]
sim/bfin/dv-bfin_wdog.c [new file with mode: 0644]
sim/bfin/dv-bfin_wdog.h [new file with mode: 0644]
sim/bfin/dv-bfin_wp.c [new file with mode: 0644]
sim/bfin/dv-bfin_wp.h [new file with mode: 0644]
sim/bfin/dv-eth_phy.c [new file with mode: 0644]
sim/bfin/gui.c [new file with mode: 0644]
sim/bfin/gui.h [new file with mode: 0644]
sim/bfin/insn_list.def [new file with mode: 0644]
sim/bfin/interp.c [new file with mode: 0644]
sim/bfin/linux-fixed-code.h [new file with mode: 0644]
sim/bfin/linux-fixed-code.s [new file with mode: 0644]
sim/bfin/linux-targ-map.h [new file with mode: 0644]
sim/bfin/machs.c [new file with mode: 0644]
sim/bfin/machs.h [new file with mode: 0644]
sim/bfin/proc_list.def [new file with mode: 0644]
sim/bfin/sim-main.h [new file with mode: 0644]
sim/bfin/tconfig.in [new file with mode: 0644]
sim/common/ChangeLog
sim/common/gennltvals.sh
sim/common/nltvals.def
sim/configure
sim/configure.tgt

index 19509e2..8b31e11 100644 (file)
@@ -1,3 +1,7 @@
+2011-03-05  Mike Frysinger  <vapier@gentoo.org>
+
+       * sim-bfin.h: New file.
+
 2011-01-11  Andrew Burgess  <aburgess@broadcom.com>
 
        * remote-sim.h (sim_store_register): Update the API
diff --git a/include/gdb/sim-bfin.h b/include/gdb/sim-bfin.h
new file mode 100644 (file)
index 0000000..3a006b8
--- /dev/null
@@ -0,0 +1,82 @@
+/* This file defines the interface between the Blackfin simulator and GDB.
+
+   Copyright (C) 2005-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices.
+
+   This file is part of GDB.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+enum sim_bfin_regnum {
+  SIM_BFIN_R0_REGNUM = 0,
+  SIM_BFIN_R1_REGNUM,
+  SIM_BFIN_R2_REGNUM,
+  SIM_BFIN_R3_REGNUM,
+  SIM_BFIN_R4_REGNUM,
+  SIM_BFIN_R5_REGNUM,
+  SIM_BFIN_R6_REGNUM,
+  SIM_BFIN_R7_REGNUM,
+  SIM_BFIN_P0_REGNUM,
+  SIM_BFIN_P1_REGNUM,
+  SIM_BFIN_P2_REGNUM,
+  SIM_BFIN_P3_REGNUM,
+  SIM_BFIN_P4_REGNUM,
+  SIM_BFIN_P5_REGNUM,
+  SIM_BFIN_SP_REGNUM,
+  SIM_BFIN_FP_REGNUM,
+  SIM_BFIN_I0_REGNUM,
+  SIM_BFIN_I1_REGNUM,
+  SIM_BFIN_I2_REGNUM,
+  SIM_BFIN_I3_REGNUM,
+  SIM_BFIN_M0_REGNUM,
+  SIM_BFIN_M1_REGNUM,
+  SIM_BFIN_M2_REGNUM,
+  SIM_BFIN_M3_REGNUM,
+  SIM_BFIN_B0_REGNUM,
+  SIM_BFIN_B1_REGNUM,
+  SIM_BFIN_B2_REGNUM,
+  SIM_BFIN_B3_REGNUM,
+  SIM_BFIN_L0_REGNUM,
+  SIM_BFIN_L1_REGNUM,
+  SIM_BFIN_L2_REGNUM,
+  SIM_BFIN_L3_REGNUM,
+  SIM_BFIN_A0_DOT_X_REGNUM,
+  SIM_BFIN_A0_DOT_W_REGNUM,
+  SIM_BFIN_A1_DOT_X_REGNUM,
+  SIM_BFIN_A1_DOT_W_REGNUM,
+  SIM_BFIN_ASTAT_REGNUM,
+  SIM_BFIN_RETS_REGNUM,
+  SIM_BFIN_LC0_REGNUM,
+  SIM_BFIN_LT0_REGNUM,
+  SIM_BFIN_LB0_REGNUM,
+  SIM_BFIN_LC1_REGNUM,
+  SIM_BFIN_LT1_REGNUM,
+  SIM_BFIN_LB1_REGNUM,
+  SIM_BFIN_CYCLES_REGNUM,
+  SIM_BFIN_CYCLES2_REGNUM,
+  SIM_BFIN_USP_REGNUM,
+  SIM_BFIN_SEQSTAT_REGNUM,
+  SIM_BFIN_SYSCFG_REGNUM,
+  SIM_BFIN_RETI_REGNUM,
+  SIM_BFIN_RETX_REGNUM,
+  SIM_BFIN_RETN_REGNUM,
+  SIM_BFIN_RETE_REGNUM,
+  SIM_BFIN_PC_REGNUM,
+  SIM_BFIN_CC_REGNUM,
+  SIM_BFIN_TEXT_ADDR,
+  SIM_BFIN_TEXT_END_ADDR,
+  SIM_BFIN_DATA_ADDR,
+  SIM_BFIN_IPEND_REGNUM
+};
+
index debebb2..7227992 100644 (file)
@@ -1,3 +1,9 @@
+2011-03-05  Mike Frysinger  <vapier@gentoo.org>
+
+       * MAINTAINERS: Add bfin entry.
+       * configure.tgt (bfin-*-*): Handle bfin targets.
+       * configure: Regenerate.
+
 2011-01-05  Mike Frysinger  <vapier@gentoo.org>
 
        * .gitignore: Add /*/hw-config.h.
index 1e0f2ce..d273002 100644 (file)
@@ -10,6 +10,7 @@ gdb-patches@sources.redhat.com
        Maintainers for particular sims:
 
 arm            Nick Clifton <nickc@redhat.com>
+bfin           Mike Frysinger <vapier@gentoo.org>
 cr16           M R Swami Reddy <MR.Swami.Reddy@nsc.com>
 frv            Dave Brolley <brolley@redhat.com>
 igen           (igen simulators)
diff --git a/sim/bfin/Makefile.in b/sim/bfin/Makefile.in
new file mode 100644 (file)
index 0000000..64f26d3
--- /dev/null
@@ -0,0 +1,97 @@
+#    Makefile template for Configure for the Blackfin simulator.
+#    Copyright (C) 2005-2011 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 3 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, see <http://www.gnu.org/licenses/>.
+
+# This selects the bfin newlib/libgloss syscall definitions.
+NL_TARGET = -DNL_TARGET_bfin
+
+## COMMON_PRE_CONFIG_FRAG
+
+# List of main object files for `run'.
+SIM_RUN_OBJS = nrun.o
+
+SIM_OBJS = \
+       $(SIM_NEW_COMMON_OBJS) \
+       bfin-sim.o \
+       devices.o \
+       gui.o \
+       interp.o \
+       machs.o \
+       sim-cpu.o \
+       sim-engine.o \
+       sim-hload.o \
+       sim-hrw.o \
+       sim-model.o \
+       sim-reason.o \
+       sim-reg.o \
+       sim-resume.o \
+       sim-stop.o \
+       @BFIN_SIM_EXTRA_OBJS@ \
+       $(SIM_EXTRA_OBJS)
+
+INCLUDE = bfin-sim.h
+
+SIM_EXTRA_CFLAGS = @SDL_CFLAGS@
+SIM_EXTRA_LIBS = @SDL_LIBS@ -lm
+
+## COMMON_POST_CONFIG_FRAG
+
+$(srcdir)/linux-fixed-code.h: $(srcdir)/linux-fixed-code.s Makefile.in
+       $(AS_FOR_TARGET) $< -o linux-fixed-code.o
+       (       set -e; \
+               echo "/* DO NOT EDIT: Autogenerated from linux-fixed-code.s.  */"; \
+               echo "static const unsigned char bfin_linux_fixed_code[] = {"; \
+               $(OBJDUMP_FOR_TARGET) -d -z linux-fixed-code.o > $@.dis; \
+               sed -n $@.dis \
+                       -e 's:^[^       ]*      :0x:' \
+                       -e '/^0x/{s:    .*::;s: *$$:,:;s: :, 0x:g;p}'; \
+               rm -f $@.dis; \
+               echo "};" \
+       ) > $@.tmp
+       rm -f linux-fixed-code.o
+       mv $@.tmp $@
+
+interp.o: interp.c targ-vals.h linux-targ-map.h linux-fixed-code.h devices.h $(INCLUDE)
+bfin-sim.o: bfin-sim.c $(INCLUDE)
+gui.o: gui.c $(INCLUDE)
+machs.o: machs.c $(INCLUDE)
+dv-bfin_cec.o: dv-bfin_cec.c devices.h $(INCLUDE)
+dv-bfin_ctimer.o: dv-bfin_ctimer.c devices.h $(INCLUDE)
+dv-bfin_dma.o: dv-bfin_dma.c devices.h $(INCLUDE)
+dv-bfin_dma_pmap.o: dv-bfin_dma_pmap.c devices.h $(INCLUDE)
+dv-bfin_ebiu_amc.o: dv-bfin_ebiu_amc.c devices.h $(INCLUDE)
+dv-bfin_ebiu_ddrc.o: dv-bfin_ebiu_ddrc.c devices.h $(INCLUDE)
+dv-bfin_ebiu_sdc.o: dv-bfin_ebiu_sdc.c devices.h $(INCLUDE)
+dv-bfin_emac.o: dv-bfin_emac.c devices.h $(INCLUDE)
+dv-bfin_eppi.o: dv-bfin_eppi.c devices.h $(INCLUDE)
+dv-bfin_evt.o: dv-bfin_evt.c devices.h $(INCLUDE)
+dv-bfin_gptimer.o: dv-bfin_gptimer.c devices.h $(INCLUDE)
+dv-bfin_jtag.o: dv-bfin_jtag.c devices.h $(INCLUDE)
+dv-bfin_mmu.o: dv-bfin_mmu.c devices.h $(INCLUDE)
+dv-bfin_nfc.o: dv-bfin_nfc.c devices.h $(INCLUDE)
+dv-bfin_otp.o: dv-bfin_otp.c devices.h $(INCLUDE)
+dv-bfin_pll.o: dv-bfin_pll.c devices.h $(INCLUDE)
+dv-bfin_ppi.o: dv-bfin_ppi.c devices.h $(INCLUDE)
+dv-bfin_rtc.o: dv-bfin_rtc.c devices.h $(INCLUDE)
+dv-bfin_sic.o: dv-bfin_sic.c devices.h $(INCLUDE)
+dv-bfin_spi.o: dv-bfin_spi.c devices.h $(INCLUDE)
+dv-bfin_trace.o: dv-bfin_trace.c devices.h $(INCLUDE)
+dv-bfin_twi.o: dv-bfin_twi.c devices.h $(INCLUDE)
+dv-bfin_uart.o: dv-bfin_uart.c devices.h $(INCLUDE)
+dv-bfin_uart2.o: dv-bfin_uart2.c devices.h $(INCLUDE)
+dv-bfin_wdog.o: dv-bfin_wdog.c devices.h $(INCLUDE)
+dv-bfin_wp.o: dv-bfin_wp.c devices.h $(INCLUDE)
+dv-eth_phy.o: devices.h $(INCLUDE)
diff --git a/sim/bfin/TODO b/sim/bfin/TODO
new file mode 100644 (file)
index 0000000..d180ab2
--- /dev/null
@@ -0,0 +1,28 @@
+need to review ASTAT write behavior
+
+how to model RETE and IVG0 bit in IPEND ...
+
+model the loop buffer ?  this means no ifetches because they're cached.
+see page 4-26 in Blackfin PRM under hardware loops.
+
+handle DSPID at 0xffe05000
+
+CEC should handle multiple exceptions at same address.  would need
+exception processing to be delayed ?  at least needs a stack for
+the CEC to pop things off.
+
+R0 = [SP++]; gets traced as R0 = [P6++];
+
+merge dv-bfin_evt with dv-bfin_cec since the EVT regs are part of the CEC
+
+fix single stepping over debug assert instructions in hardware
+
+exception in IVG5 causes double fault ?
+
+add a "file" option to the async banks to back it
+
+tests:
+       - check AN bits with Dreg subtraction
+               R0 = R1 - R2;
+       - check astat bits with vector add/sub +|+
+       - check acc with VIT_MAX and similiar insns
diff --git a/sim/bfin/aclocal.m4 b/sim/bfin/aclocal.m4
new file mode 100644 (file)
index 0000000..cbe3b55
--- /dev/null
@@ -0,0 +1,171 @@
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
+# serial 1 (pkg-config-0.24)
+# 
+# Copyright Â© 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+       AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+       _pkg_min_version=m4_default([$1], [0.9.0])
+       AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+       if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+               AC_MSG_RESULT([yes])
+       else
+               AC_MSG_RESULT([no])
+               PKG_CONFIG=""
+       fi
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists.  Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+# only at the first occurence in configure.ac, so if the first place
+# it's called might be skipped (such as if it is within an "if", you
+# have to call PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_default([$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+    pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+    PKG_CHECK_EXISTS([$3],
+                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+                    [pkg_failed=yes])
+ else
+    pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+       AC_MSG_RESULT([no])
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
+        else 
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+       m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+        ])
+elif test $pkg_failed = untried; then
+       AC_MSG_RESULT([no])
+       m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])dnl
+        ])
+else
+       $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+       $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+       $3
+fi[]dnl
+])# PKG_CHECK_MODULES
+
diff --git a/sim/bfin/bfin-sim.c b/sim/bfin/bfin-sim.c
new file mode 100644 (file)
index 0000000..6d9361e
--- /dev/null
@@ -0,0 +1,6099 @@
+/* Simulator for Analog Devices Blackfin processors.
+
+   Copyright (C) 2005-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "opcode/bfin.h"
+#include "sim-main.h"
+#include "dv-bfin_cec.h"
+#include "dv-bfin_mmu.h"
+
+#define HOST_LONG_WORD_SIZE (sizeof (long) * 8)
+
+#define SIGNEXTEND(v, n) \
+  (((bs32)(v) << (HOST_LONG_WORD_SIZE - (n))) >> (HOST_LONG_WORD_SIZE - (n)))
+
+static __attribute__ ((noreturn)) void
+illegal_instruction (SIM_CPU *cpu)
+{
+  TRACE_INSN (cpu, "ILLEGAL INSTRUCTION");
+  while (1)
+    cec_exception (cpu, VEC_UNDEF_I);
+}
+
+static __attribute__ ((noreturn)) void
+illegal_instruction_combination (SIM_CPU *cpu)
+{
+  TRACE_INSN (cpu, "ILLEGAL INSTRUCTION COMBINATION");
+  while (1)
+    cec_exception (cpu, VEC_ILGAL_I);
+}
+
+static __attribute__ ((noreturn)) void
+unhandled_instruction (SIM_CPU *cpu, const char *insn)
+{
+  SIM_DESC sd = CPU_STATE (cpu);
+  bu16 iw0, iw1;
+  bu32 iw2;
+
+  TRACE_EVENTS (cpu, "unhandled instruction");
+
+  iw0 = IFETCH (PCREG);
+  iw1 = IFETCH (PCREG + 2);
+  iw2 = ((bu32)iw0 << 16) | iw1;
+
+  sim_io_eprintf (sd, "Unhandled instruction at 0x%08x (%s opcode 0x", PCREG, insn);
+  if ((iw0 & 0xc000) == 0xc000)
+    sim_io_eprintf (sd, "%08x", iw2);
+  else
+    sim_io_eprintf (sd, "%04x", iw0);
+
+  sim_io_eprintf (sd, ") ... aborting\n");
+
+  illegal_instruction (cpu);
+}
+
+typedef enum
+{
+  c_0, c_1, c_4, c_2, c_uimm2, c_uimm3, c_imm3, c_pcrel4,
+  c_imm4, c_uimm4s4, c_uimm4s4d, c_uimm4, c_uimm4s2, c_negimm5s4, c_imm5,
+  c_imm5d, c_uimm5, c_imm6, c_imm7, c_imm7d, c_imm8, c_uimm8, c_pcrel8,
+  c_uimm8s4, c_pcrel8s4, c_lppcrel10, c_pcrel10, c_pcrel12, c_imm16s4,
+  c_luimm16, c_imm16, c_imm16d, c_huimm16, c_rimm16, c_imm16s2, c_uimm16s4,
+  c_uimm16s4d, c_uimm16, c_pcrel24, c_uimm32, c_imm32, c_huimm32, c_huimm32e,
+} const_forms_t;
+
+static const struct
+{
+  const char *name;
+  const int nbits;
+  const char reloc;
+  const char issigned;
+  const char pcrel;
+  const char scale;
+  const char offset;
+  const char negative;
+  const char positive;
+  const char decimal;
+  const char leading;
+  const char exact;
+} constant_formats[] =
+{
+  { "0",          0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "1",          0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "4",          0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "2",          0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "uimm2",      2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "uimm3",      3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "imm3",       3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "pcrel4",     4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
+  { "imm4",       4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "uimm4s4",    4, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0},
+  { "uimm4s4d",   4, 0, 0, 0, 2, 0, 0, 1, 1, 0, 0},
+  { "uimm4",      4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "uimm4s2",    4, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0},
+  { "negimm5s4",  5, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0},
+  { "imm5",       5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "imm5d",      5, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
+  { "uimm5",      5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "imm6",       6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "imm7",       7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "imm7d",      7, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
+  { "imm8",       8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "uimm8",      8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "pcrel8",     8, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
+  { "uimm8s4",    8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
+  { "pcrel8s4",   8, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
+  { "lppcrel10", 10, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
+  { "pcrel10",   10, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
+  { "pcrel12",   12, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
+  { "imm16s4",   16, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
+  { "luimm16",   16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "imm16",     16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "imm16d",    16, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
+  { "huimm16",   16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "rimm16",    16, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "imm16s2",   16, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0},
+  { "uimm16s4",  16, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
+  { "uimm16s4d", 16, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0},
+  { "uimm16",    16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "pcrel24",   24, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
+  { "uimm32",    32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "imm32",     32, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
+  { "huimm32",   32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+  { "huimm32e",  32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
+};
+
+static const char *
+fmtconst_str (const_forms_t cf, bs32 x, bu32 pc)
+{
+  static char buf[60];
+
+  if (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;
+     /*if (outf->symbol_at_address_func (ea, outf) || !constant_formats[cf].exact)
+       {
+         outf->print_address_func (ea, outf);
+         return "";
+       }
+     else*/
+       {
+         sprintf (buf, "%#x", x);
+         return buf;
+       }
+    }
+
+  /* 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
+    x = constant_formats[cf].issigned ? SIGNEXTEND (x, constant_formats[cf].nbits) : x;
+
+  if (constant_formats[cf].offset)
+    x += constant_formats[cf].offset;
+
+  if (constant_formats[cf].scale)
+    x <<= constant_formats[cf].scale;
+
+  if (constant_formats[cf].decimal)
+    {
+      if (constant_formats[cf].leading)
+       {
+         char ps[10];
+         sprintf (ps, "%%%ii", constant_formats[cf].leading);
+         sprintf (buf, ps, x);
+       }
+      else
+       sprintf (buf, "%i", x);
+    }
+  else
+    {
+      if (constant_formats[cf].issigned && x < 0)
+       sprintf (buf, "-0x%x", abs (x));
+      else
+       sprintf (buf, "0x%x", x);
+    }
+
+  return buf;
+}
+
+static bu32
+fmtconst_val (const_forms_t cf, bu32 x, bu32 pc)
+{
+  if (0 && constant_formats[cf].reloc)
+    {
+      bu32 ea = (((constant_formats[cf].pcrel
+                  ? (bu32)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_val (c_uimm16s4, x, 0)
+#define uimm16s4_str(x)        fmtconst_str (c_uimm16s4, x, 0)
+#define uimm16s4d(x)   fmtconst_val (c_uimm16s4d, x, 0)
+#define pcrel4(x)      fmtconst_val (c_pcrel4, x, pc)
+#define pcrel8(x)      fmtconst_val (c_pcrel8, x, pc)
+#define pcrel8s4(x)    fmtconst_val (c_pcrel8s4, x, pc)
+#define pcrel10(x)     fmtconst_val (c_pcrel10, x, pc)
+#define pcrel12(x)     fmtconst_val (c_pcrel12, x, pc)
+#define negimm5s4(x)   fmtconst_val (c_negimm5s4, x, 0)
+#define negimm5s4_str(x)       fmtconst_str (c_negimm5s4, x, 0)
+#define rimm16(x)      fmtconst_val (c_rimm16, x, 0)
+#define huimm16(x)     fmtconst_val (c_huimm16, x, 0)
+#define imm16(x)       fmtconst_val (c_imm16, x, 0)
+#define imm16_str(x)   fmtconst_str (c_imm16, x, 0)
+#define imm16d(x)      fmtconst_val (c_imm16d, x, 0)
+#define uimm2(x)       fmtconst_val (c_uimm2, x, 0)
+#define uimm3(x)       fmtconst_val (c_uimm3, x, 0)
+#define uimm3_str(x)   fmtconst_str (c_uimm3, x, 0)
+#define luimm16(x)     fmtconst_val (c_luimm16, x, 0)
+#define luimm16_str(x) fmtconst_str (c_luimm16, x, 0)
+#define uimm4(x)       fmtconst_val (c_uimm4, x, 0)
+#define uimm4_str(x)   fmtconst_str (c_uimm4, x, 0)
+#define uimm5(x)       fmtconst_val (c_uimm5, x, 0)
+#define uimm5_str(x)   fmtconst_str (c_uimm5, x, 0)
+#define imm16s2(x)     fmtconst_val (c_imm16s2, x, 0)
+#define imm16s2_str(x) fmtconst_str (c_imm16s2, x, 0)
+#define uimm8(x)       fmtconst_val (c_uimm8, x, 0)
+#define imm16s4(x)     fmtconst_val (c_imm16s4, x, 0)
+#define imm16s4_str(x) fmtconst_str (c_imm16s4, x, 0)
+#define uimm4s2(x)     fmtconst_val (c_uimm4s2, x, 0)
+#define uimm4s2_str(x) fmtconst_str (c_uimm4s2, x, 0)
+#define uimm4s4(x)     fmtconst_val (c_uimm4s4, x, 0)
+#define uimm4s4_str(x) fmtconst_str (c_uimm4s4, x, 0)
+#define uimm4s4d(x)    fmtconst_val (c_uimm4s4d, x, 0)
+#define lppcrel10(x)   fmtconst_val (c_lppcrel10, x, pc)
+#define imm3(x)                fmtconst_val (c_imm3, x, 0)
+#define imm3_str(x)    fmtconst_str (c_imm3, x, 0)
+#define imm4(x)                fmtconst_val (c_imm4, x, 0)
+#define uimm8s4(x)     fmtconst_val (c_uimm8s4, x, 0)
+#define imm5(x)                fmtconst_val (c_imm5, x, 0)
+#define imm5d(x)       fmtconst_val (c_imm5d, x, 0)
+#define imm6(x)                fmtconst_val (c_imm6, x, 0)
+#define imm7(x)                fmtconst_val (c_imm7, x, 0)
+#define imm7_str(x)    fmtconst_str (c_imm7, x, 0)
+#define imm7d(x)       fmtconst_val (c_imm7d, x, 0)
+#define imm8(x)                fmtconst_val (c_imm8, x, 0)
+#define pcrel24(x)     fmtconst_val (c_pcrel24, x, pc)
+#define pcrel24_str(x) fmtconst_str (c_pcrel24, x, pc)
+#define uimm16(x)      fmtconst_val (c_uimm16, x, 0)
+#define uimm32(x)      fmtconst_val (c_uimm32, x, 0)
+#define imm32(x)       fmtconst_val (c_imm32, x, 0)
+#define huimm32(x)     fmtconst_val (c_huimm32, x, 0)
+#define huimm32e(x)    fmtconst_val (c_huimm32e, x, 0)
+
+/* Table C-4. Core Register Encoding Map.  */
+const char * const greg_names[] =
+{
+  "R0",    "R1",      "R2",     "R3",    "R4",    "R5",    "R6",     "R7",
+  "P0",    "P1",      "P2",     "P3",    "P4",    "P5",    "SP",     "FP",
+  "I0",    "I1",      "I2",     "I3",    "M0",    "M1",    "M2",     "M3",
+  "B0",    "B1",      "B2",     "B3",    "L0",    "L1",    "L2",     "L3",
+  "A0.X",  "A0.W",    "A1.X",   "A1.W",  "<res>", "<res>", "ASTAT",  "RETS",
+  "<res>", "<res>",   "<res>",  "<res>", "<res>", "<res>", "<res>",  "<res>",
+  "LC0",   "LT0",     "LB0",    "LC1",   "LT1",   "LB1",   "CYCLES", "CYCLES2",
+  "USP",   "SEQSTAT", "SYSCFG", "RETI",  "RETX",  "RETN",  "RETE",   "EMUDAT",
+};
+static const char *
+get_allreg_name (int grp, int reg)
+{
+  return greg_names[(grp << 3) | reg];
+}
+static const char *
+get_preg_name (int reg)
+{
+  return get_allreg_name (1, reg);
+}
+
+static bool
+reg_is_reserved (int grp, int reg)
+{
+  return (grp == 4 && (reg == 4 || reg == 5)) || (grp == 5);
+}
+
+static bu32 *
+get_allreg (SIM_CPU *cpu, 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);
+    case 2: case 3: return &PREG (reg);
+    case 4: return &IREG (reg & 3);
+    case 5: return &MREG (reg & 3);
+    case 6: return &BREG (reg & 3);
+    case 7: return &LREG (reg & 3);
+    default:
+      switch (fullreg)
+       {
+       case 32: return &AXREG (0);
+       case 33: return &AWREG (0);
+       case 34: return &AXREG (1);
+       case 35: return &AWREG (1);
+       case 39: return &RETSREG;
+       case 48: return &LCREG (0);
+       case 49: return &LTREG (0);
+       case 50: return &LBREG (0);
+       case 51: return &LCREG (1);
+       case 52: return &LTREG (1);
+       case 53: return &LBREG (1);
+       case 54: return &CYCLESREG;
+       case 55: return &CYCLES2REG;
+       case 56: return &USPREG;
+       case 57: return &SEQSTATREG;
+       case 58: return &SYSCFGREG;
+       case 59: return &RETIREG;
+       case 60: return &RETXREG;
+       case 61: return &RETNREG;
+       case 62: return &RETEREG;
+       case 63: return &EMUDAT_INREG;
+       }
+      illegal_instruction (cpu);
+    }
+}
+
+static const char *
+amod0 (int s0, int x0)
+{
+  static const char * const mod0[] = {
+    "", " (S)", " (CO)", " (SCO)",
+  };
+  int i = s0 + (x0 << 1);
+
+  if (i < ARRAY_SIZE (mod0))
+    return mod0[i];
+  else
+    return "";
+}
+
+static const char *
+amod0amod2 (int s0, int x0, int aop0)
+{
+  static const char * const mod02[] = {
+    "", " (S)", " (CO)", " (SCO)",
+    "", "", "", "",
+    " (ASR)", " (S, ASR)", " (CO, ASR)", " (SCO, ASR)",
+    " (ASL)", " (S, ASL)", " (CO, ASL)", " (SCO, ASL)",
+  };
+  int i = s0 + (x0 << 1) + (aop0 << 2);
+
+  if (i < ARRAY_SIZE (mod02))
+    return mod02[i];
+  else
+    return "";
+}
+
+static const char *
+amod1 (int s0, int x0)
+{
+  static const char * const mod1[] = {
+    " (NS)", " (S)",
+  };
+  int i = s0 + (x0 << 1);
+
+  if (i < ARRAY_SIZE (mod1))
+    return mod1[i];
+  else
+    return "";
+}
+
+static const char *
+mac_optmode (int mmod, int MM)
+{
+  static const char * const omode[] = {
+    [(M_S2RND << 1) + 0] = " (S2RND)",
+    [(M_T     << 1) + 0] = " (T)",
+    [(M_W32   << 1) + 0] = " (W32)",
+    [(M_FU    << 1) + 0] = " (FU)",
+    [(M_TFU   << 1) + 0] = " (TFU)",
+    [(M_IS    << 1) + 0] = " (IS)",
+    [(M_ISS2  << 1) + 0] = " (ISS2)",
+    [(M_IH    << 1) + 0] = " (IH)",
+    [(M_IU    << 1) + 0] = " (IU)",
+    [(M_S2RND << 1) + 1] = " (M, S2RND)",
+    [(M_T     << 1) + 1] = " (M, T)",
+    [(M_W32   << 1) + 1] = " (M, W32)",
+    [(M_FU    << 1) + 1] = " (M, FU)",
+    [(M_TFU   << 1) + 1] = " (M, TFU)",
+    [(M_IS    << 1) + 1] = " (M, IS)",
+    [(M_ISS2  << 1) + 1] = " (M, ISS2)",
+    [(M_IH    << 1) + 1] = " (M, IH)",
+    [(M_IU    << 1) + 1] = " (M, IU)",
+  };
+  int i = MM + (mmod << 1);
+
+  if (i < ARRAY_SIZE (omode) && omode[i])
+    return omode[i];
+  else
+    return "";
+}
+
+static const char *
+get_store_name (SIM_CPU *cpu, bu32 *p)
+{
+  if (p >= &DREG (0) && p <= &CYCLESREG)
+    return greg_names[p - &DREG (0)];
+  else if (p == &AXREG (0))
+    return greg_names[4 * 8 + 0];
+  else if (p == &AWREG (0))
+    return greg_names[4 * 8 + 1];
+  else if (p == &AXREG (1))
+    return greg_names[4 * 8 + 2];
+  else if (p == &AWREG (1))
+    return greg_names[4 * 8 + 3];
+  else if (p == &ASTATREG (av0))
+    return "ASTAT[av0]";
+  else if (p == &ASTATREG (av0s))
+    return "ASTAT[av0s]";
+  else if (p == &ASTATREG (av1))
+    return "ASTAT[av1]";
+  else if (p == &ASTATREG (av1s))
+    return "ASTAT[av1s]";
+  else if (p == &ASTATREG (v))
+    return "ASTAT[v]";
+  else if (p == &ASTATREG (vs))
+    return "ASTAT[vs]";
+  else if (p == &ASTATREG (v_copy))
+    return "ASTAT[v_copy]";
+  else if (p == &ASTATREG (az))
+    return "ASTAT[az]";
+  else if (p == &ASTATREG (an))
+    return "ASTAT[an]";
+  else if (p == &ASTATREG (az))
+    return "ASTAT[az]";
+  else if (p == &ASTATREG (ac0))
+    return "ASTAT[ac0]";
+  else if (p == &ASTATREG (ac0_copy))
+    return "ASTAT[ac0_copy]";
+  else
+    {
+      /* Worry about this when we start to STORE() it.  */
+      sim_io_eprintf (CPU_STATE (cpu), "STORE(): unknown register\n");
+      abort ();
+    }
+}
+
+static void
+queue_store (SIM_CPU *cpu, bu32 *addr, bu32 val)
+{
+  struct store *s = &BFIN_CPU_STATE.stores[BFIN_CPU_STATE.n_stores];
+  s->addr = addr;
+  s->val = val;
+  TRACE_REGISTER (cpu, "queuing write %s = %#x",
+                 get_store_name (cpu, addr), val);
+  ++BFIN_CPU_STATE.n_stores;
+}
+#define STORE(X, Y) \
+  do { \
+    if (BFIN_CPU_STATE.n_stores == 20) abort (); \
+    queue_store (cpu, &(X), (Y)); \
+  } while (0)
+
+static void
+setflags_nz (SIM_CPU *cpu, bu32 val)
+{
+  SET_ASTATREG (az, val == 0);
+  SET_ASTATREG (an, val >> 31);
+}
+
+static void
+setflags_nz_2x16 (SIM_CPU *cpu, bu32 val)
+{
+  SET_ASTATREG (an, (bs16)val < 0 || (bs16)(val >> 16) < 0);
+  SET_ASTATREG (az, (bs16)val == 0 || (bs16)(val >> 16) == 0);
+}
+
+static void
+setflags_logical (SIM_CPU *cpu, bu32 val)
+{
+  setflags_nz (cpu, val);
+  SET_ASTATREG (ac0, 0);
+  SET_ASTATREG (v, 0);
+}
+
+static bu32
+add_brev (bu32 addend1, bu32 addend2)
+{
+  bu32 mask, b, r;
+  int i, cy;
+
+  mask = 0x80000000;
+  r = 0;
+  cy = 0;
+
+  for (i = 31; i >= 0; --i)
+    {
+      b = ((addend1 & mask) >> i) + ((addend2 & mask) >> i);
+      b += cy;
+      cy = b >> 1;
+      b &= 1;
+      r |= b << i;
+      mask >>= 1;
+    }
+
+  return r;
+}
+
+/* This is a bit crazy, but we want to simulate the hardware behavior exactly
+   rather than worry about the circular buffers being used correctly.  Which
+   isn't to say there isn't room for improvement here, just that we want to
+   be conservative.  See also dagsub().  */
+static bu32
+dagadd (SIM_CPU *cpu, int dagno, bs32 M)
+{
+  bu64 i = IREG (dagno);
+  bu64 l = LREG (dagno);
+  bu64 b = BREG (dagno);
+  bu64 m = (bu32)M;
+
+  bu64 LB, IM, IML;
+  bu32 im32, iml32, lb32, res;
+  bu64 msb, car;
+
+  /* A naïve implementation that mostly works:
+  res = i + m;
+  if (l && res >= b + l)
+    res -= l;
+  STORE (IREG (dagno), res);
+   */
+
+  msb = (bu64)1 << 31;
+  car = (bu64)1 << 32;
+
+  IM = i + m;
+  im32 = IM;
+  LB = l + b;
+  lb32 = LB;
+
+  if (M < 0)
+    {
+      IML = i + m + l;
+      iml32 = IML;
+      if ((i & msb) || (IM & car))
+       res = (im32 < b) ? iml32 : im32;
+      else
+       res = (im32 < b) ? im32 : iml32;
+    }
+  else
+    {
+      IML = i + m - l;
+      iml32 = IML;
+      if ((IM & car) == (LB & car))
+       res = (im32 < lb32) ? im32 : iml32;
+      else
+       res = (im32 < lb32) ? iml32 : im32;
+    }
+
+  STORE (IREG (dagno), res);
+  return res;
+}
+
+/* See dagadd() notes above.  */
+static bu32
+dagsub (SIM_CPU *cpu, int dagno, bs32 M)
+{
+  bu64 i = IREG (dagno);
+  bu64 l = LREG (dagno);
+  bu64 b = BREG (dagno);
+  bu64 m = (bu32)M;
+
+  bu64 mbar = (bu32)(~m + 1);
+  bu64 LB, IM, IML;
+  bu32 b32, im32, iml32, lb32, res;
+  bu64 msb, car;
+
+  /* A naïve implementation that mostly works:
+  res = i - m;
+  if (l && newi < b)
+    newi += l;
+  STORE (IREG (dagno), newi);
+   */
+
+  msb = (bu64)1 << 31;
+  car = (bu64)1 << 32;
+
+  IM = i + mbar;
+  im32 = IM;
+  LB = l + b;
+  lb32 = LB;
+
+  if (M < 0)
+    {
+      IML = i + mbar - l;
+      iml32 = IML;
+      if (!!((i & msb) && (IM & car)) == !!(LB & car))
+       res = (im32 < lb32) ? im32 : iml32;
+      else
+       res = (im32 < lb32) ? iml32 : im32;
+    }
+  else
+    {
+      IML = i + mbar + l;
+      iml32 = IML;
+      b32 = b;
+      if (M == 0 || IM & car)
+       res = (im32 < b32) ? iml32 : im32;
+      else
+       res = (im32 < b32) ? im32 : iml32;
+    }
+
+  STORE (IREG (dagno), res);
+  return res;
+}
+
+static bu40
+ashiftrt (SIM_CPU *cpu, bu40 val, int cnt, int size)
+{
+  int real_cnt = cnt > size ? size : cnt;
+  bu40 sgn = ~(((val & 0xFFFFFFFFFFull) >> (size - 1)) - 1);
+  int sgncnt = size - 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;
+  SET_ASTATREG (an, val >> (size - 1));
+  SET_ASTATREG (az, val == 0);
+  /* XXX: Need to check ASTAT[v] behavior here.  */
+  SET_ASTATREG (v, 0);
+  return val;
+}
+
+static bu64
+lshiftrt (SIM_CPU *cpu, bu64 val, int cnt, int size)
+{
+  int real_cnt = cnt > size ? size : cnt;
+  if (real_cnt > 16)
+    val >>= 16, real_cnt -= 16;
+  val >>= real_cnt;
+  switch (size)
+    {
+    case 16:
+      val &= 0xFFFF;
+      break;
+    case 32:
+      val &= 0xFFFFFFFF;
+      break;
+    case 40:
+      val &= 0xFFFFFFFFFFull;
+      break;
+    default:
+      illegal_instruction (cpu);
+      break;
+    }
+  SET_ASTATREG (an, val >> (size - 1));
+  SET_ASTATREG (az, val == 0);
+  SET_ASTATREG (v, 0);
+  return val;
+}
+
+static bu64
+lshift (SIM_CPU *cpu, bu64 val, int cnt, int size, bool saturate)
+{
+  int i, j, real_cnt = cnt > size ? size : cnt;
+  bu64 sgn = ~((val >> (size - 1)) - 1);
+  int mask_cnt = size - 1;
+  bu64 masked, new_val = val, tmp;
+  bu64 mask = ~0;
+
+  mask <<= mask_cnt;
+  sgn <<= mask_cnt;
+  masked = val & mask;
+
+  if (real_cnt > 16)
+    new_val <<= 16, real_cnt -= 16;
+
+  new_val <<= real_cnt;
+
+  masked = new_val & mask;
+
+  /* If an operation would otherwise cause a positive value to overflow
+     and become negative, instead, saturation limits the result to the
+     maximum positive value for the size register being used.
+
+     Conversely, if an operation would otherwise cause a negative value
+     to overflow and become positive, saturation limits the result to the
+     maximum negative value for the register size.
+
+     However, it's a little more complex than looking at sign bits, we need
+     to see if we are shifting the sign information away...  */
+  tmp = val & ((~mask << 1) | 1);
+
+  j = 0;
+  for (i = 1; i <= real_cnt && saturate; i++)
+    {
+      if ((tmp & ((bu64)1 << (size - 1))) !=
+         (((val >> mask_cnt) & 0x1) << mask_cnt))
+       j++;
+      tmp <<= 1;
+    }
+  saturate &= (!sgn && (new_val & (1 << mask_cnt)))
+             || (sgn && !(new_val & (1 << mask_cnt)));
+
+  switch (size)
+    {
+    case 16:
+      if (j || (saturate && (new_val & mask)))
+       new_val = sgn == 0 ? 0x7fff : 0x8000, saturate = 1;
+      new_val &= 0xFFFF;
+      break;
+    case 32:
+      new_val &= 0xFFFFFFFF;
+      masked &= 0xFFFFFFFF;
+      if (j || (saturate && ((sgn != masked) || (!sgn && new_val == 0))))
+       new_val = sgn == 0 ? 0x7fffffff : 0x80000000, saturate = 1;
+      break;
+    case 40:
+      new_val &= 0xFFFFFFFFFFull;
+      masked &= 0xFFFFFFFFFFull;
+      break;
+    default:
+      illegal_instruction (cpu);
+      break;
+    }
+
+  SET_ASTATREG (an, new_val >> (size - 1));
+  SET_ASTATREG (az, new_val == 0);
+  SET_ASTATREG (v, !!(saturate || j));
+  if (saturate || j)
+    SET_ASTATREG (vs, 1);
+  return new_val;
+}
+
+static bu32
+algn (bu32 l, bu32 h, bu32 aln)
+{
+  if (aln == 0)
+    return l;
+  else
+    return (l >> (8 * aln)) | (h << (32 - 8 * aln));
+}
+
+static bu32
+saturate_s16 (bu64 val, bu32 *overflow)
+{
+  if ((bs64)val < -0x8000ll)
+    {
+      if (overflow)
+       *overflow = 1;
+      return 0x8000;
+    }
+  if ((bs64)val > 0x7fff)
+    {
+      if (overflow)
+       *overflow = 1;
+      return 0x7fff;
+    }
+  return val & 0xffff;
+}
+
+static bu40
+rot40 (bu40 val, int shift, bu32 *cc)
+{
+  const int nbits = 40;
+  bu40 ret;
+
+  shift = CLAMP (shift, -nbits, nbits);
+  if (shift == 0)
+    return val;
+
+  /* Reduce everything to rotate left.  */
+  if (shift < 0)
+    shift += nbits + 1;
+
+  ret = shift == nbits ? 0 : val << shift;
+  ret |= shift == 1 ? 0 : val >> ((nbits + 1) - shift);
+  ret |= (bu40)*cc << (shift - 1);
+  *cc = (val >> (nbits - shift)) & 1;
+
+  return ret;
+}
+
+static bu32
+rot32 (bu32 val, int shift, bu32 *cc)
+{
+  const int nbits = 32;
+  bu32 ret;
+
+  shift = CLAMP (shift, -nbits, nbits);
+  if (shift == 0)
+    return val;
+
+  /* Reduce everything to rotate left.  */
+  if (shift < 0)
+    shift += nbits + 1;
+
+  ret = shift == nbits ? 0 : val << shift;
+  ret |= shift == 1 ? 0 : val >> ((nbits + 1) - shift);
+  ret |= (bu32)*cc << (shift - 1);
+  *cc = (val >> (nbits - shift)) & 1;
+
+  return ret;
+}
+
+static bu32
+add32 (SIM_CPU *cpu, bu32 a, bu32 b, int carry, int sat)
+{
+  int flgs = (a >> 31) & 1;
+  int flgo = (b >> 31) & 1;
+  bu32 v = a + b;
+  int flgn = (v >> 31) & 1;
+  int overflow = (flgs ^ flgn) & (flgo ^ flgn);
+
+  if (sat && overflow)
+    {
+      v = (bu32)1 << 31;
+      if (flgn)
+       v -= 1;
+      flgn = (v >> 31) & 1;
+    }
+
+  SET_ASTATREG (an, flgn);
+  if (overflow)
+    SET_ASTATREG (vs, 1);
+  SET_ASTATREG (v, overflow);
+  ASTATREG (v_internal) |= overflow;
+  SET_ASTATREG (az, v == 0);
+  if (carry)
+    SET_ASTATREG (ac0, ~a < b);
+
+  return v;
+}
+
+static bu32
+sub32 (SIM_CPU *cpu, bu32 a, bu32 b, int carry, int sat, int parallel)
+{
+  int flgs = (a >> 31) & 1;
+  int flgo = (b >> 31) & 1;
+  bu32 v = a - b;
+  int flgn = (v >> 31) & 1;
+  int overflow = (flgs ^ flgo) & (flgn ^ flgs);
+
+  if (sat && overflow)
+    {
+      v = (bu32)1 << 31;
+      if (flgn)
+       v -= 1;
+      flgn = (v >> 31) & 1;
+    }
+
+  if (!parallel || flgn)
+    SET_ASTATREG (an, flgn);
+  if (overflow)
+    SET_ASTATREG (vs, 1);
+  if (!parallel || overflow)
+    SET_ASTATREG (v, overflow);
+  if (!parallel || overflow)
+    ASTATREG (v_internal) |= overflow;
+  if (!parallel || v == 0)
+    SET_ASTATREG (az, v == 0);
+  if (carry && (!parallel || b <= a))
+    SET_ASTATREG (ac0, b <= a);
+
+  return v;
+}
+
+static bu32
+add16 (SIM_CPU *cpu, bu16 a, bu16 b, bu32 *carry, bu32 *overfl,
+       bu32 *zero, bu32 *neg, int sat, int scale)
+{
+  int flgs = (a >> 15) & 1;
+  int flgo = (b >> 15) & 1;
+  bs64 v = (bs16)a + (bs16)b;
+  int flgn = (v >> 15) & 1;
+  int overflow = (flgs ^ flgn) & (flgo ^ flgn);
+
+  switch (scale)
+    {
+    case 0:
+      break;
+    case 2:
+      /* (ASR)  */
+      v = (a >> 1) + (a & 0x8000) + (b >> 1) + (b & 0x8000)
+         + (((a & 1) + (b & 1)) >> 1);
+      v |= -(v & 0x8000);
+      break;
+    case 3:
+      /* (ASL)  */
+      v = (v << 1);
+      break;
+    default:
+      illegal_instruction (cpu);
+    }
+
+  flgn = (v >> 15) & 1;
+  overflow = (flgs ^ flgn) & (flgo ^ flgn);
+
+  if (v > (bs64)0xffff)
+    overflow = 1;
+
+  if (sat)
+    v = saturate_s16 (v, 0);
+
+  if (neg)
+    *neg |= (v >> 15) & 1;
+  if (overfl)
+    *overfl |= overflow;
+  if (zero)
+    *zero |= (v & 0xFFFF) == 0;
+  if (carry)
+      *carry |= ((bu16)~a < (bu16)b);
+
+  return v & 0xffff;
+}
+
+static bu32
+sub16 (SIM_CPU *cpu, bu16 a, bu16 b, bu32 *carry, bu32 *overfl,
+       bu32 *zero, bu32 *neg, int sat, int scale)
+{
+  int flgs = (a >> 15) & 1;
+  int flgo = (b >> 15) & 1;
+  bs64 v = (bs16)a - (bs16)b;
+  int flgn = (v >> 15) & 1;
+  int overflow = (flgs ^ flgo) & (flgn ^ flgs);
+
+  switch (scale)
+    {
+    case 0:
+      break;
+    case 2:
+      /* (ASR)  */
+      if (sat)
+       v = ((a >> 1) + (a & 0x8000)) - ( (b >> 1) + (b & 0x8000))
+           + (((a & 1)-(b & 1)));
+      else
+       {
+         v = ((v & 0xFFFF) >> 1);
+         if ((!flgs & !flgo & flgn)
+             || (flgs & !flgo & !flgn)
+             || (flgs & flgo & flgn)
+             || (flgs & !flgo & flgn))
+           v |= 0x8000;
+       }
+      v |= -(v & 0x8000);
+      flgn = (v >> 15) & 1;
+      overflow = (flgs ^ flgo) & (flgn ^ flgs);
+      break;
+    case 3:
+      /* (ASL)  */
+      v <<= 1;
+      if (v > (bs64)0x7fff || v < (bs64)-0xffff)
+       overflow = 1;
+      break;
+    default:
+      illegal_instruction (cpu);
+    }
+
+  if (sat)
+    {
+      v = saturate_s16 (v, 0);
+    }
+  if (neg)
+    *neg |= (v >> 15) & 1;
+  if (zero)
+    *zero |= (v & 0xFFFF) == 0;
+  if (overfl)
+    *overfl |= overflow;
+  if (carry)
+    *carry |= (bu16)b <= (bu16)a;
+  return v;
+}
+
+static bu32
+min32 (SIM_CPU *cpu, bu32 a, bu32 b)
+{
+  int val = a;
+  if ((bs32)a > (bs32)b)
+    val = b;
+  setflags_nz (cpu, val);
+  SET_ASTATREG (v, 0);
+  return val;
+}
+
+static bu32
+max32 (SIM_CPU *cpu, bu32 a, bu32 b)
+{
+  int val = a;
+  if ((bs32)a < (bs32)b)
+    val = b;
+  setflags_nz (cpu, val);
+  SET_ASTATREG (v, 0);
+  return val;
+}
+
+static bu32
+min2x16 (SIM_CPU *cpu, bu32 a, bu32 b)
+{
+  int val = a;
+  if ((bs16)a > (bs16)b)
+    val = (val & 0xFFFF0000) | (b & 0xFFFF);
+  if ((bs16)(a >> 16) > (bs16)(b >> 16))
+    val = (val & 0xFFFF) | (b & 0xFFFF0000);
+  setflags_nz_2x16 (cpu, val);
+  SET_ASTATREG (v, 0);
+  return val;
+}
+
+static bu32
+max2x16 (SIM_CPU *cpu, bu32 a, bu32 b)
+{
+  int val = a;
+  if ((bs16)a < (bs16)b)
+    val = (val & 0xFFFF0000) | (b & 0xFFFF);
+  if ((bs16)(a >> 16) < (bs16)(b >> 16))
+    val = (val & 0xFFFF) | (b & 0xFFFF0000);
+  setflags_nz_2x16 (cpu, val);
+  SET_ASTATREG (v, 0);
+  return val;
+}
+
+static bu32
+add_and_shift (SIM_CPU *cpu, bu32 a, bu32 b, int shift)
+{
+  int v;
+  ASTATREG (v_internal) = 0;
+  v = add32 (cpu, a, b, 0, 0);
+  while (shift-- > 0)
+    {
+      int x = (v >> 30) & 0x3;
+      if (x == 1 || x == 2)
+       ASTATREG (v_internal) = 1;
+      v <<= 1;
+    }
+  SET_ASTATREG (az, v == 0);
+  SET_ASTATREG (an, v & 0x80000000);
+  SET_ASTATREG (v, ASTATREG (v_internal));
+  if (ASTATREG (v))
+    SET_ASTATREG (vs, 1);
+  return v;
+}
+
+static bu32
+xor_reduce (bu64 acc0, bu64 acc1)
+{
+  int i;
+  bu32 v = 0;
+  for (i = 0; i < 40; ++i)
+    {
+      v ^= (acc0 & acc1 & 1);
+      acc0 >>= 1;
+      acc1 >>= 1;
+    }
+  return v;
+}
+
+/* DIVS ( Dreg, Dreg ) ;
+   Initialize for DIVQ.  Set the AQ status bit based on the signs of
+   the 32-bit dividend and the 16-bit divisor.  Left shift the dividend
+   one bit.  Copy AQ into the dividend LSB.  */
+static bu32
+divs (SIM_CPU *cpu, bu32 pquo, bu16 divisor)
+{
+  bu16 r = pquo >> 16;
+  int aq;
+
+  aq = (r ^ divisor) >> 15;  /* Extract msb's and compute quotient bit.  */
+  SET_ASTATREG (aq, aq);     /* Update global quotient state.  */
+
+  pquo <<= 1;
+  pquo |= aq;
+  pquo = (pquo & 0x1FFFF) | (r << 17);
+  return pquo;
+}
+
+/* DIVQ ( Dreg, Dreg ) ;
+   Based on AQ status bit, either add or subtract the divisor from
+   the dividend.  Then set the AQ status bit based on the MSBs of the
+   32-bit dividend and the 16-bit divisor.  Left shift the dividend one
+   bit.  Copy the logical inverse of AQ into the dividend LSB.  */
+static bu32
+divq (SIM_CPU *cpu, bu32 pquo, bu16 divisor)
+{
+  unsigned short af = pquo >> 16;
+  unsigned short r;
+  int aq;
+
+  if (ASTATREG (aq))
+    r = divisor + af;
+  else
+    r = af - divisor;
+
+  aq = (r ^ divisor) >> 15;  /* Extract msb's and compute quotient bit.  */
+  SET_ASTATREG (aq, aq);     /* Update global quotient state.  */
+
+  pquo <<= 1;
+  pquo |= !aq;
+  pquo = (pquo & 0x1FFFF) | (r << 17);
+  return pquo;
+}
+
+/* ONES ( Dreg ) ;
+   Count the number of bits set to 1 in the 32bit value.  */
+static bu32
+ones (bu32 val)
+{
+  bu32 i;
+  bu32 ret;
+
+  ret = 0;
+  for (i = 0; i < 32; ++i)
+    ret += !!(val & (1 << i));
+
+  return ret;
+}
+
+static void
+reg_check_sup (SIM_CPU *cpu, int grp, int reg)
+{
+  if (grp == 7)
+    cec_require_supervisor (cpu);
+}
+
+static void
+reg_write (SIM_CPU *cpu, int grp, int reg, bu32 value)
+{
+  bu32 *whichreg;
+
+  /* ASTAT is special!  */
+  if (grp == 4 && reg == 6)
+    {
+      SET_ASTAT (value);
+      return;
+    }
+
+  /* Check supervisor after get_allreg() so exception order is correct.  */
+  whichreg = get_allreg (cpu, grp, reg);
+  reg_check_sup (cpu, grp, reg);
+
+  if (whichreg == &CYCLES2REG)
+    /* Writes to CYCLES2 goes to the shadow.  */
+    whichreg = &CYCLES2SHDREG;
+  else if (whichreg == &SEQSTATREG)
+    /* Register is read only -- discard writes.  */
+    return;
+  else if (whichreg == &EMUDAT_INREG)
+    /* Writes to EMUDAT goes to the output.  */
+    whichreg = &EMUDAT_OUTREG;
+  else if (whichreg == &LTREG (0) || whichreg == &LTREG (1))
+    /* Writes to LT clears LSB automatically.  */
+    value &= ~0x1;
+  else if (whichreg == &AXREG (0) || whichreg == &AXREG (1))
+    value &= 0xFF;
+
+  TRACE_REGISTER (cpu, "wrote %s = %#x", get_allreg_name (grp, reg), value);
+
+  *whichreg = value;
+}
+
+static bu32
+reg_read (SIM_CPU *cpu, int grp, int reg)
+{
+  bu32 *whichreg;
+  bu32 value;
+
+  /* ASTAT is special!  */
+  if (grp == 4 && reg == 6)
+    return ASTAT;
+
+  /* Check supervisor after get_allreg() so exception order is correct.  */
+  whichreg = get_allreg (cpu, grp, reg);
+  reg_check_sup (cpu, grp, reg);
+
+  value = *whichreg;
+
+  if (whichreg == &CYCLESREG)
+    /* Reads of CYCLES reloads CYCLES2 from the shadow.  */
+    SET_CYCLES2REG (CYCLES2SHDREG);
+  else if ((whichreg == &AXREG (1) || whichreg == &AXREG (0)) && (value & 0x80))
+    /* Sign extend if necessary.  */
+    value |= 0xFFFFFF00;
+
+  return value;
+}
+
+static bu64
+get_extended_cycles (SIM_CPU *cpu)
+{
+  return ((bu64)CYCLES2SHDREG << 32) | CYCLESREG;
+}
+
+/* We can't re-use sim_events_time() because the CYCLES registers may be
+   written/cleared/reset/stopped/started at any time by software.  */
+static void
+cycles_inc (SIM_CPU *cpu, bu32 inc)
+{
+  bu64 cycles;
+  bu32 cycles2;
+
+  if (!(SYSCFGREG & SYSCFG_CCEN))
+    return;
+
+  cycles = get_extended_cycles (cpu) + inc;
+  SET_CYCLESREG (cycles);
+  cycles2 = cycles >> 32;
+  if (CYCLES2SHDREG != cycles2)
+    SET_CYCLES2SHDREG (cycles2);
+}
+
+static bu64
+get_unextended_acc (SIM_CPU *cpu, int which)
+{
+  return ((bu64)(AXREG (which) & 0xff) << 32) | AWREG (which);
+}
+
+static bu64
+get_extended_acc (SIM_CPU *cpu, int which)
+{
+  bu64 acc = AXREG (which);
+  /* Sign extend accumulator values before adding.  */
+  if (acc & 0x80)
+    acc |= -0x80;
+  else
+    acc &= 0xFF;
+  acc <<= 32;
+  acc |= AWREG (which);
+  return acc;
+}
+
+/* Perform a multiplication of D registers SRC0 and SRC1, sign- or
+   zero-extending the result to 64 bit.  H0 and H1 determine whether the
+   high part or the low part of the source registers is used.  Store 1 in
+   *PSAT if saturation occurs, 0 otherwise.  */
+static bu64
+decode_multfunc (SIM_CPU *cpu, int h0, int h1, int src0, int src1, int mmod,
+                int MM, bu32 *psat)
+{
+  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:
+      case M_W32:
+       s0 |= sgn0;
+       s1 |= sgn1;
+       break;
+      case M_FU:
+      case M_IU:
+      case M_TFU:
+       break;
+      default:
+       illegal_instruction (cpu);
+      }
+
+  val = s0 * s1;
+  /* Perform shift correction if appropriate for the mode.  */
+  *psat = 0;
+  if (!MM && (mmod == 0 || mmod == M_T || mmod == M_S2RND || mmod == M_W32))
+    {
+      if (val == 0x40000000)
+       {
+         if (mmod == M_W32)
+           val = 0x7fffffff;
+         else
+           val = 0x80000000;
+         *psat = 1;
+       }
+      else
+       val <<= 1;
+    }
+  val1 = val;
+
+  if (mmod == 0 || mmod == M_IS || mmod == M_T || mmod == M_S2RND
+      || mmod == M_ISS2 || mmod == M_IH || (MM && mmod == M_FU))
+    val1 |= -(val1 & 0x80000000);
+
+  if (*psat)
+    val1 &= 0xFFFFFFFFull;
+
+  return val1;
+}
+
+static bu40
+saturate_s40_astat (bu64 val, bu32 *v)
+{
+  if ((bs64)val < -((bs64)1 << 39))
+    {
+      *v = 1;
+      return -((bs64)1 << 39);
+    }
+  else if ((bs64)val >= ((bs64)1 << 39) - 1)
+    {
+      *v = 1;
+      return ((bu64)1 << 39) - 1;
+    }
+  *v = 0; /* No overflow.  */
+  return val;
+}
+
+static bu40
+saturate_s40 (bu64 val)
+{
+  bu32 v;
+  return saturate_s40_astat (val, &v);
+}
+
+static bu32
+saturate_s32 (bu64 val, bu32 *overflow)
+{
+  if ((bs64)val < -0x80000000ll)
+    {
+      if (overflow)
+       *overflow = 1;
+      return 0x80000000;
+    }
+  if ((bs64)val > 0x7fffffff)
+    {
+      if (overflow)
+       *overflow = 1;
+      return 0x7fffffff;
+    }
+  return val;
+}
+
+static bu32
+saturate_u32 (bu64 val, bu32 *overflow)
+{
+  if (val > 0xffffffff)
+    {
+      if (overflow)
+       *overflow = 1;
+      return 0xffffffff;
+    }
+  return val;
+}
+
+static bu32
+saturate_u16 (bu64 val, bu32 *overflow)
+{
+  if (val > 0xffff)
+    {
+      if (overflow)
+       *overflow = 1;
+      return 0xffff;
+    }
+  return val;
+}
+
+static bu64
+rnd16 (bu64 val)
+{
+  bu64 sgnbits;
+
+  /* FIXME: Should honour rounding mode.  */
+  if ((val & 0xffff) > 0x8000
+      || ((val & 0xffff) == 0x8000 && (val & 0x10000)))
+    val += 0x8000;
+
+  sgnbits = val & 0xffff000000000000ull;
+  val >>= 16;
+  return val | sgnbits;
+}
+
+static bu64
+trunc16 (bu64 val)
+{
+  bu64 sgnbits = val & 0xffff000000000000ull;
+  val >>= 16;
+  return val | sgnbits;
+}
+
+static int
+signbits (bu64 val, int size)
+{
+  bu64 mask = (bu64)1 << (size - 1);
+  bu64 bit = val & mask;
+  int count = 0;
+  for (;;)
+    {
+      mask >>= 1;
+      bit >>= 1;
+      if (mask == 0)
+       break;
+      if ((val & mask) != bit)
+       break;
+      count++;
+    }
+  if (size == 40)
+    count -= 8;
+
+  return count;
+}
+
+/* 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 (SIM_CPU *cpu, bu64 res, int mmod, int MM,
+             int fullword, bu32 *overflow)
+{
+  if (fullword)
+    switch (mmod)
+      {
+      case 0:
+      case M_IS:
+       return saturate_s32 (res, overflow);
+      case M_FU:
+       if (MM)
+         return saturate_s32 (res, overflow);
+       return saturate_u32 (res, overflow);
+      case M_S2RND:
+      case M_ISS2:
+       return saturate_s32 (res << 1, overflow);
+      default:
+       illegal_instruction (cpu);
+      }
+  else
+    switch (mmod)
+      {
+      case 0:
+      case M_W32:
+       return saturate_s16 (rnd16 (res), overflow);
+      case M_IH:
+       return saturate_s32 (rnd16 (res), overflow) & 0xFFFF;
+      case M_IS:
+       return saturate_s16 (res, overflow);
+      case M_FU:
+       if (MM)
+         return saturate_s16 (rnd16 (res), overflow);
+       return saturate_u16 (rnd16 (res), overflow);
+      case M_IU:
+       if (MM)
+         return saturate_s16 (res, overflow);
+       return saturate_u16 (res, overflow);
+
+      case M_T:
+       return saturate_s16 (trunc16 (res), overflow);
+      case M_TFU:
+       return saturate_u16 (trunc16 (res), overflow);
+
+      case M_S2RND:
+       return saturate_s16 (rnd16 (res << 1), overflow);
+      case M_ISS2:
+       return saturate_s16 (res << 1, overflow);
+      default:
+       illegal_instruction (cpu);
+      }
+}
+
+static bu32
+decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
+               int src1, int mmod, int MM, int fullword, bu32 *overflow)
+{
+  bu64 acc;
+  bu32 sat = 0, tsat;
+
+  /* Sign extend accumulator if necessary, otherwise unsigned.  */
+  if (mmod == 0 || mmod == M_T || mmod == M_IS || mmod == M_ISS2
+      || mmod == M_S2RND || mmod == M_IH || mmod == M_W32)
+    acc = get_extended_acc (cpu, which);
+  else
+    acc = get_unextended_acc (cpu, which);
+
+  if (MM && (mmod == M_T || mmod == M_IS || mmod == M_ISS2
+      || mmod == M_S2RND || mmod == M_IH || mmod == M_W32))
+    acc |= -(acc & 0x80000000);
+
+  if (op != 3)
+    {
+      bu8 sgn0 = (acc >> 31) & 1;
+      /* This can't saturate, so we don't keep track of the sat flag.  */
+      bu64 res = decode_multfunc (cpu, h0, h1, src0, src1, mmod,
+                                 MM, &tsat);
+
+      /* Perform accumulation.  */
+      switch (op)
+       {
+       case 0:
+         acc = res;
+         sgn0 = (acc >> 31) & 1;
+         break;
+       case 1:
+         acc = acc + res;
+         break;
+       case 2:
+         acc = acc - res;
+         break;
+       }
+
+      /* Saturate.  */
+      switch (mmod)
+       {
+       case 0:
+       case M_T:
+       case M_IS:
+       case M_ISS2:
+       case M_S2RND:
+         if ((bs64)acc < -((bs64)1 << 39))
+           acc = -((bu64)1 << 39), sat = 1;
+         else if ((bs64)acc > 0x7fffffffffll)
+           acc = 0x7fffffffffull, sat = 1;
+         break;
+       case M_TFU:
+         if (!MM && acc > 0xFFFFFFFFFFull)
+           acc = 0x0, sat = 1;
+         if (MM && acc > 0xFFFFFFFF)
+           acc &= 0xFFFFFFFF;
+         break;
+       case M_IU:
+         if (acc & 0x8000000000000000ull)
+           acc = 0x0, sat = 1;
+         if (acc > 0xFFFFFFFFFFull)
+           acc &= 0xFFFFFFFFFFull, sat = 1;
+         if (MM && acc > 0xFFFFFFFF)
+           acc &= 0xFFFFFFFF;
+         if (acc & 0x80000000)
+           acc |= 0xffffffff00000000ull;
+         break;
+       case M_FU:
+         if (!MM && (bs64)acc < 0)
+           acc = 0x0, sat = 1;
+         if (MM && (bs64)acc < -((bs64)1 << 39))
+           acc = -((bu64)1 << 39), sat = 1;
+         if (!MM && (bs64)acc > (bs64)0xFFFFFFFFFFll)
+           acc = 0xFFFFFFFFFFull, sat = 1;
+         if (MM && acc > 0xFFFFFFFFFFull)
+           acc &= 0xFFFFFFFFFFull;
+         if (MM && acc & 0x80000000)
+           acc |= 0xffffffff00000000ull;
+         break;
+       case M_IH:
+         if ((bs64)acc < -0x80000000ll)
+           acc = -0x80000000ull, sat = 1;
+         else if ((bs64)acc >= 0x7fffffffll)
+           acc = 0x7fffffffull, sat = 1;
+         break;
+       case M_W32:
+         if (sgn0 && (sgn0 != ((acc >> 31) & 1))
+             && (((acc >> 32) & 0xFF) == 0xff))
+           acc = 0x80000000;
+         acc &= 0xffffffff;
+         if (acc & 0x80000000)
+           acc |= 0xffffffff00000000ull;
+         break;
+       default:
+         illegal_instruction (cpu);
+       }
+    }
+
+  STORE (AXREG (which), (acc >> 32) & 0xff);
+  STORE (AWREG (which), acc & 0xffffffff);
+  STORE (ASTATREG (av[which]), sat);
+  if (sat)
+    STORE (ASTATREG (avs[which]), sat);
+
+  return extract_mult (cpu, acc, mmod, MM, fullword, overflow);
+}
+
+bu32
+hwloop_get_next_pc (SIM_CPU *cpu, bu32 pc, bu32 insn_len)
+{
+  int i;
+
+  if (insn_len == 0)
+    return pc;
+
+  /* If our PC has reached the bottom of a hardware loop,
+     move back up to the top of the hardware loop.  */
+  for (i = 1; i >= 0; --i)
+    if (LCREG (i) > 1 && pc == LBREG (i))
+      {
+       TRACE_BRANCH (cpu, pc, LTREG (i), i, "Hardware loop %i", i);
+       return LTREG (i);
+      }
+
+  return pc + insn_len;
+}
+
+static void
+decode_ProgCtrl_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
+{
+  /* ProgCtrl
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int poprnd  = ((iw0 >> ProgCtrl_poprnd_bits) & ProgCtrl_poprnd_mask);
+  int prgfunc = ((iw0 >> ProgCtrl_prgfunc_bits) & ProgCtrl_prgfunc_mask);
+
+  TRACE_EXTRACT (cpu, "%s: poprnd:%i prgfunc:%i", __func__, poprnd, prgfunc);
+
+  if (prgfunc == 0 && poprnd == 0)
+    {
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_nop);
+      TRACE_INSN (cpu, "NOP;");
+    }
+  else if (prgfunc == 1 && poprnd == 0)
+    {
+      bu32 newpc = RETSREG;
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
+      TRACE_INSN (cpu, "RTS;");
+      IFETCH_CHECK (newpc);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      TRACE_BRANCH (cpu, pc, newpc, -1, "RTS");
+      SET_PCREG (newpc);
+      BFIN_CPU_STATE.did_jump = true;
+      CYCLE_DELAY = 5;
+    }
+  else if (prgfunc == 1 && poprnd == 1)
+    {
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
+      TRACE_INSN (cpu, "RTI;");
+      /* Do not do IFETCH_CHECK here -- LSB has special meaning.  */
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      cec_return (cpu, -1);
+      CYCLE_DELAY = 5;
+    }
+  else if (prgfunc == 1 && poprnd == 2)
+    {
+      bu32 newpc = RETXREG;
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
+      TRACE_INSN (cpu, "RTX;");
+      /* XXX: Not sure if this is what the hardware does.  */
+      IFETCH_CHECK (newpc);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      cec_return (cpu, IVG_EVX);
+      CYCLE_DELAY = 5;
+    }
+  else if (prgfunc == 1 && poprnd == 3)
+    {
+      bu32 newpc = RETNREG;
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
+      TRACE_INSN (cpu, "RTN;");
+      /* XXX: Not sure if this is what the hardware does.  */
+      IFETCH_CHECK (newpc);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      cec_return (cpu, IVG_NMI);
+      CYCLE_DELAY = 5;
+    }
+  else if (prgfunc == 1 && poprnd == 4)
+    {
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
+      TRACE_INSN (cpu, "RTE;");
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      cec_return (cpu, IVG_EMU);
+      CYCLE_DELAY = 5;
+    }
+  else if (prgfunc == 2 && poprnd == 0)
+    {
+      SIM_DESC sd = CPU_STATE (cpu);
+      sim_events *events = STATE_EVENTS (sd);
+
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
+      /* XXX: in supervisor mode, utilizes wake up sources
+         in user mode, it's a NOP ...  */
+      TRACE_INSN (cpu, "IDLE;");
+
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+
+      /* Timewarp !  */
+      if (events->queue)
+       CYCLE_DELAY = events->time_from_event;
+      else
+       abort (); /* XXX: Should this ever happen ?  */
+    }
+  else if (prgfunc == 2 && poprnd == 3)
+    {
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
+      /* Just NOP it.  */
+      TRACE_INSN (cpu, "CSYNC;");
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      CYCLE_DELAY = 10;
+    }
+  else if (prgfunc == 2 && poprnd == 4)
+    {
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
+      /* Just NOP it.  */
+      TRACE_INSN (cpu, "SSYNC;");
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+
+      /* Really 10+, but no model info for this.  */
+      CYCLE_DELAY = 10;
+    }
+  else if (prgfunc == 2 && poprnd == 5)
+    {
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
+      TRACE_INSN (cpu, "EMUEXCPT;");
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      cec_exception (cpu, VEC_SIM_TRAP);
+    }
+  else if (prgfunc == 3 && poprnd < 8)
+    {
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
+      TRACE_INSN (cpu, "CLI R%i;", poprnd);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      SET_DREG (poprnd, cec_cli (cpu));
+    }
+  else if (prgfunc == 4 && poprnd < 8)
+    {
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
+      TRACE_INSN (cpu, "STI R%i;", poprnd);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      cec_sti (cpu, DREG (poprnd));
+      CYCLE_DELAY = 3;
+    }
+  else if (prgfunc == 5 && poprnd < 8)
+    {
+      bu32 newpc = PREG (poprnd);
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
+      TRACE_INSN (cpu, "JUMP (%s);", get_preg_name (poprnd));
+      IFETCH_CHECK (newpc);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP (Preg)");
+      SET_PCREG (newpc);
+      BFIN_CPU_STATE.did_jump = true;
+      PROFILE_BRANCH_TAKEN (cpu);
+      CYCLE_DELAY = 5;
+    }
+  else if (prgfunc == 6 && poprnd < 8)
+    {
+      bu32 newpc = PREG (poprnd);
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
+      TRACE_INSN (cpu, "CALL (%s);", get_preg_name (poprnd));
+      IFETCH_CHECK (newpc);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      TRACE_BRANCH (cpu, pc, newpc, -1, "CALL (Preg)");
+      /* If we're at the end of a hardware loop, RETS is going to be
+         the top of the loop rather than the next instruction.  */
+      SET_RETSREG (hwloop_get_next_pc (cpu, pc, 2));
+      SET_PCREG (newpc);
+      BFIN_CPU_STATE.did_jump = true;
+      PROFILE_BRANCH_TAKEN (cpu);
+      CYCLE_DELAY = 5;
+    }
+  else if (prgfunc == 7 && poprnd < 8)
+    {
+      bu32 newpc = pc + PREG (poprnd);
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
+      TRACE_INSN (cpu, "CALL (PC + %s);", get_preg_name (poprnd));
+      IFETCH_CHECK (newpc);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      TRACE_BRANCH (cpu, pc, newpc, -1, "CALL (PC + Preg)");
+      SET_RETSREG (hwloop_get_next_pc (cpu, pc, 2));
+      SET_PCREG (newpc);
+      BFIN_CPU_STATE.did_jump = true;
+      PROFILE_BRANCH_TAKEN (cpu);
+      CYCLE_DELAY = 5;
+    }
+  else if (prgfunc == 8 && poprnd < 8)
+    {
+      bu32 newpc = pc + PREG (poprnd);
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
+      TRACE_INSN (cpu, "JUMP (PC + %s);", get_preg_name (poprnd));
+      IFETCH_CHECK (newpc);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP (PC + Preg)");
+      SET_PCREG (newpc);
+      BFIN_CPU_STATE.did_jump = true;
+      PROFILE_BRANCH_TAKEN (cpu);
+      CYCLE_DELAY = 5;
+    }
+  else if (prgfunc == 9)
+    {
+      int raise = uimm4 (poprnd);
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
+      TRACE_INSN (cpu, "RAISE %s;", uimm4_str (raise));
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      cec_require_supervisor (cpu);
+      if (raise == IVG_IVHW)
+       cec_hwerr (cpu, HWERR_RAISE_5);
+      else
+       cec_latch (cpu, raise);
+      CYCLE_DELAY = 3; /* XXX: Only if IVG is unmasked.  */
+    }
+  else if (prgfunc == 10)
+    {
+      int excpt = uimm4 (poprnd);
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
+      TRACE_INSN (cpu, "EXCPT %s;", uimm4_str (excpt));
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      cec_exception (cpu, excpt);
+      CYCLE_DELAY = 3;
+    }
+  else if (prgfunc == 11 && poprnd < 6)
+    {
+      bu32 addr = PREG (poprnd);
+      bu8 byte;
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_atomic);
+      TRACE_INSN (cpu, "TESTSET (%s);", get_preg_name (poprnd));
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      byte = GET_WORD (addr);
+      SET_CCREG (byte == 0);
+      PUT_BYTE (addr, byte | 0x80);
+      /* Also includes memory stalls, but we don't model that.  */
+      CYCLE_DELAY = 2;
+    }
+  else
+    illegal_instruction (cpu);
+}
+
+static void
+decode_CaCTRL_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* CaCTRL
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int a   = ((iw0 >> CaCTRL_a_bits) & CaCTRL_a_mask);
+  int op  = ((iw0 >> CaCTRL_op_bits) & CaCTRL_op_mask);
+  int reg = ((iw0 >> CaCTRL_reg_bits) & CaCTRL_reg_mask);
+  bu32 preg = PREG (reg);
+  const char * const sinsn[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CaCTRL);
+  TRACE_EXTRACT (cpu, "%s: a:%i op:%i reg:%i", __func__, a, op, reg);
+  TRACE_INSN (cpu, "%s [%s%s];", sinsn[op], get_preg_name (reg), a ? "++" : "");
+
+  if (INSN_LEN == 8)
+    /* None of these can be part of a parallel instruction.  */
+    illegal_instruction_combination (cpu);
+
+  /* No cache simulation, so these are (mostly) all NOPs.
+     XXX: The hardware takes care of masking to cache lines, but need
+     to check behavior of the post increment.  Should we be aligning
+     the value to the cache line before adding the cache line size, or
+     do we just add the cache line size ?  */
+  if (op == 0)
+    {  /* PREFETCH  */
+      mmu_check_cache_addr (cpu, preg, false, false);
+    }
+  else if (op == 1)
+    {  /* FLUSHINV  */
+      mmu_check_cache_addr (cpu, preg, true, false);
+    }
+  else if (op == 2)
+    {  /* FLUSH  */
+      mmu_check_cache_addr (cpu, preg, true, false);
+    }
+  else if (op == 3)
+    {  /* IFLUSH  */
+      mmu_check_cache_addr (cpu, preg, false, true);
+    }
+
+  if (a)
+    SET_PREG (reg, preg + BFIN_L1_CACHE_BYTES);
+}
+
+static void
+decode_PushPopReg_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* PushPopReg
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int W   = ((iw0 >> PushPopReg_W_bits) & PushPopReg_W_mask);
+  int grp = ((iw0 >> PushPopReg_grp_bits) & PushPopReg_grp_mask);
+  int reg = ((iw0 >> PushPopReg_reg_bits) & PushPopReg_reg_mask);
+  const char *reg_name = get_allreg_name (grp, reg);
+  bu32 value;
+  bu32 sp = SPREG;
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PushPopReg);
+  TRACE_EXTRACT (cpu, "%s: W:%i grp:%i reg:%i", __func__, W, grp, reg);
+  TRACE_DECODE (cpu, "%s: reg:%s", __func__, reg_name);
+
+  /* Can't push/pop reserved registers  */
+  if (reg_is_reserved (grp, reg))
+    illegal_instruction (cpu);
+
+  if (W == 0)
+    {
+      /* Dreg and Preg are not supported by this instruction.  */
+      if (grp == 0 || grp == 1)
+       illegal_instruction (cpu);
+      TRACE_INSN (cpu, "%s = [SP++];", reg_name);
+      /* Can't pop USP while in userspace.  */
+      if (INSN_LEN == 8 || (grp == 7 && reg == 0 && cec_is_user_mode(cpu)))
+       illegal_instruction_combination (cpu);
+      /* XXX: The valid register check is in reg_write(), so we might
+              incorrectly do a GET_LONG() here ...  */
+      value = GET_LONG (sp);
+      reg_write (cpu, grp, reg, value);
+      if (grp == 7 && reg == 3)
+       cec_pop_reti (cpu);
+
+      sp += 4;
+    }
+  else
+    {
+      TRACE_INSN (cpu, "[--SP] = %s;", reg_name);
+      /* Can't push SP.  */
+      if (INSN_LEN == 8 || (grp == 1 && reg == 6))
+       illegal_instruction_combination (cpu);
+
+      sp -= 4;
+      value = reg_read (cpu, grp, reg);
+      if (grp == 7 && reg == 3)
+       cec_push_reti (cpu);
+
+      PUT_LONG (sp, value);
+    }
+
+  /* Note: SP update must be delayed until after all reads/writes; see
+           comments in decode_PushPopMultiple_0() for more info.  */
+  SET_SPREG (sp);
+}
+
+static void
+decode_PushPopMultiple_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* PushPopMultiple
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int p  = ((iw0 >> PushPopMultiple_p_bits) & PushPopMultiple_p_mask);
+  int d  = ((iw0 >> PushPopMultiple_d_bits) & PushPopMultiple_d_mask);
+  int W  = ((iw0 >> PushPopMultiple_W_bits) & PushPopMultiple_W_mask);
+  int dr = ((iw0 >> PushPopMultiple_dr_bits) & PushPopMultiple_dr_mask);
+  int pr = ((iw0 >> PushPopMultiple_pr_bits) & PushPopMultiple_pr_mask);
+  int i;
+  bu32 sp = SPREG;
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PushPopMultiple);
+  TRACE_EXTRACT (cpu, "%s: d:%i p:%i W:%i dr:%i pr:%i",
+                __func__, d, p, W, dr, pr);
+
+  if ((d == 0 && p == 0) || (p && imm5 (pr) > 5)
+      || (d && !p && pr) || (p && !d && dr))
+    illegal_instruction (cpu);
+
+  if (W == 1)
+    {
+      if (d && p)
+       TRACE_INSN (cpu, "[--SP] = (R7:%i, P5:%i);", dr, pr);
+      else if (d)
+       TRACE_INSN (cpu, "[--SP] = (R7:%i);", dr);
+      else
+       TRACE_INSN (cpu, "[--SP] = (P5:%i);", pr);
+
+      if (d)
+       for (i = dr; i < 8; i++)
+         {
+           sp -= 4;
+           PUT_LONG (sp, DREG (i));
+         }
+      if (p)
+       for (i = pr; i < 6; i++)
+         {
+           sp -= 4;
+           PUT_LONG (sp, PREG (i));
+         }
+
+      CYCLE_DELAY = 14;
+    }
+  else
+    {
+      if (d && p)
+       TRACE_INSN (cpu, "(R7:%i, P5:%i) = [SP++];", dr, pr);
+      else if (d)
+       TRACE_INSN (cpu, "(R7:%i) = [SP++];", dr);
+      else
+       TRACE_INSN (cpu, "(P5:%i) = [SP++];", pr);
+
+      if (p)
+       for (i = 5; i >= pr; i--)
+         {
+           SET_PREG (i, GET_LONG (sp));
+           sp += 4;
+         }
+      if (d)
+       for (i = 7; i >= dr; i--)
+         {
+           SET_DREG (i, GET_LONG (sp));
+           sp += 4;
+         }
+
+      CYCLE_DELAY = 11;
+    }
+
+  /* Note: SP update must be delayed until after all reads/writes so that
+           if an exception does occur, the insn may be re-executed as the
+           SP has not yet changed.  */
+  SET_SPREG (sp);
+}
+
+static void
+decode_ccMV_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* ccMV
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int s  = ((iw0 >> CCmv_s_bits) & CCmv_s_mask);
+  int d  = ((iw0 >> CCmv_d_bits) & CCmv_d_mask);
+  int T  = ((iw0 >> CCmv_T_bits) & CCmv_T_mask);
+  int src = ((iw0 >> CCmv_src_bits) & CCmv_src_mask);
+  int dst = ((iw0 >> CCmv_dst_bits) & CCmv_dst_mask);
+  int cond = T ? CCREG : ! CCREG;
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ccMV);
+  TRACE_EXTRACT (cpu, "%s: T:%i d:%i s:%i dst:%i src:%i",
+                __func__, T, d, s, dst, src);
+
+  TRACE_INSN (cpu, "IF %sCC %s = %s;", T ? "" : "! ",
+             get_allreg_name (d, dst),
+             get_allreg_name (s, src));
+  if (INSN_LEN == 8)
+    illegal_instruction_combination (cpu);
+
+  if (cond)
+    reg_write (cpu, d, dst, reg_read (cpu, s, src));
+}
+
+static void
+decode_CCflag_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* CCflag
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int x = ((iw0 >> CCflag_x_bits) & CCflag_x_mask);
+  int y = ((iw0 >> CCflag_y_bits) & CCflag_y_mask);
+  int I = ((iw0 >> CCflag_I_bits) & CCflag_I_mask);
+  int G = ((iw0 >> CCflag_G_bits) & CCflag_G_mask);
+  int opc = ((iw0 >> CCflag_opc_bits) & CCflag_opc_mask);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CCflag);
+  TRACE_EXTRACT (cpu, "%s: I:%i opc:%i G:%i y:%i x:%i",
+                __func__, I, opc, G, y, x);
+
+  if (opc > 4)
+    {
+      bs64 acc0 = get_extended_acc (cpu, 0);
+      bs64 acc1 = get_extended_acc (cpu, 1);
+      bs64 diff = acc0 - acc1;
+
+      if (x != 0 || y != 0)
+       illegal_instruction (cpu);
+
+      if (opc == 5 && I == 0 && G == 0)
+       {
+         TRACE_INSN (cpu, "CC = A0 == A1;");
+         if (INSN_LEN == 8)
+           illegal_instruction_combination (cpu);
+         SET_CCREG (acc0 == acc1);
+       }
+      else if (opc == 6 && I == 0 && G == 0)
+       {
+         TRACE_INSN (cpu, "CC = A0 < A1");
+         if (INSN_LEN == 8)
+           illegal_instruction_combination (cpu);
+         SET_CCREG (acc0 < acc1);
+       }
+      else if (opc == 7 && I == 0 && G == 0)
+       {
+         TRACE_INSN (cpu, "CC = A0 <= A1");
+         if (INSN_LEN == 8)
+           illegal_instruction_combination (cpu);
+         SET_CCREG (acc0 <= acc1);
+       }
+      else
+       illegal_instruction (cpu);
+
+      SET_ASTATREG (az, diff == 0);
+      SET_ASTATREG (an, diff < 0);
+      SET_ASTATREG (ac0, (bu40)acc1 <= (bu40)acc0);
+    }
+  else
+    {
+      int issigned = opc < 3;
+      const char *sign = issigned ? "" : " (IU)";
+      bu32 srcop = G ? PREG (x) : DREG (x);
+      char s = G ? 'P' : 'R';
+      bu32 dstop = I ? (issigned ? imm3 (y) : uimm3 (y)) : G ? PREG (y) : DREG (y);
+      const char *op;
+      char d = G ? 'P' : 'R';
+      int flgs = srcop >> 31;
+      int flgo = dstop >> 31;
+
+      bu32 result = srcop - dstop;
+      int cc;
+      int flgn = result >> 31;
+      int overflow = (flgs ^ flgo) & (flgn ^ flgs);
+      int az = result == 0;
+      int ac0 = dstop <= srcop;
+      int an;
+      if (issigned)
+       an = (flgn && !overflow) || (!flgn && overflow);
+      else
+       an = dstop > srcop;
+
+      switch (opc)
+       {
+       default: /* Shutup useless gcc warnings.  */
+       case 0: /* signed  */
+         op = "==";
+         cc = az;
+         break;
+       case 1: /* signed  */
+         op = "<";
+         cc = an;
+         break;
+       case 2: /* signed  */
+         op = "<=";
+         cc = an || az;
+         break;
+       case 3: /* unsigned  */
+         op = "<";
+         cc = !ac0;
+         break;
+       case 4: /* unsigned  */
+         op = "<=";
+         cc = !ac0 || az;
+         break;
+       }
+
+      if (I)
+       TRACE_INSN (cpu, "CC = %c%i %s %s%s;", s, x, op,
+                   issigned ? imm3_str (y) : uimm3_str (y), sign);
+      else
+       {
+         TRACE_DECODE (cpu, "%s %c%i:%x %c%i:%x", __func__,
+                       s, x, srcop,  d, y, dstop);
+         TRACE_INSN (cpu, "CC = %c%i %s %c%i%s;", s, x, op, d, y, sign);
+       }
+
+      SET_CCREG (cc);
+      /* Pointer compares only touch CC.  */
+      if (!G)
+       {
+         SET_ASTATREG (az, az);
+         SET_ASTATREG (an, an);
+         SET_ASTATREG (ac0, ac0);
+       }
+    }
+}
+
+static void
+decode_CC2dreg_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* CC2dreg
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int op  = ((iw0 >> CC2dreg_op_bits) & CC2dreg_op_mask);
+  int reg = ((iw0 >> CC2dreg_reg_bits) & CC2dreg_reg_mask);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CC2dreg);
+  TRACE_EXTRACT (cpu, "%s: op:%i reg:%i", __func__, op, reg);
+
+  if (op == 0)
+    {
+      TRACE_INSN (cpu, "R%i = CC;", reg);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      SET_DREG (reg, CCREG);
+    }
+  else if (op == 1)
+    {
+      TRACE_INSN (cpu, "CC = R%i;", reg);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      SET_CCREG (DREG (reg) != 0);
+    }
+  else if (op == 3 && reg == 0)
+    {
+      TRACE_INSN (cpu, "CC = !CC;");
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      SET_CCREG (!CCREG);
+    }
+  else
+    illegal_instruction (cpu);
+}
+
+static void
+decode_CC2stat_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* CC2stat
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int D    = ((iw0 >> CC2stat_D_bits) & CC2stat_D_mask);
+  int op   = ((iw0 >> CC2stat_op_bits) & CC2stat_op_mask);
+  int cbit = ((iw0 >> CC2stat_cbit_bits) & CC2stat_cbit_mask);
+  bu32 pval;
+
+  const char * const op_names[] = { "", "|", "&", "^" } ;
+  const char *astat_name;
+  const char * const astat_names[32] = {
+    [ 0] = "AZ",
+    [ 1] = "AN",
+    [ 2] = "AC0_COPY",
+    [ 3] = "V_COPY",
+    [ 5] = "CC",
+    [ 6] = "AQ",
+    [ 8] = "RND_MOD",
+    [12] = "AC0",
+    [13] = "AC1",
+    [16] = "AV0",
+    [17] = "AV0S",
+    [18] = "AV1",
+    [19] = "AV1S",
+    [24] = "V",
+    [25] = "VS",
+  };
+  astat_name = astat_names[cbit];
+  if (!astat_name)
+    {
+      static char astat_bit[12];
+      sprintf (astat_bit, "ASTAT[%i]", cbit);
+      astat_name = astat_bit;
+    }
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CC2stat);
+  TRACE_EXTRACT (cpu, "%s: D:%i op:%i cbit:%i", __func__, D, op, cbit);
+
+  TRACE_INSN (cpu, "%s %s= %s;", D ? astat_name : "CC",
+             op_names[op], D ? "CC" : astat_name);
+
+  /* CC = CC; is invalid.  */
+  if (cbit == 5)
+    illegal_instruction (cpu);
+
+  if (INSN_LEN == 8)
+    illegal_instruction_combination (cpu);
+
+  pval = !!(ASTAT & (1 << cbit));
+  if (D == 0)
+    switch (op)
+      {
+      case 0: SET_CCREG (pval); break;
+      case 1: SET_CCREG (CCREG | pval); break;
+      case 2: SET_CCREG (CCREG & pval); break;
+      case 3: SET_CCREG (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;
+       }
+      if (astat_names[cbit])
+       TRACE_REGISTER (cpu, "wrote ASTAT[%s] = %i", astat_name, pval);
+      else
+       TRACE_REGISTER (cpu, "wrote %s = %i", astat_name, pval);
+      SET_ASTAT ((ASTAT & ~(1 << cbit)) | (pval << cbit));
+    }
+}
+
+static void
+decode_BRCC_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
+{
+  /* BRCC
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int B = ((iw0 >> BRCC_B_bits) & BRCC_B_mask);
+  int T = ((iw0 >> BRCC_T_bits) & BRCC_T_mask);
+  int offset = ((iw0 >> BRCC_offset_bits) & BRCC_offset_mask);
+  int cond = T ? CCREG : ! CCREG;
+  int pcrel = pcrel10 (offset);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_BRCC);
+  TRACE_EXTRACT (cpu, "%s: T:%i B:%i offset:%#x", __func__, T, B, offset);
+  TRACE_DECODE (cpu, "%s: pcrel10:%#x", __func__, pcrel);
+
+  TRACE_INSN (cpu, "IF %sCC JUMP %#x%s;", T ? "" : "! ",
+             pcrel, B ? " (bp)" : "");
+
+  if (INSN_LEN == 8)
+    illegal_instruction_combination (cpu);
+
+  if (cond)
+    {
+      bu32 newpc = pc + pcrel;
+      TRACE_BRANCH (cpu, pc, newpc, -1, "Conditional JUMP");
+      SET_PCREG (newpc);
+      BFIN_CPU_STATE.did_jump = true;
+      PROFILE_BRANCH_TAKEN (cpu);
+      CYCLE_DELAY = B ? 5 : 9;
+    }
+  else
+    {
+      PROFILE_BRANCH_UNTAKEN (cpu);
+      CYCLE_DELAY = B ? 9 : 1;
+    }
+}
+
+static void
+decode_UJUMP_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
+{
+  /* UJUMP
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 1 | 0 |.offset........................................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int offset = ((iw0 >> UJump_offset_bits) & UJump_offset_mask);
+  int pcrel = pcrel12 (offset);
+  bu32 newpc = pc + pcrel;
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_UJUMP);
+  TRACE_EXTRACT (cpu, "%s: offset:%#x", __func__, offset);
+  TRACE_DECODE (cpu, "%s: pcrel12:%#x", __func__, pcrel);
+
+  TRACE_INSN (cpu, "JUMP.S %#x;", pcrel);
+
+  if (INSN_LEN == 8)
+    illegal_instruction_combination (cpu);
+
+  TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP.S");
+
+  SET_PCREG (newpc);
+  BFIN_CPU_STATE.did_jump = true;
+  PROFILE_BRANCH_TAKEN (cpu);
+  CYCLE_DELAY = 5;
+}
+
+static void
+decode_REGMV_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* REGMV
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int gs  = ((iw0 >> RegMv_gs_bits) & RegMv_gs_mask);
+  int gd  = ((iw0 >> RegMv_gd_bits) & RegMv_gd_mask);
+  int src = ((iw0 >> RegMv_src_bits) & RegMv_src_mask);
+  int dst = ((iw0 >> RegMv_dst_bits) & RegMv_dst_mask);
+  const char *srcreg_name = get_allreg_name (gs, src);
+  const char *dstreg_name = get_allreg_name (gd, dst);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_REGMV);
+  TRACE_EXTRACT (cpu, "%s: gd:%i gs:%i dst:%i src:%i",
+                __func__, gd, gs, dst, src);
+  TRACE_DECODE (cpu, "%s: dst:%s src:%s", __func__, dstreg_name, srcreg_name);
+
+  TRACE_INSN (cpu, "%s = %s;", dstreg_name, srcreg_name);
+
+  /* Reserved slots cannot be a src/dst.  */
+  if (reg_is_reserved (gs, src) || reg_is_reserved (gd, dst))
+    goto invalid_move;
+
+  /* Standard register moves.  */
+  if ((gs < 2)                                         /* Dregs/Pregs src  */
+      || (gd < 2)                                      /* Dregs/Pregs dst  */
+      || (gs == 4 && src < 4)                          /* Accumulators src  */
+      || (gd == 4 && dst < 4 && (gs < 4))              /* Accumulators dst  */
+      || (gs == 7 && src == 7 && !(gd == 4 && dst < 4))        /* EMUDAT src  */
+      || (gd == 7 && dst == 7))                        /* EMUDAT dst  */
+    goto valid_move;
+
+  /* dareg = dareg (IMBL)  */
+  if (gs < 4 && gd < 4)
+    goto valid_move;
+
+  /* USP can be src to sysregs, but not dagregs.  */
+  if ((gs == 7 && src == 0) && (gd >= 4))
+    goto valid_move;
+
+  /* USP can move between genregs (only check Accumulators).  */
+  if (((gs == 7 && src == 0) && (gd == 4 && dst < 4))
+      || ((gd == 7 && dst == 0) && (gs == 4 && src < 4)))
+    goto valid_move;
+
+  /* Still here ?  Invalid reg pair.  */
+ invalid_move:
+  illegal_instruction (cpu);
+
+ valid_move:
+  reg_write (cpu, gd, dst, reg_read (cpu, gs, src));
+}
+
+static void
+decode_ALU2op_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* ALU2op
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int src = ((iw0 >> ALU2op_src_bits) & ALU2op_src_mask);
+  int opc = ((iw0 >> ALU2op_opc_bits) & ALU2op_opc_mask);
+  int dst = ((iw0 >> ALU2op_dst_bits) & ALU2op_dst_mask);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ALU2op);
+  TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
+
+  if (opc == 0)
+    {
+      TRACE_INSN (cpu, "R%i >>>= R%i;", dst, src);
+      SET_DREG (dst, ashiftrt (cpu, DREG (dst), DREG (src), 32));
+    }
+  else if (opc == 1)
+    {
+      bu32 val;
+      TRACE_INSN (cpu, "R%i >>= R%i;", dst, src);
+      if (DREG (src) <= 0x1F)
+       val = lshiftrt (cpu, DREG (dst), DREG (src), 32);
+      else
+       val = 0;
+      SET_DREG (dst, val);
+    }
+  else if (opc == 2)
+    {
+      TRACE_INSN (cpu, "R%i <<= R%i;", dst, src);
+      SET_DREG (dst, lshift (cpu, DREG (dst), DREG (src), 32, 0));
+    }
+  else if (opc == 3)
+    {
+      TRACE_INSN (cpu, "R%i *= R%i;", dst, src);
+      SET_DREG (dst, DREG (dst) * DREG (src));
+      CYCLE_DELAY = 3;
+    }
+  else if (opc == 4)
+    {
+      TRACE_INSN (cpu, "R%i = (R%i + R%i) << 1;", dst, dst, src);
+      SET_DREG (dst, add_and_shift (cpu, DREG (dst), DREG (src), 1));
+    }
+  else if (opc == 5)
+    {
+      TRACE_INSN (cpu, "R%i = (R%i + R%i) << 2;", dst, dst, src);
+      SET_DREG (dst, add_and_shift (cpu, DREG (dst), DREG (src), 2));
+    }
+  else if (opc == 8)
+    {
+      TRACE_INSN (cpu, "DIVQ ( R%i, R%i );", dst, src);
+      SET_DREG (dst, divq (cpu, DREG (dst), (bu16)DREG (src)));
+    }
+  else if (opc == 9)
+    {
+      TRACE_INSN (cpu, "DIVS ( R%i, R%i );", dst, src);
+      SET_DREG (dst, divs (cpu, DREG (dst), (bu16)DREG (src)));
+    }
+  else if (opc == 10)
+    {
+      TRACE_INSN (cpu, "R%i = R%i.L (X);", dst, src);
+      SET_DREG (dst, (bs32) (bs16) DREG (src));
+      setflags_logical (cpu, DREG (dst));
+    }
+  else if (opc == 11)
+    {
+      TRACE_INSN (cpu, "R%i = R%i.L (Z);", dst, src);
+      SET_DREG (dst, (bu32) (bu16) DREG (src));
+      setflags_logical (cpu, DREG (dst));
+    }
+  else if (opc == 12)
+    {
+      TRACE_INSN (cpu, "R%i = R%i.B (X);", dst, src);
+      SET_DREG (dst, (bs32) (bs8) DREG (src));
+      setflags_logical (cpu, DREG (dst));
+    }
+  else if (opc == 13)
+    {
+      TRACE_INSN (cpu, "R%i = R%i.B (Z);", dst, src);
+      SET_DREG (dst, (bu32) (bu8) DREG (src));
+      setflags_logical (cpu, DREG (dst));
+    }
+  else if (opc == 14)
+    {
+      bu32 val = DREG (src);
+      TRACE_INSN (cpu, "R%i = - R%i;", dst, src);
+      SET_DREG (dst, -val);
+      setflags_nz (cpu, DREG (dst));
+      SET_ASTATREG (v, val == 0x80000000);
+      if (ASTATREG (v))
+       SET_ASTATREG (vs, 1);
+      SET_ASTATREG (ac0, val == 0x0);
+      /* XXX: Documentation isn't entirely clear about av0 and av1.  */
+    }
+  else if (opc == 15)
+    {
+      TRACE_INSN (cpu, "R%i = ~ R%i;", dst, src);
+      SET_DREG (dst, ~DREG (src));
+      setflags_logical (cpu, DREG (dst));
+    }
+  else
+    illegal_instruction (cpu);
+}
+
+static void
+decode_PTR2op_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* PTR2op
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int src = ((iw0 >> PTR2op_src_bits) & PTR2op_dst_mask);
+  int opc = ((iw0 >> PTR2op_opc_bits) & PTR2op_opc_mask);
+  int dst = ((iw0 >> PTR2op_dst_bits) & PTR2op_dst_mask);
+  const char *src_name = get_preg_name (src);
+  const char *dst_name = get_preg_name (dst);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PTR2op);
+  TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
+
+  if (opc == 0)
+    {
+      TRACE_INSN (cpu, "%s -= %s", dst_name, src_name);
+      SET_PREG (dst, PREG (dst) - PREG (src));
+    }
+  else if (opc == 1)
+    {
+      TRACE_INSN (cpu, "%s = %s << 2", dst_name, src_name);
+      SET_PREG (dst, PREG (src) << 2);
+    }
+  else if (opc == 3)
+    {
+      TRACE_INSN (cpu, "%s = %s >> 2", dst_name, src_name);
+      SET_PREG (dst, PREG (src) >> 2);
+    }
+  else if (opc == 4)
+    {
+      TRACE_INSN (cpu, "%s = %s >> 1", dst_name, src_name);
+      SET_PREG (dst, PREG (src) >> 1);
+    }
+  else if (opc == 5)
+    {
+      TRACE_INSN (cpu, "%s += %s (BREV)", dst_name, src_name);
+      SET_PREG (dst, add_brev (PREG (dst), PREG (src)));
+    }
+  else if (opc == 6)
+    {
+      TRACE_INSN (cpu, "%s = (%s + %s) << 1", dst_name, dst_name, src_name);
+      SET_PREG (dst, (PREG (dst) + PREG (src)) << 1);
+    }
+  else if (opc == 7)
+    {
+      TRACE_INSN (cpu, "%s = (%s + %s) << 2", dst_name, dst_name, src_name);
+      SET_PREG (dst, (PREG (dst) + PREG (src)) << 2);
+    }
+  else
+    illegal_instruction (cpu);
+}
+
+static void
+decode_LOGI2op_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* LOGI2op
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int src = ((iw0 >> LOGI2op_src_bits) & LOGI2op_src_mask);
+  int opc = ((iw0 >> LOGI2op_opc_bits) & LOGI2op_opc_mask);
+  int dst = ((iw0 >> LOGI2op_dst_bits) & LOGI2op_dst_mask);
+  int uimm = uimm5 (src);
+  const char *uimm_str = uimm5_str (uimm);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LOGI2op);
+  TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
+  TRACE_DECODE (cpu, "%s: uimm5:%#x", __func__, uimm);
+
+  if (opc == 0)
+    {
+      TRACE_INSN (cpu, "CC = ! BITTST (R%i, %s);", dst, uimm_str);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      SET_CCREG ((~DREG (dst) >> uimm) & 1);
+    }
+  else if (opc == 1)
+    {
+      TRACE_INSN (cpu, "CC = BITTST (R%i, %s);", dst, uimm_str);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      SET_CCREG ((DREG (dst) >> uimm) & 1);
+    }
+  else if (opc == 2)
+    {
+      TRACE_INSN (cpu, "BITSET (R%i, %s);", dst, uimm_str);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      SET_DREG (dst, DREG (dst) | (1 << uimm));
+      setflags_logical (cpu, DREG (dst));
+    }
+  else if (opc == 3)
+    {
+      TRACE_INSN (cpu, "BITTGL (R%i, %s);", dst, uimm_str);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      SET_DREG (dst, DREG (dst) ^ (1 << uimm));
+      setflags_logical (cpu, DREG (dst));
+    }
+  else if (opc == 4)
+    {
+      TRACE_INSN (cpu, "BITCLR (R%i, %s);", dst, uimm_str);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      SET_DREG (dst, DREG (dst) & ~(1 << uimm));
+      setflags_logical (cpu, DREG (dst));
+    }
+  else if (opc == 5)
+    {
+      TRACE_INSN (cpu, "R%i >>>= %s;", dst, uimm_str);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      SET_DREG (dst, ashiftrt (cpu, DREG (dst), uimm, 32));
+    }
+  else if (opc == 6)
+    {
+      TRACE_INSN (cpu, "R%i >>= %s;", dst, uimm_str);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      SET_DREG (dst, lshiftrt (cpu, DREG (dst), uimm, 32));
+    }
+  else if (opc == 7)
+    {
+      TRACE_INSN (cpu, "R%i <<= %s;", dst, uimm_str);
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      SET_DREG (dst, lshift (cpu, DREG (dst), uimm, 32, 0));
+    }
+}
+
+static void
+decode_COMP3op_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* COMP3op
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int opc  = ((iw0 >> COMP3op_opc_bits) & COMP3op_opc_mask);
+  int dst  = ((iw0 >> COMP3op_dst_bits) & COMP3op_dst_mask);
+  int src0 = ((iw0 >> COMP3op_src0_bits) & COMP3op_src0_mask);
+  int src1 = ((iw0 >> COMP3op_src1_bits) & COMP3op_src1_mask);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMP3op);
+  TRACE_EXTRACT (cpu, "%s: opc:%i dst:%i src1:%i src0:%i",
+                __func__, opc, dst, src1, src0);
+
+  if (opc == 0)
+    {
+      TRACE_INSN (cpu, "R%i = R%i + R%i;", dst, src0, src1);
+      SET_DREG (dst, add32 (cpu, DREG (src0), DREG (src1), 1, 0));
+    }
+  else if (opc == 1)
+    {
+      TRACE_INSN (cpu, "R%i = R%i - R%i;", dst, src0, src1);
+      SET_DREG (dst, sub32 (cpu, DREG (src0), DREG (src1), 1, 0, 0));
+    }
+  else if (opc == 2)
+    {
+      TRACE_INSN (cpu, "R%i = R%i & R%i;", dst, src0, src1);
+      SET_DREG (dst, DREG (src0) & DREG (src1));
+      setflags_logical (cpu, DREG (dst));
+    }
+  else if (opc == 3)
+    {
+      TRACE_INSN (cpu, "R%i = R%i | R%i;", dst, src0, src1);
+      SET_DREG (dst, DREG (src0) | DREG (src1));
+      setflags_logical (cpu, DREG (dst));
+    }
+  else if (opc == 4)
+    {
+      TRACE_INSN (cpu, "R%i = R%i ^ R%i;", dst, src0, src1);
+      SET_DREG (dst, DREG (src0) ^ DREG (src1));
+      setflags_logical (cpu, DREG (dst));
+    }
+  else
+    {
+      int shift = opc - 5;
+      const char *dst_name = get_preg_name (dst);
+      const char *src0_name = get_preg_name (src0);
+      const char *src1_name = get_preg_name (src1);
+
+      /* If src0 == src1 this is disassembled as a shift by 1, but this
+         distinction doesn't matter for our purposes.  */
+      if (shift)
+       TRACE_INSN (cpu, "%s = (%s + %s) << %#x;",
+                   dst_name, src0_name, src1_name, shift);
+      else
+       TRACE_INSN (cpu, "%s = %s + %s",
+                   dst_name, src0_name, src1_name);
+      SET_PREG (dst, PREG (src0) + (PREG (src1) << shift));
+    }
+}
+
+static void
+decode_COMPI2opD_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* COMPI2opD
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int op  = ((iw0 >> COMPI2opD_op_bits) & COMPI2opD_op_mask);
+  int dst = ((iw0 >> COMPI2opD_dst_bits) & COMPI2opD_dst_mask);
+  int src = ((iw0 >> COMPI2opD_src_bits) & COMPI2opD_src_mask);
+  int imm = imm7 (src);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMPI2opD);
+  TRACE_EXTRACT (cpu, "%s: op:%i src:%i dst:%i", __func__, op, src, dst);
+  TRACE_DECODE (cpu, "%s: imm7:%#x", __func__, imm);
+
+  if (op == 0)
+    {
+      TRACE_INSN (cpu, "R%i = %s (X);", dst, imm7_str (imm));
+      SET_DREG (dst, imm);
+    }
+  else if (op == 1)
+    {
+      TRACE_INSN (cpu, "R%i += %s;", dst, imm7_str (imm));
+      SET_DREG (dst, add32 (cpu, DREG (dst), imm, 1, 0));
+    }
+}
+
+static void
+decode_COMPI2opP_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* COMPI2opP
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int op  = ((iw0 >> COMPI2opP_op_bits) & COMPI2opP_op_mask);
+  int src = ((iw0 >> COMPI2opP_src_bits) & COMPI2opP_src_mask);
+  int dst = ((iw0 >> COMPI2opP_dst_bits) & COMPI2opP_dst_mask);
+  int imm = imm7 (src);
+  const char *dst_name = get_preg_name (dst);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMPI2opP);
+  TRACE_EXTRACT (cpu, "%s: op:%i src:%i dst:%i", __func__, op, src, dst);
+  TRACE_DECODE (cpu, "%s: imm:%#x", __func__, imm);
+
+  if (op == 0)
+    {
+      TRACE_INSN (cpu, "%s = %s;", dst_name, imm7_str (imm));
+      SET_PREG (dst, imm);
+    }
+  else if (op == 1)
+    {
+      TRACE_INSN (cpu, "%s += %s;", dst_name, imm7_str (imm));
+      SET_PREG (dst, PREG (dst) + imm);
+    }
+}
+
+static void
+decode_LDSTpmod_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* LDSTpmod
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int W   = ((iw0 >> LDSTpmod_W_bits) & LDSTpmod_W_mask);
+  int aop = ((iw0 >> LDSTpmod_aop_bits) & LDSTpmod_aop_mask);
+  int idx = ((iw0 >> LDSTpmod_idx_bits) & LDSTpmod_idx_mask);
+  int ptr = ((iw0 >> LDSTpmod_ptr_bits) & LDSTpmod_ptr_mask);
+  int reg = ((iw0 >> LDSTpmod_reg_bits) & LDSTpmod_reg_mask);
+  const char *ptr_name = get_preg_name (ptr);
+  const char *idx_name = get_preg_name (idx);
+  bu32 addr, val;
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTpmod);
+  TRACE_EXTRACT (cpu, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
+                __func__, W, aop, reg, idx, ptr);
+
+  if (aop == 1 && W == 0 && idx == ptr)
+    {
+      TRACE_INSN (cpu, "R%i.L = W[%s];", reg, ptr_name);
+      addr = PREG (ptr);
+      val = GET_WORD (addr);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val);
+    }
+  else if (aop == 2 && W == 0 && idx == ptr)
+    {
+      TRACE_INSN (cpu, "R%i.H = W[%s];", reg, ptr_name);
+      addr = PREG (ptr);
+      val = GET_WORD (addr);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16));
+    }
+  else if (aop == 1 && W == 1 && idx == ptr)
+    {
+      TRACE_INSN (cpu, "W[%s] = R%i.L;", ptr_name, reg);
+      addr = PREG (ptr);
+      PUT_WORD (addr, DREG (reg));
+    }
+  else if (aop == 2 && W == 1 && idx == ptr)
+    {
+      TRACE_INSN (cpu, "W[%s] = R%i.H;", ptr_name, reg);
+      addr = PREG (ptr);
+      PUT_WORD (addr, DREG (reg) >> 16);
+    }
+  else if (aop == 0 && W == 0)
+    {
+      TRACE_INSN (cpu, "R%i = [%s ++ %s];", reg, ptr_name, idx_name);
+      addr = PREG (ptr);
+      val = GET_LONG (addr);
+      STORE (DREG (reg), val);
+      if (ptr != idx)
+       STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 1 && W == 0)
+    {
+      TRACE_INSN (cpu, "R%i.L = W[%s ++ %s];", reg, ptr_name, idx_name);
+      addr = PREG (ptr);
+      val = GET_WORD (addr);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val);
+      if (ptr != idx)
+       STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 2 && W == 0)
+    {
+      TRACE_INSN (cpu, "R%i.H = W[%s ++ %s];", reg, ptr_name, idx_name);
+      addr = PREG (ptr);
+      val = GET_WORD (addr);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16));
+      if (ptr != idx)
+       STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 3 && W == 0)
+    {
+      TRACE_INSN (cpu, "R%i = W[%s ++ %s] (Z);", reg, ptr_name, idx_name);
+      addr = PREG (ptr);
+      val = GET_WORD (addr);
+      STORE (DREG (reg), val);
+      if (ptr != idx)
+       STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 3 && W == 1)
+    {
+      TRACE_INSN (cpu, "R%i = W[%s ++ %s] (X);", reg, ptr_name, idx_name);
+      addr = PREG (ptr);
+      val = GET_WORD (addr);
+      STORE (DREG (reg), (bs32) (bs16) val);
+      if (ptr != idx)
+       STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 0 && W == 1)
+    {
+      TRACE_INSN (cpu, "[%s ++ %s] = R%i;", ptr_name, idx_name, reg);
+      addr = PREG (ptr);
+      PUT_LONG (addr, DREG (reg));
+      if (ptr != idx)
+       STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 1 && W == 1)
+    {
+      TRACE_INSN (cpu, "W[%s ++ %s] = R%i.L;", ptr_name, idx_name, reg);
+      addr = PREG (ptr);
+      PUT_WORD (addr, DREG (reg));
+      if (ptr != idx)
+       STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else if (aop == 2 && W == 1)
+    {
+      TRACE_INSN (cpu, "W[%s ++ %s] = R%i.H;", ptr_name, idx_name, reg);
+      addr = PREG (ptr);
+      PUT_WORD (addr, DREG (reg) >> 16);
+      if (ptr != idx)
+       STORE (PREG (ptr), addr + PREG (idx));
+    }
+  else
+    illegal_instruction (cpu);
+}
+
+static void
+decode_dagMODim_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* dagMODim
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int i  = ((iw0 >> DagMODim_i_bits) & DagMODim_i_mask);
+  int m  = ((iw0 >> DagMODim_m_bits) & DagMODim_m_mask);
+  int br = ((iw0 >> DagMODim_br_bits) & DagMODim_br_mask);
+  int op = ((iw0 >> DagMODim_op_bits) & DagMODim_op_mask);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dagMODim);
+  TRACE_EXTRACT (cpu, "%s: br:%i op:%i m:%i i:%i", __func__, br, op, m, i);
+
+  if (op == 0 && br == 1)
+    {
+      TRACE_INSN (cpu, "I%i += M%i (BREV);", i, m);
+      SET_IREG (i, add_brev (IREG (i), MREG (m)));
+    }
+  else if (op == 0)
+    {
+      TRACE_INSN (cpu, "I%i += M%i;", i, m);
+      dagadd (cpu, i, MREG (m));
+    }
+  else if (op == 1 && br == 0)
+    {
+      TRACE_INSN (cpu, "I%i -= M%i;", i, m);
+      dagsub (cpu, i, MREG (m));
+    }
+  else
+    illegal_instruction (cpu);
+}
+
+static void
+decode_dagMODik_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* dagMODik
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int i  = ((iw0 >> DagMODik_i_bits) & DagMODik_i_mask);
+  int op = ((iw0 >> DagMODik_op_bits) & DagMODik_op_mask);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dagMODik);
+  TRACE_EXTRACT (cpu, "%s: op:%i i:%i", __func__, op, i);
+
+  if (op == 0)
+    {
+      TRACE_INSN (cpu, "I%i += 2;", i);
+      dagadd (cpu, i, 2);
+    }
+  else if (op == 1)
+    {
+      TRACE_INSN (cpu, "I%i -= 2;", i);
+      dagsub (cpu, i, 2);
+    }
+  else if (op == 2)
+    {
+      TRACE_INSN (cpu, "I%i += 4;", i);
+      dagadd (cpu, i, 4);
+    }
+  else if (op == 3)
+    {
+      TRACE_INSN (cpu, "I%i -= 4;", i);
+      dagsub (cpu, i, 4);
+    }
+  else
+    illegal_instruction (cpu);
+}
+
+static void
+decode_dspLDST_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* dspLDST
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int i   = ((iw0 >> DspLDST_i_bits) & DspLDST_i_mask);
+  int m   = ((iw0 >> DspLDST_m_bits) & DspLDST_m_mask);
+  int W   = ((iw0 >> DspLDST_W_bits) & DspLDST_W_mask);
+  int aop = ((iw0 >> DspLDST_aop_bits) & DspLDST_aop_mask);
+  int reg = ((iw0 >> DspLDST_reg_bits) & DspLDST_reg_mask);
+  bu32 addr;
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dspLDST);
+  TRACE_EXTRACT (cpu, "%s: aop:%i m:%i i:%i reg:%i", __func__, aop, m, i, reg);
+
+  if (aop == 0 && W == 0 && m == 0)
+    {
+      TRACE_INSN (cpu, "R%i = [I%i++];", reg, i);
+      addr = IREG (i);
+      if (DIS_ALGN_EXPT & 0x1)
+       addr &= ~3;
+      dagadd (cpu, i, 4);
+      STORE (DREG (reg), GET_LONG (addr));
+    }
+  else if (aop == 0 && W == 0 && m == 1)
+    {
+      TRACE_INSN (cpu, "R%i.L = W[I%i++];", reg, i);
+      addr = IREG (i);
+      dagadd (cpu, i, 2);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
+    }
+  else if (aop == 0 && W == 0 && m == 2)
+    {
+      TRACE_INSN (cpu, "R%i.H = W[I%i++];", reg, i);
+      addr = IREG (i);
+      dagadd (cpu, i, 2);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
+    }
+  else if (aop == 1 && W == 0 && m == 0)
+    {
+      TRACE_INSN (cpu, "R%i = [I%i--];", reg, i);
+      addr = IREG (i);
+      if (DIS_ALGN_EXPT & 0x1)
+       addr &= ~3;
+      dagsub (cpu, i, 4);
+      STORE (DREG (reg), GET_LONG (addr));
+    }
+  else if (aop == 1 && W == 0 && m == 1)
+    {
+      TRACE_INSN (cpu, "R%i.L = W[I%i--];", reg, i);
+      addr = IREG (i);
+      dagsub (cpu, i, 2);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
+    }
+  else if (aop == 1 && W == 0 && m == 2)
+    {
+      TRACE_INSN (cpu, "R%i.H = W[I%i--];", reg, i);
+      addr = IREG (i);
+      dagsub (cpu, i, 2);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
+    }
+  else if (aop == 2 && W == 0 && m == 0)
+    {
+      TRACE_INSN (cpu, "R%i = [I%i];", reg, i);
+      addr = IREG (i);
+      if (DIS_ALGN_EXPT & 0x1)
+       addr &= ~3;
+      STORE (DREG (reg), GET_LONG (addr));
+    }
+  else if (aop == 2 && W == 0 && m == 1)
+    {
+      TRACE_INSN (cpu, "R%i.L = W[I%i];", reg, i);
+      addr = IREG (i);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
+    }
+  else if (aop == 2 && W == 0 && m == 2)
+    {
+      TRACE_INSN (cpu, "R%i.H = W[I%i];", reg, i);
+      addr = IREG (i);
+      STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
+    }
+  else if (aop == 0 && W == 1 && m == 0)
+    {
+      TRACE_INSN (cpu, "[I%i++] = R%i;", i, reg);
+      addr = IREG (i);
+      dagadd (cpu, i, 4);
+      PUT_LONG (addr, DREG (reg));
+    }
+  else if (aop == 0 && W == 1 && m == 1)
+    {
+      TRACE_INSN (cpu, "W[I%i++] = R%i.L;", i, reg);
+      addr = IREG (i);
+      dagadd (cpu, i, 2);
+      PUT_WORD (addr, DREG (reg));
+    }
+  else if (aop == 0 && W == 1 && m == 2)
+    {
+      TRACE_INSN (cpu, "W[I%i++] = R%i.H;", i, reg);
+      addr = IREG (i);
+      dagadd (cpu, i, 2);
+      PUT_WORD (addr, DREG (reg) >> 16);
+    }
+  else if (aop == 1 && W == 1 && m == 0)
+    {
+      TRACE_INSN (cpu, "[I%i--] = R%i;", i, reg);
+      addr = IREG (i);
+      dagsub (cpu, i, 4);
+      PUT_LONG (addr, DREG (reg));
+    }
+  else if (aop == 1 && W == 1 && m == 1)
+    {
+      TRACE_INSN (cpu, "W[I%i--] = R%i.L;", i, reg);
+      addr = IREG (i);
+      dagsub (cpu, i, 2);
+      PUT_WORD (addr, DREG (reg));
+    }
+  else if (aop == 1 && W == 1 && m == 2)
+    {
+      TRACE_INSN (cpu, "W[I%i--] = R%i.H;", i, reg);
+      addr = IREG (i);
+      dagsub (cpu, i, 2);
+      PUT_WORD (addr, DREG (reg) >> 16);
+    }
+  else if (aop == 2 && W == 1 && m == 0)
+    {
+      TRACE_INSN (cpu, "[I%i] = R%i;", i, reg);
+      addr = IREG (i);
+      PUT_LONG (addr, DREG (reg));
+    }
+  else if (aop == 2 && W == 1 && m == 1)
+    {
+      TRACE_INSN (cpu, "W[I%i] = R%i.L;", i, reg);
+      addr = IREG (i);
+      PUT_WORD (addr, DREG (reg));
+    }
+  else if (aop == 2 && W == 1 && m == 2)
+    {
+      TRACE_INSN (cpu, "W[I%i] = R%i.H;", i, reg);
+      addr = IREG (i);
+      PUT_WORD (addr, DREG (reg) >> 16);
+    }
+  else if (aop == 3 && W == 0)
+    {
+      TRACE_INSN (cpu, "R%i = [I%i ++ M%i];", reg, i, m);
+      addr = IREG (i);
+      if (DIS_ALGN_EXPT & 0x1)
+       addr &= ~3;
+      dagadd (cpu, i, MREG (m));
+      STORE (DREG (reg), GET_LONG (addr));
+    }
+  else if (aop == 3 && W == 1)
+    {
+      TRACE_INSN (cpu, "[I%i ++ M%i] = R%i;", i, m, reg);
+      addr = IREG (i);
+      dagadd (cpu, i, MREG (m));
+      PUT_LONG (addr, DREG (reg));
+    }
+  else
+    illegal_instruction (cpu);
+}
+
+static void
+decode_LDST_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* LDST
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int Z   = ((iw0 >> LDST_Z_bits) & LDST_Z_mask);
+  int W   = ((iw0 >> LDST_W_bits) & LDST_W_mask);
+  int sz  = ((iw0 >> LDST_sz_bits) & LDST_sz_mask);
+  int aop = ((iw0 >> LDST_aop_bits) & LDST_aop_mask);
+  int reg = ((iw0 >> LDST_reg_bits) & LDST_reg_mask);
+  int ptr = ((iw0 >> LDST_ptr_bits) & LDST_ptr_mask);
+  const char * const posts[] = { "++", "--", "" };
+  const char *post = posts[aop];
+  const char *ptr_name = get_preg_name (ptr);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDST);
+  TRACE_EXTRACT (cpu, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
+                __func__, sz, W, aop, Z, ptr, reg);
+
+  if (aop == 3)
+    illegal_instruction (cpu);
+
+  if (W == 0)
+    {
+      if (sz == 0 && Z == 0)
+       {
+         TRACE_INSN (cpu, "R%i = [%s%s];", reg, ptr_name, post);
+         SET_DREG (reg, GET_LONG (PREG (ptr)));
+       }
+      else if (sz == 0 && Z == 1)
+       {
+         TRACE_INSN (cpu, "%s = [%s%s];", get_preg_name (reg), ptr_name, post);
+         if (aop < 2 && ptr == reg)
+           illegal_instruction_combination (cpu);
+         SET_PREG (reg, GET_LONG (PREG (ptr)));
+       }
+      else if (sz == 1 && Z == 0)
+       {
+         TRACE_INSN (cpu, "R%i = W[%s%s] (Z);", reg, ptr_name, post);
+         SET_DREG (reg, GET_WORD (PREG (ptr)));
+       }
+      else if (sz == 1 && Z == 1)
+       {
+         TRACE_INSN (cpu, "R%i = W[%s%s] (X);", reg, ptr_name, post);
+         SET_DREG (reg, (bs32) (bs16) GET_WORD (PREG (ptr)));
+       }
+      else if (sz == 2 && Z == 0)
+       {
+         TRACE_INSN (cpu, "R%i = B[%s%s] (Z);", reg, ptr_name, post);
+         SET_DREG (reg, GET_BYTE (PREG (ptr)));
+       }
+      else if (sz == 2 && Z == 1)
+       {
+         TRACE_INSN (cpu, "R%i = B[%s%s] (X);", reg, ptr_name, post);
+         SET_DREG (reg, (bs32) (bs8) GET_BYTE (PREG (ptr)));
+       }
+      else
+       illegal_instruction (cpu);
+    }
+  else
+    {
+      if (sz == 0 && Z == 0)
+       {
+         TRACE_INSN (cpu, "[%s%s] = R%i;", ptr_name, post, reg);
+         PUT_LONG (PREG (ptr), DREG (reg));
+       }
+      else if (sz == 0 && Z == 1)
+       {
+         TRACE_INSN (cpu, "[%s%s] = %s;", ptr_name, post, get_preg_name (reg));
+         PUT_LONG (PREG (ptr), PREG (reg));
+       }
+      else if (sz == 1 && Z == 0)
+       {
+         TRACE_INSN (cpu, "W[%s%s] = R%i;", ptr_name, post, reg);
+         PUT_WORD (PREG (ptr), DREG (reg));
+       }
+      else if (sz == 2 && Z == 0)
+       {
+         TRACE_INSN (cpu, "B[%s%s] = R%i;", ptr_name, post, reg);
+         PUT_BYTE (PREG (ptr), DREG (reg));
+       }
+      else
+       illegal_instruction (cpu);
+    }
+
+  if (aop == 0)
+    SET_PREG (ptr, PREG (ptr) + (1 << (2 - sz)));
+  if (aop == 1)
+    SET_PREG (ptr, PREG (ptr) - (1 << (2 - sz)));
+}
+
+static void
+decode_LDSTiiFP_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* LDSTiiFP
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
+     but for our usage, its functionality the same thing.  */
+  int grp = ((iw0 >> 3) & 0x1);
+  int reg = ((iw0 >> LDSTiiFP_reg_bits) & 0x7 /*LDSTiiFP_reg_mask*/);
+  int offset = ((iw0 >> LDSTiiFP_offset_bits) & LDSTiiFP_offset_mask);
+  int W = ((iw0 >> LDSTiiFP_W_bits) & LDSTiiFP_W_mask);
+  bu32 imm = negimm5s4 (offset);
+  bu32 ea = FPREG + imm;
+  const char *imm_str = negimm5s4_str (offset);
+  const char *reg_name = get_allreg_name (grp, reg);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTiiFP);
+  TRACE_EXTRACT (cpu, "%s: W:%i offset:%#x grp:%i reg:%i", __func__,
+                W, offset, grp, reg);
+  TRACE_DECODE (cpu, "%s: negimm5s4:%#x", __func__, imm);
+
+  if (W == 0)
+    {
+      TRACE_INSN (cpu, "%s = [FP + %s];", reg_name, imm_str);
+      reg_write (cpu, grp, reg, GET_LONG (ea));
+    }
+  else
+    {
+      TRACE_INSN (cpu, "[FP + %s] = %s;", imm_str, reg_name);
+      PUT_LONG (ea, reg_read (cpu, grp, reg));
+    }
+}
+
+static void
+decode_LDSTii_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* LDSTii
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int reg = ((iw0 >> LDSTii_reg_bit) & LDSTii_reg_mask);
+  int ptr = ((iw0 >> LDSTii_ptr_bit) & LDSTii_ptr_mask);
+  int offset = ((iw0 >> LDSTii_offset_bit) & LDSTii_offset_mask);
+  int op = ((iw0 >> LDSTii_op_bit) & LDSTii_op_mask);
+  int W = ((iw0 >> LDSTii_W_bit) & LDSTii_W_mask);
+  bu32 imm, ea;
+  const char *imm_str;
+  const char *ptr_name = get_preg_name (ptr);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTii);
+  TRACE_EXTRACT (cpu, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
+                __func__, W, op, offset, ptr, reg);
+
+  if (op == 0 || op == 3)
+    imm = uimm4s4 (offset), imm_str = uimm4s4_str (offset);
+  else
+    imm = uimm4s2 (offset), imm_str = uimm4s2_str (offset);
+  ea = PREG (ptr) + imm;
+
+  TRACE_DECODE (cpu, "%s: uimm4s4/uimm4s2:%#x", __func__, imm);
+
+  if (W == 1 && op == 2)
+    illegal_instruction (cpu);
+
+  if (W == 0)
+    {
+      if (op == 0)
+       {
+         TRACE_INSN (cpu, "R%i = [%s + %s];", reg, ptr_name, imm_str);
+         SET_DREG (reg, GET_LONG (ea));
+       }
+      else if (op == 1)
+       {
+         TRACE_INSN (cpu, "R%i = W[%s + %s] (Z);", reg, ptr_name, imm_str);
+         SET_DREG (reg, GET_WORD (ea));
+       }
+      else if (op == 2)
+       {
+         TRACE_INSN (cpu, "R%i = W[%s + %s] (X);", reg, ptr_name, imm_str);
+         SET_DREG (reg, (bs32) (bs16) GET_WORD (ea));
+       }
+      else if (op == 3)
+       {
+         TRACE_INSN (cpu, "%s = [%s + %s];",
+                     get_preg_name (reg), ptr_name, imm_str);
+         SET_PREG (reg, GET_LONG (ea));
+       }
+    }
+  else
+    {
+      if (op == 0)
+       {
+         TRACE_INSN (cpu, "[%s + %s] = R%i;", ptr_name, imm_str, reg);
+         PUT_LONG (ea, DREG (reg));
+       }
+      else if (op == 1)
+       {
+         TRACE_INSN (cpu, "W[%s + %s] = R%i;", ptr_name, imm_str, reg);
+         PUT_WORD (ea, DREG (reg));
+       }
+      else if (op == 3)
+       {
+         TRACE_INSN (cpu, "[%s + %s] = %s;",
+                     ptr_name, imm_str, get_preg_name (reg));
+         PUT_LONG (ea, PREG (reg));
+       }
+    }
+}
+
+static void
+decode_LoopSetup_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
+{
+  /* LoopSetup
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
+     |.reg...........| - | - |.eoffset...............................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int c   = ((iw0 >> (LoopSetup_c_bits - 16)) & LoopSetup_c_mask);
+  int reg = ((iw1 >> LoopSetup_reg_bits) & LoopSetup_reg_mask);
+  int rop = ((iw0 >> (LoopSetup_rop_bits - 16)) & LoopSetup_rop_mask);
+  int soffset = ((iw0 >> (LoopSetup_soffset_bits - 16)) & LoopSetup_soffset_mask);
+  int eoffset = ((iw1 >> LoopSetup_eoffset_bits) & LoopSetup_eoffset_mask);
+  int spcrel = pcrel4 (soffset);
+  int epcrel = lppcrel10 (eoffset);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LoopSetup);
+  TRACE_EXTRACT (cpu, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
+                __func__, rop, c, soffset, reg, eoffset);
+  TRACE_DECODE (cpu, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
+               __func__, spcrel, epcrel);
+
+  if (reg > 7)
+    illegal_instruction (cpu);
+
+  if (INSN_LEN == 8)
+    illegal_instruction_combination (cpu);
+
+  if (rop == 0)
+    {
+      TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i;", spcrel, epcrel, c);
+    }
+  else if (rop == 1 && reg <= 7)
+    {
+      TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i = %s;",
+                 spcrel, epcrel, c, get_preg_name (reg));
+      SET_LCREG (c, PREG (reg));
+    }
+  else if (rop == 3 && reg <= 7)
+    {
+      TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
+                 spcrel, epcrel, c, get_preg_name (reg));
+      SET_LCREG (c, PREG (reg) >> 1);
+    }
+  else
+    illegal_instruction (cpu);
+
+  SET_LTREG (c, pc + spcrel);
+  SET_LBREG (c, pc + epcrel);
+}
+
+static void
+decode_LDIMMhalf_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
+{
+  /* LDIMMhalf
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
+     |.hword.........................................................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int H = ((iw0 >> (LDIMMhalf_H_bits - 16)) & LDIMMhalf_H_mask);
+  int Z = ((iw0 >> (LDIMMhalf_Z_bits - 16)) & LDIMMhalf_Z_mask);
+  int S = ((iw0 >> (LDIMMhalf_S_bits - 16)) & LDIMMhalf_S_mask);
+  int reg = ((iw0 >> (LDIMMhalf_reg_bits - 16)) & LDIMMhalf_reg_mask);
+  int grp = ((iw0 >> (LDIMMhalf_grp_bits - 16)) & LDIMMhalf_grp_mask);
+  int hword = ((iw1 >> LDIMMhalf_hword_bits) & LDIMMhalf_hword_mask);
+  bu32 val;
+  const char *val_str;
+  const char *reg_name = get_allreg_name (grp, reg);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDIMMhalf);
+  TRACE_EXTRACT (cpu, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
+                __func__, Z, H, S, grp, reg, hword);
+
+  if (INSN_LEN == 8)
+    illegal_instruction_combination (cpu);
+
+  if (S == 1)
+    val = imm16 (hword), val_str = imm16_str (hword);
+  else
+    val = luimm16 (hword), val_str = luimm16_str (hword);
+
+  if (H == 0 && S == 1 && Z == 0)
+    {
+      TRACE_INSN (cpu, "%s = %s (X);", reg_name, val_str);
+    }
+  else if (H == 0 && S == 0 && Z == 1)
+    {
+      TRACE_INSN (cpu, "%s = %s (Z);", reg_name, val_str);
+    }
+  else if (H == 0 && S == 0 && Z == 0)
+    {
+      TRACE_INSN (cpu, "%s.L = %s;", reg_name, val_str);
+      val = REG_H_L (reg_read (cpu, grp, reg), val);
+    }
+  else if (H == 1 && S == 0 && Z == 0)
+    {
+      TRACE_INSN (cpu, "%s.H = %s;", reg_name, val_str);
+      val = REG_H_L (val << 16, reg_read (cpu, grp, reg));
+    }
+  else
+    illegal_instruction (cpu);
+
+  reg_write (cpu, grp, reg, val);
+}
+
+static void
+decode_CALLa_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
+{
+  /* CALLa
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
+     |.lsw...........................................................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int S   = ((iw0 >> (CALLa_S_bits - 16)) & CALLa_S_mask);
+  int lsw = ((iw1 >> 0) & 0xffff);
+  int msw = ((iw0 >> 0) & 0xff);
+  int pcrel = pcrel24 ((msw << 16) | lsw);
+  bu32 newpc = pc + pcrel;
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CALLa);
+  TRACE_EXTRACT (cpu, "%s: S:%i msw:%#x lsw:%#x", __func__, S, msw, lsw);
+  TRACE_DECODE (cpu, "%s: pcrel24:%#x", __func__, pcrel);
+
+  TRACE_INSN (cpu, "%s %#x;", S ? "CALL" : "JUMP.L", pcrel);
+
+  if (INSN_LEN == 8)
+    illegal_instruction_combination (cpu);
+
+  if (S == 1)
+    {
+      TRACE_BRANCH (cpu, pc, newpc, -1, "CALL");
+      SET_RETSREG (hwloop_get_next_pc (cpu, pc, 4));
+    }
+  else
+    TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP.L");
+
+  SET_PCREG (newpc);
+  BFIN_CPU_STATE.did_jump = true;
+  PROFILE_BRANCH_TAKEN (cpu);
+  CYCLE_DELAY = 5;
+}
+
+static void
+decode_LDSTidxI_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
+{
+  /* LDSTidxI
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
+     |.offset........................................................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int Z = ((iw0 >> (LDSTidxI_Z_bits - 16)) & LDSTidxI_Z_mask);
+  int W = ((iw0 >> (LDSTidxI_W_bits - 16)) & LDSTidxI_W_mask);
+  int sz = ((iw0 >> (LDSTidxI_sz_bits - 16)) & LDSTidxI_sz_mask);
+  int reg = ((iw0 >> (LDSTidxI_reg_bits - 16)) & LDSTidxI_reg_mask);
+  int ptr = ((iw0 >> (LDSTidxI_ptr_bits - 16)) & LDSTidxI_ptr_mask);
+  int offset = ((iw1 >> LDSTidxI_offset_bits) & LDSTidxI_offset_mask);
+  const char *ptr_name = get_preg_name (ptr);
+  bu32 imm_16s4 = imm16s4 (offset);
+  bu32 imm_16s2 = imm16s2 (offset);
+  bu32 imm_16 = imm16 (offset);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTidxI);
+  TRACE_EXTRACT (cpu, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
+                __func__, W, Z, sz, ptr, reg, offset);
+
+  if (sz == 3)
+    illegal_instruction (cpu);
+
+  if (W == 0)
+    {
+      if (sz == 0 && Z == 0)
+       {
+         TRACE_INSN (cpu, "R%i = [%s + %s];",
+                     reg, ptr_name, imm16s4_str (offset));
+         SET_DREG (reg, GET_LONG (PREG (ptr) + imm_16s4));
+       }
+      else if (sz == 0 && Z == 1)
+       {
+         TRACE_INSN (cpu, "%s = [%s + %s];",
+                     get_preg_name (reg), ptr_name, imm16s4_str (offset));
+         SET_PREG (reg, GET_LONG (PREG (ptr) + imm_16s4));
+       }
+      else if (sz == 1 && Z == 0)
+       {
+         TRACE_INSN (cpu, "R%i = W[%s + %s] (Z);",
+                     reg, ptr_name, imm16s2_str (offset));
+         SET_DREG (reg, GET_WORD (PREG (ptr) + imm_16s2));
+       }
+      else if (sz == 1 && Z == 1)
+       {
+         TRACE_INSN (cpu, "R%i = W[%s + %s] (X);",
+                     reg, ptr_name, imm16s2_str (offset));
+         SET_DREG (reg, (bs32) (bs16) GET_WORD (PREG (ptr) + imm_16s2));
+       }
+      else if (sz == 2 && Z == 0)
+       {
+         TRACE_INSN (cpu, "R%i = B[%s + %s] (Z);",
+                     reg, ptr_name, imm16_str (offset));
+         SET_DREG (reg, GET_BYTE (PREG (ptr) + imm_16));
+       }
+      else if (sz == 2 && Z == 1)
+       {
+         TRACE_INSN (cpu, "R%i = B[%s + %s] (X);",
+                     reg, ptr_name, imm16_str (offset));
+         SET_DREG (reg, (bs32) (bs8) GET_BYTE (PREG (ptr) + imm_16));
+       }
+    }
+  else
+    {
+      if (sz != 0 && Z != 0)
+       illegal_instruction (cpu);
+
+      if (sz == 0 && Z == 0)
+       {
+         TRACE_INSN (cpu, "[%s + %s] = R%i;", ptr_name,
+                     imm16s4_str (offset), reg);
+         PUT_LONG (PREG (ptr) + imm_16s4, DREG (reg));
+       }
+      else if (sz == 0 && Z == 1)
+       {
+         TRACE_INSN (cpu, "[%s + %s] = %s;",
+                     ptr_name, imm16s4_str (offset), get_preg_name (reg));
+         PUT_LONG (PREG (ptr) + imm_16s4, PREG (reg));
+       }
+      else if (sz == 1 && Z == 0)
+       {
+         TRACE_INSN (cpu, "W[%s + %s] = R%i;",
+                     ptr_name, imm16s2_str (offset), reg);
+         PUT_WORD (PREG (ptr) + imm_16s2, DREG (reg));
+       }
+      else if (sz == 2 && Z == 0)
+       {
+         TRACE_INSN (cpu, "B[%s + %s] = R%i;",
+                     ptr_name, imm16_str (offset), reg);
+         PUT_BYTE (PREG (ptr) + imm_16, DREG (reg));
+       }
+    }
+}
+
+static void
+decode_linkage_0 (SIM_CPU *cpu, 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 >> (Linkage_R_bits - 16)) & Linkage_R_mask);
+  int framesize = ((iw1 >> Linkage_framesize_bits) & Linkage_framesize_mask);
+  bu32 sp;
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_linkage);
+  TRACE_EXTRACT (cpu, "%s: R:%i framesize:%#x", __func__, R, framesize);
+
+  if (R == 0)
+    {
+      int size = uimm16s4 (framesize);
+      sp = SPREG;
+      TRACE_INSN (cpu, "LINK %s;", uimm16s4_str (framesize));
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      sp -= 4;
+      PUT_LONG (sp, RETSREG);
+      sp -= 4;
+      PUT_LONG (sp, FPREG);
+      SET_FPREG (sp);
+      sp -= size;
+      CYCLE_DELAY = 3;
+    }
+  else
+    {
+      /* Restore SP from FP.  */
+      sp = FPREG;
+      TRACE_INSN (cpu, "UNLINK;");
+      if (INSN_LEN == 8)
+       illegal_instruction_combination (cpu);
+      SET_FPREG (GET_LONG (sp));
+      sp += 4;
+      SET_RETSREG (GET_LONG (sp));
+      sp += 4;
+      CYCLE_DELAY = 2;
+    }
+
+  SET_SPREG (sp);
+}
+
+static void
+decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
+{
+  /* 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 >> (DSP32Mac_op1_bits - 16)) & DSP32Mac_op1_mask);
+  int w1   = ((iw0 >> (DSP32Mac_w1_bits - 16)) & DSP32Mac_w1_mask);
+  int P    = ((iw0 >> (DSP32Mac_p_bits - 16)) & DSP32Mac_p_mask);
+  int MM   = ((iw0 >> (DSP32Mac_MM_bits - 16)) & DSP32Mac_MM_mask);
+  int mmod = ((iw0 >> (DSP32Mac_mmod_bits - 16)) & DSP32Mac_mmod_mask);
+  int M    = ((iw0 >> (DSP32Mac_M_bits - 16)) & DSP32Mac_M_mask);
+  int w0   = ((iw1 >> DSP32Mac_w0_bits) & DSP32Mac_w0_mask);
+  int src0 = ((iw1 >> DSP32Mac_src0_bits) & DSP32Mac_src0_mask);
+  int src1 = ((iw1 >> DSP32Mac_src1_bits) & DSP32Mac_src1_mask);
+  int dst  = ((iw1 >> DSP32Mac_dst_bits) & DSP32Mac_dst_mask);
+  int h10  = ((iw1 >> DSP32Mac_h10_bits) & DSP32Mac_h10_mask);
+  int h00  = ((iw1 >> DSP32Mac_h00_bits) & DSP32Mac_h00_mask);
+  int op0  = ((iw1 >> DSP32Mac_op0_bits) & DSP32Mac_op0_mask);
+  int h11  = ((iw1 >> DSP32Mac_h11_bits) & DSP32Mac_h11_mask);
+  int h01  = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask);
+
+  bu32 res = DREG (dst);
+  bu32 v_i = 0, zero = 0;
+
+  static const char * const ops[] = { "=", "+=", "-=" };
+  char _buf[128], *buf = _buf;
+  int _MM = MM;
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mac);
+  TRACE_EXTRACT (cpu, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
+                     "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
+                __func__, M, mmod, MM, P, w1, op1, h01, h11, w0, op0, h00, h10,
+                dst, src0, src1);
+
+  if (w0 == 0 && w1 == 0 && op1 == 3 && op0 == 3)
+    illegal_instruction (cpu);
+
+  if ((w1 || w0) && mmod == M_W32)
+    illegal_instruction (cpu);
+
+  if (((1 << mmod) & (P ? 0x131b : 0x1b5f)) == 0)
+    illegal_instruction (cpu);
+
+  /* First handle MAC1 side.  */
+  if (w1 == 1 || op1 != 3)
+    {
+      bu32 res1 = decode_macfunc (cpu, 1, op1, h01, h11, src0,
+                                 src1, mmod, MM, P, &v_i);
+
+      if (w1)
+       buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P);
+
+      if (op1 == 3)
+       {
+         buf += sprintf (buf, " = A1");
+         zero = !!(res1 == 0);
+       }
+      else
+       {
+         if (w1)
+           buf += sprintf (buf, " = (");
+         buf += sprintf (buf, "A1 %s R%i.%c * R%i.%c", ops[op1],
+                         src0, h01 ? 'H' : 'L',
+                         src1, h11 ? 'H' : 'L');
+         if (w1)
+           buf += sprintf (buf, ")");
+       }
+
+      if (w1)
+       {
+         if (P)
+           STORE (DREG (dst + 1), res1);
+         else
+           {
+             if (res1 & 0xffff0000)
+               illegal_instruction (cpu);
+             res = REG_H_L (res1 << 16, res);
+           }
+       }
+
+      if (w0 == 1 || op0 != 3)
+       {
+         if (_MM)
+           buf += sprintf (buf, " (M)");
+         _MM = 0;
+         buf += sprintf (buf, ", ");
+       }
+    }
+
+  /* Then handle MAC0 side.  */
+  if (w0 == 1 || op0 != 3)
+    {
+      bu32 res0 = decode_macfunc (cpu, 0, op0, h00, h10, src0,
+                                 src1, mmod, 0, P, &v_i);
+
+      if (w0)
+       buf += sprintf (buf, P ? "R%i" : "R%i.L", dst);
+
+      if (op0 == 3)
+       {
+         buf += sprintf (buf, " = A0");
+         zero |= !!(res0 == 0);
+       }
+      else
+       {
+         if (w0)
+           buf += sprintf (buf, " = (");
+         buf += sprintf (buf, "A0 %s R%i.%c * R%i.%c", ops[op0],
+                         src0, h00 ? 'H' : 'L',
+                         src1, h10 ? 'H' : 'L');
+         if (w0)
+           buf += sprintf (buf, ")");
+       }
+
+      if (w0)
+       {
+         if (P)
+           STORE (DREG (dst), res0);
+         else
+           {
+             if (res0 & 0xffff0000)
+               illegal_instruction (cpu);
+             res = REG_H_L (res, res0);
+           }
+       }
+    }
+
+  TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM));
+
+  if (!P && (w0 || w1))
+    {
+      STORE (DREG (dst), res);
+      SET_ASTATREG (v, v_i);
+      if (v_i)
+       SET_ASTATREG (vs, v_i);
+    }
+  else if (P)
+    {
+      SET_ASTATREG (v, v_i);
+      if (v_i)
+       SET_ASTATREG (vs, v_i);
+    }
+  if (op0 == 3 || op1 == 3)
+    SET_ASTATREG (az, zero);
+}
+
+static void
+decode_dsp32mult_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
+{
+  /* 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 >> (DSP32Mac_op1_bits - 16)) & DSP32Mac_op1_mask);
+  int w1   = ((iw0 >> (DSP32Mac_w1_bits - 16)) & DSP32Mac_w1_mask);
+  int P    = ((iw0 >> (DSP32Mac_p_bits - 16)) & DSP32Mac_p_mask);
+  int MM   = ((iw0 >> (DSP32Mac_MM_bits - 16)) & DSP32Mac_MM_mask);
+  int mmod = ((iw0 >> (DSP32Mac_mmod_bits - 16)) & DSP32Mac_mmod_mask);
+  int M    = ((iw0 >> (DSP32Mac_M_bits - 16)) & DSP32Mac_M_mask);
+  int w0   = ((iw1 >> DSP32Mac_w0_bits) & DSP32Mac_w0_mask);
+  int src0 = ((iw1 >> DSP32Mac_src0_bits) & DSP32Mac_src0_mask);
+  int src1 = ((iw1 >> DSP32Mac_src1_bits) & DSP32Mac_src1_mask);
+  int dst  = ((iw1 >> DSP32Mac_dst_bits) & DSP32Mac_dst_mask);
+  int h10  = ((iw1 >> DSP32Mac_h10_bits) & DSP32Mac_h10_mask);
+  int h00  = ((iw1 >> DSP32Mac_h00_bits) & DSP32Mac_h00_mask);
+  int op0  = ((iw1 >> DSP32Mac_op0_bits) & DSP32Mac_op0_mask);
+  int h11  = ((iw1 >> DSP32Mac_h11_bits) & DSP32Mac_h11_mask);
+  int h01  = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask);
+
+  bu32 res = DREG (dst);
+  bu32 sat0 = 0, sat1 = 0;
+  char _buf[128], *buf = _buf;
+  int _MM = MM;
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mult);
+  TRACE_EXTRACT (cpu, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
+                     "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
+                __func__, M, mmod, MM, P, w1, op1, h01, h11, w0, op0, h00, h10,
+                dst, src0, src1);
+
+  if (w1 == 0 && w0 == 0)
+    illegal_instruction (cpu);
+  if (((1 << mmod) & (P ? 0x313 : 0x1b57)) == 0)
+    illegal_instruction (cpu);
+  if (P && ((dst & 1) || (op1 != 0) || (op0 != 0) || !is_macmod_pmove (mmod)))
+    illegal_instruction (cpu);
+  if (!P && ((op1 != 0) || (op0 != 0) || !is_macmod_hmove (mmod)))
+    illegal_instruction (cpu);
+
+  /* First handle MAC1 side.  */
+  if (w1)
+    {
+      bu64 r = decode_multfunc (cpu, h01, h11, src0, src1, mmod, MM, &sat1);
+      bu32 res1 = extract_mult (cpu, r, mmod, MM, P, NULL);
+
+      buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P);
+      buf += sprintf (buf, " = R%i.%c * R%i.%c",
+                     src0, h01 ? 'H' : 'L',
+                     src1, h11 ? 'H' : 'L');
+      if (w0)
+       {
+         if (_MM)
+           buf += sprintf (buf, " (M)");
+         _MM = 0;
+         buf += sprintf (buf, ", ");
+       }
+
+      if (P)
+       STORE (DREG (dst + 1), res1);
+      else
+       {
+         if (res1 & 0xFFFF0000)
+           illegal_instruction (cpu);
+         res = REG_H_L (res1 << 16, res);
+       }
+    }
+
+  /* First handle MAC0 side.  */
+  if (w0)
+    {
+      bu64 r = decode_multfunc (cpu, h00, h10, src0, src1, mmod, 0, &sat0);
+      bu32 res0 = extract_mult (cpu, r, mmod, 0, P, NULL);
+
+      buf += sprintf (buf, P ? "R%i" : "R%i.L", dst);
+      buf += sprintf (buf, " = R%i.%c * R%i.%c",
+                     src0, h01 ? 'H' : 'L',
+                     src1, h11 ? 'H' : 'L');
+
+      if (P)
+       STORE (DREG (dst), res0);
+      else
+       {
+         if (res0 & 0xFFFF0000)
+           illegal_instruction (cpu);
+         res = REG_H_L (res, res0);
+       }
+    }
+
+  TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM));
+
+  if (!P && (w0 || w1))
+    STORE (DREG (dst), res);
+
+  if (w0 || w1)
+    {
+      STORE (ASTATREG (v), sat0 | sat1);
+      STORE (ASTATREG (v_copy), sat0 | sat1);
+      if (sat0 | sat1)
+       STORE (ASTATREG (vs), 1);
+    }
+}
+
+static void
+decode_dsp32alu_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
+{
+  /* dsp32alu
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
+     |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int s    = ((iw1 >> DSP32Alu_s_bits) & DSP32Alu_s_mask);
+  int x    = ((iw1 >> DSP32Alu_x_bits) & DSP32Alu_x_mask);
+  int aop  = ((iw1 >> DSP32Alu_aop_bits) & DSP32Alu_aop_mask);
+  int src0 = ((iw1 >> DSP32Alu_src0_bits) & DSP32Alu_src0_mask);
+  int src1 = ((iw1 >> DSP32Alu_src1_bits) & DSP32Alu_src1_mask);
+  int dst0 = ((iw1 >> DSP32Alu_dst0_bits) & DSP32Alu_dst0_mask);
+  int dst1 = ((iw1 >> DSP32Alu_dst1_bits) & DSP32Alu_dst1_mask);
+  int M    = ((iw0 >> (DSP32Alu_M_bits - 16)) & DSP32Alu_M_mask);
+  int HL   = ((iw0 >> (DSP32Alu_HL_bits - 16)) & DSP32Alu_HL_mask);
+  int aopcde = ((iw0 >> (DSP32Alu_aopcde_bits - 16)) & DSP32Alu_aopcde_mask);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32alu);
+  TRACE_EXTRACT (cpu, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
+                     "dst1:%i src0:%i src1:%i",
+                __func__, M, HL, aopcde, aop, s, x, dst0, dst1, src0, src1);
+
+  if ((aop == 0 || aop == 2) && aopcde == 9 && HL == 0 && s == 0)
+    {
+      int a = aop >> 1;
+      TRACE_INSN (cpu, "A%i.L = R%i.L;", a, src0);
+      SET_AWREG (a, REG_H_L (AWREG (a), DREG (src0)));
+    }
+  else if ((aop == 0 || aop == 2) && aopcde == 9 && HL == 1 && s == 0)
+    {
+      int a = aop >> 1;
+      TRACE_INSN (cpu, "A%i.H = R%i.H;", a, src0);
+      SET_AWREG (a, REG_H_L (DREG (src0), AWREG (a)));
+    }
+  else if ((aop == 1 || aop == 0) && aopcde == 5)
+    {
+      bs32 val0 = DREG (src0);
+      bs32 val1 = DREG (src1);
+      bs32 res;
+      bs32 signRes;
+      bs32 ovX, sBit1, sBit2, sBitRes1, sBitRes2;
+
+      TRACE_INSN (cpu, "R%i.%s = R%i %s R%i (RND12)", dst0, HL ? "L" : "H",
+                 src0, aop & 0x1 ? "-" : "+", src1);
+
+      /* If subtract, just invert and add one.  */
+      if (aop & 0x1)
+       val1 = ~val1 + 1;
+
+      /* Get the sign bits, since we need them later.  */
+      sBit1 = !!(val0 & 0x80000000);
+      sBit2 = !!(val1 & 0x80000000);
+
+      res = val0 + val1;
+
+      sBitRes1 = !!(res & 0x80000000);
+      /* Round to the 12th bit.  */
+      res += 0x0800;
+      sBitRes2 = !!(res & 0x80000000);
+
+      signRes = res;
+      signRes >>= 27;
+
+      /* Overflow if
+           pos + pos = neg
+           neg + neg = pos
+           positive_res + positive_round = neg
+         Shift and upper 4 bits where not the same.  */
+      if ((!(sBit1 ^ sBit2) && (sBit1 ^ sBitRes1))
+         || (!sBit1 && !sBit2 && sBitRes2)
+         || ((signRes != 0) && (signRes != -1)))
+       {
+         /* Both X1 and X2 Neg res is neg overflow.  */
+         if (sBit1 && sBit2)
+           res = 0x80000000;
+         /* Both X1 and X2 Pos res is pos overflow.  */
+         else if (!sBit1 && !sBit2)
+           res = 0x7FFFFFFF;
+         /* Pos+Neg or Neg+Pos take the sign of the result.  */
+         else if (sBitRes1)
+           res = 0x80000000;
+         else
+           res = 0x7FFFFFFF;
+
+         ovX = 1;
+       }
+      else
+       {
+         /* Shift up now after overflow detection.  */
+         ovX = 0;
+         res <<= 4;
+       }
+
+      res >>= 16;
+
+      if (HL)
+       STORE (DREG (dst0), REG_H_L (res << 16, DREG (dst0)));
+      else
+       STORE (DREG (dst0), REG_H_L (DREG (dst0), res));
+
+      SET_ASTATREG (az, res == 0);
+      SET_ASTATREG (an, res & 0x8000);
+      SET_ASTATREG (v, ovX);
+      if (ovX)
+       SET_ASTATREG (vs, ovX);
+    }
+  else if ((aop == 2 || aop == 3) && aopcde == 5)
+    {
+      bs32 val0 = DREG (src0);
+      bs32 val1 = DREG (src1);
+      bs32 res;
+
+      TRACE_INSN (cpu, "R%i.%s = R%i %s R%i (RND20)", dst0, HL ? "L" : "H",
+                 src0, aop & 0x1 ? "-" : "+", src1);
+
+      /* If subtract, just invert and add one.  */
+      if (aop & 0x1)
+       val1 = ~val1 + 1;
+
+      res = (val0 >> 4) + (val1 >> 4) + (((val0 & 0xf) + (val1 & 0xf)) >> 4);
+      res += 0x8000;
+      /* Don't sign extend during the shift.  */
+      res = ((bu32)res >> 16);
+
+      /* Don't worry about overflows, since we are shifting right.  */
+
+      if (HL)
+       STORE (DREG (dst0), REG_H_L (res << 16, DREG (dst0)));
+      else
+       STORE (DREG (dst0), REG_H_L (DREG (dst0), res));
+
+      SET_ASTATREG (az, res == 0);
+      SET_ASTATREG (an, res & 0x8000);
+      SET_ASTATREG (v, 0);
+    }
+  else if (aopcde == 2 || aopcde == 3)
+    {
+      bu32 s1, s2, val, ac0_i = 0, v_i = 0;
+
+      TRACE_INSN (cpu, "R%i.%c = R%i.%c %c R%i.%c%s;",
+                 dst0, HL ? 'H' : 'L',
+                 src0, aop & 2 ? 'H' : 'L',
+                 aopcde == 2 ? '+' : '-',
+                 src1, aop & 1 ? 'H' : 'L',
+                 amod1 (s, x));
+
+      s1 = DREG (src0);
+      s2 = DREG (src1);
+      if (aop & 1)
+       s2 >>= 16;
+      if (aop & 2)
+       s1 >>= 16;
+
+      if (aopcde == 2)
+       val = add16 (cpu, s1, s2, &ac0_i, &v_i, 0, 0, s, 0);
+      else
+       val = sub16 (cpu, s1, s2, &ac0_i, &v_i, 0, 0, s, 0);
+
+      SET_ASTATREG (ac0, ac0_i);
+      SET_ASTATREG (v, v_i);
+      if (HL)
+       SET_DREG_H (dst0, val << 16);
+      else
+       SET_DREG_L (dst0, val);
+
+      SET_ASTATREG (an, val & 0x8000);
+
+    }
+  else if ((aop == 0 || aop == 2) && aopcde == 9 && s == 1)
+    {
+      int a = aop >> 1;
+      TRACE_INSN (cpu, "A%i = R%i;", a, src0);
+      SET_AREG32 (a, DREG (src0));
+    }
+  else if ((aop == 1 || aop == 3) && aopcde == 9 && s == 0)
+    {
+      int a = aop >> 1;
+      TRACE_INSN (cpu, "A%i.X = R%i.L;", a, src0);
+      SET_AXREG (a, (bs8)DREG (src0));
+    }
+  else if (aop == 3 && aopcde == 11 && (s == 0 || s == 1))
+    {
+      bu64 acc0 = get_extended_acc (cpu, 0);
+      bu64 acc1 = get_extended_acc (cpu, 1);
+      bu32 carry = (bu40)acc1 < (bu40)acc0;
+      bu32 sat = 0;
+
+      TRACE_INSN (cpu, "A0 -= A1%s;", s ? " (W32)" : "");
+
+      acc0 -= acc1;
+      if ((bs64)acc0 < -0x8000000000ll)
+       acc0 = -0x8000000000ull, sat = 1;
+      else if ((bs64)acc0 >= 0x7fffffffffll)
+       acc0 = 0x7fffffffffull, sat = 1;
+
+      if (s == 1)
+       {
+         /* A0 -= A1 (W32)  */
+         if (acc0 & (bu64)0x8000000000ll)
+           acc0 &= 0x80ffffffffll, sat = 1;
+         else
+           acc0 &= 0xffffffffll;
+       }
+      STORE (AXREG (0), (acc0 >> 32) & 0xff);
+      STORE (AWREG (0), acc0 & 0xffffffff);
+      STORE (ASTATREG (az), acc0 == 0);
+      STORE (ASTATREG (an), !!(acc0 & (bu64)0x8000000000ll));
+      STORE (ASTATREG (ac0), carry);
+      STORE (ASTATREG (ac0_copy), carry);
+      STORE (ASTATREG (av0), sat);
+      if (sat)
+       STORE (ASTATREG (av0s), sat);
+    }
+  else if ((aop == 0 || aop == 1) && aopcde == 22)
+    {
+      bu32 s0, s0L, s0H, s1, s1L, s1H;
+      bu32 tmp0, tmp1, i;
+      const char * const opts[] = { "rndl", "rndh", "tl", "th" };
+
+      TRACE_INSN (cpu, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0,
+                 src0 + 1, src0, src1 + 1, src1, opts[HL + (aop << 1)],
+                 s ? ", r" : "");
+
+      if (src0 == src1)
+       illegal_instruction_combination (cpu);
+
+      s0L = DREG (src0);
+      s0H = DREG (src0 + 1);
+      s1L = DREG (src1);
+      s1H = DREG (src1 + 1);
+      if (s)
+       {
+         s0 = algn (s0H, s0L, IREG (0) & 3);
+         s1 = algn (s1H, s1L, IREG (0) & 3);
+       }
+      else
+       {
+         s0 = algn (s0L, s0H, IREG (0) & 3);
+         s1 = algn (s1L, s1H, IREG (0) & 3);
+       }
+
+      i = !aop * 2;
+      tmp0 = ((((s1 >>  8) & 0xff) + ((s1 >>  0) & 0xff) +
+              ((s0 >>  8) & 0xff) + ((s0 >>  0) & 0xff) + i) >> 2) & 0xff;
+      tmp1 = ((((s1 >> 24) & 0xff) + ((s1 >> 16) & 0xff) +
+              ((s0 >> 24) & 0xff) + ((s0 >> 16) & 0xff) + i) >> 2) & 0xff;
+      SET_DREG (dst0, (tmp1 << (16 + (HL * 8))) | (tmp0 << (HL * 8)));
+    }
+  else if ((aop == 0 || aop == 1) && s == 0 && aopcde == 8)
+    {
+      TRACE_INSN (cpu, "A%i = 0;", aop);
+      SET_AREG (aop, 0);
+    }
+  else if (aop == 2 && s == 0 && aopcde == 8)
+    {
+      TRACE_INSN (cpu, "A1 = A0 = 0;");
+      SET_AREG (0, 0);
+      SET_AREG (1, 0);
+    }
+  else if ((aop == 0 || aop == 1 || aop == 2) && s == 1 && aopcde == 8)
+    {
+      bs40 acc0 = get_extended_acc (cpu, 0);
+      bs40 acc1 = get_extended_acc (cpu, 1);
+      bu32 sat;
+
+      if (aop == 0 || aop == 1)
+       TRACE_INSN (cpu, "A%i = A%i (S);", aop, aop);
+      else
+       TRACE_INSN (cpu, "A1 = A1 (S), A0 = A0 (S);");
+
+      if (aop == 0 || aop == 2)
+       {
+         sat = 0;
+         acc0 = saturate_s32 (acc0, &sat);
+         acc0 |= -(acc0 & 0x80000000ull);
+         SET_AXREG (0, (acc0 >> 31) & 0xFF);
+         SET_AWREG (0, acc0 & 0xFFFFFFFF);
+         SET_ASTATREG (av0, sat);
+         if (sat)
+           SET_ASTATREG (av0s, sat);
+       }
+      else
+       acc0 = 1;
+
+      if (aop == 1 || aop == 2)
+       {
+         sat = 0;
+         acc1 = saturate_s32 (acc1, &sat);
+         acc1 |= -(acc1 & 0x80000000ull);
+         SET_AXREG (1, (acc1 >> 31) & 0xFF);
+         SET_AWREG (1, acc1 & 0xFFFFFFFF);
+         SET_ASTATREG (av1, sat);
+         if (sat)
+           SET_ASTATREG (av1s, sat);
+       }
+      else
+       acc1 = 1;
+
+      SET_ASTATREG (az, (acc0 == 0) || (acc1 == 0));
+      SET_ASTATREG (an, ((acc0 >> 31) & 1) || ((acc1 >> 31) & 1));
+    }
+  else if (aop == 3 && (s == 0 || s == 1) && aopcde == 8)
+    {
+      TRACE_INSN (cpu, "A%i = A%i;", s, !s);
+      SET_AXREG (s, AXREG (!s));
+      SET_AWREG (s, AWREG (!s));
+    }
+  else if (aop == 3 && HL == 0 && aopcde == 16)
+    {
+      int i;
+      bu32 az;
+
+      TRACE_INSN (cpu, "A1 = ABS A1 , A0 = ABS A0;");
+
+      az = 0;
+      for (i = 0; i < 2; ++i)
+       {
+         bu32 av;
+         bs40 acc = get_extended_acc (cpu, i);
+
+         if (acc >> 39)
+           acc = -acc;
+         av = acc == ((bs40)1 << 39);
+         if (av)
+           acc = ((bs40)1 << 39) - 1;
+
+         SET_AREG (i, acc);
+         SET_ASTATREG (av[i], av);
+         if (av)
+           SET_ASTATREG (avs[i], av);
+         az |= (acc == 0);
+       }
+      SET_ASTATREG (az, az);
+      SET_ASTATREG (an, 0);
+    }
+  else if (aop == 0 && aopcde == 23)
+    {
+      bu32 s0, s0L, s0H, s1, s1L, s1H;
+      bs32 tmp0, tmp1;
+
+      TRACE_INSN (cpu, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0,
+                 src0 + 1, src0, src1 + 1, src1, HL ? "HI" : "LO",
+                 s ? ", R" : "");
+
+      if (src0 == src1)
+       illegal_instruction_combination (cpu);
+
+      s0L = DREG (src0);
+      s0H = DREG (src0 + 1);
+      s1L = DREG (src1);
+      s1H = DREG (src1 + 1);
+      if (s)
+       {
+         s0 = algn (s0H, s0L, IREG (0) & 3);
+         s1 = algn (s1H, s1L, IREG (1) & 3);
+       }
+      else
+       {
+         s0 = algn (s0L, s0H, IREG (0) & 3);
+         s1 = algn (s1L, s1H, IREG (1) & 3);
+       }
+
+      tmp0 = (bs32)(bs16)(s0 >>  0) + ((s1 >> ( 0 + (8 * !HL))) & 0xff);
+      tmp1 = (bs32)(bs16)(s0 >> 16) + ((s1 >> (16 + (8 * !HL))) & 0xff);
+      SET_DREG (dst0, (CLAMP (tmp0, 0, 255) << ( 0 + (8 * HL))) |
+                     (CLAMP (tmp1, 0, 255) << (16 + (8 * HL))));
+    }
+  else if ((aop == 0 || aop == 1) && aopcde == 16)
+    {
+      bu32 av;
+      bs40 acc;
+
+      TRACE_INSN (cpu, "A%i = ABS A%i;", HL, aop);
+
+      acc = get_extended_acc (cpu, aop);
+      if (acc >> 39)
+       acc = -acc;
+      av = acc == ((bs40)1 << 39);
+      if (av)
+       acc = ((bs40)1 << 39) - 1;
+      SET_AREG (HL, acc);
+
+      SET_ASTATREG (av[HL], av);
+      if (av)
+       SET_ASTATREG (avs[HL], av);
+      SET_ASTATREG (az, acc == 0);
+      SET_ASTATREG (an, 0);
+    }
+  else if (aop == 3 && aopcde == 12)
+    {
+      bs32 res = DREG (src0);
+      bs32 ovX;
+      bool sBit_a, sBit_b;
+
+      TRACE_INSN (cpu, "R%i.%s = R%i (RND);", dst0, HL == 0 ? "L" : "H", src0);
+      TRACE_DECODE (cpu, "R%i.%s = R%i:%#x (RND);", dst0,
+                   HL == 0 ? "L" : "H", src0, res);
+
+      sBit_b = !!(res & 0x80000000);
+
+      res += 0x8000;
+      sBit_a = !!(res & 0x80000000);
+
+      /* Overflow if the sign bit changed when we rounded.  */
+      if ((res >> 16) && (sBit_b != sBit_a))
+       {
+         ovX = 1;
+         if (!sBit_b)
+           res = 0x7FFF;
+         else
+           res = 0x8000;
+       }
+      else
+       {
+         res = res >> 16;
+         ovX = 0;
+       }
+
+      if (!HL)
+       SET_DREG (dst0, REG_H_L (DREG (dst0), res));
+      else
+       SET_DREG (dst0, REG_H_L (res << 16, DREG (dst0)));
+
+      SET_ASTATREG (az, res == 0);
+      SET_ASTATREG (an, res < 0);
+      SET_ASTATREG (v, ovX);
+      if (ovX)
+       SET_ASTATREG (vs, ovX);
+    }
+  else if (aop == 3 && HL == 0 && aopcde == 15)
+    {
+      bu32 hi = (-(bs16)(DREG (src0) >> 16)) << 16;
+      bu32 lo = (-(bs16)(DREG (src0) & 0xFFFF)) & 0xFFFF;
+      int v, ac0, ac1;
+
+      TRACE_INSN (cpu, "R%i = -R%i (V);", dst0, src0);
+
+      v = ac0 = ac1 = 0;
+
+      if (hi == 0x80000000)
+       {
+         hi = 0x7fff0000;
+         v = 1;
+       }
+      else if (hi == 0)
+       ac1 = 1;
+
+      if (lo == 0x8000)
+       {
+         lo = 0x7fff;
+         v = 1;
+       }
+      else if (lo == 0)
+       ac0 = 1;
+
+      SET_DREG (dst0, hi | lo);
+
+      SET_ASTATREG (v, v);
+      if (v)
+       SET_ASTATREG (vs, 1);
+      SET_ASTATREG (ac0, ac0);
+      SET_ASTATREG (ac1, ac1);
+      setflags_nz_2x16 (cpu, DREG (dst0));
+    }
+  else if (aop == 3 && HL == 0 && aopcde == 14)
+    {
+      TRACE_INSN (cpu, "A1 = - A1 , A0 = - A0;");
+
+      SET_AREG (0, saturate_s40 (-get_extended_acc (cpu, 0)));
+      SET_AREG (1, saturate_s40 (-get_extended_acc (cpu, 1)));
+      /* XXX: what ASTAT flags need updating ?  */
+    }
+  else if ((aop == 0 || aop == 1) && (HL == 0 || HL == 1) && aopcde == 14)
+    {
+      bs40 src_acc = get_extended_acc (cpu, aop);
+
+      TRACE_INSN (cpu, "A%i = - A%i;", HL, aop);
+
+      SET_AREG (HL, saturate_s40 (-src_acc));
+
+      SET_ASTATREG (az, AWREG (HL) == 0 && AXREG (HL) == 0);
+      SET_ASTATREG (an, AXREG (HL) >> 7);
+      SET_ASTATREG (ac0, src_acc == 0);
+      if (HL == 0)
+       {
+         SET_ASTATREG (av0, src_acc < 0);
+         if (ASTATREG (av0))
+           SET_ASTATREG (av0s, 1);
+       }
+      else
+       {
+         SET_ASTATREG (av1, src_acc < 0);
+         if (ASTATREG (av1))
+           SET_ASTATREG (av1s, 1);
+       }
+    }
+  else if (aop == 0 && aopcde == 12)
+    {
+      bs16 tmp0_hi = DREG (src0) >> 16;
+      bs16 tmp0_lo = DREG (src0);
+      bs16 tmp1_hi = DREG (src1) >> 16;
+      bs16 tmp1_lo = DREG (src1);
+
+      TRACE_INSN (cpu, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
+                 dst0, dst0, src0, src1, src0, src1);
+
+      if ((tmp0_hi >> 15) & 1)
+       tmp1_hi = ~tmp1_hi + 1;
+
+      if ((tmp0_lo >> 15) & 1)
+       tmp1_lo = ~tmp1_lo + 1;
+
+      tmp1_hi = tmp1_hi + tmp1_lo;
+
+      STORE (DREG (dst0), REG_H_L (tmp1_hi << 16, tmp1_hi));
+    }
+  else if (aopcde == 0)
+    {
+      bu32 s0 = DREG (src0);
+      bu32 s1 = DREG (src1);
+      bu32 s0h = s0 >> 16;
+      bu32 s0l = s0 & 0xFFFF;
+      bu32 s1h = s1 >> 16;
+      bu32 s1l = s1 & 0xFFFF;
+      bu32 t0, t1;
+      bu32 ac1_i = 0, ac0_i = 0, v_i = 0, z_i = 0, n_i = 0;
+
+      TRACE_INSN (cpu, "R%i = R%i %c|%c R%i%s;", dst0, src0,
+                 (aop & 2) ? '-' : '+', (aop & 1) ? '-' : '+', src1,
+                 amod0 (s, x));
+      if (aop & 2)
+       t0 = sub16 (cpu, s0h, s1h, &ac1_i, &v_i, &z_i, &n_i, s, 0);
+      else
+       t0 = add16 (cpu, s0h, s1h, &ac1_i, &v_i, &z_i, &n_i, s, 0);
+
+      if (aop & 1)
+       t1 = sub16 (cpu, s0l, s1l, &ac0_i, &v_i, &z_i, &n_i, s, 0);
+      else
+       t1 = add16 (cpu, s0l, s1l, &ac0_i, &v_i, &z_i, &n_i, s, 0);
+
+      SET_ASTATREG (ac1, ac1_i);
+      SET_ASTATREG (ac0, ac0_i);
+      SET_ASTATREG (az, z_i);
+      SET_ASTATREG (an, n_i);
+      SET_ASTATREG (v, v_i);
+      if (v_i)
+       SET_ASTATREG (vs, v_i);
+
+      t0 &= 0xFFFF;
+      t1 &= 0xFFFF;
+      if (x)
+       SET_DREG (dst0, (t1 << 16) | t0);
+      else
+       SET_DREG (dst0, (t0 << 16) | t1);
+    }
+  else if (aop == 1 && aopcde == 12)
+    {
+      bu32 val0 = ((AWREG (0) >> 16) + (AWREG (0) & 0xFFFF)) & 0xFFFF;
+      bu32 val1 = ((AWREG (1) >> 16) + (AWREG (1) & 0xFFFF)) & 0xFFFF;
+
+      TRACE_INSN (cpu, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1, dst0);
+
+      if (dst0 == dst1)
+       illegal_instruction_combination (cpu);
+
+      if (val0 & 0x8000)
+       val0 |= 0xFFFF0000;
+
+      if (val1 & 0x8000)
+       val1 |= 0xFFFF0000;
+
+      SET_DREG (dst0, val0);
+      SET_DREG (dst1, val1);
+      /* XXX: ASTAT ?  */
+    }
+  else if (aopcde == 1)
+    {
+      bu32 d0, d1;
+      bu32 x0, x1;
+      bu16 s0L = DREG (src0);
+      bu16 s0H = DREG (src0) >> 16;
+      bu16 s1L = DREG (src1);
+      bu16 s1H = DREG (src1) >> 16;
+      bu32 v_i = 0, n_i = 0, z_i = 0;
+
+      TRACE_INSN (cpu, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
+                 dst1, src0, HL ? "+|-" : "+|+", src1,
+                 dst0, src0, HL ? "-|+" : "-|-", src1,
+                 amod0amod2 (s, x, aop));
+
+      if (dst0 == dst1)
+       illegal_instruction_combination (cpu);
+
+      if (HL == 0)
+       {
+         x0 = add16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
+         x1 = add16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
+         d1 = (x0 << 16) | x1;
+
+         x0 = sub16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
+         x1 = sub16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
+         if (x == 0)
+           d0 = (x0 << 16) | x1;
+         else
+           d0 = (x1 << 16) | x0;
+       }
+      else
+       {
+         x0 = add16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
+         x1 = sub16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
+         d1 = (x0 << 16) | x1;
+
+         x0 = sub16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
+         x1 = add16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
+         if (x == 0)
+           d0 = (x0 << 16) | x1;
+         else
+           d0 = (x1 << 16) | x0;
+       }
+      SET_ASTATREG (az, z_i);
+      SET_ASTATREG (an, n_i);
+      SET_ASTATREG (v, v_i);
+      if (v_i)
+       SET_ASTATREG (vs, v_i);
+
+      STORE (DREG (dst0), d0);
+      STORE (DREG (dst1), d1);
+    }
+  else if ((aop == 0 || aop == 1 || aop == 2) && aopcde == 11)
+    {
+      bs40 acc0 = get_extended_acc (cpu, 0);
+      bs40 acc1 = get_extended_acc (cpu, 1);
+      bu32 v, dreg, sat = 0;
+      bu32 carry = !!((bu40)~acc1 < (bu40)acc0);
+
+      if (aop == 0)
+       TRACE_INSN (cpu, "R%i = (A0 += A1);", dst0);
+      else if (aop == 1)
+       TRACE_INSN (cpu, "R%i.%c = (A0 += A1);", dst0, HL ? 'H' : 'L');
+      else
+       TRACE_INSN (cpu, "A0 += A1%s;", s ? " (W32)" : "");
+
+      acc0 += acc1;
+      acc0 = saturate_s40_astat (acc0, &v);
+
+      if (aop == 2 && s == 1)   /* A0 += A1 (W32)  */
+       {
+         if (acc0 & (bs40)0x8000000000ll)
+           acc0 &= 0x80ffffffffll;
+         else
+           acc0 &= 0xffffffffll;
+       }
+
+      STORE (AXREG (0), acc0 >> 32);
+      STORE (AWREG (0), acc0);
+      SET_ASTATREG (av0, v && acc1);
+      if (v)
+       SET_ASTATREG (av0s, v);
+
+      if (aop == 0 || aop == 1)
+       {
+         if (aop)      /* Dregs_lo = A0 += A1  */
+           {
+             dreg = saturate_s32 (rnd16 (acc0) << 16, &sat);
+             if (HL)
+               STORE (DREG (dst0), REG_H_L (dreg, DREG (dst0)));
+             else
+               STORE (DREG (dst0), REG_H_L (DREG (dst0), dreg >> 16));
+           }
+         else          /* Dregs = A0 += A1  */
+           {
+             dreg = saturate_s32 (acc0, &sat);
+             STORE (DREG (dst0), dreg);
+           }
+
+         STORE (ASTATREG (az), dreg == 0);
+         STORE (ASTATREG (an), !!(dreg & 0x80000000));
+         STORE (ASTATREG (ac0), carry);
+         STORE (ASTATREG (ac0_copy), carry);
+         STORE (ASTATREG (v), sat);
+         STORE (ASTATREG (v_copy), sat);
+         if (sat)
+           STORE (ASTATREG (vs), sat);
+       }
+      else
+       {
+         STORE (ASTATREG (az), acc0 == 0);
+         STORE (ASTATREG (an), !!(acc0 & 0x8000000000ull));
+         STORE (ASTATREG (ac0), carry);
+         STORE (ASTATREG (ac0_copy), carry);
+       }
+    }
+  else if ((aop == 0 || aop == 1) && aopcde == 10)
+    {
+      TRACE_INSN (cpu, "R%i.L = A%i.X;", dst0, aop);
+      SET_DREG_L (dst0, (bs8)AXREG (aop));
+    }
+  else if (aop == 0 && aopcde == 4)
+    {
+      TRACE_INSN (cpu, "R%i = R%i + R%i%s;", dst0, src0, src1, amod1 (s, x));
+      SET_DREG (dst0, add32 (cpu, DREG (src0), DREG (src1), 1, s));
+    }
+  else if (aop == 1 && aopcde == 4)
+    {
+      TRACE_INSN (cpu, "R%i = R%i - R%i%s;", dst0, src0, src1, amod1 (s, x));
+      SET_DREG (dst0, sub32 (cpu, DREG (src0), DREG (src1), 1, s, 0));
+    }
+  else if (aop == 2 && aopcde == 4)
+    {
+      TRACE_INSN (cpu, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
+                 dst1, src0, src1, dst0, src0, src1, amod1 (s, x));
+
+      if (dst0 == dst1)
+       illegal_instruction_combination (cpu);
+
+      STORE (DREG (dst1), add32 (cpu, DREG (src0), DREG (src1), 1, s));
+      STORE (DREG (dst0), sub32 (cpu, DREG (src0), DREG (src1), 1, s, 1));
+    }
+  else if ((aop == 0 || aop == 1) && aopcde == 17)
+    {
+      bs40 acc0 = get_extended_acc (cpu, 0);
+      bs40 acc1 = get_extended_acc (cpu, 1);
+      bs40 val0, val1, sval0, sval1;
+      bu32 sat, sat_i;
+
+      TRACE_INSN (cpu, "R%i = A%i + A%i, R%i = A%i - A%i%s",
+                 dst1, !aop, aop, dst0, !aop, aop, amod1 (s, x));
+      TRACE_DECODE (cpu, "R%i = A%i:%#"PRIx64" + A%i:%#"PRIx64", "
+                        "R%i = A%i:%#"PRIx64" - A%i:%#"PRIx64"%s",
+                   dst1, !aop, aop ? acc0 : acc1, aop, aop ? acc1 : acc0,
+                   dst0, !aop, aop ? acc0 : acc1, aop, aop ? acc1 : acc0,
+                   amod1 (s, x));
+
+      if (dst0 == dst1)
+       illegal_instruction_combination (cpu);
+
+      val1 = acc0 + acc1;
+      if (aop)
+       val0 = acc0 - acc1;
+      else
+       val0 = acc1 - acc0;
+
+      sval0 = saturate_s32 (val0, &sat);
+      sat_i = sat;
+      sval1 = saturate_s32 (val1, &sat);
+      sat_i |= sat;
+      if (s)
+       {
+         val0 = sval0;
+         val1 = sval1;
+       }
+
+      STORE (DREG (dst0), val0);
+      STORE (DREG (dst1), val1);
+      SET_ASTATREG (v, sat_i);
+      if (sat_i)
+       SET_ASTATREG (vs, sat_i);
+      SET_ASTATREG (an, val0 & 0x80000000 || val1 & 0x80000000);
+      SET_ASTATREG (az, val0 == 0 || val1 == 0);
+      SET_ASTATREG (ac1, (bu40)~acc0 < (bu40)acc1);
+      if (aop)
+       SET_ASTATREG (ac0, !!((bu40)acc1 <= (bu40)acc0));
+      else
+       SET_ASTATREG (ac0, !!((bu40)acc0 <= (bu40)acc1));
+    }
+  else if (aop == 0 && aopcde == 18)
+    {
+      bu40 acc0 = get_extended_acc (cpu, 0);
+      bu40 acc1 = get_extended_acc (cpu, 1);
+      bu32 s0L = DREG (src0);
+      bu32 s0H = DREG (src0 + 1);
+      bu32 s1L = DREG (src1);
+      bu32 s1H = DREG (src1 + 1);
+      bu32 s0, s1;
+      bs16 tmp0, tmp1, tmp2, tmp3;
+
+      /* This instruction is only defined for register pairs R1:0 and R3:2.  */
+      if (!((src0 == 0 || src0 == 2) && (src1 == 0 || src1 == 2)))
+       illegal_instruction (cpu);
+
+      TRACE_INSN (cpu, "SAA (R%i:%i, R%i:%i)%s", src0 + 1, src0,
+                 src1 + 1, src1, s ? " (R)" :"");
+
+      /* Bit s determines the order of the two registers from a pair:
+         if s=0 the low-order bytes come from the low reg in the pair,
+         and if s=1 the low-order bytes come from the high reg.  */
+
+      if (s)
+       {
+         s0 = algn (s0H, s0L, IREG (0) & 3);
+         s1 = algn (s1H, s1L, IREG (1) & 3);
+       }
+      else
+       {
+         s0 = algn (s0L, s0H, IREG (0) & 3);
+         s1 = algn (s1L, s1H, IREG (1) & 3);
+       }
+
+      /* Find the absolute difference between pairs, make it
+         absolute, then add it to the existing accumulator half.  */
+      /* Byte 0  */
+      tmp0  = ((s0 << 24) >> 24) - ((s1 << 24) >> 24);
+      tmp1  = ((s0 << 16) >> 24) - ((s1 << 16) >> 24);
+      tmp2  = ((s0 <<  8) >> 24) - ((s1 <<  8) >> 24);
+      tmp3  = ((s0 <<  0) >> 24) - ((s1 <<  0) >> 24);
+
+      tmp0  = (tmp0 < 0) ? -tmp0 : tmp0;
+      tmp1  = (tmp1 < 0) ? -tmp1 : tmp1;
+      tmp2  = (tmp2 < 0) ? -tmp2 : tmp2;
+      tmp3  = (tmp3 < 0) ? -tmp3 : tmp3;
+
+      s0L = saturate_u16 ((bu32)tmp0 + ((acc0 >>  0) & 0xffff), 0);
+      s0H = saturate_u16 ((bu32)tmp1 + ((acc0 >> 16) & 0xffff), 0);
+      s1L = saturate_u16 ((bu32)tmp2 + ((acc1 >>  0) & 0xffff), 0);
+      s1H = saturate_u16 ((bu32)tmp3 + ((acc1 >> 16) & 0xffff), 0);
+
+      STORE (AWREG (0), (s0H << 16) | (s0L & 0xFFFF));
+      STORE (AXREG (0), 0);
+      STORE (AWREG (1), (s1H << 16) | (s1L & 0xFFFF));
+      STORE (AXREG (1), 0);
+    }
+  else if (aop == 3 && aopcde == 18)
+    {
+      TRACE_INSN (cpu, "DISALGNEXCPT");
+      DIS_ALGN_EXPT |= 1;
+    }
+  else if ((aop == 0 || aop == 1) && aopcde == 20)
+    {
+      bu32 s0, s0L, s0H, s1, s1L, s1H;
+      const char * const opts[] = { "", " (R)", " (T)", " (T, R)" };
+
+      TRACE_INSN (cpu, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0,
+                 src0 + 1, src0, src1 + 1, src1, opts[s + (aop << 1)]);
+
+      if (src0 == src1)
+       illegal_instruction_combination (cpu);
+
+      s0L = DREG (src0);
+      s0H = DREG (src0 + 1);
+      s1L = DREG (src1);
+      s1H = DREG (src1 + 1);
+      if (s)
+       {
+         s0 = algn (s0H, s0L, IREG (0) & 3);
+         s1 = algn (s1H, s1L, IREG (1) & 3);
+       }
+      else
+       {
+         s0 = algn (s0L, s0H, IREG (0) & 3);
+         s1 = algn (s1L, s1H, IREG (1) & 3);
+       }
+
+      SET_DREG (dst0,
+               (((((s0 >>  0) & 0xff) + ((s1 >>  0) & 0xff) + !aop) >> 1) <<  0) |
+               (((((s0 >>  8) & 0xff) + ((s1 >>  8) & 0xff) + !aop) >> 1) <<  8) |
+               (((((s0 >> 16) & 0xff) + ((s1 >> 16) & 0xff) + !aop) >> 1) << 16) |
+               (((((s0 >> 24) & 0xff) + ((s1 >> 24) & 0xff) + !aop) >> 1) << 24));
+    }
+  else if (aop == 0 && aopcde == 21)
+    {
+      bu32 s0, s0L, s0H, s1, s1L, s1H;
+
+      TRACE_INSN (cpu, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1, dst0,
+                 src0 + 1, src0, src1 + 1, src1, s ? " (R)" : "");
+
+      if (dst0 == dst1)
+       illegal_instruction_combination (cpu);
+
+      s0L = DREG (src0);
+      s0H = DREG (src0 + 1);
+      s1L = DREG (src1);
+      s1H = DREG (src1 + 1);
+      if (s)
+       {
+         s0 = algn (s0H, s0L, IREG (0) & 3);
+         s1 = algn (s1H, s1L, IREG (1) & 3);
+       }
+      else
+       {
+         s0 = algn (s0L, s0H, IREG (0) & 3);
+         s1 = algn (s1L, s1H, IREG (1) & 3);
+       }
+
+      SET_DREG (dst0,
+               ((((s0 >>  0) & 0xff) + ((s1 >>  0) & 0xff)) <<  0) |
+               ((((s0 >>  8) & 0xff) + ((s1 >>  8) & 0xff)) << 16));
+      SET_DREG (dst1,
+               ((((s0 >> 16) & 0xff) + ((s1 >> 16) & 0xff)) <<  0) |
+               ((((s0 >> 24) & 0xff) + ((s1 >> 24) & 0xff)) << 16));
+    }
+  else if (aop == 1 && aopcde == 21)
+    {
+      bu32 s0, s0L, s0H, s1, s1L, s1H;
+
+      TRACE_INSN (cpu, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1, dst0,
+                 src0 + 1, src0, src1 + 1, src1, s ? " (R)" : "");
+
+      if (dst0 == dst1)
+       illegal_instruction_combination (cpu);
+
+      s0L = DREG (src0);
+      s0H = DREG (src0 + 1);
+      s1L = DREG (src1);
+      s1H = DREG (src1 + 1);
+      if (s)
+       {
+         s0 = algn (s0H, s0L, IREG (0) & 3);
+         s1 = algn (s1H, s1L, IREG (1) & 3);
+       }
+      else
+       {
+         s0 = algn (s0L, s0H, IREG (0) & 3);
+         s1 = algn (s1L, s1H, IREG (1) & 3);
+       }
+
+      SET_DREG (dst0,
+               (((((s0 >>  0) & 0xff) - ((s1 >>  0) & 0xff)) <<  0) & 0xffff) |
+               (((((s0 >>  8) & 0xff) - ((s1 >>  8) & 0xff)) << 16)));
+      SET_DREG (dst1,
+               (((((s0 >> 16) & 0xff) - ((s1 >> 16) & 0xff)) <<  0) & 0xffff) |
+               (((((s0 >> 24) & 0xff) - ((s1 >> 24) & 0xff)) << 16)));
+    }
+  else if (aop == 1 && aopcde == 7)
+    {
+      TRACE_INSN (cpu, "R%i = MIN (R%i, R%i);", dst0, src0, src1);
+      SET_DREG (dst0, min32 (cpu, DREG (src0), DREG (src1)));
+    }
+  else if (aop == 0 && aopcde == 7)
+    {
+      TRACE_INSN (cpu, "R%i = MAX (R%i, R%i);", dst0, src0, src1);
+      SET_DREG (dst0, max32 (cpu, DREG (src0), DREG (src1)));
+    }
+  else if (aop == 2 && aopcde == 7)
+    {
+      bu32 val = DREG (src0);
+      int v;
+
+      TRACE_INSN (cpu, "R%i = ABS R%i;", dst0, src0);
+
+      if (val >> 31)
+       val = -val;
+      v = (val == 0x80000000);
+      if (v)
+       val = 0x7fffffff;
+      SET_DREG (dst0, val);
+
+      SET_ASTATREG (v, v);
+      if (v)
+       SET_ASTATREG (vs, 1);
+      setflags_nz (cpu, val);
+    }
+  else if (aop == 3 && aopcde == 7)
+    {
+      bu32 val = DREG (src0);
+
+      TRACE_INSN (cpu, "R%i = - R%i %s;", dst0, src0, amod1 (s, 0));
+
+      if (s && val == 0x80000000)
+       {
+         val = 0x7fffffff;
+         SET_ASTATREG (v, 1);
+         SET_ASTATREG (vs, 1);
+       }
+      else if (val == 0x80000000)
+       val = 0x80000000;
+      else
+       val = -val;
+      SET_DREG (dst0, val);
+
+      SET_ASTATREG (az, val == 0);
+      SET_ASTATREG (an, val & 0x80000000);
+    }
+  else if (aop == 2 && aopcde == 6)
+    {
+      bu32 in = DREG (src0);
+      bu32 hi = (in & 0x80000000 ? (bu32)-(bs16)(in >> 16) : in >> 16) << 16;
+      bu32 lo = (in & 0x8000 ? (bu32)-(bs16)(in & 0xFFFF) : in) & 0xFFFF;
+      int v;
+
+      TRACE_INSN (cpu, "R%i = ABS R%i (V);", dst0, src0);
+
+      v = 0;
+      if (hi == 0x80000000)
+       {
+         hi = 0x7fff0000;
+         v = 1;
+       }
+      if (lo == 0x8000)
+       {
+         lo = 0x7fff;
+         v = 1;
+       }
+      SET_DREG (dst0, hi | lo);
+
+      SET_ASTATREG (v, v);
+      if (v)
+       SET_ASTATREG (vs, 1);
+      setflags_nz_2x16 (cpu, DREG (dst0));
+    }
+  else if (aop == 1 && aopcde == 6)
+    {
+      TRACE_INSN (cpu, "R%i = MIN (R%i, R%i) (V);", dst0, src0, src1);
+      SET_DREG (dst0, min2x16 (cpu, DREG (src0), DREG (src1)));
+    }
+  else if (aop == 0 && aopcde == 6)
+    {
+      TRACE_INSN (cpu, "R%i = MAX (R%i, R%i) (V);", dst0, src0, src1);
+      SET_DREG (dst0, max2x16 (cpu, DREG (src0), DREG (src1)));
+    }
+  else if (aop == 0 && aopcde == 24)
+    {
+      TRACE_INSN (cpu, "R%i = BYTEPACK (R%i, R%i);", dst0, src0, src1);
+      SET_DREG (dst0,
+       (((DREG (src0) >>  0) & 0xff) <<  0) |
+       (((DREG (src0) >> 16) & 0xff) <<  8) |
+       (((DREG (src1) >>  0) & 0xff) << 16) |
+       (((DREG (src1) >> 16) & 0xff) << 24));
+    }
+  else if (aop == 1 && aopcde == 24)
+    {
+      int order, lo, hi;
+      bu64 comb_src;
+      bu8 bytea, byteb, bytec, byted;
+
+      TRACE_INSN (cpu, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
+                 dst1, dst0, src0 + 1, src0, s ? " (R)" : "");
+
+      if (dst0 == dst1)
+       illegal_instruction_combination (cpu);
+
+      order = IREG (0) & 0x3;
+      if (s)
+       hi = src0, lo = src0 + 1;
+      else
+       hi = src0 + 1, lo = src0;
+      comb_src = (((bu64)DREG (hi)) << 32) | DREG (lo);
+      bytea = (comb_src >> (0 + 8 * order));
+      byteb = (comb_src >> (8 + 8 * order));
+      bytec = (comb_src >> (16 + 8 * order));
+      byted = (comb_src >> (24 + 8 * order));
+      SET_DREG (dst0, bytea | ((bu32)byteb << 16));
+      SET_DREG (dst1, bytec | ((bu32)byted << 16));
+    }
+  else if (aopcde == 13)
+    {
+      const char *searchmodes[] = { "GT", "GE", "LT", "LE" };
+      bool up_hi, up_lo;
+      bs16 a0_lo, a1_lo, src_hi, src_lo;
+
+      TRACE_INSN (cpu, "(R%i, R%i) = SEARCH R%i (%s);",
+                 dst1, dst0, src0, searchmodes[aop]);
+
+      if (dst0 == dst1)
+       illegal_instruction_combination (cpu);
+
+      up_hi = up_lo = false;
+      a0_lo = AWREG (0);
+      a1_lo = AWREG (1);
+      src_lo = DREG (src0);
+      src_hi = DREG (src0) >> 16;
+
+      switch (aop)
+       {
+       case 0:
+         up_hi = (src_hi > a1_lo);
+         up_lo = (src_lo > a0_lo);
+         break;
+       case 1:
+         up_hi = (src_hi >= a1_lo);
+         up_lo = (src_lo >= a0_lo);
+         break;
+       case 2:
+         up_hi = (src_hi < a1_lo);
+         up_lo = (src_lo < a0_lo);
+         break;
+       case 3:
+         up_hi = (src_hi <= a1_lo);
+         up_lo = (src_lo <= a0_lo);
+         break;
+       }
+
+      if (up_hi)
+       {
+         SET_AREG (1, src_hi);
+         SET_DREG (dst1, PREG (0));
+       }
+      if (up_lo)
+       {
+         SET_AREG (0, src_lo);
+         SET_DREG (dst0, PREG (0));
+       }
+    }
+  else
+    illegal_instruction (cpu);
+}
+
+static void
+decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
+{
+  /* dsp32shift
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
+     |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int HLs  = ((iw1 >> DSP32Shift_HLs_bits) & DSP32Shift_HLs_mask);
+  int sop  = ((iw1 >> DSP32Shift_sop_bits) & DSP32Shift_sop_mask);
+  int src0 = ((iw1 >> DSP32Shift_src0_bits) & DSP32Shift_src0_mask);
+  int src1 = ((iw1 >> DSP32Shift_src1_bits) & DSP32Shift_src1_mask);
+  int dst0 = ((iw1 >> DSP32Shift_dst0_bits) & DSP32Shift_dst0_mask);
+  int sopcde = ((iw0 >> (DSP32Shift_sopcde_bits - 16)) & DSP32Shift_sopcde_mask);
+  int M = ((iw0 >> (DSP32Shift_M_bits - 16)) & DSP32Shift_M_mask);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32shift);
+  TRACE_EXTRACT (cpu, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
+                __func__, M, sopcde, sop, HLs, dst0, src0, src1);
+
+  if ((sop == 0 || sop == 1) && sopcde == 0)
+    {
+      bu16 val;
+      bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
+
+      TRACE_INSN (cpu, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
+                 dst0, HLs < 2 ? 'L' : 'H',
+                 src1, HLs & 1 ? 'H' : 'L',
+                 src0, sop == 1 ? " (S)" : "");
+
+      if ((HLs & 1) == 0)
+       val = (bu16)(DREG (src1) & 0xFFFF);
+      else
+       val = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
+
+      /* Positive shift magnitudes produce Logical Left shifts.
+         Negative shift magnitudes produce Arithmetic Right shifts.  */
+      if (shft <= 0)
+       val = ashiftrt (cpu, val, -shft, 16);
+      else
+       val = lshift (cpu, val, shft, 16, sop == 1);
+
+      if ((HLs & 2) == 0)
+       STORE (DREG (dst0), REG_H_L (DREG (dst0), val));
+      else
+       STORE (DREG (dst0), REG_H_L (val << 16, DREG (dst0)));
+    }
+  else if (sop == 2 && sopcde == 0)
+    {
+      bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
+      bu16 val;
+
+      TRACE_INSN (cpu, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
+                 dst0, HLs < 2 ? 'L' : 'H',
+                 src1, HLs & 1 ? 'H' : 'L', src0);
+
+      if ((HLs & 1) == 0)
+       val = (bu16)(DREG (src1) & 0xFFFF);
+      else
+       val = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
+
+      if (shft < 0)
+       val = val >> (-1 * shft);
+      else
+       val = val << shft;
+
+      if ((HLs & 2) == 0)
+       SET_DREG (dst0, REG_H_L (DREG (dst0), val));
+      else
+       SET_DREG (dst0, REG_H_L (val << 16, DREG (dst0)));
+
+      SET_ASTATREG (az, !((val & 0xFFFF0000) == 0) || ((val & 0xFFFF) == 0));
+      SET_ASTATREG (an, (!!(val & 0x80000000)) ^ (!!(val & 0x8000)));
+      SET_ASTATREG (v, 0);
+    }
+  else if (sop == 2 && sopcde == 3 && (HLs == 1 || HLs == 0))
+    {
+      int shift = imm6 (DREG (src0) & 0xFFFF);
+      bu32 cc = CCREG;
+      bu40 acc = get_unextended_acc (cpu, HLs);
+
+      TRACE_INSN (cpu, "A%i = ROT A%i BY R%i.L;", HLs, HLs, src0);
+      TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i CC:%i", HLs, acc, shift, cc);
+
+      acc = rot40 (acc, shift, &cc);
+      SET_AREG (HLs, acc);
+      if (shift)
+       SET_CCREG (cc);
+    }
+  else if (sop == 0 && sopcde == 3 && (HLs == 0 || HLs == 1))
+    {
+      bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
+      bu64 val = get_extended_acc (cpu, HLs);
+
+      HLs = !!HLs;
+      TRACE_INSN (cpu, "A%i = ASHIFT A%i BY R%i.L;", HLs, HLs, src0);
+      TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i", HLs, val, shft);
+
+      if (shft <= 0)
+       val = ashiftrt (cpu, val, -shft, 40);
+      else
+       val = lshift (cpu, val, shft, 40, 0);
+
+      STORE (AXREG (HLs), (val >> 32) & 0xff);
+      STORE (AWREG (HLs), (val & 0xffffffff));
+    }
+  else if (sop == 1 && sopcde == 3 && (HLs == 0 || HLs == 1))
+    {
+      bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
+      bu64 val;
+
+      HLs = !!HLs;
+      TRACE_INSN (cpu, "A%i = LSHIFT A%i BY R%i.L;", HLs, HLs, src0);
+      val = get_extended_acc (cpu, HLs);
+
+      if (shft <= 0)
+       val = lshiftrt (cpu, val, -shft, 40);
+      else
+       val = lshift (cpu, val, shft, 40, 0);
+
+      STORE (AXREG (HLs), (val >> 32) & 0xff);
+      STORE (AWREG (HLs), (val & 0xffffffff));
+    }
+  else if ((sop == 0 || sop == 1) && sopcde == 1)
+    {
+      bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
+      bu16 val0, val1;
+      bu32 astat;
+
+      TRACE_INSN (cpu, "R%i = ASHIFT R%i BY R%i.L (V%s);",
+                 dst0, src1, src0, sop == 1 ? ",S" : "");
+
+      val0 = (bu16)DREG (src1) & 0xFFFF;
+      val1 = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
+
+      if (shft <= 0)
+       {
+         val0 = ashiftrt (cpu, val0, -shft, 16);
+         astat = ASTAT;
+         val1 = ashiftrt (cpu, val1, -shft, 16);
+       }
+      else
+       {
+         val0 = lshift (cpu, val0, shft, 16, sop == 1);
+         astat = ASTAT;
+         val1 = lshift (cpu, val1, shft, 16, sop == 1);
+       }
+      SET_ASTAT (ASTAT | astat);
+      STORE (DREG (dst0), (val1 << 16) | val0);
+    }
+  else if ((sop == 0 || sop == 1 || sop == 2) && sopcde == 2)
+    {
+      /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S)  */
+      /* sop == 1 : opt_S  */
+      bu32 v = DREG (src1);
+      /* LSHIFT uses sign extended low 6 bits of dregs_lo.  */
+      bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
+
+      TRACE_INSN (cpu, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0,
+                 shft && sop != 2 ? 'A' : 'L', src1, src0,
+                 sop == 1 ? " (S)" : "");
+
+      if (shft < 0)
+       {
+         if (sop == 2)
+           STORE (DREG (dst0), lshiftrt (cpu, v, -shft, 32));
+         else
+           STORE (DREG (dst0), ashiftrt (cpu, v, -shft, 32));
+       }
+      else
+       STORE (DREG (dst0), lshift (cpu, v, shft, 32, sop == 1));
+    }
+  else if (sop == 3 && sopcde == 2)
+    {
+      int shift = imm6 (DREG (src0) & 0xFFFF);
+      bu32 src = DREG (src1);
+      bu32 ret, cc = CCREG;
+
+      TRACE_INSN (cpu, "R%i = ROT R%i BY R%i.L;", dst0, src1, src0);
+      TRACE_DECODE (cpu, "R%i:%#x R%i:%#x shift:%i CC:%i",
+                   dst0, DREG (dst0), src1, src, shift, cc);
+
+      ret = rot32 (src, shift, &cc);
+      STORE (DREG (dst0), ret);
+      if (shift)
+       SET_CCREG (cc);
+    }
+  else if (sop == 2 && sopcde == 1)
+    {
+      bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
+      bu16 val0, val1;
+      bu32 astat;
+
+      TRACE_INSN (cpu, "R%i = LSHIFT R%i BY R%i.L (V);", dst0, src1, src0);
+
+      val0 = (bu16)DREG (src1) & 0xFFFF;
+      val1 = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
+
+      if (shft <= 0)
+       {
+         val0 = lshiftrt (cpu, val0, -shft, 16);
+         astat = ASTAT;
+         val1 = lshiftrt (cpu, val1, -shft, 16);
+       }
+      else
+       {
+         val0 = lshift (cpu, val0, shft, 16, 0);
+         astat = ASTAT;
+         val1 = lshift (cpu, val1, shft, 16, 0);
+       }
+      SET_ASTAT (ASTAT | astat);
+      STORE (DREG (dst0), (val1 << 16) | val0);
+    }
+  else if (sopcde == 4)
+    {
+      bu32 sv0 = DREG (src0);
+      bu32 sv1 = DREG (src1);
+      TRACE_INSN (cpu, "R%i = PACK (R%i.%c, R%i.%c);", dst0,
+                 src1, sop & 2 ? 'H' : 'L',
+                 src0, sop & 1 ? 'H' : 'L');
+      if (sop & 1)
+       sv0 >>= 16;
+      if (sop & 2)
+       sv1 >>= 16;
+      SET_DREG (dst0, (sv1 << 16) | (sv0 & 0xFFFF));
+    }
+  else if (sop == 0 && sopcde == 5)
+    {
+      bu32 sv1 = DREG (src1);
+      TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i;", dst0, src1);
+      SET_DREG_L (dst0, signbits (sv1, 32));
+    }
+  else if (sop == 1 && sopcde == 5)
+    {
+      bu32 sv1 = DREG (src1);
+      TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i.L;", dst0, src1);
+      SET_DREG_L (dst0, signbits (sv1, 16));
+    }
+  else if (sop == 2 && sopcde == 5)
+    {
+      bu32 sv1 = DREG (src1);
+      TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i.H;", dst0, src1);
+      SET_DREG_L (dst0, signbits (sv1 >> 16, 16));
+    }
+  else if ((sop == 0 || sop == 1) && sopcde == 6)
+    {
+      bu64 acc = AXREG (sop);
+      TRACE_INSN (cpu, "R%i.L = SIGNBITS A%i;", dst0, sop);
+      acc <<= 32;
+      acc |= AWREG (sop);
+      SET_DREG_L (dst0, signbits (acc, 40) & 0xFFFF);
+    }
+  else if (sop == 3 && sopcde == 6)
+    {
+      bu32 v = ones (DREG (src1));
+      TRACE_INSN (cpu, "R%i.L = ONES R%i;", dst0, src1);
+      SET_DREG_L (dst0, v);
+    }
+  else if (sop == 0 && sopcde == 7)
+    {
+      bu16 sv1 = (bu16)signbits (DREG (src1), 32);
+      bu16 sv0 = (bu16)DREG (src0);
+      bu16 dst_lo;
+
+      TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i, R%i.L);", dst0, src1, src0);
+
+      if ((sv1 & 0x1f) < (sv0 & 0x1f))
+       dst_lo = sv1;
+      else
+       dst_lo = sv0;
+      STORE (DREG (dst0), REG_H_L (DREG (dst0), dst_lo));
+    }
+  else if (sop == 1 && sopcde == 7)
+    {
+      /* Exponent adjust on two 16-bit inputs.  Select
+         smallest norm among 3 inputs.  */
+      bs16 src1_hi = (DREG (src1) & 0xFFFF0000) >> 16;
+      bs16 src1_lo = (DREG (src1) & 0xFFFF);
+      bu16 src0_lo = (DREG (src0) & 0xFFFF);
+      bu16 tmp_hi, tmp_lo, tmp;
+
+      TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0, src1, src0);
+
+      tmp_hi = signbits (src1_hi, 16);
+      tmp_lo = signbits (src1_lo, 16);
+
+      if ((tmp_hi & 0xf) < (tmp_lo & 0xf))
+       if ((tmp_hi & 0xf) < (src0_lo & 0xf))
+         tmp = tmp_hi;
+       else
+         tmp = src0_lo;
+      else
+       if ((tmp_lo & 0xf) < (src0_lo & 0xf))
+         tmp = tmp_lo;
+       else
+         tmp = src0_lo;
+      STORE (DREG (dst0), REG_H_L (DREG (dst0), tmp));
+    }
+  else if (sop == 2 && sopcde == 7)
+    {
+      /* Exponent adjust on single 16-bit register.  */
+      bu16 tmp;
+      bu16 src0_lo = (bu16)(DREG (src0) & 0xFFFF);
+
+      TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0, src1, src0);
+
+      tmp = signbits (DREG (src1) & 0xFFFF, 16);
+
+      if ((tmp & 0xf) < (src0_lo & 0xf))
+       SET_DREG_L (dst0, tmp);
+      else
+       SET_DREG_L (dst0, src0_lo);
+    }
+  else if (sop == 3 && sopcde == 7)
+    {
+      bu16 tmp;
+      bu16 src0_lo = (bu16)(DREG (src0) & 0xFFFF);
+
+      TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0, src1, src0);
+
+      tmp = signbits ((DREG (src1) & 0xFFFF0000) >> 16, 16);
+
+      if ((tmp & 0xf) < (src0_lo & 0xf))
+       SET_DREG_L (dst0, tmp);
+      else
+       SET_DREG_L (dst0, src0_lo);
+    }
+  else if (sop == 0 && sopcde == 8)
+    {
+      bu64 acc = get_unextended_acc (cpu, 0);
+      bu32 s0, s1;
+
+      TRACE_INSN (cpu, "BITMUX (R%i, R%i, A0) (ASR);", src0, src1);
+
+      if (src0 == src1)
+       illegal_instruction_combination (cpu);
+
+      s0 = DREG (src0);
+      s1 = DREG (src1);
+      acc = (acc >> 2) |
+       (((bu64)s0 & 1) << 38) |
+       (((bu64)s1 & 1) << 39);
+      SET_DREG (src0, s0 >> 1);
+      SET_DREG (src1, s1 >> 1);
+
+      SET_AREG (0, acc);
+    }
+  else if (sop == 1 && sopcde == 8)
+    {
+      bu64 acc = get_unextended_acc (cpu, 0);
+      bu32 s0, s1;
+
+      TRACE_INSN (cpu, "BITMUX (R%i, R%i, A0) (ASL);", src0, src1);
+
+      if (src0 == src1)
+       illegal_instruction_combination (cpu);
+
+      s0 = DREG (src0);
+      s1 = DREG (src1);
+      acc = (acc << 2) |
+       ((s0 >> 31) & 1) |
+       ((s1 >> 30) & 2);
+      SET_DREG (src0, s0 << 1);
+      SET_DREG (src1, s1 << 1);
+
+      SET_AREG (0, acc);
+    }
+  else if ((sop == 0 || sop == 1) && sopcde == 9)
+    {
+      bs40 acc0 = get_extended_acc (cpu, 0);
+      bs16 sL, sH, out;
+
+      TRACE_INSN (cpu, "R%i.L = VIT_MAX (R%i) (AS%c);",
+                 dst0, src1, sop & 1 ? 'R' : 'L');
+
+      sL = DREG (src1);
+      sH = DREG (src1) >> 16;
+
+      if (sop & 1)
+       acc0 >>= 1;
+      else
+       acc0 <<= 1;
+
+      if (((sH - sL) & 0x8000) == 0)
+       {
+         out = sH;
+         acc0 |= (sop & 1) ? 0x80000000 : 1;
+       }
+      else
+       out = sL;
+
+      SET_AREG (0, acc0);
+      SET_DREG (dst0, REG_H_L (DREG (dst0), out));
+    }
+  else if ((sop == 2 || sop == 3) && sopcde == 9)
+    {
+      bs40 acc0 = get_extended_acc (cpu, 0);
+      bs16 s0L, s0H, s1L, s1H, out0, out1;
+
+      TRACE_INSN (cpu, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
+                 dst0, src1, src0, sop & 1 ? 'R' : 'L');
+
+      s0L = DREG (src0);
+      s0H = DREG (src0) >> 16;
+      s1L = DREG (src1);
+      s1H = DREG (src1) >> 16;
+
+      if (sop & 1)
+       acc0 >>= 2;
+      else
+       acc0 <<= 2;
+
+      if (((s0H - s0L) & 0x8000) == 0)
+       {
+         out0 = s0H;
+         acc0 |= (sop & 1) ? 0x40000000 : 2;
+       }
+      else
+       out0 = s0L;
+
+      if (((s1H - s1L) & 0x8000) == 0)
+       {
+         out1 = s1H;
+         acc0 |= (sop & 1) ? 0x80000000 : 1;
+       }
+      else
+       out1 = s1L;
+
+      SET_AREG (0, acc0);
+      SET_DREG (dst0, REG_H_L (out1 << 16, out0));
+    }
+  else if (sop == 0 && sopcde == 10)
+    {
+      bu32 v = DREG (src0);
+      bu32 x = DREG (src1);
+      bu32 mask = (1 << (v & 0x1f)) - 1;
+      TRACE_INSN (cpu, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0, src1, src0);
+      x >>= ((v >> 8) & 0x1f);
+      SET_DREG (dst0, x & mask);
+      setflags_logical (cpu, DREG (dst0));
+    }
+  else if (sop == 1 && sopcde == 10)
+    {
+      bu32 v = DREG (src0);
+      bu32 x = DREG (src1);
+      bu32 sgn = (1 << (v & 0x1f)) >> 1;
+      bu32 mask = (1 << (v & 0x1f)) - 1;
+      TRACE_INSN (cpu, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0, src1, src0);
+      x >>= ((v >> 8) & 0x1f);
+      x &= mask;
+      if (x & sgn)
+       x |= ~mask;
+      SET_DREG (dst0, x);
+      setflags_logical (cpu, DREG (dst0));
+    }
+  else if ((sop == 2 || sop == 3) && sopcde == 10)
+    {
+      /* The first dregs is the "background" while the second dregs is the
+         "foreground".  The fg reg is used to overlay the bg reg and is:
+         | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
+           n = the fg bit field
+           p = bit position in bg reg to start LSB of fg field
+           L = number of fg bits to extract
+         Using (X) sign-extends the fg bit field.  */
+      bu32 fg = DREG (src0);
+      bu32 bg = DREG (src1);
+      bu32 len = fg & 0x1f;
+      bu32 mask = (1 << MIN (16, len)) - 1;
+      bu32 fgnd = (fg >> 16) & mask;
+      int shft = ((fg >> 8) & 0x1f);
+
+      TRACE_INSN (cpu, "R%i = DEPOSIT (R%i, R%i)%s;", dst0, src1, src0,
+                 sop == 3 ? " (X)" : "");
+
+      if (sop == 3)
+       {
+         /* Sign extend the fg bit field.  */
+         mask = -1;
+         fgnd = ((bs32)(bs16)(fgnd << (16 - len))) >> (16 - len);
+       }
+      fgnd <<= shft;
+      mask <<= shft;
+      bg &= ~mask;
+
+      SET_DREG (dst0, bg | fgnd);
+      setflags_logical (cpu, DREG (dst0));
+    }
+  else if (sop == 0 && sopcde == 11)
+    {
+      bu64 acc0 = get_unextended_acc (cpu, 0);
+
+      TRACE_INSN (cpu, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0, src0);
+
+      acc0 <<= 1;
+      SET_CCREG (xor_reduce (acc0, DREG (src0)));
+      SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
+      SET_AREG (0, acc0);
+    }
+  else if (sop == 1 && sopcde == 11)
+    {
+      bu64 acc0 = get_unextended_acc (cpu, 0);
+
+      TRACE_INSN (cpu, "R%i.L = CC = BXOR (A0, R%i);", dst0, src0);
+
+      SET_CCREG (xor_reduce (acc0, DREG (src0)));
+      SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
+    }
+  else if (sop == 0 && sopcde == 12)
+    {
+      bu64 acc0 = get_unextended_acc (cpu, 0);
+      bu64 acc1 = get_unextended_acc (cpu, 1);
+
+      TRACE_INSN (cpu, "A0 = BXORSHIFT (A0, A1, CC);");
+
+      acc0 = (acc0 << 1) | (CCREG ^ xor_reduce (acc0, acc1));
+      SET_AREG (0, acc0);
+    }
+  else if (sop == 1 && sopcde == 12)
+    {
+      bu64 acc0 = get_unextended_acc (cpu, 0);
+      bu64 acc1 = get_unextended_acc (cpu, 1);
+
+      TRACE_INSN (cpu, "R%i.L = CC = BXOR (A0, A1, CC);", dst0);
+
+      SET_CCREG (CCREG ^ xor_reduce (acc0, acc1));
+      acc0 = (acc0 << 1) | CCREG;
+      SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
+    }
+  else if ((sop == 0 || sop == 1 || sop == 2) && sopcde == 13)
+    {
+      int shift = (sop + 1) * 8;
+      TRACE_INSN (cpu, "R%i = ALIGN%i (R%i, R%i);", dst0, shift, src1, src0);
+      SET_DREG (dst0, (DREG (src1) << (32 - shift)) | (DREG (src0) >> shift));
+    }
+  else
+    illegal_instruction (cpu);
+}
+
+static void
+decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
+{
+  /* dsp32shiftimm
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
+     |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int src1     = ((iw1 >> DSP32ShiftImm_src1_bits) & DSP32ShiftImm_src1_mask);
+  int sop      = ((iw1 >> DSP32ShiftImm_sop_bits) & DSP32ShiftImm_sop_mask);
+  int bit8     = ((iw1 >> 8) & 0x1);
+  int immag    = ((iw1 >> DSP32ShiftImm_immag_bits) & DSP32ShiftImm_immag_mask);
+  int newimmag = (-(iw1 >> DSP32ShiftImm_immag_bits) & DSP32ShiftImm_immag_mask);
+  int dst0     = ((iw1 >> DSP32ShiftImm_dst0_bits) & DSP32ShiftImm_dst0_mask);
+  int M        = ((iw0 >> (DSP32ShiftImm_M_bits - 16)) & DSP32ShiftImm_M_mask);
+  int sopcde   = ((iw0 >> (DSP32ShiftImm_sopcde_bits - 16)) & DSP32ShiftImm_sopcde_mask);
+  int HLs      = ((iw1 >> DSP32ShiftImm_HLs_bits) & DSP32ShiftImm_HLs_mask);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32shiftimm);
+  TRACE_EXTRACT (cpu, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
+                __func__, M, sopcde, sop, HLs, dst0, immag, src1);
+
+  if (sopcde == 0)
+    {
+      bu16 in = DREG (src1) >> ((HLs & 1) ? 16 : 0);
+      bu16 result;
+      bu32 v;
+
+      if (sop == 0)
+       {
+         TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i;",
+                     dst0, (HLs & 2) ? 'H' : 'L',
+                     src1, (HLs & 1) ? 'H' : 'L', newimmag);
+         result = ashiftrt (cpu, in, newimmag, 16);
+       }
+      else if (sop == 1 && bit8 == 0)
+       {
+         TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i (S);",
+                     dst0, (HLs & 2) ? 'H' : 'L',
+                     src1, (HLs & 1) ? 'H' : 'L', immag);
+         result = lshift (cpu, in, immag, 16, 1);
+       }
+      else if (sop == 1 && bit8)
+       {
+         TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i (S);",
+                     dst0, (HLs & 2) ? 'H' : 'L',
+                     src1, (HLs & 1) ? 'H' : 'L', immag);
+         result = lshift (cpu, in, immag, 16, 1);
+       }
+      else if (sop == 2 && bit8)
+       {
+         TRACE_INSN (cpu, "R%i.%c = R%i.%c >> %i;",
+                     dst0, (HLs & 2) ? 'H' : 'L',
+                     src1, (HLs & 1) ? 'H' : 'L', newimmag);
+         result = lshiftrt (cpu, in, newimmag, 16);
+       }
+      else if (sop == 2 && bit8 == 0)
+       {
+         TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i;",
+                     dst0, (HLs & 2) ? 'H' : 'L',
+                     src1, (HLs & 1) ? 'H' : 'L', immag);
+         result = lshift (cpu, in, immag, 16, 0);
+       }
+      else
+       illegal_instruction (cpu);
+
+      v = DREG (dst0);
+      if (HLs & 2)
+       STORE (DREG (dst0), (v & 0xFFFF) | (result << 16));
+      else
+       STORE (DREG (dst0), (v & 0xFFFF0000) | result);
+    }
+  else if (sop == 2 && sopcde == 3 && (HLs == 1 || HLs == 0))
+    {
+      int shift = imm6 (immag);
+      bu32 cc = CCREG;
+      bu40 acc = get_unextended_acc (cpu, HLs);
+
+      TRACE_INSN (cpu, "A%i = ROT A%i BY %i;", HLs, HLs, shift);
+      TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i CC:%i", HLs, acc, shift, cc);
+
+      acc = rot40 (acc, shift, &cc);
+      SET_AREG (HLs, acc);
+      if (shift)
+       SET_CCREG (cc);
+    }
+  else if (sop == 0 && sopcde == 3 && bit8 == 1)
+    {
+      /* Arithmetic shift, so shift in sign bit copies.  */
+      bu64 acc;
+      int shift = uimm5 (newimmag);
+      HLs = !!HLs;
+
+      TRACE_INSN (cpu, "A%i = A%i >>> %i;", HLs, HLs, shift);
+
+      acc = get_extended_acc (cpu, HLs);
+      acc >>= shift;
+      /* Sign extend again.  */
+      if (acc & (1ULL << 39))
+       acc |= -(1ULL << 39);
+      else
+       acc &= ~(-(1ULL << 39));
+
+      STORE (AXREG (HLs), (acc >> 32) & 0xFF);
+      STORE (AWREG (HLs), acc & 0xFFFFFFFF);
+    }
+  else if ((sop == 0 && sopcde == 3 && bit8 == 0)
+          || (sop == 1 && sopcde == 3))
+    {
+      bu64 acc;
+      int shiftup = uimm5 (immag);
+      int shiftdn = uimm5 (newimmag);
+      HLs = !!HLs;
+
+      TRACE_INSN (cpu, "A%i = A%i %s %i;", HLs, HLs,
+                 sop == 0 ? "<<" : ">>",
+                 sop == 0 ? shiftup : shiftdn);
+
+      acc = AXREG (HLs);
+      /* Logical shift, so shift in zeroes.  */
+      acc &= 0xFF;
+      acc <<= 32;
+      acc |= AWREG (HLs);
+
+      if (sop == 0)
+       acc <<= shiftup;
+      else
+       acc >>= shiftdn;
+
+      SET_AREG (HLs, acc);
+      SET_ASTATREG (an, !!(acc & 0x8000000000ull));
+      SET_ASTATREG (az, acc == 0);
+    }
+  else if (sop == 1 && sopcde == 1 && bit8 == 0)
+    {
+      int count = imm5 (immag);
+      bu16 val0 = DREG (src1) >> 16;
+      bu16 val1 = DREG (src1) & 0xFFFF;
+      bu32 astat;
+
+      TRACE_INSN (cpu, "R%i = R%i << %i (V,S);", dst0, src1, count);
+      val0 = lshift (cpu, val0, count, 16, 1);
+      astat = ASTAT;
+      val1 = lshift (cpu, val1, count, 16, 1);
+      SET_ASTAT (ASTAT | astat);
+
+      STORE (DREG (dst0), (val0 << 16) | val1);
+    }
+  else if (sop == 2 && sopcde == 1 && bit8 == 1)
+    {
+      int count = imm5 (newimmag);
+      bu16 val0 = DREG (src1) & 0xFFFF;
+      bu16 val1 = DREG (src1) >> 16;
+      bu32 astat;
+
+      TRACE_INSN (cpu, "R%i = R%i >> %i (V);", dst0, src1, count);
+      val0 = lshiftrt (cpu, val0, count, 16);
+      astat = ASTAT;
+      val1 = lshiftrt (cpu, val1, count, 16);
+      SET_ASTAT (ASTAT | astat);
+
+      STORE (DREG (dst0), val0 | (val1 << 16));
+    }
+  else if (sop == 2 && sopcde == 1 && bit8 == 0)
+    {
+      int count = imm5 (immag);
+      bu16 val0 = DREG (src1) & 0xFFFF;
+      bu16 val1 = DREG (src1) >> 16;
+      bu32 astat;
+
+      TRACE_INSN (cpu, "R%i = R%i << %i (V);", dst0, src1, count);
+      val0 = lshift (cpu, val0, count, 16, 0);
+      astat = ASTAT;
+      val1 = lshift (cpu, val1, count, 16, 0);
+      SET_ASTAT (ASTAT | astat);
+
+      STORE (DREG (dst0), val0 | (val1 << 16));
+    }
+  else if (sopcde == 1 && (sop == 0 || (sop == 1 && bit8 == 1)))
+    {
+      int count = uimm5 (newimmag);
+      bu16 val0 = DREG (src1) & 0xFFFF;
+      bu16 val1 = DREG (src1) >> 16;
+      bu32 astat;
+
+      TRACE_INSN (cpu, "R%i = R%i >>> %i %s;", dst0, src1, count,
+                 sop == 0 ? "(V)" : "(V,S)");
+
+      val0 = ashiftrt (cpu, val0, count, 16);
+      astat = ASTAT;
+      val1 = ashiftrt (cpu, val1, count, 16);
+      SET_ASTAT (ASTAT | astat);
+
+      STORE (DREG (dst0), REG_H_L (val1 << 16, val0));
+    }
+  else if (sop == 1 && sopcde == 2)
+    {
+      int count = imm6 (immag);
+
+      TRACE_INSN (cpu, "R%i = R%i << %i (S);", dst0, src1, count);
+      STORE (DREG (dst0), lshift (cpu, DREG (src1), count, 32, 1));
+    }
+  else if (sop == 2 && sopcde == 2)
+    {
+      int count = imm6 (newimmag);
+
+      TRACE_INSN (cpu, "R%i = R%i >> %i;", dst0, src1, count);
+
+      if (count < 0)
+       STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0));
+      else
+       STORE (DREG (dst0), lshiftrt (cpu, DREG (src1), count, 32));
+    }
+  else if (sop == 3 && sopcde == 2)
+    {
+      int shift = imm6 (immag);
+      bu32 src = DREG (src1);
+      bu32 ret, cc = CCREG;
+
+      TRACE_INSN (cpu, "R%i = ROT R%i BY %i;", dst0, src1, shift);
+      TRACE_DECODE (cpu, "R%i:%#x R%i:%#x shift:%i CC:%i",
+                   dst0, DREG (dst0), src1, src, shift, cc);
+
+      ret = rot32 (src, shift, &cc);
+      STORE (DREG (dst0), ret);
+      if (shift)
+       SET_CCREG (cc);
+    }
+  else if (sop == 0 && sopcde == 2)
+    {
+      int count = imm6 (newimmag);
+
+      TRACE_INSN (cpu, "R%i = R%i >>> %i;", dst0, src1, count);
+
+      if (count < 0)
+       STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0));
+      else
+       STORE (DREG (dst0), ashiftrt (cpu, DREG (src1), count, 32));
+    }
+  else
+    illegal_instruction (cpu);
+}
+
+static void
+outc (SIM_CPU *cpu, char ch)
+{
+  SIM_DESC sd = CPU_STATE (cpu);
+  sim_io_printf (sd, "%c", ch);
+  if (ch == '\n')
+    sim_io_flush_stdout (sd);
+}
+
+static void
+decode_psedoDEBUG_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* psedoDEBUG
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  SIM_DESC sd = CPU_STATE (cpu);
+  int fn  = ((iw0 >> PseudoDbg_fn_bits) & PseudoDbg_fn_mask);
+  int grp = ((iw0 >> PseudoDbg_grp_bits) & PseudoDbg_grp_mask);
+  int reg = ((iw0 >> PseudoDbg_reg_bits) & PseudoDbg_reg_mask);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedoDEBUG);
+  TRACE_EXTRACT (cpu, "%s: fn:%i grp:%i reg:%i", __func__, fn, grp, reg);
+
+  if ((reg == 0 || reg == 1) && fn == 3)
+    {
+      TRACE_INSN (cpu, "DBG A%i;", reg);
+      sim_io_printf (sd, "DBG : A%i = %#"PRIx64"\n", reg,
+                    get_unextended_acc (cpu, reg));
+    }
+  else if (reg == 3 && fn == 3)
+    {
+      TRACE_INSN (cpu, "ABORT;");
+      cec_exception (cpu, VEC_SIM_ABORT);
+      SET_DREG (0, 1);
+    }
+  else if (reg == 4 && fn == 3)
+    {
+      TRACE_INSN (cpu, "HLT;");
+      cec_exception (cpu, VEC_SIM_HLT);
+      SET_DREG (0, 0);
+    }
+  else if (reg == 5 && fn == 3)
+    unhandled_instruction (cpu, "DBGHALT");
+  else if (reg == 6 && fn == 3)
+    unhandled_instruction (cpu, "DBGCMPLX (dregs)");
+  else if (reg == 7 && fn == 3)
+    unhandled_instruction (cpu, "DBG");
+  else if (grp == 0 && fn == 2)
+    {
+      TRACE_INSN (cpu, "OUTC R%i;", reg);
+      outc (cpu, DREG (reg));
+    }
+  else if (fn == 0)
+    {
+      const char *reg_name = get_allreg_name (grp, reg);
+      TRACE_INSN (cpu, "DBG %s;", reg_name);
+      sim_io_printf (sd, "DBG : %s = 0x%08x\n", reg_name,
+                    reg_read (cpu, grp, reg));
+    }
+  else if (fn == 1)
+    unhandled_instruction (cpu, "PRNT allregs");
+  else
+    illegal_instruction (cpu);
+}
+
+static void
+decode_psedoOChar_0 (SIM_CPU *cpu, bu16 iw0)
+{
+  /* psedoOChar
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  int ch = ((iw0 >> PseudoChr_ch_bits) & PseudoChr_ch_mask);
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedoOChar);
+  TRACE_EXTRACT (cpu, "%s: ch:%#x", __func__, ch);
+  TRACE_INSN (cpu, "OUTC %#x;", ch);
+
+  outc (cpu, ch);
+}
+
+static void
+decode_psedodbg_assert_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
+{
+  /* psedodbg_assert
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
+     | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
+     |.expected......................................................|
+     +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
+  SIM_DESC sd = CPU_STATE (cpu);
+  int expected = ((iw1 >> PseudoDbg_Assert_expected_bits) & PseudoDbg_Assert_expected_mask);
+  int dbgop    = ((iw0 >> (PseudoDbg_Assert_dbgop_bits - 16)) & PseudoDbg_Assert_dbgop_mask);
+  int grp      = ((iw0 >> (PseudoDbg_Assert_grp_bits - 16)) & PseudoDbg_Assert_grp_mask);
+  int regtest  = ((iw0 >> (PseudoDbg_Assert_regtest_bits - 16)) & PseudoDbg_Assert_regtest_mask);
+  bu16 actual;
+  bu32 val = reg_read (cpu, grp, regtest);
+  const char *reg_name = get_allreg_name (grp, regtest);
+  const char *dbg_name, *dbg_appd;
+
+  PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedodbg_assert);
+  TRACE_EXTRACT (cpu, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
+                __func__, dbgop, grp, regtest, expected);
+
+  if (dbgop == 0 || dbgop == 2)
+    {
+      dbg_name = dbgop == 0 ? "DBGA" : "DBGAL";
+      dbg_appd = dbgop == 0 ? ".L" : "";
+      actual = val;
+    }
+  else if (dbgop == 1 || dbgop == 3)
+    {
+      dbg_name = dbgop == 1 ? "DBGA" : "DBGAH";
+      dbg_appd = dbgop == 1 ? ".H" : "";
+      actual = val >> 16;
+    }
+  else
+    illegal_instruction (cpu);
+
+  TRACE_INSN (cpu, "%s (%s%s, 0x%x);", dbg_name, reg_name, dbg_appd, expected);
+  if (actual != expected)
+    {
+      sim_io_printf (sd, "FAIL at %#x: %s (%s%s, 0x%04x), actual value %#x\n",
+                    pc, dbg_name, reg_name, dbg_appd, expected, actual);
+      cec_exception (cpu, VEC_SIM_DBGA);
+      SET_DREG (0, 1);
+    }
+}
+
+static bu32
+_interp_insn_bfin (SIM_CPU *cpu, bu32 pc)
+{
+  bu32 insn_len;
+  bu16 iw0, iw1;
+
+  BFIN_CPU_STATE.multi_pc = pc;
+  iw0 = IFETCH (pc);
+  if ((iw0 & 0xc000) != 0xc000)
+    {
+      /* 16-bit opcode.  */
+      insn_len = 2;
+      if (INSN_LEN == 0)
+       INSN_LEN = insn_len;
+
+      TRACE_EXTRACT (cpu, "%s: iw0:%#x", __func__, iw0);
+      if ((iw0 & 0xFF00) == 0x0000)
+       decode_ProgCtrl_0 (cpu, iw0, pc);
+      else if ((iw0 & 0xFFC0) == 0x0240)
+       decode_CaCTRL_0 (cpu, iw0);
+      else if ((iw0 & 0xFF80) == 0x0100)
+       decode_PushPopReg_0 (cpu, iw0);
+      else if ((iw0 & 0xFE00) == 0x0400)
+       decode_PushPopMultiple_0 (cpu, iw0);
+      else if ((iw0 & 0xFE00) == 0x0600)
+       decode_ccMV_0 (cpu, iw0);
+      else if ((iw0 & 0xF800) == 0x0800)
+       decode_CCflag_0 (cpu, iw0);
+      else if ((iw0 & 0xFFE0) == 0x0200)
+       decode_CC2dreg_0 (cpu, iw0);
+      else if ((iw0 & 0xFF00) == 0x0300)
+       decode_CC2stat_0 (cpu, iw0);
+      else if ((iw0 & 0xF000) == 0x1000)
+       decode_BRCC_0 (cpu, iw0, pc);
+      else if ((iw0 & 0xF000) == 0x2000)
+       decode_UJUMP_0 (cpu, iw0, pc);
+      else if ((iw0 & 0xF000) == 0x3000)
+       decode_REGMV_0 (cpu, iw0);
+      else if ((iw0 & 0xFC00) == 0x4000)
+       decode_ALU2op_0 (cpu, iw0);
+      else if ((iw0 & 0xFE00) == 0x4400)
+       decode_PTR2op_0 (cpu, iw0);
+      else if ((iw0 & 0xF800) == 0x4800)
+       decode_LOGI2op_0 (cpu, iw0);
+      else if ((iw0 & 0xF000) == 0x5000)
+       decode_COMP3op_0 (cpu, iw0);
+      else if ((iw0 & 0xF800) == 0x6000)
+       decode_COMPI2opD_0 (cpu, iw0);
+      else if ((iw0 & 0xF800) == 0x6800)
+       decode_COMPI2opP_0 (cpu, iw0);
+      else if ((iw0 & 0xF000) == 0x8000)
+       decode_LDSTpmod_0 (cpu, iw0);
+      else if ((iw0 & 0xFF60) == 0x9E60)
+       decode_dagMODim_0 (cpu, iw0);
+      else if ((iw0 & 0xFFF0) == 0x9F60)
+       decode_dagMODik_0 (cpu, iw0);
+      else if ((iw0 & 0xFC00) == 0x9C00)
+       decode_dspLDST_0 (cpu, iw0);
+      else if ((iw0 & 0xF000) == 0x9000)
+       decode_LDST_0 (cpu, iw0);
+      else if ((iw0 & 0xFC00) == 0xB800)
+       decode_LDSTiiFP_0 (cpu, iw0);
+      else if ((iw0 & 0xE000) == 0xA000)
+       decode_LDSTii_0 (cpu, iw0);
+      else
+       {
+         TRACE_EXTRACT (cpu, "%s: no matching 16-bit pattern", __func__);
+         illegal_instruction (cpu);
+       }
+      return insn_len;
+    }
+
+  /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode.  */
+  iw1 = IFETCH (pc + 2);
+  if ((iw0 & BIT_MULTI_INS) && (iw0 & 0xe800) != 0xe800 /* not linkage  */)
+    {
+      SIM_DESC sd = CPU_STATE (cpu);
+      trace_prefix (sd, cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu),
+                       NULL, 0, "|| %#"PRIx64, sim_events_time (sd));
+      insn_len = 8;
+    }
+  else
+    insn_len = 4;
+
+  TRACE_EXTRACT (cpu, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__,
+                    iw0, iw1, insn_len);
+
+  /* Only cache on first run through (in case of parallel insns).  */
+  if (INSN_LEN == 0)
+    INSN_LEN = insn_len;
+
+  if ((iw0 & 0xf7ff) == 0xc003 && (iw1 & 0xfe00) == 0x1800)
+    {
+      PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mac);
+      TRACE_INSN (cpu, "MNOP;");
+    }
+  else if (((iw0 & 0xFF80) == 0xE080) && ((iw1 & 0x0C00) == 0x0000))
+    decode_LoopSetup_0 (cpu, iw0, iw1, pc);
+  else if (((iw0 & 0xFF00) == 0xE100) && ((iw1 & 0x0000) == 0x0000))
+    decode_LDIMMhalf_0 (cpu, iw0, iw1);
+  else if (((iw0 & 0xFE00) == 0xE200) && ((iw1 & 0x0000) == 0x0000))
+    decode_CALLa_0 (cpu, iw0, iw1, pc);
+  else if (((iw0 & 0xFC00) == 0xE400) && ((iw1 & 0x0000) == 0x0000))
+    decode_LDSTidxI_0 (cpu, iw0, iw1);
+  else if (((iw0 & 0xFFFE) == 0xE800) && ((iw1 & 0x0000) == 0x0000))
+    decode_linkage_0 (cpu, iw0, iw1);
+  else if (((iw0 & 0xF600) == 0xC000) && ((iw1 & 0x0000) == 0x0000))
+    decode_dsp32mac_0 (cpu, iw0, iw1);
+  else if (((iw0 & 0xF600) == 0xC200) && ((iw1 & 0x0000) == 0x0000))
+    decode_dsp32mult_0 (cpu, iw0, iw1);
+  else if (((iw0 & 0xF7C0) == 0xC400) && ((iw1 & 0x0000) == 0x0000))
+    decode_dsp32alu_0 (cpu, iw0, iw1);
+  else if (((iw0 & 0xF7E0) == 0xC600) && ((iw1 & 0x01C0) == 0x0000))
+    decode_dsp32shift_0 (cpu, iw0, iw1);
+  else if (((iw0 & 0xF7E0) == 0xC680) && ((iw1 & 0x0000) == 0x0000))
+    decode_dsp32shiftimm_0 (cpu, iw0, iw1);
+  else if ((iw0 & 0xFF00) == 0xF800)
+    decode_psedoDEBUG_0 (cpu, iw0), insn_len = 2;
+  else if ((iw0 & 0xFF00) == 0xF900)
+    decode_psedoOChar_0 (cpu, iw0), insn_len = 2;
+  else if (((iw0 & 0xFF00) == 0xF000) && ((iw1 & 0x0000) == 0x0000))
+    decode_psedodbg_assert_0 (cpu, iw0, iw1, pc);
+  else
+    {
+      TRACE_EXTRACT (cpu, "%s: no matching 32-bit pattern", __func__);
+      illegal_instruction (cpu);
+    }
+
+  return insn_len;
+}
+
+bu32
+interp_insn_bfin (SIM_CPU *cpu, bu32 pc)
+{
+  int i;
+  bu32 insn_len;
+
+  BFIN_CPU_STATE.n_stores = 0;
+  DIS_ALGN_EXPT &= ~1;
+  CYCLE_DELAY = 1;
+  INSN_LEN = 0;
+
+  insn_len = _interp_insn_bfin (cpu, pc);
+
+  /* Proper display of multiple issue instructions.  */
+  if (insn_len == 8)
+    {
+      _interp_insn_bfin (cpu, pc + 4);
+      _interp_insn_bfin (cpu, pc + 6);
+    }
+  for (i = 0; i < BFIN_CPU_STATE.n_stores; i++)
+    {
+      bu32 *addr = BFIN_CPU_STATE.stores[i].addr;
+      *addr = BFIN_CPU_STATE.stores[i].val;
+      TRACE_REGISTER (cpu, "dequeuing write %s = %#x",
+                     get_store_name (cpu, addr), *addr);
+    }
+
+  cycles_inc (cpu, CYCLE_DELAY);
+
+  /* Set back to zero in case a pending CEC event occurs
+     after this this insn.  */
+  INSN_LEN = 0;
+
+  return insn_len;
+}
diff --git a/sim/bfin/bfin-sim.h b/sim/bfin/bfin-sim.h
new file mode 100644 (file)
index 0000000..d61e7fe
--- /dev/null
@@ -0,0 +1,350 @@
+/* Simulator for Analog Devices Blackfin processors.
+
+   Copyright (C) 2005-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BFIN_SIM_H_
+#define _BFIN_SIM_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef uint8_t bu8;
+typedef uint16_t bu16;
+typedef uint32_t bu32;
+typedef uint64_t bu40;
+typedef uint64_t bu64;
+typedef int8_t bs8;
+typedef int16_t bs16;
+typedef int32_t bs32;
+typedef int64_t bs40;
+typedef int64_t bs64;
+
+/* 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.
+   XXX: Should go and convert all 32 bit insns to use this.  */
+struct store {
+  bu32 *addr;
+  bu32 val;
+};
+
+/* The KSP/USP handling wrt SP may not follow the hardware exactly (the hw
+   looks at current mode and uses either SP or USP based on that.  We instead
+   always operate on SP and mirror things in KSP and USP.  During a CEC
+   transition, we take care of syncing the values.  This lowers the simulation
+   complexity and speeds things up a bit.  */
+struct bfin_cpu_state
+{
+  bu32 dpregs[16], iregs[4], mregs[4], bregs[4], lregs[4], cycles[3];
+  bu32 ax[2], aw[2];
+  bu32 lt[2], lc[2], lb[2];
+  bu32 ksp, usp, seqstat, syscfg, rets, reti, retx, retn, rete;
+  bu32 pc, emudat[2];
+  /* These ASTAT flags need not be bu32, but it makes pointers easier.  */
+  bu32 ac0, ac0_copy, ac1, an, aq;
+  union { struct { bu32 av0;  bu32 av1;  }; bu32 av [2]; };
+  union { struct { bu32 av0s; bu32 av1s; }; bu32 avs[2]; };
+  bu32 az, cc, v, v_copy, vs;
+  bu32 rnd_mod;
+  bu32 v_internal;
+  bu32 astat_reserved;
+
+  /* Set by an instruction emulation function if we performed a jump.  We
+     cannot compare oldpc to newpc as this ignores the "jump 0;" case.  */
+  bool did_jump;
+
+  /* Used by the CEC to figure out where to return to.  */
+  bu32 insn_len;
+
+  /* How many cycles did this insn take to complete ?  */
+  bu32 cycle_delay;
+
+  /* The pc currently being interpreted in parallel insns.  */
+  bu32 multi_pc;
+
+  /* Needed for supporting the DISALGNEXCPT instruction */
+  int dis_algn_expt;
+
+  /* See notes above for struct store.  */
+  struct store stores[20];
+  int n_stores;
+
+#if (WITH_HW)
+  /* Cache heavily used CPU-specific device pointers.  */
+  void *cec_cache;
+  void *evt_cache;
+  void *mmu_cache;
+  void *trace_cache;
+#endif
+};
+
+#define REG_H_L(h, l)  (((h) & 0xffff0000) | ((l) & 0x0000ffff))
+
+#define DREG(x)                (BFIN_CPU_STATE.dpregs[x])
+#define PREG(x)                (BFIN_CPU_STATE.dpregs[x + 8])
+#define SPREG          PREG (6)
+#define FPREG          PREG (7)
+#define IREG(x)                (BFIN_CPU_STATE.iregs[x])
+#define MREG(x)                (BFIN_CPU_STATE.mregs[x])
+#define BREG(x)                (BFIN_CPU_STATE.bregs[x])
+#define LREG(x)                (BFIN_CPU_STATE.lregs[x])
+#define AXREG(x)       (BFIN_CPU_STATE.ax[x])
+#define AWREG(x)       (BFIN_CPU_STATE.aw[x])
+#define CCREG          (BFIN_CPU_STATE.cc)
+#define LCREG(x)       (BFIN_CPU_STATE.lc[x])
+#define LTREG(x)       (BFIN_CPU_STATE.lt[x])
+#define LBREG(x)       (BFIN_CPU_STATE.lb[x])
+#define CYCLESREG      (BFIN_CPU_STATE.cycles[0])
+#define CYCLES2REG     (BFIN_CPU_STATE.cycles[1])
+#define CYCLES2SHDREG  (BFIN_CPU_STATE.cycles[2])
+#define KSPREG         (BFIN_CPU_STATE.ksp)
+#define USPREG         (BFIN_CPU_STATE.usp)
+#define SEQSTATREG     (BFIN_CPU_STATE.seqstat)
+#define SYSCFGREG      (BFIN_CPU_STATE.syscfg)
+#define RETSREG                (BFIN_CPU_STATE.rets)
+#define RETIREG                (BFIN_CPU_STATE.reti)
+#define RETXREG                (BFIN_CPU_STATE.retx)
+#define RETNREG                (BFIN_CPU_STATE.retn)
+#define RETEREG                (BFIN_CPU_STATE.rete)
+#define PCREG          (BFIN_CPU_STATE.pc)
+#define EMUDAT_INREG   (BFIN_CPU_STATE.emudat[0])
+#define EMUDAT_OUTREG  (BFIN_CPU_STATE.emudat[1])
+#define INSN_LEN       (BFIN_CPU_STATE.insn_len)
+#define CYCLE_DELAY    (BFIN_CPU_STATE.cycle_delay)
+#define DIS_ALGN_EXPT  (BFIN_CPU_STATE.dis_algn_expt)
+
+#define EXCAUSE_SHIFT          0
+#define EXCAUSE_MASK           (0x3f << EXCAUSE_SHIFT)
+#define EXCAUSE                        ((SEQSTATREG & EXCAUSE_MASK) >> EXCAUSE_SHIFT)
+#define HWERRCAUSE_SHIFT       14
+#define HWERRCAUSE_MASK                (0x1f << HWERRCAUSE_SHIFT)
+#define HWERRCAUSE             ((SEQSTATREG & HWERRCAUSE_MASK) >> HWERRCAUSE_SHIFT)
+
+#define _SET_CORE32REG_IDX(reg, p, x, val) \
+  do { \
+    bu32 __v = (val); \
+    TRACE_REGISTER (cpu, "wrote "#p"%i = %#x", x, __v); \
+    reg = __v; \
+  } while (0)
+#define SET_DREG(x, val) _SET_CORE32REG_IDX (DREG (x), R, x, val)
+#define SET_PREG(x, val) _SET_CORE32REG_IDX (PREG (x), P, x, val)
+#define SET_IREG(x, val) _SET_CORE32REG_IDX (IREG (x), I, x, val)
+#define SET_MREG(x, val) _SET_CORE32REG_IDX (MREG (x), M, x, val)
+#define SET_BREG(x, val) _SET_CORE32REG_IDX (BREG (x), B, x, val)
+#define SET_LREG(x, val) _SET_CORE32REG_IDX (LREG (x), L, x, val)
+#define SET_LCREG(x, val) _SET_CORE32REG_IDX (LCREG (x), LC, x, val)
+#define SET_LTREG(x, val) _SET_CORE32REG_IDX (LTREG (x), LT, x, val)
+#define SET_LBREG(x, val) _SET_CORE32REG_IDX (LBREG (x), LB, x, val)
+
+#define SET_DREG_L_H(x, l, h) SET_DREG (x, REG_H_L (h, l))
+#define SET_DREG_L(x, l) SET_DREG (x, REG_H_L (DREG (x), l))
+#define SET_DREG_H(x, h) SET_DREG (x, REG_H_L (h, DREG (x)))
+
+#define _SET_CORE32REG_ALU(reg, p, x, val) \
+  do { \
+    bu32 __v = (val); \
+    TRACE_REGISTER (cpu, "wrote A%i"#p" = %#x", x, __v); \
+    reg = __v; \
+  } while (0)
+#define SET_AXREG(x, val) _SET_CORE32REG_ALU (AXREG (x), X, x, val)
+#define SET_AWREG(x, val) _SET_CORE32REG_ALU (AWREG (x), W, x, val)
+
+#define SET_AREG(x, val) \
+  do { \
+    bu40 __a = (val); \
+    SET_AXREG (x, (__a >> 32) & 0xff); \
+    SET_AWREG (x, __a); \
+  } while (0)
+#define SET_AREG32(x, val) \
+  do { \
+    SET_AWREG (x, val); \
+    SET_AXREG (x, -(AWREG (x) >> 31)); \
+  } while (0)
+
+#define _SET_CORE32REG(reg, val) \
+  do { \
+    bu32 __v = (val); \
+    TRACE_REGISTER (cpu, "wrote "#reg" = %#x", __v); \
+    reg##REG = __v; \
+  } while (0)
+#define SET_FPREG(val) _SET_CORE32REG (FP, val)
+#define SET_SPREG(val) _SET_CORE32REG (SP, val)
+#define SET_CYCLESREG(val) _SET_CORE32REG (CYCLES, val)
+#define SET_CYCLES2REG(val) _SET_CORE32REG (CYCLES2, val)
+#define SET_CYCLES2SHDREG(val) _SET_CORE32REG (CYCLES2SHD, val)
+#define SET_KSPREG(val) _SET_CORE32REG (KSP, val)
+#define SET_USPREG(val) _SET_CORE32REG (USP, val)
+#define SET_SYSCFGREG(val) _SET_CORE32REG (SYSCFG, val)
+#define SET_RETSREG(val) _SET_CORE32REG (RETS, val)
+#define SET_RETIREG(val) _SET_CORE32REG (RETI, val)
+#define SET_RETXREG(val) _SET_CORE32REG (RETX, val)
+#define SET_RETNREG(val) _SET_CORE32REG (RETN, val)
+#define SET_RETEREG(val) _SET_CORE32REG (RETE, val)
+#define SET_PCREG(val) _SET_CORE32REG (PC, val)
+
+#define _SET_CORE32REGFIELD(reg, field, val, mask, shift) \
+  do { \
+    bu32 __f = (val); \
+    bu32 __v = ((reg##REG) & ~(mask)) | (__f << (shift)); \
+    TRACE_REGISTER (cpu, "wrote "#field" = %#x ("#reg" = %#x)", __f, __v); \
+    reg##REG = __v; \
+  } while (0)
+#define SET_SEQSTATREG(val)   _SET_CORE32REG (SEQSTAT, val)
+#define SET_EXCAUSE(excp)     _SET_CORE32REGFIELD (SEQSTAT, EXCAUSE, excp, EXCAUSE_MASK, EXCAUSE_SHIFT)
+#define SET_HWERRCAUSE(hwerr) _SET_CORE32REGFIELD (SEQSTAT, HWERRCAUSE, hwerr, HWERRCAUSE_MASK, HWERRCAUSE_SHIFT)
+
+#define AZ_BIT         0
+#define AN_BIT         1
+#define AC0_COPY_BIT   2
+#define V_COPY_BIT     3
+#define CC_BIT         5
+#define AQ_BIT         6
+#define RND_MOD_BIT    8
+#define AC0_BIT                12
+#define AC1_BIT                13
+#define AV0_BIT                16
+#define AV0S_BIT       17
+#define AV1_BIT                18
+#define AV1S_BIT       19
+#define V_BIT          24
+#define VS_BIT         25
+#define ASTAT_DEFINED_BITS \
+  ((1 << AZ_BIT) | (1 << AN_BIT) | (1 << AC0_COPY_BIT) | (1 << V_COPY_BIT) \
+  |(1 << CC_BIT) | (1 << AQ_BIT) \
+  |(1 << RND_MOD_BIT) \
+  |(1 << AC0_BIT) | (1 << AC1_BIT) \
+  |(1 << AV0_BIT) | (1 << AV0S_BIT) | (1 << AV1_BIT) | (1 << AV1S_BIT) \
+  |(1 << V_BIT) | (1 << VS_BIT))
+
+#define ASTATREG(field) (BFIN_CPU_STATE.field)
+#define ASTAT_DEPOSIT(field, bit) (ASTATREG(field) << (bit))
+#define ASTAT \
+  (ASTAT_DEPOSIT(az,       AZ_BIT)       \
+  |ASTAT_DEPOSIT(an,       AN_BIT)       \
+  |ASTAT_DEPOSIT(ac0_copy, AC0_COPY_BIT) \
+  |ASTAT_DEPOSIT(v_copy,   V_COPY_BIT)   \
+  |ASTAT_DEPOSIT(cc,       CC_BIT)       \
+  |ASTAT_DEPOSIT(aq,       AQ_BIT)       \
+  |ASTAT_DEPOSIT(rnd_mod,  RND_MOD_BIT)  \
+  |ASTAT_DEPOSIT(ac0,      AC0_BIT)      \
+  |ASTAT_DEPOSIT(ac1,      AC1_BIT)      \
+  |ASTAT_DEPOSIT(av0,      AV0_BIT)      \
+  |ASTAT_DEPOSIT(av0s,     AV0S_BIT)     \
+  |ASTAT_DEPOSIT(av1,      AV1_BIT)      \
+  |ASTAT_DEPOSIT(av1s,     AV1S_BIT)     \
+  |ASTAT_DEPOSIT(v,        V_BIT)        \
+  |ASTAT_DEPOSIT(vs,       VS_BIT)       \
+  |ASTATREG(astat_reserved))
+
+#define ASTAT_EXTRACT(a, bit)     (((a) >> bit) & 1)
+#define _SET_ASTAT(a, field, bit) (ASTATREG(field) = ASTAT_EXTRACT(a, bit))
+#define SET_ASTAT(a) \
+  do { \
+    TRACE_REGISTER (cpu, "wrote ASTAT = %#x", a); \
+    _SET_ASTAT(a, az,       AZ_BIT); \
+    _SET_ASTAT(a, an,       AN_BIT); \
+    _SET_ASTAT(a, ac0_copy, AC0_COPY_BIT); \
+    _SET_ASTAT(a, v_copy,   V_COPY_BIT); \
+    _SET_ASTAT(a, cc,       CC_BIT); \
+    _SET_ASTAT(a, aq,       AQ_BIT); \
+    _SET_ASTAT(a, rnd_mod,  RND_MOD_BIT); \
+    _SET_ASTAT(a, ac0,      AC0_BIT); \
+    _SET_ASTAT(a, ac1,      AC1_BIT); \
+    _SET_ASTAT(a, av0,      AV0_BIT); \
+    _SET_ASTAT(a, av0s,     AV0S_BIT); \
+    _SET_ASTAT(a, av1,      AV1_BIT); \
+    _SET_ASTAT(a, av1s,     AV1S_BIT); \
+    _SET_ASTAT(a, v,        V_BIT); \
+    _SET_ASTAT(a, vs,       VS_BIT); \
+    ASTATREG(astat_reserved) = (a) & ~ASTAT_DEFINED_BITS; \
+  } while (0)
+#define SET_ASTATREG(field, val) \
+  do { \
+    int __v = !!(val); \
+    TRACE_REGISTER (cpu, "wrote ASTAT["#field"] = %i", __v); \
+    ASTATREG (field) = __v; \
+    if (&ASTATREG (field) == &ASTATREG (ac0)) \
+      { \
+       TRACE_REGISTER (cpu, "wrote ASTAT["#field"_copy] = %i", __v); \
+       ASTATREG (ac0_copy) = __v; \
+      } \
+    else if (&ASTATREG (field) == &ASTATREG (v)) \
+      { \
+       TRACE_REGISTER (cpu, "wrote ASTAT["#field"_copy] = %i", __v); \
+       ASTATREG (v_copy) = __v; \
+      } \
+  } while (0)
+#define SET_CCREG(val) SET_ASTATREG (cc, val)
+
+#define SYSCFG_SSSTEP  (1 << 0)
+#define SYSCFG_CCEN    (1 << 1)
+#define SYSCFG_SNEN    (1 << 2)
+
+#define __PUT_MEM(taddr, v, size) \
+do { \
+  bu##size __v = (v); \
+  bu32 __taddr = (taddr); \
+  int __cnt, __bytes = size / 8; \
+  mmu_check_addr (cpu, __taddr, true, false, __bytes); \
+  __cnt = sim_core_write_buffer (CPU_STATE(cpu), cpu, write_map, \
+                                (void *)&__v, __taddr, __bytes); \
+  if (__cnt != __bytes) \
+    mmu_process_fault (cpu, __taddr, true, false, false, true); \
+  TRACE_CORE (cpu, __taddr, __bytes, write_map, __v); \
+} while (0)
+#define PUT_BYTE(taddr, v) __PUT_MEM(taddr, v, 8)
+#define PUT_WORD(taddr, v) __PUT_MEM(taddr, v, 16)
+#define PUT_LONG(taddr, v) __PUT_MEM(taddr, v, 32)
+
+#define __GET_MEM(taddr, size, inst, map) \
+({ \
+  bu##size __ret; \
+  bu32 __taddr = (taddr); \
+  int __cnt, __bytes = size / 8; \
+  mmu_check_addr (cpu, __taddr, false, inst, __bytes); \
+  __cnt = sim_core_read_buffer (CPU_STATE(cpu), cpu, map, \
+                               (void *)&__ret, __taddr, __bytes); \
+  if (__cnt != __bytes) \
+    mmu_process_fault (cpu, __taddr, false, inst, false, true); \
+  TRACE_CORE (cpu, __taddr, __bytes, map, __ret); \
+  __ret; \
+})
+#define _GET_MEM(taddr, size) __GET_MEM(taddr, size, false, read_map)
+#define GET_BYTE(taddr) _GET_MEM(taddr, 8)
+#define GET_WORD(taddr) _GET_MEM(taddr, 16)
+#define GET_LONG(taddr) _GET_MEM(taddr, 32)
+
+#define IFETCH(taddr) __GET_MEM(taddr, 16, true, exec_map)
+#define IFETCH_CHECK(taddr) mmu_check_addr (cpu, taddr, false, true, 2)
+
+extern void bfin_syscall (SIM_CPU *);
+extern bu32 interp_insn_bfin (SIM_CPU *, bu32);
+extern bu32 hwloop_get_next_pc (SIM_CPU *, bu32, bu32);
+
+/* Defines for Blackfin memory layouts.  */
+#define BFIN_ASYNC_BASE           0x20000000
+#define BFIN_SYSTEM_MMR_BASE      0xFFC00000
+#define BFIN_CORE_MMR_BASE        0xFFE00000
+#define BFIN_L1_SRAM_SCRATCH      0xFFB00000
+#define BFIN_L1_SRAM_SCRATCH_SIZE 0x1000
+#define BFIN_L1_SRAM_SCRATCH_END  (BFIN_L1_SRAM_SCRATCH + BFIN_L1_SRAM_SCRATCH_SIZE)
+
+#define BFIN_L1_CACHE_BYTES       32
+
+#endif
diff --git a/sim/bfin/bfroms/all.h b/sim/bfin/bfroms/all.h
new file mode 100644 (file)
index 0000000..1b562d9
--- /dev/null
@@ -0,0 +1,43 @@
+#include "bf50x-0.0.h"
+
+#include "bf51x-0.0.h"
+#include "bf51x-0.1.h"
+#include "bf51x-0.2.h"
+
+#include "bf526-0.0.h"
+#include "bf526-0.1.h"
+#include "bf527-0.0.h"
+#include "bf527-0.1.h"
+#include "bf527-0.2.h"
+
+#include "bf533-0.1.h"
+#include "bf533-0.2.h"
+#include "bf533-0.3.h"
+#define bfrom_bf533_0_4 bfrom_bf533_0_3
+#define bfrom_bf533_0_5 bfrom_bf533_0_3
+#define bfrom_bf533_0_6 bfrom_bf533_0_3
+
+#include "bf537-0.0.h"
+#include "bf537-0.1.h"
+#define bfrom_bf537_0_2 bfrom_bf537_0_1
+#include "bf537-0.3.h"
+
+#include "bf538-0.0.h"
+#define bfrom_bf538_0_1 bfrom_bf538_0_0
+#define bfrom_bf538_0_2 bfrom_bf538_0_0
+#define bfrom_bf538_0_3 bfrom_bf538_0_0
+#define bfrom_bf538_0_4 bfrom_bf538_0_0
+#define bfrom_bf538_0_5 bfrom_bf538_0_0
+
+#include "bf54x-0.0.h"
+#include "bf54x-0.1.h"
+#include "bf54x-0.2.h"
+#include "bf54x_l1-0.0.h"
+#include "bf54x_l1-0.1.h"
+#include "bf54x_l1-0.2.h"
+
+#include "bf561-0.5.h"
+
+#include "bf59x-0.0.h"
+#define bfrom_bf59x_0_1 bfrom_bf59x_0_0
+#include "bf59x_l1-0.1.h"
diff --git a/sim/bfin/bfroms/bf50x-0.0.h b/sim/bfin/bfroms/bf50x-0.0.h
new file mode 100644 (file)
index 0000000..00dcc10
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf50x_0_0[] = {
+};
diff --git a/sim/bfin/bfroms/bf51x-0.0.h b/sim/bfin/bfroms/bf51x-0.0.h
new file mode 100644 (file)
index 0000000..62b5682
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf51x_0_0[] = {
+};
diff --git a/sim/bfin/bfroms/bf51x-0.1.h b/sim/bfin/bfroms/bf51x-0.1.h
new file mode 100644 (file)
index 0000000..ab82f8f
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf51x_0_1[] = {
+};
diff --git a/sim/bfin/bfroms/bf51x-0.2.h b/sim/bfin/bfroms/bf51x-0.2.h
new file mode 100644 (file)
index 0000000..6cd8dbc
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf51x_0_2[] = {
+};
diff --git a/sim/bfin/bfroms/bf526-0.0.h b/sim/bfin/bfroms/bf526-0.0.h
new file mode 100644 (file)
index 0000000..8b60b47
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf526_0_0[] = {
+};
diff --git a/sim/bfin/bfroms/bf526-0.1.h b/sim/bfin/bfroms/bf526-0.1.h
new file mode 100644 (file)
index 0000000..4d53e0b
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf526_0_1[] = {
+};
diff --git a/sim/bfin/bfroms/bf527-0.0.h b/sim/bfin/bfroms/bf527-0.0.h
new file mode 100644 (file)
index 0000000..9e23e90
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf527_0_0[] = {
+};
diff --git a/sim/bfin/bfroms/bf527-0.1.h b/sim/bfin/bfroms/bf527-0.1.h
new file mode 100644 (file)
index 0000000..1d0c0a9
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf527_0_1[] = {
+};
diff --git a/sim/bfin/bfroms/bf527-0.2.h b/sim/bfin/bfroms/bf527-0.2.h
new file mode 100644 (file)
index 0000000..e0066f3
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf527_0_2[] = {
+};
diff --git a/sim/bfin/bfroms/bf533-0.1.h b/sim/bfin/bfroms/bf533-0.1.h
new file mode 100644 (file)
index 0000000..1f1fd66
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf533_0_1[] = {
+};
diff --git a/sim/bfin/bfroms/bf533-0.2.h b/sim/bfin/bfroms/bf533-0.2.h
new file mode 100644 (file)
index 0000000..00aba57
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf533_0_2[] = {
+};
diff --git a/sim/bfin/bfroms/bf533-0.3.h b/sim/bfin/bfroms/bf533-0.3.h
new file mode 100644 (file)
index 0000000..829485b
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf533_0_3[] = {
+};
diff --git a/sim/bfin/bfroms/bf537-0.0.h b/sim/bfin/bfroms/bf537-0.0.h
new file mode 100644 (file)
index 0000000..ec945d2
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf537_0_0[] = {
+};
diff --git a/sim/bfin/bfroms/bf537-0.1.h b/sim/bfin/bfroms/bf537-0.1.h
new file mode 100644 (file)
index 0000000..4c6d46d
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf537_0_1[] = {
+};
diff --git a/sim/bfin/bfroms/bf537-0.3.h b/sim/bfin/bfroms/bf537-0.3.h
new file mode 100644 (file)
index 0000000..4483a9f
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf537_0_3[] = {
+};
diff --git a/sim/bfin/bfroms/bf538-0.0.h b/sim/bfin/bfroms/bf538-0.0.h
new file mode 100644 (file)
index 0000000..a5dff38
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf538_0_0[] = {
+};
diff --git a/sim/bfin/bfroms/bf54x-0.0.h b/sim/bfin/bfroms/bf54x-0.0.h
new file mode 100644 (file)
index 0000000..9141b29
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf54x_0_0[] = {
+};
diff --git a/sim/bfin/bfroms/bf54x-0.1.h b/sim/bfin/bfroms/bf54x-0.1.h
new file mode 100644 (file)
index 0000000..9d82c58
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf54x_0_1[] = {
+};
diff --git a/sim/bfin/bfroms/bf54x-0.2.h b/sim/bfin/bfroms/bf54x-0.2.h
new file mode 100644 (file)
index 0000000..ea57225
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf54x_0_2[] = {
+};
diff --git a/sim/bfin/bfroms/bf54x_l1-0.0.h b/sim/bfin/bfroms/bf54x_l1-0.0.h
new file mode 100644 (file)
index 0000000..afeaf74
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf54x_l1_0_0[] = {
+};
diff --git a/sim/bfin/bfroms/bf54x_l1-0.1.h b/sim/bfin/bfroms/bf54x_l1-0.1.h
new file mode 100644 (file)
index 0000000..7a1ff33
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf54x_l1_0_1[] = {
+};
diff --git a/sim/bfin/bfroms/bf54x_l1-0.2.h b/sim/bfin/bfroms/bf54x_l1-0.2.h
new file mode 100644 (file)
index 0000000..ad138cf
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf54x_l1_0_2[] = {
+};
diff --git a/sim/bfin/bfroms/bf561-0.5.h b/sim/bfin/bfroms/bf561-0.5.h
new file mode 100644 (file)
index 0000000..1d27141
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf561_0_5[] = {
+};
diff --git a/sim/bfin/bfroms/bf59x-0.0.h b/sim/bfin/bfroms/bf59x-0.0.h
new file mode 100644 (file)
index 0000000..737f644
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf59x_0_0[] = {
+};
diff --git a/sim/bfin/bfroms/bf59x_l1-0.1.h b/sim/bfin/bfroms/bf59x_l1-0.1.h
new file mode 100644 (file)
index 0000000..3be46ee
--- /dev/null
@@ -0,0 +1,3 @@
+/* DO NOT EDIT: Autogenerated.  */
+static const char bfrom_bf59x_l1_0_1[] = {
+};
diff --git a/sim/bfin/config.in b/sim/bfin/config.in
new file mode 100644 (file)
index 0000000..b44011d
--- /dev/null
@@ -0,0 +1,176 @@
+/* config.in.  Generated from configure.ac by autoheader.  */
+
+/* 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
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+#undef ENABLE_NLS
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define if dv-sockser is usable. */
+#undef HAVE_DV_SOCKSER
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the <fpu_control.h> header file. */
+#undef HAVE_FPU_CONTROL_H
+
+/* Define to 1 if you have the `getegid' function. */
+#undef HAVE_GETEGID
+
+/* Define to 1 if you have the `geteuid' function. */
+#undef HAVE_GETEUID
+
+/* Define to 1 if you have the `getgid' function. */
+#undef HAVE_GETGID
+
+/* Define to 1 if you have the `getrusage' function. */
+#undef HAVE_GETRUSAGE
+
+/* Define to 1 if you have the `getuid' function. */
+#undef HAVE_GETUID
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define to 1 if you have the <linux/if_tun.h> header file. */
+#undef HAVE_LINUX_IF_TUN_H
+
+/* Define to 1 if you have the <linux/mii.h> header file. */
+#undef HAVE_LINUX_MII_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mmap' function. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the `munmap' function. */
+#undef HAVE_MUNMAP
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#undef HAVE_NET_IF_H
+
+/* Define to 1 if you have the `setgid' function. */
+#undef HAVE_SETGID
+
+/* Define to 1 if you have the `setuid' function. */
+#undef HAVE_SETUID
+
+/* Define to 1 if you have the `sigaction' function. */
+#undef HAVE_SIGACTION
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the `time' function. */
+#undef HAVE_TIME
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <zlib.h> header file. */
+#undef HAVE_ZLIB_H
+
+/* Define to 1 if you have the `__setfpucw' function. */
+#undef HAVE___SETFPUCW
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Additional package description */
+#undef PKGVERSION
+
+/* Bug reporting address */
+#undef REPORT_BUGS_TO
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+#  undef WORDS_BIGENDIAN
+# endif
+#endif
diff --git a/sim/bfin/configure b/sim/bfin/configure
new file mode 100755 (executable)
index 0000000..ff71b59
--- /dev/null
@@ -0,0 +1,6779 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.64.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
+# Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+       expr "X$arg" : "X\\(.*\\)$as_nl";
+       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+        /*)
+          for as_base in sh bash ksh sh5; do
+            # Try only shells that exist, to save several forks.
+            as_shell=$as_dir/$as_base
+            if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+                   { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+                  if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+          done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+             { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  # We cannot yet assume a decent shell, so we have to provide a
+       # neutralization value for shells without unset; and this also
+       # works around shells that cannot unset nonexistent variables.
+       BASH_ENV=/dev/null
+       ENV=/dev/null
+       (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+       export CONFIG_SHELL
+       exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$?; test $as_status -eq 0 && as_status=1
+  if test "$3"; then
+    as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+  fi
+  $as_echo "$as_me: error: $1" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='        ';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+       test -d "$1/.";
+      else
+       case $1 in #(
+       -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="Makefile.in"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+cgen_breaks
+SDL_LIBS
+SDL_CFLAGS
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
+BFIN_SIM_EXTRA_OBJS
+REPORT_BUGS_TEXI
+REPORT_BUGS_TO
+PKGVERSION
+sim_profile
+sim_trace
+sim_stdio
+sim_debug
+sim_cflags
+sim_bswap
+MAINT
+EGREP
+GREP
+CPP
+CATOBJEXT
+GENCAT
+INSTOBJEXT
+DATADIRNAME
+CATALOGS
+POSUB
+GMSGFMT
+XGETTEXT
+INCINTL
+LIBINTL_DEP
+LIBINTL
+USE_NLS
+RANLIB
+AR
+HDEFINES
+CC_FOR_BUILD
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_os
+target_vendor
+target_cpu
+target
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+WERROR_CFLAGS
+WARN_CFLAGS
+sim_xor_endian
+sim_stdcall
+sim_smp
+sim_reserved_bits
+sim_regparm
+sim_packages
+sim_inline
+sim_hw
+sim_hw_objs
+sim_hw_cflags
+sim_default_model
+sim_scache
+sim_float
+sim_hostendian
+sim_endian
+sim_bitsize
+sim_assert
+sim_alignment
+sim_environment
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_zlib
+enable_maintainer_mode
+enable_sim_bswap
+enable_sim_cflags
+enable_sim_debug
+enable_sim_stdio
+enable_sim_trace
+enable_sim_profile
+with_pkgversion
+with_bugurl
+enable_sim_endian
+enable_sim_alignment
+enable_sim_hostendian
+enable_sim_default_model
+enable_sim_environment
+enable_sim_inline
+enable_build_warnings
+enable_sim_build_warnings
+enable_sim_hardware
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+SDL_CFLAGS
+SDL_LIBS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)   ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information."
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
+               datadir sysconfdir sharedstatedir localstatedir includedir \
+               oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+               libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_myself" : 'X\(//\)[^/]' \| \
+        X"$as_myself" : 'X\(//\)$' \| \
+        X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+       cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg"
+       pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-maintainer-mode             Enable developer functionality.
+  --enable-sim-bswap                   Use Host specific BSWAP instruction.
+  --enable-sim-cflags=opts             Extra CFLAGS for use in building simulator
+  --enable-sim-debug=opts              Enable debugging flags
+  --enable-sim-stdio                   Specify whether to use stdio for console input/output.
+  --enable-sim-trace=opts              Enable tracing flags
+  --enable-sim-profile=opts            Enable profiling flags
+  --enable-sim-endian=endian           Specify target byte endian orientation.
+  --enable-sim-alignment=align         Specify strict,  nonstrict or forced alignment of memory accesses.
+  --enable-sim-hostendian=end          Specify host byte endian orientation.
+  --enable-sim-default-model=model     Specify default model to simulate.
+  --enable-sim-environment=environment Specify mixed, user, virtual or operating environment.
+  --enable-sim-inline=inlines          Specify which functions should be inlined.
+  --enable-build-warnings Enable build-time compiler warnings if gcc is used
+  --enable-gdb-build-warnings Enable SIM specific build-time compiler warnings if gcc is used
+  --enable-sim-hardware=LIST           Specify the hardware to be included in the build.
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-zlib             include zlib support (auto/yes/no) default=auto
+  --with-pkgversion=PKG   Use PKG in the version string in place of "GDB"
+  --with-bugurl=URL       Direct users to URL to report a bug
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+  PKG_CONFIG  path to pkg-config utility
+  PKG_CONFIG_PATH
+              directories to add to pkg-config's search path
+  PKG_CONFIG_LIBDIR
+              path overriding pkg-config's built-in search path
+  SDL_CFLAGS  C compiler flags for SDL, overriding pkg-config
+  SDL_LIBS    linker flags for SDL, overriding pkg-config
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.64
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        $as_test_x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_func
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.64.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+       "s/'\''/'\''\\\\'\'''\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=\$$ac_var
+       case $ac_val in
+       *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+       esac
+       $as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  ac_site_file1=$CONFIG_SITE
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       # differences in whitespace do not lead to failure.
+       ac_old_val_w=`echo x $ac_old_val`
+       ac_new_val_w=`echo x $ac_new_val`
+       if test "$ac_old_val_w" != "$ac_new_val_w"; then
+         { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+         ac_cache_corrupted=:
+       else
+         { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+         eval $ac_var=\$ac_old_val
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+       { $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_config_headers="$ac_config_headers config.h:config.in"
+
+
+# This file contains common code used by all simulators.
+#
+# SIM_AC_COMMON invokes AC macros used by all simulators and by the common
+# directory.  It is intended to be invoked before any target specific stuff.
+# SIM_AC_OUTPUT is a cover function to AC_OUTPUT to generate the Makefile.
+# It is intended to be invoked last.
+#
+# The simulator's configure.in should look like:
+#
+# dnl Process this file with autoconf to produce a configure script.
+# sinclude(../common/aclocal.m4)
+# AC_PREREQ(2.5)dnl
+# AC_INIT(Makefile.in)
+#
+# SIM_AC_COMMON
+#
+# ... target specific stuff ...
+#
+# SIM_AC_OUTPUT
+
+# Include global overrides and fixes for Autoconf.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# _AC_CHECK_DECL_BODY
+# -------------------
+# Shell function body for AC_CHECK_DECL.
+# _AC_CHECK_DECL_BODY
+
+# _AC_CHECK_DECLS(SYMBOL, ACTION-IF_FOUND, ACTION-IF-NOT-FOUND,
+#                 INCLUDES)
+# -------------------------------------------------------------
+# Helper to AC_CHECK_DECLS, which generates the check for a single
+# SYMBOL with INCLUDES, performs the AC_DEFINE, then expands
+# ACTION-IF-FOUND or ACTION-IF-NOT-FOUND.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+sim_inline="-DDEFAULT_INLINE=0"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# intl sister-directory configuration rules.
+#
+
+# The idea behind this macro is that there's no need to repeat all the
+# autoconf probes done by the intl directory - it's already done them
+# for us.  In fact, there's no need even to look at the cache for the
+# answers.  All we need to do is nab a few pieces of information.
+# The intl directory is set up to make this easy, by generating a
+# small file which can be sourced as a shell script; then we produce
+# the necessary substitutions and definitions for this directory.
+
+
+
+# Autoconf M4 include file defining utility macros for complex Canadian
+# cross builds.
+
+
+
+
+
+
+
+
+
+####
+# _NCN_TOOL_PREFIXES:  Some stuff that oughtta be done in AC_CANONICAL_SYSTEM
+# or AC_INIT.
+# These demand that AC_CANONICAL_SYSTEM be called beforehand.
+
+####
+# NCN_STRICT_CHECK_TOOLS(variable, progs-to-check-for,[value-if-not-found],[path])
+# Like plain AC_CHECK_TOOLS, but require prefix if build!=host.
+
+
+####
+# NCN_STRICT_CHECK_TARGET_TOOLS(variable, progs-to-check-for,[value-if-not-found],[path])
+# Like CVS Autoconf AC_CHECK_TARGET_TOOLS, but require prefix if build!=target.
+
+
+
+# Backported from Autoconf 2.5x; can go away when and if
+# we switch.  Put the OS path separator in $PATH_SEPARATOR.
+
+
+
+
+# ACX_HAVE_GCC_FOR_TARGET
+# Check if the variable GCC_FOR_TARGET really points to a GCC binary.
+
+
+# ACX_CHECK_INSTALLED_TARGET_TOOL(VAR, PROG)
+# Searching for installed target binutils.  We need to take extra care,
+# else we may find the wrong assembler, linker, etc., and lose.
+#
+# First try --with-build-time-tools, if specified.
+#
+# For build != host, we ask the installed GCC for the name of the tool it
+# uses, and accept it if it is an absolute path.  This is because the
+# only good choice for a compiler is the same GCC version that is being
+# installed (or we couldn't make target libraries), and we assume that
+# on the host system we'll have not only the same GCC version, but also
+# the same binutils version.
+#
+# For build == host, search the same directories that the installed
+# compiler will search.  We used to do this for the assembler, linker,
+# and nm only; for simplicity of configuration, however, we extend this
+# criterion to tools (such as ar and ranlib) that are never invoked by
+# the compiler, to avoid mismatches.
+#
+# Also note we have to check MD_EXEC_PREFIX before checking the user's path
+# if build == target.  This makes the most sense only when bootstrapping,
+# but we also do so when build != host.  In this case, we hope that the
+# build and host systems will have similar contents of MD_EXEC_PREFIX.
+#
+# If we do not find a suitable binary, then try the user's path.
+
+
+###
+# AC_PROG_CPP_WERROR
+# Used for autoconf 2.5x to force AC_PREPROC_IFELSE to reject code which
+# triggers warnings from the preprocessor.  Will be in autoconf 2.58.
+# For now, using this also overrides header checks to use only the
+# preprocessor (matches 2.13 behavior; matching 2.58's behavior is a
+# bit harder from here).
+# Eventually autoconf will default to checking headers with the compiler
+# instead, and we'll have to do this differently.
+
+# AC_PROG_CPP_WERROR
+
+# Test for GNAT.
+# We require the gnatbind program, and a compiler driver that
+# understands Ada.  We use the user's CC setting, already found,
+# and possibly add $1 to the command-line parameters.
+#
+# Sets the shell variable have_gnat to yes or no as appropriate, and
+# substitutes GNATBIND and GNATMAKE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Bugs in autoconf 2.59 break the call to SIM_AC_COMMON, hack around
+# it by inlining the macro's contents.
+# This file contains common code used by all simulators.
+#
+# common.m4 invokes AC macros used by all simulators and by the common
+# directory.  It is intended to be included before any target specific
+# stuff.  SIM_AC_OUTPUT is a cover function to AC_OUTPUT to generate
+# the Makefile.  It is intended to be invoked last.
+#
+# The simulator's configure.in should look like:
+#
+# dnl Process this file with autoconf to produce a configure script.
+# AC_PREREQ(2.5)dnl
+# AC_INIT(Makefile.in)
+# AC_CONFIG_HEADER(config.h:config.in)
+#
+# sinclude(../common/aclocal.m4)
+# sinclude(../common/common.m4)
+#
+# ... target specific stuff ...
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  for ac_t in install-sh install.sh shtool; do
+    if test -f "$ac_dir/$ac_t"; then
+      ac_aux_dir=$ac_dir
+      ac_install_sh="$ac_aux_dir/$ac_t -c"
+      break 2
+    fi
+  done
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if test "${ac_cv_build+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if test "${ac_cv_host+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if test "${ac_cv_target+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$target_alias" = x; then
+  ac_cv_target=$ac_cv_host
+else
+  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+    as_fn_error "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "no acceptable C compiler found in \$PATH
+See \`config.log' for more details." "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    rm -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out conftest.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+       if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+       then :; else
+          ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       fi
+       # We set ac_cv_exeext here because the later test for it is not
+       # safe: cross compilers may not add the suffix if given an `-o'
+       # argument, so we may need to know it at that point already.
+       # Even if this section looks crufty: it has the advantage of
+       # actually working.
+       break;;
+    * )
+       break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+if test -z "$ac_file"; then :
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "C compiler cannot create executables
+See \`config.log' for more details." "$LINENO" 5; }; }
+fi
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           rm -rf conftest.one conftest.two conftest.dir
+           echo one > conftest.one
+           echo two > conftest.two
+           mkdir conftest.dir
+           if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+             test -s conftest.one && test -s conftest.two &&
+             test -s conftest.dir/conftest.one &&
+             test -s conftest.dir/conftest.two
+           then
+             ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+             break 3
+           fi
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+# Put a plausible default for CC_FOR_BUILD in Makefile.
+if test "x$cross_compiling" = "xno"; then
+  CC_FOR_BUILD='$(CC)'
+else
+  CC_FOR_BUILD=gcc
+fi
+
+
+
+
+AR=${AR-ar}
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+ALL_LINGUAS=
+# If we haven't got the data from the intl directory,
+# assume NLS is disabled.
+USE_NLS=no
+LIBINTL=
+LIBINTL_DEP=
+INCINTL=
+XGETTEXT=
+GMSGFMT=
+POSUB=
+
+if test -f  ../../intl/config.intl; then
+  .  ../../intl/config.intl
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5
+$as_echo_n "checking whether NLS is requested... " >&6; }
+if test x"$USE_NLS" != xyes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define ENABLE_NLS 1" >>confdefs.h
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for catalogs to be installed" >&5
+$as_echo_n "checking for catalogs to be installed... " >&6; }
+  # Look for .po and .gmo files in the source directory.
+  CATALOGS=
+  XLINGUAS=
+  for cat in $srcdir/po/*.gmo $srcdir/po/*.po; do
+    # If there aren't any .gmo files the shell will give us the
+    # literal string "../path/to/srcdir/po/*.gmo" which has to be
+    # weeded out.
+    case "$cat" in *\**)
+      continue;;
+    esac
+    # The quadruple backslash is collapsed to a double backslash
+    # by the backticks, then collapsed again by the double quotes,
+    # leaving us with one backslash in the sed expression (right
+    # before the dot that mustn't act as a wildcard).
+    cat=`echo $cat | sed -e "s!$srcdir/po/!!" -e "s!\\\\.po!.gmo!"`
+    lang=`echo $cat | sed -e "s!\\\\.gmo!!"`
+    # The user is allowed to set LINGUAS to a list of languages to
+    # install catalogs for.  If it's empty that means "all of them."
+    if test "x$LINGUAS" = x; then
+      CATALOGS="$CATALOGS $cat"
+      XLINGUAS="$XLINGUAS $lang"
+    else
+      case "$LINGUAS" in *$lang*)
+        CATALOGS="$CATALOGS $cat"
+        XLINGUAS="$XLINGUAS $lang"
+        ;;
+      esac
+    fi
+  done
+  LINGUAS="$XLINGUAS"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LINGUAS" >&5
+$as_echo "$LINGUAS" >&6; }
+
+
+    DATADIRNAME=share
+
+  INSTOBJEXT=.mo
+
+  GENCAT=gencat
+
+  CATOBJEXT=.gmo
+
+fi
+
+# Check for common headers.
+# FIXME: Seems to me this can cause problems for i386-windows hosts.
+# At one point there were hardcoded AC_DEFINE's if ${host} = i386-*-windows*.
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in stdlib.h string.h strings.h unistd.h time.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in sys/time.h sys/resource.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in fcntl.h fpu_control.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in dlfcn.h errno.h sys/stat.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in getrusage time sigaction __setfpucw
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# Check for socket libraries
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for bind in -lsocket" >&5
+$as_echo_n "checking for bind in -lsocket... " >&6; }
+if test "${ac_cv_lib_socket_bind+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char bind ();
+int
+main ()
+{
+return bind ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_socket_bind=yes
+else
+  ac_cv_lib_socket_bind=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_bind" >&5
+$as_echo "$ac_cv_lib_socket_bind" >&6; }
+if test "x$ac_cv_lib_socket_bind" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSOCKET 1
+_ACEOF
+
+  LIBS="-lsocket $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5
+$as_echo_n "checking for gethostbyname in -lnsl... " >&6; }
+if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_nsl_gethostbyname=yes
+else
+  ac_cv_lib_nsl_gethostbyname=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5
+$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; }
+if test "x$ac_cv_lib_nsl_gethostbyname" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBNSL 1
+_ACEOF
+
+  LIBS="-lnsl $LIBS"
+
+fi
+
+
+# BFD conditionally uses zlib, so we must link it in if libbfd does, by
+# using the same condition.
+
+  # See if the user specified whether he wants zlib support or not.
+
+# Check whether --with-zlib was given.
+if test "${with_zlib+set}" = set; then :
+  withval=$with_zlib;
+else
+  with_zlib=auto
+fi
+
+
+  if test "$with_zlib" != "no"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing zlibVersion" >&5
+$as_echo_n "checking for library containing zlibVersion... " >&6; }
+if test "${ac_cv_search_zlibVersion+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char zlibVersion ();
+int
+main ()
+{
+return zlibVersion ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' z; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_zlibVersion=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if test "${ac_cv_search_zlibVersion+set}" = set; then :
+  break
+fi
+done
+if test "${ac_cv_search_zlibVersion+set}" = set; then :
+
+else
+  ac_cv_search_zlibVersion=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_zlibVersion" >&5
+$as_echo "$ac_cv_search_zlibVersion" >&6; }
+ac_res=$ac_cv_search_zlibVersion
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+  for ac_header in zlib.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_zlib_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_ZLIB_H 1
+_ACEOF
+
+fi
+
+done
+
+fi
+
+    if test "$with_zlib" = "yes" -a "$ac_cv_header_zlib_h" != "yes"; then
+      as_fn_error "zlib (libz) library was explicitly requested but not found" "$LINENO" 5
+    fi
+  fi
+
+
+. ${srcdir}/../../bfd/configure.host
+
+
+
+USE_MAINTAINER_MODE=no
+# Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then :
+  enableval=$enable_maintainer_mode; case "${enableval}" in
+  yes) MAINT="" USE_MAINTAINER_MODE=yes ;;
+  no)  MAINT="#" ;;
+  *)   as_fn_error "\"--enable-maintainer-mode does not take a value\"" "$LINENO" 5; MAINT="#" ;;
+esac
+if test x"$silent" != x"yes" && test x"$MAINT" = x""; then
+  echo "Setting maintainer mode" 6>&1
+fi
+else
+  MAINT="#"
+fi
+
+
+
+# Check whether --enable-sim-bswap was given.
+if test "${enable_sim_bswap+set}" = set; then :
+  enableval=$enable_sim_bswap; case "${enableval}" in
+  yes) sim_bswap="-DWITH_BSWAP=1 -DUSE_BSWAP=1";;
+  no)  sim_bswap="-DWITH_BSWAP=0";;
+  *)   as_fn_error "\"--enable-sim-bswap does not take a value\"" "$LINENO" 5; sim_bswap="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_bswap" != x""; then
+  echo "Setting bswap flags = $sim_bswap" 6>&1
+fi
+else
+  sim_bswap=""
+fi
+
+
+
+# Check whether --enable-sim-cflags was given.
+if test "${enable_sim_cflags+set}" = set; then :
+  enableval=$enable_sim_cflags; case "${enableval}" in
+  yes)  sim_cflags="-O2 -fomit-frame-pointer";;
+  trace) as_fn_error "\"Please use --enable-sim-debug instead.\"" "$LINENO" 5; sim_cflags="";;
+  no)   sim_cflags="";;
+  *)    sim_cflags=`echo "${enableval}" | sed -e "s/,/ /g"`;;
+esac
+if test x"$silent" != x"yes" && test x"$sim_cflags" != x""; then
+  echo "Setting sim cflags = $sim_cflags" 6>&1
+fi
+else
+  sim_cflags=""
+fi
+
+
+
+# Check whether --enable-sim-debug was given.
+if test "${enable_sim_debug+set}" = set; then :
+  enableval=$enable_sim_debug; case "${enableval}" in
+  yes) sim_debug="-DDEBUG=7 -DWITH_DEBUG=7";;
+  no)  sim_debug="-DDEBUG=0 -DWITH_DEBUG=0";;
+  *)   sim_debug="-DDEBUG='(${enableval})' -DWITH_DEBUG='(${enableval})'";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_debug" != x""; then
+  echo "Setting sim debug = $sim_debug" 6>&1
+fi
+else
+  sim_debug=""
+fi
+
+
+
+# Check whether --enable-sim-stdio was given.
+if test "${enable_sim_stdio+set}" = set; then :
+  enableval=$enable_sim_stdio; case "${enableval}" in
+  yes) sim_stdio="-DWITH_STDIO=DO_USE_STDIO";;
+  no)  sim_stdio="-DWITH_STDIO=DONT_USE_STDIO";;
+  *)   as_fn_error "\"Unknown value $enableval passed to --enable-sim-stdio\"" "$LINENO" 5; sim_stdio="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then
+  echo "Setting stdio flags = $sim_stdio" 6>&1
+fi
+else
+  sim_stdio=""
+fi
+
+
+
+# Check whether --enable-sim-trace was given.
+if test "${enable_sim_trace+set}" = set; then :
+  enableval=$enable_sim_trace; case "${enableval}" in
+  yes) sim_trace="-DTRACE=1 -DWITH_TRACE=-1";;
+  no)  sim_trace="-DTRACE=0 -DWITH_TRACE=0";;
+  [-0-9]*)
+       sim_trace="-DTRACE='(${enableval})' -DWITH_TRACE='(${enableval})'";;
+  [a-z]*)
+       sim_trace=""
+       for x in `echo "$enableval" | sed -e "s/,/ /g"`; do
+         if test x"$sim_trace" = x; then
+           sim_trace="-DWITH_TRACE='(TRACE_$x"
+         else
+           sim_trace="${sim_trace}|TRACE_$x"
+         fi
+       done
+       sim_trace="$sim_trace)'" ;;
+esac
+if test x"$silent" != x"yes" && test x"$sim_trace" != x""; then
+  echo "Setting sim trace = $sim_trace" 6>&1
+fi
+else
+  sim_trace=""
+fi
+
+
+
+# Check whether --enable-sim-profile was given.
+if test "${enable_sim_profile+set}" = set; then :
+  enableval=$enable_sim_profile; case "${enableval}" in
+  yes) sim_profile="-DPROFILE=1 -DWITH_PROFILE=-1";;
+  no)  sim_profile="-DPROFILE=0 -DWITH_PROFILE=0";;
+  [-0-9]*)
+       sim_profile="-DPROFILE='(${enableval})' -DWITH_PROFILE='(${enableval})'";;
+  [a-z]*)
+       sim_profile=""
+       for x in `echo "$enableval" | sed -e "s/,/ /g"`; do
+         if test x"$sim_profile" = x; then
+           sim_profile="-DWITH_PROFILE='(PROFILE_$x"
+         else
+           sim_profile="${sim_profile}|PROFILE_$x"
+         fi
+       done
+       sim_profile="$sim_profile)'" ;;
+esac
+if test x"$silent" != x"yes" && test x"$sim_profile" != x""; then
+  echo "Setting sim profile = $sim_profile" 6>&1
+fi
+else
+  sim_profile="-DPROFILE=1 -DWITH_PROFILE=-1"
+fi
+
+
+
+
+# Check whether --with-pkgversion was given.
+if test "${with_pkgversion+set}" = set; then :
+  withval=$with_pkgversion; case "$withval" in
+      yes) as_fn_error "package version not specified" "$LINENO" 5 ;;
+      no)  PKGVERSION= ;;
+      *)   PKGVERSION="($withval) " ;;
+     esac
+else
+  PKGVERSION="(GDB) "
+
+fi
+
+
+
+
+
+# Check whether --with-bugurl was given.
+if test "${with_bugurl+set}" = set; then :
+  withval=$with_bugurl; case "$withval" in
+      yes) as_fn_error "bug URL not specified" "$LINENO" 5 ;;
+      no)  BUGURL=
+          ;;
+      *)   BUGURL="$withval"
+          ;;
+     esac
+else
+  BUGURL="http://www.gnu.org/software/gdb/bugs/"
+
+fi
+
+  case ${BUGURL} in
+  "")
+    REPORT_BUGS_TO=
+    REPORT_BUGS_TEXI=
+    ;;
+  *)
+    REPORT_BUGS_TO="<$BUGURL>"
+    REPORT_BUGS_TEXI=@uref{`echo "$BUGURL" | sed 's/@/@@/g'`}
+    ;;
+  esac;
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define PKGVERSION "$PKGVERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define REPORT_BUGS_TO "$REPORT_BUGS_TO"
+_ACEOF
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5
+$as_echo_n "checking return type of signal handlers... " >&6; }
+if test "${ac_cv_type_signal+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <signal.h>
+
+int
+main ()
+{
+return *(signal (0, 0)) (0) == 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_type_signal=int
+else
+  ac_cv_type_signal=void
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5
+$as_echo "$ac_cv_type_signal" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+
+
+
+sim_link_files=
+sim_link_links=
+
+sim_link_links=tconfig.h
+if test -f ${srcdir}/tconfig.in
+then
+  sim_link_files=tconfig.in
+else
+  sim_link_files=../common/tconfig.in
+fi
+
+# targ-vals.def points to the libc macro description file.
+case "${target}" in
+*-*-*) TARG_VALS_DEF=../common/nltvals.def ;;
+esac
+sim_link_files="${sim_link_files} ${TARG_VALS_DEF}"
+sim_link_links="${sim_link_links} targ-vals.def"
+
+
+
+wire_endian="LITTLE_ENDIAN"
+default_endian=""
+# Check whether --enable-sim-endian was given.
+if test "${enable_sim_endian+set}" = set; then :
+  enableval=$enable_sim_endian; case "${enableval}" in
+  b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
+  l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
+  yes)  if test x"$wire_endian" != x; then
+          sim_endian="-DWITH_TARGET_BYTE_ORDER=${wire_endian}"
+        else
+           if test x"$default_endian" != x; then
+            sim_endian="-DWITH_TARGET_BYTE_ORDER=${default_endian}"
+          else
+            echo "No hard-wired endian for target $target" 1>&6
+            sim_endian="-DWITH_TARGET_BYTE_ORDER=0"
+          fi
+        fi;;
+  no)   if test x"$default_endian" != x; then
+          sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=${default_endian}"
+        else
+          if test x"$wire_endian" != x; then
+            sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=${wire_endian}"
+          else
+            echo "No default endian for target $target" 1>&6
+            sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=0"
+          fi
+        fi;;
+  *)    as_fn_error "\"Unknown value $enableval for --enable-sim-endian\"" "$LINENO" 5; sim_endian="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_endian" != x""; then
+  echo "Setting endian flags = $sim_endian" 6>&1
+fi
+else
+  if test x"$default_endian" != x; then
+  sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=${default_endian}"
+else
+  if test x"$wire_endian" != x; then
+    sim_endian="-DWITH_TARGET_BYTE_ORDER=${wire_endian}"
+  else
+    sim_endian=
+  fi
+fi
+fi
+
+wire_alignment="STRICT_ALIGNMENT"
+default_alignment="STRICT_ALIGNMENT"
+
+# Check whether --enable-sim-alignment was given.
+if test "${enable_sim_alignment+set}" = set; then :
+  enableval=$enable_sim_alignment; case "${enableval}" in
+  strict | STRICT)       sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
+  nonstrict | NONSTRICT) sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";;
+  forced | FORCED)       sim_alignment="-DWITH_ALIGNMENT=FORCED_ALIGNMENT";;
+  yes) if test x"$wire_alignment" != x; then
+        sim_alignment="-DWITH_ALIGNMENT=${wire_alignment}"
+       else
+         if test x"$default_alignment" != x; then
+           sim_alignment="-DWITH_ALIGNMENT=${default_alignment}"
+         else
+          echo "No hard-wired alignment for target $target" 1>&6
+          sim_alignment="-DWITH_ALIGNMENT=0"
+         fi
+       fi;;
+  no)  if test x"$default_alignment" != x; then
+        sim_alignment="-DWITH_DEFAULT_ALIGNMENT=${default_alignment}"
+       else
+         if test x"$wire_alignment" != x; then
+          sim_alignment="-DWITH_DEFAULT_ALIGNMENT=${wire_alignment}"
+         else
+           echo "No default alignment for target $target" 1>&6
+           sim_alignment="-DWITH_DEFAULT_ALIGNMENT=0"
+         fi
+       fi;;
+  *)   as_fn_error "\"Unknown value $enableval passed to --enable-sim-alignment\"" "$LINENO" 5; sim_alignment="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then
+  echo "Setting alignment flags = $sim_alignment" 6>&1
+fi
+else
+  if test x"$default_alignment" != x; then
+  sim_alignment="-DWITH_DEFAULT_ALIGNMENT=${default_alignment}"
+else
+  if test x"$wire_alignment" != x; then
+    sim_alignment="-DWITH_ALIGNMENT=${wire_alignment}"
+  else
+    sim_alignment=
+  fi
+fi
+fi
+
+
+# Check whether --enable-sim-hostendian was given.
+if test "${enable_sim_hostendian+set}" = set; then :
+  enableval=$enable_sim_hostendian; case "${enableval}" in
+  no)   sim_hostendian="-DWITH_HOST_BYTE_ORDER=0";;
+  b*|B*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN";;
+  l*|L*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN";;
+  *)    as_fn_error "\"Unknown value $enableval for --enable-sim-hostendian\"" "$LINENO" 5; sim_hostendian="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_hostendian" != x""; then
+  echo "Setting hostendian flags = $sim_hostendian" 6>&1
+fi
+else
+
+if test "x$cross_compiling" = "xno"; then
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if test "${ac_cv_c_bigendian+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_bigendian=unknown
+    # See if we're dealing with a universal compiler.
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __APPLE_CC__
+              not a universal capable compiler
+            #endif
+            typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+       # Check for potential -arch flags.  It is not universal unless
+       # there are at least two -arch flags with different values.
+       ac_arch=
+       ac_prev=
+       for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+        if test -n "$ac_prev"; then
+          case $ac_word in
+            i?86 | x86_64 | ppc | ppc64)
+              if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+                ac_arch=$ac_word
+              else
+                ac_cv_c_bigendian=universal
+                break
+              fi
+              ;;
+          esac
+          ac_prev=
+        elif test "x$ac_word" = "x-arch"; then
+          ac_prev=arch
+        fi
+       done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if sys/param.h defines the BYTE_ORDER macro.
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+            #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+                    && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+                    && LITTLE_ENDIAN)
+             bogus endian macros
+            #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+               #include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+                not big endian
+               #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+             bogus endian macros
+            #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to _BIG_ENDIAN or not.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+                not big endian
+               #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # Compile a test program.
+      if test "$cross_compiling" = yes; then :
+  # Try to guess by grepping values from an object file.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+short int ascii_mm[] =
+                 { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+               short int ascii_ii[] =
+                 { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+               int use_ascii (int i) {
+                 return ascii_mm[i] + ascii_ii[i];
+               }
+               short int ebcdic_ii[] =
+                 { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+               short int ebcdic_mm[] =
+                 { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+               int use_ebcdic (int i) {
+                 return ebcdic_mm[i] + ebcdic_ii[i];
+               }
+               extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+             ac_cv_c_bigendian=yes
+           fi
+           if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+             if test "$ac_cv_c_bigendian" = unknown; then
+               ac_cv_c_bigendian=no
+             else
+               # finding both strings is unlikely to happen, but who knows?
+               ac_cv_c_bigendian=unknown
+             fi
+           fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+            /* Are we little or big endian?  From Harbison&Steele.  */
+            union
+            {
+              long int l;
+              char c[sizeof (long int)];
+            } u;
+            u.l = 1;
+            return u.c[sizeof (long int) - 1] == 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_c_bigendian=no
+else
+  ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+   yes)
+     $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+   no)
+      ;; #(
+   universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+     ;; #(
+   *)
+     as_fn_error "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+  if test $ac_cv_c_bigendian = yes; then
+    sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN"
+  else
+    sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN"
+  fi
+else
+  sim_hostendian="-DWITH_HOST_BYTE_ORDER=0"
+fi
+fi
+
+
+default_sim_default_model="bf537"
+# Check whether --enable-sim-default-model was given.
+if test "${enable_sim_default_model+set}" = set; then :
+  enableval=$enable_sim_default_model; case "${enableval}" in
+  yes|no) as_fn_error "\"Missing argument to --enable-sim-default-model\"" "$LINENO" 5;;
+  *)   sim_default_model="-DWITH_DEFAULT_MODEL='\"${enableval}\"'";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_default_model" != x""; then
+  echo "Setting default model = $sim_default_model" 6>&1
+fi
+else
+  sim_default_model="-DWITH_DEFAULT_MODEL='\"${default_sim_default_model}\"'"
+fi
+
+
+
+# Check whether --enable-sim-environment was given.
+if test "${enable_sim_environment+set}" = set; then :
+  enableval=$enable_sim_environment; case "${enableval}" in
+  all | ALL)             sim_environment="-DWITH_ENVIRONMENT=ALL_ENVIRONMENT";;
+  user | USER)           sim_environment="-DWITH_ENVIRONMENT=USER_ENVIRONMENT";;
+  virtual | VIRTUAL)     sim_environment="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT";;
+  operating | OPERATING) sim_environment="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT";;
+  *)   as_fn_error "\"Unknown value $enableval passed to --enable-sim-environment\"" "$LINENO" 5;
+       sim_environment="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_environment" != x""; then
+  echo "Setting sim environment = $sim_environment" 6>&1
+fi
+else
+  sim_environment="-DWITH_ENVIRONMENT=ALL_ENVIRONMENT"
+fi
+
+
+default_sim_inline=""
+# Check whether --enable-sim-inline was given.
+if test "${enable_sim_inline+set}" = set; then :
+  enableval=$enable_sim_inline; sim_inline=""
+case "$enableval" in
+  no)          sim_inline="-DDEFAULT_INLINE=0";;
+  0)           sim_inline="-DDEFAULT_INLINE=0";;
+  yes | 2)     sim_inline="-DDEFAULT_INLINE=ALL_C_INLINE";;
+  1)           sim_inline="-DDEFAULT_INLINE=INLINE_LOCALS";;
+  *) for x in `echo "$enableval" | sed -e "s/,/ /g"`; do
+       new_flag=""
+       case "$x" in
+        *_INLINE=*)    new_flag="-D$x";;
+        *=*)           new_flag=`echo "$x" | sed -e "s/=/_INLINE=/" -e "s/^/-D/"`;;
+        *_INLINE)      new_flag="-D$x=ALL_C_INLINE";;
+        *)             new_flag="-D$x""_INLINE=ALL_C_INLINE";;
+       esac
+       if test x"$sim_inline" = x""; then
+        sim_inline="$new_flag"
+       else
+        sim_inline="$sim_inline $new_flag"
+       fi
+     done;;
+esac
+if test x"$silent" != x"yes" && test x"$sim_inline" != x""; then
+  echo "Setting inline flags = $sim_inline" 6>&1
+fi
+else
+
+if test "x$cross_compiling" = "xno"; then
+  if test x"$GCC" != "x" -a x"${default_sim_inline}" != "x" ; then
+    sim_inline="${default_sim_inline}"
+    if test x"$silent" != x"yes"; then
+      echo "Setting inline flags = $sim_inline" 6>&1
+    fi
+  else
+    sim_inline=""
+  fi
+else
+  sim_inline="-DDEFAULT_INLINE=0"
+fi
+fi
+
+
+# NOTE: Don't add -Wall or -Wunused, they both include
+# -Wunused-parameter which reports bogus warnings.
+# NOTE: If you add to this list, remember to update
+# gdb/doc/gdbint.texinfo.
+build_warnings="-Wimplicit -Wreturn-type -Wcomment -Wtrigraphs \
+-Wformat -Wparentheses -Wpointer-arith"
+# GCC supports -Wuninitialized only with -O or -On, n != 0.
+if test x${CFLAGS+set} = xset; then
+  case "${CFLAGS}" in
+    *"-O0"* ) ;;
+    *"-O"* )
+      build_warnings="${build_warnings} -Wuninitialized"
+    ;;
+  esac
+else
+  build_warnings="${build_warnings} -Wuninitialized"
+fi
+# Up for debate: -Wswitch -Wcomment -trigraphs -Wtrigraphs
+# -Wunused-function -Wunused-label -Wunused-variable -Wunused-value
+# -Wchar-subscripts -Wtraditional -Wshadow -Wcast-qual
+# -Wcast-align -Wwrite-strings -Wconversion -Wstrict-prototypes
+# -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls
+# -Woverloaded-virtual -Winline -Werror"
+# Check whether --enable-build-warnings was given.
+if test "${enable_build_warnings+set}" = set; then :
+  enableval=$enable_build_warnings; case "${enableval}" in
+  yes) ;;
+  no)  build_warnings="-w";;
+  ,*)   t=`echo "${enableval}" | sed -e "s/,/ /g"`
+        build_warnings="${build_warnings} ${t}";;
+  *,)   t=`echo "${enableval}" | sed -e "s/,/ /g"`
+        build_warnings="${t} ${build_warnings}";;
+  *)    build_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
+esac
+if test x"$silent" != x"yes" && test x"$build_warnings" != x""; then
+  echo "Setting compiler warning flags = $build_warnings" 6>&1
+fi
+fi
+# Check whether --enable-sim-build-warnings was given.
+if test "${enable_sim_build_warnings+set}" = set; then :
+  enableval=$enable_sim_build_warnings; case "${enableval}" in
+  yes) ;;
+  no)  build_warnings="-w";;
+  ,*)   t=`echo "${enableval}" | sed -e "s/,/ /g"`
+        build_warnings="${build_warnings} ${t}";;
+  *,)   t=`echo "${enableval}" | sed -e "s/,/ /g"`
+        build_warnings="${t} ${build_warnings}";;
+  *)    build_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
+esac
+if test x"$silent" != x"yes" && test x"$build_warnings" != x""; then
+  echo "Setting GDB specific compiler warning flags = $build_warnings" 6>&1
+fi
+fi
+WARN_CFLAGS=""
+WERROR_CFLAGS=""
+if test "x${build_warnings}" != x -a "x$GCC" = xyes
+then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking compiler warning flags" >&5
+$as_echo_n "checking compiler warning flags... " >&6; }
+    # Separate out the -Werror flag as some files just cannot be
+    # compiled with it enabled.
+    for w in ${build_warnings}; do
+       case $w in
+       -Werr*) WERROR_CFLAGS=-Werror ;;
+       *) # Check that GCC accepts it
+           saved_CFLAGS="$CFLAGS"
+           CFLAGS="$CFLAGS $w"
+           cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  WARN_CFLAGS="${WARN_CFLAGS} $w"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+           CFLAGS="$saved_CFLAGS"
+       esac
+    done
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${WARN_CFLAGS}${WERROR_CFLAGS}" >&5
+$as_echo "${WARN_CFLAGS}${WERROR_CFLAGS}" >&6; }
+fi
+
+
+if test x"yes" = x"yes"; then
+  sim_hw_p=yes
+else
+  sim_hw_p=no
+fi
+if test ""; then
+  hardware=""
+else
+  hardware="core pal glue"
+fi
+hardware="$hardware \
+       bfin_cec \
+       bfin_ctimer \
+       bfin_dma \
+       bfin_dmac \
+       bfin_ebiu_amc \
+       bfin_ebiu_ddrc \
+       bfin_ebiu_sdc \
+       bfin_emac \
+       bfin_eppi \
+       bfin_evt \
+       bfin_gptimer \
+       bfin_jtag \
+       bfin_mmu \
+       bfin_nfc \
+       bfin_otp \
+       bfin_pll \
+       bfin_ppi \
+       bfin_rtc \
+       bfin_sic \
+       bfin_spi \
+       bfin_trace \
+       bfin_twi \
+       bfin_uart \
+       bfin_uart2 \
+       bfin_wdog \
+       bfin_wp \
+       eth_phy \
+"
+sim_hw_cflags="-DWITH_HW=1"
+sim_hw="$hardware"
+sim_hw_objs="\$(SIM_COMMON_HW_OBJS) `echo $sim_hw | sed -e 's/\([^ ][^ ]*\)/dv-\1.o/g'`"
+# Check whether --enable-sim-hardware was given.
+if test "${enable_sim_hardware+set}" = set; then :
+  enableval=$enable_sim_hardware;
+case "${enableval}" in
+  yes) sim_hw_p=yes;;
+  no)  sim_hw_p=no;;
+  ,*)   sim_hw_p=yes; hardware="${hardware} `echo ${enableval} | sed -e 's/,/ /'`";;
+  *,)   sim_hw_p=yes; hardware="`echo ${enableval} | sed -e 's/,/ /'` ${hardware}";;
+  *)   sim_hw_p=yes; hardware="`echo ${enableval} | sed -e 's/,/ /'`"'';;
+esac
+if test "$sim_hw_p" != yes; then
+  sim_hw_objs=
+  sim_hw_cflags="-DWITH_HW=0"
+  sim_hw=
+else
+  sim_hw_cflags="-DWITH_HW=1"
+  # remove duplicates
+  sim_hw=""
+  sim_hw_objs="\$(SIM_COMMON_HW_OBJS)"
+  for i in $hardware ; do
+    case " $sim_hw " in
+      *" $i "*) ;;
+      *) sim_hw="$sim_hw $i" ; sim_hw_objs="$sim_hw_objs dv-$i.o";;
+    esac
+  done
+fi
+if test x"$silent" != x"yes" && test "$sim_hw_p" = "yes"; then
+  echo "Setting hardware to $sim_hw_cflags, $sim_hw, $sim_hw_objs"
+fi
+else
+
+if test "$sim_hw_p" != yes; then
+  sim_hw_objs=
+  sim_hw_cflags="-DWITH_HW=0"
+  sim_hw=
+fi
+if test x"$silent" != x"yes"; then
+  echo "Setting hardware to $sim_hw_cflags, $sim_hw, $sim_hw_objs"
+fi
+fi
+
+
+for ac_func in getuid getgid geteuid getegid setuid setgid mmap munmap
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+for ac_header in sys/ioctl.h sys/mman.h net/if.h linux/if_tun.h linux/mii.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+BFIN_SIM_EXTRA_OBJS=
+
+case ${host} in
+  *mingw32*) ;;
+  *)
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DV_SOCKSER 1
+_ACEOF
+
+    BFIN_SIM_EXTRA_OBJS="${BFIN_SIM_EXTRA_OBJS} dv-sockser.o"
+    ;;
+esac
+
+BFIN_SIM_EXTRA_OBJS=${BFIN_SIM_EXTRA_OBJS}
+
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+       if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_PKG_CONFIG+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+  ac_pt_PKG_CONFIG=$PKG_CONFIG
+  # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_PKG_CONFIG" = x; then
+    PKG_CONFIG=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    PKG_CONFIG=$ac_pt_PKG_CONFIG
+  fi
+else
+  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+       _pkg_min_version=0.9.0
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+       if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               PKG_CONFIG=""
+       fi
+fi
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDL" >&5
+$as_echo_n "checking for SDL... " >&6; }
+
+if test -n "$SDL_CFLAGS"; then
+    pkg_cv_SDL_CFLAGS="$SDL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sdl") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_SDL_CFLAGS=`$PKG_CONFIG --cflags "sdl" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$SDL_LIBS"; then
+    pkg_cv_SDL_LIBS="$SDL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sdl") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_SDL_LIBS=`$PKG_CONFIG --libs "sdl" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+               SDL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "sdl" 2>&1`
+        else
+               SDL_PKG_ERRORS=`$PKG_CONFIG --print-errors "sdl" 2>&1`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$SDL_PKG_ERRORS" >&5
+
+       :
+elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       :
+else
+       SDL_CFLAGS=$pkg_cv_SDL_CFLAGS
+       SDL_LIBS=$pkg_cv_SDL_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+
+               SDL_CFLAGS="${SDL_CFLAGS} -DHAVE_SDL"
+               SDL_LIBS="-ldl"
+
+else
+  SDL_CFLAGS= SDL_LIBS=
+fi
+
+
+fi
+
+
+
+
+ac_sources="$sim_link_files"
+ac_dests="$sim_link_links"
+while test -n "$ac_sources"; do
+  set $ac_dests; ac_dest=$1; shift; ac_dests=$*
+  set $ac_sources; ac_source=$1; shift; ac_sources=$*
+  ac_config_links_1="$ac_config_links_1 $ac_dest:$ac_source"
+done
+ac_config_links="$ac_config_links $ac_config_links_1"
+
+cgen_breaks=""
+if grep CGEN_MAINT $srcdir/Makefile.in >/dev/null; then
+cgen_breaks="break cgen_rtx_error";
+fi
+
+ac_config_files="$ac_config_files Makefile.sim:Makefile.in"
+
+ac_config_files="$ac_config_files Make-common.sim:../common/Make-common.in"
+
+ac_config_files="$ac_config_files .gdbinit:../common/gdbinit.in"
+
+ac_config_commands="$ac_config_commands Makefile"
+
+ac_config_commands="$ac_config_commands stamp-h"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+       expr "X$arg" : "X\\(.*\\)$as_nl";
+       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$?; test $as_status -eq 0 && as_status=1
+  if test "$3"; then
+    as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+  fi
+  $as_echo "$as_me: error: $1" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='        ';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+       test -d "$1/.";
+      else
+       case $1 in #(
+       -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.64.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_links="$ac_config_links"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration links:
+$config_links
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.64,
+  with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:config.in" ;;
+    "$ac_config_links_1") CONFIG_LINKS="$CONFIG_LINKS $ac_config_links_1" ;;
+    "Makefile.sim") CONFIG_FILES="$CONFIG_FILES Makefile.sim:Makefile.in" ;;
+    "Make-common.sim") CONFIG_FILES="$CONFIG_FILES Make-common.sim:../common/Make-common.in" ;;
+    ".gdbinit") CONFIG_FILES="$CONFIG_FILES .gdbinit:../common/gdbinit.in" ;;
+    "Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS Makefile" ;;
+    "stamp-h") CONFIG_COMMANDS="$CONFIG_COMMANDS stamp-h" ;;
+
+  *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\).*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\).*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = "\a"
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+  || as_fn_error "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[    ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[      ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_t=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_t"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[    ]*#[    ]*define[       ][      ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = "\a"
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS  :L $CONFIG_LINKS  :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+        # (if the path is not absolute).  The absolute path cannot be DOS-style,
+        # because $ac_f cannot contain `:'.
+        test -f "$ac_f" ||
+          case $ac_f in
+          [\\/$]*) false;;
+          *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+          esac ||
+          as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+         $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+       `' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin" \
+      || as_fn_error "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+  || as_fn_error "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[         ]*datarootdir[  ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out" && rm -f "$tmp/out";;
+  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
+    } >"$tmp/config.h" \
+      || as_fn_error "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$tmp/config.h" "$ac_file" \
+       || as_fn_error "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error "could not create -" "$LINENO" 5
+  fi
+ ;;
+  :L)
+  #
+  # CONFIG_LINK
+  #
+
+  if test "$ac_source" = "$ac_file" && test "$srcdir" = '.'; then
+    :
+  else
+    # Prefer the file from the source tree if names are identical.
+    if test "$ac_source" = "$ac_file" || test ! -r "$ac_source"; then
+      ac_source=$srcdir/$ac_source
+    fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: linking $ac_source to $ac_file" >&5
+$as_echo "$as_me: linking $ac_source to $ac_file" >&6;}
+
+    if test ! -r "$ac_source"; then
+      as_fn_error "$ac_source: file not found" "$LINENO" 5
+    fi
+    rm -f "$ac_file"
+
+    # Try a relative symlink, then a hard link, then a copy.
+    case $srcdir in
+    [\\/$]* | ?:[\\/]* ) ac_rel_source=$ac_source ;;
+       *) ac_rel_source=$ac_top_build_prefix$ac_source ;;
+    esac
+    ln -s "$ac_rel_source" "$ac_file" 2>/dev/null ||
+      ln "$ac_source" "$ac_file" 2>/dev/null ||
+      cp -p "$ac_source" "$ac_file" ||
+      as_fn_error "cannot link or copy $ac_source to $ac_file" "$LINENO" 5
+  fi
+ ;;
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "Makefile":C) echo "Merging Makefile.sim+Make-common.sim into Makefile ..."
+ rm -f Makesim1.tmp Makesim2.tmp Makefile
+ sed -n -e '/^## COMMON_PRE_/,/^## End COMMON_PRE_/ p' <Make-common.sim >Makesim1.tmp
+ sed -n -e '/^## COMMON_POST_/,/^## End COMMON_POST_/ p' <Make-common.sim >Makesim2.tmp
+ sed -e '/^## COMMON_PRE_/ r Makesim1.tmp' \
+       -e '/^## COMMON_POST_/ r Makesim2.tmp' \
+       <Makefile.sim >Makefile
+ rm -f Makefile.sim Make-common.sim Makesim1.tmp Makesim2.tmp
+ ;;
+    "stamp-h":C) echo > stamp-h ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit $?
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
diff --git a/sim/bfin/configure.ac b/sim/bfin/configure.ac
new file mode 100644 (file)
index 0000000..736a212
--- /dev/null
@@ -0,0 +1,75 @@
+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)
+
+# Bugs in autoconf 2.59 break the call to SIM_AC_COMMON, hack around
+# it by inlining the macro's contents.
+sinclude(../common/common.m4)
+
+SIM_AC_OPTION_ENDIAN(LITTLE_ENDIAN)
+SIM_AC_OPTION_ALIGNMENT(STRICT_ALIGNMENT,STRICT_ALIGNMENT)
+SIM_AC_OPTION_HOSTENDIAN
+SIM_AC_OPTION_DEFAULT_MODEL(bf537)
+SIM_AC_OPTION_ENVIRONMENT
+SIM_AC_OPTION_INLINE
+SIM_AC_OPTION_WARNINGS
+SIM_AC_OPTION_HARDWARE(yes,,\
+       bfin_cec \
+       bfin_ctimer \
+       bfin_dma \
+       bfin_dmac \
+       bfin_ebiu_amc \
+       bfin_ebiu_ddrc \
+       bfin_ebiu_sdc \
+       bfin_emac \
+       bfin_eppi \
+       bfin_evt \
+       bfin_gptimer \
+       bfin_jtag \
+       bfin_mmu \
+       bfin_nfc \
+       bfin_otp \
+       bfin_pll \
+       bfin_ppi \
+       bfin_rtc \
+       bfin_sic \
+       bfin_spi \
+       bfin_trace \
+       bfin_twi \
+       bfin_uart \
+       bfin_uart2 \
+       bfin_wdog \
+       bfin_wp \
+       eth_phy \
+)
+
+AC_CHECK_FUNCS([getuid getgid geteuid getegid setuid setgid mmap munmap])
+AC_CHECK_HEADERS([sys/ioctl.h sys/mman.h net/if.h linux/if_tun.h linux/mii.h])
+
+BFIN_SIM_EXTRA_OBJS=
+
+dnl make sure the dv-sockser code can be supported (i.e. windows)
+case ${host} in
+  *mingw32*) ;;
+  *)
+    AC_DEFINE_UNQUOTED([HAVE_DV_SOCKSER], 1, [Define if dv-sockser is usable.])
+    BFIN_SIM_EXTRA_OBJS="${BFIN_SIM_EXTRA_OBJS} dv-sockser.o"
+    ;;
+esac
+
+AC_SUBST([BFIN_SIM_EXTRA_OBJS], ${BFIN_SIM_EXTRA_OBJS})
+
+PKG_PROG_PKG_CONFIG
+PKG_CHECK_MODULES(SDL, sdl, [
+       AC_CHECK_LIB(dl, dlopen, [
+               SDL_CFLAGS="${SDL_CFLAGS} -DHAVE_SDL"
+               SDL_LIBS="-ldl"
+               ], [SDL_CFLAGS= SDL_LIBS=])
+       ], [:])
+AC_SUBST(SDL_CFLAGS)
+AC_SUBST(SDL_LIBS)
+
+SIM_AC_OUTPUT
diff --git a/sim/bfin/devices.c b/sim/bfin/devices.c
new file mode 100644 (file)
index 0000000..50c53d1
--- /dev/null
@@ -0,0 +1,163 @@
+/* Blackfin device support.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "sim-hw.h"
+#include "hw-device.h"
+#include "dv-bfin_cec.h"
+#include "dv-bfin_mmu.h"
+
+static void
+bfin_mmr_invalid (struct hw *me, SIM_CPU *cpu, address_word addr,
+                 unsigned nr_bytes, bool write)
+{
+  if (!cpu)
+    cpu = hw_system_cpu (me);
+
+  /* Only throw a fit if the cpu is doing the access.  DMA/GDB simply
+     go unnoticed.  Not exactly hardware behavior, but close enough.  */
+  if (!cpu)
+    {
+      sim_io_eprintf (hw_system (me), "%s: invalid MMR access @ %#x\n",
+                     hw_path (me), addr);
+      return;
+    }
+
+  HW_TRACE ((me, "invalid MMR %s to 0x%08lx length %u",
+            write ? "write" : "read", (unsigned long) addr, nr_bytes));
+
+  /* XXX: is this what hardware does ?  */
+  if (addr >= BFIN_CORE_MMR_BASE)
+    /* XXX: This should be setting up CPLB fault addrs ?  */
+    mmu_process_fault (cpu, addr, write, false, false, true);
+  else
+    /* XXX: Newer parts set up an interrupt from EBIU and program
+            EBIU_ERRADDR with the address.  */
+    cec_hwerr (cpu, HWERR_SYSTEM_MMR);
+}
+
+void
+dv_bfin_mmr_invalid (struct hw *me, address_word addr, unsigned nr_bytes,
+                    bool write)
+{
+  bfin_mmr_invalid (me, NULL, addr, nr_bytes, write);
+}
+
+void
+dv_bfin_mmr_require (struct hw *me, address_word addr, unsigned nr_bytes,
+                    unsigned size, bool write)
+{
+  if (nr_bytes != size)
+    dv_bfin_mmr_invalid (me, addr, nr_bytes, write);
+}
+
+static bool
+bfin_mmr_check (struct hw *me, SIM_CPU *cpu, address_word addr,
+               unsigned nr_bytes, bool write)
+{
+  if (addr >= BFIN_CORE_MMR_BASE)
+    {
+      /* All Core MMRs are aligned 32bits.  */
+      if ((addr & 3) == 0 && nr_bytes == 4)
+       return true;
+    }
+  else if (addr >= BFIN_SYSTEM_MMR_BASE)
+    {
+      /* All System MMRs are 32bit aligned, but can be 16bits or 32bits.  */
+      if ((addr & 0x3) == 0 && (nr_bytes == 2 || nr_bytes == 4))
+       return true;
+    }
+  else
+    return true;
+
+  /* Still here ?  Must be crap.  */
+  bfin_mmr_invalid (me, cpu, addr, nr_bytes, write);
+
+  return false;
+}
+
+bool
+dv_bfin_mmr_check (struct hw *me, address_word addr, unsigned nr_bytes,
+                  bool write)
+{
+  return bfin_mmr_check (me, NULL, addr, nr_bytes, write);
+}
+
+int
+device_io_read_buffer (device *me, void *source, int space,
+                      address_word addr, unsigned nr_bytes,
+                      SIM_DESC sd, SIM_CPU *cpu, sim_cia cia)
+{
+  struct hw *dv_me = (struct hw *) me;
+
+  if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
+    return nr_bytes;
+
+  if (bfin_mmr_check (dv_me, cpu, addr, nr_bytes, false))
+    if (cpu)
+      {
+       sim_cpu_hw_io_read_buffer (cpu, cia, dv_me, source, space,
+                                  addr, nr_bytes);
+       return nr_bytes;
+      }
+    else
+      return sim_hw_io_read_buffer (sd, dv_me, source, space, addr, nr_bytes);
+  else
+    return 0;
+}
+
+int
+device_io_write_buffer (device *me, const void *source, int space,
+                       address_word addr, unsigned nr_bytes,
+                        SIM_DESC sd, SIM_CPU *cpu, sim_cia cia)
+{
+  struct hw *dv_me = (struct hw *) me;
+
+  if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
+    return nr_bytes;
+
+  if (bfin_mmr_check (dv_me, cpu, addr, nr_bytes, true))
+    if (cpu)
+      {
+       sim_cpu_hw_io_write_buffer (cpu, cia, dv_me, source, space,
+                                   addr, nr_bytes);
+       return nr_bytes;
+      }
+    else
+      return sim_hw_io_write_buffer (sd, dv_me, source, space, addr, nr_bytes);
+  else
+    return 0;
+}
+
+void device_error (device *me, const char *message, ...)
+{
+  /* Don't bother doing anything here -- any place in common code that
+     calls device_error() follows it with sim_hw_abort().  Since the
+     device isn't bound to the system yet, we can't call any common
+     hardware error funcs on it or we'll hit a NULL pointer.  */
+}
+
+unsigned int dv_get_bus_num (struct hw *me)
+{
+  const hw_unit *unit = hw_unit_address (me);
+  return unit->cells[unit->nr_cells - 1];
+}
diff --git a/sim/bfin/devices.h b/sim/bfin/devices.h
new file mode 100644 (file)
index 0000000..76854ed
--- /dev/null
@@ -0,0 +1,156 @@
+/* Common Blackfin device stuff.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DEVICES_H
+#define DEVICES_H
+
+#include "hw-base.h"
+#include "hw-main.h"
+#include "hw-device.h"
+#include "hw-tree.h"
+
+/* We keep the same inital structure layout with DMA enabled devices.  */
+struct dv_bfin {
+  bu32 base;
+  struct hw *dma_master;
+  bool acked;
+};
+
+#define BFIN_MMR_16(mmr) mmr, __pad_##mmr
+
+/* Most peripherals have either one interrupt or these three.  */
+#define DV_PORT_TX   0
+#define DV_PORT_RX   1
+#define DV_PORT_STAT 2
+
+unsigned int dv_get_bus_num (struct hw *);
+\f
+static inline bu8 dv_load_1 (const void *ptr)
+{
+  const unsigned char *c = ptr;
+  return c[0];
+}
+
+static inline void dv_store_1 (void *ptr, bu8 val)
+{
+  unsigned char *c = ptr;
+  c[0] = val;
+}
+
+static inline bu16 dv_load_2 (const void *ptr)
+{
+  const unsigned char *c = ptr;
+  return (c[1] << 8) | dv_load_1 (ptr);
+}
+
+static inline void dv_store_2 (void *ptr, bu16 val)
+{
+  unsigned char *c = ptr;
+  c[1] = val >> 8;
+  dv_store_1 (ptr, val);
+}
+
+static inline bu32 dv_load_4 (const void *ptr)
+{
+  const unsigned char *c = ptr;
+  return (c[3] << 24) | (c[2] << 16) | dv_load_2 (ptr);
+}
+
+static inline void dv_store_4 (void *ptr, bu32 val)
+{
+  unsigned char *c = ptr;
+  c[3] = val >> 24;
+  c[2] = val >> 16;
+  dv_store_2 (ptr, val);
+}
+\f
+/* Helpers for MMRs where all bits are W1C except for the specified
+   bits -- those ones are RO.  */
+#define dv_w1c(ptr, val, bits) (*(ptr) &= ~((val) & (bits)))
+static inline void dv_w1c_2 (bu16 *ptr, bu16 val, bu16 bits)
+{
+  dv_w1c (ptr, val, bits);
+}
+static inline void dv_w1c_4 (bu32 *ptr, bu32 val, bu32 bits)
+{
+  dv_w1c (ptr, val, bits);
+}
+
+/* Helpers for MMRs where all bits are RW except for the specified
+   bits -- those ones are W1C.  */
+#define dv_w1c_partial(ptr, val, bits) \
+  (*(ptr) = ((val) | (*(ptr) & (bits))) & ~((val) & (bits)))
+static inline void dv_w1c_2_partial (bu16 *ptr, bu16 val, bu16 bits)
+{
+  dv_w1c_partial (ptr, val, bits);
+}
+static inline void dv_w1c_4_partial (bu32 *ptr, bu32 val, bu32 bits)
+{
+  dv_w1c_partial (ptr, val, bits);
+}
+\f
+/* XXX: Grubbing around in device internals is probably wrong, but
+        until someone shows me what's right ...  */
+static inline struct hw *
+dv_get_device (SIM_CPU *cpu, const char *device_name)
+{
+  SIM_DESC sd = CPU_STATE (cpu);
+  void *root = STATE_HW (sd);
+  return hw_tree_find_device (root, device_name);
+}
+
+static inline void *
+dv_get_state (SIM_CPU *cpu, const char *device_name)
+{
+  return hw_data (dv_get_device (cpu, device_name));
+}
+
+#define DV_STATE(cpu, dv) dv_get_state (cpu, "/core/bfin_"#dv)
+
+#define DV_STATE_CACHED(cpu, dv) \
+  ({ \
+    struct bfin_##dv *__##dv = BFIN_CPU_STATE.dv##_cache; \
+    if (!__##dv) \
+      BFIN_CPU_STATE.dv##_cache = __##dv = dv_get_state (cpu, "/core/bfin_"#dv); \
+    __##dv; \
+  })
+\f
+void dv_bfin_mmr_invalid (struct hw *, address_word, unsigned nr_bytes, bool write);
+void dv_bfin_mmr_require (struct hw *, address_word, unsigned nr_bytes, unsigned size, bool write);
+bool dv_bfin_mmr_check (struct hw *, address_word, unsigned nr_bytes, bool write);
+
+#define dv_bfin_mmr_require_16(hw, addr, nr_bytes, write) dv_bfin_mmr_require (hw, addr, nr_bytes, 2, write)
+#define dv_bfin_mmr_require_32(hw, addr, nr_bytes, write) dv_bfin_mmr_require (hw, addr, nr_bytes, 4, write)
+\f
+#define HW_TRACE_WRITE() \
+  HW_TRACE ((me, "write 0x%08lx (%s) length %u with 0x%x", \
+            (unsigned long) addr, mmr_name (mmr_off), nr_bytes, value))
+#define HW_TRACE_READ() \
+  HW_TRACE ((me, "read 0x%08lx (%s) length %u", \
+            (unsigned long) addr, mmr_name (mmr_off), nr_bytes))
+
+#define HW_TRACE_DMA_WRITE() \
+  HW_TRACE ((me, "dma write 0x%08lx length %u", \
+            (unsigned long) addr, nr_bytes))
+#define HW_TRACE_DMA_READ() \
+  HW_TRACE ((me, "dma read 0x%08lx length %u", \
+            (unsigned long) addr, nr_bytes))
+
+#endif
diff --git a/sim/bfin/dv-bfin_cec.c b/sim/bfin/dv-bfin_cec.c
new file mode 100644 (file)
index 0000000..88fe9dd
--- /dev/null
@@ -0,0 +1,807 @@
+/* Blackfin Core Event Controller (CEC) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_cec.h"
+#include "dv-bfin_evt.h"
+#include "dv-bfin_mmu.h"
+
+struct bfin_cec
+{
+  bu32 base;
+  SIM_CPU *cpu;
+  struct hw *me;
+  struct hw_event *pending;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu32 evt_override, imask, ipend, ilat, iprio;
+};
+#define mmr_base()      offsetof(struct bfin_cec, evt_override)
+#define mmr_offset(mmr) (offsetof(struct bfin_cec, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "EVT_OVERRIDE", "IMASK", "IPEND", "ILAT", "IPRIO",
+};
+#define mmr_name(off) mmr_names[(off) / 4]
+
+static void _cec_raise (SIM_CPU *, struct bfin_cec *, int);
+
+static void
+bfin_cec_hw_event_callback (struct hw *me, void *data)
+{
+  struct bfin_cec *cec = data;
+  hw_event_queue_deschedule (me, cec->pending);
+  _cec_raise (cec->cpu, cec, -1);
+  cec->pending = NULL;
+}
+static void
+bfin_cec_check_pending (struct hw *me, struct bfin_cec *cec)
+{
+  if (cec->pending)
+    return;
+  cec->pending = hw_event_queue_schedule (me, 0, bfin_cec_hw_event_callback, cec);
+}
+static void
+_cec_check_pending (SIM_CPU *cpu, struct bfin_cec *cec)
+{
+  bfin_cec_check_pending (cec->me, cec);
+}
+
+static void
+_cec_imask_write (struct bfin_cec *cec, bu32 value)
+{
+  cec->imask = (value & IVG_MASKABLE_B) | (cec->imask & IVG_UNMASKABLE_B);
+}
+
+static unsigned
+bfin_cec_io_write_buffer (struct hw *me, const void *source,
+                         int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_cec *cec = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+
+  value = dv_load_4 (source);
+  mmr_off = addr - cec->base;
+
+  HW_TRACE_WRITE ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(evt_override):
+      cec->evt_override = value;
+      break;
+    case mmr_offset(imask):
+      _cec_imask_write (cec, value);
+      bfin_cec_check_pending (me, cec);
+      break;
+    case mmr_offset(ipend):
+      /* Read-only register.  */
+      break;
+    case mmr_offset(ilat):
+      dv_w1c_4 (&cec->ilat, value, 0);
+      break;
+    case mmr_offset(iprio):
+      cec->iprio = (value & IVG_UNMASKABLE_B);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_cec_io_read_buffer (struct hw *me, void *dest,
+                        int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_cec *cec = hw_data (me);
+  bu32 mmr_off;
+  bu32 *valuep;
+
+  mmr_off = addr - cec->base;
+  valuep = (void *)((unsigned long)cec + mmr_base() + mmr_off);
+
+  HW_TRACE_READ ();
+
+  dv_store_4 (dest, *valuep);
+
+  return nr_bytes;
+}
+
+static const struct hw_port_descriptor bfin_cec_ports[] = {
+  { "emu",   IVG_EMU,   0, input_port, },
+  { "rst",   IVG_RST,   0, input_port, },
+  { "nmi",   IVG_NMI,   0, input_port, },
+  { "evx",   IVG_EVX,   0, input_port, },
+  { "ivhw",  IVG_IVHW,  0, input_port, },
+  { "ivtmr", IVG_IVTMR, 0, input_port, },
+  { "ivg7",  IVG7,      0, input_port, },
+  { "ivg8",  IVG8,      0, input_port, },
+  { "ivg9",  IVG9,      0, input_port, },
+  { "ivg10", IVG10,     0, input_port, },
+  { "ivg11", IVG11,     0, input_port, },
+  { "ivg12", IVG12,     0, input_port, },
+  { "ivg13", IVG13,     0, input_port, },
+  { "ivg14", IVG14,     0, input_port, },
+  { "ivg15", IVG15,     0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+bfin_cec_port_event (struct hw *me, int my_port, struct hw *source,
+                    int source_port, int level)
+{
+  struct bfin_cec *cec = hw_data (me);
+  _cec_raise (cec->cpu, cec, my_port);
+}
+
+static void
+attach_bfin_cec_regs (struct hw *me, struct bfin_cec *cec)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_COREMMR_CEC_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_COREMMR_CEC_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  cec->base = attach_address;
+  /* XXX: should take from the device tree.  */
+  cec->cpu = STATE_CPU (hw_system (me), 0);
+  cec->me = me;
+}
+
+static void
+bfin_cec_finish (struct hw *me)
+{
+  struct bfin_cec *cec;
+
+  cec = HW_ZALLOC (me, struct bfin_cec);
+
+  set_hw_data (me, cec);
+  set_hw_io_read_buffer (me, bfin_cec_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_cec_io_write_buffer);
+  set_hw_ports (me, bfin_cec_ports);
+  set_hw_port_event (me, bfin_cec_port_event);
+
+  attach_bfin_cec_regs (me, cec);
+
+  /* Initialize the CEC.  */
+  cec->imask = IVG_UNMASKABLE_B;
+  cec->ipend = IVG_RST_B | IVG_IRPTEN_B;
+}
+
+const struct hw_descriptor dv_bfin_cec_descriptor[] = {
+  {"bfin_cec", bfin_cec_finish,},
+  {NULL, NULL},
+};
+
+static const char * const excp_decoded[] = {
+  [VEC_SYS        ] = "Custom exception 0 (system call)",
+  [VEC_EXCPT01    ] = "Custom exception 1 (software breakpoint)",
+  [VEC_EXCPT02    ] = "Custom exception 2 (KGDB hook)",
+  [VEC_EXCPT03    ] = "Custom exception 3 (userspace stack overflow)",
+  [VEC_EXCPT04    ] = "Custom exception 4 (dump trace buffer)",
+  [VEC_EXCPT05    ] = "Custom exception 5",
+  [VEC_EXCPT06    ] = "Custom exception 6",
+  [VEC_EXCPT07    ] = "Custom exception 7",
+  [VEC_EXCPT08    ] = "Custom exception 8",
+  [VEC_EXCPT09    ] = "Custom exception 9",
+  [VEC_EXCPT10    ] = "Custom exception 10",
+  [VEC_EXCPT11    ] = "Custom exception 11",
+  [VEC_EXCPT12    ] = "Custom exception 12",
+  [VEC_EXCPT13    ] = "Custom exception 13",
+  [VEC_EXCPT14    ] = "Custom exception 14",
+  [VEC_EXCPT15    ] = "Custom exception 15",
+  [VEC_STEP       ] = "Hardware single step",
+  [VEC_OVFLOW     ] = "Trace buffer overflow",
+  [VEC_UNDEF_I    ] = "Undefined instruction",
+  [VEC_ILGAL_I    ] = "Illegal instruction combo (multi-issue)",
+  [VEC_CPLB_VL    ] = "DCPLB protection violation",
+  [VEC_MISALI_D   ] = "Unaligned data access",
+  [VEC_UNCOV      ] = "Unrecoverable event (double fault)",
+  [VEC_CPLB_M     ] = "DCPLB miss",
+  [VEC_CPLB_MHIT  ] = "Multiple DCPLB hit",
+  [VEC_WATCH      ] = "Watchpoint match",
+  [VEC_ISTRU_VL   ] = "ADSP-BF535 only",
+  [VEC_MISALI_I   ] = "Unaligned instruction access",
+  [VEC_CPLB_I_VL  ] = "ICPLB protection violation",
+  [VEC_CPLB_I_M   ] = "ICPLB miss",
+  [VEC_CPLB_I_MHIT] = "Multiple ICPLB hit",
+  [VEC_ILL_RES    ] = "Illegal supervisor resource",
+};
+
+#define CEC_STATE(cpu) DV_STATE_CACHED (cpu, cec)
+
+#define __cec_get_ivg(val) (ffs ((val) & ~IVG_IRPTEN_B) - 1)
+#define _cec_get_ivg(cec) __cec_get_ivg ((cec)->ipend & ~IVG_EMU_B)
+
+int
+cec_get_ivg (SIM_CPU *cpu)
+{
+  switch (STATE_ENVIRONMENT (CPU_STATE (cpu)))
+    {
+    case OPERATING_ENVIRONMENT:
+      return _cec_get_ivg (CEC_STATE (cpu));
+    default:
+      return IVG_USER;
+    }
+}
+
+static bool
+_cec_is_supervisor_mode (struct bfin_cec *cec)
+{
+  return (cec->ipend & ~(IVG_EMU_B | IVG_IRPTEN_B));
+}
+bool
+cec_is_supervisor_mode (SIM_CPU *cpu)
+{
+  switch (STATE_ENVIRONMENT (CPU_STATE (cpu)))
+    {
+    case OPERATING_ENVIRONMENT:
+      return _cec_is_supervisor_mode (CEC_STATE (cpu));
+    case USER_ENVIRONMENT:
+      return false;
+    default:
+      return true;
+    }
+}
+static bool
+_cec_is_user_mode (struct bfin_cec *cec)
+{
+  return !_cec_is_supervisor_mode (cec);
+}
+bool
+cec_is_user_mode (SIM_CPU *cpu)
+{
+  return !cec_is_supervisor_mode (cpu);
+}
+static void
+_cec_require_supervisor (SIM_CPU *cpu, struct bfin_cec *cec)
+{
+  if (_cec_is_user_mode (cec))
+    cec_exception (cpu, VEC_ILL_RES);
+}
+void
+cec_require_supervisor (SIM_CPU *cpu)
+{
+  /* Do not call _cec_require_supervisor() to avoid CEC_STATE()
+     as that macro requires OS operating mode.  */
+  if (cec_is_user_mode (cpu))
+    cec_exception (cpu, VEC_ILL_RES);
+}
+
+#define excp_to_sim_halt(reason, sigrc) \
+  sim_engine_halt (CPU_STATE (cpu), cpu, NULL, PCREG, reason, sigrc)
+void
+cec_exception (SIM_CPU *cpu, int excp)
+{
+  SIM_DESC sd = CPU_STATE (cpu);
+  int sigrc = -1;
+
+  TRACE_EVENTS (cpu, "processing exception %#x in EVT%i", excp,
+               cec_get_ivg (cpu));
+
+  /* Ideally what would happen here for real hardware exceptions (not
+     fake sim ones) is that:
+      - For service exceptions (excp <= 0x11):
+         RETX is the _next_ PC which can be tricky with jumps/hardware loops/...
+      - For error exceptions (excp > 0x11):
+         RETX is the _current_ PC (i.e. the one causing the exception)
+      - PC is loaded with EVT3 MMR
+      - ILAT/IPEND in CEC is updated depending on current IVG level
+      - the fault address MMRs get updated with data/instruction info
+      - Execution continues on in the EVT3 handler  */
+
+  /* Handle simulator exceptions first.  */
+  switch (excp)
+    {
+    case VEC_SIM_HLT:
+      excp_to_sim_halt (sim_exited, 0);
+      return;
+    case VEC_SIM_ABORT:
+      excp_to_sim_halt (sim_exited, 1);
+      return;
+    case VEC_SIM_TRAP:
+      /* GDB expects us to step over EMUEXCPT.  */
+      /* XXX: What about hwloops and EMUEXCPT at the end?
+              Pretty sure gdb doesn't handle this already...  */
+      SET_PCREG (PCREG + 2);
+      /* Only trap when we are running in gdb.  */
+      if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
+       excp_to_sim_halt (sim_stopped, SIM_SIGTRAP);
+      return;
+    case VEC_SIM_DBGA:
+      /* If running in gdb, simply trap.  */
+      if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
+       excp_to_sim_halt (sim_stopped, SIM_SIGTRAP);
+      else
+       excp_to_sim_halt (sim_exited, 2);
+    }
+
+  if (excp <= 0x3f)
+    {
+      SET_EXCAUSE (excp);
+      if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
+       {
+         /* ICPLB regs always get updated.  */
+         /* XXX: Should optimize this call path ...  */
+         if (excp != VEC_MISALI_I && excp != VEC_MISALI_D
+             && excp != VEC_CPLB_I_M && excp != VEC_CPLB_M
+             && excp != VEC_CPLB_I_VL && excp != VEC_CPLB_VL
+             && excp != VEC_CPLB_I_MHIT && excp != VEC_CPLB_MHIT)
+           mmu_log_ifault (cpu);
+         _cec_raise (cpu, CEC_STATE (cpu), IVG_EVX);
+         /* We need to restart the engine so that we don't return
+            and continue processing this bad insn.  */
+         if (EXCAUSE >= 0x20)
+           sim_engine_restart (sd, cpu, NULL, PCREG);
+         return;
+       }
+    }
+
+  TRACE_EVENTS (cpu, "running virtual exception handler");
+
+  switch (excp)
+    {
+    case VEC_SYS:
+      bfin_syscall (cpu);
+      break;
+
+    case VEC_EXCPT01:  /* Userspace gdb breakpoint.  */
+      sigrc = SIM_SIGTRAP;
+      break;
+
+    case VEC_UNDEF_I:  /* Undefined instruction.  */
+      sigrc = SIM_SIGILL;
+      break;
+
+    case VEC_ILL_RES:  /* Illegal supervisor resource.  */
+    case VEC_MISALI_I: /* Misaligned instruction.  */
+      sigrc = SIM_SIGBUS;
+      break;
+
+    case VEC_CPLB_M:
+    case VEC_CPLB_I_M:
+      sigrc = SIM_SIGSEGV;
+      break;
+
+    default:
+      sim_io_eprintf (sd, "Unhandled exception %#x at 0x%08x (%s)\n",
+                     excp, PCREG, excp_decoded[excp]);
+      sigrc = SIM_SIGILL;
+      break;
+    }
+
+  if (sigrc != -1)
+    excp_to_sim_halt (sim_stopped, sigrc);
+}
+
+bu32 cec_cli (SIM_CPU *cpu)
+{
+  struct bfin_cec *cec;
+  bu32 old_mask;
+
+  if (STATE_ENVIRONMENT (CPU_STATE (cpu)) != OPERATING_ENVIRONMENT)
+    return 0;
+
+  cec = CEC_STATE (cpu);
+  _cec_require_supervisor (cpu, cec);
+
+  /* XXX: what about IPEND[4] ?  */
+  old_mask = cec->imask;
+  _cec_imask_write (cec, 0);
+
+  TRACE_EVENTS (cpu, "CLI changed IMASK from %#x to %#x", old_mask, cec->imask);
+
+  return old_mask;
+}
+
+void cec_sti (SIM_CPU *cpu, bu32 ints)
+{
+  struct bfin_cec *cec;
+  bu32 old_mask;
+
+  if (STATE_ENVIRONMENT (CPU_STATE (cpu)) != OPERATING_ENVIRONMENT)
+    return;
+
+  cec = CEC_STATE (cpu);
+  _cec_require_supervisor (cpu, cec);
+
+  /* XXX: what about IPEND[4] ?  */
+  old_mask = cec->imask;
+  _cec_imask_write (cec, ints);
+
+  TRACE_EVENTS (cpu, "STI changed IMASK from %#x to %#x", old_mask, cec->imask);
+
+  /* Check for pending interrupts that are now enabled.  */
+  _cec_check_pending (cpu, cec);
+}
+
+static void
+cec_irpten_enable (SIM_CPU *cpu, struct bfin_cec *cec)
+{
+  /* Globally mask interrupts.  */
+  TRACE_EVENTS (cpu, "setting IPEND[4] to globally mask interrupts");
+  cec->ipend |= IVG_IRPTEN_B;
+}
+
+static void
+cec_irpten_disable (SIM_CPU *cpu, struct bfin_cec *cec)
+{
+  /* Clear global interrupt mask.  */
+  TRACE_EVENTS (cpu, "clearing IPEND[4] to not globally mask interrupts");
+  cec->ipend &= ~IVG_IRPTEN_B;
+}
+
+static void
+_cec_raise (SIM_CPU *cpu, struct bfin_cec *cec, int ivg)
+{
+  SIM_DESC sd = CPU_STATE (cpu);
+  int curr_ivg = _cec_get_ivg (cec);
+  bool snen;
+  bool irpten;
+
+  TRACE_EVENTS (cpu, "processing request for EVT%i while at EVT%i",
+               ivg, curr_ivg);
+
+  irpten = (cec->ipend & IVG_IRPTEN_B);
+  snen = (SYSCFGREG & SYSCFG_SNEN);
+
+  if (curr_ivg == -1)
+    curr_ivg = IVG_USER;
+
+  /* Just check for higher latched interrupts.  */
+  if (ivg == -1)
+    {
+      if (irpten)
+       goto done; /* All interrupts are masked anyways.  */
+
+      ivg = __cec_get_ivg (cec->ilat & cec->imask);
+      if (ivg < 0)
+       goto done; /* Nothing latched.  */
+
+      if (ivg > curr_ivg)
+       goto done; /* Nothing higher latched.  */
+
+      if (!snen && ivg == curr_ivg)
+       goto done; /* Self nesting disabled.  */
+
+      /* Still here, so fall through to raise to higher pending.  */
+    }
+
+  cec->ilat |= (1 << ivg);
+
+  if (ivg <= IVG_EVX)
+    {
+      /* These two are always processed.  */
+      if (ivg == IVG_EMU || ivg == IVG_RST)
+       goto process_int;
+
+      /* Anything lower might trigger a double fault.  */
+      if (curr_ivg <= ivg)
+       {
+         /* Double fault ! :(  */
+         SET_EXCAUSE (VEC_UNCOV);
+         /* XXX: SET_RETXREG (...);  */
+         sim_io_error (sd, "%s: double fault at 0x%08x ! :(", __func__, PCREG);
+         excp_to_sim_halt (sim_stopped, SIM_SIGABRT);
+       }
+
+      /* No double fault -> always process.  */
+      goto process_int;
+    }
+  else if (irpten && curr_ivg != IVG_USER)
+    {
+      /* Interrupts are globally masked.  */
+    }
+  else if (!(cec->imask & (1 << ivg)))
+    {
+      /* This interrupt is masked.  */
+    }
+  else if (ivg < curr_ivg || (snen && ivg == curr_ivg))
+    {
+      /* Do transition!  */
+      bu32 oldpc;
+
+ process_int:
+      cec->ipend |= (1 << ivg);
+      cec->ilat &= ~(1 << ivg);
+
+      /* Interrupts are processed in between insns which means the return
+         point is the insn-to-be-executed (which is the current PC).  But
+         exceptions are handled while executing an insn, so we may have to
+         advance the PC ourselves when setting RETX.
+         XXX: Advancing the PC should only be for "service" exceptions, and
+              handling them after executing the insn should be OK, which
+              means we might be able to use the event interface for it.  */
+
+      oldpc = PCREG;
+      switch (ivg)
+       {
+       case IVG_EMU:
+         /* Signal the JTAG ICE.  */
+         /* XXX: what happens with 'raise 0' ?  */
+         SET_RETEREG (oldpc);
+         excp_to_sim_halt (sim_stopped, SIM_SIGTRAP);
+         /* XXX: Need an easy way for gdb to signal it isnt here.  */
+         cec->ipend &= ~IVG_EMU_B;
+         break;
+       case IVG_RST:
+         /* Have the core reset simply exit (i.e. "shutdown").  */
+         excp_to_sim_halt (sim_exited, 0);
+         break;
+       case IVG_NMI:
+         /* XXX: Should check this.  */
+         SET_RETNREG (oldpc);
+         break;
+       case IVG_EVX:
+         /* Non-service exceptions point to the excepting instruction.  */
+         if (EXCAUSE >= 0x20)
+           SET_RETXREG (oldpc);
+         else
+           {
+             bu32 nextpc = hwloop_get_next_pc (cpu, oldpc, INSN_LEN);
+             SET_RETXREG (nextpc);
+           }
+
+         break;
+       case IVG_IRPTEN:
+         /* XXX: what happens with 'raise 4' ?  */
+         sim_io_error (sd, "%s: what to do with 'raise 4' ?", __func__);
+         break;
+       default:
+         SET_RETIREG (oldpc | (ivg == curr_ivg ? 1 : 0));
+         break;
+       }
+
+      /* If EVT_OVERRIDE is in effect (IVG7+), use the reset address.  */
+      if ((cec->evt_override & 0xff80) & (1 << ivg))
+       SET_PCREG (cec_get_reset_evt (cpu));
+      else
+       SET_PCREG (cec_get_evt (cpu, ivg));
+
+      TRACE_BRANCH (cpu, oldpc, PCREG, -1, "CEC changed PC (to EVT%i):", ivg);
+      BFIN_CPU_STATE.did_jump = true;
+
+      /* Enable the global interrupt mask upon interrupt entry.  */
+      if (ivg >= IVG_IVHW)
+       cec_irpten_enable (cpu, cec);
+    }
+
+  /* When moving between states, don't let internal states bleed through.  */
+  DIS_ALGN_EXPT &= ~1;
+
+  /* When going from user to super, we set LSB in LB regs to avoid
+     misbehavior and/or malicious code.
+     Also need to load SP alias with KSP.  */
+  if (curr_ivg == IVG_USER)
+    {
+      int i;
+      for (i = 0; i < 2; ++i)
+       if (!(LBREG (i) & 1))
+         SET_LBREG (i, LBREG (i) | 1);
+      SET_USPREG (SPREG);
+      SET_SPREG (KSPREG);
+    }
+
+ done:
+  TRACE_EVENTS (cpu, "now at EVT%i", _cec_get_ivg (cec));
+}
+
+static bu32
+cec_read_ret_reg (SIM_CPU *cpu, int ivg)
+{
+  switch (ivg)
+    {
+    case IVG_EMU: return RETEREG;
+    case IVG_NMI: return RETNREG;
+    case IVG_EVX: return RETXREG;
+    default:      return RETIREG;
+    }
+}
+
+void
+cec_latch (SIM_CPU *cpu, int ivg)
+{
+  struct bfin_cec *cec;
+
+  if (STATE_ENVIRONMENT (CPU_STATE (cpu)) != OPERATING_ENVIRONMENT)
+    {
+      bu32 oldpc = PCREG;
+      SET_PCREG (cec_read_ret_reg (cpu, ivg));
+      TRACE_BRANCH (cpu, oldpc, PCREG, -1, "CEC changed PC");
+      return;
+    }
+
+  cec = CEC_STATE (cpu);
+  cec->ilat |= (1 << ivg);
+  _cec_check_pending (cpu, cec);
+}
+
+void
+cec_hwerr (SIM_CPU *cpu, int hwerr)
+{
+  SET_HWERRCAUSE (hwerr);
+  cec_latch (cpu, IVG_IVHW);
+}
+
+void
+cec_return (SIM_CPU *cpu, int ivg)
+{
+  SIM_DESC sd = CPU_STATE (cpu);
+  struct bfin_cec *cec;
+  bool snen;
+  int curr_ivg;
+  bu32 oldpc, newpc;
+
+  oldpc = PCREG;
+
+  BFIN_CPU_STATE.did_jump = true;
+  if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
+    {
+      SET_PCREG (cec_read_ret_reg (cpu, ivg));
+      TRACE_BRANCH (cpu, oldpc, PCREG, -1, "CEC changed PC");
+      return;
+    }
+
+  cec = CEC_STATE (cpu);
+
+  /* XXX: This isn't entirely correct ...  */
+  cec->ipend &= ~IVG_EMU_B;
+
+  curr_ivg = _cec_get_ivg (cec);
+  if (curr_ivg == -1)
+    curr_ivg = IVG_USER;
+  if (ivg == -1)
+    ivg = curr_ivg;
+
+  TRACE_EVENTS (cpu, "returning from EVT%i (should be EVT%i)", curr_ivg, ivg);
+
+  /* Not allowed to return from usermode.  */
+  if (curr_ivg == IVG_USER)
+    cec_exception (cpu, VEC_ILL_RES);
+
+  if (ivg > IVG15 || ivg < 0)
+    sim_io_error (sd, "%s: ivg %i out of range !", __func__, ivg);
+
+  _cec_require_supervisor (cpu, cec);
+
+  switch (ivg)
+    {
+    case IVG_EMU:
+      /* RTE -- only valid in emulation mode.  */
+      /* XXX: What does the hardware do ?  */
+      if (curr_ivg != IVG_EMU)
+       cec_exception (cpu, VEC_ILL_RES);
+      break;
+    case IVG_NMI:
+      /* RTN -- only valid in NMI.  */
+      /* XXX: What does the hardware do ?  */
+      if (curr_ivg != IVG_NMI)
+       cec_exception (cpu, VEC_ILL_RES);
+      break;
+    case IVG_EVX:
+      /* RTX -- only valid in exception.  */
+      /* XXX: What does the hardware do ?  */
+      if (curr_ivg != IVG_EVX)
+       cec_exception (cpu, VEC_ILL_RES);
+      break;
+    default:
+      /* RTI -- not valid in emulation, nmi, exception, or user.  */
+      /* XXX: What does the hardware do ?  */
+      if (curr_ivg == IVG_EMU || curr_ivg == IVG_NMI
+         || curr_ivg == IVG_EVX || curr_ivg == IVG_USER)
+       cec_exception (cpu, VEC_ILL_RES);
+      break;
+    case IVG_IRPTEN:
+      /* XXX: Is this even possible ?  */
+      excp_to_sim_halt (sim_stopped, SIM_SIGABRT);
+      break;
+    }
+  newpc = cec_read_ret_reg (cpu, ivg);
+
+  /* XXX: Does this nested trick work on EMU/NMI/EVX ?  */
+  snen = (newpc & 1);
+  /* XXX: Delayed clear shows bad PCREG register trace above ?  */
+  SET_PCREG (newpc & ~1);
+
+  TRACE_BRANCH (cpu, oldpc, PCREG, -1, "CEC changed PC (from EVT%i)", ivg);
+
+  /* Update ipend after the TRACE_BRANCH so dv-bfin_trace
+     knows current CEC state wrt overflow.  */
+  if (!snen)
+    cec->ipend &= ~(1 << ivg);
+
+  /* Disable global interrupt mask to let any interrupt take over, but
+     only when we were already in a RTI level.  Only way we could have
+     raised at that point is if it was cleared in the first place.  */
+  if (ivg >= IVG_IVHW || ivg == IVG_RST)
+    cec_irpten_disable (cpu, cec);
+
+  /* When going from super to user, we clear LSB in LB regs in case
+     it was set on the transition up.
+     Also need to load SP alias with USP.  */
+  if (_cec_get_ivg (cec) == -1)
+    {
+      int i;
+      for (i = 0; i < 2; ++i)
+       if (LBREG (i) & 1)
+         SET_LBREG (i, LBREG (i) & ~1);
+      SET_KSPREG (SPREG);
+      SET_SPREG (USPREG);
+    }
+
+  /* Check for pending interrupts before we return to usermode.  */
+  _cec_check_pending (cpu, cec);
+}
+
+void
+cec_push_reti (SIM_CPU *cpu)
+{
+  /* XXX: Need to check hardware with popped RETI value
+     and bit 1 is set (when handling nested interrupts).
+     Also need to check behavior wrt SNEN in SYSCFG.  */
+  struct bfin_cec *cec;
+
+  if (STATE_ENVIRONMENT (CPU_STATE (cpu)) != OPERATING_ENVIRONMENT)
+    return;
+
+  TRACE_EVENTS (cpu, "pushing RETI");
+
+  cec = CEC_STATE (cpu);
+  cec_irpten_disable (cpu, cec);
+  /* Check for pending interrupts.  */
+  _cec_check_pending (cpu, cec);
+}
+
+void
+cec_pop_reti (SIM_CPU *cpu)
+{
+  /* XXX: Need to check hardware with popped RETI value
+     and bit 1 is set (when handling nested interrupts).
+     Also need to check behavior wrt SNEN in SYSCFG.  */
+  struct bfin_cec *cec;
+
+  if (STATE_ENVIRONMENT (CPU_STATE (cpu)) != OPERATING_ENVIRONMENT)
+    return;
+
+  TRACE_EVENTS (cpu, "popping RETI");
+
+  cec = CEC_STATE (cpu);
+  cec_irpten_enable (cpu, cec);
+}
diff --git a/sim/bfin/dv-bfin_cec.h b/sim/bfin/dv-bfin_cec.h
new file mode 100644 (file)
index 0000000..027c893
--- /dev/null
@@ -0,0 +1,139 @@
+/* Blackfin Core Event Controller (CEC) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_CEC_H
+#define DV_BFIN_CEC_H
+
+#include "sim-main.h"
+
+#define BFIN_COREMMR_CEC_BASE  0xFFE02100
+#define BFIN_COREMMR_CEC_SIZE  (4 * 5)
+
+/* 0xFFE02100 ... 0xFFE02110 */
+#define BFIN_COREMMR_EVT_OVERRIDE      (BFIN_COREMMR_CEC_BASE + (4 * 0))
+#define BFIN_COREMMR_IMASK             (BFIN_COREMMR_CEC_BASE + (4 * 1))
+#define BFIN_COREMMR_IPEND             (BFIN_COREMMR_CEC_BASE + (4 * 2))
+#define BFIN_COREMMR_ILAT              (BFIN_COREMMR_CEC_BASE + (4 * 3))
+#define BFIN_COREMMR_IPRIO             (BFIN_COREMMR_CEC_BASE + (4 * 4))
+
+#define IVG_EMU                0
+#define IVG_RST                1
+#define IVG_NMI                2
+#define IVG_EVX                3
+#define IVG_IRPTEN     4       /* Global is Reserved */
+#define IVG_IVHW       5
+#define IVG_IVTMR      6
+#define IVG7           7
+#define IVG8           8
+#define IVG9           9
+#define IVG10          10
+#define IVG11          11
+#define IVG12          12
+#define IVG13          13
+#define IVG14          14
+#define IVG15          15
+#define IVG_USER       16      /* Not real; for internal use */
+
+#define IVG_EMU_B      (1 << IVG_EMU)
+#define IVG_RST_B      (1 << IVG_RST)
+#define IVG_NMI_B      (1 << IVG_NMI)
+#define IVG_EVX_B      (1 << IVG_EVX)
+#define IVG_IRPTEN_B   (1 << IVG_IRPTEN)
+#define IVG_IVHW_B     (1 << IVG_IVHW)
+#define IVG_IVTMR_B    (1 << IVG_IVTMR)
+#define IVG7_B         (1 << IVG7)
+#define IVG8_B         (1 << IVG8)
+#define IVG9_B         (1 << IVG9)
+#define IVG10_B                (1 << IVG10)
+#define IVG11_B                (1 << IVG11)
+#define IVG12_B                (1 << IVG12)
+#define IVG13_B                (1 << IVG13)
+#define IVG14_B                (1 << IVG14)
+#define IVG15_B                (1 << IVG15)
+#define IVG_UNMASKABLE_B \
+       (IVG_EMU_B | IVG_RST_B | IVG_NMI_B | IVG_EVX_B | IVG_IRPTEN_B)
+#define IVG_MASKABLE_B \
+       (IVG_IVHW_B | IVG_IVTMR_B | IVG7_B | IVG8_B | IVG9_B | \
+        IVG10_B | IVG11_B | IVG12_B | IVG13_B | IVG14_B | IVG15_B)
+
+#define VEC_SYS                0x0
+#define VEC_EXCPT01    0x1
+#define VEC_EXCPT02    0x2
+#define VEC_EXCPT03    0x3
+#define VEC_EXCPT04    0x4
+#define VEC_EXCPT05    0x5
+#define VEC_EXCPT06    0x6
+#define VEC_EXCPT07    0x7
+#define VEC_EXCPT08    0x8
+#define VEC_EXCPT09    0x9
+#define VEC_EXCPT10    0xa
+#define VEC_EXCPT11    0xb
+#define VEC_EXCPT12    0xc
+#define VEC_EXCPT13    0xd
+#define VEC_EXCPT14    0xe
+#define VEC_EXCPT15    0xf
+#define VEC_STEP       0x10    /* single step */
+#define VEC_OVFLOW     0x11    /* trace buffer overflow */
+#define VEC_UNDEF_I    0x21    /* undefined instruction */
+#define VEC_ILGAL_I    0x22    /* illegal instruction combo (multi-issue) */
+#define VEC_CPLB_VL    0x23    /* DCPLB protection violation */
+#define VEC_MISALI_D   0x24    /* unaligned data access */
+#define VEC_UNCOV      0x25    /* unrecoverable event (double fault) */
+#define VEC_CPLB_M     0x26    /* DCPLB miss */
+#define VEC_CPLB_MHIT  0x27    /* multiple DCPLB hit */
+#define VEC_WATCH      0x28    /* watchpoint match */
+#define VEC_ISTRU_VL   0x29    /* ADSP-BF535 only */
+#define VEC_MISALI_I   0x2a    /* unaligned instruction access */
+#define VEC_CPLB_I_VL  0x2b    /* ICPLB protection violation */
+#define VEC_CPLB_I_M   0x2c    /* ICPLB miss */
+#define VEC_CPLB_I_MHIT        0x2d    /* multiple ICPLB hit */
+#define VEC_ILL_RES    0x2e    /* illegal supervisor resource */
+/*
+ * The hardware reserves 63+ for future use - we use it to tell our
+ * normal exception handling code we have a hardware error
+ */
+#define VEC_HWERR      63
+#define VEC_SIM_BASE   64
+#define VEC_SIM_HLT    (VEC_SIM_BASE + 1)
+#define VEC_SIM_ABORT  (VEC_SIM_BASE + 2)
+#define VEC_SIM_TRAP   (VEC_SIM_BASE + 3)
+#define VEC_SIM_DBGA   (VEC_SIM_BASE + 4)
+extern void cec_exception (SIM_CPU *, int vec_excp);
+
+#define HWERR_SYSTEM_MMR       0x02
+#define HWERR_EXTERN_ADDR      0x03
+#define HWERR_PERF_FLOW                0x12
+#define HWERR_RAISE_5          0x18
+extern void cec_hwerr (SIM_CPU *, int hwerr);
+extern void cec_latch (SIM_CPU *, int ivg);
+extern void cec_return (SIM_CPU *, int ivg);
+
+extern int cec_get_ivg (SIM_CPU *);
+extern bool cec_is_supervisor_mode (SIM_CPU *);
+extern bool cec_is_user_mode (SIM_CPU *);
+extern void cec_require_supervisor (SIM_CPU *);
+
+extern bu32 cec_cli (SIM_CPU *);
+extern void cec_sti (SIM_CPU *, bu32 ints);
+
+extern void cec_push_reti (SIM_CPU *);
+extern void cec_pop_reti (SIM_CPU *);
+
+#endif
diff --git a/sim/bfin/dv-bfin_ctimer.c b/sim/bfin/dv-bfin_ctimer.c
new file mode 100644 (file)
index 0000000..b6d575c
--- /dev/null
@@ -0,0 +1,267 @@
+/* Blackfin Core Timer model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_cec.h"
+#include "dv-bfin_ctimer.h"
+
+struct bfin_ctimer
+{
+  bu32 base;
+  struct hw_event *handler;
+  signed64 timeout;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu32 tcntl, tperiod, tscale, tcount;
+};
+#define mmr_base()      offsetof(struct bfin_ctimer, tcntl)
+#define mmr_offset(mmr) (offsetof(struct bfin_ctimer, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "TCNTL", "TPERIOD", "TSCALE", "TCOUNT",
+};
+#define mmr_name(off) mmr_names[(off) / 4]
+
+static bool
+bfin_ctimer_enabled (struct bfin_ctimer *ctimer)
+{
+  return (ctimer->tcntl & TMPWR) && (ctimer->tcntl & TMREN);
+}
+
+static bu32
+bfin_ctimer_scale (struct bfin_ctimer *ctimer)
+{
+  /* Only low 8 bits are actually checked.  */
+  return (ctimer->tscale & 0xff) + 1;
+}
+
+static void
+bfin_ctimer_schedule (struct hw *me, struct bfin_ctimer *ctimer);
+
+static void
+bfin_ctimer_expire (struct hw *me, void *data)
+{
+  struct bfin_ctimer *ctimer = data;
+
+  ctimer->tcntl |= TINT;
+  if (ctimer->tcntl & TAUTORLD)
+    {
+      ctimer->tcount = ctimer->tperiod;
+      bfin_ctimer_schedule (me, ctimer);
+    }
+  else
+    {
+      ctimer->tcount = 0;
+      ctimer->handler = NULL;
+    }
+
+  hw_port_event (me, IVG_IVTMR, 1);
+}
+
+static void
+bfin_ctimer_update_count (struct hw *me, struct bfin_ctimer *ctimer)
+{
+  bu32 scale, ticks;
+  signed64 timeout;
+
+  /* If the timer was enabled w/out autoreload and has expired, then
+     there's nothing to calculate here.  */
+  if (ctimer->handler == NULL)
+    return;
+
+  scale = bfin_ctimer_scale (ctimer);
+  timeout = hw_event_remain_time (me, ctimer->handler);
+  ticks = ctimer->timeout - timeout;
+  ctimer->tcount -= (scale * ticks);
+  ctimer->timeout = timeout;
+}
+
+static void
+bfin_ctimer_deschedule (struct hw *me, struct bfin_ctimer *ctimer)
+{
+  if (ctimer->handler)
+    {
+      hw_event_queue_deschedule (me, ctimer->handler);
+      ctimer->handler = NULL;
+    }
+}
+
+static void
+bfin_ctimer_schedule (struct hw *me, struct bfin_ctimer *ctimer)
+{
+  bu32 scale = bfin_ctimer_scale (ctimer);
+  ctimer->timeout = (ctimer->tcount / scale) + !!(ctimer->tcount % scale);
+  ctimer->handler = hw_event_queue_schedule (me, ctimer->timeout,
+                                            bfin_ctimer_expire,
+                                            ctimer);
+}
+
+static unsigned
+bfin_ctimer_io_write_buffer (struct hw *me, const void *source,
+                            int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_ctimer *ctimer = hw_data (me);
+  bool curr_enabled;
+  bu32 mmr_off;
+  bu32 value;
+  bu32 *valuep;
+
+  value = dv_load_4 (source);
+  mmr_off = addr - ctimer->base;
+  valuep = (void *)((unsigned long)ctimer + mmr_base() + mmr_off);
+
+  HW_TRACE_WRITE ();
+
+  curr_enabled = bfin_ctimer_enabled (ctimer);
+  switch (mmr_off)
+    {
+    case mmr_offset(tcntl):
+      /* HRM describes TINT as sticky, but it isn't W1C.  */
+      *valuep = value;
+
+      if (bfin_ctimer_enabled (ctimer) == curr_enabled)
+       {
+         /* Do nothing.  */
+       }
+      else if (curr_enabled)
+       {
+         bfin_ctimer_update_count (me, ctimer);
+         bfin_ctimer_deschedule (me, ctimer);
+       }
+      else
+       bfin_ctimer_schedule (me, ctimer);
+
+      break;
+    case mmr_offset(tcount):
+      /* HRM says writes are discarded when enabled.  */
+      /* XXX: But hardware seems to be writeable all the time ?  */
+      /* if (!curr_enabled) */
+       *valuep = value;
+      break;
+    case mmr_offset(tperiod):
+      /* HRM says writes are discarded when enabled.  */
+      /* XXX: But hardware seems to be writeable all the time ?  */
+      /* if (!curr_enabled) */
+       {
+         /* Writes are mirrored into TCOUNT.  */
+         ctimer->tcount = value;
+         *valuep = value;
+       }
+      break;
+    case mmr_offset(tscale):
+      if (curr_enabled)
+       {
+         bfin_ctimer_update_count (me, ctimer);
+         bfin_ctimer_deschedule (me, ctimer);
+       }
+      *valuep = value;
+      if (curr_enabled)
+       bfin_ctimer_schedule (me, ctimer);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_ctimer_io_read_buffer (struct hw *me, void *dest,
+                           int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_ctimer *ctimer = hw_data (me);
+  bu32 mmr_off;
+  bu32 *valuep;
+
+  mmr_off = addr - ctimer->base;
+  valuep = (void *)((unsigned long)ctimer + mmr_base() + mmr_off);
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(tcount):
+      /* Since we're optimizing events here, we need to calculate
+         the new tcount value.  */
+      if (bfin_ctimer_enabled (ctimer))
+       bfin_ctimer_update_count (me, ctimer);
+      break;
+    }
+
+  dv_store_4 (dest, *valuep);
+
+  return nr_bytes;
+}
+
+static const struct hw_port_descriptor bfin_ctimer_ports[] = {
+  { "ivtmr", IVG_IVTMR, 0, output_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+attach_bfin_ctimer_regs (struct hw *me, struct bfin_ctimer *ctimer)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_COREMMR_CTIMER_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_COREMMR_CTIMER_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  ctimer->base = attach_address;
+}
+
+static void
+bfin_ctimer_finish (struct hw *me)
+{
+  struct bfin_ctimer *ctimer;
+
+  ctimer = HW_ZALLOC (me, struct bfin_ctimer);
+
+  set_hw_data (me, ctimer);
+  set_hw_io_read_buffer (me, bfin_ctimer_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_ctimer_io_write_buffer);
+  set_hw_ports (me, bfin_ctimer_ports);
+
+  attach_bfin_ctimer_regs (me, ctimer);
+
+  /* Initialize the Core Timer.  */
+}
+
+const struct hw_descriptor dv_bfin_ctimer_descriptor[] = {
+  {"bfin_ctimer", bfin_ctimer_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_ctimer.h b/sim/bfin/dv-bfin_ctimer.h
new file mode 100644 (file)
index 0000000..c097588
--- /dev/null
@@ -0,0 +1,33 @@
+/* Blackfin Core Timer model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_CTIMER_H
+#define DV_BFIN_CTIMER_H
+
+#define BFIN_COREMMR_CTIMER_BASE       0xFFE03000
+#define BFIN_COREMMR_CTIMER_SIZE       (4 * 4)
+
+/* TCNTL Masks */
+#define TMPWR          (1 << 0)
+#define TMREN          (1 << 1)
+#define TAUTORLD       (1 << 2)
+#define TINT           (1 << 3)
+
+#endif
diff --git a/sim/bfin/dv-bfin_dma.c b/sim/bfin/dv-bfin_dma.c
new file mode 100644 (file)
index 0000000..e61348a
--- /dev/null
@@ -0,0 +1,553 @@
+/* Blackfin Direct Memory Access (DMA) Channel model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "hw-device.h"
+#include "dv-bfin_dma.h"
+#include "dv-bfin_dmac.h"
+
+/* Note: This DMA implementation requires the producer to be the master when
+         the peer is MDMA.  The source is always a slave.  This way we don't
+         have the two DMA devices thrashing each other with one trying to
+         write and the other trying to read.  */
+
+struct bfin_dma
+{
+  /* This top portion matches common dv_bfin struct.  */
+  bu32 base;
+  struct hw *dma_master;
+  bool acked;
+
+  struct hw_event *handler;
+  unsigned ele_size;
+  struct hw *hw_peer;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  union {
+    struct { bu16 ndpl, ndph; };
+    bu32 next_desc_ptr;
+  };
+  union {
+    struct { bu16 sal, sah; };
+    bu32 start_addr;
+  };
+  bu16 BFIN_MMR_16 (config);
+  bu32 _pad0;
+  bu16 BFIN_MMR_16 (x_count);
+  bs16 BFIN_MMR_16 (x_modify);
+  bu16 BFIN_MMR_16 (y_count);
+  bs16 BFIN_MMR_16 (y_modify);
+  bu32 curr_desc_ptr, curr_addr;
+  bu16 BFIN_MMR_16 (irq_status);
+  bu16 BFIN_MMR_16 (peripheral_map);
+  bu16 BFIN_MMR_16 (curr_x_count);
+  bu32 _pad1;
+  bu16 BFIN_MMR_16 (curr_y_count);
+  bu32 _pad2;
+};
+#define mmr_base()      offsetof(struct bfin_dma, next_desc_ptr)
+#define mmr_offset(mmr) (offsetof(struct bfin_dma, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "NEXT_DESC_PTR", "START_ADDR", "CONFIG", "<INV>", "X_COUNT", "X_MODIFY",
+  "Y_COUNT", "Y_MODIFY", "CURR_DESC_PTR", "CURR_ADDR", "IRQ_STATUS",
+  "PERIPHERAL_MAP", "CURR_X_COUNT", "<INV>", "CURR_Y_COUNT", "<INV>",
+};
+#define mmr_name(off) mmr_names[(off) / 4]
+
+static bool
+bfin_dma_enabled (struct bfin_dma *dma)
+{
+  return (dma->config & DMAEN);
+}
+
+static bool
+bfin_dma_running (struct bfin_dma *dma)
+{
+  return (dma->irq_status & DMA_RUN);
+}
+
+static struct hw *
+bfin_dma_get_peer (struct hw *me, struct bfin_dma *dma)
+{
+  if (dma->hw_peer)
+    return dma->hw_peer;
+  return dma->hw_peer = bfin_dmac_get_peer (me, dma->peripheral_map);
+}
+
+static void
+bfin_dma_process_desc (struct hw *me, struct bfin_dma *dma)
+{
+  bu8 ndsize = (dma->config & NDSIZE) >> NDSIZE_SHIFT;
+  bu16 _flows[9], *flows = _flows;
+
+  HW_TRACE ((me, "dma starting up %#x", dma->config));
+
+  switch (dma->config & WDSIZE)
+    {
+    case WDSIZE_32:
+      dma->ele_size = 4;
+      break;
+    case WDSIZE_16:
+      dma->ele_size = 2;
+      break;
+    default:
+      dma->ele_size = 1;
+      break;
+    }
+
+  /* Address has to be mutiple of transfer size.  */
+  if (dma->start_addr & (dma->ele_size - 1))
+    dma->irq_status |= DMA_ERR;
+
+  if (dma->ele_size != (unsigned) abs (dma->x_modify))
+    hw_abort (me, "DMA config (striding) %#x not supported (x_modify: %d)",
+             dma->config, dma->x_modify);
+
+  switch (dma->config & DMAFLOW)
+    {
+    case DMAFLOW_AUTO:
+    case DMAFLOW_STOP:
+      if (ndsize)
+       hw_abort (me, "DMA config error: DMAFLOW_{AUTO,STOP} requires NDSIZE_0");
+      break;
+    case DMAFLOW_ARRAY:
+      if (ndsize == 0 || ndsize > 7)
+       hw_abort (me, "DMA config error: DMAFLOW_ARRAY requires NDSIZE 1...7");
+      sim_read (hw_system (me), dma->curr_desc_ptr, (void *)flows, ndsize * 2);
+      break;
+    case DMAFLOW_SMALL:
+      if (ndsize == 0 || ndsize > 8)
+       hw_abort (me, "DMA config error: DMAFLOW_SMALL requires NDSIZE 1...8");
+      sim_read (hw_system (me), dma->next_desc_ptr, (void *)flows, ndsize * 2);
+      break;
+    case DMAFLOW_LARGE:
+      if (ndsize == 0 || ndsize > 9)
+       hw_abort (me, "DMA config error: DMAFLOW_LARGE requires NDSIZE 1...9");
+      sim_read (hw_system (me), dma->next_desc_ptr, (void *)flows, ndsize * 2);
+      break;
+    default:
+      hw_abort (me, "DMA config error: invalid DMAFLOW %#x", dma->config);
+    }
+
+  if (ndsize)
+    {
+      bu8 idx;
+      bu16 *stores[] = {
+       &dma->sal,
+       &dma->sah,
+       &dma->config,
+       &dma->x_count,
+       (void *) &dma->x_modify,
+       &dma->y_count,
+       (void *) &dma->y_modify,
+      };
+
+      switch (dma->config & DMAFLOW)
+       {
+       case DMAFLOW_LARGE:
+         dma->ndph = _flows[1];
+         --ndsize;
+         ++flows;
+       case DMAFLOW_SMALL:
+         dma->ndpl = _flows[0];
+         --ndsize;
+         ++flows;
+         break;
+       }
+
+      for (idx = 0; idx < ndsize; ++idx)
+       *stores[idx] = flows[idx];
+    }
+
+  dma->curr_desc_ptr = dma->next_desc_ptr;
+  dma->curr_addr = dma->start_addr;
+  dma->curr_x_count = dma->x_count ? : 0xffff;
+  dma->curr_y_count = dma->y_count ? : 0xffff;
+}
+
+static int
+bfin_dma_finish_x (struct hw *me, struct bfin_dma *dma)
+{
+  /* XXX: This would be the time to process the next descriptor.  */
+  /* XXX: Should this toggle Enable in dma->config ?  */
+
+  if (dma->config & DI_EN)
+    hw_port_event (me, 0, 1);
+
+  if ((dma->config & DMA2D) && dma->curr_y_count > 1)
+    {
+      dma->curr_y_count -= 1;
+      dma->curr_x_count = dma->x_count;
+
+      /* With 2D, last X transfer does not modify curr_addr.  */
+      dma->curr_addr = dma->curr_addr - dma->x_modify + dma->y_modify;
+
+      return 1;
+    }
+
+  switch (dma->config & DMAFLOW)
+    {
+    case DMAFLOW_STOP:
+      HW_TRACE ((me, "dma is complete"));
+      dma->irq_status = (dma->irq_status & ~DMA_RUN) | DMA_DONE;
+      return 0;
+    default:
+      bfin_dma_process_desc (me, dma);
+      return 1;
+    }
+}
+
+static void bfin_dma_hw_event_callback (struct hw *, void *);
+
+static void
+bfin_dma_reschedule (struct hw *me, unsigned delay)
+{
+  struct bfin_dma *dma = hw_data (me);
+  if (dma->handler)
+    {
+      hw_event_queue_deschedule (me, dma->handler);
+      dma->handler = NULL;
+    }
+  if (!delay)
+    return;
+  HW_TRACE ((me, "scheduling next process in %u", delay));
+  dma->handler = hw_event_queue_schedule (me, delay,
+                                         bfin_dma_hw_event_callback, dma);
+}
+
+/* Chew through the DMA over and over.  */
+static void
+bfin_dma_hw_event_callback (struct hw *me, void *data)
+{
+  struct bfin_dma *dma = data;
+  struct hw *peer;
+  struct dv_bfin *bfin_peer;
+  bu8 buf[4096];
+  unsigned ret, nr_bytes, ele_count;
+
+  dma->handler = NULL;
+  peer = bfin_dma_get_peer (me, dma);
+  bfin_peer = hw_data (peer);
+  ret = 0;
+  if (dma->x_modify < 0)
+    /* XXX: This sucks performance wise.  */
+    nr_bytes = dma->ele_size;
+  else
+    nr_bytes = MIN (sizeof (buf), dma->curr_x_count * dma->ele_size);
+
+  /* Pumping a chunk!  */
+  bfin_peer->dma_master = me;
+  bfin_peer->acked = false;
+  if (dma->config & WNR)
+    {
+      HW_TRACE ((me, "dma transfer to 0x%08lx length %u",
+                (unsigned long) dma->curr_addr, nr_bytes));
+
+      ret = hw_dma_read_buffer (peer, buf, 0, dma->curr_addr, nr_bytes);
+      /* Has the DMA stalled ?  abort for now.  */
+      if (ret == 0)
+       goto reschedule;
+      /* XXX: How to handle partial DMA transfers ?  */
+      if (ret % dma->ele_size)
+       goto error;
+      ret = sim_write (hw_system (me), dma->curr_addr, buf, ret);
+    }
+  else
+    {
+      HW_TRACE ((me, "dma transfer from 0x%08lx length %u",
+                (unsigned long) dma->curr_addr, nr_bytes));
+
+      ret = sim_read (hw_system (me), dma->curr_addr, buf, nr_bytes);
+      if (ret == 0)
+       goto reschedule;
+      /* XXX: How to handle partial DMA transfers ?  */
+      if (ret % dma->ele_size)
+       goto error;
+      ret = hw_dma_write_buffer (peer, buf, 0, dma->curr_addr, ret, 0);
+      if (ret == 0)
+       goto reschedule;
+    }
+
+  /* Ignore partial writes.  */
+  ele_count = ret / dma->ele_size;
+  dma->curr_addr += ele_count * dma->x_modify;
+  dma->curr_x_count -= ele_count;
+
+  if ((!dma->acked && dma->curr_x_count) || bfin_dma_finish_x (me, dma))
+    /* Still got work to do, so schedule again.  */
+ reschedule:
+    bfin_dma_reschedule (me, ret ? 1 : 5000);
+
+  return;
+
+ error:
+  /* Don't reschedule on errors ...  */
+  dma->irq_status |= DMA_ERR;
+}
+
+static unsigned
+bfin_dma_io_write_buffer (struct hw *me, const void *source, int space,
+                         address_word addr, unsigned nr_bytes)
+{
+  struct bfin_dma *dma = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  if (nr_bytes == 4)
+    value = dv_load_4 (source);
+  else
+    value = dv_load_2 (source);
+
+  mmr_off = addr % dma->base;
+  valuep = (void *)((unsigned long)dma + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_WRITE ();
+
+  /* XXX: All registers are RO when DMA is enabled (except IRQ_STATUS).
+          But does the HW discard writes or send up IVGHW ?  The sim
+          simply discards atm ... */
+  switch (mmr_off)
+    {
+    case mmr_offset(next_desc_ptr):
+    case mmr_offset(start_addr):
+    case mmr_offset(curr_desc_ptr):
+    case mmr_offset(curr_addr):
+      /* Don't require 32bit access as all DMA MMRs can be used as 16bit.  */
+      if (!bfin_dma_running (dma))
+       {
+         if (nr_bytes == 4)
+           *value32p = value;
+         else
+          *value16p = value;
+       }
+      else
+       HW_TRACE ((me, "discarding write while dma running"));
+      break;
+    case mmr_offset(x_count):
+    case mmr_offset(x_modify):
+    case mmr_offset(y_count):
+    case mmr_offset(y_modify):
+      if (!bfin_dma_running (dma))
+       *value16p = value;
+      break;
+    case mmr_offset(peripheral_map):
+      if (!bfin_dma_running (dma))
+       {
+         *value16p = (*value16p & CTYPE) | (value & ~CTYPE);
+         /* Clear peripheral peer so it gets looked up again.  */
+         dma->hw_peer = NULL;
+       }
+      else
+       HW_TRACE ((me, "discarding write while dma running"));
+      break;
+    case mmr_offset(config):
+      /* XXX: How to handle updating CONFIG of a running channel ?  */
+      if (nr_bytes == 4)
+       *value32p = value;
+      else
+       *value16p = value;
+
+      if (bfin_dma_enabled (dma))
+       {
+         dma->irq_status |= DMA_RUN;
+         bfin_dma_process_desc (me, dma);
+         /* The writer is the master.  */
+         if (!(dma->peripheral_map & CTYPE) || (dma->config & WNR))
+           bfin_dma_reschedule (me, 1);
+       }
+      else
+       {
+         dma->irq_status &= ~DMA_RUN;
+         bfin_dma_reschedule (me, 0);
+       }
+      break;
+    case mmr_offset(irq_status):
+      dv_w1c_2 (value16p, value, DMA_DONE | DMA_ERR);
+      break;
+    case mmr_offset(curr_x_count):
+    case mmr_offset(curr_y_count):
+      if (!bfin_dma_running (dma))
+       *value16p = value;
+      else
+       HW_TRACE ((me, "discarding write while dma running"));
+      break;
+    default:
+      /* XXX: The HW lets the pad regions be read/written ...  */
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_dma_io_read_buffer (struct hw *me, void *dest, int space,
+                        address_word addr, unsigned nr_bytes)
+{
+  struct bfin_dma *dma = hw_data (me);
+  bu32 mmr_off;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  mmr_off = addr % dma->base;
+  valuep = (void *)((unsigned long)dma + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_READ ();
+
+  /* Hardware lets you read all MMRs as 16 or 32 bits, even reserved.  */
+  if (nr_bytes == 4)
+    dv_store_4 (dest, *value32p);
+  else
+    dv_store_2 (dest, *value16p);
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_dma_dma_read_buffer (struct hw *me, void *dest, int space,
+                         unsigned_word addr, unsigned nr_bytes)
+{
+  struct bfin_dma *dma = hw_data (me);
+  unsigned ret, ele_count;
+
+  HW_TRACE_DMA_READ ();
+
+  /* If someone is trying to read from me, I have to be enabled.  */
+  if (!bfin_dma_enabled (dma) && !bfin_dma_running (dma))
+    return 0;
+
+  /* XXX: handle x_modify ...  */
+  ret = sim_read (hw_system (me), dma->curr_addr, dest, nr_bytes);
+  /* Ignore partial writes.  */
+  ele_count = ret / dma->ele_size;
+  /* Has the DMA stalled ?  abort for now.  */
+  if (!ele_count)
+    return 0;
+
+  dma->curr_addr += ele_count * dma->x_modify;
+  dma->curr_x_count -= ele_count;
+
+  if (dma->curr_x_count == 0)
+    bfin_dma_finish_x (me, dma);
+
+  return ret;
+}
+
+static unsigned
+bfin_dma_dma_write_buffer (struct hw *me, const void *source,
+                          int space, unsigned_word addr,
+                          unsigned nr_bytes,
+                          int violate_read_only_section)
+{
+  struct bfin_dma *dma = hw_data (me);
+  unsigned ret, ele_count;
+
+  HW_TRACE_DMA_WRITE ();
+
+  /* If someone is trying to write to me, I have to be enabled.  */
+  if (!bfin_dma_enabled (dma) && !bfin_dma_running (dma))
+    return 0;
+
+  /* XXX: handle x_modify ...  */
+  ret = sim_write (hw_system (me), dma->curr_addr, source, nr_bytes);
+  /* Ignore partial writes.  */
+  ele_count = ret / dma->ele_size;
+  /* Has the DMA stalled ?  abort for now.  */
+  if (!ele_count)
+    return 0;
+
+  dma->curr_addr += ele_count * dma->x_modify;
+  dma->curr_x_count -= ele_count;
+
+  if (dma->curr_x_count == 0)
+    bfin_dma_finish_x (me, dma);
+
+  return ret;
+}
+
+static const struct hw_port_descriptor bfin_dma_ports[] = {
+  { "di", 0, 0, output_port, }, /* DMA Interrupt */
+  { NULL, 0, 0, 0, },
+};
+
+static void
+attach_bfin_dma_regs (struct hw *me, struct bfin_dma *dma)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_DMA_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_DMA_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  dma->base = attach_address;
+}
+
+static void
+bfin_dma_finish (struct hw *me)
+{
+  struct bfin_dma *dma;
+
+  dma = HW_ZALLOC (me, struct bfin_dma);
+
+  set_hw_data (me, dma);
+  set_hw_io_read_buffer (me, bfin_dma_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_dma_io_write_buffer);
+  set_hw_dma_read_buffer (me, bfin_dma_dma_read_buffer);
+  set_hw_dma_write_buffer (me, bfin_dma_dma_write_buffer);
+  set_hw_ports (me, bfin_dma_ports);
+
+  attach_bfin_dma_regs (me, dma);
+
+  /* Initialize the DMA Channel.  */
+  dma->peripheral_map = bfin_dmac_default_pmap (me);
+}
+
+const struct hw_descriptor dv_bfin_dma_descriptor[] = {
+  {"bfin_dma", bfin_dma_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_dma.h b/sim/bfin/dv-bfin_dma.h
new file mode 100644 (file)
index 0000000..03d412b
--- /dev/null
@@ -0,0 +1,65 @@
+/* Blackfin Direct Memory Access (DMA) Channel model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_DMA_H
+#define DV_BFIN_DMA_H
+
+#define BFIN_MMR_DMA_SIZE      (4 * 16)
+
+/* DMA_CONFIG Masks */
+#define DMAEN          0x0001  /* DMA Channel Enable */
+#define WNR            0x0002  /* Channel Direction (W/R*) */
+#define WDSIZE_8       0x0000  /* Transfer Word Size = 8 */
+#define WDSIZE_16      0x0004  /* Transfer Word Size = 16 */
+#define WDSIZE_32      0x0008  /* Transfer Word Size = 32 */
+#define WDSIZE         0x000c  /* Transfer Word Size */
+#define DMA2D          0x0010  /* DMA Mode (2D/1D*) */
+#define RESTART                0x0020  /* DMA Buffer Clear */
+#define DI_SEL         0x0040  /* Data Interrupt Timing Select */
+#define DI_EN          0x0080  /* Data Interrupt Enable */
+#define NDSIZE_0       0x0000  /* Next Descriptor Size = 0 (Stop/Autobuffer) */
+#define NDSIZE_1       0x0100  /* Next Descriptor Size = 1 */
+#define NDSIZE_2       0x0200  /* Next Descriptor Size = 2 */
+#define NDSIZE_3       0x0300  /* Next Descriptor Size = 3 */
+#define NDSIZE_4       0x0400  /* Next Descriptor Size = 4 */
+#define NDSIZE_5       0x0500  /* Next Descriptor Size = 5 */
+#define NDSIZE_6       0x0600  /* Next Descriptor Size = 6 */
+#define NDSIZE_7       0x0700  /* Next Descriptor Size = 7 */
+#define NDSIZE_8       0x0800  /* Next Descriptor Size = 8 */
+#define NDSIZE_9       0x0900  /* Next Descriptor Size = 9 */
+#define NDSIZE         0x0f00  /* Next Descriptor Size */
+#define NDSIZE_SHIFT   8
+#define DMAFLOW                0x7000  /* Flow Control */
+#define DMAFLOW_STOP   0x0000  /* Stop Mode */
+#define DMAFLOW_AUTO   0x1000  /* Autobuffer Mode */
+#define DMAFLOW_ARRAY  0x4000  /* Descriptor Array Mode */
+#define DMAFLOW_SMALL  0x6000  /* Small Model Descriptor List Mode */
+#define DMAFLOW_LARGE  0x7000  /* Large Model Descriptor List Mode */
+
+/* DMA_IRQ_STATUS Masks */
+#define DMA_DONE       0x0001  /* DMA Completion Interrupt Status */
+#define DMA_ERR                0x0002  /* DMA Error Interrupt Status */
+#define DFETCH         0x0004  /* DMA Descriptor Fetch Indicator */
+#define DMA_RUN                0x0008  /* DMA Channel Running Indicator */
+
+/* DMA_PERIPHERAL_MAP Masks */
+#define CTYPE          (1 << 6)
+
+#endif
diff --git a/sim/bfin/dv-bfin_dmac.c b/sim/bfin/dv-bfin_dmac.c
new file mode 100644 (file)
index 0000000..f0f3c8c
--- /dev/null
@@ -0,0 +1,469 @@
+/* Blackfin Direct Memory Access (DMA) Controller model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "sim-hw.h"
+#include "devices.h"
+#include "hw-device.h"
+#include "dv-bfin_dma.h"
+#include "dv-bfin_dmac.h"
+
+struct bfin_dmac
+{
+  /* This top portion matches common dv_bfin struct.  */
+  bu32 base;
+  struct hw *dma_master;
+  bool acked;
+
+  const char **pmap;
+  unsigned int pmap_count;
+};
+
+struct hw *
+bfin_dmac_get_peer (struct hw *dma, bu16 pmap)
+{
+  struct hw *ret, *me;
+  struct bfin_dmac *dmac;
+  char peer[100];
+
+  me = hw_parent (dma);
+  dmac = hw_data (me);
+  if (pmap & CTYPE)
+    {
+      /* MDMA channel.  */
+      unsigned int chan_num = dv_get_bus_num (dma);
+      if (chan_num & 1)
+       chan_num &= ~1;
+      else
+       chan_num |= 1;
+      sprintf (peer, "%s/bfin_dma@%u", hw_path (me), chan_num);
+    }
+  else
+    {
+      unsigned int idx = pmap >> 12;
+      if (idx >= dmac->pmap_count)
+       hw_abort (me, "Invalid DMA peripheral_map %#x", pmap);
+      else
+       sprintf (peer, "/core/bfin_%s", dmac->pmap[idx]);
+    }
+
+  ret = hw_tree_find_device (me, peer);
+  if (!ret)
+    hw_abort (me, "Unable to locate peer for %s (pmap:%#x %s)",
+             hw_name (dma), pmap, peer);
+  return ret;
+}
+
+bu16
+bfin_dmac_default_pmap (struct hw *dma)
+{
+  unsigned int chan_num = dv_get_bus_num (dma);
+
+  if (chan_num < BFIN_DMAC_MDMA_BASE)
+    return (chan_num % 12) << 12;
+  else
+    return CTYPE;      /* MDMA */
+}
+
+static const char *bfin_dmac_50x_pmap[] = {
+  "ppi@0", "rsi", "sport@0", "sport@0", "sport@1", "sport@1",
+  "spi@0", "spi@1", "uart2@0", "uart2@0", "uart2@1", "uart2@1",
+};
+
+/* XXX: Need to figure out how to handle portmuxed DMA channels.  */
+static const struct hw_port_descriptor bfin_dmac_50x_ports[] = {
+  { "ppi@0",       0, 0, input_port, },
+  { "rsi",         1, 0, input_port, },
+  { "sport@0_rx",  2, 0, input_port, },
+  { "sport@0_tx",  3, 0, input_port, },
+  { "sport@1_tx",  4, 0, input_port, },
+  { "sport@1_rx",  5, 0, input_port, },
+  { "spi@0",       6, 0, input_port, },
+  { "spi@1",       7, 0, input_port, },
+  { "uart2@0_rx",  8, 0, input_port, },
+  { "uart2@0_tx",  9, 0, input_port, },
+  { "uart2@1_rx", 10, 0, input_port, },
+  { "uart2@1_tx", 11, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const char *bfin_dmac_51x_pmap[] = {
+  "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
+  "sport@1", "spi@0", "uart@0", "uart@0", "uart@1", "uart@1",
+};
+
+/* XXX: Need to figure out how to handle portmuxed DMA channels.  */
+static const struct hw_port_descriptor bfin_dmac_51x_ports[] = {
+  { "ppi@0",       0, 0, input_port, },
+  { "emac_rx",     1, 0, input_port, },
+  { "emac_tx",     2, 0, input_port, },
+  { "sport@0_rx",  3, 0, input_port, },
+  { "sport@0_tx",  4, 0, input_port, },
+/*{ "rsi",         4, 0, input_port, },*/
+  { "sport@1_tx",  5, 0, input_port, },
+/*{ "spi@1",       5, 0, input_port, },*/
+  { "sport@1_rx",  6, 0, input_port, },
+  { "spi@0",       7, 0, input_port, },
+  { "uart@0_rx",   8, 0, input_port, },
+  { "uart@0_tx",   9, 0, input_port, },
+  { "uart@1_rx",  10, 0, input_port, },
+  { "uart@1_tx",  11, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const char *bfin_dmac_52x_pmap[] = {
+  "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
+  "sport@1", "spi", "uart@0", "uart@0", "uart@1", "uart@1",
+};
+
+/* XXX: Need to figure out how to handle portmuxed DMA channels
+        like PPI/NFC here which share DMA0.  */
+static const struct hw_port_descriptor bfin_dmac_52x_ports[] = {
+  { "ppi@0",       0, 0, input_port, },
+/*{ "nfc",         0, 0, input_port, },*/
+  { "emac_rx",     1, 0, input_port, },
+/*{ "hostdp",      1, 0, input_port, },*/
+  { "emac_tx",     2, 0, input_port, },
+/*{ "nfc",         2, 0, input_port, },*/
+  { "sport@0_tx",  3, 0, input_port, },
+  { "sport@0_rx",  4, 0, input_port, },
+  { "sport@1_tx",  5, 0, input_port, },
+  { "sport@1_rx",  6, 0, input_port, },
+  { "spi",         7, 0, input_port, },
+  { "uart@0_tx",   8, 0, input_port, },
+  { "uart@0_rx",   9, 0, input_port, },
+  { "uart@1_tx",  10, 0, input_port, },
+  { "uart@1_rx",  11, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const char *bfin_dmac_533_pmap[] = {
+  "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi",
+  "uart@0", "uart@0",
+};
+
+static const struct hw_port_descriptor bfin_dmac_533_ports[] = {
+  { "ppi@0",       0, 0, input_port, },
+  { "sport@0_tx",  1, 0, input_port, },
+  { "sport@0_rx",  2, 0, input_port, },
+  { "sport@1_tx",  3, 0, input_port, },
+  { "sport@1_rx",  4, 0, input_port, },
+  { "spi",         5, 0, input_port, },
+  { "uart@0_tx",   6, 0, input_port, },
+  { "uart@0_rx",   7, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const char *bfin_dmac_537_pmap[] = {
+  "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
+  "sport@1", "spi", "uart@0", "uart@0", "uart@1", "uart@1",
+};
+
+static const struct hw_port_descriptor bfin_dmac_537_ports[] = {
+  { "ppi@0",       0, 0, input_port, },
+  { "emac_rx",     1, 0, input_port, },
+  { "emac_tx",     2, 0, input_port, },
+  { "sport@0_tx",  3, 0, input_port, },
+  { "sport@0_rx",  4, 0, input_port, },
+  { "sport@1_tx",  5, 0, input_port, },
+  { "sport@1_rx",  6, 0, input_port, },
+  { "spi",         7, 0, input_port, },
+  { "uart@0_tx",   8, 0, input_port, },
+  { "uart@0_rx",   9, 0, input_port, },
+  { "uart@1_tx",  10, 0, input_port, },
+  { "uart@1_rx",  11, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const char *bfin_dmac0_538_pmap[] = {
+  "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi@0",
+  "uart@0", "uart@0",
+};
+
+static const struct hw_port_descriptor bfin_dmac0_538_ports[] = {
+  { "ppi@0",       0, 0, input_port, },
+  { "sport@0_rx",  1, 0, input_port, },
+  { "sport@0_tx",  2, 0, input_port, },
+  { "sport@1_rx",  3, 0, input_port, },
+  { "sport@1_tx",  4, 0, input_port, },
+  { "spi@0",       5, 0, input_port, },
+  { "uart@0_rx",   6, 0, input_port, },
+  { "uart@0_tx",   7, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const char *bfin_dmac1_538_pmap[] = {
+  "sport@2", "sport@2", "sport@3", "sport@3", NULL, NULL,
+  "spi@1", "spi@2", "uart@1", "uart@1", "uart@2", "uart@2",
+};
+
+static const struct hw_port_descriptor bfin_dmac1_538_ports[] = {
+  { "sport@2_rx",  0, 0, input_port, },
+  { "sport@2_tx",  1, 0, input_port, },
+  { "sport@3_rx",  2, 0, input_port, },
+  { "sport@3_tx",  3, 0, input_port, },
+  { "spi@1",       6, 0, input_port, },
+  { "spi@2",       7, 0, input_port, },
+  { "uart@1_rx",   8, 0, input_port, },
+  { "uart@1_tx",   9, 0, input_port, },
+  { "uart@2_rx",  10, 0, input_port, },
+  { "uart@2_tx",  11, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const char *bfin_dmac0_54x_pmap[] = {
+  "sport@0", "sport@0", "sport@1", "sport@1", "spi@0", "spi@1",
+  "uart2@0", "uart2@0", "uart2@1", "uart2@1", "atapi", "atapi",
+};
+
+static const struct hw_port_descriptor bfin_dmac0_54x_ports[] = {
+  { "sport@0_rx",  0, 0, input_port, },
+  { "sport@0_tx",  1, 0, input_port, },
+  { "sport@1_rx",  2, 0, input_port, },
+  { "sport@1_tx",  3, 0, input_port, },
+  { "spi@0",       4, 0, input_port, },
+  { "spi@1",       5, 0, input_port, },
+  { "uart2@0_rx",  6, 0, input_port, },
+  { "uart2@0_tx",  7, 0, input_port, },
+  { "uart2@1_rx",  8, 0, input_port, },
+  { "uart2@1_tx",  9, 0, input_port, },
+  { "atapi",      10, 0, input_port, },
+  { "atapi",      11, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const char *bfin_dmac1_54x_pmap[] = {
+  "eppi@0", "eppi@1", "eppi@2", "pixc", "pixc", "pixc",
+  "sport@2", "sport@2", "sport@3", "sport@3", "sdh",
+  "spi@2", "uart2@2", "uart2@2", "uart2@3", "uart2@3",
+};
+
+static const struct hw_port_descriptor bfin_dmac1_54x_ports[] = {
+  { "eppi@0",      0, 0, input_port, },
+  { "eppi@1",      1, 0, input_port, },
+  { "eppi@2",      2, 0, input_port, },
+  { "pixc",        3, 0, input_port, },
+  { "pixc",        4, 0, input_port, },
+  { "pixc",        5, 0, input_port, },
+  { "sport@2_rx",  6, 0, input_port, },
+  { "sport@2_tx",  7, 0, input_port, },
+  { "sport@3_rx",  8, 0, input_port, },
+  { "sport@3_tx",  9, 0, input_port, },
+  { "sdh",        10, 0, input_port, },
+/*{ "nfc",        10, 0, input_port, },*/
+  { "spi@2",      11, 0, input_port, },
+  { "uart2@2_rx", 12, 0, input_port, },
+  { "uart2@2_tx", 13, 0, input_port, },
+  { "uart2@3_rx", 14, 0, input_port, },
+  { "uart2@3_tx", 15, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const char *bfin_dmac0_561_pmap[] = {
+  "sport@0", "sport@0", "sport@1", "sport@1", "spi", "uart@0", "uart@0",
+};
+
+static const struct hw_port_descriptor bfin_dmac0_561_ports[] = {
+  { "sport@0_rx",  0, 0, input_port, },
+  { "sport@0_tx",  1, 0, input_port, },
+  { "sport@1_rx",  2, 0, input_port, },
+  { "sport@1_tx",  3, 0, input_port, },
+  { "spi@0",       4, 0, input_port, },
+  { "uart@0_rx",   5, 0, input_port, },
+  { "uart@0_tx",   6, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const char *bfin_dmac1_561_pmap[] = {
+  "ppi@0", "ppi@1",
+};
+
+static const struct hw_port_descriptor bfin_dmac1_561_ports[] = {
+  { "ppi@0",       0, 0, input_port, },
+  { "ppi@1",       1, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const char *bfin_dmac_59x_pmap[] = {
+  "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi@0",
+  "spi@1", "uart@0", "uart@0",
+};
+
+static const struct hw_port_descriptor bfin_dmac_59x_ports[] = {
+  { "ppi@0",       0, 0, input_port, },
+  { "sport@0_tx",  1, 0, input_port, },
+  { "sport@0_rx",  2, 0, input_port, },
+  { "sport@1_tx",  3, 0, input_port, },
+  { "sport@1_rx",  4, 0, input_port, },
+  { "spi@0",       5, 0, input_port, },
+  { "spi@1",       6, 0, input_port, },
+  { "uart@0_rx",   7, 0, input_port, },
+  { "uart@0_tx",   8, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+bfin_dmac_port_event (struct hw *me, int my_port, struct hw *source,
+                     int source_port, int level)
+{
+  SIM_DESC sd = hw_system (me);
+  struct bfin_dmac *dmac = hw_data (me);
+  struct hw *dma = hw_child (me);
+
+  while (dma)
+    {
+      bu16 pmap;
+      sim_hw_io_read_buffer (sd, dma, &pmap, 0, 0x2c, sizeof (pmap));
+      pmap >>= 12;
+      if (pmap == my_port)
+       break;
+      dma = hw_sibling (dma);
+    }
+
+  if (!dma)
+    hw_abort (me, "no valid dma mapping found for %s", dmac->pmap[my_port]);
+
+  /* Have the DMA channel raise its interrupt to the SIC.  */
+  hw_port_event (dma, 0, 1);
+}
+
+static void
+bfin_dmac_finish (struct hw *me)
+{
+  struct bfin_dmac *dmac;
+  unsigned int dmac_num = dv_get_bus_num (me);
+
+  dmac = HW_ZALLOC (me, struct bfin_dmac);
+
+  set_hw_data (me, dmac);
+  set_hw_port_event (me, bfin_dmac_port_event);
+
+  /* Initialize the DMA Controller.  */
+  if (hw_find_property (me, "type") == NULL)
+    hw_abort (me, "Missing \"type\" property");
+
+  switch (hw_find_integer_property (me, "type"))
+    {
+    case 500 ... 509:
+      if (dmac_num != 0)
+       hw_abort (me, "this Blackfin only has a DMAC0");
+      dmac->pmap = bfin_dmac_50x_pmap;
+      dmac->pmap_count = ARRAY_SIZE (bfin_dmac_50x_pmap);
+      set_hw_ports (me, bfin_dmac_50x_ports);
+      break;
+    case 510 ... 519:
+      if (dmac_num != 0)
+       hw_abort (me, "this Blackfin only has a DMAC0");
+      dmac->pmap = bfin_dmac_51x_pmap;
+      dmac->pmap_count = ARRAY_SIZE (bfin_dmac_51x_pmap);
+      set_hw_ports (me, bfin_dmac_51x_ports);
+      break;
+    case 522 ... 527:
+      if (dmac_num != 0)
+       hw_abort (me, "this Blackfin only has a DMAC0");
+      dmac->pmap = bfin_dmac_52x_pmap;
+      dmac->pmap_count = ARRAY_SIZE (bfin_dmac_52x_pmap);
+      set_hw_ports (me, bfin_dmac_52x_ports);
+      break;
+    case 531 ... 533:
+      if (dmac_num != 0)
+       hw_abort (me, "this Blackfin only has a DMAC0");
+      dmac->pmap = bfin_dmac_533_pmap;
+      dmac->pmap_count = ARRAY_SIZE (bfin_dmac_533_pmap);
+      set_hw_ports (me, bfin_dmac_533_ports);
+      break;
+    case 534:
+    case 536:
+    case 537:
+      if (dmac_num != 0)
+       hw_abort (me, "this Blackfin only has a DMAC0");
+      dmac->pmap = bfin_dmac_537_pmap;
+      dmac->pmap_count = ARRAY_SIZE (bfin_dmac_537_pmap);
+      set_hw_ports (me, bfin_dmac_537_ports);
+      break;
+    case 538 ... 539:
+      switch (dmac_num)
+       {
+       case 0:
+         dmac->pmap = bfin_dmac0_538_pmap;
+         dmac->pmap_count = ARRAY_SIZE (bfin_dmac0_538_pmap);
+         set_hw_ports (me, bfin_dmac0_538_ports);
+         break;
+       case 1:
+         dmac->pmap = bfin_dmac1_538_pmap;
+         dmac->pmap_count = ARRAY_SIZE (bfin_dmac1_538_pmap);
+         set_hw_ports (me, bfin_dmac1_538_ports);
+         break;
+       default:
+         hw_abort (me, "this Blackfin only has a DMAC0 & DMAC1");
+       }
+      break;
+    case 540 ... 549:
+      switch (dmac_num)
+       {
+       case 0:
+         dmac->pmap = bfin_dmac0_54x_pmap;
+         dmac->pmap_count = ARRAY_SIZE (bfin_dmac0_54x_pmap);
+         set_hw_ports (me, bfin_dmac0_54x_ports);
+         break;
+       case 1:
+         dmac->pmap = bfin_dmac1_54x_pmap;
+         dmac->pmap_count = ARRAY_SIZE (bfin_dmac1_54x_pmap);
+         set_hw_ports (me, bfin_dmac1_54x_ports);
+         break;
+       default:
+         hw_abort (me, "this Blackfin only has a DMAC0 & DMAC1");
+       }
+      break;
+    case 561:
+      switch (dmac_num)
+       {
+       case 0:
+         dmac->pmap = bfin_dmac0_561_pmap;
+         dmac->pmap_count = ARRAY_SIZE (bfin_dmac0_561_pmap);
+         set_hw_ports (me, bfin_dmac0_561_ports);
+         break;
+       case 1:
+         dmac->pmap = bfin_dmac1_561_pmap;
+         dmac->pmap_count = ARRAY_SIZE (bfin_dmac1_561_pmap);
+         set_hw_ports (me, bfin_dmac1_561_ports);
+         break;
+       default:
+         hw_abort (me, "this Blackfin only has a DMAC0 & DMAC1");
+       }
+      break;
+    case 590 ... 599:
+      if (dmac_num != 0)
+       hw_abort (me, "this Blackfin only has a DMAC0");
+      dmac->pmap = bfin_dmac_59x_pmap;
+      dmac->pmap_count = ARRAY_SIZE (bfin_dmac_59x_pmap);
+      set_hw_ports (me, bfin_dmac_59x_ports);
+      break;
+    default:
+      hw_abort (me, "no support for DMAC on this Blackfin model yet");
+    }
+}
+
+const struct hw_descriptor dv_bfin_dmac_descriptor[] = {
+  {"bfin_dmac", bfin_dmac_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_dmac.h b/sim/bfin/dv-bfin_dmac.h
new file mode 100644 (file)
index 0000000..dfe9535
--- /dev/null
@@ -0,0 +1,32 @@
+/* Blackfin Direct Memory Access (DMA) Controller model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_DMAC_H
+#define DV_BFIN_DMAC_H
+
+#define BFIN_MMR_DMAC0_BASE    0xFFC00C00
+#define BFIN_MMR_DMAC1_BASE    0xFFC01C00
+
+#define BFIN_DMAC_MDMA_BASE    0x100
+
+struct hw *bfin_dmac_get_peer (struct hw *dma, bu16 pmap);
+bu16 bfin_dmac_default_pmap (struct hw *dma);
+
+#endif
diff --git a/sim/bfin/dv-bfin_ebiu_amc.c b/sim/bfin/dv-bfin_ebiu_amc.c
new file mode 100644 (file)
index 0000000..504e33b
--- /dev/null
@@ -0,0 +1,456 @@
+/* Blackfin External Bus Interface Unit (EBIU) Asynchronous Memory Controller
+   (AMC) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_ebiu_amc.h"
+
+struct bfin_ebiu_amc
+{
+  bu32 base;
+  int type;
+  bu32 bank_size;
+  unsigned (*io_write) (struct hw *, const void *, int, address_word,
+                       unsigned, struct bfin_ebiu_amc *, bu32, bu32);
+  unsigned (*io_read) (struct hw *, void *, int, address_word, unsigned,
+                      struct bfin_ebiu_amc *, bu32, void *, bu16 *, bu32 *);
+  struct hw *slaves[4];
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu16 BFIN_MMR_16(amgctl);
+  union {
+    struct {
+      bu32 ambctl0, ambctl1;
+      bu32 _pad0[5];
+      bu16 BFIN_MMR_16(mode);
+      bu16 BFIN_MMR_16(fctl);
+    } bf50x;
+    struct {
+      bu32 ambctl0, ambctl1;
+    } bf53x;
+    struct {
+      bu32 ambctl0, ambctl1;
+      bu32 mbsctl, arbstat, mode, fctl;
+    } bf54x;
+  };
+};
+#define mmr_base()      offsetof(struct bfin_ebiu_amc, amgctl)
+#define mmr_offset(mmr) (offsetof(struct bfin_ebiu_amc, mmr) - mmr_base())
+#define mmr_idx(mmr)    (mmr_offset (mmr) / 4)
+
+static const char * const bf50x_mmr_names[] = {
+  "EBIU_AMGCTL", "EBIU_AMBCTL0", "EBIU_AMBCTL1",
+  [mmr_idx (bf50x.mode)] = "EBIU_MODE", "EBIU_FCTL",
+};
+static const char * const bf53x_mmr_names[] = {
+  "EBIU_AMGCTL", "EBIU_AMBCTL0", "EBIU_AMBCTL1",
+};
+static const char * const bf54x_mmr_names[] = {
+  "EBIU_AMGCTL", "EBIU_AMBCTL0", "EBIU_AMBCTL1",
+  "EBIU_MSBCTL", "EBIU_ARBSTAT", "EBIU_MODE", "EBIU_FCTL",
+};
+static const char * const *mmr_names;
+#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
+
+static void
+bfin_ebiu_amc_write_amgctl (struct hw *me, struct bfin_ebiu_amc *amc,
+                           bu16 amgctl)
+{
+  bu32 amben_old, amben, addr, i;
+
+  amben_old = MIN ((amc->amgctl >> 1) & 0x7, 4);
+  amben = MIN ((amgctl >> 1) & 0x7, 4);
+
+  HW_TRACE ((me, "reattaching banks: AMGCTL 0x%04x[%u] -> 0x%04x[%u]",
+            amc->amgctl, amben_old, amgctl, amben));
+
+  for (i = 0; i < 4; ++i)
+    {
+      addr = BFIN_EBIU_AMC_BASE + i * amc->bank_size;
+
+      if (i < amben_old)
+       {
+         HW_TRACE ((me, "detaching bank %u (%#x base)", i, addr));
+         sim_core_detach (hw_system (me), NULL, 0, 0, addr);
+       }
+
+      if (i < amben)
+       {
+         struct hw *slave = amc->slaves[i];
+
+         HW_TRACE ((me, "attaching bank %u (%#x base) to %s", i, addr,
+                    slave ? hw_path (slave) : "<floating pins>"));
+
+         sim_core_attach (hw_system (me), NULL, 0, access_read_write_exec,
+                          0, addr, amc->bank_size, 0, slave, NULL);
+       }
+    }
+
+  amc->amgctl = amgctl;
+}
+
+static unsigned
+bf50x_ebiu_amc_io_write_buffer (struct hw *me, const void *source, int space,
+                               address_word addr, unsigned nr_bytes,
+                               struct bfin_ebiu_amc *amc, bu32 mmr_off,
+                               bu32 value)
+{
+  switch (mmr_off)
+    {
+    case mmr_offset(amgctl):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      bfin_ebiu_amc_write_amgctl (me, amc, value);
+      break;
+    case mmr_offset(bf50x.ambctl0):
+      amc->bf50x.ambctl0 = value;
+      break;
+    case mmr_offset(bf50x.ambctl1):
+      amc->bf50x.ambctl1 = value;
+      break;
+    case mmr_offset(bf50x.mode):
+      /* XXX: implement this.  */
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      break;
+    case mmr_offset(bf50x.fctl):
+      /* XXX: implement this.  */
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bf53x_ebiu_amc_io_write_buffer (struct hw *me, const void *source, int space,
+                               address_word addr, unsigned nr_bytes,
+                               struct bfin_ebiu_amc *amc, bu32 mmr_off,
+                               bu32 value)
+{
+  switch (mmr_off)
+    {
+    case mmr_offset(amgctl):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      bfin_ebiu_amc_write_amgctl (me, amc, value);
+      break;
+    case mmr_offset(bf53x.ambctl0):
+      amc->bf53x.ambctl0 = value;
+      break;
+    case mmr_offset(bf53x.ambctl1):
+      amc->bf53x.ambctl1 = value;
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bf54x_ebiu_amc_io_write_buffer (struct hw *me, const void *source, int space,
+                               address_word addr, unsigned nr_bytes,
+                               struct bfin_ebiu_amc *amc, bu32 mmr_off,
+                               bu32 value)
+{
+  switch (mmr_off)
+    {
+    case mmr_offset(amgctl):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      bfin_ebiu_amc_write_amgctl (me, amc, value);
+      break;
+    case mmr_offset(bf54x.ambctl0):
+      amc->bf54x.ambctl0 = value;
+      break;
+    case mmr_offset(bf54x.ambctl1):
+      amc->bf54x.ambctl1 = value;
+      break;
+    case mmr_offset(bf54x.mbsctl):
+      /* XXX: implement this.  */
+      break;
+    case mmr_offset(bf54x.arbstat):
+      /* XXX: implement this.  */
+      break;
+    case mmr_offset(bf54x.mode):
+      /* XXX: implement this.  */
+      break;
+    case mmr_offset(bf54x.fctl):
+      /* XXX: implement this.  */
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_ebiu_amc_io_write_buffer (struct hw *me, const void *source, int space,
+                              address_word addr, unsigned nr_bytes)
+{
+  struct bfin_ebiu_amc *amc = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+
+  value = dv_load_4 (source);
+  mmr_off = addr - amc->base;
+
+  HW_TRACE_WRITE ();
+
+  return amc->io_write (me, source, space, addr, nr_bytes,
+                       amc, mmr_off, value);
+}
+
+static unsigned
+bf50x_ebiu_amc_io_read_buffer (struct hw *me, void *dest, int space,
+                              address_word addr, unsigned nr_bytes,
+                              struct bfin_ebiu_amc *amc, bu32 mmr_off,
+                              void *valuep, bu16 *value16, bu32 *value32)
+{
+  switch (mmr_off)
+    {
+    case mmr_offset(amgctl):
+    case mmr_offset(bf50x.fctl):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+      dv_store_2 (dest, *value16);
+      break;
+    case mmr_offset(bf50x.ambctl0):
+    case mmr_offset(bf50x.ambctl1):
+    case mmr_offset(bf50x.mode):
+      dv_store_4 (dest, *value32);
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bf53x_ebiu_amc_io_read_buffer (struct hw *me, void *dest, int space,
+                              address_word addr, unsigned nr_bytes,
+                              struct bfin_ebiu_amc *amc, bu32 mmr_off,
+                              void *valuep, bu16 *value16, bu32 *value32)
+{
+  switch (mmr_off)
+    {
+    case mmr_offset(amgctl):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+      dv_store_2 (dest, *value16);
+      break;
+    case mmr_offset(bf53x.ambctl0):
+    case mmr_offset(bf53x.ambctl1):
+      dv_store_4 (dest, *value32);
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bf54x_ebiu_amc_io_read_buffer (struct hw *me, void *dest, int space,
+                              address_word addr, unsigned nr_bytes,
+                              struct bfin_ebiu_amc *amc, bu32 mmr_off,
+                              void *valuep, bu16 *value16, bu32 *value32)
+{
+  switch (mmr_off)
+    {
+    case mmr_offset(amgctl):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+      dv_store_2 (dest, *value16);
+      break;
+    case mmr_offset(bf54x.ambctl0):
+    case mmr_offset(bf54x.ambctl1):
+    case mmr_offset(bf54x.mbsctl):
+    case mmr_offset(bf54x.arbstat):
+    case mmr_offset(bf54x.mode):
+    case mmr_offset(bf54x.fctl):
+      dv_store_4 (dest, *value32);
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_ebiu_amc_io_read_buffer (struct hw *me, void *dest, int space,
+                             address_word addr, unsigned nr_bytes)
+{
+  struct bfin_ebiu_amc *amc = hw_data (me);
+  bu32 mmr_off;
+  void *valuep;
+
+  mmr_off = addr - amc->base;
+  valuep = (void *)((unsigned long)amc + mmr_base() + mmr_off);
+
+  HW_TRACE_READ ();
+
+  return amc->io_read (me, dest, space, addr, nr_bytes, amc,
+                      mmr_off, valuep, valuep, valuep);
+}
+
+static void
+bfin_ebiu_amc_attach_address_callback (struct hw *me,
+                                      int level,
+                                      int space,
+                                      address_word addr,
+                                      address_word nr_bytes,
+                                      struct hw *client)
+{
+  struct bfin_ebiu_amc *amc = hw_data (me);
+
+  HW_TRACE ((me, "attach - level=%d, space=%d, addr=0x%lx, nr_bytes=%lu, client=%s",
+            level, space, (unsigned long) addr, (unsigned long) nr_bytes, hw_path (client)));
+
+  if (addr + nr_bytes > 4)
+    hw_abort (me, "ebiu amc attaches are done in terms of banks");
+
+  while (nr_bytes--)
+    amc->slaves[addr + nr_bytes] = client;
+
+  bfin_ebiu_amc_write_amgctl (me, amc, amc->amgctl);
+}
+
+static void
+attach_bfin_ebiu_amc_regs (struct hw *me, struct bfin_ebiu_amc *amc,
+                          unsigned reg_size)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  if (hw_find_property (me, "type") == NULL)
+    hw_abort (me, "Missing \"type\" property");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != reg_size)
+    hw_abort (me, "\"reg\" size must be %#x", reg_size);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  amc->base = attach_address;
+}
+
+static void
+bfin_ebiu_amc_finish (struct hw *me)
+{
+  struct bfin_ebiu_amc *amc;
+  bu32 amgctl;
+  unsigned reg_size;
+
+  amc = HW_ZALLOC (me, struct bfin_ebiu_amc);
+
+  set_hw_data (me, amc);
+  set_hw_io_read_buffer (me, bfin_ebiu_amc_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_ebiu_amc_io_write_buffer);
+  set_hw_attach_address (me, bfin_ebiu_amc_attach_address_callback);
+
+  amc->type = hw_find_integer_property (me, "type");
+
+  switch (amc->type)
+    {
+    case 500 ... 509:
+      amc->io_write = bf50x_ebiu_amc_io_write_buffer;
+      amc->io_read = bf50x_ebiu_amc_io_read_buffer;
+      mmr_names = bf50x_mmr_names;
+      reg_size = sizeof (amc->bf50x) + 4;
+
+      /* Initialize the AMC.  */
+      amc->bank_size     = 1 * 1024 * 1024;
+      amgctl             = 0x00F3;
+      amc->bf50x.ambctl0 = 0x0000FFC2;
+      amc->bf50x.ambctl1 = 0x0000FFC2;
+      amc->bf50x.mode    = 0x0001;
+      amc->bf50x.fctl    = 0x0002;
+      break;
+    case 540 ... 549:
+      amc->io_write = bf54x_ebiu_amc_io_write_buffer;
+      amc->io_read = bf54x_ebiu_amc_io_read_buffer;
+      mmr_names = bf54x_mmr_names;
+      reg_size = sizeof (amc->bf54x) + 4;
+
+      /* Initialize the AMC.  */
+      amc->bank_size     = 64 * 1024 * 1024;
+      amgctl             = 0x0002;
+      amc->bf54x.ambctl0 = 0xFFC2FFC2;
+      amc->bf54x.ambctl1 = 0xFFC2FFC2;
+      amc->bf54x.fctl    = 0x0006;
+      break;
+    case 510 ... 519:
+    case 522 ... 527:
+    case 531 ... 533:
+    case 534:
+    case 536:
+    case 537:
+    case 538 ... 539:
+    case 561:
+      amc->io_write = bf53x_ebiu_amc_io_write_buffer;
+      amc->io_read = bf53x_ebiu_amc_io_read_buffer;
+      mmr_names = bf53x_mmr_names;
+      reg_size = sizeof (amc->bf53x) + 4;
+
+      /* Initialize the AMC.  */
+      if (amc->type == 561)
+       amc->bank_size   = 64 * 1024 * 1024;
+      else
+       amc->bank_size   = 1 * 1024 * 1024;
+      amgctl             = 0x00F2;
+      amc->bf53x.ambctl0 = 0xFFC2FFC2;
+      amc->bf53x.ambctl1 = 0xFFC2FFC2;
+      break;
+    case 590 ... 599: /* BF59x has no AMC.  */
+    default:
+      hw_abort (me, "no support for EBIU AMC on this Blackfin model yet");
+    }
+
+  attach_bfin_ebiu_amc_regs (me, amc, reg_size);
+
+  bfin_ebiu_amc_write_amgctl (me, amc, amgctl);
+}
+
+const struct hw_descriptor dv_bfin_ebiu_amc_descriptor[] = {
+  {"bfin_ebiu_amc", bfin_ebiu_amc_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_ebiu_amc.h b/sim/bfin/dv-bfin_ebiu_amc.h
new file mode 100644 (file)
index 0000000..e47fd11
--- /dev/null
@@ -0,0 +1,31 @@
+/* Blackfin External Bus Interface Unit (EBIU) Asynchronous Memory Controller
+   (AMC) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_EBIU_AMC_H
+#define DV_BFIN_EBIU_AMC_H
+
+#define BFIN_MMR_EBIU_AMC_SIZE (4 * 3)
+#define BF50X_MMR_EBIU_AMC_SIZE        0x28
+#define BF54X_MMR_EBIU_AMC_SIZE        (4 * 7)
+
+#define BFIN_EBIU_AMC_BASE     0x20000000
+
+#endif
diff --git a/sim/bfin/dv-bfin_ebiu_ddrc.c b/sim/bfin/dv-bfin_ebiu_ddrc.c
new file mode 100644 (file)
index 0000000..fa54c8e
--- /dev/null
@@ -0,0 +1,184 @@
+/* Blackfin External Bus Interface Unit (EBIU) DDR Controller (DDRC) Model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_ebiu_ddrc.h"
+
+struct bfin_ebiu_ddrc
+{
+  bu32 base, reg_size, bank_size;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  union {
+    struct { bu32 ddrctl0, ddrctl1, ddrctl2, ddrctl3; };
+    bu32 ddrctl[4];
+  };
+  bu32 ddrque, erradd;
+  bu16 BFIN_MMR_16(errmst);
+  bu16 BFIN_MMR_16(rstctl);
+  bu32 ddrbrc[8], ddrbwc[8];
+  bu32 ddracct, ddrtact, ddrarct;
+  bu32 ddrgc[4];
+  bu32 ddrmcen, ddrmccl;
+};
+#define mmr_base()      offsetof(struct bfin_ebiu_ddrc, ddrctl0)
+#define mmr_offset(mmr) (offsetof(struct bfin_ebiu_ddrc, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "EBIU_DDRCTL0", "EBIU_DDRCTL1", "EBIU_DDRCTL2", "EBIU_DDRCTL3", "EBIU_DDRQUE",
+  "EBIU_ERRADD", "EBIU_ERRMST", "EBIU_RSTCTL", "EBIU_DDRBRC0", "EBIU_DDRBRC1",
+  "EBIU_DDRBRC2", "EBIU_DDRBRC3", "EBIU_DDRBRC4", "EBIU_DDRBRC5",
+  "EBIU_DDRBRC6", "EBIU_DDRBRC7", "EBIU_DDRBWC0", "EBIU_DDRBWC1"
+  "EBIU_DDRBWC2", "EBIU_DDRBWC3", "EBIU_DDRBWC4", "EBIU_DDRBWC5",
+  "EBIU_DDRBWC6", "EBIU_DDRBWC7", "EBIU_DDRACCT", "EBIU_DDRTACT",
+  "EBIU_ARCT", "EBIU_DDRGC0", "EBIU_DDRGC1", "EBIU_DDRGC2", "EBIU_DDRGC3",
+  "EBIU_DDRMCEN", "EBIU_DDRMCCL",
+};
+#define mmr_name(off) mmr_names[(off) / 4]
+
+static unsigned
+bfin_ebiu_ddrc_io_write_buffer (struct hw *me, const void *source,
+                              int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_ebiu_ddrc *ddrc = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  if (nr_bytes == 4)
+    value = dv_load_4 (source);
+  else
+    value = dv_load_2 (source);
+
+  mmr_off = addr - ddrc->base;
+  valuep = (void *)((unsigned long)ddrc + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_WRITE ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(errmst):
+    case mmr_offset(rstctl):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      *value16p = value;
+      break;
+    default:
+      dv_bfin_mmr_require_32 (me, addr, nr_bytes, true);
+      *value32p = value;
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_ebiu_ddrc_io_read_buffer (struct hw *me, void *dest,
+                             int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_ebiu_ddrc *ddrc = hw_data (me);
+  bu32 mmr_off;
+  bu32 *value32p;
+  bu16 *value16p;
+  void *valuep;
+
+  mmr_off = addr - ddrc->base;
+  valuep = (void *)((unsigned long)ddrc + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(errmst):
+    case mmr_offset(rstctl):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+      dv_store_2 (dest, *value16p);
+      break;
+    default:
+      dv_bfin_mmr_require_32 (me, addr, nr_bytes, false);
+      dv_store_4 (dest, *value32p);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static void
+attach_bfin_ebiu_ddrc_regs (struct hw *me, struct bfin_ebiu_ddrc *ddrc)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_EBIU_DDRC_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_EBIU_DDRC_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  ddrc->base = attach_address;
+}
+
+static void
+bfin_ebiu_ddrc_finish (struct hw *me)
+{
+  struct bfin_ebiu_ddrc *ddrc;
+
+  ddrc = HW_ZALLOC (me, struct bfin_ebiu_ddrc);
+
+  set_hw_data (me, ddrc);
+  set_hw_io_read_buffer (me, bfin_ebiu_ddrc_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_ebiu_ddrc_io_write_buffer);
+
+  attach_bfin_ebiu_ddrc_regs (me, ddrc);
+
+  /* Initialize the DDRC.  */
+  ddrc->ddrctl0 = 0x098E8411;
+  ddrc->ddrctl1 = 0x10026223;
+  ddrc->ddrctl2 = 0x00000021;
+  ddrc->ddrctl3 = 0x00000003; /* XXX: MDDR is 0x20 ...  */
+  ddrc->ddrque = 0x00001115;
+  ddrc->rstctl = 0x0002;
+}
+
+const struct hw_descriptor dv_bfin_ebiu_ddrc_descriptor[] = {
+  {"bfin_ebiu_ddrc", bfin_ebiu_ddrc_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_ebiu_ddrc.h b/sim/bfin/dv-bfin_ebiu_ddrc.h
new file mode 100644 (file)
index 0000000..ac970bf
--- /dev/null
@@ -0,0 +1,26 @@
+/* Blackfin External Bus Interface Unit (EBIU) DDR Controller (DDRC) Model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_EBIU_DDRC_H
+#define DV_BFIN_EBIU_DDRC_H
+
+#define BFIN_MMR_EBIU_DDRC_SIZE        0xb0
+
+#endif
diff --git a/sim/bfin/dv-bfin_ebiu_sdc.c b/sim/bfin/dv-bfin_ebiu_sdc.c
new file mode 100644 (file)
index 0000000..710f2f8
--- /dev/null
@@ -0,0 +1,201 @@
+/* Blackfin External Bus Interface Unit (EBIU) SDRAM Controller (SDC) Model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_ebiu_sdc.h"
+
+struct bfin_ebiu_sdc
+{
+  bu32 base;
+  int type;
+  bu32 reg_size, bank_size;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu32 sdgctl;
+  bu32 sdbctl; /* 16bit on most parts ... */
+  bu16 BFIN_MMR_16(sdrrc);
+  bu16 BFIN_MMR_16(sdstat);
+};
+#define mmr_base()      offsetof(struct bfin_ebiu_sdc, sdgctl)
+#define mmr_offset(mmr) (offsetof(struct bfin_ebiu_sdc, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "EBIU_SDGCTL", "EBIU_SDBCTL", "EBIU_SDRRC", "EBIU_SDSTAT",
+};
+#define mmr_name(off) mmr_names[(off) / 4]
+
+static unsigned
+bfin_ebiu_sdc_io_write_buffer (struct hw *me, const void *source,
+                              int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_ebiu_sdc *sdc = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  if (nr_bytes == 4)
+    value = dv_load_4 (source);
+  else
+    value = dv_load_2 (source);
+
+  mmr_off = addr - sdc->base;
+  valuep = (void *)((unsigned long)sdc + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_WRITE ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(sdgctl):
+      /* XXX: SRFS should make external mem unreadable.  */
+      *value32p = value;
+      break;
+    case mmr_offset(sdbctl):
+      if (sdc->type == 561)
+       {
+         dv_bfin_mmr_require_32 (me, addr, nr_bytes, true);
+         *value32p = value;
+       }
+      else
+       {
+         dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+         *value16p = value;
+       }
+      break;
+    case mmr_offset(sdrrc):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      *value16p = value;
+      break;
+    case mmr_offset(sdstat):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      /* XXX: Some bits are W1C ...  */
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_ebiu_sdc_io_read_buffer (struct hw *me, void *dest,
+                             int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_ebiu_sdc *sdc = hw_data (me);
+  bu32 mmr_off;
+  bu32 *value32p;
+  bu16 *value16p;
+  void *valuep;
+
+  mmr_off = addr - sdc->base;
+  valuep = (void *)((unsigned long)sdc + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(sdgctl):
+      dv_store_4 (dest, *value32p);
+      break;
+    case mmr_offset(sdbctl):
+      if (sdc->type == 561)
+       {
+         dv_bfin_mmr_require_32 (me, addr, nr_bytes, false);
+         dv_store_4 (dest, *value32p);
+       }
+      else
+       {
+         dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+         dv_store_2 (dest, *value16p);
+       }
+      break;
+    case mmr_offset(sdrrc):
+    case mmr_offset(sdstat):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+      dv_store_2 (dest, *value16p);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static void
+attach_bfin_ebiu_sdc_regs (struct hw *me, struct bfin_ebiu_sdc *sdc)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_EBIU_SDC_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_EBIU_SDC_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  sdc->base = attach_address;
+}
+
+static void
+bfin_ebiu_sdc_finish (struct hw *me)
+{
+  struct bfin_ebiu_sdc *sdc;
+
+  sdc = HW_ZALLOC (me, struct bfin_ebiu_sdc);
+
+  set_hw_data (me, sdc);
+  set_hw_io_read_buffer (me, bfin_ebiu_sdc_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_ebiu_sdc_io_write_buffer);
+
+  attach_bfin_ebiu_sdc_regs (me, sdc);
+
+  sdc->type = hw_find_integer_property (me, "type");
+
+  /* Initialize the SDC.  */
+  sdc->sdgctl = 0xE0088849;
+  sdc->sdbctl = 0x00000000;
+  sdc->sdrrc = 0x081A;
+  sdc->sdstat = 0x0008;
+
+  /* XXX: We boot with 64M external memory by default ...  */
+  sdc->sdbctl |= EBE | EBSZ_64 | EBCAW_10;
+}
+
+const struct hw_descriptor dv_bfin_ebiu_sdc_descriptor[] = {
+  {"bfin_ebiu_sdc", bfin_ebiu_sdc_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_ebiu_sdc.h b/sim/bfin/dv-bfin_ebiu_sdc.h
new file mode 100644 (file)
index 0000000..7849806
--- /dev/null
@@ -0,0 +1,39 @@
+/* Blackfin External Bus Interface Unit (EBIU) SDRAM Controller (SDC) Model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_EBIU_SDC_H
+#define DV_BFIN_EBIU_SDC_H
+
+#define BFIN_MMR_EBIU_SDC_SIZE (4 * 4)
+
+/* EBIU_SDBCTL Masks */
+#define EBE            0x0001  /* Enable SDRAM External Bank */
+#define EBSZ_16                0x0000  /* Size = 16MB */
+#define EBSZ_32                0x0002  /* Size = 32MB */
+#define EBSZ_64                0x0004  /* Size = 64MB */
+#define EBSZ_128       0x0006  /* Size = 128MB */
+#define EBSZ_256       0x0008  /* Size = 256MB */
+#define EBSZ_512       0x000A  /* Size = 512MB */
+#define EBCAW_8                0x0000  /* Column Address Width = 8 Bits */
+#define EBCAW_9                0x0010  /* Column Address Width = 9 Bits */
+#define EBCAW_10       0x0020  /* Column Address Width = 10 Bits */
+#define EBCAW_11       0x0030  /* Column Address Width = 11 Bits */
+
+#endif
diff --git a/sim/bfin/dv-bfin_emac.c b/sim/bfin/dv-bfin_emac.c
new file mode 100644 (file)
index 0000000..bfd8dc9
--- /dev/null
@@ -0,0 +1,603 @@
+/* Blackfin Ethernet Media Access Controller (EMAC) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_LINUX_IF_TUN_H
+#include <linux/if_tun.h>
+#endif
+
+#ifdef HAVE_LINUX_IF_TUN_H
+# define WITH_TUN 1
+#else
+# define WITH_TUN 0
+#endif
+
+#include "sim-main.h"
+#include "sim-hw.h"
+#include "devices.h"
+#include "dv-bfin_emac.h"
+
+/* XXX: This doesn't support partial DMA transfers.  */
+/* XXX: The TUN pieces should be pushed to the PHY so that we work with
+        multiple "networks" and the PHY takes care of it.  */
+
+struct bfin_emac
+{
+  /* This top portion matches common dv_bfin struct.  */
+  bu32 base;
+  struct hw *dma_master;
+  bool acked;
+
+  int tap;
+#if WITH_TUN
+  struct ifreq ifr;
+#endif
+  bu32 rx_crc;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu32 opmode, addrlo, addrhi, hashlo, hashhi, staadd, stadat, flc, vlan1, vlan2;
+  bu32 _pad0;
+  bu32 wkup_ctl, wkup_ffmsk0, wkup_ffmsk1, wkup_ffmsk2, wkup_ffmsk3;
+  bu32 wkup_ffcmd, wkup_ffoff, wkup_ffcrc0, wkup_ffcrc1;
+  bu32 _pad1[4];
+  bu32 sysctl, systat, rx_stat, rx_stky, rx_irqe, tx_stat, tx_stky, tx_irqe;
+  bu32 mmc_ctl, mmc_rirqs, mmc_rirqe, mmc_tirqs, mmc_tirqe;
+  bu32 _pad2[3];
+  bu16 BFIN_MMR_16(ptp_ctl);
+  bu16 BFIN_MMR_16(ptp_ie);
+  bu16 BFIN_MMR_16(ptp_istat);
+  bu32 ptp_foff, ptp_fv1, ptp_fv2, ptp_fv3, ptp_addend, ptp_accr, ptp_offset;
+  bu32 ptp_timelo, ptp_timehi, ptp_rxsnaplo, ptp_rxsnaphi, ptp_txsnaplo;
+  bu32 ptp_txsnaphi, ptp_alarmlo, ptp_alarmhi, ptp_id_off, ptp_id_snap;
+  bu32 ptp_pps_startlo, ptp_pps_starthi, ptp_pps_period;
+  bu32 _pad3[1];
+  bu32 rxc_ok, rxc_fcs, rxc_lign, rxc_octet, rxc_dmaovf, rxc_unicst, rxc_multi;
+  bu32 rxc_broad, rxc_lnerri, rxc_lnerro, rxc_long, rxc_macctl, rxc_opcode;
+  bu32 rxc_pause, rxc_allfrm, rxc_alloct, rxc_typed, rxc_short, rxc_eq64;
+  bu32 rxc_lt128, rxc_lt256, rxc_lt512, rxc_lt1024, rxc_ge1024;
+  bu32 _pad4[8];
+  bu32 txc_ok, txc_1col, txc_gt1col, txc_octet, txc_defer, txc_latecl;
+  bu32 txc_xs_col, txc_dmaund, txc_crserr, txc_unicst, txc_multi, txc_broad;
+  bu32 txc_xs_dfr, txc_macctl, txc_allfrm, txc_alloct, txc_eq64, txc_lt128;
+  bu32 txc_lt256, txc_lt512, txc_lt1024, txc_ge1024, txc_abort;
+};
+#define mmr_base()      offsetof(struct bfin_emac, opmode)
+#define mmr_offset(mmr) (offsetof(struct bfin_emac, mmr) - mmr_base())
+#define mmr_idx(mmr)    (mmr_offset (mmr) / 4)
+
+static const char * const mmr_names[BFIN_MMR_EMAC_SIZE / 4] = {
+  "EMAC_OPMODE", "EMAC_ADDRLO", "EMAC_ADDRHI", "EMAC_HASHLO", "EMAC_HASHHI",
+  "EMAC_STAADD", "EMAC_STADAT", "EMAC_FLC", "EMAC_VLAN1", "EMAC_VLAN2", NULL,
+  "EMAC_WKUP_CTL", "EMAC_WKUP_FFMSK0", "EMAC_WKUP_FFMSK1", "EMAC_WKUP_FFMSK2",
+  "EMAC_WKUP_FFMSK3", "EMAC_WKUP_FFCMD", "EMAC_WKUP_FFOFF", "EMAC_WKUP_FFCRC0",
+  "EMAC_WKUP_FFCRC1", [mmr_idx (sysctl)] = "EMAC_SYSCTL", "EMAC_SYSTAT",
+  "EMAC_RX_STAT", "EMAC_RX_STKY", "EMAC_RX_IRQE", "EMAC_TX_STAT",
+  "EMAC_TX_STKY", "EMAC_TX_IRQE", "EMAC_MMC_CTL", "EMAC_MMC_RIRQS",
+  "EMAC_MMC_RIRQE", "EMAC_MMC_TIRQS", "EMAC_MMC_TIRQE",
+  [mmr_idx (ptp_ctl)] = "EMAC_PTP_CTL", "EMAC_PTP_IE", "EMAC_PTP_ISTAT",
+  "EMAC_PTP_FOFF", "EMAC_PTP_FV1", "EMAC_PTP_FV2", "EMAC_PTP_FV3",
+  "EMAC_PTP_ADDEND", "EMAC_PTP_ACCR", "EMAC_PTP_OFFSET", "EMAC_PTP_TIMELO",
+  "EMAC_PTP_TIMEHI", "EMAC_PTP_RXSNAPLO", "EMAC_PTP_RXSNAPHI",
+  "EMAC_PTP_TXSNAPLO", "EMAC_PTP_TXSNAPHI", "EMAC_PTP_ALARMLO",
+  "EMAC_PTP_ALARMHI", "EMAC_PTP_ID_OFF", "EMAC_PTP_ID_SNAP",
+  "EMAC_PTP_PPS_STARTLO", "EMAC_PTP_PPS_STARTHI", "EMAC_PTP_PPS_PERIOD",
+  [mmr_idx (rxc_ok)] = "EMAC_RXC_OK", "EMAC_RXC_FCS", "EMAC_RXC_LIGN",
+  "EMAC_RXC_OCTET", "EMAC_RXC_DMAOVF", "EMAC_RXC_UNICST", "EMAC_RXC_MULTI",
+  "EMAC_RXC_BROAD", "EMAC_RXC_LNERRI", "EMAC_RXC_LNERRO", "EMAC_RXC_LONG",
+  "EMAC_RXC_MACCTL", "EMAC_RXC_OPCODE", "EMAC_RXC_PAUSE", "EMAC_RXC_ALLFRM",
+  "EMAC_RXC_ALLOCT", "EMAC_RXC_TYPED", "EMAC_RXC_SHORT", "EMAC_RXC_EQ64",
+  "EMAC_RXC_LT128", "EMAC_RXC_LT256", "EMAC_RXC_LT512", "EMAC_RXC_LT1024",
+  "EMAC_RXC_GE1024",
+  [mmr_idx (txc_ok)] = "EMAC_TXC_OK", "EMAC_TXC_1COL", "EMAC_TXC_GT1COL",
+  "EMAC_TXC_OCTET", "EMAC_TXC_DEFER", "EMAC_TXC_LATECL", "EMAC_TXC_XS_COL",
+  "EMAC_TXC_DMAUND", "EMAC_TXC_CRSERR", "EMAC_TXC_UNICST", "EMAC_TXC_MULTI",
+  "EMAC_TXC_BROAD", "EMAC_TXC_XS_DFR", "EMAC_TXC_MACCTL", "EMAC_TXC_ALLFRM",
+  "EMAC_TXC_ALLOCT", "EMAC_TXC_EQ64", "EMAC_TXC_LT128", "EMAC_TXC_LT256",
+  "EMAC_TXC_LT512", "EMAC_TXC_LT1024", "EMAC_TXC_GE1024", "EMAC_TXC_ABORT",
+};
+#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
+
+static struct hw *
+mii_find_phy (struct hw *me, bu8 addr)
+{
+  struct hw *phy = hw_child (me);
+  while (phy && --addr)
+    phy = hw_sibling (phy);
+  return phy;
+}
+
+static void
+mii_write (struct hw *me)
+{
+  SIM_DESC sd = hw_system (me);
+  struct bfin_emac *emac = hw_data (me);
+  struct hw *phy;
+  bu8 addr = PHYAD (emac->staadd);
+  bu8 reg = REGAD (emac->staadd);
+  bu16 data = emac->stadat;
+
+  phy = mii_find_phy (me, addr);
+  if (!phy)
+    return;
+  sim_hw_io_write_buffer (sd, phy, &data, 1, reg, 2);
+}
+
+static void
+mii_read (struct hw *me)
+{
+  SIM_DESC sd = hw_system (me);
+  struct bfin_emac *emac = hw_data (me);
+  struct hw *phy;
+  bu8 addr = PHYAD (emac->staadd);
+  bu8 reg = REGAD (emac->staadd);
+  bu16 data;
+
+  phy = mii_find_phy (me, addr);
+  if (!phy || sim_hw_io_read_buffer (sd, phy, &data, 1, reg, 2) != 2)
+    data = 0xffff;
+
+  emac->stadat = data;
+}
+
+static unsigned
+bfin_emac_io_write_buffer (struct hw *me, const void *source,
+                          int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_emac *emac = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu32 *valuep;
+
+  /* XXX: 16bit accesses are allowed ...  */
+  dv_bfin_mmr_require_32 (me, addr, nr_bytes, true);
+  value = dv_load_4 (source);
+
+  mmr_off = addr - emac->base;
+  valuep = (void *)((unsigned long)emac + mmr_base() + mmr_off);
+
+  HW_TRACE_WRITE ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(hashlo):
+    case mmr_offset(hashhi):
+    case mmr_offset(stadat):
+    case mmr_offset(flc):
+    case mmr_offset(vlan1):
+    case mmr_offset(vlan2):
+    case mmr_offset(wkup_ffmsk0):
+    case mmr_offset(wkup_ffmsk1):
+    case mmr_offset(wkup_ffmsk2):
+    case mmr_offset(wkup_ffmsk3):
+    case mmr_offset(wkup_ffcmd):
+    case mmr_offset(wkup_ffoff):
+    case mmr_offset(wkup_ffcrc0):
+    case mmr_offset(wkup_ffcrc1):
+    case mmr_offset(sysctl):
+    case mmr_offset(rx_irqe):
+    case mmr_offset(tx_irqe):
+    case mmr_offset(mmc_rirqe):
+    case mmr_offset(mmc_tirqe):
+      *valuep = value;
+      break;
+    case mmr_offset(opmode):
+      if (!(*valuep & RE) && (value & RE))
+       emac->rx_stat &= ~RX_COMP;
+      if (!(*valuep & TE) && (value & TE))
+       emac->tx_stat &= ~TX_COMP;
+      *valuep = value;
+      break;
+    case mmr_offset(addrlo):
+    case mmr_offset(addrhi):
+      *valuep = value;
+      break;
+    case mmr_offset(wkup_ctl):
+      dv_w1c_4_partial (valuep, value, 0xf20);
+      break;
+    case mmr_offset(systat):
+      dv_w1c_4 (valuep, value, 0x1e);
+      break;
+    case mmr_offset(staadd):
+      *valuep = value | STABUSY;
+      if (value & STAOP)
+       mii_write (me);
+      else
+       mii_read (me);
+      *valuep &= ~STABUSY;
+      break;
+    case mmr_offset(rx_stat):
+    case mmr_offset(tx_stat):
+      /* Discard writes to these.  */
+      break;
+    case mmr_offset(rx_stky):
+    case mmr_offset(tx_stky):
+    case mmr_offset(mmc_rirqs):
+    case mmr_offset(mmc_tirqs):
+      dv_w1c_4 (valuep, value, 0);
+      break;
+    case mmr_offset(mmc_ctl):
+      /* Writing to bit 0 clears all counters.  */
+      *valuep = value & ~1;
+      if (value & 1)
+       {
+         memset (&emac->rxc_ok, 0, mmr_offset (rxc_ge1024) - mmr_offset (rxc_ok) + 4);
+         memset (&emac->txc_ok, 0, mmr_offset (txc_abort) - mmr_offset (txc_ok) + 4);
+       }
+      break;
+    case mmr_offset(rxc_ok) ... mmr_offset(rxc_ge1024):
+    case mmr_offset(txc_ok) ... mmr_offset(txc_abort):
+      /* XXX: Are these supposed to be read-only ?  */
+      *valuep = value;
+      break;
+    case mmr_offset(ptp_ctl) ... mmr_offset(ptp_pps_period):
+      /* XXX: Only on some models; ignore for now.  */
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_emac_io_read_buffer (struct hw *me, void *dest,
+                         int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_emac *emac = hw_data (me);
+  bu32 mmr_off;
+  bu32 *valuep;
+
+  /* XXX: 16bit accesses are allowed ...  */
+  dv_bfin_mmr_require_32 (me, addr, nr_bytes, false);
+
+  mmr_off = addr - emac->base;
+  valuep = (void *)((unsigned long)emac + mmr_base() + mmr_off);
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(opmode):
+    case mmr_offset(addrlo):
+    case mmr_offset(addrhi):
+    case mmr_offset(hashlo):
+    case mmr_offset(hashhi):
+    case mmr_offset(staadd):
+    case mmr_offset(stadat):
+    case mmr_offset(flc):
+    case mmr_offset(vlan1):
+    case mmr_offset(vlan2):
+    case mmr_offset(wkup_ctl):
+    case mmr_offset(wkup_ffmsk0):
+    case mmr_offset(wkup_ffmsk1):
+    case mmr_offset(wkup_ffmsk2):
+    case mmr_offset(wkup_ffmsk3):
+    case mmr_offset(wkup_ffcmd):
+    case mmr_offset(wkup_ffoff):
+    case mmr_offset(wkup_ffcrc0):
+    case mmr_offset(wkup_ffcrc1):
+    case mmr_offset(sysctl):
+    case mmr_offset(systat):
+    case mmr_offset(rx_stat):
+    case mmr_offset(rx_stky):
+    case mmr_offset(rx_irqe):
+    case mmr_offset(tx_stat):
+    case mmr_offset(tx_stky):
+    case mmr_offset(tx_irqe):
+    case mmr_offset(mmc_rirqs):
+    case mmr_offset(mmc_rirqe):
+    case mmr_offset(mmc_tirqs):
+    case mmr_offset(mmc_tirqe):
+    case mmr_offset(mmc_ctl):
+    case mmr_offset(rxc_ok) ... mmr_offset(rxc_ge1024):
+    case mmr_offset(txc_ok) ... mmr_offset(txc_abort):
+      dv_store_4 (dest, *valuep);
+      break;
+    case mmr_offset(ptp_ctl) ... mmr_offset(ptp_pps_period):
+      /* XXX: Only on some models; ignore for now.  */
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static void
+attach_bfin_emac_regs (struct hw *me, struct bfin_emac *emac)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_EMAC_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_EMAC_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  emac->base = attach_address;
+}
+
+static struct dv_bfin *dma_tx;
+
+static unsigned
+bfin_emac_dma_read_buffer (struct hw *me, void *dest, int space,
+                          unsigned_word addr, unsigned nr_bytes)
+{
+  struct bfin_emac *emac = hw_data (me);
+  struct dv_bfin *dma = hw_data (emac->dma_master);
+  unsigned char *data = dest;
+  static bool flop; /* XXX: This sucks.  */
+  bu16 len;
+  ssize_t ret;
+
+  HW_TRACE_DMA_READ ();
+
+  if (dma_tx == dma)
+    {
+      /* Handle the TX turn around and write the status.  */
+      emac->tx_stat |= TX_OK;
+      emac->tx_stky |= TX_OK;
+
+      memcpy (data, &emac->tx_stat, 4);
+
+      dma->acked = true;
+      return 4;
+    }
+
+  if (!(emac->opmode & RE))
+    return 0;
+
+  if (!flop)
+    {
+      ssize_t pad_ret;
+      /* Outgoing DMA buffer has 16bit len prepended to it.  */
+      data += 2;
+
+      /* This doesn't seem to work.
+      if (emac->sysctl & RXDWA)
+       {
+         memset (data, 0, 2);
+         data += 2;
+       } */
+
+      ret = read (emac->tap, data, nr_bytes);
+      if (ret < 0)
+       return 0;
+      ret += 4; /* include crc */
+      pad_ret = MAX (ret + 4, 64);
+      len = pad_ret;
+      memcpy (dest, &len, 2);
+
+      pad_ret = (pad_ret + 3) & ~3;
+      if (ret < pad_ret)
+       memset (data + ret, 0, pad_ret - ret);
+      pad_ret += 4;
+
+      /* XXX: Need to check -- u-boot doesn't look at this.  */
+      if (emac->sysctl & RXCKS)
+       {
+         pad_ret += 4;
+         emac->rx_crc = 0;
+       }
+      ret = pad_ret;
+
+      /* XXX: Don't support promiscuous yet.  */
+      emac->rx_stat |= RX_ACCEPT;
+      emac->rx_stat = (emac->rx_stat & ~RX_FRLEN) | len;
+
+      emac->rx_stat |= RX_COMP;
+      emac->rx_stky |= RX_COMP;
+    }
+  else
+    {
+      /* Write the RX status and crc info.  */
+      emac->rx_stat |= RX_OK;
+      emac->rx_stky |= RX_OK;
+
+      ret = 4;
+      if (emac->sysctl & RXCKS)
+       {
+         memcpy (data, &emac->rx_crc, 4);
+         data += 4;
+         ret += 4;
+       }
+      memcpy (data, &emac->rx_stat, 4);
+    }
+
+  flop = !flop;
+  dma->acked = true;
+  return ret;
+}
+
+static unsigned
+bfin_emac_dma_write_buffer (struct hw *me, const void *source,
+                           int space, unsigned_word addr,
+                           unsigned nr_bytes,
+                           int violate_read_only_section)
+{
+  struct bfin_emac *emac = hw_data (me);
+  struct dv_bfin *dma = hw_data (emac->dma_master);
+  const unsigned char *data = source;
+  bu16 len;
+  ssize_t ret;
+
+  HW_TRACE_DMA_WRITE ();
+
+  if (!(emac->opmode & TE))
+    return 0;
+
+  /* Incoming DMA buffer has 16bit len prepended to it.  */
+  memcpy (&len, data, 2);
+  if (!len)
+    return 0;
+
+  ret = write (emac->tap, data + 2, len);
+  if (ret < 0)
+    return 0;
+  ret += 2;
+
+  emac->tx_stat |= TX_COMP;
+  emac->tx_stky |= TX_COMP;
+
+  dma_tx = dma;
+  dma->acked = true;
+  return ret;
+}
+
+static const struct hw_port_descriptor bfin_emac_ports[] = {
+  { "tx",   DV_PORT_TX,   0, output_port, },
+  { "rx",   DV_PORT_RX,   0, output_port, },
+  { "stat", DV_PORT_STAT, 0, output_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+bfin_emac_attach_address_callback (struct hw *me,
+                                  int level,
+                                  int space,
+                                  address_word addr,
+                                  address_word nr_bytes,
+                                  struct hw *client)
+{
+  const hw_unit *unit = hw_unit_address (client);
+  HW_TRACE ((me, "attach - level=%d, space=%d, addr=0x%lx, nr_bytes=%lu, client=%s",
+            level, space, (unsigned long) addr, (unsigned long) nr_bytes, hw_path (client)));
+  /* NOTE: At preset the space is assumed to be zero.  Perhaphs the
+     space should be mapped onto something for instance: space0 -
+     unified memory; space1 - IO memory; ... */
+  sim_core_attach (hw_system (me),
+                  NULL, /*cpu*/
+                  level + 10 + unit->cells[unit->nr_cells - 1],
+                  access_read_write_exec,
+                  space, addr,
+                  nr_bytes,
+                  0, /* modulo */
+                  client,
+                  NULL);
+}
+
+static void
+bfin_emac_delete (struct hw *me)
+{
+  struct bfin_emac *emac = hw_data (me);
+  close (emac->tap);
+}
+
+static void
+bfin_emac_tap_init (struct hw *me)
+{
+#if WITH_TUN
+  struct bfin_emac *emac = hw_data (me);
+  const hw_unit *unit;
+  int flags;
+
+  unit = hw_unit_address (me);
+
+  emac->tap = open ("/dev/net/tun", O_RDWR);
+  if (emac->tap == -1)
+    {
+      HW_TRACE ((me, "unable to open /dev/net/tun: %s", strerror (errno)));
+      return;
+    }
+
+  memset (&emac->ifr, 0, sizeof (emac->ifr));
+  emac->ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+  strcpy (emac->ifr.ifr_name, "tap-gdb");
+
+  flags = 1 * 1024 * 1024;
+  if (ioctl (emac->tap, TUNSETIFF, &emac->ifr) < 0
+#ifdef TUNSETNOCSUM
+      || ioctl (emac->tap, TUNSETNOCSUM) < 0
+#endif
+#ifdef TUNSETSNDBUF
+      || ioctl (emac->tap, TUNSETSNDBUF, &flags) < 0
+#endif
+     )
+    {
+      HW_TRACE ((me, "tap ioctl setup failed: %s", strerror (errno)));
+      close (emac->tap);
+      return;
+    }
+
+  flags = fcntl (emac->tap, F_GETFL);
+  fcntl (emac->tap, F_SETFL, flags | O_NONBLOCK);
+#endif
+}
+
+static void
+bfin_emac_finish (struct hw *me)
+{
+  struct bfin_emac *emac;
+
+  emac = HW_ZALLOC (me, struct bfin_emac);
+
+  set_hw_data (me, emac);
+  set_hw_io_read_buffer (me, bfin_emac_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_emac_io_write_buffer);
+  set_hw_dma_read_buffer (me, bfin_emac_dma_read_buffer);
+  set_hw_dma_write_buffer (me, bfin_emac_dma_write_buffer);
+  set_hw_ports (me, bfin_emac_ports);
+  set_hw_attach_address (me, bfin_emac_attach_address_callback);
+  set_hw_delete (me, bfin_emac_delete);
+
+  attach_bfin_emac_regs (me, emac);
+
+  /* Initialize the EMAC.  */
+  emac->addrlo = 0xffffffff;
+  emac->addrhi = 0x0000ffff;
+  emac->vlan1 = 0x0000ffff;
+  emac->vlan2 = 0x0000ffff;
+  emac->sysctl = 0x00003f00;
+  emac->mmc_ctl = 0x0000000a;
+
+  bfin_emac_tap_init (me);
+}
+
+const struct hw_descriptor dv_bfin_emac_descriptor[] = {
+  {"bfin_emac", bfin_emac_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_emac.h b/sim/bfin/dv-bfin_emac.h
new file mode 100644 (file)
index 0000000..2522292
--- /dev/null
@@ -0,0 +1,61 @@
+/* Blackfin Ethernet Media Access Controller (EMAC) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_EMAC_H
+#define DV_BFIN_EMAC_H
+
+#define BFIN_MMR_EMAC_BASE     0xFFC03000
+#define BFIN_MMR_EMAC_SIZE     0x200
+
+/* EMAC_OPMODE Masks */
+#define RE             (1 << 0)
+#define ASTP           (1 << 1)
+#define PR             (1 << 7)
+#define TE             (1 << 16)
+
+/* EMAC_STAADD Masks */
+#define STABUSY                (1 << 0)
+#define STAOP          (1 << 1)
+#define STADISPRE      (1 << 2)
+#define STAIE          (1 << 3)
+#define REGAD_SHIFT    6
+#define REGAD_MASK     (0x1f << REGAD_SHIFT)
+#define REGAD(val)     (((val) & REGAD_MASK) >> REGAD_SHIFT)
+#define PHYAD_SHIFT    11
+#define PHYAD_MASK     (0x1f << PHYAD_SHIFT)
+#define PHYAD(val)     (((val) & PHYAD_MASK) >> PHYAD_SHIFT)
+
+/* EMAC_SYSCTL Masks */
+#define PHYIE          (1 << 0)
+#define RXDWA          (1 << 1)
+#define RXCKS          (1 << 2)
+#define TXDWA          (1 << 4)
+
+/* EMAC_RX_STAT Masks */
+#define RX_FRLEN       0x7ff
+#define RX_COMP                (1 << 12)
+#define RX_OK          (1 << 13)
+#define RX_ACCEPT      (1 << 31)
+
+/* EMAC_TX_STAT Masks */
+#define TX_COMP                (1 << 0)
+#define TX_OK          (1 << 1)
+
+#endif
diff --git a/sim/bfin/dv-bfin_eppi.c b/sim/bfin/dv-bfin_eppi.c
new file mode 100644 (file)
index 0000000..7a1d6db
--- /dev/null
@@ -0,0 +1,271 @@
+/* Blackfin Enhanced Parallel Port Interface (EPPI) model
+   For "new style" PPIs on BF54x/etc... parts.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_eppi.h"
+#include "gui.h"
+
+/* XXX: TX is merely a stub.  */
+
+struct bfin_eppi
+{
+  /* This top portion matches common dv_bfin struct.  */
+  bu32 base;
+  struct hw *dma_master;
+  bool acked;
+
+  struct hw_event *handler;
+  char saved_byte;
+  int saved_count;
+
+  /* GUI state.  */
+  void *gui_state;
+  int color;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu16 BFIN_MMR_16(status);
+  bu16 BFIN_MMR_16(hcount);
+  bu16 BFIN_MMR_16(hdelay);
+  bu16 BFIN_MMR_16(vcount);
+  bu16 BFIN_MMR_16(vdelay);
+  bu16 BFIN_MMR_16(frame);
+  bu16 BFIN_MMR_16(line);
+  bu16 BFIN_MMR_16(clkdiv);
+  bu32 control, fs1w_hbl, fs1p_avpl, fsw2_lvb, fs2p_lavf, clip, err;
+};
+#define mmr_base()      offsetof(struct bfin_eppi, status)
+#define mmr_offset(mmr) (offsetof(struct bfin_eppi, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "EPPI_STATUS", "EPPI_HCOUNT", "EPPI_HDELAY", "EPPI_VCOUNT", "EPPI_VDELAY",
+  "EPPI_FRAME", "EPPI_LINE", "EPPI_CLKDIV", "EPPI_CONTROL", "EPPI_FS1W_HBL",
+  "EPPI_FS1P_AVPL", "EPPI_FS2W_LVB", "EPPI_FS2P_LAVF", "EPPI_CLIP", "EPPI_ERR",
+};
+#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
+
+static void
+bfin_eppi_gui_setup (struct bfin_eppi *eppi)
+{
+  /* If we are in RX mode, nothing to do.  */
+  if (!(eppi->control & PORT_DIR))
+    return;
+
+  eppi->gui_state = bfin_gui_setup (eppi->gui_state,
+                                   eppi->control & PORT_EN,
+                                   eppi->hcount,
+                                   eppi->vcount,
+                                   eppi->color);
+}
+
+static unsigned
+bfin_eppi_io_write_buffer (struct hw *me, const void *source,
+                          int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_eppi *eppi = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  if (nr_bytes == 4)
+    value = dv_load_4 (source);
+  else
+    value = dv_load_2 (source);
+
+  mmr_off = addr - eppi->base;
+  valuep = (void *)((unsigned long)eppi + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_WRITE ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(status):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      dv_w1c_2 (value16p, value, 0);
+      break;
+    case mmr_offset(hcount):
+    case mmr_offset(hdelay):
+    case mmr_offset(vcount):
+    case mmr_offset(vdelay):
+    case mmr_offset(frame):
+    case mmr_offset(line):
+    case mmr_offset(clkdiv):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      *value16p = value;
+      break;
+    case mmr_offset(control):
+      *value32p = value;
+      bfin_eppi_gui_setup (eppi);
+      break;
+    case mmr_offset(fs1w_hbl):
+    case mmr_offset(fs1p_avpl):
+    case mmr_offset(fsw2_lvb):
+    case mmr_offset(fs2p_lavf):
+    case mmr_offset(clip):
+    case mmr_offset(err):
+      dv_bfin_mmr_require_32 (me, addr, nr_bytes, true);
+      *value32p = value;
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_eppi_io_read_buffer (struct hw *me, void *dest,
+                         int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_eppi *eppi = hw_data (me);
+  bu32 mmr_off;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  mmr_off = addr - eppi->base;
+  valuep = (void *)((unsigned long)eppi + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(status):
+    case mmr_offset(hcount):
+    case mmr_offset(hdelay):
+    case mmr_offset(vcount):
+    case mmr_offset(vdelay):
+    case mmr_offset(frame):
+    case mmr_offset(line):
+    case mmr_offset(clkdiv):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+      dv_store_2 (dest, *value16p);
+      break;
+    case mmr_offset(control):
+    case mmr_offset(fs1w_hbl):
+    case mmr_offset(fs1p_avpl):
+    case mmr_offset(fsw2_lvb):
+    case mmr_offset(fs2p_lavf):
+    case mmr_offset(clip):
+    case mmr_offset(err):
+      dv_bfin_mmr_require_32 (me, addr, nr_bytes, false);
+      dv_store_4 (dest, *value32p);
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_eppi_dma_read_buffer (struct hw *me, void *dest, int space,
+                          unsigned_word addr, unsigned nr_bytes)
+{
+  HW_TRACE_DMA_READ ();
+  return 0;
+}
+
+static unsigned
+bfin_eppi_dma_write_buffer (struct hw *me, const void *source,
+                           int space, unsigned_word addr,
+                           unsigned nr_bytes,
+                           int violate_read_only_section)
+{
+  struct bfin_eppi *eppi = hw_data (me);
+
+  HW_TRACE_DMA_WRITE ();
+
+  return bfin_gui_update (eppi->gui_state, source, nr_bytes);
+}
+
+static const struct hw_port_descriptor bfin_eppi_ports[] = {
+  { "stat", 0, 0, output_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+attach_bfin_eppi_regs (struct hw *me, struct bfin_eppi *eppi)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_EPPI_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_EPPI_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  eppi->base = attach_address;
+}
+
+static void
+bfin_eppi_finish (struct hw *me)
+{
+  struct bfin_eppi *eppi;
+  const char *color;
+
+  eppi = HW_ZALLOC (me, struct bfin_eppi);
+
+  set_hw_data (me, eppi);
+  set_hw_io_read_buffer (me, bfin_eppi_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_eppi_io_write_buffer);
+  set_hw_dma_read_buffer (me, bfin_eppi_dma_read_buffer);
+  set_hw_dma_write_buffer (me, bfin_eppi_dma_write_buffer);
+  set_hw_ports (me, bfin_eppi_ports);
+
+  attach_bfin_eppi_regs (me, eppi);
+
+  /* Initialize the EPPI.  */
+  if (hw_find_property (me, "color"))
+    color = hw_find_string_property (me, "color");
+  else
+    color = NULL;
+  eppi->color = bfin_gui_color (color);
+}
+
+const struct hw_descriptor dv_bfin_eppi_descriptor[] = {
+  {"bfin_eppi", bfin_eppi_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_eppi.h b/sim/bfin/dv-bfin_eppi.h
new file mode 100644 (file)
index 0000000..1856800
--- /dev/null
@@ -0,0 +1,30 @@
+/* Blackfin Enhanced Parallel Port Interface (EPPI) model
+   For "new style" PPIs on BF54x/etc... parts.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_EPPI_H
+#define DV_BFIN_EPPI_H
+
+#include "dv-bfin_ppi.h"
+
+/* XXX: This should be pushed into the model data.  */
+#define BFIN_MMR_EPPI_SIZE     0x40
+
+#endif
diff --git a/sim/bfin/dv-bfin_evt.c b/sim/bfin/dv-bfin_evt.c
new file mode 100644 (file)
index 0000000..3af0717
--- /dev/null
@@ -0,0 +1,153 @@
+/* Blackfin Event Vector Table (EVT) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_cec.h"
+#include "dv-bfin_evt.h"
+
+struct bfin_evt
+{
+  bu32 base;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu32 evt[16];
+};
+#define mmr_base()      offsetof(struct bfin_evt, evt[0])
+#define mmr_offset(mmr) (offsetof(struct bfin_evt, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "EVT0", "EVT1", "EVT2", "EVT3", "EVT4", "EVT5", "EVT6", "EVT7", "EVT8",
+  "EVT9", "EVT10", "EVT11", "EVT12", "EVT13", "EVT14", "EVT15",
+};
+#define mmr_name(off) mmr_names[(off) / 4]
+
+static unsigned
+bfin_evt_io_write_buffer (struct hw *me, const void *source,
+                         int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_evt *evt = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+
+  value = dv_load_4 (source);
+  mmr_off = addr - evt->base;
+
+  HW_TRACE_WRITE ();
+
+  evt->evt[mmr_off / 4] = value;
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_evt_io_read_buffer (struct hw *me, void *dest,
+                        int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_evt *evt = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+
+  mmr_off = addr - evt->base;
+
+  HW_TRACE_READ ();
+
+  value = evt->evt[mmr_off / 4];
+
+  dv_store_4 (dest, value);
+
+  return nr_bytes;
+}
+
+static void
+attach_bfin_evt_regs (struct hw *me, struct bfin_evt *evt)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_COREMMR_EVT_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_COREMMR_EVT_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  evt->base = attach_address;
+}
+
+static void
+bfin_evt_finish (struct hw *me)
+{
+  struct bfin_evt *evt;
+
+  evt = HW_ZALLOC (me, struct bfin_evt);
+
+  set_hw_data (me, evt);
+  set_hw_io_read_buffer (me, bfin_evt_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_evt_io_write_buffer);
+
+  attach_bfin_evt_regs (me, evt);
+}
+
+const struct hw_descriptor dv_bfin_evt_descriptor[] = {
+  {"bfin_evt", bfin_evt_finish,},
+  {NULL, NULL},
+};
+
+#define EVT_STATE(cpu) DV_STATE_CACHED (cpu, evt)
+
+void
+cec_set_evt (SIM_CPU *cpu, int ivg, bu32 handler_addr)
+{
+  if (ivg > IVG15 || ivg < 0)
+    sim_io_error (CPU_STATE (cpu), "%s: ivg %i out of range !", __func__, ivg);
+
+  EVT_STATE (cpu)->evt[ivg] = handler_addr;
+}
+
+bu32
+cec_get_evt (SIM_CPU *cpu, int ivg)
+{
+  if (ivg > IVG15 || ivg < 0)
+    sim_io_error (CPU_STATE (cpu), "%s: ivg %i out of range !", __func__, ivg);
+
+  return EVT_STATE (cpu)->evt[ivg];
+}
+
+bu32
+cec_get_reset_evt (SIM_CPU *cpu)
+{
+  /* XXX: This should tail into the model to get via BMODE pins.  */
+  return 0xef000000;
+}
diff --git a/sim/bfin/dv-bfin_evt.h b/sim/bfin/dv-bfin_evt.h
new file mode 100644 (file)
index 0000000..defa082
--- /dev/null
@@ -0,0 +1,31 @@
+/* Blackfin Event Vector Table (EVT) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_EVT_H
+#define DV_BFIN_EVT_H
+
+#define BFIN_COREMMR_EVT_BASE  0xFFE02000
+#define BFIN_COREMMR_EVT_SIZE  (4 * 16)
+
+extern void cec_set_evt (SIM_CPU *, int ivg, bu32 handler_addr);
+extern bu32 cec_get_evt (SIM_CPU *, int ivg);
+extern bu32 cec_get_reset_evt (SIM_CPU *);
+
+#endif
diff --git a/sim/bfin/dv-bfin_gptimer.c b/sim/bfin/dv-bfin_gptimer.c
new file mode 100644 (file)
index 0000000..23c906f
--- /dev/null
@@ -0,0 +1,183 @@
+/* Blackfin General Purpose Timers (GPtimer) model
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_gptimer.h"
+
+/* XXX: This is merely a stub.  */
+
+struct bfin_gptimer
+{
+  /* This top portion matches common dv_bfin struct.  */
+  bu32 base;
+  struct hw *dma_master;
+  bool acked;
+
+  struct hw_event *handler;
+  char saved_byte;
+  int saved_count;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu16 BFIN_MMR_16(config);
+  bu32 counter, period, width;
+};
+#define mmr_base()      offsetof(struct bfin_gptimer, config)
+#define mmr_offset(mmr) (offsetof(struct bfin_gptimer, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "TIMER_CONFIG", "TIMER_COUNTER", "TIMER_PERIOD", "TIMER_WIDTH",
+};
+#define mmr_name(off) mmr_names[(off) / 4]
+
+static unsigned
+bfin_gptimer_io_write_buffer (struct hw *me, const void *source, int space,
+                             address_word addr, unsigned nr_bytes)
+{
+  struct bfin_gptimer *gptimer = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  if (nr_bytes == 4)
+    value = dv_load_4 (source);
+  else
+    value = dv_load_2 (source);
+
+  mmr_off = addr - gptimer->base;
+  valuep = (void *)((unsigned long)gptimer + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_WRITE ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(config):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      *value16p = value;
+      break;
+    case mmr_offset(counter):
+    case mmr_offset(period):
+    case mmr_offset(width):
+      dv_bfin_mmr_require_32 (me, addr, nr_bytes, true);
+      *value32p = value;
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_gptimer_io_read_buffer (struct hw *me, void *dest, int space,
+                            address_word addr, unsigned nr_bytes)
+{
+  struct bfin_gptimer *gptimer = hw_data (me);
+  bu32 mmr_off;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  mmr_off = addr - gptimer->base;
+  valuep = (void *)((unsigned long)gptimer + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(config):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+      dv_store_2 (dest, *value16p);
+      break;
+    case mmr_offset(counter):
+    case mmr_offset(period):
+    case mmr_offset(width):
+      dv_bfin_mmr_require_32 (me, addr, nr_bytes, false);
+      dv_store_4 (dest, *value32p);
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static const struct hw_port_descriptor bfin_gptimer_ports[] = {
+  { "stat", 0, 0, output_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+attach_bfin_gptimer_regs (struct hw *me, struct bfin_gptimer *gptimer)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_GPTIMER_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_GPTIMER_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  gptimer->base = attach_address;
+}
+
+static void
+bfin_gptimer_finish (struct hw *me)
+{
+  struct bfin_gptimer *gptimer;
+
+  gptimer = HW_ZALLOC (me, struct bfin_gptimer);
+
+  set_hw_data (me, gptimer);
+  set_hw_io_read_buffer (me, bfin_gptimer_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_gptimer_io_write_buffer);
+  set_hw_ports (me, bfin_gptimer_ports);
+
+  attach_bfin_gptimer_regs (me, gptimer);
+}
+
+const struct hw_descriptor dv_bfin_gptimer_descriptor[] = {
+  {"bfin_gptimer", bfin_gptimer_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_gptimer.h b/sim/bfin/dv-bfin_gptimer.h
new file mode 100644 (file)
index 0000000..2c7c149
--- /dev/null
@@ -0,0 +1,27 @@
+/* Blackfin General Purpose Timers (GPtimer) model
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_GPTIMER_H
+#define DV_BFIN_GPTIMER_H
+
+/* XXX: This should be pushed into the model data.  */
+#define BFIN_MMR_GPTIMER_SIZE  (4 * 4)
+
+#endif
diff --git a/sim/bfin/dv-bfin_jtag.c b/sim/bfin/dv-bfin_jtag.c
new file mode 100644 (file)
index 0000000..76b59ac
--- /dev/null
@@ -0,0 +1,157 @@
+/* Blackfin JTAG model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_jtag.h"
+
+/* XXX: This is mostly a stub.  There are more registers, but they're only
+        accessible via the JTAG scan chain and not the MMR interface.  */
+
+struct bfin_jtag
+{
+  bu32 base;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu32 dspid;
+  bu32 _pad0;
+  bu32 dbgstat;
+};
+#define mmr_base()      offsetof(struct bfin_jtag, dspid)
+#define mmr_offset(mmr) (offsetof(struct bfin_jtag, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "DSPID", NULL, "DBGSTAT",
+};
+#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
+
+static unsigned
+bfin_jtag_io_write_buffer (struct hw *me, const void *source, int space,
+                          address_word addr, unsigned nr_bytes)
+{
+  struct bfin_jtag *jtag = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu32 *valuep;
+
+  value = dv_load_4 (source);
+  mmr_off = addr - jtag->base;
+  valuep = (void *)((unsigned long)jtag + mmr_base() + mmr_off);
+
+  HW_TRACE_WRITE ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(dbgstat):
+      dv_w1c_4 (valuep, value, ~0xc);
+      break;
+    case mmr_offset(dspid):
+      /* Discard writes to these.  */
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_jtag_io_read_buffer (struct hw *me, void *dest, int space,
+                         address_word addr, unsigned nr_bytes)
+{
+  struct bfin_jtag *jtag = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu32 *valuep;
+
+  mmr_off = addr - jtag->base;
+  valuep = (void *)((unsigned long)jtag + mmr_base() + mmr_off);
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(dbgstat):
+    case mmr_offset(dspid):
+      value = *valuep;
+      break;
+    default:
+      while (1) /* Core MMRs -> exception -> doesn't return.  */
+       dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  dv_store_4 (dest, value);
+
+  return nr_bytes;
+}
+
+static void
+attach_bfin_jtag_regs (struct hw *me, struct bfin_jtag *jtag)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_COREMMR_JTAG_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_COREMMR_JTAG_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  jtag->base = attach_address;
+}
+
+static void
+bfin_jtag_finish (struct hw *me)
+{
+  struct bfin_jtag *jtag;
+
+  jtag = HW_ZALLOC (me, struct bfin_jtag);
+
+  set_hw_data (me, jtag);
+  set_hw_io_read_buffer (me, bfin_jtag_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_jtag_io_write_buffer);
+
+  attach_bfin_jtag_regs (me, jtag);
+
+  /* Initialize the JTAG state.  */
+  jtag->dspid = bfin_model_get_dspid (hw_system (me));
+}
+
+const struct hw_descriptor dv_bfin_jtag_descriptor[] = {
+  {"bfin_jtag", bfin_jtag_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_jtag.h b/sim/bfin/dv-bfin_jtag.h
new file mode 100644 (file)
index 0000000..65c1d3b
--- /dev/null
@@ -0,0 +1,27 @@
+/* Blackfin JTAG model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_JTAG_H
+#define DV_BFIN_JTAG_H
+
+#define BFIN_COREMMR_JTAG_BASE 0xFFE05000
+#define BFIN_COREMMR_JTAG_SIZE (4 * 3)
+
+#endif
diff --git a/sim/bfin/dv-bfin_mmu.c b/sim/bfin/dv-bfin_mmu.c
new file mode 100644 (file)
index 0000000..9f27636
--- /dev/null
@@ -0,0 +1,574 @@
+/* Blackfin Memory Management Unit (MMU) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "sim-options.h"
+#include "devices.h"
+#include "dv-bfin_mmu.h"
+#include "dv-bfin_cec.h"
+
+/* XXX: Should this really be two blocks of registers ?  PRM describes
+        these as two Content Addressable Memory (CAM) blocks.  */
+
+struct bfin_mmu
+{
+  bu32 base;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu32 sram_base_address;
+
+  bu32 dmem_control, dcplb_fault_status, dcplb_fault_addr;
+  char _dpad0[0x100 - 0x0 - (4 * 4)];
+  bu32 dcplb_addr[16];
+  char _dpad1[0x200 - 0x100 - (4 * 16)];
+  bu32 dcplb_data[16];
+  char _dpad2[0x300 - 0x200 - (4 * 16)];
+  bu32 dtest_command;
+  char _dpad3[0x400 - 0x300 - (4 * 1)];
+  bu32 dtest_data[2];
+
+  char _dpad4[0x1000 - 0x400 - (4 * 2)];
+
+  bu32 idk;    /* Filler MMR; hardware simply ignores.  */
+  bu32 imem_control, icplb_fault_status, icplb_fault_addr;
+  char _ipad0[0x100 - 0x0 - (4 * 4)];
+  bu32 icplb_addr[16];
+  char _ipad1[0x200 - 0x100 - (4 * 16)];
+  bu32 icplb_data[16];
+  char _ipad2[0x300 - 0x200 - (4 * 16)];
+  bu32 itest_command;
+  char _ipad3[0x400 - 0x300 - (4 * 1)];
+  bu32 itest_data[2];
+};
+#define mmr_base()      offsetof(struct bfin_mmu, sram_base_address)
+#define mmr_offset(mmr) (offsetof(struct bfin_mmu, mmr) - mmr_base())
+#define mmr_idx(mmr)    (mmr_offset (mmr) / 4)
+
+static const char * const mmr_names[BFIN_COREMMR_MMU_SIZE / 4] = {
+  "SRAM_BASE_ADDRESS", "DMEM_CONTROL", "DCPLB_FAULT_STATUS", "DCPLB_FAULT_ADDR",
+  [mmr_idx (dcplb_addr[0])] = "DCPLB_ADDR0",
+  "DCPLB_ADDR1", "DCPLB_ADDR2", "DCPLB_ADDR3", "DCPLB_ADDR4", "DCPLB_ADDR5",
+  "DCPLB_ADDR6", "DCPLB_ADDR7", "DCPLB_ADDR8", "DCPLB_ADDR9", "DCPLB_ADDR10",
+  "DCPLB_ADDR11", "DCPLB_ADDR12", "DCPLB_ADDR13", "DCPLB_ADDR14", "DCPLB_ADDR15",
+  [mmr_idx (dcplb_data[0])] = "DCPLB_DATA0",
+  "DCPLB_DATA1", "DCPLB_DATA2", "DCPLB_DATA3", "DCPLB_DATA4", "DCPLB_DATA5",
+  "DCPLB_DATA6", "DCPLB_DATA7", "DCPLB_DATA8", "DCPLB_DATA9", "DCPLB_DATA10",
+  "DCPLB_DATA11", "DCPLB_DATA12", "DCPLB_DATA13", "DCPLB_DATA14", "DCPLB_DATA15",
+  [mmr_idx (dtest_command)] = "DTEST_COMMAND",
+  [mmr_idx (dtest_data[0])] = "DTEST_DATA0", "DTEST_DATA1",
+  [mmr_idx (imem_control)] = "IMEM_CONTROL", "ICPLB_FAULT_STATUS", "ICPLB_FAULT_ADDR",
+  [mmr_idx (icplb_addr[0])] = "ICPLB_ADDR0",
+  "ICPLB_ADDR1", "ICPLB_ADDR2", "ICPLB_ADDR3", "ICPLB_ADDR4", "ICPLB_ADDR5",
+  "ICPLB_ADDR6", "ICPLB_ADDR7", "ICPLB_ADDR8", "ICPLB_ADDR9", "ICPLB_ADDR10",
+  "ICPLB_ADDR11", "ICPLB_ADDR12", "ICPLB_ADDR13", "ICPLB_ADDR14", "ICPLB_ADDR15",
+  [mmr_idx (icplb_data[0])] = "ICPLB_DATA0",
+  "ICPLB_DATA1", "ICPLB_DATA2", "ICPLB_DATA3", "ICPLB_DATA4", "ICPLB_DATA5",
+  "ICPLB_DATA6", "ICPLB_DATA7", "ICPLB_DATA8", "ICPLB_DATA9", "ICPLB_DATA10",
+  "ICPLB_DATA11", "ICPLB_DATA12", "ICPLB_DATA13", "ICPLB_DATA14", "ICPLB_DATA15",
+  [mmr_idx (itest_command)] = "ITEST_COMMAND",
+  [mmr_idx (itest_data[0])] = "ITEST_DATA0", "ITEST_DATA1",
+};
+#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
+
+static bool bfin_mmu_skip_cplbs = false;
+
+static unsigned
+bfin_mmu_io_write_buffer (struct hw *me, const void *source,
+                         int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_mmu *mmu = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu32 *valuep;
+
+  value = dv_load_4 (source);
+
+  mmr_off = addr - mmu->base;
+  valuep = (void *)((unsigned long)mmu + mmr_base() + mmr_off);
+
+  HW_TRACE_WRITE ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(dmem_control):
+    case mmr_offset(imem_control):
+      /* XXX: IMC/DMC bit should add/remove L1 cache regions ...  */
+    case mmr_offset(dtest_data[0]) ... mmr_offset(dtest_data[1]):
+    case mmr_offset(itest_data[0]) ... mmr_offset(itest_data[1]):
+    case mmr_offset(dcplb_addr[0]) ... mmr_offset(dcplb_addr[15]):
+    case mmr_offset(dcplb_data[0]) ... mmr_offset(dcplb_data[15]):
+    case mmr_offset(icplb_addr[0]) ... mmr_offset(icplb_addr[15]):
+    case mmr_offset(icplb_data[0]) ... mmr_offset(icplb_data[15]):
+      *valuep = value;
+      break;
+    case mmr_offset(sram_base_address):
+    case mmr_offset(dcplb_fault_status):
+    case mmr_offset(dcplb_fault_addr):
+    case mmr_offset(idk):
+    case mmr_offset(icplb_fault_status):
+    case mmr_offset(icplb_fault_addr):
+      /* Discard writes to these.  */
+      break;
+    case mmr_offset(itest_command):
+      /* XXX: Not supported atm.  */
+      if (value)
+       hw_abort (me, "ITEST_COMMAND unimplemented");
+      break;
+    case mmr_offset(dtest_command):
+      /* Access L1 memory indirectly.  */
+      *valuep = value;
+      if (value)
+       {
+         bu32 addr = mmu->sram_base_address   |
+           ((value >> (26 - 11)) & (1 << 11)) | /* addr bit 11 (Way0/Way1)   */
+           ((value >> (24 - 21)) & (1 << 21)) | /* addr bit 21 (Data/Inst)   */
+           ((value >> (23 - 15)) & (1 << 15)) | /* addr bit 15 (Data Bank)   */
+           ((value >> (16 - 12)) & (3 << 12)) | /* addr bits 13:12 (Subbank) */
+           (value & 0x47F8);                    /* addr bits 14 & 10:3       */
+
+         if (!(value & TEST_DATA_ARRAY))
+           hw_abort (me, "DTEST_COMMAND tag array unimplemented");
+         if (value & 0xfa7cb801)
+           hw_abort (me, "DTEST_COMMAND bits undefined");
+
+         if (value & TEST_WRITE)
+           sim_write (hw_system (me), addr, (void *)mmu->dtest_data, 8);
+         else
+           sim_read (hw_system (me), addr, (void *)mmu->dtest_data, 8);
+       }
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_mmu_io_read_buffer (struct hw *me, void *dest,
+                        int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_mmu *mmu = hw_data (me);
+  bu32 mmr_off;
+  bu32 *valuep;
+
+  mmr_off = addr - mmu->base;
+  valuep = (void *)((unsigned long)mmu + mmr_base() + mmr_off);
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(dmem_control):
+    case mmr_offset(imem_control):
+    case mmr_offset(dtest_command):
+    case mmr_offset(dtest_data[0]) ... mmr_offset(dtest_data[2]):
+    case mmr_offset(itest_command):
+    case mmr_offset(itest_data[0]) ... mmr_offset(itest_data[2]):
+      /* XXX: should do something here.  */
+    case mmr_offset(dcplb_addr[0]) ... mmr_offset(dcplb_addr[15]):
+    case mmr_offset(dcplb_data[0]) ... mmr_offset(dcplb_data[15]):
+    case mmr_offset(icplb_addr[0]) ... mmr_offset(icplb_addr[15]):
+    case mmr_offset(icplb_data[0]) ... mmr_offset(icplb_data[15]):
+    case mmr_offset(sram_base_address):
+    case mmr_offset(dcplb_fault_status):
+    case mmr_offset(dcplb_fault_addr):
+    case mmr_offset(idk):
+    case mmr_offset(icplb_fault_status):
+    case mmr_offset(icplb_fault_addr):
+      dv_store_4 (dest, *valuep);
+      break;
+    default:
+      while (1) /* Core MMRs -> exception -> doesn't return.  */
+       dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static void
+attach_bfin_mmu_regs (struct hw *me, struct bfin_mmu *mmu)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_COREMMR_MMU_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_COREMMR_MMU_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  mmu->base = attach_address;
+}
+
+static void
+bfin_mmu_finish (struct hw *me)
+{
+  struct bfin_mmu *mmu;
+
+  mmu = HW_ZALLOC (me, struct bfin_mmu);
+
+  set_hw_data (me, mmu);
+  set_hw_io_read_buffer (me, bfin_mmu_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_mmu_io_write_buffer);
+
+  attach_bfin_mmu_regs (me, mmu);
+
+  /* Initialize the MMU.  */
+  mmu->sram_base_address = 0xff800000 - 0;
+                          /*(4 * 1024 * 1024 * CPU_INDEX (hw_system_cpu (me)));*/
+  mmu->dmem_control = 0x00000001;
+  mmu->imem_control = 0x00000001;
+}
+
+const struct hw_descriptor dv_bfin_mmu_descriptor[] = {
+  {"bfin_mmu", bfin_mmu_finish,},
+  {NULL, NULL},
+};
+\f
+/* Device option parsing.  */
+
+static DECLARE_OPTION_HANDLER (bfin_mmu_option_handler);
+
+enum {
+  OPTION_MMU_SKIP_TABLES = OPTION_START,
+};
+
+const OPTION bfin_mmu_options[] =
+{
+  { {"mmu-skip-cplbs", no_argument, NULL, OPTION_MMU_SKIP_TABLES },
+      '\0', NULL, "Skip parsing of CPLB tables (big speed increase)",
+      bfin_mmu_option_handler, NULL },
+
+  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
+};
+
+static SIM_RC
+bfin_mmu_option_handler (SIM_DESC sd, sim_cpu *current_cpu, int opt,
+                        char *arg, int is_command)
+{
+  switch (opt)
+    {
+    case OPTION_MMU_SKIP_TABLES:
+      bfin_mmu_skip_cplbs = true;
+      return SIM_RC_OK;
+
+    default:
+      sim_io_eprintf (sd, "Unknown Blackfin MMU option %d\n", opt);
+      return SIM_RC_FAIL;
+    }
+}
+\f
+#define MMU_STATE(cpu) DV_STATE_CACHED (cpu, mmu)
+
+static void
+_mmu_log_ifault (SIM_CPU *cpu, struct bfin_mmu *mmu, bu32 pc, bool supv)
+{
+  mmu->icplb_fault_addr = pc;
+  mmu->icplb_fault_status = supv << 17;
+}
+
+void
+mmu_log_ifault (SIM_CPU *cpu)
+{
+  _mmu_log_ifault (cpu, MMU_STATE (cpu), PCREG, cec_get_ivg (cpu) >= 0);
+}
+
+static void
+_mmu_log_fault (SIM_CPU *cpu, struct bfin_mmu *mmu, bu32 addr, bool write,
+               bool inst, bool miss, bool supv, bool dag1, bu32 faults)
+{
+  bu32 *fault_status, *fault_addr;
+
+  /* No logging in non-OS mode.  */
+  if (!mmu)
+    return;
+
+  fault_status = inst ? &mmu->icplb_fault_status : &mmu->dcplb_fault_status;
+  fault_addr = inst ? &mmu->icplb_fault_addr : &mmu->dcplb_fault_addr;
+  /* ICPLB regs always get updated.  */
+  if (!inst)
+    _mmu_log_ifault (cpu, mmu, PCREG, supv);
+
+  *fault_addr = addr;
+  *fault_status =
+       (miss << 19) |
+       (dag1 << 18) |
+       (supv << 17) |
+       (write << 16) |
+       faults;
+}
+
+static void
+_mmu_process_fault (SIM_CPU *cpu, struct bfin_mmu *mmu, bu32 addr, bool write,
+                   bool inst, bool unaligned, bool miss, bool supv, bool dag1)
+{
+  int excp;
+
+  /* See order in mmu_check_addr() */
+  if (unaligned)
+    excp = inst ? VEC_MISALI_I : VEC_MISALI_D;
+  else if (addr >= BFIN_SYSTEM_MMR_BASE)
+    excp = VEC_ILL_RES;
+  else if (!mmu)
+    excp = inst ? VEC_CPLB_I_M : VEC_CPLB_M;
+  else
+    {
+      /* Misses are hardware errors.  */
+      cec_hwerr (cpu, HWERR_EXTERN_ADDR);
+      return;
+    }
+
+  _mmu_log_fault (cpu, mmu, addr, write, inst, miss, supv, dag1, 0);
+  cec_exception (cpu, excp);
+}
+
+void
+mmu_process_fault (SIM_CPU *cpu, bu32 addr, bool write, bool inst,
+                  bool unaligned, bool miss)
+{
+  SIM_DESC sd = CPU_STATE (cpu);
+  struct bfin_mmu *mmu;
+
+  if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
+    mmu = NULL;
+  else
+    mmu = MMU_STATE (cpu);
+
+  _mmu_process_fault (cpu, mmu, addr, write, inst, unaligned, miss,
+                     cec_is_supervisor_mode (cpu),
+                     BFIN_CPU_STATE.multi_pc == PCREG + 6);
+}
+
+/* Return values:
+    -2: no known problems
+    -1: valid
+     0: miss
+     1: protection violation
+     2: multiple hits
+     3: unaligned
+     4: miss; hwerr  */
+static int
+mmu_check_implicit_addr (SIM_CPU *cpu, bu32 addr, bool inst, int size,
+                        bool supv, bool dag1)
+{
+  bool l1 = ((addr & 0xFF000000) == 0xFF000000);
+  bu32 amask = (addr & 0xFFF00000);
+
+  if (addr & (size - 1))
+    return 3;
+
+  /* MMRs may never be executable or accessed from usermode.  */
+  if (addr >= BFIN_SYSTEM_MMR_BASE)
+    {
+      if (inst)
+       return 0;
+      else if (!supv || dag1)
+       return 1;
+      else
+       return -1;
+    }
+  else if (inst)
+    {
+      /* Some regions are not executable.  */
+      /* XXX: Should this be in the model data ?  Core B 561 ?  */
+      if (l1)
+       return (amask == 0xFFA00000) ? -1 : 1;
+    }
+  else
+    {
+      /* Some regions are not readable.  */
+      /* XXX: Should this be in the model data ?  Core B 561 ?  */
+      if (l1)
+       return (amask != 0xFFA00000) ? -1 : 4;
+    }
+
+  return -2;
+}
+
+/* Exception order per the PRM (first has highest):
+     Inst Multiple CPLB Hits
+     Inst Misaligned Access
+     Inst Protection Violation
+     Inst CPLB Miss
+  Only the alignment matters in non-OS mode though.  */
+static int
+_mmu_check_addr (SIM_CPU *cpu, bu32 addr, bool write, bool inst, int size)
+{
+  SIM_DESC sd = CPU_STATE (cpu);
+  struct bfin_mmu *mmu;
+  bu32 *fault_status, *fault_addr, *mem_control, *cplb_addr, *cplb_data;
+  bu32 faults;
+  bool supv, do_excp, dag1;
+  int i, hits;
+
+  supv = cec_is_supervisor_mode (cpu);
+  dag1 = (BFIN_CPU_STATE.multi_pc == PCREG + 6);
+
+  if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT || bfin_mmu_skip_cplbs)
+    {
+      int ret = mmu_check_implicit_addr (cpu, addr, inst, size, supv, dag1);
+      /* Valid hits and misses are OK in non-OS envs.  */
+      if (ret < 0)
+       return 0;
+      _mmu_process_fault (cpu, NULL, addr, write, inst, (ret == 3), false, supv, dag1);
+    }
+
+  mmu = MMU_STATE (cpu);
+  fault_status = inst ? &mmu->icplb_fault_status : &mmu->dcplb_fault_status;
+  fault_addr = inst ? &mmu->icplb_fault_addr : &mmu->dcplb_fault_addr;
+  mem_control = inst ? &mmu->imem_control : &mmu->dmem_control;
+  cplb_addr = inst ? &mmu->icplb_addr[0] : &mmu->dcplb_addr[0];
+  cplb_data = inst ? &mmu->icplb_data[0] : &mmu->dcplb_data[0];
+
+  faults = 0;
+  hits = 0;
+  do_excp = false;
+
+  /* CPLBs disabled -> little to do.  */
+  if (!(*mem_control & ENCPLB))
+    {
+      hits = 1;
+      goto implicit_check;
+    }
+
+  /* Check all the CPLBs first.  */
+  for (i = 0; i < 16; ++i)
+    {
+      const bu32 pages[4] = { 0x400, 0x1000, 0x100000, 0x400000 };
+      bu32 addr_lo, addr_hi;
+
+      /* Skip invalid entries.  */
+      if (!(cplb_data[i] & CPLB_VALID))
+       continue;
+
+      /* See if this entry covers this address.  */
+      addr_lo = cplb_addr[i];
+      addr_hi = cplb_addr[i] + pages[(cplb_data[i] & PAGE_SIZE) >> 16];
+      if (addr < addr_lo || addr >= addr_hi)
+       continue;
+
+      ++hits;
+      faults |= (1 << i);
+      if (write)
+       {
+         if (!supv && !(cplb_data[i] & CPLB_USER_WR))
+           do_excp = true;
+         if (supv && !(cplb_data[i] & CPLB_SUPV_WR))
+           do_excp = true;
+         if ((cplb_data[i] & (CPLB_WT | CPLB_L1_CHBL | CPLB_DIRTY)) == CPLB_L1_CHBL)
+           do_excp = true;
+       }
+      else
+       {
+         if (!supv && !(cplb_data[i] & CPLB_USER_RD))
+           do_excp = true;
+       }
+    }
+
+  /* Handle default/implicit CPLBs.  */
+  if (!do_excp && hits < 2)
+    {
+      int ihits;
+ implicit_check:
+      ihits = mmu_check_implicit_addr (cpu, addr, inst, size, supv, dag1);
+      switch (ihits)
+       {
+       /* No faults and one match -> good to go.  */
+       case -1: return 0;
+       case -2:
+         if (hits == 1)
+           return 0;
+         break;
+       case 4:
+         cec_hwerr (cpu, HWERR_EXTERN_ADDR);
+         return 0;
+       default:
+         hits = ihits;
+       }
+    }
+  else
+    /* Normalize hit count so hits==2 is always multiple hit exception.  */
+    hits = MIN (2, hits);
+
+  _mmu_log_fault (cpu, mmu, addr, write, inst, hits == 0, supv, dag1, faults);
+
+  if (inst)
+    {
+      int iexcps[] = { VEC_CPLB_I_M, VEC_CPLB_I_VL, VEC_CPLB_I_MHIT, VEC_MISALI_I };
+      return iexcps[hits];
+    }
+  else
+    {
+      int dexcps[] = { VEC_CPLB_M, VEC_CPLB_VL, VEC_CPLB_MHIT, VEC_MISALI_D };
+      return dexcps[hits];
+    }
+}
+
+void
+mmu_check_addr (SIM_CPU *cpu, bu32 addr, bool write, bool inst, int size)
+{
+  int excp = _mmu_check_addr (cpu, addr, write, inst, size);
+  if (excp)
+    cec_exception (cpu, excp);
+}
+
+void
+mmu_check_cache_addr (SIM_CPU *cpu, bu32 addr, bool write, bool inst)
+{
+  bu32 cacheaddr;
+  int excp;
+
+  cacheaddr = addr & ~(BFIN_L1_CACHE_BYTES - 1);
+  excp = _mmu_check_addr (cpu, cacheaddr, write, inst, BFIN_L1_CACHE_BYTES);
+  if (excp == 0)
+    return;
+
+  /* Most exceptions are ignored with cache funcs.  */
+  /* XXX: Not sure if we should be ignoring CPLB misses.  */
+  if (inst)
+    {
+      if (excp == VEC_CPLB_I_VL)
+       return;
+    }
+  else
+    {
+      if (excp == VEC_CPLB_VL)
+       return;
+    }
+  cec_exception (cpu, excp);
+}
diff --git a/sim/bfin/dv-bfin_mmu.h b/sim/bfin/dv-bfin_mmu.h
new file mode 100644 (file)
index 0000000..e03a327
--- /dev/null
@@ -0,0 +1,94 @@
+/* Blackfin Memory Management Unit (MMU) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_MMU_H
+#define DV_BFIN_MMU_H
+
+#define BFIN_COREMMR_MMU_BASE  0xFFE00000
+#define BFIN_COREMMR_MMU_SIZE  0x2000
+
+void mmu_check_addr (SIM_CPU *, bu32 addr, bool write, bool inst, int size);
+void mmu_check_cache_addr (SIM_CPU *, bu32 addr, bool write, bool inst);
+void mmu_process_fault (SIM_CPU *, bu32 addr, bool write, bool inst, bool unaligned, bool miss);
+void mmu_log_ifault (SIM_CPU *);
+
+/* MEM_CONTROL */
+#define ENM    (1 << 0)
+#define ENCPLB (1 << 1)
+#define MC     (1 << 2)
+
+#define ENDM         ENM
+#define ENDCPLB      ENCPLB
+#define DMC_AB_SRAM      0x0
+#define DMC_AB_CACHE     0xc
+#define DMC_ACACHE_BSRAM 0x8
+
+/* CPLB_DATA */
+#define CPLB_VALID   (1 << 0)
+#define CPLB_USER_RD (1 << 2)
+#define CPLB_USER_WR (1 << 3)
+#define CPLB_USER_RW (CPLB_USER_RD | CPLB_USER_WR)
+#define CPLB_SUPV_WR (1 << 4)
+#define CPLB_L1SRAM  (1 << 5)
+#define CPLB_DA0ACC  (1 << 6)
+#define CPLB_DIRTY   (1 << 7)
+#define CPLB_L1_CHBL (1 << 12)
+#define CPLB_WT      (1 << 14)
+#define PAGE_SIZE    (3 << 16)
+#define PAGE_SIZE_1K (0 << 16)
+#define PAGE_SIZE_4K (1 << 16)
+#define PAGE_SIZE_1M (2 << 16)
+#define PAGE_SIZE_4M (3 << 16)
+
+/* CPLB_STATUS */
+#define FAULT_CPLB0   (1 << 0)
+#define FAULT_CPLB1   (1 << 1)
+#define FAULT_CPLB2   (1 << 2)
+#define FAULT_CPLB3   (1 << 3)
+#define FAULT_CPLB4   (1 << 4)
+#define FAULT_CPLB5   (1 << 5)
+#define FAULT_CPLB6   (1 << 6)
+#define FAULT_CPLB7   (1 << 7)
+#define FAULT_CPLB8   (1 << 8)
+#define FAULT_CPLB9   (1 << 9)
+#define FAULT_CPLB10  (1 << 10)
+#define FAULT_CPLB11  (1 << 11)
+#define FAULT_CPLB12  (1 << 12)
+#define FAULT_CPLB13  (1 << 13)
+#define FAULT_CPLB14  (1 << 14)
+#define FAULT_CPLB15  (1 << 15)
+#define FAULT_READ    (0 << 16)
+#define FAULT_WRITE   (1 << 16)
+#define FAULT_USER    (0 << 17)
+#define FAULT_SUPV    (1 << 17)
+#define FAULT_DAG0    (0 << 18)
+#define FAULT_DAG1    (1 << 18)
+#define FAULT_ILLADDR (1 << 19)
+
+/* DTEST_COMMAND */
+#define TEST_READ       (0 << 1)
+#define TEST_WRITE      (1 << 1)
+#define TEST_TAG_ARRAY  (0 << 2)
+#define TEST_DATA_ARRAY (1 << 2)
+#define TEST_DBANK      (1 << 23)
+#define TEST_DATA_SRAM  (0 << 24)
+#define TEST_INST_SRAM  (1 << 24)
+
+#endif
diff --git a/sim/bfin/dv-bfin_nfc.c b/sim/bfin/dv-bfin_nfc.c
new file mode 100644 (file)
index 0000000..48990ee
--- /dev/null
@@ -0,0 +1,241 @@
+/* Blackfin NAND Flash Memory Controller (NFC) model
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_nfc.h"
+
+/* XXX: This is merely a stub.  */
+
+struct bfin_nfc
+{
+  /* This top portion matches common dv_bfin struct.  */
+  bu32 base;
+  struct hw *dma_master;
+  bool acked;
+
+  struct hw_event *handler;
+  char saved_byte;
+  int saved_count;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu16 BFIN_MMR_16(ctl);
+  bu16 BFIN_MMR_16(stat);
+  bu16 BFIN_MMR_16(irqstat);
+  bu16 BFIN_MMR_16(irqmask);
+  bu16 BFIN_MMR_16(ecc0);
+  bu16 BFIN_MMR_16(ecc1);
+  bu16 BFIN_MMR_16(ecc2);
+  bu16 BFIN_MMR_16(ecc3);
+  bu16 BFIN_MMR_16(count);
+  bu16 BFIN_MMR_16(rst);
+  bu16 BFIN_MMR_16(pgctl);
+  bu16 BFIN_MMR_16(read);
+  bu32 _pad0[4];
+  bu16 BFIN_MMR_16(addr);
+  bu16 BFIN_MMR_16(cmd);
+  bu16 BFIN_MMR_16(data_wr);
+  bu16 BFIN_MMR_16(data_rd);
+};
+#define mmr_base()      offsetof(struct bfin_nfc, ctl)
+#define mmr_offset(mmr) (offsetof(struct bfin_nfc, mmr) - mmr_base())
+#define mmr_idx(mmr)    (mmr_offset (mmr) / 4)
+
+static const char * const mmr_names[] = {
+  "NFC_CTL", "NFC_STAT", "NFC_IRQSTAT", "NFC_IRQMASK", "NFC_ECC0", "NFC_ECC1",
+  "NFC_ECC2", "NFC_ECC3", "NFC_COUNT", "NFC_RST", "NFC_PGCTL", "NFC_READ",
+  [mmr_idx (addr)] = "NFC_ADDR", "NFC_CMD", "NFC_DATA_WR", "NFC_DATA_RD",
+};
+#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
+
+static unsigned
+bfin_nfc_io_write_buffer (struct hw *me, const void *source, int space,
+                         address_word addr, unsigned nr_bytes)
+{
+  struct bfin_nfc *nfc = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *valuep;
+
+  value = dv_load_2 (source);
+  mmr_off = addr - nfc->base;
+  valuep = (void *)((unsigned long)nfc + mmr_base() + mmr_off);
+
+  HW_TRACE_WRITE ();
+
+  dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+
+  switch (mmr_off)
+    {
+    case mmr_offset(ctl):
+    case mmr_offset(stat):
+    case mmr_offset(irqmask):
+    case mmr_offset(ecc0):
+    case mmr_offset(ecc1):
+    case mmr_offset(ecc2):
+    case mmr_offset(ecc3):
+    case mmr_offset(count):
+    case mmr_offset(rst):
+    case mmr_offset(pgctl):
+    case mmr_offset(read):
+    case mmr_offset(addr):
+    case mmr_offset(cmd):
+    case mmr_offset(data_wr):
+      *valuep = value;
+      break;
+    case mmr_offset(data_rd):
+      nfc->irqstat |= RD_RDY;
+      *valuep = value;
+      break;
+    case mmr_offset(irqstat):
+      dv_w1c_2 (valuep, value, 0);
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_nfc_io_read_buffer (struct hw *me, void *dest, int space,
+                        address_word addr, unsigned nr_bytes)
+{
+  struct bfin_nfc *nfc = hw_data (me);
+  bu32 mmr_off;
+  bu16 *valuep;
+
+  mmr_off = addr - nfc->base;
+  valuep = (void *)((unsigned long)nfc + mmr_base() + mmr_off);
+
+  HW_TRACE_READ ();
+
+  dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+
+  switch (mmr_off)
+    {
+    case mmr_offset(ctl):
+    case mmr_offset(stat):
+    case mmr_offset(irqstat):
+    case mmr_offset(irqmask):
+    case mmr_offset(ecc0):
+    case mmr_offset(ecc1):
+    case mmr_offset(ecc2):
+    case mmr_offset(ecc3):
+    case mmr_offset(count):
+    case mmr_offset(rst):
+    case mmr_offset(read):
+      dv_store_2 (dest, *valuep);
+      break;
+    case mmr_offset(pgctl):
+    case mmr_offset(addr):
+    case mmr_offset(cmd):
+    case mmr_offset(data_wr):
+    case mmr_offset(data_rd):
+      /* These regs are write only.  */
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_nfc_dma_read_buffer (struct hw *me, void *dest, int space,
+                         unsigned_word addr, unsigned nr_bytes)
+{
+  HW_TRACE_DMA_READ ();
+  return 0;
+}
+
+static unsigned
+bfin_nfc_dma_write_buffer (struct hw *me, const void *source,
+                          int space, unsigned_word addr,
+                          unsigned nr_bytes,
+                          int violate_read_only_section)
+{
+  HW_TRACE_DMA_WRITE ();
+  return nr_bytes;
+}
+
+static const struct hw_port_descriptor bfin_nfc_ports[] = {
+  { "stat", 0, 0, output_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+attach_bfin_nfc_regs (struct hw *me, struct bfin_nfc *nfc)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_NFC_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_NFC_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  nfc->base = attach_address;
+}
+
+static void
+bfin_nfc_finish (struct hw *me)
+{
+  struct bfin_nfc *nfc;
+
+  nfc = HW_ZALLOC (me, struct bfin_nfc);
+
+  set_hw_data (me, nfc);
+  set_hw_io_read_buffer (me, bfin_nfc_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_nfc_io_write_buffer);
+  set_hw_dma_read_buffer (me, bfin_nfc_dma_read_buffer);
+  set_hw_dma_write_buffer (me, bfin_nfc_dma_write_buffer);
+  set_hw_ports (me, bfin_nfc_ports);
+
+  attach_bfin_nfc_regs (me, nfc);
+
+  /* Initialize the NFC.  */
+  nfc->ctl     = 0x0200;
+  nfc->stat    = 0x0011;
+  nfc->irqstat = 0x0004;
+  nfc->irqmask = 0x001F;
+}
+
+const struct hw_descriptor dv_bfin_nfc_descriptor[] = {
+  {"bfin_nfc", bfin_nfc_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_nfc.h b/sim/bfin/dv-bfin_nfc.h
new file mode 100644 (file)
index 0000000..42dbec6
--- /dev/null
@@ -0,0 +1,41 @@
+/* Blackfin NAND Flash Memory Controller (NFC) model
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_NFC_H
+#define DV_BFIN_NFC_H
+
+/* XXX: This should be pushed into the model data.  */
+#define BFIN_MMR_NFC_SIZE      0x50
+
+/* NFC_STAT masks.  */
+#define NBUSY          (1 << 0)
+#define WB_FULL                (1 << 1)
+#define PG_WR_STAT     (1 << 2)
+#define PG_RD_STAT     (1 << 3)
+#define WB_EMPTY       (1 << 4)
+
+/* NFC_IRQSTAT masks.  */
+#define NBUSYIRQ       (1 << 0)
+#define WB_OVF         (1 << 1)
+#define WB_EDGE                (1 << 2)
+#define RD_RDY         (1 << 3)
+#define WR_DONE                (1 << 4)
+
+#endif
diff --git a/sim/bfin/dv-bfin_otp.c b/sim/bfin/dv-bfin_otp.c
new file mode 100644 (file)
index 0000000..d30a414
--- /dev/null
@@ -0,0 +1,307 @@
+/* Blackfin One-Time Programmable Memory (OTP) model
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_otp.h"
+
+/* XXX: No public documentation on this interface.  This seems to work
+        with the on-chip ROM functions though and was figured out by
+        disassembling & walking that code.  */
+/* XXX: About only thing that should be done here are CRC fields.  And
+        supposedly there is an interrupt that could be generated.  */
+
+struct bfin_otp
+{
+  bu32 base;
+
+  /* The actual OTP storage -- 0x200 pages, each page is 128bits.
+     While certain pages have predefined and/or secure access, we don't
+     bother trying to implement that coverage.  All pages are open for
+     reading & writing.  */
+  bu32 mem[0x200 * 4];
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu16 BFIN_MMR_16(control);
+  bu16 BFIN_MMR_16(ben);
+  bu16 BFIN_MMR_16(status);
+  bu32 timing;
+  bu32 _pad0[28];
+  bu32 data0, data1, data2, data3;
+};
+#define mmr_base()      offsetof(struct bfin_otp, control)
+#define mmr_offset(mmr) (offsetof(struct bfin_otp, mmr) - mmr_base())
+#define mmr_idx(mmr)    (mmr_offset (mmr) / 4)
+
+static const char * const mmr_names[] = {
+  "OTP_CONTROL", "OTP_BEN", "OTP_STATUS", "OTP_TIMING",
+  [mmr_idx (data0)] = "OTP_DATA0", "OTP_DATA1", "OTP_DATA2", "OTP_DATA3",
+};
+#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
+
+/* XXX: This probably misbehaves with big endian hosts.  */
+static void
+bfin_otp_transfer (struct bfin_otp *otp, void *vdst, void *vsrc)
+{
+  bu8 *dst = vdst, *src = vsrc;
+  int bidx;
+  for (bidx = 0; bidx < 16; ++bidx)
+    if (otp->ben & (1 << bidx))
+      dst[bidx] = src[bidx];
+}
+
+static void
+bfin_otp_read_page (struct bfin_otp *otp, bu16 page)
+{
+  bfin_otp_transfer (otp, &otp->data0, &otp->mem[page * 4]);
+}
+
+static void
+bfin_otp_write_page_val (struct bfin_otp *otp, bu16 page, bu64 val[2])
+{
+  bfin_otp_transfer (otp, &otp->mem[page * 4], val);
+}
+static void
+bfin_otp_write_page_val2 (struct bfin_otp *otp, bu16 page, bu64 lo, bu64 hi)
+{
+  bu64 val[2] = { lo, hi };
+  bfin_otp_write_page_val (otp, page, val);
+}
+static void
+bfin_otp_write_page (struct bfin_otp *otp, bu16 page)
+{
+  bfin_otp_write_page_val (otp, page, (void *)&otp->data0);
+}
+
+static unsigned
+bfin_otp_io_write_buffer (struct hw *me, const void *source, int space,
+                         address_word addr, unsigned nr_bytes)
+{
+  struct bfin_otp *otp = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  if (nr_bytes == 4)
+    value = dv_load_4 (source);
+  else
+    value = dv_load_2 (source);
+
+  mmr_off = addr - otp->base;
+  valuep = (void *)((unsigned long)otp + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_WRITE ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(control):
+      {
+       int page;
+
+       dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+       /* XXX: Seems like these bits aren't writable.  */
+       *value16p = value & 0x39FF;
+
+       /* Low bits seem to be the page address.  */
+       page = value & PAGE_ADDR;
+
+       /* Write operation.  */
+       if (value & DO_WRITE)
+         bfin_otp_write_page (otp, page);
+
+       /* Read operation.  */
+       if (value & DO_READ)
+         bfin_otp_read_page (otp, page);
+
+       otp->status |= STATUS_DONE;
+
+       break;
+      }
+    case mmr_offset(ben):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      /* XXX: All bits seem to be writable.  */
+      *value16p = value;
+      break;
+    case mmr_offset(status):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      /* XXX: All bits seem to be W1C.  */
+      dv_w1c_2 (value16p, value, 0);
+      break;
+    case mmr_offset(timing):
+    case mmr_offset(data0):
+    case mmr_offset(data1):
+    case mmr_offset(data2):
+    case mmr_offset(data3):
+      dv_bfin_mmr_require_32 (me, addr, nr_bytes, true);
+      *value32p = value;
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_otp_io_read_buffer (struct hw *me, void *dest, int space,
+                        address_word addr, unsigned nr_bytes)
+{
+  struct bfin_otp *otp = hw_data (me);
+  bu32 mmr_off;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  mmr_off = addr - otp->base;
+  valuep = (void *)((unsigned long)otp + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(control):
+    case mmr_offset(ben):
+    case mmr_offset(status):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+      dv_store_2 (dest, *value16p);
+      break;
+    case mmr_offset(timing):
+    case mmr_offset(data0):
+    case mmr_offset(data1):
+    case mmr_offset(data2):
+    case mmr_offset(data3):
+      dv_bfin_mmr_require_32 (me, addr, nr_bytes, false);
+      dv_store_4 (dest, *value32p);
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static void
+attach_bfin_otp_regs (struct hw *me, struct bfin_otp *otp)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_OTP_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_OTP_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  otp->base = attach_address;
+}
+
+static void
+bfin_otp_finish (struct hw *me)
+{
+  char part_str[16];
+  struct bfin_otp *otp;
+  unsigned int fps03;
+  int type = hw_find_integer_property (me, "type");
+
+  otp = HW_ZALLOC (me, struct bfin_otp);
+
+  set_hw_data (me, otp);
+  set_hw_io_read_buffer (me, bfin_otp_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_otp_io_write_buffer);
+
+  attach_bfin_otp_regs (me, otp);
+
+  /* Initialize the OTP.  */
+  otp->ben     = 0xFFFF;
+  otp->timing  = 0x00001485;
+
+  /* Semi-random value for unique chip id.  */
+  bfin_otp_write_page_val2 (otp, FPS00, (unsigned long)otp, ~(unsigned long)otp);
+
+  memset (part_str, 0, sizeof (part_str));
+  sprintf (part_str, "ADSP-BF%iX", type);
+  switch (type)
+    {
+    case 512:
+      fps03 = FPS03_BF512;
+      break;
+    case 514:
+      fps03 = FPS03_BF514;
+      break;
+    case 516:
+      fps03 = FPS03_BF516;
+      break;
+    case 518:
+      fps03 = FPS03_BF518;
+      break;
+    case 522:
+      fps03 = FPS03_BF522;
+      break;
+    case 523:
+      fps03 = FPS03_BF523;
+      break;
+    case 524:
+      fps03 = FPS03_BF524;
+      break;
+    case 525:
+      fps03 = FPS03_BF525;
+      break;
+    case 526:
+      fps03 = FPS03_BF526;
+      break;
+    case 527:
+      fps03 = FPS03_BF527;
+      break;
+    default:
+      fps03 = 0;
+      break;
+    }
+  part_str[14] = (fps03 >> 0);
+  part_str[15] = (fps03 >> 8);
+  bfin_otp_write_page_val (otp, FPS03, (void *)part_str);
+}
+
+const struct hw_descriptor dv_bfin_otp_descriptor[] = {
+  {"bfin_otp", bfin_otp_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_otp.h b/sim/bfin/dv-bfin_otp.h
new file mode 100644 (file)
index 0000000..bbb49ce
--- /dev/null
@@ -0,0 +1,100 @@
+/* Blackfin One-Time Programmable Memory (OTP) model
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_OTP_H
+#define DV_BFIN_OTP_H
+
+/* XXX: This should be pushed into the model data.  */
+/* XXX: Not exactly true; it's two sets of 4 regs near each other:
+          0xFFC03600 0x10 - Control
+          0xFFC03680 0x10 - Data  */
+#define BFIN_MMR_OTP_SIZE      0xa0
+
+/* OTP Defined Pages.  */
+#define FPS00          0x004
+#define FPS01          0x005
+#define FPS02          0x006
+#define FPS03          0x007
+#define FPS04          0x008
+#define FPS05          0x009
+#define FPS06          0x00A
+#define FPS07          0x00B
+#define FPS08          0x00C
+#define FPS09          0x00D
+#define FPS10          0x00E
+#define FPS11          0x00F
+#define CPS00          0x010
+#define CPS01          0x011
+#define CPS02          0x012
+#define CPS03          0x013
+#define CPS04          0x014
+#define CPS05          0x015
+#define CPS06          0x016
+#define CPS07          0x017
+#define PBS00          0x018
+#define PBS01          0x019
+#define PBS02          0x01A
+#define PBS03          0x01B
+#define PUB000         0x01C
+#define PUBCRC000      0x0E0
+#define PRIV000                0x110
+#define PRIVCRC000     0x1E0
+
+/* FPS03 Part values.  */
+#define FPS03_BF51XF(n)        (FPS03_BF##n | 0xF000)
+#define FPS03_BF512    0x0200
+#define FPS03_BF512F   FPS03_BF51XF(512)
+#define FPS03_BF514    0x0202
+#define FPS03_BF514F   FPS03_BF51XF(514)
+#define FPS03_BF516    0x0204
+#define FPS03_BF516F   FPS03_BF51XF(516)
+#define FPS03_BF518    0x0206
+#define FPS03_BF518F   FPS03_BF51XF(518)
+#define FPS03_BF52X_C1(n)      (FPS03_BF##n | 0x8000)
+#define FPS03_BF52X_C2(n)      (FPS03_BF##n | 0x4000)
+#define FPS03_BF522    0x020A
+#define FPS03_BF522_C1 FPS03_BF52X_C1(522)
+#define FPS03_BF522_C2 FPS03_BF52X_C2(522)
+#define FPS03_BF523    0x020B
+#define FPS03_BF523_C1 FPS03_BF52X_C1(523)
+#define FPS03_BF523_C2 FPS03_BF52X_C2(523)
+#define FPS03_BF524    0x020C
+#define FPS03_BF524_C1 FPS03_BF52X_C1(524)
+#define FPS03_BF524_C2 FPS03_BF52X_C2(524)
+#define FPS03_BF525    0x020D
+#define FPS03_BF525_C1 FPS03_BF52X_C1(525)
+#define FPS03_BF525_C2 FPS03_BF52X_C2(525)
+#define FPS03_BF526    0x020E
+#define FPS03_BF526_C1 FPS03_BF52X_C1(526)
+#define FPS03_BF526_C2 FPS03_BF52X_C2(526)
+#define FPS03_BF527    0x020F
+#define FPS03_BF527_C1 FPS03_BF52X_C1(527)
+#define FPS03_BF527_C2 FPS03_BF52X_C2(527)
+
+/* OTP_CONTROL masks.  */
+#define PAGE_ADDR      (0x1FF)
+#define DO_READ                (1 << 14)
+#define DO_WRITE       (1 << 15)
+
+/* OTP_STATUS masks.  */
+#define STATUS_DONE    (1 << 0)
+#define STATUS_ERR     (1 << 1)
+
+#endif
diff --git a/sim/bfin/dv-bfin_pll.c b/sim/bfin/dv-bfin_pll.c
new file mode 100644 (file)
index 0000000..b6e110a
--- /dev/null
@@ -0,0 +1,187 @@
+/* Blackfin Phase Lock Loop (PLL) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "machs.h"
+#include "devices.h"
+#include "dv-bfin_pll.h"
+
+struct bfin_pll
+{
+  bu32 base;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu16 BFIN_MMR_16(pll_ctl);
+  bu16 BFIN_MMR_16(pll_div);
+  bu16 BFIN_MMR_16(vr_ctl);
+  bu16 BFIN_MMR_16(pll_stat);
+  bu16 BFIN_MMR_16(pll_lockcnt);
+
+  /* XXX: Not really the best place for this ...  */
+  bu32 chipid;
+};
+#define mmr_base()      offsetof(struct bfin_pll, pll_ctl)
+#define mmr_offset(mmr) (offsetof(struct bfin_pll, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "PLL_CTL", "PLL_DIV", "VR_CTL", "PLL_STAT", "PLL_LOCKCNT", "CHIPID",
+};
+#define mmr_name(off) mmr_names[(off) / 4]
+
+static unsigned
+bfin_pll_io_write_buffer (struct hw *me, const void *source,
+                         int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_pll *pll = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  if (nr_bytes == 4)
+    value = dv_load_4 (source);
+  else
+    value = dv_load_2 (source);
+
+  mmr_off = addr - pll->base;
+  valuep = (void *)((unsigned long)pll + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_WRITE ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(pll_stat):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+    case mmr_offset(chipid):
+      /* Discard writes.  */
+      break;
+    default:
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+      *value16p = value;
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_pll_io_read_buffer (struct hw *me, void *dest,
+                        int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_pll *pll = hw_data (me);
+  bu32 mmr_off;
+  bu32 *value32p;
+  bu16 *value16p;
+  void *valuep;
+
+  mmr_off = addr - pll->base;
+  valuep = (void *)((unsigned long)pll + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(chipid):
+      dv_store_4 (dest, *value32p);
+      break;
+    default:
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+      dv_store_2 (dest, *value16p);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static const struct hw_port_descriptor bfin_pll_ports[] = {
+  { "pll", 0, 0, output_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+attach_bfin_pll_regs (struct hw *me, struct bfin_pll *pll)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_PLL_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_PLL_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  pll->base = attach_address;
+}
+
+static void
+bfin_pll_finish (struct hw *me)
+{
+  struct bfin_pll *pll;
+
+  pll = HW_ZALLOC (me, struct bfin_pll);
+
+  set_hw_data (me, pll);
+  set_hw_io_read_buffer (me, bfin_pll_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_pll_io_write_buffer);
+  set_hw_ports (me, bfin_pll_ports);
+
+  attach_bfin_pll_regs (me, pll);
+
+  /* Initialize the PLL.  */
+  /* XXX: Depends on part ?  */
+  pll->pll_ctl = 0x1400;
+  pll->pll_div = 0x0005;
+  pll->vr_ctl = 0x40DB;
+  pll->pll_stat = 0x00A2;
+  pll->pll_lockcnt = 0x0200;
+  pll->chipid = bfin_model_get_chipid (hw_system (me));
+
+  /* XXX: slow it down!  */
+  pll->pll_ctl = 0xa800;
+  pll->pll_div = 0x4;
+  pll->vr_ctl = 0x40fb;
+  pll->pll_stat = 0xa2;
+  pll->pll_lockcnt = 0x300;
+}
+
+const struct hw_descriptor dv_bfin_pll_descriptor[] = {
+  {"bfin_pll", bfin_pll_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_pll.h b/sim/bfin/dv-bfin_pll.h
new file mode 100644 (file)
index 0000000..b63104a
--- /dev/null
@@ -0,0 +1,27 @@
+/* Blackfin Phase Lock Loop (PLL) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_PLL_H
+#define DV_BFIN_PLL_H
+
+#define BFIN_MMR_PLL_BASE      0xFFC00000
+#define BFIN_MMR_PLL_SIZE      (4 * 6)
+
+#endif
diff --git a/sim/bfin/dv-bfin_ppi.c b/sim/bfin/dv-bfin_ppi.c
new file mode 100644 (file)
index 0000000..fc72b94
--- /dev/null
@@ -0,0 +1,231 @@
+/* Blackfin Parallel Port Interface (PPI) model
+   For "old style" PPIs on BF53x/etc... parts.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_ppi.h"
+#include "gui.h"
+
+/* XXX: TX is merely a stub.  */
+
+struct bfin_ppi
+{
+  /* This top portion matches common dv_bfin struct.  */
+  bu32 base;
+  struct hw *dma_master;
+  bool acked;
+
+  struct hw_event *handler;
+  char saved_byte;
+  int saved_count;
+
+  /* GUI state.  */
+  void *gui_state;
+  int color;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu16 BFIN_MMR_16(control);
+  bu16 BFIN_MMR_16(status);
+  bu16 BFIN_MMR_16(count);
+  bu16 BFIN_MMR_16(delay);
+  bu16 BFIN_MMR_16(frame);
+};
+#define mmr_base()      offsetof(struct bfin_ppi, control)
+#define mmr_offset(mmr) (offsetof(struct bfin_ppi, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "PPI_CONTROL", "PPI_STATUS", "PPI_COUNT", "PPI_DELAY", "PPI_FRAME",
+};
+#define mmr_name(off) mmr_names[(off) / 4]
+
+static void
+bfin_ppi_gui_setup (struct bfin_ppi *ppi)
+{
+  int bpp;
+
+  /* If we are in RX mode, nothing to do.  */
+  if (!(ppi->control & PORT_DIR))
+    return;
+
+  bpp = bfin_gui_color_depth (ppi->color);
+  ppi->gui_state = bfin_gui_setup (ppi->gui_state,
+                                  ppi->control & PORT_EN,
+                                  (ppi->count + 1) / (bpp / 8),
+                                  ppi->frame,
+                                  ppi->color);
+}
+
+static unsigned
+bfin_ppi_io_write_buffer (struct hw *me, const void *source, int space,
+                         address_word addr, unsigned nr_bytes)
+{
+  struct bfin_ppi *ppi = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *valuep;
+
+  value = dv_load_2 (source);
+  mmr_off = addr - ppi->base;
+  valuep = (void *)((unsigned long)ppi + mmr_base() + mmr_off);
+
+  HW_TRACE_WRITE ();
+
+  dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+
+  switch (mmr_off)
+    {
+    case mmr_offset(control):
+      *valuep = value;
+      bfin_ppi_gui_setup (ppi);
+      break;
+    case mmr_offset(count):
+    case mmr_offset(delay):
+    case mmr_offset(frame):
+      *valuep = value;
+      break;
+    case mmr_offset(status):
+      dv_w1c_2 (valuep, value, (1 << 10));
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_ppi_io_read_buffer (struct hw *me, void *dest, int space,
+                        address_word addr, unsigned nr_bytes)
+{
+  struct bfin_ppi *ppi = hw_data (me);
+  bu32 mmr_off;
+  bu16 *valuep;
+
+  mmr_off = addr - ppi->base;
+  valuep = (void *)((unsigned long)ppi + mmr_base() + mmr_off);
+
+  HW_TRACE_READ ();
+
+  dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+
+  switch (mmr_off)
+    {
+    case mmr_offset(control):
+    case mmr_offset(count):
+    case mmr_offset(delay):
+    case mmr_offset(frame):
+    case mmr_offset(status):
+      dv_store_2 (dest, *valuep);
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_ppi_dma_read_buffer (struct hw *me, void *dest, int space,
+                         unsigned_word addr, unsigned nr_bytes)
+{
+  HW_TRACE_DMA_READ ();
+  return 0;
+}
+
+static unsigned
+bfin_ppi_dma_write_buffer (struct hw *me, const void *source,
+                          int space, unsigned_word addr,
+                          unsigned nr_bytes,
+                          int violate_read_only_section)
+{
+  struct bfin_ppi *ppi = hw_data (me);
+
+  HW_TRACE_DMA_WRITE ();
+
+  return bfin_gui_update (ppi->gui_state, source, nr_bytes);
+}
+
+static const struct hw_port_descriptor bfin_ppi_ports[] = {
+  { "stat", 0, 0, output_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+attach_bfin_ppi_regs (struct hw *me, struct bfin_ppi *ppi)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_PPI_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_PPI_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  ppi->base = attach_address;
+}
+
+static void
+bfin_ppi_finish (struct hw *me)
+{
+  struct bfin_ppi *ppi;
+  const char *color;
+
+  ppi = HW_ZALLOC (me, struct bfin_ppi);
+
+  set_hw_data (me, ppi);
+  set_hw_io_read_buffer (me, bfin_ppi_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_ppi_io_write_buffer);
+  set_hw_dma_read_buffer (me, bfin_ppi_dma_read_buffer);
+  set_hw_dma_write_buffer (me, bfin_ppi_dma_write_buffer);
+  set_hw_ports (me, bfin_ppi_ports);
+
+  attach_bfin_ppi_regs (me, ppi);
+
+  /* Initialize the PPI.  */
+  if (hw_find_property (me, "color"))
+    color = hw_find_string_property (me, "color");
+  else
+    color = NULL;
+  ppi->color = bfin_gui_color (color);
+}
+
+const struct hw_descriptor dv_bfin_ppi_descriptor[] = {
+  {"bfin_ppi", bfin_ppi_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_ppi.h b/sim/bfin/dv-bfin_ppi.h
new file mode 100644 (file)
index 0000000..24e8fd9
--- /dev/null
@@ -0,0 +1,32 @@
+/* Blackfin Parallel Port Interface (PPI) model
+   For "old style" PPIs on BF53x/etc... parts.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_PPI_H
+#define DV_BFIN_PPI_H
+
+/* XXX: This should be pushed into the model data.  */
+#define BFIN_MMR_PPI_SIZE      (4 * 5)
+
+/* PPI_CONTROL Masks.  */
+#define PORT_EN                (1 << 0)
+#define PORT_DIR       (1 << 1)
+
+#endif
diff --git a/sim/bfin/dv-bfin_rtc.c b/sim/bfin/dv-bfin_rtc.c
new file mode 100644 (file)
index 0000000..6d8aa3d
--- /dev/null
@@ -0,0 +1,194 @@
+/* Blackfin Real Time Clock (RTC) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include <time.h>
+#include "sim-main.h"
+#include "dv-sockser.h"
+#include "devices.h"
+#include "dv-bfin_rtc.h"
+
+/* XXX: This read-only stub setup is based on host system clock.  */
+
+struct bfin_rtc
+{
+  bu32 base;
+  bu32 stat_shadow;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu32 stat;
+  bu16 BFIN_MMR_16(ictl);
+  bu16 BFIN_MMR_16(istat);
+  bu16 BFIN_MMR_16(swcnt);
+  bu32 alarm;
+  bu16 BFIN_MMR_16(pren);
+};
+#define mmr_base()      offsetof(struct bfin_rtc, stat)
+#define mmr_offset(mmr) (offsetof(struct bfin_rtc, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "RTC_STAT", "RTC_ICTL", "RTC_ISTAT", "RTC_SWCNT", "RTC_ALARM", "RTC_PREN",
+};
+#define mmr_name(off) mmr_names[(off) / 4]
+
+static unsigned
+bfin_rtc_io_write_buffer (struct hw *me, const void *source,
+                         int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_rtc *rtc = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  if (nr_bytes == 4)
+    value = dv_load_4 (source);
+  else
+    value = dv_load_2 (source);
+
+  mmr_off = addr - rtc->base;
+  valuep = (void *)((unsigned long)rtc + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_WRITE ();
+
+  /* XXX: These probably need more work.  */
+  switch (mmr_off)
+    {
+    case mmr_offset(stat):
+      /* XXX: Ignore these since we are wired to host.  */
+      break;
+    case mmr_offset(istat):
+      dv_w1c_2 (value16p, value, 1 << 14);
+      break;
+    case mmr_offset(alarm):
+      break;
+    case mmr_offset(ictl):
+      /* XXX: This should schedule an event handler.  */
+    case mmr_offset(swcnt):
+    case mmr_offset(pren):
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_rtc_io_read_buffer (struct hw *me, void *dest,
+                        int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_rtc *rtc = hw_data (me);
+  bu32 mmr_off;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  mmr_off = addr - rtc->base;
+  valuep = (void *)((unsigned long)rtc + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(stat):
+      {
+       time_t t = time (NULL);
+       struct tm *tm = localtime (&t);
+       bu32 value =
+         (((tm->tm_year - 70) * 365 + tm->tm_yday) << 17) |
+         (tm->tm_hour << 12) |
+         (tm->tm_min << 6) |
+         (tm->tm_sec << 0);
+       dv_store_4 (dest, value);
+       break;
+      }
+    case mmr_offset(alarm):
+      dv_store_4 (dest, *value32p);
+      break;
+    case mmr_offset(istat):
+    case mmr_offset(ictl):
+    case mmr_offset(swcnt):
+    case mmr_offset(pren):
+      dv_store_2 (dest, *value16p);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static const struct hw_port_descriptor bfin_rtc_ports[] = {
+  { "rtc", 0, 0, output_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+attach_bfin_rtc_regs (struct hw *me, struct bfin_rtc *rtc)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_RTC_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_RTC_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  rtc->base = attach_address;
+}
+
+static void
+bfin_rtc_finish (struct hw *me)
+{
+  struct bfin_rtc *rtc;
+
+  rtc = HW_ZALLOC (me, struct bfin_rtc);
+
+  set_hw_data (me, rtc);
+  set_hw_io_read_buffer (me, bfin_rtc_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_rtc_io_write_buffer);
+  set_hw_ports (me, bfin_rtc_ports);
+
+  attach_bfin_rtc_regs (me, rtc);
+
+  /* Initialize the RTC.  */
+}
+
+const struct hw_descriptor dv_bfin_rtc_descriptor[] = {
+  {"bfin_rtc", bfin_rtc_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_rtc.h b/sim/bfin/dv-bfin_rtc.h
new file mode 100644 (file)
index 0000000..04ffde1
--- /dev/null
@@ -0,0 +1,26 @@
+/* Blackfin Real Time Clock (RTC) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_RTC_H
+#define DV_BFIN_RTC_H
+
+#define BFIN_MMR_RTC_SIZE      (4 * 6)
+
+#endif
diff --git a/sim/bfin/dv-bfin_sic.c b/sim/bfin/dv-bfin_sic.c
new file mode 100644 (file)
index 0000000..0cc2e40
--- /dev/null
@@ -0,0 +1,1439 @@
+/* Blackfin System Interrupt Controller (SIC) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_sic.h"
+#include "dv-bfin_cec.h"
+
+struct bfin_sic
+{
+  /* We assume first element is the base.  */
+  bu32 base;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu16 BFIN_MMR_16(swrst);
+  bu16 BFIN_MMR_16(syscr);
+  bu16 BFIN_MMR_16(rvect);  /* XXX: BF59x has a 32bit AUX_REVID here.  */
+  union {
+    struct {
+      bu32 imask0;
+      bu32 iar0, iar1, iar2, iar3;
+      bu32 isr0, iwr0;
+      bu32 _pad0[9];
+      bu32 imask1;
+      bu32 iar4, iar5, iar6, iar7;
+      bu32 isr1, iwr1;
+    } bf52x;
+    struct {
+      bu32 imask;
+      bu32 iar0, iar1, iar2, iar3;
+      bu32 isr, iwr;
+    } bf537;
+    struct {
+      bu32 imask0, imask1, imask2;
+      bu32 isr0, isr1, isr2;
+      bu32 iwr0, iwr1, iwr2;
+      bu32 iar0, iar1, iar2, iar3;
+      bu32 iar4, iar5, iar6, iar7;
+      bu32 iar8, iar9, iar10, iar11;
+    } bf54x;
+    struct {
+      bu32 imask0, imask1;
+      bu32 iar0, iar1, iar2, iar3;
+      bu32 iar4, iar5, iar6, iar7;
+      bu32 isr0, isr1;
+      bu32 iwr0, iwr1;
+    } bf561;
+  };
+};
+#define mmr_base()      offsetof(struct bfin_sic, swrst)
+#define mmr_offset(mmr) (offsetof(struct bfin_sic, mmr) - mmr_base())
+#define mmr_idx(mmr)    (mmr_offset (mmr) / 4)
+
+static const char * const bf52x_mmr_names[] = {
+  "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK0", "SIC_IAR0", "SIC_IAR1",
+  "SIC_IAR2", "SIC_IAR3", "SIC_ISR0", "SIC_IWR0",
+  [mmr_idx (bf52x.imask1)] = "SIC_IMASK1", "SIC_IAR4", "SIC_IAR5",
+  "SIC_IAR6", "SIC_IAR7", "SIC_ISR1", "SIC_IWR1",
+};
+static const char * const bf537_mmr_names[] = {
+  "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK", "SIC_IAR0", "SIC_IAR1",
+  "SIC_IAR2", "SIC_IAR3", "SIC_ISR", "SIC_IWR",
+};
+static const char * const bf54x_mmr_names[] = {
+  "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK0", "SIC_IMASK1", "SIC_IMASK2",
+  "SIC_ISR0", "SIC_ISR1", "SIC_ISR2", "SIC_IWR0", "SIC_IWR1", "SIC_IWR2",
+  "SIC_IAR0", "SIC_IAR1", "SIC_IAR2", "SIC_IAR3",
+  "SIC_IAR4", "SIC_IAR5", "SIC_IAR6", "SIC_IAR7",
+  "SIC_IAR8", "SIC_IAR9", "SIC_IAR10", "SIC_IAR11",
+};
+static const char * const bf561_mmr_names[] = {
+  "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK0", "SIC_IMASK1",
+  "SIC_IAR0", "SIC_IAR1", "SIC_IAR2", "SIC_IAR3",
+  "SIC_IAR4", "SIC_IAR5", "SIC_IAR6", "SIC_IAR7",
+  "SIC_ISR0", "SIC_ISR1", "SIC_IWR0", "SIC_IWR1",
+};
+static const char * const *mmr_names;
+#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
+
+static void
+bfin_sic_forward_interrupts (struct hw *me, bu32 *isr, bu32 *imask, bu32 *iar)
+{
+  int my_port;
+  bu32 ipend;
+
+  /* Process pending and unmasked interrupts.  */
+  ipend = *isr & *imask;
+
+  /* Usually none are pending unmasked, so avoid bit twiddling.  */
+  if (!ipend)
+    return;
+
+  for (my_port = 0; my_port < 32; ++my_port)
+    {
+      bu32 iar_idx, iar_off, iar_val;
+      bu32 bit = (1 << my_port);
+
+      /* This bit isn't pending, so check next one.  */
+      if (!(ipend & bit))
+       continue;
+
+      /* The IAR registers map the System input to the Core output.
+         Every 4 bits in the IAR are used to map to IVG{7..15}.  */
+      iar_idx = my_port / 8;
+      iar_off = (my_port % 8) * 4;
+      iar_val = (iar[iar_idx] & (0xf << iar_off)) >> iar_off;
+      hw_port_event (me, IVG7 + iar_val, 1);
+    }
+}
+
+static void
+bfin_sic_52x_forward_interrupts (struct hw *me, struct bfin_sic *sic)
+{
+  bfin_sic_forward_interrupts (me, &sic->bf52x.isr0, &sic->bf52x.imask0, &sic->bf52x.iar0);
+  bfin_sic_forward_interrupts (me, &sic->bf52x.isr1, &sic->bf52x.imask1, &sic->bf52x.iar4);
+}
+
+static unsigned
+bfin_sic_52x_io_write_buffer (struct hw *me, const void *source, int space,
+                             address_word addr, unsigned nr_bytes)
+{
+  struct bfin_sic *sic = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  if (nr_bytes == 4)
+    value = dv_load_4 (source);
+  else
+    value = dv_load_2 (source);
+
+  mmr_off = addr - sic->base;
+  valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_WRITE ();
+
+  /* XXX: Discard all SIC writes for now.  */
+  switch (mmr_off)
+    {
+    case mmr_offset(swrst):
+      /* XXX: This should trigger a software reset ...  */
+      break;
+    case mmr_offset(syscr):
+      /* XXX: what to do ...  */
+      break;
+    case mmr_offset(bf52x.imask0):
+    case mmr_offset(bf52x.imask1):
+      bfin_sic_52x_forward_interrupts (me, sic);
+      *value32p = value;
+      break;
+    case mmr_offset(bf52x.iar0) ... mmr_offset(bf52x.iar3):
+    case mmr_offset(bf52x.iar4) ... mmr_offset(bf52x.iar7):
+    case mmr_offset(bf52x.iwr0):
+    case mmr_offset(bf52x.iwr1):
+      *value32p = value;
+      break;
+    case mmr_offset(bf52x.isr0):
+    case mmr_offset(bf52x.isr1):
+      /* ISR is read-only.  */
+      break;
+    default:
+      /* XXX: Should discard other writes.  */
+      ;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_sic_52x_io_read_buffer (struct hw *me, void *dest, int space,
+                            address_word addr, unsigned nr_bytes)
+{
+  struct bfin_sic *sic = hw_data (me);
+  bu32 mmr_off;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  mmr_off = addr - sic->base;
+  valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(swrst):
+    case mmr_offset(syscr):
+    case mmr_offset(rvect):
+      dv_store_2 (dest, *value16p);
+      break;
+    case mmr_offset(bf52x.imask0):
+    case mmr_offset(bf52x.imask1):
+    case mmr_offset(bf52x.iar0) ... mmr_offset(bf52x.iar3):
+    case mmr_offset(bf52x.iar4) ... mmr_offset(bf52x.iar7):
+    case mmr_offset(bf52x.iwr0):
+    case mmr_offset(bf52x.iwr1):
+    case mmr_offset(bf52x.isr0):
+    case mmr_offset(bf52x.isr1):
+      dv_store_4 (dest, *value32p);
+      break;
+    default:
+      if (nr_bytes == 2)
+       dv_store_2 (dest, 0);
+      else
+       dv_store_4 (dest, 0);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static void
+bfin_sic_537_forward_interrupts (struct hw *me, struct bfin_sic *sic)
+{
+  bfin_sic_forward_interrupts (me, &sic->bf537.isr, &sic->bf537.imask, &sic->bf537.iar0);
+}
+
+static unsigned
+bfin_sic_537_io_write_buffer (struct hw *me, const void *source, int space,
+                             address_word addr, unsigned nr_bytes)
+{
+  struct bfin_sic *sic = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  if (nr_bytes == 4)
+    value = dv_load_4 (source);
+  else
+    value = dv_load_2 (source);
+
+  mmr_off = addr - sic->base;
+  valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_WRITE ();
+
+  /* XXX: Discard all SIC writes for now.  */
+  switch (mmr_off)
+    {
+    case mmr_offset(swrst):
+      /* XXX: This should trigger a software reset ...  */
+      break;
+    case mmr_offset(syscr):
+      /* XXX: what to do ...  */
+      break;
+    case mmr_offset(bf537.imask):
+      bfin_sic_537_forward_interrupts (me, sic);
+      *value32p = value;
+      break;
+    case mmr_offset(bf537.iar0):
+    case mmr_offset(bf537.iar1):
+    case mmr_offset(bf537.iar2):
+    case mmr_offset(bf537.iar3):
+    case mmr_offset(bf537.iwr):
+      *value32p = value;
+      break;
+    case mmr_offset(bf537.isr):
+      /* ISR is read-only.  */
+      break;
+    default:
+      /* XXX: Should discard other writes.  */
+      ;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_sic_537_io_read_buffer (struct hw *me, void *dest, int space,
+                            address_word addr, unsigned nr_bytes)
+{
+  struct bfin_sic *sic = hw_data (me);
+  bu32 mmr_off;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  mmr_off = addr - sic->base;
+  valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(swrst):
+    case mmr_offset(syscr):
+    case mmr_offset(rvect):
+      dv_store_2 (dest, *value16p);
+      break;
+    case mmr_offset(bf537.imask):
+    case mmr_offset(bf537.iar0):
+    case mmr_offset(bf537.iar1):
+    case mmr_offset(bf537.iar2):
+    case mmr_offset(bf537.iar3):
+    case mmr_offset(bf537.isr):
+    case mmr_offset(bf537.iwr):
+      dv_store_4 (dest, *value32p);
+      break;
+    default:
+      if (nr_bytes == 2)
+       dv_store_2 (dest, 0);
+      else
+       dv_store_4 (dest, 0);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static void
+bfin_sic_54x_forward_interrupts (struct hw *me, struct bfin_sic *sic)
+{
+  bfin_sic_forward_interrupts (me, &sic->bf54x.isr0, &sic->bf54x.imask0, &sic->bf54x.iar0);
+  bfin_sic_forward_interrupts (me, &sic->bf54x.isr1, &sic->bf54x.imask1, &sic->bf54x.iar4);
+  bfin_sic_forward_interrupts (me, &sic->bf54x.isr2, &sic->bf54x.imask2, &sic->bf54x.iar8);
+}
+
+static unsigned
+bfin_sic_54x_io_write_buffer (struct hw *me, const void *source, int space,
+                             address_word addr, unsigned nr_bytes)
+{
+  struct bfin_sic *sic = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  if (nr_bytes == 4)
+    value = dv_load_4 (source);
+  else
+    value = dv_load_2 (source);
+
+  mmr_off = addr - sic->base;
+  valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_WRITE ();
+
+  /* XXX: Discard all SIC writes for now.  */
+  switch (mmr_off)
+    {
+    case mmr_offset(swrst):
+      /* XXX: This should trigger a software reset ...  */
+      break;
+    case mmr_offset(syscr):
+      /* XXX: what to do ...  */
+      break;
+    case mmr_offset(bf54x.imask0) ... mmr_offset(bf54x.imask2):
+      bfin_sic_54x_forward_interrupts (me, sic);
+      *value32p = value;
+      break;
+    case mmr_offset(bf54x.iar0) ... mmr_offset(bf54x.iar11):
+    case mmr_offset(bf54x.iwr0) ... mmr_offset(bf54x.iwr2):
+      *value32p = value;
+      break;
+    case mmr_offset(bf54x.isr0) ... mmr_offset(bf54x.isr2):
+      /* ISR is read-only.  */
+      break;
+    default:
+      /* XXX: Should discard other writes.  */
+      ;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_sic_54x_io_read_buffer (struct hw *me, void *dest, int space,
+                            address_word addr, unsigned nr_bytes)
+{
+  struct bfin_sic *sic = hw_data (me);
+  bu32 mmr_off;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  mmr_off = addr - sic->base;
+  valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(swrst):
+    case mmr_offset(syscr):
+    case mmr_offset(rvect):
+      dv_store_2 (dest, *value16p);
+      break;
+    case mmr_offset(bf54x.imask0) ... mmr_offset(bf54x.imask2):
+    case mmr_offset(bf54x.iar0) ... mmr_offset(bf54x.iar11):
+    case mmr_offset(bf54x.iwr0) ... mmr_offset(bf54x.iwr2):
+    case mmr_offset(bf54x.isr0) ... mmr_offset(bf54x.isr2):
+      dv_store_4 (dest, *value32p);
+      break;
+    default:
+      if (nr_bytes == 2)
+       dv_store_2 (dest, 0);
+      else
+       dv_store_4 (dest, 0);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static void
+bfin_sic_561_forward_interrupts (struct hw *me, struct bfin_sic *sic)
+{
+  bfin_sic_forward_interrupts (me, &sic->bf561.isr0, &sic->bf561.imask0, &sic->bf561.iar0);
+  bfin_sic_forward_interrupts (me, &sic->bf561.isr1, &sic->bf561.imask1, &sic->bf561.iar4);
+}
+
+static unsigned
+bfin_sic_561_io_write_buffer (struct hw *me, const void *source, int space,
+                             address_word addr, unsigned nr_bytes)
+{
+  struct bfin_sic *sic = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  if (nr_bytes == 4)
+    value = dv_load_4 (source);
+  else
+    value = dv_load_2 (source);
+
+  mmr_off = addr - sic->base;
+  valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_WRITE ();
+
+  /* XXX: Discard all SIC writes for now.  */
+  switch (mmr_off)
+    {
+    case mmr_offset(swrst):
+      /* XXX: This should trigger a software reset ...  */
+      break;
+    case mmr_offset(syscr):
+      /* XXX: what to do ...  */
+      break;
+    case mmr_offset(bf561.imask0):
+    case mmr_offset(bf561.imask1):
+      bfin_sic_561_forward_interrupts (me, sic);
+      *value32p = value;
+      break;
+    case mmr_offset(bf561.iar0) ... mmr_offset(bf561.iar3):
+    case mmr_offset(bf561.iar4) ... mmr_offset(bf561.iar7):
+    case mmr_offset(bf561.iwr0):
+    case mmr_offset(bf561.iwr1):
+      *value32p = value;
+      break;
+    case mmr_offset(bf561.isr0):
+    case mmr_offset(bf561.isr1):
+      /* ISR is read-only.  */
+      break;
+    default:
+      /* XXX: Should discard other writes.  */
+      ;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_sic_561_io_read_buffer (struct hw *me, void *dest, int space,
+                            address_word addr, unsigned nr_bytes)
+{
+  struct bfin_sic *sic = hw_data (me);
+  bu32 mmr_off;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  mmr_off = addr - sic->base;
+  valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(swrst):
+    case mmr_offset(syscr):
+    case mmr_offset(rvect):
+      dv_store_2 (dest, *value16p);
+      break;
+    case mmr_offset(bf561.imask0):
+    case mmr_offset(bf561.imask1):
+    case mmr_offset(bf561.iar0) ... mmr_offset(bf561.iar3):
+    case mmr_offset(bf561.iar4) ... mmr_offset(bf561.iar7):
+    case mmr_offset(bf561.iwr0):
+    case mmr_offset(bf561.iwr1):
+    case mmr_offset(bf561.isr0):
+    case mmr_offset(bf561.isr1):
+      dv_store_4 (dest, *value32p);
+      break;
+    default:
+      if (nr_bytes == 2)
+       dv_store_2 (dest, 0);
+      else
+       dv_store_4 (dest, 0);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+/* XXX: This doesn't handle DMA<->peripheral mappings.  */
+#define BFIN_SIC_TO_CEC_PORTS \
+  { "ivg7",  IVG7,  0, output_port, }, \
+  { "ivg8",  IVG8,  0, output_port, }, \
+  { "ivg9",  IVG9,  0, output_port, }, \
+  { "ivg10", IVG10, 0, output_port, }, \
+  { "ivg11", IVG11, 0, output_port, }, \
+  { "ivg12", IVG12, 0, output_port, }, \
+  { "ivg13", IVG13, 0, output_port, }, \
+  { "ivg14", IVG14, 0, output_port, }, \
+  { "ivg15", IVG15, 0, output_port, },
+
+static const struct hw_port_descriptor bfin_sic_50x_ports[] = {
+  BFIN_SIC_TO_CEC_PORTS
+  /* SIC0 */
+  { "pll",            0, 0, input_port, },
+  { "dma_stat",       1, 0, input_port, },
+  { "ppi@0",          2, 0, input_port, },
+  { "sport@0_stat",   3, 0, input_port, },
+  { "sport@1_stat",   4, 0, input_port, },
+  { "uart2@0_stat",   5, 0, input_port, },
+  { "uart2@1_stat",   6, 0, input_port, },
+  { "spi@0",          7, 0, input_port, },
+  { "spi@1",          8, 0, input_port, },
+  { "can_stat",       9, 0, input_port, },
+  { "rsi_int0",      10, 0, input_port, },
+/*{ "reserved",      11, 0, input_port, },*/
+  { "counter@0",     12, 0, input_port, },
+  { "counter@1",     13, 0, input_port, },
+  { "dma@0",         14, 0, input_port, },
+  { "dma@1",         15, 0, input_port, },
+  { "dma@2",         16, 0, input_port, },
+  { "dma@3",         17, 0, input_port, },
+  { "dma@4",         18, 0, input_port, },
+  { "dma@5",         19, 0, input_port, },
+  { "dma@6",         20, 0, input_port, },
+  { "dma@7",         21, 0, input_port, },
+  { "dma@8",         22, 0, input_port, },
+  { "dma@9",         23, 0, input_port, },
+  { "dma@10",        24, 0, input_port, },
+  { "dma@11",        25, 0, input_port, },
+  { "can_rx",        26, 0, input_port, },
+  { "can_tx",        27, 0, input_port, },
+  { "twi@0",         28, 0, input_port, },
+  { "portf_irq_a",   29, 0, input_port, },
+  { "portf_irq_b",   30, 0, input_port, },
+/*{ "reserved",      31, 0, input_port, },*/
+  /* SIC1 */
+  { "gptimer@0",    100, 0, input_port, },
+  { "gptimer@1",    101, 0, input_port, },
+  { "gptimer@2",    102, 0, input_port, },
+  { "gptimer@3",    103, 0, input_port, },
+  { "gptimer@4",    104, 0, input_port, },
+  { "gptimer@5",    105, 0, input_port, },
+  { "gptimer@6",    106, 0, input_port, },
+  { "gptimer@7",    107, 0, input_port, },
+  { "portg_irq_a",  108, 0, input_port, },
+  { "portg_irq_b",  109, 0, input_port, },
+  { "mdma@0",       110, 0, input_port, },
+  { "mdma@1",       111, 0, input_port, },
+  { "wdog",         112, 0, input_port, },
+  { "porth_irq_a",  113, 0, input_port, },
+  { "porth_irq_b",  114, 0, input_port, },
+  { "acm_stat",     115, 0, input_port, },
+  { "acm_int",      116, 0, input_port, },
+/*{ "reserved",     117, 0, input_port, },*/
+/*{ "reserved",     118, 0, input_port, },*/
+  { "pwm@0_trip",   119, 0, input_port, },
+  { "pwm@0_sync",   120, 0, input_port, },
+  { "pwm@1_trip",   121, 0, input_port, },
+  { "pwm@1_sync",   122, 0, input_port, },
+  { "rsi_int1",     123, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const struct hw_port_descriptor bfin_sic_51x_ports[] = {
+  BFIN_SIC_TO_CEC_PORTS
+  /* SIC0 */
+  { "pll",            0, 0, input_port, },
+  { "dma_stat",       1, 0, input_port, },
+  { "dmar0_block",    2, 0, input_port, },
+  { "dmar1_block",    3, 0, input_port, },
+  { "dmar0_over",     4, 0, input_port, },
+  { "dmar1_over",     5, 0, input_port, },
+  { "ppi@0",          6, 0, input_port, },
+  { "emac_stat",      7, 0, input_port, },
+  { "sport@0_stat",   8, 0, input_port, },
+  { "sport@1_stat",   9, 0, input_port, },
+  { "ptp_err",       10, 0, input_port, },
+/*{ "reserved",      11, 0, input_port, },*/
+  { "uart@0_stat",   12, 0, input_port, },
+  { "uart@1_stat",   13, 0, input_port, },
+  { "rtc",           14, 0, input_port, },
+  { "dma@0",         15, 0, input_port, },
+  { "dma@3",         16, 0, input_port, },
+  { "dma@4",         17, 0, input_port, },
+  { "dma@5",         18, 0, input_port, },
+  { "dma@6",         19, 0, input_port, },
+  { "twi@0",         20, 0, input_port, },
+  { "dma@7",         21, 0, input_port, },
+  { "dma@8",         22, 0, input_port, },
+  { "dma@9",         23, 0, input_port, },
+  { "dma@10",        24, 0, input_port, },
+  { "dma@11",        25, 0, input_port, },
+  { "otp",           26, 0, input_port, },
+  { "counter",       27, 0, input_port, },
+  { "dma@1",         28, 0, input_port, },
+  { "porth_irq_a",   29, 0, input_port, },
+  { "dma@2",         30, 0, input_port, },
+  { "porth_irq_b",   31, 0, input_port, },
+  /* SIC1 */
+  { "gptimer@0",    100, 0, input_port, },
+  { "gptimer@1",    101, 0, input_port, },
+  { "gptimer@2",    102, 0, input_port, },
+  { "gptimer@3",    103, 0, input_port, },
+  { "gptimer@4",    104, 0, input_port, },
+  { "gptimer@5",    105, 0, input_port, },
+  { "gptimer@6",    106, 0, input_port, },
+  { "gptimer@7",    107, 0, input_port, },
+  { "portg_irq_a",  108, 0, input_port, },
+  { "portg_irq_b",  109, 0, input_port, },
+  { "mdma@0",       110, 0, input_port, },
+  { "mdma@1",       111, 0, input_port, },
+  { "wdog",         112, 0, input_port, },
+  { "portf_irq_a",  113, 0, input_port, },
+  { "portf_irq_b",  114, 0, input_port, },
+  { "spi@0",        115, 0, input_port, },
+  { "spi@1",        116, 0, input_port, },
+/*{ "reserved",     117, 0, input_port, },*/
+/*{ "reserved",     118, 0, input_port, },*/
+  { "rsi_int0",     119, 0, input_port, },
+  { "rsi_int1",     120, 0, input_port, },
+  { "pwm_trip",     121, 0, input_port, },
+  { "pwm_sync",     122, 0, input_port, },
+  { "ptp_stat",     123, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const struct hw_port_descriptor bfin_sic_52x_ports[] = {
+  BFIN_SIC_TO_CEC_PORTS
+  /* SIC0 */
+  { "pll",            0, 0, input_port, },
+  { "dma_stat",       1, 0, input_port, },
+  { "dmar0_block",    2, 0, input_port, },
+  { "dmar1_block",    3, 0, input_port, },
+  { "dmar0_over",     4, 0, input_port, },
+  { "dmar1_over",     5, 0, input_port, },
+  { "ppi@0",          6, 0, input_port, },
+  { "emac_stat",      7, 0, input_port, },
+  { "sport@0_stat",   8, 0, input_port, },
+  { "sport@1_stat",   9, 0, input_port, },
+/*{ "reserved",      10, 0, input_port, },*/
+/*{ "reserved",      11, 0, input_port, },*/
+  { "uart@0_stat",   12, 0, input_port, },
+  { "uart@1_stat",   13, 0, input_port, },
+  { "rtc",           14, 0, input_port, },
+  { "dma@0",         15, 0, input_port, },
+  { "dma@3",         16, 0, input_port, },
+  { "dma@4",         17, 0, input_port, },
+  { "dma@5",         18, 0, input_port, },
+  { "dma@6",         19, 0, input_port, },
+  { "twi@0",         20, 0, input_port, },
+  { "dma@7",         21, 0, input_port, },
+  { "dma@8",         22, 0, input_port, },
+  { "dma@9",         23, 0, input_port, },
+  { "dma@10",        24, 0, input_port, },
+  { "dma@11",        25, 0, input_port, },
+  { "otp",           26, 0, input_port, },
+  { "counter",       27, 0, input_port, },
+  { "dma@1",         28, 0, input_port, },
+  { "porth_irq_a",   29, 0, input_port, },
+  { "dma@2",         30, 0, input_port, },
+  { "porth_irq_b",   31, 0, input_port, },
+  /* SIC1 */
+  { "gptimer@0",    100, 0, input_port, },
+  { "gptimer@1",    101, 0, input_port, },
+  { "gptimer@2",    102, 0, input_port, },
+  { "gptimer@3",    103, 0, input_port, },
+  { "gptimer@4",    104, 0, input_port, },
+  { "gptimer@5",    105, 0, input_port, },
+  { "gptimer@6",    106, 0, input_port, },
+  { "gptimer@7",    107, 0, input_port, },
+  { "portg_irq_a",  108, 0, input_port, },
+  { "portg_irq_b",  109, 0, input_port, },
+  { "mdma@0",       110, 0, input_port, },
+  { "mdma@1",       111, 0, input_port, },
+  { "wdog",         112, 0, input_port, },
+  { "portf_irq_a",  113, 0, input_port, },
+  { "portf_irq_b",  114, 0, input_port, },
+  { "spi@0",        115, 0, input_port, },
+  { "nfc_stat",     116, 0, input_port, },
+  { "hostdp_stat",  117, 0, input_port, },
+  { "hostdp_done",  118, 0, input_port, },
+  { "usb_int0",     120, 0, input_port, },
+  { "usb_int1",     121, 0, input_port, },
+  { "usb_int2",     122, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+bfin_sic_52x_port_event (struct hw *me, int my_port, struct hw *source,
+                        int source_port, int level)
+{
+  struct bfin_sic *sic = hw_data (me);
+  bu32 idx = my_port / 100;
+  bu32 bit = (1 << (my_port & 0x1f));
+
+  /* SIC only exists to forward interrupts from the system to the CEC.  */
+  switch (idx)
+    {
+    case 0: sic->bf52x.isr0 |= bit; break;
+    case 1: sic->bf52x.isr1 |= bit; break;
+    }
+
+  /* XXX: Handle SIC wakeup source ?
+  if (sic->bf52x.iwr0 & bit)
+    What to do ?;
+  if (sic->bf52x.iwr1 & bit)
+    What to do ?;
+   */
+
+  bfin_sic_52x_forward_interrupts (me, sic);
+}
+
+static const struct hw_port_descriptor bfin_sic_533_ports[] = {
+  BFIN_SIC_TO_CEC_PORTS
+  { "pll",            0, 0, input_port, },
+  { "dma_stat",       1, 0, input_port, },
+  { "ppi@0",          2, 0, input_port, },
+  { "sport@0_stat",   3, 0, input_port, },
+  { "sport@1_stat",   4, 0, input_port, },
+  { "spi@0",          5, 0, input_port, },
+  { "uart@0_stat",    6, 0, input_port, },
+  { "rtc",            7, 0, input_port, },
+  { "dma@0",          8, 0, input_port, },
+  { "dma@1",          9, 0, input_port, },
+  { "dma@2",         10, 0, input_port, },
+  { "dma@3",         11, 0, input_port, },
+  { "dma@4",         12, 0, input_port, },
+  { "dma@5",         13, 0, input_port, },
+  { "dma@6",         14, 0, input_port, },
+  { "dma@7",         15, 0, input_port, },
+  { "gptimer@0",     16, 0, input_port, },
+  { "gptimer@1",     17, 0, input_port, },
+  { "gptimer@2",     18, 0, input_port, },
+  { "portf_irq_a",   19, 0, input_port, },
+  { "portf_irq_b",   20, 0, input_port, },
+  { "mdma@0",        21, 0, input_port, },
+  { "mdma@1",        22, 0, input_port, },
+  { "wdog",          23, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+bfin_sic_533_port_event (struct hw *me, int my_port, struct hw *source,
+                        int source_port, int level)
+{
+  struct bfin_sic *sic = hw_data (me);
+  bu32 bit = (1 << my_port);
+
+  /* SIC only exists to forward interrupts from the system to the CEC.  */
+  sic->bf537.isr |= bit;
+
+  /* XXX: Handle SIC wakeup source ?
+  if (sic->bf537.iwr & bit)
+    What to do ?;
+   */
+
+  bfin_sic_537_forward_interrupts (me, sic);
+}
+
+static const struct hw_port_descriptor bfin_sic_537_ports[] = {
+  BFIN_SIC_TO_CEC_PORTS
+  { "pll",            0, 0, input_port, },
+  { "dma_stat",      10, 0, input_port, },
+  { "dmar0_block",   11, 0, input_port, },
+  { "dmar1_block",   12, 0, input_port, },
+  { "dmar0_over",    13, 0, input_port, },
+  { "dmar1_over",    14, 0, input_port, },
+  { "can_stat",      20, 0, input_port, },
+  { "emac_stat",     21, 0, input_port, },
+  { "sport@0_stat",  22, 0, input_port, },
+  { "sport@1_stat",  23, 0, input_port, },
+  { "ppi@0",         24, 0, input_port, },
+  { "spi@0",         25, 0, input_port, },
+  { "uart@0_stat",   26, 0, input_port, },
+  { "uart@1_stat",   27, 0, input_port, },
+  { "rtc",           30, 0, input_port, },
+  { "dma@0",         40, 0, input_port, },
+  { "dma@3",         50, 0, input_port, },
+  { "dma@4",         60, 0, input_port, },
+  { "dma@5",         70, 0, input_port, },
+  { "dma@6",         80, 0, input_port, },
+  { "twi@0",         90, 0, input_port, },
+  { "dma@7",        100, 0, input_port, },
+  { "dma@8",        110, 0, input_port, },
+  { "dma@9",        120, 0, input_port, },
+  { "dma@10",       130, 0, input_port, },
+  { "dma@11",       140, 0, input_port, },
+  { "can_rx",       150, 0, input_port, },
+  { "can_tx",       160, 0, input_port, },
+  { "dma@1",        170, 0, input_port, },
+  { "porth_irq_a",  171, 0, input_port, },
+  { "dma@2",        180, 0, input_port, },
+  { "porth_irq_b",  181, 0, input_port, },
+  { "gptimer@0",    190, 0, input_port, },
+  { "gptimer@1",    200, 0, input_port, },
+  { "gptimer@2",    210, 0, input_port, },
+  { "gptimer@3",    220, 0, input_port, },
+  { "gptimer@4",    230, 0, input_port, },
+  { "gptimer@5",    240, 0, input_port, },
+  { "gptimer@6",    250, 0, input_port, },
+  { "gptimer@7",    260, 0, input_port, },
+  { "portf_irq_a",  270, 0, input_port, },
+  { "portg_irq_a",  271, 0, input_port, },
+  { "portg_irq_b",  280, 0, input_port, },
+  { "mdma@0",       290, 0, input_port, },
+  { "mdma@1",       300, 0, input_port, },
+  { "wdog",         310, 0, input_port, },
+  { "portf_irq_b",  311, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+bfin_sic_537_port_event (struct hw *me, int my_port, struct hw *source,
+                        int source_port, int level)
+{
+  struct bfin_sic *sic = hw_data (me);
+  bu32 bit = (1 << (my_port / 10));
+
+  /* SIC only exists to forward interrupts from the system to the CEC.  */
+  sic->bf537.isr |= bit;
+
+  /* XXX: Handle SIC wakeup source ?
+  if (sic->bf537.iwr & bit)
+    What to do ?;
+   */
+
+  bfin_sic_537_forward_interrupts (me, sic);
+}
+
+static const struct hw_port_descriptor bfin_sic_538_ports[] = {
+  BFIN_SIC_TO_CEC_PORTS
+  /* SIC0 */
+  { "pll",            0, 0, input_port, },
+  { "dmac@0_stat",    1, 0, input_port, },
+  { "ppi@0",          2, 0, input_port, },
+  { "sport@0_stat",   3, 0, input_port, },
+  { "sport@1_stat",   4, 0, input_port, },
+  { "spi@0",          5, 0, input_port, },
+  { "uart@0_stat",    6, 0, input_port, },
+  { "rtc",            7, 0, input_port, },
+  { "dma@0",          8, 0, input_port, },
+  { "dma@1",          9, 0, input_port, },
+  { "dma@2",         10, 0, input_port, },
+  { "dma@3",         11, 0, input_port, },
+  { "dma@4",         12, 0, input_port, },
+  { "dma@5",         13, 0, input_port, },
+  { "dma@6",         14, 0, input_port, },
+  { "dma@7",         15, 0, input_port, },
+  { "gptimer@0",     16, 0, input_port, },
+  { "gptimer@1",     17, 0, input_port, },
+  { "gptimer@2",     18, 0, input_port, },
+  { "portf_irq_a",   19, 0, input_port, },
+  { "portf_irq_b",   20, 0, input_port, },
+  { "mdma@0",        21, 0, input_port, },
+  { "mdma@1",        22, 0, input_port, },
+  { "wdog",          23, 0, input_port, },
+  { "dmac@1_stat",   24, 0, input_port, },
+  { "sport@2_stat",  25, 0, input_port, },
+  { "sport@3_stat",  26, 0, input_port, },
+/*{ "reserved",      27, 0, input_port, },*/
+  { "spi@1",         28, 0, input_port, },
+  { "spi@2",         29, 0, input_port, },
+  { "uart@1_stat",   30, 0, input_port, },
+  { "uart@2_stat",   31, 0, input_port, },
+  /* SIC1 */
+  { "can_stat",     100, 0, input_port, },
+  { "dma@8",        101, 0, input_port, },
+  { "dma@9",        102, 0, input_port, },
+  { "dma@10",       103, 0, input_port, },
+  { "dma@11",       104, 0, input_port, },
+  { "dma@12",       105, 0, input_port, },
+  { "dma@13",       106, 0, input_port, },
+  { "dma@14",       107, 0, input_port, },
+  { "dma@15",       108, 0, input_port, },
+  { "dma@16",       109, 0, input_port, },
+  { "dma@17",       110, 0, input_port, },
+  { "dma@18",       111, 0, input_port, },
+  { "dma@19",       112, 0, input_port, },
+  { "twi@0",        113, 0, input_port, },
+  { "twi@1",        114, 0, input_port, },
+  { "can_rx",       115, 0, input_port, },
+  { "can_tx",       116, 0, input_port, },
+  { "mdma@2",       117, 0, input_port, },
+  { "mdma@3",       118, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static const struct hw_port_descriptor bfin_sic_54x_ports[] = {
+  BFIN_SIC_TO_CEC_PORTS
+  /* SIC0 */
+  { "pll",            0, 0, input_port, },
+  { "dmac@0_stat",    1, 0, input_port, },
+  { "eppi@0",         2, 0, input_port, },
+  { "sport@0_stat",   3, 0, input_port, },
+  { "sport@1_stat",   4, 0, input_port, },
+  { "spi@0",          5, 0, input_port, },
+  { "uart2@0_stat",   6, 0, input_port, },
+  { "rtc",            7, 0, input_port, },
+  { "dma@12",         8, 0, input_port, },
+  { "dma@0",          9, 0, input_port, },
+  { "dma@1",         10, 0, input_port, },
+  { "dma@2",         11, 0, input_port, },
+  { "dma@3",         12, 0, input_port, },
+  { "dma@4",         13, 0, input_port, },
+  { "dma@6",         14, 0, input_port, },
+  { "dma@7",         15, 0, input_port, },
+  { "gptimer@8",     16, 0, input_port, },
+  { "gptimer@9",     17, 0, input_port, },
+  { "gptimer@10",    18, 0, input_port, },
+  { "pint@0",        19, 0, input_port, },
+  { "pint@1",        20, 0, input_port, },
+  { "mdma@0",        21, 0, input_port, },
+  { "mdma@1",        22, 0, input_port, },
+  { "wdog",          23, 0, input_port, },
+  { "dmac@1_stat",   24, 0, input_port, },
+  { "sport@2_stat",  25, 0, input_port, },
+  { "sport@3_stat",  26, 0, input_port, },
+  { "mxvr",          27, 0, input_port, },
+  { "spi@1",         28, 0, input_port, },
+  { "spi@2",         29, 0, input_port, },
+  { "uart2@1_stat",  30, 0, input_port, },
+  { "uart2@2_stat",  31, 0, input_port, },
+  /* SIC1 */
+  { "can@0_stat",    32, 0, input_port, },
+  { "dma@18",        33, 0, input_port, },
+  { "dma@19",        34, 0, input_port, },
+  { "dma@20",        35, 0, input_port, },
+  { "dma@21",        36, 0, input_port, },
+  { "dma@13",        37, 0, input_port, },
+  { "dma@14",        38, 0, input_port, },
+  { "dma@5",         39, 0, input_port, },
+  { "dma@23",        40, 0, input_port, },
+  { "dma@8",         41, 0, input_port, },
+  { "dma@9",         42, 0, input_port, },
+  { "dma@10",        43, 0, input_port, },
+  { "dma@11",        44, 0, input_port, },
+  { "twi@0",         45, 0, input_port, },
+  { "twi@1",         46, 0, input_port, },
+  { "can@0_rx",      47, 0, input_port, },
+  { "can@0_tx",      48, 0, input_port, },
+  { "mdma@2",        49, 0, input_port, },
+  { "mdma@3",        50, 0, input_port, },
+  { "mxvr_stat",     51, 0, input_port, },
+  { "mxvr_message",  52, 0, input_port, },
+  { "mxvr_packet",   53, 0, input_port, },
+  { "eppi@1",        54, 0, input_port, },
+  { "eppi@2",        55, 0, input_port, },
+  { "uart2@3_stat",  56, 0, input_port, },
+  { "hostdp",        57, 0, input_port, },
+/*{ "reserved",      58, 0, input_port, },*/
+  { "pixc_stat",     59, 0, input_port, },
+  { "nfc",           60, 0, input_port, },
+  { "atapi",         61, 0, input_port, },
+  { "can@1_stat",    62, 0, input_port, },
+  { "dmar",          63, 0, input_port, },
+  /* SIC2 */
+  { "dma@15",        64, 0, input_port, },
+  { "dma@16",        65, 0, input_port, },
+  { "dma@17",        66, 0, input_port, },
+  { "dma@22",        67, 0, input_port, },
+  { "counter",       68, 0, input_port, },
+  { "key",           69, 0, input_port, },
+  { "can@1_rx",      70, 0, input_port, },
+  { "can@1_tx",      71, 0, input_port, },
+  { "sdh_mask0",     72, 0, input_port, },
+  { "sdh_mask1",     73, 0, input_port, },
+/*{ "reserved",      74, 0, input_port, },*/
+  { "usb_int0",      75, 0, input_port, },
+  { "usb_int1",      76, 0, input_port, },
+  { "usb_int2",      77, 0, input_port, },
+  { "usb_dma",       78, 0, input_port, },
+  { "otpsec",        79, 0, input_port, },
+/*{ "reserved",      80, 0, input_port, },*/
+/*{ "reserved",      81, 0, input_port, },*/
+/*{ "reserved",      82, 0, input_port, },*/
+/*{ "reserved",      83, 0, input_port, },*/
+/*{ "reserved",      84, 0, input_port, },*/
+/*{ "reserved",      85, 0, input_port, },*/
+  { "gptimer@0",     86, 0, input_port, },
+  { "gptimer@1",     87, 0, input_port, },
+  { "gptimer@2",     88, 0, input_port, },
+  { "gptimer@3",     89, 0, input_port, },
+  { "gptimer@4",     90, 0, input_port, },
+  { "gptimer@5",     91, 0, input_port, },
+  { "gptimer@6",     92, 0, input_port, },
+  { "gptimer@7",     93, 0, input_port, },
+  { "pint2",         94, 0, input_port, },
+  { "pint3",         95, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+bfin_sic_54x_port_event (struct hw *me, int my_port, struct hw *source,
+                        int source_port, int level)
+{
+  struct bfin_sic *sic = hw_data (me);
+  bu32 idx = my_port / 100;
+  bu32 bit = (1 << (my_port & 0x1f));
+
+  /* SIC only exists to forward interrupts from the system to the CEC.  */
+  switch (idx)
+    {
+    case 0: sic->bf54x.isr0 |= bit; break;
+    case 1: sic->bf54x.isr1 |= bit; break;
+    case 2: sic->bf54x.isr2 |= bit; break;
+    }
+
+  /* XXX: Handle SIC wakeup source ?
+  if (sic->bf54x.iwr0 & bit)
+    What to do ?;
+  if (sic->bf54x.iwr1 & bit)
+    What to do ?;
+  if (sic->bf54x.iwr2 & bit)
+    What to do ?;
+   */
+
+  bfin_sic_54x_forward_interrupts (me, sic);
+}
+
+static const struct hw_port_descriptor bfin_sic_561_ports[] = {
+  BFIN_SIC_TO_CEC_PORTS
+  /* SIC0 */
+  { "pll",            0, 0, input_port, },
+  { "dmac@0_stat",    1, 0, input_port, },
+  { "dmac@1_stat",    2, 0, input_port, },
+  { "imdma_stat",     3, 0, input_port, },
+  { "ppi@0",          4, 0, input_port, },
+  { "ppi@1",          5, 0, input_port, },
+  { "sport@0_stat",   6, 0, input_port, },
+  { "sport@1_stat",   7, 0, input_port, },
+  { "spi@0",          8, 0, input_port, },
+  { "uart@0_stat",    9, 0, input_port, },
+/*{ "reserved",      10, 0, input_port, },*/
+  { "dma@12",        11, 0, input_port, },
+  { "dma@13",        12, 0, input_port, },
+  { "dma@14",        13, 0, input_port, },
+  { "dma@15",        14, 0, input_port, },
+  { "dma@16",        15, 0, input_port, },
+  { "dma@17",        16, 0, input_port, },
+  { "dma@18",        17, 0, input_port, },
+  { "dma@19",        18, 0, input_port, },
+  { "dma@20",        19, 0, input_port, },
+  { "dma@21",        20, 0, input_port, },
+  { "dma@22",        21, 0, input_port, },
+  { "dma@23",        22, 0, input_port, },
+  { "dma@0",         23, 0, input_port, },
+  { "dma@1",         24, 0, input_port, },
+  { "dma@2",         25, 0, input_port, },
+  { "dma@3",         26, 0, input_port, },
+  { "dma@4",         27, 0, input_port, },
+  { "dma@5",         28, 0, input_port, },
+  { "dma@6",         29, 0, input_port, },
+  { "dma@7",         30, 0, input_port, },
+  { "dma@8",         31, 0, input_port, },
+  /* SIC1 */
+  { "dma@9",        100, 0, input_port, },
+  { "dma@10",       101, 0, input_port, },
+  { "dma@11",       102, 0, input_port, },
+  { "gptimer@0",    103, 0, input_port, },
+  { "gptimer@1",    104, 0, input_port, },
+  { "gptimer@2",    105, 0, input_port, },
+  { "gptimer@3",    106, 0, input_port, },
+  { "gptimer@4",    107, 0, input_port, },
+  { "gptimer@5",    108, 0, input_port, },
+  { "gptimer@6",    109, 0, input_port, },
+  { "gptimer@7",    110, 0, input_port, },
+  { "gptimer@8",    111, 0, input_port, },
+  { "gptimer@9",    112, 0, input_port, },
+  { "gptimer@10",   113, 0, input_port, },
+  { "gptimer@11",   114, 0, input_port, },
+  { "portf_irq_a",  115, 0, input_port, },
+  { "portf_irq_b",  116, 0, input_port, },
+  { "portg_irq_a",  117, 0, input_port, },
+  { "portg_irq_b",  118, 0, input_port, },
+  { "porth_irq_a",  119, 0, input_port, },
+  { "porth_irq_b",  120, 0, input_port, },
+  { "mdma@0",       121, 0, input_port, },
+  { "mdma@1",       122, 0, input_port, },
+  { "mdma@2",       123, 0, input_port, },
+  { "mdma@3",       124, 0, input_port, },
+  { "imdma@0",      125, 0, input_port, },
+  { "imdma@1",      126, 0, input_port, },
+  { "wdog",         127, 0, input_port, },
+/*{ "reserved",     128, 0, input_port, },*/
+/*{ "reserved",     129, 0, input_port, },*/
+  { "sup_irq_0",    130, 0, input_port, },
+  { "sup_irq_1",    131, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+bfin_sic_561_port_event (struct hw *me, int my_port, struct hw *source,
+                        int source_port, int level)
+{
+  struct bfin_sic *sic = hw_data (me);
+  bu32 idx = my_port / 100;
+  bu32 bit = (1 << (my_port & 0x1f));
+
+  /* SIC only exists to forward interrupts from the system to the CEC.  */
+  switch (idx)
+    {
+    case 0: sic->bf561.isr0 |= bit; break;
+    case 1: sic->bf561.isr1 |= bit; break;
+    }
+
+  /* XXX: Handle SIC wakeup source ?
+  if (sic->bf561.iwr0 & bit)
+    What to do ?;
+  if (sic->bf561.iwr1 & bit)
+    What to do ?;
+   */
+
+  bfin_sic_561_forward_interrupts (me, sic);
+}
+
+static const struct hw_port_descriptor bfin_sic_59x_ports[] = {
+  BFIN_SIC_TO_CEC_PORTS
+  { "pll",            0, 0, input_port, },
+  { "dma_stat",       1, 0, input_port, },
+  { "ppi@0",          2, 0, input_port, },
+  { "sport@0_stat",   3, 0, input_port, },
+  { "sport@1_stat",   4, 0, input_port, },
+  { "spi@0",          5, 0, input_port, },
+  { "spi@1",          6, 0, input_port, },
+  { "uart@0_stat",    7, 0, input_port, },
+  { "dma@0",          8, 0, input_port, },
+  { "dma@1",          9, 0, input_port, },
+  { "dma@2",         10, 0, input_port, },
+  { "dma@3",         11, 0, input_port, },
+  { "dma@4",         12, 0, input_port, },
+  { "dma@5",         13, 0, input_port, },
+  { "dma@6",         14, 0, input_port, },
+  { "dma@7",         15, 0, input_port, },
+  { "dma@8",         16, 0, input_port, },
+  { "portf_irq_a",   17, 0, input_port, },
+  { "portf_irq_b",   18, 0, input_port, },
+  { "gptimer@0",     19, 0, input_port, },
+  { "gptimer@1",     20, 0, input_port, },
+  { "gptimer@2",     21, 0, input_port, },
+  { "portg_irq_a",   22, 0, input_port, },
+  { "portg_irq_b",   23, 0, input_port, },
+  { "twi@0",         24, 0, input_port, },
+/* XXX: 25 - 28 are supposed to be reserved; see comment in machs.c:bf592_dmac[]  */
+  { "dma@9",         25, 0, input_port, },
+  { "dma@10",        26, 0, input_port, },
+  { "dma@11",        27, 0, input_port, },
+  { "dma@12",        28, 0, input_port, },
+/*{ "reserved",      25, 0, input_port, },*/
+/*{ "reserved",      26, 0, input_port, },*/
+/*{ "reserved",      27, 0, input_port, },*/
+/*{ "reserved",      28, 0, input_port, },*/
+  { "mdma@0",        29, 0, input_port, },
+  { "mdma@1",        30, 0, input_port, },
+  { "wdog",          31, 0, input_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+attach_bfin_sic_regs (struct hw *me, struct bfin_sic *sic)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_SIC_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_SIC_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  sic->base = attach_address;
+}
+
+static void
+bfin_sic_finish (struct hw *me)
+{
+  struct bfin_sic *sic;
+
+  sic = HW_ZALLOC (me, struct bfin_sic);
+
+  set_hw_data (me, sic);
+  attach_bfin_sic_regs (me, sic);
+
+  switch (hw_find_integer_property (me, "type"))
+    {
+    case 500 ... 509:
+      set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer);
+      set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer);
+      set_hw_ports (me, bfin_sic_50x_ports);
+      set_hw_port_event (me, bfin_sic_52x_port_event);
+      mmr_names = bf52x_mmr_names;
+
+      /* Initialize the SIC.  */
+      sic->bf52x.imask0 = sic->bf52x.imask1 = 0;
+      sic->bf52x.isr0 = sic->bf52x.isr1 = 0;
+      sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF;
+      sic->bf52x.iar0 = 0x00000000;
+      sic->bf52x.iar1 = 0x22111000;
+      sic->bf52x.iar2 = 0x33332222;
+      sic->bf52x.iar3 = 0x44444433;
+      sic->bf52x.iar4 = 0x55555555;
+      sic->bf52x.iar5 = 0x06666655;
+      sic->bf52x.iar6 = 0x33333003;
+      sic->bf52x.iar7 = 0x00000000;    /* XXX: Find and fix */
+      break;
+    case 510 ... 519:
+      set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer);
+      set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer);
+      set_hw_ports (me, bfin_sic_51x_ports);
+      set_hw_port_event (me, bfin_sic_52x_port_event);
+      mmr_names = bf52x_mmr_names;
+
+      /* Initialize the SIC.  */
+      sic->bf52x.imask0 = sic->bf52x.imask1 = 0;
+      sic->bf52x.isr0 = sic->bf52x.isr1 = 0;
+      sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF;
+      sic->bf52x.iar0 = 0x00000000;
+      sic->bf52x.iar1 = 0x11000000;
+      sic->bf52x.iar2 = 0x33332222;
+      sic->bf52x.iar3 = 0x44444433;
+      sic->bf52x.iar4 = 0x55555555;
+      sic->bf52x.iar5 = 0x06666655;
+      sic->bf52x.iar6 = 0x33333000;
+      sic->bf52x.iar7 = 0x00000000;    /* XXX: Find and fix */
+      break;
+    case 522 ... 527:
+      set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer);
+      set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer);
+      set_hw_ports (me, bfin_sic_52x_ports);
+      set_hw_port_event (me, bfin_sic_52x_port_event);
+      mmr_names = bf52x_mmr_names;
+
+      /* Initialize the SIC.  */
+      sic->bf52x.imask0 = sic->bf52x.imask1 = 0;
+      sic->bf52x.isr0 = sic->bf52x.isr1 = 0;
+      sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF;
+      sic->bf52x.iar0 = 0x00000000;
+      sic->bf52x.iar1 = 0x11000000;
+      sic->bf52x.iar2 = 0x33332222;
+      sic->bf52x.iar3 = 0x44444433;
+      sic->bf52x.iar4 = 0x55555555;
+      sic->bf52x.iar5 = 0x06666655;
+      sic->bf52x.iar6 = 0x33333000;
+      sic->bf52x.iar7 = 0x00000000;    /* XXX: Find and fix */
+      break;
+    case 531 ... 533:
+      set_hw_io_read_buffer (me, bfin_sic_537_io_read_buffer);
+      set_hw_io_write_buffer (me, bfin_sic_537_io_write_buffer);
+      set_hw_ports (me, bfin_sic_533_ports);
+      set_hw_port_event (me, bfin_sic_533_port_event);
+      mmr_names = bf537_mmr_names;
+
+      /* Initialize the SIC.  */
+      sic->bf537.imask = 0;
+      sic->bf537.isr = 0;
+      sic->bf537.iwr = 0xFFFFFFFF;
+      sic->bf537.iar0 = 0x10000000;
+      sic->bf537.iar1 = 0x33322221;
+      sic->bf537.iar2 = 0x66655444;
+      sic->bf537.iar3 = 0; /* XXX: fix this */
+      break;
+    case 534:
+    case 536:
+    case 537:
+      set_hw_io_read_buffer (me, bfin_sic_537_io_read_buffer);
+      set_hw_io_write_buffer (me, bfin_sic_537_io_write_buffer);
+      set_hw_ports (me, bfin_sic_537_ports);
+      set_hw_port_event (me, bfin_sic_537_port_event);
+      mmr_names = bf537_mmr_names;
+
+      /* Initialize the SIC.  */
+      sic->bf537.imask = 0;
+      sic->bf537.isr = 0;
+      sic->bf537.iwr = 0xFFFFFFFF;
+      sic->bf537.iar0 = 0x22211000;
+      sic->bf537.iar1 = 0x43333332;
+      sic->bf537.iar2 = 0x55555444;
+      sic->bf537.iar3 = 0x66655555;
+      break;
+    case 538 ... 539:
+      set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer);
+      set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer);
+      set_hw_ports (me, bfin_sic_538_ports);
+      set_hw_port_event (me, bfin_sic_52x_port_event);
+      mmr_names = bf52x_mmr_names;
+
+      /* Initialize the SIC.  */
+      sic->bf52x.imask0 = sic->bf52x.imask1 = 0;
+      sic->bf52x.isr0 = sic->bf52x.isr1 = 0;
+      sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF;
+      sic->bf52x.iar0 = 0x10000000;
+      sic->bf52x.iar1 = 0x33322221;
+      sic->bf52x.iar2 = 0x66655444;
+      sic->bf52x.iar3 = 0x00000000;
+      sic->bf52x.iar4 = 0x32222220;
+      sic->bf52x.iar5 = 0x44433333;
+      sic->bf52x.iar6 = 0x00444664;
+      sic->bf52x.iar7 = 0x00000000;    /* XXX: Find and fix */
+      break;
+    case 540 ... 549:
+      set_hw_io_read_buffer (me, bfin_sic_54x_io_read_buffer);
+      set_hw_io_write_buffer (me, bfin_sic_54x_io_write_buffer);
+      set_hw_ports (me, bfin_sic_54x_ports);
+      set_hw_port_event (me, bfin_sic_54x_port_event);
+      mmr_names = bf54x_mmr_names;
+
+      /* Initialize the SIC.  */
+      sic->bf54x.imask0 = sic->bf54x.imask1 = sic->bf54x.imask2 = 0;
+      sic->bf54x.isr0 = sic->bf54x.isr1 = sic->bf54x.isr2 = 0;
+      sic->bf54x.iwr0 = sic->bf54x.iwr1 = sic->bf54x.iwr1 = 0xFFFFFFFF;
+      sic->bf54x.iar0 = 0x10000000;
+      sic->bf54x.iar1 = 0x33322221;
+      sic->bf54x.iar2 = 0x66655444;
+      sic->bf54x.iar3 = 0x00000000;
+      sic->bf54x.iar4 = 0x32222220;
+      sic->bf54x.iar5 = 0x44433333;
+      sic->bf54x.iar6 = 0x00444664;
+      sic->bf54x.iar7 = 0x00000000;
+      sic->bf54x.iar8 = 0x44111111;
+      sic->bf54x.iar9 = 0x44444444;
+      sic->bf54x.iar10 = 0x44444444;
+      sic->bf54x.iar11 = 0x55444444;
+      break;
+    case 561:
+      set_hw_io_read_buffer (me, bfin_sic_561_io_read_buffer);
+      set_hw_io_write_buffer (me, bfin_sic_561_io_write_buffer);
+      set_hw_ports (me, bfin_sic_561_ports);
+      set_hw_port_event (me, bfin_sic_561_port_event);
+      mmr_names = bf561_mmr_names;
+
+      /* Initialize the SIC.  */
+      sic->bf561.imask0 = sic->bf561.imask1 = 0;
+      sic->bf561.isr0 = sic->bf561.isr1 = 0;
+      sic->bf561.iwr0 = sic->bf561.iwr1 = 0xFFFFFFFF;
+      sic->bf561.iar0 = 0x00000000;
+      sic->bf561.iar1 = 0x11111000;
+      sic->bf561.iar2 = 0x21111111;
+      sic->bf561.iar3 = 0x22222222;
+      sic->bf561.iar4 = 0x33333222;
+      sic->bf561.iar5 = 0x43333333;
+      sic->bf561.iar6 = 0x21144444;
+      sic->bf561.iar7 = 0x00006552;
+      break;
+    case 590 ... 599:
+      set_hw_io_read_buffer (me, bfin_sic_537_io_read_buffer);
+      set_hw_io_write_buffer (me, bfin_sic_537_io_write_buffer);
+      set_hw_ports (me, bfin_sic_59x_ports);
+      set_hw_port_event (me, bfin_sic_533_port_event);
+      mmr_names = bf537_mmr_names;
+
+      /* Initialize the SIC.  */
+      sic->bf537.imask = 0;
+      sic->bf537.isr = 0;
+      sic->bf537.iwr = 0xFFFFFFFF;
+      sic->bf537.iar0 = 0x00000000;
+      sic->bf537.iar1 = 0x33322221;
+      sic->bf537.iar2 = 0x55444443;
+      sic->bf537.iar3 = 0x66600005;
+      break;
+    default:
+      hw_abort (me, "no support for SIC on this Blackfin model yet");
+    }
+}
+
+const struct hw_descriptor dv_bfin_sic_descriptor[] = {
+  {"bfin_sic", bfin_sic_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_sic.h b/sim/bfin/dv-bfin_sic.h
new file mode 100644 (file)
index 0000000..e70a749
--- /dev/null
@@ -0,0 +1,27 @@
+/* Blackfin System Interrupt Controller (SIC) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_SIC_H
+#define DV_BFIN_SIC_H
+
+#define BFIN_MMR_SIC_BASE      0xFFC00100
+#define BFIN_MMR_SIC_SIZE      0x100
+
+#endif
diff --git a/sim/bfin/dv-bfin_spi.c b/sim/bfin/dv-bfin_spi.c
new file mode 100644 (file)
index 0000000..4c783d0
--- /dev/null
@@ -0,0 +1,229 @@
+/* Blackfin Serial Peripheral Interface (SPI) model
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_spi.h"
+
+/* XXX: This is merely a stub.  */
+
+struct bfin_spi
+{
+  /* This top portion matches common dv_bfin struct.  */
+  bu32 base;
+  struct hw *dma_master;
+  bool acked;
+
+  struct hw_event *handler;
+  char saved_byte;
+  int saved_count;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu16 BFIN_MMR_16(ctl);
+  bu16 BFIN_MMR_16(flg);
+  bu16 BFIN_MMR_16(stat);
+  bu16 BFIN_MMR_16(tdbr);
+  bu16 BFIN_MMR_16(rdbr);
+  bu16 BFIN_MMR_16(baud);
+  bu16 BFIN_MMR_16(shadow);
+};
+#define mmr_base()      offsetof(struct bfin_spi, ctl)
+#define mmr_offset(mmr) (offsetof(struct bfin_spi, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "SPI_CTL", "SPI_FLG", "SPI_STAT", "SPI_TDBR",
+  "SPI_RDBR", "SPI_BAUD", "SPI_SHADOW",
+};
+#define mmr_name(off) mmr_names[(off) / 4]
+
+static bool
+bfin_spi_enabled (struct bfin_spi *spi)
+{
+  return (spi->ctl & SPE);
+}
+
+static bu16
+bfin_spi_timod (struct bfin_spi *spi)
+{
+  return (spi->ctl & TIMOD);
+}
+
+static unsigned
+bfin_spi_io_write_buffer (struct hw *me, const void *source, int space,
+                         address_word addr, unsigned nr_bytes)
+{
+  struct bfin_spi *spi = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *valuep;
+
+  value = dv_load_2 (source);
+  mmr_off = addr - spi->base;
+  valuep = (void *)((unsigned long)spi + mmr_base() + mmr_off);
+
+  HW_TRACE_WRITE ();
+
+  dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+
+  switch (mmr_off)
+    {
+    case mmr_offset(stat):
+      dv_w1c_2 (valuep, value, SPIF | TXS | RXS);
+      break;
+    case mmr_offset(tdbr):
+      *valuep = value;
+      if (bfin_spi_enabled (spi) && bfin_spi_timod (spi) == TDBR_CORE)
+       {
+         spi->stat |= RXS;
+         spi->stat &= ~TXS;
+       }
+      break;
+    case mmr_offset(rdbr):
+    case mmr_offset(ctl):
+    case mmr_offset(flg):
+    case mmr_offset(baud):
+    case mmr_offset(shadow):
+      *valuep = value;
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_spi_io_read_buffer (struct hw *me, void *dest, int space,
+                        address_word addr, unsigned nr_bytes)
+{
+  struct bfin_spi *spi = hw_data (me);
+  bu32 mmr_off;
+  bu16 *valuep;
+
+  mmr_off = addr - spi->base;
+  valuep = (void *)((unsigned long)spi + mmr_base() + mmr_off);
+
+  HW_TRACE_READ ();
+
+  dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+
+  switch (mmr_off)
+    {
+    case mmr_offset(rdbr):
+      dv_store_2 (dest, *valuep);
+      if (bfin_spi_enabled (spi) && bfin_spi_timod (spi) == RDBR_CORE)
+       spi->stat &= ~(RXS | TXS);
+      break;
+    case mmr_offset(ctl):
+    case mmr_offset(stat):
+    case mmr_offset(flg):
+    case mmr_offset(tdbr):
+    case mmr_offset(baud):
+    case mmr_offset(shadow):
+      dv_store_2 (dest, *valuep);
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_spi_dma_read_buffer (struct hw *me, void *dest, int space,
+                         unsigned_word addr, unsigned nr_bytes)
+{
+  HW_TRACE_DMA_READ ();
+  return 0;
+}
+
+static unsigned
+bfin_spi_dma_write_buffer (struct hw *me, const void *source,
+                          int space, unsigned_word addr,
+                          unsigned nr_bytes,
+                          int violate_read_only_section)
+{
+  HW_TRACE_DMA_WRITE ();
+  return 0;
+}
+
+static const struct hw_port_descriptor bfin_spi_ports[] = {
+  { "stat", 0, 0, output_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+attach_bfin_spi_regs (struct hw *me, struct bfin_spi *spi)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_SPI_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_SPI_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  spi->base = attach_address;
+}
+
+static void
+bfin_spi_finish (struct hw *me)
+{
+  struct bfin_spi *spi;
+
+  spi = HW_ZALLOC (me, struct bfin_spi);
+
+  set_hw_data (me, spi);
+  set_hw_io_read_buffer (me, bfin_spi_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_spi_io_write_buffer);
+  set_hw_dma_read_buffer (me, bfin_spi_dma_read_buffer);
+  set_hw_dma_write_buffer (me, bfin_spi_dma_write_buffer);
+  set_hw_ports (me, bfin_spi_ports);
+
+  attach_bfin_spi_regs (me, spi);
+
+  /* Initialize the SPI.  */
+  spi->ctl  = 0x0400;
+  spi->flg  = 0xFF00;
+  spi->stat = 0x0001;
+}
+
+const struct hw_descriptor dv_bfin_spi_descriptor[] = {
+  {"bfin_spi", bfin_spi_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_spi.h b/sim/bfin/dv-bfin_spi.h
new file mode 100644 (file)
index 0000000..5e216bf
--- /dev/null
@@ -0,0 +1,54 @@
+/* Blackfin Serial Peripheral Interface (SPI) model
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_SPI_H
+#define DV_BFIN_SPI_H
+
+/* XXX: This should be pushed into the model data.  */
+#define BFIN_MMR_SPI_SIZE      (4 * 7)
+
+/* SPI_CTL Masks.  */
+#define TIMOD          (3 << 0)
+#define RDBR_CORE      (0 << 0)
+#define TDBR_CORE      (1 << 0)
+#define RDBR_DMA       (2 << 0)
+#define TDBR_DMA       (3 << 0)
+#define SZ             (1 << 2)
+#define GM             (1 << 3)
+#define PSSE           (1 << 4)
+#define EMISO          (1 << 5)
+#define SZE            (1 << 8)
+#define LSBF           (1 << 9)
+#define CPHA           (1 << 10)
+#define CPOL           (1 << 11)
+#define MSTR           (1 << 12)
+#define WOM            (1 << 13)
+#define SPE            (1 << 14)
+
+/* SPI_STAT Masks.  */
+#define SPIF           (1 << 0)
+#define MODF           (1 << 1)
+#define TXE            (1 << 2)
+#define TXS            (1 << 3)
+#define RBSY           (1 << 4)
+#define RXS            (1 << 5)
+#define TXCOL          (1 << 6)
+
+#endif
diff --git a/sim/bfin/dv-bfin_trace.c b/sim/bfin/dv-bfin_trace.c
new file mode 100644 (file)
index 0000000..a77dd64
--- /dev/null
@@ -0,0 +1,285 @@
+/* Blackfin Trace (TBUF) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_cec.h"
+#include "dv-bfin_trace.h"
+
+/* Note: The circular buffering here might look a little buggy wrt mid-reads
+         and consuming the top entry, but this is simulating hardware behavior.
+         The hardware is simple, dumb, and fast.  Don't write dumb Blackfin
+         software and you won't have a problem.  */
+
+/* The hardware is limited to 16 entries and defines TBUFCTL.  Let's extend it ;).  */
+#ifndef SIM_BFIN_TRACE_DEPTH
+#define SIM_BFIN_TRACE_DEPTH 6
+#endif
+#define SIM_BFIN_TRACE_LEN (1 << SIM_BFIN_TRACE_DEPTH)
+#define SIM_BFIN_TRACE_LEN_MASK (SIM_BFIN_TRACE_LEN - 1)
+
+struct bfin_trace_entry
+{
+  bu32 src, dst;
+};
+struct bfin_trace
+{
+  bu32 base;
+  struct bfin_trace_entry buffer[SIM_BFIN_TRACE_LEN];
+  int top, bottom;
+  bool mid;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu32 tbufctl, tbufstat;
+  char _pad[0x100 - 0x8];
+  bu32 tbuf;
+};
+#define mmr_base()      offsetof(struct bfin_trace, tbufctl)
+#define mmr_offset(mmr) (offsetof(struct bfin_trace, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "TBUFCTL", "TBUFSTAT", [mmr_offset (tbuf) / 4] = "TBUF",
+};
+#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
+
+/* Ugh, circular buffers.  */
+#define TBUF_LEN(t) ((t)->top - (t)->bottom)
+#define TBUF_IDX(i) ((i) & SIM_BFIN_TRACE_LEN_MASK)
+/* TOP is the next slot to fill.  */
+#define TBUF_TOP(t) (&(t)->buffer[TBUF_IDX ((t)->top)])
+/* LAST is the latest valid slot.  */
+#define TBUF_LAST(t) (&(t)->buffer[TBUF_IDX ((t)->top - 1)])
+/* LAST_LAST is the second-to-last valid slot.  */
+#define TBUF_LAST_LAST(t) (&(t)->buffer[TBUF_IDX ((t)->top - 2)])
+
+static unsigned
+bfin_trace_io_write_buffer (struct hw *me, const void *source,
+                           int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_trace *trace = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+
+  value = dv_load_4 (source);
+  mmr_off = addr - trace->base;
+
+  HW_TRACE_WRITE ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(tbufctl):
+      trace->tbufctl = value;
+      break;
+    case mmr_offset(tbufstat):
+    case mmr_offset(tbuf):
+      /* Discard writes to these.  */
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_trace_io_read_buffer (struct hw *me, void *dest,
+                          int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_trace *trace = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+
+  mmr_off = addr - trace->base;
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(tbufctl):
+      value = trace->tbufctl;
+      break;
+    case mmr_offset(tbufstat):
+      /* Hardware is limited to 16 entries, so to stay compatible with
+         software, limit the value to 16.  For software algorithms that
+         keep reading while (TBUFSTAT != 0), they'll get all of it.  */
+      value = MIN (TBUF_LEN (trace), 16);
+      break;
+    case mmr_offset(tbuf):
+      {
+       struct bfin_trace_entry *e;
+
+       if (TBUF_LEN (trace) == 0)
+         {
+           value = 0;
+           break;
+         }
+
+       e = TBUF_LAST (trace);
+       if (trace->mid)
+         {
+           value = e->src;
+           --trace->top;
+         }
+       else
+         value = e->dst;
+       trace->mid = !trace->mid;
+
+       break;
+      }
+    default:
+      while (1) /* Core MMRs -> exception -> doesn't return.  */
+       dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  dv_store_4 (dest, value);
+
+  return nr_bytes;
+}
+
+static void
+attach_bfin_trace_regs (struct hw *me, struct bfin_trace *trace)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_COREMMR_TRACE_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_COREMMR_TRACE_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  trace->base = attach_address;
+}
+
+static void
+bfin_trace_finish (struct hw *me)
+{
+  struct bfin_trace *trace;
+
+  trace = HW_ZALLOC (me, struct bfin_trace);
+
+  set_hw_data (me, trace);
+  set_hw_io_read_buffer (me, bfin_trace_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_trace_io_write_buffer);
+
+  attach_bfin_trace_regs (me, trace);
+}
+
+const struct hw_descriptor dv_bfin_trace_descriptor[] = {
+  {"bfin_trace", bfin_trace_finish,},
+  {NULL, NULL},
+};
+
+#define TRACE_STATE(cpu) DV_STATE_CACHED (cpu, trace)
+
+/* This is not re-entrant, but neither is the cpu state, so this shouldn't
+   be a big deal ...  */
+void bfin_trace_queue (SIM_CPU *cpu, bu32 src_pc, bu32 dst_pc, int hwloop)
+{
+  struct bfin_trace *trace = TRACE_STATE (cpu);
+  struct bfin_trace_entry *e;
+  int len, ivg;
+
+  /* Only queue if powered.  */
+  if (!(trace->tbufctl & TBUFPWR))
+    return;
+
+  /* Only queue if enabled.  */
+  if (!(trace->tbufctl & TBUFEN))
+    return;
+
+  /* Ignore hardware loops.
+     XXX: This is what the hardware does, but an option to ignore
+     could be useful for debugging ...  */
+  if (hwloop >= 0)
+    return;
+
+  /* Only queue if at right level.  */
+  ivg = cec_get_ivg (cpu);
+  if (ivg == IVG_RST)
+    /* XXX: This is what the hardware does, but an option to ignore
+            could be useful for debugging ...  */
+    return;
+  if (ivg <= IVG_EVX && (trace->tbufctl & TBUFOVF))
+    /* XXX: This is what the hardware does, but an option to ignore
+            could be useful for debugging ... just don't throw an
+            exception when full and in EVT{0..3}.  */
+    return;
+
+  /* Are we full ?  */
+  len = TBUF_LEN (trace);
+  if (len == SIM_BFIN_TRACE_LEN)
+    {
+      if (trace->tbufctl & TBUFOVF)
+       {
+         cec_exception (cpu, VEC_OVFLOW);
+         return;
+       }
+
+      /* Overwrite next entry.  */
+      ++trace->bottom;
+    }
+
+  /* One level compression.  */
+  if (len >= 1 && (trace->tbufctl & TBUFCMPLP))
+    {
+      e = TBUF_LAST (trace);
+      if (src_pc == (e->src & ~1) && dst_pc == (e->dst & ~1))
+       {
+         /* Hardware sets LSB when level is compressed.  */
+         e->dst |= 1;
+         return;
+       }
+    }
+
+  /* Two level compression.  */
+  if (len >= 2 && (trace->tbufctl & TBUFCMPLP_DOUBLE))
+    {
+      e = TBUF_LAST_LAST (trace);
+      if (src_pc == (e->src & ~1) && dst_pc == (e->dst & ~1))
+       {
+         /* Hardware sets LSB when level is compressed.  */
+         e->src |= 1;
+         return;
+       }
+    }
+
+  e = TBUF_TOP (trace);
+  e->dst = dst_pc;
+  e->src = src_pc;
+  ++trace->top;
+}
diff --git a/sim/bfin/dv-bfin_trace.h b/sim/bfin/dv-bfin_trace.h
new file mode 100644 (file)
index 0000000..3acfddf
--- /dev/null
@@ -0,0 +1,37 @@
+/* Blackfin Trace (TBUF) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_TRACE_H
+#define DV_BFIN_TRACE_H
+
+#define BFIN_COREMMR_TRACE_BASE        0xFFE06000
+#define BFIN_COREMMR_TRACE_SIZE        (4 * 65)
+
+/* TBUFCTL Masks */
+#define TBUFPWR                        0x0001
+#define TBUFEN                 0x0002
+#define TBUFOVF                        0x0004
+#define TBUFCMPLP_SINGLE       0x0008
+#define TBUFCMPLP_DOUBLE       0x0010
+#define TBUFCMPLP              (TBUFCMPLP_SINGLE | TBUFCMPLP_DOUBLE)
+
+void bfin_trace_queue (SIM_CPU *, bu32 src_pc, bu32 dst_pc, int hwloop);
+
+#endif
diff --git a/sim/bfin/dv-bfin_twi.c b/sim/bfin/dv-bfin_twi.c
new file mode 100644 (file)
index 0000000..4e6783d
--- /dev/null
@@ -0,0 +1,227 @@
+/* Blackfin Two Wire Interface (TWI) model
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_twi.h"
+
+/* XXX: This is merely a stub.  */
+
+struct bfin_twi
+{
+  /* This top portion matches common dv_bfin struct.  */
+  bu32 base;
+  struct hw *dma_master;
+  bool acked;
+
+  struct hw_event *handler;
+  char saved_byte;
+  int saved_count;
+
+  bu16 xmt_fifo, rcv_fifo;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu16 BFIN_MMR_16(clkdiv);
+  bu16 BFIN_MMR_16(control);
+  bu16 BFIN_MMR_16(slave_ctl);
+  bu16 BFIN_MMR_16(slave_stat);
+  bu16 BFIN_MMR_16(slave_addr);
+  bu16 BFIN_MMR_16(master_ctl);
+  bu16 BFIN_MMR_16(master_stat);
+  bu16 BFIN_MMR_16(master_addr);
+  bu16 BFIN_MMR_16(int_stat);
+  bu16 BFIN_MMR_16(int_mask);
+  bu16 BFIN_MMR_16(fifo_ctl);
+  bu16 BFIN_MMR_16(fifo_stat);
+  bu32 _pad0[20];
+  bu16 BFIN_MMR_16(xmt_data8);
+  bu16 BFIN_MMR_16(xmt_data16);
+  bu16 BFIN_MMR_16(rcv_data8);
+  bu16 BFIN_MMR_16(rcv_data16);
+};
+#define mmr_base()      offsetof(struct bfin_twi, clkdiv)
+#define mmr_offset(mmr) (offsetof(struct bfin_twi, mmr) - mmr_base())
+#define mmr_idx(mmr)    (mmr_offset (mmr) / 4)
+
+static const char * const mmr_names[] = {
+  "TWI_CLKDIV", "TWI_CONTROL", "TWI_SLAVE_CTL", "TWI_SLAVE_STAT",
+  "TWI_SLAVE_ADDR", "TWI_MASTER_CTL", "TWI_MASTER_STAT", "TWI_MASTER_ADDR",
+  "TWI_INT_STAT", "TWI_INT_MASK", "TWI_FIFO_CTL", "TWI_FIFO_STAT",
+  [mmr_idx (xmt_data8)] = "TWI_XMT_DATA8", "TWI_XMT_DATA16", "TWI_RCV_DATA8",
+  "TWI_RCV_DATA16",
+};
+#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
+
+static unsigned
+bfin_twi_io_write_buffer (struct hw *me, const void *source, int space,
+                         address_word addr, unsigned nr_bytes)
+{
+  struct bfin_twi *twi = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *valuep;
+
+  value = dv_load_2 (source);
+  mmr_off = addr - twi->base;
+  valuep = (void *)((unsigned long)twi + mmr_base() + mmr_off);
+
+  HW_TRACE_WRITE ();
+
+  dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+
+  switch (mmr_off)
+    {
+    case mmr_offset(clkdiv):
+    case mmr_offset(control):
+    case mmr_offset(slave_ctl):
+    case mmr_offset(slave_addr):
+    case mmr_offset(master_ctl):
+    case mmr_offset(master_addr):
+    case mmr_offset(int_mask):
+    case mmr_offset(fifo_ctl):
+      *valuep = value;
+      break;
+    case mmr_offset(int_stat):
+      dv_w1c_2 (valuep, value, 0);
+      break;
+    case mmr_offset(master_stat):
+      dv_w1c_2 (valuep, value, MPROG | SDASEN | SCLSEN | BUSBUSY);
+      break;
+    case mmr_offset(slave_stat):
+    case mmr_offset(fifo_stat):
+    case mmr_offset(rcv_data8):
+    case mmr_offset(rcv_data16):
+      /* These are all RO.  XXX: Does these throw error ?  */
+      break;
+    case mmr_offset(xmt_data8):
+      value &= 0xff;
+    case mmr_offset(xmt_data16):
+      twi->xmt_fifo = value;
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_twi_io_read_buffer (struct hw *me, void *dest, int space,
+                        address_word addr, unsigned nr_bytes)
+{
+  struct bfin_twi *twi = hw_data (me);
+  bu32 mmr_off;
+  bu16 *valuep;
+
+  mmr_off = addr - twi->base;
+  valuep = (void *)((unsigned long)twi + mmr_base() + mmr_off);
+
+  HW_TRACE_READ ();
+
+  dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+
+  switch (mmr_off)
+    {
+    case mmr_offset(clkdiv):
+    case mmr_offset(control):
+    case mmr_offset(slave_ctl):
+    case mmr_offset(slave_stat):
+    case mmr_offset(slave_addr):
+    case mmr_offset(master_ctl):
+    case mmr_offset(master_stat):
+    case mmr_offset(master_addr):
+    case mmr_offset(int_stat):
+    case mmr_offset(int_mask):
+    case mmr_offset(fifo_ctl):
+    case mmr_offset(fifo_stat):
+      dv_store_2 (dest, *valuep);
+      break;
+    case mmr_offset(rcv_data8):
+    case mmr_offset(rcv_data16):
+      dv_store_2 (dest, twi->rcv_fifo);
+      break;
+    case mmr_offset(xmt_data8):
+    case mmr_offset(xmt_data16):
+      /* These always read as 0.  */
+      dv_store_2 (dest, 0);
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static const struct hw_port_descriptor bfin_twi_ports[] = {
+  { "stat", 0, 0, output_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+attach_bfin_twi_regs (struct hw *me, struct bfin_twi *twi)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_TWI_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_TWI_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  twi->base = attach_address;
+}
+
+static void
+bfin_twi_finish (struct hw *me)
+{
+  struct bfin_twi *twi;
+
+  twi = HW_ZALLOC (me, struct bfin_twi);
+
+  set_hw_data (me, twi);
+  set_hw_io_read_buffer (me, bfin_twi_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_twi_io_write_buffer);
+  set_hw_ports (me, bfin_twi_ports);
+
+  attach_bfin_twi_regs (me, twi);
+}
+
+const struct hw_descriptor dv_bfin_twi_descriptor[] = {
+  {"bfin_twi", bfin_twi_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_twi.h b/sim/bfin/dv-bfin_twi.h
new file mode 100644 (file)
index 0000000..9189999
--- /dev/null
@@ -0,0 +1,38 @@
+/* Blackfin Two Wire Interface (TWI) model
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_TWI_H
+#define DV_BFIN_TWI_H
+
+/* XXX: This should be pushed into the model data.  */
+#define BFIN_MMR_TWI_SIZE      0x90
+
+/* TWI_MASTER_STAT Masks */
+#define MPROG          (1 << 0)
+#define LOSTARG                (1 << 1)
+#define ANAK           (1 << 2)
+#define DNAK           (1 << 3)
+#define BUFRDERR       (1 << 4)
+#define BUFWRERR       (1 << 5)
+#define SDASEN         (1 << 6)
+#define SCLSEN         (1 << 7)
+#define BUSBUSY                (1 << 8)
+
+#endif
diff --git a/sim/bfin/dv-bfin_uart.c b/sim/bfin/dv-bfin_uart.c
new file mode 100644 (file)
index 0000000..be9038d
--- /dev/null
@@ -0,0 +1,437 @@
+/* Blackfin Universal Asynchronous Receiver/Transmitter (UART) model.
+   For "old style" UARTs on BF53x/etc... parts.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "dv-sockser.h"
+#include "devices.h"
+#include "dv-bfin_uart.h"
+
+/* XXX: Should we bother emulating the TX/RX FIFOs ?  */
+
+/* Internal state needs to be the same as bfin_uart2.  */
+struct bfin_uart
+{
+  /* This top portion matches common dv_bfin struct.  */
+  bu32 base;
+  struct hw *dma_master;
+  bool acked;
+
+  struct hw_event *handler;
+  char saved_byte;
+  int saved_count;
+
+  /* This is aliased to DLH.  */
+  bu16 ier;
+  /* These are aliased to DLL.  */
+  bu16 thr, rbr;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu16 BFIN_MMR_16(dll);
+  bu16 BFIN_MMR_16(dlh);
+  bu16 BFIN_MMR_16(iir);
+  bu16 BFIN_MMR_16(lcr);
+  bu16 BFIN_MMR_16(mcr);
+  bu16 BFIN_MMR_16(lsr);
+  bu16 BFIN_MMR_16(msr);
+  bu16 BFIN_MMR_16(scr);
+  bu16 _pad0[2];
+  bu16 BFIN_MMR_16(gctl);
+};
+#define mmr_base()      offsetof(struct bfin_uart, dll)
+#define mmr_offset(mmr) (offsetof(struct bfin_uart, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "UART_RBR/UART_THR", "UART_IER", "UART_IIR", "UART_LCR", "UART_MCR",
+  "UART_LSR", "UART_MSR", "UART_SCR", "<INV>", "UART_GCTL",
+};
+static const char *mmr_name (struct bfin_uart *uart, bu32 idx)
+{
+  if (uart->lcr & DLAB)
+    if (idx < 2)
+      return idx == 0 ? "UART_DLL" : "UART_DLH";
+  return mmr_names[idx];
+}
+#define mmr_name(off) mmr_name (uart, (off) / 4)
+
+#ifndef HAVE_DV_SOCKSER
+# define dv_sockser_status(sd) -1
+# define dv_sockser_write(sd, byte) do { ; } while (0)
+# define dv_sockser_read(sd) 0xff
+#endif
+
+static void
+bfin_uart_poll (struct hw *me, void *data)
+{
+  struct bfin_uart *uart = data;
+  bu16 lsr;
+
+  uart->handler = NULL;
+
+  lsr = bfin_uart_get_status (me);
+  if (lsr & DR)
+    hw_port_event (me, DV_PORT_RX, 1);
+
+  bfin_uart_reschedule (me);
+}
+
+void
+bfin_uart_reschedule (struct hw *me)
+{
+  struct bfin_uart *uart = hw_data (me);
+
+  if (uart->ier & ERBFI)
+    {
+      if (!uart->handler)
+       uart->handler = hw_event_queue_schedule (me, 10000,
+                                                bfin_uart_poll, uart);
+    }
+  else
+    {
+      if (uart->handler)
+       {
+         hw_event_queue_deschedule (me, uart->handler);
+         uart->handler = NULL;
+       }
+    }
+}
+
+bu16
+bfin_uart_write_byte (struct hw *me, bu16 thr)
+{
+  unsigned char ch = thr;
+  bfin_uart_write_buffer (me, &ch, 1);
+  return thr;
+}
+
+static unsigned
+bfin_uart_io_write_buffer (struct hw *me, const void *source,
+                          int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_uart *uart = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *valuep;
+
+  value = dv_load_2 (source);
+  mmr_off = addr - uart->base;
+  valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off);
+
+  HW_TRACE_WRITE ();
+
+  dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+
+  /* XXX: All MMRs are "8bit" ... what happens to high 8bits ?  */
+  switch (mmr_off)
+    {
+    case mmr_offset(dll):
+      if (uart->lcr & DLAB)
+       uart->dll = value;
+      else
+       {
+         uart->thr = bfin_uart_write_byte (me, value);
+
+         if (uart->ier & ETBEI)
+           hw_port_event (me, DV_PORT_TX, 1);
+       }
+      break;
+    case mmr_offset(dlh):
+      if (uart->lcr & DLAB)
+       uart->dlh = value;
+      else
+       {
+         uart->ier = value;
+         bfin_uart_reschedule (me);
+       }
+      break;
+    case mmr_offset(iir):
+    case mmr_offset(lsr):
+      /* XXX: Writes are ignored ?  */
+      break;
+    case mmr_offset(lcr):
+    case mmr_offset(mcr):
+    case mmr_offset(scr):
+    case mmr_offset(gctl):
+      *valuep = value;
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+/* Switch between socket and stdin on the fly.  */
+bu16
+bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bool *fresh)
+{
+  SIM_DESC sd = hw_system (me);
+  struct bfin_uart *uart = hw_data (me);
+  int status = dv_sockser_status (sd);
+  bool _fresh;
+
+  /* NB: The "uart" here may only use interal state.  */
+
+  if (!fresh)
+    fresh = &_fresh;
+
+  *fresh = false;
+  if (status & DV_SOCKSER_DISCONNECTED)
+    {
+      if (uart->saved_count > 0)
+       {
+         *fresh = true;
+         rbr = uart->saved_byte;
+         --uart->saved_count;
+       }
+      else
+       {
+         char byte;
+         int ret = sim_io_poll_read (sd, 0/*STDIN*/, &byte, 1);
+         if (ret > 0)
+           {
+             *fresh = true;
+             rbr = byte;
+           }
+       }
+    }
+  else
+    rbr = dv_sockser_read (sd);
+
+  return rbr;
+}
+
+bu16
+bfin_uart_get_status (struct hw *me)
+{
+  SIM_DESC sd = hw_system (me);
+  struct bfin_uart *uart = hw_data (me);
+  int status = dv_sockser_status (sd);
+  bu16 lsr = 0;
+
+  if (status & DV_SOCKSER_DISCONNECTED)
+    {
+      if (uart->saved_count <= 0)
+       uart->saved_count = sim_io_poll_read (sd, 0/*STDIN*/,
+                                             &uart->saved_byte, 1);
+      lsr |= TEMT | THRE | (uart->saved_count > 0 ? DR : 0);
+    }
+  else
+    lsr |= (status & DV_SOCKSER_INPUT_EMPTY ? 0 : DR) |
+                (status & DV_SOCKSER_OUTPUT_EMPTY ? TEMT | THRE : 0);
+
+  return lsr;
+}
+
+static unsigned
+bfin_uart_io_read_buffer (struct hw *me, void *dest,
+                         int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_uart *uart = hw_data (me);
+  bu32 mmr_off;
+  bu16 *valuep;
+
+  mmr_off = addr - uart->base;
+  valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off);
+
+  HW_TRACE_READ ();
+
+  dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+
+  switch (mmr_off)
+    {
+    case mmr_offset(dll):
+      if (uart->lcr & DLAB)
+       dv_store_2 (dest, uart->dll);
+      else
+       {
+         uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, NULL);
+         dv_store_2 (dest, uart->rbr);
+       }
+      break;
+    case mmr_offset(dlh):
+      if (uart->lcr & DLAB)
+       dv_store_2 (dest, uart->dlh);
+      else
+       dv_store_2 (dest, uart->ier);
+      break;
+    case mmr_offset(lsr):
+      /* XXX: Reads are destructive on most parts, but not all ...  */
+      uart->lsr |= bfin_uart_get_status (me);
+      dv_store_2 (dest, *valuep);
+      uart->lsr = 0;
+      break;
+    case mmr_offset(iir):
+      /* XXX: Reads are destructive ...  */
+    case mmr_offset(lcr):
+    case mmr_offset(mcr):
+    case mmr_offset(scr):
+    case mmr_offset(gctl):
+      dv_store_2 (dest, *valuep);
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+unsigned
+bfin_uart_read_buffer (struct hw *me, unsigned char *buffer, unsigned nr_bytes)
+{
+  SIM_DESC sd = hw_system (me);
+  struct bfin_uart *uart = hw_data (me);
+  int status = dv_sockser_status (sd);
+  unsigned i = 0;
+
+  if (status & DV_SOCKSER_DISCONNECTED)
+    {
+      int ret;
+
+      while (uart->saved_count > 0 && i < nr_bytes)
+       {
+         buffer[i++] = uart->saved_byte;
+         --uart->saved_count;
+       }
+
+      ret = sim_io_poll_read (sd, 0/*STDIN*/, (char *) buffer, nr_bytes - i);
+      if (ret > 0)
+       i += ret;
+    }
+  else
+    buffer[i++] = dv_sockser_read (sd);
+
+  return i;
+}
+
+static unsigned
+bfin_uart_dma_read_buffer (struct hw *me, void *dest, int space,
+                          unsigned_word addr, unsigned nr_bytes)
+{
+  HW_TRACE_DMA_READ ();
+  return bfin_uart_read_buffer (me, dest, nr_bytes);
+}
+
+unsigned
+bfin_uart_write_buffer (struct hw *me, const unsigned char *buffer,
+                       unsigned nr_bytes)
+{
+  SIM_DESC sd = hw_system (me);
+  int status = dv_sockser_status (sd);
+
+  if (status & DV_SOCKSER_DISCONNECTED)
+    {
+      sim_io_write_stdout (sd, (const char *) buffer, nr_bytes);
+      sim_io_flush_stdout (sd);
+    }
+  else
+    {
+      /* Normalize errors to a value of 0.  */
+      int ret = dv_sockser_write_buffer (sd, buffer, nr_bytes);
+      nr_bytes = CLAMP (ret, 0, nr_bytes);
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_uart_dma_write_buffer (struct hw *me, const void *source,
+                           int space, unsigned_word addr,
+                           unsigned nr_bytes,
+                           int violate_read_only_section)
+{
+  struct bfin_uart *uart = hw_data (me);
+  unsigned ret;
+
+  HW_TRACE_DMA_WRITE ();
+
+  ret = bfin_uart_write_buffer (me, source, nr_bytes);
+
+  if (ret == nr_bytes && (uart->ier & ETBEI))
+    hw_port_event (me, DV_PORT_TX, 1);
+
+  return ret;
+}
+
+static const struct hw_port_descriptor bfin_uart_ports[] = {
+  { "tx",   DV_PORT_TX,   0, output_port, },
+  { "rx",   DV_PORT_RX,   0, output_port, },
+  { "stat", DV_PORT_STAT, 0, output_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+attach_bfin_uart_regs (struct hw *me, struct bfin_uart *uart)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_UART_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_UART_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  uart->base = attach_address;
+}
+
+static void
+bfin_uart_finish (struct hw *me)
+{
+  struct bfin_uart *uart;
+
+  uart = HW_ZALLOC (me, struct bfin_uart);
+
+  set_hw_data (me, uart);
+  set_hw_io_read_buffer (me, bfin_uart_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_uart_io_write_buffer);
+  set_hw_dma_read_buffer (me, bfin_uart_dma_read_buffer);
+  set_hw_dma_write_buffer (me, bfin_uart_dma_write_buffer);
+  set_hw_ports (me, bfin_uart_ports);
+
+  attach_bfin_uart_regs (me, uart);
+
+  /* Initialize the UART.  */
+  uart->dll = 0x0001;
+  uart->iir = 0x0001;
+  uart->lsr = 0x0060;
+}
+
+const struct hw_descriptor dv_bfin_uart_descriptor[] = {
+  {"bfin_uart", bfin_uart_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_uart.h b/sim/bfin/dv-bfin_uart.h
new file mode 100644 (file)
index 0000000..1d144d4
--- /dev/null
@@ -0,0 +1,49 @@
+/* Blackfin Universal Asynchronous Receiver/Transmitter (UART) model.
+   For "old style" UARTs on BF53x/etc... parts.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_UART_H
+#define DV_BFIN_UART_H
+
+/* XXX: This should be pushed into the model data.  */
+#define BFIN_MMR_UART_SIZE     0x30
+
+struct bfin_uart;
+bu16 bfin_uart_get_next_byte (struct hw *, bu16, bool *fresh);
+bu16 bfin_uart_write_byte (struct hw *, bu16);
+bu16 bfin_uart_get_status (struct hw *);
+unsigned bfin_uart_write_buffer (struct hw *, const unsigned char *, unsigned);
+unsigned bfin_uart_read_buffer (struct hw *, unsigned char *, unsigned);
+void bfin_uart_reschedule (struct hw *);
+
+/* UART_LCR */
+#define DLAB (1 << 7)
+
+/* UART_LSR */
+#define TEMT (1 << 6)
+#define THRE (1 << 5)
+#define DR (1 << 0)
+
+/* UART_IER */
+#define ERBFI (1 << 0)
+#define ETBEI (1 << 1)
+#define ELSI  (1 << 2)
+
+#endif
diff --git a/sim/bfin/dv-bfin_uart2.c b/sim/bfin/dv-bfin_uart2.c
new file mode 100644 (file)
index 0000000..dd09c5e
--- /dev/null
@@ -0,0 +1,258 @@
+/* Blackfin Universal Asynchronous Receiver/Transmitter (UART) model.
+   For "new style" UARTs on BF50x/BF54x parts.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_uart2.h"
+
+/* XXX: Should we bother emulating the TX/RX FIFOs ?  */
+
+/* Internal state needs to be the same as bfin_uart.  */
+struct bfin_uart
+{
+  /* This top portion matches common dv_bfin struct.  */
+  bu32 base;
+  struct hw *dma_master;
+  bool acked;
+
+  struct hw_event *handler;
+  char saved_byte;
+  int saved_count;
+
+  /* Accessed indirectly by ier_{set,clear}.  */
+  bu16 ier;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu16 BFIN_MMR_16(dll);
+  bu16 BFIN_MMR_16(dlh);
+  bu16 BFIN_MMR_16(gctl);
+  bu16 BFIN_MMR_16(lcr);
+  bu16 BFIN_MMR_16(mcr);
+  bu16 BFIN_MMR_16(lsr);
+  bu16 BFIN_MMR_16(msr);
+  bu16 BFIN_MMR_16(scr);
+  bu16 BFIN_MMR_16(ier_set);
+  bu16 BFIN_MMR_16(ier_clear);
+  bu16 BFIN_MMR_16(thr);
+  bu16 BFIN_MMR_16(rbr);
+};
+#define mmr_base()      offsetof(struct bfin_uart, dll)
+#define mmr_offset(mmr) (offsetof(struct bfin_uart, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "UART_DLL", "UART_DLH", "UART_GCTL", "UART_LCR", "UART_MCR", "UART_LSR",
+  "UART_MSR", "UART_SCR", "UART_IER_SET", "UART_IER_CLEAR", "UART_THR",
+  "UART_RBR",
+};
+#define mmr_name(off) mmr_names[(off) / 4]
+
+static unsigned
+bfin_uart_io_write_buffer (struct hw *me, const void *source,
+                          int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_uart *uart = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *valuep;
+
+  value = dv_load_2 (source);
+  mmr_off = addr - uart->base;
+  valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off);
+
+  HW_TRACE_WRITE ();
+
+  dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
+
+  /* XXX: All MMRs are "8bit" ... what happens to high 8bits ?  */
+
+  switch (mmr_off)
+    {
+    case mmr_offset(thr):
+      uart->thr = bfin_uart_write_byte (me, value);
+      if (uart->ier & ETBEI)
+       hw_port_event (me, DV_PORT_TX, 1);
+      break;
+    case mmr_offset(ier_set):
+      uart->ier |= value;
+      break;
+    case mmr_offset(ier_clear):
+      dv_w1c_2 (&uart->ier, value, 0);
+      break;
+    case mmr_offset(lsr):
+      dv_w1c_2 (valuep, value, TEMT | THRE | DR);
+      break;
+    case mmr_offset(rbr):
+      /* XXX: Writes are ignored ?  */
+      break;
+    case mmr_offset(msr):
+      dv_w1c_2 (valuep, value, SCTS);
+      break;
+    case mmr_offset(dll):
+    case mmr_offset(dlh):
+    case mmr_offset(gctl):
+    case mmr_offset(lcr):
+    case mmr_offset(mcr):
+    case mmr_offset(scr):
+      *valuep = value;
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_uart_io_read_buffer (struct hw *me, void *dest,
+                         int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_uart *uart = hw_data (me);
+  bu32 mmr_off;
+  bu16 *valuep;
+
+  mmr_off = addr - uart->base;
+  valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off);
+
+  HW_TRACE_READ ();
+
+  dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+
+  switch (mmr_off)
+    {
+    case mmr_offset(rbr):
+      uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, NULL);
+      dv_store_2 (dest, uart->rbr);
+      break;
+    case mmr_offset(ier_set):
+    case mmr_offset(ier_clear):
+      dv_store_2 (dest, uart->ier);
+      bfin_uart_reschedule (me);
+      break;
+    case mmr_offset(lsr):
+      uart->lsr |= bfin_uart_get_status (me);
+    case mmr_offset(thr):
+    case mmr_offset(msr):
+    case mmr_offset(dll):
+    case mmr_offset(dlh):
+    case mmr_offset(gctl):
+    case mmr_offset(lcr):
+    case mmr_offset(mcr):
+    case mmr_offset(scr):
+      dv_store_2 (dest, *valuep);
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_uart_dma_read_buffer (struct hw *me, void *dest, int space,
+                          unsigned_word addr, unsigned nr_bytes)
+{
+  HW_TRACE_DMA_READ ();
+  return bfin_uart_read_buffer (me, dest, nr_bytes);
+}
+
+static unsigned
+bfin_uart_dma_write_buffer (struct hw *me, const void *source,
+                           int space, unsigned_word addr,
+                           unsigned nr_bytes,
+                           int violate_read_only_section)
+{
+  struct bfin_uart *uart = hw_data (me);
+  unsigned ret;
+
+  HW_TRACE_DMA_WRITE ();
+
+  ret = bfin_uart_write_buffer (me, source, nr_bytes);
+
+  if (ret == nr_bytes && (uart->ier & ETBEI))
+    hw_port_event (me, DV_PORT_TX, 1);
+
+  return ret;
+}
+
+static const struct hw_port_descriptor bfin_uart_ports[] = {
+  { "tx",   DV_PORT_TX,   0, output_port, },
+  { "rx",   DV_PORT_RX,   0, output_port, },
+  { "stat", DV_PORT_STAT, 0, output_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+attach_bfin_uart_regs (struct hw *me, struct bfin_uart *uart)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_UART2_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_UART2_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  uart->base = attach_address;
+}
+
+static void
+bfin_uart_finish (struct hw *me)
+{
+  struct bfin_uart *uart;
+
+  uart = HW_ZALLOC (me, struct bfin_uart);
+
+  set_hw_data (me, uart);
+  set_hw_io_read_buffer (me, bfin_uart_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_uart_io_write_buffer);
+  set_hw_dma_read_buffer (me, bfin_uart_dma_read_buffer);
+  set_hw_dma_write_buffer (me, bfin_uart_dma_write_buffer);
+  set_hw_ports (me, bfin_uart_ports);
+
+  attach_bfin_uart_regs (me, uart);
+
+  /* Initialize the UART.  */
+  uart->dll = 0x0001;
+  uart->lsr = 0x0060;
+}
+
+const struct hw_descriptor dv_bfin_uart2_descriptor[] = {
+  {"bfin_uart2", bfin_uart_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_uart2.h b/sim/bfin/dv-bfin_uart2.h
new file mode 100644 (file)
index 0000000..f8269a4
--- /dev/null
@@ -0,0 +1,33 @@
+/* Blackfin Universal Asynchronous Receiver/Transmitter (UART) model.
+   For "new style" UARTs on BF50x/BF54x parts.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_UART2_H
+#define DV_BFIN_UART2_H
+
+#include "dv-bfin_uart.h"
+
+/* XXX: This should be pushed into the model data.  */
+#define BFIN_MMR_UART2_SIZE    0x30
+
+/* UART_MSR */
+#define SCTS (1 << 0)
+
+#endif
diff --git a/sim/bfin/dv-bfin_wdog.c b/sim/bfin/dv-bfin_wdog.c
new file mode 100644 (file)
index 0000000..4aada47
--- /dev/null
@@ -0,0 +1,206 @@
+/* Blackfin Watchdog (WDOG) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "dv-sockser.h"
+#include "devices.h"
+#include "dv-bfin_wdog.h"
+
+/* XXX: Should we bother emulating the TX/RX FIFOs ?  */
+
+struct bfin_wdog
+{
+  bu32 base;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu16 BFIN_MMR_16(ctl);
+  bu32 cnt, stat;
+};
+#define mmr_base()      offsetof(struct bfin_wdog, ctl)
+#define mmr_offset(mmr) (offsetof(struct bfin_wdog, mmr) - mmr_base())
+
+static const char * const mmr_names[] = {
+  "WDOG_CTL", "WDOG_CNT", "WDOG_STAT",
+};
+#define mmr_name(off) mmr_names[(off) / 4]
+
+static bool
+bfin_wdog_enabled (struct bfin_wdog *wdog)
+{
+  return ((wdog->ctl & WDEN) != WDDIS);
+}
+
+static unsigned
+bfin_wdog_io_write_buffer (struct hw *me, const void *source,
+                          int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_wdog *wdog = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  if (nr_bytes == 4)
+    value = dv_load_4 (source);
+  else
+    value = dv_load_2 (source);
+
+  mmr_off = addr - wdog->base;
+  valuep = (void *)((unsigned long)wdog + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_WRITE ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(ctl):
+      dv_w1c_2_partial (value16p, value, WDRO);
+      /* XXX: Should enable an event here to handle timeouts.  */
+      break;
+
+    case mmr_offset(cnt):
+      /* Writes are discarded when enabeld.  */
+      if (!bfin_wdog_enabled (wdog))
+       {
+         *value32p = value;
+         /* Writes to CNT preloads the STAT.  */
+         wdog->stat = wdog->cnt;
+       }
+      break;
+
+    case mmr_offset(stat):
+      /* When enabled, writes to STAT reload the counter.  */
+      if (bfin_wdog_enabled (wdog))
+       wdog->stat = wdog->cnt;
+      /* XXX: When disabled, are writes just ignored ?  */
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_wdog_io_read_buffer (struct hw *me, void *dest,
+                         int space, address_word addr, unsigned nr_bytes)
+{
+  struct bfin_wdog *wdog = hw_data (me);
+  bu32 mmr_off;
+  bu16 *value16p;
+  bu32 *value32p;
+  void *valuep;
+
+  mmr_off = addr - wdog->base;
+  valuep = (void *)((unsigned long)wdog + mmr_base() + mmr_off);
+  value16p = valuep;
+  value32p = valuep;
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(ctl):
+      dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
+      dv_store_2 (dest, *value16p);
+      break;
+
+    case mmr_offset(cnt):
+    case mmr_offset(stat):
+      dv_store_4 (dest, *value32p);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static const struct hw_port_descriptor bfin_wdog_ports[] = {
+  { "reset", WDEV_RESET, 0, output_port, },
+  { "nmi",   WDEV_NMI,   0, output_port, },
+  { "gpi",   WDEV_GPI,   0, output_port, },
+  { NULL, 0, 0, 0, },
+};
+
+static void
+bfin_wdog_port_event (struct hw *me, int my_port, struct hw *source,
+                     int source_port, int level)
+{
+  struct bfin_wdog *wdog = hw_data (me);
+  bu16 wdev;
+
+  wdog->ctl |= WDRO;
+  wdev = (wdog->ctl & WDEV);
+  if (wdev != WDEV_NONE)
+    hw_port_event (me, wdev, 1);
+}
+
+static void
+attach_bfin_wdog_regs (struct hw *me, struct bfin_wdog *wdog)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_MMR_WDOG_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_WDOG_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  wdog->base = attach_address;
+}
+
+static void
+bfin_wdog_finish (struct hw *me)
+{
+  struct bfin_wdog *wdog;
+
+  wdog = HW_ZALLOC (me, struct bfin_wdog);
+
+  set_hw_data (me, wdog);
+  set_hw_io_read_buffer (me, bfin_wdog_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_wdog_io_write_buffer);
+  set_hw_ports (me, bfin_wdog_ports);
+  set_hw_port_event (me, bfin_wdog_port_event);
+
+  attach_bfin_wdog_regs (me, wdog);
+
+  /* Initialize the Watchdog.  */
+  wdog->ctl = WDDIS;
+}
+
+const struct hw_descriptor dv_bfin_wdog_descriptor[] = {
+  {"bfin_wdog", bfin_wdog_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_wdog.h b/sim/bfin/dv-bfin_wdog.h
new file mode 100644 (file)
index 0000000..9be602d
--- /dev/null
@@ -0,0 +1,36 @@
+/* Blackfin Watchdog (WDOG) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_WDOG_H
+#define DV_BFIN_WDOG_H
+
+#define BFIN_MMR_WDOG_SIZE     (4 * 3)
+
+/* WDOG_CTL */
+#define WDEV            0x0006  /* event generated on roll over */
+#define WDEV_RESET      0x0000  /* generate reset event on roll over */
+#define WDEV_NMI        0x0002  /* generate NMI event on roll over */
+#define WDEV_GPI        0x0004  /* generate GP IRQ on roll over */
+#define WDEV_NONE       0x0006  /* no event on roll over */
+#define WDEN            0x0FF0  /* enable watchdog */
+#define WDDIS           0x0AD0  /* disable watchdog */
+#define WDRO            0x8000  /* watchdog rolled over latch */
+
+#endif
diff --git a/sim/bfin/dv-bfin_wp.c b/sim/bfin/dv-bfin_wp.c
new file mode 100644 (file)
index 0000000..efa0804
--- /dev/null
@@ -0,0 +1,188 @@
+/* Blackfin Watchpoint (WP) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+#include "dv-bfin_wp.h"
+
+/* XXX: This is mostly a stub.  */
+
+#define WPI_NUM 6      /* 6 instruction watchpoints.  */
+#define WPD_NUM 2      /* 2 data watchpoints.  */
+
+struct bfin_wp
+{
+  bu32 base;
+
+  /* Order after here is important -- matches hardware MMR layout.  */
+  bu32 iactl;
+  bu32 _pad0[15];
+  bu32 ia[WPI_NUM];
+  bu32 _pad1[16 - WPI_NUM];
+  bu32 iacnt[WPI_NUM];
+  bu32 _pad2[32 - WPI_NUM];
+
+  bu32 dactl;
+  bu32 _pad3[15];
+  bu32 da[WPD_NUM];
+  bu32 _pad4[16 - WPD_NUM];
+  bu32 dacnt[WPD_NUM];
+  bu32 _pad5[32 - WPD_NUM];
+
+  bu32 stat;
+};
+#define mmr_base()      offsetof(struct bfin_wp, iactl)
+#define mmr_offset(mmr) (offsetof(struct bfin_wp, mmr) - mmr_base())
+#define mmr_idx(mmr)    (mmr_offset (mmr) / 4)
+
+static const char * const mmr_names[] = {
+  [mmr_idx (iactl)] = "WPIACTL",
+  [mmr_idx (ia)]    = "WPIA0", "WPIA1", "WPIA2", "WPIA3", "WPIA4", "WPIA5",
+  [mmr_idx (iacnt)] = "WPIACNT0", "WPIACNT1", "WPIACNT2",
+                     "WPIACNT3", "WPIACNT4", "WPIACNT5",
+  [mmr_idx (dactl)] = "WPDACTL",
+  [mmr_idx (da)]    = "WPDA0", "WPDA1", "WPDA2", "WPDA3", "WPDA4", "WPDA5",
+  [mmr_idx (dacnt)] = "WPDACNT0", "WPDACNT1", "WPDACNT2",
+                     "WPDACNT3", "WPDACNT4", "WPDACNT5",
+  [mmr_idx (stat)]  = "WPSTAT",
+};
+#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
+
+static unsigned
+bfin_wp_io_write_buffer (struct hw *me, const void *source, int space,
+                        address_word addr, unsigned nr_bytes)
+{
+  struct bfin_wp *wp = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu32 *valuep;
+
+  value = dv_load_4 (source);
+  mmr_off = addr - wp->base;
+  valuep = (void *)((unsigned long)wp + mmr_base() + mmr_off);
+
+  HW_TRACE_WRITE ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(iactl):
+    case mmr_offset(ia[0]) ... mmr_offset(ia[WPI_NUM - 1]):
+    case mmr_offset(iacnt[0]) ... mmr_offset(iacnt[WPI_NUM - 1]):
+    case mmr_offset(dactl):
+    case mmr_offset(da[0]) ... mmr_offset(da[WPD_NUM - 1]):
+    case mmr_offset(dacnt[0]) ... mmr_offset(dacnt[WPD_NUM - 1]):
+      *valuep = value;
+      break;
+    case mmr_offset(stat):
+      /* Yes, the hardware is this dumb -- clear all bits on any write.  */
+      *valuep = 0;
+      break;
+    default:
+      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+bfin_wp_io_read_buffer (struct hw *me, void *dest, int space,
+                       address_word addr, unsigned nr_bytes)
+{
+  struct bfin_wp *wp = hw_data (me);
+  bu32 mmr_off;
+  bu32 value;
+  bu32 *valuep;
+
+  mmr_off = addr - wp->base;
+  valuep = (void *)((unsigned long)wp + mmr_base() + mmr_off);
+
+  HW_TRACE_READ ();
+
+  switch (mmr_off)
+    {
+    case mmr_offset(iactl):
+    case mmr_offset(ia[0]) ... mmr_offset(ia[WPI_NUM - 1]):
+    case mmr_offset(iacnt[0]) ... mmr_offset(iacnt[WPI_NUM - 1]):
+    case mmr_offset(dactl):
+    case mmr_offset(da[0]) ... mmr_offset(da[WPD_NUM - 1]):
+    case mmr_offset(dacnt[0]) ... mmr_offset(dacnt[WPD_NUM - 1]):
+    case mmr_offset(stat):
+      value = *valuep;
+      break;
+    default:
+      while (1) /* Core MMRs -> exception -> doesn't return.  */
+       dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
+      break;
+    }
+
+  dv_store_4 (dest, value);
+
+  return nr_bytes;
+}
+
+static void
+attach_bfin_wp_regs (struct hw *me, struct bfin_wp *wp)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != BFIN_COREMMR_WP_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", BFIN_COREMMR_WP_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  wp->base = attach_address;
+}
+
+static void
+bfin_wp_finish (struct hw *me)
+{
+  struct bfin_wp *wp;
+
+  wp = HW_ZALLOC (me, struct bfin_wp);
+
+  set_hw_data (me, wp);
+  set_hw_io_read_buffer (me, bfin_wp_io_read_buffer);
+  set_hw_io_write_buffer (me, bfin_wp_io_write_buffer);
+
+  attach_bfin_wp_regs (me, wp);
+}
+
+const struct hw_descriptor dv_bfin_wp_descriptor[] = {
+  {"bfin_wp", bfin_wp_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/dv-bfin_wp.h b/sim/bfin/dv-bfin_wp.h
new file mode 100644 (file)
index 0000000..f6c0d80
--- /dev/null
@@ -0,0 +1,27 @@
+/* Blackfin Watchpoint (WP) model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DV_BFIN_WP_H
+#define DV_BFIN_WP_H
+
+#define BFIN_COREMMR_WP_BASE   0xFFE07000
+#define BFIN_COREMMR_WP_SIZE   0x204
+
+#endif
diff --git a/sim/bfin/dv-eth_phy.c b/sim/bfin/dv-eth_phy.c
new file mode 100644 (file)
index 0000000..59eaece
--- /dev/null
@@ -0,0 +1,206 @@
+/* Ethernet Physical Receiver model.
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "devices.h"
+
+#ifdef HAVE_LINUX_MII_H
+
+/* Workaround old/broken linux headers.  */
+#define _LINUX_TYPES_H
+#define __u16 unsigned short
+#include <linux/mii.h>
+
+#define REG_PHY_SIZE 0x20
+
+struct eth_phy
+{
+  bu32 base;
+  bu16 regs[REG_PHY_SIZE];
+};
+#define reg_base()      offsetof(struct eth_phy, regs[0])
+#define reg_offset(reg) (offsetof(struct eth_phy, reg) - reg_base())
+#define reg_idx(reg)    (reg_offset (reg) / 4)
+
+static const char * const reg_names[] = {
+  [MII_BMCR       ] = "MII_BMCR",
+  [MII_BMSR       ] = "MII_BMSR",
+  [MII_PHYSID1    ] = "MII_PHYSID1",
+  [MII_PHYSID2    ] = "MII_PHYSID2",
+  [MII_ADVERTISE  ] = "MII_ADVERTISE",
+  [MII_LPA        ] = "MII_LPA",
+  [MII_EXPANSION  ] = "MII_EXPANSION",
+#ifdef MII_CTRL1000
+  [MII_CTRL1000   ] = "MII_CTRL1000",
+#endif
+#ifdef MII_STAT1000
+  [MII_STAT1000   ] = "MII_STAT1000",
+#endif
+#ifdef MII_ESTATUS
+  [MII_ESTATUS    ] = "MII_ESTATUS",
+#endif
+  [MII_DCOUNTER   ] = "MII_DCOUNTER",
+  [MII_FCSCOUNTER ] = "MII_FCSCOUNTER",
+  [MII_NWAYTEST   ] = "MII_NWAYTEST",
+  [MII_RERRCOUNTER] = "MII_RERRCOUNTER",
+  [MII_SREVISION  ] = "MII_SREVISION",
+  [MII_RESV1      ] = "MII_RESV1",
+  [MII_LBRERROR   ] = "MII_LBRERROR",
+  [MII_PHYADDR    ] = "MII_PHYADDR",
+  [MII_RESV2      ] = "MII_RESV2",
+  [MII_TPISTATUS  ] = "MII_TPISTATUS",
+  [MII_NCONFIG    ] = "MII_NCONFIG",
+};
+#define mmr_name(off) (reg_names[off] ? : "<INV>")
+#define mmr_off reg_off
+
+static unsigned
+eth_phy_io_write_buffer (struct hw *me, const void *source,
+                        int space, address_word addr, unsigned nr_bytes)
+{
+  struct eth_phy *phy = hw_data (me);
+  bu16 reg_off;
+  bu16 value;
+  bu16 *valuep;
+
+  value = dv_load_2 (source);
+
+  reg_off = addr - phy->base;
+  valuep = (void *)((unsigned long)phy + reg_base() + reg_off);
+
+  HW_TRACE_WRITE ();
+
+  switch (reg_off)
+    {
+    case MII_BMCR:
+      *valuep = value;
+      break;
+    case MII_PHYSID1:
+    case MII_PHYSID2:
+      /* Discard writes to these.  */
+      break;
+    default:
+      /* XXX: Discard writes to unknown regs ?  */
+      *valuep = value;
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static unsigned
+eth_phy_io_read_buffer (struct hw *me, void *dest,
+                       int space, address_word addr, unsigned nr_bytes)
+{
+  struct eth_phy *phy = hw_data (me);
+  bu16 reg_off;
+  bu16 *valuep;
+
+  reg_off = addr - phy->base;
+  valuep = (void *)((unsigned long)phy + reg_base() + reg_off);
+
+  HW_TRACE_READ ();
+
+  switch (reg_off)
+    {
+    case MII_BMCR:
+      dv_store_2 (dest, *valuep);
+      break;
+    case MII_BMSR:
+      /* XXX: Let people control this ?  */
+      *valuep = BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | BMSR_10HALF |
+               BMSR_ANEGCOMPLETE | BMSR_ANEGCAPABLE | BMSR_LSTATUS;
+      dv_store_2 (dest, *valuep);
+      break;
+    case MII_LPA:
+      /* XXX: Let people control this ?  */
+      *valuep = LPA_100FULL | LPA_100HALF | LPA_10FULL | LPA_10HALF;
+      dv_store_2 (dest, *valuep);
+      break;
+    default:
+      dv_store_2 (dest, *valuep);
+      break;
+    }
+
+  return nr_bytes;
+}
+
+static void
+attach_eth_phy_regs (struct hw *me, struct eth_phy *phy)
+{
+  address_word attach_address;
+  int attach_space;
+  unsigned attach_size;
+  reg_property_spec reg;
+
+  if (hw_find_property (me, "reg") == NULL)
+    hw_abort (me, "Missing \"reg\" property");
+
+  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+    hw_abort (me, "\"reg\" property must contain three addr/size entries");
+
+  hw_unit_address_to_attach_address (hw_parent (me),
+                                    &reg.address,
+                                    &attach_space, &attach_address, me);
+  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
+
+  if (attach_size != REG_PHY_SIZE)
+    hw_abort (me, "\"reg\" size must be %#x", REG_PHY_SIZE);
+
+  hw_attach_address (hw_parent (me),
+                    0, attach_space, attach_address, attach_size, me);
+
+  phy->base = attach_address;
+}
+
+static void
+eth_phy_finish (struct hw *me)
+{
+  struct eth_phy *phy;
+
+  phy = HW_ZALLOC (me, struct eth_phy);
+
+  set_hw_data (me, phy);
+  set_hw_io_read_buffer (me, eth_phy_io_read_buffer);
+  set_hw_io_write_buffer (me, eth_phy_io_write_buffer);
+
+  attach_eth_phy_regs (me, phy);
+
+  /* Initialize the PHY.  */
+  phy->regs[MII_PHYSID1] = 0;    /* Unassigned Vendor */
+  phy->regs[MII_PHYSID2] = 0xAD; /* Product */
+}
+
+#else
+
+static void
+eth_phy_finish (struct hw *me)
+{
+  HW_TRACE ((me, "No linux/mii.h support found"));
+}
+
+#endif
+
+const struct hw_descriptor dv_eth_phy_descriptor[] = {
+  {"eth_phy", eth_phy_finish,},
+  {NULL, NULL},
+};
diff --git a/sim/bfin/gui.c b/sim/bfin/gui.c
new file mode 100644 (file)
index 0000000..65f3735
--- /dev/null
@@ -0,0 +1,286 @@
+/* Blackfin GUI (SDL) helper code
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#ifdef HAVE_SDL
+# include <SDL.h>
+#endif
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+#endif
+
+#include "libiberty.h"
+#include "gui.h"
+
+#ifdef HAVE_SDL
+
+static struct {
+  void *handle;
+  int (*Init) (Uint32 flags);
+  void (*Quit) (void);
+  SDL_Surface *(*SetVideoMode) (int width, int height, int bpp, Uint32 flags);
+  void (*WM_SetCaption) (const char *title, const char *icon);
+  int (*ShowCursor) (int toggle);
+  int (*LockSurface) (SDL_Surface *surface);
+  void (*UnlockSurface) (SDL_Surface *surface);
+  void (*GetRGB) (Uint32 pixel, const SDL_PixelFormat * const fmt, Uint8 *r, Uint8 *g, Uint8 *b);
+  Uint32 (*MapRGB) (const SDL_PixelFormat * const format, const Uint8 r, const Uint8 g, const Uint8 b);
+  void (*UpdateRect) (SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h);
+} sdl;
+
+static const char * const sdl_syms[] = {
+  "SDL_Init",
+  "SDL_Quit",
+  "SDL_SetVideoMode",
+  "SDL_WM_SetCaption",
+  "SDL_ShowCursor",
+  "SDL_LockSurface",
+  "SDL_UnlockSurface",
+  "SDL_GetRGB",
+  "SDL_MapRGB",
+  "SDL_UpdateRect",
+};
+
+struct gui_state {
+  SDL_Surface *screen;
+  const SDL_PixelFormat *format;
+  int throttle, throttle_limit;
+  enum gui_color color;
+  int curr_line;
+};
+
+/* Load the SDL lib on the fly to avoid hard linking against it.  */
+static int
+bfin_gui_sdl_setup (void)
+{
+  int i;
+  uintptr_t **funcs;
+
+  if (sdl.handle)
+    return 0;
+
+  sdl.handle = dlopen ("libSDL-1.2.so.0", RTLD_LAZY);
+  if (sdl.handle == NULL)
+    return -1;
+
+  funcs = (void *) &sdl.Init;
+  for (i = 0; i < ARRAY_SIZE (sdl_syms); ++i)
+    {
+      funcs[i] = dlsym (sdl.handle, sdl_syms[i]);
+      if (funcs[i] == NULL)
+       {
+         dlclose (sdl.handle);
+         sdl.handle = NULL;
+         return -1;
+       }
+    }
+
+  return 0;
+}
+
+static const SDL_PixelFormat *bfin_gui_color_format (enum gui_color color);
+
+void *
+bfin_gui_setup (void *state, int enabled, int width, int height,
+               enum gui_color color)
+{
+  if (bfin_gui_sdl_setup ())
+    return NULL;
+
+  /* Create an SDL window if enabled and we don't have one yet.  */
+  if (enabled && !state)
+    {
+      struct gui_state *gui = xmalloc (sizeof (*gui));
+      if (!gui)
+       return NULL;
+
+      if (sdl.Init (SDL_INIT_VIDEO))
+       goto error;
+
+      gui->color = color;
+      gui->format = bfin_gui_color_format (gui->color);
+      gui->screen = sdl.SetVideoMode (width, height, 32,
+                                     SDL_ANYFORMAT|SDL_HWSURFACE);
+      if (!gui->screen)
+       {
+         sdl.Quit();
+         goto error;
+       }
+
+      sdl.WM_SetCaption ("GDB Blackfin Simulator", NULL);
+      sdl.ShowCursor (0);
+      gui->curr_line = 0;
+      gui->throttle = 0;
+      gui->throttle_limit = 0xf; /* XXX: let people control this ?  */
+      return gui;
+
+ error:
+      free (gui);
+      return NULL;
+    }
+
+  /* Else break down a window if disabled and we had one.  */
+  else if (!enabled && state)
+    {
+      sdl.Quit();
+      free (state);
+      return NULL;
+    }
+
+  /* Retain existing state, whatever that may be.  */
+  return state;
+}
+
+static int
+SDL_ConvertBlitLineFrom (const Uint8 *src, const SDL_PixelFormat * const format,
+                        SDL_Surface *dst, int dsty)
+{
+  Uint8 r, g, b;
+  Uint32 *pixels;
+  unsigned i, j;
+
+  if (SDL_MUSTLOCK (dst))
+    if (sdl.LockSurface (dst))
+      return 1;
+
+  pixels = dst->pixels;
+  pixels += (dsty * dst->pitch / 4);
+
+  for (i = 0; i < dst->w; ++i)
+    {
+      /* Exract the packed source pixel; RGB or BGR.  */
+      Uint32 pix = 0;
+      for (j = 0; j < format->BytesPerPixel; ++j)
+       if (format->Rshift)
+         pix = (pix << 8) | src[j];
+       else
+         pix = pix | ((Uint32)src[j] << (j * 8));
+
+      /* Unpack the source pixel into its components.  */
+      sdl.GetRGB (pix, format, &r, &g, &b);
+      /* Translate into the screen pixel format.  */
+      *pixels++ = sdl.MapRGB (dst->format, r, g, b);
+
+      src += format->BytesPerPixel;
+    }
+
+  if (SDL_MUSTLOCK (dst))
+    sdl.UnlockSurface (dst);
+
+  sdl.UpdateRect (dst, 0, dsty, dst->w, 1);
+
+  return 0;
+}
+
+unsigned
+bfin_gui_update (void *state, const void *source, unsigned nr_bytes)
+{
+  struct gui_state *gui = state;
+  int ret;
+
+  if (!gui)
+    return 0;
+
+  /* XXX: Make this an option ?  */
+  gui->throttle = (gui->throttle + 1) & gui->throttle_limit;
+  if (gui->throttle)
+    return 0;
+
+  ret = SDL_ConvertBlitLineFrom (source, gui->format, gui->screen,
+                                gui->curr_line);
+  if (ret)
+    return 0;
+
+  gui->curr_line = (gui->curr_line + 1) % gui->screen->h;
+
+  return nr_bytes;
+}
+
+#define FMASK(cnt, shift) (((1 << (cnt)) - 1) << (shift))
+#define _FORMAT(bpp, rcnt, gcnt, bcnt, acnt, rsh, gsh, bsh, ash) \
+  NULL, bpp, (bpp)/8, 8-(rcnt), 8-(gcnt), 8-(bcnt), 8-(acnt), rsh, gsh, bsh, ash, \
+  FMASK (rcnt, rsh), FMASK (gcnt, gsh), FMASK (bcnt, bsh), FMASK (acnt, ash),
+#define FORMAT(rcnt, gcnt, bcnt, acnt, rsh, gsh, bsh, ash) \
+  _FORMAT(((((rcnt) + (gcnt) + (bcnt) + (acnt)) + 7) / 8) * 8, \
+         rcnt, gcnt, bcnt, acnt, rsh, gsh, bsh, ash)
+
+static const SDL_PixelFormat sdl_rgb_565 = {
+  FORMAT (5, 6, 5, 0, 11, 5, 0, 0)
+};
+static const SDL_PixelFormat sdl_bgr_565 = {
+  FORMAT (5, 6, 5, 0, 0, 5, 11, 0)
+};
+static const SDL_PixelFormat sdl_rgb_888 = {
+  FORMAT (8, 8, 8, 0, 16, 8, 0, 0)
+};
+static const SDL_PixelFormat sdl_bgr_888 = {
+  FORMAT (8, 8, 8, 0, 0, 8, 16, 0)
+};
+static const SDL_PixelFormat sdl_rgba_8888 = {
+  FORMAT (8, 8, 8, 8, 24, 16, 8, 0)
+};
+
+static const struct {
+  const char *name;
+  const SDL_PixelFormat *format;
+  enum gui_color color;
+} color_spaces[] = {
+  { "rgb565",   &sdl_rgb_565,   GUI_COLOR_RGB_565,   },
+  { "bgr565",   &sdl_bgr_565,   GUI_COLOR_BGR_565,   },
+  { "rgb888",   &sdl_rgb_888,   GUI_COLOR_RGB_888,   },
+  { "bgr888",   &sdl_bgr_888,   GUI_COLOR_BGR_888,   },
+  { "rgba8888", &sdl_rgba_8888, GUI_COLOR_RGBA_8888, },
+};
+
+enum gui_color bfin_gui_color (const char *color)
+{
+  int i;
+
+  if (!color)
+    goto def;
+
+  for (i = 0; i < ARRAY_SIZE (color_spaces); ++i)
+    if (!strcmp (color, color_spaces[i].name))
+      return color_spaces[i].color;
+
+  /* Pick a random default.  */
+ def:
+  return GUI_COLOR_RGB_888;
+}
+
+static const SDL_PixelFormat *bfin_gui_color_format (enum gui_color color)
+{
+  int i;
+
+  for (i = 0; i < ARRAY_SIZE (color_spaces); ++i)
+    if (color == color_spaces[i].color)
+      return color_spaces[i].format;
+
+  return NULL;
+}
+
+int bfin_gui_color_depth (enum gui_color color)
+{
+  const SDL_PixelFormat *format = bfin_gui_color_format (color);
+  return format ? format->BitsPerPixel : 0;
+}
+
+#endif
diff --git a/sim/bfin/gui.h b/sim/bfin/gui.h
new file mode 100644 (file)
index 0000000..3456ac9
--- /dev/null
@@ -0,0 +1,50 @@
+/* Blackfin GUI (SDL) helper code
+
+   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef BFIN_GUI_H
+#define BFIN_GUI_H
+
+#ifdef HAVE_SDL
+
+enum gui_color {
+  GUI_COLOR_RGB_565,
+  GUI_COLOR_BGR_565,
+  GUI_COLOR_RGB_888,
+  GUI_COLOR_BGR_888,
+  GUI_COLOR_RGBA_8888,
+};
+enum gui_color bfin_gui_color (const char *color);
+int bfin_gui_color_depth (enum gui_color color);
+
+void *bfin_gui_setup (void *state, int enabled, int height, int width,
+                     enum gui_color color);
+
+unsigned bfin_gui_update (void *state, const void *source, unsigned nr_bytes);
+
+#else
+
+# define bfin_gui_color(...)           0
+# define bfin_gui_color_depth(...)     0
+# define bfin_gui_setup(...)           NULL
+# define bfin_gui_update(...)          0
+
+#endif
+
+#endif
diff --git a/sim/bfin/insn_list.def b/sim/bfin/insn_list.def
new file mode 100644 (file)
index 0000000..41ff91c
--- /dev/null
@@ -0,0 +1,62 @@
+/* Blackfin instruction classes list
+
+   Copyright (C) 2005-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+/* Only bother with insn groups rather than exact insn (for now?).  */
+I(ProgCtrl_nop)
+I(ProgCtrl_branch)
+I(ProgCtrl_sync)
+I(ProgCtrl_cec)
+I(ProgCtrl_atomic)
+I(CaCTRL)
+I(PushPopReg)
+I(PushPopMultiple)
+I(ccMV)
+I(CCflag)
+I(CC2dreg)
+I(CC2stat)
+I(BRCC)
+I(UJUMP)
+I(REGMV)
+I(ALU2op)
+I(PTR2op)
+I(LOGI2op)
+I(COMP3op)
+I(COMPI2opD)
+I(COMPI2opP)
+I(LDSTpmod)
+I(dagMODim)
+I(dagMODik)
+I(dspLDST)
+I(LDST)
+I(LDSTiiFP)
+I(LDSTii)
+I(LoopSetup)
+I(LDIMMhalf)
+I(CALLa)
+I(LDSTidxI)
+I(linkage)
+I(dsp32mac)
+I(dsp32mult)
+I(dsp32alu)
+I(dsp32shift)
+I(dsp32shiftimm)
+I(psedoDEBUG)
+I(psedoOChar)
+I(psedodbg_assert)
diff --git a/sim/bfin/interp.c b/sim/bfin/interp.c
new file mode 100644 (file)
index 0000000..1f8681d
--- /dev/null
@@ -0,0 +1,1241 @@
+/* Simulator for Analog Devices Blackfin processors.
+
+   Copyright (C) 2005-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "gdb/callback.h"
+#include "gdb/signals.h"
+#include "sim-main.h"
+#include "sim-hw.h"
+
+#include "targ-vals.h"
+
+/* The numbers here do not matter.  They just need to be unique.  */
+#define CB_SYS_ioctl        201
+#define CB_SYS_mmap2        202
+#define CB_SYS_munmap       203
+#define CB_SYS_dup2         204
+#define CB_SYS_getuid       205
+#define CB_SYS_getuid32     206
+#define CB_SYS_getgid       207
+#define CB_SYS_getgid32     208
+#define CB_SYS_setuid       209
+#define CB_SYS_setuid32     210
+#define CB_SYS_setgid       211
+#define CB_SYS_setgid32     212
+#define CB_SYS_pread        213
+#define CB_SYS__llseek      214
+#define CB_SYS_getcwd       215
+#define CB_SYS_stat64       216
+#define CB_SYS_lstat64      217
+#define CB_SYS_fstat64      218
+#define CB_SYS_ftruncate64  219
+#define CB_SYS_gettimeofday 220
+#define CB_SYS_access       221
+#include "linux-targ-map.h"
+#include "linux-fixed-code.h"
+
+#include "elf/common.h"
+#include "elf/external.h"
+#include "elf/internal.h"
+#include "elf/bfin.h"
+#include "elf-bfd.h"
+
+#include "dv-bfin_cec.h"
+#include "dv-bfin_mmu.h"
+
+#ifndef HAVE_GETUID
+# define getuid() 0
+#endif
+#ifndef HAVE_GETGID
+# define getgid() 0
+#endif
+#ifndef HAVE_GETEUID
+# define geteuid() 0
+#endif
+#ifndef HAVE_GETEGID
+# define getegid() 0
+#endif
+#ifndef HAVE_SETUID
+# define setuid(uid) -1
+#endif
+#ifndef HAVE_SETGID
+# define setgid(gid) -1
+#endif
+
+static const char stat_map_32[] =
+/* Linux kernel 32bit layout:  */
+"st_dev,2:space,2:st_ino,4:st_mode,2:st_nlink,2:st_uid,2:st_gid,2:st_rdev,2:"
+"space,2:st_size,4:st_blksize,4:st_blocks,4:st_atime,4:st_atimensec,4:"
+"st_mtime,4:st_mtimensec,4:st_ctime,4:st_ctimensec,4:space,4:space,4";
+/* uClibc public ABI 32bit layout:
+"st_dev,8:space,2:space,2:st_ino,4:st_mode,4:st_nlink,4:st_uid,4:st_gid,4:"
+"st_rdev,8:space,2:space,2:st_size,4:st_blksiez,4:st_blocks,4:st_atime,4:"
+"st_atimensec,4:st_mtime,4:st_mtimensec,4:st_ctime,4:st_ctimensec,4:space,4:"
+"space,4";  */
+static const char stat_map_64[] =
+"st_dev,8:space,4:space,4:st_mode,4:st_nlink,4:st_uid,4:st_gid,4:st_rdev,8:"
+"space,4:st_size,8:st_blksize,4:st_blocks,8:st_atime,4:st_atimensec,4:"
+"st_mtime,4:st_mtimensec,4:st_ctime,4:st_ctimensec,4:st_ino,8";
+
+/* Count the number of arguments in an argv.  */
+static int
+count_argc (const char * const *argv)
+{
+  int i;
+
+  if (! argv)
+    return -1;
+
+  for (i = 0; argv[i] != NULL; ++i)
+    continue;
+  return i;
+}
+
+/* Read/write functions for system call interface.  */
+
+static int
+syscall_read_mem (host_callback *cb, struct cb_syscall *sc,
+                 unsigned long taddr, char *buf, int bytes)
+{
+  SIM_DESC sd = (SIM_DESC) sc->p1;
+  SIM_CPU *cpu = (SIM_CPU *) sc->p2;
+
+  MAYBE_TRACE (CORE, cpu, "DBUS FETCH (syscall) %i bytes @ 0x%08lx", bytes, taddr);
+
+  return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
+}
+
+static int
+syscall_write_mem (host_callback *cb, struct cb_syscall *sc,
+                 unsigned long taddr, const char *buf, int bytes)
+{
+  SIM_DESC sd = (SIM_DESC) sc->p1;
+  SIM_CPU *cpu = (SIM_CPU *) sc->p2;
+
+  MAYBE_TRACE (CORE, cpu, "DBUS STORE (syscall) %i bytes @ 0x%08lx", bytes, taddr);
+
+  return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
+}
+
+/* Simulate a monitor trap, put the result into r0 and errno into r1
+   return offset by which to adjust pc.  */
+
+void
+bfin_syscall (SIM_CPU *cpu)
+{
+  SIM_DESC sd = CPU_STATE (cpu);
+  const char * const *argv = (void *)STATE_PROG_ARGV (sd);
+  host_callback *cb = STATE_CALLBACK (sd);
+  bu32 args[6];
+  CB_SYSCALL sc;
+  char *p;
+  char _tbuf[512], *tbuf = _tbuf;
+  int fmt_ret_hex = 0;
+
+  CB_SYSCALL_INIT (&sc);
+
+  if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT)
+    {
+      /* Linux syscall.  */
+      sc.func = PREG (0);
+      sc.arg1 = args[0] = DREG (0);
+      sc.arg2 = args[1] = DREG (1);
+      sc.arg3 = args[2] = DREG (2);
+      sc.arg4 = args[3] = DREG (3);
+      /*sc.arg5 =*/ args[4] = DREG (4);
+      /*sc.arg6 =*/ args[5] = DREG (5);
+    }
+  else
+    {
+      /* libgloss syscall.  */
+      sc.func = PREG (0);
+      sc.arg1 = args[0] = GET_LONG (DREG (0));
+      sc.arg2 = args[1] = GET_LONG (DREG (0) + 4);
+      sc.arg3 = args[2] = GET_LONG (DREG (0) + 8);
+      sc.arg4 = args[3] = GET_LONG (DREG (0) + 12);
+      /*sc.arg5 =*/ args[4] = GET_LONG (DREG (0) + 16);
+      /*sc.arg6 =*/ args[5] = GET_LONG (DREG (0) + 20);
+    }
+  sc.p1 = (PTR) sd;
+  sc.p2 = (PTR) cpu;
+  sc.read_mem = syscall_read_mem;
+  sc.write_mem = syscall_write_mem;
+
+  /* Common cb_syscall() handles most functions.  */
+  switch (cb_target_to_host_syscall (cb, sc.func))
+    {
+    case CB_SYS_exit:
+      tbuf += sprintf (tbuf, "exit(%i)", args[0]);
+      sim_engine_halt (sd, cpu, NULL, PCREG, sim_exited, sc.arg1);
+
+#ifdef CB_SYS_argc
+    case CB_SYS_argc:
+      tbuf += sprintf (tbuf, "argc()");
+      sc.result = count_argc (argv);
+      break;
+    case CB_SYS_argnlen:
+      {
+      tbuf += sprintf (tbuf, "argnlen(%u)", args[0]);
+       if (sc.arg1 < count_argc (argv))
+         sc.result = strlen (argv[sc.arg1]);
+       else
+         sc.result = -1;
+      }
+      break;
+    case CB_SYS_argn:
+      {
+       tbuf += sprintf (tbuf, "argn(%u)", args[0]);
+       if (sc.arg1 < count_argc (argv))
+         {
+           const char *argn = argv[sc.arg1];
+           int len = strlen (argn);
+           int written = sc.write_mem (cb, &sc, sc.arg2, argn, len + 1);
+           if (written == len + 1)
+             sc.result = sc.arg2;
+           else
+             sc.result = -1;
+         }
+       else
+         sc.result = -1;
+      }
+      break;
+#endif
+
+    case CB_SYS_gettimeofday:
+      {
+       struct timeval _tv, *tv = &_tv;
+       struct timezone _tz, *tz = &_tz;
+
+       tbuf += sprintf (tbuf, "gettimeofday(%#x, %#x)", args[0], args[1]);
+
+       if (sc.arg1 == 0)
+         tv = NULL;
+       if (sc.arg2 == 0)
+         tz = NULL;
+       sc.result = gettimeofday (tv, tz);
+
+       if (sc.result == 0)
+         {
+           bu32 t;
+
+           if (tv)
+             {
+               t = tv->tv_sec;
+               sc.write_mem (cb, &sc, sc.arg1, (void *)&t, 4);
+               t = tv->tv_usec;
+               sc.write_mem (cb, &sc, sc.arg1 + 4, (void *)&t, 4);
+             }
+
+           if (sc.arg2)
+             {
+               t = tz->tz_minuteswest;
+               sc.write_mem (cb, &sc, sc.arg1, (void *)&t, 4);
+               t = tz->tz_dsttime;
+               sc.write_mem (cb, &sc, sc.arg1 + 4, (void *)&t, 4);
+             }
+         }
+       else
+         goto sys_finish;
+      }
+      break;
+
+    case CB_SYS_ioctl:
+      /* XXX: hack just enough to get basic stdio w/uClibc ...  */
+      tbuf += sprintf (tbuf, "ioctl(%i, %#x, %u)", args[0], args[1], args[2]);
+      if (sc.arg2 == 0x5401)
+       {
+         sc.result = !isatty (sc.arg1);
+         sc.errcode = 0;
+       }
+      else
+       {
+         sc.result = -1;
+         sc.errcode = TARGET_EINVAL;
+       }
+      break;
+
+    case CB_SYS_mmap2:
+      {
+       static bu32 heap = BFIN_DEFAULT_MEM_SIZE / 2;
+
+       fmt_ret_hex = 1;
+       tbuf += sprintf (tbuf, "mmap2(%#x, %u, %#x, %#x, %i, %u)",
+                        args[0], args[1], args[2], args[3], args[4], args[5]);
+
+       sc.errcode = 0;
+
+       if (sc.arg4 & 0x20 /*MAP_ANONYMOUS*/)
+         /* XXX: We don't handle zeroing, but default is all zeros.  */;
+       else if (args[4] >= MAX_CALLBACK_FDS)
+         sc.errcode = TARGET_ENOSYS;
+       else
+         {
+           char *data = xmalloc (sc.arg2);
+
+           /* XXX: Should add a cb->pread.  */
+           if (pread (cb->fdmap[args[4]], data, sc.arg2, args[5] << 12) == sc.arg2)
+             sc.write_mem (cb, &sc, heap, data, sc.arg2);
+           else
+             sc.errcode = TARGET_EINVAL;
+
+           free (data);
+         }
+
+       if (sc.errcode)
+         {
+           sc.result = -1;
+           break;
+         }
+
+       sc.result = heap;
+       heap += sc.arg2;
+       /* Keep it page aligned.  */
+       heap = ALIGN (heap, 4096);
+
+       break;
+      }
+
+    case CB_SYS_munmap:
+      /* XXX: meh, just lie for mmap().  */
+      tbuf += sprintf (tbuf, "munmap(%#x, %u)", args[0], args[1]);
+      sc.result = 0;
+      break;
+
+    case CB_SYS_dup2:
+      tbuf += sprintf (tbuf, "dup2(%i, %i)", args[0], args[1]);
+      if (sc.arg1 >= MAX_CALLBACK_FDS || sc.arg2 >= MAX_CALLBACK_FDS)
+       {
+         sc.result = -1;
+         sc.errcode = TARGET_EINVAL;
+       }
+      else
+       {
+         sc.result = dup2 (cb->fdmap[sc.arg1], cb->fdmap[sc.arg2]);
+         goto sys_finish;
+       }
+      break;
+
+    case CB_SYS__llseek:
+      tbuf += sprintf (tbuf, "llseek(%i, %u, %u, %#x, %u)",
+                      args[0], args[1], args[2], args[3], args[4]);
+      sc.func = TARGET_LINUX_SYS_lseek;
+      if (sc.arg2)
+       {
+         sc.result = -1;
+         sc.errcode = TARGET_EINVAL;
+       }
+      else
+       {
+         sc.arg2 = sc.arg3;
+         sc.arg3 = args[4];
+         cb_syscall (cb, &sc);
+         if (sc.result != -1)
+           {
+             bu32 z = 0;
+             sc.write_mem (cb, &sc, args[3], (void *)&sc.result, 4);
+             sc.write_mem (cb, &sc, args[3] + 4, (void *)&z, 4);
+           }
+       }
+      break;
+
+    /* XXX: Should add a cb->pread.  */
+    case CB_SYS_pread:
+      tbuf += sprintf (tbuf, "pread(%i, %#x, %u, %i)",
+                      args[0], args[1], args[2], args[3]);
+      if (sc.arg1 >= MAX_CALLBACK_FDS)
+       {
+         sc.result = -1;
+         sc.errcode = TARGET_EINVAL;
+       }
+      else
+       {
+         long old_pos, read_result, read_errcode;
+
+         /* Get current filepos.  */
+         sc.func = TARGET_LINUX_SYS_lseek;
+         sc.arg2 = 0;
+         sc.arg3 = SEEK_CUR;
+         cb_syscall (cb, &sc);
+         if (sc.result == -1)
+           break;
+         old_pos = sc.result;
+
+         /* Move to the new pos.  */
+         sc.func = TARGET_LINUX_SYS_lseek;
+         sc.arg2 = args[3];
+         sc.arg3 = SEEK_SET;
+         cb_syscall (cb, &sc);
+         if (sc.result == -1)
+           break;
+
+         /* Read the data.  */
+         sc.func = TARGET_LINUX_SYS_read;
+         sc.arg2 = args[1];
+         sc.arg3 = args[2];
+         cb_syscall (cb, &sc);
+         read_result = sc.result;
+         read_errcode = sc.errcode;
+
+         /* Move back to the old pos.  */
+         sc.func = TARGET_LINUX_SYS_lseek;
+         sc.arg2 = old_pos;
+         sc.arg3 = SEEK_SET;
+         cb_syscall (cb, &sc);
+
+         sc.result = read_result;
+         sc.errcode = read_errcode;
+       }
+      break;
+
+    case CB_SYS_getcwd:
+      tbuf += sprintf (tbuf, "getcwd(%#x, %u)", args[0], args[1]);
+
+      p = alloca (sc.arg2);
+      if (getcwd (p, sc.arg2) == NULL)
+       {
+         sc.result = -1;
+         sc.errcode = TARGET_EINVAL;
+       }
+      else
+       {
+         sc.write_mem (cb, &sc, sc.arg1, p, sc.arg2);
+         sc.result = sc.arg1;
+       }
+      break;
+
+    case CB_SYS_stat64:
+      tbuf += sprintf (tbuf, "stat64(%#x, %u)", args[0], args[1]);
+      cb->stat_map = stat_map_64;
+      sc.func = TARGET_LINUX_SYS_stat;
+      cb_syscall (cb, &sc);
+      cb->stat_map = stat_map_32;
+      break;
+    case CB_SYS_lstat64:
+      tbuf += sprintf (tbuf, "lstat64(%#x, %u)", args[0], args[1]);
+      cb->stat_map = stat_map_64;
+      sc.func = TARGET_LINUX_SYS_lstat;
+      cb_syscall (cb, &sc);
+      cb->stat_map = stat_map_32;
+      break;
+    case CB_SYS_fstat64:
+      tbuf += sprintf (tbuf, "fstat64(%#x, %u)", args[0], args[1]);
+      cb->stat_map = stat_map_64;
+      sc.func = TARGET_LINUX_SYS_fstat;
+      cb_syscall (cb, &sc);
+      cb->stat_map = stat_map_32;
+      break;
+
+    case CB_SYS_ftruncate64:
+      tbuf += sprintf (tbuf, "ftruncate64(%u, %u)", args[0], args[1]);
+      sc.func = TARGET_LINUX_SYS_ftruncate;
+      cb_syscall (cb, &sc);
+      break;
+
+    case CB_SYS_getuid:
+    case CB_SYS_getuid32:
+      tbuf += sprintf (tbuf, "getuid()");
+      sc.result = getuid ();
+      goto sys_finish;
+    case CB_SYS_getgid:
+    case CB_SYS_getgid32:
+      tbuf += sprintf (tbuf, "getgid()");
+      sc.result = getgid ();
+      goto sys_finish;
+    case CB_SYS_setuid:
+      sc.arg1 &= 0xffff;
+    case CB_SYS_setuid32:
+      tbuf += sprintf (tbuf, "setuid(%u)", args[0]);
+      sc.result = setuid (sc.arg1);
+      goto sys_finish;
+    case CB_SYS_setgid:
+      sc.arg1 &= 0xffff;
+    case CB_SYS_setgid32:
+      tbuf += sprintf (tbuf, "setgid(%u)", args[0]);
+      sc.result = setgid (sc.arg1);
+      goto sys_finish;
+
+    case CB_SYS_getpid:
+      tbuf += sprintf (tbuf, "getpid()");
+      sc.result = getpid ();
+      goto sys_finish;
+    case CB_SYS_kill:
+      tbuf += sprintf (tbuf, "kill(%u, %i)", args[0], args[1]);
+      /* Only let the app kill itself.  */
+      if (sc.arg1 != getpid ())
+       {
+         sc.result = -1;
+         sc.errcode = TARGET_EPERM;
+       }
+      else
+       {
+         sc.result = kill (sc.arg1, sc.arg2);
+         goto sys_finish;
+       }
+      break;
+
+    case CB_SYS_open:
+      tbuf += sprintf (tbuf, "open(%#x, %#x, %o)", args[0], args[1], args[2]);
+      goto case_default;
+    case CB_SYS_close:
+      tbuf += sprintf (tbuf, "close(%i)", args[0]);
+      goto case_default;
+    case CB_SYS_read:
+      tbuf += sprintf (tbuf, "read(%i, %#x, %u)", args[0], args[1], args[2]);
+      goto case_default;
+    case CB_SYS_write:
+      tbuf += sprintf (tbuf, "write(%i, %#x, %u)", args[0], args[1], args[2]);
+      goto case_default;
+    case CB_SYS_lseek:
+      tbuf += sprintf (tbuf, "lseek(%i, %i, %i)", args[0], args[1], args[2]);
+      goto case_default;
+    case CB_SYS_unlink:
+      tbuf += sprintf (tbuf, "unlink(%#x)", args[0]);
+      goto case_default;
+    case CB_SYS_truncate:
+      tbuf += sprintf (tbuf, "truncate(%#x, %i)", args[0], args[1]);
+      goto case_default;
+    case CB_SYS_ftruncate:
+      tbuf += sprintf (tbuf, "ftruncate(%i, %i)", args[0], args[1]);
+      goto case_default;
+    case CB_SYS_rename:
+      tbuf += sprintf (tbuf, "rename(%#x, %#x)", args[0], args[1]);
+      goto case_default;
+    case CB_SYS_stat:
+      tbuf += sprintf (tbuf, "stat(%#x, %#x)", args[0], args[1]);
+      goto case_default;
+    case CB_SYS_fstat:
+      tbuf += sprintf (tbuf, "fstat(%i, %#x)", args[0], args[1]);
+      goto case_default;
+    case CB_SYS_lstat:
+      tbuf += sprintf (tbuf, "lstat(%i, %#x)", args[0], args[1]);
+      goto case_default;
+    case CB_SYS_pipe:
+      tbuf += sprintf (tbuf, "pipe(%#x, %#x)", args[0], args[1]);
+      goto case_default;
+
+    default:
+      tbuf += sprintf (tbuf, "???_%i(%#x, %#x, %#x, %#x, %#x, %#x)", sc.func,
+                      args[0], args[1], args[2], args[3], args[4], args[5]);
+    case_default:
+      cb_syscall (cb, &sc);
+      break;
+
+    sys_finish:
+      if (sc.result == -1)
+       {
+         cb->last_errno = errno;
+         sc.errcode = cb->get_errno (cb);
+       }
+    }
+
+  TRACE_EVENTS (cpu, "syscall_%i(%#x, %#x, %#x, %#x, %#x, %#x) = %li (error = %i)",
+               sc.func, args[0], args[1], args[2], args[3], args[4], args[5],
+               sc.result, sc.errcode);
+
+  tbuf += sprintf (tbuf, " = ");
+  if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT)
+    {
+      if (sc.result == -1)
+       {
+         tbuf += sprintf (tbuf, "-1 (error = %i)", sc.errcode);
+         if (sc.errcode == cb_host_to_target_errno (cb, ENOSYS))
+           {
+             sim_io_eprintf (sd, "bfin-sim: %#x: unimplemented syscall %i\n",
+                             PCREG, sc.func);
+           }
+         SET_DREG (0, -sc.errcode);
+       }
+      else
+       {
+         if (fmt_ret_hex)
+           tbuf += sprintf (tbuf, "%#lx", sc.result);
+         else
+           tbuf += sprintf (tbuf, "%lu", sc.result);
+         SET_DREG (0, sc.result);
+       }
+    }
+  else
+    {
+      tbuf += sprintf (tbuf, "%lu (error = %i)", sc.result, sc.errcode);
+      SET_DREG (0, sc.result);
+      /* Blackfin libgloss only expects R0 to be updated, not R1.  */
+      /*SET_DREG (1, sc.errcode);*/
+    }
+
+  TRACE_SYSCALL (cpu, "%s", _tbuf);
+}
+
+void
+trace_register (SIM_DESC sd,
+               sim_cpu *cpu,
+               const char *fmt,
+               ...)
+{
+  va_list ap;
+  trace_printf (sd, cpu, "%s %s",
+               "reg:     ",
+               TRACE_PREFIX (CPU_TRACE_DATA (cpu)));
+  va_start (ap, fmt);
+  trace_vprintf (sd, cpu, fmt, ap);
+  va_end (ap);
+  trace_printf (sd, cpu, "\n");
+}
+
+/* Execute a single instruction.  */
+
+static sim_cia
+step_once (SIM_CPU *cpu)
+{
+  SIM_DESC sd = CPU_STATE (cpu);
+  bu32 insn_len, oldpc = PCREG;
+  int i;
+  bool ssstep;
+
+  if (TRACE_ANY_P (cpu))
+    trace_prefix (sd, cpu, NULL_CIA, oldpc, TRACE_LINENUM_P (cpu),
+                 NULL, 0, " "); /* Use a space for gcc warnings.  */
+
+  /* Handle hardware single stepping when lower than EVT3, and when SYSCFG
+     has already had the SSSTEP bit enabled.  */
+  ssstep = false;
+  if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT
+      && (SYSCFGREG & SYSCFG_SSSTEP))
+    {
+      int ivg = cec_get_ivg (cpu);
+      if (ivg == -1 || ivg > 3)
+       ssstep = true;
+    }
+
+#if 0
+  /* XXX: Is this what happens on the hardware ?  */
+  if (cec_get_ivg (cpu) == EVT_EMU)
+    cec_return (cpu, EVT_EMU);
+#endif
+
+  BFIN_CPU_STATE.did_jump = false;
+
+  insn_len = interp_insn_bfin (cpu, oldpc);
+
+  /* If we executed this insn successfully, then we always decrement
+     the loop counter.  We don't want to update the PC though if the
+     last insn happened to be a change in code flow (jump/etc...).  */
+  if (!BFIN_CPU_STATE.did_jump)
+    SET_PCREG (hwloop_get_next_pc (cpu, oldpc, insn_len));
+  for (i = 1; i >= 0; --i)
+    if (LCREG (i) && oldpc == LBREG (i))
+      {
+       SET_LCREG (i, LCREG (i) - 1);
+       if (LCREG (i))
+         break;
+      }
+
+  ++ PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu));
+
+  /* Handle hardware single stepping only if we're still lower than EVT3.
+     XXX: May not be entirely correct wrt EXCPT insns.  */
+  if (ssstep)
+    {
+      int ivg = cec_get_ivg (cpu);
+      if (ivg == -1 || ivg > 3)
+       {
+         INSN_LEN = 0;
+         cec_exception (cpu, VEC_STEP);
+       }
+    }
+
+  return oldpc;
+}
+
+void
+sim_engine_run (SIM_DESC sd,
+               int next_cpu_nr, /* ignore  */
+               int nr_cpus, /* ignore  */
+               int siggnal) /* ignore  */
+{
+  bu32 ticks;
+  SIM_CPU *cpu;
+
+  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
+
+  cpu = STATE_CPU (sd, 0);
+
+  while (1)
+    {
+      step_once (cpu);
+      /* Process any events -- can't use tickn because it may
+         advance right over the next event.  */
+      for (ticks = 0; ticks < CYCLE_DELAY; ++ticks)
+       if (sim_events_tick (sd))
+         sim_events_process (sd);
+    }
+}
+
+/* Cover function of sim_state_free to free the cpu buffers as well.  */
+
+static void
+free_state (SIM_DESC sd)
+{
+  if (STATE_MODULES (sd) != NULL)
+    sim_module_uninstall (sd);
+  sim_cpu_free_all (sd);
+  sim_state_free (sd);
+}
+
+/* Create an instance of the simulator.  */
+
+static void
+bfin_initialize_cpu (SIM_DESC sd, SIM_CPU *cpu)
+{
+  memset (&cpu->state, 0, sizeof (cpu->state));
+
+  PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) = 0;
+
+  bfin_model_cpu_init (sd, cpu);
+
+  /* Set default stack to top of scratch pad.  */
+  SET_SPREG (BFIN_DEFAULT_MEM_SIZE);
+  SET_KSPREG (BFIN_DEFAULT_MEM_SIZE);
+  SET_USPREG (BFIN_DEFAULT_MEM_SIZE);
+
+  /* This is what the hardware likes.  */
+  SET_SYSCFGREG (0x30);
+}
+
+SIM_DESC
+sim_open (SIM_OPEN_KIND kind, host_callback *callback,
+         struct bfd *abfd, char **argv)
+{
+  char c;
+  int i;
+  SIM_DESC sd = sim_state_alloc (kind, callback);
+
+  /* The cpu data is kept in a separately allocated chunk of memory.  */
+  if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
+    {
+      free_state (sd);
+      return 0;
+    }
+
+  {
+    /* XXX: Only first core gets profiled ?  */
+    SIM_CPU *cpu = STATE_CPU (sd, 0);
+    STATE_WATCHPOINTS (sd)->pc = &PCREG;
+    STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PCREG);
+  }
+
+  if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
+    {
+      free_state (sd);
+      return 0;
+    }
+
+  /* XXX: Default to the Virtual environment.  */
+  if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT)
+    STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT;
+
+  /* These options override any module options.
+     Obviously ambiguity should be avoided, however the caller may wish to
+     augment the meaning of an option.  */
+#define e_sim_add_option_table(sd, options) \
+  do { \
+    extern const OPTION options[]; \
+    sim_add_option_table (sd, NULL, options); \
+  } while (0)
+  e_sim_add_option_table (sd, bfin_mmu_options);
+  e_sim_add_option_table (sd, bfin_mach_options);
+
+  /* getopt will print the error message so we just have to exit if this fails.
+     FIXME: Hmmm...  in the case of gdb we need getopt to call
+     print_filtered.  */
+  if (sim_parse_args (sd, argv) != SIM_RC_OK)
+    {
+      free_state (sd);
+      return 0;
+    }
+
+  /* Allocate external memory if none specified by user.
+     Use address 4 here in case the user wanted address 0 unmapped.  */
+  if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0)
+    {
+      bu16 emuexcpt = 0x25;
+      sim_do_commandf (sd, "memory-size 0x%lx", BFIN_DEFAULT_MEM_SIZE);
+      sim_write (sd, 0, (void *)&emuexcpt, 2);
+    }
+
+  /* Check for/establish the a reference program image.  */
+  if (sim_analyze_program (sd,
+                          (STATE_PROG_ARGV (sd) != NULL
+                           ? *STATE_PROG_ARGV (sd)
+                           : NULL), abfd) != SIM_RC_OK)
+    {
+      free_state (sd);
+      return 0;
+    }
+
+  /* Establish any remaining configuration options.  */
+  if (sim_config (sd) != SIM_RC_OK)
+    {
+      free_state (sd);
+      return 0;
+    }
+
+  if (sim_post_argv_init (sd) != SIM_RC_OK)
+    {
+      free_state (sd);
+      return 0;
+    }
+
+  /* CPU specific initialization.  */
+  for (i = 0; i < MAX_NR_PROCESSORS; ++i)
+    {
+      SIM_CPU *cpu = STATE_CPU (sd, i);
+      bfin_initialize_cpu (sd, cpu);
+    }
+
+  return sd;
+}
+
+void
+sim_close (SIM_DESC sd, int quitting)
+{
+  sim_module_uninstall (sd);
+}
+
+/* Some utils don't like having a NULL environ.  */
+static const char * const simple_env[] = { "HOME=/", "PATH=/bin", NULL };
+
+static bu32 fdpic_load_offset;
+
+static bool
+bfin_fdpic_load (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, bu32 *sp,
+                bu32 *elf_addrs, char **ldso_path)
+{
+  bool ret;
+  int i;
+
+  Elf_Internal_Ehdr *iehdr;
+  Elf32_External_Ehdr ehdr;
+  Elf_Internal_Phdr *phdrs;
+  unsigned char *data;
+  long phdr_size;
+  int phdrc;
+  bu32 nsegs;
+
+  bu32 max_load_addr;
+
+  unsigned char null[4] = { 0, 0, 0, 0 };
+
+  ret = false;
+  *ldso_path = NULL;
+
+  /* See if this an FDPIC ELF.  */
+  phdrs = NULL;
+  if (!abfd)
+    goto skip_fdpic_init;
+  if (bfd_seek (abfd, 0, SEEK_SET) != 0)
+    goto skip_fdpic_init;
+  if (bfd_bread (&ehdr, sizeof (ehdr), abfd) != sizeof (ehdr))
+    goto skip_fdpic_init;
+  iehdr = elf_elfheader (abfd);
+  if (!(iehdr->e_flags & EF_BFIN_FDPIC))
+    goto skip_fdpic_init;
+
+  if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
+    sim_io_printf (sd, "Loading FDPIC ELF %s\n Load base: %#x\n ELF entry: %#x\n",
+                  bfd_get_filename (abfd), fdpic_load_offset, elf_addrs[0]);
+
+  /* Grab the Program Headers to set up the loadsegs on the stack.  */
+  phdr_size = bfd_get_elf_phdr_upper_bound (abfd);
+  if (phdr_size == -1)
+    goto skip_fdpic_init;
+  phdrs = xmalloc (phdr_size);
+  phdrc = bfd_get_elf_phdrs (abfd, phdrs);
+  if (phdrc == -1)
+    goto skip_fdpic_init;
+
+  /* Push the Ehdr onto the stack.  */
+  *sp -= sizeof (ehdr);
+  elf_addrs[3] = *sp;
+  sim_write (sd, *sp, (void *)&ehdr, sizeof (ehdr));
+  if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
+    sim_io_printf (sd, " Elf_Ehdr: %#x\n", *sp);
+
+  /* Since we're relocating things ourselves, we need to relocate
+     the start address as well.  */
+  elf_addrs[0] = bfd_get_start_address (abfd) + fdpic_load_offset;
+
+  /* And the Exec's Phdrs onto the stack.  */
+  if (STATE_PROG_BFD (sd) == abfd)
+    {
+      elf_addrs[4] = elf_addrs[0];
+
+      phdr_size = iehdr->e_phentsize * iehdr->e_phnum;
+      if (bfd_seek (abfd, iehdr->e_phoff, SEEK_SET) != 0)
+       goto skip_fdpic_init;
+      data = xmalloc (phdr_size);
+      if (bfd_bread (data, phdr_size, abfd) != phdr_size)
+       goto skip_fdpic_init;
+      *sp -= phdr_size;
+      elf_addrs[1] = *sp;
+      elf_addrs[2] = phdrc;
+      sim_write (sd, *sp, data, phdr_size);
+      free (data);
+      if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
+       sim_io_printf (sd, " Elf_Phdrs: %#x\n", *sp);
+    }
+
+  /* Now push all the loadsegs.  */
+  nsegs = 0;
+  max_load_addr = 0;
+  for (i = phdrc; i >= 0; --i)
+    if (phdrs[i].p_type == PT_LOAD)
+      {
+       Elf_Internal_Phdr *p = &phdrs[i];
+       bu32 paddr, vaddr, memsz, filesz;
+
+       paddr = p->p_paddr + fdpic_load_offset;
+       vaddr = p->p_vaddr;
+       memsz = p->p_memsz;
+       filesz = p->p_filesz;
+
+       if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
+         sim_io_printf (sd, " PHDR %i: vma %#x lma %#x filesz %#x memsz %#x\n",
+                        i, vaddr, paddr, filesz, memsz);
+
+       data = xmalloc (memsz);
+       if (memsz != filesz)
+         memset (data + filesz, 0, memsz - filesz);
+
+       if (bfd_seek (abfd, p->p_offset, SEEK_SET) == 0
+           && bfd_bread (data, filesz, abfd) == filesz)
+         sim_write (sd, paddr, data, memsz);
+
+       free (data);
+
+       max_load_addr = MAX (paddr + memsz, max_load_addr);
+
+       *sp -= 12;
+       sim_write (sd, *sp+0, (void *)&paddr, 4); /* loadseg.addr  */
+       sim_write (sd, *sp+4, (void *)&vaddr, 4); /* loadseg.p_vaddr  */
+       sim_write (sd, *sp+8, (void *)&memsz, 4); /* loadseg.p_memsz  */
+       ++nsegs;
+      }
+    else if (phdrs[i].p_type == PT_DYNAMIC)
+      {
+       elf_addrs[5] = phdrs[i].p_paddr + fdpic_load_offset;
+       if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
+         sim_io_printf (sd, " PT_DYNAMIC: %#x\n", elf_addrs[5]);
+      }
+    else if (phdrs[i].p_type == PT_INTERP)
+      {
+       uint32_t off = phdrs[i].p_offset;
+       uint32_t len = phdrs[i].p_filesz;
+
+       *ldso_path = xmalloc (len);
+       if (bfd_seek (abfd, off, SEEK_SET) != 0
+           || bfd_bread (*ldso_path, len, abfd) != len)
+         {
+           free (*ldso_path);
+           *ldso_path = NULL;
+         }
+       else if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
+         sim_io_printf (sd, " PT_INTERP: %s\n", *ldso_path);
+      }
+
+  /* Update the load offset with a few extra pages.  */
+  fdpic_load_offset = ALIGN (MAX (max_load_addr, fdpic_load_offset), 0x10000);
+  fdpic_load_offset += 0x10000;
+
+  /* Push the summary loadmap info onto the stack last.  */
+  *sp -= 4;
+  sim_write (sd, *sp+0, null, 2); /* loadmap.version  */
+  sim_write (sd, *sp+2, (void *)&nsegs, 2); /* loadmap.nsegs  */
+
+  ret = true;
+ skip_fdpic_init:
+  free (phdrs);
+
+  return ret;
+}
+
+static void
+bfin_user_init (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd,
+               const char * const *argv, const char * const *env)
+{
+  /* XXX: Missing host -> target endian ...  */
+  /* Linux starts the user app with the stack:
+       argc
+       argv[0]          -- pointers to the actual strings
+       argv[1..N]
+       NULL
+       env[0]
+       env[1..N]
+       NULL
+       auxvt[0].type    -- ELF Auxiliary Vector Table
+       auxvt[0].value
+       auxvt[1..N]
+       AT_NULL
+       0
+       argv[0..N][0..M] -- actual argv/env strings
+       env[0..N][0..M]
+       FDPIC loadmaps   -- for FDPIC apps
+     So set things up the same way.  */
+  int i, argc, envc;
+  bu32 argv_flat, env_flat;
+
+  bu32 sp, sp_flat;
+
+  /* start, at_phdr, at_phnum, at_base, at_entry, pt_dynamic  */
+  bu32 elf_addrs[6];
+  bu32 auxvt, auxvt_size;
+  bu32 exec_loadmap, ldso_loadmap;
+  char *ldso_path;
+
+  unsigned char null[4] = { 0, 0, 0, 0 };
+
+  host_callback *cb = STATE_CALLBACK (sd);
+
+  elf_addrs[0] = elf_addrs[4] = bfd_get_start_address (abfd);
+  elf_addrs[1] = elf_addrs[2] = elf_addrs[3] = elf_addrs[5] = 0;
+
+  /* Keep the load addresses consistent between runs.  Also make sure we make
+     space for the fixed code region (part of the Blackfin Linux ABI).  */
+  fdpic_load_offset = 0x1000;
+
+  /* First try to load this as an FDPIC executable.  */
+  sp = SPREG;
+  if (!bfin_fdpic_load (sd, cpu, STATE_PROG_BFD (sd), &sp, elf_addrs, &ldso_path))
+    goto skip_fdpic_init;
+  exec_loadmap = sp;
+
+  /* If that worked, then load the fixed code region.  We only do this for
+     FDPIC ELFs atm because they are PIEs and let us relocate them without
+     manual fixups.  FLAT files however require location processing which
+     we do not do ourselves, and they link with a VMA of 0.  */
+  sim_write (sd, 0x400, bfin_linux_fixed_code, sizeof (bfin_linux_fixed_code));
+
+  /* If the FDPIC needs an interpreter, then load it up too.  */
+  if (ldso_path)
+    {
+      const char *ldso_full_path = concat (simulator_sysroot, ldso_path, NULL);
+      struct bfd *ldso_bfd;
+
+      ldso_bfd = bfd_openr (ldso_full_path, STATE_TARGET (sd));
+      if (!ldso_bfd)
+       {
+         sim_io_eprintf (sd, "bfin-sim: bfd open failed: %s\n", ldso_full_path);
+         goto static_fdpic;
+       }
+      if (!bfd_check_format (ldso_bfd, bfd_object))
+       sim_io_eprintf (sd, "bfin-sim: bfd format not valid: %s\n", ldso_full_path);
+      bfd_set_arch_info (ldso_bfd, STATE_ARCHITECTURE (sd));
+
+      if (!bfin_fdpic_load (sd, cpu, ldso_bfd, &sp, elf_addrs, &ldso_path))
+       sim_io_eprintf (sd, "bfin-sim: FDPIC ldso failed to load: %s\n", ldso_full_path);
+      if (ldso_path)
+       sim_io_eprintf (sd, "bfin-sim: FDPIC ldso (%s) needs an interpreter (%s) !?\n",
+                       ldso_full_path, ldso_path);
+
+      ldso_loadmap = sp;
+    }
+  else
+ static_fdpic:
+    ldso_loadmap = 0;
+
+  /* Finally setup the registers required by the FDPIC ABI.  */
+  SET_DREG (7, 0); /* Zero out FINI funcptr -- ldso will set this up.  */
+  SET_PREG (0, exec_loadmap); /* Exec loadmap addr.  */
+  SET_PREG (1, ldso_loadmap); /* Interp loadmap addr.  */
+  SET_PREG (2, elf_addrs[5]); /* PT_DYNAMIC map addr.  */
+
+  auxvt = 1;
+  SET_SPREG (sp);
+ skip_fdpic_init:
+  sim_pc_set (cpu, elf_addrs[0]);
+
+  /* Figure out how much storage the argv/env strings need.  */
+  argc = count_argc (argv);
+  if (argc == -1)
+    argc = 0;
+  argv_flat = argc; /* NUL bytes  */
+  for (i = 0; i < argc; ++i)
+    argv_flat += strlen (argv[i]);
+
+  if (!env)
+    env = simple_env;
+  envc = count_argc (env);
+  env_flat = envc; /* NUL bytes  */
+  for (i = 0; i < envc; ++i)
+    env_flat += strlen (env[i]);
+
+  /* Push the Auxiliary Vector Table between argv/env and actual strings.  */
+  sp_flat = sp = ALIGN (SPREG - argv_flat - env_flat - 4, 4);
+  if (auxvt)
+    {
+# define AT_PUSH(at, val) \
+  auxvt_size += 8; \
+  sp -= 4; \
+  auxvt = (val); \
+  sim_write (sd, sp, (void *)&auxvt, 4); \
+  sp -= 4; \
+  auxvt = (at); \
+  sim_write (sd, sp, (void *)&auxvt, 4)
+  auxvt_size = 0;
+      unsigned int egid = getegid (), gid = getgid ();
+      unsigned int euid = geteuid (), uid = getuid ();
+      AT_PUSH (AT_NULL, 0);
+      AT_PUSH (AT_SECURE, egid != gid || euid != uid);
+      AT_PUSH (AT_EGID, egid);
+      AT_PUSH (AT_GID, gid);
+      AT_PUSH (AT_EUID, euid);
+      AT_PUSH (AT_UID, uid);
+      AT_PUSH (AT_ENTRY, elf_addrs[4]);
+      AT_PUSH (AT_FLAGS, 0);
+      AT_PUSH (AT_BASE, elf_addrs[3]);
+      AT_PUSH (AT_PHNUM, elf_addrs[2]);
+      AT_PUSH (AT_PHENT, sizeof (Elf32_External_Phdr));
+      AT_PUSH (AT_PHDR, elf_addrs[1]);
+      AT_PUSH (AT_CLKTCK, 100); /* XXX: This ever not 100 ?  */
+      AT_PUSH (AT_PAGESZ, 4096);
+      AT_PUSH (AT_HWCAP, 0);
+#undef AT_PUSH
+    }
+  SET_SPREG (sp);
+
+  /* Push the argc/argv/env after the auxvt.  */
+  sp -= ((1 + argc + 1 + envc + 1) * 4);
+  SET_SPREG (sp);
+
+  /* First push the argc value.  */
+  sim_write (sd, sp, (void *)&argc, 4);
+  sp += 4;
+
+  /* Then the actual argv strings so we know where to point argv[].  */
+  for (i = 0; i < argc; ++i)
+    {
+      unsigned len = strlen (argv[i]) + 1;
+      sim_write (sd, sp_flat, (void *)argv[i], len);
+      sim_write (sd, sp, (void *)&sp_flat, 4);
+      sp_flat += len;
+      sp += 4;
+    }
+  sim_write (sd, sp, null, 4);
+  sp += 4;
+
+  /* Then the actual env strings so we know where to point env[].  */
+  for (i = 0; i < envc; ++i)
+    {
+      unsigned len = strlen (env[i]) + 1;
+      sim_write (sd, sp_flat, (void *)env[i], len);
+      sim_write (sd, sp, (void *)&sp_flat, 4);
+      sp_flat += len;
+      sp += 4;
+    }
+
+  /* Set some callbacks.  */
+  cb->syscall_map = cb_linux_syscall_map;
+  cb->errno_map = cb_linux_errno_map;
+  cb->open_map = cb_linux_open_map;
+  cb->signal_map = cb_linux_signal_map;
+  cb->stat_map = stat_map_32;
+}
+
+static void
+bfin_os_init (SIM_DESC sd, SIM_CPU *cpu, const char * const *argv)
+{
+  /* Pass the command line via a string in R0 like Linux expects.  */
+  int i;
+  bu8 byte;
+  bu32 cmdline = BFIN_L1_SRAM_SCRATCH;
+
+  SET_DREG (0, cmdline);
+  if (argv && argv[0])
+    {
+      i = 1;
+      byte = ' ';
+      while (argv[i])
+       {
+         bu32 len = strlen (argv[i]);
+         sim_write (sd, cmdline, (void *)argv[i], len);
+         cmdline += len;
+         sim_write (sd, cmdline, &byte, 1);
+         ++cmdline;
+         ++i;
+       }
+    }
+  byte = 0;
+  sim_write (sd, cmdline, &byte, 1);
+}
+
+SIM_RC
+sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
+                    char **argv, char **env)
+{
+  SIM_CPU *cpu = STATE_CPU (sd, 0);
+  SIM_ADDR addr;
+
+  /* Set the PC.  */
+  if (abfd != NULL)
+    addr = bfd_get_start_address (abfd);
+  else
+    addr = 0;
+  sim_pc_set (cpu, addr);
+
+  /* Standalone mode (i.e. `bfin-...-run`) will take care of the argv
+     for us in sim_open() -> sim_parse_args().  But in debug mode (i.e.
+     'target sim' with `bfin-...-gdb`), we need to handle it.  */
+  if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
+    {
+      free (STATE_PROG_ARGV (sd));
+      STATE_PROG_ARGV (sd) = dupargv (argv);
+    }
+
+  switch (STATE_ENVIRONMENT (sd))
+    {
+    case USER_ENVIRONMENT:
+      bfin_user_init (sd, cpu, abfd, (void *)argv, (void *)env);
+      break;
+    case OPERATING_ENVIRONMENT:
+      bfin_os_init (sd, cpu, (void *)argv);
+      break;
+    default:
+      /* Nothing to do for virtual/all envs.  */
+      break;
+    }
+
+  return SIM_RC_OK;
+}
+
+void
+sim_do_command (SIM_DESC sd, char *cmd)
+{
+  if (sim_args_command (sd, cmd) != SIM_RC_OK)
+    sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
+}
diff --git a/sim/bfin/linux-fixed-code.h b/sim/bfin/linux-fixed-code.h
new file mode 100644 (file)
index 0000000..7b42ed3
--- /dev/null
@@ -0,0 +1,74 @@
+/* DO NOT EDIT: Autogenerated from linux-fixed-code.s.  */
+static const unsigned char bfin_linux_fixed_code[] = {
+0x28, 0xe1, 0xad, 0x00,
+0xa0, 0x00,
+0x00, 0x20,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x91,
+0x01, 0x93,
+0x10, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x91,
+0x08, 0x08,
+0x02, 0x10,
+0x02, 0x93,
+0x10, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x01, 0x91,
+0x01, 0x50,
+0x00, 0x93,
+0x10, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x01, 0x91,
+0x01, 0x52,
+0x00, 0x93,
+0x10, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x01, 0x91,
+0x01, 0x56,
+0x00, 0x93,
+0x10, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x01, 0x91,
+0x01, 0x54,
+0x00, 0x93,
+0x10, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x01, 0x91,
+0x01, 0x58,
+0x00, 0x93,
+0x10, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0xa4, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+0x00, 0x00,
+};
diff --git a/sim/bfin/linux-fixed-code.s b/sim/bfin/linux-fixed-code.s
new file mode 100644 (file)
index 0000000..c1dd358
--- /dev/null
@@ -0,0 +1,85 @@
+/* Linux fixed code userspace ABI
+
+   Copyright (C) 2005-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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, see <http://www.gnu.org/licenses/>.  */
+
+/* For more info, see this page:
+   http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:fixed-code  */
+
+.text
+
+.align 16
+_sigreturn_stub:
+       P0 = 173;
+       EXCPT 0;
+0:     JUMP.S 0b;
+
+.align 16
+_atomic_xchg32:
+       R0 = [P0];
+       [P0] = R1;
+       rts;
+
+.align 16
+_atomic_cas32:
+       R0 = [P0];
+       CC = R0 == R1;
+       IF !CC JUMP 1f;
+       [P0] = R2;
+1:
+       rts;
+
+.align 16
+_atomic_add32:
+       R1 = [P0];
+       R0 = R1 + R0;
+       [P0] = R0;
+       rts;
+
+.align 16
+_atomic_sub32:
+       R1 = [P0];
+       R0 = R1 - R0;
+       [P0] = R0;
+       rts;
+
+.align 16
+_atomic_ior32:
+       R1 = [P0];
+       R0 = R1 | R0;
+       [P0] = R0;
+       rts;
+
+.align 16
+_atomic_and32:
+       R1 = [P0];
+       R0 = R1 & R0;
+       [P0] = R0;
+       rts;
+
+.align 16
+_atomic_xor32:
+       R1 = [P0];
+       R0 = R1 ^ R0;
+       [P0] = R0;
+       rts;
+
+.align 16
+_safe_user_instruction:
+       NOP; NOP; NOP; NOP;
+       EXCPT 0x4;
diff --git a/sim/bfin/linux-targ-map.h b/sim/bfin/linux-targ-map.h
new file mode 100644 (file)
index 0000000..ca340d5
--- /dev/null
@@ -0,0 +1,1992 @@
+#if 0 /* Auto generated: sh ./targ-linux.h
+
+sed -n '1,/^#endif/p' targ-linux.h
+echo
+
+echo '#include <sys/syscall.h>' | \
+bfin-uclinux-gcc -E -dD -P - | \
+sed -r -n \
+    -e '1istatic CB_TARGET_DEFS_MAP cb_linux_syscall_map[] = {' \
+    -e '$i\ \ { -1, -1 }\n};' \
+    -e '/#define __NR_/{s:^.* __NR_(.*) (.*):#ifdef CB_SYS_\1\n# define TARGET_LINUX_SYS_\1 \2\n  { CB_SYS_\1, TARGET_LINUX_SYS_\1 },\n#endif:;p;}'
+echo
+
+echo '#include <errno.h>' | \
+bfin-uclinux-gcc -E -dD -P - | \
+sed -r -n \
+    -e '1istatic CB_TARGET_DEFS_MAP cb_linux_errno_map[] = {' \
+    -e '$i\ \ { 0, 0 }\n};' \
+    -e '/#define E.* [0-9]/{s:^.* (E.*) (.*):#ifdef \1\n# define TARGET_LINUX_\1 \2\n  { \1, TARGET_LINUX_\1 },\n#endif:;p;}'
+echo
+
+echo '#include <fcntl.h>' | \
+bfin-uclinux-gcc -E -dD -P - | \
+sed -r -n \
+    -e '1istatic CB_TARGET_DEFS_MAP cb_linux_open_map[] = {' \
+    -e '$i\ \ { -1, -1 }\n};' \
+    -e '/#define O.* [0-9]/{s:^.* (O_.*) (.*):#ifdef \1\n# define TARGET_LINUX_\1 \2\n  { \1, TARGET_LINUX_\1 },\n#endif:;p;}'
+echo
+
+# XXX: nothing uses this ?
+echo '#include <signal.h>' | \
+bfin-uclinux-gcc -E -dD -P - | \
+sed -r -n \
+    -e '1istatic CB_TARGET_DEFS_MAP cb_linux_signal_map[] = {' \
+    -e '$i\ \ { -1, -1 }\n};' \
+    -e '/#define SIG.* [0-9]+$/{s:^.* (SIG.*) (.*):#ifdef \1\n# define TARGET_LINUX_\1 \2\n  { \1, TARGET_LINUX_\1 },\n#endif:;p;}'
+
+exit 0
+*/
+#endif
+
+static CB_TARGET_DEFS_MAP cb_linux_syscall_map[] = {
+#ifdef CB_SYS_restart_syscall
+# define TARGET_LINUX_SYS_restart_syscall 0
+  { CB_SYS_restart_syscall, TARGET_LINUX_SYS_restart_syscall },
+#endif
+#ifdef CB_SYS_exit
+# define TARGET_LINUX_SYS_exit 1
+  { CB_SYS_exit, TARGET_LINUX_SYS_exit },
+#endif
+#ifdef CB_SYS_fork
+# define TARGET_LINUX_SYS_fork 2
+  { CB_SYS_fork, TARGET_LINUX_SYS_fork },
+#endif
+#ifdef CB_SYS_read
+# define TARGET_LINUX_SYS_read 3
+  { CB_SYS_read, TARGET_LINUX_SYS_read },
+#endif
+#ifdef CB_SYS_write
+# define TARGET_LINUX_SYS_write 4
+  { CB_SYS_write, TARGET_LINUX_SYS_write },
+#endif
+#ifdef CB_SYS_open
+# define TARGET_LINUX_SYS_open 5
+  { CB_SYS_open, TARGET_LINUX_SYS_open },
+#endif
+#ifdef CB_SYS_close
+# define TARGET_LINUX_SYS_close 6
+  { CB_SYS_close, TARGET_LINUX_SYS_close },
+#endif
+#ifdef CB_SYS_creat
+# define TARGET_LINUX_SYS_creat 8
+  { CB_SYS_creat, TARGET_LINUX_SYS_creat },
+#endif
+#ifdef CB_SYS_link
+# define TARGET_LINUX_SYS_link 9
+  { CB_SYS_link, TARGET_LINUX_SYS_link },
+#endif
+#ifdef CB_SYS_unlink
+# define TARGET_LINUX_SYS_unlink 10
+  { CB_SYS_unlink, TARGET_LINUX_SYS_unlink },
+#endif
+#ifdef CB_SYS_execve
+# define TARGET_LINUX_SYS_execve 11
+  { CB_SYS_execve, TARGET_LINUX_SYS_execve },
+#endif
+#ifdef CB_SYS_chdir
+# define TARGET_LINUX_SYS_chdir 12
+  { CB_SYS_chdir, TARGET_LINUX_SYS_chdir },
+#endif
+#ifdef CB_SYS_time
+# define TARGET_LINUX_SYS_time 13
+  { CB_SYS_time, TARGET_LINUX_SYS_time },
+#endif
+#ifdef CB_SYS_mknod
+# define TARGET_LINUX_SYS_mknod 14
+  { CB_SYS_mknod, TARGET_LINUX_SYS_mknod },
+#endif
+#ifdef CB_SYS_chmod
+# define TARGET_LINUX_SYS_chmod 15
+  { CB_SYS_chmod, TARGET_LINUX_SYS_chmod },
+#endif
+#ifdef CB_SYS_chown
+# define TARGET_LINUX_SYS_chown 16
+  { CB_SYS_chown, TARGET_LINUX_SYS_chown },
+#endif
+#ifdef CB_SYS_lseek
+# define TARGET_LINUX_SYS_lseek 19
+  { CB_SYS_lseek, TARGET_LINUX_SYS_lseek },
+#endif
+#ifdef CB_SYS_getpid
+# define TARGET_LINUX_SYS_getpid 20
+  { CB_SYS_getpid, TARGET_LINUX_SYS_getpid },
+#endif
+#ifdef CB_SYS_mount
+# define TARGET_LINUX_SYS_mount 21
+  { CB_SYS_mount, TARGET_LINUX_SYS_mount },
+#endif
+#ifdef CB_SYS_setuid
+# define TARGET_LINUX_SYS_setuid 23
+  { CB_SYS_setuid, TARGET_LINUX_SYS_setuid },
+#endif
+#ifdef CB_SYS_getuid
+# define TARGET_LINUX_SYS_getuid 24
+  { CB_SYS_getuid, TARGET_LINUX_SYS_getuid },
+#endif
+#ifdef CB_SYS_stime
+# define TARGET_LINUX_SYS_stime 25
+  { CB_SYS_stime, TARGET_LINUX_SYS_stime },
+#endif
+#ifdef CB_SYS_ptrace
+# define TARGET_LINUX_SYS_ptrace 26
+  { CB_SYS_ptrace, TARGET_LINUX_SYS_ptrace },
+#endif
+#ifdef CB_SYS_alarm
+# define TARGET_LINUX_SYS_alarm 27
+  { CB_SYS_alarm, TARGET_LINUX_SYS_alarm },
+#endif
+#ifdef CB_SYS_pause
+# define TARGET_LINUX_SYS_pause 29
+  { CB_SYS_pause, TARGET_LINUX_SYS_pause },
+#endif
+#ifdef CB_SYS_access
+# define TARGET_LINUX_SYS_access 33
+  { CB_SYS_access, TARGET_LINUX_SYS_access },
+#endif
+#ifdef CB_SYS_nice
+# define TARGET_LINUX_SYS_nice 34
+  { CB_SYS_nice, TARGET_LINUX_SYS_nice },
+#endif
+#ifdef CB_SYS_sync
+# define TARGET_LINUX_SYS_sync 36
+  { CB_SYS_sync, TARGET_LINUX_SYS_sync },
+#endif
+#ifdef CB_SYS_kill
+# define TARGET_LINUX_SYS_kill 37
+  { CB_SYS_kill, TARGET_LINUX_SYS_kill },
+#endif
+#ifdef CB_SYS_rename
+# define TARGET_LINUX_SYS_rename 38
+  { CB_SYS_rename, TARGET_LINUX_SYS_rename },
+#endif
+#ifdef CB_SYS_mkdir
+# define TARGET_LINUX_SYS_mkdir 39
+  { CB_SYS_mkdir, TARGET_LINUX_SYS_mkdir },
+#endif
+#ifdef CB_SYS_rmdir
+# define TARGET_LINUX_SYS_rmdir 40
+  { CB_SYS_rmdir, TARGET_LINUX_SYS_rmdir },
+#endif
+#ifdef CB_SYS_dup
+# define TARGET_LINUX_SYS_dup 41
+  { CB_SYS_dup, TARGET_LINUX_SYS_dup },
+#endif
+#ifdef CB_SYS_pipe
+# define TARGET_LINUX_SYS_pipe 42
+  { CB_SYS_pipe, TARGET_LINUX_SYS_pipe },
+#endif
+#ifdef CB_SYS_times
+# define TARGET_LINUX_SYS_times 43
+  { CB_SYS_times, TARGET_LINUX_SYS_times },
+#endif
+#ifdef CB_SYS_brk
+# define TARGET_LINUX_SYS_brk 45
+  { CB_SYS_brk, TARGET_LINUX_SYS_brk },
+#endif
+#ifdef CB_SYS_setgid
+# define TARGET_LINUX_SYS_setgid 46
+  { CB_SYS_setgid, TARGET_LINUX_SYS_setgid },
+#endif
+#ifdef CB_SYS_getgid
+# define TARGET_LINUX_SYS_getgid 47
+  { CB_SYS_getgid, TARGET_LINUX_SYS_getgid },
+#endif
+#ifdef CB_SYS_geteuid
+# define TARGET_LINUX_SYS_geteuid 49
+  { CB_SYS_geteuid, TARGET_LINUX_SYS_geteuid },
+#endif
+#ifdef CB_SYS_getegid
+# define TARGET_LINUX_SYS_getegid 50
+  { CB_SYS_getegid, TARGET_LINUX_SYS_getegid },
+#endif
+#ifdef CB_SYS_acct
+# define TARGET_LINUX_SYS_acct 51
+  { CB_SYS_acct, TARGET_LINUX_SYS_acct },
+#endif
+#ifdef CB_SYS_umount2
+# define TARGET_LINUX_SYS_umount2 52
+  { CB_SYS_umount2, TARGET_LINUX_SYS_umount2 },
+#endif
+#ifdef CB_SYS_ioctl
+# define TARGET_LINUX_SYS_ioctl 54
+  { CB_SYS_ioctl, TARGET_LINUX_SYS_ioctl },
+#endif
+#ifdef CB_SYS_fcntl
+# define TARGET_LINUX_SYS_fcntl 55
+  { CB_SYS_fcntl, TARGET_LINUX_SYS_fcntl },
+#endif
+#ifdef CB_SYS_setpgid
+# define TARGET_LINUX_SYS_setpgid 57
+  { CB_SYS_setpgid, TARGET_LINUX_SYS_setpgid },
+#endif
+#ifdef CB_SYS_umask
+# define TARGET_LINUX_SYS_umask 60
+  { CB_SYS_umask, TARGET_LINUX_SYS_umask },
+#endif
+#ifdef CB_SYS_chroot
+# define TARGET_LINUX_SYS_chroot 61
+  { CB_SYS_chroot, TARGET_LINUX_SYS_chroot },
+#endif
+#ifdef CB_SYS_ustat
+# define TARGET_LINUX_SYS_ustat 62
+  { CB_SYS_ustat, TARGET_LINUX_SYS_ustat },
+#endif
+#ifdef CB_SYS_dup2
+# define TARGET_LINUX_SYS_dup2 63
+  { CB_SYS_dup2, TARGET_LINUX_SYS_dup2 },
+#endif
+#ifdef CB_SYS_getppid
+# define TARGET_LINUX_SYS_getppid 64
+  { CB_SYS_getppid, TARGET_LINUX_SYS_getppid },
+#endif
+#ifdef CB_SYS_getpgrp
+# define TARGET_LINUX_SYS_getpgrp 65
+  { CB_SYS_getpgrp, TARGET_LINUX_SYS_getpgrp },
+#endif
+#ifdef CB_SYS_setsid
+# define TARGET_LINUX_SYS_setsid 66
+  { CB_SYS_setsid, TARGET_LINUX_SYS_setsid },
+#endif
+#ifdef CB_SYS_sgetmask
+# define TARGET_LINUX_SYS_sgetmask 68
+  { CB_SYS_sgetmask, TARGET_LINUX_SYS_sgetmask },
+#endif
+#ifdef CB_SYS_ssetmask
+# define TARGET_LINUX_SYS_ssetmask 69
+  { CB_SYS_ssetmask, TARGET_LINUX_SYS_ssetmask },
+#endif
+#ifdef CB_SYS_setreuid
+# define TARGET_LINUX_SYS_setreuid 70
+  { CB_SYS_setreuid, TARGET_LINUX_SYS_setreuid },
+#endif
+#ifdef CB_SYS_setregid
+# define TARGET_LINUX_SYS_setregid 71
+  { CB_SYS_setregid, TARGET_LINUX_SYS_setregid },
+#endif
+#ifdef CB_SYS_sethostname
+# define TARGET_LINUX_SYS_sethostname 74
+  { CB_SYS_sethostname, TARGET_LINUX_SYS_sethostname },
+#endif
+#ifdef CB_SYS_setrlimit
+# define TARGET_LINUX_SYS_setrlimit 75
+  { CB_SYS_setrlimit, TARGET_LINUX_SYS_setrlimit },
+#endif
+#ifdef CB_SYS_getrusage
+# define TARGET_LINUX_SYS_getrusage 77
+  { CB_SYS_getrusage, TARGET_LINUX_SYS_getrusage },
+#endif
+#ifdef CB_SYS_gettimeofday
+# define TARGET_LINUX_SYS_gettimeofday 78
+  { CB_SYS_gettimeofday, TARGET_LINUX_SYS_gettimeofday },
+#endif
+#ifdef CB_SYS_settimeofday
+# define TARGET_LINUX_SYS_settimeofday 79
+  { CB_SYS_settimeofday, TARGET_LINUX_SYS_settimeofday },
+#endif
+#ifdef CB_SYS_getgroups
+# define TARGET_LINUX_SYS_getgroups 80
+  { CB_SYS_getgroups, TARGET_LINUX_SYS_getgroups },
+#endif
+#ifdef CB_SYS_setgroups
+# define TARGET_LINUX_SYS_setgroups 81
+  { CB_SYS_setgroups, TARGET_LINUX_SYS_setgroups },
+#endif
+#ifdef CB_SYS_symlink
+# define TARGET_LINUX_SYS_symlink 83
+  { CB_SYS_symlink, TARGET_LINUX_SYS_symlink },
+#endif
+#ifdef CB_SYS_readlink
+# define TARGET_LINUX_SYS_readlink 85
+  { CB_SYS_readlink, TARGET_LINUX_SYS_readlink },
+#endif
+#ifdef CB_SYS_reboot
+# define TARGET_LINUX_SYS_reboot 88
+  { CB_SYS_reboot, TARGET_LINUX_SYS_reboot },
+#endif
+#ifdef CB_SYS_munmap
+# define TARGET_LINUX_SYS_munmap 91
+  { CB_SYS_munmap, TARGET_LINUX_SYS_munmap },
+#endif
+#ifdef CB_SYS_truncate
+# define TARGET_LINUX_SYS_truncate 92
+  { CB_SYS_truncate, TARGET_LINUX_SYS_truncate },
+#endif
+#ifdef CB_SYS_ftruncate
+# define TARGET_LINUX_SYS_ftruncate 93
+  { CB_SYS_ftruncate, TARGET_LINUX_SYS_ftruncate },
+#endif
+#ifdef CB_SYS_fchmod
+# define TARGET_LINUX_SYS_fchmod 94
+  { CB_SYS_fchmod, TARGET_LINUX_SYS_fchmod },
+#endif
+#ifdef CB_SYS_fchown
+# define TARGET_LINUX_SYS_fchown 95
+  { CB_SYS_fchown, TARGET_LINUX_SYS_fchown },
+#endif
+#ifdef CB_SYS_getpriority
+# define TARGET_LINUX_SYS_getpriority 96
+  { CB_SYS_getpriority, TARGET_LINUX_SYS_getpriority },
+#endif
+#ifdef CB_SYS_setpriority
+# define TARGET_LINUX_SYS_setpriority 97
+  { CB_SYS_setpriority, TARGET_LINUX_SYS_setpriority },
+#endif
+#ifdef CB_SYS_statfs
+# define TARGET_LINUX_SYS_statfs 99
+  { CB_SYS_statfs, TARGET_LINUX_SYS_statfs },
+#endif
+#ifdef CB_SYS_fstatfs
+# define TARGET_LINUX_SYS_fstatfs 100
+  { CB_SYS_fstatfs, TARGET_LINUX_SYS_fstatfs },
+#endif
+#ifdef CB_SYS_syslog
+# define TARGET_LINUX_SYS_syslog 103
+  { CB_SYS_syslog, TARGET_LINUX_SYS_syslog },
+#endif
+#ifdef CB_SYS_setitimer
+# define TARGET_LINUX_SYS_setitimer 104
+  { CB_SYS_setitimer, TARGET_LINUX_SYS_setitimer },
+#endif
+#ifdef CB_SYS_getitimer
+# define TARGET_LINUX_SYS_getitimer 105
+  { CB_SYS_getitimer, TARGET_LINUX_SYS_getitimer },
+#endif
+#ifdef CB_SYS_stat
+# define TARGET_LINUX_SYS_stat 106
+  { CB_SYS_stat, TARGET_LINUX_SYS_stat },
+#endif
+#ifdef CB_SYS_lstat
+# define TARGET_LINUX_SYS_lstat 107
+  { CB_SYS_lstat, TARGET_LINUX_SYS_lstat },
+#endif
+#ifdef CB_SYS_fstat
+# define TARGET_LINUX_SYS_fstat 108
+  { CB_SYS_fstat, TARGET_LINUX_SYS_fstat },
+#endif
+#ifdef CB_SYS_vhangup
+# define TARGET_LINUX_SYS_vhangup 111
+  { CB_SYS_vhangup, TARGET_LINUX_SYS_vhangup },
+#endif
+#ifdef CB_SYS_wait4
+# define TARGET_LINUX_SYS_wait4 114
+  { CB_SYS_wait4, TARGET_LINUX_SYS_wait4 },
+#endif
+#ifdef CB_SYS_sysinfo
+# define TARGET_LINUX_SYS_sysinfo 116
+  { CB_SYS_sysinfo, TARGET_LINUX_SYS_sysinfo },
+#endif
+#ifdef CB_SYS_fsync
+# define TARGET_LINUX_SYS_fsync 118
+  { CB_SYS_fsync, TARGET_LINUX_SYS_fsync },
+#endif
+#ifdef CB_SYS_clone
+# define TARGET_LINUX_SYS_clone 120
+  { CB_SYS_clone, TARGET_LINUX_SYS_clone },
+#endif
+#ifdef CB_SYS_setdomainname
+# define TARGET_LINUX_SYS_setdomainname 121
+  { CB_SYS_setdomainname, TARGET_LINUX_SYS_setdomainname },
+#endif
+#ifdef CB_SYS_uname
+# define TARGET_LINUX_SYS_uname 122
+  { CB_SYS_uname, TARGET_LINUX_SYS_uname },
+#endif
+#ifdef CB_SYS_adjtimex
+# define TARGET_LINUX_SYS_adjtimex 124
+  { CB_SYS_adjtimex, TARGET_LINUX_SYS_adjtimex },
+#endif
+#ifdef CB_SYS_mprotect
+# define TARGET_LINUX_SYS_mprotect 125
+  { CB_SYS_mprotect, TARGET_LINUX_SYS_mprotect },
+#endif
+#ifdef CB_SYS_init_module
+# define TARGET_LINUX_SYS_init_module 128
+  { CB_SYS_init_module, TARGET_LINUX_SYS_init_module },
+#endif
+#ifdef CB_SYS_delete_module
+# define TARGET_LINUX_SYS_delete_module 129
+  { CB_SYS_delete_module, TARGET_LINUX_SYS_delete_module },
+#endif
+#ifdef CB_SYS_quotactl
+# define TARGET_LINUX_SYS_quotactl 131
+  { CB_SYS_quotactl, TARGET_LINUX_SYS_quotactl },
+#endif
+#ifdef CB_SYS_getpgid
+# define TARGET_LINUX_SYS_getpgid 132
+  { CB_SYS_getpgid, TARGET_LINUX_SYS_getpgid },
+#endif
+#ifdef CB_SYS_fchdir
+# define TARGET_LINUX_SYS_fchdir 133
+  { CB_SYS_fchdir, TARGET_LINUX_SYS_fchdir },
+#endif
+#ifdef CB_SYS_bdflush
+# define TARGET_LINUX_SYS_bdflush 134
+  { CB_SYS_bdflush, TARGET_LINUX_SYS_bdflush },
+#endif
+#ifdef CB_SYS_personality
+# define TARGET_LINUX_SYS_personality 136
+  { CB_SYS_personality, TARGET_LINUX_SYS_personality },
+#endif
+#ifdef CB_SYS_setfsuid
+# define TARGET_LINUX_SYS_setfsuid 138
+  { CB_SYS_setfsuid, TARGET_LINUX_SYS_setfsuid },
+#endif
+#ifdef CB_SYS_setfsgid
+# define TARGET_LINUX_SYS_setfsgid 139
+  { CB_SYS_setfsgid, TARGET_LINUX_SYS_setfsgid },
+#endif
+#ifdef CB_SYS__llseek
+# define TARGET_LINUX_SYS__llseek 140
+  { CB_SYS__llseek, TARGET_LINUX_SYS__llseek },
+#endif
+#ifdef CB_SYS_getdents
+# define TARGET_LINUX_SYS_getdents 141
+  { CB_SYS_getdents, TARGET_LINUX_SYS_getdents },
+#endif
+#ifdef CB_SYS_flock
+# define TARGET_LINUX_SYS_flock 143
+  { CB_SYS_flock, TARGET_LINUX_SYS_flock },
+#endif
+#ifdef CB_SYS_readv
+# define TARGET_LINUX_SYS_readv 145
+  { CB_SYS_readv, TARGET_LINUX_SYS_readv },
+#endif
+#ifdef CB_SYS_writev
+# define TARGET_LINUX_SYS_writev 146
+  { CB_SYS_writev, TARGET_LINUX_SYS_writev },
+#endif
+#ifdef CB_SYS_getsid
+# define TARGET_LINUX_SYS_getsid 147
+  { CB_SYS_getsid, TARGET_LINUX_SYS_getsid },
+#endif
+#ifdef CB_SYS_fdatasync
+# define TARGET_LINUX_SYS_fdatasync 148
+  { CB_SYS_fdatasync, TARGET_LINUX_SYS_fdatasync },
+#endif
+#ifdef CB_SYS__sysctl
+# define TARGET_LINUX_SYS__sysctl 149
+  { CB_SYS__sysctl, TARGET_LINUX_SYS__sysctl },
+#endif
+#ifdef CB_SYS_sched_setparam
+# define TARGET_LINUX_SYS_sched_setparam 154
+  { CB_SYS_sched_setparam, TARGET_LINUX_SYS_sched_setparam },
+#endif
+#ifdef CB_SYS_sched_getparam
+# define TARGET_LINUX_SYS_sched_getparam 155
+  { CB_SYS_sched_getparam, TARGET_LINUX_SYS_sched_getparam },
+#endif
+#ifdef CB_SYS_sched_setscheduler
+# define TARGET_LINUX_SYS_sched_setscheduler 156
+  { CB_SYS_sched_setscheduler, TARGET_LINUX_SYS_sched_setscheduler },
+#endif
+#ifdef CB_SYS_sched_getscheduler
+# define TARGET_LINUX_SYS_sched_getscheduler 157
+  { CB_SYS_sched_getscheduler, TARGET_LINUX_SYS_sched_getscheduler },
+#endif
+#ifdef CB_SYS_sched_yield
+# define TARGET_LINUX_SYS_sched_yield 158
+  { CB_SYS_sched_yield, TARGET_LINUX_SYS_sched_yield },
+#endif
+#ifdef CB_SYS_sched_get_priority_max
+# define TARGET_LINUX_SYS_sched_get_priority_max 159
+  { CB_SYS_sched_get_priority_max, TARGET_LINUX_SYS_sched_get_priority_max },
+#endif
+#ifdef CB_SYS_sched_get_priority_min
+# define TARGET_LINUX_SYS_sched_get_priority_min 160
+  { CB_SYS_sched_get_priority_min, TARGET_LINUX_SYS_sched_get_priority_min },
+#endif
+#ifdef CB_SYS_sched_rr_get_interval
+# define TARGET_LINUX_SYS_sched_rr_get_interval 161
+  { CB_SYS_sched_rr_get_interval, TARGET_LINUX_SYS_sched_rr_get_interval },
+#endif
+#ifdef CB_SYS_nanosleep
+# define TARGET_LINUX_SYS_nanosleep 162
+  { CB_SYS_nanosleep, TARGET_LINUX_SYS_nanosleep },
+#endif
+#ifdef CB_SYS_mremap
+# define TARGET_LINUX_SYS_mremap 163
+  { CB_SYS_mremap, TARGET_LINUX_SYS_mremap },
+#endif
+#ifdef CB_SYS_setresuid
+# define TARGET_LINUX_SYS_setresuid 164
+  { CB_SYS_setresuid, TARGET_LINUX_SYS_setresuid },
+#endif
+#ifdef CB_SYS_getresuid
+# define TARGET_LINUX_SYS_getresuid 165
+  { CB_SYS_getresuid, TARGET_LINUX_SYS_getresuid },
+#endif
+#ifdef CB_SYS_nfsservctl
+# define TARGET_LINUX_SYS_nfsservctl 169
+  { CB_SYS_nfsservctl, TARGET_LINUX_SYS_nfsservctl },
+#endif
+#ifdef CB_SYS_setresgid
+# define TARGET_LINUX_SYS_setresgid 170
+  { CB_SYS_setresgid, TARGET_LINUX_SYS_setresgid },
+#endif
+#ifdef CB_SYS_getresgid
+# define TARGET_LINUX_SYS_getresgid 171
+  { CB_SYS_getresgid, TARGET_LINUX_SYS_getresgid },
+#endif
+#ifdef CB_SYS_prctl
+# define TARGET_LINUX_SYS_prctl 172
+  { CB_SYS_prctl, TARGET_LINUX_SYS_prctl },
+#endif
+#ifdef CB_SYS_rt_sigreturn
+# define TARGET_LINUX_SYS_rt_sigreturn 173
+  { CB_SYS_rt_sigreturn, TARGET_LINUX_SYS_rt_sigreturn },
+#endif
+#ifdef CB_SYS_rt_sigaction
+# define TARGET_LINUX_SYS_rt_sigaction 174
+  { CB_SYS_rt_sigaction, TARGET_LINUX_SYS_rt_sigaction },
+#endif
+#ifdef CB_SYS_rt_sigprocmask
+# define TARGET_LINUX_SYS_rt_sigprocmask 175
+  { CB_SYS_rt_sigprocmask, TARGET_LINUX_SYS_rt_sigprocmask },
+#endif
+#ifdef CB_SYS_rt_sigpending
+# define TARGET_LINUX_SYS_rt_sigpending 176
+  { CB_SYS_rt_sigpending, TARGET_LINUX_SYS_rt_sigpending },
+#endif
+#ifdef CB_SYS_rt_sigtimedwait
+# define TARGET_LINUX_SYS_rt_sigtimedwait 177
+  { CB_SYS_rt_sigtimedwait, TARGET_LINUX_SYS_rt_sigtimedwait },
+#endif
+#ifdef CB_SYS_rt_sigqueueinfo
+# define TARGET_LINUX_SYS_rt_sigqueueinfo 178
+  { CB_SYS_rt_sigqueueinfo, TARGET_LINUX_SYS_rt_sigqueueinfo },
+#endif
+#ifdef CB_SYS_rt_sigsuspend
+# define TARGET_LINUX_SYS_rt_sigsuspend 179
+  { CB_SYS_rt_sigsuspend, TARGET_LINUX_SYS_rt_sigsuspend },
+#endif
+#ifdef CB_SYS_pread
+# define TARGET_LINUX_SYS_pread 180
+  { CB_SYS_pread, TARGET_LINUX_SYS_pread },
+#endif
+#ifdef CB_SYS_pwrite
+# define TARGET_LINUX_SYS_pwrite 181
+  { CB_SYS_pwrite, TARGET_LINUX_SYS_pwrite },
+#endif
+#ifdef CB_SYS_lchown
+# define TARGET_LINUX_SYS_lchown 182
+  { CB_SYS_lchown, TARGET_LINUX_SYS_lchown },
+#endif
+#ifdef CB_SYS_getcwd
+# define TARGET_LINUX_SYS_getcwd 183
+  { CB_SYS_getcwd, TARGET_LINUX_SYS_getcwd },
+#endif
+#ifdef CB_SYS_capget
+# define TARGET_LINUX_SYS_capget 184
+  { CB_SYS_capget, TARGET_LINUX_SYS_capget },
+#endif
+#ifdef CB_SYS_capset
+# define TARGET_LINUX_SYS_capset 185
+  { CB_SYS_capset, TARGET_LINUX_SYS_capset },
+#endif
+#ifdef CB_SYS_sigaltstack
+# define TARGET_LINUX_SYS_sigaltstack 186
+  { CB_SYS_sigaltstack, TARGET_LINUX_SYS_sigaltstack },
+#endif
+#ifdef CB_SYS_sendfile
+# define TARGET_LINUX_SYS_sendfile 187
+  { CB_SYS_sendfile, TARGET_LINUX_SYS_sendfile },
+#endif
+#ifdef CB_SYS_vfork
+# define TARGET_LINUX_SYS_vfork 190
+  { CB_SYS_vfork, TARGET_LINUX_SYS_vfork },
+#endif
+#ifdef CB_SYS_getrlimit
+# define TARGET_LINUX_SYS_getrlimit 191
+  { CB_SYS_getrlimit, TARGET_LINUX_SYS_getrlimit },
+#endif
+#ifdef CB_SYS_mmap2
+# define TARGET_LINUX_SYS_mmap2 192
+  { CB_SYS_mmap2, TARGET_LINUX_SYS_mmap2 },
+#endif
+#ifdef CB_SYS_truncate64
+# define TARGET_LINUX_SYS_truncate64 193
+  { CB_SYS_truncate64, TARGET_LINUX_SYS_truncate64 },
+#endif
+#ifdef CB_SYS_ftruncate64
+# define TARGET_LINUX_SYS_ftruncate64 194
+  { CB_SYS_ftruncate64, TARGET_LINUX_SYS_ftruncate64 },
+#endif
+#ifdef CB_SYS_stat64
+# define TARGET_LINUX_SYS_stat64 195
+  { CB_SYS_stat64, TARGET_LINUX_SYS_stat64 },
+#endif
+#ifdef CB_SYS_lstat64
+# define TARGET_LINUX_SYS_lstat64 196
+  { CB_SYS_lstat64, TARGET_LINUX_SYS_lstat64 },
+#endif
+#ifdef CB_SYS_fstat64
+# define TARGET_LINUX_SYS_fstat64 197
+  { CB_SYS_fstat64, TARGET_LINUX_SYS_fstat64 },
+#endif
+#ifdef CB_SYS_chown32
+# define TARGET_LINUX_SYS_chown32 198
+  { CB_SYS_chown32, TARGET_LINUX_SYS_chown32 },
+#endif
+#ifdef CB_SYS_getuid32
+# define TARGET_LINUX_SYS_getuid32 199
+  { CB_SYS_getuid32, TARGET_LINUX_SYS_getuid32 },
+#endif
+#ifdef CB_SYS_getgid32
+# define TARGET_LINUX_SYS_getgid32 200
+  { CB_SYS_getgid32, TARGET_LINUX_SYS_getgid32 },
+#endif
+#ifdef CB_SYS_geteuid32
+# define TARGET_LINUX_SYS_geteuid32 201
+  { CB_SYS_geteuid32, TARGET_LINUX_SYS_geteuid32 },
+#endif
+#ifdef CB_SYS_getegid32
+# define TARGET_LINUX_SYS_getegid32 202
+  { CB_SYS_getegid32, TARGET_LINUX_SYS_getegid32 },
+#endif
+#ifdef CB_SYS_setreuid32
+# define TARGET_LINUX_SYS_setreuid32 203
+  { CB_SYS_setreuid32, TARGET_LINUX_SYS_setreuid32 },
+#endif
+#ifdef CB_SYS_setregid32
+# define TARGET_LINUX_SYS_setregid32 204
+  { CB_SYS_setregid32, TARGET_LINUX_SYS_setregid32 },
+#endif
+#ifdef CB_SYS_getgroups32
+# define TARGET_LINUX_SYS_getgroups32 205
+  { CB_SYS_getgroups32, TARGET_LINUX_SYS_getgroups32 },
+#endif
+#ifdef CB_SYS_setgroups32
+# define TARGET_LINUX_SYS_setgroups32 206
+  { CB_SYS_setgroups32, TARGET_LINUX_SYS_setgroups32 },
+#endif
+#ifdef CB_SYS_fchown32
+# define TARGET_LINUX_SYS_fchown32 207
+  { CB_SYS_fchown32, TARGET_LINUX_SYS_fchown32 },
+#endif
+#ifdef CB_SYS_setresuid32
+# define TARGET_LINUX_SYS_setresuid32 208
+  { CB_SYS_setresuid32, TARGET_LINUX_SYS_setresuid32 },
+#endif
+#ifdef CB_SYS_getresuid32
+# define TARGET_LINUX_SYS_getresuid32 209
+  { CB_SYS_getresuid32, TARGET_LINUX_SYS_getresuid32 },
+#endif
+#ifdef CB_SYS_setresgid32
+# define TARGET_LINUX_SYS_setresgid32 210
+  { CB_SYS_setresgid32, TARGET_LINUX_SYS_setresgid32 },
+#endif
+#ifdef CB_SYS_getresgid32
+# define TARGET_LINUX_SYS_getresgid32 211
+  { CB_SYS_getresgid32, TARGET_LINUX_SYS_getresgid32 },
+#endif
+#ifdef CB_SYS_lchown32
+# define TARGET_LINUX_SYS_lchown32 212
+  { CB_SYS_lchown32, TARGET_LINUX_SYS_lchown32 },
+#endif
+#ifdef CB_SYS_setuid32
+# define TARGET_LINUX_SYS_setuid32 213
+  { CB_SYS_setuid32, TARGET_LINUX_SYS_setuid32 },
+#endif
+#ifdef CB_SYS_setgid32
+# define TARGET_LINUX_SYS_setgid32 214
+  { CB_SYS_setgid32, TARGET_LINUX_SYS_setgid32 },
+#endif
+#ifdef CB_SYS_setfsuid32
+# define TARGET_LINUX_SYS_setfsuid32 215
+  { CB_SYS_setfsuid32, TARGET_LINUX_SYS_setfsuid32 },
+#endif
+#ifdef CB_SYS_setfsgid32
+# define TARGET_LINUX_SYS_setfsgid32 216
+  { CB_SYS_setfsgid32, TARGET_LINUX_SYS_setfsgid32 },
+#endif
+#ifdef CB_SYS_pivot_root
+# define TARGET_LINUX_SYS_pivot_root 217
+  { CB_SYS_pivot_root, TARGET_LINUX_SYS_pivot_root },
+#endif
+#ifdef CB_SYS_getdents64
+# define TARGET_LINUX_SYS_getdents64 220
+  { CB_SYS_getdents64, TARGET_LINUX_SYS_getdents64 },
+#endif
+#ifdef CB_SYS_fcntl64
+# define TARGET_LINUX_SYS_fcntl64 221
+  { CB_SYS_fcntl64, TARGET_LINUX_SYS_fcntl64 },
+#endif
+#ifdef CB_SYS_gettid
+# define TARGET_LINUX_SYS_gettid 224
+  { CB_SYS_gettid, TARGET_LINUX_SYS_gettid },
+#endif
+#ifdef CB_SYS_readahead
+# define TARGET_LINUX_SYS_readahead 225
+  { CB_SYS_readahead, TARGET_LINUX_SYS_readahead },
+#endif
+#ifdef CB_SYS_setxattr
+# define TARGET_LINUX_SYS_setxattr 226
+  { CB_SYS_setxattr, TARGET_LINUX_SYS_setxattr },
+#endif
+#ifdef CB_SYS_lsetxattr
+# define TARGET_LINUX_SYS_lsetxattr 227
+  { CB_SYS_lsetxattr, TARGET_LINUX_SYS_lsetxattr },
+#endif
+#ifdef CB_SYS_fsetxattr
+# define TARGET_LINUX_SYS_fsetxattr 228
+  { CB_SYS_fsetxattr, TARGET_LINUX_SYS_fsetxattr },
+#endif
+#ifdef CB_SYS_getxattr
+# define TARGET_LINUX_SYS_getxattr 229
+  { CB_SYS_getxattr, TARGET_LINUX_SYS_getxattr },
+#endif
+#ifdef CB_SYS_lgetxattr
+# define TARGET_LINUX_SYS_lgetxattr 230
+  { CB_SYS_lgetxattr, TARGET_LINUX_SYS_lgetxattr },
+#endif
+#ifdef CB_SYS_fgetxattr
+# define TARGET_LINUX_SYS_fgetxattr 231
+  { CB_SYS_fgetxattr, TARGET_LINUX_SYS_fgetxattr },
+#endif
+#ifdef CB_SYS_listxattr
+# define TARGET_LINUX_SYS_listxattr 232
+  { CB_SYS_listxattr, TARGET_LINUX_SYS_listxattr },
+#endif
+#ifdef CB_SYS_llistxattr
+# define TARGET_LINUX_SYS_llistxattr 233
+  { CB_SYS_llistxattr, TARGET_LINUX_SYS_llistxattr },
+#endif
+#ifdef CB_SYS_flistxattr
+# define TARGET_LINUX_SYS_flistxattr 234
+  { CB_SYS_flistxattr, TARGET_LINUX_SYS_flistxattr },
+#endif
+#ifdef CB_SYS_removexattr
+# define TARGET_LINUX_SYS_removexattr 235
+  { CB_SYS_removexattr, TARGET_LINUX_SYS_removexattr },
+#endif
+#ifdef CB_SYS_lremovexattr
+# define TARGET_LINUX_SYS_lremovexattr 236
+  { CB_SYS_lremovexattr, TARGET_LINUX_SYS_lremovexattr },
+#endif
+#ifdef CB_SYS_fremovexattr
+# define TARGET_LINUX_SYS_fremovexattr 237
+  { CB_SYS_fremovexattr, TARGET_LINUX_SYS_fremovexattr },
+#endif
+#ifdef CB_SYS_tkill
+# define TARGET_LINUX_SYS_tkill 238
+  { CB_SYS_tkill, TARGET_LINUX_SYS_tkill },
+#endif
+#ifdef CB_SYS_sendfile64
+# define TARGET_LINUX_SYS_sendfile64 239
+  { CB_SYS_sendfile64, TARGET_LINUX_SYS_sendfile64 },
+#endif
+#ifdef CB_SYS_futex
+# define TARGET_LINUX_SYS_futex 240
+  { CB_SYS_futex, TARGET_LINUX_SYS_futex },
+#endif
+#ifdef CB_SYS_sched_setaffinity
+# define TARGET_LINUX_SYS_sched_setaffinity 241
+  { CB_SYS_sched_setaffinity, TARGET_LINUX_SYS_sched_setaffinity },
+#endif
+#ifdef CB_SYS_sched_getaffinity
+# define TARGET_LINUX_SYS_sched_getaffinity 242
+  { CB_SYS_sched_getaffinity, TARGET_LINUX_SYS_sched_getaffinity },
+#endif
+#ifdef CB_SYS_io_setup
+# define TARGET_LINUX_SYS_io_setup 245
+  { CB_SYS_io_setup, TARGET_LINUX_SYS_io_setup },
+#endif
+#ifdef CB_SYS_io_destroy
+# define TARGET_LINUX_SYS_io_destroy 246
+  { CB_SYS_io_destroy, TARGET_LINUX_SYS_io_destroy },
+#endif
+#ifdef CB_SYS_io_getevents
+# define TARGET_LINUX_SYS_io_getevents 247
+  { CB_SYS_io_getevents, TARGET_LINUX_SYS_io_getevents },
+#endif
+#ifdef CB_SYS_io_submit
+# define TARGET_LINUX_SYS_io_submit 248
+  { CB_SYS_io_submit, TARGET_LINUX_SYS_io_submit },
+#endif
+#ifdef CB_SYS_io_cancel
+# define TARGET_LINUX_SYS_io_cancel 249
+  { CB_SYS_io_cancel, TARGET_LINUX_SYS_io_cancel },
+#endif
+#ifdef CB_SYS_exit_group
+# define TARGET_LINUX_SYS_exit_group 252
+  { CB_SYS_exit_group, TARGET_LINUX_SYS_exit_group },
+#endif
+#ifdef CB_SYS_lookup_dcookie
+# define TARGET_LINUX_SYS_lookup_dcookie 253
+  { CB_SYS_lookup_dcookie, TARGET_LINUX_SYS_lookup_dcookie },
+#endif
+#ifdef CB_SYS_bfin_spinlock
+# define TARGET_LINUX_SYS_bfin_spinlock 254
+  { CB_SYS_bfin_spinlock, TARGET_LINUX_SYS_bfin_spinlock },
+#endif
+#ifdef CB_SYS_epoll_create
+# define TARGET_LINUX_SYS_epoll_create 255
+  { CB_SYS_epoll_create, TARGET_LINUX_SYS_epoll_create },
+#endif
+#ifdef CB_SYS_epoll_ctl
+# define TARGET_LINUX_SYS_epoll_ctl 256
+  { CB_SYS_epoll_ctl, TARGET_LINUX_SYS_epoll_ctl },
+#endif
+#ifdef CB_SYS_epoll_wait
+# define TARGET_LINUX_SYS_epoll_wait 257
+  { CB_SYS_epoll_wait, TARGET_LINUX_SYS_epoll_wait },
+#endif
+#ifdef CB_SYS_set_tid_address
+# define TARGET_LINUX_SYS_set_tid_address 259
+  { CB_SYS_set_tid_address, TARGET_LINUX_SYS_set_tid_address },
+#endif
+#ifdef CB_SYS_timer_create
+# define TARGET_LINUX_SYS_timer_create 260
+  { CB_SYS_timer_create, TARGET_LINUX_SYS_timer_create },
+#endif
+#ifdef CB_SYS_timer_settime
+# define TARGET_LINUX_SYS_timer_settime 261
+  { CB_SYS_timer_settime, TARGET_LINUX_SYS_timer_settime },
+#endif
+#ifdef CB_SYS_timer_gettime
+# define TARGET_LINUX_SYS_timer_gettime 262
+  { CB_SYS_timer_gettime, TARGET_LINUX_SYS_timer_gettime },
+#endif
+#ifdef CB_SYS_timer_getoverrun
+# define TARGET_LINUX_SYS_timer_getoverrun 263
+  { CB_SYS_timer_getoverrun, TARGET_LINUX_SYS_timer_getoverrun },
+#endif
+#ifdef CB_SYS_timer_delete
+# define TARGET_LINUX_SYS_timer_delete 264
+  { CB_SYS_timer_delete, TARGET_LINUX_SYS_timer_delete },
+#endif
+#ifdef CB_SYS_clock_settime
+# define TARGET_LINUX_SYS_clock_settime 265
+  { CB_SYS_clock_settime, TARGET_LINUX_SYS_clock_settime },
+#endif
+#ifdef CB_SYS_clock_gettime
+# define TARGET_LINUX_SYS_clock_gettime 266
+  { CB_SYS_clock_gettime, TARGET_LINUX_SYS_clock_gettime },
+#endif
+#ifdef CB_SYS_clock_getres
+# define TARGET_LINUX_SYS_clock_getres 267
+  { CB_SYS_clock_getres, TARGET_LINUX_SYS_clock_getres },
+#endif
+#ifdef CB_SYS_clock_nanosleep
+# define TARGET_LINUX_SYS_clock_nanosleep 268
+  { CB_SYS_clock_nanosleep, TARGET_LINUX_SYS_clock_nanosleep },
+#endif
+#ifdef CB_SYS_statfs64
+# define TARGET_LINUX_SYS_statfs64 269
+  { CB_SYS_statfs64, TARGET_LINUX_SYS_statfs64 },
+#endif
+#ifdef CB_SYS_fstatfs64
+# define TARGET_LINUX_SYS_fstatfs64 270
+  { CB_SYS_fstatfs64, TARGET_LINUX_SYS_fstatfs64 },
+#endif
+#ifdef CB_SYS_tgkill
+# define TARGET_LINUX_SYS_tgkill 271
+  { CB_SYS_tgkill, TARGET_LINUX_SYS_tgkill },
+#endif
+#ifdef CB_SYS_utimes
+# define TARGET_LINUX_SYS_utimes 272
+  { CB_SYS_utimes, TARGET_LINUX_SYS_utimes },
+#endif
+#ifdef CB_SYS_fadvise64_64
+# define TARGET_LINUX_SYS_fadvise64_64 273
+  { CB_SYS_fadvise64_64, TARGET_LINUX_SYS_fadvise64_64 },
+#endif
+#ifdef CB_SYS_mq_open
+# define TARGET_LINUX_SYS_mq_open 278
+  { CB_SYS_mq_open, TARGET_LINUX_SYS_mq_open },
+#endif
+#ifdef CB_SYS_mq_unlink
+# define TARGET_LINUX_SYS_mq_unlink 279
+  { CB_SYS_mq_unlink, TARGET_LINUX_SYS_mq_unlink },
+#endif
+#ifdef CB_SYS_mq_timedsend
+# define TARGET_LINUX_SYS_mq_timedsend 280
+  { CB_SYS_mq_timedsend, TARGET_LINUX_SYS_mq_timedsend },
+#endif
+#ifdef CB_SYS_mq_timedreceive
+# define TARGET_LINUX_SYS_mq_timedreceive 281
+  { CB_SYS_mq_timedreceive, TARGET_LINUX_SYS_mq_timedreceive },
+#endif
+#ifdef CB_SYS_mq_notify
+# define TARGET_LINUX_SYS_mq_notify 282
+  { CB_SYS_mq_notify, TARGET_LINUX_SYS_mq_notify },
+#endif
+#ifdef CB_SYS_mq_getsetattr
+# define TARGET_LINUX_SYS_mq_getsetattr 283
+  { CB_SYS_mq_getsetattr, TARGET_LINUX_SYS_mq_getsetattr },
+#endif
+#ifdef CB_SYS_kexec_load
+# define TARGET_LINUX_SYS_kexec_load 284
+  { CB_SYS_kexec_load, TARGET_LINUX_SYS_kexec_load },
+#endif
+#ifdef CB_SYS_waitid
+# define TARGET_LINUX_SYS_waitid 285
+  { CB_SYS_waitid, TARGET_LINUX_SYS_waitid },
+#endif
+#ifdef CB_SYS_add_key
+# define TARGET_LINUX_SYS_add_key 286
+  { CB_SYS_add_key, TARGET_LINUX_SYS_add_key },
+#endif
+#ifdef CB_SYS_request_key
+# define TARGET_LINUX_SYS_request_key 287
+  { CB_SYS_request_key, TARGET_LINUX_SYS_request_key },
+#endif
+#ifdef CB_SYS_keyctl
+# define TARGET_LINUX_SYS_keyctl 288
+  { CB_SYS_keyctl, TARGET_LINUX_SYS_keyctl },
+#endif
+#ifdef CB_SYS_ioprio_set
+# define TARGET_LINUX_SYS_ioprio_set 289
+  { CB_SYS_ioprio_set, TARGET_LINUX_SYS_ioprio_set },
+#endif
+#ifdef CB_SYS_ioprio_get
+# define TARGET_LINUX_SYS_ioprio_get 290
+  { CB_SYS_ioprio_get, TARGET_LINUX_SYS_ioprio_get },
+#endif
+#ifdef CB_SYS_inotify_init
+# define TARGET_LINUX_SYS_inotify_init 291
+  { CB_SYS_inotify_init, TARGET_LINUX_SYS_inotify_init },
+#endif
+#ifdef CB_SYS_inotify_add_watch
+# define TARGET_LINUX_SYS_inotify_add_watch 292
+  { CB_SYS_inotify_add_watch, TARGET_LINUX_SYS_inotify_add_watch },
+#endif
+#ifdef CB_SYS_inotify_rm_watch
+# define TARGET_LINUX_SYS_inotify_rm_watch 293
+  { CB_SYS_inotify_rm_watch, TARGET_LINUX_SYS_inotify_rm_watch },
+#endif
+#ifdef CB_SYS_openat
+# define TARGET_LINUX_SYS_openat 295
+  { CB_SYS_openat, TARGET_LINUX_SYS_openat },
+#endif
+#ifdef CB_SYS_mkdirat
+# define TARGET_LINUX_SYS_mkdirat 296
+  { CB_SYS_mkdirat, TARGET_LINUX_SYS_mkdirat },
+#endif
+#ifdef CB_SYS_mknodat
+# define TARGET_LINUX_SYS_mknodat 297
+  { CB_SYS_mknodat, TARGET_LINUX_SYS_mknodat },
+#endif
+#ifdef CB_SYS_fchownat
+# define TARGET_LINUX_SYS_fchownat 298
+  { CB_SYS_fchownat, TARGET_LINUX_SYS_fchownat },
+#endif
+#ifdef CB_SYS_futimesat
+# define TARGET_LINUX_SYS_futimesat 299
+  { CB_SYS_futimesat, TARGET_LINUX_SYS_futimesat },
+#endif
+#ifdef CB_SYS_fstatat64
+# define TARGET_LINUX_SYS_fstatat64 300
+  { CB_SYS_fstatat64, TARGET_LINUX_SYS_fstatat64 },
+#endif
+#ifdef CB_SYS_unlinkat
+# define TARGET_LINUX_SYS_unlinkat 301
+  { CB_SYS_unlinkat, TARGET_LINUX_SYS_unlinkat },
+#endif
+#ifdef CB_SYS_renameat
+# define TARGET_LINUX_SYS_renameat 302
+  { CB_SYS_renameat, TARGET_LINUX_SYS_renameat },
+#endif
+#ifdef CB_SYS_linkat
+# define TARGET_LINUX_SYS_linkat 303
+  { CB_SYS_linkat, TARGET_LINUX_SYS_linkat },
+#endif
+#ifdef CB_SYS_symlinkat
+# define TARGET_LINUX_SYS_symlinkat 304
+  { CB_SYS_symlinkat, TARGET_LINUX_SYS_symlinkat },
+#endif
+#ifdef CB_SYS_readlinkat
+# define TARGET_LINUX_SYS_readlinkat 305
+  { CB_SYS_readlinkat, TARGET_LINUX_SYS_readlinkat },
+#endif
+#ifdef CB_SYS_fchmodat
+# define TARGET_LINUX_SYS_fchmodat 306
+  { CB_SYS_fchmodat, TARGET_LINUX_SYS_fchmodat },
+#endif
+#ifdef CB_SYS_faccessat
+# define TARGET_LINUX_SYS_faccessat 307
+  { CB_SYS_faccessat, TARGET_LINUX_SYS_faccessat },
+#endif
+#ifdef CB_SYS_pselect6
+# define TARGET_LINUX_SYS_pselect6 308
+  { CB_SYS_pselect6, TARGET_LINUX_SYS_pselect6 },
+#endif
+#ifdef CB_SYS_ppoll
+# define TARGET_LINUX_SYS_ppoll 309
+  { CB_SYS_ppoll, TARGET_LINUX_SYS_ppoll },
+#endif
+#ifdef CB_SYS_unshare
+# define TARGET_LINUX_SYS_unshare 310
+  { CB_SYS_unshare, TARGET_LINUX_SYS_unshare },
+#endif
+#ifdef CB_SYS_sram_alloc
+# define TARGET_LINUX_SYS_sram_alloc 311
+  { CB_SYS_sram_alloc, TARGET_LINUX_SYS_sram_alloc },
+#endif
+#ifdef CB_SYS_sram_free
+# define TARGET_LINUX_SYS_sram_free 312
+  { CB_SYS_sram_free, TARGET_LINUX_SYS_sram_free },
+#endif
+#ifdef CB_SYS_dma_memcpy
+# define TARGET_LINUX_SYS_dma_memcpy 313
+  { CB_SYS_dma_memcpy, TARGET_LINUX_SYS_dma_memcpy },
+#endif
+#ifdef CB_SYS_accept
+# define TARGET_LINUX_SYS_accept 314
+  { CB_SYS_accept, TARGET_LINUX_SYS_accept },
+#endif
+#ifdef CB_SYS_bind
+# define TARGET_LINUX_SYS_bind 315
+  { CB_SYS_bind, TARGET_LINUX_SYS_bind },
+#endif
+#ifdef CB_SYS_connect
+# define TARGET_LINUX_SYS_connect 316
+  { CB_SYS_connect, TARGET_LINUX_SYS_connect },
+#endif
+#ifdef CB_SYS_getpeername
+# define TARGET_LINUX_SYS_getpeername 317
+  { CB_SYS_getpeername, TARGET_LINUX_SYS_getpeername },
+#endif
+#ifdef CB_SYS_getsockname
+# define TARGET_LINUX_SYS_getsockname 318
+  { CB_SYS_getsockname, TARGET_LINUX_SYS_getsockname },
+#endif
+#ifdef CB_SYS_getsockopt
+# define TARGET_LINUX_SYS_getsockopt 319
+  { CB_SYS_getsockopt, TARGET_LINUX_SYS_getsockopt },
+#endif
+#ifdef CB_SYS_listen
+# define TARGET_LINUX_SYS_listen 320
+  { CB_SYS_listen, TARGET_LINUX_SYS_listen },
+#endif
+#ifdef CB_SYS_recv
+# define TARGET_LINUX_SYS_recv 321
+  { CB_SYS_recv, TARGET_LINUX_SYS_recv },
+#endif
+#ifdef CB_SYS_recvfrom
+# define TARGET_LINUX_SYS_recvfrom 322
+  { CB_SYS_recvfrom, TARGET_LINUX_SYS_recvfrom },
+#endif
+#ifdef CB_SYS_recvmsg
+# define TARGET_LINUX_SYS_recvmsg 323
+  { CB_SYS_recvmsg, TARGET_LINUX_SYS_recvmsg },
+#endif
+#ifdef CB_SYS_send
+# define TARGET_LINUX_SYS_send 324
+  { CB_SYS_send, TARGET_LINUX_SYS_send },
+#endif
+#ifdef CB_SYS_sendmsg
+# define TARGET_LINUX_SYS_sendmsg 325
+  { CB_SYS_sendmsg, TARGET_LINUX_SYS_sendmsg },
+#endif
+#ifdef CB_SYS_sendto
+# define TARGET_LINUX_SYS_sendto 326
+  { CB_SYS_sendto, TARGET_LINUX_SYS_sendto },
+#endif
+#ifdef CB_SYS_setsockopt
+# define TARGET_LINUX_SYS_setsockopt 327
+  { CB_SYS_setsockopt, TARGET_LINUX_SYS_setsockopt },
+#endif
+#ifdef CB_SYS_shutdown
+# define TARGET_LINUX_SYS_shutdown 328
+  { CB_SYS_shutdown, TARGET_LINUX_SYS_shutdown },
+#endif
+#ifdef CB_SYS_socket
+# define TARGET_LINUX_SYS_socket 329
+  { CB_SYS_socket, TARGET_LINUX_SYS_socket },
+#endif
+#ifdef CB_SYS_socketpair
+# define TARGET_LINUX_SYS_socketpair 330
+  { CB_SYS_socketpair, TARGET_LINUX_SYS_socketpair },
+#endif
+#ifdef CB_SYS_semctl
+# define TARGET_LINUX_SYS_semctl 331
+  { CB_SYS_semctl, TARGET_LINUX_SYS_semctl },
+#endif
+#ifdef CB_SYS_semget
+# define TARGET_LINUX_SYS_semget 332
+  { CB_SYS_semget, TARGET_LINUX_SYS_semget },
+#endif
+#ifdef CB_SYS_semop
+# define TARGET_LINUX_SYS_semop 333
+  { CB_SYS_semop, TARGET_LINUX_SYS_semop },
+#endif
+#ifdef CB_SYS_msgctl
+# define TARGET_LINUX_SYS_msgctl 334
+  { CB_SYS_msgctl, TARGET_LINUX_SYS_msgctl },
+#endif
+#ifdef CB_SYS_msgget
+# define TARGET_LINUX_SYS_msgget 335
+  { CB_SYS_msgget, TARGET_LINUX_SYS_msgget },
+#endif
+#ifdef CB_SYS_msgrcv
+# define TARGET_LINUX_SYS_msgrcv 336
+  { CB_SYS_msgrcv, TARGET_LINUX_SYS_msgrcv },
+#endif
+#ifdef CB_SYS_msgsnd
+# define TARGET_LINUX_SYS_msgsnd 337
+  { CB_SYS_msgsnd, TARGET_LINUX_SYS_msgsnd },
+#endif
+#ifdef CB_SYS_shmat
+# define TARGET_LINUX_SYS_shmat 338
+  { CB_SYS_shmat, TARGET_LINUX_SYS_shmat },
+#endif
+#ifdef CB_SYS_shmctl
+# define TARGET_LINUX_SYS_shmctl 339
+  { CB_SYS_shmctl, TARGET_LINUX_SYS_shmctl },
+#endif
+#ifdef CB_SYS_shmdt
+# define TARGET_LINUX_SYS_shmdt 340
+  { CB_SYS_shmdt, TARGET_LINUX_SYS_shmdt },
+#endif
+#ifdef CB_SYS_shmget
+# define TARGET_LINUX_SYS_shmget 341
+  { CB_SYS_shmget, TARGET_LINUX_SYS_shmget },
+#endif
+#ifdef CB_SYS_splice
+# define TARGET_LINUX_SYS_splice 342
+  { CB_SYS_splice, TARGET_LINUX_SYS_splice },
+#endif
+#ifdef CB_SYS_sync_file_range
+# define TARGET_LINUX_SYS_sync_file_range 343
+  { CB_SYS_sync_file_range, TARGET_LINUX_SYS_sync_file_range },
+#endif
+#ifdef CB_SYS_tee
+# define TARGET_LINUX_SYS_tee 344
+  { CB_SYS_tee, TARGET_LINUX_SYS_tee },
+#endif
+#ifdef CB_SYS_vmsplice
+# define TARGET_LINUX_SYS_vmsplice 345
+  { CB_SYS_vmsplice, TARGET_LINUX_SYS_vmsplice },
+#endif
+#ifdef CB_SYS_epoll_pwait
+# define TARGET_LINUX_SYS_epoll_pwait 346
+  { CB_SYS_epoll_pwait, TARGET_LINUX_SYS_epoll_pwait },
+#endif
+#ifdef CB_SYS_utimensat
+# define TARGET_LINUX_SYS_utimensat 347
+  { CB_SYS_utimensat, TARGET_LINUX_SYS_utimensat },
+#endif
+#ifdef CB_SYS_signalfd
+# define TARGET_LINUX_SYS_signalfd 348
+  { CB_SYS_signalfd, TARGET_LINUX_SYS_signalfd },
+#endif
+#ifdef CB_SYS_timerfd_create
+# define TARGET_LINUX_SYS_timerfd_create 349
+  { CB_SYS_timerfd_create, TARGET_LINUX_SYS_timerfd_create },
+#endif
+#ifdef CB_SYS_eventfd
+# define TARGET_LINUX_SYS_eventfd 350
+  { CB_SYS_eventfd, TARGET_LINUX_SYS_eventfd },
+#endif
+#ifdef CB_SYS_pread64
+# define TARGET_LINUX_SYS_pread64 351
+  { CB_SYS_pread64, TARGET_LINUX_SYS_pread64 },
+#endif
+#ifdef CB_SYS_pwrite64
+# define TARGET_LINUX_SYS_pwrite64 352
+  { CB_SYS_pwrite64, TARGET_LINUX_SYS_pwrite64 },
+#endif
+#ifdef CB_SYS_fadvise64
+# define TARGET_LINUX_SYS_fadvise64 353
+  { CB_SYS_fadvise64, TARGET_LINUX_SYS_fadvise64 },
+#endif
+#ifdef CB_SYS_set_robust_list
+# define TARGET_LINUX_SYS_set_robust_list 354
+  { CB_SYS_set_robust_list, TARGET_LINUX_SYS_set_robust_list },
+#endif
+#ifdef CB_SYS_get_robust_list
+# define TARGET_LINUX_SYS_get_robust_list 355
+  { CB_SYS_get_robust_list, TARGET_LINUX_SYS_get_robust_list },
+#endif
+#ifdef CB_SYS_fallocate
+# define TARGET_LINUX_SYS_fallocate 356
+  { CB_SYS_fallocate, TARGET_LINUX_SYS_fallocate },
+#endif
+#ifdef CB_SYS_semtimedop
+# define TARGET_LINUX_SYS_semtimedop 357
+  { CB_SYS_semtimedop, TARGET_LINUX_SYS_semtimedop },
+#endif
+#ifdef CB_SYS_timerfd_settime
+# define TARGET_LINUX_SYS_timerfd_settime 358
+  { CB_SYS_timerfd_settime, TARGET_LINUX_SYS_timerfd_settime },
+#endif
+#ifdef CB_SYS_timerfd_gettime
+# define TARGET_LINUX_SYS_timerfd_gettime 359
+  { CB_SYS_timerfd_gettime, TARGET_LINUX_SYS_timerfd_gettime },
+#endif
+#ifdef CB_SYS_signalfd4
+# define TARGET_LINUX_SYS_signalfd4 360
+  { CB_SYS_signalfd4, TARGET_LINUX_SYS_signalfd4 },
+#endif
+#ifdef CB_SYS_eventfd2
+# define TARGET_LINUX_SYS_eventfd2 361
+  { CB_SYS_eventfd2, TARGET_LINUX_SYS_eventfd2 },
+#endif
+#ifdef CB_SYS_epoll_create1
+# define TARGET_LINUX_SYS_epoll_create1 362
+  { CB_SYS_epoll_create1, TARGET_LINUX_SYS_epoll_create1 },
+#endif
+#ifdef CB_SYS_dup3
+# define TARGET_LINUX_SYS_dup3 363
+  { CB_SYS_dup3, TARGET_LINUX_SYS_dup3 },
+#endif
+#ifdef CB_SYS_pipe2
+# define TARGET_LINUX_SYS_pipe2 364
+  { CB_SYS_pipe2, TARGET_LINUX_SYS_pipe2 },
+#endif
+#ifdef CB_SYS_inotify_init1
+# define TARGET_LINUX_SYS_inotify_init1 365
+  { CB_SYS_inotify_init1, TARGET_LINUX_SYS_inotify_init1 },
+#endif
+#ifdef CB_SYS_preadv
+# define TARGET_LINUX_SYS_preadv 366
+  { CB_SYS_preadv, TARGET_LINUX_SYS_preadv },
+#endif
+#ifdef CB_SYS_pwritev
+# define TARGET_LINUX_SYS_pwritev 367
+  { CB_SYS_pwritev, TARGET_LINUX_SYS_pwritev },
+#endif
+#ifdef CB_SYS_rt_tgsigqueueinfo
+# define TARGET_LINUX_SYS_rt_tgsigqueueinfo 368
+  { CB_SYS_rt_tgsigqueueinfo, TARGET_LINUX_SYS_rt_tgsigqueueinfo },
+#endif
+#ifdef CB_SYS_perf_event_open
+# define TARGET_LINUX_SYS_perf_event_open 369
+  { CB_SYS_perf_event_open, TARGET_LINUX_SYS_perf_event_open },
+#endif
+#ifdef CB_SYS_recvmmsg
+# define TARGET_LINUX_SYS_recvmmsg 370
+  { CB_SYS_recvmmsg, TARGET_LINUX_SYS_recvmmsg },
+#endif
+#ifdef CB_SYS_fanotify_init
+# define TARGET_LINUX_SYS_fanotify_init 371
+  { CB_SYS_fanotify_init, TARGET_LINUX_SYS_fanotify_init },
+#endif
+#ifdef CB_SYS_fanotify_mark
+# define TARGET_LINUX_SYS_fanotify_mark 372
+  { CB_SYS_fanotify_mark, TARGET_LINUX_SYS_fanotify_mark },
+#endif
+#ifdef CB_SYS_prlimit64
+# define TARGET_LINUX_SYS_prlimit64 373
+  { CB_SYS_prlimit64, TARGET_LINUX_SYS_prlimit64 },
+#endif
+#ifdef CB_SYS_cacheflush
+# define TARGET_LINUX_SYS_cacheflush 374
+  { CB_SYS_cacheflush, TARGET_LINUX_SYS_cacheflush },
+#endif
+#ifdef CB_SYS_syscall
+# define TARGET_LINUX_SYS_syscall 375
+  { CB_SYS_syscall, TARGET_LINUX_SYS_syscall },
+#endif
+  { -1, -1 }
+};
+
+static CB_TARGET_DEFS_MAP cb_linux_errno_map[] = {
+#ifdef EPERM
+# define TARGET_LINUX_EPERM 1
+  { EPERM, TARGET_LINUX_EPERM },
+#endif
+#ifdef ENOENT
+# define TARGET_LINUX_ENOENT 2
+  { ENOENT, TARGET_LINUX_ENOENT },
+#endif
+#ifdef ESRCH
+# define TARGET_LINUX_ESRCH 3
+  { ESRCH, TARGET_LINUX_ESRCH },
+#endif
+#ifdef EINTR
+# define TARGET_LINUX_EINTR 4
+  { EINTR, TARGET_LINUX_EINTR },
+#endif
+#ifdef EIO
+# define TARGET_LINUX_EIO 5
+  { EIO, TARGET_LINUX_EIO },
+#endif
+#ifdef ENXIO
+# define TARGET_LINUX_ENXIO 6
+  { ENXIO, TARGET_LINUX_ENXIO },
+#endif
+#ifdef E2BIG
+# define TARGET_LINUX_E2BIG 7
+  { E2BIG, TARGET_LINUX_E2BIG },
+#endif
+#ifdef ENOEXEC
+# define TARGET_LINUX_ENOEXEC 8
+  { ENOEXEC, TARGET_LINUX_ENOEXEC },
+#endif
+#ifdef EBADF
+# define TARGET_LINUX_EBADF 9
+  { EBADF, TARGET_LINUX_EBADF },
+#endif
+#ifdef ECHILD
+# define TARGET_LINUX_ECHILD 10
+  { ECHILD, TARGET_LINUX_ECHILD },
+#endif
+#ifdef EAGAIN
+# define TARGET_LINUX_EAGAIN 11
+  { EAGAIN, TARGET_LINUX_EAGAIN },
+#endif
+#ifdef ENOMEM
+# define TARGET_LINUX_ENOMEM 12
+  { ENOMEM, TARGET_LINUX_ENOMEM },
+#endif
+#ifdef EACCES
+# define TARGET_LINUX_EACCES 13
+  { EACCES, TARGET_LINUX_EACCES },
+#endif
+#ifdef EFAULT
+# define TARGET_LINUX_EFAULT 14
+  { EFAULT, TARGET_LINUX_EFAULT },
+#endif
+#ifdef ENOTBLK
+# define TARGET_LINUX_ENOTBLK 15
+  { ENOTBLK, TARGET_LINUX_ENOTBLK },
+#endif
+#ifdef EBUSY
+# define TARGET_LINUX_EBUSY 16
+  { EBUSY, TARGET_LINUX_EBUSY },
+#endif
+#ifdef EEXIST
+# define TARGET_LINUX_EEXIST 17
+  { EEXIST, TARGET_LINUX_EEXIST },
+#endif
+#ifdef EXDEV
+# define TARGET_LINUX_EXDEV 18
+  { EXDEV, TARGET_LINUX_EXDEV },
+#endif
+#ifdef ENODEV
+# define TARGET_LINUX_ENODEV 19
+  { ENODEV, TARGET_LINUX_ENODEV },
+#endif
+#ifdef ENOTDIR
+# define TARGET_LINUX_ENOTDIR 20
+  { ENOTDIR, TARGET_LINUX_ENOTDIR },
+#endif
+#ifdef EISDIR
+# define TARGET_LINUX_EISDIR 21
+  { EISDIR, TARGET_LINUX_EISDIR },
+#endif
+#ifdef EINVAL
+# define TARGET_LINUX_EINVAL 22
+  { EINVAL, TARGET_LINUX_EINVAL },
+#endif
+#ifdef ENFILE
+# define TARGET_LINUX_ENFILE 23
+  { ENFILE, TARGET_LINUX_ENFILE },
+#endif
+#ifdef EMFILE
+# define TARGET_LINUX_EMFILE 24
+  { EMFILE, TARGET_LINUX_EMFILE },
+#endif
+#ifdef ENOTTY
+# define TARGET_LINUX_ENOTTY 25
+  { ENOTTY, TARGET_LINUX_ENOTTY },
+#endif
+#ifdef ETXTBSY
+# define TARGET_LINUX_ETXTBSY 26
+  { ETXTBSY, TARGET_LINUX_ETXTBSY },
+#endif
+#ifdef EFBIG
+# define TARGET_LINUX_EFBIG 27
+  { EFBIG, TARGET_LINUX_EFBIG },
+#endif
+#ifdef ENOSPC
+# define TARGET_LINUX_ENOSPC 28
+  { ENOSPC, TARGET_LINUX_ENOSPC },
+#endif
+#ifdef ESPIPE
+# define TARGET_LINUX_ESPIPE 29
+  { ESPIPE, TARGET_LINUX_ESPIPE },
+#endif
+#ifdef EROFS
+# define TARGET_LINUX_EROFS 30
+  { EROFS, TARGET_LINUX_EROFS },
+#endif
+#ifdef EMLINK
+# define TARGET_LINUX_EMLINK 31
+  { EMLINK, TARGET_LINUX_EMLINK },
+#endif
+#ifdef EPIPE
+# define TARGET_LINUX_EPIPE 32
+  { EPIPE, TARGET_LINUX_EPIPE },
+#endif
+#ifdef EDOM
+# define TARGET_LINUX_EDOM 33
+  { EDOM, TARGET_LINUX_EDOM },
+#endif
+#ifdef ERANGE
+# define TARGET_LINUX_ERANGE 34
+  { ERANGE, TARGET_LINUX_ERANGE },
+#endif
+#ifdef EDEADLK
+# define TARGET_LINUX_EDEADLK 35
+  { EDEADLK, TARGET_LINUX_EDEADLK },
+#endif
+#ifdef ENAMETOOLONG
+# define TARGET_LINUX_ENAMETOOLONG 36
+  { ENAMETOOLONG, TARGET_LINUX_ENAMETOOLONG },
+#endif
+#ifdef ENOLCK
+# define TARGET_LINUX_ENOLCK 37
+  { ENOLCK, TARGET_LINUX_ENOLCK },
+#endif
+#ifdef ENOSYS
+# define TARGET_LINUX_ENOSYS 38
+  { ENOSYS, TARGET_LINUX_ENOSYS },
+#endif
+#ifdef ENOTEMPTY
+# define TARGET_LINUX_ENOTEMPTY 39
+  { ENOTEMPTY, TARGET_LINUX_ENOTEMPTY },
+#endif
+#ifdef ELOOP
+# define TARGET_LINUX_ELOOP 40
+  { ELOOP, TARGET_LINUX_ELOOP },
+#endif
+#ifdef ENOMSG
+# define TARGET_LINUX_ENOMSG 42
+  { ENOMSG, TARGET_LINUX_ENOMSG },
+#endif
+#ifdef EIDRM
+# define TARGET_LINUX_EIDRM 43
+  { EIDRM, TARGET_LINUX_EIDRM },
+#endif
+#ifdef ECHRNG
+# define TARGET_LINUX_ECHRNG 44
+  { ECHRNG, TARGET_LINUX_ECHRNG },
+#endif
+#ifdef EL2NSYNC
+# define TARGET_LINUX_EL2NSYNC 45
+  { EL2NSYNC, TARGET_LINUX_EL2NSYNC },
+#endif
+#ifdef EL3HLT
+# define TARGET_LINUX_EL3HLT 46
+  { EL3HLT, TARGET_LINUX_EL3HLT },
+#endif
+#ifdef EL3RST
+# define TARGET_LINUX_EL3RST 47
+  { EL3RST, TARGET_LINUX_EL3RST },
+#endif
+#ifdef ELNRNG
+# define TARGET_LINUX_ELNRNG 48
+  { ELNRNG, TARGET_LINUX_ELNRNG },
+#endif
+#ifdef EUNATCH
+# define TARGET_LINUX_EUNATCH 49
+  { EUNATCH, TARGET_LINUX_EUNATCH },
+#endif
+#ifdef ENOCSI
+# define TARGET_LINUX_ENOCSI 50
+  { ENOCSI, TARGET_LINUX_ENOCSI },
+#endif
+#ifdef EL2HLT
+# define TARGET_LINUX_EL2HLT 51
+  { EL2HLT, TARGET_LINUX_EL2HLT },
+#endif
+#ifdef EBADE
+# define TARGET_LINUX_EBADE 52
+  { EBADE, TARGET_LINUX_EBADE },
+#endif
+#ifdef EBADR
+# define TARGET_LINUX_EBADR 53
+  { EBADR, TARGET_LINUX_EBADR },
+#endif
+#ifdef EXFULL
+# define TARGET_LINUX_EXFULL 54
+  { EXFULL, TARGET_LINUX_EXFULL },
+#endif
+#ifdef ENOANO
+# define TARGET_LINUX_ENOANO 55
+  { ENOANO, TARGET_LINUX_ENOANO },
+#endif
+#ifdef EBADRQC
+# define TARGET_LINUX_EBADRQC 56
+  { EBADRQC, TARGET_LINUX_EBADRQC },
+#endif
+#ifdef EBADSLT
+# define TARGET_LINUX_EBADSLT 57
+  { EBADSLT, TARGET_LINUX_EBADSLT },
+#endif
+#ifdef EBFONT
+# define TARGET_LINUX_EBFONT 59
+  { EBFONT, TARGET_LINUX_EBFONT },
+#endif
+#ifdef ENOSTR
+# define TARGET_LINUX_ENOSTR 60
+  { ENOSTR, TARGET_LINUX_ENOSTR },
+#endif
+#ifdef ENODATA
+# define TARGET_LINUX_ENODATA 61
+  { ENODATA, TARGET_LINUX_ENODATA },
+#endif
+#ifdef ETIME
+# define TARGET_LINUX_ETIME 62
+  { ETIME, TARGET_LINUX_ETIME },
+#endif
+#ifdef ENOSR
+# define TARGET_LINUX_ENOSR 63
+  { ENOSR, TARGET_LINUX_ENOSR },
+#endif
+#ifdef ENONET
+# define TARGET_LINUX_ENONET 64
+  { ENONET, TARGET_LINUX_ENONET },
+#endif
+#ifdef ENOPKG
+# define TARGET_LINUX_ENOPKG 65
+  { ENOPKG, TARGET_LINUX_ENOPKG },
+#endif
+#ifdef EREMOTE
+# define TARGET_LINUX_EREMOTE 66
+  { EREMOTE, TARGET_LINUX_EREMOTE },
+#endif
+#ifdef ENOLINK
+# define TARGET_LINUX_ENOLINK 67
+  { ENOLINK, TARGET_LINUX_ENOLINK },
+#endif
+#ifdef EADV
+# define TARGET_LINUX_EADV 68
+  { EADV, TARGET_LINUX_EADV },
+#endif
+#ifdef ESRMNT
+# define TARGET_LINUX_ESRMNT 69
+  { ESRMNT, TARGET_LINUX_ESRMNT },
+#endif
+#ifdef ECOMM
+# define TARGET_LINUX_ECOMM 70
+  { ECOMM, TARGET_LINUX_ECOMM },
+#endif
+#ifdef EPROTO
+# define TARGET_LINUX_EPROTO 71
+  { EPROTO, TARGET_LINUX_EPROTO },
+#endif
+#ifdef EMULTIHOP
+# define TARGET_LINUX_EMULTIHOP 72
+  { EMULTIHOP, TARGET_LINUX_EMULTIHOP },
+#endif
+#ifdef EDOTDOT
+# define TARGET_LINUX_EDOTDOT 73
+  { EDOTDOT, TARGET_LINUX_EDOTDOT },
+#endif
+#ifdef EBADMSG
+# define TARGET_LINUX_EBADMSG 74
+  { EBADMSG, TARGET_LINUX_EBADMSG },
+#endif
+#ifdef EOVERFLOW
+# define TARGET_LINUX_EOVERFLOW 75
+  { EOVERFLOW, TARGET_LINUX_EOVERFLOW },
+#endif
+#ifdef ENOTUNIQ
+# define TARGET_LINUX_ENOTUNIQ 76
+  { ENOTUNIQ, TARGET_LINUX_ENOTUNIQ },
+#endif
+#ifdef EBADFD
+# define TARGET_LINUX_EBADFD 77
+  { EBADFD, TARGET_LINUX_EBADFD },
+#endif
+#ifdef EREMCHG
+# define TARGET_LINUX_EREMCHG 78
+  { EREMCHG, TARGET_LINUX_EREMCHG },
+#endif
+#ifdef ELIBACC
+# define TARGET_LINUX_ELIBACC 79
+  { ELIBACC, TARGET_LINUX_ELIBACC },
+#endif
+#ifdef ELIBBAD
+# define TARGET_LINUX_ELIBBAD 80
+  { ELIBBAD, TARGET_LINUX_ELIBBAD },
+#endif
+#ifdef ELIBSCN
+# define TARGET_LINUX_ELIBSCN 81
+  { ELIBSCN, TARGET_LINUX_ELIBSCN },
+#endif
+#ifdef ELIBMAX
+# define TARGET_LINUX_ELIBMAX 82
+  { ELIBMAX, TARGET_LINUX_ELIBMAX },
+#endif
+#ifdef ELIBEXEC
+# define TARGET_LINUX_ELIBEXEC 83
+  { ELIBEXEC, TARGET_LINUX_ELIBEXEC },
+#endif
+#ifdef EILSEQ
+# define TARGET_LINUX_EILSEQ 84
+  { EILSEQ, TARGET_LINUX_EILSEQ },
+#endif
+#ifdef ERESTART
+# define TARGET_LINUX_ERESTART 85
+  { ERESTART, TARGET_LINUX_ERESTART },
+#endif
+#ifdef ESTRPIPE
+# define TARGET_LINUX_ESTRPIPE 86
+  { ESTRPIPE, TARGET_LINUX_ESTRPIPE },
+#endif
+#ifdef EUSERS
+# define TARGET_LINUX_EUSERS 87
+  { EUSERS, TARGET_LINUX_EUSERS },
+#endif
+#ifdef ENOTSOCK
+# define TARGET_LINUX_ENOTSOCK 88
+  { ENOTSOCK, TARGET_LINUX_ENOTSOCK },
+#endif
+#ifdef EDESTADDRREQ
+# define TARGET_LINUX_EDESTADDRREQ 89
+  { EDESTADDRREQ, TARGET_LINUX_EDESTADDRREQ },
+#endif
+#ifdef EMSGSIZE
+# define TARGET_LINUX_EMSGSIZE 90
+  { EMSGSIZE, TARGET_LINUX_EMSGSIZE },
+#endif
+#ifdef EPROTOTYPE
+# define TARGET_LINUX_EPROTOTYPE 91
+  { EPROTOTYPE, TARGET_LINUX_EPROTOTYPE },
+#endif
+#ifdef ENOPROTOOPT
+# define TARGET_LINUX_ENOPROTOOPT 92
+  { ENOPROTOOPT, TARGET_LINUX_ENOPROTOOPT },
+#endif
+#ifdef EPROTONOSUPPORT
+# define TARGET_LINUX_EPROTONOSUPPORT 93
+  { EPROTONOSUPPORT, TARGET_LINUX_EPROTONOSUPPORT },
+#endif
+#ifdef ESOCKTNOSUPPORT
+# define TARGET_LINUX_ESOCKTNOSUPPORT 94
+  { ESOCKTNOSUPPORT, TARGET_LINUX_ESOCKTNOSUPPORT },
+#endif
+#ifdef EOPNOTSUPP
+# define TARGET_LINUX_EOPNOTSUPP 95
+  { EOPNOTSUPP, TARGET_LINUX_EOPNOTSUPP },
+#endif
+#ifdef EPFNOSUPPORT
+# define TARGET_LINUX_EPFNOSUPPORT 96
+  { EPFNOSUPPORT, TARGET_LINUX_EPFNOSUPPORT },
+#endif
+#ifdef EAFNOSUPPORT
+# define TARGET_LINUX_EAFNOSUPPORT 97
+  { EAFNOSUPPORT, TARGET_LINUX_EAFNOSUPPORT },
+#endif
+#ifdef EADDRINUSE
+# define TARGET_LINUX_EADDRINUSE 98
+  { EADDRINUSE, TARGET_LINUX_EADDRINUSE },
+#endif
+#ifdef EADDRNOTAVAIL
+# define TARGET_LINUX_EADDRNOTAVAIL 99
+  { EADDRNOTAVAIL, TARGET_LINUX_EADDRNOTAVAIL },
+#endif
+#ifdef ENETDOWN
+# define TARGET_LINUX_ENETDOWN 100
+  { ENETDOWN, TARGET_LINUX_ENETDOWN },
+#endif
+#ifdef ENETUNREACH
+# define TARGET_LINUX_ENETUNREACH 101
+  { ENETUNREACH, TARGET_LINUX_ENETUNREACH },
+#endif
+#ifdef ENETRESET
+# define TARGET_LINUX_ENETRESET 102
+  { ENETRESET, TARGET_LINUX_ENETRESET },
+#endif
+#ifdef ECONNABORTED
+# define TARGET_LINUX_ECONNABORTED 103
+  { ECONNABORTED, TARGET_LINUX_ECONNABORTED },
+#endif
+#ifdef ECONNRESET
+# define TARGET_LINUX_ECONNRESET 104
+  { ECONNRESET, TARGET_LINUX_ECONNRESET },
+#endif
+#ifdef ENOBUFS
+# define TARGET_LINUX_ENOBUFS 105
+  { ENOBUFS, TARGET_LINUX_ENOBUFS },
+#endif
+#ifdef EISCONN
+# define TARGET_LINUX_EISCONN 106
+  { EISCONN, TARGET_LINUX_EISCONN },
+#endif
+#ifdef ENOTCONN
+# define TARGET_LINUX_ENOTCONN 107
+  { ENOTCONN, TARGET_LINUX_ENOTCONN },
+#endif
+#ifdef ESHUTDOWN
+# define TARGET_LINUX_ESHUTDOWN 108
+  { ESHUTDOWN, TARGET_LINUX_ESHUTDOWN },
+#endif
+#ifdef ETOOMANYREFS
+# define TARGET_LINUX_ETOOMANYREFS 109
+  { ETOOMANYREFS, TARGET_LINUX_ETOOMANYREFS },
+#endif
+#ifdef ETIMEDOUT
+# define TARGET_LINUX_ETIMEDOUT 110
+  { ETIMEDOUT, TARGET_LINUX_ETIMEDOUT },
+#endif
+#ifdef ECONNREFUSED
+# define TARGET_LINUX_ECONNREFUSED 111
+  { ECONNREFUSED, TARGET_LINUX_ECONNREFUSED },
+#endif
+#ifdef EHOSTDOWN
+# define TARGET_LINUX_EHOSTDOWN 112
+  { EHOSTDOWN, TARGET_LINUX_EHOSTDOWN },
+#endif
+#ifdef EHOSTUNREACH
+# define TARGET_LINUX_EHOSTUNREACH 113
+  { EHOSTUNREACH, TARGET_LINUX_EHOSTUNREACH },
+#endif
+#ifdef EALREADY
+# define TARGET_LINUX_EALREADY 114
+  { EALREADY, TARGET_LINUX_EALREADY },
+#endif
+#ifdef EINPROGRESS
+# define TARGET_LINUX_EINPROGRESS 115
+  { EINPROGRESS, TARGET_LINUX_EINPROGRESS },
+#endif
+#ifdef ESTALE
+# define TARGET_LINUX_ESTALE 116
+  { ESTALE, TARGET_LINUX_ESTALE },
+#endif
+#ifdef EUCLEAN
+# define TARGET_LINUX_EUCLEAN 117
+  { EUCLEAN, TARGET_LINUX_EUCLEAN },
+#endif
+#ifdef ENOTNAM
+# define TARGET_LINUX_ENOTNAM 118
+  { ENOTNAM, TARGET_LINUX_ENOTNAM },
+#endif
+#ifdef ENAVAIL
+# define TARGET_LINUX_ENAVAIL 119
+  { ENAVAIL, TARGET_LINUX_ENAVAIL },
+#endif
+#ifdef EISNAM
+# define TARGET_LINUX_EISNAM 120
+  { EISNAM, TARGET_LINUX_EISNAM },
+#endif
+#ifdef EREMOTEIO
+# define TARGET_LINUX_EREMOTEIO 121
+  { EREMOTEIO, TARGET_LINUX_EREMOTEIO },
+#endif
+#ifdef EDQUOT
+# define TARGET_LINUX_EDQUOT 122
+  { EDQUOT, TARGET_LINUX_EDQUOT },
+#endif
+#ifdef ENOMEDIUM
+# define TARGET_LINUX_ENOMEDIUM 123
+  { ENOMEDIUM, TARGET_LINUX_ENOMEDIUM },
+#endif
+#ifdef EMEDIUMTYPE
+# define TARGET_LINUX_EMEDIUMTYPE 124
+  { EMEDIUMTYPE, TARGET_LINUX_EMEDIUMTYPE },
+#endif
+#ifdef ECANCELED
+# define TARGET_LINUX_ECANCELED 125
+  { ECANCELED, TARGET_LINUX_ECANCELED },
+#endif
+#ifdef EOWNERDEAD
+# define TARGET_LINUX_EOWNERDEAD 130
+  { EOWNERDEAD, TARGET_LINUX_EOWNERDEAD },
+#endif
+#ifdef ENOTRECOVERABLE
+# define TARGET_LINUX_ENOTRECOVERABLE 131
+  { ENOTRECOVERABLE, TARGET_LINUX_ENOTRECOVERABLE },
+#endif
+  { 0, 0 }
+};
+
+static CB_TARGET_DEFS_MAP cb_linux_open_map[] = {
+#ifdef O_ACCMODE
+# define TARGET_LINUX_O_ACCMODE 0003
+  { O_ACCMODE, TARGET_LINUX_O_ACCMODE },
+#endif
+#ifdef O_RDONLY
+# define TARGET_LINUX_O_RDONLY 00
+  { O_RDONLY, TARGET_LINUX_O_RDONLY },
+#endif
+#ifdef O_WRONLY
+# define TARGET_LINUX_O_WRONLY 01
+  { O_WRONLY, TARGET_LINUX_O_WRONLY },
+#endif
+#ifdef O_RDWR
+# define TARGET_LINUX_O_RDWR 02
+  { O_RDWR, TARGET_LINUX_O_RDWR },
+#endif
+#ifdef O_CREAT
+# define TARGET_LINUX_O_CREAT 0100
+  { O_CREAT, TARGET_LINUX_O_CREAT },
+#endif
+#ifdef O_EXCL
+# define TARGET_LINUX_O_EXCL 0200
+  { O_EXCL, TARGET_LINUX_O_EXCL },
+#endif
+#ifdef O_NOCTTY
+# define TARGET_LINUX_O_NOCTTY 0400
+  { O_NOCTTY, TARGET_LINUX_O_NOCTTY },
+#endif
+#ifdef O_TRUNC
+# define TARGET_LINUX_O_TRUNC 01000
+  { O_TRUNC, TARGET_LINUX_O_TRUNC },
+#endif
+#ifdef O_APPEND
+# define TARGET_LINUX_O_APPEND 02000
+  { O_APPEND, TARGET_LINUX_O_APPEND },
+#endif
+#ifdef O_NONBLOCK
+# define TARGET_LINUX_O_NONBLOCK 04000
+  { O_NONBLOCK, TARGET_LINUX_O_NONBLOCK },
+#endif
+#ifdef O_SYNC
+# define TARGET_LINUX_O_SYNC 010000
+  { O_SYNC, TARGET_LINUX_O_SYNC },
+#endif
+#ifdef O_ASYNC
+# define TARGET_LINUX_O_ASYNC 020000
+  { O_ASYNC, TARGET_LINUX_O_ASYNC },
+#endif
+  { -1, -1 }
+};
+
+static CB_TARGET_DEFS_MAP cb_linux_signal_map[] = {
+#ifdef SIGHUP
+# define TARGET_LINUX_SIGHUP 1
+  { SIGHUP, TARGET_LINUX_SIGHUP },
+#endif
+#ifdef SIGINT
+# define TARGET_LINUX_SIGINT 2
+  { SIGINT, TARGET_LINUX_SIGINT },
+#endif
+#ifdef SIGQUIT
+# define TARGET_LINUX_SIGQUIT 3
+  { SIGQUIT, TARGET_LINUX_SIGQUIT },
+#endif
+#ifdef SIGILL
+# define TARGET_LINUX_SIGILL 4
+  { SIGILL, TARGET_LINUX_SIGILL },
+#endif
+#ifdef SIGTRAP
+# define TARGET_LINUX_SIGTRAP 5
+  { SIGTRAP, TARGET_LINUX_SIGTRAP },
+#endif
+#ifdef SIGABRT
+# define TARGET_LINUX_SIGABRT 6
+  { SIGABRT, TARGET_LINUX_SIGABRT },
+#endif
+#ifdef SIGIOT
+# define TARGET_LINUX_SIGIOT 6
+  { SIGIOT, TARGET_LINUX_SIGIOT },
+#endif
+#ifdef SIGBUS
+# define TARGET_LINUX_SIGBUS 7
+  { SIGBUS, TARGET_LINUX_SIGBUS },
+#endif
+#ifdef SIGFPE
+# define TARGET_LINUX_SIGFPE 8
+  { SIGFPE, TARGET_LINUX_SIGFPE },
+#endif
+#ifdef SIGKILL
+# define TARGET_LINUX_SIGKILL 9
+  { SIGKILL, TARGET_LINUX_SIGKILL },
+#endif
+#ifdef SIGUSR1
+# define TARGET_LINUX_SIGUSR1 10
+  { SIGUSR1, TARGET_LINUX_SIGUSR1 },
+#endif
+#ifdef SIGSEGV
+# define TARGET_LINUX_SIGSEGV 11
+  { SIGSEGV, TARGET_LINUX_SIGSEGV },
+#endif
+#ifdef SIGUSR2
+# define TARGET_LINUX_SIGUSR2 12
+  { SIGUSR2, TARGET_LINUX_SIGUSR2 },
+#endif
+#ifdef SIGPIPE
+# define TARGET_LINUX_SIGPIPE 13
+  { SIGPIPE, TARGET_LINUX_SIGPIPE },
+#endif
+#ifdef SIGALRM
+# define TARGET_LINUX_SIGALRM 14
+  { SIGALRM, TARGET_LINUX_SIGALRM },
+#endif
+#ifdef SIGTERM
+# define TARGET_LINUX_SIGTERM 15
+  { SIGTERM, TARGET_LINUX_SIGTERM },
+#endif
+#ifdef SIGSTKFLT
+# define TARGET_LINUX_SIGSTKFLT 16
+  { SIGSTKFLT, TARGET_LINUX_SIGSTKFLT },
+#endif
+#ifdef SIGCHLD
+# define TARGET_LINUX_SIGCHLD 17
+  { SIGCHLD, TARGET_LINUX_SIGCHLD },
+#endif
+#ifdef SIGCONT
+# define TARGET_LINUX_SIGCONT 18
+  { SIGCONT, TARGET_LINUX_SIGCONT },
+#endif
+#ifdef SIGSTOP
+# define TARGET_LINUX_SIGSTOP 19
+  { SIGSTOP, TARGET_LINUX_SIGSTOP },
+#endif
+#ifdef SIGTSTP
+# define TARGET_LINUX_SIGTSTP 20
+  { SIGTSTP, TARGET_LINUX_SIGTSTP },
+#endif
+#ifdef SIGTTIN
+# define TARGET_LINUX_SIGTTIN 21
+  { SIGTTIN, TARGET_LINUX_SIGTTIN },
+#endif
+#ifdef SIGTTOU
+# define TARGET_LINUX_SIGTTOU 22
+  { SIGTTOU, TARGET_LINUX_SIGTTOU },
+#endif
+#ifdef SIGURG
+# define TARGET_LINUX_SIGURG 23
+  { SIGURG, TARGET_LINUX_SIGURG },
+#endif
+#ifdef SIGXCPU
+# define TARGET_LINUX_SIGXCPU 24
+  { SIGXCPU, TARGET_LINUX_SIGXCPU },
+#endif
+#ifdef SIGXFSZ
+# define TARGET_LINUX_SIGXFSZ 25
+  { SIGXFSZ, TARGET_LINUX_SIGXFSZ },
+#endif
+#ifdef SIGVTALRM
+# define TARGET_LINUX_SIGVTALRM 26
+  { SIGVTALRM, TARGET_LINUX_SIGVTALRM },
+#endif
+#ifdef SIGPROF
+# define TARGET_LINUX_SIGPROF 27
+  { SIGPROF, TARGET_LINUX_SIGPROF },
+#endif
+#ifdef SIGWINCH
+# define TARGET_LINUX_SIGWINCH 28
+  { SIGWINCH, TARGET_LINUX_SIGWINCH },
+#endif
+#ifdef SIGIO
+# define TARGET_LINUX_SIGIO 29
+  { SIGIO, TARGET_LINUX_SIGIO },
+#endif
+#ifdef SIGPWR
+# define TARGET_LINUX_SIGPWR 30
+  { SIGPWR, TARGET_LINUX_SIGPWR },
+#endif
+#ifdef SIGSYS
+# define TARGET_LINUX_SIGSYS 31
+  { SIGSYS, TARGET_LINUX_SIGSYS },
+#endif
+#ifdef SIGUNUSED
+# define TARGET_LINUX_SIGUNUSED 31
+  { SIGUNUSED, TARGET_LINUX_SIGUNUSED },
+#endif
+#ifdef SIG_BLOCK
+# define TARGET_LINUX_SIG_BLOCK 0
+  { SIG_BLOCK, TARGET_LINUX_SIG_BLOCK },
+#endif
+#ifdef SIG_UNBLOCK
+# define TARGET_LINUX_SIG_UNBLOCK 1
+  { SIG_UNBLOCK, TARGET_LINUX_SIG_UNBLOCK },
+#endif
+#ifdef SIG_SETMASK
+# define TARGET_LINUX_SIG_SETMASK 2
+  { SIG_SETMASK, TARGET_LINUX_SIG_SETMASK },
+#endif
+#ifdef SIGSTKSZ
+# define TARGET_LINUX_SIGSTKSZ 8192
+  { SIGSTKSZ, TARGET_LINUX_SIGSTKSZ },
+#endif
+  { -1, -1 }
+};
diff --git a/sim/bfin/machs.c b/sim/bfin/machs.c
new file mode 100644 (file)
index 0000000..e60e8c9
--- /dev/null
@@ -0,0 +1,1287 @@
+/* Simulator for Analog Devices Blackfin processors.
+
+   Copyright (C) 2005-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#include "sim-main.h"
+#include "gdb/sim-bfin.h"
+#include "bfd.h"
+
+#include "sim-hw.h"
+#include "devices.h"
+#include "dv-bfin_cec.h"
+#include "dv-bfin_ctimer.h"
+#include "dv-bfin_dma.h"
+#include "dv-bfin_dmac.h"
+#include "dv-bfin_ebiu_amc.h"
+#include "dv-bfin_ebiu_ddrc.h"
+#include "dv-bfin_ebiu_sdc.h"
+#include "dv-bfin_emac.h"
+#include "dv-bfin_eppi.h"
+#include "dv-bfin_evt.h"
+#include "dv-bfin_gptimer.h"
+#include "dv-bfin_jtag.h"
+#include "dv-bfin_mmu.h"
+#include "dv-bfin_nfc.h"
+#include "dv-bfin_otp.h"
+#include "dv-bfin_ppi.h"
+#include "dv-bfin_pll.h"
+#include "dv-bfin_rtc.h"
+#include "dv-bfin_sic.h"
+#include "dv-bfin_spi.h"
+#include "dv-bfin_trace.h"
+#include "dv-bfin_twi.h"
+#include "dv-bfin_uart.h"
+#include "dv-bfin_uart2.h"
+#include "dv-bfin_wdog.h"
+#include "dv-bfin_wp.h"
+
+static const MACH bfin_mach;
+
+struct bfin_memory_layout {
+  address_word addr, len;
+  unsigned mask;       /* see mapmask in sim_core_attach() */
+};
+struct bfin_dev_layout {
+  address_word base, len;
+  unsigned int dmac;
+  const char *dev;
+};
+struct bfin_dmac_layout {
+  address_word base;
+  unsigned int dma_count;
+};
+struct bfin_model_data {
+  bu32 chipid;
+  int model_num;
+  const struct bfin_memory_layout *mem;
+  size_t mem_count;
+  const struct bfin_dev_layout *dev;
+  size_t dev_count;
+  const struct bfin_dmac_layout *dmac;
+  size_t dmac_count;
+};
+
+#define LAYOUT(_addr, _len, _mask) { .addr = _addr, .len = _len, .mask = access_##_mask, }
+#define _DEVICE(_base, _len, _dev, _dmac) { .base = _base, .len = _len, .dev = _dev, .dmac = _dmac, }
+#define DEVICE(_base, _len, _dev) _DEVICE(_base, _len, _dev, 0)
+
+/* [1] Common sim code can't model exec-only memory.
+   http://sourceware.org/ml/gdb/2010-02/msg00047.html */
+
+#define bf000_chipid 0
+static const struct bfin_memory_layout bf000_mem[] = {};
+static const struct bfin_dev_layout bf000_dev[] = {};
+static const struct bfin_dmac_layout bf000_dmac[] = {};
+
+#define bf50x_chipid 0x2800
+#define bf504_chipid bf50x_chipid
+#define bf506_chipid bf50x_chipid
+static const struct bfin_memory_layout bf50x_mem[] = {
+  LAYOUT (0xFFC00700, 0x50, read_write),       /* PORTF stub */
+  LAYOUT (0xFFC00800, 0x60, read_write),       /* SPORT0 stub */
+  LAYOUT (0xFFC00900, 0x60, read_write),       /* SPORT1 stub */
+  LAYOUT (0xFFC01500, 0x50, read_write),       /* PORTG stub */
+  LAYOUT (0xFFC01700, 0x50, read_write),       /* PORTH stub */
+  LAYOUT (0xFFC03200, 0x50, read_write),       /* PORT_MUX stub */
+  LAYOUT (0xFFC03800, 0x100, read_write),      /* RSI stub */
+  LAYOUT (0xFFC0328C, 0xC, read_write),                /* Flash stub */
+  LAYOUT (0xFF800000, 0x4000, read_write),     /* Data A */
+  LAYOUT (0xFF804000, 0x4000, read_write),     /* Data A Cache */
+  LAYOUT (0xFFA00000, 0x4000, read_write_exec),        /* Inst A [1] */
+  LAYOUT (0xFFA04000, 0x4000, read_write_exec),        /* Inst Cache [1] */
+};
+#define bf504_mem bf50x_mem
+#define bf506_mem bf50x_mem
+static const struct bfin_dev_layout bf50x_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART2_SIZE,     "bfin_uart2@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC00610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC00620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC00630, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@3"),
+  DEVICE (0xFFC00640, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@4"),
+  DEVICE (0xFFC00650, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@5"),
+  DEVICE (0xFFC00660, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@6"),
+  DEVICE (0xFFC00670, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@7"),
+  DEVICE (0xFFC00A00, BF50X_MMR_EBIU_AMC_SIZE, "bfin_ebiu_amc"),
+  DEVICE (0xFFC01000, BFIN_MMR_PPI_SIZE,       "bfin_ppi@0"),
+  DEVICE (0xFFC01400, BFIN_MMR_TWI_SIZE,       "bfin_twi@0"),
+  DEVICE (0xFFC02000, BFIN_MMR_UART2_SIZE,     "bfin_uart2@1"),
+  DEVICE (0xFFC03400, BFIN_MMR_SPI_SIZE,       "bfin_spi@1"),
+};
+#define bf504_dev bf50x_dev
+#define bf506_dev bf50x_dev
+static const struct bfin_dmac_layout bf50x_dmac[] = {
+  { BFIN_MMR_DMAC0_BASE, 12, },
+};
+#define bf504_dmac bf50x_dmac
+#define bf506_dmac bf50x_dmac
+
+#define bf51x_chipid 0x27e8
+#define bf512_chipid bf51x_chipid
+#define bf514_chipid bf51x_chipid
+#define bf516_chipid bf51x_chipid
+#define bf518_chipid bf51x_chipid
+static const struct bfin_memory_layout bf51x_mem[] = {
+  LAYOUT (0xFFC00680, 0xC, read_write),                /* TIMER stub */
+  LAYOUT (0xFFC00700, 0x50, read_write),       /* PORTF stub */
+  LAYOUT (0xFFC00800, 0x60, read_write),       /* SPORT0 stub */
+  LAYOUT (0xFFC00900, 0x60, read_write),       /* SPORT1 stub */
+  LAYOUT (0xFFC01500, 0x50, read_write),       /* PORTG stub */
+  LAYOUT (0xFFC01700, 0x50, read_write),       /* PORTH stub */
+  LAYOUT (0xFFC03200, 0x50, read_write),       /* PORT_MUX stub */
+  LAYOUT (0xFFC03800, 0xD0, read_write),       /* RSI stub */
+  LAYOUT (0xFFC03FE0, 0x20, read_write),       /* RSI peripheral stub */
+  LAYOUT (0xFF800000, 0x4000, read_write),     /* Data A */
+  LAYOUT (0xFF804000, 0x4000, read_write),     /* Data A Cache */
+  LAYOUT (0xFF900000, 0x4000, read_write),     /* Data B */
+  LAYOUT (0xFF904000, 0x4000, read_write),     /* Data B Cache */
+  LAYOUT (0xFFA00000, 0x8000, read_write_exec),        /* Inst A [1] */
+  LAYOUT (0xFFA10000, 0x4000, read_write_exec),        /* Inst Cache [1] */
+};
+#define bf512_mem bf51x_mem
+#define bf514_mem bf51x_mem
+#define bf516_mem bf51x_mem
+#define bf518_mem bf51x_mem
+static const struct bfin_dev_layout bf512_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00300, BFIN_MMR_RTC_SIZE,       "bfin_rtc"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART_SIZE,      "bfin_uart@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC00610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC00620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC00630, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@3"),
+  DEVICE (0xFFC00640, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@4"),
+  DEVICE (0xFFC00650, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@5"),
+  DEVICE (0xFFC00660, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@6"),
+  DEVICE (0xFFC00670, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@7"),
+  DEVICE (0xFFC00A00, BFIN_MMR_EBIU_AMC_SIZE,  "bfin_ebiu_amc"),
+  DEVICE (0xFFC00A10, BFIN_MMR_EBIU_SDC_SIZE,  "bfin_ebiu_sdc"),
+  DEVICE (0xFFC01000, BFIN_MMR_PPI_SIZE,       "bfin_ppi@0"),
+  DEVICE (0xFFC01400, BFIN_MMR_TWI_SIZE,       "bfin_twi@0"),
+  DEVICE (0xFFC02000, BFIN_MMR_UART_SIZE,      "bfin_uart@1"),
+  DEVICE (0xFFC03400, BFIN_MMR_SPI_SIZE,       "bfin_spi@1"),
+  DEVICE (0xFFC03600, BFIN_MMR_OTP_SIZE,       "bfin_otp"),
+};
+#define bf514_dev bf512_dev
+static const struct bfin_dev_layout bf516_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00300, BFIN_MMR_RTC_SIZE,       "bfin_rtc"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART_SIZE,      "bfin_uart@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC00610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC00620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC00630, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@3"),
+  DEVICE (0xFFC00640, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@4"),
+  DEVICE (0xFFC00650, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@5"),
+  DEVICE (0xFFC00660, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@6"),
+  DEVICE (0xFFC00670, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@7"),
+  DEVICE (0xFFC00A00, BFIN_MMR_EBIU_AMC_SIZE,  "bfin_ebiu_amc"),
+  DEVICE (0xFFC00A10, BFIN_MMR_EBIU_SDC_SIZE,  "bfin_ebiu_sdc"),
+  DEVICE (0xFFC01000, BFIN_MMR_PPI_SIZE,       "bfin_ppi@0"),
+  DEVICE (0xFFC01400, BFIN_MMR_TWI_SIZE,       "bfin_twi@0"),
+  DEVICE (0xFFC02000, BFIN_MMR_UART_SIZE,      "bfin_uart@1"),
+  DEVICE (0xFFC03000, BFIN_MMR_EMAC_SIZE,      "bfin_emac"),
+  DEVICE (0, 0x20, "bfin_emac/eth_phy"),
+  DEVICE (0xFFC03400, BFIN_MMR_SPI_SIZE,       "bfin_spi@1"),
+  DEVICE (0xFFC03600, BFIN_MMR_OTP_SIZE,       "bfin_otp"),
+};
+#define bf518_dev bf516_dev
+#define bf512_dmac bf50x_dmac
+#define bf514_dmac bf50x_dmac
+#define bf516_dmac bf50x_dmac
+#define bf518_dmac bf50x_dmac
+
+#define bf522_chipid 0x27e4
+#define bf523_chipid 0x27e0
+#define bf524_chipid bf522_chipid
+#define bf525_chipid bf523_chipid
+#define bf526_chipid bf522_chipid
+#define bf527_chipid bf523_chipid
+static const struct bfin_memory_layout bf52x_mem[] = {
+  LAYOUT (0xFFC00680, 0xC, read_write),                /* TIMER stub */
+  LAYOUT (0xFFC00700, 0x50, read_write),       /* PORTF stub */
+  LAYOUT (0xFFC00800, 0x60, read_write),       /* SPORT0 stub */
+  LAYOUT (0xFFC00900, 0x60, read_write),       /* SPORT1 stub */
+  LAYOUT (0xFFC01500, 0x50, read_write),       /* PORTG stub */
+  LAYOUT (0xFFC01700, 0x50, read_write),       /* PORTH stub */
+  LAYOUT (0xFFC03200, 0x50, read_write),       /* PORT_MUX stub */
+  LAYOUT (0xFFC03800, 0x500, read_write),      /* MUSB stub */
+  LAYOUT (0xFF800000, 0x4000, read_write),     /* Data A */
+  LAYOUT (0xFF804000, 0x4000, read_write),     /* Data A Cache */
+  LAYOUT (0xFF900000, 0x4000, read_write),     /* Data B */
+  LAYOUT (0xFF904000, 0x4000, read_write),     /* Data B Cache */
+  LAYOUT (0xFFA00000, 0x8000, read_write_exec),        /* Inst A [1] */
+  LAYOUT (0xFFA08000, 0x4000, read_write_exec),        /* Inst B [1] */
+  LAYOUT (0xFFA10000, 0x4000, read_write_exec),        /* Inst Cache [1] */
+};
+#define bf522_mem bf52x_mem
+#define bf523_mem bf52x_mem
+#define bf524_mem bf52x_mem
+#define bf525_mem bf52x_mem
+#define bf526_mem bf52x_mem
+#define bf527_mem bf52x_mem
+static const struct bfin_dev_layout bf522_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00300, BFIN_MMR_RTC_SIZE,       "bfin_rtc"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART_SIZE,      "bfin_uart@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC00610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC00620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC00630, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@3"),
+  DEVICE (0xFFC00640, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@4"),
+  DEVICE (0xFFC00650, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@5"),
+  DEVICE (0xFFC00660, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@6"),
+  DEVICE (0xFFC00670, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@7"),
+  DEVICE (0xFFC00A00, BFIN_MMR_EBIU_AMC_SIZE,  "bfin_ebiu_amc"),
+  DEVICE (0xFFC00A10, BFIN_MMR_EBIU_SDC_SIZE,  "bfin_ebiu_sdc"),
+  DEVICE (0xFFC01000, BFIN_MMR_PPI_SIZE,       "bfin_ppi@0"),
+  DEVICE (0xFFC01400, BFIN_MMR_TWI_SIZE,       "bfin_twi@0"),
+  DEVICE (0xFFC02000, BFIN_MMR_UART_SIZE,      "bfin_uart@1"),
+  DEVICE (0xFFC03600, BFIN_MMR_OTP_SIZE,       "bfin_otp"),
+  DEVICE (0xFFC03700, BFIN_MMR_NFC_SIZE,       "bfin_nfc"),
+};
+#define bf523_dev bf522_dev
+#define bf524_dev bf522_dev
+#define bf525_dev bf522_dev
+static const struct bfin_dev_layout bf526_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00300, BFIN_MMR_RTC_SIZE,       "bfin_rtc"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART_SIZE,      "bfin_uart@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC00610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC00620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC00630, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@3"),
+  DEVICE (0xFFC00640, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@4"),
+  DEVICE (0xFFC00650, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@5"),
+  DEVICE (0xFFC00660, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@6"),
+  DEVICE (0xFFC00670, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@7"),
+  DEVICE (0xFFC00A00, BFIN_MMR_EBIU_AMC_SIZE,  "bfin_ebiu_amc"),
+  DEVICE (0xFFC00A10, BFIN_MMR_EBIU_SDC_SIZE,  "bfin_ebiu_sdc"),
+  DEVICE (0xFFC01000, BFIN_MMR_PPI_SIZE,       "bfin_ppi@0"),
+  DEVICE (0xFFC01400, BFIN_MMR_TWI_SIZE,       "bfin_twi@0"),
+  DEVICE (0xFFC02000, BFIN_MMR_UART_SIZE,      "bfin_uart@1"),
+  DEVICE (0xFFC03000, BFIN_MMR_EMAC_SIZE,      "bfin_emac"),
+  DEVICE (0, 0x20, "bfin_emac/eth_phy"),
+  DEVICE (0xFFC03600, BFIN_MMR_OTP_SIZE,       "bfin_otp"),
+  DEVICE (0xFFC03700, BFIN_MMR_NFC_SIZE,       "bfin_nfc"),
+};
+#define bf527_dev bf526_dev
+#define bf522_dmac bf50x_dmac
+#define bf523_dmac bf50x_dmac
+#define bf524_dmac bf50x_dmac
+#define bf525_dmac bf50x_dmac
+#define bf526_dmac bf50x_dmac
+#define bf527_dmac bf50x_dmac
+
+#define bf531_chipid 0x27a5
+#define bf532_chipid bf531_chipid
+#define bf533_chipid bf531_chipid
+static const struct bfin_memory_layout bf531_mem[] = {
+  LAYOUT (0xFFC00640, 0xC, read_write),                /* TIMER stub */
+  LAYOUT (0xFFC00700, 0x50, read_write),       /* GPIO stub */
+  LAYOUT (0xFFC00800, 0x60, read_write),       /* SPORT0 stub */
+  LAYOUT (0xFFC00900, 0x60, read_write),       /* SPORT1 stub */
+  LAYOUT (0xFF804000, 0x4000, read_write),     /* Data A Cache */
+  LAYOUT (0xFFA08000, 0x4000, read_write_exec),        /* Inst B [1] */
+  LAYOUT (0xFFA10000, 0x4000, read_write_exec),        /* Inst Cache [1] */
+};
+static const struct bfin_memory_layout bf532_mem[] = {
+  LAYOUT (0xFFC00640, 0xC, read_write),                /* TIMER stub */
+  LAYOUT (0xFFC00700, 0x50, read_write),       /* GPIO stub */
+  LAYOUT (0xFFC00800, 0x60, read_write),       /* SPORT0 stub */
+  LAYOUT (0xFFC00900, 0x60, read_write),       /* SPORT1 stub */
+  LAYOUT (0xFF804000, 0x4000, read_write),     /* Data A Cache */
+  LAYOUT (0xFF904000, 0x4000, read_write),     /* Data B Cache */
+  LAYOUT (0xFFA08000, 0x4000, read_write_exec),        /* Inst B [1] */
+  LAYOUT (0xFFA0C000, 0x4000, read_write_exec),        /* Inst C [1] */
+  LAYOUT (0xFFA10000, 0x4000, read_write_exec),        /* Inst Cache [1] */
+};
+static const struct bfin_memory_layout bf533_mem[] = {
+  LAYOUT (0xFFC00640, 0xC, read_write),                /* TIMER stub */
+  LAYOUT (0xFFC00700, 0x50, read_write),       /* GPIO stub */
+  LAYOUT (0xFFC00800, 0x60, read_write),       /* SPORT0 stub */
+  LAYOUT (0xFFC00900, 0x60, read_write),       /* SPORT1 stub */
+  LAYOUT (0xFF800000, 0x4000, read_write),     /* Data A */
+  LAYOUT (0xFF804000, 0x4000, read_write),     /* Data A Cache */
+  LAYOUT (0xFF900000, 0x4000, read_write),     /* Data B */
+  LAYOUT (0xFF904000, 0x4000, read_write),     /* Data B Cache */
+  LAYOUT (0xFFA00000, 0x8000, read_write_exec),        /* Inst A [1] */
+  LAYOUT (0xFFA08000, 0x4000, read_write_exec),        /* Inst B [1] */
+  LAYOUT (0xFFA0C000, 0x4000, read_write_exec),        /* Inst C [1] */
+  LAYOUT (0xFFA10000, 0x4000, read_write_exec),        /* Inst Cache [1] */
+};
+static const struct bfin_dev_layout bf533_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00300, BFIN_MMR_RTC_SIZE,       "bfin_rtc"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART_SIZE,      "bfin_uart@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC00610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC00620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC00A00, BFIN_MMR_EBIU_AMC_SIZE,  "bfin_ebiu_amc"),
+  DEVICE (0xFFC00A10, BFIN_MMR_EBIU_SDC_SIZE,  "bfin_ebiu_sdc"),
+  DEVICE (0xFFC01000, BFIN_MMR_PPI_SIZE,       "bfin_ppi@0"),
+};
+#define bf531_dev bf533_dev
+#define bf532_dev bf533_dev
+static const struct bfin_dmac_layout bf533_dmac[] = {
+  { BFIN_MMR_DMAC0_BASE, 8, },
+};
+#define bf531_dmac bf533_dmac
+#define bf532_dmac bf533_dmac
+
+#define bf534_chipid 0x27c6
+#define bf536_chipid 0x27c8
+#define bf537_chipid bf536_chipid
+static const struct bfin_memory_layout bf534_mem[] = {
+  LAYOUT (0xFFC00680, 0xC, read_write),                /* TIMER stub */
+  LAYOUT (0xFFC00700, 0x50, read_write),       /* PORTF stub */
+  LAYOUT (0xFFC00800, 0x60, read_write),       /* SPORT0 stub */
+  LAYOUT (0xFFC00900, 0x60, read_write),       /* SPORT1 stub */
+  LAYOUT (0xFFC01500, 0x50, read_write),       /* PORTG stub */
+  LAYOUT (0xFFC01700, 0x50, read_write),       /* PORTH stub */
+  LAYOUT (0xFFC03200, 0x10, read_write),       /* PORT_MUX stub */
+  LAYOUT (0xFF800000, 0x4000, read_write),     /* Data A */
+  LAYOUT (0xFF804000, 0x4000, read_write),     /* Data A Cache */
+  LAYOUT (0xFF900000, 0x4000, read_write),     /* Data B */
+  LAYOUT (0xFF904000, 0x4000, read_write),     /* Data B Cache */
+  LAYOUT (0xFFA00000, 0x8000, read_write_exec),        /* Inst A [1] */
+  LAYOUT (0xFFA08000, 0x4000, read_write_exec),        /* Inst B [1] */
+  LAYOUT (0xFFA10000, 0x4000, read_write_exec),        /* Inst Cache [1] */
+};
+static const struct bfin_memory_layout bf536_mem[] = {
+  LAYOUT (0xFFC00680, 0xC, read_write),                /* TIMER stub */
+  LAYOUT (0xFFC00700, 0x50, read_write),       /* PORTF stub */
+  LAYOUT (0xFFC00800, 0x60, read_write),       /* SPORT0 stub */
+  LAYOUT (0xFFC00900, 0x60, read_write),       /* SPORT1 stub */
+  LAYOUT (0xFFC01500, 0x50, read_write),       /* PORTG stub */
+  LAYOUT (0xFFC01700, 0x50, read_write),       /* PORTG stub */
+  LAYOUT (0xFFC03200, 0x10, read_write),       /* PORT_MUX stub */
+  LAYOUT (0xFF804000, 0x4000, read_write),     /* Data A Cache */
+  LAYOUT (0xFF904000, 0x4000, read_write),     /* Data B Cache */
+  LAYOUT (0xFFA00000, 0x8000, read_write_exec),        /* Inst A [1] */
+  LAYOUT (0xFFA08000, 0x4000, read_write_exec),        /* Inst B [1] */
+  LAYOUT (0xFFA10000, 0x4000, read_write_exec),        /* Inst Cache [1] */
+};
+static const struct bfin_memory_layout bf537_mem[] = {
+  LAYOUT (0xFFC00680, 0xC, read_write),                /* TIMER stub */
+  LAYOUT (0xFFC00700, 0x50, read_write),       /* PORTF stub */
+  LAYOUT (0xFFC00800, 0x60, read_write),       /* SPORT0 stub */
+  LAYOUT (0xFFC00900, 0x60, read_write),       /* SPORT1 stub */
+  LAYOUT (0xFFC01500, 0x50, read_write),       /* PORTG stub */
+  LAYOUT (0xFFC01700, 0x50, read_write),       /* PORTG stub */
+  LAYOUT (0xFFC03200, 0x10, read_write),       /* PORT_MUX stub */
+  LAYOUT (0xFF800000, 0x4000, read_write),     /* Data A */
+  LAYOUT (0xFF804000, 0x4000, read_write),     /* Data A Cache */
+  LAYOUT (0xFF900000, 0x4000, read_write),     /* Data B */
+  LAYOUT (0xFF904000, 0x4000, read_write),     /* Data B Cache */
+  LAYOUT (0xFFA00000, 0x8000, read_write_exec),        /* Inst A [1] */
+  LAYOUT (0xFFA08000, 0x4000, read_write_exec),        /* Inst B [1] */
+  LAYOUT (0xFFA10000, 0x4000, read_write_exec),        /* Inst Cache [1] */
+};
+static const struct bfin_dev_layout bf534_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00300, BFIN_MMR_RTC_SIZE,       "bfin_rtc"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART_SIZE,      "bfin_uart@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC00610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC00620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC00630, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@3"),
+  DEVICE (0xFFC00640, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@4"),
+  DEVICE (0xFFC00650, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@5"),
+  DEVICE (0xFFC00660, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@6"),
+  DEVICE (0xFFC00670, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@7"),
+  DEVICE (0xFFC00A00, BFIN_MMR_EBIU_AMC_SIZE,  "bfin_ebiu_amc"),
+  DEVICE (0xFFC00A10, BFIN_MMR_EBIU_SDC_SIZE,  "bfin_ebiu_sdc"),
+  DEVICE (0xFFC01000, BFIN_MMR_PPI_SIZE,       "bfin_ppi@0"),
+  DEVICE (0xFFC01400, BFIN_MMR_TWI_SIZE,       "bfin_twi@0"),
+  DEVICE (0xFFC02000, BFIN_MMR_UART_SIZE,      "bfin_uart@1"),
+};
+static const struct bfin_dev_layout bf537_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00300, BFIN_MMR_RTC_SIZE,       "bfin_rtc"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART_SIZE,      "bfin_uart@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC00610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC00620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC00630, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@3"),
+  DEVICE (0xFFC00640, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@4"),
+  DEVICE (0xFFC00650, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@5"),
+  DEVICE (0xFFC00660, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@6"),
+  DEVICE (0xFFC00670, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@7"),
+  DEVICE (0xFFC00A00, BFIN_MMR_EBIU_AMC_SIZE,  "bfin_ebiu_amc"),
+  DEVICE (0xFFC00A10, BFIN_MMR_EBIU_SDC_SIZE,  "bfin_ebiu_sdc"),
+  DEVICE (0xFFC01000, BFIN_MMR_PPI_SIZE,       "bfin_ppi@0"),
+  DEVICE (0xFFC01400, BFIN_MMR_TWI_SIZE,       "bfin_twi@0"),
+  DEVICE (0xFFC02000, BFIN_MMR_UART_SIZE,      "bfin_uart@1"),
+  DEVICE (0xFFC03000, BFIN_MMR_EMAC_SIZE,      "bfin_emac"),
+  DEVICE (0, 0x20, "bfin_emac/eth_phy"),
+};
+#define bf536_dev bf537_dev
+#define bf534_dmac bf50x_dmac
+#define bf536_dmac bf50x_dmac
+#define bf537_dmac bf50x_dmac
+
+#define bf538_chipid 0x27c4
+#define bf539_chipid bf538_chipid
+static const struct bfin_memory_layout bf538_mem[] = {
+  LAYOUT (0xFFC00700, 0x50, read_write),       /* PORTF stub */
+  LAYOUT (0xFFC00800, 0x60, read_write),       /* SPORT0 stub */
+  LAYOUT (0xFFC00900, 0x60, read_write),       /* SPORT1 stub */
+  LAYOUT (0xFFC01500, 0x70, read_write),       /* PORTC/D/E stub */
+  LAYOUT (0xFFC02500, 0x60, read_write),       /* SPORT2 stub */
+  LAYOUT (0xFFC02600, 0x60, read_write),       /* SPORT3 stub */
+  LAYOUT (0xFF800000, 0x4000, read_write),     /* Data A */
+  LAYOUT (0xFF804000, 0x4000, read_write),     /* Data A Cache */
+  LAYOUT (0xFF900000, 0x4000, read_write),     /* Data B */
+  LAYOUT (0xFF904000, 0x4000, read_write),     /* Data B Cache */
+  LAYOUT (0xFFA00000, 0x8000, read_write_exec),        /* Inst A [1] */
+  LAYOUT (0xFFA08000, 0x4000, read_write_exec),        /* Inst B [1] */
+  LAYOUT (0xFFA0C000, 0x4000, read_write_exec),        /* Inst C [1] */
+  LAYOUT (0xFFA10000, 0x4000, read_write_exec),        /* Inst Cache [1] */
+};
+#define bf539_mem bf538_mem
+static const struct bfin_dev_layout bf538_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00300, BFIN_MMR_RTC_SIZE,       "bfin_rtc"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART_SIZE,      "bfin_uart@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC00610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC00620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC00A00, BFIN_MMR_EBIU_AMC_SIZE,  "bfin_ebiu_amc"),
+  DEVICE (0xFFC00A10, BFIN_MMR_EBIU_SDC_SIZE,  "bfin_ebiu_sdc"),
+  DEVICE (0xFFC01000, BFIN_MMR_PPI_SIZE,       "bfin_ppi@0"),
+  DEVICE (0xFFC01400, BFIN_MMR_TWI_SIZE,       "bfin_twi@0"),
+ _DEVICE (0xFFC02000, BFIN_MMR_UART_SIZE,      "bfin_uart@1", 1),
+ _DEVICE (0xFFC02100, BFIN_MMR_UART_SIZE,      "bfin_uart@2", 1),
+  DEVICE (0xFFC02200, BFIN_MMR_TWI_SIZE,       "bfin_twi@1"),
+ _DEVICE (0xFFC02300, BFIN_MMR_SPI_SIZE,       "bfin_spi@1", 1),
+ _DEVICE (0xFFC02400, BFIN_MMR_SPI_SIZE,       "bfin_spi@2", 1),
+};
+#define bf539_dev bf538_dev
+static const struct bfin_dmac_layout bf538_dmac[] = {
+  { BFIN_MMR_DMAC0_BASE,  8, },
+  { BFIN_MMR_DMAC1_BASE, 12, },
+};
+#define bf539_dmac bf538_dmac
+
+#define bf54x_chipid 0x27de
+#define bf542_chipid bf54x_chipid
+#define bf544_chipid bf54x_chipid
+#define bf547_chipid bf54x_chipid
+#define bf548_chipid bf54x_chipid
+#define bf549_chipid bf54x_chipid
+static const struct bfin_memory_layout bf54x_mem[] = {
+  LAYOUT (0xFFC00800, 0x60, read_write),       /* SPORT0 stub XXX: not on BF542/4 */
+  LAYOUT (0xFFC00900, 0x60, read_write),       /* SPORT1 stub */
+  LAYOUT (0xFFC01400, 0x200, read_write),      /* PORT/GPIO stub */
+  LAYOUT (0xFFC02500, 0x60, read_write),       /* SPORT2 stub */
+  LAYOUT (0xFFC02600, 0x60, read_write),       /* SPORT3 stub */
+  LAYOUT (0xFFC03800, 0x70, read_write),       /* ATAPI stub */
+  LAYOUT (0xFFC03900, 0x100, read_write),      /* RSI stub */
+  LAYOUT (0xFFC03C00, 0x500, read_write),      /* MUSB stub */
+  LAYOUT (0xFEB00000, 0x20000, read_write_exec),       /* L2 */
+  LAYOUT (0xFF800000, 0x4000, read_write),     /* Data A */
+  LAYOUT (0xFF804000, 0x4000, read_write),     /* Data A Cache */
+  LAYOUT (0xFF900000, 0x4000, read_write),     /* Data B */
+  LAYOUT (0xFF904000, 0x4000, read_write),     /* Data B Cache */
+  LAYOUT (0xFFA00000, 0x8000, read_write_exec),        /* Inst A [1] */
+  LAYOUT (0xFFA08000, 0x4000, read_write_exec),        /* Inst B [1] */
+  LAYOUT (0xFFA10000, 0x4000, read_write_exec),        /* Inst Cache [1] */
+};
+#define bf542_mem bf54x_mem
+#define bf544_mem bf54x_mem
+#define bf547_mem bf54x_mem
+#define bf548_mem bf54x_mem
+#define bf549_mem bf54x_mem
+static const struct bfin_dev_layout bf542_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00300, BFIN_MMR_RTC_SIZE,       "bfin_rtc"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART2_SIZE,     "bfin_uart2@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00700, BFIN_MMR_TWI_SIZE,       "bfin_twi@0"),
+  DEVICE (0xFFC00A00, BF54X_MMR_EBIU_AMC_SIZE, "bfin_ebiu_amc"),
+  DEVICE (0xFFC00A20, BFIN_MMR_EBIU_DDRC_SIZE, "bfin_ebiu_ddrc"),
+ _DEVICE (0xFFC01300, BFIN_MMR_EPPI_SIZE,      "bfin_eppi@1", 1),
+  DEVICE (0xFFC01600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC01610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC01620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC01630, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@3"),
+  DEVICE (0xFFC01640, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@4"),
+  DEVICE (0xFFC01650, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@5"),
+  DEVICE (0xFFC01660, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@6"),
+  DEVICE (0xFFC01670, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@7"),
+  DEVICE (0xFFC02000, BFIN_MMR_UART2_SIZE,     "bfin_uart2@1"),
+ _DEVICE (0xFFC02100, BFIN_MMR_UART2_SIZE,     "bfin_uart2@2", 1),
+  DEVICE (0xFFC02300, BFIN_MMR_SPI_SIZE,       "bfin_spi@1"),
+ _DEVICE (0xFFC02900, BFIN_MMR_EPPI_SIZE,      "bfin_eppi@2", 1),
+ _DEVICE (0xFFC03100, BFIN_MMR_UART2_SIZE,     "bfin_uart2@3", 1),
+  DEVICE (0xFFC03B00, BFIN_MMR_NFC_SIZE,       "bfin_nfc"),
+  DEVICE (0xFFC04300, BFIN_MMR_OTP_SIZE,       "bfin_otp"),
+};
+static const struct bfin_dev_layout bf544_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00300, BFIN_MMR_RTC_SIZE,       "bfin_rtc"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART2_SIZE,     "bfin_uart2@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@8"),
+  DEVICE (0xFFC00610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@9"),
+  DEVICE (0xFFC00620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@10"),
+  DEVICE (0xFFC00700, BFIN_MMR_TWI_SIZE,       "bfin_twi@0"),
+  DEVICE (0xFFC00A00, BF54X_MMR_EBIU_AMC_SIZE, "bfin_ebiu_amc"),
+  DEVICE (0xFFC00A20, BFIN_MMR_EBIU_DDRC_SIZE, "bfin_ebiu_ddrc"),
+ _DEVICE (0xFFC01000, BFIN_MMR_EPPI_SIZE,      "bfin_eppi@0", 1),
+ _DEVICE (0xFFC01300, BFIN_MMR_EPPI_SIZE,      "bfin_eppi@1", 1),
+  DEVICE (0xFFC01600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC01610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC01620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC01630, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@3"),
+  DEVICE (0xFFC01640, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@4"),
+  DEVICE (0xFFC01650, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@5"),
+  DEVICE (0xFFC01660, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@6"),
+  DEVICE (0xFFC01670, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@7"),
+  DEVICE (0xFFC02000, BFIN_MMR_UART2_SIZE,     "bfin_uart2@1"),
+ _DEVICE (0xFFC02100, BFIN_MMR_UART2_SIZE,     "bfin_uart2@2", 1),
+  DEVICE (0xFFC02200, BFIN_MMR_TWI_SIZE,       "bfin_twi@1"),
+  DEVICE (0xFFC02300, BFIN_MMR_SPI_SIZE,       "bfin_spi@1"),
+ _DEVICE (0xFFC02900, BFIN_MMR_EPPI_SIZE,      "bfin_eppi@2", 1),
+ _DEVICE (0xFFC03100, BFIN_MMR_UART2_SIZE,     "bfin_uart2@3", 1),
+  DEVICE (0xFFC03B00, BFIN_MMR_NFC_SIZE,       "bfin_nfc"),
+  DEVICE (0xFFC04300, BFIN_MMR_OTP_SIZE,       "bfin_otp"),
+};
+static const struct bfin_dev_layout bf547_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00300, BFIN_MMR_RTC_SIZE,       "bfin_rtc"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART2_SIZE,     "bfin_uart2@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@8"),
+  DEVICE (0xFFC00610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@9"),
+  DEVICE (0xFFC00620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@10"),
+  DEVICE (0xFFC00700, BFIN_MMR_TWI_SIZE,       "bfin_twi@0"),
+  DEVICE (0xFFC00A00, BF54X_MMR_EBIU_AMC_SIZE, "bfin_ebiu_amc"),
+  DEVICE (0xFFC00A20, BFIN_MMR_EBIU_DDRC_SIZE, "bfin_ebiu_ddrc"),
+ _DEVICE (0xFFC01000, BFIN_MMR_EPPI_SIZE,      "bfin_eppi@0", 1),
+ _DEVICE (0xFFC01300, BFIN_MMR_EPPI_SIZE,      "bfin_eppi@1", 1),
+  DEVICE (0xFFC01600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC01610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC01620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC01630, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@3"),
+  DEVICE (0xFFC01640, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@4"),
+  DEVICE (0xFFC01650, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@5"),
+  DEVICE (0xFFC01660, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@6"),
+  DEVICE (0xFFC01670, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@7"),
+  DEVICE (0xFFC02000, BFIN_MMR_UART2_SIZE,     "bfin_uart2@1"),
+ _DEVICE (0xFFC02100, BFIN_MMR_UART2_SIZE,     "bfin_uart2@2", 1),
+  DEVICE (0xFFC02200, BFIN_MMR_TWI_SIZE,       "bfin_twi@1"),
+  DEVICE (0xFFC02300, BFIN_MMR_SPI_SIZE,       "bfin_spi@1"),
+ _DEVICE (0xFFC02400, BFIN_MMR_SPI_SIZE,       "bfin_spi@2", 1),
+ _DEVICE (0xFFC02900, BFIN_MMR_EPPI_SIZE,      "bfin_eppi@2", 1),
+ _DEVICE (0xFFC03100, BFIN_MMR_UART2_SIZE,     "bfin_uart2@3", 1),
+  DEVICE (0xFFC03B00, BFIN_MMR_NFC_SIZE,       "bfin_nfc"),
+};
+#define bf548_dev bf547_dev
+#define bf549_dev bf547_dev
+static const struct bfin_dmac_layout bf54x_dmac[] = {
+  { BFIN_MMR_DMAC0_BASE, 12, },
+  { BFIN_MMR_DMAC1_BASE, 12, },
+};
+#define bf542_dmac bf54x_dmac
+#define bf544_dmac bf54x_dmac
+#define bf547_dmac bf54x_dmac
+#define bf548_dmac bf54x_dmac
+#define bf549_dmac bf54x_dmac
+
+/* This is only Core A of course ...  */
+#define bf561_chipid 0x27bb
+static const struct bfin_memory_layout bf561_mem[] = {
+  LAYOUT (0xFFC00700, 0x50, read_write),       /* GPIO0 stub */
+  LAYOUT (0xFFC00800, 0x60, read_write),       /* SPORT0 stub */
+  LAYOUT (0xFFC00900, 0x60, read_write),       /* SPORT1 stub */
+  LAYOUT (0xFFC01500, 0x50, read_write),       /* GPIO1 stub */
+  LAYOUT (0xFFC01700, 0x50, read_write),       /* GPIO2 stub */
+  LAYOUT (0xFEB00000, 0x20000, read_write_exec),       /* L2 */
+  LAYOUT (0xFF800000, 0x4000, read_write),     /* Data A */
+  LAYOUT (0xFF804000, 0x4000, read_write),     /* Data A Cache */
+  LAYOUT (0xFF900000, 0x4000, read_write),     /* Data B */
+  LAYOUT (0xFF904000, 0x4000, read_write),     /* Data B Cache */
+  LAYOUT (0xFFA00000, 0x4000, read_write_exec),        /* Inst A [1] */
+  LAYOUT (0xFFA10000, 0x4000, read_write_exec),        /* Inst Cache [1] */
+};
+static const struct bfin_dev_layout bf561_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART_SIZE,      "bfin_uart@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC00610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC00620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC00630, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@3"),
+  DEVICE (0xFFC00640, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@4"),
+  DEVICE (0xFFC00650, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@5"),
+  DEVICE (0xFFC00660, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@6"),
+  DEVICE (0xFFC00670, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@7"),
+  DEVICE (0xFFC00A00, BFIN_MMR_EBIU_AMC_SIZE,  "bfin_ebiu_amc"),
+  DEVICE (0xFFC00A10, BFIN_MMR_EBIU_SDC_SIZE,  "bfin_ebiu_sdc"),
+ _DEVICE (0xFFC01000, BFIN_MMR_PPI_SIZE,       "bfin_ppi@0", 1),
+  DEVICE (0xFFC01200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@1"),
+ _DEVICE (0xFFC01300, BFIN_MMR_PPI_SIZE,       "bfin_ppi@1", 1),
+  DEVICE (0xFFC01600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@8"),
+  DEVICE (0xFFC01610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@9"),
+  DEVICE (0xFFC01620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@10"),
+  DEVICE (0xFFC01630, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@11"),
+};
+static const struct bfin_dmac_layout bf561_dmac[] = {
+  { BFIN_MMR_DMAC0_BASE, 12, },
+  { BFIN_MMR_DMAC1_BASE, 12, },
+  /* XXX: IMDMA: { 0xFFC01800, 4, }, */
+};
+
+#define bf592_chipid 0x20cb
+static const struct bfin_memory_layout bf592_mem[] = {
+  LAYOUT (0xFFC00700, 0x50, read_write),       /* GPIO0 stub */
+  LAYOUT (0xFFC00800, 0x60, read_write),       /* SPORT0 stub */
+  LAYOUT (0xFFC00900, 0x60, read_write),       /* SPORT1 stub */
+  LAYOUT (0xFFC01500, 0x50, read_write),       /* GPIO1 stub */
+  LAYOUT (0xFF800000, 0x8000, read_write),     /* Data A */
+  LAYOUT (0xFFA00000, 0x4000, read_write_exec),        /* Inst A [1] */
+  LAYOUT (0xFFA04000, 0x4000, read_write_exec),        /* Inst B [1] */
+};
+static const struct bfin_dev_layout bf592_dev[] = {
+  DEVICE (0xFFC00200, BFIN_MMR_WDOG_SIZE,      "bfin_wdog@0"),
+  DEVICE (0xFFC00400, BFIN_MMR_UART_SIZE,      "bfin_uart@0"),
+  DEVICE (0xFFC00500, BFIN_MMR_SPI_SIZE,       "bfin_spi@0"),
+  DEVICE (0xFFC00600, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@0"),
+  DEVICE (0xFFC00610, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@1"),
+  DEVICE (0xFFC00620, BFIN_MMR_GPTIMER_SIZE,   "bfin_gptimer@2"),
+  DEVICE (0xFFC01000, BFIN_MMR_PPI_SIZE,       "bfin_ppi@0"),
+  DEVICE (0xFFC01300, BFIN_MMR_SPI_SIZE,       "bfin_spi@1"),
+  DEVICE (0xFFC01400, BFIN_MMR_TWI_SIZE,       "bfin_twi@0"),
+};
+static const struct bfin_dmac_layout bf592_dmac[] = {
+  /* XXX: there are only 9 channels, but mdma code below assumes that they
+          start right after the dma channels ... */
+  { BFIN_MMR_DMAC0_BASE, 12, },
+};
+
+static const struct bfin_model_data bfin_model_data[] =
+{
+#define P(n) \
+  [MODEL_BF##n] = { \
+    bf##n##_chipid, n, \
+    bf##n##_mem , ARRAY_SIZE (bf##n##_mem ), \
+    bf##n##_dev , ARRAY_SIZE (bf##n##_dev ), \
+    bf##n##_dmac, ARRAY_SIZE (bf##n##_dmac), \
+  },
+#include "proc_list.def"
+#undef P
+};
+
+#define CORE_DEVICE(dev, DEV) \
+  DEVICE (BFIN_COREMMR_##DEV##_BASE, BFIN_COREMMR_##DEV##_SIZE, "bfin_"#dev)
+static const struct bfin_dev_layout bfin_core_dev[] = {
+  CORE_DEVICE (cec, CEC),
+  CORE_DEVICE (ctimer, CTIMER),
+  CORE_DEVICE (evt, EVT),
+  CORE_DEVICE (jtag, JTAG),
+  CORE_DEVICE (mmu, MMU),
+  CORE_DEVICE (trace, TRACE),
+  CORE_DEVICE (wp, WP),
+};
+
+#define dv_bfin_hw_parse(sd, dv, DV) \
+  do { \
+    bu32 base = BFIN_MMR_##DV##_BASE; \
+    bu32 size = BFIN_MMR_##DV##_SIZE; \
+    sim_hw_parse (sd, "/core/bfin_"#dv"/reg %#x %i", base, size); \
+    sim_hw_parse (sd, "/core/bfin_"#dv"/type %i",  mdata->model_num); \
+  } while (0)
+
+static void
+bfin_model_hw_tree_init (SIM_DESC sd, SIM_CPU *cpu)
+{
+  const MODEL *model = CPU_MODEL (cpu);
+  const struct bfin_model_data *mdata = CPU_MODEL_DATA (cpu);
+  const struct bfin_board_data *board = STATE_BOARD_DATA (sd);
+  int mnum = MODEL_NUM (model);
+  unsigned i, j, dma_chan;
+
+  /* Map the core devices.  */
+  for (i = 0; i < ARRAY_SIZE (bfin_core_dev); ++i)
+    {
+      const struct bfin_dev_layout *dev = &bfin_core_dev[i];
+      sim_hw_parse (sd, "/core/%s/reg %#x %i", dev->dev, dev->base, dev->len);
+    }
+  sim_hw_parse (sd, "/core/bfin_ctimer > ivtmr ivtmr /core/bfin_cec");
+
+  if (mnum == MODEL_BF000)
+    goto done;
+
+  /* Map the system devices.  */
+  dv_bfin_hw_parse (sd, sic, SIC);
+  sim_hw_parse (sd, "/core/bfin_sic/type %i", mdata->model_num);
+  for (i = 7; i < 16; ++i)
+    sim_hw_parse (sd, "/core/bfin_sic > ivg%i ivg%i /core/bfin_cec", i, i);
+
+  dv_bfin_hw_parse (sd, pll, PLL);
+  sim_hw_parse (sd, "/core/bfin_pll > pll pll /core/bfin_sic");
+
+  dma_chan = 0;
+  for (i = 0; i < mdata->dmac_count; ++i)
+    {
+      const struct bfin_dmac_layout *dmac = &mdata->dmac[i];
+
+      sim_hw_parse (sd, "/core/bfin_dmac@%u/type %i", i, mdata->model_num);
+
+      /* Hook up the non-mdma channels.  */
+      for (j = 0; j < dmac->dma_count; ++j)
+       {
+         sim_hw_parse (sd, "/core/bfin_dmac@%u/bfin_dma@%u/reg %#x %i", i,
+                       dma_chan, dmac->base + j * BFIN_MMR_DMA_SIZE,
+                       BFIN_MMR_DMA_SIZE);
+
+         /* Could route these into the bfin_dmac and let that
+            forward it to the SIC, but not much value.  */
+         sim_hw_parse (sd, "/core/bfin_dmac@%u/bfin_dma@%u > di dma@%u /core/bfin_sic",
+                       i, dma_chan, dma_chan);
+
+         ++dma_chan;
+       }
+
+      /* Hook up the mdma channels -- assume every DMAC has 4.  */
+      for (j = 0; j < 4; ++j)
+       {
+         sim_hw_parse (sd, "/core/bfin_dmac@%u/bfin_dma@%u/reg %#x %i",
+                       i, j + BFIN_DMAC_MDMA_BASE,
+                       dmac->base + (j + dmac->dma_count) * BFIN_MMR_DMA_SIZE,
+                       BFIN_MMR_DMA_SIZE);
+         sim_hw_parse (sd, "/core/bfin_dmac@%u/bfin_dma@%u > di mdma@%u /core/bfin_sic",
+                       i, j + BFIN_DMAC_MDMA_BASE, (2 * i) + (j / 2));
+       }
+    }
+
+  for (i = 0; i < mdata->dev_count; ++i)
+    {
+      const struct bfin_dev_layout *dev = &mdata->dev[i];
+      sim_hw_parse (sd, "/core/%s/reg %#x %i", dev->dev, dev->base, dev->len);
+      sim_hw_parse (sd, "/core/%s/type %i", dev->dev, mdata->model_num);
+      if (strchr (dev->dev, '/'))
+       continue;
+      if (!strncmp (dev->dev, "bfin_uart", 9)
+         || !strncmp (dev->dev, "bfin_emac", 9)
+         || !strncmp (dev->dev, "bfin_sport", 10))
+       {
+         const char *sint = dev->dev + 5;
+         sim_hw_parse (sd, "/core/%s > tx   %s_tx   /core/bfin_dmac@%u", dev->dev, sint, dev->dmac);
+         sim_hw_parse (sd, "/core/%s > rx   %s_rx   /core/bfin_dmac@%u", dev->dev, sint, dev->dmac);
+         sim_hw_parse (sd, "/core/%s > stat %s_stat /core/bfin_sic", dev->dev, sint);
+       }
+      else if (!strncmp (dev->dev, "bfin_gptimer", 12)
+              || !strncmp (dev->dev, "bfin_ppi", 8)
+              || !strncmp (dev->dev, "bfin_spi", 8)
+              || !strncmp (dev->dev, "bfin_twi", 8))
+       {
+         const char *sint = dev->dev + 5;
+         sim_hw_parse (sd, "/core/%s > stat %s /core/bfin_sic", dev->dev, sint);
+       }
+      else if (!strncmp (dev->dev, "bfin_rtc", 8))
+       {
+         const char *sint = dev->dev + 5;
+         sim_hw_parse (sd, "/core/%s > %s %s /core/bfin_sic", dev->dev, sint, sint);
+       }
+      else if (!strncmp (dev->dev, "bfin_wdog", 9))
+       {
+         sim_hw_parse (sd, "/core/%s > reset rst  /core/bfin_cec", dev->dev);
+         sim_hw_parse (sd, "/core/%s > nmi   nmi  /core/bfin_cec", dev->dev);
+         sim_hw_parse (sd, "/core/%s > gpi   wdog /core/bfin_sic", dev->dev);
+       }
+    }
+
+ done:
+  /* Add any additional user board content.  */
+  if (board->hw_file)
+    sim_do_commandf (sd, "hw-file %s", board->hw_file);
+
+  /* Trigger all the new devices' finish func.  */
+  hw_tree_finish (dv_get_device (cpu, "/"));
+}
+
+#include "bfroms/all.h"
+
+struct bfrom {
+  bu32 addr, len, alias_len;
+  int sirev;
+  const char *buf;
+};
+
+#define BFROMA(addr, rom, sirev, alias_len) \
+  { addr, sizeof (bfrom_bf##rom##_0_##sirev), alias_len, \
+    sirev, bfrom_bf##rom##_0_##sirev, }
+#define BFROM(rom, sirev, alias_len) BFROMA (0xef000000, rom, sirev, alias_len)
+#define BFROM_STUB { 0, 0, 0, 0, NULL, }
+static const struct bfrom bf50x_roms[] = {
+  BFROM (50x, 0, 0x1000000),
+  BFROM_STUB,
+};
+static const struct bfrom bf51x_roms[] = {
+  BFROM (51x, 2, 0x1000000),
+  BFROM (51x, 1, 0x1000000),
+  BFROM (51x, 0, 0x1000000),
+  BFROM_STUB,
+};
+static const struct bfrom bf526_roms[] = {
+  BFROM (526, 1, 0x1000000),
+  BFROM (526, 0, 0x1000000),
+  BFROM_STUB,
+};
+static const struct bfrom bf527_roms[] = {
+  BFROM (527, 2, 0x1000000),
+  BFROM (527, 1, 0x1000000),
+  BFROM (527, 0, 0x1000000),
+  BFROM_STUB,
+};
+static const struct bfrom bf533_roms[] = {
+  BFROM (533, 6, 0x1000000),
+  BFROM (533, 5, 0x1000000),
+  BFROM (533, 4, 0x1000000),
+  BFROM (533, 3, 0x1000000),
+  BFROM (533, 2, 0x1000000),
+  BFROM (533, 1, 0x1000000),
+  BFROM_STUB,
+};
+static const struct bfrom bf537_roms[] = {
+  BFROM (537, 3, 0x100000),
+  BFROM (537, 2, 0x100000),
+  BFROM (537, 1, 0x100000),
+  BFROM (537, 0, 0x100000),
+  BFROM_STUB,
+};
+static const struct bfrom bf538_roms[] = {
+  BFROM (538, 5, 0x1000000),
+  BFROM (538, 4, 0x1000000),
+  BFROM (538, 3, 0x1000000),
+  BFROM (538, 2, 0x1000000),
+  BFROM (538, 1, 0x1000000),
+  BFROM (538, 0, 0x1000000),
+  BFROM_STUB,
+};
+static const struct bfrom bf54x_roms[] = {
+  BFROM (54x, 2, 0),
+  BFROM (54x, 1, 0),
+  BFROM (54x, 0, 0),
+  BFROMA (0xffa14000, 54x_l1, 2, 0),
+  BFROMA (0xffa14000, 54x_l1, 1, 0),
+  BFROMA (0xffa14000, 54x_l1, 0, 0),
+  BFROM_STUB,
+};
+static const struct bfrom bf561_roms[] = {
+  /* XXX: No idea what the actual wrap limit is here.  */
+  BFROM (561, 5, 0),
+  BFROM_STUB,
+};
+static const struct bfrom bf59x_roms[] = {
+  BFROM (59x, 1, 0x1000000),
+  BFROM (59x, 0, 0x1000000),
+  BFROMA (0xffa10000, 59x_l1, 1, 0),
+  BFROM_STUB,
+};
+
+static void
+bfin_model_map_bfrom (SIM_DESC sd, SIM_CPU *cpu)
+{
+  const struct bfin_model_data *mdata = CPU_MODEL_DATA (cpu);
+  const struct bfin_board_data *board = STATE_BOARD_DATA (sd);
+  int mnum = mdata->model_num;
+  const struct bfrom *bfrom;
+  unsigned int sirev;
+
+  if (mnum >= 500 && mnum <= 509)
+    bfrom = bf50x_roms;
+  else if (mnum >= 510 && mnum <= 519)
+    bfrom = bf51x_roms;
+  else if (mnum >= 520 && mnum <= 529)
+    bfrom = (mnum & 1) ? bf527_roms : bf526_roms;
+  else if (mnum >= 531 && mnum <= 533)
+    bfrom = bf533_roms;
+  else if (mnum == 535)
+    /* Stub.  */;
+  else if (mnum >= 534 && mnum <= 537)
+    bfrom = bf537_roms;
+  else if (mnum >= 538 && mnum <= 539)
+    bfrom = bf538_roms;
+  else if (mnum >= 540 && mnum <= 549)
+    bfrom = bf54x_roms;
+  else if (mnum == 561)
+    bfrom = bf561_roms;
+  else if (mnum >= 590 && mnum <= 599)
+    bfrom = bf59x_roms;
+  else
+    return;
+
+  if (board->sirev_valid)
+    sirev = board->sirev;
+  else
+    sirev = bfrom->sirev;
+  while (bfrom->buf)
+    {
+      /* Map all the ranges for this model/sirev.  */
+      if (bfrom->sirev == sirev)
+        sim_core_attach (sd, NULL, 0, access_read_exec, 0, bfrom->addr,
+                        bfrom->alias_len ? : bfrom->len, bfrom->len, NULL,
+                        (char *)bfrom->buf);
+      ++bfrom;
+    }
+}
+
+void
+bfin_model_cpu_init (SIM_DESC sd, SIM_CPU *cpu)
+{
+  const MODEL *model = CPU_MODEL (cpu);
+  const struct bfin_model_data *mdata = CPU_MODEL_DATA (cpu);
+  int mnum = MODEL_NUM (model);
+  size_t idx;
+
+  /* These memory maps are supposed to be cpu-specific, but the common sim
+     code does not yet allow that (2nd arg is "cpu" rather than "NULL".  */
+  sim_core_attach (sd, NULL, 0, access_read_write, 0, BFIN_L1_SRAM_SCRATCH,
+                  BFIN_L1_SRAM_SCRATCH_SIZE, 0, NULL, NULL);
+
+  if (STATE_ENVIRONMENT (CPU_STATE (cpu)) != OPERATING_ENVIRONMENT)
+    return;
+
+  if (mnum == MODEL_BF000)
+    goto core_only;
+
+  /* Map in the on-chip memories (SRAMs).  */
+  mdata = &bfin_model_data[MODEL_NUM (model)];
+  for (idx = 0; idx < mdata->mem_count; ++idx)
+    {
+      const struct bfin_memory_layout *mem = &mdata->mem[idx];
+      sim_core_attach (sd, NULL, 0, mem->mask, 0, mem->addr,
+                      mem->len, 0, NULL, NULL);
+    }
+
+  /* Map the on-chip ROMs.  */
+  bfin_model_map_bfrom (sd, cpu);
+
+ core_only:
+  /* Finally, build up the tree for this cpu model.  */
+  bfin_model_hw_tree_init (sd, cpu);
+}
+
+bu32
+bfin_model_get_chipid (SIM_DESC sd)
+{
+  SIM_CPU *cpu = STATE_CPU (sd, 0);
+  const struct bfin_model_data *mdata = CPU_MODEL_DATA (cpu);
+  const struct bfin_board_data *board = STATE_BOARD_DATA (sd);
+  return
+        (board->sirev << 28) |
+        (mdata->chipid << 12) |
+        (((0xE5 << 1) | 1) & 0xFF);
+}
+
+bu32
+bfin_model_get_dspid (SIM_DESC sd)
+{
+  const struct bfin_board_data *board = STATE_BOARD_DATA (sd);
+  return
+        (0xE5 << 24) |
+        (0x04 << 16) |
+        (board->sirev);
+}
+
+static void
+bfin_model_init (SIM_CPU *cpu)
+{
+  CPU_MODEL_DATA (cpu) = (void *) &bfin_model_data[MODEL_NUM (CPU_MODEL (cpu))];
+}
+
+static bu32
+bfin_extract_unsigned_integer (unsigned char *addr, int len)
+{
+  bu32 retval;
+  unsigned char * p;
+  unsigned char * startaddr = (unsigned char *)addr;
+  unsigned char * endaddr = startaddr + len;
+
+  retval = 0;
+
+  for (p = endaddr; p > startaddr;)
+    retval = (retval << 8) | *--p;
+
+  return retval;
+}
+
+static void
+bfin_store_unsigned_integer (unsigned char *addr, int len, bu32 val)
+{
+  unsigned char *p;
+  unsigned char *startaddr = addr;
+  unsigned char *endaddr = startaddr + len;
+
+  for (p = startaddr; p < endaddr;)
+    {
+      *p++ = val & 0xff;
+      val >>= 8;
+    }
+}
+
+static bu32 *
+bfin_get_reg (SIM_CPU *cpu, int rn)
+{
+  switch (rn)
+    {
+    case SIM_BFIN_R0_REGNUM: return &DREG (0);
+    case SIM_BFIN_R1_REGNUM: return &DREG (1);
+    case SIM_BFIN_R2_REGNUM: return &DREG (2);
+    case SIM_BFIN_R3_REGNUM: return &DREG (3);
+    case SIM_BFIN_R4_REGNUM: return &DREG (4);
+    case SIM_BFIN_R5_REGNUM: return &DREG (5);
+    case SIM_BFIN_R6_REGNUM: return &DREG (6);
+    case SIM_BFIN_R7_REGNUM: return &DREG (7);
+    case SIM_BFIN_P0_REGNUM: return &PREG (0);
+    case SIM_BFIN_P1_REGNUM: return &PREG (1);
+    case SIM_BFIN_P2_REGNUM: return &PREG (2);
+    case SIM_BFIN_P3_REGNUM: return &PREG (3);
+    case SIM_BFIN_P4_REGNUM: return &PREG (4);
+    case SIM_BFIN_P5_REGNUM: return &PREG (5);
+    case SIM_BFIN_SP_REGNUM: return &SPREG;
+    case SIM_BFIN_FP_REGNUM: return &FPREG;
+    case SIM_BFIN_I0_REGNUM: return &IREG (0);
+    case SIM_BFIN_I1_REGNUM: return &IREG (1);
+    case SIM_BFIN_I2_REGNUM: return &IREG (2);
+    case SIM_BFIN_I3_REGNUM: return &IREG (3);
+    case SIM_BFIN_M0_REGNUM: return &MREG (0);
+    case SIM_BFIN_M1_REGNUM: return &MREG (1);
+    case SIM_BFIN_M2_REGNUM: return &MREG (2);
+    case SIM_BFIN_M3_REGNUM: return &MREG (3);
+    case SIM_BFIN_B0_REGNUM: return &BREG (0);
+    case SIM_BFIN_B1_REGNUM: return &BREG (1);
+    case SIM_BFIN_B2_REGNUM: return &BREG (2);
+    case SIM_BFIN_B3_REGNUM: return &BREG (3);
+    case SIM_BFIN_L0_REGNUM: return &LREG (0);
+    case SIM_BFIN_L1_REGNUM: return &LREG (1);
+    case SIM_BFIN_L2_REGNUM: return &LREG (2);
+    case SIM_BFIN_L3_REGNUM: return &LREG (3);
+    case SIM_BFIN_RETS_REGNUM: return &RETSREG;
+    case SIM_BFIN_A0_DOT_X_REGNUM: return &AXREG (0);
+    case SIM_BFIN_A0_DOT_W_REGNUM: return &AWREG (0);
+    case SIM_BFIN_A1_DOT_X_REGNUM: return &AXREG (1);
+    case SIM_BFIN_A1_DOT_W_REGNUM: return &AWREG (1);
+    case SIM_BFIN_LC0_REGNUM: return &LCREG (0);
+    case SIM_BFIN_LT0_REGNUM: return &LTREG (0);
+    case SIM_BFIN_LB0_REGNUM: return &LBREG (0);
+    case SIM_BFIN_LC1_REGNUM: return &LCREG (1);
+    case SIM_BFIN_LT1_REGNUM: return &LTREG (1);
+    case SIM_BFIN_LB1_REGNUM: return &LBREG (1);
+    case SIM_BFIN_CYCLES_REGNUM: return &CYCLESREG;
+    case SIM_BFIN_CYCLES2_REGNUM: return &CYCLES2REG;
+    case SIM_BFIN_USP_REGNUM: return &USPREG;
+    case SIM_BFIN_SEQSTAT_REGNUM: return &SEQSTATREG;
+    case SIM_BFIN_SYSCFG_REGNUM: return &SYSCFGREG;
+    case SIM_BFIN_RETI_REGNUM: return &RETIREG;
+    case SIM_BFIN_RETX_REGNUM: return &RETXREG;
+    case SIM_BFIN_RETN_REGNUM: return &RETNREG;
+    case SIM_BFIN_RETE_REGNUM: return &RETEREG;
+    case SIM_BFIN_PC_REGNUM: return &PCREG;
+    default: return NULL;
+  }
+}
+
+static int
+bfin_reg_fetch (SIM_CPU *cpu, int rn, unsigned char *buf, int len)
+{
+  bu32 value, *reg;
+
+  reg = bfin_get_reg (cpu, rn);
+  if (reg)
+    value = *reg;
+  else if (rn == SIM_BFIN_ASTAT_REGNUM)
+    value = ASTAT;
+  else if (rn == SIM_BFIN_CC_REGNUM)
+    value = CCREG;
+  else
+    return 0; // will be an error in gdb
+
+  /* Handle our KSP/USP shadowing in SP.  While in supervisor mode, we
+     have the normal SP/USP behavior.  User mode is tricky though.  */
+  if (STATE_ENVIRONMENT (CPU_STATE (cpu)) == OPERATING_ENVIRONMENT
+      && cec_is_user_mode (cpu))
+    {
+      if (rn == SIM_BFIN_SP_REGNUM)
+       value = KSPREG;
+      else if (rn == SIM_BFIN_USP_REGNUM)
+       value = SPREG;
+    }
+
+  bfin_store_unsigned_integer (buf, 4, value);
+
+  return -1; // disables size checking in gdb
+}
+
+static int
+bfin_reg_store (SIM_CPU *cpu, int rn, unsigned char *buf, int len)
+{
+  bu32 value, *reg;
+
+  value = bfin_extract_unsigned_integer (buf, 4);
+  reg = bfin_get_reg (cpu, rn);
+
+  if (reg)
+    /* XXX: Need register trace ?  */
+    *reg = value;
+  else if (rn == SIM_BFIN_ASTAT_REGNUM)
+    SET_ASTAT (value);
+  else if (rn == SIM_BFIN_CC_REGNUM)
+    SET_CCREG (value);
+  else
+    return 0; // will be an error in gdb
+
+  return -1; // disables size checking in gdb
+}
+
+static sim_cia
+bfin_pc_get (SIM_CPU *cpu)
+{
+  return PCREG;
+}
+
+static void
+bfin_pc_set (SIM_CPU *cpu, sim_cia newpc)
+{
+  SET_PCREG (newpc);
+}
+
+static const char *
+bfin_insn_name (SIM_CPU *cpu, int i)
+{
+  static const char * const insn_name[] = {
+#define I(insn) #insn,
+#include "insn_list.def"
+#undef I
+  };
+  return insn_name[i];
+}
+
+static void
+bfin_init_cpu (SIM_CPU *cpu)
+{
+  CPU_REG_FETCH (cpu) = bfin_reg_fetch;
+  CPU_REG_STORE (cpu) = bfin_reg_store;
+  CPU_PC_FETCH (cpu) = bfin_pc_get;
+  CPU_PC_STORE (cpu) = bfin_pc_set;
+  CPU_MAX_INSNS (cpu) = BFIN_INSN_MAX;
+  CPU_INSN_NAME (cpu) = bfin_insn_name;
+}
+
+static void
+bfin_prepare_run (SIM_CPU *cpu)
+{
+}
+
+static const MODEL bfin_models[] =
+{
+#define P(n) { "bf"#n, & bfin_mach, MODEL_BF##n, NULL, bfin_model_init },
+#include "proc_list.def"
+#undef P
+  { 0, NULL, 0, NULL, NULL, }
+};
+
+static const MACH_IMP_PROPERTIES bfin_imp_properties =
+{
+  sizeof (SIM_CPU),
+  0,
+};
+
+static const MACH bfin_mach =
+{
+  "bfin", "bfin", MACH_BFIN,
+  32, 32, & bfin_models[0], & bfin_imp_properties,
+  bfin_init_cpu,
+  bfin_prepare_run
+};
+
+const MACH *sim_machs[] =
+{
+  & bfin_mach,
+  NULL
+};
+\f
+/* Device option parsing.  */
+
+static DECLARE_OPTION_HANDLER (bfin_mach_option_handler);
+
+enum {
+  OPTION_MACH_SIREV = OPTION_START,
+  OPTION_MACH_HW_BOARD_FILE,
+};
+
+const OPTION bfin_mach_options[] =
+{
+  { {"sirev", required_argument, NULL, OPTION_MACH_SIREV },
+      '\0', "NUMBER", "Set CPU silicon revision",
+      bfin_mach_option_handler, NULL },
+
+  { {"hw-board-file", required_argument, NULL, OPTION_MACH_HW_BOARD_FILE },
+      '\0', "FILE", "Add the supplemental devices listed in the file",
+      bfin_mach_option_handler, NULL },
+
+  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
+};
+
+static SIM_RC
+bfin_mach_option_handler (SIM_DESC sd, sim_cpu *current_cpu, int opt,
+                         char *arg, int is_command)
+{
+  struct bfin_board_data *board = STATE_BOARD_DATA (sd);
+
+  switch (opt)
+    {
+    case OPTION_MACH_SIREV:
+      board->sirev_valid = 1;
+      /* Accept (and throw away) a leading "0." in the version.  */
+      if (!strncmp (arg, "0.", 2))
+       arg += 2;
+      board->sirev = atoi (arg);
+      if (board->sirev > 0xf)
+       {
+         sim_io_eprintf (sd, "sirev '%s' needs to fit into 4 bits\n", arg);
+         return SIM_RC_FAIL;
+       }
+      return SIM_RC_OK;
+
+    case OPTION_MACH_HW_BOARD_FILE:
+      board->hw_file = xstrdup (arg);
+      return SIM_RC_OK;
+
+    default:
+      sim_io_eprintf (sd, "Unknown Blackfin option %d\n", opt);
+      return SIM_RC_FAIL;
+    }
+}
diff --git a/sim/bfin/machs.h b/sim/bfin/machs.h
new file mode 100644 (file)
index 0000000..ac16adb
--- /dev/null
@@ -0,0 +1,56 @@
+/* Simulator for Analog Devices Blackfin processors.
+
+   Copyright (C) 2005-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BFIN_MACHS_H_
+#define _BFIN_MACHS_H_
+
+typedef enum model_type {
+#define P(n) MODEL_BF##n,
+#include "proc_list.def"
+#undef P
+  MODEL_MAX
+} MODEL_TYPE;
+
+typedef enum mach_attr {
+  MACH_BASE,
+  MACH_BFIN,
+  MACH_MAX
+} MACH_ATTR;
+
+#define CPU_MODEL_NUM(cpu) MODEL_NUM (CPU_MODEL (cpu))
+
+/* XXX: Some of this probably belongs in CPU_MODEL.  */
+struct bfin_board_data {
+  unsigned int sirev, sirev_valid;
+  const char *hw_file;
+};
+
+void bfin_model_cpu_init (SIM_DESC, SIM_CPU *);
+bu32 bfin_model_get_chipid (SIM_DESC);
+bu32 bfin_model_get_dspid (SIM_DESC);
+
+enum {
+#define I(insn) BFIN_INSN_##insn,
+#include "insn_list.def"
+#undef I
+  BFIN_INSN_MAX
+};
+
+#endif
diff --git a/sim/bfin/proc_list.def b/sim/bfin/proc_list.def
new file mode 100644 (file)
index 0000000..aa9d337
--- /dev/null
@@ -0,0 +1,50 @@
+/* Blackfin processor list
+
+   Copyright (C) 2005-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+/* First entry is the default model.  */
+P(537)
+P(504)
+P(506)
+P(512)
+P(514)
+P(516)
+P(518)
+P(522)
+P(523)
+P(524)
+P(525)
+P(526)
+P(527)
+P(531)
+P(532)
+P(533)
+P(534)
+/*P(535)*/
+P(536)
+P(538)
+P(539)
+P(542)
+P(544)
+P(547)
+P(548)
+P(549)
+P(561)
+P(592)
+P(000)
diff --git a/sim/bfin/sim-main.h b/sim/bfin/sim-main.h
new file mode 100644 (file)
index 0000000..3a93703
--- /dev/null
@@ -0,0 +1,117 @@
+/* Simulator for Analog Devices Blackfin processors.
+
+   Copyright (C) 2005-2011 Free Software Foundation, Inc.
+   Contributed by Analog Devices, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BFIN_MAIN_SIM_H_
+#define _BFIN_MAIN_SIM_H_
+
+#include "sim-basics.h"
+#include "sim-signal.h"
+
+typedef unsigned32 sim_cia;
+
+#define CIA_GET(cpu)     CPU_PC_GET (cpu)
+#define CIA_SET(cpu,val) CPU_PC_SET ((cpu), (val))
+
+typedef struct _sim_cpu SIM_CPU;
+
+#include "bfin-sim.h"
+
+#include "machs.h"
+
+#include "sim-base.h"
+
+struct _sim_cpu {
+  /* ... simulator specific members ... */
+  struct bfin_cpu_state state;
+  sim_cpu_base base;
+};
+#define BFIN_CPU_STATE ((cpu)->state)
+
+struct sim_state {
+  sim_cpu *cpu[MAX_NR_PROCESSORS];
+#if (WITH_SMP)
+#define STATE_CPU(sd,n) ((sd)->cpu[n])
+#else
+#define STATE_CPU(sd,n) ((sd)->cpu[0])
+#endif
+  /* ... simulator specific members ... */
+  struct bfin_board_data board;
+#define STATE_BOARD_DATA(sd) (&(sd)->board)
+  sim_state_base base;
+};
+
+#include "sim-config.h"
+#include "sim-types.h"
+#include "sim-engine.h"
+#include "sim-options.h"
+#include "run-sim.h"
+#include "dv-bfin_trace.h"
+
+#undef MAX
+#undef MIN
+#undef CLAMP
+#undef ALIGN
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define CLAMP(a, b, c) MIN (MAX (a, b), c)
+#define ALIGN(addr, size) (((addr) + ((size)-1)) & ~((size)-1))
+
+#define MAYBE_TRACE(type, cpu, fmt, ...) \
+  do { \
+    if (TRACE_##type##_P (cpu)) \
+      trace_generic (CPU_STATE (cpu), cpu, TRACE_##type##_IDX, \
+                    fmt, ## __VA_ARGS__); \
+  } while (0)
+#define TRACE_INSN(cpu, fmt, ...) MAYBE_TRACE (INSN, cpu, fmt, ## __VA_ARGS__)
+#define TRACE_DECODE(cpu, fmt, ...) MAYBE_TRACE (DECODE, cpu, fmt, ## __VA_ARGS__)
+#define TRACE_EXTRACT(cpu, fmt, ...) MAYBE_TRACE (EXTRACT, cpu, fmt, ## __VA_ARGS__)
+#define TRACE_SYSCALL(cpu, fmt, ...) MAYBE_TRACE (EVENTS, cpu, fmt, ## __VA_ARGS__)
+#define TRACE_CORE(cpu, addr, size, map, val) \
+  do { \
+    MAYBE_TRACE (CORE, cpu, "%cBUS %s %i bytes @ 0x%08x: 0x%0*x", \
+                map == exec_map ? 'I' : 'D', \
+                map == write_map ? "STORE" : "FETCH", \
+                size, addr, size * 2, val); \
+    PROFILE_COUNT_CORE (cpu, addr, size, map); \
+  } while (0)
+#define TRACE_EVENTS(cpu, fmt, ...) MAYBE_TRACE (EVENTS, cpu, fmt, ## __VA_ARGS__)
+#define TRACE_BRANCH(cpu, oldpc, newpc, hwloop, fmt, ...) \
+  do { \
+    MAYBE_TRACE (BRANCH, cpu, fmt " to %#x", ## __VA_ARGS__, newpc); \
+    if (STATE_ENVIRONMENT (CPU_STATE (cpu)) == OPERATING_ENVIRONMENT) \
+      bfin_trace_queue (cpu, oldpc, newpc, hwloop); \
+  } while (0)
+
+extern void trace_register PARAMS ((SIM_DESC sd,
+                                   sim_cpu *cpu,
+                                   const char *fmt,
+                                   ...))
+     __attribute__((format (printf, 3, 4)));
+#define TRACE_REGISTER(cpu, fmt, ...) \
+  do { \
+    if (TRACE_CORE_P (cpu)) \
+      trace_register (CPU_STATE (cpu), cpu, fmt, ## __VA_ARGS__); \
+  } while (0)
+#define TRACE_REG(cpu, reg, val) TRACE_REGISTER (cpu, "wrote "#reg" = %#x", val)
+
+/* Default memory size.  */
+#define BFIN_DEFAULT_MEM_SIZE (128 * 1024 * 1024)
+
+#endif
diff --git a/sim/bfin/tconfig.in b/sim/bfin/tconfig.in
new file mode 100644 (file)
index 0000000..130707a
--- /dev/null
@@ -0,0 +1,27 @@
+/* Blackfin target configuration file.  -*- C -*- */
+
+/* See sim-hload.c.  We properly handle LMA. -- TODO: check this */
+#define SIM_HANDLES_LMA 1
+
+/* We use this so that we are passed the requesting CPU for HW acesses.
+   Common sim core by default sets hw_system_cpu to NULL for WITH_HW.  */
+#define WITH_DEVICES 1
+
+/* FIXME: This is unnecessarily necessary: */
+#include "ansidecl.h"
+#include "gdb/callback.h"
+#include "gdb/remote-sim.h"
+#include "sim-module.h"
+
+/* FIXME: Revisit.  */
+#ifdef HAVE_DV_SOCKSER
+MODULE_INSTALL_FN dv_sockser_install;
+#define MODULE_LIST dv_sockser_install,
+#endif
+
+/* ??? Temporary hack until model support unified.  */
+#define SIM_HAVE_MODEL
+
+/* Allows us to do the memory aliasing that some bfroms have:
+   {0xef000000 - 0xef100000} => {0xef000000 - 0xef000800}  */
+#define WITH_MODULO_MEMORY 1
index b88fc32..3a9da40 100644 (file)
@@ -1,3 +1,8 @@
+2011-03-05  Mike Frysinger  <vapier@gentoo.org>
+
+       * gennltvals.sh: Handle bfin targets.
+       * nltvals.def: Regenerate.
+
 2011-02-25  Kevin Buettner  <kevinb@redhat.com>
 
        * callback.c (fdbad): Return EBADF rather than EINVAL for bad
index 462e576..d882e20 100644 (file)
@@ -29,6 +29,10 @@ $shell ${srccom}/gentvals.sh "" open ${srcroot}/newlib/libc/include \
 # Note that there is a standard syscall.h file (libgloss/syscall.h) now which
 # hopefully more targets can use.
 
+dir=libgloss target=bfin
+$shell ${srccom}/gentvals.sh $target sys ${srcroot}/$dir \
+       "syscall.h" 'SYS_[_A-Za-z0-9]*' "${cpp}"
+
 dir=newlib/libc/sys/d10v/sys target=d10v
 $shell ${srccom}/gentvals.sh $target sys ${srcroot}/$dir \
        "syscall.h" 'SYS_[_A-Za-z0-9]*' "${cpp}"
index c8089c0..ab051b1 100644 (file)
  { "O_WRONLY", 1  },
 /* end open target macros */
 #endif
+#ifdef NL_TARGET_bfin
+#ifdef sys_defs
+/* from syscall.h */
+/* begin bfin sys target macros */
+ { "SYS_argc", 22 },
+ { "SYS_argn", 24 },
+ { "SYS_argnlen", 23 },
+ { "SYS_argv", 13 },
+ { "SYS_argvlen", 12 },
+ { "SYS_chdir", 14 },
+ { "SYS_chmod", 16 },
+ { "SYS_close", 3 },
+ { "SYS_exit", 1 },
+ { "SYS_fstat", 10 },
+ { "SYS_getpid", 8 },
+ { "SYS_gettimeofday", 19 },
+ { "SYS_kill", 9 },
+ { "SYS_link", 21 },
+ { "SYS_lseek", 6 },
+ { "SYS_open", 2 },
+ { "SYS_read", 4 },
+ { "SYS_stat", 15 },
+ { "SYS_time", 18 },
+ { "SYS_times", 20 },
+ { "SYS_unlink", 7 },
+ { "SYS_utime", 17 },
+ { "SYS_write", 5 },
+/* end bfin sys target macros */
+#endif
+#endif
 #ifdef NL_TARGET_d10v
 #ifdef sys_defs
 /* from syscall.h */
index b6488e2..b3d8b39 100755 (executable)
@@ -636,6 +636,7 @@ LIBS
 CPPFLAGS'
 ac_subdirs_all='arm
 avr
+bfin
 cr16
 cris
 d10v
@@ -3639,6 +3640,13 @@ subdirs="$subdirs arm"
 
 
        ;;
+   bfin-*-*)
+
+  sim_arch=bfin
+  subdirs="$subdirs bfin"
+
+
+       ;;
    cr16*-*-*)
 
   sim_arch=cr16
index 592bc3c..9808492 100644 (file)
@@ -23,6 +23,9 @@ case "${target}" in
    avr*-*-*)
        SIM_ARCH(avr)
        ;;
+   bfin-*-*)
+       SIM_ARCH(bfin)
+       ;;
    cr16*-*-*)
        SIM_ARCH(cr16)
        sim_testsuite=yes