From: Mike Frysinger Date: Sun, 6 Mar 2011 00:20:21 +0000 (+0000) Subject: sim: bfin: new port X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ef016f835f292f01f065412fcfd84c50bfff1fea;p=binutils-gdb.git sim: bfin: new port 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 --- diff --git a/include/gdb/ChangeLog b/include/gdb/ChangeLog index 19509e22188..8b31e114759 100644 --- a/include/gdb/ChangeLog +++ b/include/gdb/ChangeLog @@ -1,3 +1,7 @@ +2011-03-05 Mike Frysinger + + * sim-bfin.h: New file. + 2011-01-11 Andrew Burgess * 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 index 00000000000..3a006b882ef --- /dev/null +++ b/include/gdb/sim-bfin.h @@ -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 . */ + +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 +}; + diff --git a/sim/ChangeLog b/sim/ChangeLog index debebb23278..72279928622 100644 --- a/sim/ChangeLog +++ b/sim/ChangeLog @@ -1,3 +1,9 @@ +2011-03-05 Mike Frysinger + + * MAINTAINERS: Add bfin entry. + * configure.tgt (bfin-*-*): Handle bfin targets. + * configure: Regenerate. + 2011-01-05 Mike Frysinger * .gitignore: Add /*/hw-config.h. diff --git a/sim/MAINTAINERS b/sim/MAINTAINERS index 1e0f2ce67c0..d273002d043 100644 --- a/sim/MAINTAINERS +++ b/sim/MAINTAINERS @@ -10,6 +10,7 @@ gdb-patches@sources.redhat.com Maintainers for particular sims: arm Nick Clifton +bfin Mike Frysinger cr16 M R Swami Reddy frv Dave Brolley igen (igen simulators) diff --git a/sim/bfin/Makefile.in b/sim/bfin/Makefile.in new file mode 100644 index 00000000000..64f26d3e59c --- /dev/null +++ b/sim/bfin/Makefile.in @@ -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 . + +# 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 index 00000000000..d180ab26843 --- /dev/null +++ b/sim/bfin/TODO @@ -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 index 00000000000..cbe3b5592dd --- /dev/null +++ b/sim/bfin/aclocal.m4 @@ -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 . +# +# 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 .])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 index 00000000000..6d9361e94cd --- /dev/null +++ b/sim/bfin/bfin-sim.c @@ -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 . */ + +#include "config.h" + +#include +#include +#include +#include + +#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", "", "", "ASTAT", "RETS", + "", "", "", "", "", "", "", "", + "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 <REG (0); + case 50: return &LBREG (0); + case 51: return &LCREG (1); + case 52: return <REG (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 == <REG (0) || whichreg == <REG (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 index 00000000000..d61e7fe1f7b --- /dev/null +++ b/sim/bfin/bfin-sim.h @@ -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 . */ + +#ifndef _BFIN_SIM_H_ +#define _BFIN_SIM_H_ + +#include +#include + +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 index 00000000000..1b562d9df40 --- /dev/null +++ b/sim/bfin/bfroms/all.h @@ -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 index 00000000000..00dcc104c9a --- /dev/null +++ b/sim/bfin/bfroms/bf50x-0.0.h @@ -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 index 00000000000..62b5682b498 --- /dev/null +++ b/sim/bfin/bfroms/bf51x-0.0.h @@ -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 index 00000000000..ab82f8f8b67 --- /dev/null +++ b/sim/bfin/bfroms/bf51x-0.1.h @@ -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 index 00000000000..6cd8dbcb6a9 --- /dev/null +++ b/sim/bfin/bfroms/bf51x-0.2.h @@ -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 index 00000000000..8b60b479ca9 --- /dev/null +++ b/sim/bfin/bfroms/bf526-0.0.h @@ -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 index 00000000000..4d53e0b3fb6 --- /dev/null +++ b/sim/bfin/bfroms/bf526-0.1.h @@ -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 index 00000000000..9e23e90f74b --- /dev/null +++ b/sim/bfin/bfroms/bf527-0.0.h @@ -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 index 00000000000..1d0c0a977a5 --- /dev/null +++ b/sim/bfin/bfroms/bf527-0.1.h @@ -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 index 00000000000..e0066f3bba2 --- /dev/null +++ b/sim/bfin/bfroms/bf527-0.2.h @@ -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 index 00000000000..1f1fd6660c3 --- /dev/null +++ b/sim/bfin/bfroms/bf533-0.1.h @@ -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 index 00000000000..00aba572ef9 --- /dev/null +++ b/sim/bfin/bfroms/bf533-0.2.h @@ -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 index 00000000000..829485b05d5 --- /dev/null +++ b/sim/bfin/bfroms/bf533-0.3.h @@ -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 index 00000000000..ec945d26a84 --- /dev/null +++ b/sim/bfin/bfroms/bf537-0.0.h @@ -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 index 00000000000..4c6d46d9a0b --- /dev/null +++ b/sim/bfin/bfroms/bf537-0.1.h @@ -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 index 00000000000..4483a9f7caf --- /dev/null +++ b/sim/bfin/bfroms/bf537-0.3.h @@ -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 index 00000000000..a5dff38542a --- /dev/null +++ b/sim/bfin/bfroms/bf538-0.0.h @@ -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 index 00000000000..9141b29f033 --- /dev/null +++ b/sim/bfin/bfroms/bf54x-0.0.h @@ -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 index 00000000000..9d82c58a8da --- /dev/null +++ b/sim/bfin/bfroms/bf54x-0.1.h @@ -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 index 00000000000..ea5722576dd --- /dev/null +++ b/sim/bfin/bfroms/bf54x-0.2.h @@ -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 index 00000000000..afeaf74411d --- /dev/null +++ b/sim/bfin/bfroms/bf54x_l1-0.0.h @@ -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 index 00000000000..7a1ff33064f --- /dev/null +++ b/sim/bfin/bfroms/bf54x_l1-0.1.h @@ -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 index 00000000000..ad138cf82ab --- /dev/null +++ b/sim/bfin/bfroms/bf54x_l1-0.2.h @@ -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 index 00000000000..1d271415fae --- /dev/null +++ b/sim/bfin/bfroms/bf561-0.5.h @@ -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 index 00000000000..737f6440090 --- /dev/null +++ b/sim/bfin/bfroms/bf59x-0.0.h @@ -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 index 00000000000..3be46eeee81 --- /dev/null +++ b/sim/bfin/bfroms/bf59x_l1-0.1.h @@ -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 index 00000000000..b44011d7e80 --- /dev/null +++ b/sim/bfin/config.in @@ -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 header file. */ +#undef HAVE_DLFCN_H + +/* Define if dv-sockser is usable. */ +#undef HAVE_DV_SOCKSER + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the 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 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 header file. */ +#undef HAVE_LINUX_IF_TUN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_MII_H + +/* Define to 1 if you have the 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 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 header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the 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 index 00000000000..ff71b591f55 --- /dev/null +++ b/sim/bfin/configure @@ -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 &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 +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#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 if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + 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 declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 +#include +#include +#include +/* 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 to if __STDC__ is defined, since + # 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 +#else +# include +#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 +_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 to if __STDC__ is defined, since + # 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 +#else +# include +#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 +_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 +#include +#include +#include + +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 + +_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 + +_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 +#include +#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 +#include + +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 + #include + +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 + #include + +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 defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +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 + +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` +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 +' >$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 = "" + +} +{ + 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 +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\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' Makesim1.tmp + sed -n -e '/^## COMMON_POST_/,/^## End COMMON_POST_/ p' Makesim2.tmp + sed -e '/^## COMMON_PRE_/ r Makesim1.tmp' \ + -e '/^## COMMON_POST_/ r Makesim2.tmp' \ + 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 index 00000000000..736a212458f --- /dev/null +++ b/sim/bfin/configure.ac @@ -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 index 00000000000..50c53d10445 --- /dev/null +++ b/sim/bfin/devices.c @@ -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 . */ + +#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 index 00000000000..76854ed33a4 --- /dev/null +++ b/sim/bfin/devices.h @@ -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 . */ + +#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 *); + +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); +} + +/* 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); +} + +/* 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; \ + }) + +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) + +#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 index 00000000000..88fe9ddeabd --- /dev/null +++ b/sim/bfin/dv-bfin_cec.c @@ -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 . */ + +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..027c89389bc --- /dev/null +++ b/sim/bfin/dv-bfin_cec.h @@ -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 . */ + +#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 index 00000000000..b6d575c1148 --- /dev/null +++ b/sim/bfin/dv-bfin_ctimer.c @@ -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 . */ + +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..c097588fec6 --- /dev/null +++ b/sim/bfin/dv-bfin_ctimer.h @@ -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 . */ + +#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 index 00000000000..e61348af87c --- /dev/null +++ b/sim/bfin/dv-bfin_dma.c @@ -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 . */ + +#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", "", "X_COUNT", "X_MODIFY", + "Y_COUNT", "Y_MODIFY", "CURR_DESC_PTR", "CURR_ADDR", "IRQ_STATUS", + "PERIPHERAL_MAP", "CURR_X_COUNT", "", "CURR_Y_COUNT", "", +}; +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..03d412b7e9d --- /dev/null +++ b/sim/bfin/dv-bfin_dma.h @@ -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 . */ + +#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 index 00000000000..f0f3c8cd067 --- /dev/null +++ b/sim/bfin/dv-bfin_dmac.c @@ -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 . */ + +#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 index 00000000000..dfe953575e6 --- /dev/null +++ b/sim/bfin/dv-bfin_dmac.h @@ -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 . */ + +#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 index 00000000000..504e33ba66f --- /dev/null +++ b/sim/bfin/dv-bfin_ebiu_amc.c @@ -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 . */ + +#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] ? : "") + +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) : "")); + + 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, ®)) + 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), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..e47fd1177e9 --- /dev/null +++ b/sim/bfin/dv-bfin_ebiu_amc.h @@ -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 . */ + +#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 index 00000000000..fa54c8e95fc --- /dev/null +++ b/sim/bfin/dv-bfin_ebiu_ddrc.c @@ -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 . */ + +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..ac970bf5317 --- /dev/null +++ b/sim/bfin/dv-bfin_ebiu_ddrc.h @@ -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 . */ + +#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 index 00000000000..710f2f8f9a8 --- /dev/null +++ b/sim/bfin/dv-bfin_ebiu_sdc.c @@ -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 . */ + +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..7849806d936 --- /dev/null +++ b/sim/bfin/dv-bfin_ebiu_sdc.h @@ -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 . */ + +#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 index 00000000000..bfd8dc926bc --- /dev/null +++ b/sim/bfin/dv-bfin_emac.c @@ -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 . */ + +#include "config.h" + +#include +#include +#include + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_LINUX_IF_TUN_H +#include +#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] ? : "") + +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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..2522292c764 --- /dev/null +++ b/sim/bfin/dv-bfin_emac.h @@ -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 . */ + +#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 index 00000000000..7a1d6dbc438 --- /dev/null +++ b/sim/bfin/dv-bfin_eppi.c @@ -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 . */ + +#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] ? : "") + +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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..1856800aacd --- /dev/null +++ b/sim/bfin/dv-bfin_eppi.h @@ -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 . */ + +#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 index 00000000000..3af0717286e --- /dev/null +++ b/sim/bfin/dv-bfin_evt.c @@ -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 . */ + +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..defa0826c06 --- /dev/null +++ b/sim/bfin/dv-bfin_evt.h @@ -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 . */ + +#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 index 00000000000..23c906fa95e --- /dev/null +++ b/sim/bfin/dv-bfin_gptimer.c @@ -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 . */ + +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..2c7c149e497 --- /dev/null +++ b/sim/bfin/dv-bfin_gptimer.h @@ -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 . */ + +#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 index 00000000000..76b59acccee --- /dev/null +++ b/sim/bfin/dv-bfin_jtag.c @@ -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 . */ + +#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] ? : "") + +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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..65c1d3be577 --- /dev/null +++ b/sim/bfin/dv-bfin_jtag.h @@ -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 . */ + +#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 index 00000000000..9f27636c76a --- /dev/null +++ b/sim/bfin/dv-bfin_mmu.c @@ -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 . */ + +#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] ? : "") + +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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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}, +}; + +/* 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; + } +} + +#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 index 00000000000..e03a327f839 --- /dev/null +++ b/sim/bfin/dv-bfin_mmu.h @@ -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 . */ + +#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 index 00000000000..48990ee76a3 --- /dev/null +++ b/sim/bfin/dv-bfin_nfc.c @@ -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 . */ + +#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] ? : "") + +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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..42dbec6b43f --- /dev/null +++ b/sim/bfin/dv-bfin_nfc.h @@ -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 . */ + +#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 index 00000000000..d30a4140435 --- /dev/null +++ b/sim/bfin/dv-bfin_otp.c @@ -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 . */ + +#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] ? : "") + +/* 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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..bbb49ce4211 --- /dev/null +++ b/sim/bfin/dv-bfin_otp.h @@ -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 . */ + +#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 index 00000000000..b6e110a7ee5 --- /dev/null +++ b/sim/bfin/dv-bfin_pll.c @@ -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 . */ + +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..b63104a6f3f --- /dev/null +++ b/sim/bfin/dv-bfin_pll.h @@ -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 . */ + +#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 index 00000000000..fc72b947b39 --- /dev/null +++ b/sim/bfin/dv-bfin_ppi.c @@ -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 . */ + +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..24e8fd9eb35 --- /dev/null +++ b/sim/bfin/dv-bfin_ppi.h @@ -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 . */ + +#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 index 00000000000..6d8aa3d5a4e --- /dev/null +++ b/sim/bfin/dv-bfin_rtc.c @@ -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 . */ + +#include "config.h" + +#include +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..04ffde14496 --- /dev/null +++ b/sim/bfin/dv-bfin_rtc.h @@ -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 . */ + +#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 index 00000000000..0cc2e407e1b --- /dev/null +++ b/sim/bfin/dv-bfin_sic.c @@ -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 . */ + +#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] ? : "") + +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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..e70a749c9bc --- /dev/null +++ b/sim/bfin/dv-bfin_sic.h @@ -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 . */ + +#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 index 00000000000..4c783d05855 --- /dev/null +++ b/sim/bfin/dv-bfin_spi.c @@ -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 . */ + +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..5e216bf0414 --- /dev/null +++ b/sim/bfin/dv-bfin_spi.h @@ -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 . */ + +#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 index 00000000000..a77dd646a40 --- /dev/null +++ b/sim/bfin/dv-bfin_trace.c @@ -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 . */ + +#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] ? : "") + +/* 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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..3acfddf037b --- /dev/null +++ b/sim/bfin/dv-bfin_trace.h @@ -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 . */ + +#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 index 00000000000..4e6783ded5c --- /dev/null +++ b/sim/bfin/dv-bfin_twi.c @@ -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 . */ + +#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] ? : "") + +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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..91899994959 --- /dev/null +++ b/sim/bfin/dv-bfin_twi.h @@ -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 . */ + +#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 index 00000000000..be9038d3998 --- /dev/null +++ b/sim/bfin/dv-bfin_uart.c @@ -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 . */ + +#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", "", "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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..1d144d49048 --- /dev/null +++ b/sim/bfin/dv-bfin_uart.h @@ -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 . */ + +#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 index 00000000000..dd09c5e5750 --- /dev/null +++ b/sim/bfin/dv-bfin_uart2.c @@ -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 . */ + +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..f8269a404c5 --- /dev/null +++ b/sim/bfin/dv-bfin_uart2.h @@ -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 . */ + +#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 index 00000000000..4aada471708 --- /dev/null +++ b/sim/bfin/dv-bfin_wdog.c @@ -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 . */ + +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..9be602dbd3b --- /dev/null +++ b/sim/bfin/dv-bfin_wdog.h @@ -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 . */ + +#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 index 00000000000..efa0804fe66 --- /dev/null +++ b/sim/bfin/dv-bfin_wp.c @@ -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 . */ + +#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] ? : "") + +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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..f6c0d80df57 --- /dev/null +++ b/sim/bfin/dv-bfin_wp.h @@ -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 . */ + +#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 index 00000000000..59eaecec98e --- /dev/null +++ b/sim/bfin/dv-eth_phy.c @@ -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 . */ + +#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 + +#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] ? : "") +#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, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + hw_unit_size_to_attach_size (hw_parent (me), ®.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 index 00000000000..65f37355bcd --- /dev/null +++ b/sim/bfin/gui.c @@ -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 . */ + +#include "config.h" + +#ifdef HAVE_SDL +# include +#endif +#ifdef HAVE_DLFCN_H +# include +#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 index 00000000000..3456ac903d2 --- /dev/null +++ b/sim/bfin/gui.h @@ -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 . */ + +#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 index 00000000000..41ff91ca119 --- /dev/null +++ b/sim/bfin/insn_list.def @@ -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 . */ + +/* 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 index 00000000000..1f8681df16a --- /dev/null +++ b/sim/bfin/interp.c @@ -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 . */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 00000000000..7b42ed37d88 --- /dev/null +++ b/sim/bfin/linux-fixed-code.h @@ -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 index 00000000000..c1dd358852e --- /dev/null +++ b/sim/bfin/linux-fixed-code.s @@ -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 . */ + +/* 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 index 00000000000..ca340d5136f --- /dev/null +++ b/sim/bfin/linux-targ-map.h @@ -0,0 +1,1992 @@ +#if 0 /* Auto generated: sh ./targ-linux.h + +sed -n '1,/^#endif/p' targ-linux.h +echo + +echo '#include ' | \ +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 ' | \ +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 ' | \ +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 ' | \ +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 index 00000000000..e60e8c94ccc --- /dev/null +++ b/sim/bfin/machs.c @@ -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 . */ + +#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 <REG (0); + case SIM_BFIN_LB0_REGNUM: return &LBREG (0); + case SIM_BFIN_LC1_REGNUM: return &LCREG (1); + case SIM_BFIN_LT1_REGNUM: return <REG (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 +}; + +/* 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 index 00000000000..ac16adb21f1 --- /dev/null +++ b/sim/bfin/machs.h @@ -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 . */ + +#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 index 00000000000..aa9d33764ed --- /dev/null +++ b/sim/bfin/proc_list.def @@ -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 . */ + +/* 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 index 00000000000..3a937034817 --- /dev/null +++ b/sim/bfin/sim-main.h @@ -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 . */ + +#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 index 00000000000..130707a90a8 --- /dev/null +++ b/sim/bfin/tconfig.in @@ -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 diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index b88fc325737..3a9da40c6bd 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,3 +1,8 @@ +2011-03-05 Mike Frysinger + + * gennltvals.sh: Handle bfin targets. + * nltvals.def: Regenerate. + 2011-02-25 Kevin Buettner * callback.c (fdbad): Return EBADF rather than EINVAL for bad diff --git a/sim/common/gennltvals.sh b/sim/common/gennltvals.sh index 462e57631ee..d882e20c340 100644 --- a/sim/common/gennltvals.sh +++ b/sim/common/gennltvals.sh @@ -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}" diff --git a/sim/common/nltvals.def b/sim/common/nltvals.def index c8089c09946..ab051b12909 100644 --- a/sim/common/nltvals.def +++ b/sim/common/nltvals.def @@ -180,6 +180,36 @@ { "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 */ diff --git a/sim/configure b/sim/configure index b6488e2623f..b3d8b3996d6 100755 --- a/sim/configure +++ b/sim/configure @@ -636,6 +636,7 @@ LIBS CPPFLAGS' ac_subdirs_all='arm avr +bfin cr16 cris d10v @@ -3638,6 +3639,13 @@ subdirs="$subdirs arm" subdirs="$subdirs avr" + ;; + bfin-*-*) + + sim_arch=bfin + subdirs="$subdirs bfin" + + ;; cr16*-*-*) diff --git a/sim/configure.tgt b/sim/configure.tgt index 592bc3cf629..980849249bc 100644 --- a/sim/configure.tgt +++ b/sim/configure.tgt @@ -23,6 +23,9 @@ case "${target}" in avr*-*-*) SIM_ARCH(avr) ;; + bfin-*-*) + SIM_ARCH(bfin) + ;; cr16*-*-*) SIM_ARCH(cr16) sim_testsuite=yes