public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 2/2] Add testsuite for the PRU simulator port
  2016-12-27 21:26 [PATCH v2 1/2] PRU Simulator port Dimitar Dimitrov
@ 2016-12-27 21:26 ` Dimitar Dimitrov
  2017-02-13  5:36   ` Mike Frysinger
  2017-01-14  7:05 ` [PATCH v2 1/2] PRU Simulator port Dimitar Dimitrov
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Dimitar Dimitrov @ 2016-12-27 21:26 UTC (permalink / raw)
  To: gdb-patches; +Cc: Dimitar Dimitrov

2016-12-26  Dimitar Dimitrov <dimitar@dinux.eu>

sim/test

	* configure: Regenerate.
	* pru: New directory.

Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
---
 sim/testsuite/configure                |  3 ++
 sim/testsuite/sim/pru/ChangeLog        | 14 +++++++
 sim/testsuite/sim/pru/add.s            | 22 ++++++++++
 sim/testsuite/sim/pru/allinsn.exp      | 15 +++++++
 sim/testsuite/sim/pru/dmem-zero-pass.s | 11 +++++
 sim/testsuite/sim/pru/dmem-zero-trap.s | 14 +++++++
 sim/testsuite/sim/pru/dram.s           | 54 +++++++++++++++++++++++++
 sim/testsuite/sim/pru/jmp.s            | 22 ++++++++++
 sim/testsuite/sim/pru/loop-imm.s       | 25 ++++++++++++
 sim/testsuite/sim/pru/loop-reg.s       | 26 ++++++++++++
 sim/testsuite/sim/pru/subreg.s         | 22 ++++++++++
 sim/testsuite/sim/pru/testutils.inc    | 73 ++++++++++++++++++++++++++++++++++
 12 files changed, 301 insertions(+)
 create mode 100644 sim/testsuite/sim/pru/ChangeLog
 create mode 100644 sim/testsuite/sim/pru/add.s
 create mode 100644 sim/testsuite/sim/pru/allinsn.exp
 create mode 100644 sim/testsuite/sim/pru/dmem-zero-pass.s
 create mode 100644 sim/testsuite/sim/pru/dmem-zero-trap.s
 create mode 100644 sim/testsuite/sim/pru/dram.s
 create mode 100644 sim/testsuite/sim/pru/jmp.s
 create mode 100644 sim/testsuite/sim/pru/loop-imm.s
 create mode 100644 sim/testsuite/sim/pru/loop-reg.s
 create mode 100644 sim/testsuite/sim/pru/subreg.s
 create mode 100644 sim/testsuite/sim/pru/testutils.inc

diff --git a/sim/testsuite/configure b/sim/testsuite/configure
index bbc3bea48d..6565debbfc 100755
--- a/sim/testsuite/configure
+++ b/sim/testsuite/configure
@@ -1906,6 +1906,9 @@ case "${target}" in
    powerpc*-*-*)
        sim_arch=ppc
        ;;
+   pru*-*-*)
+       sim_arch=pru
+       ;;
    ft32-*-*)
        sim_arch=ft32
        ;;
diff --git a/sim/testsuite/sim/pru/ChangeLog b/sim/testsuite/sim/pru/ChangeLog
new file mode 100644
index 0000000000..7a141ed47e
--- /dev/null
+++ b/sim/testsuite/sim/pru/ChangeLog
@@ -0,0 +1,14 @@
+2016-12-26  Dimitar Dimitrov  <dimitar@dinux.eu>
+
+	* ChangeLog: New file.
+	* add.s: New test.
+	* allinsn.exp: New file.
+	* dmem-zero-pass.s: New test.
+	* dmem-zero-trap.s: New test.
+	* dram.s: New test.
+	* jmp.s: New test.
+	* loop-imm.s: New test.
+	* loop-reg.s: New test.
+	* subreg.s: New test.
+	* testutils.inc: New file.
+
diff --git a/sim/testsuite/sim/pru/add.s b/sim/testsuite/sim/pru/add.s
new file mode 100644
index 0000000000..10bdd9a8ef
--- /dev/null
+++ b/sim/testsuite/sim/pru/add.s
@@ -0,0 +1,22 @@
+# check that basic add insn works.
+# mach: pru
+
+.include "testutils.inc"
+
+	start
+
+	ldi r4, 10
+	add r4, r4, 23
+	qbne 2f, r4, 33
+
+	qblt 2f, r4, 33
+
+	qbgt 2f, r4, 33
+
+	jmp 1f
+
+	fail
+
+1:
+	pass
+2:	fail
diff --git a/sim/testsuite/sim/pru/allinsn.exp b/sim/testsuite/sim/pru/allinsn.exp
new file mode 100644
index 0000000000..6e50710224
--- /dev/null
+++ b/sim/testsuite/sim/pru/allinsn.exp
@@ -0,0 +1,15 @@
+# PRU simulator testsuite
+
+if [istarget pru-*] {
+    # all machines
+    set all_machs "pru"
+
+    foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.s]] {
+	# If we're only testing specific files and this isn't one of them,
+	# skip it.
+	if ![runtest_file_p $runtests $src] {
+	    continue
+	}
+	run_sim_test $src $all_machs
+    }
+}
diff --git a/sim/testsuite/sim/pru/dmem-zero-pass.s b/sim/testsuite/sim/pru/dmem-zero-pass.s
new file mode 100644
index 0000000000..3cdc715d35
--- /dev/null
+++ b/sim/testsuite/sim/pru/dmem-zero-pass.s
@@ -0,0 +1,11 @@
+# check that DMEM zero address access works by default.
+# mach: pru
+
+.include "testutils.inc"
+
+	start
+
+	ldi r1, 0
+	lbbo &r2, r1, 0, 4
+
+	pass
diff --git a/sim/testsuite/sim/pru/dmem-zero-trap.s b/sim/testsuite/sim/pru/dmem-zero-trap.s
new file mode 100644
index 0000000000..55d8a22505
--- /dev/null
+++ b/sim/testsuite/sim/pru/dmem-zero-trap.s
@@ -0,0 +1,14 @@
+# check that DMEM zero address access can be trapped.
+# mach: pru
+# sim: --error-null-deref
+# xerror:
+# output: core: 4 byte read to unmapped address 0x0 at *\n
+
+.include "testutils.inc"
+
+	start
+
+	ldi r1, 0
+	lbbo &r2, r1, 0, 4
+
+	pass
diff --git a/sim/testsuite/sim/pru/dram.s b/sim/testsuite/sim/pru/dram.s
new file mode 100644
index 0000000000..2a998b566c
--- /dev/null
+++ b/sim/testsuite/sim/pru/dram.s
@@ -0,0 +1,54 @@
+# check that DRAM memory access works.
+# mach: pru
+
+.include "testutils.inc"
+
+	start
+
+	fill r20, 16
+	ldi r10, 0
+	not r10, r10
+	qbne F, r20, r10
+	qbne F, r21, r10
+	qbne F, r22, r10
+	qbne F, r23, r10
+
+	zero r20, 16
+	qbne F, r20, 0
+	qbne F, r21, 0
+	qbne F, r22, 0
+	qbne F, r23, 0
+
+	ldi r0, testarray
+	lbbo &r20, r0, 0, 7
+	qbne F, r20.b0, 0x01
+	qbne F, r20.b1, 0x23
+	qbne F, r20.b2, 0x45
+	qbne F, r20.b3, 0x67
+	qbne F, r21.b0, 0x89
+	qbne F, r21.b1, 0xab
+	qbne F, r21.b2, 0xcd
+	qbne F, r21.b3, 0x00 ; Should not have been loaded!
+	qbne F, r22, 0
+	qbne F, r23, 0
+
+	ldi r1, 0x11
+	sbbo &r1, r0, 9, 1
+	ldi r1, 0x11
+	sbbo &r1, r0, 12, 4
+
+	lbbo &r20, r0, 0, 16
+	qbne F, r21.b3, 0xef
+	qbne F, r22.b0, 0xff
+	qbne F, r22.b1, 0x11
+	qbne F, r22.b2, 0xff
+	qbne F, r22.b3, 0xff
+	qbne F, r23, 0x11
+
+	pass
+F:	fail
+
+	.data
+testarray:
+	.byte 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
+	.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
diff --git a/sim/testsuite/sim/pru/jmp.s b/sim/testsuite/sim/pru/jmp.s
new file mode 100644
index 0000000000..d01d78f823
--- /dev/null
+++ b/sim/testsuite/sim/pru/jmp.s
@@ -0,0 +1,22 @@
+# check that basic add insn works.
+# mach: pru
+
+.include "testutils.inc"
+
+	start
+
+	ldi r10, 10
+	call func1
+	qbne F, r10, 11
+
+	ldi r0, %pmem(1f)
+	jmp r0
+	fail
+1:
+	pass
+F:	fail
+
+
+func1:
+	add r10, r10, 1
+	ret
diff --git a/sim/testsuite/sim/pru/loop-imm.s b/sim/testsuite/sim/pru/loop-imm.s
new file mode 100644
index 0000000000..118219b54c
--- /dev/null
+++ b/sim/testsuite/sim/pru/loop-imm.s
@@ -0,0 +1,25 @@
+# check that loop insn works.
+# mach: pru
+
+.include "testutils.inc"
+
+	start
+
+	ldi r25, 0
+	ldi r26, 0
+	ldi r27, 0
+
+	add r27, r27, 1
+	loop 1f, 10
+	add r25, r25, 1
+	add r26, r26, 2
+1:
+	add r27, r27, 1
+
+	qbne F, r25, 10
+	qbne F, r26, 20
+	qbne F, r27, 2
+
+	pass
+
+F:	fail
diff --git a/sim/testsuite/sim/pru/loop-reg.s b/sim/testsuite/sim/pru/loop-reg.s
new file mode 100644
index 0000000000..d4843e9415
--- /dev/null
+++ b/sim/testsuite/sim/pru/loop-reg.s
@@ -0,0 +1,26 @@
+# check that loop insn works.
+# mach: pru
+
+.include "testutils.inc"
+
+	start
+
+	ldi r25, 0
+	ldi r26, 0
+	ldi r27, 0
+	ldi r28, 10
+
+	add r27, r27, 1
+	loop 1f, r28
+	add r25, r25, 1
+	add r26, r26, 2
+1:
+	add r27, r27, 1
+
+	qbne F, r25, 10
+	qbne F, r26, 20
+	qbne F, r27, 2
+
+	pass
+
+F:	fail
diff --git a/sim/testsuite/sim/pru/subreg.s b/sim/testsuite/sim/pru/subreg.s
new file mode 100644
index 0000000000..a100e411b2
--- /dev/null
+++ b/sim/testsuite/sim/pru/subreg.s
@@ -0,0 +1,22 @@
+# check that subregister addressing works.
+# mach: pru
+
+.include "testutils.inc"
+
+	start
+
+	ldi r0, 0x01ff
+	add r0, r0.b0, r0.b1
+	qbne F, r0.b0, 0x00
+	qbne F, r0.b1, 0x01
+	qbne F, r0.w2, 0x00
+
+	ldi r0, 0x01ff
+	add r0.b0, r0.b0, r0.b1
+	adc r0, r0.b1, r0.b3
+	qbne F, r0.b0, 0x02
+	qbne F, r0.b1, 0x00
+	qbne F, r0.w2, 0x00
+
+	pass
+F:	fail
diff --git a/sim/testsuite/sim/pru/testutils.inc b/sim/testsuite/sim/pru/testutils.inc
new file mode 100644
index 0000000000..7a5029f90e
--- /dev/null
+++ b/sim/testsuite/sim/pru/testutils.inc
@@ -0,0 +1,73 @@
+# MACRO: start
+# All assembler tests should start with a call to "main_test"
+	.macro start
+	.text
+
+        .global _start
+_start:
+
+	# Skip over these inlined funcs.
+	jmp __main_test;
+
+	.global __pass
+	.type __pass, function
+__pass:
+	# Note - DRAM LMA and VMA are equal for PRU, so
+	# we can afford to pass DRAM pointer directly.
+	write 1, _passmsg, 5
+	exit 0
+
+	.global __fail
+	.type __fail, function
+__fail:
+	write 1, _failmsg, 5
+	exit 1
+
+	.data
+_passmsg:
+	.ascii "pass\n"
+
+_failmsg:
+	.ascii "fail\n"
+
+	.text
+	.global __main_test
+	.type __main_test, function
+__main_test:
+	.endm
+
+# MACRO: system_call
+# Make a libgloss system call
+	.macro system_call nr:req, arg1=0, arg2=0, arg3=0
+	ldi r1, \nr
+	ldi r14, \arg1
+	ldi r15, \arg2
+	ldi r16, \arg3
+	halt
+	.endm
+
+# MACRO: exit
+# Quit the current test
+	.macro exit rc:req
+	system_call 1, \rc
+	.endm
+
+# MACRO: pass
+# Write 'pass' to stdout via syscalls and quit;
+# meant for non-OS operating environments
+	.macro pass
+	jmp __pass;
+	.endm
+
+# MACRO: fail
+# Write 'fail' to stdout via syscalls and quit;
+# meant for non-OS operating environments
+	.macro fail
+	jmp __fail;
+	.endm
+
+# MACRO: write
+# Just like the write() C function; uses system calls
+	.macro write fd:req, str:req, len:req
+	system_call 5, \fd, \str, \len
+	.endm
-- 
2.11.0

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/2] PRU Simulator port
@ 2016-12-27 21:26 Dimitar Dimitrov
  2016-12-27 21:26 ` [PATCH v2 2/2] Add testsuite for the PRU simulator port Dimitar Dimitrov
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Dimitar Dimitrov @ 2016-12-27 21:26 UTC (permalink / raw)
  To: gdb-patches; +Cc: Dimitar Dimitrov

I hope I have addressed all review comments from v1.

The corresponding libgloss changes have not yet been mainlined. The PRU patches are available here: https://github.com/dinuxbg/gnupru/tree/for-next/patches/newlib-cygwin

The corresponding binutils patches have been submitted for review on the binutils mailing list: https://sourceware.org/ml/binutils/2016-12/msg00425.html

Changes since patch series v1:
  - Added sim testsuite.
  - Added myself to MAINTAINERS
  - Regenerated sim/configure.
  - Updated C comments per review suggestions.
  - Forced LITTLE endian mode.
  - Switched to SIM_ASSERT/ASSERT/sim_io_error/sim_io_eprintf.
  - Added --error-null-deref command line option.
  - Switched to using sim_syscall and updated libgloss accordingly.
  - Switched to standard libgloss syscall IDs.
  - Made IMEM address space access checks depend on SIM_OPEN_STANDALONE, in
    order to prevent GDB breaking.

2016-12-26  Dimitar Dimitrov <dimitar@dinux.eu>

	* sim/MAINTAINERS.tgt: Add myself as PRU maintainer.
	* sim/common/gennltvals.sh: Add PRU libgloss target.
	* sim/common/nltvals.def: Regenerate from the unofficial
	PRU libgloss port.
	* sim/configure: Regenerate.
	* sim/configure.tgt: Add PRU.
	* sim/pru/Makefile.in: New file.
	* sim/pru/aclocal.m4: New file.
	* sim/pru/config.in: New file.
	* sim/pru/configure: Regenerate.
	* sim/pru/configure.ac: New file.
	* sim/pru/interp.c: New file.
	* sim/pru/pru.h: New file.
	* sim/pru/pru.isa: New file.
	* sim/pru/sim-main.h: New file.

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         | 722 +++++++++++++++++++++++++++++++++++++++++++++++
 sim/pru/pru.h            | 110 ++++++++
 sim/pru/pru.isa          | 250 ++++++++++++++++
 sim/pru/sim-main.h       |  76 +++++
 13 files changed, 1623 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 b373f66a7b..51328cacf9 100644
--- a/sim/MAINTAINERS
+++ b/sim/MAINTAINERS
@@ -28,6 +28,7 @@ microblaze	Michael Eager <eager@eagercon.com>
 mips		Maciej W. Rozycki <macro@imgtec.com>
 moxie		Anthony Green <green@moxielogic.com>
 msp430		Nick Clifton <nickc@redhat.com>
+pru		Dimitar Dimitrov <dimitar@dinux.eu>
 rx		DJ Delorie <dj@redhat.com>
 sh		(global maintainers)
 sh64		Dave Brolley <brolley@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 2729e69817..f92d310a2c 100755
--- a/sim/configure
+++ b/sim/configure
@@ -654,6 +654,7 @@ mips
 mn10300
 moxie
 msp430
+pru
 rl78
 rx
 sh64
@@ -3768,6 +3769,13 @@ subdirs="$subdirs aarch64"
 
 
        ;;
+   pru*-*-*)
+
+  sim_arch=pru
+  subdirs="$subdirs pru"
+
+
+       ;;
    rl78-*-*)
 
   sim_arch=rl78
diff --git a/sim/configure.tgt b/sim/configure.tgt
index c958fb3174..357d7ac337 100644
--- a/sim/configure.tgt
+++ b/sim/configure.tgt
@@ -76,6 +76,9 @@ case "${target}" in
    msp430*-*-*)
        SIM_ARCH(msp430)
        ;;
+   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..03f791dbd9
--- /dev/null
+++ b/sim/pru/Makefile.in
@@ -0,0 +1,29 @@
+#    Makefile template for Configure for the PRU sim library.
+#    Copyright (C) 2014-2016 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..e7da826afe
--- /dev/null
+++ b/sim/pru/interp.c
@@ -0,0 +1,722 @@
+/* Simulator for the Texas Instruments PRU processor
+   Copyright 2014-2016 Free Software Foundation, Inc.
+   Inspired by the Microblase 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 "bfd.h"
+#include "gdb/callback.h"
+#include "libiberty.h"
+#include "gdb/remote-sim.h"
+#include "sim-main.h"
+#include "sim-options.h"
+#include "sim-syscall.h"
+#include "pru.h"
+
+#ifndef NUM_ELEM
+#define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
+#endif
+
+/* 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 int 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");
+    }
+}
+
+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);
+}
+
+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;
+}
+
+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 (standalone && 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");
+      sim_engine_halt (CPU_STATE (cpu), NULL, NULL, PC_byteaddr,
+		       sim_stopped, SIM_SIGILL);
+    }
+  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++;
+	    }
+	}
+    }
+}
+
+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 (standalone && 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");
+      sim_engine_halt (CPU_STATE (cpu), NULL, NULL, PC_byteaddr,
+		       sim_stopped, SIM_SIGILL);
+    }
+  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++;
+	    }
+	}
+    }
+}
+
+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 = 0x20000000; /* from default linker script? */
+
+  /* Clean out the GPRs.  */
+  for (i = 0; i < NUM_ELEM (CPU.regs); i++)
+    CPU.regs[i] = 0;
+  for (i = 0; i < NUM_ELEM (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;
+}
+
+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");
+    }
+}
+
+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);
+
+  if ((CPU.macregs[PRU_MACREG_MODE] & MAC_R25_MAC_MODE_MASK) == 0)
+    {
+      /* Per TRM, PRU auto-samples R28/R29 on every cycle.  But in fact we
+	 calculate only when interested in the product.  */
+      uint64_t prod;
+      prod = (uint64_t)CPU.regs[28] * (uint64_t)CPU.regs[29];
+      CPU.macregs[PRU_MACREG_PROD_L] = prod & 0xfffffffful;
+      CPU.macregs[PRU_MACREG_PROD_H] = prod >> 32;
+    }
+
+  /* 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++;
+	}
+    }
+}
+
+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 == 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);
+    }
+}
+
+static void
+pru_sim_xout (SIM_DESC sd, SIM_CPU *cpu, unsigned int wba,
+	      unsigned int rd_regn, unsigned int rdb, unsigned int length)
+{
+  const int modereg_accessed = (rd_regn == 25);	/* revise! */
+
+  if (wba != 0)
+    sim_io_error (sd, "XOUT: XFR device %d not supported.\n", wba);
+
+  /* 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_ACC_CARRY_MASK))
+    {
+      /* store 1 to clear.  */
+      CPU.macregs[PRU_MACREG_MODE] &= ~MAC_R25_ACC_CARRY_MASK;
+    }
+
+  if (modereg_accessed
+      && (CPU.macregs[PRU_MACREG_MODE] & MAC_R25_MAC_MODE_MASK))
+    {
+      uint64_t prod, oldsum, sum;
+      prod = (uint64_t)CPU.regs[28] * (uint64_t)CPU.regs[29];
+      oldsum = CPU.macregs[PRU_MACREG_PROD_L];
+      oldsum += (uint64_t)CPU.macregs[PRU_MACREG_PROD_H] << 32;
+      sum = oldsum + prod;
+
+      CPU.macregs[PRU_MACREG_PROD_L] = sum & 0xfffffffful;
+      CPU.macregs[PRU_MACREG_PROD_H] = sum >> 32;
+
+      if (oldsum > sum)
+	CPU.macregs[PRU_MACREG_MODE] |= MAC_R25_ACC_CARRY_MASK;
+    }
+}
+
+static void
+pru_sim_syscall (SIM_DESC sd, SIM_CPU *cpu)
+{
+
+  const uint32_t syscall_num = CPU.regs[1];
+
+  CPU.regs[14] = sim_syscall (cpu, syscall_num,
+			      CPU.regs[14], CPU.regs[15],
+			      CPU.regs[16], CPU.regs[17]);
+}
+
+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 ();
+    }
+  else
+    {
+      TRACE_DISASM (cpu, PC_byteaddr);
+
+      switch (op->type)
+	{
+#define INSTRUCTION(NAME, ACTION)		\
+	case prui_ ## NAME:			\
+						ACTION;				\
+	  break;
+#include "pru.isa"
+#undef INSTRUCTION
+
+	default:
+	  RAISE_SIGILL ();
+	  sim_io_eprintf (sd, "Unknown opcode.\n");
+	}
+
+      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;
+	}
+
+      /* Update cycle counts.  */
+      CPU.insts += 1;		  /* One instructions completed ...  */
+      CPU.cycles += 1;		  /* and it takes a single cycle.  */
+
+      /* Account for memory access latency with a reasonable estimate.  */
+      if (op->type == prui_lbbo || op->type == prui_sbbo
+	  || op->type == prui_lbco || op->type == prui_sbco)
+	CPU.cycles += MEM_ACCESS_CYCLES;
+
+    }
+}
+
+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 = 1;
+      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;
+  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);
+    }
+
+  sim_do_commandf (sd, "memory-region 0x%x,0x%x",
+		   0,
+		   DMEM_DEFAULT_SIZE);
+  sim_do_commandf (sd, "memory-region 0x%x,0x%x",
+		   0x20000000,
+		   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..0fddbe971e
--- /dev/null
+++ b/sim/pru/pru.h
@@ -0,0 +1,110 @@
+/* Copyright 2014-2016 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 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)
+
+#define CPU     (cpu->pru_cpu)
+
+/* (void)0 is a guard against using RD as a left-hand side value.  */
+#define RD      (void)0; rd_is_modified = 1; _RDVAL
+
+#define PC		(cpu->pru_cpu.pc)
+#define PC_byteaddr	((cpu->pru_cpu.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_SYSCALL()	pru_sim_syscall(sd, cpu)
+
+#define RAISE_SIGILL()	sim_engine_halt (sd, NULL, NULL, PC_byteaddr, \
+					 sim_signalled, SIM_SIGILL);
+#define RAISE_SIGINT()	sim_engine_halt (sd, NULL, NULL, PC_byteaddr, \
+					 sim_signalled, 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
+
+#define NUM_REGS 	33
+#define PCREG_NUM	32
+#define INST_SIZE 	4
+
+/* Number of cycles spent for memory access.  No distinction is currently
+   made between SRAM, DRAM and generic L3 slaves.  */
+#define MEM_ACCESS_CYCLES 2
+
+#endif /* PRU_H */
+
diff --git a/sim/pru/pru.isa b/sim/pru/pru.isa
new file mode 100644
index 0000000000..f963564289
--- /dev/null
+++ b/sim/pru/pru.isa
@@ -0,0 +1,250 @@
+/* Copyright 2014-2016 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,
+	     DO_SYSCALL ();
+	     PC++)
+
+INSTRUCTION (slp,
+	     if (!WAKEONSTATUS)
+	      {
+		RAISE_SIGINT ();
+	      }
+	     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,
+	     fprintf (stderr, "XCHG instruction not supported by sim\n");
+	     RAISE_SIGILL ())
+
+INSTRUCTION (sxin,
+	     fprintf (stderr, "SXIN instruction not supported by sim\n");
+	     RAISE_SIGILL ())
+
+INSTRUCTION (sxout,
+	     fprintf (stderr, "SXOUT instruction not supported by sim\n");
+	     RAISE_SIGILL ())
+
+INSTRUCTION (sxchg,
+	     fprintf (stderr, "SXCHG instruction not supported by sim\n");
+	     RAISE_SIGILL ())
+
+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..6d49809a5a
--- /dev/null
+++ b/sim/pru/sim-main.h
@@ -0,0 +1,76 @@
+/* Copyright 2014-2016 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 "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.  */
+
+enum pru_macreg_id {
+    PRU_MACREG_MODE,
+    PRU_MACREG_PROD_L,
+    PRU_MACREG_PROD_H,
+    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];
+  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.11.0

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/2] PRU Simulator port
  2016-12-27 21:26 [PATCH v2 1/2] PRU Simulator port Dimitar Dimitrov
  2016-12-27 21:26 ` [PATCH v2 2/2] Add testsuite for the PRU simulator port Dimitar Dimitrov
@ 2017-01-14  7:05 ` Dimitar Dimitrov
  2017-02-11 18:35 ` [PING] " Dimitar Dimitrov
  2017-02-13  5:36 ` Mike Frysinger
  3 siblings, 0 replies; 7+ messages in thread
From: Dimitar Dimitrov @ 2017-01-14  7:05 UTC (permalink / raw)
  To: gdb-patches

On вторник, 27 декември 2016 г. 23:25:55 EET Dimitar Dimitrov wrote:
> I hope I have addressed all review comments from v1.
> 
> The corresponding libgloss changes have not yet been mainlined. The PRU
> patches are available here:
> https://github.com/dinuxbg/gnupru/tree/for-next/patches/newlib-cygwin
> 
> The corresponding binutils patches have been submitted for review on the
> binutils mailing list:
> https://sourceware.org/ml/binutils/2016-12/msg00425.html
Ping. The binutils patches for PRU have already been merged.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PING] [PATCH v2 1/2] PRU Simulator port
  2016-12-27 21:26 [PATCH v2 1/2] PRU Simulator port Dimitar Dimitrov
  2016-12-27 21:26 ` [PATCH v2 2/2] Add testsuite for the PRU simulator port Dimitar Dimitrov
  2017-01-14  7:05 ` [PATCH v2 1/2] PRU Simulator port Dimitar Dimitrov
@ 2017-02-11 18:35 ` Dimitar Dimitrov
  2017-02-13  5:36 ` Mike Frysinger
  3 siblings, 0 replies; 7+ messages in thread
From: Dimitar Dimitrov @ 2017-02-11 18:35 UTC (permalink / raw)
  To: gdb-patches

On вторник, 27 декември 2016 г. 23:25:55 EET Dimitar Dimitrov wrote:
> 2016-12-26  Dimitar Dimitrov <dimitar@dinux.eu>
> 
>         * sim/MAINTAINERS.tgt: Add myself as PRU maintainer.
>         * sim/common/gennltvals.sh: Add PRU libgloss target.
>         * sim/common/nltvals.def: Regenerate from the unofficial
>         PRU libgloss port.
>         * sim/configure: Regenerate.
>         * sim/configure.tgt: Add PRU.
>         * sim/pru/Makefile.in: New file.
>         * sim/pru/aclocal.m4: New file.
>         * sim/pru/config.in: New file.
>         * sim/pru/configure: Regenerate.
>         * sim/pru/configure.ac: New file.
>         * sim/pru/interp.c: New file.
>         * sim/pru/pru.h: New file.
>         * sim/pru/pru.isa: New file.
>         * sim/pru/sim-main.h: New file.

Ping
http://sourceware.org/ml/gdb-patches/2016-12/msg00431.html
http://sourceware.org/ml/gdb-patches/2016-12/msg00430.html

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 2/2] Add testsuite for the PRU simulator port
  2016-12-27 21:26 ` [PATCH v2 2/2] Add testsuite for the PRU simulator port Dimitar Dimitrov
@ 2017-02-13  5:36   ` Mike Frysinger
  0 siblings, 0 replies; 7+ messages in thread
From: Mike Frysinger @ 2017-02-13  5:36 UTC (permalink / raw)
  To: Dimitar Dimitrov; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 25 bytes --]

thanks, looks fine
-mike

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/2] PRU Simulator port
  2016-12-27 21:26 [PATCH v2 1/2] PRU Simulator port Dimitar Dimitrov
                   ` (2 preceding siblings ...)
  2017-02-11 18:35 ` [PING] " Dimitar Dimitrov
@ 2017-02-13  5:36 ` Mike Frysinger
  2017-02-14 21:25   ` Dimitar Dimitrov
  3 siblings, 1 reply; 7+ messages in thread
From: Mike Frysinger @ 2017-02-13  5:36 UTC (permalink / raw)
  To: Dimitar Dimitrov; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 4725 bytes --]

On 27 Dec 2016 23:25, Dimitar Dimitrov wrote:
> The corresponding libgloss changes have not yet been mainlined.
> The PRU patches are available here:
> https://github.com/dinuxbg/gnupru/tree/for-next/patches/newlib-cygwin

have you sent them to the mailing list ?  i don't see them ...
	https://sourceware.org/ml/newlib/

> 2016-12-26  Dimitar Dimitrov <dimitar@dinux.eu>
> 
> 	* sim/MAINTAINERS.tgt: Add myself as PRU maintainer.

ChangeLog is relative to sim/, so should be "MAINTAINERS".
also, this file doesn't have a .tgt suffix.

> --- /dev/null
> +++ b/sim/pru/interp.c
>
> +#ifndef NUM_ELEM
> +#define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
> +#endif

use the standard ARRAY_SIZE from libiberty.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 int abort_on_dmem_zero_access;

use bfd_boolean instead, and TRUE/FALSE values

> +extract_regval (uint32_t val, uint32_t regsel)
> +{
> ...
> +    default:	      sim_io_error(NULL, "invalid regsel");

space before the (

this comes up a few times in this file -- please fix them all

> +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.  */

only one space before "in"

> +  bool standalone = (STATE_OPEN_KIND (CPU_STATE (cpu)) == SIM_OPEN_STANDALONE);
> +
> +  if (standalone && abort_on_dmem_zero_access && addr < 4)

i don't think you need the standalone check here.  you already have
the abort_on_dmem_zero_access check here.  it'll work in gdb too.

> +sim_step_once (SIM_DESC sd)
> ...
> +	default:
> +	  RAISE_SIGILL ();
> +	  sim_io_eprintf (sd, "Unknown opcode.\n");

RAISE_SIGILL never returns, so this sim_io_eprintf is never shown,
so you might as well delete it

> +SIM_DESC
> +sim_open (SIM_OPEN_KIND kind, host_callback *cb,
> +	  struct bfd *abfd, char * const *argv)
> ...
> +  sim_do_commandf (sd, "memory-region 0x%x,0x%x",
> +		   0,
> +		   DMEM_DEFAULT_SIZE);
> +  sim_do_commandf (sd, "memory-region 0x%x,0x%x",
> +		   0x20000000,
> +		   IMEM_DEFAULT_SIZE);

in other sims, we check the memory map before we add this

  /* 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)
    {
      ...do the sim_do_commandf call...
    }

> --- /dev/null
> +++ b/sim/pru/pru.h
>
> +/* (void)0 is a guard against using RD as a left-hand side value.  */
> +#define RD      (void)0; rd_is_modified = 1; _RDVAL

the standard way to handle (void)0 is with a do{...}while(0) loop

looks like you want to make a helper call macro anyways.  something like
#define FOO(x) do { ...; _RDVAL = x; } while (0)

also, RD depends on _RDVAL which only exists inside a single func.
this should be moved to interp.c i think for the one user.

> +#define PC		(cpu->pru_cpu.pc)

use CPU ?

> +#define PC_byteaddr	((cpu->pru_cpu.pc << 2) | PC_ADDR_SPACE_MARKER)

use PC ?

> +#define DO_SYSCALL()	pru_sim_syscall(sd, cpu)

you use this once.  doesn't seem like a good use of a define.
i.e. delete this and inline the code in the one call site.

> +#define RAISE_SIGILL()	sim_engine_halt (sd, NULL, NULL, PC_byteaddr, \
> +					 sim_signalled, SIM_SIGILL);
> +#define RAISE_SIGINT()	sim_engine_halt (sd, NULL, NULL, PC_byteaddr, \
> +					 sim_signalled, SIM_SIGINT);

shouldn't you pass in cpu here ?

drop the semi-colons too

> +#define NUM_REGS 	33

you've got a space then a tab.  you should fix that.

> +#define PCREG_NUM	32
> +#define INST_SIZE 	4

you aren't using these.  delete them ?

> +/* Number of cycles spent for memory access.  No distinction is currently
> +   made between SRAM, DRAM and generic L3 slaves.  */
> +#define MEM_ACCESS_CYCLES 2

you only use this once.  does it need to be a define ?

> --- /dev/null
> +++ b/sim/pru/pru.isa
>
> +INSTRUCTION (xchg,
> +	     fprintf (stderr, "XCHG instruction not supported by sim\n");
> +	     RAISE_SIGILL ())
> +
> +INSTRUCTION (sxin,
> +	     fprintf (stderr, "SXIN instruction not supported by sim\n");
> +	     RAISE_SIGILL ())
> +
> +INSTRUCTION (sxout,
> +	     fprintf (stderr, "SXOUT instruction not supported by sim\n");
> +	     RAISE_SIGILL ())
> +
> +INSTRUCTION (sxchg,
> +	     fprintf (stderr, "SXCHG instruction not supported by sim\n");
> +	     RAISE_SIGILL ())

you should use sim_io_eprintf instead of fprintf
-mike

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/2] PRU Simulator port
  2017-02-13  5:36 ` Mike Frysinger
@ 2017-02-14 21:25   ` Dimitar Dimitrov
  0 siblings, 0 replies; 7+ messages in thread
From: Dimitar Dimitrov @ 2017-02-14 21:25 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: gdb-patches

Hi Mike,

Thank you for the review.

On понеделник, 13 февруари 2017 г. 0:36:09 EET Mike Frysinger wrote:
> On 27 Dec 2016 23:25, Dimitar Dimitrov wrote:
> > The corresponding libgloss changes have not yet been mainlined.
> > The PRU patches are available here:
> > https://github.com/dinuxbg/gnupru/tree/for-next/patches/newlib-cygwin
> 
> have you sent them to the mailing list ?  i don't see them ...
> 	https://sourceware.org/ml/newlib/
I have not sent the newlib patches yet. My understanding is that I should first 
mainline binutils and simulator, then GCC, and finally newlib.

...
> > --- /dev/null
> > +++ b/sim/pru/pru.h
> > 
> > +/* (void)0 is a guard against using RD as a left-hand side value.  */
> > +#define RD      (void)0; rd_is_modified = 1; _RDVAL
> 
> the standard way to handle (void)0 is with a do{...}while(0) loop
I'll do it.

> 
> looks like you want to make a helper call macro anyways.  something like
> #define FOO(x) do { ...; _RDVAL = x; } while (0)
My intention was to keep pru.isa simple and clear, resembling an ISA 
specification. Compare
    RD = RS1 & OP2
to
   STORE_RD (RS1 & OP2)
> 
> also, RD depends on _RDVAL which only exists inside a single func.
> this should be moved to interp.c i think for the one user.
I'll do it.
> 

Regards,
Dimitar

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-02-14 21:25 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-27 21:26 [PATCH v2 1/2] PRU Simulator port Dimitar Dimitrov
2016-12-27 21:26 ` [PATCH v2 2/2] Add testsuite for the PRU simulator port Dimitar Dimitrov
2017-02-13  5:36   ` Mike Frysinger
2017-01-14  7:05 ` [PATCH v2 1/2] PRU Simulator port Dimitar Dimitrov
2017-02-11 18:35 ` [PING] " Dimitar Dimitrov
2017-02-13  5:36 ` Mike Frysinger
2017-02-14 21:25   ` Dimitar Dimitrov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).