mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-24 02:24:46 +08:00
sim: example-synacor: a simple implementation for reference
Provide a simple example simulator for people porting to new targets to use as a reference. This one has the advantage of being used by people and having a fun program available for it. It doesn't require a special target -- the example simulators can be built for any existing port.
This commit is contained in:
parent
a389375f5b
commit
26da232cbd
@ -1,3 +1,8 @@
|
||||
2021-04-03 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* configure.ac: Add --example-sims option.
|
||||
* configure: Regenerate.
|
||||
|
||||
2021-04-03 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* Makefile.am (check_PROGRAMS, CLEANFILES, DISTCLEANFILES): Define.
|
||||
|
16
sim/configure
vendored
16
sim/configure
vendored
@ -744,6 +744,7 @@ enable_maintainer_mode
|
||||
enable_dependency_tracking
|
||||
enable_silent_rules
|
||||
enable_sim
|
||||
enable_example_sims
|
||||
enable_targets
|
||||
'
|
||||
ac_precious_vars='build_alias
|
||||
@ -785,7 +786,8 @@ sh
|
||||
erc32
|
||||
ppc
|
||||
ft32
|
||||
v850'
|
||||
v850
|
||||
example-synacor'
|
||||
|
||||
# Initialize some variables set by options.
|
||||
ac_init_help=
|
||||
@ -1414,6 +1416,7 @@ Optional Features:
|
||||
--enable-silent-rules less verbose build output (undo: "make V=1")
|
||||
--disable-silent-rules verbose build output (undo: "make V=0")
|
||||
--enable-sim Enable the GNU simulator
|
||||
--enable-example-sims enable example GNU simulators
|
||||
--enable-targets alternative target configurations
|
||||
|
||||
Some influential environment variables:
|
||||
@ -4832,6 +4835,12 @@ esac
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --enable-example-sims was given.
|
||||
if test "${enable_example_sims+set}" = set; then :
|
||||
enableval=$enable_example_sims;
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --enable-targets was given.
|
||||
if test "${enable_targets+set}" = set; then :
|
||||
enableval=$enable_targets; case "${enableval}" in
|
||||
@ -5227,6 +5236,11 @@ subdirs="$subdirs aarch64"
|
||||
esac
|
||||
|
||||
done
|
||||
|
||||
if test "x${enable_example_sims}" = xyes; then
|
||||
subdirs="$subdirs example-synacor"
|
||||
|
||||
fi
|
||||
fi
|
||||
if test "$sim_igen" = "yes"; then
|
||||
SIM_ENABLE_IGEN_TRUE=
|
||||
|
@ -19,6 +19,10 @@ yes | no) ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} given for --enable-sim option) ;;
|
||||
esac])
|
||||
|
||||
AC_ARG_ENABLE([example-sims],
|
||||
[AC_HELP_STRING([--enable-example-sims],
|
||||
[enable example GNU simulators])])
|
||||
|
||||
AC_ARG_ENABLE(targets,
|
||||
[ --enable-targets alternative target configurations],
|
||||
[case "${enableval}" in
|
||||
@ -85,6 +89,10 @@ if test "${enable_sim}" != no; then
|
||||
SIM_TARGET([ft32-*-*], [ft32])
|
||||
SIM_TARGET([v850*-*-*], [v850], [sim_igen=yes])
|
||||
done
|
||||
|
||||
if test "x${enable_example_sims}" = xyes; then
|
||||
AC_CONFIG_SUBDIRS(example-synacor)
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL([SIM_ENABLE_IGEN], [test "$sim_igen" = "yes"])
|
||||
|
||||
|
5
sim/example-synacor/ChangeLog
Normal file
5
sim/example-synacor/ChangeLog
Normal file
@ -0,0 +1,5 @@
|
||||
2021-04-03 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* configure.ac, interp.c, Makefile.in, README, README.arch-spec,
|
||||
sim-main.c, sim-main.h: New files for example simulator.
|
||||
* aclocal.m4, config.in, configure: Regenerated.
|
26
sim/example-synacor/Makefile.in
Normal file
26
sim/example-synacor/Makefile.in
Normal file
@ -0,0 +1,26 @@
|
||||
# Makefile template for Configure for the example synacor simulator.
|
||||
# Copyright (C) 2005-2021 Free Software Foundation, Inc.
|
||||
# Written by Mike Frysinger <vapier@gentoo.org>
|
||||
#
|
||||
# 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) \
|
||||
sim-resume.o \
|
||||
interp.o \
|
||||
sim-main.o
|
||||
|
||||
## COMMON_POST_CONFIG_FRAG
|
15
sim/example-synacor/README
Normal file
15
sim/example-synacor/README
Normal file
@ -0,0 +1,15 @@
|
||||
= OVERVIEW =
|
||||
|
||||
The Synacor Challenge is a fun programming exercise with a number of puzzles
|
||||
built into it. You can find more details about it here:
|
||||
https://challenge.synacor.com/
|
||||
|
||||
The first puzzle is writing an interpreter for their custom ISA. This is a
|
||||
simulator for that custom CPU. The CPU is quite basic: it's 16-bit with only
|
||||
8 registers and a limited set of instructions. This means the port will never
|
||||
grow new features. See README.arch-spec for more details.
|
||||
|
||||
Implementing it here ends up being quite useful: it acts as a simple constrained
|
||||
"real world" example for people who want to implement a new simulator for their
|
||||
own architecture. We demonstrate all the basic fundamentals (registers, memory,
|
||||
branches, and tracing) that all ports should have.
|
73
sim/example-synacor/README.arch-spec
Normal file
73
sim/example-synacor/README.arch-spec
Normal file
@ -0,0 +1,73 @@
|
||||
== architecture ==
|
||||
- three storage regions
|
||||
- memory with 15-bit address space storing 16-bit values
|
||||
- eight registers
|
||||
- an unbounded stack which holds individual 16-bit values
|
||||
- all numbers are unsigned integers 0..32767 (15-bit)
|
||||
- all math is modulo 32768; 32758 + 15 => 5
|
||||
|
||||
== binary format ==
|
||||
- each number is stored as a 16-bit little-endian pair (low byte, high byte)
|
||||
- numbers 0..32767 mean a literal value
|
||||
- numbers 32768..32775 instead mean registers 0..7
|
||||
- numbers 32776..65535 are invalid
|
||||
- programs are loaded into memory starting at address 0
|
||||
- address 0 is the first 16-bit value, address 1 is the second 16-bit value, etc
|
||||
|
||||
== execution ==
|
||||
- After an operation is executed, the next instruction to read is immediately after the last argument of the current operation.
|
||||
If a jump was performed, the next operation is instead the exact destination of the jump.
|
||||
- Encountering a register as an operation argument should be taken as reading from the register or setting into the register as appropriate.
|
||||
|
||||
== hints ==
|
||||
- Start with operations 0, 19, and 21.
|
||||
- Here's a code for the challenge website: jTTockJlJiOC
|
||||
- The program "9,32768,32769,4,19,32768" occupies six memory addresses and should:
|
||||
- Store into register 0 the sum of 4 and the value contained in register 1.
|
||||
- Output to the terminal the character with the ascii code contained in register 0.
|
||||
|
||||
== opcode listing ==
|
||||
halt: 0
|
||||
stop execution and terminate the program
|
||||
set: 1 a b
|
||||
set register <a> to the value of <b>
|
||||
push: 2 a
|
||||
push <a> onto the stack
|
||||
pop: 3 a
|
||||
remove the top element from the stack and write it into <a>; empty stack = error
|
||||
eq: 4 a b c
|
||||
set <a> to 1 if <b> is equal to <c>; set it to 0 otherwise
|
||||
gt: 5 a b c
|
||||
set <a> to 1 if <b> is greater than <c>; set it to 0 otherwise
|
||||
jmp: 6 a
|
||||
jump to <a>
|
||||
jt: 7 a b
|
||||
if <a> is nonzero, jump to <b>
|
||||
jf: 8 a b
|
||||
if <a> is zero, jump to <b>
|
||||
add: 9 a b c
|
||||
assign into <a> the sum of <b> and <c> (modulo 32768)
|
||||
mult: 10 a b c
|
||||
store into <a> the product of <b> and <c> (modulo 32768)
|
||||
mod: 11 a b c
|
||||
store into <a> the remainder of <b> divided by <c>
|
||||
and: 12 a b c
|
||||
stores into <a> the bitwise and of <b> and <c>
|
||||
or: 13 a b c
|
||||
stores into <a> the bitwise or of <b> and <c>
|
||||
not: 14 a b
|
||||
stores 15-bit bitwise inverse of <b> in <a>
|
||||
rmem: 15 a b
|
||||
read memory at address <b> and write it to <a>
|
||||
wmem: 16 a b
|
||||
write the value from <b> into memory at address <a>
|
||||
call: 17 a
|
||||
write the address of the next instruction to the stack and jump to <a>
|
||||
ret: 18
|
||||
remove the top element from the stack and jump to it; empty stack = halt
|
||||
out: 19 a
|
||||
write the character represented by ascii code <a> to the terminal
|
||||
in: 20 a
|
||||
read a character from the terminal and write its ascii code to <a>; it can be assumed that once input starts, it will continue until a newline is encountered; this means that you can safely read whole lines from the keyboard and trust that they will be fully read
|
||||
noop: 21
|
||||
no operation
|
121
sim/example-synacor/aclocal.m4
vendored
Normal file
121
sim/example-synacor/aclocal.m4
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2017 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.
|
||||
|
||||
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
|
||||
# AM_CONDITIONAL -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997-2017 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.
|
||||
|
||||
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
|
||||
# -------------------------------------
|
||||
# Define a conditional.
|
||||
AC_DEFUN([AM_CONDITIONAL],
|
||||
[AC_PREREQ([2.52])dnl
|
||||
m4_if([$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])])
|
||||
|
||||
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
|
||||
# From Jim Meyering
|
||||
|
||||
# Copyright (C) 1996-2017 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.
|
||||
|
||||
# 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 enable maintainer-specific portions of Makefiles])
|
||||
dnl maintainer-mode's default is 'disable' unless 'enable' is passed
|
||||
AC_ARG_ENABLE([maintainer-mode],
|
||||
[AS_HELP_STRING([--]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
|
||||
]
|
||||
)
|
||||
|
||||
# Copyright (C) 2006-2017 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.
|
||||
|
||||
# _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($@)])
|
||||
|
||||
m4_include([../m4/sim_ac_common.m4])
|
||||
m4_include([../m4/sim_ac_option_alignment.m4])
|
||||
m4_include([../m4/sim_ac_option_assert.m4])
|
||||
m4_include([../m4/sim_ac_option_endian.m4])
|
||||
m4_include([../m4/sim_ac_option_environment.m4])
|
||||
m4_include([../m4/sim_ac_option_inline.m4])
|
||||
m4_include([../m4/sim_ac_option_warnings.m4])
|
||||
m4_include([../m4/sim_ac_output.m4])
|
||||
m4_include([../m4/sim_ac_toolchain.m4])
|
||||
m4_include([../../config/acx.m4])
|
||||
m4_include([../../config/depstand.m4])
|
||||
m4_include([../../config/gettext-sister.m4])
|
||||
m4_include([../../config/lead-dot.m4])
|
||||
m4_include([../../config/override.m4])
|
||||
m4_include([../../config/plugins.m4])
|
||||
m4_include([../../config/zlib.m4])
|
||||
m4_include([../../libtool.m4])
|
||||
m4_include([../../ltoptions.m4])
|
||||
m4_include([../../ltsugar.m4])
|
||||
m4_include([../../ltversion.m4])
|
||||
m4_include([../../lt~obsolete.m4])
|
242
sim/example-synacor/config.in
Normal file
242
sim/example-synacor/config.in
Normal file
@ -0,0 +1,242 @@
|
||||
/* 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 <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 `st_atime' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_ATIME
|
||||
|
||||
/* Define to 1 if `st_blksize' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
|
||||
/* Define to 1 if `st_blocks' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_BLOCKS
|
||||
|
||||
/* Define to 1 if `st_ctime' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_CTIME
|
||||
|
||||
/* Define to 1 if `st_dev' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_DEV
|
||||
|
||||
/* Define to 1 if `st_gid' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_GID
|
||||
|
||||
/* Define to 1 if `st_ino' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_INO
|
||||
|
||||
/* Define to 1 if `st_mode' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_MODE
|
||||
|
||||
/* Define to 1 if `st_mtime' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_MTIME
|
||||
|
||||
/* Define to 1 if `st_nlink' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_NLINK
|
||||
|
||||
/* Define to 1 if `st_rdev' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_RDEV
|
||||
|
||||
/* Define to 1 if `st_size' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_SIZE
|
||||
|
||||
/* Define to 1 if `st_uid' is a member of `struct stat'. */
|
||||
#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 `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
|
14333
sim/example-synacor/configure
vendored
Executable file
14333
sim/example-synacor/configure
vendored
Executable file
File diff suppressed because it is too large
Load Diff
10
sim/example-synacor/configure.ac
Normal file
10
sim/example-synacor/configure.ac
Normal file
@ -0,0 +1,10 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(Makefile.in)
|
||||
AC_CONFIG_MACRO_DIRS([../m4 ../.. ../../config])
|
||||
|
||||
SIM_AC_COMMON
|
||||
|
||||
SIM_AC_OPTION_ENDIAN(LITTLE)
|
||||
SIM_AC_OPTION_ALIGNMENT(STRICT_ALIGNMENT,STRICT_ALIGNMENT)
|
||||
|
||||
SIM_AC_OUTPUT
|
176
sim/example-synacor/interp.c
Normal file
176
sim/example-synacor/interp.c
Normal file
@ -0,0 +1,176 @@
|
||||
/* Example synacor simulator.
|
||||
|
||||
Copyright (C) 2005-2021 Free Software Foundation, Inc.
|
||||
Contributed by Mike Frysinger.
|
||||
|
||||
This file is part of simulators.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This file contains the main glue logic between the sim core and the target
|
||||
specific simulator. Normally this file will be kept small and the target
|
||||
details will live in other files.
|
||||
|
||||
For more specific details on these functions, see the gdb/remote-sim.h
|
||||
header file. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sim-main.h"
|
||||
#include "sim-options.h"
|
||||
|
||||
/* This function is the main loop. It should process ticks and decode+execute
|
||||
a single instruction.
|
||||
|
||||
Usually you do not need to change things here. */
|
||||
|
||||
void
|
||||
sim_engine_run (SIM_DESC sd,
|
||||
int next_cpu_nr, /* ignore */
|
||||
int nr_cpus, /* ignore */
|
||||
int siggnal) /* ignore */
|
||||
{
|
||||
SIM_CPU *cpu;
|
||||
|
||||
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
||||
|
||||
cpu = STATE_CPU (sd, 0);
|
||||
|
||||
while (1)
|
||||
{
|
||||
step_once (cpu);
|
||||
if (sim_events_tick (sd))
|
||||
sim_events_process (sd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the simulator from scratch. This is called once per lifetime of
|
||||
the simulation. Think of it as a processor reset.
|
||||
|
||||
Usually all cpu-specific setup is handled in the initialize_cpu callback.
|
||||
If you want to do cpu-independent stuff, then it should go at the end (see
|
||||
where memory is initialized). */
|
||||
|
||||
#define DEFAULT_MEM_SIZE (16 * 1024 * 1024)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
SIM_DESC
|
||||
sim_open (SIM_OPEN_KIND kind, host_callback *callback,
|
||||
struct bfd *abfd, char * const *argv)
|
||||
{
|
||||
char c;
|
||||
int i;
|
||||
SIM_DESC sd = sim_state_alloc (kind, callback);
|
||||
|
||||
/* The cpu data is kept in a separately allocated chunk of memory. */
|
||||
if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
|
||||
{
|
||||
free_state (sd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
|
||||
{
|
||||
free_state (sd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX: Default to the Virtual environment. */
|
||||
if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT)
|
||||
STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Establish any remaining configuration options. */
|
||||
if (sim_config (sd) != SIM_RC_OK)
|
||||
{
|
||||
free_state (sd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sim_post_argv_init (sd) != SIM_RC_OK)
|
||||
{
|
||||
free_state (sd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CPU specific initialization. */
|
||||
for (i = 0; i < MAX_NR_PROCESSORS; ++i)
|
||||
{
|
||||
SIM_CPU *cpu = STATE_CPU (sd, i);
|
||||
|
||||
initialize_cpu (sd, 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-size %#x", DEFAULT_MEM_SIZE);
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
/* Prepare to run a program that has already been loaded into memory.
|
||||
|
||||
Usually you do not need to change things here. */
|
||||
|
||||
SIM_RC
|
||||
sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
|
||||
char * const *argv, char * const *env)
|
||||
{
|
||||
SIM_CPU *cpu = STATE_CPU (sd, 0);
|
||||
sim_cia addr;
|
||||
|
||||
/* Set the PC. */
|
||||
if (abfd != NULL)
|
||||
addr = bfd_get_start_address (abfd);
|
||||
else
|
||||
addr = 0;
|
||||
sim_pc_set (cpu, addr);
|
||||
|
||||
/* Standalone mode (i.e. `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;
|
||||
}
|
530
sim/example-synacor/sim-main.c
Normal file
530
sim/example-synacor/sim-main.c
Normal file
@ -0,0 +1,530 @@
|
||||
/* Example synacor simulator.
|
||||
|
||||
Copyright (C) 2005-2021 Free Software Foundation, Inc.
|
||||
Contributed by Mike Frysinger.
|
||||
|
||||
This file is part of simulators.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This file contains the main simulator decoding logic. i.e. everything that
|
||||
is architecture specific. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sim-main.h"
|
||||
|
||||
/* Get the register number from the number. */
|
||||
static unsigned16
|
||||
register_num (SIM_CPU *cpu, unsigned16 num)
|
||||
{
|
||||
SIM_DESC sd = CPU_STATE (cpu);
|
||||
|
||||
if (num < 0x8000 || num >= 0x8008)
|
||||
sim_engine_halt (sd, cpu, NULL, cpu->pc, sim_signalled, SIM_SIGILL);
|
||||
|
||||
return num & 0xf;
|
||||
}
|
||||
|
||||
/* Helper to process immediates according to the ISA. */
|
||||
static unsigned16
|
||||
interp_num (SIM_CPU *cpu, unsigned16 num)
|
||||
{
|
||||
SIM_DESC sd = CPU_STATE (cpu);
|
||||
|
||||
if (num < 0x8000)
|
||||
{
|
||||
/* Numbers 0..32767 mean a literal value. */
|
||||
TRACE_DECODE (cpu, "%#x is a literal", num);
|
||||
return num;
|
||||
}
|
||||
else if (num < 0x8008)
|
||||
{
|
||||
/* Numbers 32768..32775 instead mean registers 0..7. */
|
||||
TRACE_DECODE (cpu, "%#x is register R%i", num, num & 0xf);
|
||||
return cpu->regs[num & 0xf];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Numbers 32776..65535 are invalid. */
|
||||
TRACE_DECODE (cpu, "%#x is an invalid number", num);
|
||||
sim_engine_halt (sd, cpu, NULL, cpu->pc, sim_signalled, SIM_SIGILL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode & execute a single instruction. */
|
||||
void step_once (SIM_CPU *cpu)
|
||||
{
|
||||
SIM_DESC sd = CPU_STATE (cpu);
|
||||
unsigned16 iw1, num1;
|
||||
sim_cia pc = sim_pc_get (cpu);
|
||||
|
||||
iw1 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc);
|
||||
TRACE_EXTRACT (cpu, "%04x: iw1: %#x", pc, iw1);
|
||||
/* This never happens, but technically is possible in the ISA. */
|
||||
num1 = interp_num (cpu, iw1);
|
||||
|
||||
if (num1 == 0)
|
||||
{
|
||||
/* halt: 0: Stop execution and terminate the program. */
|
||||
TRACE_INSN (cpu, "HALT");
|
||||
sim_engine_halt (sd, cpu, NULL, pc, sim_exited, 0);
|
||||
}
|
||||
else if (num1 == 1)
|
||||
{
|
||||
/* set: 1 a b: Set register <a> to the value of <b>. */
|
||||
unsigned16 iw2, iw3, num2, num3;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = register_num (cpu, iw2);
|
||||
iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
|
||||
num3 = interp_num (cpu, iw3);
|
||||
TRACE_EXTRACT (cpu, "SET %#x %#x", iw2, iw3);
|
||||
TRACE_INSN (cpu, "SET R%i %#x", num2, num3);
|
||||
|
||||
TRACE_REGISTER (cpu, "R%i = %#x", num2, num3);
|
||||
cpu->regs[num2] = num3;
|
||||
|
||||
pc += 6;
|
||||
}
|
||||
else if (num1 == 2)
|
||||
{
|
||||
/* push: 2 a: Push <a> onto the stack. */
|
||||
unsigned16 iw2, num2;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = interp_num (cpu, iw2);
|
||||
TRACE_EXTRACT (cpu, "PUSH %#x", iw2);
|
||||
TRACE_INSN (cpu, "PUSH %#x", num2);
|
||||
|
||||
sim_core_write_aligned_2 (cpu, pc, write_map, cpu->sp, num2);
|
||||
cpu->sp -= 2;
|
||||
TRACE_REGISTER (cpu, "SP = %#x", cpu->sp);
|
||||
|
||||
pc += 4;
|
||||
}
|
||||
else if (num1 == 3)
|
||||
{
|
||||
/* pop: 3 a: Remove the top element from the stack and write it into <a>.
|
||||
Empty stack = error. */
|
||||
unsigned16 iw2, num2, result;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = register_num (cpu, iw2);
|
||||
TRACE_EXTRACT (cpu, "POP %#x", iw2);
|
||||
TRACE_INSN (cpu, "POP R%i", num2);
|
||||
cpu->sp += 2;
|
||||
TRACE_REGISTER (cpu, "SP = %#x", cpu->sp);
|
||||
result = sim_core_read_aligned_2 (cpu, pc, read_map, cpu->sp);
|
||||
|
||||
TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
|
||||
cpu->regs[num2] = result;
|
||||
|
||||
pc += 4;
|
||||
}
|
||||
else if (num1 == 4)
|
||||
{
|
||||
/* eq: 4 a b c: Set <a> to 1 if <b> is equal to <c>; set it to 0
|
||||
otherwise. */
|
||||
unsigned16 iw2, iw3, iw4, num2, num3, num4, result;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = register_num (cpu, iw2);
|
||||
iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
|
||||
num3 = interp_num (cpu, iw3);
|
||||
iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
|
||||
num4 = interp_num (cpu, iw4);
|
||||
result = (num3 == num4);
|
||||
TRACE_EXTRACT (cpu, "EQ %#x %#x %#x", iw2, iw3, iw4);
|
||||
TRACE_INSN (cpu, "EQ R%i %#x %#x", num2, num3, num4);
|
||||
TRACE_DECODE (cpu, "R%i = (%#x == %#x) = %i", num2, num3, num4, result);
|
||||
|
||||
TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
|
||||
cpu->regs[num2] = result;
|
||||
|
||||
pc += 8;
|
||||
}
|
||||
else if (num1 == 5)
|
||||
{
|
||||
/* gt: 5 a b c: Set <a> to 1 if <b> is greater than <c>; set it to 0
|
||||
otherwise. */
|
||||
unsigned16 iw2, iw3, iw4, num2, num3, num4, result;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = register_num (cpu, iw2);
|
||||
iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
|
||||
num3 = interp_num (cpu, iw3);
|
||||
iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
|
||||
num4 = interp_num (cpu, iw4);
|
||||
result = (num3 > num4);
|
||||
TRACE_EXTRACT (cpu, "GT %#x %#x %#x", iw2, iw3, iw4);
|
||||
TRACE_INSN (cpu, "GT R%i %#x %#x", num2, num3, num4);
|
||||
TRACE_DECODE (cpu, "R%i = (%#x > %#x) = %i", num2, num3, num4, result);
|
||||
|
||||
TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
|
||||
cpu->regs[num2] = result;
|
||||
|
||||
pc += 8;
|
||||
}
|
||||
else if (num1 == 6)
|
||||
{
|
||||
/* jmp: 6 a: Jump to <a>. */
|
||||
unsigned16 iw2, num2;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = interp_num (cpu, iw2);
|
||||
/* Addresses are 16-bit aligned. */
|
||||
num2 <<= 1;
|
||||
TRACE_EXTRACT (cpu, "JMP %#x", iw2);
|
||||
TRACE_INSN (cpu, "JMP %#x", num2);
|
||||
|
||||
pc = num2;
|
||||
TRACE_BRANCH (cpu, "JMP %#x", pc);
|
||||
}
|
||||
else if (num1 == 7)
|
||||
{
|
||||
/* jt: 7 a b: If <a> is nonzero, jump to <b>. */
|
||||
unsigned16 iw2, iw3, num2, num3;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = interp_num (cpu, iw2);
|
||||
iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
|
||||
num3 = interp_num (cpu, iw3);
|
||||
/* Addresses are 16-bit aligned. */
|
||||
num3 <<= 1;
|
||||
TRACE_EXTRACT (cpu, "JT %#x %#x", iw2, iw3);
|
||||
TRACE_INSN (cpu, "JT %#x %#x", num2, num3);
|
||||
TRACE_DECODE (cpu, "JT %#x != 0 -> %s", num2, num2 ? "taken" : "nop");
|
||||
|
||||
if (num2)
|
||||
{
|
||||
pc = num3;
|
||||
TRACE_BRANCH (cpu, "JT %#x", pc);
|
||||
}
|
||||
else
|
||||
pc += 6;
|
||||
}
|
||||
else if (num1 == 8)
|
||||
{
|
||||
/* jf: 8 a b: If <a> is zero, jump to <b>. */
|
||||
unsigned16 iw2, iw3, num2, num3;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = interp_num (cpu, iw2);
|
||||
iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
|
||||
num3 = interp_num (cpu, iw3);
|
||||
/* Addresses are 16-bit aligned. */
|
||||
num3 <<= 1;
|
||||
TRACE_EXTRACT (cpu, "JF %#x %#x", iw2, iw3);
|
||||
TRACE_INSN (cpu, "JF %#x %#x", num2, num3);
|
||||
TRACE_DECODE (cpu, "JF %#x == 0 -> %s", num2, num2 ? "nop" : "taken");
|
||||
|
||||
if (!num2)
|
||||
{
|
||||
pc = num3;
|
||||
TRACE_BRANCH (cpu, "JF %#x", pc);
|
||||
}
|
||||
else
|
||||
pc += 6;
|
||||
}
|
||||
else if (num1 == 9)
|
||||
{
|
||||
/* add: 9 a b c: Assign <a> the sum of <b> and <c> (modulo 32768). */
|
||||
unsigned16 iw2, iw3, iw4, num2, num3, num4, result;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = register_num (cpu, iw2);
|
||||
iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
|
||||
num3 = interp_num (cpu, iw3);
|
||||
iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
|
||||
num4 = interp_num (cpu, iw4);
|
||||
result = (num3 + num4) % 32768;
|
||||
TRACE_EXTRACT (cpu, "ADD %#x %#x %#x", iw2, iw3, iw4);
|
||||
TRACE_INSN (cpu, "ADD R%i %#x %#x", num2, num3, num4);
|
||||
TRACE_DECODE (cpu, "R%i = (%#x + %#x) %% %i = %#x", num2, num3, num4,
|
||||
32768, result);
|
||||
|
||||
TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
|
||||
cpu->regs[num2] = result;
|
||||
|
||||
pc += 8;
|
||||
}
|
||||
else if (num1 == 10)
|
||||
{
|
||||
/* mult: 10 a b c: Store into <a> the product of <b> and <c> (modulo
|
||||
32768). */
|
||||
unsigned16 iw2, iw3, iw4, num2, num3, num4, result;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = register_num (cpu, iw2);
|
||||
iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
|
||||
num3 = interp_num (cpu, iw3);
|
||||
iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
|
||||
num4 = interp_num (cpu, iw4);
|
||||
result = (num3 * num4) % 32768;
|
||||
TRACE_EXTRACT (cpu, "MULT %#x %#x %#x", iw2, iw3, iw4);
|
||||
TRACE_INSN (cpu, "MULT R%i %#x %#x", num2, num3, num4);
|
||||
TRACE_DECODE (cpu, "R%i = (%#x * %#x) %% %i = %#x", num2, num3, num4,
|
||||
32768, result);
|
||||
|
||||
TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
|
||||
cpu->regs[num2] = result;
|
||||
|
||||
pc += 8;
|
||||
}
|
||||
else if (num1 == 11)
|
||||
{
|
||||
/* mod: 11 a b c: Store into <a> the remainder of <b> divided by <c>. */
|
||||
unsigned16 iw2, iw3, iw4, num2, num3, num4, result;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = register_num (cpu, iw2);
|
||||
iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
|
||||
num3 = interp_num (cpu, iw3);
|
||||
iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
|
||||
num4 = interp_num (cpu, iw4);
|
||||
result = num3 % num4;
|
||||
TRACE_EXTRACT (cpu, "MOD %#x %#x %#x", iw2, iw3, iw4);
|
||||
TRACE_INSN (cpu, "MOD R%i %#x %#x", num2, num3, num4);
|
||||
TRACE_DECODE (cpu, "R%i = %#x %% %#x = %#x", num2, num3, num4, result);
|
||||
|
||||
TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
|
||||
cpu->regs[num2] = result;
|
||||
|
||||
pc += 8;
|
||||
}
|
||||
else if (num1 == 12)
|
||||
{
|
||||
/* and: 12 a b c: Stores into <a> the bitwise and of <b> and <c>. */
|
||||
unsigned16 iw2, iw3, iw4, num2, num3, num4, result;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = register_num (cpu, iw2);
|
||||
iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
|
||||
num3 = interp_num (cpu, iw3);
|
||||
iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
|
||||
num4 = interp_num (cpu, iw4);
|
||||
result = (num3 & num4);
|
||||
TRACE_EXTRACT (cpu, "AND %#x %#x %#x", iw2, iw3, iw4);
|
||||
TRACE_INSN (cpu, "AND R%i %#x %#x", num2, num3, num4);
|
||||
TRACE_DECODE (cpu, "R%i = %#x & %#x = %#x", num2, num3, num4, result);
|
||||
|
||||
TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
|
||||
cpu->regs[num2] = result;
|
||||
|
||||
pc += 8;
|
||||
}
|
||||
else if (num1 == 13)
|
||||
{
|
||||
/* or: 13 a b c: Stores into <a> the bitwise or of <b> and <c>. */
|
||||
unsigned16 iw2, iw3, iw4, num2, num3, num4, result;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = register_num (cpu, iw2);
|
||||
iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
|
||||
num3 = interp_num (cpu, iw3);
|
||||
iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
|
||||
num4 = interp_num (cpu, iw4);
|
||||
result = (num3 | num4);
|
||||
TRACE_EXTRACT (cpu, "OR %#x %#x %#x", iw2, iw3, iw4);
|
||||
TRACE_INSN (cpu, "OR R%i %#x %#x", num2, num3, num4);
|
||||
TRACE_DECODE (cpu, "R%i = %#x | %#x = %#x", num2, num3, num4, result);
|
||||
|
||||
TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
|
||||
cpu->regs[num2] = result;
|
||||
|
||||
pc += 8;
|
||||
}
|
||||
else if (num1 == 14)
|
||||
{
|
||||
/* not: 14 a b: Stores 15-bit bitwise inverse of <b> in <a>. */
|
||||
unsigned16 iw2, iw3, num2, num3, result;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = register_num (cpu, iw2);
|
||||
iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
|
||||
num3 = interp_num (cpu, iw3);
|
||||
result = (~num3) & 0x7fff;
|
||||
TRACE_EXTRACT (cpu, "NOT %#x %#x", iw2, iw3);
|
||||
TRACE_INSN (cpu, "NOT R%i %#x", num2, num3);
|
||||
TRACE_DECODE (cpu, "R%i = (~%#x) & 0x7fff = %#x", num2, num3, result);
|
||||
|
||||
TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
|
||||
cpu->regs[num2] = result;
|
||||
|
||||
pc += 6;
|
||||
}
|
||||
else if (num1 == 15)
|
||||
{
|
||||
/* rmem: 15 a b: Read memory at address <b> and write it to <a>. */
|
||||
unsigned16 iw2, iw3, num2, num3, result;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = register_num (cpu, iw2);
|
||||
iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
|
||||
num3 = interp_num (cpu, iw3);
|
||||
/* Addresses are 16-bit aligned. */
|
||||
num3 <<= 1;
|
||||
TRACE_EXTRACT (cpu, "RMEM %#x %#x", iw2, iw3);
|
||||
TRACE_INSN (cpu, "RMEM R%i %#x", num2, num3);
|
||||
|
||||
TRACE_MEMORY (cpu, "reading %#x", num3);
|
||||
result = sim_core_read_aligned_2 (cpu, pc, read_map, num3);
|
||||
|
||||
TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
|
||||
cpu->regs[num2] = result;
|
||||
|
||||
pc += 6;
|
||||
}
|
||||
else if (num1 == 16)
|
||||
{
|
||||
/* wmem: 16 a b: Write the value from <b> into memory at address <a>. */
|
||||
unsigned16 iw2, iw3, num2, num3;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = interp_num (cpu, iw2);
|
||||
iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
|
||||
num3 = interp_num (cpu, iw3);
|
||||
/* Addresses are 16-bit aligned. */
|
||||
num2 <<= 1;
|
||||
TRACE_EXTRACT (cpu, "WMEM %#x %#x", iw2, iw3);
|
||||
TRACE_INSN (cpu, "WMEM %#x %#x", num2, num3);
|
||||
|
||||
TRACE_MEMORY (cpu, "writing %#x to %#x", num3, num2);
|
||||
sim_core_write_aligned_2 (cpu, pc, write_map, num2, num3);
|
||||
|
||||
pc += 6;
|
||||
}
|
||||
else if (num1 == 17)
|
||||
{
|
||||
/* call: 17 a: Write the address of the next instruction to the stack and
|
||||
jump to <a>. */
|
||||
unsigned16 iw2, num2;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = interp_num (cpu, iw2);
|
||||
/* Addresses are 16-bit aligned. */
|
||||
num2 <<= 1;
|
||||
TRACE_EXTRACT (cpu, "CALL %#x", iw2);
|
||||
TRACE_INSN (cpu, "CALL %#x", num2);
|
||||
|
||||
TRACE_MEMORY (cpu, "pushing %#x onto stack", (pc + 4) >> 1);
|
||||
sim_core_write_aligned_2 (cpu, pc, write_map, cpu->sp, (pc + 4) >> 1);
|
||||
cpu->sp -= 2;
|
||||
TRACE_REGISTER (cpu, "SP = %#x", cpu->sp);
|
||||
|
||||
pc = num2;
|
||||
TRACE_BRANCH (cpu, "CALL %#x", pc);
|
||||
}
|
||||
else if (num1 == 18)
|
||||
{
|
||||
/* ret: 18: Remove the top element from the stack and jump to it; empty
|
||||
stack = halt. */
|
||||
unsigned16 result;
|
||||
|
||||
TRACE_INSN (cpu, "RET");
|
||||
cpu->sp += 2;
|
||||
TRACE_REGISTER (cpu, "SP = %#x", cpu->sp);
|
||||
result = sim_core_read_aligned_2 (cpu, pc, read_map, cpu->sp);
|
||||
TRACE_MEMORY (cpu, "popping %#x off of stack", result << 1);
|
||||
|
||||
pc = result << 1;
|
||||
TRACE_BRANCH (cpu, "RET -> %#x", pc);
|
||||
}
|
||||
else if (num1 == 19)
|
||||
{
|
||||
/* out: 19 a: Write the character <a> to the terminal. */
|
||||
unsigned16 iw2, num2;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = interp_num (cpu, iw2);
|
||||
TRACE_EXTRACT (cpu, "OUT %#x", iw2);
|
||||
TRACE_INSN (cpu, "OUT %#x", num2);
|
||||
TRACE_EVENTS (cpu, "write to stdout: %#x (%c)", num2, num2);
|
||||
|
||||
sim_io_printf (sd, "%c", num2);
|
||||
|
||||
pc += 4;
|
||||
}
|
||||
else if (num1 == 20)
|
||||
{
|
||||
/* in: 20 a: read a character from the terminal and write its ascii code
|
||||
to <a>. It can be assumed that once input starts, it will continue
|
||||
until a newline is encountered. This means that you can safely read
|
||||
lines from the keyboard and trust that they will be fully read. */
|
||||
unsigned16 iw2, num2;
|
||||
char c;
|
||||
|
||||
iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
|
||||
num2 = register_num (cpu, iw2);
|
||||
TRACE_EXTRACT (cpu, "IN %#x", iw2);
|
||||
TRACE_INSN (cpu, "IN %#x", num2);
|
||||
sim_io_read_stdin (sd, &c, 1);
|
||||
TRACE_EVENTS (cpu, "read from stdin: %#x (%c)", c, c);
|
||||
|
||||
/* The challenge uses lowercase for all inputs, so insert some low level
|
||||
helpers of our own to make it a bit nicer. */
|
||||
switch (c)
|
||||
{
|
||||
case 'Q':
|
||||
sim_engine_halt (sd, cpu, NULL, pc, sim_exited, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE_REGISTER (cpu, "R%i = %#x", iw2 & 0xf, c);
|
||||
cpu->regs[iw2 & 0xf] = c;
|
||||
|
||||
pc += 4;
|
||||
}
|
||||
else if (num1 == 21)
|
||||
{
|
||||
/* noop: 21: no operation */
|
||||
TRACE_INSN (cpu, "NOOP");
|
||||
|
||||
pc += 2;
|
||||
}
|
||||
else
|
||||
sim_engine_halt (sd, cpu, NULL, pc, sim_signalled, SIM_SIGILL);
|
||||
|
||||
TRACE_REGISTER (cpu, "PC = %#x", pc);
|
||||
sim_pc_set (cpu, pc);
|
||||
}
|
||||
|
||||
/* Return the program counter for this cpu. */
|
||||
static sim_cia
|
||||
pc_get (sim_cpu *cpu)
|
||||
{
|
||||
return cpu->pc;
|
||||
}
|
||||
|
||||
/* Set the program counter for this cpu to the new pc value. */
|
||||
static void
|
||||
pc_set (sim_cpu *cpu, sim_cia pc)
|
||||
{
|
||||
cpu->pc = pc;
|
||||
}
|
||||
|
||||
/* Initialize the state for a single cpu. Usuaully this involves clearing all
|
||||
registers back to their reset state. Should also hook up the fetch/store
|
||||
helper functions too. */
|
||||
void initialize_cpu (SIM_DESC sd, SIM_CPU *cpu)
|
||||
{
|
||||
memset (cpu->regs, 0, sizeof (cpu->regs));
|
||||
cpu->pc = 0;
|
||||
/* Make sure it's initialized outside of the 16-bit address space. */
|
||||
cpu->sp = 0x80000;
|
||||
|
||||
CPU_PC_FETCH (cpu) = pc_get;
|
||||
CPU_PC_STORE (cpu) = pc_set;
|
||||
}
|
49
sim/example-synacor/sim-main.h
Normal file
49
sim/example-synacor/sim-main.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* Example synacor simulator.
|
||||
|
||||
Copyright (C) 2005-2021 Free Software Foundation, Inc.
|
||||
Contributed by Mike Frysinger.
|
||||
|
||||
This file is part of simulators.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef SIM_MAIN_H
|
||||
#define SIM_MAIN_H
|
||||
|
||||
#include "sim-basics.h"
|
||||
#include "sim-base.h"
|
||||
|
||||
struct _sim_cpu {
|
||||
/* ... simulator specific members ... */
|
||||
unsigned16 regs[8];
|
||||
sim_cia pc;
|
||||
|
||||
/* This isn't a real register, and the stack is not directly addressable,
|
||||
so use memory outside of the 16-bit address space. */
|
||||
unsigned32 sp;
|
||||
|
||||
sim_cpu_base base;
|
||||
};
|
||||
|
||||
struct sim_state {
|
||||
sim_cpu *cpu[MAX_NR_PROCESSORS];
|
||||
|
||||
/* ... simulator specific members ... */
|
||||
sim_state_base base;
|
||||
};
|
||||
|
||||
extern void step_once (SIM_CPU *);
|
||||
extern void initialize_cpu (SIM_DESC, SIM_CPU *);
|
||||
|
||||
#endif
|
@ -1,3 +1,7 @@
|
||||
2021-04-03 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* lib/sim-defs.exp (run_sim_test): Convert examples to binaries.
|
||||
|
||||
2021-04-03 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* local.mk: Include %D%/common/local.mk.
|
||||
|
5
sim/testsuite/example-synacor/ChangeLog
Normal file
5
sim/testsuite/example-synacor/ChangeLog
Normal file
@ -0,0 +1,5 @@
|
||||
2021-04-03 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* add.s, allinsn.exp, and.s, call.s, exit-0.s, gt.s, isa.inc, jmp.s,
|
||||
mem.s, mod.s, mult.s, not.s, or.s, push-pop.s, ret.s, set.s,
|
||||
testutils.inc: New files.
|
24
sim/testsuite/example-synacor/add.s
Normal file
24
sim/testsuite/example-synacor/add.s
Normal file
@ -0,0 +1,24 @@
|
||||
# check the ADD insn.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
JMP 3
|
||||
HALT
|
||||
|
||||
SET r2, 2
|
||||
ADD r2, r2, r2
|
||||
EQ r3, r2, 4
|
||||
JF r3, 2
|
||||
|
||||
ADD r1, 100, r2
|
||||
EQ r4, r1, 104
|
||||
JF r4, 2
|
||||
|
||||
# 0x7ffe == -2
|
||||
ADD r0, r1, 0x7ffe
|
||||
EQ r4, r0, 102
|
||||
JF r4, 2
|
||||
|
||||
pass
|
19
sim/testsuite/example-synacor/allinsn.exp
Normal file
19
sim/testsuite/example-synacor/allinsn.exp
Normal file
@ -0,0 +1,19 @@
|
||||
# Example synacor simulator testsuite.
|
||||
|
||||
if [istarget *] {
|
||||
# Used to locate the `run` program.
|
||||
global arch
|
||||
set arch "example-synacor"
|
||||
|
||||
# All machines.
|
||||
set all_machs "example"
|
||||
|
||||
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
|
||||
}
|
||||
}
|
18
sim/testsuite/example-synacor/and.s
Normal file
18
sim/testsuite/example-synacor/and.s
Normal file
@ -0,0 +1,18 @@
|
||||
# check the AND insn.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
JMP 3
|
||||
HALT
|
||||
|
||||
AND r2, 0xfff, 0x7f0c
|
||||
EQ r3, r2, 0xf0c
|
||||
JF r3, 2
|
||||
|
||||
AND r2, r2, 0xf
|
||||
EQ r3, r2, 0xc
|
||||
JF r3, 2
|
||||
|
||||
pass
|
14
sim/testsuite/example-synacor/call.s
Normal file
14
sim/testsuite/example-synacor/call.s
Normal file
@ -0,0 +1,14 @@
|
||||
# check the CALL insn.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
CALL 3
|
||||
HALT
|
||||
|
||||
POP r0
|
||||
EQ r1, r0, 2
|
||||
JF r1, 2
|
||||
|
||||
pass
|
10
sim/testsuite/example-synacor/exit-0.s
Normal file
10
sim/testsuite/example-synacor/exit-0.s
Normal file
@ -0,0 +1,10 @@
|
||||
# check that the sim doesn't die immediately.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
NOOP
|
||||
NOOP
|
||||
NOOP
|
||||
pass
|
31
sim/testsuite/example-synacor/gt.s
Normal file
31
sim/testsuite/example-synacor/gt.s
Normal file
@ -0,0 +1,31 @@
|
||||
# check the GT insn.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
JMP 3
|
||||
HALT
|
||||
|
||||
GT r0, 3, 2
|
||||
EQ r1, r0, 1
|
||||
JF r1, 2
|
||||
|
||||
GT r0, 2, 2
|
||||
EQ r1, r0, 0
|
||||
JF r1, 2
|
||||
|
||||
GT r0, 1, 2
|
||||
EQ r1, r0, 0
|
||||
JF r1, 2
|
||||
|
||||
SET r2, 3
|
||||
SET r3, 4
|
||||
GT r0, r2, r3
|
||||
EQ r1, r0, 0
|
||||
JF r1, 2
|
||||
GT r0, r3, r2
|
||||
EQ r1, r0, 1
|
||||
JF r1, 2
|
||||
|
||||
pass
|
108
sim/testsuite/example-synacor/isa.inc
Normal file
108
sim/testsuite/example-synacor/isa.inc
Normal file
@ -0,0 +1,108 @@
|
||||
# Macros for the fake ISA. Keep in sync with example-synacor/README.arch-spec.
|
||||
|
||||
# These .set macros will generate symbols in the output ELF, but it also allows
|
||||
# use to use them as arguments to the insns below. Oh well.
|
||||
.set r0, 32768
|
||||
.set r1, r0+1
|
||||
.set r2, r0+2
|
||||
.set r3, r0+3
|
||||
.set r4, r0+4
|
||||
.set r5, r0+5
|
||||
.set r6, r0+6
|
||||
.set r7, r0+7
|
||||
|
||||
# The target is little endian, so make sure we output the 16-bit words as such.
|
||||
.macro _op op:req, more:vararg
|
||||
.byte \op & 0xff, (\op >> 8) & 0xff
|
||||
.ifnb \more
|
||||
_op \more
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro HALT
|
||||
_op 0
|
||||
.endm
|
||||
|
||||
.macro SET a:req, b:req
|
||||
_op 1, \a, \b
|
||||
.endm
|
||||
|
||||
.macro PUSH a:req
|
||||
_op 2, \a
|
||||
.endm
|
||||
|
||||
.macro POP a:req
|
||||
_op 3, \a
|
||||
.endm
|
||||
|
||||
.macro EQ a:req, b:req, c:req
|
||||
_op 4, \a, \b, \c
|
||||
.endm
|
||||
|
||||
.macro GT a:req, b:req, c:req
|
||||
_op 5, \a, \b, \c
|
||||
.endm
|
||||
|
||||
.macro JMP a:req
|
||||
_op 6, \a
|
||||
.endm
|
||||
|
||||
.macro JT a:req, b:req
|
||||
_op 7, \a, \b
|
||||
.endm
|
||||
|
||||
.macro JF a:req, b:req
|
||||
_op 8, \a, \b
|
||||
.endm
|
||||
|
||||
.macro ADD a:req, b:req, c:req
|
||||
_op 9, \a, \b, \c
|
||||
.endm
|
||||
|
||||
.macro MULT a:req, b:req, c:req
|
||||
_op 10, \a, \b, \c
|
||||
.endm
|
||||
|
||||
.macro MOD a:req, b:req, c:req
|
||||
_op 11, \a, \b, \c
|
||||
.endm
|
||||
|
||||
.macro AND a:req, b:req, c:req
|
||||
_op 12, \a, \b, \c
|
||||
.endm
|
||||
|
||||
.macro OR a:req, b:req, c:req
|
||||
_op 13, \a, \b, \c
|
||||
.endm
|
||||
|
||||
.macro NOT a:req, b:req
|
||||
_op 14, \a, \b
|
||||
.endm
|
||||
|
||||
.macro RMEM a:req, b:req
|
||||
_op 15, \a, \b
|
||||
.endm
|
||||
|
||||
.macro WMEM a:req, b:req
|
||||
_op 16, \a, \b
|
||||
.endm
|
||||
|
||||
.macro CALL a:req
|
||||
_op 17, \a
|
||||
.endm
|
||||
|
||||
.macro RET
|
||||
_op 18
|
||||
.endm
|
||||
|
||||
.macro OUT a:req
|
||||
_op 19, \a
|
||||
.endm
|
||||
|
||||
.macro IN a:req
|
||||
_op 20, \a
|
||||
.endm
|
||||
|
||||
.macro NOOP
|
||||
_op 21
|
||||
.endm
|
9
sim/testsuite/example-synacor/jmp.s
Normal file
9
sim/testsuite/example-synacor/jmp.s
Normal file
@ -0,0 +1,9 @@
|
||||
# check the JMP insn.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
JMP 3
|
||||
HALT
|
||||
pass
|
25
sim/testsuite/example-synacor/mem.s
Normal file
25
sim/testsuite/example-synacor/mem.s
Normal file
@ -0,0 +1,25 @@
|
||||
# check the RMEM & WMEM insns.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
JMP 14
|
||||
HALT
|
||||
pass
|
||||
|
||||
# Read a constant address.
|
||||
RMEM r0, 1
|
||||
EQ r1, r0, 14
|
||||
JF r1, 2
|
||||
|
||||
# Change the first JMP to skip HALT and hit the pass.
|
||||
WMEM 1, 3
|
||||
|
||||
# Read an address in a register.
|
||||
SET r2, 1
|
||||
RMEM r0, r2
|
||||
EQ r1, r0, 3
|
||||
JF r1, 2
|
||||
|
||||
JMP 0
|
18
sim/testsuite/example-synacor/mod.s
Normal file
18
sim/testsuite/example-synacor/mod.s
Normal file
@ -0,0 +1,18 @@
|
||||
# check the MOD insn.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
JMP 3
|
||||
HALT
|
||||
|
||||
MOD r0, 8, 3
|
||||
EQ r1, r0, 2
|
||||
JF r1, 2
|
||||
|
||||
MOD r0, r0, 2
|
||||
EQ r1, r0, 0
|
||||
JF r1, 2
|
||||
|
||||
pass
|
18
sim/testsuite/example-synacor/mult.s
Normal file
18
sim/testsuite/example-synacor/mult.s
Normal file
@ -0,0 +1,18 @@
|
||||
# check the MULT insn.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
JMP 3
|
||||
HALT
|
||||
|
||||
MULT r0, 3, 2
|
||||
EQ r1, r0, 6
|
||||
JF r1, 2
|
||||
|
||||
MULT r0, r0, 8
|
||||
EQ r1, r0, 48
|
||||
JF r1, 2
|
||||
|
||||
pass
|
15
sim/testsuite/example-synacor/not.s
Normal file
15
sim/testsuite/example-synacor/not.s
Normal file
@ -0,0 +1,15 @@
|
||||
# check the NOT insn.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
JMP 3
|
||||
HALT
|
||||
|
||||
SET r2, 0xc
|
||||
NOT r0, r2
|
||||
EQ r3, r0, 0x7ff3
|
||||
JF r3, 2
|
||||
|
||||
pass
|
18
sim/testsuite/example-synacor/or.s
Normal file
18
sim/testsuite/example-synacor/or.s
Normal file
@ -0,0 +1,18 @@
|
||||
# check the OR insn.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
JMP 3
|
||||
HALT
|
||||
|
||||
OR r2, 0xf, 0x80
|
||||
EQ r3, r2, 0x8f
|
||||
JF r3, 2
|
||||
|
||||
OR r2, r2, 0xff
|
||||
EQ r3, r2, 0xff
|
||||
JF r3, 2
|
||||
|
||||
pass
|
22
sim/testsuite/example-synacor/push-pop.s
Normal file
22
sim/testsuite/example-synacor/push-pop.s
Normal file
@ -0,0 +1,22 @@
|
||||
# check the PUSH & POP insns.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
JMP 3
|
||||
HALT
|
||||
|
||||
PUSH 1
|
||||
SET r0, 3
|
||||
PUSH r0
|
||||
POP r1
|
||||
POP r2
|
||||
EQ r7, r0, 3
|
||||
JF r7, 2
|
||||
EQ r7, r1, 3
|
||||
JF r7, 2
|
||||
EQ r7, r2, 1
|
||||
JF r7, 2
|
||||
|
||||
pass
|
13
sim/testsuite/example-synacor/ret.s
Normal file
13
sim/testsuite/example-synacor/ret.s
Normal file
@ -0,0 +1,13 @@
|
||||
# check the RET insn.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
JMP 13
|
||||
pass
|
||||
|
||||
SET r5, 2
|
||||
PUSH r5
|
||||
RET
|
||||
HALT
|
20
sim/testsuite/example-synacor/set.s
Normal file
20
sim/testsuite/example-synacor/set.s
Normal file
@ -0,0 +1,20 @@
|
||||
# check the SET insn.
|
||||
# mach: example
|
||||
|
||||
.include "testutils.inc"
|
||||
|
||||
start
|
||||
JMP 3
|
||||
HALT
|
||||
|
||||
SET r2, 2
|
||||
EQ r3, r2, 2
|
||||
JF r3, 2
|
||||
SET r1, 1
|
||||
EQ r3, r1, 1
|
||||
JF r3, 2
|
||||
SET r0, r2
|
||||
EQ r3, r0, 2
|
||||
JF r3, 2
|
||||
|
||||
pass
|
31
sim/testsuite/example-synacor/testutils.inc
Normal file
31
sim/testsuite/example-synacor/testutils.inc
Normal file
@ -0,0 +1,31 @@
|
||||
.include "isa.inc"
|
||||
|
||||
# MACRO: pass
|
||||
# Write 'pass' to stdout and quit
|
||||
.macro pass
|
||||
OUT 'p'
|
||||
OUT 'a'
|
||||
OUT 's'
|
||||
OUT 's'
|
||||
OUT '\n'
|
||||
HALT
|
||||
.endm
|
||||
|
||||
# MACRO: fail
|
||||
# Write 'fail' to stdout and quit
|
||||
.macro fail
|
||||
OUT 'f'
|
||||
OUT 'a'
|
||||
OUT 'i'
|
||||
OUT 'l'
|
||||
OUT '\n'
|
||||
HALT
|
||||
.endm
|
||||
|
||||
# MACRO: start
|
||||
# All assembler tests should start with a call to "start"
|
||||
.macro start
|
||||
.text
|
||||
.global _start
|
||||
_start:
|
||||
.endm
|
@ -378,6 +378,13 @@ proc run_sim_test { name requested_machs } {
|
||||
set options "$options timeout=$opts(timeout)"
|
||||
}
|
||||
|
||||
if [string match "example" "$mach"] {
|
||||
set objcopy [find_binutils_prog objcopy]
|
||||
set comp_output [remote_exec host $objcopy "-O binary -j .text ${name}.x ${name}.bin"]
|
||||
file rename -force "${name}.bin" "${name}.x"
|
||||
append opts(sim,$mach) " --target binary"
|
||||
}
|
||||
|
||||
set result [sim_run ${name}.x "$opts(sim,$mach) $global_sim_options" "$opts(progopts)" "" "$options"]
|
||||
set return_code [lindex $result 0]
|
||||
set output [lindex $result 1]
|
||||
|
Loading…
Reference in New Issue
Block a user