From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ed1-x52a.google.com (mail-ed1-x52a.google.com [IPv6:2a00:1450:4864:20::52a]) by sourceware.org (Postfix) with ESMTPS id 43A00383541B for ; Thu, 4 Feb 2021 10:57:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 43A00383541B Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=jeremy.bennett@embecosm.com Received: by mail-ed1-x52a.google.com with SMTP id df22so3621116edb.1 for ; Thu, 04 Feb 2021 02:57:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=reply-to:subject:to:references:from:autocrypt:organization :message-id:date:user-agent:mime-version:in-reply-to :content-language:content-transfer-encoding; bh=7WHIGYGA9FqrOASd1QtlbfH501v7ewzdJBNfu2M9a9Q=; b=Lr0YoLXkSkmxTe0fxzqFWOY/s8VIL8X5tacbhoods/batHHcdDws1uDeHXkGHYKsz3 Tk2rdWnk710yDOX3p030W6HdJkvX/lemJUNlWgm/r7j6KUKXgjmiIv3LSq8s0Y/LkSH3 TDel3QkpemTfMV7ePJ1Q6ZM21yxI1OHuBVwPEzpsCeDE/P8R61P6sc3kAGP+2FI9N8+l yi07hCWT+x3+Ex9x0IABjuRNUZS8AYlJSyTXNtjJ4B6mPHxujX0azI8ntSQZY7VsCfkx Ryh8VAvj1w/lzouPNQR91R5bMGIOHosfOLLa62mu20WwHnlydymlLWkyTlVmSzXybY3c B4HA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:reply-to:subject:to:references:from:autocrypt :organization:message-id:date:user-agent:mime-version:in-reply-to :content-language:content-transfer-encoding; bh=7WHIGYGA9FqrOASd1QtlbfH501v7ewzdJBNfu2M9a9Q=; b=M6pk4sPQ5SSFsvLQZC1OQqtzQ/PtH+Q3upLpZkJvwbf3boVT3DAvX1TO0xSmXOPOqN FJo4yijs22BNrhCD2MvyllGzT6IDsxRGS+/B2/F8p/t8+gxBoLF8wEBnbws8w1Du1K2b DTpyQ1AmGYJpXGLkIdp9NuMzhdfGYkDglpNxXrZHiz+2u0BRaKPdAluBNmsM9IvoqzTc tn2qHWBgVrOlP0GVe4XBPZCMcVc4n0rwVBXEWBzwOd3TdtBArDQxl+dYrRDPvX8OW7NR v63v8vLwAmEtFCNqzlHzlpAvM+pYkyKStyZFxfxrqnNrqNaV1PseCt2ZT6sa0oLu0k+n mtPw== X-Gm-Message-State: AOAM5323BrGxscCIK81aYngiEP9gYSDATd3OfPhRhELPK17LGlDIY1Xk kQ83/21VGNrFPzdJyeWtrHadWGDooH5YR3n0 X-Google-Smtp-Source: ABdhPJwsNjewMlCzogMKMriwsx1HPgPOKZwv2iaY0QGXmoEegUyjw37GWA7yDMpCvc0G/Uu1V3NlbQ== X-Received: by 2002:aa7:c94a:: with SMTP id h10mr7620240edt.41.1612436239612; Thu, 04 Feb 2021 02:57:19 -0800 (PST) Received: from [192.168.1.116] (cust239-dsl57.idnet.net. [212.69.57.239]) by smtp.gmail.com with ESMTPSA id bd27sm1620507edb.37.2021.02.04.02.57.17 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 04 Feb 2021 02:57:18 -0800 (PST) Reply-To: jeremy.bennett@embecosm.com Subject: Re: [PATCH v2] sim: example-synacor: a simple implementation for reference To: gdb-patches@sourceware.org References: <20210103072446.10840-1-vapier@gentoo.org> <20210119040555.7487-1-vapier@gentoo.org> From: Jeremy Bennett Autocrypt: addr=jeremy.bennett@embecosm.com; keydata= mQGiBEnDq+8RBACazhX1MUYl3LIurwWxJWhR/0JYLhaZhI9mhi2/1vBxkIubSi7ZQn0vaF5f 11YmQqKAtqRRKp0BflUwvjjEpgfY6Bb251MaxGeY3kZE2v33JqHCvuCWxt7YwNUgaA7QAkSo 3ea5R9BiP1ncfppSzcHznEyYy6tzoF6AxWNy64E6OwCgk/set6NdP7cbCW+1VubstJLOTu8D /A3IAPe+LWBABcakcbo3skoCimDqR0JE3JZJm2uLJ5Yyyk7mFQiaalUvfOuecFKiuhll2FHq kg7upU+ZgQgpb6qmCt60L7NsLlmNPhj7pRkPElHYoRamEi5ycDM8abM908xemzJJ8Kv5sq/D AeaQcrDiNz/c0COEQGI1AQRNY+5YA/9XUTAjFc2Mdxs1x9s0JspwTMoHi2MWoyaIiQA55/F7 qSAYumjPFrQhELnxXNS0o2hOXXp8SdSE8jfENj1iMebDcVkt8brRLjg9JnxJQYccTO4QlvLD hhKS2yB99UCEzqjhzhzt8awIeXlRD2DuHhw3pi9XOM0j/oam3izaWnXbrLQ7SmVyZW15IEJl bm5ldHQgKEplcmVteSBIb21lIGtleSkgPGplcmVteUBqZXJlbXliZW5uZXR0LmNvbT6IYgQT EQIAIgUCVVrodwIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQvvWBcvtHVOGezQCf ZaxQR7BMPlvsmtxazEyVmEc+I/cAoIMnfrT/XCDRuuBp/YaXKpOf4ouOuQINBEnDq+8QCACj rS2Q9dIbQKg/s3x/FaAovRfBUcauoWfToBLvy6S0a/KQeSF5KdWWIS3EtxZjSuV5A+Yj5DHy 8dHjNEjPfAwR/GOJA6JF5WUHkTIPHi90rYriWehhtaK6hXpq89Raf48Bdw3giKN5Zy5bsXm1 Kp+b6CclJ9tzjpkbvGrJK4NfUwDcxO6M9BWkhTFAGkHPPTUexl9kFYYmp6yVwmojwqWLi6TI zHobg9pY6KVsQ/Ob3AGwDTNShYF42zJLehnLaeeGNhcsP4yKKGqFdyaa/M16Bjv6JXHXiXHc derOAH5UpDhnah6ZTEC5WKvJ0j4JrlVpBSGLZzLIZuVJAi2Dky6XAAMFCACKCUxQ5pPMw433 JmRnCKvYnsQdBY3W8UsCwvwX8Am3l8CgCFJnGQIEb/VS1GYw+3OeY7jhY368qm51vijJasqW MF7upeSVn5N6cWuR5ORjnNPqf9NXxhfTlCpWvSH6rRAVHXvG8qxi52nfHnK8NsH0G+zc/1PR ak064+TIlC8ZHdUqeQ6+ByeS7EPwZS2ODg5j1IYpkKE1EfDUN7TfgkvsxGjuJwXVKLWgNZps O8qu5CcnTa70ywziF7xWUgHEtkzsQdPJWRRMjQULsnmrK/ySBgPHuPPO70IvB51IkxXOZTzC NHfwIGG1je1icwvcPTB52vXGMqZQp6yZzEc0tuATiEkEGBECAAkFAknDq+8CGwwACgkQvvWB cvtHVOEuDwCcCiTxCqrN8ndGXbKgOqyCFEzd0YQAn0xiO8Gm70ehZCS9WUrVpTu1QNl6 Organization: Embecosm Message-ID: <2bbd7a63-3fb6-6d02-20ef-ad9b5ee9f42c@embecosm.com> Date: Thu, 4 Feb 2021 10:57:16 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 MIME-Version: 1.0 In-Reply-To: <20210119040555.7487-1-vapier@gentoo.org> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-9.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, SCC_10_SHORT_WORD_LINES, SCC_5_SHORT_WORD_LINES, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 04 Feb 2021 10:57:26 -0000 -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 19/01/2021 04:05, Mike Frysinger via Gdb-patches wrote: > 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. Hi Mike, Good to see your proposal and the lack of a RISC-V simulator being addressed again. There has been a patch for a full CGEN based simulator for RISC-V waiting to complete review since late 2019. Here is the thread which starts with the CPU description and then has the simulator port. It is configured to only generate the simulator, not the assembler/disassembler. https://sourceware.org/pipermail/binutils/2019-September/108051.html The patch is derived from a CGEN port which is actively used out of tree, and supports all the ratified RISC-V extensions (the out of tree version also supports the unratified bitmanip extension). Would it be more useful to pursue the CGEN based simulator, giving more flexibility for development as new extensions are ratified. I can ask Ed Jones to resubmit his patch, rebased on the current top-of-tree. We'd really appreciate your help in getting this patch adopted. Best wishes, Jeremy > > It doesn't require a special target -- the example simulators can > be built for any existing port. --- sim/ChangeLog > | 5 + sim/configure | 15 +- > sim/configure.ac | 7 + > sim/example-synacor/ChangeLog | 5 + > sim/example-synacor/Makefile.in | 26 + > sim/example-synacor/README | 15 + > sim/example-synacor/README.arch-spec | 73 + > sim/example-synacor/aclocal.m4 | 119 + > sim/example-synacor/config.in | 242 + > sim/example-synacor/configure | 16029 > ++++++++++++++++++ sim/example-synacor/configure.ac | > 10 + sim/example-synacor/interp.c | 178 + > sim/example-synacor/sim-main.c | 530 + > sim/example-synacor/sim-main.h | 49 + > sim/testsuite/example-synacor/ChangeLog | 5 + > sim/testsuite/example-synacor/add.s | 24 + > sim/testsuite/example-synacor/allinsn.exp | 15 + > sim/testsuite/example-synacor/and.s | 18 + > sim/testsuite/example-synacor/call.s | 14 + > sim/testsuite/example-synacor/exit-0.s | 10 + > sim/testsuite/example-synacor/gt.s | 31 + > sim/testsuite/example-synacor/isa.inc | 108 + > sim/testsuite/example-synacor/jmp.s | 9 + > sim/testsuite/example-synacor/mem.s | 25 + > sim/testsuite/example-synacor/mod.s | 18 + > sim/testsuite/example-synacor/mult.s | 18 + > sim/testsuite/example-synacor/not.s | 15 + > sim/testsuite/example-synacor/or.s | 18 + > sim/testsuite/example-synacor/push-pop.s | 22 + > sim/testsuite/example-synacor/ret.s | 13 + > sim/testsuite/example-synacor/set.s | 20 + > sim/testsuite/example-synacor/testutils.inc | 31 + > sim/testsuite/lib/sim-defs.exp | 7 + 33 files > changed, 17723 insertions(+), 1 deletion(-) create mode 100644 > sim/example-synacor/ChangeLog create mode 100644 > sim/example-synacor/Makefile.in create mode 100644 > sim/example-synacor/README create mode 100644 > sim/example-synacor/README.arch-spec create mode 100644 > sim/example-synacor/aclocal.m4 create mode 100644 > sim/example-synacor/config.in create mode 100755 > sim/example-synacor/configure create mode 100644 > sim/example-synacor/configure.ac create mode 100644 > sim/example-synacor/interp.c create mode 100644 > sim/example-synacor/sim-main.c create mode 100644 > sim/example-synacor/sim-main.h create mode 100644 > sim/testsuite/example-synacor/ChangeLog create mode 100644 > sim/testsuite/example-synacor/add.s create mode 100644 > sim/testsuite/example-synacor/allinsn.exp create mode 100644 > sim/testsuite/example-synacor/and.s create mode 100644 > sim/testsuite/example-synacor/call.s create mode 100644 > sim/testsuite/example-synacor/exit-0.s create mode 100644 > sim/testsuite/example-synacor/gt.s create mode 100644 > sim/testsuite/example-synacor/isa.inc create mode 100644 > sim/testsuite/example-synacor/jmp.s create mode 100644 > sim/testsuite/example-synacor/mem.s create mode 100644 > sim/testsuite/example-synacor/mod.s create mode 100644 > sim/testsuite/example-synacor/mult.s create mode 100644 > sim/testsuite/example-synacor/not.s create mode 100644 > sim/testsuite/example-synacor/or.s create mode 100644 > sim/testsuite/example-synacor/push-pop.s create mode 100644 > sim/testsuite/example-synacor/ret.s create mode 100644 > sim/testsuite/example-synacor/set.s create mode 100644 > sim/testsuite/example-synacor/testutils.inc > > diff --git a/sim/ChangeLog b/sim/ChangeLog index > 7b83115d9c5c..bd85fc1c2a64 100644 --- a/sim/ChangeLog +++ > b/sim/ChangeLog @@ -1,3 +1,8 @@ +2021-01-03 Mike Frysinger > + + * configure.ac: Add --example-sims option. > + * configure: Regenerate. + 2021-01-18 Mike Frysinger > > > * configure.ac: Call AC_PROG_CPP. diff --git a/sim/configure.ac > b/sim/configure.ac index 99364cac7f4e..cb9c1c9f69ab 100644 --- > a/sim/configure.ac +++ b/sim/configure.ac @@ -49,5 +49,12 @@ if > test "${enable_sim}" != no; then fi fi > > +AC_ARG_ENABLE([example-sims], + > [AC_HELP_STRING([--enable-example-sims], + [enable example > GNU simulators])]) +if test "x${enable_example_sims}" = xyes; then > + AC_CONFIG_SUBDIRS(example-synacor) +fi + > AC_CONFIG_FILES([Makefile testsuite/Makefile]) AC_OUTPUT diff --git > a/sim/example-synacor/ChangeLog b/sim/example-synacor/ChangeLog new > file mode 100644 index 000000000000..f4eb00116888 --- /dev/null +++ > b/sim/example-synacor/ChangeLog @@ -0,0 +1,5 @@ +2021-01-03 Mike > Frysinger + + * 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. diff --git > a/sim/example-synacor/Makefile.in > b/sim/example-synacor/Makefile.in new file mode 100644 index > 000000000000..edd77ac801e8 diff --git a/sim/example-synacor/README > b/sim/example-synacor/README new file mode 100644 index > 000000000000..93ffd53d5a49 --- /dev/null +++ > b/sim/example-synacor/README @@ -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. diff --git > a/sim/example-synacor/README.arch-spec > b/sim/example-synacor/README.arch-spec new file mode 100644 index > 000000000000..da2d9d003670 --- /dev/null +++ > b/sim/example-synacor/README.arch-spec @@ -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 to the value of +push: 2 a + push > onto the stack +pop: 3 a + remove the top element from the stack > and write it into ; empty stack = error +eq: 4 a b c + set > to 1 if is equal to ; set it to 0 otherwise +gt: 5 a b c + > set to 1 if is greater than ; set it to 0 otherwise > +jmp: 6 a + jump to +jt: 7 a b + if is nonzero, jump to > +jf: 8 a b + if is zero, jump to +add: 9 a b c + > assign into the sum of and (modulo 32768) +mult: 10 a b > c + store into the product of and (modulo 32768) +mod: > 11 a b c + store into the remainder of divided by > +and: 12 a b c + stores into the bitwise and of and > +or: 13 a b c + stores into the bitwise or of and > +not: 14 a b + stores 15-bit bitwise inverse of in +rmem: > 15 a b + read memory at address and write it to +wmem: 16 > a b + write the value from into memory at address +call: > 17 a + write the address of the next instruction to the stack and > jump to +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 to the terminal +in: 20 a + read a > character from the terminal and write its ascii code to ; 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 diff --git a/sim/example-synacor/aclocal.m4 > b/sim/example-synacor/aclocal.m4 new file mode 100644 index > 000000000000..e9f11c775c31 diff --git > a/sim/example-synacor/config.in b/sim/example-synacor/config.in new > file mode 100644 index 000000000000..cb5ea1b01c95 diff --git > a/sim/example-synacor/configure b/sim/example-synacor/configure new > file mode 100755 index 000000000000..b8b0b4fa349b diff --git > a/sim/example-synacor/configure.ac > b/sim/example-synacor/configure.ac new file mode 100644 index > 000000000000..ccb2ba8d7308 --- /dev/null +++ > b/sim/example-synacor/configure.ac @@ -0,0 +1,10 @@ +dnl Process > this file with autoconf to produce a configure script. > +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_OUTPUT diff --git a/sim/example-synacor/interp.c > b/sim/example-synacor/interp.c new file mode 100644 index > 000000000000..7b831101f809 --- /dev/null +++ > b/sim/example-synacor/interp.c @@ -0,0 +1,178 @@ +/* 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 > . */ + +/* 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; + + /* getopt will > print the error message so we just have to exit if this fails. + > FIXME: Hmmm... in the case of gdb we need getopt to call + > print_filtered. */ + if (sim_parse_args (sd, argv) != SIM_RC_OK) > + { + free_state (sd); + return 0; + } + + /* > 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; +} diff --git a/sim/example-synacor/sim-main.c > b/sim/example-synacor/sim-main.c new file mode 100644 index > 000000000000..a7d748f3022c --- /dev/null +++ > b/sim/example-synacor/sim-main.c @@ -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 > . */ + +/* 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 to the value of . */ + > 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 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 . + > 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 to 1 if is equal to > ; 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 to 1 if is > greater than ; 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 . */ + > 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 is nonzero, jump to . */ + 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 is zero, jump to > . */ + 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 the sum of and (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 the product of and (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 the remainder > of divided by . */ + 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 the bitwise and of and . */ + > 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 the > bitwise or of and . */ + 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 in . */ + 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 > and write it to . */ + 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 into > memory at address . */ + 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 . */ + 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 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 . 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; +} diff --git > a/sim/example-synacor/sim-main.h b/sim/example-synacor/sim-main.h > new file mode 100644 index 000000000000..ba0e4efa12a9 --- > /dev/null +++ b/sim/example-synacor/sim-main.h @@ -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 . */ + +#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 diff --git a/sim/testsuite/example-synacor/ChangeLog > b/sim/testsuite/example-synacor/ChangeLog new file mode 100644 > index 000000000000..58295bb38fa0 --- /dev/null +++ > b/sim/testsuite/example-synacor/ChangeLog @@ -0,0 +1,5 @@ > +2021-01-13 Mike Frysinger + + * 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. diff --git > a/sim/testsuite/example-synacor/add.s > b/sim/testsuite/example-synacor/add.s new file mode 100644 index > 000000000000..64a8c20d8edc --- /dev/null +++ > b/sim/testsuite/example-synacor/add.s @@ -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 diff > --git a/sim/testsuite/example-synacor/allinsn.exp > b/sim/testsuite/example-synacor/allinsn.exp new file mode 100644 > index 000000000000..a73312b8adfb --- /dev/null +++ > b/sim/testsuite/example-synacor/allinsn.exp @@ -0,0 +1,15 @@ +# > Example synacor simulator testsuite. + +if [istarget *] { + # > 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 + } +} diff --git > a/sim/testsuite/example-synacor/and.s > b/sim/testsuite/example-synacor/and.s new file mode 100644 index > 000000000000..1d1885985590 --- /dev/null +++ > b/sim/testsuite/example-synacor/and.s @@ -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 diff > --git a/sim/testsuite/example-synacor/call.s > b/sim/testsuite/example-synacor/call.s new file mode 100644 index > 000000000000..6d7b545a14bc --- /dev/null +++ > b/sim/testsuite/example-synacor/call.s @@ -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 diff --git a/sim/testsuite/example-synacor/exit-0.s > b/sim/testsuite/example-synacor/exit-0.s new file mode 100644 index > 000000000000..2c1fb72f5d7c --- /dev/null +++ > b/sim/testsuite/example-synacor/exit-0.s @@ -0,0 +1,10 @@ +# check > that the sim doesn't die immediately. +# mach: example + +.include > "testutils.inc" + + start + NOOP + NOOP + NOOP + pass diff --git > a/sim/testsuite/example-synacor/gt.s > b/sim/testsuite/example-synacor/gt.s new file mode 100644 index > 000000000000..aef28e34404c --- /dev/null +++ > b/sim/testsuite/example-synacor/gt.s @@ -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 diff --git > a/sim/testsuite/example-synacor/isa.inc > b/sim/testsuite/example-synacor/isa.inc new file mode 100644 index > 000000000000..e2e1136ecfb7 --- /dev/null +++ > b/sim/testsuite/example-synacor/isa.inc @@ -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 diff --git a/sim/testsuite/example-synacor/jmp.s > b/sim/testsuite/example-synacor/jmp.s new file mode 100644 index > 000000000000..dcacf668adc4 --- /dev/null +++ > b/sim/testsuite/example-synacor/jmp.s @@ -0,0 +1,9 @@ +# check the > JMP insn. +# mach: example + +.include "testutils.inc" + + start + > JMP 3 + HALT + pass diff --git > a/sim/testsuite/example-synacor/mem.s > b/sim/testsuite/example-synacor/mem.s new file mode 100644 index > 000000000000..24aa0a9e6fc6 --- /dev/null +++ > b/sim/testsuite/example-synacor/mem.s @@ -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 diff --git a/sim/testsuite/example-synacor/mod.s > b/sim/testsuite/example-synacor/mod.s new file mode 100644 index > 000000000000..f0b4217574c5 --- /dev/null +++ > b/sim/testsuite/example-synacor/mod.s @@ -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 diff --git > a/sim/testsuite/example-synacor/mult.s > b/sim/testsuite/example-synacor/mult.s new file mode 100644 index > 000000000000..d323cf53aa77 --- /dev/null +++ > b/sim/testsuite/example-synacor/mult.s @@ -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 diff --git > a/sim/testsuite/example-synacor/not.s > b/sim/testsuite/example-synacor/not.s new file mode 100644 index > 000000000000..8a4a570ce6e0 --- /dev/null +++ > b/sim/testsuite/example-synacor/not.s @@ -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 diff --git a/sim/testsuite/example-synacor/or.s > b/sim/testsuite/example-synacor/or.s new file mode 100644 index > 000000000000..f8f2ae3a1539 --- /dev/null +++ > b/sim/testsuite/example-synacor/or.s @@ -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 diff --git > a/sim/testsuite/example-synacor/push-pop.s > b/sim/testsuite/example-synacor/push-pop.s new file mode 100644 > index 000000000000..b8199c5d34e4 --- /dev/null +++ > b/sim/testsuite/example-synacor/push-pop.s @@ -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 diff --git > a/sim/testsuite/example-synacor/ret.s > b/sim/testsuite/example-synacor/ret.s new file mode 100644 index > 000000000000..63bfa7132cbe --- /dev/null +++ > b/sim/testsuite/example-synacor/ret.s @@ -0,0 +1,13 @@ +# check the > RET insn. +# mach: example + +.include "testutils.inc" + + start + > JMP 13 + pass + + SET r5, 2 + PUSH r5 + RET + HALT diff --git > a/sim/testsuite/example-synacor/set.s > b/sim/testsuite/example-synacor/set.s new file mode 100644 index > 000000000000..8b441c762eaa --- /dev/null +++ > b/sim/testsuite/example-synacor/set.s @@ -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 diff --git a/sim/testsuite/example-synacor/testutils.inc > b/sim/testsuite/example-synacor/testutils.inc new file mode 100644 > index 000000000000..0f286c6036ca --- /dev/null +++ > b/sim/testsuite/example-synacor/testutils.inc @@ -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 diff --git a/sim/testsuite/lib/sim-defs.exp > b/sim/testsuite/lib/sim-defs.exp index 43a07050f508..04ab4685612b > 100644 --- a/sim/testsuite/lib/sim-defs.exp +++ > b/sim/testsuite/lib/sim-defs.exp @@ -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] > - -- Cell: +44 (7970) 676050 SkypeID: jeremybennett Twitter: @jeremypbennett Email: jeremy.bennett@embecosm.com Web: www.embecosm.com PGP key: 1024D/BEF58172FB4754E1 2009-03-20 -----BEGIN PGP SIGNATURE----- iF0EARECAB0WIQRASGDWqmhRZUfAaPW+9YFy+0dU4QUCYBvTCgAKCRC+9YFy+0dU 4RPoAJ9M55mCdgF1p7G3Da947lDVeLAAMwCfcL7cr5P14DJh5bng7xO6dwahlsQ= =6SkR -----END PGP SIGNATURE-----