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


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

Re: [PATCH v5 1/2] PRU Simulator port


* Dimitar Dimitrov <dimitar@dinux.eu> [2019-08-26 07:08:16 +0300]:

> I'd like to contribute a sim port for the TI PRU I/O processor. This
> is the fifth version of the patch series.
> 
> The GCC and binutils ports have already been merged. I've sent
> patches for newlib.
> 
> Changes since patch series v4:
>   - Rebased to latest top-of-tree.
>   - Added XCHG instruction support.
> 
> v1: https://sourceware.org/ml/gdb-patches/2016-12/msg00143.html
> v2: https://sourceware.org/ml/gdb-patches/2017-02/msg00397.html
> v3: https://sourceware.org/ml/gdb-patches/2017-02/msg00516.html
> v4: https://sourceware.org/ml/gdb-patches/2018-06/msg00484.html
> 
> sim/
> 2019-08-25  Dimitar Dimitrov <dimitar@dinux.eu>
> 
> 	* MAINTAINERS: Add myself as PRU maintainer.
> 	* configure: Add PRU.
> 	* configure.tgt: Add PRU.
> 
> sim/common/
> 2019-08-25  Dimitar Dimitrov <dimitar@dinux.eu>
> 
> 	* gennltvals.sh: Add PRU libgloss target.
> 	* nltvals.def: Regenerate from the latest libgloss sources.
> 
> sim/pru/
> 2019-08-25  Dimitar Dimitrov <dimitar@dinux.eu>
> 
> 	* Makefile.in: New file.
> 	* aclocal.m4: New file.
> 	* config.in: New file.
> 	* configure: Regenerate.
> 	* configure.ac: New file.
> 	* interp.c: New file.
> 	* pru.h: New file.
> 	* pru.isa: New file.
> 	* sim-main.h: New file.

There isn't a NEWS file for the simulator, but I just checked and it
looks like new simulators are announced in the gdb/NEWS file.  Look
for the string "* New Simulators" and you'll see a couple of targets
announced.

You should probably add an entry for this target too.

Thanks,
Andrew


> 
> Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
> ---
>  sim/MAINTAINERS          |   1 +
>  sim/common/gennltvals.sh |   4 +
>  sim/common/nltvals.def   |  31 ++
>  sim/configure            |   8 +
>  sim/configure.tgt        |   3 +
>  sim/pru/Makefile.in      |  29 ++
>  sim/pru/aclocal.m4       | 129 ++++++
>  sim/pru/config.in        | 248 ++++++++++++
>  sim/pru/configure.ac     |  12 +
>  sim/pru/interp.c         | 841 +++++++++++++++++++++++++++++++++++++++
>  sim/pru/pru.h            | 110 +++++
>  sim/pru/pru.isa          | 249 ++++++++++++
>  sim/pru/sim-main.h       |  82 ++++
>  13 files changed, 1747 insertions(+)
>  create mode 100644 sim/pru/Makefile.in
>  create mode 100644 sim/pru/aclocal.m4
>  create mode 100644 sim/pru/config.in
>  create mode 100644 sim/pru/configure.ac
>  create mode 100644 sim/pru/interp.c
>  create mode 100644 sim/pru/pru.h
>  create mode 100644 sim/pru/pru.isa
>  create mode 100644 sim/pru/sim-main.h
> 
> diff --git a/sim/MAINTAINERS b/sim/MAINTAINERS
> index 3b9b08c40d..4ca67cfd1d 100644
> --- a/sim/MAINTAINERS
> +++ b/sim/MAINTAINERS
> @@ -29,6 +29,7 @@ mips I-IV	Maciej W. Rozycki <macro@linux-mips.org>
>  moxie		Anthony Green <green@moxielogic.com>
>  msp430		Nick Clifton <nickc@redhat.com>
>  or1k		Stafford Horne <shorne@gmail.com>
> +pru		Dimitar Dimitrov <dimitar@dinux.eu>
>  sh		(global maintainers)
>  sh64		Dave Brolley <brolley@redhat.com>
>  common		Frank Ch. Eigler <fche@redhat.com>
> diff --git a/sim/common/gennltvals.sh b/sim/common/gennltvals.sh
> index 7027c35ad4..79180335b6 100755
> --- a/sim/common/gennltvals.sh
> +++ b/sim/common/gennltvals.sh
> @@ -95,3 +95,7 @@ $shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
>  dir=libgloss target=lm32
>  $shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
>  	"syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
> +
> +dir=libgloss target=pru
> +$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
> +	"syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
> diff --git a/sim/common/nltvals.def b/sim/common/nltvals.def
> index 3f82d47b6b..92ccc9aded 100644
> --- a/sim/common/nltvals.def
> +++ b/sim/common/nltvals.def
> @@ -574,3 +574,34 @@
>  /* end lm32 sys target macros */
>  #endif
>  #endif
> +#ifdef NL_TARGET_pru
> +#ifdef sys_defs
> +/* from syscall.h */
> +/* begin pru 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_reconfig", 25 },
> + { "SYS_stat", 15 },
> + { "SYS_time", 18 },
> + { "SYS_times", 20 },
> + { "SYS_unlink", 7 },
> + { "SYS_utime", 17 },
> + { "SYS_write", 5 },
> +/* end pru sys target macros */
> +#endif
> +#endif
> diff --git a/sim/configure b/sim/configure
> index ca3fd673ab..72f95cd5c7 100755
> --- a/sim/configure
> +++ b/sim/configure
> @@ -686,6 +686,7 @@ mn10300
>  moxie
>  msp430
>  or1k
> +pru
>  rl78
>  rx
>  sh64
> @@ -3837,6 +3838,13 @@ subdirs="$subdirs aarch64"
>    subdirs="$subdirs or1k"
>  
>  
> +       ;;
> +   pru*-*-*)
> +
> +  sim_arch=pru
> +  subdirs="$subdirs pru"
> +
> +
>         ;;
>     rl78-*-*)
>  
> diff --git a/sim/configure.tgt b/sim/configure.tgt
> index a6dbd1af83..8a8e03d96f 100644
> --- a/sim/configure.tgt
> +++ b/sim/configure.tgt
> @@ -79,6 +79,9 @@ case "${target}" in
>     or1k-*-* | or1knd-*-*)
>         SIM_ARCH(or1k)
>         ;;
> +   pru*-*-*)
> +       SIM_ARCH(pru)
> +       ;;
>     rl78-*-*)
>         SIM_ARCH(rl78)
>         ;;
> diff --git a/sim/pru/Makefile.in b/sim/pru/Makefile.in
> new file mode 100644
> index 0000000000..f32b489870
> --- /dev/null
> +++ b/sim/pru/Makefile.in
> @@ -0,0 +1,29 @@
> +#    Makefile template for Configure for the PRU sim library.
> +#    Copyright (C) 2014-2019 Free Software Foundation, Inc.
> +#    Written by Dimitar Dimitrov <dimitar@dinux.eu>
> +#
> +#    Based on the MCore sim library
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +## COMMON_PRE_CONFIG_FRAG
> +
> +SIM_OBJS = \
> +	$(SIM_NEW_COMMON_OBJS) \
> +	interp.o \
> +	sim-resume.o
> +
> +NL_TARGET = -DNL_TARGET_pru
> +
> +## COMMON_POST_CONFIG_FRAG
> diff --git a/sim/pru/aclocal.m4 b/sim/pru/aclocal.m4
> new file mode 100644
> index 0000000000..517bc73b03
> --- /dev/null
> +++ b/sim/pru/aclocal.m4
> @@ -0,0 +1,129 @@
> +# 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.
> +
> +# AM_CONDITIONAL                                            -*- Autoconf -*-
> +
> +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
> +# 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.
> +
> +# serial 9
> +
> +# AM_CONDITIONAL(NAME, SHELL-CONDITION)
> +# -------------------------------------
> +# Define a conditional.
> +AC_DEFUN([AM_CONDITIONAL],
> +[AC_PREREQ(2.52)dnl
> + ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
> +	[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
> +AC_SUBST([$1_TRUE])dnl
> +AC_SUBST([$1_FALSE])dnl
> +_AM_SUBST_NOTMAKE([$1_TRUE])dnl
> +_AM_SUBST_NOTMAKE([$1_FALSE])dnl
> +m4_define([_AM_COND_VALUE_$1], [$2])dnl
> +if $2; then
> +  $1_TRUE=
> +  $1_FALSE='#'
> +else
> +  $1_TRUE='#'
> +  $1_FALSE=
> +fi
> +AC_CONFIG_COMMANDS_PRE(
> +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
> +  AC_MSG_ERROR([[conditional "$1" was never defined.
> +Usually this means the macro was only invoked conditionally.]])
> +fi])])
> +
> +# Copyright (C) 2003, 2005  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.
> +
> +# serial 2
> +
> +# Check whether the underlying file-system supports filenames
> +# with a leading dot.  For instance MS-DOS doesn't.
> +AC_DEFUN([AM_SET_LEADING_DOT],
> +[rm -rf .tst 2>/dev/null
> +mkdir .tst 2>/dev/null
> +if test -d .tst; then
> +  am__leading_dot=.
> +else
> +  am__leading_dot=_
> +fi
> +rmdir .tst 2>/dev/null
> +AC_SUBST([am__leading_dot])])
> +
> +# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
> +# From Jim Meyering
> +
> +# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008
> +# 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.
> +
> +# serial 5
> +
> +# AM_MAINTAINER_MODE([DEFAULT-MODE])
> +# ----------------------------------
> +# Control maintainer-specific portions of Makefiles.
> +# Default is to disable them, unless `enable' is passed literally.
> +# For symmetry, `disable' may be passed as well.  Anyway, the user
> +# can override the default with the --enable/--disable switch.
> +AC_DEFUN([AM_MAINTAINER_MODE],
> +[m4_case(m4_default([$1], [disable]),
> +       [enable], [m4_define([am_maintainer_other], [disable])],
> +       [disable], [m4_define([am_maintainer_other], [enable])],
> +       [m4_define([am_maintainer_other], [enable])
> +        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
> +AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles])
> +  dnl maintainer-mode's default is 'disable' unless 'enable' is passed
> +  AC_ARG_ENABLE([maintainer-mode],
> +[  --][am_maintainer_other][-maintainer-mode  am_maintainer_other make rules and dependencies not useful
> +			  (and sometimes confusing) to the casual installer],
> +      [USE_MAINTAINER_MODE=$enableval],
> +      [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
> +  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
> +  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
> +  MAINT=$MAINTAINER_MODE_TRUE
> +  AC_SUBST([MAINT])dnl
> +]
> +)
> +
> +AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
> +
> +# Copyright (C) 2006, 2008  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.
> +
> +# serial 2
> +
> +# _AM_SUBST_NOTMAKE(VARIABLE)
> +# ---------------------------
> +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
> +# This macro is traced by Automake.
> +AC_DEFUN([_AM_SUBST_NOTMAKE])
> +
> +# AM_SUBST_NOTMAKE(VARIABLE)
> +# ---------------------------
> +# Public sister of _AM_SUBST_NOTMAKE.
> +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
> +
> diff --git a/sim/pru/config.in b/sim/pru/config.in
> new file mode 100644
> index 0000000000..aa3e45ca4a
> --- /dev/null
> +++ b/sim/pru/config.in
> @@ -0,0 +1,248 @@
> +/* config.in.  Generated from configure.ac by autoheader.  */
> +
> +/* Define if building universal (internal helper macro) */
> +#undef AC_APPLE_UNIVERSAL_BUILD
> +
> +/* Sim debug setting */
> +#undef DEBUG
> +
> +/* Define to 1 if translation of program messages to the user's native
> +   language is requested. */
> +#undef ENABLE_NLS
> +
> +/* Define to 1 if you have the <dlfcn.h> header file. */
> +#undef HAVE_DLFCN_H
> +
> +/* Define to 1 if you have the <errno.h> header file. */
> +#undef HAVE_ERRNO_H
> +
> +/* Define to 1 if you have the <fcntl.h> header file. */
> +#undef HAVE_FCNTL_H
> +
> +/* Define to 1 if you have the <fpu_control.h> header file. */
> +#undef HAVE_FPU_CONTROL_H
> +
> +/* Define to 1 if you have the `ftruncate' function. */
> +#undef HAVE_FTRUNCATE
> +
> +/* Define to 1 if you have the `getrusage' function. */
> +#undef HAVE_GETRUSAGE
> +
> +/* Define to 1 if you have the <inttypes.h> header file. */
> +#undef HAVE_INTTYPES_H
> +
> +/* Define to 1 if you have the `nsl' library (-lnsl). */
> +#undef HAVE_LIBNSL
> +
> +/* Define to 1 if you have the `socket' library (-lsocket). */
> +#undef HAVE_LIBSOCKET
> +
> +/* Define to 1 if you have the `lstat' function. */
> +#undef HAVE_LSTAT
> +
> +/* Define to 1 if you have the <memory.h> header file. */
> +#undef HAVE_MEMORY_H
> +
> +/* Define to 1 if you have the `mmap' function. */
> +#undef HAVE_MMAP
> +
> +/* Define to 1 if you have the `munmap' function. */
> +#undef HAVE_MUNMAP
> +
> +/* Define to 1 if you have the `posix_fallocate' function. */
> +#undef HAVE_POSIX_FALLOCATE
> +
> +/* Define to 1 if you have the `sigaction' function. */
> +#undef HAVE_SIGACTION
> +
> +/* Define to 1 if the system has the type `socklen_t'. */
> +#undef HAVE_SOCKLEN_T
> +
> +/* Define to 1 if you have the <stdint.h> header file. */
> +#undef HAVE_STDINT_H
> +
> +/* Define to 1 if you have the <stdlib.h> header file. */
> +#undef HAVE_STDLIB_H
> +
> +/* Define to 1 if you have the <strings.h> header file. */
> +#undef HAVE_STRINGS_H
> +
> +/* Define to 1 if you have the <string.h> header file. */
> +#undef HAVE_STRING_H
> +
> +/* Define to 1 if `struct stat' is a member of `st_atime'. */
> +#undef HAVE_STRUCT_STAT_ST_ATIME
> +
> +/* Define to 1 if `struct stat' is a member of `st_blksize'. */
> +#undef HAVE_STRUCT_STAT_ST_BLKSIZE
> +
> +/* Define to 1 if `struct stat' is a member of `st_blocks'. */
> +#undef HAVE_STRUCT_STAT_ST_BLOCKS
> +
> +/* Define to 1 if `struct stat' is a member of `st_ctime'. */
> +#undef HAVE_STRUCT_STAT_ST_CTIME
> +
> +/* Define to 1 if `struct stat' is a member of `st_dev'. */
> +#undef HAVE_STRUCT_STAT_ST_DEV
> +
> +/* Define to 1 if `struct stat' is a member of `st_gid'. */
> +#undef HAVE_STRUCT_STAT_ST_GID
> +
> +/* Define to 1 if `struct stat' is a member of `st_ino'. */
> +#undef HAVE_STRUCT_STAT_ST_INO
> +
> +/* Define to 1 if `struct stat' is a member of `st_mode'. */
> +#undef HAVE_STRUCT_STAT_ST_MODE
> +
> +/* Define to 1 if `struct stat' is a member of `st_mtime'. */
> +#undef HAVE_STRUCT_STAT_ST_MTIME
> +
> +/* Define to 1 if `struct stat' is a member of `st_nlink'. */
> +#undef HAVE_STRUCT_STAT_ST_NLINK
> +
> +/* Define to 1 if `struct stat' is a member of `st_rdev'. */
> +#undef HAVE_STRUCT_STAT_ST_RDEV
> +
> +/* Define to 1 if `struct stat' is a member of `st_size'. */
> +#undef HAVE_STRUCT_STAT_ST_SIZE
> +
> +/* Define to 1 if `struct stat' is a member of `st_uid'. */
> +#undef HAVE_STRUCT_STAT_ST_UID
> +
> +/* Define to 1 if you have the <sys/mman.h> header file. */
> +#undef HAVE_SYS_MMAN_H
> +
> +/* Define to 1 if you have the <sys/resource.h> header file. */
> +#undef HAVE_SYS_RESOURCE_H
> +
> +/* Define to 1 if you have the <sys/stat.h> header file. */
> +#undef HAVE_SYS_STAT_H
> +
> +/* Define to 1 if you have the <sys/times.h> header file. */
> +#undef HAVE_SYS_TIMES_H
> +
> +/* Define to 1 if you have the <sys/time.h> header file. */
> +#undef HAVE_SYS_TIME_H
> +
> +/* Define to 1 if you have the <sys/types.h> header file. */
> +#undef HAVE_SYS_TYPES_H
> +
> +/* Define to 1 if you have the `time' function. */
> +#undef HAVE_TIME
> +
> +/* Define to 1 if you have the <time.h> header file. */
> +#undef HAVE_TIME_H
> +
> +/* Define to 1 if you have the `truncate' function. */
> +#undef HAVE_TRUNCATE
> +
> +/* Define to 1 if you have the <unistd.h> header file. */
> +#undef HAVE_UNISTD_H
> +
> +/* Define to 1 if you have the <windows.h> header file. */
> +#undef HAVE_WINDOWS_H
> +
> +/* Define to 1 if you have the `__setfpucw' function. */
> +#undef HAVE___SETFPUCW
> +
> +/* Define to the sub-directory in which libtool stores uninstalled libraries.
> +   */
> +#undef LT_OBJDIR
> +
> +/* Name of this package. */
> +#undef PACKAGE
> +
> +/* 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
> +
> +/* Sim profile settings */
> +#undef PROFILE
> +
> +/* 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
> +
> +/* Enable extensions on AIX 3, Interix.  */
> +#ifndef _ALL_SOURCE
> +# undef _ALL_SOURCE
> +#endif
> +/* Enable GNU extensions on systems that have them.  */
> +#ifndef _GNU_SOURCE
> +# undef _GNU_SOURCE
> +#endif
> +/* Enable threading extensions on Solaris.  */
> +#ifndef _POSIX_PTHREAD_SEMANTICS
> +# undef _POSIX_PTHREAD_SEMANTICS
> +#endif
> +/* Enable extensions on HP NonStop.  */
> +#ifndef _TANDEM_SOURCE
> +# undef _TANDEM_SOURCE
> +#endif
> +/* Enable general extensions on Solaris.  */
> +#ifndef __EXTENSIONS__
> +# undef __EXTENSIONS__
> +#endif
> +
> +
> +/* Sim assert settings */
> +#undef WITH_ASSERT
> +
> +/* Sim debug setting */
> +#undef WITH_DEBUG
> +
> +/* Sim default environment */
> +#undef WITH_ENVIRONMENT
> +
> +/* Sim profile settings */
> +#undef WITH_PROFILE
> +
> +/* How to route I/O */
> +#undef WITH_STDIO
> +
> +/* Sim trace settings */
> +#undef WITH_TRACE
> +
> +/* 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
> +
> +/* Define to 1 if on MINIX. */
> +#undef _MINIX
> +
> +/* Define to 2 if the system does not provide POSIX.1 features except with
> +   this defined. */
> +#undef _POSIX_1_SOURCE
> +
> +/* Define to 1 if you need to in order for `stat' and other things to work. */
> +#undef _POSIX_SOURCE
> diff --git a/sim/pru/configure.ac b/sim/pru/configure.ac
> new file mode 100644
> index 0000000000..54ac06f48e
> --- /dev/null
> +++ b/sim/pru/configure.ac
> @@ -0,0 +1,12 @@
> +dnl Process this file with autoconf to produce a configure script.
> +AC_PREREQ(2.64)dnl
> +AC_INIT(Makefile.in)
> +sinclude(../common/acinclude.m4)
> +
> +SIM_AC_COMMON
> +
> +SIM_AC_OPTION_ENDIAN(LITTLE)
> +SIM_AC_OPTION_ALIGNMENT(STRICT_ALIGNMENT,STRICT_ALIGNMENT)
> +SIM_AC_OPTION_WARNINGS
> +
> +SIM_AC_OUTPUT
> diff --git a/sim/pru/interp.c b/sim/pru/interp.c
> new file mode 100644
> index 0000000000..a794941532
> --- /dev/null
> +++ b/sim/pru/interp.c
> @@ -0,0 +1,841 @@
> +/* Simulator for the Texas Instruments PRU processor
> +   Copyright 2014-2019 Free Software Foundation, Inc.
> +   Inspired by the Microblaze simulator
> +   Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
> +
> +   This file is part of the simulators.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
> +
> +#include "config.h"
> +#include <stdbool.h>
> +#include <stdint.h>
> +#include <stddef.h>
> +#include "bfd.h"
> +#include "gdb/callback.h"
> +#include "libiberty.h"
> +#include "gdb/remote-sim.h"
> +#include "sim-main.h"
> +#include "sim-assert.h"
> +#include "sim-options.h"
> +#include "sim-syscall.h"
> +#include "pru.h"
> +
> +/* DMEM zero address is perfectly valid.  But if CRT leaves the first word
> +   alone, we can use it as a trap to catch NULL pointer access.  */
> +static bfd_boolean abort_on_dmem_zero_access;
> +
> +enum {
> +  OPTION_ERROR_NULL_DEREF = OPTION_START,
> +};
> +
> +/* Extract (from PRU endianess) and return an integer in HOST's endianness.  */
> +static uint32_t
> +pru_extract_unsigned_integer (uint8_t *addr, size_t len)
> +{
> +  uint32_t retval;
> +  uint8_t *p;
> +  uint8_t *startaddr = addr;
> +  uint8_t *endaddr = startaddr + len;
> +
> +  /* Start at the most significant end of the integer, and work towards
> +     the least significant.  */
> +  retval = 0;
> +
> +  for (p = endaddr; p > startaddr;)
> +    retval = (retval << 8) | * -- p;
> +  return retval;
> +}
> +
> +/* Store "val" (which is in HOST's endianess) into "addr"
> +   (using PRU's endianness).  */
> +static void
> +pru_store_unsigned_integer (uint8_t *addr, size_t len, uint32_t val)
> +{
> +  uint8_t *p;
> +  uint8_t *startaddr = (uint8_t *)addr;
> +  uint8_t *endaddr = startaddr + len;
> +
> +  for (p = startaddr; p < endaddr;)
> +    {
> +      *p++ = val & 0xff;
> +      val >>= 8;
> +    }
> +}
> +
> +/* Extract a field value from CPU register using the given REGSEL selector.
> +
> +   NOTE: Byte number maps directly to first values of RSEL, so we can
> +   safely use "regsel" as a register byte number (0..3).  */
> +static inline uint32_t
> +extract_regval (uint32_t val, uint32_t regsel)
> +{
> +  ASSERT (RSEL_7_0 == 0);
> +  ASSERT (RSEL_15_8 == 1);
> +  ASSERT (RSEL_23_16 == 2);
> +  ASSERT (RSEL_31_24 == 3);
> +
> +  switch (regsel)
> +    {
> +    case RSEL_7_0:    return (val >> 0) & 0xff;
> +    case RSEL_15_8:   return (val >> 8) & 0xff;
> +    case RSEL_23_16:  return (val >> 16) & 0xff;
> +    case RSEL_31_24:  return (val >> 24) & 0xff;
> +    case RSEL_15_0:   return (val >> 0) & 0xffff;
> +    case RSEL_23_8:   return (val >> 8) & 0xffff;
> +    case RSEL_31_16:  return (val >> 16) & 0xffff;
> +    case RSEL_31_0:   return val;
> +    default:	      sim_io_error (NULL, "invalid regsel");
> +    }
> +}
> +
> +/* Write a value into CPU subregister pointed by reg and regsel.  */
> +static inline void
> +write_regval (uint32_t val, uint32_t *reg, uint32_t regsel)
> +{
> +  uint32_t mask, sh;
> +
> +  switch (regsel)
> +    {
> +    case RSEL_7_0:    mask = (0xffu << 0); sh = 0; break;
> +    case RSEL_15_8:   mask = (0xffu << 8); sh = 8; break;
> +    case RSEL_23_16:  mask = (0xffu << 16); sh = 16; break;
> +    case RSEL_31_24:  mask = (0xffu << 24); sh = 24; break;
> +    case RSEL_15_0:   mask = (0xffffu << 0); sh = 0; break;
> +    case RSEL_23_8:   mask = (0xffffu << 8); sh = 8; break;
> +    case RSEL_31_16:  mask = (0xffffu << 16); sh = 16; break;
> +    case RSEL_31_0:   mask = 0xffffffffu; sh = 0; break;
> +    default:	      sim_io_error (NULL, "invalid regsel");
> +    }
> +
> +  *reg = (*reg & ~mask) | ((val << sh) & mask);
> +}
> +
> +/* Convert the given IMEM word address to a  regular byte address used by the
> +   GNU ELF container.  */
> +static uint32_t
> +imem_wordaddr_to_byteaddr (SIM_CPU *cpu, uint16_t wa)
> +{
> +  return (((uint32_t) wa << 2) & IMEM_ADDR_MASK) | PC_ADDR_SPACE_MARKER;
> +}
> +
> +/* Convert the given ELF text byte address to IMEM word address.  */
> +static uint16_t
> +imem_byteaddr_to_wordaddr (SIM_CPU *cpu, uint32_t ba)
> +{
> +  return (ba >> 2) & 0xffff;
> +}
> +
> +
> +/* Store "nbytes" into DMEM "addr" from CPU register file, starting with
> +   register "regn", and byte "regb" within it.  */
> +static inline void
> +pru_reg2dmem (SIM_CPU *cpu, uint32_t addr, unsigned int nbytes,
> +	      int regn, int regb)
> +{
> +  /* GDB assumes unconditional access to all memories, so enable additional
> +     checks only in standalone mode.  */
> +  bool standalone = (STATE_OPEN_KIND (CPU_STATE (cpu)) == SIM_OPEN_STANDALONE);
> +
> +  if (abort_on_dmem_zero_access && addr < 4)
> +    {
> +      sim_core_signal (CPU_STATE (cpu), cpu, PC_byteaddr, write_map,
> +		       nbytes, addr, write_transfer,
> +		       sim_core_unmapped_signal);
> +    }
> +  else if (standalone && ((addr >= PC_ADDR_SPACE_MARKER)
> +			  || (addr + nbytes > PC_ADDR_SPACE_MARKER)))
> +    {
> +      sim_core_signal (CPU_STATE (cpu), cpu, PC_byteaddr, write_map,
> +		       nbytes, addr, write_transfer,
> +		       sim_core_unmapped_signal);
> +    }
> +  else if ((regn * 4 + regb + nbytes) > (32 * 4))
> +    {
> +      sim_io_eprintf (CPU_STATE (cpu),
> +		      "SBBO/SBCO with invalid store data length\n");
> +      RAISE_SIGILL (CPU_STATE (cpu));
> +    }
> +  else
> +    {
> +      TRACE_MEMORY (cpu, "write of %d bytes to %08x", nbytes, addr);
> +      while (nbytes--)
> +	{
> +	  sim_core_write_1 (cpu,
> +			    PC_byteaddr,
> +			    write_map,
> +			    addr++,
> +			    extract_regval (CPU.regs[regn], regb));
> +
> +	  if (++regb >= 4)
> +	    {
> +	      regb = 0;
> +	      regn++;
> +	    }
> +	}
> +    }
> +}
> +
> +/* Load "nbytes" from DMEM "addr" into CPU register file, starting with
> +   register "regn", and byte "regb" within it.  */
> +static inline void
> +pru_dmem2reg (SIM_CPU *cpu, uint32_t addr, unsigned int nbytes,
> +	      int regn, int regb)
> +{
> +  /* GDB assumes unconditional access to all memories, so enable additional
> +     checks only in standalone mode.  */
> +  bool standalone = (STATE_OPEN_KIND (CPU_STATE (cpu)) == SIM_OPEN_STANDALONE);
> +
> +  if (abort_on_dmem_zero_access && addr < 4)
> +    {
> +      sim_core_signal (CPU_STATE (cpu), cpu, PC_byteaddr, read_map,
> +		       nbytes, addr, read_transfer,
> +		       sim_core_unmapped_signal);
> +    }
> +  else if (standalone && ((addr >= PC_ADDR_SPACE_MARKER)
> +			  || (addr + nbytes > PC_ADDR_SPACE_MARKER)))
> +    {
> +      /* This check is necessary because our IMEM "address space"
> +	 is not really accessible, yet we have mapped it as a generic
> +	 memory space.  */
> +      sim_core_signal (CPU_STATE (cpu), cpu, PC_byteaddr, read_map,
> +		       nbytes, addr, read_transfer,
> +		       sim_core_unmapped_signal);
> +    }
> +  else if ((regn * 4 + regb + nbytes) > (32 * 4))
> +    {
> +      sim_io_eprintf (CPU_STATE (cpu),
> +		      "LBBO/LBCO with invalid load data length\n");
> +      RAISE_SIGILL (CPU_STATE (cpu));
> +    }
> +  else
> +    {
> +      unsigned int b;
> +      TRACE_MEMORY (cpu, "read of %d bytes from %08x", nbytes, addr);
> +      while (nbytes--)
> +	{
> +	  b = sim_core_read_1 (cpu, PC_byteaddr, read_map, addr++);
> +
> +	  /* Reuse the fact the Register Byte Number maps directly to RSEL.  */
> +	  ASSERT (RSEL_7_0 == 0);
> +	  write_regval (b, &CPU.regs[regn], regb);
> +
> +	  if (++regb >= 4)
> +	    {
> +	      regb = 0;
> +	      regn++;
> +	    }
> +	}
> +    }
> +}
> +
> +/* Set reset values of general-purpose registers.  */
> +static void
> +set_initial_gprs (SIM_CPU *cpu)
> +{
> +  int i;
> +
> +  /* Set up machine just out of reset.  */
> +  CPU_PC_SET (cpu, 0);
> +  PC_ADDR_SPACE_MARKER = IMEM_ADDR_DEFAULT; /* from default linker script? */
> +
> +  /* Clean out the GPRs.  */
> +  for (i = 0; i < ARRAY_SIZE (CPU.regs); i++)
> +    CPU.regs[i] = 0;
> +  for (i = 0; i < ARRAY_SIZE (CPU.macregs); i++)
> +    CPU.macregs[i] = 0;
> +
> +  CPU.loop.looptop = CPU.loop.loopend = 0;
> +  CPU.loop.loop_in_progress = 0;
> +  CPU.loop.loop_counter = 0;
> +
> +  CPU.carry = 0;
> +  CPU.insts = 0;
> +  CPU.cycles = 0;
> +
> +  /* AM335x should provide sane defaults.  */
> +  CPU.ctable[0] = 0x00020000;
> +  CPU.ctable[1] = 0x48040000;
> +  CPU.ctable[2] = 0x4802a000;
> +  CPU.ctable[3] = 0x00030000;
> +  CPU.ctable[4] = 0x00026000;
> +  CPU.ctable[5] = 0x48060000;
> +  CPU.ctable[6] = 0x48030000;
> +  CPU.ctable[7] = 0x00028000;
> +  CPU.ctable[8] = 0x46000000;
> +  CPU.ctable[9] = 0x4a100000;
> +  CPU.ctable[10] = 0x48318000;
> +  CPU.ctable[11] = 0x48022000;
> +  CPU.ctable[12] = 0x48024000;
> +  CPU.ctable[13] = 0x48310000;
> +  CPU.ctable[14] = 0x481cc000;
> +  CPU.ctable[15] = 0x481d0000;
> +  CPU.ctable[16] = 0x481a0000;
> +  CPU.ctable[17] = 0x4819c000;
> +  CPU.ctable[18] = 0x48300000;
> +  CPU.ctable[19] = 0x48302000;
> +  CPU.ctable[20] = 0x48304000;
> +  CPU.ctable[21] = 0x00032400;
> +  CPU.ctable[22] = 0x480c8000;
> +  CPU.ctable[23] = 0x480ca000;
> +  CPU.ctable[24] = 0x00000000;
> +  CPU.ctable[25] = 0x00002000;
> +  CPU.ctable[26] = 0x0002e000;
> +  CPU.ctable[27] = 0x00032000;
> +  CPU.ctable[28] = 0x00000000;
> +  CPU.ctable[29] = 0x49000000;
> +  CPU.ctable[30] = 0x40000000;
> +  CPU.ctable[31] = 0x80000000;
> +}
> +
> +/* Map regsel selector to subregister field width.  */
> +static inline unsigned int
> +regsel_width (uint32_t regsel)
> +{
> +  switch (regsel)
> +    {
> +    case RSEL_7_0:    return 8;
> +    case RSEL_15_8:   return 8;
> +    case RSEL_23_16:  return 8;
> +    case RSEL_31_24:  return 8;
> +    case RSEL_15_0:   return 16;
> +    case RSEL_23_8:   return 16;
> +    case RSEL_31_16:  return 16;
> +    case RSEL_31_0:   return 32;
> +    default:	      sim_io_error (NULL, "invalid regsel");
> +    }
> +}
> +
> +/* Handle XIN instruction addressing the MAC peripheral.  */
> +static void
> +pru_sim_xin_mac (SIM_DESC sd, SIM_CPU *cpu, unsigned int rd_regn,
> +		 unsigned int rdb, unsigned int length)
> +{
> +  if (rd_regn < 25 || (rd_regn * 4 + rdb + length) > (27 + 1) * 4)
> +    sim_io_error (sd, "XIN MAC: invalid transfer regn=%u.%u, length=%u\n",
> +		  rd_regn, rdb, length);
> +
> +  /* Copy from MAC to PRU regs.  Ranges have been validated above.  */
> +  while (length--)
> +    {
> +      write_regval (CPU.macregs[rd_regn - 25] >> (rdb * 8),
> +		    &CPU.regs[rd_regn],
> +		    rdb);
> +      if (++rdb == 4)
> +	{
> +	  rdb = 0;
> +	  rd_regn++;
> +	}
> +    }
> +}
> +
> +/* Handle XIN instruction.  */
> +static void
> +pru_sim_xin (SIM_DESC sd, SIM_CPU *cpu, unsigned int wba,
> +	     unsigned int rd_regn, unsigned int rdb, unsigned int length)
> +{
> +  if (wba == 0)
> +    {
> +      pru_sim_xin_mac (sd, cpu, rd_regn, rdb, length);
> +    }
> +  else if (wba == XFRID_SCRATCH_BANK_0 || wba == XFRID_SCRATCH_BANK_1
> +	   || wba == XFRID_SCRATCH_BANK_2 || wba == XFRID_SCRATCH_BANK_PEER)
> +    {
> +      while (length--)
> +	{
> +	  unsigned int val;
> +
> +	  val = extract_regval (CPU.scratchpads[wba][rd_regn], rdb);
> +	  write_regval (val, &CPU.regs[rd_regn], rdb);
> +	  if (++rdb == 4)
> +	    {
> +	      rdb = 0;
> +	      rd_regn++;
> +	    }
> +	}
> +    }
> +  else if (wba == 254 || wba == 255)
> +    {
> +      /* FILL/ZERO pseudos implemented via XIN.  */
> +      unsigned int fillbyte = (wba == 254) ? 0xff : 0x00;
> +      while (length--)
> +	{
> +	  write_regval (fillbyte, &CPU.regs[rd_regn], rdb);
> +	  if (++rdb == 4)
> +	    {
> +	      rdb = 0;
> +	      rd_regn++;
> +	    }
> +	}
> +    }
> +  else
> +    {
> +      sim_io_error (sd, "XIN: XFR device %d not supported.\n", wba);
> +    }
> +}
> +
> +/* Handle XOUT instruction addressing the MAC peripheral.  */
> +static void
> +pru_sim_xout_mac (SIM_DESC sd, SIM_CPU *cpu, unsigned int rd_regn,
> +		  unsigned int rdb, unsigned int length)
> +{
> +  const int modereg_accessed = (rd_regn == 25);
> +
> +  /* Multiple Accumulate.  */
> +  if (rd_regn < 25 || (rd_regn * 4 + rdb + length) > (27 + 1) * 4)
> +    sim_io_error (sd, "XOUT MAC: invalid transfer regn=%u.%u, length=%u\n",
> +		  rd_regn, rdb, length);
> +
> +  /* Copy from PRU to MAC regs.  Ranges have been validated above.  */
> +  while (length--)
> +    {
> +      write_regval (CPU.regs[rd_regn] >> (rdb * 8),
> +		    &CPU.macregs[rd_regn - 25],
> +		    rdb);
> +      if (++rdb == 4)
> +	{
> +	  rdb = 0;
> +	  rd_regn++;
> +	}
> +    }
> +
> +  if (modereg_accessed
> +      && (CPU.macregs[PRU_MACREG_MODE] & MAC_R25_MAC_MODE_MASK))
> +    {
> +      /* MUL/MAC operands are sampled every XOUT in multiply and
> +	 accumulate mode.  */
> +      uint64_t prod, oldsum, sum;
> +      CPU.macregs[PRU_MACREG_OP_0] = CPU.regs[28];
> +      CPU.macregs[PRU_MACREG_OP_1] = CPU.regs[29];
> +
> +      prod = CPU.macregs[PRU_MACREG_OP_0];
> +      prod *= (uint64_t)CPU.macregs[PRU_MACREG_OP_1];
> +
> +      oldsum = CPU.macregs[PRU_MACREG_ACC_L];
> +      oldsum += (uint64_t)CPU.macregs[PRU_MACREG_ACC_H] << 32;
> +      sum = oldsum + prod;
> +
> +      CPU.macregs[PRU_MACREG_PROD_L] = sum & 0xfffffffful;
> +      CPU.macregs[PRU_MACREG_PROD_H] = sum >> 32;
> +      CPU.macregs[PRU_MACREG_ACC_L] = CPU.macregs[PRU_MACREG_PROD_L];
> +      CPU.macregs[PRU_MACREG_ACC_H] = CPU.macregs[PRU_MACREG_PROD_H];
> +
> +      if (oldsum > sum)
> +	CPU.macregs[PRU_MACREG_MODE] |= MAC_R25_ACC_CARRY_MASK;
> +    }
> +  if (modereg_accessed
> +      && (CPU.macregs[PRU_MACREG_MODE] & MAC_R25_ACC_CARRY_MASK))
> +    {
> +      /* store 1 to clear.  */
> +      CPU.macregs[PRU_MACREG_MODE] &= ~MAC_R25_ACC_CARRY_MASK;
> +      CPU.macregs[PRU_MACREG_ACC_L] = 0;
> +      CPU.macregs[PRU_MACREG_ACC_H] = 0;
> +    }
> +
> +}
> +
> +/* Handle XOUT instruction.  */
> +static void
> +pru_sim_xout (SIM_DESC sd, SIM_CPU *cpu, unsigned int wba,
> +	      unsigned int rd_regn, unsigned int rdb, unsigned int length)
> +{
> +  if (wba == 0)
> +    {
> +      pru_sim_xout_mac (sd, cpu, rd_regn, rdb, length);
> +    }
> +  else if (wba == XFRID_SCRATCH_BANK_0 || wba == XFRID_SCRATCH_BANK_1
> +	   || wba == XFRID_SCRATCH_BANK_2 || wba == XFRID_SCRATCH_BANK_PEER)
> +    {
> +      while (length--)
> +	{
> +	  unsigned int val;
> +
> +	  val = extract_regval (CPU.regs[rd_regn], rdb);
> +	  write_regval (val, &CPU.scratchpads[wba][rd_regn], rdb);
> +	  if (++rdb == 4)
> +	    {
> +	      rdb = 0;
> +	      rd_regn++;
> +	    }
> +	}
> +    }
> +  else
> +    sim_io_error (sd, "XOUT: XFR device %d not supported.\n", wba);
> +}
> +
> +/* Handle XCHG instruction.  */
> +static void
> +pru_sim_xchg (SIM_DESC sd, SIM_CPU *cpu, unsigned int wba,
> +	      unsigned int rd_regn, unsigned int rdb, unsigned int length)
> +{
> +  if (wba == XFRID_SCRATCH_BANK_0 || wba == XFRID_SCRATCH_BANK_1
> +	   || wba == XFRID_SCRATCH_BANK_2 || wba == XFRID_SCRATCH_BANK_PEER)
> +    {
> +      while (length--)
> +	{
> +	  unsigned int valr, vals;
> +
> +	  valr = extract_regval (CPU.regs[rd_regn], rdb);
> +	  vals = extract_regval (CPU.scratchpads[wba][rd_regn], rdb);
> +	  write_regval (valr, &CPU.scratchpads[wba][rd_regn], rdb);
> +	  write_regval (vals, &CPU.regs[rd_regn], rdb);
> +	  if (++rdb == 4)
> +	    {
> +	      rdb = 0;
> +	      rd_regn++;
> +	    }
> +	}
> +    }
> +  else
> +    sim_io_error (sd, "XOUT: XFR device %d not supported.\n", wba);
> +}
> +
> +/* Handle syscall simulation.  Its ABI is specific to the GNU simulator.  */
> +static void
> +pru_sim_syscall (SIM_DESC sd, SIM_CPU *cpu)
> +{
> +  /* If someday TI confirms that the "reserved" HALT opcode fields
> +     can be used for extra arguments, then maybe we can embed
> +     the syscall number there.  Until then, let's use R1.  */
> +  const uint32_t syscall_num = CPU.regs[1];
> +  long ret;
> +
> +  ret = sim_syscall (cpu, syscall_num,
> +		     CPU.regs[14], CPU.regs[15],
> +		     CPU.regs[16], CPU.regs[17]);
> +  CPU.regs[14] = ret;
> +}
> +
> +/* Simulate one instruction.  */
> +static void
> +sim_step_once (SIM_DESC sd)
> +{
> +  SIM_CPU *cpu = STATE_CPU (sd, 0);
> +  const struct pru_opcode *op;
> +  uint32_t inst;
> +  uint32_t _RDVAL, OP2;	/* intermediate values.  */
> +  int rd_is_modified = 0;	/* RD modified and must be stored back.  */
> +
> +  /* Fetch the initial instruction that we'll decode.  */
> +  inst = sim_core_read_4 (cpu, PC_byteaddr, exec_map, PC_byteaddr);
> +  TRACE_MEMORY (cpu, "read of insn 0x%08x from %08x", inst, PC_byteaddr);
> +
> +  op = pru_find_opcode (inst);
> +
> +  if (!op)
> +    {
> +      sim_io_eprintf (sd, "Unknown instruction 0x%04x\n", inst);
> +      RAISE_SIGILL (sd);
> +    }
> +  else
> +    {
> +      TRACE_DISASM (cpu, PC_byteaddr);
> +
> +      /* In multiply-only mode, R28/R29 operands are sampled on every clock
> +	 cycle.  */
> +      if ((CPU.macregs[PRU_MACREG_MODE] & MAC_R25_MAC_MODE_MASK) == 0)
> +	{
> +	  CPU.macregs[PRU_MACREG_OP_0] = CPU.regs[28];
> +	  CPU.macregs[PRU_MACREG_OP_1] = CPU.regs[29];
> +	}
> +
> +      switch (op->type)
> +	{
> +/* Helper macro to improve clarity of pru.isa.  The empty while is a
> +   guard against using RD as a left-hand side value.  */
> +#define RD  do { } while (0); rd_is_modified = 1; _RDVAL
> +#define INSTRUCTION(NAME, ACTION)		\
> +	case prui_ ## NAME:			\
> +		ACTION;				\
> +	  break;
> +#include "pru.isa"
> +#undef INSTRUCTION
> +#undef RD
> +
> +	default:
> +	  RAISE_SIGILL (sd);
> +	}
> +
> +      if (rd_is_modified)
> +	write_regval (_RDVAL, &CPU.regs[RD_REGN], RDSEL);
> +
> +      /* Don't treat r30 and r31 as regular registers, they are I/O!  */
> +      CPU.regs[30] = 0;
> +      CPU.regs[31] = 0;
> +
> +      /* Handle PC match of loop end.  */
> +      if (LOOP_IN_PROGRESS && (PC == LOOPEND))
> +	{
> +	  SIM_ASSERT (LOOPCNT > 0);
> +	  if (--LOOPCNT == 0)
> +	    LOOP_IN_PROGRESS = 0;
> +	  else
> +	    PC = LOOPTOP;
> +	}
> +
> +      /* In multiply-only mode, MAC does multiplication every cycle.  */
> +      if ((CPU.macregs[PRU_MACREG_MODE] & MAC_R25_MAC_MODE_MASK) == 0)
> +	{
> +	  uint64_t prod;
> +	  prod = CPU.macregs[PRU_MACREG_OP_0];
> +	  prod *= (uint64_t)CPU.macregs[PRU_MACREG_OP_1];
> +	  CPU.macregs[PRU_MACREG_PROD_L] = prod & 0xfffffffful;
> +	  CPU.macregs[PRU_MACREG_PROD_H] = prod >> 32;
> +
> +	  /* Clear the MAC accumulator when in normal mode.  */
> +	  CPU.macregs[PRU_MACREG_ACC_L] = 0;
> +	  CPU.macregs[PRU_MACREG_ACC_H] = 0;
> +	}
> +
> +      /* Update cycle counts.  */
> +      CPU.insts += 1;		  /* One instruction completed ...  */
> +      CPU.cycles += 1;		  /* ... and it takes a single cycle.  */
> +
> +      /* Account for memory access latency with a reasonable estimate.
> +	 No distinction is currently made between SRAM, DRAM and generic
> +	 L3 slaves.  */
> +      if (op->type == prui_lbbo || op->type == prui_sbbo
> +	  || op->type == prui_lbco || op->type == prui_sbco)
> +	CPU.cycles += 2;
> +
> +    }
> +}
> +
> +void
> +sim_engine_run (SIM_DESC sd,
> +		int next_cpu_nr, /* ignore  */
> +		int nr_cpus, /* ignore  */
> +		int siggnal) /* ignore  */
> +{
> +  SIM_CPU *cpu = STATE_CPU (sd, 0);
> +
> +  while (1)
> +    {
> +      sim_step_once (sd);
> +      if (sim_events_tick (sd))
> +	sim_events_process (sd);
> +    }
> +}
> +
> +
> +static sim_cia
> +pru_pc_get (sim_cpu *cpu)
> +{
> +  /* Present PC as byte address.  */
> +  return imem_wordaddr_to_byteaddr (cpu, cpu->pru_cpu.pc);
> +}
> +
> +static void
> +pru_pc_set (sim_cpu *cpu, sim_cia pc)
> +{
> +  /* PC given as byte address.  */
> +  cpu->pru_cpu.pc = imem_byteaddr_to_wordaddr (cpu, pc);
> +}
> +
> +
> +static int
> +pru_store_register (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
> +{
> +  if (rn < NUM_REGS && rn >= 0)
> +    {
> +      if (length == 4)
> +	{
> +	  /* Misalignment safe.  */
> +	  long ival = pru_extract_unsigned_integer (memory, 4);
> +	  if (rn < 32)
> +	    CPU.regs[rn] = ival;
> +	  else
> +	    pru_pc_set (cpu, ival);
> +	  return 4;
> +	}
> +      else
> +	return 0;
> +    }
> +  else
> +    return 0;
> +}
> +
> +static int
> +pru_fetch_register (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
> +{
> +  long ival;
> +
> +  if (rn < NUM_REGS && rn >= 0)
> +    {
> +      if (length == 4)
> +	{
> +	  if (rn < 32)
> +	    ival = CPU.regs[rn];
> +	  else
> +	    ival = pru_pc_get (cpu);
> +
> +	  /* Misalignment-safe.  */
> +	  pru_store_unsigned_integer (memory, 4, ival);
> +	  return 4;
> +	}
> +      else
> +	return 0;
> +    }
> +  else
> +    return 0;
> +}
> +
> +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);
> +}
> +
> +static DECLARE_OPTION_HANDLER (pru_option_handler);
> +
> +static SIM_RC
> +pru_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, char *arg,
> +		    int is_command)
> +{
> +  switch (opt)
> +    {
> +    case OPTION_ERROR_NULL_DEREF:
> +      abort_on_dmem_zero_access = TRUE;
> +      return SIM_RC_OK;
> +
> +    default:
> +      sim_io_eprintf (sd, "Unknown PRU option %d\n", opt);
> +      return SIM_RC_FAIL;
> +    }
> +}
> +
> +static const OPTION pru_options[] =
> +{
> +  { {"error-null-deref", no_argument, NULL, OPTION_ERROR_NULL_DEREF},
> +      '\0', NULL, "Trap any access to DMEM address zero",
> +      pru_option_handler, NULL },
> +
> +  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
> +};
> +
> +SIM_DESC
> +sim_open (SIM_OPEN_KIND kind, host_callback *cb,
> +	  struct bfd *abfd, char * const *argv)
> +{
> +  int i;
> +  SIM_CPU *cpu;
> +  char c;
> +  SIM_DESC sd = sim_state_alloc (kind, cb);
> +  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
> +
> +  /* 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;
> +    }
> +
> +  if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
> +    {
> +      free_state (sd);
> +      return 0;
> +    }
> +  sim_add_option_table (sd, NULL, pru_options);
> +
> +  /* The parser will print an error message for us, so we silently return.  */
> +  if (sim_parse_args (sd, argv) != SIM_RC_OK)
> +    {
> +      free_state (sd);
> +      return 0;
> +    }
> +
> +  /* 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;
> +    }
> +
> +  /* Configure/verify the target byte order and other runtime
> +     configuration options.  */
> +  if (sim_config (sd) != SIM_RC_OK)
> +    {
> +      sim_module_uninstall (sd);
> +      return 0;
> +    }
> +
> +  if (sim_post_argv_init (sd) != SIM_RC_OK)
> +    {
> +      /* Uninstall the modules to avoid memory leaks,
> +	 file descriptor leaks, etc.  */
> +      sim_module_uninstall (sd);
> +      return 0;
> +    }
> +
> +  /* CPU specific initialization.  */
> +  for (i = 0; i < MAX_NR_PROCESSORS; ++i)
> +    {
> +      SIM_CPU *cpu = STATE_CPU (sd, i);
> +
> +      CPU_REG_STORE (cpu) = pru_store_register;
> +      CPU_REG_FETCH (cpu) = pru_fetch_register;
> +      CPU_PC_FETCH (cpu) = pru_pc_get;
> +      CPU_PC_STORE (cpu) = pru_pc_set;
> +
> +      set_initial_gprs (cpu);
> +    }
> +
> +  /* 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)
> +    {
> +      sim_do_commandf (sd, "memory-region 0x%x,0x%x",
> +		       0,
> +		       DMEM_DEFAULT_SIZE);
> +    }
> +  if (sim_core_read_buffer (sd, NULL, read_map, &c, IMEM_ADDR_DEFAULT, 1) == 0)
> +    {
> +      sim_do_commandf (sd, "memory-region 0x%x,0x%x",
> +		       IMEM_ADDR_DEFAULT,
> +		       IMEM_DEFAULT_SIZE);
> +    }
> +
> +  return sd;
> +}
> +
> +SIM_RC
> +sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
> +		     char * const *argv, char * const *env)
> +{
> +  SIM_CPU *cpu = STATE_CPU (sd, 0);
> +  SIM_ADDR addr;
> +
> +  addr = bfd_get_start_address (prog_bfd);
> +
> +  sim_pc_set (cpu, addr);
> +  PC_ADDR_SPACE_MARKER = addr & ~IMEM_ADDR_MASK;
> +
> +  /* Standalone mode (i.e. `run`) will take care of the argv for us in
> +     sim_open () -> sim_parse_args ().  But in debug mode (i.e. 'target sim'
> +     with `gdb`), we need to handle it because the user can change the
> +     argv on the fly via gdb's 'run'.  */
> +  if (STATE_PROG_ARGV (sd) != argv)
> +    {
> +      freeargv (STATE_PROG_ARGV (sd));
> +      STATE_PROG_ARGV (sd) = dupargv (argv);
> +    }
> +
> +  return SIM_RC_OK;
> +}
> diff --git a/sim/pru/pru.h b/sim/pru/pru.h
> new file mode 100644
> index 0000000000..9d74029d90
> --- /dev/null
> +++ b/sim/pru/pru.h
> @@ -0,0 +1,110 @@
> +/* Copyright 2014-2019 Free Software Foundation, Inc.
> +   Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
> +
> +   This file is part of the PRU simulator.
> +
> +   This library is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef PRU_H
> +#define PRU_H
> +
> +#include "config.h"
> +#include "opcode/pru.h"
> +
> +/* NOTE: Needed for handling the dual PRU address space.  */
> +#define IMEM_ADDR_MASK	((1u << 23) - 1)
> +
> +#define IMEM_ADDR_DEFAULT 0x20000000
> +
> +/* Define memory sizes to allocate for simulated target.  Sizes are
> +   artificially large to accommodate execution of compiler test suite.
> +   Please synchronize with the linker script for prusim target.  */
> +#define DMEM_DEFAULT_SIZE (64 * 1024 * 1024)
> +
> +/* 16-bit word addressable space.  */
> +#define IMEM_DEFAULT_SIZE (64 * 4 * 1024)
> +
> +/* For AM335x SoCs.  */
> +#define XFRID_SCRATCH_BANK_0	  10
> +#define XFRID_SCRATCH_BANK_1	  11
> +#define XFRID_SCRATCH_BANK_2	  12
> +#define XFRID_SCRATCH_BANK_PEER	  14
> +#define XFRID_MAX		  255
> +
> +#define CPU     (cpu->pru_cpu)
> +
> +#define PC		(CPU.pc)
> +#define PC_byteaddr	((PC << 2) | PC_ADDR_SPACE_MARKER)
> +
> +/* Various opcode fields.  */
> +#define RS1 extract_regval (CPU.regs[GET_INSN_FIELD (RS1, inst)], \
> +			    GET_INSN_FIELD (RS1SEL, inst))
> +#define RS2 extract_regval (CPU.regs[GET_INSN_FIELD (RS2, inst)], \
> +			    GET_INSN_FIELD (RS2SEL, inst))
> +
> +#define RS2_w0 extract_regval (CPU.regs[GET_INSN_FIELD (RS2, inst)], \
> +			       RSEL_15_0)
> +
> +#define XBBO_BASEREG (CPU.regs[GET_INSN_FIELD (RS1, inst)])
> +
> +#define RDSEL GET_INSN_FIELD (RDSEL, inst)
> +#define RD_WIDTH regsel_width (RDSEL)
> +#define RD_REGN GET_INSN_FIELD (RD, inst)
> +#define IO GET_INSN_FIELD (IO, inst)
> +#define IMM8 GET_INSN_FIELD (IMM8, inst)
> +#define IMM16 GET_INSN_FIELD (IMM16, inst)
> +#define WAKEONSTATUS GET_INSN_FIELD (WAKEONSTATUS, inst)
> +#define CB GET_INSN_FIELD (CB, inst)
> +#define RDB GET_INSN_FIELD (RDB, inst)
> +#define XFR_WBA GET_INSN_FIELD (XFR_WBA, inst)
> +#define LOOP_JMPOFFS GET_INSN_FIELD (LOOP_JMPOFFS, inst)
> +#define BROFF ((uint32_t) GET_BROFF_SIGNED (inst))
> +
> +#define _BURSTLEN_CALCULATE(BITFIELD)					    \
> +  ((BITFIELD) >= LSSBBO_BYTECOUNT_R0_BITS7_0 ?				    \
> +  (CPU.regs[0] >> ((BITFIELD) - LSSBBO_BYTECOUNT_R0_BITS7_0) * 8) & 0xff    \
> +  : (BITFIELD) + 1)
> +
> +#define BURSTLEN _BURSTLEN_CALCULATE (GET_BURSTLEN (inst))
> +#define XFR_LENGTH _BURSTLEN_CALCULATE (GET_INSN_FIELD (XFR_LENGTH, inst))
> +
> +#define DO_XIN(wba,regn,rdb,l)	  \
> +  pru_sim_xin (sd, cpu, (wba), (regn), (rdb), (l))
> +#define DO_XOUT(wba,regn,rdb,l)	  \
> +  pru_sim_xout (sd, cpu, (wba), (regn), (rdb), (l))
> +#define DO_XCHG(wba,regn,rdb,l)	  \
> +  pru_sim_xchg (sd, cpu, (wba), (regn), (rdb), (l))
> +
> +#define RAISE_SIGILL(sd)  sim_engine_halt ((sd), NULL, NULL, PC_byteaddr, \
> +					   sim_stopped, SIM_SIGILL)
> +#define RAISE_SIGINT(sd)  sim_engine_halt ((sd), NULL, NULL, PC_byteaddr, \
> +					   sim_stopped, SIM_SIGINT)
> +
> +#define MAC_R25_MAC_MODE_MASK	  (1u << 0)
> +#define MAC_R25_ACC_CARRY_MASK	  (1u << 1)
> +
> +#define CARRY	CPU.carry
> +#define CTABLE	CPU.ctable
> +
> +#define PC_ADDR_SPACE_MARKER	CPU.pc_addr_space_marker
> +
> +#define LOOPTOP		  CPU.loop.looptop
> +#define LOOPEND		  CPU.loop.loopend
> +#define LOOP_IN_PROGRESS  CPU.loop.loop_in_progress
> +#define LOOPCNT		  CPU.loop.loop_counter
> +
> +/* 32 GP registers plus PC.  */
> +#define NUM_REGS	33
> +
> +#endif /* PRU_H */
> diff --git a/sim/pru/pru.isa b/sim/pru/pru.isa
> new file mode 100644
> index 0000000000..017f85ec50
> --- /dev/null
> +++ b/sim/pru/pru.isa
> @@ -0,0 +1,249 @@
> +/* Copyright 2014-2019 Free Software Foundation, Inc.
> +   Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
> +
> +   This file is part of the PRU simulator.
> +
> +   This library is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
> +
> +/*
> +   PRU Instruction Set Architecture
> +
> +   INSTRUCTION (NAME,
> +		SEMANTICS)
> + */
> +
> +INSTRUCTION (add,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = RS1 + OP2;
> +	     CARRY = (((uint64_t) RS1 + (uint64_t) OP2) >> RD_WIDTH) & 1;
> +	     PC++)
> +
> +INSTRUCTION (adc,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = RS1 + OP2 + CARRY;
> +	     CARRY = (((uint64_t) RS1 + (uint64_t) OP2 + (uint64_t) CARRY)
> +		      >> RD_WIDTH) & 1;
> +	     PC++)
> +
> +INSTRUCTION (sub,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = RS1 - OP2;
> +	     CARRY = (((uint64_t) RS1 - (uint64_t) OP2) >> RD_WIDTH) & 1;
> +	     PC++)
> +
> +INSTRUCTION (suc,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = RS1 - OP2 - CARRY;
> +	     CARRY = (((uint64_t) RS1 - (uint64_t) OP2 - (uint64_t) CARRY)
> +		      >> RD_WIDTH) & 1;
> +	     PC++)
> +
> +INSTRUCTION (rsb,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = OP2 - RS1;
> +	     CARRY = (((uint64_t) OP2 - (uint64_t) RS1) >> RD_WIDTH) & 1;
> +	     PC++)
> +
> +INSTRUCTION (rsc,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = OP2 - RS1 - CARRY;
> +	     CARRY = (((uint64_t) OP2 - (uint64_t) RS1 - (uint64_t) CARRY)
> +		      >> RD_WIDTH) & 1;
> +	     PC++)
> +
> +INSTRUCTION (lsl,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = RS1 << (OP2 & 0x1f);
> +	     PC++)
> +
> +INSTRUCTION (lsr,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = RS1 >> (OP2 & 0x1f);
> +	     PC++)
> +
> +INSTRUCTION (and,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = RS1 & OP2;
> +	     PC++)
> +
> +INSTRUCTION (or,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = RS1 | OP2;
> +	     PC++)
> +
> +INSTRUCTION (xor,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = RS1 ^ OP2;
> +	     PC++)
> +
> +INSTRUCTION (not,
> +	     RD = ~RS1;
> +	     PC++)
> +
> +INSTRUCTION (min,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = RS1 < OP2 ? RS1 : OP2;
> +	     PC++)
> +
> +INSTRUCTION (max,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = RS1 > OP2 ? RS1 : OP2;
> +	     PC++)
> +
> +INSTRUCTION (clr,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = RS1 & ~(1u << (OP2 & 0x1f));
> +	     PC++)
> +
> +INSTRUCTION (set,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     RD = RS1 | (1u << (OP2 & 0x1f));
> +	     PC++)
> +
> +INSTRUCTION (jmp,
> +	     OP2 = (IO ? IMM16 : RS2);
> +	     PC = OP2)
> +
> +INSTRUCTION (jal,
> +	     OP2 = (IO ? IMM16 : RS2);
> +	     RD = PC + 1;
> +	     PC = OP2)
> +
> +INSTRUCTION (ldi,
> +	     RD = IMM16;
> +	     PC++)
> +
> +INSTRUCTION (halt,
> +	     pru_sim_syscall (sd, cpu);
> +	     PC++)
> +
> +INSTRUCTION (slp,
> +	     if (!WAKEONSTATUS)
> +	      {
> +		RAISE_SIGINT (sd);
> +	      }
> +	     else
> +	      {
> +		PC++;
> +	      })
> +
> +INSTRUCTION (qbgt,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     PC = (OP2 > RS1) ? (PC + BROFF) : (PC + 1))
> +
> +INSTRUCTION (qbge,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     PC = (OP2 >= RS1) ? (PC + BROFF) : (PC + 1))
> +
> +INSTRUCTION (qblt,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     PC = (OP2 < RS1) ? (PC + BROFF) : (PC + 1))
> +
> +INSTRUCTION (qble,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     PC = (OP2 <= RS1) ? (PC + BROFF) : (PC + 1))
> +
> +INSTRUCTION (qbeq,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     PC = (OP2 == RS1) ? (PC + BROFF) : (PC + 1))
> +
> +INSTRUCTION (qbne,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     PC = (OP2 != RS1) ? (PC + BROFF) : (PC + 1))
> +
> +INSTRUCTION (qba,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     PC = PC + BROFF)
> +
> +INSTRUCTION (qbbs,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     PC = (RS1 & (1u << (OP2 & 0x1f))) ? (PC + BROFF) : (PC + 1))
> +
> +INSTRUCTION (qbbc,
> +	     OP2 = (IO ? IMM8 : RS2);
> +	     PC = !(RS1 & (1u << (OP2 & 0x1f))) ? (PC + BROFF) : (PC + 1))
> +
> +INSTRUCTION (lbbo,
> +	     pru_dmem2reg (cpu, XBBO_BASEREG + (IO ? IMM8 : RS2),
> +			   BURSTLEN, RD_REGN, RDB);
> +	     PC++)
> +
> +INSTRUCTION (sbbo,
> +	     pru_reg2dmem (cpu, XBBO_BASEREG + (IO ? IMM8 : RS2),
> +			   BURSTLEN, RD_REGN, RDB);
> +	     PC++)
> +
> +INSTRUCTION (lbco,
> +	     pru_dmem2reg (cpu, CTABLE[CB] + (IO ? IMM8 : RS2),
> +			   BURSTLEN, RD_REGN, RDB);
> +	     PC++)
> +
> +INSTRUCTION (sbco,
> +	     pru_reg2dmem (cpu, CTABLE[CB] + (IO ? IMM8 : RS2),
> +			   BURSTLEN, RD_REGN, RDB);
> +	     PC++)
> +
> +INSTRUCTION (xin,
> +	     DO_XIN (XFR_WBA, RD_REGN, RDB, XFR_LENGTH);
> +	     PC++)
> +
> +INSTRUCTION (xout,
> +	     DO_XOUT (XFR_WBA, RD_REGN, RDB, XFR_LENGTH);
> +	     PC++)
> +
> +INSTRUCTION (xchg,
> +	     DO_XCHG (XFR_WBA, RD_REGN, RDB, XFR_LENGTH);
> +	     PC++)
> +
> +INSTRUCTION (sxin,
> +	     sim_io_eprintf (sd, "SXIN instruction not supported by sim\n");
> +	     RAISE_SIGILL (sd))
> +
> +INSTRUCTION (sxout,
> +	     sim_io_eprintf (sd, "SXOUT instruction not supported by sim\n");
> +	     RAISE_SIGILL (sd))
> +
> +INSTRUCTION (sxchg,
> +	     sim_io_eprintf (sd, "SXCHG instruction not supported by sim\n");
> +	     RAISE_SIGILL (sd))
> +
> +INSTRUCTION (loop,
> +	     OP2 = (IO ? IMM8 + 1 : RS2_w0);
> +	     if (OP2 == 0)
> +	      {
> +		PC = LOOPEND;
> +	      }
> +	     else
> +	      {
> +		LOOPTOP = PC + 1;
> +		LOOPEND = PC + LOOP_JMPOFFS;
> +		LOOPCNT = OP2;
> +		LOOP_IN_PROGRESS = 1;
> +		PC++;
> +	     })
> +
> +INSTRUCTION (iloop,
> +	     OP2 = (IO ? IMM8 + 1 : RS2_w0);
> +	     if (OP2 == 0)
> +	      {
> +		PC = LOOPEND;
> +	      }
> +	     else
> +	      {
> +		LOOPTOP = PC + 1;
> +		LOOPEND = PC + LOOP_JMPOFFS;
> +		LOOPCNT = OP2;
> +		LOOP_IN_PROGRESS = 1;
> +		PC++;
> +	     })
> diff --git a/sim/pru/sim-main.h b/sim/pru/sim-main.h
> new file mode 100644
> index 0000000000..4ad7b56a87
> --- /dev/null
> +++ b/sim/pru/sim-main.h
> @@ -0,0 +1,82 @@
> +/* Copyright 2014-2019 Free Software Foundation, Inc.
> +   Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
> +
> +   This file is part of the PRU simulator.
> +
> +   This library is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef PRU_SIM_MAIN
> +#define PRU_SIM_MAIN
> +
> +#include <stdint.h>
> +#include <stddef.h>
> +#include "pru.h"
> +#include "sim-basics.h"
> +
> +#include "sim-base.h"
> +
> +/* The machine state.
> +   This state is maintained in host byte order.  The
> +   fetch/store register functions must translate between host
> +   byte order and the target processor byte order.
> +   Keeping this data in target byte order simplifies the register
> +   read/write functions.  Keeping this data in native order improves
> +   the performance of the simulator.  Simulation speed is deemed more
> +   important.  */
> +
> +/* Please keep the same order as the GP registers.  */
> +enum pru_macreg_id {
> +    PRU_MACREG_MODE,	  /* r25 */
> +    PRU_MACREG_PROD_L,	  /* r26 */
> +    PRU_MACREG_PROD_H,	  /* r27 */
> +    PRU_MACREG_OP_0,	  /* r28 */
> +    PRU_MACREG_OP_1,	  /* r29 */
> +    PRU_MACREG_ACC_L,	  /* N/A */
> +    PRU_MACREG_ACC_H,	  /* N/A */
> +    PRU_MAC_NREGS
> +};
> +
> +struct pru_regset
> +{
> +  uint32_t	  regs[32];		/* Primary registers.  */
> +  uint16_t	  pc;			/* IMEM _word_ address.  */
> +  uint32_t	  pc_addr_space_marker; /* IMEM virtual linker offset.  This
> +					   is the artificial offset that
> +					   we invent in order to "separate"
> +					   the DMEM and IMEM memory spaces.  */
> +  unsigned int	  carry : 1;
> +  uint32_t	  ctable[32];		/* Constant offsets table for xBCO.  */
> +  uint32_t	  macregs[PRU_MAC_NREGS];
> +  uint32_t	  scratchpads[XFRID_MAX + 1][32];
> +  struct {
> +    uint16_t looptop;			/* LOOP top (PC of loop instr).  */
> +    uint16_t loopend;			/* LOOP end (PC of loop end label).  */
> +    int loop_in_progress;		/* Whether to check for PC==loopend.  */
> +    uint32_t loop_counter;		/* LOOP counter.  */
> +  } loop;
> +  int		  cycles;
> +  int		  insts;
> +};
> +
> +struct _sim_cpu {
> +  struct pru_regset pru_cpu;
> +  sim_cpu_base base;
> +};
> +
> +struct sim_state {
> +  sim_cpu *cpu[MAX_NR_PROCESSORS];
> +
> +  sim_state_base base;
> +};
> +#endif /* PRU_SIM_MAIN */
> -- 
> 2.20.1
> 


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